private async Task Socks5DataReceived(object Sender, P2P.SOCKS5.DataReceivedEventArgs e) { Socks5Receiver Rx = (Socks5Receiver)e.State; if (HttpxChunks.chunkedStreams.TryGetValue(Rx.Key, out ChunkRecord Rec)) { #if LOG_SOCKS5_EVENTS this.client.Information(e.Count.ToString() + " bytes received over SOCKS5 stream " + Rx.Key + "."); #endif byte[] Buffer = e.Buffer; int Offset = e.Offset; int Count = e.Count; int d; while (Count > 0) { switch (Rx.State) { case 0: Rx.BlockSize = Buffer[Offset++]; Count--; Rx.State++; break; case 1: Rx.BlockSize <<= 8; Rx.BlockSize |= Buffer[Offset++]; Count--; if (Rx.BlockSize == 0) { HttpxChunks.chunkedStreams.Remove(Rx.Key); await Rec.ChunkReceived(Rx.Nr++, true, new byte[0]); e.Stream.Dispose(); return; } Rx.BlockPos = 0; if (Rx.Block is null || Rx.Block.Length != Rx.BlockSize) { Rx.Block = new byte[Rx.BlockSize]; } Rx.State++; break; case 2: d = Math.Min(Count, Rx.BlockSize - Rx.BlockPos); Array.Copy(Buffer, Offset, Rx.Block, Rx.BlockPos, d); Offset += d; Rx.BlockPos += d; Count -= d; if (Rx.BlockPos >= Rx.BlockSize) { if (Rx.E2e) { string Id = Rec.NextId().ToString(); Rx.Block = this.e2e.Decrypt(Rx.EndpointReference, Id, Rx.StreamId, Rx.From, Rx.To, Rx.Block, Rx.SymmetricCipher); if (Rx.Block is null) { string Message = "Decryption of chunk " + Rx.Nr.ToString() + " failed."; #if LOG_SOCKS5_EVENTS this.client.Error(Message); #endif await Rec.Fail(Message); e.Stream.Dispose(); return; } } #if LOG_SOCKS5_EVENTS this.client.Information("Chunk " + Rx.Nr.ToString() + " received and forwarded."); #endif await Rec.ChunkReceived(Rx.Nr++, false, Rx.Block); Rx.State = 0; } break; } } } else { #if LOG_SOCKS5_EVENTS this.client.Warning(e.Count.ToString() + " bytes received over SOCKS5 stream " + Rx.Key + " and discarded."); #endif e.Stream.Dispose(); } }