Пример #1
0
		private void ReceiveCallback(IAsyncResult ar)
		{
			UdpClient listener = (UdpClient) ar.AsyncState;

			// Check if we already closed the server
			if (listener.Client == null) return;

			// WSAECONNRESET:
			// The virtual circuit was reset by the remote side executing a hard or abortive close. 
			// The application should close the socket; it is no longer usable. On a UDP-datagram socket 
			// this error indicates a previous send operation resulted in an ICMP Port Unreachable message.
			// Note the spocket settings on creation of the server. It makes us ignore these resets.
			IPEndPoint senderEndpoint = new IPEndPoint(0, 0);
			Byte[] receiveBytes = null;
			try
			{
				receiveBytes = listener.EndReceive(ar, ref senderEndpoint);
			}
			catch (Exception e)
			{
				Log.Error("Unexpected end of transmission?", e);
				if (listener.Client != null)
				{
					try
					{
						listener.BeginReceive(ReceiveCallback, listener);
					}
					catch (ObjectDisposedException dex)
					{
						Log.Error("Unexpected end of transmission?", dex);
					}
				}

				return;
			}

			if (receiveBytes.Length != 0)
			{
				listener.BeginReceive(ReceiveCallback, listener);
				ServerInfo.AvailableBytes = listener.Available;
				ServerInfo.NumberOfPacketsInPerSecond++;
				ServerInfo.TotalPacketSizeIn += receiveBytes.Length;
				try
				{
					if (!GreylistManager.IsWhitelisted(senderEndpoint.Address) && GreylistManager.IsBlacklisted(senderEndpoint.Address)) return;
					if (GreylistManager.IsGreylisted(senderEndpoint.Address)) return;
					ProcessMessage(receiveBytes, senderEndpoint);
				}
				catch (Exception e)
				{
					//Log.Warn(string.Format("Process message error from: {0}", senderEndpoint.Address), e);
				}
			}
			else
			{
				//Log.Error("Unexpected end of transmission?");
			}
		}
Пример #2
0
        private void HandleRakNetMessage(IPEndPoint senderEndpoint, OpenConnectionRequest1 incoming)
        {
            if (!GreylistManager.AcceptConnection(senderEndpoint))
            {
                var noFree = NoFreeIncomingConnections.CreateObject();
                var bytes  = noFree.Encode();
                noFree.PutPool();

                TraceSend(noFree);

                SendData(bytes, senderEndpoint, new object());
                return;
            }

            if (Log.IsDebugEnabled)
            {
                Log.DebugFormat("New connection from: {0} {1}", senderEndpoint.Address, senderEndpoint.Port);
            }

            lock (_playerSessions)
            {
                // Already connecting, then this is just a duplicate
                if (_connectionAttemps.ContainsKey(senderEndpoint))
                {
                    DateTime created;
                    _connectionAttemps.TryGetValue(senderEndpoint, out created);

                    if (DateTime.UtcNow < created + TimeSpan.FromSeconds(3))
                    {
                        return;
                    }

                    _connectionAttemps.TryRemove(senderEndpoint, out created);
                }

                if (!_connectionAttemps.TryAdd(senderEndpoint, DateTime.UtcNow))
                {
                    return;
                }
            }

            var packet = OpenConnectionReply1.CreateObject();

            packet.serverGuid        = 12345;
            packet.mtuSize           = incoming.mtuSize;
            packet.serverHasSecurity = 0;
            var data = packet.Encode();

            packet.PutPool();

            TraceSend(packet);

            SendData(data, senderEndpoint, new object());
        }
