Пример #1
0
        /// <summary>
        /// Shutsdown the ClientManager server and socket
        /// </summary>
        public void Shutdown()
        {
            // Stop accepting new connections
            base.IgnoreNewConnections = true;
            Exiting = true;

            // Unregister events so we dont get a shit ton of calls
            GpcmClient.OnSuccessfulLogin -= GpcmClient_OnSuccessfulLogin;
            GpcmClient.OnDisconnect      -= GpcmClient_OnDisconnect;

            // Discard the poll timer
            PollTimer.Stop();
            PollTimer.Dispose();
            StatusTimer.Stop();
            StatusTimer.Dispose();

            // Disconnected all connected clients
            Console.WriteLine("Disconnecting all users...");
            Parallel.ForEach(Clients.Values, client => client.Disconnect(DisconnectReason.ForcedServerShutdown));
            Parallel.ForEach(Processing.Values, client => client.Disconnect(DisconnectReason.ForcedServerShutdown));

            // Update the database
            try
            {
                // Set everyone's online session to 0
                using (Database.GamespyDatabase db = new Database.GamespyDatabase())
                    db.Execute("UPDATE player SET online=0");
            }
            catch (Exception e)
            {
                Program.ErrorLog.Write("WARNING: [GpcmServer.Shutdown] Failed to update client database: " + e.Message);
            }

            // Update Connected Clients in the Database
            Clients.Clear();

            // Shutdown the listener socket
            base.ShutdownSocket();

            // Tell the base to dispose all free objects
            base.Dispose();
        }
Пример #2
0
        /// <summary>
        /// Creates a new instance of <see cref="GpcmServer"/>
        /// </summary>
        /// <param name="bindTo"></param>
        public GpcmServer(IPEndPoint bindTo) : base(bindTo, MaxConnections)
        {
            // Register for events
            GpcmClient.OnSuccessfulLogin += GpcmClient_OnSuccessfulLogin;
            GpcmClient.OnDisconnect      += GpcmClient_OnDisconnect;

            // Setup timer. Every 15 seconds should be sufficient
            if (PollTimer == null || !PollTimer.Enabled)
            {
                PollTimer          = new System.Timers.Timer(15000);
                PollTimer.Elapsed += (s, e) =>
                {
                    // Send keep alive to all connected clients
                    if (Clients.Count > 0)
                    {
                        Parallel.ForEach(Clients.Values, client => client.SendKeepAlive());
                    }

                    // Disconnect hanging connections
                    if (Processing.Count > 0)
                    {
                        Parallel.ForEach(Processing.Values, client => CheckTimeout(client));
                    }
                };
                PollTimer.Start();
            }

            // Setup timer. Every 5 seconds should be sufficient
            if (StatusTimer == null || !StatusTimer.Enabled)
            {
                StatusTimer          = new System.Timers.Timer(5000);
                StatusTimer.Elapsed += (s, e) =>
                {
                    // Return if we are empty
                    if (PlayerStatusQueue.IsEmpty)
                    {
                        return;
                    }

                    // Open database connection
                    using (Database.GamespyDatabase db = new Database.GamespyDatabase())
                        using (var transaction = db.BeginTransaction())
                        {
                            try
                            {
                                var timestamp = DateTime.UtcNow.ToUnixTimestamp();
                                PlayerStatusUpdate result;
                                while (PlayerStatusQueue.TryDequeue(out result))
                                {
                                    // Skip if this player never finished logging in
                                    if (!result.Client.CompletedLoginProcess)
                                    {
                                        continue;
                                    }

                                    // Only update record under these two status'
                                    if (result.Status != LoginStatus.Completed && result.Status != LoginStatus.Disconnected)
                                    {
                                        continue;
                                    }

                                    // Update player record
                                    db.Execute(
                                        "UPDATE player SET online=@P0, lastip=@P1, lastonline=@P2 WHERE id=@P3",
                                        (result.Status == LoginStatus.Disconnected) ? 0 : 1,
                                        result.Client.RemoteEndPoint.Address,
                                        timestamp,
                                        result.Client.PlayerId
                                        );
                                }

                                transaction.Commit();
                            }
                            catch (Exception ex)
                            {
                                ServerManager.Log("[Gpcm..ctor] StatusTimer: " + ex.Message);
                                transaction.Rollback();
                            }
                        }
                };
                StatusTimer.Start();
            }

            // Set connection handling
            base.ConnectionEnforceMode = EnforceMode.DuringPrepare;
            base.FullErrorMessage      = Config.GetValue("Settings", "LoginServerFullMessage").Replace("\"", "");

            // Begin accepting connections
            base.StartAcceptAsync();
        }