/// <summary>
 /// Used to clean up the target composer from memory
 /// </summary>
 /// <param name="composer">The composer that has completed</param>
 private void ComposerCompleted(UDPPacketComposer composer)
 {
     lock (pendingComposers)
     {
         pendingComposers.Remove(composer);
     }
 }
Example #2
0
        /// <summary>
        /// Star the next composer available composer
        /// </summary>
        private void NextComposerInQueue()
        {
            // If there are not currently any queued composers then we can stop here
            if (reliableComposers.Count == 0)
            {
                return;
            }

            // If there are no more composers in queue, end
            if (!nextComposerReady)
            {
                return;
            }

            // Prevent any queued composers from starting until this one finishes
            nextComposerReady = false;

            lock (reliableComposers)
            {
                currentComposer = reliableComposers[0];
            }

            if (!composerReady && Networker.IsBound && !NetWorker.ExitingApplication)
            {
                // Run this on a separate thread so that it doesn't interfere with the reading thread
                Task.Queue(() =>
                {
                    while (Networker.IsBound && !Disconnected)
                    {
                        if (nextComposerReady)
                        {
                            Task.Sleep(10);
                            continue;
                        }

                        do
                        {
                            lock (currentComposer.PendingPackets)
                            {
                                if (currentComposer.PendingPackets.Count > 0)
                                {
                                    if (Networker.LatencySimulation > 0)
                                    {
                                        Task.Sleep(Networker.LatencySimulation);
                                    }

                                    currentComposer.ResendPackets();
                                }
                            }

                            // TODO:  Wait the latency for this
                            Task.Sleep(10);
                        } while (!currentComposer.Player.Disconnected && currentComposer.PendingPackets.Count > 0 && Networker.IsBound && !NetWorker.ExitingApplication);
                    }
                });

                composerReady = true;
            }
        }
Example #3
0
        /// <summary>
        /// Used to clean up the target composer from memory
        /// </summary>
        /// <param name="composer">The composer that has completed</param>
        protected void ComposerCompleted(UDPPacketComposer composer)
        {
#if DEEP_LOGGING
            Logging.BMSLog.Log($"<<<<<<<<<<<<<<<<<<<<<<<<<<< CONFIRMING: {composer.Frame.UniqueId}");
#endif

            lock (pendingComposers) {
                pendingComposers.Remove(composer);
            }
        }
Example #4
0
        public override void Send(FrameStream frame, bool reliable = false)
        {
            UDPPacketComposer composer = new UDPPacketComposer();

            // If this message is reliable then make sure to keep a reference to the composer
            // so that there are not any run-away threads
            if (reliable)
            {
                composer.completed += ComposerCompleted;
                pendingComposers.Add(composer);
            }

            composer.Init(this, ServerPlayer, frame, reliable);
        }
Example #5
0
        public void QueueComposer(UDPPacketComposer composer)
        {
            if (Disconnected)
            {
                return;
            }

            lock (reliableComposers)
            {
                reliableComposers.Add(composer);
            }

            // Start the reliable send thread on this composer
            NextComposerInQueue();
        }
Example #6
0
        public void Send(NetworkingPlayer player, FrameStream frame, bool reliable = false)
        {
            UDPPacketComposer composer = new UDPPacketComposer(this, player, frame, reliable);

            // If this message is reliable then make sure to keep a reference to the composer
            // so that there are not any run-away threads
            if (reliable)
            {
                lock (pendingComposers) {
                    // Use the completed event to clean up the object from memory
                    composer.completed += ComposerCompleted;
                    pendingComposers.Add(composer);
                }
            }
        }
        public override void Send(FrameStream frame, bool reliable = false)
        {
            UDPPacketComposer composer = new UDPPacketComposer();

            // If this message is reliable then make sure to keep a reference to the composer
            // so that there are not any run-away threads
            if (reliable)
            {
                // Use the completed event to clean up the object from memory
                composer.completed += ComposerCompleted;
                pendingComposers.Add(composer);
            }

            //TODO: New constructor for setting up callbacks before regular constructor (as seen above)
            composer.Init(this, Server, frame, reliable);
        }
