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); } } }
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); } } }
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); } }); }
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); } }); }
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()); })); }
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); })); }
void DisconnectInternal() { Proxy.RemoveClient(this); _disconnected = true; _serverSocket.SafeClose(); _clientSocket.SafeClose(); lock (_encryptionLock) { _clientEncryption.Dispose(); _clientEncryption = null; _serverEncryption.Dispose(); _serverEncryption = null; } Proxy.InvokeDisconnected(this); }
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); }