/// /// Pass recieved data into the packet buffer and try to parse. /// /// number of bytes waiting to be read protected override void OnReceive(int num_bytes) { try { short pakSize; // decrypt the packet if needed if (IsEncrypted) { pakSize = GetExpectedLength(true); } else { pakSize = GetExpectedLength(false); } // we received just enough data for the full message. not too litt,e not too much if (pakSize + 2 == num_bytes) { byte[] fullMessage = new byte[num_bytes]; Array.Copy(m_inBuf, 0, fullMessage, 0, num_bytes); Array.Clear(m_inBuf, 0, num_bytes); m_inOffset = 0; RealmPacketIn packet = new RealmPacketIn(fullMessage); TryHandlePacket(packet); return; } // we received an excess of data else if (pakSize + 2 < num_bytes) { // get only the data we need byte[] fullMessage = new byte[pakSize + 2]; Array.Copy(m_inBuf, 0, fullMessage, 0, pakSize + 2); // shift the remaining data to the top Array.Copy(m_inBuf, m_inOffset, m_inBuf, 0, m_inBuf.Length - m_inOffset); // set the offset to the end of the data that was in excess m_inOffset = num_bytes - (pakSize + 2); RealmPacketIn packet = new RealmPacketIn(fullMessage); TryHandlePacket(packet); return; } else { // partial packet. we don't touch the offset and just let it async read more data. return; } } catch (InsufficientDataException e) { m_srvr.Warning(this, e); } } protected short GetExpectedLength(bool encrypted) { short pakSize; if (encrypted) { byte[] decryptedHeader = new byte[6]; Array.Copy(m_inBuf, 0, decryptedHeader, 0, 6); DecryptHeader(decryptedHeader); pakSize = IPAddress.NetworkToHostOrder((short) (decryptedHeader[0] | (decryptedHeader[1] << 8))); } else { pakSize = IPAddress.NetworkToHostOrder((short) (m_inBuf[0] | (m_inBuf[1] << 8))); } return pakSize; } /// /// Attempts to parse the packet /// /// the packet to parse protected void TryHandlePacket(RealmPacketIn packet) { try { if (IsEncrypted) Decrypt(packet, 0); packet.Initialize(); if (packet.Parse(this)) { } else { } } catch (Exception e) { m_srvr.Warning(this, e); } } /// /// Write packet out across network /// /// packet to send public virtual void Send(RealmPacketOut packet) { byte[] packetBytes = packet.GetBytes(); Encrypt(packetBytes); Send(packetBytes); } /// /// Encrypts the byte array /// /// The raw packet data to encrypt private void Encrypt(byte[] data) { if (IsEncrypted) { byte[] SS_Hash = Account.SessionKey.GetBytes(40); for (int t = 0; t < 4; t++) { byte a = m_cryptKey[3]; a = (byte) (SS_Hash[a] ^ data[t]); byte d = m_cryptKey[2]; a += d; data[t] = a; m_cryptKey[2] = a; a = m_cryptKey[3]; a++; m_cryptKey[3] = (byte) (a%40); } } } /// /// Decrypts the header of an incoming packet, returning to the original packet position /// /// /// private void Decrypt(RealmPacketIn packet, long startPos) { long endPos = packet.Position; packet.Position = startPos; byte[] header = packet.ReadBytes(6); DecryptHeader(header); packet.Position = startPos; packet.BaseStream.Write(header, 0, 6); packet.Position = endPos; } /// /// Decrypts the byte array /// /// private void DecryptHeader(byte[] data) { byte[] SS_Hash = Account.SessionKey.GetBytes(); for (int t = 0; t < 6; t++) { byte a = m_cryptKey[0]; m_cryptKey[0] = data[t]; byte b = data[t]; b = (byte) (b - a); byte d = m_cryptKey[1]; a = SS_Hash[d]; a = (byte) (a ^ b); data[t] = a; a = m_cryptKey[1]; a++; m_cryptKey[1] = (byte) (a%40); } }