Example #8
0
        private void HandleMaximumClientPacketResponse(string incomingEndpoint, IPEndPoint groupEP)
        {
            // Tell the client why they are being disconnected
            Error frame = Error.CreateErrorMessage(Time.Timestep, "Max Players Reached On Server",
                                                   false, MessageGroupIds.MAX_CONNECTIONS, false);

            var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint,
                                                             false, groupEP, this);

            UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect, frame, false);

            // Send the close connection frame to the client
            UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect,
                                               new ConnectionClose(Time.Timestep, false, Receivers.Target,
                                                                   MessageGroupIds.DISCONNECT, false), false);
        }
Example #9
0
        private void HandleNotAcceptingConnectionsPacketResponse(string incomingEndpoint, IPEndPoint groupEP)
        {
            // Tell the client why they are being disconnected
            var frame = Error.CreateErrorMessage(Time.Timestep,
                                                 "The server is busy and not accepting connections", false,
                                                 MessageGroupIds.NOT_ACCEPT_CONNECTIONS, false);

            var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++,
                                                             incomingEndpoint, false, groupEP, this);

            UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect, frame, false);

            // Send the close connection frame to the client
            UDPPacketComposer.SendNewUDPPacket(this, playerToDisconnect,
                                               new ConnectionClose(Time.Timestep, false, Receivers.Target,
                                                                   MessageGroupIds.DISCONNECT, false), false);
        }
        public override void Send(FrameStream frame, bool reliable = false)
        {
            UDPPacketComposer composer = new UDPPacketComposer();

            //如果这个信息是可靠的,那么一定要保持对作曲家的引用
            //这样就没有任何失控的线程
            // If this message is reliable then make sure to keep a reference to the composer
            // so that there are not any run-away threads
            if (reliable)
            {
                //使用完成的事件从内存中清理对象
                // Use the completed event to clean up the object from memory
                composer.completed += ComposerCompleted;
                pendingComposers.Add(composer);
            }

            // TODO:在正则构造函数之前设置回调的新构造函数(如上所示)
            //TODO: New constructor for setting up callbacks before regular constructor (as seen above)
            composer.Init(this, Server, frame, reliable);
        }
Example #11
0
        private void SetupClient(BMSByte packet, string incomingEndpoint, IPEndPoint groupEP)
        {
            // Check for a local listing request
            if (packet.Size.Between(2, 4) && packet[0] == BROADCAST_LISTING_REQUEST_1 && packet[1] == BROADCAST_LISTING_REQUEST_2 && packet[2] == BROADCAST_LISTING_REQUEST_3)
            {
                // Don't reply if the server is not currently accepting connections
                if (!AcceptingConnections)
                {
                    return;
                }

                // This may be a local listing request so respond with the server flag byte
                Client.Send(new byte[] { SERVER_BROADCAST_CODE }, 1, groupEP);
                return;
            }

            if (Players.Count == MaxConnections)
            {
                // Tell the client why they are being disconnected
                var frame = Error.CreateErrorMessage(Time.Timestep, "Max Players Reached On Server", false, MessageGroupIds.MAX_CONNECTIONS, true);
                var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this);
                var composer           = new UDPPacketComposer(this, playerToDisconnect, frame, false);

                // Send the close connection frame to the client
                composer = new UDPPacketComposer(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), false);

                return;
            }
            else if (!AcceptingConnections)
            {
                // Tell the client why they are being disconnected
                var frame = Error.CreateErrorMessage(Time.Timestep, "The server is busy and not accepting connections", false, MessageGroupIds.NOT_ACCEPT_CONNECTIONS, true);
                var playerToDisconnect = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this);
                var composer           = new UDPPacketComposer(this, playerToDisconnect, frame, false);

                // Send the close connection frame to the client
                composer = new UDPPacketComposer(this, playerToDisconnect, new ConnectionClose(Time.Timestep, false, Receivers.Target, MessageGroupIds.DISCONNECT, false), false);

                return;
            }

            // Validate that the connection headers are properly formatted
            byte[] response = Websockets.ValidateConnectionHeader(packet.CompressBytes());

            // The response will be null if the header sent is invalid, if so then disconnect client as they are sending invalid headers
            if (response == null)
            {
                return;
            }

            UDPNetworkingPlayer player = new UDPNetworkingPlayer(ServerPlayerCounter++, incomingEndpoint, false, groupEP, this);

            // If all is in order then send the validated response to the client
            Client.Send(response, response.Length, groupEP);

            OnPlayerConnected(player);
            udpPlayers.Add(incomingEndpoint, player);

            // The player has successfully connected
            player.Connected = true;
        }