Commit ae70efce authored by Brickner_cp's avatar Brickner_cp

Code Analysis and Documentation - 87 warnings left.

parent 136fbcc7
......@@ -29,6 +29,7 @@
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>true</RunCodeAnalysis>
<DocumentationFile>..\..\bin\Debug\PcapDotNet.Base.XML</DocumentationFile>
<CodeAnalysisRules>-Microsoft.Design#CA1004</CodeAnalysisRules>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
......
......@@ -152,7 +152,7 @@ namespace PcapDotNet.Core.Test
random.NextByte(),
random.NextIpV4Address(), random.NextIpV4Address(), random.NextIpV4Options(),
random.NextUShort(), random.NextUShort(), random.NextUInt(), random.NextUInt(),
random.NextFlags<TcpFlags>(),
random.NextFlags<TcpControlBits>(),
random.NextUShort(), random.NextUShort(),
random.NextTcpOptions(),
random.NextDatagram(random.Next(100)));
......@@ -525,7 +525,7 @@ namespace PcapDotNet.Core.Test
break;
case "tcp.flags":
field.AssertShowHex((byte)tcpDatagram.Flags);
field.AssertShowHex((byte)tcpDatagram.ControlBits);
foreach (var flagField in field.Fields())
{
switch (flagField.Name())
......
......@@ -85,7 +85,7 @@ namespace PcapDotNet.Packets.Test
ushort tcpDestinationPort = random.NextUShort();
uint tcpSequenceNumber = random.NextUInt();
uint tcpAcknowledgmentNumber = random.NextUInt();
TcpFlags tcpFlags = random.NextFlags<TcpFlags>();
TcpControlBits tcpControlBits = random.NextFlags<TcpControlBits>();
ushort tcpWindow = random.NextUShort();
ushort tcpUrgentPointer = random.NextUShort();
TcpOptions tcpOptions = random.NextTcpOptions();
......@@ -95,7 +95,7 @@ namespace PcapDotNet.Packets.Test
ethernetSource, ethernetDestination,
ipV4TypeOfService, ipV4Identification, ipV4Fragmentation, ipV4Ttl,
ipV4Source, ipV4Destination, ipV4Options,
tcpSourcePort, tcpDestinationPort, tcpSequenceNumber, tcpAcknowledgmentNumber, tcpFlags, tcpWindow, tcpUrgentPointer,
tcpSourcePort, tcpDestinationPort, tcpSequenceNumber, tcpAcknowledgmentNumber, tcpControlBits, tcpWindow, tcpUrgentPointer,
tcpOptions,
tcpPayload);
......@@ -106,7 +106,7 @@ namespace PcapDotNet.Packets.Test
Assert.AreEqual(tcpDestinationPort, packet.Ethernet.IpV4.Tcp.DestinationPort, "Destination Port");
Assert.AreEqual(tcpSequenceNumber, packet.Ethernet.IpV4.Tcp.SequenceNumber, "Sequence Number");
Assert.AreEqual(tcpAcknowledgmentNumber, packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber, "Acknowledgment Number");
Assert.AreEqual(tcpFlags, packet.Ethernet.IpV4.Tcp.Flags, "Flags");
Assert.AreEqual(tcpControlBits, packet.Ethernet.IpV4.Tcp.ControlBits, "Flags");
Assert.AreEqual(tcpWindow, packet.Ethernet.IpV4.Tcp.Window, "Window");
Assert.AreEqual(tcpUrgentPointer, packet.Ethernet.IpV4.Tcp.UrgentPointer, "Urgent Pointer");
Assert.AreEqual(tcpOptions, packet.Ethernet.IpV4.Tcp.Options, "Options");
......@@ -117,14 +117,14 @@ namespace PcapDotNet.Packets.Test
Assert.IsFalse(string.IsNullOrEmpty(option.ToString()));
}
Assert.AreEqual(tcpOptions, packet.Ethernet.IpV4.Tcp.Options, "Options");
Assert.AreEqual((tcpFlags & TcpFlags.Acknowledgment) == TcpFlags.Acknowledgment, packet.Ethernet.IpV4.Tcp.IsAcknowledgment, "IsAcknowledgment");
Assert.AreEqual((tcpFlags & TcpFlags.CongestionWindowReduced) == TcpFlags.CongestionWindowReduced, packet.Ethernet.IpV4.Tcp.IsCongestionWindowReduced, "IsCongestionWindowReduced");
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.Push) == TcpFlags.Push, packet.Ethernet.IpV4.Tcp.IsPush, "IsPush");
Assert.AreEqual((tcpFlags & TcpFlags.Reset) == TcpFlags.Reset, packet.Ethernet.IpV4.Tcp.IsReset, "IsReset");
Assert.AreEqual((tcpFlags & TcpFlags.Synchronize) == TcpFlags.Synchronize, packet.Ethernet.IpV4.Tcp.IsSynchronize, "IsSynchronize");
Assert.AreEqual((tcpFlags & TcpFlags.Urgent) == TcpFlags.Urgent, packet.Ethernet.IpV4.Tcp.IsUrgent, "IsUrgent");
Assert.AreEqual((tcpControlBits & TcpControlBits.Acknowledgment) == TcpControlBits.Acknowledgment, packet.Ethernet.IpV4.Tcp.IsAcknowledgment, "IsAcknowledgment");
Assert.AreEqual((tcpControlBits & TcpControlBits.CongestionWindowReduced) == TcpControlBits.CongestionWindowReduced, packet.Ethernet.IpV4.Tcp.IsCongestionWindowReduced, "IsCongestionWindowReduced");
Assert.AreEqual((tcpControlBits & TcpControlBits.ExplicitCongestionNotificationEcho) == TcpControlBits.ExplicitCongestionNotificationEcho, packet.Ethernet.IpV4.Tcp.IsExplicitCongestionNotificationEcho, "IsExplicitCongestionNotificationEcho");
Assert.AreEqual((tcpControlBits & TcpControlBits.Fin) == TcpControlBits.Fin, packet.Ethernet.IpV4.Tcp.IsFin, "IsFin");
Assert.AreEqual((tcpControlBits & TcpControlBits.Push) == TcpControlBits.Push, packet.Ethernet.IpV4.Tcp.IsPush, "IsPush");
Assert.AreEqual((tcpControlBits & TcpControlBits.Reset) == TcpControlBits.Reset, packet.Ethernet.IpV4.Tcp.IsReset, "IsReset");
Assert.AreEqual((tcpControlBits & TcpControlBits.Synchronize) == TcpControlBits.Synchronize, packet.Ethernet.IpV4.Tcp.IsSynchronize, "IsSynchronize");
Assert.AreEqual((tcpControlBits & TcpControlBits.Urgent) == TcpControlBits.Urgent, packet.Ethernet.IpV4.Tcp.IsUrgent, "IsUrgent");
Assert.IsFalse(packet.Ethernet.IpV4.Tcp.IsChecksumOptional, "IsChecksumOptional");
Assert.AreEqual(TcpDatagram.HeaderMinimumLength + tcpOptions.BytesLength + tcpPayload.Length, packet.Ethernet.IpV4.Tcp.Length, "Total Length");
Assert.IsTrue(packet.Ethernet.IpV4.IsTransportChecksumCorrect, "IsTransportChecksumCorrect");
......
......@@ -238,6 +238,10 @@ namespace PcapDotNet.Packets.IpV4
}
}
/// <summary>
/// Returns the Tranposrt Datagram.
/// This is either a TCP Datagram or a UDP Datagram (according to the protocol).
/// </summary>
public TransportDatagram Transport
{
get
......
......@@ -38,6 +38,9 @@ namespace PcapDotNet.Packets.IpV4
{
}
/// <summary>
/// Returns the Data of the option.
/// </summary>
public ReadOnlyCollection<byte> Data { get; private set; }
/// <summary>
......
......@@ -26,11 +26,23 @@ namespace PcapDotNet.Packets
Buffer.BlockCopy(source, sourceOffset, destination, destinationOffset, count);
}
/// <summary>
/// Reads a byte from a specific offset.
/// </summary>
/// <param name="buffer">The buffer to read the byte from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <returns>The value read from the buffer.</returns>
public static byte ReadByte(this byte[] buffer, int offset)
{
return buffer[offset];
}
/// <summary>
/// Reads a byte from a specific offset and increments the offset by 1.
/// </summary>
/// <param name="buffer">The buffer to read the byte from.</param>
/// <param name="offset">The offset in the buffer to start reading and to increment.</param>
/// <returns>The value read from the buffer.</returns>
public static byte ReadByte(this byte[] buffer, ref int offset)
{
byte result = ReadByte(buffer, offset);
......@@ -38,6 +50,13 @@ namespace PcapDotNet.Packets
return result;
}
/// <summary>
/// Reads bytes from a specific offset.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading.</param>
/// <param name="length">The number of bytes to read.</param>
/// <returns>The value read from the buffer.</returns>
public static byte[] ReadBytes(this byte[] buffer, int offset, int length)
{
byte[] bytes = new byte[length];
......@@ -45,6 +64,13 @@ namespace PcapDotNet.Packets
return bytes;
}
/// <summary>
/// Reads bytes from a specific offset and increments the offset by the number of bytes read.
/// </summary>
/// <param name="buffer">The buffer to read the bytes from.</param>
/// <param name="offset">The offset in the buffer to start reading and to increment.</param>
/// <param name="length">The number of bytes to read.</param>
/// <returns>The value read from the buffer.</returns>
public static byte[] ReadBytes(this byte[] buffer, ref int offset, int length)
{
byte[] result = buffer.ReadBytes(offset, length);
......@@ -258,17 +284,35 @@ namespace PcapDotNet.Packets
return new IpV4OptionTimeOfDay(buffer.ReadUInt(ref offset, endianity));
}
/// <summary>
/// Writes the given value to the buffer.
/// </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>
public static void Write(this byte[] buffer, int offset, byte value)
{
buffer[offset] = value;
}
/// <summary>
/// Writes the given value to the buffer 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>
public static void Write(this byte[] buffer, ref int offset, byte value)
{
Write(buffer, offset, value);
offset += sizeof(byte);
}
/// <summary>
/// Writes the given value to the buffer 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>
public static void Write(this byte[] buffer, ref int offset, IEnumerable<byte> value)
{
foreach (byte b in value)
......
......@@ -6,19 +6,7 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets
{
public class OptionComplexFactoryBase
{
/// <summary>
/// The header length in bytes for the option (type and size).
/// </summary>
public const int OptionHeaderLength = 2;
protected OptionComplexFactoryBase()
{
}
}
public sealed class OptionComplexFactory<TOptionType> : OptionComplexFactoryBase
internal sealed class OptionComplexFactory<TOptionType> : OptionComplexFactoryBase
{
internal static Option Read(TOptionType optionType, byte[] buffer, ref int offset, int length)
{
......
namespace PcapDotNet.Packets
{
internal abstract class OptionComplexFactoryBase
{
/// <summary>
/// The header length in bytes for the option (type and size).
/// </summary>
public const int OptionHeaderLength = 2;
protected OptionComplexFactoryBase()
{
}
}
}
\ No newline at end of file
......@@ -6,6 +6,11 @@ using PcapDotNet.Base;
namespace PcapDotNet.Packets
{
/// <summary>
/// A generic Options class.
/// Represents a list of options (either IPv4 options or TCP options).
/// </summary>
/// <typeparam name="T">The Option type this collection contains.</typeparam>
public abstract class Options<T> : ReadOnlyCollection<T> where T : Option
{
/// <summary>
......@@ -74,7 +79,7 @@ namespace PcapDotNet.Packets
buffer[offset++] = 0;
}
protected Options(IList<T> options, T end, int maximumBytesLength)
internal Options(IList<T> options, T end, int maximumBytesLength)
: this(EndOptions(options, end), true)
{
if (BytesLength > maximumBytesLength)
......
......@@ -14,6 +14,9 @@ namespace PcapDotNet.Packets
/// </summary>
public class Packet : IList<byte>, IEquatable<Packet>
{
/// <summary>
/// Creates a packet from a string that represents bytes in a hexadecimal format.
/// </summary>
public static Packet FromHexadecimalString(string value, DateTime timestamp, DataLinkKind dataLink)
{
byte[] bytes = new byte[value.Length / 2];
......
......@@ -132,7 +132,6 @@ namespace PcapDotNet.Packets
/// <param name="tcpDestinationPort">The destination udp port.</param>
/// <param name="tcpPayload">The payload of UDP datagram.</param>
/// <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,
MacAddress ethernetSource, MacAddress ethernetDestination,
byte ipV4TypeOfService, ushort ipV4Identification, IpV4Fragmentation ipV4Fragmentation,
......@@ -141,7 +140,7 @@ namespace PcapDotNet.Packets
IpV4Options ipV4Options,
ushort tcpSourcePort, ushort tcpDestinationPort,
uint tcpSequenceNumber, uint tcpAcknowledgmentNumber,
TcpFlags tcpFlags, ushort tcpWindow, ushort tcpUrgentPointer,
TcpControlBits tcpControlBits, ushort tcpWindow, ushort tcpUrgentPointer,
TcpOptions tcpOptions,
Datagram tcpPayload)
......@@ -163,7 +162,7 @@ namespace PcapDotNet.Packets
TcpDatagram.WriteHeader(buffer, ethernetIpV4HeadersLength,
tcpSourcePort, tcpDestinationPort,
tcpSequenceNumber, tcpAcknowledgmentNumber,
tcpFlags, tcpWindow, tcpUrgentPointer,
tcpControlBits, tcpWindow, tcpUrgentPointer,
tcpOptions);
tcpPayload.Write(buffer, ethernetIpV4HeadersLength + tcpHeaderLength);
......
......@@ -103,13 +103,14 @@
<Compile Include="IpV4\IpV4Protocol.cs" />
<Compile Include="MoreByteArray.cs" />
<Compile Include="OptionComplexFactory.cs" />
<Compile Include="OptionComplexFactoryBase.cs" />
<Compile Include="Options.cs" />
<Compile Include="OptionTypeRegistrationAttribute.cs" />
<Compile Include="Packet.cs" />
<Compile Include="PacketBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Transport\TcpDatagram.cs" />
<Compile Include="Transport\TcpFlags.cs" />
<Compile Include="Transport\TcpControlBits.cs" />
<Compile Include="Transport\TcpOption.cs" />
<Compile Include="Transport\TcpOptionAlternateChecksumData.cs" />
<Compile Include="Transport\TcpOptionAlternateChecksumRequest.cs" />
......
......@@ -10,18 +10,56 @@ namespace PcapDotNet.Packets.Transport
/// | 0 | | NS | CWR | ECE | URG | ACK | PSH | RST | SYN | FIN |
/// +-----+-----+----+-----+-----+-----+-----+-----+-----+-----+-----+
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flags"), Flags]
public enum TcpFlags : ushort
[Flags]
public enum TcpControlBits : ushort
{
/// <summary>
/// No control bits are turned on.
/// </summary>
None = 0x0000,
/// <summary>
/// No more data from sender.
/// </summary>
Fin = 0x0001,
/// <summary>
/// Synchronize sequence numbers.
/// </summary>
Synchronize = 0x0002,
/// <summary>
/// Reset the connection.
/// </summary>
Reset = 0x0004,
/// <summary>
/// Push Function.
/// </summary>
Push = 0x0008,
/// <summary>
/// Acknowledgment field significant.
/// </summary>
Acknowledgment = 0x0010,
/// <summary>
/// Urgent Pointer field significant.
/// </summary>
Urgent = 0x0020,
/// <summary>
/// RFC 3168.
/// </summary>
ExplicitCongestionNotificationEcho = 0x0040,
/// <summary>
/// RFC 3168.
/// </summary>
CongestionWindowReduced = 0x0080,
Ns = 0x0100,
/// <summary>
/// RFC 3540.
/// </summary>
NonceSum = 0x0100,
}
}
\ No newline at end of file
......@@ -22,7 +22,14 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public class TcpDatagram : TransportDatagram
{
/// <summary>
/// The minimum number of bytes the header takes.
/// </summary>
public const int HeaderMinimumLength = 20;
/// <summary>
/// The maximum number of bytes the header takes.
/// </summary>
public const int HeaderMaximumLength = 60;
internal static class Offset
......@@ -36,11 +43,6 @@ namespace PcapDotNet.Packets.Transport
public const int Options = 20;
}
public TcpDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
/// <summary>
/// The sequence number of the first data octet in this segment (except when SYN is present).
/// If SYN is present the sequence number is the initial sequence number (ISN) and the first data octet is ISN+1.
......@@ -70,37 +72,80 @@ namespace PcapDotNet.Packets.Transport
get { return 4 * (this[Offset.HeaderLengthAndFlags] >> 4); }
}
/// <summary>
/// Returns the actual header length.
/// </summary>
public int RealHeaderLength
{
get { return Math.Min(HeaderLength, Length); }
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Flags")]
public TcpFlags Flags
/// <summary>
/// A collection of bits for the TCP control.
/// </summary>
public TcpControlBits ControlBits
{
get { return (TcpFlags)(ReadUShort(Offset.HeaderLengthAndFlags, Endianity.Big) & 0x01FF); }
get { return (TcpControlBits)(ReadUShort(Offset.HeaderLengthAndFlags, Endianity.Big) & 0x01FF); }
}
/// <summary>
/// The number of data octets beginning with the one indicated in the acknowledgment field which the sender of this segment is willing to accept.
/// </summary>
public ushort Window
{
get { return ReadUShort(Offset.Window, Endianity.Big); }
}
/// <summary>
/// The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header and text.
/// If a segment contains an odd number of header and text octets to be checksummed,
/// the last octet is padded on the right with zeros to form a 16 bit word for checksum purposes.
/// The pad is not transmitted as part of the segment.
/// While computing the checksum, the checksum field itself is replaced with zeros.
///
/// The checksum also covers a 96 bit pseudo header conceptually prefixed to the TCP header.
/// This pseudo header contains the Source Address, the Destination Address, the Protocol, and TCP length.
/// This gives the TCP protection against misrouted segments.
/// This information is carried in the Internet Protocol and is transferred across the TCP/Network interface in the arguments or results of calls
/// by the TCP on the IP.
///
/// +--------+--------+--------+--------+
/// | Source Address |
/// +--------+--------+--------+--------+
/// | Destination Address |
/// +--------+--------+--------+--------+
/// | zero | PTCL | TCP Length |
/// +--------+--------+--------+--------+
///
/// The TCP Length is the TCP header length plus the data length in octets (this is not an explicitly transmitted quantity, but is computed),
/// and it does not count the 12 octets of the pseudo header.
/// </summary>
public override ushort Checksum
{
get { return ReadUShort(Offset.Checksum, Endianity.Big); }
}
/// <summary>
/// True iff the checksum for the transport type is optional.
/// </summary>
public override bool IsChecksumOptional
{
get { return false; }
}
/// <summary>
/// This field communicates the current value of the urgent pointer as a positive offset from the sequence number in this segment.
/// The urgent pointer points to the sequence number of the octet following the urgent data.
/// This field is only be interpreted in segments with the URG control bit set.
/// </summary>
public ushort UrgentPointer
{
get { return ReadUShort(Offset.UrgentPointer, Endianity.Big); }
}
/// <summary>
/// Returns the tcp options contained in this TCP Datagram.
/// </summary>
public TcpOptions Options
{
get
......@@ -119,44 +164,73 @@ namespace PcapDotNet.Packets.Transport
get { return new Datagram(Buffer, StartOffset + HeaderLength, Length - HeaderLength); }
}
/// <summary>
/// True iff the CongestionWindowReduced control bit is turned on.
/// </summary>
public bool IsCongestionWindowReduced
{
get { return (Flags & TcpFlags.CongestionWindowReduced) == TcpFlags.CongestionWindowReduced; }
get { return (ControlBits & TcpControlBits.CongestionWindowReduced) == TcpControlBits.CongestionWindowReduced; }
}
/// <summary>
/// True iff the ExplicitCongestionNotificationEcho control bit is turned on.
/// </summary>
public bool IsExplicitCongestionNotificationEcho
{
get { return (Flags & TcpFlags.ExplicitCongestionNotificationEcho) == TcpFlags.ExplicitCongestionNotificationEcho; }
get { return (ControlBits & TcpControlBits.ExplicitCongestionNotificationEcho) == TcpControlBits.ExplicitCongestionNotificationEcho; }
}
/// <summary>
/// True iff the Urgent control bit is turned on.
/// </summary>
public bool IsUrgent
{
get { return (Flags & TcpFlags.Urgent) == TcpFlags.Urgent; }
get { return (ControlBits & TcpControlBits.Urgent) == TcpControlBits.Urgent; }
}
/// <summary>
/// True iff the Acknowledgment control bit is turned on.
/// </summary>
public bool IsAcknowledgment
{
get { return (Flags & TcpFlags.Acknowledgment) == TcpFlags.Acknowledgment; }
get { return (ControlBits & TcpControlBits.Acknowledgment) == TcpControlBits.Acknowledgment; }
}
/// <summary>
/// True iff the Push control bit is turned on.
/// </summary>
public bool IsPush
{
get { return (Flags & TcpFlags.Push) == TcpFlags.Push; }
get { return (ControlBits & TcpControlBits.Push) == TcpControlBits.Push; }
}
/// <summary>
/// True iff the Reset control bit is turned on.
/// </summary>
public bool IsReset
{
get { return (Flags & TcpFlags.Reset) == TcpFlags.Reset; }
get { return (ControlBits & TcpControlBits.Reset) == TcpControlBits.Reset; }
}
/// <summary>
/// True iff the Synchronize control bit is turned on.
/// </summary>
public bool IsSynchronize
{
get { return (Flags & TcpFlags.Synchronize) == TcpFlags.Synchronize; }
get { return (ControlBits & TcpControlBits.Synchronize) == TcpControlBits.Synchronize; }
}
/// <summary>
/// True iff the Fin control bit is turned on.
/// </summary>
public bool IsFin
{
get { return (Flags & TcpFlags.Fin) == TcpFlags.Fin; }
get { return (ControlBits & TcpControlBits.Fin) == TcpControlBits.Fin; }
}
internal TcpDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
internal override int ChecksumOffset
......@@ -167,7 +241,7 @@ namespace PcapDotNet.Packets.Transport
internal static void WriteHeader(byte[] buffer, int offset,
ushort sourcePort, ushort destinationPort,
uint sequenceNumber, uint acknowledgmentNumber,
TcpFlags flags, ushort window, ushort urgentPointer,
TcpControlBits controlBits, ushort window, ushort urgentPointer,
TcpOptions options)
{
int headerLength = HeaderMinimumLength + options.BytesLength;
......@@ -175,7 +249,7 @@ namespace PcapDotNet.Packets.Transport
WriteHeader(buffer, offset, sourcePort, destinationPort);
buffer.Write(offset + Offset.SequenceNumber, sequenceNumber, Endianity.Big);
buffer.Write(offset + Offset.AcknowledgmentNumber, acknowledgmentNumber, Endianity.Big);
buffer.Write(offset + Offset.HeaderLengthAndFlags, (ushort)(((ushort)((headerLength / 4) << 12)) | (ushort)flags), Endianity.Big);
buffer.Write(offset + Offset.HeaderLengthAndFlags, (ushort)(((ushort)((headerLength / 4) << 12)) | (ushort)controlBits), Endianity.Big);
buffer.Write(offset + Offset.Window, window, Endianity.Big);
buffer.Write(offset + Offset.UrgentPointer, urgentPointer, Endianity.Big);
options.Write(buffer, offset + Offset.Options);
......
......@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Transport
{
......@@ -30,19 +31,31 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public const int OptionMinimumLength = OptionHeaderLength;
/// <summary>
/// The minimum number of bytes this option's value take.
/// </summary>
public const int OptionValueMinimumLength = OptionMinimumLength - OptionHeaderLength;
/// <summary>
/// Creates the option using the given data.
/// </summary>
public TcpOptionAlternateChecksumData(IList<byte> data)
: base(TcpOptionType.AlternateChecksumData)
{
Data = new ReadOnlyCollection<byte>(data);
}
/// <summary>
/// the default option data is no data.
/// </summary>
public TcpOptionAlternateChecksumData()
: this(new byte[0])
{
}
/// <summary>
/// The alternate checksum data.
/// </summary>
public ReadOnlyCollection<byte> Data { get; private set; }
/// <summary>
......@@ -61,6 +74,9 @@ namespace PcapDotNet.Packets.Transport
get { return true; }
}
/// <summary>
/// Two alternate checksum data options are equal if they have the same data.
/// </summary>
public bool Equals(TcpOptionAlternateChecksumData other)
{
if (other == null)
......@@ -68,15 +84,21 @@ namespace PcapDotNet.Packets.Transport
return Data.SequenceEqual(other.Data);
}
/// <summary>
/// Two alternate checksum data options are equal if they have the same data.
/// </summary>
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionAlternateChecksumData);
}
/// <summary>
/// The hash code of this option is the hash code of the option type xored with the hash code of the data.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
Data.GetHashCode();
Data.BytesSequenceGetHashCode();
}
/// <summary>
......
......@@ -25,19 +25,31 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public const int OptionLength = 3;
/// <summary>
/// The number of bytes this option value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Creates the option using the given checksum type.
/// </summary>
public TcpOptionAlternateChecksumRequest(TcpOptionAlternateChecksumType checksumType)
: base(TcpOptionType.AlternateChecksumRequest)
{
ChecksumType = checksumType;
}
/// <summary>
/// The default checksum type is the TCP checksum.
/// </summary>
public TcpOptionAlternateChecksumRequest()
: this(0)
: this(TcpOptionAlternateChecksumType.TcpChecksum)
{
}
/// <summary>
/// The type of the checksum.
/// </summary>
public TcpOptionAlternateChecksumType ChecksumType { get; private set; }
/// <summary>
......@@ -56,6 +68,9 @@ namespace PcapDotNet.Packets.Transport
get { return true; }
}
/// <summary>
/// Two alternate checksum request options are equal if they have the same checksum type.
/// </summary>
public bool Equals(TcpOptionAlternateChecksumRequest other)
{
if (other == null)
......@@ -63,11 +78,17 @@ namespace PcapDotNet.Packets.Transport
return ChecksumType == other.ChecksumType;
}
/// <summary>
/// Two alternate checksum request options are equal if they have the same checksum type.
/// </summary>
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionAlternateChecksumRequest);
}
/// <summary>
/// The hash code of this option is the hash code of the option type xored with hash code of the checksum type.
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode() ^
......
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// The type of the checksum to be used.
/// </summary>
public enum TcpOptionAlternateChecksumType : byte
{
/// <summary>
/// TCP checksum.
/// </summary>
TcpChecksum = 0,
/// <summary>
/// 8-bit Fletcher's algorithm.
/// </summary>
FletchersAlgorithm8Bit = 1,
/// <summary>
/// 16-bit Fletcher's algorithm.
/// </summary>
FletchersAlgorithm16Bit = 2,
}
}
\ No newline at end of file
......@@ -6,6 +6,9 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public abstract class TcpOptionComplex : TcpOption
{
/// <summary>
/// The number of bytes this option header take.
/// </summary>
public const int OptionHeaderLength = 2;
internal override void Write(byte[] buffer, ref int offset)
......@@ -14,6 +17,9 @@ namespace PcapDotNet.Packets.Transport
buffer[offset++] = (byte)Length;
}
/// <summary>
/// Creates a complex option using the given option type.
/// </summary>
protected TcpOptionComplex(TcpOptionType type)
: base(type)
{
......
......@@ -14,11 +14,17 @@ namespace PcapDotNet.Packets.Transport
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCount)]
public class TcpOptionConnectionCount : TcpOptionConnectionCountBase, IOptionComplexFactory
{
/// <summary>
/// Create a connection count tcp option by a given connection count.
/// </summary>
public TcpOptionConnectionCount(uint connectionCount)
: base(TcpOptionType.ConnectionCount, connectionCount)
{
}
/// <summary>
/// The default connection count is 0.
/// </summary>
public TcpOptionConnectionCount()
: this(0)
{
......
......@@ -2,6 +2,9 @@ using System;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// The base class for connection count TCP options.
/// </summary>
public abstract class TcpOptionConnectionCountBase : TcpOptionComplex, IEquatable<TcpOptionConnectionCountBase>
{
/// <summary>
......@@ -9,8 +12,14 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public const int OptionLength = 6;
/// <summary>
/// The number of bytes this option value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// The connection count value.
/// </summary>
public uint ConnectionCount { get; private set; }
/// <summary>
......@@ -29,6 +38,9 @@ namespace PcapDotNet.Packets.Transport
get { return true; }
}
/// <summary>
/// Two connection count options are equal of they are of the same option type and have the same connection count.
/// </summary>
public bool Equals(TcpOptionConnectionCountBase other)
{
if (other == null)
......@@ -38,6 +50,9 @@ namespace PcapDotNet.Packets.Transport
ConnectionCount == other.ConnectionCount;
}
/// <summary>
/// Two connection count options are equal of they are of the same option type and have the same connection count.
/// </summary>
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionConnectionCountBase);
......@@ -49,12 +64,23 @@ namespace PcapDotNet.Packets.Transport
buffer.Write(ref offset, ConnectionCount, Endianity.Big);
}
/// <summary>
/// Creates a connection count option according to the given option type and given connection count value.
/// </summary>
protected TcpOptionConnectionCountBase(TcpOptionType optionType, uint connectionCount)
: base(optionType)
{
ConnectionCount = connectionCount;
}
/// <summary>
/// Reads the connection count value from the buffer.
/// </summary>
/// <param name="connectionCount">The result connection count.</param>
/// <param name="buffer">The buffer to read the connection count from.</param>
/// <param name="offset">The offset to start reading the connection byte from.</param>
/// <param name="valueLength">The number of bytes available for read in this buffer.</param>
/// <returns>True iff the connection count could be read (there were enough bytes to read).</returns>
protected static bool TryRead(out uint connectionCount, byte[] buffer, ref int offset, byte valueLength)
{
if (valueLength != OptionValueLength)
......
......@@ -16,11 +16,17 @@ namespace PcapDotNet.Packets.Transport
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCountEcho)]
public class TcpOptionConnectionCountEcho : TcpOptionConnectionCountBase, IOptionComplexFactory
{
/// <summary>
/// Creates the option using the given connection count value.
/// </summary>
public TcpOptionConnectionCountEcho(uint connectionCount)
: base(TcpOptionType.ConnectionCountEcho, connectionCount)
{
}
/// <summary>
/// The default connection count value is 0.
/// </summary>
public TcpOptionConnectionCountEcho()
: this(0)
{
......
......@@ -11,14 +11,21 @@ namespace PcapDotNet.Packets.Transport
/// to indicate that the SEG.CC value may not be larger than the previous value.
/// Its SEG.CC value is the TCB.CCsend value from the sender's TCB.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.ConnectionCountNew)]
public class TcpOptionConnectionCountNew : TcpOptionConnectionCountBase, IOptionComplexFactory
{
/// <summary>
/// Creates the option using the given connection count value.
/// </summary>
public TcpOptionConnectionCountNew(uint connectionCount)
: base(TcpOptionType.ConnectionCountNew, connectionCount)
{
}
/// <summary>
/// The default connection count value is 0.
/// </summary>
public TcpOptionConnectionCountNew()
: this(0)
{
......
......@@ -22,19 +22,31 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public const int OptionLength = 6;
/// <summary>
/// The number of bytes this option value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Creates the option using the given echo info.
/// </summary>
public TcpOptionEcho(uint info)
: base(TcpOptionType.Echo)
{
Info = info;
}
/// <summary>
/// The default info is 0.
/// </summary>
public TcpOptionEcho()
: this(0)
{
}
/// <summary>
/// The info value of the option to be echoed.
/// </summary>
public uint Info { get; private set;}
/// <summary>
......@@ -53,6 +65,9 @@ namespace PcapDotNet.Packets.Transport
get { return true; }
}
/// <summary>
/// Two echo options are equal if they have the same info.
/// </summary>
public bool Equals(TcpOptionEcho other)
{
if (other == null)
......@@ -61,6 +76,9 @@ namespace PcapDotNet.Packets.Transport
return Info == other.Info;
}
/// <summary>
/// Two echo options are equal if they have the same info.
/// </summary>
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionEcho);
......
......@@ -27,19 +27,31 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public const int OptionLength = 6;
/// <summary>
/// The number of bytes this option value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Creates the option using the given echo info.
/// </summary>
public TcpOptionEchoReply(uint info)
: base(TcpOptionType.EchoReply)
{
Info = info;
}
/// <summary>
/// The default echo info is 0.
/// </summary>
public TcpOptionEchoReply()
: this(0)
{
}
/// <summary>
/// The echoed info.
/// </summary>
public uint Info { get; private set; }
/// <summary>
......@@ -58,6 +70,9 @@ namespace PcapDotNet.Packets.Transport
get { return true; }
}
/// <summary>
/// Two echo reply options are equal if they have the same info.
/// </summary>
public bool Equals(TcpOptionEchoReply other)
{
if (other == null)
......@@ -66,6 +81,9 @@ namespace PcapDotNet.Packets.Transport
return Info == other.Info;
}
/// <summary>
/// Two echo reply options are equal if they have the same info.
/// </summary>
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionEchoReply);
......
......@@ -21,19 +21,31 @@ namespace PcapDotNet.Packets.Transport
/// </summary>
public const int OptionLength = 4;
/// <summary>
/// The number of bytes this option value take.
/// </summary>
public const int OptionValueLength = OptionLength - OptionHeaderLength;
/// <summary>
/// Creates the option using the given maximum segment size.
/// </summary>
public TcpOptionMaximumSegmentSize(ushort maximumSegmentSize)
: base(TcpOptionType.MaximumSegmentSize)
{
MaximumSegmentSize = maximumSegmentSize;
}
/// <summary>
/// The default maximum segment size is 0.
/// </summary>
public TcpOptionMaximumSegmentSize()
: this(0)
{
}
/// <summary>
/// The maximum segment size value.
/// </summary>
public ushort MaximumSegmentSize { get; private set; }
/// <summary>
......@@ -52,6 +64,9 @@ namespace PcapDotNet.Packets.Transport
get { return true; }
}
/// <summary>
/// Two maximum segment size options are equal if they have the same maximum segment size.
/// </summary>
public bool Equals(TcpOptionMaximumSegmentSize other)
{
if (other == null)
......@@ -59,11 +74,18 @@ namespace PcapDotNet.Packets.Transport
return MaximumSegmentSize == other.MaximumSegmentSize;
}
/// <summary>
/// Two maximum segment size options are equal if they have the same maximum segment size.
/// </summary>
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionMaximumSegmentSize);
}
/// <summary>
/// The hash code of the option is the hash code of the option type xored with the hash code of the maximum segment size.
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return base.GetHashCode() ^
......
......@@ -14,6 +14,7 @@ namespace PcapDotNet.Packets.Transport
PartialOrderConnectionPermitted = 9,
PartialOrderServiceProfile = 10,
ConnectionCount = 11,
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
ConnectionCountNew = 12,
ConnectionCountEcho = 13,
AlternateChecksumRequest = 14,
......
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