Skip to content

Commit 875334a

Browse files
fix: TODOs (#7)
1 parent 83ecae7 commit 875334a

3 files changed

Lines changed: 58 additions & 40 deletions

File tree

lsquic/context/stream.nim

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ proc onClose*(stream: ptr lsquic_stream_t, ctx: ptr lsquic_stream_ctx_t) {.cdecl
1313
if not streamCtx.closeWrite:
1414
streamCtx.isEof = true
1515
streamCtx.closed.fire()
16-
# TODO: remove pending writes)
16+
streamCtx.abortPendingWrites("stream closed")
1717

1818
type StreamReadContext = object
1919
stream: ptr lsquic_stream_t
@@ -35,14 +35,16 @@ proc readCtxCb(
3535
proc onRead*(stream: ptr lsquic_stream_t, ctx: ptr lsquic_stream_ctx_t) {.cdecl.} =
3636
trace "stream read"
3737
let readContext = StreamReadContext(stream: stream, ctx: ctx)
38+
let streamCtx = cast[Stream](ctx)
3839
let nread = lsquic_stream_readf(stream, readCtxCb, (addr readContext))
3940
if nread < 0:
40-
discard
41-
# TODO: notify stream of error and close
42-
41+
error "could not read from stream", nread, streamId = lsquic_stream_id(stream)
42+
streamCtx.abort()
43+
4344
if lsquic_stream_wantread(stream, 0) == -1:
44-
discard
45-
# TODO: notify stream of error and close
45+
error "could not set stream wantread", streamId = lsquic_stream_id(stream)
46+
streamCtx.abort()
47+
4648

4749
proc onWrite*(stream: ptr lsquic_stream_t, ctx: ptr lsquic_stream_ctx_t) {.cdecl.} =
4850
trace "onWrite"
@@ -54,8 +56,8 @@ proc onWrite*(stream: ptr lsquic_stream_t, ctx: ptr lsquic_stream_ctx_t) {.cdecl
5456
let streamCtx = cast[Stream](ctx)
5557
if streamCtx.toWrite.len == 0:
5658
if lsquic_stream_wantwrite(stream, 0) == -1:
57-
discard
58-
# TODO: notify stream of error and close
59+
error "could not set stream wantwrite", streamId = lsquic_stream_id(stream)
60+
streamCtx.abort()
5961

6062
# always drain from head of queue to preserve order
6163
while streamCtx.toWrite.len > 0:
@@ -76,21 +78,18 @@ proc onWrite*(stream: ptr lsquic_stream_t, ctx: ptr lsquic_stream_ctx_t) {.cdecl
7678
if not w.doneFut.finished:
7779
w.doneFut.complete()
7880
if lsquic_stream_flush(stream) != 0:
79-
discard # TODO: handle error
81+
streamCtx.abort()
82+
return
8083
streamCtx.toWrite.delete(0)
8184
elif n == 0:
82-
# flow control; stop
8385
break
8486
else:
85-
# error: fail all pending
86-
for pendingWrite in streamCtx.toWrite.mitems:
87-
if not pendingWrite.doneFut.finished:
88-
pendingWrite.doneFut.fail(newException(StreamError, "write failed"))
89-
streamCtx.toWrite.setLen(0)
87+
streamCtx.abortPendingWrites("write failed")
9088
return
9189

9290
if streamCtx.toWrite.len == 0:
9391
if lsquic_stream_wantwrite(stream, 0) == -1:
94-
discard # TODO: handle error
92+
error "could not set stream wantwrite", streamId = lsquic_stream_id(stream)
93+
streamCtx.abort()
9594

9695
return

lsquic/stream.nim

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import chronos
2+
import chronicles
23
import ./lsquic_ffi
34

45
type StreamError* = object of IOError
@@ -23,30 +24,42 @@ proc new*(T: typedesc[Stream], quicStream: ptr lsquic_stream_t = nil): T =
2324
closed: newAsyncEvent(),
2425
)
2526

26-
proc close*(stream: Stream): bool =
27+
proc abortPendingWrites*(stream: Stream, reason: string = "") =
28+
for pendingWrite in stream.toWrite.mitems:
29+
if not pendingWrite.doneFut.finished:
30+
pendingWrite.doneFut.fail(newException(StreamError, reason))
31+
stream.toWrite.setLen(0)
32+
33+
proc abort*(stream: Stream) =
34+
if stream.closeWrite and stream.isEof:
35+
if not stream.closed.isSet():
36+
stream.closed.fire()
37+
stream.abortPendingWrites("stream aborted")
38+
return
39+
40+
let ret = lsquic_stream_close(stream.quicStream)
41+
if ret != 0:
42+
error "could not abort stream", streamId = lsquic_stream_id(stream.quicStream)
43+
44+
stream.closeWrite = true
45+
stream.isEof = true
46+
stream.abortPendingWrites("stream aborted")
47+
stream.closed.fire()
48+
49+
proc close*(stream: Stream) =
2750
if stream.closeWrite:
28-
return true
51+
return
2952

3053
# Closing only the write side
3154
let ret = lsquic_stream_shutdown(stream.quicStream, 1)
3255
if ret == 0:
3356
if stream.isEof:
3457
if lsquic_stream_close(stream.quicStream) != 0:
58+
stream.abort()
3559
raise newException(StreamError, "could not close the stream")
3660

61+
stream.abortPendingWrites("steam closed")
3762
stream.closeWrite = true
38-
return true
39-
false
40-
# TODO: clear all pending writes
41-
42-
proc abort*(stream: Stream): bool =
43-
let ret = lsquic_stream_close(stream.quicStream) == 0
44-
if ret:
45-
stream.closeWrite = true
46-
stream.isEof = true
47-
return true
48-
false
49-
# TODO: clear all pending writes and cancel reads
5063

5164
proc read*(
5265
stream: Stream
@@ -55,7 +68,7 @@ proc read*(
5568
return @[]
5669

5770
if lsquic_stream_wantread(stream.quicStream, 1) == -1:
58-
discard stream.abort()
71+
stream.abort()
5972
raise newException(StreamError, "could not set wantread")
6073

6174
let incomingFut = stream.incoming.get()
@@ -65,14 +78,14 @@ proc read*(
6578
await incomingFut.cancelAndWait()
6679
stream.isEof = true
6780
stream.closeWrite = true
68-
raise newException(StreamError, "connection closed")
81+
raise newException(StreamError, "stream closed")
6982

7083
let incoming = await incomingFut
7184
if incoming.len == 0:
7285
if stream.closeWrite:
7386
# We were already closed for write. Close the stream completely
7487
if lsquic_stream_close(stream.quicStream) != 0:
75-
discard stream.abort()
88+
stream.abort()
7689
raise newException(StreamError, "could not close the stream")
7790
stream.isEof = true
7891

@@ -90,7 +103,7 @@ proc write*(
90103
discard lsquic_stream_wantwrite(stream.quicStream, 1)
91104
let raceFut = await race(closedFut, doneFut)
92105
if raceFut == closedFut:
93-
doneFut.fail(newException(StreamError, "connection closed"))
106+
doneFut.fail(newException(StreamError, "stream closed"))
94107
stream.closeWrite = true
95108

96109
await doneFut

tests/test_connection.nim

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,12 @@ suite "connections":
6767
await stream.write(@[6'u8, 7, 8, 9, 10])
6868

6969
echo "Closing client stream"
70-
echo "Client closed: ", stream.close()
71-
echo "Client abort: ", stream.abort() # Not interested in RW anything else
70+
71+
echo "Client closed"
72+
stream.close()
73+
74+
#echo "Client aborted"
75+
# stream.abort() # Not interested in RW anything else
7276

7377
let incomingBehaviour = proc() {.async.} =
7478
try:
@@ -86,8 +90,11 @@ suite "connections":
8690
check:
8791
stream.isEof
8892

89-
echo "Server closed: ", stream.close()
90-
echo "Server aborted: ", stream.abort() # Not interested in RW anything else
93+
echo "Server closed"
94+
stream.close()
95+
96+
#echo "Server aborted"
97+
#stream.abort() # Not interested in RW anything else
9198
except StreamError:
9299
echo "Stream error: ", getCurrentExceptionMsg()
93100
except CancelledError:
@@ -105,9 +112,8 @@ suite "connections":
105112
await client.stop()
106113
await listener.stop()
107114

108-
# TODO: Close all event loops related to writing
115+
# TODO: perf example
109116
# TODO: destructors: (nice to have:)
110117
# - lsquic_global_cleanup() to free global resources.
111118
# - lsquic_engine_destroy(engine)
112-
# chronicles topics
113119
await sleepAsync(2.seconds)

0 commit comments

Comments
 (0)