Commit 2e45fef3 authored by Brickner_cp's avatar Brickner_cp

Code Analysis and Documentation - 8 warnings left.

parent 8aeae762
......@@ -11,6 +11,13 @@ namespace PcapDotNet.Core.Extensions
/// </summary>
public static class LivePacketDeviceExtensions
{
/// <summary>
/// Returns the network interface of the packet device.
/// The interface is found using its id.
/// If no interface is found, null is returned.
/// </summary>
/// <param name="livePacketDevice">The LivePacketDevice to look for a matching network interface for.</param>
/// <returns>The network interface found according to the given device or null if none is found.</returns>
public static NetworkInterface GetNetworkInterface(this LivePacketDevice livePacketDevice)
{
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
......@@ -22,6 +29,12 @@ namespace PcapDotNet.Core.Extensions
return null;
}
/// <summary>
/// Returns the MacAddress of the network interface of the given device.
/// If no interface matches the given packet device, an exception is thrown.
/// </summary>
/// <param name="livePacketDevice">The packet device to look for the matching interface.</param>
/// <returns>The MacAddress of the given device's matching interface.</returns>
public static MacAddress GetMacAddress(this LivePacketDevice livePacketDevice)
{
NetworkInterface networkInterface = livePacketDevice.GetNetworkInterface();
......
......@@ -104,7 +104,7 @@ namespace PcapDotNet.Core.Test
TestReceiveSomePackets(NumPacketsToSend, NumPacketsToSend, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02);
TestReceiveSomePackets(NumPacketsToSend, 0, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02);
TestReceiveSomePackets(NumPacketsToSend, -1, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02);
TestReceiveSomePackets(NumPacketsToSend, NumPacketsToSend + 1, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.02);
TestReceiveSomePackets(NumPacketsToSend, NumPacketsToSend + 1, int.MaxValue, PacketSize, false, PacketCommunicatorReceiveResult.Ok, NumPacketsToSend, 0, 0.031);
// Test non blocking
TestReceiveSomePackets(0, 0, int.MaxValue, PacketSize, true, PacketCommunicatorReceiveResult.Ok, 0, 0, 0.02);
......
......@@ -78,38 +78,38 @@ namespace PcapDotNet.Core.Test
}
}
[TestMethod]
public void Temp()
{
EthernetLayer ethernetLayer = new EthernetLayer
{
Source = new MacAddress("00:01:02:03:04:05"),
Destination = new MacAddress("A0:A1:A2:A3:A4:A5")
};
IpV4Layer ipV4Layer = new IpV4Layer
{
Source = new IpV4Address("1.2.3.4"),
Ttl = 128,
};
IcmpEchoLayer icmpLayer = new IcmpEchoLayer();
PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, icmpLayer);
List<Packet> packets = new List<Packet>();
for (int i = 0; i != 100; ++i)
{
ipV4Layer.Destination = new IpV4Address("2.3.4." + i);
ipV4Layer.Identification = (ushort)i;
icmpLayer.SequenceNumber = (ushort)i;
icmpLayer.Identifier = (ushort)i;
packets.Add(builder.Build(DateTime.Now));
}
PacketDumpFile.Dump(@"c:\users\boaz\temp.pcap", new PcapDataLink(DataLinkKind.Ethernet), int.MaxValue, packets);
}
// [TestMethod]
// public void Temp()
// {
// EthernetLayer ethernetLayer = new EthernetLayer
// {
// Source = new MacAddress("00:01:02:03:04:05"),
// Destination = new MacAddress("A0:A1:A2:A3:A4:A5")
// };
//
// IpV4Layer ipV4Layer = new IpV4Layer
// {
// Source = new IpV4Address("1.2.3.4"),
// Ttl = 128,
// };
//
// IcmpEchoLayer icmpLayer = new IcmpEchoLayer();
//
// PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, icmpLayer);
//
// List<Packet> packets = new List<Packet>();
//
// for (int i = 0; i != 100; ++i)
// {
// ipV4Layer.Destination = new IpV4Address("2.3.4." + i);
// ipV4Layer.Identification = (ushort)i;
// icmpLayer.SequenceNumber = (ushort)i;
// icmpLayer.Identifier = (ushort)i;
//
// packets.Add(builder.Build(DateTime.Now));
// }
//
// PacketDumpFile.Dump(@"c:\users\boaz\temp.pcap", new PcapDataLink(DataLinkKind.Ethernet), int.MaxValue, packets);
// }
}
}
\ No newline at end of file
......@@ -376,5 +376,20 @@ namespace PcapDotNet.Packets.Test
});
Assert.IsNull(packet);
}
[TestMethod]
public void DifferentIgmpSimpleLayersTest()
{
IgmpSimpleLayer layer1 = new IgmpQueryVersion1Layer
{
GroupAddress = new IpV4Address("1.2.3.4")
};
IgmpSimpleLayer layer2 = new IgmpQueryVersion2Layer
{
GroupAddress = new IpV4Address("1.2.3.4"),
MaxResponseTime = TimeSpan.FromMinutes(55)
};
Assert.IsFalse(layer1.Equals(layer2));
}
}
}
\ No newline at end of file
......@@ -596,6 +596,17 @@ namespace PcapDotNet.Packets.Test
Assert.IsNull(packet);
}
[TestMethod]
public void IpV4LayerNullChecksumAndProtocolGetHashCodeTest()
{
IpV4Layer layer = new IpV4Layer
{
HeaderChecksum = null,
Protocol = null,
};
Assert.IsNotNull(layer.GetHashCode());
}
private static Packet HexToPacket(string hexString, DataLinkKind dataLinkKind)
{
return Packet.FromHexadecimalString(hexString, DateTime.MinValue, dataLinkKind);
......
......@@ -132,11 +132,20 @@ namespace PcapDotNet.Packets.Arp
TargetProtocolAddress.SequenceEqual(other.TargetProtocolAddress);
}
/// <summary>
/// True iff the two ARP layers have equal protocol type, operation and addresses.
/// </summary>
/// <param name="other">The ARP layer to compare the layer to.</param>
/// <returns>True iff the two layers are equal.</returns>
public override sealed bool Equals(Layer other)
{
return base.Equals(other) && Equals(other as ArpLayer);
return Equals(other as ArpLayer);
}
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of a combination of the protocol type and operation and the hash codes of the layer length and data link.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
......
......@@ -90,23 +90,37 @@ namespace PcapDotNet.Packets.Ethernet
get { return ArpHardwareType.Ethernet; }
}
/// <summary>
/// Two Ethernet layers are equal if they have the same source, destination and ethernet type.
/// </summary>
public bool Equals(EthernetLayer other)
{
return other != null &&
Source == other.Source && Destination == other.Destination && EtherType == other.EtherType;
}
/// <summary>
/// Two Ethernet layers are equal if they have the same source, destination and ethernet type.
/// </summary>
public override sealed bool Equals(Layer other)
{
return base.Equals(other) && Equals(other as EthernetLayer);
return Equals(other as EthernetLayer);
}
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the hash codes of the layer length, data link, source and destination addresses and the ethernet type.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
Source.GetHashCode() ^ Destination.GetHashCode() ^ EtherType.GetHashCode();
}
/// <summary>
/// Contains the source, destination and ether type.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return Source + " -> " + Destination + " (" + EtherType + ")";
......
......@@ -61,6 +61,9 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// ICMP is valid if the datagram's length is OK, the checksum is correct and the code is in the expected range.
/// </summary>
protected override bool CalculateIsValid()
{
return base.CalculateIsValid() && Length == DatagramLength;
......
......@@ -42,20 +42,19 @@ namespace PcapDotNet.Packets.Icmp
}
/// <summary>
/// Two ICMP Address Mask Request layers are equal if they have the same sequence number, identifier and address mask.
/// True iff the address mask is equal to the other address mask.
/// </summary>
public bool Equals(IcmpAddressMaskRequestLayer other)
protected override bool EqualPayload(IcmpLayer other)
{
return other != null &&
AddressMask == other.AddressMask;
return EqualPayload(other as IcmpAddressMaskRequestLayer);
}
/// <summary>
/// Two ICMP Address Mask Request layers are equal if they have the same sequence number, identifier and address mask.
/// True iff the address mask is equal to the other address mask.
/// </summary>
public override sealed bool Equals(IcmpLayer other)
private bool EqualPayload(IcmpAddressMaskRequestLayer other)
{
return base.Equals(other) && Equals(other as IcmpAddressMaskRequestLayer);
return other != null && AddressMask.Equals(other.AddressMask);
}
}
}
\ No newline at end of file
......@@ -55,6 +55,11 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range
/// and the IPv4 payload contains at least an IPv4 header and the transport header.
/// If the code is for unsupported transport protocol, the IPv4 payload should contain 256 bytes of the original datagram.
/// </summary>
protected override bool CalculateIsValid()
{
if (!base.CalculateIsValid())
......
......@@ -95,6 +95,10 @@ namespace PcapDotNet.Packets.Icmp
/// </summary>
public override abstract ILayer ExtractLayer();
/// <summary>
/// The payload of the ICMP.
/// All the data without the header.
/// </summary>
public Datagram Payload
{
get
......@@ -163,9 +167,13 @@ namespace PcapDotNet.Packets.Icmp
return Sum16BitsToChecksum(sum);
}
private bool? _isChecksumCorrect;
private Datagram _payload;
/// <summary>
/// Creates an IcmpDatagram from a buffer according to the message type.
/// </summary>
/// <param name="buffer">The buffer of the datagram.</param>
/// <param name="offset">The offset where the datagram starts.</param>
/// <param name="length">The length of the datagram in the buffer.</param>
/// <returns>An IcmpDatagram according to the Icmp message type.</returns>
public static IcmpDatagram CreateDatagram(byte[] buffer, int offset, int length)
{
if (length <= Offset.Type)
......@@ -236,5 +244,8 @@ namespace PcapDotNet.Packets.Icmp
return new IcmpUnknownDatagram(buffer, offset, length);
}
}
private bool? _isChecksumCorrect;
private Datagram _payload;
}
}
\ No newline at end of file
......@@ -21,6 +21,11 @@ namespace PcapDotNet.Packets.Icmp
/// </summary>
public class IcmpDestinationUnreachableDatagram : IcmpIpV4HeaderPlus64BitsPayloadDatagram
{
/// <summary>
/// The minimum value of the maximum transmission unit for FragmentationNeededAndDoNotFragmentSet code.
/// </summary>
public const ushort MinimumMaximumTransmissionUnit = 68;
private static class Offset
{
public const int NextHopMtu = 6;
......@@ -54,11 +59,20 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range,
/// the IPv4 payload contains at least an IPv4 header, the IPv4's payload is in the expected size
/// and if the NextHopMaximumTransmissionUnit is at least 68 for FragmentationNeededAndDoNotFragmentSet code or exactly 0 for other codes.
/// </summary>
protected override bool CalculateIsValid()
{
return base.CalculateIsValid() &&
(((IcmpCodeDestinationUnreachable)Code == IcmpCodeDestinationUnreachable.FragmentationNeededAndDoNotFragmentSet) ||
NextHopMaximumTransmissionUnit == 0);
if (!base.CalculateIsValid())
return false;
if ((IcmpCodeDestinationUnreachable)Code == IcmpCodeDestinationUnreachable.FragmentationNeededAndDoNotFragmentSet)
return NextHopMaximumTransmissionUnit >= MinimumMaximumTransmissionUnit;
return NextHopMaximumTransmissionUnit == 0;
}
/// <summary>
......
......@@ -85,6 +85,14 @@ namespace PcapDotNet.Packets.Icmp
{
}
/// <summary>
/// Finalizes the layer data in the buffer.
/// Used for the ICMP checksum.
/// </summary>
/// <param name="buffer">The buffer to finalize the layer in.</param>
/// <param name="offset">The offset in the buffer the layer starts.</param>
/// <param name="payloadLength">The length of the layer's payload (the number of bytes after the layer in the packet).</param>
/// <param name="nextLayer">The layer that comes after this layer. null if this is the last layer.</param>
public override sealed void Finalize(byte[] buffer, int offset, int payloadLength, ILayer nextLayer)
{
IcmpDatagram.WriteChecksum(buffer, offset, Length + payloadLength, Checksum);
......@@ -98,28 +106,50 @@ namespace PcapDotNet.Packets.Icmp
get { return IpV4Protocol.InternetControlMessageProtocol; }
}
public virtual bool Equals(IcmpLayer other)
/// <summary>
/// ICMP layers are equal if they have the same message type, code, checksum, variable and payload.
/// </summary>
public bool Equals(IcmpLayer other)
{
return other != null &&
MessageType == other.MessageType && CodeValue == other.CodeValue &&
Checksum == other.Checksum &&
Variable == other.Variable;
Variable == other.Variable &&
EqualPayload(other);
}
/// <summary>
/// ICMP layers are equal if they have the same message type, code, checksum, variable and payload.
/// </summary>
public sealed override bool Equals(Layer other)
{
return base.Equals(other) && Equals(other as IcmpLayer);
return Equals(other as IcmpLayer);
}
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the layer length, data link, message type and code, checksum and variable.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
MessageTypeAndCode.GetHashCode() ^ Checksum.GetHashCode() ^ Variable.GetHashCode();
}
/// <summary>
/// Returns a string containing the message type, code and variable.
/// </summary>
public override string ToString()
{
return MessageType + "." + CodeValue + "(" + Variable + ")";
}
/// <summary>
/// True iff the ICMP payload is equal to the other ICMP payload.
/// </summary>
protected virtual bool EqualPayload(IcmpLayer other)
{
return true;
}
}
}
\ No newline at end of file
......@@ -51,6 +51,11 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range,
/// the IPv4 payload contains at least an IPv4 header, the IPv4's payload is in the expected size
/// and the pointer points to a byte within the IPv4 header.
/// </summary>
protected override bool CalculateIsValid()
{
return base.CalculateIsValid() && Pointer < IpV4.Length;
......
......@@ -41,6 +41,9 @@ namespace PcapDotNet.Packets.Icmp
{
}
/// <summary>
/// Creates a Layer that represents the datagram to be used with PacketBuilder.
/// </summary>
public override ILayer ExtractLayer()
{
return new IcmpRedirectLayer
......
......@@ -114,6 +114,10 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range
/// and the address entry size is the default address entry size.
/// </summary>
protected override bool CalculateIsValid()
{
return base.CalculateIsValid() &&
......
......@@ -54,6 +54,9 @@ namespace PcapDotNet.Packets.Icmp
return Equals(obj as IcmpRouterAdvertisementEntry);
}
/// <summary>
/// A xor of the hash codes of the router address and preference.
/// </summary>
public override int GetHashCode()
{
return RouterAddress.GetHashCode() ^ RouterAddressPreference.GetHashCode();
......
......@@ -77,15 +77,21 @@ namespace PcapDotNet.Packets.Icmp
IcmpRouterAdvertisementDatagram.WriteHeaderAdditional(buffer, offset, Entries);
}
public bool Equals(IcmpRouterAdvertisementLayer other)
/// <summary>
/// True iff the Entries are equal to the other ICMP entries.
/// </summary>
protected override bool EqualPayload(IcmpLayer other)
{
return other != null &&
Entries.SequenceEqual(other.Entries);
return EqualPayload(other as IcmpRouterAdvertisementLayer);
}
public sealed override bool Equals(IcmpLayer other)
/// <summary>
/// True iff the Entries are equal to the other ICMP entries.
/// </summary>
private bool EqualPayload(IcmpRouterAdvertisementLayer other)
{
return base.Equals(other) && Equals(other as IcmpRouterAdvertisementLayer);
return other != null &&
Entries.SequenceEqual(other.Entries);
}
private readonly IList<IcmpRouterAdvertisementEntry> _entries;
......
......@@ -54,6 +54,10 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct, the code is in the expected range,
/// the IPv4 payload contains at least an IPv4 header, the IPv4's payload is in the expected size and the Pointer points to a byte in the IPv4 payload.
/// </summary>
protected override bool CalculateIsValid()
{
return base.CalculateIsValid() && Pointer < IpV4.Length;
......
......@@ -85,6 +85,9 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct and the code is in the expected range.
/// </summary>
protected override bool CalculateIsValid()
{
return base.CalculateIsValid() && Length == DatagramLength;
......
......@@ -52,17 +52,23 @@ namespace PcapDotNet.Packets.Icmp
OriginateTimestamp, ReceiveTimestamp, TransmitTimestamp);
}
public bool Equals(IcmpTimestampLayer other)
/// <summary>
/// True iff the OriginateTimestamp, ReceiveTimestamp and the TransmitTimestamp fields are equal.
/// </summary>
protected override bool EqualPayload(IcmpLayer other)
{
return EqualPayload(other as IcmpTimestampLayer);
}
/// <summary>
/// True iff the OriginateTimestamp, ReceiveTimestamp and the TransmitTimestamp fields are equal.
/// </summary>
private bool EqualPayload(IcmpTimestampLayer other)
{
return other != null &&
OriginateTimestamp == other.OriginateTimestamp &&
ReceiveTimestamp == other.ReceiveTimestamp &&
TransmitTimestamp == other.TransmitTimestamp;
}
public sealed override bool Equals(IcmpLayer other)
{
return base.Equals(other) && Equals(other as IcmpTimestampLayer);
}
}
}
\ No newline at end of file
......@@ -98,6 +98,10 @@ namespace PcapDotNet.Packets.Icmp
get { return ReadUInt(Offset.OutputLinkMtu, Endianity.Big); }
}
/// <summary>
/// Is the packet an Outbound packet.
/// This is indicated by a value of 0xFFFF in the ReturnHopCount field.
/// </summary>
public bool IsOutbound
{
get { return ReturnHopCount == OutboundReturnHopCountValue; }
......@@ -120,6 +124,9 @@ namespace PcapDotNet.Packets.Icmp
};
}
/// <summary>
/// Valid if the datagram's length is OK, the checksum is correct and the code is in the expected range.
/// </summary>
protected override bool CalculateIsValid()
{
return base.CalculateIsValid() && Length == DatagramLength;
......
......@@ -87,7 +87,18 @@ namespace PcapDotNet.Packets.Icmp
IcmpTraceRouteDatagram.WriteHeaderAdditional(buffer, offset, OutboundHopCount, ReturnHopCount, OutputLinkSpeed, OutputLinkMaximumTransmissionUnit);
}
public bool Equals(IcmpTraceRouteLayer other)
/// <summary>
/// True iff the OutboundHopCount, ReturnHopCount, OutputLinkSpeed and OutputLinkMaximumTransmissionUnit fields are equal to the other layer fields.
/// </summary>
protected override bool EqualPayload(IcmpLayer other)
{
return EqualPayload(other as IcmpTraceRouteLayer);
}
/// <summary>
/// True iff the OutboundHopCount, ReturnHopCount, OutputLinkSpeed and OutputLinkMaximumTransmissionUnit fields are equal to the other layer fields.
/// </summary>
private bool EqualPayload(IcmpTraceRouteLayer other)
{
return other != null &&
OutboundHopCount == other.OutboundHopCount &&
......@@ -95,10 +106,5 @@ namespace PcapDotNet.Packets.Icmp
OutputLinkSpeed == other.OutputLinkSpeed &&
OutputLinkMaximumTransmissionUnit == other.OutputLinkMaximumTransmissionUnit;
}
public override sealed bool Equals(IcmpLayer other)
{
return base.Equals(other) && Equals(other as IcmpTraceRouteLayer);
}
}
}
\ No newline at end of file
......@@ -37,23 +37,43 @@ namespace PcapDotNet.Packets.Igmp
get { return IpV4Protocol.InternetGroupManagementProtocol; }
}
public virtual bool Equals(IgmpLayer other)
/// <summary>
/// IGMP layers are equal if they have the same message type, query version, similar max response time and the same specific type fields.
/// </summary>
public bool Equals(IgmpLayer other)
{
return other != null &&
MessageType == other.MessageType &&
QueryVersion == other.QueryVersion &&
MaxResponseTimeValue.Divide(2) <= other.MaxResponseTimeValue && MaxResponseTimeValue.Multiply(2) >= other.MaxResponseTimeValue;
EqualMaxResponseTime(MaxResponseTimeValue, other.MaxResponseTimeValue) &&
EqualFields(other);
}
/// <summary>
/// IGMP layers are equal if they have the same message type, query version, similar max response time and the same specific type fields.
/// </summary>
public sealed override bool Equals(Layer other)
{
return base.Equals(other) && Equals(other as IgmpLayer);
return Equals(other as IgmpLayer);
}
/// <summary>
/// Xor of the hash codes of the layer length, datalink, message type and query version.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
MessageType.GetHashCode() ^ QueryVersion.GetHashCode();
}
/// <summary>
/// true iff the fields that are not mutual to all IGMP layers are equal.
/// </summary>
protected abstract bool EqualFields(IgmpLayer other);
private static bool EqualMaxResponseTime(TimeSpan value1, TimeSpan value2)
{
return value1.Divide(2) <= value2 && value1.Multiply(2) >= value2;
}
}
}
\ No newline at end of file
......@@ -115,21 +115,10 @@ namespace PcapDotNet.Packets.Igmp
get { return MaxResponseTime; }
}
public bool Equals(IgmpQueryVersion3Layer other)
{
return other != null &&
GroupAddress == other.GroupAddress &&
IsSuppressRouterSideProcessing == other.IsSuppressRouterSideProcessing &&
QueryRobustnessVariable == other.QueryRobustnessVariable &&
QueryInterval.Divide(2) <= other.QueryInterval && QueryInterval.Multiply(2) >= other.QueryInterval &&
SourceAddresses.SequenceEqual(other.SourceAddresses);
}
public override sealed bool Equals(IgmpLayer other)
{
return base.Equals(other) && Equals(other as IgmpQueryVersion3Layer);
}
/// <summary>
/// Xor of the combination of the IsSuppressRouterSideProcessing and QueryRobustnessVariable fields with
/// the hash codes of the layer length, datalink, message type, query version, group address and all the source addresses.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
......@@ -139,6 +128,29 @@ namespace PcapDotNet.Packets.Igmp
}
/// <summary>
/// true iff the GroupAddress, IsSuppressRouterSideProcessing, QueryRobustnessVariable and SourceAddresses fields are equal
/// and the QueryInterval is similar.
/// </summary>
protected override bool EqualFields(IgmpLayer other)
{
return EqualFields(other as IgmpQueryVersion3Layer);
}
/// <summary>
/// true iff the GroupAddress, IsSuppressRouterSideProcessing, QueryRobustnessVariable and SourceAddresses fields are equal
/// and the QueryInterval is similar.
/// </summary>
private bool EqualFields(IgmpQueryVersion3Layer other)
{
return other != null &&
GroupAddress == other.GroupAddress &&
IsSuppressRouterSideProcessing == other.IsSuppressRouterSideProcessing &&
QueryRobustnessVariable == other.QueryRobustnessVariable &&
QueryInterval.Divide(2) <= other.QueryInterval && QueryInterval.Multiply(2) >= other.QueryInterval &&
SourceAddresses.SequenceEqual(other.SourceAddresses);
}
private readonly IList<IpV4Address> _sourceAddresses;
}
}
\ No newline at end of file
......@@ -75,23 +75,32 @@ namespace PcapDotNet.Packets.Igmp
get { return TimeSpan.Zero; }
}
public bool Equals(IgmpReportVersion3Layer other)
/// <summary>
/// Xor of the hash codes of the layer length, datalink, message type, query version and the group records.
/// </summary>
public override int GetHashCode()
{
return other != null &&
GroupRecords.SequenceEqual(other.GroupRecords);
return base.GetHashCode() ^
GroupRecords.SequenceGetHashCode();
}
public sealed override bool Equals(IgmpLayer other)
/// <summary>
/// true iff the group records are equal.
/// </summary>
protected override bool EqualFields(IgmpLayer other)
{
return base.Equals(other) && Equals(other as IgmpReportVersion3Layer);
return EqualFields(other as IgmpReportVersion3Layer);
}
public override int GetHashCode()
/// <summary>
/// true iff the group records are equal.
/// </summary>
private bool EqualFields(IgmpReportVersion3Layer other)
{
return base.GetHashCode() ^
GroupRecords.SequenceGetHashCode();
return other != null &&
GroupRecords.SequenceEqual(other.GroupRecords);
}
private readonly IList<IgmpGroupRecord> _groupRecords;
}
}
\ No newline at end of file
......@@ -37,21 +37,30 @@ namespace PcapDotNet.Packets.Igmp
MessageType, MaxResponseTimeValue, GroupAddress);
}
public bool Equals(IgmpSimpleLayer other)
/// <summary>
/// Xor of the hash codes of the layer length, datalink, message type, query version and group address.
/// </summary>
public override sealed int GetHashCode()
{
return other != null &&
GroupAddress == other.GroupAddress;
return base.GetHashCode() ^
GroupAddress.GetHashCode();
}
public override sealed bool Equals(IgmpLayer other)
/// <summary>
/// true iff the the group address is equal.
/// </summary>
protected override sealed bool EqualFields(IgmpLayer other)
{
return base.Equals(other) && Equals(other as IgmpSimpleLayer);
return EqualFields(other as IgmpSimpleLayer);
}
public override int GetHashCode()
/// <summary>
/// true iff the the group address is equal.
/// </summary>
private bool EqualFields(IgmpSimpleLayer other)
{
return base.GetHashCode() ^
GroupAddress.GetHashCode();
return other != null &&
GroupAddress == other.GroupAddress;
}
}
}
\ No newline at end of file
......@@ -234,6 +234,9 @@ namespace PcapDotNet.Packets.IpV4
get { return Tcp; }
}
/// <summary>
/// The payload of the datagram as an ICMP datagram.
/// </summary>
public IcmpDatagram Icmp
{
get
......
......@@ -146,6 +146,9 @@ namespace PcapDotNet.Packets.IpV4
nextTransportLayer.Checksum);
}
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public bool Equals(IpV4Layer other)
{
return other != null &&
......@@ -157,11 +160,18 @@ namespace PcapDotNet.Packets.IpV4
Options.Equals(other.Options);
}
/// <summary>
/// True iff the two IPv4 layers have the same TypeOfService, Identification, Fragmentation, Ttl, Protocol, HeaderChecksum, Source, Destination and Options.
/// </summary>
public override sealed bool Equals(Layer other)
{
return base.Equals(other) && Equals(other as IpV4Layer);
return Equals(other as IpV4Layer);
}
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the TypeOfService and Identification combined and the hash codes of the layer length, data link, Fragmentation, Protocol, HeaderChecksum, Source, Destination, Options.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
......@@ -174,6 +184,9 @@ namespace PcapDotNet.Packets.IpV4
}
/// <summary>
/// Contains the Source, Destination and Protocol.
/// </summary>
public override string ToString()
{
return Source + " -> " + Destination + " (" + Protocol + ")";
......
......@@ -47,17 +47,11 @@ namespace PcapDotNet.Packets
/// <summary>
/// True iff the two objects are equal Layers.
/// In order to be equal, the two layers must have identical length and data link.
/// </summary>
public virtual bool Equals(Layer other)
{
return other != null &&
Length == other.Length && DataLink == other.DataLink;
}
public abstract bool Equals(Layer other);
/// <summary>
/// True iff the two objects are equal Layers.
/// In order to be equal, the two layers must have identical length and data link.
/// </summary>
public override sealed bool Equals(object obj)
{
......@@ -66,7 +60,7 @@ namespace PcapDotNet.Packets
/// <summary>
/// Returns a hash code for the layer.
/// The hash code base is a XOR of the layer length and data link.
/// The hash code base is a XOR of the hash codes of the layer length and data link.
/// </summary>
public override int GetHashCode()
{
......
......@@ -412,6 +412,13 @@ namespace PcapDotNet.Packets
Write(buffer, offset, value);
}
/// <summary>
/// Writes the given value to the buffer using the given endianity and increments the offset by the number of bytes written.
/// </summary>
/// <param name="buffer">The buffer to write the value to.</param>
/// <param name="offset">The offset in the buffer to start writing.</param>
/// <param name="value">The value to write.</param>
/// <param name="endianity">The endianity to use when converting the value to bytes.</param>
public static void Write(this byte[] buffer, ref int offset, int value, Endianity endianity)
{
Write(buffer, offset, value, endianity);
......@@ -541,6 +548,13 @@ namespace PcapDotNet.Packets
buffer.Write(ref offset, value.ToValue(), endianity);
}
/// <summary>
/// Writes the given value to the buffer using the given endianity.
/// </summary>
/// <param name="buffer">The buffer to write the value to.</param>
/// <param name="offset">The offset in the buffer to start writing.</param>
/// <param name="value">The value to write.</param>
/// <param name="endianity">The endianity to use when converting the value to bytes.</param>
public static void Write(this byte[] buffer, int offset, IpV4TimeOfDay value, Endianity endianity)
{
buffer.Write(offset, value.MillisecondsSinceMidnightUniversalTime, endianity);
......
......@@ -44,16 +44,33 @@ namespace PcapDotNet.Packets
/// </summary>
public class PacketBuilder
{
/// <summary>
/// Builds a single packet using the given layers with the given timestamp.
/// </summary>
/// <param name="timestamp">The packet's timestamp.</param>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
/// <returns>A packet built from the given layers with the given timestamp.</returns>
public static Packet Build(DateTime timestamp, params ILayer[] layers)
{
return new PacketBuilder(layers).Build(timestamp);
}
/// <summary>
/// Builds a single packet using the given layers with the given timestamp.
/// </summary>
/// <param name="timestamp">The packet's timestamp.</param>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
/// <returns>A packet built from the given layers with the given timestamp.</returns>
public static Packet Build(DateTime timestamp, IEnumerable<ILayer> layers)
{
return new PacketBuilder(layers).Build(timestamp);
}
/// <summary>
/// Creates a PacketBuilder that can build packets according to the given layers and with different timestamps.
/// The layers' properties can be modified after the builder is built and this will affect the packets built.
/// </summary>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
public PacketBuilder(params ILayer[] layers)
{
if (layers.Length == 0)
......@@ -67,11 +84,22 @@ namespace PcapDotNet.Packets
_dataLink = new DataLink(dataLinkKind.Value);
}
/// <summary>
/// Creates a PacketBuilder that can build packets according to the given layers and with different timestamps.
/// The layers' properties can be modified after the builder is built and this will affect the packets built.
/// </summary>
/// <param name="layers">The layers to build the packet accordingly and by their order.</param>
public PacketBuilder(IEnumerable<ILayer> layers)
:this(layers.ToArray())
{
}
/// <summary>
/// Builds a single packet using the builder's layers with the given timestamp.
/// </summary>
/// <param name="timestamp">The packet's timestamp.</param>
/// <returns>A packet built from the builder's layers with the given timestamp.</returns>
public Packet Build(DateTime timestamp)
{
int length = _layers.Select(layer => layer.Length).Sum();
......
......@@ -43,7 +43,7 @@ namespace PcapDotNet.Packets
/// </summary>
public override sealed bool Equals(Layer other)
{
return base.Equals(other) && Equals(other as PayloadLayer);
return Equals(other as PayloadLayer);
}
/// <summary>
......
......@@ -93,7 +93,18 @@ namespace PcapDotNet.Packets.Transport
Options);
}
public bool Equals(TcpLayer other)
/// <summary>
/// True iff the SequenceNumber, AcknowledgmentNumber, ControlBits, Window, UrgentPointer and Options fields are equal.
/// </summary>
protected override sealed bool EqualFields(TransportLayer other)
{
return EqualFields(other as TcpLayer);
}
/// <summary>
/// True iff the SequenceNumber, AcknowledgmentNumber, ControlBits, Window, UrgentPointer and Options fields are equal.
/// </summary>
private bool EqualFields(TcpLayer other)
{
return other != null &&
SequenceNumber == other.SequenceNumber && AcknowledgmentNumber == other.AcknowledgmentNumber &&
......@@ -101,10 +112,5 @@ namespace PcapDotNet.Packets.Transport
Window == other.Window && UrgentPointer == other.UrgentPointer &&
Options.Equals(other.Options);
}
public override sealed bool Equals(TransportLayer other)
{
return base.Equals(other) && Equals(other as TcpLayer);
}
}
}
\ No newline at end of file
......@@ -51,24 +51,45 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public abstract bool IsChecksumOptional { get; }
public virtual bool Equals(TransportLayer other)
/// <summary>
/// Two Transport layers are equal if they have they have the same previous layer protocol value, checksum, source and destination ports,
/// and if the specific transport protocol fields are equal.
/// </summary>
public bool Equals(TransportLayer other)
{
return other != null &&
PreviousLayerProtocol == other.PreviousLayerProtocol &&
Checksum == other.Checksum &&
SourcePort == other.SourcePort && DestinationPort == other.DestinationPort;
SourcePort == other.SourcePort && DestinationPort == other.DestinationPort &&
EqualFields(other);
}
/// <summary>
/// Two Transport layers are equal if they have they have the same previous layer protocol value, checksum, source and destination ports,
/// and if the specific transport protocol fields are equal.
/// </summary>
public override sealed bool Equals(Layer other)
{
return base.Equals(other) && Equals(other as TransportLayer);
return Equals(other as TransportLayer);
}
/// <summary>
/// Returns a hash code for the layer.
/// The hash code is a XOR of the combination of the source and destination ports and the hash codes of the layer length, data link and checksum.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
Checksum.GetHashCode() ^
((SourcePort << 16) + DestinationPort);
}
/// <summary>
/// True iff the specific transport layer fields are equal.
/// </summary>
protected virtual bool EqualFields(TransportLayer other)
{
return true;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment