2015-11-15 1 views
2

L'application d'écriture qui prend le fichier Wireshark (Pcap, Snopp, Pcapng ...) ouvre ce fichier et lit tous les paquets.IEnumerable Impossible d'évaluer l'expression car le thread actuel est dans un état de débordement de pile

Ma classe de base:

public abstract class WiresharkFile 
{ 
    ... 
} 

Et toutes les sous-classes i IEnumerable réalisés notamment:

public class Libpcap: WiresharkFile, IDisposable, IEnumerable { .... }

Maintenant, quand créer l'objet mon code l'a reconnu automatiquement et ensuite créer le type object actuel, par exemple:

wiresharkFile = new Libpcap(file); 

Et puis, quand je veux boucler sur mon dossier et lu les paquets:

foreach (var packet in wiresharkFile) 
{ 

} 

donc obtenir cette erreur:

foreach statement cannot operate on variables of type WiresharkFile' because WiresharkFile' does not contain a public definition for 'GetEnumerator'

donc j'ai ajouté cette fonction à l'intérieur de la classe de base WiresharkFile:

public IEnumerator<WiresharkFilePacket> GetEnumerator() 
{ 
    return GetEnumerator(); 
} 

Et maintenant, allez cette erreur StackO verflowException:

Cannot evaluate expression because the current thread is in a stack overflow state.

Modifier

public class Libpcap: WiresharkFile, IDisposable, IEnumerable { privé BinaryReader BinaryReader; version privée version; private uint snaplen; private int thiszone; sigfigs privés d'uint; type de lien LibpcapLinkType privé; private long basePos; private bool byteSwap; uint statique privé MAGIC = 0xa1b2c3d4; uint statique privé 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 
} 

Répondre

0

Vous voyez StackOverflowException parce que vous vous appeler

public IEnumerator<WiresharkFilePacket> GetEnumerator() 
{ 
    return GetEnumerator(); 
} 

Vous devez implémenter correctement un itérateur pour que cela fonctionne. Par exemple:

public IEnumerator<WiresharkFilePacket> GetEnumerator() 
{ 
    for (int i = 0; i < 10; i++) 
     yield return new WiresharkFilePacket(); 
} 

Votre WiresharkFile devrait avoir une collection interne, il peut itérer. Qu'il s'agisse d'un paquet que vous parser sur le pcap et retour. Créer simplement une méthode GetEnumerator ne fera rien. Pour plus, peut-être que vous voulez lire How do I implement IEnumerable<T>

+0

S'il vous plaît voir ma modification, ma classe implémenter cette IEnumerable avec la classe privée, comment le convertir en IEnumerable normal? –

0

Si toutes les classes dérivées fournissent une méthode GetEnumerator(), et vous avez aucun problème nécessitant ce de toutes les classes futures dérivées, mais votre classe de base ne peut pas définir de manière significative une, qui est quand vous marquez abstract .

public abstract IEnumerator<WiresharkFilePacket> GetEnumerator(); 

est donc suffisant pour mettre en œuvre IEnumerable sur votre classe de base, vous n'avez pas besoin de la définition complète encore là.

+0

S'il vous plaît voir ma modification, ma classe implémenter ce IEnumerable avec la classe privée, comment le convertir en IEnumerable normal? –