Commit 136fbcc7 authored by Brickner_cp's avatar Brickner_cp

Code Analysis and Documentation - 185 warnings left.

parent 738f640a
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<NoWarn>1718</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
......
...@@ -11,6 +11,9 @@ namespace PcapDotNet.Base ...@@ -11,6 +11,9 @@ namespace PcapDotNet.Base
/// </summary> /// </summary>
public static class MoreIEnumerable public static class MoreIEnumerable
{ {
/// <summary>
/// True iff the sequence has no elements.
/// </summary>
public static bool IsEmpty<T>(this IEnumerable<T> sequence) public static bool IsEmpty<T>(this IEnumerable<T> sequence)
{ {
return !sequence.GetEnumerator().MoveNext(); return !sequence.GetEnumerator().MoveNext();
......
...@@ -2,11 +2,17 @@ using System.Reflection; ...@@ -2,11 +2,17 @@ using System.Reflection;
namespace PcapDotNet.Base namespace PcapDotNet.Base
{ {
/// <summary>
/// Extension methods for PropertyInfo.
/// </summary>
public static class MorePropertyInfo public static class MorePropertyInfo
{ {
public static object GetValue(this PropertyInfo propertyInfo, object obj) /// <summary>
/// Returns the value of the given instance's non-indexed property.
/// </summary>
public static object GetValue(this PropertyInfo propertyInfo, object instanceWithProperty)
{ {
return propertyInfo.GetValue(obj, null); return propertyInfo.GetValue(instanceWithProperty, null);
} }
} }
} }
\ No newline at end of file
...@@ -3,8 +3,14 @@ using System.Collections.Generic; ...@@ -3,8 +3,14 @@ using System.Collections.Generic;
namespace PcapDotNet.Base namespace PcapDotNet.Base
{ {
/// <summary>
/// Extension methods for Type.
/// </summary>
public static class MoreType public static class MoreType
{ {
/// <summary>
/// Returns all the possible values for the given enum type.
/// </summary>
public static IEnumerable<T> GetEnumValues<T>(this Type type) public static IEnumerable<T> GetEnumValues<T>(this Type type)
{ {
return (IEnumerable<T>)Enum.GetValues(type); return (IEnumerable<T>)Enum.GetValues(type);
......
...@@ -34,9 +34,9 @@ namespace PcapDotNet.Core.Test ...@@ -34,9 +34,9 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.EchoReply: case TcpOptionType.EchoReply:
return "Echo reply: " + ((TcpOptionEchoReply)option).Info; return "Echo reply: " + ((TcpOptionEchoReply)option).Info;
case TcpOptionType.TimeStamp: case TcpOptionType.Timestamp:
TcpOptionTimeStamp timeStampOption = (TcpOptionTimeStamp)option; TcpOptionTimestamp timestampOption = (TcpOptionTimestamp)option;
return "Timestamps: TSval " + timeStampOption.TimeStampValue + ", TSecr " + timeStampOption.TimeStampEchoReply; return "Timestamps: TSval " + timestampOption.TimestampValue + ", TSecr " + timestampOption.TimestampEchoReply;
case TcpOptionType.PartialOrderServiceProfile: case TcpOptionType.PartialOrderServiceProfile:
return "Unknown (0x0a) (3 bytes)"; return "Unknown (0x0a) (3 bytes)";
...@@ -100,7 +100,7 @@ namespace PcapDotNet.Core.Test ...@@ -100,7 +100,7 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.SelectiveAcknowledgmentPermitted: case TcpOptionType.SelectiveAcknowledgmentPermitted:
case TcpOptionType.Echo: case TcpOptionType.Echo:
case TcpOptionType.EchoReply: case TcpOptionType.EchoReply:
case TcpOptionType.TimeStamp: case TcpOptionType.Timestamp:
case TcpOptionType.PartialOrderServiceProfile: case TcpOptionType.PartialOrderServiceProfile:
case TcpOptionType.PartialOrderConnectionPermitted: case TcpOptionType.PartialOrderConnectionPermitted:
case TcpOptionType.ConnectionCount: case TcpOptionType.ConnectionCount:
......
...@@ -77,7 +77,7 @@ namespace PcapDotNet.Core.Test ...@@ -77,7 +77,7 @@ namespace PcapDotNet.Core.Test
[TestMethod] [TestMethod]
public void ComparePacketsToWiresharkTest() public void ComparePacketsToWiresharkTest()
{ {
for (int i = 0; i != 500; ++i) for (int i = 0; i != 50; ++i)
{ {
// Create packets // Create packets
List<Packet> packets = new List<Packet>(CreateRandomPackets(200)); List<Packet> packets = new List<Packet>(CreateRandomPackets(200));
...@@ -531,19 +531,19 @@ namespace PcapDotNet.Core.Test ...@@ -531,19 +531,19 @@ namespace PcapDotNet.Core.Test
switch (flagField.Name()) switch (flagField.Name())
{ {
case "tcp.flags.cwr": case "tcp.flags.cwr":
flagField.AssertShowDecimal(tcpDatagram.IsCwr); flagField.AssertShowDecimal(tcpDatagram.IsCongestionWindowReduced);
break; break;
case "tcp.flags.ecn": case "tcp.flags.ecn":
flagField.AssertShowDecimal(tcpDatagram.IsEce); flagField.AssertShowDecimal(tcpDatagram.IsExplicitCongestionNotificationEcho);
break; break;
case "tcp.flags.urg": case "tcp.flags.urg":
flagField.AssertShowDecimal(tcpDatagram.IsUrg); flagField.AssertShowDecimal(tcpDatagram.IsUrgent);
break; break;
case "tcp.flags.ack": case "tcp.flags.ack":
flagField.AssertShowDecimal(tcpDatagram.IsAck); flagField.AssertShowDecimal(tcpDatagram.IsAcknowledgment);
break; break;
case "tcp.flags.push": case "tcp.flags.push":
...@@ -555,7 +555,7 @@ namespace PcapDotNet.Core.Test ...@@ -555,7 +555,7 @@ namespace PcapDotNet.Core.Test
break; break;
case "tcp.flags.syn": case "tcp.flags.syn":
flagField.AssertShowDecimal(tcpDatagram.IsSyn); flagField.AssertShowDecimal(tcpDatagram.IsSynchronize);
break; break;
case "tcp.flags.fin": case "tcp.flags.fin":
...@@ -643,7 +643,7 @@ namespace PcapDotNet.Core.Test ...@@ -643,7 +643,7 @@ namespace PcapDotNet.Core.Test
break; break;
case "tcp.options.time_stamp": case "tcp.options.time_stamp":
Assert.IsTrue(option is TcpOptionTimeStamp); Assert.IsTrue(option is TcpOptionTimestamp);
field.AssertShowDecimal(1); field.AssertShowDecimal(1);
break; break;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<NoWarn>1718</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
......
...@@ -117,14 +117,14 @@ namespace PcapDotNet.Packets.Test ...@@ -117,14 +117,14 @@ namespace PcapDotNet.Packets.Test
Assert.IsFalse(string.IsNullOrEmpty(option.ToString())); Assert.IsFalse(string.IsNullOrEmpty(option.ToString()));
} }
Assert.AreEqual(tcpOptions, packet.Ethernet.IpV4.Tcp.Options, "Options"); Assert.AreEqual(tcpOptions, packet.Ethernet.IpV4.Tcp.Options, "Options");
Assert.AreEqual((tcpFlags & TcpFlags.Ack) == TcpFlags.Ack, packet.Ethernet.IpV4.Tcp.IsAck, "IsAck"); Assert.AreEqual((tcpFlags & TcpFlags.Acknowledgment) == TcpFlags.Acknowledgment, packet.Ethernet.IpV4.Tcp.IsAcknowledgment, "IsAcknowledgment");
Assert.AreEqual((tcpFlags & TcpFlags.Cwr) == TcpFlags.Cwr, packet.Ethernet.IpV4.Tcp.IsCwr, "IsCwr"); Assert.AreEqual((tcpFlags & TcpFlags.CongestionWindowReduced) == TcpFlags.CongestionWindowReduced, packet.Ethernet.IpV4.Tcp.IsCongestionWindowReduced, "IsCongestionWindowReduced");
Assert.AreEqual((tcpFlags & TcpFlags.Ece) == TcpFlags.Ece, packet.Ethernet.IpV4.Tcp.IsEce, "IsEce"); Assert.AreEqual((tcpFlags & TcpFlags.ExplicitCongestionNotificationEcho) == TcpFlags.ExplicitCongestionNotificationEcho, packet.Ethernet.IpV4.Tcp.IsExplicitCongestionNotificationEcho, "IsExplicitCongestionNotificationEcho");
Assert.AreEqual((tcpFlags & TcpFlags.Fin) == TcpFlags.Fin, packet.Ethernet.IpV4.Tcp.IsFin, "IsFin"); Assert.AreEqual((tcpFlags & TcpFlags.Fin) == TcpFlags.Fin, packet.Ethernet.IpV4.Tcp.IsFin, "IsFin");
Assert.AreEqual((tcpFlags & TcpFlags.Psh) == TcpFlags.Psh, packet.Ethernet.IpV4.Tcp.IsPush, "IsPush"); Assert.AreEqual((tcpFlags & TcpFlags.Push) == TcpFlags.Push, packet.Ethernet.IpV4.Tcp.IsPush, "IsPush");
Assert.AreEqual((tcpFlags & TcpFlags.Rst) == TcpFlags.Rst, packet.Ethernet.IpV4.Tcp.IsReset, "IsReset"); Assert.AreEqual((tcpFlags & TcpFlags.Reset) == TcpFlags.Reset, packet.Ethernet.IpV4.Tcp.IsReset, "IsReset");
Assert.AreEqual((tcpFlags & TcpFlags.Syn) == TcpFlags.Syn, packet.Ethernet.IpV4.Tcp.IsSyn, "IsSyn"); Assert.AreEqual((tcpFlags & TcpFlags.Synchronize) == TcpFlags.Synchronize, packet.Ethernet.IpV4.Tcp.IsSynchronize, "IsSynchronize");
Assert.AreEqual((tcpFlags & TcpFlags.Urg) == TcpFlags.Urg, packet.Ethernet.IpV4.Tcp.IsUrg, "IsUrg"); Assert.AreEqual((tcpFlags & TcpFlags.Urgent) == TcpFlags.Urgent, packet.Ethernet.IpV4.Tcp.IsUrgent, "IsUrgent");
Assert.IsFalse(packet.Ethernet.IpV4.Tcp.IsChecksumOptional, "IsChecksumOptional"); Assert.IsFalse(packet.Ethernet.IpV4.Tcp.IsChecksumOptional, "IsChecksumOptional");
Assert.AreEqual(TcpDatagram.HeaderMinimumLength + tcpOptions.BytesLength + tcpPayload.Length, packet.Ethernet.IpV4.Tcp.Length, "Total Length"); Assert.AreEqual(TcpDatagram.HeaderMinimumLength + tcpOptions.BytesLength + tcpPayload.Length, packet.Ethernet.IpV4.Tcp.Length, "Total Length");
Assert.IsTrue(packet.Ethernet.IpV4.IsTransportChecksumCorrect, "IsTransportChecksumCorrect"); Assert.IsTrue(packet.Ethernet.IpV4.IsTransportChecksumCorrect, "IsTransportChecksumCorrect");
......
...@@ -287,8 +287,8 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -287,8 +287,8 @@ namespace PcapDotNet.Packets.TestUtils
impossibleOptionTypes.Add(TcpOptionType.Echo); impossibleOptionTypes.Add(TcpOptionType.Echo);
if (maximumOptionLength < TcpOptionEchoReply.OptionLength) if (maximumOptionLength < TcpOptionEchoReply.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.EchoReply); impossibleOptionTypes.Add(TcpOptionType.EchoReply);
if (maximumOptionLength < TcpOptionTimeStamp.OptionLength) if (maximumOptionLength < TcpOptionTimestamp.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.TimeStamp); impossibleOptionTypes.Add(TcpOptionType.Timestamp);
if (maximumOptionLength < TcpOptionPartialOrderServiceProfile.OptionLength) if (maximumOptionLength < TcpOptionPartialOrderServiceProfile.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.PartialOrderServiceProfile); impossibleOptionTypes.Add(TcpOptionType.PartialOrderServiceProfile);
if (maximumOptionLength < TcpOptionPartialOrderConnectionPermitted.OptionLength) if (maximumOptionLength < TcpOptionPartialOrderConnectionPermitted.OptionLength)
...@@ -340,8 +340,8 @@ namespace PcapDotNet.Packets.TestUtils ...@@ -340,8 +340,8 @@ namespace PcapDotNet.Packets.TestUtils
case TcpOptionType.EchoReply: case TcpOptionType.EchoReply:
return new TcpOptionEchoReply(random.NextUInt()); return new TcpOptionEchoReply(random.NextUInt());
case TcpOptionType.TimeStamp: case TcpOptionType.Timestamp:
return new TcpOptionTimeStamp(random.NextUInt(), random.NextUInt()); return new TcpOptionTimestamp(random.NextUInt(), random.NextUInt());
case TcpOptionType.PartialOrderServiceProfile: case TcpOptionType.PartialOrderServiceProfile:
return new TcpOptionPartialOrderServiceProfile(random.NextBool(), random.NextBool()); return new TcpOptionPartialOrderServiceProfile(random.NextBool(), random.NextBool());
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
<Word>unicast</Word> <Word>unicast</Word>
<Word>genser</Word> <Word>genser</Word>
<Word>nsa</Word> <Word>nsa</Word>
<Word>md</Word>
</Recognized> </Recognized>
<Deprecated> <Deprecated>
<!--Term PreferredAlternate="EnterpriseServices">complus</Term--> <!--Term PreferredAlternate="EnterpriseServices">complus</Term-->
......
namespace PcapDotNet.Packets
{
/// <summary>
/// A factory interface for an unknown option.
/// </summary>
/// <typeparam name="TOptionType">The option type enum type.</typeparam>
public interface IOptionUnknownFactory<TOptionType>
{
/// <summary>
/// Creates an unknown option from its type and by reading a buffer for its value.
/// </summary>
/// <param name="optionType">The type of the unknown option.</param>
/// <param name="buffer">The buffer of bytes to read the value of the unknown option.</param>
/// <param name="offset">The offset in the buffer to start reading the bytes.</param>
/// <param name="valueLength">The number of bytes to read from the buffer.</param>
/// <returns>An option created from the given type and buffer.</returns>
Option CreateInstance(TOptionType optionType, byte[] buffer, ref int offset, byte valueLength);
}
}
\ No newline at end of file
namespace PcapDotNet.Packets
{
public interface IOptionUnkownFactory<TOptionType>
{
Option CreateInstance(TOptionType optionType, byte[] buffer, ref int offset, byte valueLength);
}
}
\ No newline at end of file
...@@ -183,6 +183,11 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -183,6 +183,11 @@ namespace PcapDotNet.Packets.IpV4
} }
} }
/// <summary>
/// Returns whether the TCP or UDP checksum is correct.
/// The protocol must be TCP or UDP.
/// For UDP, the checksum is optional, so 0 checksum is still correct.
/// </summary>
public bool IsTransportChecksumCorrect public bool IsTransportChecksumCorrect
{ {
get get
......
...@@ -39,9 +39,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -39,9 +39,9 @@ namespace PcapDotNet.Packets.IpV4
/// Checks whether two options have equivalent type. /// Checks whether two options have equivalent type.
/// Useful to check if an option that must appear at most once appears in the list. /// Useful to check if an option that must appear at most once appears in the list.
/// </summary> /// </summary>
public override bool Equivalent(Option option) public override bool Equivalent(Option other)
{ {
return OptionType == ((IpV4Option)option).OptionType; return OptionType == ((IpV4Option)other).OptionType;
} }
/// <summary> /// <summary>
......
...@@ -6,7 +6,10 @@ using PcapDotNet.Base; ...@@ -6,7 +6,10 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets.IpV4 namespace PcapDotNet.Packets.IpV4
{ {
public class IpV4OptionUnknown : IpV4OptionComplex, IOptionUnkownFactory<IpV4OptionType>, IEquatable<IpV4OptionUnknown> /// <summary>
/// An unknown IPv4 option.
/// </summary>
public class IpV4OptionUnknown : IpV4OptionComplex, IOptionUnknownFactory<IpV4OptionType>, IEquatable<IpV4OptionUnknown>
{ {
/// <summary> /// <summary>
/// The minimum number of bytes this option take. /// The minimum number of bytes this option take.
...@@ -18,12 +21,18 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -18,12 +21,18 @@ namespace PcapDotNet.Packets.IpV4
/// </summary> /// </summary>
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength; public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
/// <summary>
/// Creates an unknown IPv4 option by the given type and data.
/// </summary>
public IpV4OptionUnknown(IpV4OptionType optionType, IList<byte> data) public IpV4OptionUnknown(IpV4OptionType optionType, IList<byte> data)
: base(optionType) : base(optionType)
{ {
Data = new ReadOnlyCollection<byte>(data); Data = new ReadOnlyCollection<byte>(data);
} }
/// <summary>
/// The default unknown option is with type 255 and no data.
/// </summary>
public IpV4OptionUnknown() public IpV4OptionUnknown()
: this((IpV4OptionType)255, new byte[] {}) : this((IpV4OptionType)255, new byte[] {})
{ {
...@@ -47,6 +56,9 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -47,6 +56,9 @@ namespace PcapDotNet.Packets.IpV4
get { return false; } get { return false; }
} }
/// <summary>
/// Two unknown options are equal iff they are of equal type and equal data.
/// </summary>
public bool Equals(IpV4OptionUnknown other) public bool Equals(IpV4OptionUnknown other)
{ {
if (other == null) if (other == null)
...@@ -56,16 +68,30 @@ namespace PcapDotNet.Packets.IpV4 ...@@ -56,16 +68,30 @@ namespace PcapDotNet.Packets.IpV4
Data.SequenceEqual(other.Data); Data.SequenceEqual(other.Data);
} }
/// <summary>
/// Two unknown options are equal iff they are of equal type and equal data.
/// </summary>
public override bool Equals(IpV4Option other) public override bool Equals(IpV4Option other)
{ {
return Equals(other as IpV4OptionUnknown); return Equals(other as IpV4OptionUnknown);
} }
/// <summary>
/// The hash code for an unknown option is the hash code for the option type xored with the hash code of the data.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ Data.BytesSequenceGetHashCode(); return base.GetHashCode() ^ Data.BytesSequenceGetHashCode();
} }
/// <summary>
/// Creates an unknown option from its type and by reading a buffer for its value.
/// </summary>
/// <param name="optionType">The type of the unknown option.</param>
/// <param name="buffer">The buffer of bytes to read the value of the unknown option.</param>
/// <param name="offset">The offset in the buffer to start reading the bytes.</param>
/// <param name="valueLength">The number of bytes to read from the buffer.</param>
/// <returns>An option created from the given type and buffer.</returns>
public Option CreateInstance(IpV4OptionType optionType, byte[] buffer, ref int offset, byte valueLength) public Option CreateInstance(IpV4OptionType optionType, byte[] buffer, ref int offset, byte valueLength)
{ {
if (valueLength < OptionValueMinimumLength) if (valueLength < OptionValueMinimumLength)
......
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
/// <summary>
/// A generic option (for IPv4 and TCP).
/// The option is read from buffer and can be of different length.
/// </summary>
public abstract class Option public abstract class Option
{ {
/// <summary> /// <summary>
......
...@@ -6,13 +6,20 @@ using PcapDotNet.Base; ...@@ -6,13 +6,20 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets namespace PcapDotNet.Packets
{ {
public class OptionComplexFactory<TOptionType> public class OptionComplexFactoryBase
{ {
/// <summary> /// <summary>
/// The header length in bytes for the option (type and size). /// The header length in bytes for the option (type and size).
/// </summary> /// </summary>
public const int OptionHeaderLength = 2; public const int OptionHeaderLength = 2;
protected OptionComplexFactoryBase()
{
}
}
public sealed class OptionComplexFactory<TOptionType> : OptionComplexFactoryBase
{
internal static Option Read(TOptionType optionType, byte[] buffer, ref int offset, int length) internal static Option Read(TOptionType optionType, byte[] buffer, ref int offset, int length)
{ {
if (length < 1) if (length < 1)
...@@ -24,22 +31,22 @@ namespace PcapDotNet.Packets ...@@ -24,22 +31,22 @@ namespace PcapDotNet.Packets
IOptionComplexFactory prototype; IOptionComplexFactory prototype;
if (!_complexOptions.TryGetValue(optionType, out prototype)) if (!_complexOptions.TryGetValue(optionType, out prototype))
return _unkownFactoryOptionPrototype.CreateInstance(optionType, buffer, ref offset, optionValueLength); return UnknownFactoryOptionPrototype.CreateInstance(optionType, buffer, ref offset, optionValueLength);
return prototype.CreateInstance(buffer, ref offset, optionValueLength); return prototype.CreateInstance(buffer, ref offset, optionValueLength);
} }
private static IOptionUnkownFactory<TOptionType> InitializeUnkownOptionPrototype() private static IOptionUnknownFactory<TOptionType> InitializeUnknownOptionPrototype()
{ {
var unkownOptions = var unknownOptions =
from type in Assembly.GetExecutingAssembly().GetTypes() from type in Assembly.GetExecutingAssembly().GetTypes()
where typeof(IOptionUnkownFactory<TOptionType>).IsAssignableFrom(type) where typeof(IOptionUnknownFactory<TOptionType>).IsAssignableFrom(type)
select (IOptionUnkownFactory<TOptionType>)Activator.CreateInstance(type); select (IOptionUnknownFactory<TOptionType>)Activator.CreateInstance(type);
if (unkownOptions.Count() != 1) if (unknownOptions.Count() != 1)
throw new InvalidOperationException("Must be only one unkown option for option type " + typeof(TOptionType)); throw new InvalidOperationException("Must be only one unknown option for option type " + typeof(TOptionType));
return unkownOptions.First(); return unknownOptions.First();
} }
private static Dictionary<TOptionType, IOptionComplexFactory> InitializeComplexOptions() private static Dictionary<TOptionType, IOptionComplexFactory> InitializeComplexOptions()
...@@ -70,7 +77,11 @@ namespace PcapDotNet.Packets ...@@ -70,7 +77,11 @@ namespace PcapDotNet.Packets
return registraionAttributes.First(); return registraionAttributes.First();
} }
private OptionComplexFactory()
{
}
private static readonly Dictionary<TOptionType, IOptionComplexFactory> _complexOptions = InitializeComplexOptions(); private static readonly Dictionary<TOptionType, IOptionComplexFactory> _complexOptions = InitializeComplexOptions();
private static readonly IOptionUnkownFactory<TOptionType> _unkownFactoryOptionPrototype = InitializeUnkownOptionPrototype(); private static readonly IOptionUnknownFactory<TOptionType> UnknownFactoryOptionPrototype = InitializeUnknownOptionPrototype();
} }
} }
\ No newline at end of file
...@@ -132,6 +132,7 @@ namespace PcapDotNet.Packets ...@@ -132,6 +132,7 @@ namespace PcapDotNet.Packets
/// <param name="tcpDestinationPort">The destination udp port.</param> /// <param name="tcpDestinationPort">The destination udp port.</param>
/// <param name="tcpPayload">The payload of UDP datagram.</param> /// <param name="tcpPayload">The payload of UDP datagram.</param>
/// <returns>A packet with a UDP over IPv4 over Ethernet datagram.</returns> /// <returns>A packet with a UDP over IPv4 over Ethernet datagram.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flags"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "pointer")]
public static Packet EthernetIpV4Tcp(DateTime timestamp, public static Packet EthernetIpV4Tcp(DateTime timestamp,
MacAddress ethernetSource, MacAddress ethernetDestination, MacAddress ethernetSource, MacAddress ethernetDestination,
byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation, byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation,
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
<Compile Include="Ethernet\EthernetType.cs" /> <Compile Include="Ethernet\EthernetType.cs" />
<Compile Include="Ethernet\MacAddress.cs" /> <Compile Include="Ethernet\MacAddress.cs" />
<Compile Include="IDataLink.cs" /> <Compile Include="IDataLink.cs" />
<Compile Include="IOptionUnkownFactory.cs" /> <Compile Include="IOptionUnknownFactory.cs" />
<Compile Include="IpV4\IpV4OptionUnknown.cs" /> <Compile Include="IpV4\IpV4OptionUnknown.cs" />
<Compile Include="Option.cs" /> <Compile Include="Option.cs" />
<Compile Include="IOptionComplexFactory.cs" /> <Compile Include="IOptionComplexFactory.cs" />
...@@ -130,7 +130,7 @@ ...@@ -130,7 +130,7 @@
<Compile Include="Transport\TcpOptionSelectiveAcknowledgmentBlock.cs" /> <Compile Include="Transport\TcpOptionSelectiveAcknowledgmentBlock.cs" />
<Compile Include="Transport\TcpOptionSelectiveAcknowledgmentPermitted.cs" /> <Compile Include="Transport\TcpOptionSelectiveAcknowledgmentPermitted.cs" />
<Compile Include="Transport\TcpOptionSimple.cs" /> <Compile Include="Transport\TcpOptionSimple.cs" />
<Compile Include="Transport\TcpOptionTimeStamp.cs" /> <Compile Include="Transport\TcpOptionTimestamp.cs" />
<Compile Include="Transport\TcpOptionType.cs" /> <Compile Include="Transport\TcpOptionType.cs" />
<Compile Include="Transport\TcpOptionUnknown.cs" /> <Compile Include="Transport\TcpOptionUnknown.cs" />
<Compile Include="Transport\TcpOptionWindowScale.cs" /> <Compile Include="Transport\TcpOptionWindowScale.cs" />
......
...@@ -75,6 +75,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -75,6 +75,7 @@ namespace PcapDotNet.Packets.Transport
get { return Math.Min(HeaderLength, Length); } get { return Math.Min(HeaderLength, Length); }
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flags")]
public TcpFlags Flags public TcpFlags Flags
{ {
get { return (TcpFlags)(ReadUShort(Offset.HeaderLengthAndFlags, Endianity.Big) & 0x01FF); } get { return (TcpFlags)(ReadUShort(Offset.HeaderLengthAndFlags, Endianity.Big) & 0x01FF); }
...@@ -90,11 +91,6 @@ namespace PcapDotNet.Packets.Transport ...@@ -90,11 +91,6 @@ namespace PcapDotNet.Packets.Transport
get { return ReadUShort(Offset.Checksum, Endianity.Big); } get { return ReadUShort(Offset.Checksum, Endianity.Big); }
} }
public override int ChecksumOffset
{
get { return Offset.Checksum; }
}
public override bool IsChecksumOptional public override bool IsChecksumOptional
{ {
get { return false; } get { return false; }
...@@ -123,39 +119,39 @@ namespace PcapDotNet.Packets.Transport ...@@ -123,39 +119,39 @@ namespace PcapDotNet.Packets.Transport
get { return new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength); } get { return new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength); }
} }
public bool IsCwr public bool IsCongestionWindowReduced
{ {
get { return (Flags & TcpFlags.Cwr) == TcpFlags.Cwr; } get { return (Flags & TcpFlags.CongestionWindowReduced) == TcpFlags.CongestionWindowReduced; }
} }
public bool IsEce public bool IsExplicitCongestionNotificationEcho
{ {
get { return (Flags & TcpFlags.Ece) == TcpFlags.Ece; } get { return (Flags & TcpFlags.ExplicitCongestionNotificationEcho) == TcpFlags.ExplicitCongestionNotificationEcho; }
} }
public bool IsUrg public bool IsUrgent
{ {
get { return (Flags & TcpFlags.Urg) == TcpFlags.Urg; } get { return (Flags & TcpFlags.Urgent) == TcpFlags.Urgent; }
} }
public bool IsAck public bool IsAcknowledgment
{ {
get { return (Flags & TcpFlags.Ack) == TcpFlags.Ack; } get { return (Flags & TcpFlags.Acknowledgment) == TcpFlags.Acknowledgment; }
} }
public bool IsPush public bool IsPush
{ {
get { return (Flags & TcpFlags.Psh) == TcpFlags.Psh; } get { return (Flags & TcpFlags.Push) == TcpFlags.Push; }
} }
public bool IsReset public bool IsReset
{ {
get { return (Flags & TcpFlags.Rst) == TcpFlags.Rst; } get { return (Flags & TcpFlags.Reset) == TcpFlags.Reset; }
} }
public bool IsSyn public bool IsSynchronize
{ {
get { return (Flags & TcpFlags.Syn) == TcpFlags.Syn; } get { return (Flags & TcpFlags.Synchronize) == TcpFlags.Synchronize; }
} }
public bool IsFin public bool IsFin
...@@ -163,6 +159,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -163,6 +159,11 @@ namespace PcapDotNet.Packets.Transport
get { return (Flags & TcpFlags.Fin) == TcpFlags.Fin; } get { return (Flags & TcpFlags.Fin) == TcpFlags.Fin; }
} }
internal override int ChecksumOffset
{
get { return Offset.Checksum; }
}
internal static void WriteHeader(byte[] buffer, int offset, internal static void WriteHeader(byte[] buffer, int offset,
ushort sourcePort, ushort destinationPort, ushort sourcePort, ushort destinationPort,
uint sequenceNumber, uint acknowledgmentNumber, uint sequenceNumber, uint acknowledgmentNumber,
......
...@@ -10,18 +10,18 @@ namespace PcapDotNet.Packets.Transport ...@@ -10,18 +10,18 @@ namespace PcapDotNet.Packets.Transport
/// | 0 | | NS | CWR | ECE | URG | ACK | PSH | RST | SYN | FIN | /// | 0 | | NS | CWR | ECE | URG | ACK | PSH | RST | SYN | FIN |
/// +-----+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+ /// +-----+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+
/// </summary> /// </summary>
[Flags] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flags"), Flags]
public enum TcpFlags : ushort public enum TcpFlags : ushort
{ {
None = 0x0000, None = 0x0000,
Fin = 0x0001, Fin = 0x0001,
Syn = 0x0002, Synchronize = 0x0002,
Rst = 0x0004, Reset = 0x0004,
Psh = 0x0008, Push = 0x0008,
Ack = 0x0010, Acknowledgment = 0x0010,
Urg = 0x0020, Urgent = 0x0020,
Ece = 0x0040, ExplicitCongestionNotificationEcho = 0x0040,
Cwr = 0x0080, CongestionWindowReduced = 0x0080,
Ns = 0x0100, Ns = 0x0100,
} }
} }
\ No newline at end of file
...@@ -2,25 +2,42 @@ using System; ...@@ -2,25 +2,42 @@ using System;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary>
/// Represents a TCP option according to rfc 793.
/// </summary>
public abstract class TcpOption : Option, IEquatable<TcpOption> public abstract class TcpOption : Option, IEquatable<TcpOption>
{ {
/// <summary>
/// This option code indicates the end of the option list.
/// This might not coincide with the end of the TCP header according to the Data Offset field.
/// This is used at the end of all options, not the end of each option,
/// and need only be used if the end of the options would not otherwise coincide with the end of the TCP header.
/// </summary>
public static TcpOption End public static TcpOption End
{ {
get { return _end; } get { return _end; }
} }
/// <summary>
/// This option code may be used between options,
/// for example, to align the beginning of a subsequent option on a word boundary.
/// There is no guarantee that senders will use this option,
/// so receivers must be prepared to process options even if they do not begin on a word boundary.
/// </summary>
public static TcpOption Nop public static TcpOption Nop
{ {
get { return _nop; } get { return _nop; }
} }
public TcpOption(TcpOptionType optionType) /// <summary>
{ /// The type of the TCP option.
OptionType = optionType; /// </summary>
}
public TcpOptionType OptionType { get; private set; } public TcpOptionType OptionType { get; private set; }
/// <summary>
/// Checks whether two options have equivalent type.
/// Useful to check if an option that must appear at most once appears in the list.
/// </summary>
public override bool Equivalent(Option other) public override bool Equivalent(Option other)
{ {
return OptionType == ((TcpOption)other).OptionType; return OptionType == ((TcpOption)other).OptionType;
...@@ -44,11 +61,18 @@ namespace PcapDotNet.Packets.Transport ...@@ -44,11 +61,18 @@ namespace PcapDotNet.Packets.Transport
return Equals(obj as TcpOption); return Equals(obj as TcpOption);
} }
/// <summary>
/// The hash code for a tcp option is the hash code for the option type.
/// This should be overridden by tcp options with data.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return OptionType.GetHashCode(); return OptionType.GetHashCode();
} }
/// <summary>
/// The string that represents the option type.
/// </summary>
public override string ToString() public override string ToString()
{ {
return OptionType.ToString(); return OptionType.ToString();
...@@ -78,6 +102,14 @@ namespace PcapDotNet.Packets.Transport ...@@ -78,6 +102,14 @@ namespace PcapDotNet.Packets.Transport
buffer[offset++] = (byte)OptionType; buffer[offset++] = (byte)OptionType;
} }
/// <summary>
/// Initializes the option type.
/// </summary>
protected TcpOption(TcpOptionType optionType)
{
OptionType = optionType;
}
private static readonly TcpOption _end = new TcpOptionSimple(TcpOptionType.EndOfOptionList); private static readonly TcpOption _end = new TcpOptionSimple(TcpOptionType.EndOfOptionList);
private static readonly TcpOption _nop = new TcpOptionSimple(TcpOptionType.NoOperation); private static readonly TcpOption _nop = new TcpOptionSimple(TcpOptionType.NoOperation);
} }
......
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
/// <summary>
/// Represents a complex TCP option.
/// Complex option means that it contains data and not just the type.
/// </summary>
public abstract class TcpOptionComplex : TcpOption public abstract class TcpOptionComplex : TcpOption
{ {
public const int OptionHeaderLength = 2; public const int OptionHeaderLength = 2;
......
...@@ -53,6 +53,9 @@ namespace PcapDotNet.Packets.Transport ...@@ -53,6 +53,9 @@ namespace PcapDotNet.Packets.Transport
/// </summary> /// </summary>
public const int OptionMinimumLength = 2; public const int OptionMinimumLength = 2;
/// <summary>
/// The minimum number of bytes this option's value take.
/// </summary>
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength; public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
public TcpOptionSelectiveAcknowledgment(IList<TcpOptionSelectiveAcknowledgmentBlock> blocks) public TcpOptionSelectiveAcknowledgment(IList<TcpOptionSelectiveAcknowledgmentBlock> blocks)
......
...@@ -5,19 +5,22 @@ namespace PcapDotNet.Packets.Transport ...@@ -5,19 +5,22 @@ namespace PcapDotNet.Packets.Transport
public const int SizeOf = 8; public const int SizeOf = 8;
public TcpOptionSelectiveAcknowledgmentBlock(uint leftEdge, uint rightEdge) public TcpOptionSelectiveAcknowledgmentBlock(uint leftEdge, uint rightEdge)
: this()
{ {
_leftEdge = leftEdge; LeftEdge = leftEdge;
_rightEdge = rightEdge; RightEdge = rightEdge;
} }
public uint LeftEdge public uint LeftEdge
{ {
get { return _leftEdge; } get;
private set;
} }
public uint RightEdge public uint RightEdge
{ {
get { return _rightEdge; } get;
private set;
} }
public override string ToString() public override string ToString()
...@@ -25,7 +28,46 @@ namespace PcapDotNet.Packets.Transport ...@@ -25,7 +28,46 @@ namespace PcapDotNet.Packets.Transport
return LeftEdge + "-" + RightEdge; return LeftEdge + "-" + RightEdge;
} }
private readonly uint _leftEdge; /// <summary>
private readonly uint _rightEdge; /// Two blocks are equal if the have the same left and right edges.
/// </summary>
public bool Equals(TcpOptionSelectiveAcknowledgmentBlock other)
{
return LeftEdge == other.LeftEdge &&
RightEdge == other.RightEdge;
}
/// <summary>
/// Two blocks are equal if the have the same left and right edges.
/// </summary>
public override bool Equals(object obj)
{
return (obj is TcpOptionSelectiveAcknowledgmentBlock &&
Equals((TcpOptionSelectiveAcknowledgmentBlock)obj));
}
/// <summary>
/// Two blocks are equal if the have the same left and right edges.
/// </summary>
public static bool operator ==(TcpOptionSelectiveAcknowledgmentBlock value1, TcpOptionSelectiveAcknowledgmentBlock value2)
{
return value1.Equals(value2);
}
/// <summary>
/// Two blocks are different if the have the different left or right edge.
/// </summary>
public static bool operator !=(TcpOptionSelectiveAcknowledgmentBlock value1, TcpOptionSelectiveAcknowledgmentBlock value2)
{
return !(value1 == value2);
}
/// <summary>
/// The hash code of a block is the xor between the hash code of left and right edges.
/// </summary>
public override int GetHashCode()
{
return LeftEdge.GetHashCode() ^ RightEdge.GetHashCode();
}
} }
} }
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// TCP Timestamps Option (TSopt):
/// +-------+-------+---------------------+---------------------+
/// |Kind=8 | 10 | TS Value (TSval) |TS Echo Reply (TSecr)|
/// +-------+-------+---------------------+---------------------+
/// 1 1 4 4
///
/// The Timestamps option carries two four-byte timestamp fields.
/// The Timestamp Value field (TSval) contains the current value of the timestamp clock of the TCP sending the option.
///
/// The Timestamp Echo Reply field (TSecr) is only valid if the ACK bit is set in the TCP header;
/// if it is valid, it echos a timestamp value that was sent by the remote TCP in the TSval field of a Timestamps option.
/// When TSecr is not valid, its value must be zero.
/// The TSecr value will generally be from the most recent Timestamp option that was received; however, there are exceptions that are explained below.
///
/// A TCP may send the Timestamps option (TSopt) in an initial <SYN> segment (i.e., segment containing a SYN bit and no ACK bit),
/// and may send a TSopt in other segments only if it received a TSopt in the initial <SYN> segment for the connection.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.Timestamp)]
public class TcpOptionTimestamp : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionTimestamp>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 10;
public const int OptionValueLength = OptionLength - OptionHeaderLength;
public TcpOptionTimestamp(uint timestampValue, uint timestampEchoReply)
: base(TcpOptionType.Timestamp)
{
TimestampValue = timestampValue;
TimestampEchoReply = timestampEchoReply;
}
public TcpOptionTimestamp()
: this(0, 0)
{
}
public uint TimestampValue { get; private set; }
public uint TimestampEchoReply { get; private set; }
/// <summary>
/// The number of bytes this option will take.
/// </summary>
public override int Length
{
get { return OptionLength; }
}
/// <summary>
/// True iff this option may appear at most once in a datagram.
/// </summary>
public override bool IsAppearsAtMostOnce
{
get { return true; }
}
public bool Equals(TcpOptionTimestamp other)
{
if (other == null)
return false;
return TimestampValue == other.TimestampValue &&
TimestampEchoReply == other.TimestampEchoReply;
}
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionTimestamp);
}
/// <summary>
/// Tries to read the option from a buffer starting from the option value (after the type and length).
/// </summary>
/// <param name="buffer">The buffer to read the option from.</param>
/// <param name="offset">The offset to the first byte to read the buffer. Will be incremented by the number of bytes read.</param>
/// <param name="valueLength">The number of bytes the option value should take according to the length field that was already read.</param>
/// <returns>On success - the complex option read. On failure - null.</returns>
public Option CreateInstance(byte[] buffer, ref int offset, byte valueLength)
{
if (valueLength != OptionValueLength)
return null;
uint timeStampValue = buffer.ReadUInt(ref offset, Endianity.Big);
uint timeStampEchoReply = buffer.ReadUInt(ref offset, Endianity.Big);
return new TcpOptionTimestamp(timeStampValue, timeStampEchoReply);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, TimestampValue, Endianity.Big);
buffer.Write(ref offset, TimestampEchoReply, Endianity.Big);
}
}
}
\ No newline at end of file
...@@ -10,7 +10,7 @@ namespace PcapDotNet.Packets.Transport ...@@ -10,7 +10,7 @@ namespace PcapDotNet.Packets.Transport
SelectiveAcknowledgment = 5, SelectiveAcknowledgment = 5,
Echo = 6, Echo = 6,
EchoReply = 7, EchoReply = 7,
TimeStamp = 8, Timestamp = 8,
PartialOrderConnectionPermitted = 9, PartialOrderConnectionPermitted = 9,
PartialOrderServiceProfile = 10, PartialOrderServiceProfile = 10,
ConnectionCount = 11, ConnectionCount = 11,
......
...@@ -6,7 +6,10 @@ using PcapDotNet.Base; ...@@ -6,7 +6,10 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets.Transport namespace PcapDotNet.Packets.Transport
{ {
public class TcpOptionUnknown : TcpOptionComplex, IOptionUnkownFactory<TcpOptionType>, IEquatable<TcpOptionUnknown> /// <summary>
/// An unknown TCP option.
/// </summary>
public class TcpOptionUnknown : TcpOptionComplex, IOptionUnknownFactory<TcpOptionType>, IEquatable<TcpOptionUnknown>
{ {
/// <summary> /// <summary>
/// The minimum number of bytes this option take. /// The minimum number of bytes this option take.
...@@ -18,17 +21,26 @@ namespace PcapDotNet.Packets.Transport ...@@ -18,17 +21,26 @@ namespace PcapDotNet.Packets.Transport
/// </summary> /// </summary>
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength; public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
/// <summary>
/// Creates an unknown TCP option by the given type and data.
/// </summary>
public TcpOptionUnknown(TcpOptionType optionType, IList<byte> data) public TcpOptionUnknown(TcpOptionType optionType, IList<byte> data)
: base(optionType) : base(optionType)
{ {
Data = new ReadOnlyCollection<byte>(data); Data = new ReadOnlyCollection<byte>(data);
} }
/// <summary>
/// The default unknown option is with type 255 and no data.
/// </summary>
public TcpOptionUnknown() public TcpOptionUnknown()
: this((TcpOptionType)255, new byte[] { }) : this((TcpOptionType)255, new byte[] { })
{ {
} }
/// <summary>
/// The data of the unknown option.
/// </summary>
public ReadOnlyCollection<byte> Data { get; private set; } public ReadOnlyCollection<byte> Data { get; private set; }
/// <summary> /// <summary>
...@@ -47,6 +59,9 @@ namespace PcapDotNet.Packets.Transport ...@@ -47,6 +59,9 @@ namespace PcapDotNet.Packets.Transport
get { return false; } get { return false; }
} }
/// <summary>
/// Two unknown options are equal iff they are of equal type and equal data.
/// </summary>
public bool Equals(TcpOptionUnknown other) public bool Equals(TcpOptionUnknown other)
{ {
if (other == null) if (other == null)
...@@ -56,16 +71,30 @@ namespace PcapDotNet.Packets.Transport ...@@ -56,16 +71,30 @@ namespace PcapDotNet.Packets.Transport
Data.SequenceEqual(other.Data); Data.SequenceEqual(other.Data);
} }
/// <summary>
/// Two unknown options are equal iff they are of equal type and equal data.
/// </summary>
public override bool Equals(TcpOption other) public override bool Equals(TcpOption other)
{ {
return Equals(other as TcpOptionUnknown); return Equals(other as TcpOptionUnknown);
} }
/// <summary>
/// The hash code for an unknown option is the hash code for the option type xored with the hash code of the data.
/// </summary>
public override int GetHashCode() public override int GetHashCode()
{ {
return base.GetHashCode() ^ Data.BytesSequenceGetHashCode(); return base.GetHashCode() ^ Data.BytesSequenceGetHashCode();
} }
/// <summary>
/// Creates an unknown option from its type and by reading a buffer for its value.
/// </summary>
/// <param name="optionType">The type of the unknown option.</param>
/// <param name="buffer">The buffer of bytes to read the value of the unknown option.</param>
/// <param name="offset">The offset in the buffer to start reading the bytes.</param>
/// <param name="valueLength">The number of bytes to read from the buffer.</param>
/// <returns>An option created from the given type and buffer.</returns>
public Option CreateInstance(TcpOptionType optionType, byte[] buffer, ref int offset, byte valueLength) public Option CreateInstance(TcpOptionType optionType, byte[] buffer, ref int offset, byte valueLength)
{ {
if (valueLength < OptionValueMinimumLength) if (valueLength < OptionValueMinimumLength)
......
...@@ -41,13 +41,20 @@ namespace PcapDotNet.Packets.Transport ...@@ -41,13 +41,20 @@ namespace PcapDotNet.Packets.Transport
get { return ReadUShort(Offset.DestinationPort, Endianity.Big); } get { return ReadUShort(Offset.DestinationPort, Endianity.Big); }
} }
/// <summary>
/// Checksum is the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header,
/// the Transport header, and the data, padded with zero octets at the end (if necessary) to make a multiple of two octets.
/// </summary>
public abstract ushort Checksum { get; } public abstract ushort Checksum { get; }
public abstract int ChecksumOffset { get; } /// <summary>
/// True iff the checksum for the transport type is optional.
/// </summary>
public abstract bool IsChecksumOptional { get; } public abstract bool IsChecksumOptional { get; }
protected static void WriteHeader(byte[] buffer, int offset, ushort sourcePort, ushort destinationPort) internal abstract int ChecksumOffset { get; }
internal static void WriteHeader(byte[] buffer, int offset, ushort sourcePort, ushort destinationPort)
{ {
buffer.Write(offset + Offset.SourcePort, sourcePort, Endianity.Big); buffer.Write(offset + Offset.SourcePort, sourcePort, Endianity.Big);
buffer.Write(offset + Offset.DestinationPort, destinationPort, Endianity.Big); buffer.Write(offset + Offset.DestinationPort, destinationPort, Endianity.Big);
......
...@@ -24,7 +24,6 @@ namespace PcapDotNet.Packets.Transport ...@@ -24,7 +24,6 @@ namespace PcapDotNet.Packets.Transport
/// | /// |
/// | data octets ... /// | data octets ...
/// +---------------- ... /// +---------------- ...
/// </summary> /// </summary>
public class UdpDatagram : TransportDatagram public class UdpDatagram : TransportDatagram
{ {
...@@ -59,11 +58,6 @@ namespace PcapDotNet.Packets.Transport ...@@ -59,11 +58,6 @@ namespace PcapDotNet.Packets.Transport
get { return ReadUShort(Offset.Checksum, Endianity.Big); } get { return ReadUShort(Offset.Checksum, Endianity.Big); }
} }
public override int ChecksumOffset
{
get { return Offset.Checksum; }
}
public override bool IsChecksumOptional public override bool IsChecksumOptional
{ {
get { return true; } get { return true; }
...@@ -77,6 +71,11 @@ namespace PcapDotNet.Packets.Transport ...@@ -77,6 +71,11 @@ namespace PcapDotNet.Packets.Transport
get { return new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength); } get { return new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength); }
} }
internal override int ChecksumOffset
{
get { return Offset.Checksum; }
}
internal UdpDatagram(byte[] buffer, int offset, int length) internal UdpDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length) : base(buffer, offset, length)
{ {
......
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