Android Open Source - schat S Chat Server Thread






From Project

Back to project page schat.

License

The source code is released under:

MIT License

If you think the Android project schat listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package networking;
/*  www. j  a  va 2  s. c  o  m*/
import crypto.Envelope;
import data.Message;
import data.SQLiteManager;
import data.User;
import data.contents.*;

import javax.crypto.SecretKey;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Calendar;

/**
 * @author Gary
 * @version 2013/11/29
 *          This single server thread handles one single client.
 */
public class SChatServerThread extends Thread {
    private final SChatServer server;
    private Socket clientSocket;
    private User client;
    private SecretKey secretKey;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private SQLiteManager dbmanager;

    /**
     * Create a server thread, which will be handle a single client connected
     * to this server.
     *
     * @param clientSocket the socket of the client
     * @param server       the server
     * @throws IOException
     */
    public SChatServerThread(Socket clientSocket, SChatServer server) throws IOException {
        this.clientSocket = clientSocket;
        this.server = server;
        this.in = new ObjectInputStream(clientSocket.getInputStream());
        this.out = new ObjectOutputStream(clientSocket.getOutputStream());
        this.client = null;
        this.dbmanager = new SQLiteManager(SChatServer.SERVER_DB);
    }


    /**
     * Handle the login of the user and check whether it was successful or not.
     *
     * @param login the login data
     * @return whether the login of the user was successful or not
     */
    public boolean handleLogin(Login login) {
        if (server.findUser(login.getId())) {
            client = dbmanager.getUserFromGivenId(login.getId());
            server.addUser(client.getId(), out);

            sendStoredMessages();
            sendLoginSuccess(true);
            return true;
        } else {
            sendLoginSuccess(false);
            return false;
        }
    }

    /**
     * Sends to server whether the login was successful or not
     *
     * @param success
     */
    public void sendLoginSuccess(boolean success) {
        Message<LoginSuccess> pkResponse = new Message<>(Calendar.getInstance().getTime(), SChatServer.SERVER_ID,
                client.getId(), new LoginSuccess(success));
        PublicKey senderPk = dbmanager.getPublicKeyFromId(client.getId());
        sendEnvelope(new Envelope(pkResponse, secretKey, senderPk, server.getKeyPair().getPrivate()));
    }

    /**
     * Return whether the user is logged in or not.
     *
     * @return whether the user is logged in or not
     */
    public boolean isLoggedIn() {
        return client != null;
    }

    /**
     * Sends the stored messages to the user.
     * <p/>
     * The stored messages are the messages, that were not successfully sent to the user because of some
     * network error or because the user was offline at the sending time.
     * They are saved in the database and will be erased after being sent successfully.
     */
    public void sendStoredMessages() {
        ArrayList<Envelope> envelopes = dbmanager.loadEncryptedMessagesFromReceiver(client.getId());
        for (Envelope e : envelopes) {
            if (!sendEnvelope(e))
                break;
            dbmanager.removeEncryptedMessage(e);
        }
    }

