Beispiel #1
0
        void Receive(Direction direction, byte[] headerBuffer, byte[] payloadBuffer)
        {
            headerBuffer  = headerBuffer ?? new byte[PacketHeader.HeaderSize];
            payloadBuffer = payloadBuffer ?? new byte[PacketHeader.MaxPayloadSize];

            Socket from;
            Socket to;
            TeraEncryptionSession fromEnc;
            TeraEncryptionSession toEnc;

            if (direction == Direction.ClientToServer)
            {
                from    = _clientSocket;
                to      = _serverSocket;
                fromEnc = _clientEncryption;
                toEnc   = _serverEncryption;
            }
            else
            {
                from    = _serverSocket;
                to      = _clientSocket;
                fromEnc = _serverEncryption;
                toEnc   = _clientEncryption;
            }

            var toServer   = to == _serverSocket;
            var fromServer = to == _serverSocket;

            bool DoReceive()
            {
                try
                {
                    ReceiveInternal(headerBuffer, PacketHeader.HeaderSize,
                                    from, fromEnc, fromServer);

                    var header = PacketProcessor.ReadHeader(headerBuffer);

                    if (!Proxy.Processor.Serializer.Messages.Game.OpCodeToName
                        .ContainsKey(header.OpCode))
                    {
                        DisconnectInternal();
                        _log.Error("Disconnected client {0} from {1} due to invalid opcode: {2}",
                                   EndPoint, Proxy.Info.Name, header.OpCode);
                        return(false);
                    }

                    if (header.Length > PacketHeader.MaxPayloadSize)
                    {
                        DisconnectInternal();
                        _log.Error("Disconnected client {0} from {1} due to invalid packet length: {2}",
                                   EndPoint, Proxy.Info.Name, header.Length);
                        return(false);
                    }

                    ReceiveInternal(payloadBuffer, header.Length,
                                    from, fromEnc, fromServer);

                    // Can be set to a new array.
                    var payload = payloadBuffer;

                    if (Proxy.Processor.Process(this, direction, ref header, ref payload))
                    {
                        PacketProcessor.WriteHeader(header, headerBuffer);

                        SendInternal(headerBuffer, headerBuffer.Length,
                                     true, to, toEnc, toServer);
                        SendInternal(payload, header.Length,
                                     true, to, toEnc, toServer);
                    }
                }
                catch (SocketDisconnectedException)
                {
                    // Normal disconnection.
                    Disconnect();
                    return(false);
                }
                catch (Exception e) when(IsSocketException(e))
                {
                    // The client is already disconnected.
                    return(false);
                }

                return(true);
            }

            // If we don't expect a large number of clients, just use dedicated
            // tasks to receive data instead of spawning a new one per receive.
            if (Proxy.MaxClients <= Environment.ProcessorCount)
            {
                Task.Factory.StartNew(() =>
                {
                    while (DoReceive())
                    {
                    }
                }, TaskCreationOptions.LongRunning);
            }
            else
            {
                Task.Run(() =>
                {
                    DoReceive();

                    Receive(direction, headerBuffer, payloadBuffer);
                });
            }
        }
Beispiel #2
0
        void Receive(Direction direction, byte[] headerBuffer, byte[] payloadBuffer)
        {
            headerBuffer  = headerBuffer ?? new byte[PacketHeader.HeaderSize];
            payloadBuffer = payloadBuffer ?? new byte[PacketHeader.MaxPayloadSize];

            Socket from;
            Socket to;
            TeraEncryptionSession fromEnc;
            TeraEncryptionSession toEnc;

            if (direction == Direction.ClientToServer)
            {
                from    = _clientSocket;
                to      = _serverSocket;
                fromEnc = _clientEncryption;
                toEnc   = _serverEncryption;
            }
            else
            {
                from    = _serverSocket;
                to      = _clientSocket;
                fromEnc = _serverEncryption;
                toEnc   = _clientEncryption;
            }

            var toServer   = to == _serverSocket;
            var fromServer = to == _serverSocket;

            bool DoReceive()
            {
                try
                {
                    ReceiveInternal(headerBuffer, PacketHeader.HeaderSize,
                                    from, fromEnc, fromServer);

                    var header = PacketProcessor.ReadHeader(headerBuffer);

                    ReceiveInternal(payloadBuffer, header.Length,
                                    from, fromEnc, fromServer);

                    // Can be set to a new array.
                    var payload = payloadBuffer;

                    if (Proxy.Processor.Process(this, direction, ref header, ref payload))
                    {
                        PacketProcessor.WriteHeader(header, headerBuffer);

                        SendInternal(headerBuffer, headerBuffer.Length,
                                     true, to, toEnc, toServer);
                        SendInternal(payload, header.Length,
                                     true, to, toEnc, toServer);
                    }
                }
                catch (Exception e) when(IsSocketException(e))
                {
                    // The client is already disconnected.
                    return(false);
                }

                return(true);
            }

            // If we don't expect a large number of clients, just use dedicated
            // tasks to receive data instead of spawning a new one per receive.
            if (Proxy.MaxClients <= Environment.ProcessorCount)
            {
                Task.Factory.StartNew(() =>
                {
                    while (DoReceive())
                    {
                    }
                }, TaskCreationOptions.LongRunning);
            }
            else
            {
                Task.Run(() =>
                {
                    DoReceive();

                    Receive(direction, headerBuffer, payloadBuffer);
                });
            }
        }