Пример #3
0
        private void Receive(object state)
        {
            var listener = (UdpClient)state;

            while (true)
            {
                // Check if we already closed the server
                if (listener.Client == null)
                {
                    return;
                }

                // WSAECONNRESET:
                // The virtual circuit was reset by the remote side executing a hard or abortive close.
                // The application should close the socket; it is no longer usable. On a UDP-datagram socket
                // this error indicates a previous send operation resulted in an ICMP Port Unreachable message.
                // Note the spocket settings on creation of the server. It makes us ignore these resets.
                IPEndPoint senderEndpoint = null;
                try
                {
                    ReadOnlyMemory <byte> receiveBytes = listener.Receive(ref senderEndpoint);
                    //UdpReceiveResult result = listener.ReceiveAsync().Result;
                    //senderEndpoint = result.RemoteEndPoint;
                    //byte[] receiveBytes = result.Buffer;

                    Interlocked.Increment(ref ServerInfo.NumberOfPacketsInPerSecond);
                    Interlocked.Add(ref ServerInfo.TotalPacketSizeInPerSecond, receiveBytes.Length);

                    if (receiveBytes.Length != 0)
                    {
                        _receiveThreadPool.QueueUserWorkItem(() =>
                        {
                            try
                            {
                                if (!GreylistManager.IsWhitelisted(senderEndpoint.Address) && GreylistManager.IsBlacklisted(senderEndpoint.Address))
                                {
                                    return;
                                }
                                if (GreylistManager.IsGreylisted(senderEndpoint.Address))
                                {
                                    return;
                                }

                                ProcessMessage(this, receiveBytes, senderEndpoint);
                            }
                            catch (Exception e)
                            {
                                Log.Warn($"Process message error from: {senderEndpoint.Address}", e);
                            }
                        });
                    }
                    else
                    {
                        Log.Warn("Unexpected end of transmission?");
                        continue;
                    }
                }
                catch (SocketException e)
                {
                    if (e.ErrorCode != 10004)
                    {
                        Log.Error("Unexpected end of receive", e);
                    }

                    if (listener.Client != null)
                    {
                        continue;
                    }

                    return;
                }
            }
        }
Пример #4
0
        private void HandleRakNetMessage(byte[] receiveBytes, IPEndPoint senderEndpoint, byte msgId)
        {
            DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes)msgId;

            // Increase fast, decrease slow on 1s ticks.
            if (ServerInfo.NumberOfPlayers < ServerInfo.PlayerSessions.Count)
            {
                ServerInfo.NumberOfPlayers = ServerInfo.PlayerSessions.Count;
            }

            // Shortcut to reply fast, and no parsing
            if (msgIdType == DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1)
            {
                if (!GreylistManager.AcceptConnection(senderEndpoint.Address))
                {
                    var noFree = NoFreeIncomingConnections.CreateObject();
                    var bytes  = noFree.Encode();
                    noFree.PutPool();

                    TraceSend(noFree);

                    SendData(bytes, senderEndpoint);
                    Interlocked.Increment(ref ServerInfo.NumberOfDeniedConnectionRequestsPerSecond);
                    return;
                }
            }

            Package message = null;

            try
            {
                try
                {
                    message = PackageFactory.CreatePackage(msgId, receiveBytes, "raknet");
                }
                catch (Exception)
                {
                    message = null;
                }

                if (message == null)
                {
                    GreylistManager.Blacklist(senderEndpoint.Address);
                    Log.ErrorFormat("Receive bad packet with ID: {0} (0x{0:x2}) {2} from {1}", msgId, senderEndpoint.Address, (DefaultMessageIdTypes)msgId);

                    return;
                }

                TraceReceive(message);

                switch (msgIdType)
                {
                case DefaultMessageIdTypes.ID_UNCONNECTED_PING:
                case DefaultMessageIdTypes.ID_UNCONNECTED_PING_OPEN_CONNECTIONS:
                {
                    HandleRakNetMessage(senderEndpoint, (UnconnectedPing)message);
                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1:
                {
                    HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest1)message);
                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_2:
                {
                    HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest2)message);
                    break;
                }

                default:
                    GreylistManager.Blacklist(senderEndpoint.Address);
                    Log.ErrorFormat("Receive unexpected packet with ID: {0} (0x{0:x2}) {2} from {1}", msgId, senderEndpoint.Address, (DefaultMessageIdTypes)msgId);
                    break;
                }
            }
            finally
            {
                if (message != null)
                {
                    message.PutPool();
                }
            }
        }
