示例#1
0
        /// <summary>
        /// Handle a heartbeat timer elapse event, by requesting a heartbeat.
        /// </summary>
        /// <param name="sender">Unused.</param>
        /// <param name="e">Unused.</param>
        private void HeartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            DateTime        Now     = DateTime.UtcNow;
            NWServerTracker Tracker = MasterServer.Tracker;
            bool            Expired = false;

            //
            // First, check for server activity expiration.  If the server has
            // exceeded the heartbeat cut off, mark it as offline.
            //

            lock (this)
            {
                if (InitialHeartbeat)
                {
                    InitialHeartbeat = false;
                }
                else if ((Now >= LastHeartbeat) &&
                         (Now - LastHeartbeat) >= NWServerTracker.HeartbeatCutoffTimeSpan)
                {
                    ActivePlayerCount = 0;
                    Online            = false;
                    Expired           = true;

                    if (!Save())
                    {
                        Logger.Log(LogLevel.Error, "NWGameServer.HeartbeatTimer_Elapsed(): Server {0} could not be saved as expired.", this);
                        Expired = false;
                    }
                }
            }

            if (Expired)
            {
                Logger.Log(LogLevel.Normal, "NWGameServer.HeartbeatTimer_Elapsed(): Server {0} expired from online server list due to heartbeat timeout.", this);
                return;
            }

            //
            // Request the tracker to initiate this heartbeat request.  If the
            // server is not shutting down, continue on to queue the next
            // heartbeat expiration timer.
            //

            if (!MasterServer.Tracker.RequestHeartbeat(this))
            {
                return;
            }

            HeartbeatTimer.Interval = (HEARTBEAT_INTERVAL + (Rng.Next() % HEARTBEAT_JITTER));
            HeartbeatTimer.Start();
        }
示例#2
0
        /// <summary>
        /// Synchronously execute the server.
        /// </summary>
        public void Run()
        {
            //
            // Set the log file first, if one existed.
            //

            if (!String.IsNullOrEmpty(ServerSettings.Default.LogFileName))
                Logger.OpenLogFile(ServerSettings.Default.LogFileName);

            //
            // Set the log filter level.
            //

            Logger.LogFilterLevel = (LogLevel)Enum.Parse(typeof(LogLevel),
                ServerSettings.Default.LogLevel);

            try
            {
                bool IsShutdown = false;

                //
                // Bind the socket and prepare it for I/O.
                //

                SetupSockets();

                //
                // Create the underlying server tracker.
                //

                ServerTracker = new NWServerTracker(this);

                //
                // Queue the initial block of receive buffers.
                //

                MasterServerNATDuplicateSocket.InitiateAllReceives();
                GameSpySocket.InitiateAllReceives();
                MasterServerSocket.InitiateAllReceives();

                //
                // Inform the server tracker that it is clear to begin
                // heartbeat operations.
                //

                ServerTracker.QueueInitialHeartbeats();

                Logger.Log(LogLevel.Normal, "NWMasterServer.Run(): Master server version {0} initialized (game build advertised: {1}).",
                    Assembly.GetExecutingAssembly().GetName().Version,
                    BuildNumber);

                //
                // Block waiting for a quit request.  Once requested, initiate
                // shutdown on the socket and wait for outstanding receive
                // operations to drain.  Once these have drained, close the
                // socket and terminate the server.
                //

                for (; ; )
                {
                    QuitEvent.WaitOne();

                    if (!IsShutdown)
                    {
                        //
                        // Shut down future receives and inform the server
                        // tracker that new heartbeat requests should be
                        // drained out.
                        //

                        MasterServerSocket.Shutdown();
                        MasterServerNATDuplicateSocket.Shutdown();
                        GameSpySocket.Shutdown();

                        IsShutdown = true;
                        ServerTracker.DrainHeartbeats();
                    }

                    if (PendingBuffers == 0)
                        break;
                }

                //
                // Finally, flush any lingering pending queries.
                //

                lock (QueryCombineBuffer)
                {
                    if (QueryCombineBuffer.Length != 0)
                    {
                        ExecuteQueryNoReader(QueryCombineBuffer.ToString());
                        QueryCombineBuffer.Clear();
                    }
                }

                Logger.Log(LogLevel.Normal, "NWMasterServer.Run(): Main loop exiting.");

                if (ServiceObject != null)
                    ServiceObject.RequestStop();
            }
            catch (Exception e)
            {
                Logger.Log(LogLevel.Error, "NWMasterServer.Run(): Exception: {0}", e);
            }
        }