encodeSelf method

  1. @override
void encodeSelf(
  1. RawWriter writer
)

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,
    ),
  );
}