mirror of https://github.com/status-im/nim-eth.git
Improve uTP decoded packet logs + style and comment clean-up (#593)
* Improve uTP decoded packet logs + style and comment clean-up * Don't test for the exact error strings in uTP decode + clean-up
This commit is contained in:
parent
72c9858927
commit
29b14749fa
|
@ -1,9 +1,12 @@
|
||||||
# Copyright (c) 2020-2021 Status Research & Development GmbH
|
# Copyright (c) 2020-2023 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
# uTP packet format as specified in:
|
||||||
|
# https://www.bittorrent.org/beps/bep_0029.html
|
||||||
|
|
||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
|
@ -37,14 +40,9 @@ type
|
||||||
extension*: uint8
|
extension*: uint8
|
||||||
connectionId*: uint16
|
connectionId*: uint16
|
||||||
timestamp*: MicroSeconds
|
timestamp*: MicroSeconds
|
||||||
# This is the difference between the local time, at the time the last packet
|
|
||||||
# was received, and the timestamp in this last received packet
|
|
||||||
timestampDiff*: MicroSeconds
|
timestampDiff*: MicroSeconds
|
||||||
# The window size is the number of bytes currently in-flight, i.e. sent but not acked
|
|
||||||
# When sending packets, this should be set to the number of bytes left in the socket's receive buffer.
|
|
||||||
wndSize*: uint32
|
wndSize*: uint32
|
||||||
seqNr*: uint16
|
seqNr*: uint16
|
||||||
# sequence number the sender of the packet last received in the other direction
|
|
||||||
ackNr*: uint16
|
ackNr*: uint16
|
||||||
|
|
||||||
SelectiveAckExtension* = object
|
SelectiveAckExtension* = object
|
||||||
|
@ -59,22 +57,21 @@ type
|
||||||
moment*: Moment
|
moment*: Moment
|
||||||
timestamp*: uint32
|
timestamp*: uint32
|
||||||
|
|
||||||
# Important timing assumptions for utp protocol here:
|
# Important timing assumptions for uTP protocol here:
|
||||||
# 1. Microsecond precisions
|
# 1. Microsecond precisions
|
||||||
# 2. Monotonicity
|
# 2. Monotonicity
|
||||||
# Reference lib have a lot of checks to assume that this is monotonic on
|
# Reference lib has a lot of checks to assume that this is monotonic on
|
||||||
# every system, and warnings when monotonic clock is not available.
|
# every system, and warnings when monotonic clock is not available.
|
||||||
proc getMonoTimestamp*(): TimeStampInfo =
|
proc getMonoTimestamp*(): TimeStampInfo =
|
||||||
let currentMoment = Moment.now()
|
let currentMoment = Moment.now()
|
||||||
|
|
||||||
# Casting this value from int64 to uin32, my lead to some sudden spikes in
|
# Casting this value from int64 to uint32, may lead to some sudden spikes in
|
||||||
# timestamp numeric values i.e it is possible that timestamp can suddenly change
|
# timestamp numeric values, i.e it is possible that the timestamp will
|
||||||
# from 4294967296 to for example 10, this may lead to sudden spikes in
|
# suddenly change from 4294967296 to for example 10. This may lead to sudden
|
||||||
# calculated delays
|
# spikes in calculated delays.
|
||||||
# uTP implementation is resistant to those spikes are as it keeps history of
|
# The uTP implementation is resistant to those spikes are as it keeps a
|
||||||
# few last delays on uses smallest one for calculating ledbat window.
|
# history of several last delays and uses the smallest one for calculating
|
||||||
# so any outlier huge value will be ignored
|
# the ledbat window, thus any outlier value will be ignored.
|
||||||
#
|
|
||||||
let timestamp = uint32((currentMoment - zeroMoment).microseconds())
|
let timestamp = uint32((currentMoment - zeroMoment).microseconds())
|
||||||
TimeStampInfo(moment: currentMoment, timestamp: timestamp)
|
TimeStampInfo(moment: currentMoment, timestamp: timestamp)
|
||||||
|
|
||||||
|
@ -86,7 +83,7 @@ proc randUint16*(rng: var HmacDrbgContext): uint16 =
|
||||||
proc randUint32*(rng: var HmacDrbgContext): uint32 =
|
proc randUint32*(rng: var HmacDrbgContext): uint32 =
|
||||||
uint32(rand(rng, int(high(uint32))))
|
uint32(rand(rng, int(high(uint32))))
|
||||||
|
|
||||||
proc encodeTypeVer(h: PacketHeaderV1): uint8 =
|
func encodeTypeVer(h: PacketHeaderV1): uint8 =
|
||||||
var typeVer = 0'u8
|
var typeVer = 0'u8
|
||||||
let typeOrd = uint8(ord(h.pType))
|
let typeOrd = uint8(ord(h.pType))
|
||||||
typeVer = (typeVer and 0xf0) or (h.version and 0xf)
|
typeVer = (typeVer and 0xf0) or (h.version and 0xf)
|
||||||
|
@ -109,7 +106,7 @@ proc encodeHeaderStream(s: var OutputStream, h: PacketHeaderV1) =
|
||||||
|
|
||||||
proc encodeExtensionStream(s: var OutputStream, e: SelectiveAckExtension) =
|
proc encodeExtensionStream(s: var OutputStream, e: SelectiveAckExtension) =
|
||||||
try:
|
try:
|
||||||
# writing 0 as there is not further extensions after selective ack
|
# writing always 0 as there are no other extensions (only selective ack)
|
||||||
s.write(0'u8)
|
s.write(0'u8)
|
||||||
s.write(acksArrayLength)
|
s.write(acksArrayLength)
|
||||||
s.write(e.acks)
|
s.write(e.acks)
|
||||||
|
@ -130,14 +127,14 @@ proc encodePacket*(p: Packet): seq[byte] =
|
||||||
# This should not happen in case of in-memory streams
|
# This should not happen in case of in-memory streams
|
||||||
raiseAssert e.msg
|
raiseAssert e.msg
|
||||||
|
|
||||||
proc decodePacket*(bytes: openArray[byte]): Result[Packet, string] =
|
func decodePacket*(bytes: openArray[byte]): Result[Packet, string] =
|
||||||
let receivedBytesLength = len(bytes)
|
let receivedBytesLength = len(bytes)
|
||||||
if receivedBytesLength < minimalHeaderSize:
|
if receivedBytesLength < minimalHeaderSize:
|
||||||
return err("invalid header size")
|
return err("Invalid header size")
|
||||||
|
|
||||||
let version = bytes[0] and 0xf
|
let version = bytes[0] and 0xf
|
||||||
if version != protocolVersion:
|
if version != protocolVersion:
|
||||||
return err("invalid packet version")
|
return err("Invalid packet version")
|
||||||
|
|
||||||
var kind: PacketType
|
var kind: PacketType
|
||||||
if not checkedEnumAssign(kind, (bytes[0] shr 4)):
|
if not checkedEnumAssign(kind, (bytes[0] shr 4)):
|
||||||
|
@ -162,30 +159,35 @@ proc decodePacket*(bytes: openArray[byte]): Result[Packet, string] =
|
||||||
)
|
)
|
||||||
|
|
||||||
if extensionByte == 0:
|
if extensionByte == 0:
|
||||||
# packet without any extensions
|
# packet without extensions
|
||||||
let payload =
|
let payload =
|
||||||
if (receivedBytesLength == minimalHeaderSize):
|
if (receivedBytesLength == minimalHeaderSize):
|
||||||
@[]
|
@[]
|
||||||
else:
|
else:
|
||||||
bytes[minimalHeaderSize..^1]
|
bytes[minimalHeaderSize..^1]
|
||||||
|
|
||||||
return ok(Packet(header: header, eack: none[SelectiveAckExtension](), payload: payload))
|
return ok(Packet(
|
||||||
|
header: header,
|
||||||
|
eack: none[SelectiveAckExtension](),
|
||||||
|
payload: payload))
|
||||||
else:
|
else:
|
||||||
# packet with selective ack extension
|
# packet with the selective ack extension
|
||||||
if (receivedBytesLength < minimalHeaderSizeWithSelectiveAck):
|
if (receivedBytesLength < minimalHeaderSizeWithSelectiveAck):
|
||||||
return err("Packet too short for selective ack extension")
|
return err("Packet too short for selective ack extension: " &
|
||||||
|
"len = " & $receivedBytesLength)
|
||||||
|
|
||||||
let nextExtension = bytes[20]
|
let nextExtension = bytes[20]
|
||||||
let extLength = bytes[21]
|
let extLength = bytes[21]
|
||||||
|
|
||||||
# As selective ack is only supported extension the byte for nextExtension
|
# The byte for nextExtension must be 0 as selective ack is currently the
|
||||||
# must be equal to 0.
|
# only supported extension.
|
||||||
# As for extLength, specification says that it must be at least 4, and in multiples of 4
|
# For extLength, the specification states that it must be at least 4, and
|
||||||
# but reference implementation always uses 4 bytes bit mask which makes sense
|
# in multiples of 4. However, the reference implementation always uses a 4
|
||||||
# as 4byte bit mask is able to ack 32 packets in the future which is more than enough
|
# bytes bit mask, which makes sense as a 4 byte bit mask is able to ack
|
||||||
|
# 32 packets in the future, which is sounds more than enough.
|
||||||
if (nextExtension != 0 or extLength != 4):
|
if (nextExtension != 0 or extLength != 4):
|
||||||
return err("Bad format of selective ack extension")
|
return err("Bad format of selective ack extension: " &
|
||||||
|
"extension = " & $nextExtension & " len = " & $extLength)
|
||||||
|
|
||||||
let extension = SelectiveAckExtension(
|
let extension = SelectiveAckExtension(
|
||||||
acks: toArray(4, bytes.toOpenArray(22, 25))
|
acks: toArray(4, bytes.toOpenArray(22, 25))
|
||||||
|
@ -199,19 +201,21 @@ proc decodePacket*(bytes: openArray[byte]): Result[Packet, string] =
|
||||||
|
|
||||||
return ok(Packet(header: header, eack: some(extension), payload: payload))
|
return ok(Packet(header: header, eack: some(extension), payload: payload))
|
||||||
|
|
||||||
proc modifyTimeStampAndAckNr*(packetBytes: var seq[byte], newTimestamp: uint32, newAckNr: uint16) =
|
proc modifyTimeStampAndAckNr*(
|
||||||
## Modifies timestamp and ack nr of already encoded packets. Those fields should be
|
packetBytes: var seq[byte], newTimestamp: uint32, newAckNr: uint16) =
|
||||||
## filled right before sending, so when re-sending the packet we would like to update
|
## Modifies timestamp and ack nr of already encoded packets. These fields
|
||||||
## it without decoding and re-encoding the packet once again
|
## must be filled right before sending, so when re-sending the packet they
|
||||||
|
## can be updated without decoding and re-encoding the packet.
|
||||||
doAssert(len(packetBytes) >= minimalHeaderSize)
|
doAssert(len(packetBytes) >= minimalHeaderSize)
|
||||||
packetBytes[4..7] = toBytesBE(newTimestamp)
|
packetBytes[4..7] = toBytesBE(newTimestamp)
|
||||||
packetBytes[18..19] = toBytesBE(newAckNr)
|
packetBytes[18..19] = toBytesBE(newAckNr)
|
||||||
|
|
||||||
# connectionId - should be random not already used number
|
proc synPacket*(
|
||||||
# bufferSize - should be pre configured initial buffer size for socket
|
seqNr: uint16, rcvConnectionId: uint16, bufferSize: uint32): Packet =
|
||||||
# SYN packets are special, and should have the receive ID in the connid field,
|
# rcvConnectionId - should be a random, not already used, number
|
||||||
# instead of conn_id_send.
|
# bufferSize - should be a pre-configured initial buffer size for the socket
|
||||||
proc synPacket*(seqNr: uint16, rcvConnectionId: uint16, bufferSize: uint32): Packet =
|
# SYN packets are special and have the conn_id_recv in the conn_id field,
|
||||||
|
# instead of conn_id_send.
|
||||||
let h = PacketHeaderV1(
|
let h = PacketHeaderV1(
|
||||||
pType: ST_SYN,
|
pType: ST_SYN,
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
|
@ -221,8 +225,7 @@ proc synPacket*(seqNr: uint16, rcvConnectionId: uint16, bufferSize: uint32): Pac
|
||||||
timestampDiff: 0'u32,
|
timestampDiff: 0'u32,
|
||||||
wndSize: bufferSize,
|
wndSize: bufferSize,
|
||||||
seqNr: seqNr,
|
seqNr: seqNr,
|
||||||
# Initially we did not receive any acks
|
ackNr: 0'u16 # At start, no acks have been received
|
||||||
ackNr: 0'u16
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Packet(header: h, eack: none[SelectiveAckExtension](), payload: @[])
|
Packet(header: h, eack: none[SelectiveAckExtension](), payload: @[])
|
||||||
|
@ -267,8 +270,7 @@ proc dataPacket*(
|
||||||
let h = PacketHeaderV1(
|
let h = PacketHeaderV1(
|
||||||
pType: ST_DATA,
|
pType: ST_DATA,
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
# data packets always have extension field set to 0
|
extension: 0'u8, # data packets always have extension field set to 0
|
||||||
extension: 0'u8,
|
|
||||||
connectionId: sndConnectionId,
|
connectionId: sndConnectionId,
|
||||||
timestamp: getMonoTimestamp().timestamp,
|
timestamp: getMonoTimestamp().timestamp,
|
||||||
timestampDiff: timestampDiff,
|
timestampDiff: timestampDiff,
|
||||||
|
@ -279,16 +281,16 @@ proc dataPacket*(
|
||||||
|
|
||||||
Packet(header: h, eack: none[SelectiveAckExtension](), payload: payload)
|
Packet(header: h, eack: none[SelectiveAckExtension](), payload: payload)
|
||||||
|
|
||||||
proc resetPacket*(seqNr: uint16, sndConnectionId: uint16, ackNr: uint16): Packet =
|
proc resetPacket*(
|
||||||
|
seqNr: uint16, sndConnectionId: uint16, ackNr: uint16): Packet =
|
||||||
let h = PacketHeaderV1(
|
let h = PacketHeaderV1(
|
||||||
pType: ST_RESET,
|
pType: ST_RESET,
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
# data packets always have extension field set to 0
|
extension: 0'u8, # reset packets always have extension field set to 0
|
||||||
extension: 0'u8,
|
|
||||||
connectionId: sndConnectionId,
|
connectionId: sndConnectionId,
|
||||||
timestamp: getMonoTimestamp().timestamp,
|
timestamp: getMonoTimestamp().timestamp,
|
||||||
# reset packet informs remote about lack of state for given connection, therefore
|
# reset packet informs remote about lack of state for given connection,
|
||||||
# we do not inform remote about its delay.
|
# therefore the remote is not informed about its delay.
|
||||||
timestampDiff: 0,
|
timestampDiff: 0,
|
||||||
wndSize: 0,
|
wndSize: 0,
|
||||||
seqNr: seqNr,
|
seqNr: seqNr,
|
||||||
|
@ -307,8 +309,7 @@ proc finPacket*(
|
||||||
let h = PacketHeaderV1(
|
let h = PacketHeaderV1(
|
||||||
pType: ST_FIN,
|
pType: ST_FIN,
|
||||||
version: protocolVersion,
|
version: protocolVersion,
|
||||||
# fin packets always have extension field set to 0
|
extension: 0'u8, # fin packets always have extension field set to 0
|
||||||
extension: 0'u8,
|
|
||||||
connectionId: sndConnectionId,
|
connectionId: sndConnectionId,
|
||||||
timestamp: getMonoTimestamp().timestamp,
|
timestamp: getMonoTimestamp().timestamp,
|
||||||
timestampDiff: timestampDiff,
|
timestampDiff: timestampDiff,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (c) 2020-2021 Status Research & Development GmbH
|
# Copyright (c) 2020-2023 Status Research & Development GmbH
|
||||||
# Licensed and distributed under either of
|
# Licensed and distributed under either of
|
||||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||||
|
@ -14,9 +14,10 @@ import
|
||||||
|
|
||||||
suite "uTP Packet Encoding":
|
suite "uTP Packet Encoding":
|
||||||
test "Encode/decode SYN packet":
|
test "Encode/decode SYN packet":
|
||||||
let synPacket = synPacket(5, 10, 20)
|
let
|
||||||
let encoded = encodePacket(synPacket)
|
synPacket = synPacket(5, 10, 20)
|
||||||
let decoded = decodePacket(encoded)
|
encoded = encodePacket(synPacket)
|
||||||
|
decoded = decodePacket(encoded)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
len(encoded) == 20
|
len(encoded) == 20
|
||||||
|
@ -24,13 +25,13 @@ suite "uTP Packet Encoding":
|
||||||
|
|
||||||
let synPacketDec = decoded.get()
|
let synPacketDec = decoded.get()
|
||||||
|
|
||||||
check:
|
check synPacketDec == synPacket
|
||||||
synPacketDec == synPacket
|
|
||||||
|
|
||||||
test "Encode/decode FIN packet":
|
test "Encode/decode FIN packet":
|
||||||
let finPacket = finPacket(5, 10, 20, 30, 40)
|
let
|
||||||
let encoded = encodePacket(finPacket)
|
finPacket = finPacket(5, 10, 20, 30, 40)
|
||||||
let decoded = decodePacket(encoded)
|
encoded = encodePacket(finPacket)
|
||||||
|
decoded = decodePacket(encoded)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
len(encoded) == 20
|
len(encoded) == 20
|
||||||
|
@ -38,13 +39,13 @@ suite "uTP Packet Encoding":
|
||||||
|
|
||||||
let finPacketDec = decoded.get()
|
let finPacketDec = decoded.get()
|
||||||
|
|
||||||
check:
|
check finPacketDec == finPacket
|
||||||
finPacketDec == finPacket
|
|
||||||
|
|
||||||
test "Encode/decode RESET packet":
|
test "Encode/decode RESET packet":
|
||||||
let resetPacket = resetPacket(5, 10, 20)
|
let
|
||||||
let encoded = encodePacket(resetPacket)
|
resetPacket = resetPacket(5, 10, 20)
|
||||||
let decoded = decodePacket(encoded)
|
encoded = encodePacket(resetPacket)
|
||||||
|
decoded = decodePacket(encoded)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
len(encoded) == 20
|
len(encoded) == 20
|
||||||
|
@ -52,13 +53,13 @@ suite "uTP Packet Encoding":
|
||||||
|
|
||||||
let resetPacketDec = decoded.get()
|
let resetPacketDec = decoded.get()
|
||||||
|
|
||||||
check:
|
check resetPacketDec == resetPacket
|
||||||
resetPacketDec == resetPacket
|
|
||||||
|
|
||||||
test "Encode/decode ACK packet: without extensions":
|
test "Encode/decode ACK packet: without extensions":
|
||||||
let ackPacket = ackPacket(5, 10, 20, 30, 40)
|
let
|
||||||
let encoded = encodePacket(ackPacket)
|
ackPacket = ackPacket(5, 10, 20, 30, 40)
|
||||||
let decoded = decodePacket(encoded)
|
encoded = encodePacket(ackPacket)
|
||||||
|
decoded = decodePacket(encoded)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
len(encoded) == 20
|
len(encoded) == 20
|
||||||
|
@ -66,14 +67,14 @@ suite "uTP Packet Encoding":
|
||||||
|
|
||||||
let ackPacketDec = decoded.get()
|
let ackPacketDec = decoded.get()
|
||||||
|
|
||||||
check:
|
check ackPacketDec == ackPacket
|
||||||
ackPacketDec == ackPacket
|
|
||||||
|
|
||||||
test "Encode/decode ACK packet: with extensions":
|
test "Encode/decode ACK packet: with extensions":
|
||||||
let bitMask: array[4, byte] = [1'u8, 2, 3, 4]
|
let
|
||||||
let ackPacket = ackPacket(5, 10, 20, 30, 40, some(bitMask))
|
bitMask: array[4, byte] = [1'u8, 2, 3, 4]
|
||||||
let encoded = encodePacket(ackPacket)
|
ackPacket = ackPacket(5, 10, 20, 30, 40, some(bitMask))
|
||||||
let decoded = decodePacket(encoded)
|
encoded = encodePacket(ackPacket)
|
||||||
|
decoded = decodePacket(encoded)
|
||||||
|
|
||||||
check:
|
check:
|
||||||
len(encoded) == 26
|
len(encoded) == 26
|
||||||
|
@ -89,38 +90,29 @@ suite "uTP Packet Encoding":
|
||||||
let bitMask: array[4, byte] = [1'u8, 2, 3, 4]
|
let bitMask: array[4, byte] = [1'u8, 2, 3, 4]
|
||||||
let ackPacket = ackPacket(5, 10, 20, 30, 40, some(bitMask))
|
let ackPacket = ackPacket(5, 10, 20, 30, 40, some(bitMask))
|
||||||
|
|
||||||
var encoded1 = encodePacket(ackPacket)
|
block: # nextExtension to non zero
|
||||||
# change nextExtension to non zero
|
var encoded = encodePacket(ackPacket)
|
||||||
encoded1[20] = 1
|
encoded[20] = 1
|
||||||
let err1 = decodePacket(encoded1)
|
let err = decodePacket(encoded)
|
||||||
check:
|
check err.isErr()
|
||||||
err1.isErr()
|
|
||||||
err1.error() == "Bad format of selective ack extension"
|
|
||||||
|
|
||||||
var encoded2 = encodePacket(ackPacket)
|
block: # len of extension to value different than 4
|
||||||
# change len of extension to value different than 4
|
var encoded = encodePacket(ackPacket)
|
||||||
encoded2[21] = 7
|
encoded[21] = 7
|
||||||
let err2 = decodePacket(encoded2)
|
let err = decodePacket(encoded)
|
||||||
check:
|
check err.isErr()
|
||||||
err2.isErr()
|
|
||||||
err2.error() == "Bad format of selective ack extension"
|
|
||||||
|
|
||||||
var encoded3 = encodePacket(ackPacket)
|
block: # delete last byte, now packet is too short
|
||||||
# delete last byte, now packet is to short
|
var encoded = encodePacket(ackPacket)
|
||||||
encoded3.del(encoded3.high)
|
encoded.del(encoded.high)
|
||||||
let err3 = decodePacket(encoded3)
|
let err = decodePacket(encoded)
|
||||||
|
check err.isErr()
|
||||||
|
|
||||||
check:
|
block: # change extension field to something other than 0 or 1
|
||||||
err3.isErr()
|
var encoded = encodePacket(ackPacket)
|
||||||
err3.error() == "Packet too short for selective ack extension"
|
encoded[1] = 2
|
||||||
|
let err = decodePacket(encoded)
|
||||||
var encoded4 = encodePacket(ackPacket)
|
check: err.isErr()
|
||||||
# change change extension field to something other than 0 or 1
|
|
||||||
encoded4[1] = 2
|
|
||||||
let err4 = decodePacket(encoded4)
|
|
||||||
check:
|
|
||||||
err4.isErr()
|
|
||||||
err4.error() == "Invalid extension type"
|
|
||||||
|
|
||||||
test "Decode STATE packet":
|
test "Decode STATE packet":
|
||||||
# Packet obtained by interaction with c reference implementation
|
# Packet obtained by interaction with c reference implementation
|
||||||
|
@ -129,8 +121,7 @@ suite "uTP Packet Encoding":
|
||||||
0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x41, 0xA7, 0x00, 0x01]
|
0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x41, 0xA7, 0x00, 0x01]
|
||||||
let decoded = decodePacket(pack)
|
let decoded = decodePacket(pack)
|
||||||
|
|
||||||
check:
|
check decoded.isOk()
|
||||||
decoded.isOk()
|
|
||||||
|
|
||||||
let packet = decoded.get()
|
let packet = decoded.get()
|
||||||
|
|
||||||
|
@ -146,11 +137,12 @@ suite "uTP Packet Encoding":
|
||||||
packet.header.ackNr == 1
|
packet.header.ackNr == 1
|
||||||
|
|
||||||
test "Modify timestamp of encoded packet":
|
test "Modify timestamp of encoded packet":
|
||||||
let synPacket = synPacket(5, 10, 20)
|
let
|
||||||
let initialTimestamp = synPacket.header.timestamp
|
synPacket = synPacket(5, 10, 20)
|
||||||
let initialAckNr = synPacket.header.ackNr
|
initialTimestamp = synPacket.header.timestamp
|
||||||
let modifiedTimeStamp = initialTimestamp + 120324
|
initialAckNr = synPacket.header.ackNr
|
||||||
let modifiedAckNr = initialAckNr + 20
|
modifiedTimeStamp = initialTimestamp + 120324
|
||||||
|
modifiedAckNr = initialAckNr + 20
|
||||||
var encoded = encodePacket(synPacket)
|
var encoded = encodePacket(synPacket)
|
||||||
modifyTimeStampAndAckNr(encoded, modifiedTimeStamp, modifiedAckNr)
|
modifyTimeStampAndAckNr(encoded, modifiedTimeStamp, modifiedAckNr)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue