Я пишу приложение, которое берет файл Wireshark (Pcap, Snopp, Pcapng...), открывает его и читает все пакеты.
Мой базовый класс:
public abstract class WiresharkFile
{
...
}
И все подклассы реализованы IEnumerable
:
public class Libpcap : WiresharkFile, IDisposable, IEnumerable<WiresharkFilePacket>
{
....
}
Теперь, когда я создаю объект, мой код распознает его автоматически, а затем создает текущий тип object
, например:
wiresharkFile = new Libpcap(file);
И затем, когда я хочу перебрать свой файл и прочитать пакеты:
foreach (var packet in wiresharkFile)
{
...
}
Я получаю эту ошибку:
Оператор foreach не может работать с переменными типа WiresharkFile, поскольку WiresharkFile не содержит общедоступного определения для GetEnumerator.
Поэтому я добавил эту функцию в базовый класс WiresharkFile:
public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
return GetEnumerator();
}
И теперь я получаю эту ошибку StackOverflowException
:
Невозможно оценить выражение, так как текущий поток находится в состоянии переполнения стека.
Изменить
public class Libpcap : WiresharkFile, IDisposable, IEnumerable<WiresharkFilePacket>
{
private BinaryReader binaryReader;
private Version version;
private uint snaplen;
private int thiszone;
private uint sigfigs;
private LibpcapLinkType linktype;
private long basePos;
private bool byteSwap;
private static uint MAGIC = 0xa1b2c3d4;
private static uint MAGIC_ENDIAN = 0xd4c3b2a1;
public Libpcap(string path) : this(new FileStream(path, FileMode.Open, FileAccess.Read))
{
FileName = path;
binaryReader = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read));
}
public void Close()
{
binaryReader.Close();
}
public enum LibpcapLinkType
{
Null,
Ethernet,
ExpEthernet,
AX25,
ProNet,
Chaos,
TokenRing,
ArcNet,
Slip,
Ppp,
Fddi
}
public Libpcap(Stream s)
{
binaryReader = new BinaryReader(s);
uint magic = binaryReader.ReadUInt32();
ushort major = binaryReader.ReadUInt16();
ushort minor = binaryReader.ReadUInt16();
thiszone = binaryReader.ReadInt32();
sigfigs = binaryReader.ReadUInt32();
snaplen = binaryReader.ReadUInt32();
uint ltype = binaryReader.ReadUInt32();
if (byteSwap)
{
major = ByteSwap.Swap(major);
minor = ByteSwap.Swap(minor);
thiszone = ByteSwap.Swap(thiszone);
snaplen = ByteSwap.Swap(snaplen);
ltype = ByteSwap.Swap(ltype);
}
version = new Version(major, minor);
linktype = (LibpcapLinkType)((int)ltype);
basePos = binaryReader.BaseStream.Position;
protected override WiresharkFilePacket ReadPacket()
{
if (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length)
{
int secs = binaryReader.ReadInt32();
int usecs = binaryReader.ReadInt32();
uint caplen = binaryReader.ReadUInt32();
uint len = binaryReader.ReadUInt32();
if (byteSwap)
{
secs = ByteSwap.Swap(secs);
usecs = ByteSwap.Swap(usecs);
caplen = ByteSwap.Swap(caplen);
len = ByteSwap.Swap(len);
}
DateTime timeStamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds((Double)secs).AddMilliseconds((Double)usecs / 1000);
byte[] data = binaryReader.ReadBytes((int)caplen);
return new WiresharkFilePacket(timeStamp, data);
}
else
return null;
}
public Version Version
{
get
{
return version;
}
}
public uint MaximumCaptureLength
{
get
{
return snaplen;
}
}
public int TimezoneOffset
{
get
{
return thiszone;
}
}
public uint SignificantFigures
{
get
{
return sigfigs;
}
}
public LibpcapLinkType LinkType
{
get
{
return linktype;
}
}
public void Rewind()
{
binaryReader.BaseStream.Position = basePos;
}
public override string ToString()
{
string endianness;
if (BitConverter.IsLittleEndian)
{
if (byteSwap)
endianness = "Big";
else
endianness = "Little";
}
else
{
if (byteSwap)
endianness = "Little";
else
endianness = "Big";
}
return String.Format("{0}-endian {1} capture, pcap version {2}", endianness, linktype.ToString(), version.ToString());
}
public void Dispose()
{
binaryReader.Close();
}
public class PacketEnumerator : IEnumerator<WiresharkFilePacket>
{
private Libpcap file;
private WiresharkFilePacket currentPacket = null;
public PacketEnumerator(Libpcap file)
{
this.file = file;
}
#region IEnumerator<PcapPacket> Members
public WiresharkFilePacket Current
{
get { return currentPacket; }
}
#endregion
#region IDisposable Members
public void Dispose()
{
}
#endregion
#region IEnumerator Members
object System.Collections.IEnumerator.Current
{
get { return currentPacket; }
}
public bool MoveNext()
{
currentPacket = file.ReadPacket();
return currentPacket != null;
}
public void Reset()
{
file.Rewind();
}
#endregion
}
#region IEnumerable<PcapPacket> Members
public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
return new PacketEnumerator(this);
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new PacketEnumerator(this);
}
#endregion
}