Commit 2611e58a authored by Brickner_cp's avatar Brickner_cp

TCP

parent 093d3d08
......@@ -29,6 +29,12 @@ namespace PcapDotNet.Core.Test
? string.Empty
: ((TcpOptionSelectiveAcknowledgment)option).Blocks.SequenceToString(" ", " "));
case TcpOptionType.Echo:
return "Echo: " + ((TcpOptionEcho)option).Info;
case TcpOptionType.EchoReply:
return "Echo reply: " + ((TcpOptionEchoReply)option).Info;
default:
throw new InvalidOperationException("Illegal option type " + option.OptionType);
}
......@@ -43,6 +49,8 @@ namespace PcapDotNet.Core.Test
case TcpOptionType.MaximumSegmentSize:
case TcpOptionType.WindowScale:
case TcpOptionType.SelectiveAcknowledgmentPermitted:
case TcpOptionType.Echo:
case TcpOptionType.EchoReply:
break;
case TcpOptionType.SelectiveAcknowledgment:
......
......@@ -625,6 +625,10 @@ namespace PcapDotNet.Core.Test
++currentOptionIndex;
break;
case "tcp.options.echo":
field.AssertShowDecimal(option is TcpOptionEchoReply || option is TcpOptionEcho);
break;
default:
throw new InvalidOperationException(field.Name());
}
......
......@@ -245,14 +245,16 @@ namespace PcapDotNet.Packets.TestUtils
impossibleOptionTypes.Add(TcpOptionType.SelectiveAcknowledgment);
if (maximumOptionLength < TcpOptionSelectiveAcknowledgmentPermitted.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.SelectiveAcknowledgmentPermitted);
if (maximumOptionLength < TcpOptionEcho.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.Echo);
if (maximumOptionLength < TcpOptionEchoReply.OptionLength)
impossibleOptionTypes.Add(TcpOptionType.EchoReply);
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumData);
impossibleOptionTypes.Add(TcpOptionType.AlternateChecksumRequest);
impossibleOptionTypes.Add(TcpOptionType.Cc);
impossibleOptionTypes.Add(TcpOptionType.CcEcho);
impossibleOptionTypes.Add(TcpOptionType.CcNew);
impossibleOptionTypes.Add(TcpOptionType.Echo);
impossibleOptionTypes.Add(TcpOptionType.EchoReply);
impossibleOptionTypes.Add(TcpOptionType.Md5Signature);
impossibleOptionTypes.Add(TcpOptionType.PartialOrderConnectionPermitted);
impossibleOptionTypes.Add(TcpOptionType.PartialOrderServiceProfile);
......@@ -285,6 +287,12 @@ namespace PcapDotNet.Packets.TestUtils
case TcpOptionType.SelectiveAcknowledgmentPermitted:
return new TcpOptionSelectiveAcknowledgmentPermitted();
case TcpOptionType.Echo:
return new TcpOptionEcho(random.NextUInt());
case TcpOptionType.EchoReply:
return new TcpOptionEchoReply(random.NextUInt());
default:
throw new InvalidOperationException("optionType = " + optionType);
}
......
......@@ -110,6 +110,8 @@
<Compile Include="Transport\TcpFlags.cs" />
<Compile Include="Transport\TcpOption.cs" />
<Compile Include="Transport\TcpOptionComplex.cs" />
<Compile Include="Transport\TcpOptionEcho.cs" />
<Compile Include="Transport\TcpOptionEchoReply.cs" />
<Compile Include="Transport\TcpOptionMaximumSegmentSize.cs" />
<Compile Include="Transport\TcpOptions.cs" />
<Compile Include="Transport\TcpOptionSelectiveAcknowledgment.cs" />
......
using System;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// TCP Echo Option:
/// +--------+--------+--------+--------+--------+--------+
/// | Kind=6 | Length | 4 bytes of info to be echoed |
/// +--------+--------+--------+--------+--------+--------+
///
/// This option carries four bytes of information that the receiving TCP may send back in a subsequent TCP Echo Reply option.
/// A TCP may send the TCP Echo option in any segment, but only if a TCP Echo option was received in a SYN segment for the connection.
///
/// When the TCP echo option is used for RTT measurement, it will be included in data segments,
/// and the four information bytes will define the time at which the data segment was transmitted in any format convenient to the sender.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.Echo)]
public class TcpOptionEcho : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionEcho>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 6;
public const int OptionValueLength = OptionLength - OptionHeaderLength;
public TcpOptionEcho(uint info)
: base(TcpOptionType.Echo)
{
Info = info;
}
public TcpOptionEcho()
: this(0)
{
}
public uint Info { 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(TcpOptionEcho other)
{
if (other == null)
return false;
return Info == other.Info;
}
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionEcho);
}
/// <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 info = buffer.ReadUInt(ref offset, Endianity.Big);
return new TcpOptionEcho(info);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, Info, Endianity.Big);
}
}
}
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Transport
{
/// <summary>
/// TCP Echo Reply Option:
/// +--------+--------+--------+--------+--------+--------+
/// | Kind=7 | Length | 4 bytes of echoed info |
/// +--------+--------+--------+--------+--------+--------+
///
/// A TCP that receives a TCP Echo option containing four information bytes will return these same bytes in a TCP Echo Reply option.
///
/// This TCP Echo Reply option must be returned in the next segment (e.g., an ACK segment) that is sent.
/// If more than one Echo option is received before a reply segment is sent, the TCP must choose only one of the options to echo,
/// ignoring the others; specifically, it must choose the newest segment with the oldest sequence number.
///
/// To use the TCP Echo and Echo Reply options, a TCP must send a TCP Echo option in its own SYN segment
/// and receive a TCP Echo option in a SYN segment from the other TCP.
/// A TCP that does not implement the TCP Echo or Echo Reply options must simply ignore any TCP Echo options it receives.
/// However, a TCP should not receive one of these options in a non-SYN segment unless it included a TCP Echo option in its own SYN segment.
/// </summary>
[OptionTypeRegistration(typeof(TcpOptionType), TcpOptionType.EchoReply)]
public class TcpOptionEchoReply : TcpOptionComplex, IOptionComplexFactory, IEquatable<TcpOptionEchoReply>
{
/// <summary>
/// The number of bytes this option take.
/// </summary>
public const int OptionLength = 6;
public const int OptionValueLength = OptionLength - OptionHeaderLength;
public TcpOptionEchoReply(uint info)
: base(TcpOptionType.EchoReply)
{
Info = info;
}
public TcpOptionEchoReply()
: this(0)
{
}
public uint Info { 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(TcpOptionEchoReply other)
{
if (other == null)
return false;
return Info == other.Info;
}
public override bool Equals(TcpOption other)
{
return Equals(other as TcpOptionEchoReply);
}
/// <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 info = buffer.ReadUInt(ref offset, Endianity.Big);
return new TcpOptionEchoReply(info);
}
internal override void Write(byte[] buffer, ref int offset)
{
base.Write(buffer, ref offset);
buffer.Write(ref offset, Info, Endianity.Big);
}
}
}
\ 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