package org.processwarp.android;

import android.os.Build;
import android.util.Log;

import junit.framework.Assert;

import java.security.MessageDigest;

public class Router {
    public static Router getInstance() {
        return THIS;
    }

    /**
     * Initialize some module.
     */
    public void initialize() {
        try {
            myNid = "";
            schedulerInitialize();

            ServerConnector server = ServerConnector.getInstance();
            server.initialize();

        } catch (Exception e) {
            Log.e(this.getClass().getName(), "", e);
        }
    }

    /**
     * Connect server, make password SHA256 digest and send to server to check account.
     * @param account Target account name.
     * @param password Target password.
     */
    public void connectServer(String account, String password) {
        try {
            String hexString = null;
            // apply digest 10 times by SHA256
            byte[] digest = password.getBytes("UTF-8");
            for (int i = 0; i < 10; i ++) {
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                md.update(digest);
                digest = md.digest();

                // Convert to hex string.
                StringBuilder hex = new StringBuilder();
                for (byte b : digest) {
                    if ((b & 0xFF) <= 0x0F) hex.append("0");
                    hex.append(Integer.toHexString(b & 0xFF));
                }
                hexString = hex.toString();
                digest = hexString.getBytes("UTF-8");
            }

            // Send to server
            ServerConnector server = ServerConnector.getInstance();
            server.sendConnectNode(account, "[10sha256]" + hexString);

        } catch (Exception e) {
            Assert.fail("");
        }
    }

    public String getMyNid() {
        return myNid;
    }

    public void recvConnectNode(int result) {
        if (result == 0) {
            ServerConnector server = ServerConnector.getInstance();
            server.sendBindNode(myNid, Build.HOST);

        } else {
            // TODO
            Assert.fail();
        }
    }

    public void recvBindNode(int result, String nid) {
        if (result == 0) {
            myNid = nid;
            schedulerSetMyNid(nid);

        } else {
            // TODO
            Assert.fail();
        }
    }

    /**
     * When passed a command from some module in this node,
     * set destination node-id and pass content to capable module in this node or
     * another node through the server.
     * @param packet Command packet.
     */
    public void relayCommand(CommandPacket packet) {
        String realNid = (
                !SpecialNid.NONE.equals(packet.dstNid) ?
                packet.dstNid :
                schedulerGetDstNid(packet.pid, packet.module));

        CommandPacket realPacket = new CommandPacket();
        realPacket.pid     = packet.pid;
        realPacket.dstNid  = realNid;
        realPacket.srcNid  = myNid;
        realPacket.module  = packet.module;
        realPacket.content = packet.content;

        if (realPacket.dstNid.equals(myNid) || realPacket.dstNid.equals(SpecialNid.THIS)) {
            switch (realPacket.module) {
                case Module.MEMORY:
                case Module.VM:
                    // TODO
                    Assert.fail();
                    break;

                case Module.SCHEDULER:
                    schedulerRecvCommand(
                            realPacket.pid, realPacket.srcNid, realPacket.srcNid,
                            realPacket.module, realPacket.content);
                    break;

                case Module.FRONTEND:
                    // TODO
                    Assert.fail();
                    break;

                default:
                    // TODO
                    Assert.fail();
                    break;
            }
        }

        ServerConnector server = ServerConnector.getInstance();
        server.sendRelayCommand(realPacket);
    }

    public void relaySchedulerCommand(CommandPacket packet) {
        schedulerRecvCommand(
                packet.pid, packet.dstNid, packet.srcNid,
                packet.module, packet.content);
    }

    private static final Router THIS = new Router();
    private String myNid;

    private Router() {
    }

    private native void schedulerInitialize();
    private native String schedulerGetDstNid(String pid, int module);
    private native void schedulerRecvCommand(String pid, String dstNid, String srcNid,
                                             int module, String content);
    private native void schedulerSetMyNid(String nid);
    private native void schedulerActivate();
}

@@ -169,16 +169,139 @@
 outer %7B%0A
+    /**%0A     * Router instance getter as singleton pattern.%0A     * @return The singleton instance of Router class.%0A     */%0A
     publ
@@ -1964,63 +1964,278 @@
     
-public String getMyNid() %7B%0A        return myNid;%0A    %7D%0A
+/**%0A     * Get this node's node-id.%0A     * @return This node's node-id.%0A     */%0A    public String getMyNid() %7B%0A        return myNid;%0A    %7D%0A%0A    /**%0A     * When connect is success, send bind_node packet with my-nid and node-name.%0A     * @param result Result code.%0A     */
 %0A   
@@ -2498,32 +2498,187 @@
        %7D%0A    %7D%0A%0A
+    /**%0A     * When bind is success, store assigned nid as my-nid.%0A     * @param result Result code.%0A     * @param nid Assigned nid for this node.%0A     */%0A
     public void 
@@ -4548,24 +4548,153 @@
 et);%0A    %7D%0A%0A
+    /**%0A     * When receive packet from server to scheduler, relay it to scheduler.%0A     * @param packet Command packet.%0A     */%0A
     public v
@@ -4966,16 +4966,137 @@
 myNid;%0A%0A
+    /**%0A     * Constructor for singleton pattern.%0A     * This class is singleton.%0A     * This method is private.%0A     */%0A
     priv

add comment