/// <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 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>
 /// Begin accepting socket connection within thread
 /// </summary>
 public void BeginAccept()
 {
     _acceptThread = new Thread(() =>
     {
         while (true)
         {
             Socket socket = _socket.Accept();
             _logger.LogInfo(FF.StringAppend("accept new client: ", socket.RemoteEndPoint.ToString()), "Server", true);
             Ret ret;
             HoxisConnection conn = _connReception.Request(socket, out ret);
             if (ret.code != 0)
             {
                 _logger.LogWarning(ret.desc, socket.RemoteEndPoint.ToString()); continue;
             }
             _logger.LogInfo("request successful", conn.clientIP);
         }
     });
     _acceptThread.Start();
     _logger.LogInfo("accept begin...", "Server", true);
 }
 /// <summary>
 /// New log name of an user
 /// </summary>
 /// <param name="uid"></param>
 /// <returns></returns>
 public static string NewUserLogName(long uid)
 {
     return(FF.StringAppend(uid.ToString(), "@", SF.GetTimeStamp().ToString(), ".log"));
 }
        /// <summary>
        /// Init the configuration, such as the ip, port, socket and arguments
        /// </summary>
        /// <param name="configPath"></param>
        public void InitializeConfig(out Ret ret, string configPath = "")
        {
            // Init config
            string path;

            if (configPath != "")
            {
                path = configPath;
            }
            else
            {
                path = FF.StringAppend(basicPath, @"..\..\DacLib\Hoxis\Configs\hoxis_server.toml");
            }
            config = new TomlConfiguration(path, out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server", true); return;
            }
            _logger.LogInfo("read configuration success", "Server");

            // Assign ip, port and init the sokcet
            localIP = SF.GetLocalIP(out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            port = config.GetInt("server", "port", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("ip is {0}, port is {1}", localIP, port.ToString()), "Server");

            // Init connection reception
            maxConn = config.GetInt("server", "max_conn", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _connReception = new CriticalPreformPool <HoxisConnection>(maxConn);
            _logger.LogInfo(FF.StringFormat("max connections is {0}", maxConn), "Server");

            // Init affair queue
            affairQueueCapacity = config.GetInt("server", "affair_queue_capacity", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("affair queue capacity is {0}", affairQueueCapacity), "Server");
            affairQueueProcessQuantity = config.GetShort("server", "affair_queue_process_quantity", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("affair queue process quantity is {0}", affairQueueProcessQuantity), "Server");
            _affairQueue               = new FiniteProcessQueue <KV <int, object> >(affairQueueCapacity, affairQueueProcessQuantity);
            _affairQueue.onProcess    += ProcessAffair;
            affairQueueProcessInterval = config.GetInt("server", "affair_queue_process_interval", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("affair queue process interval is {0}ms", affairQueueProcessInterval), "Server");

            // Init heartbeat update
            heartbeatUpdateInterval = config.GetInt("server", "heartbeat_update_interval", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("heartbeat update interval is {0}ms", heartbeatUpdateInterval), "Server");

            // Init connection
            HoxisConnection.readBufferSize = config.GetInt("conn", "read_buffer_size", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("read buffer size of connection is {0}", HoxisConnection.readBufferSize), "Server");

            // Init cluster
            _clusters            = new Dictionary <string, HoxisCluster>();
            HoxisCluster.maxUser = config.GetInt("cluster", "max_user", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("max users of cluster is {0}", HoxisCluster.maxUser), "Server");

            // Init team
            HoxisTeam.maxUser = config.GetInt("team", "max_user", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("max users of team is {0}", HoxisTeam.maxUser), "Server");

            // Init user
            HoxisUser.requestTTL = config.GetLong("user", "request_ttl", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("request time to live is {0}ms", HoxisUser.requestTTL), "Server");
            HoxisUser.heartbeatTimeout = config.GetInt("user", "heartbeat_timeout", out ret);
            if (ret.code != 0)
            {
                _logger.LogFatal(ret.desc, "Server"); return;
            }
            _logger.LogInfo(FF.StringFormat("heartbeat timeout is {0}ms", HoxisUser.heartbeatTimeout), "Server");

            _logger.LogInfo("init success", "Server", true);
        }