/// <summary> /// Create a TcpStreamGenerator given a flow /// </summary> /// <param name="f"> /// A <see cref="TcpFlow"/> /// </param> /// <param name="timeout"> /// A <see cref="TimeSpan"/> /// </param> /// <param name="sizeLimitInBytes"> /// A <see cref="System.Nullable<System.Int64>"/> /// </param> public TcpStreamGenerator(TcpFlow f, TimeSpan timeout, long?sizeLimitInBytes) { this.flow = f; this.flow.OnPacketReceived += HandleFlowOnPacketReceived; this.timeout = timeout; this.sizeLimitInBytes = sizeLimitInBytes; packets = new LinkedList <PacketDotNet.TcpPacket>(); tcpStream = new TcpStream(); condition = TcpStreamGenerator.CallbackCondition.NextInSequence; waiting_for_start_seq = true; LastContinuousSequence = 0; last_overall_seq = 0; // use now as our last packet received time to avoid // timing this monitor out immediately last_continuous_packet_received = DateTime.Now; }
/// <summary> /// Return a new TcpStream that is the same as the previous stream but has the packets /// we've already read trimmed off of the list /// </summary> /// <returns> /// A <see cref="TcpStream"/> /// </returns> public TcpStream TrimUnusedPackets() { #if PERFORMANCE_CRITICAL_LOGGING log.Debug(""); #endif // create a new stream TcpStream newStream = new TcpStream(); // if we have no first packet then we can exit here if (FirstPacket == null) { #if PERFORMANCE_CRITICAL_LOGGING log.Debug("FirstPacket == null, returning empty TcpStream"); #endif return(newStream); } // copy the first packet variable newStream._firstPacket = FirstPacket; LinkedListNode <PacketInfo> currentPacket = GetCurrentPosition(); // special case for when we are at the end of the last packet // in which case we have nothing to do if (currentPacket == null) { #if PERFORMANCE_CRITICAL_LOGGING log.Debug("currentPacket == null, returning empty newStream"); #endif return(newStream); } // the offset of the currentPacket is the number of bytes we can discard long bytesToDiscard = currentPacket.Value.offset; #if PERFORMANCE_CRITICAL_LOGGING log.DebugFormat("bytesToDiscard {0}", bytesToDiscard); #endif // copy the PacketInfo entries from the current stream to the new one LinkedListNode <PacketInfo> pos = currentPacket; while (pos != null) { #if PERFORMANCE_CRITICAL_LOGGING log.DebugFormat("adding packet of size {0}", pos.Value.length); #endif // copy the packet info from the current stream PacketInfo newPacketInfo = new PacketInfo(pos.Value); // adjust its offset newPacketInfo.offset -= bytesToDiscard; // add it to the new stream newStream.packets.AddLast(newPacketInfo); #if PERFORMANCE_CRITICAL_LOGGING log.DebugFormat("newStream.Length {0}", newStream.Length); #endif // advance to the next packet in the current stream pos = pos.Next; } #if PERFORMANCE_CRITICAL_LOGGING log.DebugFormat("after importing all packets newStream.Length {0}", newStream.Length); #endif // now write the bytes from the old stream // NOTE: we cannot use originalBytes.Length because MemoryStream.GetBuffer() returns // the internal buffer that can be larger than the actual number of bytes in the stream byte[] originalBytes = base.GetBuffer(); newStream.Write(originalBytes, (int)bytesToDiscard, (int)(base.Length - bytesToDiscard)); // set the proper position in the newStream #if PERFORMANCE_CRITICAL_LOGGING log.DebugFormat("base.Position {0}", base.Position); #endif newStream.Position = base.Position - bytesToDiscard; //FIXME: for debugging #if false log.DebugFormat("trimmed size from {0} down to {1}, starting packets, {2}, ending packets {3}, removed {4} packets", base.Length, newStream.Length, packets.Count, newStream.packets.Count, (packets.Count - newStream.packets.Count)); log.DebugFormat("original position of {0} is position of {1} in the newStream", base.Position, newStream.Position); #endif return(newStream); }