protected override void Init(Server server) { m_Server = server; m_RSACryptoPrivate = new RSACryptoServiceProvider(RSAKeySize); m_RSACryptoPrivate.PersistKeyInCsp = false; m_SendPacketSerial = 0; m_ReceivePacketSerial = 0; IgeNetStream stream = GetStream(); stream.CalculateChecksums = true; m_WriterStream = new BinaryWriter(stream); m_CanProcessPackets.Reset(); (m_PacketReceiverThread = new Thread(PacketReceiverThread)).Start(GetStream()); base.Init(server); }
private void SendNonBlocking(Packet packet) { PacketEncryptionMethod encryption = packet.Encryption; lock (SyncSend) { if (m_WriterStream == null || !Connected) { throw new IOException("Client is not connected"); } IgeNetStream stream = (IgeNetStream)m_WriterStream.BaseStream; if (GameDebugger.MinNetLogLevel <= LogLevel.VerboseDebug) { Log(LogLevel.VerboseDebug, "Sending packet: '{0}'. Packet contents: {1}", packet.GetType().FullName, packet.ToString()); } else { Log(LogLevel.Debug, "Sending packet: '{0}'", packet.GetType().FullName); } // Log(LogLevel.Debug, "Resetting send checksum"); // stream.ResetWriteChecksum(); //Thread.MemoryBarrier(); Log(LogLevel.Debug, "Sending packet id: 0x{0:X8}", packet.Id); m_WriterStream.Write(packet.Id); switch (encryption) { case PacketEncryptionMethod.RSA: { Log(LogLevel.Debug, "Serializing packet to a RSA encrypted block"); using (BinaryWriter cryptoWriter = new BinaryWriter(new MemoryStream(), Encoding.Unicode)) { packet.Serialize(cryptoWriter); byte[] cryptoData = m_RSACryptoPublic.Encrypt(((MemoryStream)cryptoWriter.BaseStream).ToArray(), false); Log(LogLevel.Debug, "Encrypted serialized block size: {0}", cryptoData.Length); m_WriterStream.Write(cryptoData.Length); m_WriterStream.Write(cryptoData); } break; } case PacketEncryptionMethod.Rijndael: { Log(LogLevel.Debug, "Serializing packet to a Rijndael crypto stream"); using (MemoryStream mem = new MemoryStream()) { using (BinaryWriter cryptoWriter = new BinaryWriter(new CryptoStream(mem, m_RijCrypto.CreateEncryptor(), CryptoStreamMode.Write), Encoding.Unicode)) { packet.Serialize(cryptoWriter); } byte[] cryptoData = mem.ToArray(); Log(LogLevel.Debug, "Encrypted serialized block size: {0}", cryptoData.Length); m_WriterStream.Write(cryptoData.Length); m_WriterStream.Write(cryptoData); } break; } default: { Log(LogLevel.Debug, "Serializing packet to a write stream"); packet.Serialize(m_WriterStream); break; } } uint checksum = stream.WriteChecksum ^ unchecked (m_SendPacketSerial++); //Thread.MemoryBarrier(); Log(LogLevel.Debug, "Sending checksum: 0x{0:X8}", checksum); m_WriterStream.Write(checksum); //Thread.MemoryBarrier(); Log(LogLevel.Debug, "Packet sending done"); } }
private void PacketReceiverThread(object param) { IgeNetStream stream = (IgeNetStream)param; Log(LogLevel.Debug, "PacketReceiverThread: start"); try { using (BinaryReader reader = new BinaryReader(stream)) { Packet packet; uint packetId, checksum, checksum2; ((IgeNetStream)reader.BaseStream).CalculateChecksums = true; while (true) { // Log(LogLevel.Debug, "PacketReceiverThread: resetting read checksum"); // stream.ResetReadChecksum(); //Thread.MemoryBarrier(); Log(LogLevel.Debug, "PacketReceiverThread: reading packet id"); packetId = reader.ReadUInt32(); Log(LogLevel.Debug, "PacketReceiverThread: creating packet 0x{0:X8} instance", packetId); packet = Packet.CreateInstance(packetId); switch (packet.Encryption) { case PacketEncryptionMethod.RSA: { int cryptoSize = reader.ReadInt32(); Log(LogLevel.Debug, "PacketReceiverThread: deserializing packet 0x{0:X8} from an RSA encrypted block ({1} bytes)", packetId, cryptoSize); using (BinaryReader cryptoReader = new BinaryReader(new MemoryStream(m_RSACryptoPrivate.Decrypt(reader.ReadBytes(cryptoSize), false)), Encoding.Unicode)) { packet.Deserialize(cryptoReader); } break; } case PacketEncryptionMethod.Rijndael: { int cryptoSize = reader.ReadInt32(); Log(LogLevel.Debug, "PacketReceiverThread: deserializing packet 0x{0:X8} from a Rijndael crypto stream ({1} bytes)", packetId, cryptoSize); using (MemoryStream mem = new MemoryStream(reader.ReadBytes(cryptoSize))) { using (BinaryReader cryptoReader = new BinaryReader(new CryptoStream(mem, m_RijCrypto.CreateDecryptor(), CryptoStreamMode.Read), Encoding.Unicode)) { packet.Deserialize(cryptoReader); } } break; } default: { Log(LogLevel.Debug, "PacketReceiverThread: deserializing packet 0x{0:X8} from a read stream", packetId); packet.Deserialize(reader); break; } } if (GameDebugger.MinNetLogLevel <= LogLevel.VerboseDebug) { Log(LogLevel.VerboseDebug, "PacketReceiverThread: received packet '{0}'. Packet contents: {1}", packet.GetType().FullName, packet.ToString()); } else { Log(LogLevel.Debug, "PacketReceiverThread: received packet '{0}'", packet.GetType().FullName); } //Thread.MemoryBarrier(); // packet.Deserialize(reader); checksum = stream.ReadChecksum ^ unchecked (m_ReceivePacketSerial++); //Thread.MemoryBarrier(); checksum2 = reader.ReadUInt32(); //Thread.MemoryBarrier(); Log(LogLevel.Debug, "PacketReceiverThread: comparing checksums (calculated=0x{0:X8}; received=0x{1:X8})", checksum, checksum2); if (checksum != checksum2) { Disconnect(); throw new UserFriendlyException("The protocol might be broken or some packet serializer and deserializer don't match each other.", "Connection error"); } MethodInfo method; if (packet is RSAServerPublicKeyPacket || packet is RSAClientPublicKeyPacket || packet is RijndaelEncryptionKeyPacket) { Log(LogLevel.Debug, "PacketReceiverThread: searching for handler method in IGE.Net.Client"); method = typeof(Client).GetMethod("OnPacketReceived", BindingFlags.ExactBinding | BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { packet.GetType() }, null); } else { m_CanProcessPackets.WaitOne(); // block any non encryption key exchange packets Log(LogLevel.Debug, "PacketReceiverThread: searching for handler method in derived class"); method = GetType().GetMethod("OnPacketReceived", BindingFlags.ExactBinding | BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { packet.GetType() }, null); } if (method != null) { Log(LogLevel.Debug, "PacketReceiverThread: invoking custom packet received event"); method.Invoke(this, new object[] { packet }); } else { Log(LogLevel.Debug, "PacketReceiverThread: invoking default packet received event"); OnPacketReceived(packet); } if (PacketReceivedEvent != null) { PacketReceivedEvent.Invoke(this, new PacketReceivedEventArgs(packet)); } } } } catch (Exception ex) { Log(LogLevel.Debug, "PacketReceiverThread exception: {0}", ex.ToString()); } finally { stream.Dispose(); } Log(LogLevel.Debug, "PacketReceiverThread: end"); }