encodeSelf method
Writes this object to the provided RawWriter.
Implementation
@override
void encodeSelf(RawWriter writer) {
final start = writer.length;
if (parentPacket == null) {
throw StateError(
"TcpPacket field 'parentPacket' is null. TCP protocol requires IP packet for calculating checksum.",
);
}
// 4-byte span at index 0
writer
..writeUint32(_v0)
// 4-byte span at index 4
..writeUint32(sequenceNumber)
// 4-byte span at index 8
..writeUint32(acknowledgementNumber)
// 4-byte span at index 12 will be set later
..writeUint32(0)
// 4-byte span at index 16
// Checksum must have 0 during calculation.
..writeUint32(0x0000FFFF & _v4);
// Options
final options = optionsByteData;
writer.writeByteData(options);
var headerLength = writer.length - start;
// Adding padding
while (headerLength % 4 != 0) {
writer.writeUint8(0);
headerLength++;
}
// We have header length
// Set 4-byte span at index 12
final v3 = transformUint32Bits(_v3, 28, 0xF, headerLength ~/ 4);
writer.bufferAsByteData.setUint32(start + 12, v3);
// Payload
payload.encodeSelf(writer);
// ------------
// Set checksum
// ------------
int checksum = 0;
final ipPacket = parentPacket;
final ipPacketPayloadLength = writer.length - start;
if (ipPacket is Ip4Packet) {
checksum += ipPacket.source!.asUint32;
checksum += ipPacket.destination!.asUint32;
checksum += ipPacket.typeOfService;
checksum += ipPacketPayloadLength;
} else if (ipPacket is Ip6Packet) {
checksum += _checksumIp6Address(ipPacket.source!);
checksum += _checksumIp6Address(ipPacket.destination!);
checksum += ipPacketPayloadLength;
checksum += ipPacket.payloadProtocolNumber;
} else {
throw StateError('IP packet is invalid');
}
checksum = Ip4Packet.calculateChecksum(
writer.bufferAsByteData,
start,
ipPacketPayloadLength,
checksum: checksum,
);
writer.bufferAsByteData.setUint16(
start + 16,
Ip4Packet.calculateChecksum(
writer.bufferAsByteData,
start,
writer.length - start,
),
);
}