publicstatic Packet ParsePacket(LinkLayers linkLayers, byte[] packetData) { Packet p; // 使用ByteArraySegment类包装数据包字节数组,这个类很重要,后面重点讲解 var byteArraySegment = new ByteArraySegment(packetData);
Log.DebugFormat("LinkLayer {0}", linkLayers);
// 根据链路层类型构造不同的Packet子类 switch (linkLayers) { case LinkLayers.Ethernet: { p = new EthernetPacket(byteArraySegment); break; } case LinkLayers.LinuxSll: { p = new LinuxSllPacket(byteArraySegment); break; } case LinkLayers.Null: { p = new NullPacket(byteArraySegment); break; } case LinkLayers.Ppp: { p = new PppPacket(byteArraySegment); break; } case LinkLayers.Ieee80211: { p = MacFrame.ParsePacket(byteArraySegment); break; } case LinkLayers.Ieee80211RadioTap: { p = new RadioPacket(byteArraySegment); break; } case LinkLayers.Ppi: { p = new PpiPacket(byteArraySegment); break; } case LinkLayers.Raw: case LinkLayers.RawLegacy: { p = new RawIPPacket(byteArraySegment); break; } default: { // 若没有匹配的链路层类型,抛出异常 ThrowHelper.ThrowNotImplementedException(ExceptionArgument.linkLayer); p = null; break; } }
public T Extract<T>() where T : Packet { // 从当前层开始 var t = this; while (t != null) { // 若某个内层的实体类型和指定类型相同,则返回该层的实体对象 if (t is T packet) return packet; // 转到内层,即负载数据包 t = t.PayloadPacket; } returnnull; }
publicsealedclassByteArraySegment : IEnumerable<byte> { public ByteArraySegment NextSegment() { var numberOfBytesAfterThisSegment = BytesLength - (Offset + Length); return NextSegment(numberOfBytesAfterThisSegment); }
public ByteArraySegment NextSegment(int segmentLength) { var startingOffset = Offset + Length; // start at the end of the current segment
// ensure that the new segment length isn't longer than the number of bytes // available after the current segment segmentLength = Math.Min(segmentLength, BytesLength - startingOffset);
// calculate the ByteLength property of the new ByteArraySegment var bytesLength = startingOffset + segmentLength;
internalstatic PacketOrByteArraySegment ParseNextSegment (ByteArraySegment header, EthernetType type) { // slice off the payload var payload = header.NextSegment();
var payloadPacketOrData = new PacketOrByteArraySegment();
// parse the encapsulated bytes switch (type) { case EthernetType.IPv4: { payloadPacketOrData.Packet = new IPv4Packet(payload); break; } case EthernetType.IPv6: { payloadPacketOrData.Packet = new IPv6Packet(payload); break; } case EthernetType.Arp: { payloadPacketOrData.Packet = new ArpPacket(payload); break; } case EthernetType.Lldp: { payloadPacketOrData.Packet = new LldpPacket(payload); break; } case EthernetType.PppoeSessionStage: { payloadPacketOrData.Packet = new PppoePacket(payload); break; } case EthernetType.WakeOnLan: { payloadPacketOrData.Packet = new WakeOnLanPacket(payload); break; } case EthernetType.VLanTaggedFrame: case EthernetType.ProviderBridging: case EthernetType.QInQ: { payloadPacketOrData.Packet = new Ieee8021QPacket(payload); break; } case EthernetType.TransparentEthernetBridging: { payloadPacketOrData.Packet = new EthernetPacket(payload); break; } default: // consider the sub-packet to be a byte array { payloadPacketOrData.ByteArraySegment = payload; break; } }
return payloadPacketOrData; }
可以看到中间的部分就是判断 type 的类型来构造不同的网络层实体对象,包括 IPv4、IPv6、ARP 等,与 Packet.ParsePacket 方法是类似的