private bool Reconnect(string handle, HoxisProtocolArgs args)
        {
            long uid = FF.StringToLong(args["uid"]);
            List <HoxisConnection> workers = HoxisServer.Ins.GetWorkingConnections();

            foreach (HoxisConnection w in workers)
            {
                // If already signed in, response the state to let user choose if reconnecting
                if (w.user == this)
                {
                    continue;
                }
                if (w.user.userID <= 0)
                {
                    continue;
                }
                if (w.user.userID == uid)
                {
                    userID       = w.user.userID;
                    realtimeData = w.user.realtimeData;
                    Continue();
                    if (DebugRecorder.LogEnable(_logger))
                    {
                        _logger.LogInfo("reconnect", "");
                    }
                    HoxisServer.Ins.AffairEntry(C.AFFAIR_RELEASE_CONNECTION, w);
                    return(ResponseSuccess(handle, "ReconnectCb"));
                }
            }
            return(Response(handle, "ReconnectCb", new KVString("code", C.RESP_NO_USER_INFO)));
        }
        /// <summary>
        /// Fill this HoxisUser with an connected user
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        private bool SignIn(string handle, HoxisProtocolArgs args)
        {
            Ret  ret;
            long uid = FF.StringToLong(args["uid"]);

            if (uid <= 0)
            {
                return(ResponseError(handle, C.RESP_ILLEGAL_ARGUMENT, FF.StringFormat("illegal argument: {0}", args["uid"])));
            }
            userID          = uid;
            connectionState = UserConnectionState.Default;
            if (DebugRecorder.LogEnable(_logger))
            {
                _logger.LogInfo("sign in", "");
            }
            else
            {
                _logger = new DebugRecorder(FF.StringAppend(HoxisServer.basicPath, @"logs\users\", NewUserLogName(uid)), out ret);
                if (ret.code != 0)
                {
                    Console.WriteLine(ret.desc);
                }
                else
                {
                    _logger.Begin();
                    _logger.LogInfo("sign in", "");
                }
            }
            return(ResponseSuccess(handle, "SignInCb"));
        }
        public HoxisServer(string projectArg, string versionArg, bool autoStart = false)
        {
            if (Ins == null)
            {
                Ins = this;
            }

            Ret ret;

            project = projectArg;
            version = versionArg;

            // Init and begin log recording
            _logger = new DebugRecorder(FF.StringAppend(basicPath, @"logs\server.log"), out ret);
            if (ret.code != 0)
            {
                Quit();
            }
            _logger.Begin();
            _logger.LogTitle("David.Claude", project, version);

            // Auto start
            if (autoStart)
            {
                InitializeConfig(out ret);
                if (ret.code != 0)
                {
                    Quit();
                }
                Listen();
                BeginAccept();
                BeginProcess();
                BeginHeartbeatUpdate();
            }
        }
 public void Pause()
 {
     connectionState = UserConnectionState.Disconnected;
     if (DebugRecorder.LogEnable(_logger))
     {
         _logger.End();
     }
 }
 private bool SignOut(string handle, HoxisProtocolArgs args)
 {
     userID          = 0;
     connectionState = UserConnectionState.None;
     if (DebugRecorder.LogEnable(_logger))
     {
         _logger.LogInfo("sign out", ""); _logger.End();
     }
     return(ResponseSuccess(handle, "SignOutCb"));
 }
        public void Continue()
        {
            Ret ret;

            connectionState = UserConnectionState.Active;
            if (!DebugRecorder.LogEnable(_logger))
            {
                _logger = new DebugRecorder(FF.StringAppend(HoxisServer.basicPath, @"logs\users\", NewUserLogName(userID)), out ret);
                if (ret.code != 0)
                {
                    Console.WriteLine(ret.desc);
                }
                else
                {
                    _logger.Begin();
                }
            }
        }
        /// <summary>
        /// **WITHIN THREAD**
        /// The entrance of protocol bytes
        /// </summary>
        /// <param name="data"></param>
        public void ProtocolEntry(byte[] data)
        {
            string        json  = FF.BytesToString(data);
            HoxisProtocol proto = FF.JsonToObject <HoxisProtocol>(json);

            switch (proto.type)
            {
            case ProtocolType.Synchronization:
                switch (proto.receiver.type)
                {
                case ReceiverType.Cluster:
                    if (realtimeData.parentCluster == null)
                    {
                        return;
                    }
                    realtimeData.parentCluster.ProtocolBroadcast(proto);
                    break;

                case ReceiverType.Team:
                    if (realtimeData.parentTeam == null)
                    {
                        return;
                    }
                    realtimeData.parentTeam.ProtocolBroadcast(proto);
                    break;

                case ReceiverType.User:
                    HoxisUser user = HoxisServer.Ins.GetUser(proto.receiver.uid);
                    // todo send
                    break;
                }
                break;

            case ProtocolType.Request:
                // Request check
                Ret ret;
                CheckRequest(proto, out ret);
                if (ret.code != 0)
                {
                    ResponseError(proto.handle, C.RESP_CHECK_FAILED, ret.desc);
                    return;
                }
                // Check ok
                if (!respTable.ContainsKey(proto.action.method))
                {
                    if (DebugRecorder.LogEnable(_logger))
                    {
                        _logger.LogError(FF.StringFormat("invalid request: {0}", proto.action.method), "", true);
                    }
                    ResponseError(proto.handle, C.RESP_CHECK_FAILED, FF.StringFormat("invalid request: {0}", proto.action.method));
                    return;
                }
                respTable[proto.action.method](proto.handle, proto.action.args);
                break;

            default:
                if (DebugRecorder.LogEnable(_logger))
                {
                    _logger.LogError(FF.StringFormat("invalid protocol type: {0}", proto.type), "");
                }
                break;
            }
        }