I'm writing an application that takes a Wireshark File (Pcap, Snopp, Pcapng...), opens it and reads all the packets.
My base class:
public abstract class WiresharkFile
{
...
}
And all the sub classes implemented IEnumerable
:
public class Libpcap : WiresharkFile, IDisposable, IEnumerable<WiresharkFilePacket>
{
....
}
Now when I create the object my code recognizes it automatically and then creates the current object
type, for example:
wiresharkFile = new Libpcap(file);
And then when I want to loop over my file and read packets:
foreach (var packet in wiresharkFile)
{
...
}
I get this error:
foreach statement cannot operate on variables of type WiresharkFile' because WiresharkFile' does not contain a public definition for 'GetEnumerator'
So I added this function inside WiresharkFile base class:
public IEnumerator<WiresharkFilePacket> GetEnumerator()
{
return GetEnumerator();
}
And now I get this error StackOverflowException
:
Cannot evaluate expression because the current thread is in a stack overflow state.
Edit
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
}