using System; using System.Collections.Generic; using System.Text; using System.IO; namespace CommonLib.IO.File { /// /// Pcap 包捕获写入器。兼容 Tcpdump 及 Ethereal。 /// public sealed class PacketCaptureWriter { #region Fields private const uint MAGIC = 0xA1B2C3D4; private readonly Stream _BaseStream; private readonly LinkLayerType _LinkLayerType; private readonly int _MaxPacketLength; private readonly BinaryWriter m_Writer; private bool m_ExistHeader = false; private int _TimeZone; private int _CaptureTimestamp; #endregion #region Constructors /// /// 构造一个 Pcap 包捕获写入器。 /// /// 要写入的基础流 /// 数据链路类型。 /// 最大包长度。 /// 开始捕获时间。 public PacketCaptureWriter( Stream baseStream, LinkLayerType linkLayerType, int maxPacketLength, int captureTimestamp) { if (baseStream == null) throw new ArgumentNullException("baseStream"); if (maxPacketLength < 0) throw new ArgumentOutOfRangeException("maxPacketLength"); if (!baseStream.CanWrite) throw new ArgumentException("传入的流必须为可写。", "baseStream"); _BaseStream = baseStream; _LinkLayerType = linkLayerType; _MaxPacketLength = maxPacketLength; _CaptureTimestamp = captureTimestamp; m_Writer = new BinaryWriter(_BaseStream); } /* /// /// 构造一个 Pcap 包捕获写入器。 /// /// 要写入的基础流 /// 数据链路类型。 /// 开始捕获时间。 public PacketCaptureWriter(Stream baseStream, LinkLayerType linkLayerType, int captureTimestamp) : this(baseStream, linkLayerType, 0xFFFF, captureTimestamp) { } */ /// /// 构造一个 Pcap 包捕获写入器。 /// /// 要写入的基础流 /// 数据链路类型。 public PacketCaptureWriter(Stream baseStream, LinkLayerType linkLayerType) : this(baseStream, linkLayerType, 0xFFFF, UnixTime.FromDateTime(DateTime.Now).Value) { } #endregion #region Properties /// /// 主版本号,总是为 2 /// public short VersionMajor { get { return 2; } } /// /// 子版本号,总是为 4 /// public short VersionMinjor { get { return 4; } } /// /// 时区,该字段没有使用 /// public int TimeZone { get { return _TimeZone; } set { _TimeZone = value; } } /// /// 捕获时的时间戳,该字段没有使用 /// public int CaptureTimestamp { get { return _CaptureTimestamp; } set { _CaptureTimestamp = value; } } /// /// 基础流 /// public Stream BaseStream { get { return _BaseStream; } } /// /// 数据链路类型 /// public LinkLayerType LinkLaterType { get { return _LinkLayerType; } } /// /// 最大包大小 /// public int MaxPacketLength { get { return _MaxPacketLength; } } #endregion /// /// 写入一个捕获包 /// /// 捕获包 public void Write(PacketCapture packet) { CheckHeader(); m_Writer.Write(packet.Timestamp.Value); m_Writer.Write(packet.Millseconds); m_Writer.Write(packet.Packet.Count); m_Writer.Write(packet.RawLength); m_Writer.Write(packet.Packet.Array, packet.Packet.Offset, packet.Packet.Count); } /// /// 刷新基础流 /// public void Flush() { BaseStream.Flush(); } private void CheckHeader() { if (!m_ExistHeader) { m_Writer.Write(MAGIC); m_Writer.Write(VersionMajor); m_Writer.Write(VersionMinjor); m_Writer.Write(TimeZone); m_Writer.Write(CaptureTimestamp); m_Writer.Write(MaxPacketLength); m_Writer.Write((uint)LinkLaterType); m_ExistHeader = true; } } } }