/// <summary> /// Determines how large the incoming header will be by /// inspecting the first byte, then initiates reading the header. /// </summary> private void ReadSizeCallback(IAsyncResult result) { int bytesRead = this.connection.Client.EndReceive(result); if (bytesRead == 0 && result.IsCompleted) { // TODO: world server disconnect Game.UI.LogLine("Server has closed the connection"); Game.Exit(); return; } Interlocked.Increment(ref transferred); Interlocked.Increment(ref received); AuthenticationCrypto.Decrypt(ReceiveData, 0, 1); if ((ReceiveData[0] & 0x80) != 0) { // need to resize the buffer byte temp = ReceiveData[0]; ReceiveData = new byte[5]; ReceiveData[0] = (byte)((0x7f & temp)); Remaining = 4; } else { Remaining = 3; } Index = 1; BeginRead(new AsyncCallback(ReadHeaderCallback)); }
/// <summary> /// Reads the rest of the incoming header. /// </summary> private void ReadHeaderCallback(IAsyncResult result) { //if (ReceiveData.Length != 4 && ReceiveData.Length != 5) // throw new Exception("ReceiveData.Length not in order"); int bytesRead = this.connection.Client.EndReceive(result); if (bytesRead == 0 && result.IsCompleted) { // TODO: world server disconnect Game.UI.LogLine("Server has closed the connection"); Game.Exit(); return; } Interlocked.Add(ref transferred, bytesRead); Interlocked.Add(ref received, bytesRead); if (bytesRead == Remaining) { // finished reading header // the first byte was decrypted already, so skip it AuthenticationCrypto.Decrypt(ReceiveData, 1, ReceiveData.Length - 1); ServerHeader header = new ServerHeader(ReceiveData); Game.UI.LogLine(header.ToString(), LogLevel.Debug); if (header.InputDataLength > 5 || header.InputDataLength < 4) { Game.UI.LogException(String.Format("Header.InputataLength invalid: {0}", header.InputDataLength)); } if (header.Size > 0) { // read the packet payload Index = 0; Remaining = header.Size; ReceiveData = new byte[header.Size]; BeginRead(new AsyncCallback(ReadPayloadCallback), header); } else { // the packet is just a header, start next packet HandlePacket(new InPacket(header)); Start(); } } else { // more header to read Index += bytesRead; Remaining -= bytesRead; BeginRead(new AsyncCallback(ReadHeaderCallback)); } }