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;
}
}
}
}