    /**
     * Runs the main logic of this server
     */
    public void run() {
        boolean isRunning = true;
        while (isRunning) {
            try {
                Envelope envelope = (Envelope) in.readObject();
                this.secretKey = envelope.getUnwrappedKey(server.getKeyPair().getPrivate());

                switch (envelope.getType()) {
                    case CHAT_MESSAGE:
                        if (!isLoggedIn()) {
                            isRunning = false;
                        } else {
                            handleRedirecting(envelope);
                        }
                        break;
                    case LOGIN:
                        Message<Login> loginMessage = envelope.<Login>decryptMessage(secretKey, server.getKeyPair().getPublic());
                        if (!handleLogin(loginMessage.getContent()))
                            isRunning = false;
                        break;
                    case REGISTRATION:
                        if (!handleRegistration(envelope)) {
                            isRunning = false;
                        }
                        break;
                    case PUBLIC_KEY_REQUEST:
                        handlePublicKeyRequest(envelope);
                        break;
                }
            } catch (IOException e) {
                System.err.println("Connection to " + client + " closed.");
                isRunning = false;
            } catch (ClassNotFoundException e) {
                System.err.println("Class not found: " + e.getMessage());
            }
        }
        // Close and kill everything
        try {
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        server.eraseUser(client.getId());
    }

    /**
     * Handles the public key request
     *
     * @param envelope
     */
    private void handlePublicKeyRequest(Envelope envelope) {
        secretKey = envelope.getUnwrappedKey(server.getKeyPair().getPrivate()); // Still needed in the first version.
        PublicKeyRequest pkRequest = envelope.<PublicKeyRequest>decryptMessage(secretKey, client.getPublicKey()).getContent();
        PublicKey requestPK = dbmanager.getPublicKeyFromId(pkRequest.getRequestId());
        Message<PublicKeyResponse> pkResponse = new Message<PublicKeyResponse>(Calendar.getInstance().getTime(), SChatServer.SERVER_ID,
                envelope.getSender(), new PublicKeyResponse(pkRequest.getRequestId(), requestPK));
        PublicKey senderPk = dbmanager.getPublicKeyFromId(envelope.getSender());
        sendEnvelope(new Envelope(pkResponse, secretKey, senderPk, server.getKeyPair().getPrivate()));
    }

    /**
     * Handles the redirecting of the messages
     *
     * @param envelope
     */
    private void handleRedirecting(Envelope envelope) {
        redirectMessage(envelope);
    }

    /**
     * Redirects the message to the receiver.
     *
     * @param envelope
     */
    public void redirectMessage(Envelope envelope) {
        if (!sendEnvelope(envelope)) {
            dbmanager.insertEncryptedMessage(envelope);
        }
    }

    /**
     * @param envelope
     * @return whether the sending was successful or not
     */
    public boolean sendEnvelope(Envelope envelope) {
        System.out.println(envelope.getSender() + " sending to " + envelope.getReceiver());
        ObjectOutputStream out = server.getObjectOutputStreamById(envelope.getReceiver());
        if (out == null)
            return false;
        try {
            out.writeObject(envelope);
            out.flush();
        } catch (IOException e) {
            System.err.println(e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * Handle the registration of a user.
     * The registration can fail if the given id already exists.
     *
     * @param envelope the envelope
     * @return if the registration was successful or not
     */
    private boolean handleRegistration(Envelope envelope) {
        Registration registration = envelope.<Registration>decryptMessage(secretKey).getContent();
        Login login = registration.getLogin();
        if (dbmanager.userExists(login.getId())) {
            // System.err.println("Registration failed because id already exists");
            return handleLogin(registration.getLogin());
        }
        client = new User(login.getId(), new KeyPair(registration.getPublicKey(), null), secretKey);
        dbmanager.insertUser(client);
        System.out.println("New user " + login.getId() + " registered!");
        handleLogin(registration.getLogin());
        return true;
    }
}




Java Source Code List

.ServerMain.java
com.activities.Activity_Chat.java
com.activities.Activity_ContactList.java
com.activities.ContactView.java
com.data.AddContact.java
com.data.AndroidSQLManager.java
com.data.ApplicationUser.java
com.data.ChatAdapter.java
com.data.ChatArrayList.java
com.data.MySQLiteHelper.java
com.security.AndroidKeyPairManager.java
com.security.PRNGFixes.java
com.services.MessageService.java
crypto.CryptoConstants.java
crypto.Cryptography.java
crypto.Envelope.java
crypto.SecureMessage.java
crypto.TestCrypto.java
data.ChatMessage.java
data.Content.java
data.DatabaseManager.java
data.KeyPairManager.java
data.Message.java
data.SQLiteManager.java
data.User.java
data.contents.ChatContent.java
data.contents.LoginSuccess.java
data.contents.Login.java
data.contents.PublicKeyRequest.java
data.contents.PublicKeyResponse.java
data.contents.Registration.java
networking.SChatClientListener.java
networking.SChatClientWriter.java
networking.SChatClient.java
networking.SChatServerThread.java
networking.SChatServer.java