Пример #5
0
        private void ProcessMessage(byte[] receiveBytes, IPEndPoint senderEndpoint)
        {
            byte msgId = receiveBytes[0];

            if (msgId == 0xFE)
            {
                Log.InfoFormat("A query detected from: {0}", senderEndpoint.Address);
                HandleQuery(receiveBytes, senderEndpoint);
            }
            else if (msgId <= (byte)DefaultMessageIdTypes.ID_USER_PACKET_ENUM)
            {
                HandleRakNetMessage(receiveBytes, senderEndpoint, msgId);
            }
            else
            {
                PlayerNetworkSession playerSession;
                if (!_playerSessions.TryGetValue(senderEndpoint, out playerSession))
                {
                    //Log.DebugFormat("Receive MCPE message 0x{1:x2} without session {0}", senderEndpoint.Address, msgId);
                    //if (!_badPacketBans.ContainsKey(senderEndpoint.Address))
                    //{
                    //	_badPacketBans.Add(senderEndpoint.Address, true);
                    //}
                    return;
                }

                if (playerSession.MessageHandler == null)
                {
                    Log.ErrorFormat("Receive MCPE message 0x{1:x2} without message handler {0}. Session removed.", senderEndpoint.Address, msgId);
                    _playerSessions.TryRemove(senderEndpoint, out playerSession);
                    //if (!_badPacketBans.ContainsKey(senderEndpoint.Address))
                    //{
                    //	_badPacketBans.Add(senderEndpoint.Address, true);
                    //}
                    return;
                }

                if (playerSession.Evicted)
                {
                    return;
                }

                playerSession.LastUpdatedTime = DateTime.UtcNow;

                DatagramHeader header = new DatagramHeader(receiveBytes[0]);
                if (!header.isACK && !header.isNAK && header.isValid)
                {
                    if (receiveBytes[0] == 0xa0)
                    {
                        throw new Exception("Receive ERROR, NAK in wrong place");
                    }

                    ConnectedPackage package = ConnectedPackage.CreateObject();
                    try
                    {
                        package.Decode(receiveBytes);
                    }
                    catch (Exception e)
                    {
                        playerSession.Disconnect("Bad package received from client.");

                        Log.Warn($"Bad packet {receiveBytes[0]}\n{Package.HexDump(receiveBytes)}", e);

                        GreylistManager.Blacklist(senderEndpoint.Address);

                        return;
                    }


                    // IF reliable code below is enabled, useItem start sending doubles
                    // for some unknown reason.

                    //Reliability reliability = package._reliability;
                    //if (reliability == Reliability.Reliable
                    //	|| reliability == Reliability.ReliableSequenced
                    //	|| reliability == Reliability.ReliableOrdered
                    //	)
                    {
                        EnqueueAck(playerSession, package._datagramSequenceNumber);
                        //if (Log.IsDebugEnabled) Log.Debug("ACK on #" + package._datagramSequenceNumber.IntValue());
                    }

                    HandleConnectedPackage(playerSession, package);
                    package.PutPool();
                }
                else if (header.isACK && header.isValid)
                {
                    HandleAck(playerSession, receiveBytes);
                }
                else if (header.isNAK && header.isValid)
                {
                    HandleNak(playerSession, receiveBytes);
                }
                else if (!header.isValid)
                {
                    Log.Warn("!!!! ERROR, Invalid header !!!!!");
                }
            }
        }
Пример #6
0
        private void HandleRakNetMessage(byte[] receiveBytes, IPEndPoint senderEndpoint, byte msgId)
        {
            DefaultMessageIdTypes msgIdType = (DefaultMessageIdTypes)msgId;

            Package message = null;

            try
            {
                try
                {
                    message = PackageFactory.CreatePackage(msgId, receiveBytes);
                }
                catch (Exception)
                {
                    message = null;
                }

                if (message == null)
                {
                    GreylistManager.Blacklist(senderEndpoint.Address);
                    Log.ErrorFormat("Receive bad packet with ID: {0} (0x{0:x2}) {2} from {1}", msgId, senderEndpoint.Address, (DefaultMessageIdTypes)msgId);

                    return;
                }

                TraceReceive(message);

                switch (msgIdType)
                {
                case DefaultMessageIdTypes.ID_UNCONNECTED_PING:
                case DefaultMessageIdTypes.ID_UNCONNECTED_PING_OPEN_CONNECTIONS:
                {
                    HandleRakNetMessage(senderEndpoint, (UnconnectedPing)message);
                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_1:
                {
                    HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest1)message);
                    break;
                }

                case DefaultMessageIdTypes.ID_OPEN_CONNECTION_REQUEST_2:
                {
                    HandleRakNetMessage(senderEndpoint, (OpenConnectionRequest2)message);
                    break;
                }

                default:
                    GreylistManager.Blacklist(senderEndpoint.Address);
                    Log.ErrorFormat("Receive unexpected packet with ID: {0} (0x{0:x2}) {2} from {1}", msgId, senderEndpoint.Address, (DefaultMessageIdTypes)msgId);
                    break;
                }
            }
            finally
            {
                if (message != null)
                {
                    message.PutPool();
                }
            }
        }