com.chess.genesis.net.NetworkClient.java Source code

Java tutorial

Introduction

Here is the source code for com.chess.genesis.net.NetworkClient.java

Source

/* GenesisChess, an Android chess application
 * Copyright 2014, Justin Madru (justin.jdm64@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.chess.genesis.net;

import android.content.*;
import android.os.*;
import com.chess.genesis.*;
import com.chess.genesis.data.*;
import java.io.*;
import java.net.*;
import org.json.*;

public class NetworkClient implements Runnable {
    public final static int NONE = 0;
    public final static int LOGIN = 1;
    public final static int REGISTER = 2;
    public final static int JOIN_GAME = 3;
    public final static int NEW_GAME = 4;
    public final static int GAME_STATUS = 7;
    public final static int GAME_INFO = 8;
    public final static int SUBMIT_MOVE = 9;
    public final static int SUBMIT_MSG = 10;
    public final static int SYNC_GAMIDS = 11;
    public final static int GAME_SCORE = 12;
    public final static int GAME_DATA = 13;
    public final static int RESIGN_GAME = 14;
    public final static int SYNC_GAMES = 15;
    public final static int SYNC_MSGS = 16;
    public final static int GET_OPTION = 17;
    public final static int SET_OPTION = 18;
    public final static int POOL_INFO = 19;
    public final static int NUDGE_GAME = 20;
    public final static int IDLE_RESIGN = 21;
    public final static int USER_STATS = 22;
    public final static int GAME_DRAW = 23;

    private final static String _ACTION = "action";
    private final static String _COLOR = "color";
    private final static String _DRAW = "draw";
    private final static String _EMAIL = "email";
    private final static String _ERROR = "error";
    private final static String _GAME_DATA = "gamedata";
    private final static String _GAMEID = "gameid";
    private final static String _GAMEIDS = "gameids";
    private final static String _GAME_INFO = "gameinfo";
    private final static String _GAME_SCORE = "gamescore";
    private final static String _GAME_STATUS = "gamestatus";
    private final static String _GAME_TYPE = "gametype";
    private final static String _GET_OPTION = "getoption";
    private final static String _IDLE_RESIGN = "idleresign";
    private final static String _JOIN_GAME = "joingame";
    private final static String _LOGIN = "login";
    private final static String _MOVE = "move";
    private final static String _NEW_GAME = "newgame";
    private final static String _NUDGE = "nudge";
    private final static String _OK = "ok";
    private final static String _OPPONENT = "opponent";
    private final static String _OPTION = "option";
    private final static String _PASSHASH = "passhash";
    private final static String _POOL_INFO = "poolinfo";
    private final static String _REASON = "reason";
    private final static String _REGISTER = "register";
    private final static String _REQUEST = "request";
    private final static String _RESIGN = "resign";
    private final static String _RESULT = "result";
    private final static String _SEND_MOVE = "sendmove";
    private final static String _SEND_MSG = "sendmsg";
    private final static String _SET_OPTION = "setoption";
    private final static String _SYNC_GAMES = "syncgames";
    private final static String _SYNC_MSGS = "syncmsgs";
    private final static String _TIME = "time";
    private final static String _TXT = "txt";
    private final static String _TYPE = "type";
    private final static String _USERNAME = "username";
    private final static String _USER_STATS = "userstats";
    private final static String _VALUE = "value";

    private final static String CANT_CONTACT_MSG = "Can't contact server for sending data";
    private final static String LOST_CONNECTION_MSG = "Lost connection during sending data";
    private final static String SERVER_ILLOGICAL_MSG = "Server response illogical";

    private final Context context;
    private final Handler callback;
    private final SocketClient socket;

    private JSONObject request;
    private int fid = NONE;
    private boolean loginRequired;
    private boolean error = false;

    public NetworkClient(final Context _context, final Handler handler) {
        callback = handler;
        context = _context;
        socket = SocketClient.getInstance();
    }

    public NetworkClient(final SocketClient Socket, final Context _context, final Handler handler) {
        callback = handler;
        context = _context;
        socket = Socket;
    }

    private void newRequest(final String type, final int callbackId, final boolean requiresLogin) {
        fid = callbackId;
        loginRequired = requiresLogin;
        request = new JSONObject();

        try {
            request.put(_REQUEST, type);
        } catch (final JSONException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private <Type> void addValue(final String key, final Type value) {
        try {
            request.put(key, value);
        } catch (final JSONException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    // Crypto.LoginKey makes a network connection, but all
    // network calls must be on a non-main thread. This finishes
    // the json setup started in login_user.
    private void login_setup() {
        final JSONObject json = new JSONObject();

        try {
            try {
                request.put(_PASSHASH, Crypto.LoginKey(socket, request.getString(_PASSHASH)));
            } catch (final JSONException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        } catch (final SocketException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, CANT_CONTACT_MSG);
                socket.logError(context, e, request);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        } catch (final IOException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, LOST_CONNECTION_MSG);
                socket.logError(context, e, request);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        }
        if (error)
            callback.sendMessage(Message.obtain(callback, fid, json));
    }

    private JSONObject send_request(final JSONObject data) {
        JSONObject json = new JSONObject();

        try {
            socket.write(data);
        } catch (final SocketException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, CANT_CONTACT_MSG);
                socket.logError(context, e, data);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        } catch (final IOException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, LOST_CONNECTION_MSG);
                socket.logError(context, e, data);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        }
        if (error)
            return json;

        try {
            json = socket.read();
        } catch (final SocketException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, CANT_CONTACT_MSG);
                socket.logError(context, e, data);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        } catch (final IOException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, LOST_CONNECTION_MSG);
                socket.logError(context, e, data);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        } catch (final JSONException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, SERVER_ILLOGICAL_MSG);
                socket.logError(context, e, data);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        }
        return json;
    }

    private boolean relogin() {
        if (socket.getIsLoggedIn())
            return true;

        final Pref pref = new Pref(context);
        final String username = pref.getString(R.array.pf_username);
        final String password = pref.getString(R.array.pf_passhash);

        JSONObject json = new JSONObject();

        try {
            try {
                json.put(_REQUEST, _LOGIN);
                json.put(_USERNAME, username);
                json.put(_PASSHASH, Crypto.LoginKey(socket, password));
            } catch (final JSONException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        } catch (final SocketException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, CANT_CONTACT_MSG);
                socket.logError(context, e, json);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        } catch (final IOException e) {
            try {
                json.put(_RESULT, _ERROR);
                json.put(_REASON, LOST_CONNECTION_MSG);
                socket.logError(context, e, request);
            } catch (final JSONException j) {
                throw new RuntimeException(j.getMessage(), j);
            }
            error = true;
        }
        if (error) {
            callback.sendMessage(Message.obtain(callback, fid, json));
            return false;
        }

        // Send login request
        json = send_request(json);

        try {
            if (!json.getString(_RESULT).equals(_OK)) {
                callback.sendMessage(Message.obtain(callback, fid, json));
                return false;
            }
            socket.setIsLoggedIn(true);
            return true;
        } catch (final JSONException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    @Override
    public synchronized void run() {
        if (fid == LOGIN)
            login_setup();

        if (error || (loginRequired && !relogin())) {
            error = false;
            socket.disconnect();
            return;
        }

        final JSONObject json = send_request(request);
        if (error) {
            error = false;
            socket.disconnect();
        }

        callback.sendMessage(Message.obtain(callback, fid, json));
    }

    public void register(final String username, final String password, final String email) {
        newRequest(_REGISTER, REGISTER, false);
        addValue(_USERNAME, username);
        addValue(_PASSHASH, Crypto.HashPasswd(password));
        addValue(_EMAIL, email);
    }

    public void login_user(final String username, final String password) {
        newRequest(_LOGIN, LOGIN, false);
        addValue(_USERNAME, username);

        /*
         * temporarily save password to passhash login_setup will finish
         * the creation of the json in a new thread.
         */
        addValue(_PASSHASH, password);
    }

    public void join_game(final String gametype) {
        newRequest(_JOIN_GAME, JOIN_GAME, true);
        addValue(_GAME_TYPE, gametype);
    }

    public void new_game(final String opponent, final String gametype, final String color) {
        newRequest(_NEW_GAME, NEW_GAME, true);
        addValue(_OPPONENT, opponent);
        addValue(_GAME_TYPE, gametype);
        addValue(_COLOR, color);
    }

    public void submit_move(final String gameid, final String move) {
        newRequest(_SEND_MOVE, SUBMIT_MOVE, true);
        addValue(_GAMEID, gameid);
        addValue(_MOVE, move);
    }

    public void resign_game(final String gameid) {
        newRequest(_RESIGN, RESIGN_GAME, true);
        addValue(_GAMEID, gameid);
    }

    public void submit_msg(final String gameid, final String msg) {
        newRequest(_SEND_MSG, SUBMIT_MSG, true);
        addValue(_GAMEID, gameid);
        addValue(_TXT, msg);
    }

    public void sync_msgs(final long time) {
        newRequest(_SYNC_MSGS, SYNC_MSGS, true);
        addValue(_TIME, time);
    }

    public void game_status(final String gameid) {
        newRequest(_GAME_STATUS, GAME_STATUS, true);
        addValue(_GAMEID, gameid);
    }

    public void game_info(final String gameid) {
        newRequest(_GAME_INFO, GAME_INFO, true);
        addValue(_GAMEID, gameid);
    }

    public void game_data(final String gameid) {
        newRequest(_GAME_DATA, GAME_DATA, true);
        addValue(_GAMEID, gameid);
    }

    public void sync_gameids(final String type) {
        newRequest(_GAMEIDS, SYNC_GAMIDS, true);
        addValue(_TYPE, type);
    }

    public void sync_games(final long time) {
        newRequest(_SYNC_GAMES, SYNC_GAMES, true);
        addValue(_TIME, time);
    }

    public void game_score(final String gameid) {
        newRequest(_GAME_SCORE, GAME_SCORE, true);
        addValue(_GAMEID, gameid);
    }

    public <Type> void set_option(final String option, final Type value) {
        newRequest(_SET_OPTION, SET_OPTION, true);
        addValue(_OPTION, option);
        addValue(_VALUE, value);
    }

    public void get_option(final String option) {
        newRequest(_GET_OPTION, GET_OPTION, true);
        addValue(_OPTION, option);
    }

    public void pool_info() {
        newRequest(_POOL_INFO, POOL_INFO, true);
    }

    public void nudge_game(final String gameid) {
        newRequest(_NUDGE, NUDGE_GAME, true);
        addValue(_GAMEID, gameid);
    }

    public void idle_resign(final String gameid) {
        newRequest(_IDLE_RESIGN, IDLE_RESIGN, true);
        addValue(_GAMEID, gameid);
    }

    public void user_stats(final String username) {
        newRequest(_USER_STATS, USER_STATS, true);
        addValue(_USERNAME, username);
    }

    public void game_draw(final String gameid, final String action) {
        newRequest(_DRAW, GAME_DRAW, true);
        addValue(_GAMEID, gameid);
        addValue(_ACTION, action);
    }
}