/// <summary> /// Called when the <see cref="PacketReceived"/> event is raised. /// </summary> /// <remarks> /// When overriding this method in a derived class, call the base implementation after your logic. /// </remarks> /// <param name="sender">The sender of the event.</param> /// <param name="args">The packet data that was received.</param> /// <exception cref="ArgumentNullException">Thrown if <paramref name="args"/> is <see langword="null"/>.</exception> protected virtual void OnDataArrived(object sender, DataArrivedEventArgs args) { Guard.NotNull(() => args, args); byte[] data = args.Data; int position = 0, remaining = data.Length; while (PacketBuffer.FreeSpace == 0) { byte[] rawData = PacketBuffer.ExtractAndReset(0); if (rawData.Length > 0) { Crypto.Decrypt(rawData); var incomingPacketArgs = new PacketReceivedEventArgs(rawData); OnPacketReceived(incomingPacketArgs); } if (remaining == 0) { break; } int bufferred; int headerRemaining = HeaderBuffer.FreeSpace; if (headerRemaining > 0) { bufferred = HeaderBuffer.AppendFill(data, position, headerRemaining); // For the confused: if we didn't fill the header, it // means the data array didn't have enough elements. // We move on. if (bufferred < headerRemaining) { break; } position += bufferred; remaining -= bufferred; } byte[] header = HeaderBuffer.ExtractAndReset(4); int length; if (!Crypto.TryGetLength(header, out length)) { Close(@"Could not decode packet length."); return; } PacketBuffer.Reset(length); bufferred = PacketBuffer.AppendFill(data, position, remaining); position += bufferred; remaining -= bufferred; } }