in Source/Tx.Network/Ip/PacketParser.cs [80:172]
public static IpPacket Parse(
DateTimeOffset receivedTime,
bool reuseOriginalBuffer,
byte[] packetBytes,
int offset,
int packetBytesLength)
{
if (packetBytes == null)
{
throw new ArgumentNullException("packetBytes");
}
var ipVers = packetBytes.ReadBits(offset, 0, 4); //bits 0 to 3
if (ipVers != 4) throw new NotSupportedException("IPv4 only currently supported"); //ensure this is v4
var internetHeaderLength = packetBytes.ReadBits(offset++, 4, 4); //bits 4 to 7
var dscpValue = packetBytes.ReadBits(offset, 0, 6); //8 to 13
var explicitCongestionNotice = packetBytes.ReadBits(offset++, 6, 2); //14 to 15
var ipPacketLength = packetBytes.ReadNetOrderUShort(offset); //16 to 31
offset += 2;
var fragmentGroupId = packetBytes.ReadNetOrderUShort(offset); //32 to 47
offset += 2;
var ipHeaderFlags = packetBytes.ReadBits(offset, 0, 3); //48 to 50
var fragmentOffset = packetBytes.ReadNetOrderUShort(offset, 3, 13); //51 to 63
offset += 2;
var timeToLive = packetBytes[offset++]; //64 to 71
var protocolNumber = packetBytes[offset++]; //72 to 79
var protocol = (ProtocolType)protocolNumber; //Enum
var packetHeaderChecksum = packetBytes.ReadNetOrderUShort(offset); //80 to 95
offset += 2;
var sourceIpAddress = packetBytes.ReadIpAddress(offset); //96 to 127
offset += 4;
var destinationIpAddress = packetBytes.ReadIpAddress(offset); //128 to 160
offset += 4;
var ipOptions = default(ArraySegment<byte>);
if (internetHeaderLength > 5) //161 and up
{
int length = (internetHeaderLength - 5) * 4;
if (reuseOriginalBuffer)
{
ipOptions = new ArraySegment<byte>(packetBytes, offset, length);
}
else
{
var ipOptionsDataArray = new byte[length];
Array.Copy(packetBytes, offset, ipOptionsDataArray, 0, length);
ipOptions = new ArraySegment<byte>(ipOptionsDataArray);
}
offset += length;
}
var packetData = default(ArraySegment<byte>);
//IpHeader in bytes is 4*IHL bytes long
if (ipPacketLength > 4 * internetHeaderLength)
{
int length = ipPacketLength - (internetHeaderLength * 4);
if (reuseOriginalBuffer)
{
packetData = new ArraySegment<byte>(packetBytes, offset, length);
}
else
{
var packetDataArray = new byte[length];
Array.Copy(packetBytes, offset, packetDataArray, 0, length);
packetData = new ArraySegment<byte>(packetDataArray);
}
}
return new IpPacket
{
PacketHeader = new IpPacketHeader(
sourceIpAddress,
destinationIpAddress,
false,
internetHeaderLength,
dscpValue,
explicitCongestionNotice,
ipPacketLength,
fragmentGroupId,
ipHeaderFlags,
fragmentOffset,
timeToLive,
packetHeaderChecksum),
IpOptions = ipOptions,
ReceivedTime = receivedTime,
ProtocolType = protocol,
PacketData = packetData
};
}