public void Init(TcpClient client) { if (disposed) { throw new ObjectDisposedException("Session has been disposed."); } // Allow client to close immediately client.LingerState = new LingerOption(true, 0); name = client.Client.RemoteEndPoint?.ToString() ?? "Unknown"; byte[] sivBytes = RandomNumberGenerator.GetBytes(4); byte[] rivBytes = RandomNumberGenerator.GetBytes(4); this.siv = BitConverter.ToUInt32(sivBytes); this.riv = BitConverter.ToUInt32(rivBytes); this.client = client; this.networkStream = client.GetStream(); this.sendCipher = new MapleCipher.Encryptor(VERSION, siv, BLOCK_IV); this.recvCipher = new MapleCipher.Decryptor(VERSION, riv, BLOCK_IV); }
public void Init([NotNull] TcpClient client) { if (Disposed) { throw new ObjectDisposedException("Session has been disposed."); } // Allow client to close immediately client.LingerState = new(true, 0); Name = client.Client.RemoteEndPoint?.ToString(); byte[] sivBytes = new byte[4]; byte[] rivBytes = new byte[4]; Rng.GetBytes(sivBytes); Rng.GetBytes(rivBytes); Siv = BitConverter.ToUInt32(sivBytes); Riv = BitConverter.ToUInt32(rivBytes); Client = client; NetworkStream = client.GetStream(); SendCipher = new(VERSION, Siv, BLOCK_IV); RecvCipher = new(VERSION, Riv, BLOCK_IV); }
private Results ProcessPacket(byte[] bytes, bool isOutbound, DateTime timestamp) { if (mTerminated) { return(Results.Terminated); } if (Build == 0) { var packet = new ByteReader(bytes); packet.Read <ushort>(); // rawSeq int length = packet.ReadInt(); if (bytes.Length - 6 < length) { logger.Debug($"Connection on port {mLocalEndpoint} did not have a MapleStory2 Handshake"); return(Results.CloseMe); } ushort opcode = packet.Read <ushort>(); if (opcode != 0x01) { // RequestVersion logger.Debug($"Connection on port {mLocalEndpoint} did not have a valid MapleStory2 Connection Header"); return(Results.CloseMe); } uint version = packet.Read <uint>(); uint siv = packet.Read <uint>(); uint riv = packet.Read <uint>(); uint blockIV = packet.Read <uint>(); byte type = packet.ReadByte(); Build = version; Locale = MapleLocale.UNKNOWN; outDecryptor = new MapleCipher.Decryptor(Build, siv, blockIV); inDecryptor = new MapleCipher.Decryptor(Build, riv, blockIV); inDecryptor.Decrypt(bytes); // Advance the IV // Generate HandShake packet Definition definition = Config.Instance.GetDefinition(Build, Locale, false, opcode); if (definition == null) { definition = new Definition { Outbound = false, Opcode = opcode, Name = "RequestVersion", }; SaveDefinition(Locale, Build, definition); } ArraySegment <byte> segment = new ArraySegment <byte>(packet.Buffer); var maplePacket = new MaplePacket(timestamp, isOutbound, Build, opcode, segment); // Add to list of not exist (TODO: SortedSet?) if (!Opcodes.Exists(op => op.Outbound == maplePacket.Outbound && op.Header == maplePacket.Opcode)) { // Should be false, but w/e Opcodes.Add(new Opcode(maplePacket.Outbound, maplePacket.Opcode)); } AddPacket(maplePacket, false, true); logger.Info($"[CONNECTION] {mRemoteEndpoint} <-> {mLocalEndpoint}: MapleStory2 V{Build}"); return(Results.Show); } try { MapleCipher.Decryptor decryptor = isOutbound ? outDecryptor : inDecryptor; ByteReader packet = decryptor.Decrypt(bytes); // It's possible to get an empty packet, just ignore it. // Decryption is still necessary to advance sequence number. if (packet.Available == 0) { return(Results.Continue); } ushort opcode = packet.Peek <ushort>(); ArraySegment <byte> segment = new ArraySegment <byte>(packet.Buffer, 2, packet.Length - 2); var maplePacket = new MaplePacket(timestamp, isOutbound, Build, opcode, segment); AddPacket(maplePacket); return(Results.Continue); } catch (ArgumentException ex) { logger.Fatal(ex, "Exception while processing packets"); return(Results.CloseMe); } }