//Invoke by Transporter, process the message
    internal void processMessage(byte[] bytes)
    {
        Package pkg = PackageProtocol.Decode(bytes);

        //Ignore all the message except handshading at handshake stage
        if (pkg.type == enPackageType.Handshake && this.state == enProtocolState.handshaking)
        {
            //Ignore all the message except handshading
            MessageObject data = (MessageObject)SimpleJson.SimpleJson.DeserializeObject(Encoding.UTF8.GetString(pkg.body));

            ProcessHandshakeData(data);

            this.state = enProtocolState.working;
        }
        else if (pkg.type == enPackageType.Heartbeat && this.state == enProtocolState.working)
        {
            this.heartBeatService.ResetTimeout();
        }
        else if (pkg.type == enPackageType.Data && this.state == enProtocolState.working)
        {
            this.heartBeatService.ResetTimeout();
            pomeloClient.ProcessMessage(messageProtocol.Decode(pkg.body));
        }
        else if (pkg.type == enPackageType.Kick)
        {
            this.GetPomeloClient().Disconnect();
            this.Close();
        }
    }
    internal void Start(MessageObject user, Action <MessageObject> callback)
    {
        this.transporter.Start();
        this.handshake.Request(user, callback);

        this.state = enProtocolState.handshaking;
    }
    private void ProcessHandshakeData(MessageObject msg)
    {
        //Handshake error
        if (!msg.ContainsKey("code") || !msg.ContainsKey("sys") || Convert.ToInt32(msg["code"]) != 200)
        {
            throw new Exception("Handshake error! Please check your handshake config.");
        }

        //Set compress data
        MessageObject sys = (MessageObject)msg["sys"];

        MessageObject dict = new MessageObject();

        if (sys.ContainsKey("dict"))
        {
            dict = (MessageObject)sys["dict"];
        }

        MessageObject protos       = new MessageObject();
        MessageObject serverProtos = new MessageObject();
        MessageObject clientProtos = new MessageObject();

        if (sys.ContainsKey("protos"))
        {
            protos       = (MessageObject)sys["protos"];
            serverProtos = (MessageObject)protos["server"];
            clientProtos = (MessageObject)protos["client"];
        }

        messageProtocol = new MessageProtocol(dict, serverProtos, clientProtos);

        //Init heartbeat service
        int interval = 0;

        if (sys.ContainsKey("heartbeat"))
        {
            interval = Convert.ToInt32(sys["heartbeat"]);
        }
        heartBeatService = new HeartBeatService(interval, this);

        if (interval > 0)
        {
            heartBeatService.Start();
        }

        //send ack and change protocol state
        handshake.Ack();
        this.state = enProtocolState.working;

        //Invoke handshake callback
        MessageObject user = new MessageObject();

        if (msg.ContainsKey("user"))
        {
            user = (MessageObject)msg["user"];
        }
        handshake.InvokeCallback(user);
    }
    public Protocol(PomeloClient pc, System.Net.Sockets.Socket socket)
    {
        this.pomeloClient             = pc;
        this.transporter              = new Transporter(socket, this.processMessage);
        this.transporter.onDisconnect = OnDisconnect;

        this.handshake = new HandShakeService(this);
        this.state     = enProtocolState.start;
    }
    internal void Close()
    {
        transporter.Close();

        if (heartBeatService != null)
        {
            heartBeatService.Stop();
        }

        this.state = enProtocolState.closed;
    }