/// <summary> /// Overrideable. Called when a fragment of a packet is received. /// </summary> /// <param name="packet">The packet</param> protected virtual void OnReceiveFragment(TcpFragment packet) { var ignoreFull = false; if (packet.Completed && InfoHandler.ReadNextNotBuffered) { InfoHandler.ReadNextNotBuffered = false; ignoreFull = true; } if (ReceivedFragment != null) { ReceivedFragment(this, new TcpFragmentReceivedEventArgs(InfoHandler, packet)); } if (ignoreFull) { return; } if ((ReceivedFull != null || ObtainFullPackets) && InfoHandler.ReadNextNotBuffered == false) { if (packet.MemStream == null) { packet.MemStream = new MemoryStream(); } packet.WriteToStream(packet.MemStream); if (packet.Completed) { var data = packet.MemStream.ToArray(); OnReceiveFull(data); packet.MemStream.Dispose(); } } }
/// <summary> /// Not much useful outside internal callings. /// </summary> /// <param name="info">The client</param> /// <param name="packet">The packet</param> /// <param name="innerEx">the inner exception</param> public void ReportPacketFragment(TcpClientInfo info, TcpFragment packet, ref Exception innerEx) { try { OnReceiveFragment(packet); } catch (Exception e) { innerEx = e; throw e; } }
private void HandlePacket(TcpFragment packet, int readCount, ref Exception innerEx) { int offset = 8; do { if (packet.LengthFound == false) { var lengthSize = ReadNextAsLong ? 8 : 4; packet.CurrentReadCount += readCount; var countForLength = readCount - (packet.CurrentReadCount - lengthSize); if (packet.CurrentReadCount >= lengthSize) { packet.LengthRaw.Write(packet.Data, offset, countForLength); packet.FullLength = lengthSize == 4 ? IPAddress.NetworkToHostOrder(BitConverter.ToInt32(packet.Data, 0)) : IPAddress.NetworkToHostOrder(BitConverter.ToInt64(packet.Data, 0)); offset += countForLength; readCount -= countForLength; packet.LengthFound = true; ReadNextAsLong = false; } else { packet.LengthRaw.Write(packet.Data, offset, readCount); readCount -= countForLength; } } else { var countForCurrent = readCount; if (packet.CumulativeReadCount + readCount >= packet.FullLength) { countForCurrent -= (int)((packet.CumulativeReadCount + readCount) - packet.FullLength); } packet.CurrentReadCount = countForCurrent; packet.CumulativeReadCount += countForCurrent; packet.CurrentOffset = offset; readCount -= countForCurrent; if (packet.CumulativeReadCount >= packet.FullLength) { packet.Completed = true; offset += countForCurrent; packet.CumulativeReadCount = packet.FullLength; Parent.ReportPacketFragment(this, packet, ref innerEx); packet.Recycle(); } else { Parent.ReportPacketFragment(this, packet, ref innerEx); } } } while (readCount > 0); }
internal void StartReceive() { Exception innerEx = null; if (EnableSsl) { try { if (HndlType == HandlerType.Server) { FinalStream = new SslStream(Client.GetStream(), false); (FinalStream as SslStream).AuthenticateAsServer(SSLServerCertificate); } else { FinalStream = new SslStream(Client.GetStream(), false, ValidateServerCertificate, null); (FinalStream as SslStream).AuthenticateAsClient(SSLTargetHost); } } catch (Exception e) { if (FinalStream != null) { FinalStream.Dispose(); } Parent.ReportSslError(this, e); Parent.ReportDisconnection(this, ref innerEx); if (TimeoutTimer != null) { TimeoutTimer.Dispose(); TimeoutTimer = null; } if (innerEx != null) { throw innerEx; } return; } } else { FinalStream = Client.GetStream(); } Task.Run(async() => { try { using (FinalStream) { var buffer = new byte[BufferSize + 8]; var packet = new TcpFragment(buffer); if (TimeoutTimer != null) { TimeoutTimer.Stop(); } while (true) { if (TimeoutTimer != null) { TimeoutTimer.Start(); } var readCount = await FinalStream.ReadAsync(buffer, 8, BufferSize); if (TimeoutTimer != null) { TimeoutTimer.Stop(); } if (readCount == 0) { break; } HandlePacket(packet, readCount, ref innerEx); } } } catch (Exception e) { if (innerEx == null) { if (e is IOException == false && e is ObjectDisposedException == false) { Parent.ReportReceiveError(this, e); } } } finally { Parent.ReportDisconnection(this, ref innerEx); if (TimeoutTimer != null) { TimeoutTimer.Dispose(); TimeoutTimer = null; } } }).ContinueWith((task) => { if (innerEx != null) { throw innerEx; } }); }
/// <summary> /// Create the TcpFragmentReceivedEventArgs. /// </summary> /// <param name="info">The client</param> /// <param name="packet">The packet fragment received</param> public TcpFragmentReceivedEventArgs(TcpClientInfo info, TcpFragment packet) { Client = info; Packet = packet; }