Example #1
0
        bool SendRawPacketInternal(RawPacket packet, byte[] buffer, Socket socket,
                                   GameEncryptionSession encryption, bool server)
        {
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet));
            }

            if (packet.Payload.Length > PacketHeader.MaxPayloadSize)
            {
                throw new ArgumentException("Packet is too big.", nameof(packet));
            }

            var header = new PacketHeader((ushort)packet.Payload.Length,
                                          Proxy.Processor.Serializer.GameMessages.NameToCode[packet.Name]);

            lock (socket)
            {
                PacketProcessor.WriteHeader(header, buffer);
                Buffer.BlockCopy(packet.Payload, 0, buffer, PacketHeader.HeaderSize, header.Length);

                try
                {
                    return(SendInternal(buffer, header.FullLength, false, socket, encryption, server));
                }
                catch (SocketDisconnectedException)
                {
                    // Normal disconnection.
                    return(false);
                }
            }
        }
Example #2
0
        bool SendPacketInternal(Direction direction, SerializablePacket packet, Memory <byte> buffer,
                                GameBinaryWriter writer, Socket socket, GameEncryptionSession encryption, bool server,
                                bool direct)
        {
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet));
            }

            var payload = Proxy.Serializer.Serialize(packet).AsMemory();

            if (payload.Length > PacketHeader.MaxPayloadSize)
            {
                throw new ArgumentException("Packet is too large.", nameof(packet));
            }

            var code     = Proxy.Serializer.GameMessages.NameToCode[packet.Name];
            var original = payload;
            var send     = Proxy.InvokeSent(this, direction, code, ref payload, direct);

            if (!send)
            {
                return(false);
            }

            // A handler might have created a packet that's too large.
            if (payload.Length > PacketHeader.MaxPayloadSize)
            {
                _log.Error(
                    "{0}: Forged packet {1} is too large ({2} bytes) to be sent correctly after running handlers; sending original",
                    direction.ToDirectionString(), packet.Name, payload.Length);

                payload = original;
            }

            lock (socket)
            {
                var header = new PacketHeader((ushort)payload.Length, code);

                WriteHeader(writer, header);
                payload.CopyTo(buffer.Slice(PacketHeader.HeaderSize, header.Length));

                try
                {
                    return(SendInternal(buffer.Slice(0, header.FullLength), false, socket, encryption, server));
                }
                catch (SocketDisconnectedException)
                {
                    // Normal disconnection.
                    return(false);
                }
            }
        }
Example #3
0
        void ReceiveInternal(Memory <byte> data, Socket socket, GameEncryptionSession encryption,
                             bool server)
        {
            RunGuarded(true, server, () =>
            {
                socket.ReceiveFull(data.GetArray());

                lock (_encryptionLock)
                    if (encryption != null)
                    {
                        encryption.Decrypt(data);
                    }
            });
        }
Example #4
0
        void ReceiveInternal(byte[] data, int length, Socket socket, GameEncryptionSession encryption,
                             bool server)
        {
            RunGuarded(true, server, () =>
            {
                socket.ReceiveFull(data, 0, length);

                if (encryption != null)
                {
                    lock (encryption)
                        encryption.Decrypt(data, 0, length);
                }
            });
        }
Example #5
0
        bool SendInternal(Memory <byte> data, bool rethrow, Socket socket,
                          GameEncryptionSession encryption, bool server)
        {
            return(RunGuarded(rethrow, server, () =>
            {
                lock (_encryptionLock)
                    if (encryption != null)
                    {
                        encryption.Encrypt(data);
                    }

                lock (socket)
                    socket.SendFull(data.GetArray());
            }));
        }
Example #6
0
        bool SendInternal(byte[] data, int length, bool rethrow, Socket socket,
                          GameEncryptionSession encryption, bool server)
        {
            return(RunGuarded(rethrow, server, () =>
            {
                if (encryption != null)
                {
                    lock (encryption)
                        encryption.Encrypt(data, 0, length);
                }

                lock (socket)
                    socket.SendFull(data, 0, length);
            }));
        }
Example #7
0
        void DisconnectInternal()
        {
            Proxy.RemoveClient(this);

            _disconnected = true;

            _serverSocket.SafeClose();
            _clientSocket.SafeClose();

            lock (_encryptionLock)
            {
                _clientEncryption.Dispose();
                _clientEncryption = null;

                _serverEncryption.Dispose();
                _serverEncryption = null;
            }

            Proxy.InvokeDisconnected(this);
        }
Example #8
0
        void OnConnect(object sender, SocketAsyncEventArgs args)
        {
            var error = args.SocketError;

            args.Completed -= OnConnect;
            Proxy.ArgsPool.TryPut(args);

            if (error != SocketError.Success && error != SocketError.OperationAborted)
            {
                DisconnectInternal();
                _log.Error("Could not connect to {0} ({1}) for client {2}: {3}", Proxy.Info.Name,
                           Proxy.Info.RealEndPoint, EndPoint, error);
                return;
            }

            _log.Info("Connected to {0} ({1}) for client {2}", Proxy.Info.Name,
                      Proxy.Info.RealEndPoint, EndPoint);

            byte[] ckey1;
            byte[] ckey2;
            byte[] skey1;
            byte[] skey2;

            try
            {
                var magic = ReceiveFromServerInternal(_magic.Length);
                SendToClientInternal(magic, true);

                if (!magic.SequenceEqual(_magic))
                {
                    DisconnectInternal();
                    _log.Error("Disconnected client {0} from {1} due to incorrect magic bytes: {2}",
                               EndPoint, Proxy.Info.Name, magic.Aggregate("0x", (acc, x) => acc + x.ToString("X2")));
                    return;
                }

                ckey1 = ReceiveFromClientInternal(GameEncryptionSession.KeySize);
                SendToServerInternal(ckey1, true);

                skey1 = ReceiveFromServerInternal(GameEncryptionSession.KeySize);
                SendToClientInternal(skey1, true);

                ckey2 = ReceiveFromClientInternal(GameEncryptionSession.KeySize);
                SendToServerInternal(ckey2, true);

                skey2 = ReceiveFromServerInternal(GameEncryptionSession.KeySize);
                SendToClientInternal(skey2, true);
            }
            catch (SocketDisconnectedException)
            {
                // Normal disconnection.
                Disconnect();
                return;
            }
            catch (Exception e) when(IsSocketException(e))
            {
                // The client is already disconnected.
                return;
            }

            _clientEncryption = new GameEncryptionSession(Direction.ClientToServer, ckey1, ckey2, skey1, skey2);
            _serverEncryption = new GameEncryptionSession(Direction.ServerToClient, ckey1, ckey2, skey1, skey2);

            _log.Info("Established encrypted session for client {0}", EndPoint);

            Receive(Direction.ClientToServer, null, null, null, null, false);
            Receive(Direction.ServerToClient, null, null, null, null, false);

            Proxy.InvokeConnected(this);
        }