mirror of https://github.com/status-im/nim-eth.git
Re-send acks for old duplicated packets (#462)
* Re-send acks for old duplicated packets
This commit is contained in:
parent
26ab9b078e
commit
b2dab4be08
|
@ -163,7 +163,8 @@ proc processPacket[A](r: UtpRouter[A], p: Packet, sender: A) {.async.}=
|
||||||
debug "Ignoring SYN for already existing connection"
|
debug "Ignoring SYN for already existing connection"
|
||||||
else:
|
else:
|
||||||
if (r.shouldAllowConnection(sender, p.header.connectionId)):
|
if (r.shouldAllowConnection(sender, p.header.connectionId)):
|
||||||
debug "Received SYN for new connection. Initiating incoming connection"
|
debug "Received SYN for new connection. Initiating incoming connection",
|
||||||
|
synSeqNr = p.header.seqNr
|
||||||
# Initial ackNr is set to incoming packer seqNr
|
# Initial ackNr is set to incoming packer seqNr
|
||||||
let incomingSocket = newIncomingSocket[A](sender, r.sendCb, r.socketConfig ,p.header.connectionId, p.header.seqNr, r.rng[])
|
let incomingSocket = newIncomingSocket[A](sender, r.sendCb, r.socketConfig ,p.header.connectionId, p.header.seqNr, r.rng[])
|
||||||
r.registerUtpSocket(incomingSocket)
|
r.registerUtpSocket(incomingSocket)
|
||||||
|
|
|
@ -1019,6 +1019,8 @@ proc processPacket*(socket: UtpSocket, p: Packet) {.async.} =
|
||||||
|
|
||||||
debug "Process packet",
|
debug "Process packet",
|
||||||
socketKey = socket.socketKey,
|
socketKey = socket.socketKey,
|
||||||
|
socketAckNr = socket.ackNr,
|
||||||
|
socketSeqNr = socket.seqNr,
|
||||||
packetType = p.header.pType,
|
packetType = p.header.pType,
|
||||||
seqNr = p.header.seqNr,
|
seqNr = p.header.seqNr,
|
||||||
ackNr = p.header.ackNr,
|
ackNr = p.header.ackNr,
|
||||||
|
@ -1059,6 +1061,19 @@ proc processPacket*(socket: UtpSocket, p: Packet) {.async.} =
|
||||||
|
|
||||||
# If packet is totally of the mark short circout the processing
|
# If packet is totally of the mark short circout the processing
|
||||||
if pastExpected >= reorderBufferMaxSize:
|
if pastExpected >= reorderBufferMaxSize:
|
||||||
|
|
||||||
|
# if `pastExpected` is really big number (for example: uint16.high) then most
|
||||||
|
# probably we are receiving packet which we already received
|
||||||
|
# example: we already received packet with `seqNr = 10` so our `socket.ackNr = 10`
|
||||||
|
# if we receive this packet once again then `pastExpected = 10 - 10 - 1` which
|
||||||
|
# equals (due to wrapping) 65535
|
||||||
|
# this means that remote most probably did not receive our ack, so we need to resend
|
||||||
|
# it. We are doing it for last `reorderBufferMaxSize` packets
|
||||||
|
let isPossibleDuplicatedOldPacket = pastExpected >= (int(uint16.high) + 1) - reorderBufferMaxSize
|
||||||
|
|
||||||
|
if (isPossibleDuplicatedOldPacket and p.header.pType != ST_STATE):
|
||||||
|
asyncSpawn socket.sendAck()
|
||||||
|
|
||||||
debug "Got an invalid packet sequence number, too far off",
|
debug "Got an invalid packet sequence number, too far off",
|
||||||
pastExpected = pastExpected
|
pastExpected = pastExpected
|
||||||
return
|
return
|
||||||
|
@ -1231,6 +1246,13 @@ proc processPacket*(socket: UtpSocket, p: Packet) {.async.} =
|
||||||
let packet = maybePacket.unsafeGet()
|
let packet = maybePacket.unsafeGet()
|
||||||
|
|
||||||
if (len(packet.payload) > 0 and (not socket.readShutdown)):
|
if (len(packet.payload) > 0 and (not socket.readShutdown)):
|
||||||
|
debug "Got packet from reorder buffer",
|
||||||
|
packetBytes = len(packet.payload),
|
||||||
|
packetSeqNr = packet.header.seqNr,
|
||||||
|
packetAckNr = packet.header.ackNr,
|
||||||
|
socketSeqNr = socket.seqNr,
|
||||||
|
socekrAckNr = socket.ackNr
|
||||||
|
|
||||||
await upload(addr socket.buffer, unsafeAddr packet.payload[0], packet.payload.len())
|
await upload(addr socket.buffer, unsafeAddr packet.payload[0], packet.payload.len())
|
||||||
|
|
||||||
socket.inBuffer.delete(nextPacketNum)
|
socket.inBuffer.delete(nextPacketNum)
|
||||||
|
@ -1428,6 +1450,9 @@ proc numPacketsInOutGoingBuffer*(socket: UtpSocket): int =
|
||||||
# Check how many payload bytes are still in flight
|
# Check how many payload bytes are still in flight
|
||||||
proc numOfBytesInFlight*(socket: UtpSocket): uint32 = socket.sendBufferTracker.currentBytesInFlight()
|
proc numOfBytesInFlight*(socket: UtpSocket): uint32 = socket.sendBufferTracker.currentBytesInFlight()
|
||||||
|
|
||||||
|
# Check how many bytes are in incoming buffer
|
||||||
|
proc numOfBytesInIncomingBuffer*(socket: UtpSocket): uint32 = uint32(socket.buffer.dataLen())
|
||||||
|
|
||||||
# Check how many packets are still in the reorder buffer, usefull for tests or
|
# Check how many packets are still in the reorder buffer, usefull for tests or
|
||||||
# debugging.
|
# debugging.
|
||||||
# It throws assertion error when number of elements in buffer do not equal kept counter
|
# It throws assertion error when number of elements in buffer do not equal kept counter
|
||||||
|
|
|
@ -124,6 +124,49 @@ procSuite "Utp socket unit test":
|
||||||
|
|
||||||
await outgoingSocket.destroyWait()
|
await outgoingSocket.destroyWait()
|
||||||
|
|
||||||
|
asyncTest "Processing duplicated fresh data packet should ack it and stop processing":
|
||||||
|
let q = newAsyncQueue[Packet]()
|
||||||
|
let initalRemoteSeqNr = 10'u16
|
||||||
|
let data = @[1'u8, 2'u8, 3'u8]
|
||||||
|
|
||||||
|
let (outgoingSocket, initialPacket) = connectOutGoingSocket(initalRemoteSeqNr, q)
|
||||||
|
|
||||||
|
let dataP1 =
|
||||||
|
dataPacket(
|
||||||
|
initalRemoteSeqNr,
|
||||||
|
initialPacket.header.connectionId,
|
||||||
|
initialPacket.header.seqNr,
|
||||||
|
testBufferSize,
|
||||||
|
data,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
await outgoingSocket.processPacket(dataP1)
|
||||||
|
|
||||||
|
let ack1 = await q.get()
|
||||||
|
|
||||||
|
check:
|
||||||
|
ack1.header.pType == ST_STATE
|
||||||
|
ack1.header.ackNr == initalRemoteSeqNr
|
||||||
|
|
||||||
|
let receivedBytes = await outgoingSocket.read(len(data))
|
||||||
|
|
||||||
|
check:
|
||||||
|
receivedBytes == data
|
||||||
|
|
||||||
|
# remote re-send data packet, most probably due to lost ack
|
||||||
|
await outgoingSocket.processPacket(dataP1)
|
||||||
|
|
||||||
|
let ack2 = await q.get()
|
||||||
|
|
||||||
|
check:
|
||||||
|
ack2.header.pType == ST_STATE
|
||||||
|
ack2.header.ackNr == initalRemoteSeqNr
|
||||||
|
# we do not upload data one more time
|
||||||
|
outgoingSocket.numOfBytesInIncomingBuffer() == 0'u32
|
||||||
|
|
||||||
|
await outgoingSocket.destroyWait()
|
||||||
|
|
||||||
asyncTest "Processing out of order data packet should buffer it until receiving in order one":
|
asyncTest "Processing out of order data packet should buffer it until receiving in order one":
|
||||||
# TODO test is valid until implementing selective acks
|
# TODO test is valid until implementing selective acks
|
||||||
let q = newAsyncQueue[Packet]()
|
let q = newAsyncQueue[Packet]()
|
||||||
|
|
Loading…
Reference in New Issue