introduce asyncraises in transports/asyncsync (#470)
With these fixes, `transports`/`asyncsync` correctly propagate and document their raises information - generally, most transport functions (send etc) raise `TransportError` and `CancelledError` - `closeWait` is special in that it generally doesn't fail. This PR introduces the syntax `Future[void].Raises([types])` to create the `InternalRaisesFuture` type with the correct encoding for the types - this allows it to be used in user code while retaining the possibility to change the internal representation down the line. * introduce raising constraints on stream callbacks - these constraints now give a warning when called with a callback that can raise exceptions (raising callbacks would crash * fix fail and its tests, which wasn't always given a good generic match * work around nim bugs related to macro expansion of generic types * make sure transports raise only `TransportError`-derived exceptions (and `CancelledError`)
This commit is contained in:
parent
24be151cf3
commit
f5ff9e32ca
|
@ -28,7 +28,7 @@ type
|
||||||
## is blocked in ``acquire()`` is being processed.
|
## is blocked in ``acquire()`` is being processed.
|
||||||
locked: bool
|
locked: bool
|
||||||
acquired: bool
|
acquired: bool
|
||||||
waiters: seq[Future[void]]
|
waiters: seq[Future[void].Raising([CancelledError])]
|
||||||
|
|
||||||
AsyncEvent* = ref object of RootRef
|
AsyncEvent* = ref object of RootRef
|
||||||
## A primitive event object.
|
## A primitive event object.
|
||||||
|
@ -41,7 +41,7 @@ type
|
||||||
## state to be signaled, when event get fired, then all coroutines
|
## state to be signaled, when event get fired, then all coroutines
|
||||||
## continue proceeds in order, they have entered waiting state.
|
## continue proceeds in order, they have entered waiting state.
|
||||||
flag: bool
|
flag: bool
|
||||||
waiters: seq[Future[void]]
|
waiters: seq[Future[void].Raising([CancelledError])]
|
||||||
|
|
||||||
AsyncQueue*[T] = ref object of RootRef
|
AsyncQueue*[T] = ref object of RootRef
|
||||||
## A queue, useful for coordinating producer and consumer coroutines.
|
## A queue, useful for coordinating producer and consumer coroutines.
|
||||||
|
@ -50,8 +50,8 @@ type
|
||||||
## infinite. If it is an integer greater than ``0``, then "await put()"
|
## infinite. If it is an integer greater than ``0``, then "await put()"
|
||||||
## will block when the queue reaches ``maxsize``, until an item is
|
## will block when the queue reaches ``maxsize``, until an item is
|
||||||
## removed by "await get()".
|
## removed by "await get()".
|
||||||
getters: seq[Future[void]]
|
getters: seq[Future[void].Raising([CancelledError])]
|
||||||
putters: seq[Future[void]]
|
putters: seq[Future[void].Raising([CancelledError])]
|
||||||
queue: Deque[T]
|
queue: Deque[T]
|
||||||
maxsize: int
|
maxsize: int
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ type
|
||||||
EventQueueReader* = object
|
EventQueueReader* = object
|
||||||
key: EventQueueKey
|
key: EventQueueKey
|
||||||
offset: int
|
offset: int
|
||||||
waiter: Future[void]
|
waiter: Future[void].Raising([CancelledError])
|
||||||
overflow: bool
|
overflow: bool
|
||||||
|
|
||||||
AsyncEventQueue*[T] = ref object of RootObj
|
AsyncEventQueue*[T] = ref object of RootObj
|
||||||
|
@ -90,17 +90,14 @@ proc newAsyncLock*(): AsyncLock =
|
||||||
## The ``release()`` procedure changes the state to unlocked and returns
|
## The ``release()`` procedure changes the state to unlocked and returns
|
||||||
## immediately.
|
## immediately.
|
||||||
|
|
||||||
# Workaround for callSoon() not worked correctly before
|
AsyncLock()
|
||||||
# getThreadDispatcher() call.
|
|
||||||
discard getThreadDispatcher()
|
|
||||||
AsyncLock(waiters: newSeq[Future[void]](), locked: false, acquired: false)
|
|
||||||
|
|
||||||
proc wakeUpFirst(lock: AsyncLock): bool {.inline.} =
|
proc wakeUpFirst(lock: AsyncLock): bool {.inline.} =
|
||||||
## Wake up the first waiter if it isn't done.
|
## Wake up the first waiter if it isn't done.
|
||||||
var i = 0
|
var i = 0
|
||||||
var res = false
|
var res = false
|
||||||
while i < len(lock.waiters):
|
while i < len(lock.waiters):
|
||||||
var waiter = lock.waiters[i]
|
let waiter = lock.waiters[i]
|
||||||
inc(i)
|
inc(i)
|
||||||
if not(waiter.finished()):
|
if not(waiter.finished()):
|
||||||
waiter.complete()
|
waiter.complete()
|
||||||
|
@ -120,7 +117,7 @@ proc checkAll(lock: AsyncLock): bool {.inline.} =
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc acquire*(lock: AsyncLock) {.async.} =
|
proc acquire*(lock: AsyncLock) {.async: (raises: [CancelledError]).} =
|
||||||
## Acquire a lock ``lock``.
|
## Acquire a lock ``lock``.
|
||||||
##
|
##
|
||||||
## This procedure blocks until the lock ``lock`` is unlocked, then sets it
|
## This procedure blocks until the lock ``lock`` is unlocked, then sets it
|
||||||
|
@ -129,7 +126,7 @@ proc acquire*(lock: AsyncLock) {.async.} =
|
||||||
lock.acquired = true
|
lock.acquired = true
|
||||||
lock.locked = true
|
lock.locked = true
|
||||||
else:
|
else:
|
||||||
var w = newFuture[void]("AsyncLock.acquire")
|
let w = Future[void].Raising([CancelledError]).init("AsyncLock.acquire")
|
||||||
lock.waiters.add(w)
|
lock.waiters.add(w)
|
||||||
await w
|
await w
|
||||||
lock.acquired = true
|
lock.acquired = true
|
||||||
|
@ -165,13 +162,10 @@ proc newAsyncEvent*(): AsyncEvent =
|
||||||
## procedure and reset to `false` with the `clear()` procedure.
|
## procedure and reset to `false` with the `clear()` procedure.
|
||||||
## The `wait()` procedure blocks until the flag is `true`. The flag is
|
## The `wait()` procedure blocks until the flag is `true`. The flag is
|
||||||
## initially `false`.
|
## initially `false`.
|
||||||
|
AsyncEvent()
|
||||||
|
|
||||||
# Workaround for callSoon() not worked correctly before
|
proc wait*(event: AsyncEvent): Future[void] {.
|
||||||
# getThreadDispatcher() call.
|
async: (raw: true, raises: [CancelledError]).} =
|
||||||
discard getThreadDispatcher()
|
|
||||||
AsyncEvent(waiters: newSeq[Future[void]](), flag: false)
|
|
||||||
|
|
||||||
proc wait*(event: AsyncEvent): Future[void] =
|
|
||||||
## Block until the internal flag of ``event`` is `true`.
|
## Block until the internal flag of ``event`` is `true`.
|
||||||
## If the internal flag is `true` on entry, return immediately. Otherwise,
|
## If the internal flag is `true` on entry, return immediately. Otherwise,
|
||||||
## block until another task calls `fire()` to set the flag to `true`,
|
## block until another task calls `fire()` to set the flag to `true`,
|
||||||
|
@ -210,20 +204,15 @@ proc isSet*(event: AsyncEvent): bool =
|
||||||
proc newAsyncQueue*[T](maxsize: int = 0): AsyncQueue[T] =
|
proc newAsyncQueue*[T](maxsize: int = 0): AsyncQueue[T] =
|
||||||
## Creates a new asynchronous queue ``AsyncQueue``.
|
## Creates a new asynchronous queue ``AsyncQueue``.
|
||||||
|
|
||||||
# Workaround for callSoon() not worked correctly before
|
|
||||||
# getThreadDispatcher() call.
|
|
||||||
discard getThreadDispatcher()
|
|
||||||
AsyncQueue[T](
|
AsyncQueue[T](
|
||||||
getters: newSeq[Future[void]](),
|
|
||||||
putters: newSeq[Future[void]](),
|
|
||||||
queue: initDeque[T](),
|
queue: initDeque[T](),
|
||||||
maxsize: maxsize
|
maxsize: maxsize
|
||||||
)
|
)
|
||||||
|
|
||||||
proc wakeupNext(waiters: var seq[Future[void]]) {.inline.} =
|
proc wakeupNext(waiters: var seq) {.inline.} =
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < len(waiters):
|
while i < len(waiters):
|
||||||
var waiter = waiters[i]
|
let waiter = waiters[i]
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
if not(waiter.finished()):
|
if not(waiter.finished()):
|
||||||
|
@ -250,6 +239,24 @@ proc empty*[T](aq: AsyncQueue[T]): bool {.inline.} =
|
||||||
## Return ``true`` if the queue is empty, ``false`` otherwise.
|
## Return ``true`` if the queue is empty, ``false`` otherwise.
|
||||||
(len(aq.queue) == 0)
|
(len(aq.queue) == 0)
|
||||||
|
|
||||||
|
proc addFirstImpl[T](aq: AsyncQueue[T], item: T) =
|
||||||
|
aq.queue.addFirst(item)
|
||||||
|
aq.getters.wakeupNext()
|
||||||
|
|
||||||
|
proc addLastImpl[T](aq: AsyncQueue[T], item: T) =
|
||||||
|
aq.queue.addLast(item)
|
||||||
|
aq.getters.wakeupNext()
|
||||||
|
|
||||||
|
proc popFirstImpl[T](aq: AsyncQueue[T]): T =
|
||||||
|
let res = aq.queue.popFirst()
|
||||||
|
aq.putters.wakeupNext()
|
||||||
|
res
|
||||||
|
|
||||||
|
proc popLastImpl[T](aq: AsyncQueue[T]): T =
|
||||||
|
let res = aq.queue.popLast()
|
||||||
|
aq.putters.wakeupNext()
|
||||||
|
res
|
||||||
|
|
||||||
proc addFirstNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
proc addFirstNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
||||||
raises: [AsyncQueueFullError].}=
|
raises: [AsyncQueueFullError].}=
|
||||||
## Put an item ``item`` to the beginning of the queue ``aq`` immediately.
|
## Put an item ``item`` to the beginning of the queue ``aq`` immediately.
|
||||||
|
@ -257,8 +264,7 @@ proc addFirstNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
||||||
## If queue ``aq`` is full, then ``AsyncQueueFullError`` exception raised.
|
## If queue ``aq`` is full, then ``AsyncQueueFullError`` exception raised.
|
||||||
if aq.full():
|
if aq.full():
|
||||||
raise newException(AsyncQueueFullError, "AsyncQueue is full!")
|
raise newException(AsyncQueueFullError, "AsyncQueue is full!")
|
||||||
aq.queue.addFirst(item)
|
aq.addFirstImpl(item)
|
||||||
aq.getters.wakeupNext()
|
|
||||||
|
|
||||||
proc addLastNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
proc addLastNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
||||||
raises: [AsyncQueueFullError].}=
|
raises: [AsyncQueueFullError].}=
|
||||||
|
@ -267,8 +273,7 @@ proc addLastNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
||||||
## If queue ``aq`` is full, then ``AsyncQueueFullError`` exception raised.
|
## If queue ``aq`` is full, then ``AsyncQueueFullError`` exception raised.
|
||||||
if aq.full():
|
if aq.full():
|
||||||
raise newException(AsyncQueueFullError, "AsyncQueue is full!")
|
raise newException(AsyncQueueFullError, "AsyncQueue is full!")
|
||||||
aq.queue.addLast(item)
|
aq.addLastImpl(item)
|
||||||
aq.getters.wakeupNext()
|
|
||||||
|
|
||||||
proc popFirstNoWait*[T](aq: AsyncQueue[T]): T {.
|
proc popFirstNoWait*[T](aq: AsyncQueue[T]): T {.
|
||||||
raises: [AsyncQueueEmptyError].} =
|
raises: [AsyncQueueEmptyError].} =
|
||||||
|
@ -277,9 +282,7 @@ proc popFirstNoWait*[T](aq: AsyncQueue[T]): T {.
|
||||||
## If queue ``aq`` is empty, then ``AsyncQueueEmptyError`` exception raised.
|
## If queue ``aq`` is empty, then ``AsyncQueueEmptyError`` exception raised.
|
||||||
if aq.empty():
|
if aq.empty():
|
||||||
raise newException(AsyncQueueEmptyError, "AsyncQueue is empty!")
|
raise newException(AsyncQueueEmptyError, "AsyncQueue is empty!")
|
||||||
let res = aq.queue.popFirst()
|
aq.popFirstImpl()
|
||||||
aq.putters.wakeupNext()
|
|
||||||
res
|
|
||||||
|
|
||||||
proc popLastNoWait*[T](aq: AsyncQueue[T]): T {.
|
proc popLastNoWait*[T](aq: AsyncQueue[T]): T {.
|
||||||
raises: [AsyncQueueEmptyError].} =
|
raises: [AsyncQueueEmptyError].} =
|
||||||
|
@ -288,65 +291,63 @@ proc popLastNoWait*[T](aq: AsyncQueue[T]): T {.
|
||||||
## If queue ``aq`` is empty, then ``AsyncQueueEmptyError`` exception raised.
|
## If queue ``aq`` is empty, then ``AsyncQueueEmptyError`` exception raised.
|
||||||
if aq.empty():
|
if aq.empty():
|
||||||
raise newException(AsyncQueueEmptyError, "AsyncQueue is empty!")
|
raise newException(AsyncQueueEmptyError, "AsyncQueue is empty!")
|
||||||
let res = aq.queue.popLast()
|
aq.popLastImpl()
|
||||||
aq.putters.wakeupNext()
|
|
||||||
res
|
|
||||||
|
|
||||||
proc addFirst*[T](aq: AsyncQueue[T], item: T) {.async.} =
|
proc addFirst*[T](aq: AsyncQueue[T], item: T) {.async: (raises: [CancelledError]).} =
|
||||||
## Put an ``item`` to the beginning of the queue ``aq``. If the queue is full,
|
## Put an ``item`` to the beginning of the queue ``aq``. If the queue is full,
|
||||||
## wait until a free slot is available before adding item.
|
## wait until a free slot is available before adding item.
|
||||||
while aq.full():
|
while aq.full():
|
||||||
var putter = newFuture[void]("AsyncQueue.addFirst")
|
let putter = Future[void].Raising([CancelledError]).init("AsyncQueue.addFirst")
|
||||||
aq.putters.add(putter)
|
aq.putters.add(putter)
|
||||||
try:
|
try:
|
||||||
await putter
|
await putter
|
||||||
except CatchableError as exc:
|
except CancelledError as exc:
|
||||||
if not(aq.full()) and not(putter.cancelled()):
|
if not(aq.full()) and not(putter.cancelled()):
|
||||||
aq.putters.wakeupNext()
|
aq.putters.wakeupNext()
|
||||||
raise exc
|
raise exc
|
||||||
aq.addFirstNoWait(item)
|
aq.addFirstImpl(item)
|
||||||
|
|
||||||
proc addLast*[T](aq: AsyncQueue[T], item: T) {.async.} =
|
proc addLast*[T](aq: AsyncQueue[T], item: T) {.async: (raises: [CancelledError]).} =
|
||||||
## Put an ``item`` to the end of the queue ``aq``. If the queue is full,
|
## Put an ``item`` to the end of the queue ``aq``. If the queue is full,
|
||||||
## wait until a free slot is available before adding item.
|
## wait until a free slot is available before adding item.
|
||||||
while aq.full():
|
while aq.full():
|
||||||
var putter = newFuture[void]("AsyncQueue.addLast")
|
let putter = Future[void].Raising([CancelledError]).init("AsyncQueue.addLast")
|
||||||
aq.putters.add(putter)
|
aq.putters.add(putter)
|
||||||
try:
|
try:
|
||||||
await putter
|
await putter
|
||||||
except CatchableError as exc:
|
except CancelledError as exc:
|
||||||
if not(aq.full()) and not(putter.cancelled()):
|
if not(aq.full()) and not(putter.cancelled()):
|
||||||
aq.putters.wakeupNext()
|
aq.putters.wakeupNext()
|
||||||
raise exc
|
raise exc
|
||||||
aq.addLastNoWait(item)
|
aq.addLastImpl(item)
|
||||||
|
|
||||||
proc popFirst*[T](aq: AsyncQueue[T]): Future[T] {.async.} =
|
proc popFirst*[T](aq: AsyncQueue[T]): Future[T] {.async: (raises: [CancelledError]).} =
|
||||||
## Remove and return an ``item`` from the beginning of the queue ``aq``.
|
## Remove and return an ``item`` from the beginning of the queue ``aq``.
|
||||||
## If the queue is empty, wait until an item is available.
|
## If the queue is empty, wait until an item is available.
|
||||||
while aq.empty():
|
while aq.empty():
|
||||||
var getter = newFuture[void]("AsyncQueue.popFirst")
|
let getter = Future[void].Raising([CancelledError]).init("AsyncQueue.popFirst")
|
||||||
aq.getters.add(getter)
|
aq.getters.add(getter)
|
||||||
try:
|
try:
|
||||||
await getter
|
await getter
|
||||||
except CatchableError as exc:
|
except CancelledError as exc:
|
||||||
if not(aq.empty()) and not(getter.cancelled()):
|
if not(aq.empty()) and not(getter.cancelled()):
|
||||||
aq.getters.wakeupNext()
|
aq.getters.wakeupNext()
|
||||||
raise exc
|
raise exc
|
||||||
return aq.popFirstNoWait()
|
aq.popFirstImpl()
|
||||||
|
|
||||||
proc popLast*[T](aq: AsyncQueue[T]): Future[T] {.async.} =
|
proc popLast*[T](aq: AsyncQueue[T]): Future[T] {.async: (raises: [CancelledError]).} =
|
||||||
## Remove and return an ``item`` from the end of the queue ``aq``.
|
## Remove and return an ``item`` from the end of the queue ``aq``.
|
||||||
## If the queue is empty, wait until an item is available.
|
## If the queue is empty, wait until an item is available.
|
||||||
while aq.empty():
|
while aq.empty():
|
||||||
var getter = newFuture[void]("AsyncQueue.popLast")
|
let getter = Future[void].Raising([CancelledError]).init("AsyncQueue.popLast")
|
||||||
aq.getters.add(getter)
|
aq.getters.add(getter)
|
||||||
try:
|
try:
|
||||||
await getter
|
await getter
|
||||||
except CatchableError as exc:
|
except CancelledError as exc:
|
||||||
if not(aq.empty()) and not(getter.cancelled()):
|
if not(aq.empty()) and not(getter.cancelled()):
|
||||||
aq.getters.wakeupNext()
|
aq.getters.wakeupNext()
|
||||||
raise exc
|
raise exc
|
||||||
return aq.popLastNoWait()
|
aq.popLastImpl()
|
||||||
|
|
||||||
proc putNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
proc putNoWait*[T](aq: AsyncQueue[T], item: T) {.
|
||||||
raises: [AsyncQueueFullError].} =
|
raises: [AsyncQueueFullError].} =
|
||||||
|
@ -358,11 +359,13 @@ proc getNoWait*[T](aq: AsyncQueue[T]): T {.
|
||||||
## Alias of ``popFirstNoWait()``.
|
## Alias of ``popFirstNoWait()``.
|
||||||
aq.popFirstNoWait()
|
aq.popFirstNoWait()
|
||||||
|
|
||||||
proc put*[T](aq: AsyncQueue[T], item: T): Future[void] {.inline.} =
|
proc put*[T](aq: AsyncQueue[T], item: T): Future[void] {.
|
||||||
|
async: (raw: true, raises: [CancelledError]).} =
|
||||||
## Alias of ``addLast()``.
|
## Alias of ``addLast()``.
|
||||||
aq.addLast(item)
|
aq.addLast(item)
|
||||||
|
|
||||||
proc get*[T](aq: AsyncQueue[T]): Future[T] {.inline.} =
|
proc get*[T](aq: AsyncQueue[T]): Future[T] {.
|
||||||
|
async: (raw: true, raises: [CancelledError]).} =
|
||||||
## Alias of ``popFirst()``.
|
## Alias of ``popFirst()``.
|
||||||
aq.popFirst()
|
aq.popFirst()
|
||||||
|
|
||||||
|
@ -416,7 +419,7 @@ proc contains*[T](aq: AsyncQueue[T], item: T): bool {.inline.} =
|
||||||
## via the ``in`` operator.
|
## via the ``in`` operator.
|
||||||
for e in aq.queue.items():
|
for e in aq.queue.items():
|
||||||
if e == item: return true
|
if e == item: return true
|
||||||
return false
|
false
|
||||||
|
|
||||||
proc `$`*[T](aq: AsyncQueue[T]): string =
|
proc `$`*[T](aq: AsyncQueue[T]): string =
|
||||||
## Turn an async queue ``aq`` into its string representation.
|
## Turn an async queue ``aq`` into its string representation.
|
||||||
|
@ -452,8 +455,7 @@ proc compact(ab: AsyncEventQueue) {.raises: [].} =
|
||||||
else:
|
else:
|
||||||
ab.queue.clear()
|
ab.queue.clear()
|
||||||
|
|
||||||
proc getReaderIndex(ab: AsyncEventQueue, key: EventQueueKey): int {.
|
proc getReaderIndex(ab: AsyncEventQueue, key: EventQueueKey): int =
|
||||||
raises: [].} =
|
|
||||||
for index, value in ab.readers.pairs():
|
for index, value in ab.readers.pairs():
|
||||||
if value.key == key:
|
if value.key == key:
|
||||||
return index
|
return index
|
||||||
|
@ -507,7 +509,7 @@ proc close*(ab: AsyncEventQueue) {.raises: [].} =
|
||||||
ab.readers.reset()
|
ab.readers.reset()
|
||||||
ab.queue.clear()
|
ab.queue.clear()
|
||||||
|
|
||||||
proc closeWait*(ab: AsyncEventQueue): Future[void] {.raises: [].} =
|
proc closeWait*(ab: AsyncEventQueue): Future[void] {.async: (raw: true, raises: []).} =
|
||||||
let retFuture = newFuture[void]("AsyncEventQueue.closeWait()",
|
let retFuture = newFuture[void]("AsyncEventQueue.closeWait()",
|
||||||
{FutureFlag.OwnCancelSchedule})
|
{FutureFlag.OwnCancelSchedule})
|
||||||
proc continuation(udata: pointer) {.gcsafe.} =
|
proc continuation(udata: pointer) {.gcsafe.} =
|
||||||
|
@ -528,7 +530,7 @@ template readerOverflow*(ab: AsyncEventQueue,
|
||||||
reader: EventQueueReader): bool =
|
reader: EventQueueReader): bool =
|
||||||
ab.limit + (reader.offset - ab.offset) <= len(ab.queue)
|
ab.limit + (reader.offset - ab.offset) <= len(ab.queue)
|
||||||
|
|
||||||
proc emit*[T](ab: AsyncEventQueue[T], data: T) {.raises: [].} =
|
proc emit*[T](ab: AsyncEventQueue[T], data: T) =
|
||||||
if len(ab.readers) > 0:
|
if len(ab.readers) > 0:
|
||||||
# We enqueue `data` only if there active reader present.
|
# We enqueue `data` only if there active reader present.
|
||||||
var changesPresent = false
|
var changesPresent = false
|
||||||
|
@ -565,7 +567,8 @@ proc emit*[T](ab: AsyncEventQueue[T], data: T) {.raises: [].} =
|
||||||
|
|
||||||
proc waitEvents*[T](ab: AsyncEventQueue[T],
|
proc waitEvents*[T](ab: AsyncEventQueue[T],
|
||||||
key: EventQueueKey,
|
key: EventQueueKey,
|
||||||
eventsCount = -1): Future[seq[T]] {.async.} =
|
eventsCount = -1): Future[seq[T]] {.
|
||||||
|
async: (raises: [AsyncEventQueueFullError, CancelledError]).} =
|
||||||
## Wait for events
|
## Wait for events
|
||||||
var
|
var
|
||||||
events: seq[T]
|
events: seq[T]
|
||||||
|
@ -595,7 +598,8 @@ proc waitEvents*[T](ab: AsyncEventQueue[T],
|
||||||
doAssert(length >= ab.readers[index].offset)
|
doAssert(length >= ab.readers[index].offset)
|
||||||
if length == ab.readers[index].offset:
|
if length == ab.readers[index].offset:
|
||||||
# We are at the end of queue, it means that we should wait for new events.
|
# We are at the end of queue, it means that we should wait for new events.
|
||||||
let waitFuture = newFuture[void]("AsyncEventQueue.waitEvents")
|
let waitFuture = Future[void].Raising([CancelledError]).init(
|
||||||
|
"AsyncEventQueue.waitEvents")
|
||||||
ab.readers[index].waiter = waitFuture
|
ab.readers[index].waiter = waitFuture
|
||||||
resetFuture = true
|
resetFuture = true
|
||||||
await waitFuture
|
await waitFuture
|
||||||
|
@ -626,4 +630,4 @@ proc waitEvents*[T](ab: AsyncEventQueue[T],
|
||||||
if (eventsCount <= 0) or (len(events) == eventsCount):
|
if (eventsCount <= 0) or (len(events) == eventsCount):
|
||||||
break
|
break
|
||||||
|
|
||||||
return events
|
events
|
||||||
|
|
|
@ -16,7 +16,9 @@ import stew/base10
|
||||||
import ./[asyncengine, raisesfutures]
|
import ./[asyncengine, raisesfutures]
|
||||||
import ../[config, futures]
|
import ../[config, futures]
|
||||||
|
|
||||||
export raisesfutures.InternalRaisesFuture
|
export
|
||||||
|
raisesfutures.Raising, raisesfutures.InternalRaisesFuture,
|
||||||
|
raisesfutures.init, raisesfutures.error, raisesfutures.readError
|
||||||
|
|
||||||
when chronosStackTrace:
|
when chronosStackTrace:
|
||||||
import std/strutils
|
import std/strutils
|
||||||
|
@ -109,7 +111,7 @@ template newInternalRaisesFuture*[T, E](fromProc: static[string] = ""): auto =
|
||||||
## that this future belongs to, is a good habit as it helps with debugging.
|
## that this future belongs to, is a good habit as it helps with debugging.
|
||||||
newInternalRaisesFutureImpl[T, E](getSrcLocation(fromProc))
|
newInternalRaisesFutureImpl[T, E](getSrcLocation(fromProc))
|
||||||
|
|
||||||
template newFutureSeq*[A, B](fromProc: static[string] = ""): FutureSeq[A, B] =
|
template newFutureSeq*[A, B](fromProc: static[string] = ""): FutureSeq[A, B] {.deprecated.} =
|
||||||
## Create a new future which can hold/preserve GC sequence until future will
|
## Create a new future which can hold/preserve GC sequence until future will
|
||||||
## not be completed.
|
## not be completed.
|
||||||
##
|
##
|
||||||
|
@ -117,7 +119,7 @@ template newFutureSeq*[A, B](fromProc: static[string] = ""): FutureSeq[A, B] =
|
||||||
## that this future belongs to, is a good habit as it helps with debugging.
|
## that this future belongs to, is a good habit as it helps with debugging.
|
||||||
newFutureSeqImpl[A, B](getSrcLocation(fromProc))
|
newFutureSeqImpl[A, B](getSrcLocation(fromProc))
|
||||||
|
|
||||||
template newFutureStr*[T](fromProc: static[string] = ""): FutureStr[T] =
|
template newFutureStr*[T](fromProc: static[string] = ""): FutureStr[T] {.deprecated.} =
|
||||||
## Create a new future which can hold/preserve GC string until future will
|
## Create a new future which can hold/preserve GC string until future will
|
||||||
## not be completed.
|
## not be completed.
|
||||||
##
|
##
|
||||||
|
@ -205,7 +207,8 @@ template complete*(future: Future[void]) =
|
||||||
## Completes a void ``future``.
|
## Completes a void ``future``.
|
||||||
complete(future, getSrcLocation())
|
complete(future, getSrcLocation())
|
||||||
|
|
||||||
proc fail(future: FutureBase, error: ref CatchableError, loc: ptr SrcLoc) =
|
proc failImpl(
|
||||||
|
future: FutureBase, error: ref CatchableError, loc: ptr SrcLoc) =
|
||||||
if not(future.cancelled()):
|
if not(future.cancelled()):
|
||||||
checkFinished(future, loc)
|
checkFinished(future, loc)
|
||||||
future.internalError = error
|
future.internalError = error
|
||||||
|
@ -216,10 +219,16 @@ proc fail(future: FutureBase, error: ref CatchableError, loc: ptr SrcLoc) =
|
||||||
getStackTrace(error)
|
getStackTrace(error)
|
||||||
future.finish(FutureState.Failed)
|
future.finish(FutureState.Failed)
|
||||||
|
|
||||||
template fail*(
|
template fail*[T](
|
||||||
future: FutureBase, error: ref CatchableError, warn: static bool = false) =
|
future: Future[T], error: ref CatchableError, warn: static bool = false) =
|
||||||
## Completes ``future`` with ``error``.
|
## Completes ``future`` with ``error``.
|
||||||
fail(future, error, getSrcLocation())
|
failImpl(future, error, getSrcLocation())
|
||||||
|
|
||||||
|
template fail*[T, E](
|
||||||
|
future: InternalRaisesFuture[T, E], error: ref CatchableError,
|
||||||
|
warn: static bool = true) =
|
||||||
|
checkRaises(future, E, error, warn)
|
||||||
|
failImpl(future, error, getSrcLocation())
|
||||||
|
|
||||||
template newCancelledError(): ref CancelledError =
|
template newCancelledError(): ref CancelledError =
|
||||||
(ref CancelledError)(msg: "Future operation cancelled!")
|
(ref CancelledError)(msg: "Future operation cancelled!")
|
||||||
|
@ -377,8 +386,6 @@ proc futureContinue*(fut: FutureBase) {.raises: [], gcsafe.} =
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
when chronosStackTrace:
|
when chronosStackTrace:
|
||||||
import std/strutils
|
|
||||||
|
|
||||||
template getFilenameProcname(entry: StackTraceEntry): (string, string) =
|
template getFilenameProcname(entry: StackTraceEntry): (string, string) =
|
||||||
when compiles(entry.filenameStr) and compiles(entry.procnameStr):
|
when compiles(entry.filenameStr) and compiles(entry.procnameStr):
|
||||||
# We can't rely on "entry.filename" and "entry.procname" still being valid
|
# We can't rely on "entry.filename" and "entry.procname" still being valid
|
||||||
|
@ -462,31 +469,36 @@ proc internalCheckComplete*(fut: FutureBase) {.raises: [CatchableError].} =
|
||||||
injectStacktrace(fut.internalError)
|
injectStacktrace(fut.internalError)
|
||||||
raise fut.internalError
|
raise fut.internalError
|
||||||
|
|
||||||
macro internalCheckComplete*(f: InternalRaisesFuture): untyped =
|
macro internalCheckComplete*(fut: InternalRaisesFuture, raises: typed) =
|
||||||
# For InternalRaisesFuture[void, (ValueError, OSError), will do:
|
# For InternalRaisesFuture[void, (ValueError, OSError), will do:
|
||||||
# {.cast(raises: [ValueError, OSError]).}:
|
# {.cast(raises: [ValueError, OSError]).}:
|
||||||
# if isNil(f.error): discard
|
# if isNil(f.error): discard
|
||||||
# else: raise f.error
|
# else: raise f.error
|
||||||
let e = getTypeInst(f)[2]
|
# TODO https://github.com/nim-lang/Nim/issues/22937
|
||||||
let types = getType(e)
|
# we cannot `getTypeInst` on the `fut` - when aliases are involved, the
|
||||||
|
# generics are lost - so instead, we pass the raises list explicitly
|
||||||
|
|
||||||
|
let types = getRaisesTypes(raises)
|
||||||
if isNoRaises(types):
|
if isNoRaises(types):
|
||||||
return quote do:
|
return quote do:
|
||||||
if not(isNil(`f`.internalError)):
|
if not(isNil(`fut`.internalError)):
|
||||||
raiseAssert("Unhandled future exception: " & `f`.error.msg)
|
# This would indicate a bug in which `error` was set via the non-raising
|
||||||
|
# base type
|
||||||
|
raiseAssert("Error set on a non-raising future: " & `fut`.internalError.msg)
|
||||||
|
|
||||||
expectKind(types, nnkBracketExpr)
|
expectKind(types, nnkBracketExpr)
|
||||||
expectKind(types[0], nnkSym)
|
expectKind(types[0], nnkSym)
|
||||||
|
|
||||||
assert types[0].strVal == "tuple"
|
assert types[0].strVal == "tuple"
|
||||||
|
|
||||||
let ifRaise = nnkIfExpr.newTree(
|
let ifRaise = nnkIfExpr.newTree(
|
||||||
nnkElifExpr.newTree(
|
nnkElifExpr.newTree(
|
||||||
quote do: isNil(`f`.internalError),
|
quote do: isNil(`fut`.internalError),
|
||||||
quote do: discard
|
quote do: discard
|
||||||
),
|
),
|
||||||
nnkElseExpr.newTree(
|
nnkElseExpr.newTree(
|
||||||
nnkRaiseStmt.newNimNode(lineInfoFrom=f).add(
|
nnkRaiseStmt.newNimNode(lineInfoFrom=fut).add(
|
||||||
quote do: (`f`.internalError)
|
quote do: (`fut`.internalError)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1118,7 +1130,7 @@ proc one*[F: SomeFuture](futs: varargs[F]): Future[F] {.
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc race*(futs: varargs[FutureBase]): Future[FutureBase] {.
|
proc race*(futs: varargs[FutureBase]): Future[FutureBase] {.
|
||||||
async: (raw: true, raises: [CancelledError]).} =
|
async: (raw: true, raises: [ValueError, CancelledError]).} =
|
||||||
## Returns a future which will complete and return completed FutureBase,
|
## Returns a future which will complete and return completed FutureBase,
|
||||||
## when one of the futures in ``futs`` will be completed, failed or canceled.
|
## when one of the futures in ``futs`` will be completed, failed or canceled.
|
||||||
##
|
##
|
||||||
|
@ -1488,12 +1500,6 @@ when defined(windows):
|
||||||
|
|
||||||
{.pop.} # Automatically deduced raises from here onwards
|
{.pop.} # Automatically deduced raises from here onwards
|
||||||
|
|
||||||
template fail*[T, E](
|
|
||||||
future: InternalRaisesFuture[T, E], error: ref CatchableError,
|
|
||||||
warn: static bool = true) =
|
|
||||||
checkRaises(future, error, warn)
|
|
||||||
fail(future, error, getSrcLocation())
|
|
||||||
|
|
||||||
proc waitFor*[T, E](fut: InternalRaisesFuture[T, E]): T = # {.raises: [E]}
|
proc waitFor*[T, E](fut: InternalRaisesFuture[T, E]): T = # {.raises: [E]}
|
||||||
## **Blocks** the current thread until the specified future finishes and
|
## **Blocks** the current thread until the specified future finishes and
|
||||||
## reads it, potentially raising an exception if the future failed or was
|
## reads it, potentially raising an exception if the future failed or was
|
||||||
|
@ -1512,7 +1518,7 @@ proc read*[T: not void, E](future: InternalRaisesFuture[T, E]): lent T = # {.rai
|
||||||
# TODO: Make a custom exception type for this?
|
# TODO: Make a custom exception type for this?
|
||||||
raise newException(ValueError, "Future still in progress.")
|
raise newException(ValueError, "Future still in progress.")
|
||||||
|
|
||||||
internalCheckComplete(future)
|
internalCheckComplete(future, E)
|
||||||
future.internalValue
|
future.internalValue
|
||||||
|
|
||||||
proc read*[E](future: InternalRaisesFuture[void, E]) = # {.raises: [E, CancelledError].}
|
proc read*[E](future: InternalRaisesFuture[void, E]) = # {.raises: [E, CancelledError].}
|
||||||
|
|
|
@ -497,7 +497,7 @@ proc asyncSingleProc(prc, params: NimNode): NimNode {.compileTime.} =
|
||||||
|
|
||||||
prc
|
prc
|
||||||
|
|
||||||
template await*[T](f: Future[T]): untyped =
|
template await*[T](f: Future[T]): T =
|
||||||
when declared(chronosInternalRetFuture):
|
when declared(chronosInternalRetFuture):
|
||||||
chronosInternalRetFuture.internalChild = f
|
chronosInternalRetFuture.internalChild = f
|
||||||
# `futureContinue` calls the iterator generated by the `async`
|
# `futureContinue` calls the iterator generated by the `async`
|
||||||
|
@ -512,6 +512,21 @@ template await*[T](f: Future[T]): untyped =
|
||||||
else:
|
else:
|
||||||
unsupported "await is only available within {.async.}"
|
unsupported "await is only available within {.async.}"
|
||||||
|
|
||||||
|
template await*[T, E](f: InternalRaisesFuture[T, E]): T =
|
||||||
|
when declared(chronosInternalRetFuture):
|
||||||
|
chronosInternalRetFuture.internalChild = f
|
||||||
|
# `futureContinue` calls the iterator generated by the `async`
|
||||||
|
# transformation - `yield` gives control back to `futureContinue` which is
|
||||||
|
# responsible for resuming execution once the yielded future is finished
|
||||||
|
yield chronosInternalRetFuture.internalChild
|
||||||
|
# `child` released by `futureContinue`
|
||||||
|
cast[type(f)](chronosInternalRetFuture.internalChild).internalCheckComplete(E)
|
||||||
|
|
||||||
|
when T isnot void:
|
||||||
|
cast[type(f)](chronosInternalRetFuture.internalChild).value()
|
||||||
|
else:
|
||||||
|
unsupported "await is only available within {.async.}"
|
||||||
|
|
||||||
template awaitne*[T](f: Future[T]): Future[T] =
|
template awaitne*[T](f: Future[T]): Future[T] =
|
||||||
when declared(chronosInternalRetFuture):
|
when declared(chronosInternalRetFuture):
|
||||||
chronosInternalRetFuture.internalChild = f
|
chronosInternalRetFuture.internalChild = f
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import
|
import
|
||||||
std/macros,
|
std/[macros, sequtils],
|
||||||
../futures
|
../futures
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -18,6 +18,45 @@ proc makeNoRaises*(): NimNode {.compileTime.} =
|
||||||
|
|
||||||
ident"void"
|
ident"void"
|
||||||
|
|
||||||
|
macro Raising*[T](F: typedesc[Future[T]], E: varargs[typedesc]): untyped =
|
||||||
|
## Given a Future type instance, return a type storing `{.raises.}`
|
||||||
|
## information
|
||||||
|
##
|
||||||
|
## Note; this type may change in the future
|
||||||
|
E.expectKind(nnkBracket)
|
||||||
|
|
||||||
|
let raises = if E.len == 0:
|
||||||
|
makeNoRaises()
|
||||||
|
else:
|
||||||
|
nnkTupleConstr.newTree(E.mapIt(it))
|
||||||
|
nnkBracketExpr.newTree(
|
||||||
|
ident "InternalRaisesFuture",
|
||||||
|
nnkDotExpr.newTree(F, ident"T"),
|
||||||
|
raises
|
||||||
|
)
|
||||||
|
|
||||||
|
template init*[T, E](
|
||||||
|
F: type InternalRaisesFuture[T, E], fromProc: static[string] = ""): F =
|
||||||
|
## Creates a new pending future.
|
||||||
|
##
|
||||||
|
## Specifying ``fromProc``, which is a string specifying the name of the proc
|
||||||
|
## that this future belongs to, is a good habit as it helps with debugging.
|
||||||
|
let res = F()
|
||||||
|
internalInitFutureBase(res, getSrcLocation(fromProc), FutureState.Pending, {})
|
||||||
|
res
|
||||||
|
|
||||||
|
template init*[T, E](
|
||||||
|
F: type InternalRaisesFuture[T, E], fromProc: static[string] = "",
|
||||||
|
flags: static[FutureFlags]): F =
|
||||||
|
## Creates a new pending future.
|
||||||
|
##
|
||||||
|
## Specifying ``fromProc``, which is a string specifying the name of the proc
|
||||||
|
## that this future belongs to, is a good habit as it helps with debugging.
|
||||||
|
let res = F()
|
||||||
|
internalInitFutureBase(
|
||||||
|
res, getSrcLocation(fromProc), FutureState.Pending, flags)
|
||||||
|
res
|
||||||
|
|
||||||
proc isNoRaises*(n: NimNode): bool {.compileTime.} =
|
proc isNoRaises*(n: NimNode): bool {.compileTime.} =
|
||||||
n.eqIdent("void")
|
n.eqIdent("void")
|
||||||
|
|
||||||
|
@ -78,21 +117,15 @@ macro union*(tup0: typedesc[tuple], tup1: typedesc[tuple]): typedesc =
|
||||||
if result.len == 0:
|
if result.len == 0:
|
||||||
result = makeNoRaises()
|
result = makeNoRaises()
|
||||||
|
|
||||||
proc getRaises*(future: NimNode): NimNode {.compileTime.} =
|
proc getRaisesTypes*(raises: NimNode): NimNode =
|
||||||
# Given InternalRaisesFuture[T, (A, B, C)], returns (A, B, C)
|
let typ = getType(raises)
|
||||||
let types = getType(getTypeInst(future)[2])
|
case typ.typeKind
|
||||||
if isNoRaises(types):
|
of ntyTypeDesc: typ[1]
|
||||||
nnkBracketExpr.newTree(newEmptyNode())
|
else: typ
|
||||||
else:
|
|
||||||
expectKind(types, nnkBracketExpr)
|
|
||||||
expectKind(types[0], nnkSym)
|
|
||||||
assert types[0].strVal == "tuple"
|
|
||||||
assert types.len >= 1
|
|
||||||
|
|
||||||
types
|
|
||||||
|
|
||||||
macro checkRaises*[T: CatchableError](
|
macro checkRaises*[T: CatchableError](
|
||||||
future: InternalRaisesFuture, error: ref T, warn: static bool = true): untyped =
|
future: InternalRaisesFuture, raises: typed, error: ref T,
|
||||||
|
warn: static bool = true): untyped =
|
||||||
## Generate code that checks that the given error is compatible with the
|
## Generate code that checks that the given error is compatible with the
|
||||||
## raises restrictions of `future`.
|
## raises restrictions of `future`.
|
||||||
##
|
##
|
||||||
|
@ -100,11 +133,18 @@ macro checkRaises*[T: CatchableError](
|
||||||
## information available at compile time - in particular, if the raises
|
## information available at compile time - in particular, if the raises
|
||||||
## inherit from `error`, we end up with the equivalent of a downcast which
|
## inherit from `error`, we end up with the equivalent of a downcast which
|
||||||
## raises a Defect if it fails.
|
## raises a Defect if it fails.
|
||||||
let raises = getRaises(future)
|
let
|
||||||
|
raises = getRaisesTypes(raises)
|
||||||
|
|
||||||
expectKind(getTypeInst(error), nnkRefTy)
|
expectKind(getTypeInst(error), nnkRefTy)
|
||||||
let toMatch = getTypeInst(error)[0]
|
let toMatch = getTypeInst(error)[0]
|
||||||
|
|
||||||
|
|
||||||
|
if isNoRaises(raises):
|
||||||
|
error(
|
||||||
|
"`fail`: `" & repr(toMatch) & "` incompatible with `raises: []`", future)
|
||||||
|
return
|
||||||
|
|
||||||
var
|
var
|
||||||
typeChecker = ident"false"
|
typeChecker = ident"false"
|
||||||
maybeChecker = ident"false"
|
maybeChecker = ident"false"
|
||||||
|
@ -134,3 +174,15 @@ macro checkRaises*[T: CatchableError](
|
||||||
else:
|
else:
|
||||||
`warning`
|
`warning`
|
||||||
assert(`runtimeChecker`, `errorMsg`)
|
assert(`runtimeChecker`, `errorMsg`)
|
||||||
|
|
||||||
|
proc error*[T](future: InternalRaisesFuture[T, void]): ref CatchableError {.
|
||||||
|
raises: [].} =
|
||||||
|
static:
|
||||||
|
warning("No exceptions possible with this operation, `error` always returns nil")
|
||||||
|
nil
|
||||||
|
|
||||||
|
proc readError*[T](future: InternalRaisesFuture[T, void]): ref CatchableError {.
|
||||||
|
raises: [ValueError].} =
|
||||||
|
static:
|
||||||
|
warning("No exceptions possible with this operation, `readError` always raises")
|
||||||
|
raise newException(ValueError, "No error in future.")
|
||||||
|
|
|
@ -113,6 +113,8 @@ type
|
||||||
## Transport's capability not supported exception
|
## Transport's capability not supported exception
|
||||||
TransportUseClosedError* = object of TransportError
|
TransportUseClosedError* = object of TransportError
|
||||||
## Usage after transport close exception
|
## Usage after transport close exception
|
||||||
|
TransportUseEofError* = object of TransportError
|
||||||
|
## Usage after transport half-close exception
|
||||||
TransportTooManyError* = object of TransportError
|
TransportTooManyError* = object of TransportError
|
||||||
## Too many open file descriptors exception
|
## Too many open file descriptors exception
|
||||||
TransportAbortedError* = object of TransportError
|
TransportAbortedError* = object of TransportError
|
||||||
|
@ -567,11 +569,11 @@ template checkClosed*(t: untyped, future: untyped) =
|
||||||
|
|
||||||
template checkWriteEof*(t: untyped, future: untyped) =
|
template checkWriteEof*(t: untyped, future: untyped) =
|
||||||
if (WriteEof in (t).state):
|
if (WriteEof in (t).state):
|
||||||
future.fail(newException(TransportError,
|
future.fail(newException(TransportUseEofError,
|
||||||
"Transport connection is already dropped!"))
|
"Transport connection is already dropped!"))
|
||||||
return future
|
return future
|
||||||
|
|
||||||
template getError*(t: untyped): ref CatchableError =
|
template getError*(t: untyped): ref TransportError =
|
||||||
var err = (t).error
|
var err = (t).error
|
||||||
(t).error = nil
|
(t).error = nil
|
||||||
err
|
err
|
||||||
|
|
|
@ -27,7 +27,10 @@ type
|
||||||
|
|
||||||
DatagramCallback* = proc(transp: DatagramTransport,
|
DatagramCallback* = proc(transp: DatagramTransport,
|
||||||
remote: TransportAddress): Future[void] {.
|
remote: TransportAddress): Future[void] {.
|
||||||
gcsafe, raises: [].}
|
async: (raises: []).}
|
||||||
|
|
||||||
|
UnsafeDatagramCallback* = proc(transp: DatagramTransport,
|
||||||
|
remote: TransportAddress): Future[void] {.async.}
|
||||||
|
|
||||||
DatagramTransport* = ref object of RootRef
|
DatagramTransport* = ref object of RootRef
|
||||||
fd*: AsyncFD # File descriptor
|
fd*: AsyncFD # File descriptor
|
||||||
|
@ -35,7 +38,7 @@ type
|
||||||
flags: set[ServerFlags] # Flags
|
flags: set[ServerFlags] # Flags
|
||||||
buffer: seq[byte] # Reading buffer
|
buffer: seq[byte] # Reading buffer
|
||||||
buflen: int # Reading buffer effective size
|
buflen: int # Reading buffer effective size
|
||||||
error: ref CatchableError # Current error
|
error: ref TransportError # Current error
|
||||||
queue: Deque[GramVector] # Writer queue
|
queue: Deque[GramVector] # Writer queue
|
||||||
local: TransportAddress # Local address
|
local: TransportAddress # Local address
|
||||||
remote: TransportAddress # Remote address
|
remote: TransportAddress # Remote address
|
||||||
|
@ -599,6 +602,41 @@ proc close*(transp: DatagramTransport) =
|
||||||
transp.state.incl({WriteClosed, ReadClosed})
|
transp.state.incl({WriteClosed, ReadClosed})
|
||||||
closeSocket(transp.fd, continuation)
|
closeSocket(transp.fd, continuation)
|
||||||
|
|
||||||
|
proc newDatagramTransportCommon(cbproc: UnsafeDatagramCallback,
|
||||||
|
remote: TransportAddress,
|
||||||
|
local: TransportAddress,
|
||||||
|
sock: AsyncFD,
|
||||||
|
flags: set[ServerFlags],
|
||||||
|
udata: pointer,
|
||||||
|
child: DatagramTransport,
|
||||||
|
bufferSize: int,
|
||||||
|
ttl: int,
|
||||||
|
dualstack = DualStackType.Auto
|
||||||
|
): DatagramTransport {.
|
||||||
|
raises: [TransportOsError].} =
|
||||||
|
## Create new UDP datagram transport (IPv4).
|
||||||
|
##
|
||||||
|
## ``cbproc`` - callback which will be called, when new datagram received.
|
||||||
|
## ``remote`` - bind transport to remote address (optional).
|
||||||
|
## ``local`` - bind transport to local address (to serving incoming
|
||||||
|
## datagrams, optional)
|
||||||
|
## ``sock`` - application-driven socket to use.
|
||||||
|
## ``flags`` - flags that will be applied to socket.
|
||||||
|
## ``udata`` - custom argument which will be passed to ``cbproc``.
|
||||||
|
## ``bufSize`` - size of internal buffer.
|
||||||
|
## ``ttl`` - TTL for UDP datagram packet (only usable when flags has
|
||||||
|
## ``Broadcast`` option).
|
||||||
|
|
||||||
|
proc wrap(transp: DatagramTransport,
|
||||||
|
remote: TransportAddress) {.async: (raises: []).} =
|
||||||
|
try:
|
||||||
|
cbproc(transp, remote)
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert "Unexpected exception from stream server cbproc: " & exc.msg
|
||||||
|
|
||||||
|
newDatagramTransportCommon(wrap, remote, local, sock, flags, udata, child,
|
||||||
|
bufferSize, ttl, dualstack)
|
||||||
|
|
||||||
proc newDatagramTransport*(cbproc: DatagramCallback,
|
proc newDatagramTransport*(cbproc: DatagramCallback,
|
||||||
remote: TransportAddress = AnyAddress,
|
remote: TransportAddress = AnyAddress,
|
||||||
local: TransportAddress = AnyAddress,
|
local: TransportAddress = AnyAddress,
|
||||||
|
@ -689,7 +727,102 @@ proc newDatagramTransport6*[T](cbproc: DatagramCallback,
|
||||||
cast[pointer](udata), child, bufSize, ttl,
|
cast[pointer](udata), child, bufSize, ttl,
|
||||||
dualstack)
|
dualstack)
|
||||||
|
|
||||||
proc join*(transp: DatagramTransport): Future[void] =
|
proc newDatagramTransport*(cbproc: UnsafeDatagramCallback,
|
||||||
|
remote: TransportAddress = AnyAddress,
|
||||||
|
local: TransportAddress = AnyAddress,
|
||||||
|
sock: AsyncFD = asyncInvalidSocket,
|
||||||
|
flags: set[ServerFlags] = {},
|
||||||
|
udata: pointer = nil,
|
||||||
|
child: DatagramTransport = nil,
|
||||||
|
bufSize: int = DefaultDatagramBufferSize,
|
||||||
|
ttl: int = 0,
|
||||||
|
dualstack = DualStackType.Auto
|
||||||
|
): DatagramTransport {.
|
||||||
|
raises: [TransportOsError],
|
||||||
|
deprecated: "Callback must not raise exceptions, annotate with {.async: (raises: []).}".} =
|
||||||
|
## Create new UDP datagram transport (IPv4).
|
||||||
|
##
|
||||||
|
## ``cbproc`` - callback which will be called, when new datagram received.
|
||||||
|
## ``remote`` - bind transport to remote address (optional).
|
||||||
|
## ``local`` - bind transport to local address (to serving incoming
|
||||||
|
## datagrams, optional)
|
||||||
|
## ``sock`` - application-driven socket to use.
|
||||||
|
## ``flags`` - flags that will be applied to socket.
|
||||||
|
## ``udata`` - custom argument which will be passed to ``cbproc``.
|
||||||
|
## ``bufSize`` - size of internal buffer.
|
||||||
|
## ``ttl`` - TTL for UDP datagram packet (only usable when flags has
|
||||||
|
## ``Broadcast`` option).
|
||||||
|
newDatagramTransportCommon(cbproc, remote, local, sock, flags, udata, child,
|
||||||
|
bufSize, ttl, dualstack)
|
||||||
|
|
||||||
|
proc newDatagramTransport*[T](cbproc: UnsafeDatagramCallback,
|
||||||
|
udata: ref T,
|
||||||
|
remote: TransportAddress = AnyAddress,
|
||||||
|
local: TransportAddress = AnyAddress,
|
||||||
|
sock: AsyncFD = asyncInvalidSocket,
|
||||||
|
flags: set[ServerFlags] = {},
|
||||||
|
child: DatagramTransport = nil,
|
||||||
|
bufSize: int = DefaultDatagramBufferSize,
|
||||||
|
ttl: int = 0,
|
||||||
|
dualstack = DualStackType.Auto
|
||||||
|
): DatagramTransport {.
|
||||||
|
raises: [TransportOsError],
|
||||||
|
deprecated: "Callback must not raise exceptions, annotate with {.async: (raises: []).}".} =
|
||||||
|
var fflags = flags + {GCUserData}
|
||||||
|
GC_ref(udata)
|
||||||
|
newDatagramTransportCommon(cbproc, remote, local, sock, fflags,
|
||||||
|
cast[pointer](udata), child, bufSize, ttl,
|
||||||
|
dualstack)
|
||||||
|
|
||||||
|
proc newDatagramTransport6*(cbproc: UnsafeDatagramCallback,
|
||||||
|
remote: TransportAddress = AnyAddress6,
|
||||||
|
local: TransportAddress = AnyAddress6,
|
||||||
|
sock: AsyncFD = asyncInvalidSocket,
|
||||||
|
flags: set[ServerFlags] = {},
|
||||||
|
udata: pointer = nil,
|
||||||
|
child: DatagramTransport = nil,
|
||||||
|
bufSize: int = DefaultDatagramBufferSize,
|
||||||
|
ttl: int = 0,
|
||||||
|
dualstack = DualStackType.Auto
|
||||||
|
): DatagramTransport {.
|
||||||
|
raises: [TransportOsError],
|
||||||
|
deprecated: "Callback must not raise exceptions, annotate with {.async: (raises: []).}".} =
|
||||||
|
## Create new UDP datagram transport (IPv6).
|
||||||
|
##
|
||||||
|
## ``cbproc`` - callback which will be called, when new datagram received.
|
||||||
|
## ``remote`` - bind transport to remote address (optional).
|
||||||
|
## ``local`` - bind transport to local address (to serving incoming
|
||||||
|
## datagrams, optional)
|
||||||
|
## ``sock`` - application-driven socket to use.
|
||||||
|
## ``flags`` - flags that will be applied to socket.
|
||||||
|
## ``udata`` - custom argument which will be passed to ``cbproc``.
|
||||||
|
## ``bufSize`` - size of internal buffer.
|
||||||
|
## ``ttl`` - TTL for UDP datagram packet (only usable when flags has
|
||||||
|
## ``Broadcast`` option).
|
||||||
|
newDatagramTransportCommon(cbproc, remote, local, sock, flags, udata, child,
|
||||||
|
bufSize, ttl, dualstack)
|
||||||
|
|
||||||
|
proc newDatagramTransport6*[T](cbproc: UnsafeDatagramCallback,
|
||||||
|
udata: ref T,
|
||||||
|
remote: TransportAddress = AnyAddress6,
|
||||||
|
local: TransportAddress = AnyAddress6,
|
||||||
|
sock: AsyncFD = asyncInvalidSocket,
|
||||||
|
flags: set[ServerFlags] = {},
|
||||||
|
child: DatagramTransport = nil,
|
||||||
|
bufSize: int = DefaultDatagramBufferSize,
|
||||||
|
ttl: int = 0,
|
||||||
|
dualstack = DualStackType.Auto
|
||||||
|
): DatagramTransport {.
|
||||||
|
raises: [TransportOsError],
|
||||||
|
deprecated: "Callback must not raise exceptions, annotate with {.async: (raises: []).}".} =
|
||||||
|
var fflags = flags + {GCUserData}
|
||||||
|
GC_ref(udata)
|
||||||
|
newDatagramTransportCommon(cbproc, remote, local, sock, fflags,
|
||||||
|
cast[pointer](udata), child, bufSize, ttl,
|
||||||
|
dualstack)
|
||||||
|
|
||||||
|
proc join*(transp: DatagramTransport): Future[void] {.
|
||||||
|
async: (raw: true, raises: [CancelledError]).} =
|
||||||
## Wait until the transport ``transp`` will be closed.
|
## Wait until the transport ``transp`` will be closed.
|
||||||
var retFuture = newFuture[void]("datagram.transport.join")
|
var retFuture = newFuture[void]("datagram.transport.join")
|
||||||
|
|
||||||
|
@ -707,14 +840,15 @@ proc join*(transp: DatagramTransport): Future[void] =
|
||||||
|
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc closeWait*(transp: DatagramTransport): Future[void] =
|
proc closeWait*(transp: DatagramTransport): Future[void] {.
|
||||||
|
async: (raw: true, raises: []).} =
|
||||||
## Close transport ``transp`` and release all resources.
|
## Close transport ``transp`` and release all resources.
|
||||||
const FutureName = "datagram.transport.closeWait"
|
let retFuture = newFuture[void](
|
||||||
|
"datagram.transport.closeWait", {FutureFlag.OwnCancelSchedule})
|
||||||
|
|
||||||
if {ReadClosed, WriteClosed} * transp.state != {}:
|
if {ReadClosed, WriteClosed} * transp.state != {}:
|
||||||
return Future.completed(FutureName)
|
retFuture.complete()
|
||||||
|
return retFuture
|
||||||
let retFuture = newFuture[void](FutureName, {FutureFlag.OwnCancelSchedule})
|
|
||||||
|
|
||||||
proc continuation(udata: pointer) {.gcsafe.} =
|
proc continuation(udata: pointer) {.gcsafe.} =
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
|
@ -733,7 +867,8 @@ proc closeWait*(transp: DatagramTransport): Future[void] =
|
||||||
retFuture
|
retFuture
|
||||||
|
|
||||||
proc send*(transp: DatagramTransport, pbytes: pointer,
|
proc send*(transp: DatagramTransport, pbytes: pointer,
|
||||||
nbytes: int): Future[void] =
|
nbytes: int): Future[void] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Send buffer with pointer ``pbytes`` and size ``nbytes`` using transport
|
## Send buffer with pointer ``pbytes`` and size ``nbytes`` using transport
|
||||||
## ``transp`` to remote destination address which was bounded on transport.
|
## ``transp`` to remote destination address which was bounded on transport.
|
||||||
var retFuture = newFuture[void]("datagram.transport.send(pointer)")
|
var retFuture = newFuture[void]("datagram.transport.send(pointer)")
|
||||||
|
@ -751,22 +886,21 @@ proc send*(transp: DatagramTransport, pbytes: pointer,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc send*(transp: DatagramTransport, msg: sink string,
|
proc send*(transp: DatagramTransport, msg: sink string,
|
||||||
msglen = -1): Future[void] =
|
msglen = -1): Future[void] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Send string ``msg`` using transport ``transp`` to remote destination
|
## Send string ``msg`` using transport ``transp`` to remote destination
|
||||||
## address which was bounded on transport.
|
## address which was bounded on transport.
|
||||||
var retFuture = newFutureStr[void]("datagram.transport.send(string)")
|
var retFuture = newFuture[void]("datagram.transport.send(string)")
|
||||||
transp.checkClosed(retFuture)
|
transp.checkClosed(retFuture)
|
||||||
when declared(shallowCopy):
|
|
||||||
if not(isLiteral(msg)):
|
|
||||||
shallowCopy(retFuture.gcholder, msg)
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
let length = if msglen <= 0: len(msg) else: msglen
|
let length = if msglen <= 0: len(msg) else: msglen
|
||||||
let vector = GramVector(kind: WithoutAddress, buf: addr retFuture.gcholder[0],
|
var localCopy = msg
|
||||||
|
retFuture.addCallback(proc(_: pointer) = reset(localCopy))
|
||||||
|
|
||||||
|
let vector = GramVector(kind: WithoutAddress, buf: addr localCopy[0],
|
||||||
buflen: length,
|
buflen: length,
|
||||||
writer: cast[Future[void]](retFuture))
|
writer: retFuture)
|
||||||
|
|
||||||
transp.queue.addLast(vector)
|
transp.queue.addLast(vector)
|
||||||
if WritePaused in transp.state:
|
if WritePaused in transp.state:
|
||||||
let wres = transp.resumeWrite()
|
let wres = transp.resumeWrite()
|
||||||
|
@ -775,22 +909,20 @@ proc send*(transp: DatagramTransport, msg: sink string,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc send*[T](transp: DatagramTransport, msg: sink seq[T],
|
proc send*[T](transp: DatagramTransport, msg: sink seq[T],
|
||||||
msglen = -1): Future[void] =
|
msglen = -1): Future[void] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Send string ``msg`` using transport ``transp`` to remote destination
|
## Send string ``msg`` using transport ``transp`` to remote destination
|
||||||
## address which was bounded on transport.
|
## address which was bounded on transport.
|
||||||
var retFuture = newFutureSeq[void, T]("datagram.transport.send(seq)")
|
var retFuture = newFuture[void]("datagram.transport.send(seq)")
|
||||||
transp.checkClosed(retFuture)
|
transp.checkClosed(retFuture)
|
||||||
when declared(shallowCopy):
|
|
||||||
if not(isLiteral(msg)):
|
|
||||||
shallowCopy(retFuture.gcholder, msg)
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
let length = if msglen <= 0: (len(msg) * sizeof(T)) else: (msglen * sizeof(T))
|
let length = if msglen <= 0: (len(msg) * sizeof(T)) else: (msglen * sizeof(T))
|
||||||
let vector = GramVector(kind: WithoutAddress, buf: addr retFuture.gcholder[0],
|
var localCopy = msg
|
||||||
|
retFuture.addCallback(proc(_: pointer) = reset(localCopy))
|
||||||
|
|
||||||
|
let vector = GramVector(kind: WithoutAddress, buf: addr localCopy[0],
|
||||||
buflen: length,
|
buflen: length,
|
||||||
writer: cast[Future[void]](retFuture))
|
writer: retFuture)
|
||||||
transp.queue.addLast(vector)
|
transp.queue.addLast(vector)
|
||||||
if WritePaused in transp.state:
|
if WritePaused in transp.state:
|
||||||
let wres = transp.resumeWrite()
|
let wres = transp.resumeWrite()
|
||||||
|
@ -799,7 +931,8 @@ proc send*[T](transp: DatagramTransport, msg: sink seq[T],
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc sendTo*(transp: DatagramTransport, remote: TransportAddress,
|
proc sendTo*(transp: DatagramTransport, remote: TransportAddress,
|
||||||
pbytes: pointer, nbytes: int): Future[void] =
|
pbytes: pointer, nbytes: int): Future[void] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Send buffer with pointer ``pbytes`` and size ``nbytes`` using transport
|
## Send buffer with pointer ``pbytes`` and size ``nbytes`` using transport
|
||||||
## ``transp`` to remote destination address ``remote``.
|
## ``transp`` to remote destination address ``remote``.
|
||||||
var retFuture = newFuture[void]("datagram.transport.sendTo(pointer)")
|
var retFuture = newFuture[void]("datagram.transport.sendTo(pointer)")
|
||||||
|
@ -814,22 +947,20 @@ proc sendTo*(transp: DatagramTransport, remote: TransportAddress,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc sendTo*(transp: DatagramTransport, remote: TransportAddress,
|
proc sendTo*(transp: DatagramTransport, remote: TransportAddress,
|
||||||
msg: sink string, msglen = -1): Future[void] =
|
msg: sink string, msglen = -1): Future[void] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Send string ``msg`` using transport ``transp`` to remote destination
|
## Send string ``msg`` using transport ``transp`` to remote destination
|
||||||
## address ``remote``.
|
## address ``remote``.
|
||||||
var retFuture = newFutureStr[void]("datagram.transport.sendTo(string)")
|
var retFuture = newFuture[void]("datagram.transport.sendTo(string)")
|
||||||
transp.checkClosed(retFuture)
|
transp.checkClosed(retFuture)
|
||||||
when declared(shallowCopy):
|
|
||||||
if not(isLiteral(msg)):
|
|
||||||
shallowCopy(retFuture.gcholder, msg)
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
let length = if msglen <= 0: len(msg) else: msglen
|
let length = if msglen <= 0: len(msg) else: msglen
|
||||||
let vector = GramVector(kind: WithAddress, buf: addr retFuture.gcholder[0],
|
var localCopy = msg
|
||||||
|
retFuture.addCallback(proc(_: pointer) = reset(localCopy))
|
||||||
|
|
||||||
|
let vector = GramVector(kind: WithAddress, buf: addr localCopy[0],
|
||||||
buflen: length,
|
buflen: length,
|
||||||
writer: cast[Future[void]](retFuture),
|
writer: retFuture,
|
||||||
address: remote)
|
address: remote)
|
||||||
transp.queue.addLast(vector)
|
transp.queue.addLast(vector)
|
||||||
if WritePaused in transp.state:
|
if WritePaused in transp.state:
|
||||||
|
@ -839,20 +970,17 @@ proc sendTo*(transp: DatagramTransport, remote: TransportAddress,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc sendTo*[T](transp: DatagramTransport, remote: TransportAddress,
|
proc sendTo*[T](transp: DatagramTransport, remote: TransportAddress,
|
||||||
msg: sink seq[T], msglen = -1): Future[void] =
|
msg: sink seq[T], msglen = -1): Future[void] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Send sequence ``msg`` using transport ``transp`` to remote destination
|
## Send sequence ``msg`` using transport ``transp`` to remote destination
|
||||||
## address ``remote``.
|
## address ``remote``.
|
||||||
var retFuture = newFutureSeq[void, T]("datagram.transport.sendTo(seq)")
|
var retFuture = newFuture[void]("datagram.transport.sendTo(seq)")
|
||||||
transp.checkClosed(retFuture)
|
transp.checkClosed(retFuture)
|
||||||
when declared(shallowCopy):
|
|
||||||
if not(isLiteral(msg)):
|
|
||||||
shallowCopy(retFuture.gcholder, msg)
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg
|
|
||||||
let length = if msglen <= 0: (len(msg) * sizeof(T)) else: (msglen * sizeof(T))
|
let length = if msglen <= 0: (len(msg) * sizeof(T)) else: (msglen * sizeof(T))
|
||||||
let vector = GramVector(kind: WithAddress, buf: addr retFuture.gcholder[0],
|
var localCopy = msg
|
||||||
|
retFuture.addCallback(proc(_: pointer) = reset(localCopy))
|
||||||
|
|
||||||
|
let vector = GramVector(kind: WithAddress, buf: addr localCopy[0],
|
||||||
buflen: length,
|
buflen: length,
|
||||||
writer: cast[Future[void]](retFuture),
|
writer: cast[Future[void]](retFuture),
|
||||||
address: remote)
|
address: remote)
|
||||||
|
@ -864,7 +992,7 @@ proc sendTo*[T](transp: DatagramTransport, remote: TransportAddress,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc peekMessage*(transp: DatagramTransport, msg: var seq[byte],
|
proc peekMessage*(transp: DatagramTransport, msg: var seq[byte],
|
||||||
msglen: var int) {.raises: [CatchableError].} =
|
msglen: var int) {.raises: [TransportError].} =
|
||||||
## Get access to internal message buffer and length of incoming datagram.
|
## Get access to internal message buffer and length of incoming datagram.
|
||||||
if ReadError in transp.state:
|
if ReadError in transp.state:
|
||||||
transp.state.excl(ReadError)
|
transp.state.excl(ReadError)
|
||||||
|
@ -876,7 +1004,7 @@ proc peekMessage*(transp: DatagramTransport, msg: var seq[byte],
|
||||||
msglen = transp.buflen
|
msglen = transp.buflen
|
||||||
|
|
||||||
proc getMessage*(transp: DatagramTransport): seq[byte] {.
|
proc getMessage*(transp: DatagramTransport): seq[byte] {.
|
||||||
raises: [CatchableError].} =
|
raises: [TransportError].} =
|
||||||
## Copy data from internal message buffer and return result.
|
## Copy data from internal message buffer and return result.
|
||||||
var default: seq[byte]
|
var default: seq[byte]
|
||||||
if ReadError in transp.state:
|
if ReadError in transp.state:
|
||||||
|
|
|
@ -58,6 +58,8 @@ type
|
||||||
done: bool] {.
|
done: bool] {.
|
||||||
gcsafe, raises: [].}
|
gcsafe, raises: [].}
|
||||||
|
|
||||||
|
ReaderFuture = Future[void].Raising([TransportError, CancelledError])
|
||||||
|
|
||||||
const
|
const
|
||||||
StreamTransportTrackerName* = "stream.transport"
|
StreamTransportTrackerName* = "stream.transport"
|
||||||
StreamServerTrackerName* = "stream.server"
|
StreamServerTrackerName* = "stream.server"
|
||||||
|
@ -68,10 +70,10 @@ when defined(windows):
|
||||||
StreamTransport* = ref object of RootRef
|
StreamTransport* = ref object of RootRef
|
||||||
fd*: AsyncFD # File descriptor
|
fd*: AsyncFD # File descriptor
|
||||||
state: set[TransportState] # Current Transport state
|
state: set[TransportState] # Current Transport state
|
||||||
reader: Future[void] # Current reader Future
|
reader: ReaderFuture # Current reader Future
|
||||||
buffer: seq[byte] # Reading buffer
|
buffer: seq[byte] # Reading buffer
|
||||||
offset: int # Reading buffer offset
|
offset: int # Reading buffer offset
|
||||||
error: ref CatchableError # Current error
|
error: ref TransportError # Current error
|
||||||
queue: Deque[StreamVector] # Writer queue
|
queue: Deque[StreamVector] # Writer queue
|
||||||
future: Future[void] # Stream life future
|
future: Future[void] # Stream life future
|
||||||
# Windows specific part
|
# Windows specific part
|
||||||
|
@ -87,18 +89,18 @@ when defined(windows):
|
||||||
local: TransportAddress # Local address
|
local: TransportAddress # Local address
|
||||||
remote: TransportAddress # Remote address
|
remote: TransportAddress # Remote address
|
||||||
of TransportKind.Pipe:
|
of TransportKind.Pipe:
|
||||||
todo1: int
|
discard
|
||||||
of TransportKind.File:
|
of TransportKind.File:
|
||||||
todo2: int
|
discard
|
||||||
else:
|
else:
|
||||||
type
|
type
|
||||||
StreamTransport* = ref object of RootRef
|
StreamTransport* = ref object of RootRef
|
||||||
fd*: AsyncFD # File descriptor
|
fd*: AsyncFD # File descriptor
|
||||||
state: set[TransportState] # Current Transport state
|
state: set[TransportState] # Current Transport state
|
||||||
reader: Future[void] # Current reader Future
|
reader: ReaderFuture # Current reader Future
|
||||||
buffer: seq[byte] # Reading buffer
|
buffer: seq[byte] # Reading buffer
|
||||||
offset: int # Reading buffer offset
|
offset: int # Reading buffer offset
|
||||||
error: ref CatchableError # Current error
|
error: ref TransportError # Current error
|
||||||
queue: Deque[StreamVector] # Writer queue
|
queue: Deque[StreamVector] # Writer queue
|
||||||
future: Future[void] # Stream life future
|
future: Future[void] # Stream life future
|
||||||
case kind*: TransportKind
|
case kind*: TransportKind
|
||||||
|
@ -107,18 +109,23 @@ else:
|
||||||
local: TransportAddress # Local address
|
local: TransportAddress # Local address
|
||||||
remote: TransportAddress # Remote address
|
remote: TransportAddress # Remote address
|
||||||
of TransportKind.Pipe:
|
of TransportKind.Pipe:
|
||||||
todo1: int
|
discard
|
||||||
of TransportKind.File:
|
of TransportKind.File:
|
||||||
todo2: int
|
discard
|
||||||
|
|
||||||
type
|
type
|
||||||
StreamCallback* = proc(server: StreamServer,
|
StreamCallback* = proc(server: StreamServer,
|
||||||
client: StreamTransport): Future[void] {.
|
client: StreamTransport) {.async: (raises: []).}
|
||||||
gcsafe, raises: [].}
|
|
||||||
## New remote client connection callback
|
## New remote client connection callback
|
||||||
## ``server`` - StreamServer object.
|
## ``server`` - StreamServer object.
|
||||||
## ``client`` - accepted client transport.
|
## ``client`` - accepted client transport.
|
||||||
|
|
||||||
|
UnsafeStreamCallback* = proc(server: StreamServer,
|
||||||
|
client: StreamTransport) {.async.}
|
||||||
|
## Connection callback that doesn't check for exceptions at compile time
|
||||||
|
## ``server`` - StreamServer object.
|
||||||
|
## ``client`` - accepted client transport.
|
||||||
|
|
||||||
TransportInitCallback* = proc(server: StreamServer,
|
TransportInitCallback* = proc(server: StreamServer,
|
||||||
fd: AsyncFD): StreamTransport {.
|
fd: AsyncFD): StreamTransport {.
|
||||||
gcsafe, raises: [].}
|
gcsafe, raises: [].}
|
||||||
|
@ -199,7 +206,7 @@ proc completePendingWriteQueue(queue: var Deque[StreamVector],
|
||||||
vector.writer.complete(v)
|
vector.writer.complete(v)
|
||||||
|
|
||||||
proc failPendingWriteQueue(queue: var Deque[StreamVector],
|
proc failPendingWriteQueue(queue: var Deque[StreamVector],
|
||||||
error: ref CatchableError) {.inline.} =
|
error: ref TransportError) {.inline.} =
|
||||||
while len(queue) > 0:
|
while len(queue) > 0:
|
||||||
var vector = queue.popFirst()
|
var vector = queue.popFirst()
|
||||||
if not(vector.writer.finished()):
|
if not(vector.writer.finished()):
|
||||||
|
@ -640,7 +647,8 @@ when defined(windows):
|
||||||
localAddress = TransportAddress(),
|
localAddress = TransportAddress(),
|
||||||
flags: set[SocketFlags] = {},
|
flags: set[SocketFlags] = {},
|
||||||
dualstack = DualStackType.Auto
|
dualstack = DualStackType.Auto
|
||||||
): Future[StreamTransport] =
|
): Future[StreamTransport] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Open new connection to remote peer with address ``address`` and create
|
## Open new connection to remote peer with address ``address`` and create
|
||||||
## new transport object ``StreamTransport`` for established connection.
|
## new transport object ``StreamTransport`` for established connection.
|
||||||
## ``bufferSize`` is size of internal buffer for transport.
|
## ``bufferSize`` is size of internal buffer for transport.
|
||||||
|
@ -1031,7 +1039,8 @@ when defined(windows):
|
||||||
server.aovl.data.cb(addr server.aovl)
|
server.aovl.data.cb(addr server.aovl)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc accept*(server: StreamServer): Future[StreamTransport] =
|
proc accept*(server: StreamServer): Future[StreamTransport] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
var retFuture = newFuture[StreamTransport]("stream.server.accept")
|
var retFuture = newFuture[StreamTransport]("stream.server.accept")
|
||||||
|
|
||||||
doAssert(server.status != ServerStatus.Running,
|
doAssert(server.status != ServerStatus.Running,
|
||||||
|
@ -1472,7 +1481,8 @@ else:
|
||||||
localAddress = TransportAddress(),
|
localAddress = TransportAddress(),
|
||||||
flags: set[SocketFlags] = {},
|
flags: set[SocketFlags] = {},
|
||||||
dualstack = DualStackType.Auto,
|
dualstack = DualStackType.Auto,
|
||||||
): Future[StreamTransport] =
|
): Future[StreamTransport] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Open new connection to remote peer with address ``address`` and create
|
## Open new connection to remote peer with address ``address`` and create
|
||||||
## new transport object ``StreamTransport`` for established connection.
|
## new transport object ``StreamTransport`` for established connection.
|
||||||
## ``bufferSize`` - size of internal buffer for transport.
|
## ``bufferSize`` - size of internal buffer for transport.
|
||||||
|
@ -1658,7 +1668,8 @@ else:
|
||||||
transp.state.excl(WritePaused)
|
transp.state.excl(WritePaused)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc accept*(server: StreamServer): Future[StreamTransport] =
|
proc accept*(server: StreamServer): Future[StreamTransport] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
var retFuture = newFuture[StreamTransport]("stream.server.accept")
|
var retFuture = newFuture[StreamTransport]("stream.server.accept")
|
||||||
|
|
||||||
doAssert(server.status != ServerStatus.Running,
|
doAssert(server.status != ServerStatus.Running,
|
||||||
|
@ -1762,7 +1773,8 @@ proc stop*(server: StreamServer) {.raises: [TransportOsError].} =
|
||||||
let res = stop2(server)
|
let res = stop2(server)
|
||||||
if res.isErr(): raiseTransportOsError(res.error())
|
if res.isErr(): raiseTransportOsError(res.error())
|
||||||
|
|
||||||
proc join*(server: StreamServer): Future[void] =
|
proc join*(server: StreamServer): Future[void] {.
|
||||||
|
async: (raw: true, raises: [CancelledError]).} =
|
||||||
## Waits until ``server`` is not closed.
|
## Waits until ``server`` is not closed.
|
||||||
var retFuture = newFuture[void]("stream.transport.server.join")
|
var retFuture = newFuture[void]("stream.transport.server.join")
|
||||||
|
|
||||||
|
@ -1785,7 +1797,8 @@ proc connect*(address: TransportAddress,
|
||||||
flags: set[TransportFlags],
|
flags: set[TransportFlags],
|
||||||
localAddress = TransportAddress(),
|
localAddress = TransportAddress(),
|
||||||
dualstack = DualStackType.Auto
|
dualstack = DualStackType.Auto
|
||||||
): Future[StreamTransport] =
|
): Future[StreamTransport] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
# Retro compatibility with TransportFlags
|
# Retro compatibility with TransportFlags
|
||||||
var mappedFlags: set[SocketFlags]
|
var mappedFlags: set[SocketFlags]
|
||||||
if TcpNoDelay in flags: mappedFlags.incl(SocketFlags.TcpNoDelay)
|
if TcpNoDelay in flags: mappedFlags.incl(SocketFlags.TcpNoDelay)
|
||||||
|
@ -1817,7 +1830,8 @@ proc close*(server: StreamServer) =
|
||||||
else:
|
else:
|
||||||
server.sock.closeSocket(continuation)
|
server.sock.closeSocket(continuation)
|
||||||
|
|
||||||
proc closeWait*(server: StreamServer): Future[void] =
|
proc closeWait*(server: StreamServer): Future[void] {.
|
||||||
|
async: (raw: true, raises: [CancelledError]).} =
|
||||||
## Close server ``server`` and release all resources.
|
## Close server ``server`` and release all resources.
|
||||||
server.close()
|
server.close()
|
||||||
server.join()
|
server.join()
|
||||||
|
@ -2066,6 +2080,7 @@ proc createStreamServer*(host: TransportAddress,
|
||||||
sres
|
sres
|
||||||
|
|
||||||
proc createStreamServer*(host: TransportAddress,
|
proc createStreamServer*(host: TransportAddress,
|
||||||
|
cbproc: UnsafeStreamCallback,
|
||||||
flags: set[ServerFlags] = {},
|
flags: set[ServerFlags] = {},
|
||||||
sock: AsyncFD = asyncInvalidSocket,
|
sock: AsyncFD = asyncInvalidSocket,
|
||||||
backlog: int = DefaultBacklogSize,
|
backlog: int = DefaultBacklogSize,
|
||||||
|
@ -2074,8 +2089,30 @@ proc createStreamServer*(host: TransportAddress,
|
||||||
init: TransportInitCallback = nil,
|
init: TransportInitCallback = nil,
|
||||||
udata: pointer = nil,
|
udata: pointer = nil,
|
||||||
dualstack = DualStackType.Auto): StreamServer {.
|
dualstack = DualStackType.Auto): StreamServer {.
|
||||||
raises: [CatchableError].} =
|
raises: [TransportOsError],
|
||||||
createStreamServer(host, nil, flags, sock, backlog, bufferSize,
|
deprecated: "Callback must not raise exceptions, annotate with {.async: (raises: []).}".} =
|
||||||
|
proc wrap(server: StreamServer,
|
||||||
|
client: StreamTransport) {.async: (raises: []).} =
|
||||||
|
try:
|
||||||
|
cbproc(server, client)
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert "Unexpected exception from stream server cbproc: " & exc.msg
|
||||||
|
|
||||||
|
createStreamServer(
|
||||||
|
host, wrap, flags, sock, backlog, bufferSize, child, init, udata,
|
||||||
|
dualstack)
|
||||||
|
|
||||||
|
proc createStreamServer*(host: TransportAddress,
|
||||||
|
flags: set[ServerFlags] = {},
|
||||||
|
sock: AsyncFD = asyncInvalidSocket,
|
||||||
|
backlog: int = DefaultBacklogSize,
|
||||||
|
bufferSize: int = DefaultStreamBufferSize,
|
||||||
|
child: StreamServer = nil,
|
||||||
|
init: TransportInitCallback = nil,
|
||||||
|
udata: pointer = nil,
|
||||||
|
dualstack = DualStackType.Auto): StreamServer {.
|
||||||
|
raises: [TransportOsError].} =
|
||||||
|
createStreamServer(host, StreamCallback(nil), flags, sock, backlog, bufferSize,
|
||||||
child, init, cast[pointer](udata), dualstack)
|
child, init, cast[pointer](udata), dualstack)
|
||||||
|
|
||||||
proc createStreamServer*[T](host: TransportAddress,
|
proc createStreamServer*[T](host: TransportAddress,
|
||||||
|
@ -2088,7 +2125,24 @@ proc createStreamServer*[T](host: TransportAddress,
|
||||||
child: StreamServer = nil,
|
child: StreamServer = nil,
|
||||||
init: TransportInitCallback = nil,
|
init: TransportInitCallback = nil,
|
||||||
dualstack = DualStackType.Auto): StreamServer {.
|
dualstack = DualStackType.Auto): StreamServer {.
|
||||||
raises: [CatchableError].} =
|
raises: [TransportOsError].} =
|
||||||
|
var fflags = flags + {GCUserData}
|
||||||
|
GC_ref(udata)
|
||||||
|
createStreamServer(host, cbproc, fflags, sock, backlog, bufferSize,
|
||||||
|
child, init, cast[pointer](udata), dualstack)
|
||||||
|
|
||||||
|
proc createStreamServer*[T](host: TransportAddress,
|
||||||
|
cbproc: UnsafeStreamCallback,
|
||||||
|
flags: set[ServerFlags] = {},
|
||||||
|
udata: ref T,
|
||||||
|
sock: AsyncFD = asyncInvalidSocket,
|
||||||
|
backlog: int = DefaultBacklogSize,
|
||||||
|
bufferSize: int = DefaultStreamBufferSize,
|
||||||
|
child: StreamServer = nil,
|
||||||
|
init: TransportInitCallback = nil,
|
||||||
|
dualstack = DualStackType.Auto): StreamServer {.
|
||||||
|
raises: [TransportOsError],
|
||||||
|
deprecated: "Callback must not raise exceptions, annotate with {.async: (raises: []).}".} =
|
||||||
var fflags = flags + {GCUserData}
|
var fflags = flags + {GCUserData}
|
||||||
GC_ref(udata)
|
GC_ref(udata)
|
||||||
createStreamServer(host, cbproc, fflags, sock, backlog, bufferSize,
|
createStreamServer(host, cbproc, fflags, sock, backlog, bufferSize,
|
||||||
|
@ -2103,10 +2157,10 @@ proc createStreamServer*[T](host: TransportAddress,
|
||||||
child: StreamServer = nil,
|
child: StreamServer = nil,
|
||||||
init: TransportInitCallback = nil,
|
init: TransportInitCallback = nil,
|
||||||
dualstack = DualStackType.Auto): StreamServer {.
|
dualstack = DualStackType.Auto): StreamServer {.
|
||||||
raises: [CatchableError].} =
|
raises: [TransportOsError].} =
|
||||||
var fflags = flags + {GCUserData}
|
var fflags = flags + {GCUserData}
|
||||||
GC_ref(udata)
|
GC_ref(udata)
|
||||||
createStreamServer(host, nil, fflags, sock, backlog, bufferSize,
|
createStreamServer(host, StreamCallback(nil), fflags, sock, backlog, bufferSize,
|
||||||
child, init, cast[pointer](udata), dualstack)
|
child, init, cast[pointer](udata), dualstack)
|
||||||
|
|
||||||
proc getUserData*[T](server: StreamServer): T {.inline.} =
|
proc getUserData*[T](server: StreamServer): T {.inline.} =
|
||||||
|
@ -2157,7 +2211,8 @@ template fastWrite(transp: auto, pbytes: var ptr byte, rbytes: var int,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc write*(transp: StreamTransport, pbytes: pointer,
|
proc write*(transp: StreamTransport, pbytes: pointer,
|
||||||
nbytes: int): Future[int] =
|
nbytes: int): Future[int] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Write data from buffer ``pbytes`` with size ``nbytes`` using transport
|
## Write data from buffer ``pbytes`` with size ``nbytes`` using transport
|
||||||
## ``transp``.
|
## ``transp``.
|
||||||
var retFuture = newFuture[int]("stream.transport.write(pointer)")
|
var retFuture = newFuture[int]("stream.transport.write(pointer)")
|
||||||
|
@ -2179,9 +2234,10 @@ proc write*(transp: StreamTransport, pbytes: pointer,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc write*(transp: StreamTransport, msg: sink string,
|
proc write*(transp: StreamTransport, msg: sink string,
|
||||||
msglen = -1): Future[int] =
|
msglen = -1): Future[int] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Write data from string ``msg`` using transport ``transp``.
|
## Write data from string ``msg`` using transport ``transp``.
|
||||||
var retFuture = newFutureStr[int]("stream.transport.write(string)")
|
var retFuture = newFuture[int]("stream.transport.write(string)")
|
||||||
transp.checkClosed(retFuture)
|
transp.checkClosed(retFuture)
|
||||||
transp.checkWriteEof(retFuture)
|
transp.checkWriteEof(retFuture)
|
||||||
|
|
||||||
|
@ -2197,17 +2253,10 @@ proc write*(transp: StreamTransport, msg: sink string,
|
||||||
let
|
let
|
||||||
written = nbytes - rbytes # In case fastWrite wrote some
|
written = nbytes - rbytes # In case fastWrite wrote some
|
||||||
|
|
||||||
pbytes =
|
var localCopy = msg
|
||||||
when declared(shallowCopy):
|
retFuture.addCallback(proc(_: pointer) = reset(localCopy))
|
||||||
if not(isLiteral(msg)):
|
|
||||||
shallowCopy(retFuture.gcholder, msg)
|
pbytes = cast[ptr byte](addr localCopy[written])
|
||||||
cast[ptr byte](addr retFuture.gcholder[written])
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg[written ..< nbytes]
|
|
||||||
cast[ptr byte](addr retFuture.gcholder[0])
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg[written ..< nbytes]
|
|
||||||
cast[ptr byte](addr retFuture.gcholder[0])
|
|
||||||
|
|
||||||
var vector = StreamVector(kind: DataBuffer, writer: retFuture,
|
var vector = StreamVector(kind: DataBuffer, writer: retFuture,
|
||||||
buf: pbytes, buflen: rbytes, size: nbytes)
|
buf: pbytes, buflen: rbytes, size: nbytes)
|
||||||
|
@ -2218,9 +2267,10 @@ proc write*(transp: StreamTransport, msg: sink string,
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc write*[T](transp: StreamTransport, msg: sink seq[T],
|
proc write*[T](transp: StreamTransport, msg: sink seq[T],
|
||||||
msglen = -1): Future[int] =
|
msglen = -1): Future[int] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Write sequence ``msg`` using transport ``transp``.
|
## Write sequence ``msg`` using transport ``transp``.
|
||||||
var retFuture = newFutureSeq[int, T]("stream.transport.write(seq)")
|
var retFuture = newFuture[int]("stream.transport.write(seq)")
|
||||||
transp.checkClosed(retFuture)
|
transp.checkClosed(retFuture)
|
||||||
transp.checkWriteEof(retFuture)
|
transp.checkWriteEof(retFuture)
|
||||||
|
|
||||||
|
@ -2236,17 +2286,10 @@ proc write*[T](transp: StreamTransport, msg: sink seq[T],
|
||||||
let
|
let
|
||||||
written = nbytes - rbytes # In case fastWrite wrote some
|
written = nbytes - rbytes # In case fastWrite wrote some
|
||||||
|
|
||||||
pbytes =
|
var localCopy = msg
|
||||||
when declared(shallowCopy):
|
retFuture.addCallback(proc(_: pointer) = reset(localCopy))
|
||||||
if not(isLiteral(msg)):
|
|
||||||
shallowCopy(retFuture.gcholder, msg)
|
pbytes = cast[ptr byte](addr localCopy[written])
|
||||||
cast[ptr byte](addr retFuture.gcholder[written])
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg[written ..< nbytes]
|
|
||||||
cast[ptr byte](addr retFuture.gcholder[0])
|
|
||||||
else:
|
|
||||||
retFuture.gcholder = msg[written ..< nbytes]
|
|
||||||
cast[ptr byte](addr retFuture.gcholder[0])
|
|
||||||
|
|
||||||
var vector = StreamVector(kind: DataBuffer, writer: retFuture,
|
var vector = StreamVector(kind: DataBuffer, writer: retFuture,
|
||||||
buf: pbytes, buflen: rbytes, size: nbytes)
|
buf: pbytes, buflen: rbytes, size: nbytes)
|
||||||
|
@ -2257,7 +2300,8 @@ proc write*[T](transp: StreamTransport, msg: sink seq[T],
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
proc writeFile*(transp: StreamTransport, handle: int,
|
proc writeFile*(transp: StreamTransport, handle: int,
|
||||||
offset: uint = 0, size: int = 0): Future[int] =
|
offset: uint = 0, size: int = 0): Future[int] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Write data from file descriptor ``handle`` to transport ``transp``.
|
## Write data from file descriptor ``handle`` to transport ``transp``.
|
||||||
##
|
##
|
||||||
## You can specify starting ``offset`` in opened file and number of bytes
|
## You can specify starting ``offset`` in opened file and number of bytes
|
||||||
|
@ -2304,7 +2348,7 @@ template readLoop(name, body: untyped): untyped =
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
checkPending(transp)
|
checkPending(transp)
|
||||||
var fut = newFuture[void](name)
|
let fut = ReaderFuture.init(name)
|
||||||
transp.reader = fut
|
transp.reader = fut
|
||||||
let res = resumeRead(transp)
|
let res = resumeRead(transp)
|
||||||
if res.isErr():
|
if res.isErr():
|
||||||
|
@ -2328,7 +2372,8 @@ template readLoop(name, body: untyped): untyped =
|
||||||
await fut
|
await fut
|
||||||
|
|
||||||
proc readExactly*(transp: StreamTransport, pbytes: pointer,
|
proc readExactly*(transp: StreamTransport, pbytes: pointer,
|
||||||
nbytes: int) {.async.} =
|
nbytes: int) {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Read exactly ``nbytes`` bytes from transport ``transp`` and store it to
|
## Read exactly ``nbytes`` bytes from transport ``transp`` and store it to
|
||||||
## ``pbytes``. ``pbytes`` must not be ``nil`` pointer and ``nbytes`` should
|
## ``pbytes``. ``pbytes`` must not be ``nil`` pointer and ``nbytes`` should
|
||||||
## be Natural.
|
## be Natural.
|
||||||
|
@ -2357,7 +2402,8 @@ proc readExactly*(transp: StreamTransport, pbytes: pointer,
|
||||||
(consumed: count, done: index == nbytes)
|
(consumed: count, done: index == nbytes)
|
||||||
|
|
||||||
proc readOnce*(transp: StreamTransport, pbytes: pointer,
|
proc readOnce*(transp: StreamTransport, pbytes: pointer,
|
||||||
nbytes: int): Future[int] {.async.} =
|
nbytes: int): Future[int] {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Perform one read operation on transport ``transp``.
|
## Perform one read operation on transport ``transp``.
|
||||||
##
|
##
|
||||||
## If internal buffer is not empty, ``nbytes`` bytes will be transferred from
|
## If internal buffer is not empty, ``nbytes`` bytes will be transferred from
|
||||||
|
@ -2376,7 +2422,8 @@ proc readOnce*(transp: StreamTransport, pbytes: pointer,
|
||||||
return count
|
return count
|
||||||
|
|
||||||
proc readUntil*(transp: StreamTransport, pbytes: pointer, nbytes: int,
|
proc readUntil*(transp: StreamTransport, pbytes: pointer, nbytes: int,
|
||||||
sep: seq[byte]): Future[int] {.async.} =
|
sep: seq[byte]): Future[int] {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Read data from the transport ``transp`` until separator ``sep`` is found.
|
## Read data from the transport ``transp`` until separator ``sep`` is found.
|
||||||
##
|
##
|
||||||
## On success, the data and separator will be removed from the internal
|
## On success, the data and separator will be removed from the internal
|
||||||
|
@ -2428,7 +2475,8 @@ proc readUntil*(transp: StreamTransport, pbytes: pointer, nbytes: int,
|
||||||
return k
|
return k
|
||||||
|
|
||||||
proc readLine*(transp: StreamTransport, limit = 0,
|
proc readLine*(transp: StreamTransport, limit = 0,
|
||||||
sep = "\r\n"): Future[string] {.async.} =
|
sep = "\r\n"): Future[string] {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Read one line from transport ``transp``, where "line" is a sequence of
|
## Read one line from transport ``transp``, where "line" is a sequence of
|
||||||
## bytes ending with ``sep`` (default is "\r\n").
|
## bytes ending with ``sep`` (default is "\r\n").
|
||||||
##
|
##
|
||||||
|
@ -2470,7 +2518,8 @@ proc readLine*(transp: StreamTransport, limit = 0,
|
||||||
|
|
||||||
(index, (state == len(sep)) or (lim == len(result)))
|
(index, (state == len(sep)) or (lim == len(result)))
|
||||||
|
|
||||||
proc read*(transp: StreamTransport): Future[seq[byte]] {.async.} =
|
proc read*(transp: StreamTransport): Future[seq[byte]] {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Read all bytes from transport ``transp``.
|
## Read all bytes from transport ``transp``.
|
||||||
##
|
##
|
||||||
## This procedure allocates buffer seq[byte] and return it as result.
|
## This procedure allocates buffer seq[byte] and return it as result.
|
||||||
|
@ -2481,7 +2530,8 @@ proc read*(transp: StreamTransport): Future[seq[byte]] {.async.} =
|
||||||
result.add(transp.buffer.toOpenArray(0, transp.offset - 1))
|
result.add(transp.buffer.toOpenArray(0, transp.offset - 1))
|
||||||
(transp.offset, false)
|
(transp.offset, false)
|
||||||
|
|
||||||
proc read*(transp: StreamTransport, n: int): Future[seq[byte]] {.async.} =
|
proc read*(transp: StreamTransport, n: int): Future[seq[byte]] {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Read all bytes (n <= 0) or exactly `n` bytes from transport ``transp``.
|
## Read all bytes (n <= 0) or exactly `n` bytes from transport ``transp``.
|
||||||
##
|
##
|
||||||
## This procedure allocates buffer seq[byte] and return it as result.
|
## This procedure allocates buffer seq[byte] and return it as result.
|
||||||
|
@ -2496,7 +2546,8 @@ proc read*(transp: StreamTransport, n: int): Future[seq[byte]] {.async.} =
|
||||||
result.add(transp.buffer.toOpenArray(0, count - 1))
|
result.add(transp.buffer.toOpenArray(0, count - 1))
|
||||||
(count, len(result) == n)
|
(count, len(result) == n)
|
||||||
|
|
||||||
proc consume*(transp: StreamTransport): Future[int] {.async.} =
|
proc consume*(transp: StreamTransport): Future[int] {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Consume all bytes from transport ``transp`` and discard it.
|
## Consume all bytes from transport ``transp`` and discard it.
|
||||||
##
|
##
|
||||||
## Return number of bytes actually consumed and discarded.
|
## Return number of bytes actually consumed and discarded.
|
||||||
|
@ -2507,7 +2558,8 @@ proc consume*(transp: StreamTransport): Future[int] {.async.} =
|
||||||
result += transp.offset
|
result += transp.offset
|
||||||
(transp.offset, false)
|
(transp.offset, false)
|
||||||
|
|
||||||
proc consume*(transp: StreamTransport, n: int): Future[int] {.async.} =
|
proc consume*(transp: StreamTransport, n: int): Future[int] {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Consume all bytes (n <= 0) or ``n`` bytes from transport ``transp`` and
|
## Consume all bytes (n <= 0) or ``n`` bytes from transport ``transp`` and
|
||||||
## discard it.
|
## discard it.
|
||||||
##
|
##
|
||||||
|
@ -2524,7 +2576,8 @@ proc consume*(transp: StreamTransport, n: int): Future[int] {.async.} =
|
||||||
(count, result == n)
|
(count, result == n)
|
||||||
|
|
||||||
proc readMessage*(transp: StreamTransport,
|
proc readMessage*(transp: StreamTransport,
|
||||||
predicate: ReadMessagePredicate) {.async.} =
|
predicate: ReadMessagePredicate) {.
|
||||||
|
async: (raises: [TransportError, CancelledError]).} =
|
||||||
## Read all bytes from transport ``transp`` until ``predicate`` callback
|
## Read all bytes from transport ``transp`` until ``predicate`` callback
|
||||||
## will not be satisfied.
|
## will not be satisfied.
|
||||||
##
|
##
|
||||||
|
@ -2547,7 +2600,8 @@ proc readMessage*(transp: StreamTransport,
|
||||||
else:
|
else:
|
||||||
predicate(transp.buffer.toOpenArray(0, transp.offset - 1))
|
predicate(transp.buffer.toOpenArray(0, transp.offset - 1))
|
||||||
|
|
||||||
proc join*(transp: StreamTransport): Future[void] =
|
proc join*(transp: StreamTransport): Future[void] {.
|
||||||
|
async: (raw: true, raises: [CancelledError]).} =
|
||||||
## Wait until ``transp`` will not be closed.
|
## Wait until ``transp`` will not be closed.
|
||||||
var retFuture = newFuture[void]("stream.transport.join")
|
var retFuture = newFuture[void]("stream.transport.join")
|
||||||
|
|
||||||
|
@ -2606,14 +2660,15 @@ proc close*(transp: StreamTransport) =
|
||||||
elif transp.kind == TransportKind.Socket:
|
elif transp.kind == TransportKind.Socket:
|
||||||
closeSocket(transp.fd, continuation)
|
closeSocket(transp.fd, continuation)
|
||||||
|
|
||||||
proc closeWait*(transp: StreamTransport): Future[void] =
|
proc closeWait*(transp: StreamTransport): Future[void] {.
|
||||||
|
async: (raw: true, raises: []).} =
|
||||||
## Close and frees resources of transport ``transp``.
|
## Close and frees resources of transport ``transp``.
|
||||||
const FutureName = "stream.transport.closeWait"
|
let retFuture = newFuture[void](
|
||||||
|
"stream.transport.closeWait", {FutureFlag.OwnCancelSchedule})
|
||||||
|
|
||||||
if {ReadClosed, WriteClosed} * transp.state != {}:
|
if {ReadClosed, WriteClosed} * transp.state != {}:
|
||||||
return Future.completed(FutureName)
|
retFuture.complete()
|
||||||
|
return retFuture
|
||||||
let retFuture = newFuture[void](FutureName, {FutureFlag.OwnCancelSchedule})
|
|
||||||
|
|
||||||
proc continuation(udata: pointer) {.gcsafe.} =
|
proc continuation(udata: pointer) {.gcsafe.} =
|
||||||
retFuture.complete()
|
retFuture.complete()
|
||||||
|
@ -2631,7 +2686,8 @@ proc closeWait*(transp: StreamTransport): Future[void] =
|
||||||
retFuture.cancelCallback = cancellation
|
retFuture.cancelCallback = cancellation
|
||||||
retFuture
|
retFuture
|
||||||
|
|
||||||
proc shutdownWait*(transp: StreamTransport): Future[void] =
|
proc shutdownWait*(transp: StreamTransport): Future[void] {.
|
||||||
|
async: (raw: true, raises: [TransportError, CancelledError]).} =
|
||||||
## Perform graceful shutdown of TCP connection backed by transport ``transp``.
|
## Perform graceful shutdown of TCP connection backed by transport ``transp``.
|
||||||
doAssert(transp.kind == TransportKind.Socket)
|
doAssert(transp.kind == TransportKind.Socket)
|
||||||
let retFuture = newFuture[void]("stream.transport.shutdown")
|
let retFuture = newFuture[void]("stream.transport.shutdown")
|
||||||
|
|
|
@ -87,14 +87,17 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(StreamTransport) readExactly() test":
|
test "AsyncStream(StreamTransport) readExactly() test":
|
||||||
proc testReadExactly(): Future[bool] {.async.} =
|
proc testReadExactly(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
await wstream.write("000000000011111111112222222222")
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.finish()
|
await wstream.write("000000000011111111112222222222")
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var buffer = newSeq[byte](10)
|
var buffer = newSeq[byte](10)
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
|
@ -117,14 +120,17 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(StreamTransport) readUntil() test":
|
test "AsyncStream(StreamTransport) readUntil() test":
|
||||||
proc testReadUntil(): Future[bool] {.async.} =
|
proc testReadUntil(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
await wstream.write("0000000000NNz1111111111NNz2222222222NNz")
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.finish()
|
await wstream.write("0000000000NNz1111111111NNz2222222222NNz")
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var buffer = newSeq[byte](13)
|
var buffer = newSeq[byte](13)
|
||||||
var sep = @[byte('N'), byte('N'), byte('z')]
|
var sep = @[byte('N'), byte('N'), byte('z')]
|
||||||
|
@ -155,14 +161,17 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(StreamTransport) readLine() test":
|
test "AsyncStream(StreamTransport) readLine() test":
|
||||||
proc testReadLine(): Future[bool] {.async.} =
|
proc testReadLine(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
await wstream.write("0000000000\r\n1111111111\r\n2222222222\r\n")
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.finish()
|
await wstream.write("0000000000\r\n1111111111\r\n2222222222\r\n")
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -184,14 +193,17 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(StreamTransport) read() test":
|
test "AsyncStream(StreamTransport) read() test":
|
||||||
proc testRead(): Future[bool] {.async.} =
|
proc testRead(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
await wstream.write("000000000011111111112222222222")
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.finish()
|
await wstream.write("000000000011111111112222222222")
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -211,14 +223,17 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(StreamTransport) consume() test":
|
test "AsyncStream(StreamTransport) consume() test":
|
||||||
proc testConsume(): Future[bool] {.async.} =
|
proc testConsume(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
await wstream.write("0000000000111111111122222222223333333333")
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.finish()
|
await wstream.write("0000000000111111111122222222223333333333")
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -247,26 +262,29 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(AsyncStream) readExactly() test":
|
test "AsyncStream(AsyncStream) readExactly() test":
|
||||||
proc testReadExactly2(): Future[bool] {.async.} =
|
proc testReadExactly2(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newChunkedStreamWriter(wstream)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
var s1 = "00000"
|
var wstream2 = newChunkedStreamWriter(wstream)
|
||||||
var s2 = "11111"
|
var s1 = "00000"
|
||||||
var s3 = "22222"
|
var s2 = "11111"
|
||||||
await wstream2.write("00000")
|
var s3 = "22222"
|
||||||
await wstream2.write(addr s1[0], len(s1))
|
await wstream2.write("00000")
|
||||||
await wstream2.write("11111")
|
await wstream2.write(addr s1[0], len(s1))
|
||||||
await wstream2.write(s2.toBytes())
|
await wstream2.write("11111")
|
||||||
await wstream2.write("22222")
|
await wstream2.write(s2.toBytes())
|
||||||
await wstream2.write(addr s3[0], len(s3))
|
await wstream2.write("22222")
|
||||||
|
await wstream2.write(addr s3[0], len(s3))
|
||||||
|
|
||||||
await wstream2.finish()
|
await wstream2.finish()
|
||||||
await wstream.finish()
|
await wstream.finish()
|
||||||
await wstream2.closeWait()
|
await wstream2.closeWait()
|
||||||
await wstream.closeWait()
|
await wstream.closeWait()
|
||||||
await transp.closeWait()
|
await transp.closeWait()
|
||||||
server.stop()
|
server.stop()
|
||||||
server.close()
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var buffer = newSeq[byte](10)
|
var buffer = newSeq[byte](10)
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
|
@ -299,25 +317,28 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(AsyncStream) readUntil() test":
|
test "AsyncStream(AsyncStream) readUntil() test":
|
||||||
proc testReadUntil2(): Future[bool] {.async.} =
|
proc testReadUntil2(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newChunkedStreamWriter(wstream)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
var s1 = "00000NNz"
|
var wstream2 = newChunkedStreamWriter(wstream)
|
||||||
var s2 = "11111NNz"
|
var s1 = "00000NNz"
|
||||||
var s3 = "22222NNz"
|
var s2 = "11111NNz"
|
||||||
await wstream2.write("00000")
|
var s3 = "22222NNz"
|
||||||
await wstream2.write(addr s1[0], len(s1))
|
await wstream2.write("00000")
|
||||||
await wstream2.write("11111")
|
await wstream2.write(addr s1[0], len(s1))
|
||||||
await wstream2.write(s2)
|
await wstream2.write("11111")
|
||||||
await wstream2.write("22222")
|
await wstream2.write(s2)
|
||||||
await wstream2.write(s3.toBytes())
|
await wstream2.write("22222")
|
||||||
await wstream2.finish()
|
await wstream2.write(s3.toBytes())
|
||||||
await wstream.finish()
|
await wstream2.finish()
|
||||||
await wstream2.closeWait()
|
await wstream.finish()
|
||||||
await wstream.closeWait()
|
await wstream2.closeWait()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var buffer = newSeq[byte](13)
|
var buffer = newSeq[byte](13)
|
||||||
var sep = @[byte('N'), byte('N'), byte('z')]
|
var sep = @[byte('N'), byte('N'), byte('z')]
|
||||||
|
@ -358,22 +379,25 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(AsyncStream) readLine() test":
|
test "AsyncStream(AsyncStream) readLine() test":
|
||||||
proc testReadLine2(): Future[bool] {.async.} =
|
proc testReadLine2(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newChunkedStreamWriter(wstream)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream2.write("00000")
|
var wstream2 = newChunkedStreamWriter(wstream)
|
||||||
await wstream2.write("00000\r\n")
|
await wstream2.write("00000")
|
||||||
await wstream2.write("11111")
|
await wstream2.write("00000\r\n")
|
||||||
await wstream2.write("11111\r\n")
|
await wstream2.write("11111")
|
||||||
await wstream2.write("22222")
|
await wstream2.write("11111\r\n")
|
||||||
await wstream2.write("22222\r\n")
|
await wstream2.write("22222")
|
||||||
await wstream2.finish()
|
await wstream2.write("22222\r\n")
|
||||||
await wstream.finish()
|
await wstream2.finish()
|
||||||
await wstream2.closeWait()
|
await wstream.finish()
|
||||||
await wstream.closeWait()
|
await wstream2.closeWait()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -405,21 +429,24 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(AsyncStream) read() test":
|
test "AsyncStream(AsyncStream) read() test":
|
||||||
proc testRead2(): Future[bool] {.async.} =
|
proc testRead2(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newChunkedStreamWriter(wstream)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
var s2 = "1111111111"
|
var wstream2 = newChunkedStreamWriter(wstream)
|
||||||
var s3 = "2222222222"
|
var s2 = "1111111111"
|
||||||
await wstream2.write("0000000000")
|
var s3 = "2222222222"
|
||||||
await wstream2.write(s2)
|
await wstream2.write("0000000000")
|
||||||
await wstream2.write(s3.toBytes())
|
await wstream2.write(s2)
|
||||||
await wstream2.finish()
|
await wstream2.write(s3.toBytes())
|
||||||
await wstream.finish()
|
await wstream2.finish()
|
||||||
await wstream2.closeWait()
|
await wstream.finish()
|
||||||
await wstream.closeWait()
|
await wstream2.closeWait()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -446,31 +473,34 @@ suite "AsyncStream test suite":
|
||||||
test "AsyncStream(AsyncStream) consume() test":
|
test "AsyncStream(AsyncStream) consume() test":
|
||||||
proc testConsume2(): Future[bool] {.async.} =
|
proc testConsume2(): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
const
|
try:
|
||||||
S4 = @[byte('3'), byte('3'), byte('3'), byte('3'), byte('3')]
|
const
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
S4 = @[byte('3'), byte('3'), byte('3'), byte('3'), byte('3')]
|
||||||
var wstream2 = newChunkedStreamWriter(wstream)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
|
var wstream2 = newChunkedStreamWriter(wstream)
|
||||||
|
|
||||||
var s1 = "00000"
|
var s1 = "00000"
|
||||||
var s2 = "11111".toBytes()
|
var s2 = "11111".toBytes()
|
||||||
var s3 = "22222"
|
var s3 = "22222"
|
||||||
|
|
||||||
await wstream2.write("00000")
|
await wstream2.write("00000")
|
||||||
await wstream2.write(s1)
|
await wstream2.write(s1)
|
||||||
await wstream2.write("11111")
|
await wstream2.write("11111")
|
||||||
await wstream2.write(s2)
|
await wstream2.write(s2)
|
||||||
await wstream2.write("22222")
|
await wstream2.write("22222")
|
||||||
await wstream2.write(addr s3[0], len(s3))
|
await wstream2.write(addr s3[0], len(s3))
|
||||||
await wstream2.write("33333")
|
await wstream2.write("33333")
|
||||||
await wstream2.write(S4)
|
await wstream2.write(S4)
|
||||||
await wstream2.finish()
|
await wstream2.finish()
|
||||||
await wstream.finish()
|
await wstream.finish()
|
||||||
await wstream2.closeWait()
|
await wstream2.closeWait()
|
||||||
await wstream.closeWait()
|
await wstream.closeWait()
|
||||||
await transp.closeWait()
|
await transp.closeWait()
|
||||||
server.stop()
|
server.stop()
|
||||||
server.close()
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -511,27 +541,30 @@ suite "AsyncStream test suite":
|
||||||
message = createBigMessage("ABCDEFGHIJKLMNOP", size)
|
message = createBigMessage("ABCDEFGHIJKLMNOP", size)
|
||||||
|
|
||||||
proc processClient(server: StreamServer,
|
proc processClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
|
||||||
var wbstream = newBoundedStreamWriter(wstream, uint64(size))
|
|
||||||
try:
|
try:
|
||||||
check wbstream.atEof() == false
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wbstream.write(message)
|
var wbstream = newBoundedStreamWriter(wstream, uint64(size))
|
||||||
check wbstream.atEof() == false
|
try:
|
||||||
await wbstream.finish()
|
check wbstream.atEof() == false
|
||||||
check wbstream.atEof() == true
|
|
||||||
expect AsyncStreamWriteEOFError:
|
|
||||||
await wbstream.write(message)
|
await wbstream.write(message)
|
||||||
expect AsyncStreamWriteEOFError:
|
check wbstream.atEof() == false
|
||||||
await wbstream.write(message)
|
await wbstream.finish()
|
||||||
expect AsyncStreamWriteEOFError:
|
check wbstream.atEof() == true
|
||||||
await wbstream.write(message)
|
expect AsyncStreamWriteEOFError:
|
||||||
check wbstream.atEof() == true
|
await wbstream.write(message)
|
||||||
await wbstream.closeWait()
|
expect AsyncStreamWriteEOFError:
|
||||||
check wbstream.atEof() == true
|
await wbstream.write(message)
|
||||||
finally:
|
expect AsyncStreamWriteEOFError:
|
||||||
await wstream.closeWait()
|
await wbstream.write(message)
|
||||||
await transp.closeWait()
|
check wbstream.atEof() == true
|
||||||
|
await wbstream.closeWait()
|
||||||
|
check wbstream.atEof() == true
|
||||||
|
finally:
|
||||||
|
await wstream.closeWait()
|
||||||
|
await transp.closeWait()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
let flags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay}
|
let flags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay}
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
|
@ -580,15 +613,18 @@ suite "ChunkedStream test suite":
|
||||||
]
|
]
|
||||||
proc checkVector(inputstr: string): Future[string] {.async.} =
|
proc checkVector(inputstr: string): Future[string] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var data = inputstr
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.write(data)
|
var data = inputstr
|
||||||
await wstream.finish()
|
await wstream.write(data)
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -630,15 +666,18 @@ suite "ChunkedStream test suite":
|
||||||
]
|
]
|
||||||
proc checkVector(inputstr: string): Future[bool] {.async.} =
|
proc checkVector(inputstr: string): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var data = inputstr
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.write(data)
|
var data = inputstr
|
||||||
await wstream.finish()
|
await wstream.write(data)
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var res = false
|
var res = false
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
|
@ -713,14 +752,17 @@ suite "ChunkedStream test suite":
|
||||||
test "ChunkedStream too big chunk header test":
|
test "ChunkedStream too big chunk header test":
|
||||||
proc checkTooBigChunkHeader(inputstr: seq[byte]): Future[bool] {.async.} =
|
proc checkTooBigChunkHeader(inputstr: seq[byte]): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
await wstream.write(inputstr)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream.finish()
|
await wstream.write(inputstr)
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -751,23 +793,26 @@ suite "ChunkedStream test suite":
|
||||||
proc checkVector(inputstr: seq[byte],
|
proc checkVector(inputstr: seq[byte],
|
||||||
chunkSize: int): Future[seq[byte]] {.async.} =
|
chunkSize: int): Future[seq[byte]] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newChunkedStreamWriter(wstream)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
var data = inputstr
|
var wstream2 = newChunkedStreamWriter(wstream)
|
||||||
var offset = 0
|
var data = inputstr
|
||||||
while true:
|
var offset = 0
|
||||||
if len(data) == offset:
|
while true:
|
||||||
break
|
if len(data) == offset:
|
||||||
let toWrite = min(chunkSize, len(data) - offset)
|
break
|
||||||
await wstream2.write(addr data[offset], toWrite)
|
let toWrite = min(chunkSize, len(data) - offset)
|
||||||
offset = offset + toWrite
|
await wstream2.write(addr data[offset], toWrite)
|
||||||
await wstream2.finish()
|
offset = offset + toWrite
|
||||||
await wstream2.closeWait()
|
await wstream2.finish()
|
||||||
await wstream.closeWait()
|
await wstream2.closeWait()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -796,23 +841,26 @@ suite "ChunkedStream test suite":
|
||||||
writeChunkSize: int,
|
writeChunkSize: int,
|
||||||
readChunkSize: int): Future[seq[byte]] {.async.} =
|
readChunkSize: int): Future[seq[byte]] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newChunkedStreamWriter(wstream)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
var data = inputstr
|
var wstream2 = newChunkedStreamWriter(wstream)
|
||||||
var offset = 0
|
var data = inputstr
|
||||||
while true:
|
var offset = 0
|
||||||
if len(data) == offset:
|
while true:
|
||||||
break
|
if len(data) == offset:
|
||||||
let toWrite = min(writeChunkSize, len(data) - offset)
|
break
|
||||||
await wstream2.write(addr data[offset], toWrite)
|
let toWrite = min(writeChunkSize, len(data) - offset)
|
||||||
offset = offset + toWrite
|
await wstream2.write(addr data[offset], toWrite)
|
||||||
await wstream2.finish()
|
offset = offset + toWrite
|
||||||
await wstream2.closeWait()
|
await wstream2.finish()
|
||||||
await wstream.closeWait()
|
await wstream2.closeWait()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -849,30 +897,33 @@ suite "TLSStream test suite":
|
||||||
const HttpHeadersMark = @[byte(0x0D), byte(0x0A), byte(0x0D), byte(0x0A)]
|
const HttpHeadersMark = @[byte(0x0D), byte(0x0A), byte(0x0D), byte(0x0A)]
|
||||||
test "Simple HTTPS connection":
|
test "Simple HTTPS connection":
|
||||||
proc headerClient(address: TransportAddress,
|
proc headerClient(address: TransportAddress,
|
||||||
name: string): Future[bool] {.async.} =
|
name: string): Future[bool] {.async: (raises: []).} =
|
||||||
var mark = "HTTP/1.1 "
|
try:
|
||||||
var buffer = newSeq[byte](8192)
|
var mark = "HTTP/1.1 "
|
||||||
var transp = await connect(address)
|
var buffer = newSeq[byte](8192)
|
||||||
var reader = newAsyncStreamReader(transp)
|
var transp = await connect(address)
|
||||||
var writer = newAsyncStreamWriter(transp)
|
var reader = newAsyncStreamReader(transp)
|
||||||
var tlsstream = newTLSClientAsyncStream(reader, writer, name)
|
var writer = newAsyncStreamWriter(transp)
|
||||||
await tlsstream.writer.write("GET / HTTP/1.1\r\nHost: " & name &
|
var tlsstream = newTLSClientAsyncStream(reader, writer, name)
|
||||||
"\r\nConnection: close\r\n\r\n")
|
await tlsstream.writer.write("GET / HTTP/1.1\r\nHost: " & name &
|
||||||
var readFut = tlsstream.reader.readUntil(addr buffer[0], len(buffer),
|
"\r\nConnection: close\r\n\r\n")
|
||||||
HttpHeadersMark)
|
var readFut = tlsstream.reader.readUntil(addr buffer[0], len(buffer),
|
||||||
let res = await withTimeout(readFut, 5.seconds)
|
HttpHeadersMark)
|
||||||
if res:
|
let res = await withTimeout(readFut, 5.seconds)
|
||||||
var length = readFut.read()
|
if res:
|
||||||
buffer.setLen(length)
|
var length = readFut.read()
|
||||||
if len(buffer) > len(mark):
|
buffer.setLen(length)
|
||||||
if equalMem(addr buffer[0], addr mark[0], len(mark)):
|
if len(buffer) > len(mark):
|
||||||
result = true
|
if equalMem(addr buffer[0], addr mark[0], len(mark)):
|
||||||
|
result = true
|
||||||
|
|
||||||
await tlsstream.reader.closeWait()
|
await tlsstream.reader.closeWait()
|
||||||
await tlsstream.writer.closeWait()
|
await tlsstream.writer.closeWait()
|
||||||
await reader.closeWait()
|
await reader.closeWait()
|
||||||
await writer.closeWait()
|
await writer.closeWait()
|
||||||
await transp.closeWait()
|
await transp.closeWait()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
let res = waitFor(headerClient(resolveTAddress("www.google.com:443")[0],
|
let res = waitFor(headerClient(resolveTAddress("www.google.com:443")[0],
|
||||||
"www.google.com"))
|
"www.google.com"))
|
||||||
|
@ -884,20 +935,23 @@ suite "TLSStream test suite":
|
||||||
let testMessage = "TEST MESSAGE"
|
let testMessage = "TEST MESSAGE"
|
||||||
|
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var reader = newAsyncStreamReader(transp)
|
try:
|
||||||
var writer = newAsyncStreamWriter(transp)
|
var reader = newAsyncStreamReader(transp)
|
||||||
var sstream = newTLSServerAsyncStream(reader, writer, key, cert)
|
var writer = newAsyncStreamWriter(transp)
|
||||||
await handshake(sstream)
|
var sstream = newTLSServerAsyncStream(reader, writer, key, cert)
|
||||||
await sstream.writer.write(testMessage & "\r\n")
|
await handshake(sstream)
|
||||||
await sstream.writer.finish()
|
await sstream.writer.write(testMessage & "\r\n")
|
||||||
await sstream.writer.closeWait()
|
await sstream.writer.finish()
|
||||||
await sstream.reader.closeWait()
|
await sstream.writer.closeWait()
|
||||||
await reader.closeWait()
|
await sstream.reader.closeWait()
|
||||||
await writer.closeWait()
|
await reader.closeWait()
|
||||||
await transp.closeWait()
|
await writer.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
key = TLSPrivateKey.init(pemkey)
|
key = TLSPrivateKey.init(pemkey)
|
||||||
cert = TLSCertificate.init(pemcert)
|
cert = TLSCertificate.init(pemcert)
|
||||||
|
@ -931,20 +985,23 @@ suite "TLSStream test suite":
|
||||||
let trustAnchors = TrustAnchorStore.new(SelfSignedTrustAnchors)
|
let trustAnchors = TrustAnchorStore.new(SelfSignedTrustAnchors)
|
||||||
|
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var reader = newAsyncStreamReader(transp)
|
try:
|
||||||
var writer = newAsyncStreamWriter(transp)
|
var reader = newAsyncStreamReader(transp)
|
||||||
var sstream = newTLSServerAsyncStream(reader, writer, key, cert)
|
var writer = newAsyncStreamWriter(transp)
|
||||||
await handshake(sstream)
|
var sstream = newTLSServerAsyncStream(reader, writer, key, cert)
|
||||||
await sstream.writer.write(testMessage & "\r\n")
|
await handshake(sstream)
|
||||||
await sstream.writer.finish()
|
await sstream.writer.write(testMessage & "\r\n")
|
||||||
await sstream.writer.closeWait()
|
await sstream.writer.finish()
|
||||||
await sstream.reader.closeWait()
|
await sstream.writer.closeWait()
|
||||||
await reader.closeWait()
|
await sstream.reader.closeWait()
|
||||||
await writer.closeWait()
|
await reader.closeWait()
|
||||||
await transp.closeWait()
|
await writer.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -988,46 +1045,49 @@ suite "BoundedStream test suite":
|
||||||
var clientRes = false
|
var clientRes = false
|
||||||
|
|
||||||
proc processClient(server: StreamServer,
|
proc processClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
case btest
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
of BoundaryRead:
|
case btest
|
||||||
await wstream.write(message)
|
of BoundaryRead:
|
||||||
await wstream.write(boundary)
|
await wstream.write(message)
|
||||||
await wstream.finish()
|
await wstream.write(boundary)
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
clientRes = true
|
await wstream.closeWait()
|
||||||
of BoundaryDouble:
|
clientRes = true
|
||||||
await wstream.write(message)
|
of BoundaryDouble:
|
||||||
await wstream.write(boundary)
|
await wstream.write(message)
|
||||||
await wstream.write(message)
|
await wstream.write(boundary)
|
||||||
await wstream.finish()
|
await wstream.write(message)
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
clientRes = true
|
await wstream.closeWait()
|
||||||
of BoundarySize:
|
clientRes = true
|
||||||
var ncmessage = message
|
of BoundarySize:
|
||||||
ncmessage.setLen(len(message) - 2)
|
var ncmessage = message
|
||||||
await wstream.write(ncmessage)
|
ncmessage.setLen(len(message) - 2)
|
||||||
await wstream.write(@[0x2D'u8, 0x2D'u8])
|
await wstream.write(ncmessage)
|
||||||
await wstream.finish()
|
await wstream.write(@[0x2D'u8, 0x2D'u8])
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
clientRes = true
|
await wstream.closeWait()
|
||||||
of BoundaryIncomplete:
|
clientRes = true
|
||||||
var ncmessage = message
|
of BoundaryIncomplete:
|
||||||
ncmessage.setLen(len(message) - 2)
|
var ncmessage = message
|
||||||
await wstream.write(ncmessage)
|
ncmessage.setLen(len(message) - 2)
|
||||||
await wstream.finish()
|
await wstream.write(ncmessage)
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
clientRes = true
|
await wstream.closeWait()
|
||||||
of BoundaryEmpty:
|
clientRes = true
|
||||||
await wstream.write(boundary)
|
of BoundaryEmpty:
|
||||||
await wstream.finish()
|
await wstream.write(boundary)
|
||||||
await wstream.closeWait()
|
await wstream.finish()
|
||||||
clientRes = true
|
await wstream.closeWait()
|
||||||
|
clientRes = true
|
||||||
|
|
||||||
await transp.closeWait()
|
await transp.closeWait()
|
||||||
server.stop()
|
server.stop()
|
||||||
server.close()
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var res = false
|
var res = false
|
||||||
let flags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay}
|
let flags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay}
|
||||||
|
@ -1090,60 +1150,63 @@ suite "BoundedStream test suite":
|
||||||
message.add(messagePart)
|
message.add(messagePart)
|
||||||
|
|
||||||
proc processClient(server: StreamServer,
|
proc processClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wbstream = newBoundedStreamWriter(wstream, uint64(size),
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
comparison = cmp)
|
var wbstream = newBoundedStreamWriter(wstream, uint64(size),
|
||||||
case stest
|
comparison = cmp)
|
||||||
of SizeReadWrite:
|
case stest
|
||||||
for i in 0 ..< 10:
|
of SizeReadWrite:
|
||||||
await wbstream.write(messagePart)
|
for i in 0 ..< 10:
|
||||||
await wbstream.finish()
|
await wbstream.write(messagePart)
|
||||||
await wbstream.closeWait()
|
await wbstream.finish()
|
||||||
clientRes = true
|
await wbstream.closeWait()
|
||||||
of SizeOverflow:
|
|
||||||
for i in 0 ..< 10:
|
|
||||||
await wbstream.write(messagePart)
|
|
||||||
try:
|
|
||||||
await wbstream.write(messagePart)
|
|
||||||
except BoundedStreamOverflowError:
|
|
||||||
clientRes = true
|
clientRes = true
|
||||||
await wbstream.closeWait()
|
of SizeOverflow:
|
||||||
of SizeIncomplete:
|
for i in 0 ..< 10:
|
||||||
for i in 0 ..< 9:
|
await wbstream.write(messagePart)
|
||||||
await wbstream.write(messagePart)
|
|
||||||
case cmp
|
|
||||||
of BoundCmp.Equal:
|
|
||||||
try:
|
try:
|
||||||
await wbstream.finish()
|
await wbstream.write(messagePart)
|
||||||
except BoundedStreamIncompleteError:
|
except BoundedStreamOverflowError:
|
||||||
clientRes = true
|
clientRes = true
|
||||||
of BoundCmp.LessOrEqual:
|
await wbstream.closeWait()
|
||||||
try:
|
of SizeIncomplete:
|
||||||
await wbstream.finish()
|
for i in 0 ..< 9:
|
||||||
clientRes = true
|
await wbstream.write(messagePart)
|
||||||
except BoundedStreamIncompleteError:
|
case cmp
|
||||||
discard
|
of BoundCmp.Equal:
|
||||||
await wbstream.closeWait()
|
try:
|
||||||
of SizeEmpty:
|
await wbstream.finish()
|
||||||
case cmp
|
except BoundedStreamIncompleteError:
|
||||||
of BoundCmp.Equal:
|
clientRes = true
|
||||||
try:
|
of BoundCmp.LessOrEqual:
|
||||||
await wbstream.finish()
|
try:
|
||||||
except BoundedStreamIncompleteError:
|
await wbstream.finish()
|
||||||
clientRes = true
|
clientRes = true
|
||||||
of BoundCmp.LessOrEqual:
|
except BoundedStreamIncompleteError:
|
||||||
try:
|
discard
|
||||||
await wbstream.finish()
|
await wbstream.closeWait()
|
||||||
clientRes = true
|
of SizeEmpty:
|
||||||
except BoundedStreamIncompleteError:
|
case cmp
|
||||||
discard
|
of BoundCmp.Equal:
|
||||||
await wbstream.closeWait()
|
try:
|
||||||
|
await wbstream.finish()
|
||||||
|
except BoundedStreamIncompleteError:
|
||||||
|
clientRes = true
|
||||||
|
of BoundCmp.LessOrEqual:
|
||||||
|
try:
|
||||||
|
await wbstream.finish()
|
||||||
|
clientRes = true
|
||||||
|
except BoundedStreamIncompleteError:
|
||||||
|
discard
|
||||||
|
await wbstream.closeWait()
|
||||||
|
|
||||||
await wstream.closeWait()
|
await wstream.closeWait()
|
||||||
await transp.closeWait()
|
await transp.closeWait()
|
||||||
server.stop()
|
server.stop()
|
||||||
server.close()
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
let flags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay}
|
let flags = {ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay}
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
|
@ -1243,23 +1306,26 @@ suite "BoundedStream test suite":
|
||||||
writeChunkSize: int,
|
writeChunkSize: int,
|
||||||
readChunkSize: int): Future[seq[byte]] {.async.} =
|
readChunkSize: int): Future[seq[byte]] {.async.} =
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newBoundedStreamWriter(wstream, uint64(len(inputstr)))
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
var data = inputstr
|
var wstream2 = newBoundedStreamWriter(wstream, uint64(len(inputstr)))
|
||||||
var offset = 0
|
var data = inputstr
|
||||||
while true:
|
var offset = 0
|
||||||
if len(data) == offset:
|
while true:
|
||||||
break
|
if len(data) == offset:
|
||||||
let toWrite = min(writeChunkSize, len(data) - offset)
|
break
|
||||||
await wstream2.write(addr data[offset], toWrite)
|
let toWrite = min(writeChunkSize, len(data) - offset)
|
||||||
offset = offset + toWrite
|
await wstream2.write(addr data[offset], toWrite)
|
||||||
await wstream2.finish()
|
offset = offset + toWrite
|
||||||
await wstream2.closeWait()
|
await wstream2.finish()
|
||||||
await wstream.closeWait()
|
await wstream2.closeWait()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
@ -1293,17 +1359,20 @@ suite "BoundedStream test suite":
|
||||||
proc checkEmptyStreams(): Future[bool] {.async.} =
|
proc checkEmptyStreams(): Future[bool] {.async.} =
|
||||||
var writer1Res = false
|
var writer1Res = false
|
||||||
proc serveClient(server: StreamServer,
|
proc serveClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var wstream = newAsyncStreamWriter(transp)
|
try:
|
||||||
var wstream2 = newBoundedStreamWriter(wstream, 0'u64)
|
var wstream = newAsyncStreamWriter(transp)
|
||||||
await wstream2.finish()
|
var wstream2 = newBoundedStreamWriter(wstream, 0'u64)
|
||||||
let res = wstream2.atEof()
|
await wstream2.finish()
|
||||||
await wstream2.closeWait()
|
let res = wstream2.atEof()
|
||||||
await wstream.closeWait()
|
await wstream2.closeWait()
|
||||||
await transp.closeWait()
|
await wstream.closeWait()
|
||||||
server.stop()
|
await transp.closeWait()
|
||||||
server.close()
|
server.stop()
|
||||||
writer1Res = res
|
server.close()
|
||||||
|
writer1Res = res
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
var server = createStreamServer(initTAddress("127.0.0.1:0"),
|
||||||
serveClient, {ReuseAddr})
|
serveClient, {ReuseAddr})
|
||||||
|
|
|
@ -21,16 +21,19 @@ suite "Asynchronous issues test suite":
|
||||||
test: string
|
test: string
|
||||||
|
|
||||||
proc udp4DataAvailable(transp: DatagramTransport,
|
proc udp4DataAvailable(transp: DatagramTransport,
|
||||||
remote: TransportAddress) {.async, gcsafe.} =
|
remote: TransportAddress) {.async: (raises: []).} =
|
||||||
var udata = getUserData[CustomData](transp)
|
try:
|
||||||
var expect = TEST_MSG
|
var udata = getUserData[CustomData](transp)
|
||||||
var data: seq[byte]
|
var expect = TEST_MSG
|
||||||
var datalen: int
|
var data: seq[byte]
|
||||||
transp.peekMessage(data, datalen)
|
var datalen: int
|
||||||
if udata.test == "CHECK" and datalen == MSG_LEN and
|
transp.peekMessage(data, datalen)
|
||||||
equalMem(addr data[0], addr expect[0], datalen):
|
if udata.test == "CHECK" and datalen == MSG_LEN and
|
||||||
udata.test = "OK"
|
equalMem(addr data[0], addr expect[0], datalen):
|
||||||
transp.close()
|
udata.test = "OK"
|
||||||
|
transp.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc issue6(): Future[bool] {.async.} =
|
proc issue6(): Future[bool] {.async.} =
|
||||||
var myself = initTAddress("127.0.0.1:" & $HELLO_PORT)
|
var myself = initTAddress("127.0.0.1:" & $HELLO_PORT)
|
||||||
|
|
|
@ -30,286 +30,319 @@ suite "Datagram Transport test suite":
|
||||||
" clients x " & $MessagesCount & " messages)"
|
" clients x " & $MessagesCount & " messages)"
|
||||||
|
|
||||||
proc client1(transp: DatagramTransport,
|
proc client1(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("REQUEST"):
|
data.setLen(nbytes)
|
||||||
var numstr = data[7..^1]
|
if data.startsWith("REQUEST"):
|
||||||
var num = parseInt(numstr)
|
var numstr = data[7..^1]
|
||||||
var ans = "ANSWER" & $num
|
var num = parseInt(numstr)
|
||||||
await transp.sendTo(raddr, addr ans[0], len(ans))
|
var ans = "ANSWER" & $num
|
||||||
|
await transp.sendTo(raddr, addr ans[0], len(ans))
|
||||||
|
else:
|
||||||
|
var err = "ERROR"
|
||||||
|
await transp.sendTo(raddr, addr err[0], len(err))
|
||||||
else:
|
else:
|
||||||
var err = "ERROR"
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
await transp.sendTo(raddr, addr err[0], len(err))
|
counterPtr[] = -1
|
||||||
else:
|
transp.close()
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
except CatchableError as exc:
|
||||||
counterPtr[] = -1
|
raiseAssert exc.msg
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client2(transp: DatagramTransport,
|
proc client2(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == TestsCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == TestsCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var ta = initTAddress("127.0.0.1:33336")
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
await transp.sendTo(ta, addr req[0], len(req))
|
||||||
else:
|
else:
|
||||||
var ta = initTAddress("127.0.0.1:33336")
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
var req = "REQUEST" & $counterPtr[]
|
counterPtr[] = -1
|
||||||
await transp.sendTo(ta, addr req[0], len(req))
|
transp.close()
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client3(transp: DatagramTransport,
|
proc client3(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == TestsCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == TestsCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
await transp.send(addr req[0], len(req))
|
||||||
else:
|
else:
|
||||||
var req = "REQUEST" & $counterPtr[]
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
await transp.send(addr req[0], len(req))
|
counterPtr[] = -1
|
||||||
|
transp.close()
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client4(transp: DatagramTransport,
|
proc client4(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == MessagesCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == MessagesCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
await transp.send(addr req[0], len(req))
|
||||||
else:
|
else:
|
||||||
var req = "REQUEST" & $counterPtr[]
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
await transp.send(addr req[0], len(req))
|
counterPtr[] = -1
|
||||||
|
transp.close()
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client5(transp: DatagramTransport,
|
proc client5(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == MessagesCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == MessagesCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
await transp.sendTo(raddr, addr req[0], len(req))
|
||||||
else:
|
else:
|
||||||
var req = "REQUEST" & $counterPtr[]
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
await transp.sendTo(raddr, addr req[0], len(req))
|
counterPtr[] = -1
|
||||||
|
transp.close()
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client6(transp: DatagramTransport,
|
proc client6(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("REQUEST"):
|
data.setLen(nbytes)
|
||||||
var numstr = data[7..^1]
|
if data.startsWith("REQUEST"):
|
||||||
var num = parseInt(numstr)
|
var numstr = data[7..^1]
|
||||||
var ans = "ANSWER" & $num
|
var num = parseInt(numstr)
|
||||||
await transp.sendTo(raddr, ans)
|
var ans = "ANSWER" & $num
|
||||||
|
await transp.sendTo(raddr, ans)
|
||||||
|
else:
|
||||||
|
var err = "ERROR"
|
||||||
|
await transp.sendTo(raddr, err)
|
||||||
else:
|
else:
|
||||||
var err = "ERROR"
|
## Read operation failed with error
|
||||||
await transp.sendTo(raddr, err)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
else:
|
counterPtr[] = -1
|
||||||
## Read operation failed with error
|
transp.close()
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
except CatchableError as exc:
|
||||||
counterPtr[] = -1
|
raiseAssert exc.msg
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client7(transp: DatagramTransport,
|
proc client7(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == TestsCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == TestsCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
await transp.sendTo(raddr, req)
|
||||||
else:
|
else:
|
||||||
var req = "REQUEST" & $counterPtr[]
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
await transp.sendTo(raddr, req)
|
counterPtr[] = -1
|
||||||
|
transp.close()
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client8(transp: DatagramTransport,
|
proc client8(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == TestsCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == TestsCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
await transp.send(req)
|
||||||
else:
|
else:
|
||||||
var req = "REQUEST" & $counterPtr[]
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
await transp.send(req)
|
counterPtr[] = -1
|
||||||
|
transp.close()
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client9(transp: DatagramTransport,
|
proc client9(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("REQUEST"):
|
data.setLen(nbytes)
|
||||||
var numstr = data[7..^1]
|
if data.startsWith("REQUEST"):
|
||||||
var num = parseInt(numstr)
|
var numstr = data[7..^1]
|
||||||
var ans = "ANSWER" & $num
|
var num = parseInt(numstr)
|
||||||
var ansseq = newSeq[byte](len(ans))
|
var ans = "ANSWER" & $num
|
||||||
copyMem(addr ansseq[0], addr ans[0], len(ans))
|
var ansseq = newSeq[byte](len(ans))
|
||||||
await transp.sendTo(raddr, ansseq)
|
copyMem(addr ansseq[0], addr ans[0], len(ans))
|
||||||
|
await transp.sendTo(raddr, ansseq)
|
||||||
|
else:
|
||||||
|
var err = "ERROR"
|
||||||
|
var errseq = newSeq[byte](len(err))
|
||||||
|
copyMem(addr errseq[0], addr err[0], len(err))
|
||||||
|
await transp.sendTo(raddr, errseq)
|
||||||
else:
|
else:
|
||||||
var err = "ERROR"
|
## Read operation failed with error
|
||||||
var errseq = newSeq[byte](len(err))
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
copyMem(addr errseq[0], addr err[0], len(err))
|
counterPtr[] = -1
|
||||||
await transp.sendTo(raddr, errseq)
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client10(transp: DatagramTransport,
|
proc client10(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == TestsCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == TestsCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
var reqseq = newSeq[byte](len(req))
|
||||||
|
copyMem(addr reqseq[0], addr req[0], len(req))
|
||||||
|
await transp.sendTo(raddr, reqseq)
|
||||||
else:
|
else:
|
||||||
var req = "REQUEST" & $counterPtr[]
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
var reqseq = newSeq[byte](len(req))
|
counterPtr[] = -1
|
||||||
copyMem(addr reqseq[0], addr req[0], len(req))
|
transp.close()
|
||||||
await transp.sendTo(raddr, reqseq)
|
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc client11(transp: DatagramTransport,
|
proc client11(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var pbytes = transp.getMessage()
|
try:
|
||||||
var nbytes = len(pbytes)
|
var pbytes = transp.getMessage()
|
||||||
if nbytes > 0:
|
var nbytes = len(pbytes)
|
||||||
var data = newString(nbytes + 1)
|
if nbytes > 0:
|
||||||
copyMem(addr data[0], addr pbytes[0], nbytes)
|
var data = newString(nbytes + 1)
|
||||||
data.setLen(nbytes)
|
copyMem(addr data[0], addr pbytes[0], nbytes)
|
||||||
if data.startsWith("ANSWER"):
|
data.setLen(nbytes)
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
if data.startsWith("ANSWER"):
|
||||||
counterPtr[] = counterPtr[] + 1
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
if counterPtr[] == TestsCount:
|
counterPtr[] = counterPtr[] + 1
|
||||||
transp.close()
|
if counterPtr[] == TestsCount:
|
||||||
|
transp.close()
|
||||||
|
else:
|
||||||
|
var req = "REQUEST" & $counterPtr[]
|
||||||
|
var reqseq = newSeq[byte](len(req))
|
||||||
|
copyMem(addr reqseq[0], addr req[0], len(req))
|
||||||
|
await transp.send(reqseq)
|
||||||
else:
|
else:
|
||||||
var req = "REQUEST" & $counterPtr[]
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
var reqseq = newSeq[byte](len(req))
|
counterPtr[] = -1
|
||||||
copyMem(addr reqseq[0], addr req[0], len(req))
|
transp.close()
|
||||||
await transp.send(reqseq)
|
|
||||||
else:
|
else:
|
||||||
|
## Read operation failed with error
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
var counterPtr = cast[ptr int](transp.udata)
|
||||||
counterPtr[] = -1
|
counterPtr[] = -1
|
||||||
transp.close()
|
transp.close()
|
||||||
else:
|
except CatchableError as exc:
|
||||||
## Read operation failed with error
|
raiseAssert exc.msg
|
||||||
var counterPtr = cast[ptr int](transp.udata)
|
|
||||||
counterPtr[] = -1
|
|
||||||
transp.close()
|
|
||||||
|
|
||||||
proc testPointerSendTo(): Future[int] {.async.} =
|
proc testPointerSendTo(): Future[int] {.async.} =
|
||||||
## sendTo(pointer) test
|
## sendTo(pointer) test
|
||||||
|
@ -439,7 +472,7 @@ suite "Datagram Transport test suite":
|
||||||
var ta = initTAddress("127.0.0.1:0")
|
var ta = initTAddress("127.0.0.1:0")
|
||||||
var counter = 0
|
var counter = 0
|
||||||
proc clientMark(transp: DatagramTransport,
|
proc clientMark(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
counter = 1
|
counter = 1
|
||||||
transp.close()
|
transp.close()
|
||||||
var dgram1 = newDatagramTransport(client1, local = ta)
|
var dgram1 = newDatagramTransport(client1, local = ta)
|
||||||
|
@ -457,7 +490,7 @@ suite "Datagram Transport test suite":
|
||||||
proc testTransportClose(): Future[bool] {.async.} =
|
proc testTransportClose(): Future[bool] {.async.} =
|
||||||
var ta = initTAddress("127.0.0.1:45000")
|
var ta = initTAddress("127.0.0.1:45000")
|
||||||
proc clientMark(transp: DatagramTransport,
|
proc clientMark(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
discard
|
discard
|
||||||
var dgram = newDatagramTransport(clientMark, local = ta)
|
var dgram = newDatagramTransport(clientMark, local = ta)
|
||||||
dgram.close()
|
dgram.close()
|
||||||
|
@ -473,12 +506,15 @@ suite "Datagram Transport test suite":
|
||||||
var bta = initTAddress("255.255.255.255:45010")
|
var bta = initTAddress("255.255.255.255:45010")
|
||||||
var res = 0
|
var res = 0
|
||||||
proc clientMark(transp: DatagramTransport,
|
proc clientMark(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var bmsg = transp.getMessage()
|
try:
|
||||||
var smsg = string.fromBytes(bmsg)
|
var bmsg = transp.getMessage()
|
||||||
if smsg == expectMessage:
|
var smsg = string.fromBytes(bmsg)
|
||||||
inc(res)
|
if smsg == expectMessage:
|
||||||
transp.close()
|
inc(res)
|
||||||
|
transp.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
var dgram1 = newDatagramTransport(clientMark, local = ta1,
|
var dgram1 = newDatagramTransport(clientMark, local = ta1,
|
||||||
flags = {Broadcast}, ttl = 2)
|
flags = {Broadcast}, ttl = 2)
|
||||||
await dgram1.sendTo(bta, expectMessage)
|
await dgram1.sendTo(bta, expectMessage)
|
||||||
|
@ -493,15 +529,19 @@ suite "Datagram Transport test suite":
|
||||||
var event = newAsyncEvent()
|
var event = newAsyncEvent()
|
||||||
|
|
||||||
proc clientMark1(transp: DatagramTransport,
|
proc clientMark1(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var bmsg = transp.getMessage()
|
try:
|
||||||
var smsg = string.fromBytes(bmsg)
|
var bmsg = transp.getMessage()
|
||||||
if smsg == expectStr:
|
var smsg = string.fromBytes(bmsg)
|
||||||
inc(res)
|
if smsg == expectStr:
|
||||||
event.fire()
|
inc(res)
|
||||||
|
event.fire()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
|
|
||||||
proc clientMark2(transp: DatagramTransport,
|
proc clientMark2(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
var dgram1 = newDatagramTransport(clientMark1, local = ta)
|
var dgram1 = newDatagramTransport(clientMark1, local = ta)
|
||||||
|
@ -544,15 +584,18 @@ suite "Datagram Transport test suite":
|
||||||
res = 0
|
res = 0
|
||||||
|
|
||||||
proc process1(transp: DatagramTransport,
|
proc process1(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
var bmsg = transp.getMessage()
|
try:
|
||||||
var smsg = string.fromBytes(bmsg)
|
var bmsg = transp.getMessage()
|
||||||
if smsg == expectStr:
|
var smsg = string.fromBytes(bmsg)
|
||||||
inc(res)
|
if smsg == expectStr:
|
||||||
event.fire()
|
inc(res)
|
||||||
|
event.fire()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc process2(transp: DatagramTransport,
|
proc process2(transp: DatagramTransport,
|
||||||
raddr: TransportAddress): Future[void] {.async.} =
|
raddr: TransportAddress): Future[void] {.async: (raises: []).} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
let
|
let
|
||||||
|
|
|
@ -459,20 +459,31 @@ suite "Exceptions tracking":
|
||||||
check waitFor(test1()) == 12
|
check waitFor(test1()) == 12
|
||||||
|
|
||||||
proc test2: Future[int] {.async: (raw: true, raises: [IOError, OSError]).} =
|
proc test2: Future[int] {.async: (raw: true, raises: [IOError, OSError]).} =
|
||||||
|
checkNotCompiles:
|
||||||
|
result.fail(newException(ValueError, "fail"))
|
||||||
|
|
||||||
result = newFuture[int]()
|
result = newFuture[int]()
|
||||||
result.fail(newException(IOError, "fail"))
|
result.fail(newException(IOError, "fail"))
|
||||||
result.fail(newException(OSError, "fail"))
|
|
||||||
checkNotCompiles:
|
|
||||||
result.fail(newException(ValueError, "fail"))
|
|
||||||
|
|
||||||
proc test3: Future[void] {.async: (raw: true, raises: []).} =
|
proc test3: Future[void] {.async: (raw: true, raises: []).} =
|
||||||
|
result = newFuture[void]()
|
||||||
checkNotCompiles:
|
checkNotCompiles:
|
||||||
result.fail(newException(ValueError, "fail"))
|
result.fail(newException(ValueError, "fail"))
|
||||||
|
result.complete()
|
||||||
# Inheritance
|
# Inheritance
|
||||||
proc test4: Future[void] {.async: (raw: true, raises: [CatchableError]).} =
|
proc test4: Future[void] {.async: (raw: true, raises: [CatchableError]).} =
|
||||||
|
result = newFuture[void]()
|
||||||
result.fail(newException(IOError, "fail"))
|
result.fail(newException(IOError, "fail"))
|
||||||
|
|
||||||
|
check:
|
||||||
|
waitFor(test1()) == 12
|
||||||
|
expect(IOError):
|
||||||
|
discard waitFor(test2())
|
||||||
|
|
||||||
|
waitFor(test3())
|
||||||
|
expect(IOError):
|
||||||
|
waitFor(test4())
|
||||||
|
|
||||||
test "or errors":
|
test "or errors":
|
||||||
proc testit {.async: (raises: [ValueError]).} =
|
proc testit {.async: (raises: [ValueError]).} =
|
||||||
raise (ref ValueError)()
|
raise (ref ValueError)()
|
||||||
|
|
|
@ -27,29 +27,36 @@ suite "Server's test suite":
|
||||||
checkLeaks()
|
checkLeaks()
|
||||||
|
|
||||||
proc serveStreamClient(server: StreamServer,
|
proc serveStreamClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc serveCustomStreamClient(server: StreamServer,
|
proc serveCustomStreamClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var cserver = cast[CustomServer](server)
|
try:
|
||||||
var ctransp = cast[CustomTransport](transp)
|
var cserver = cast[CustomServer](server)
|
||||||
cserver.test1 = "CONNECTION"
|
var ctransp = cast[CustomTransport](transp)
|
||||||
cserver.test2 = ctransp.test
|
cserver.test1 = "CONNECTION"
|
||||||
cserver.test3 = await transp.readLine()
|
cserver.test2 = ctransp.test
|
||||||
var answer = "ANSWER\r\n"
|
cserver.test3 = await transp.readLine()
|
||||||
discard await transp.write(answer)
|
var answer = "ANSWER\r\n"
|
||||||
transp.close()
|
discard await transp.write(answer)
|
||||||
await transp.join()
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
|
|
||||||
proc serveUdataStreamClient(server: StreamServer,
|
proc serveUdataStreamClient(server: StreamServer,
|
||||||
transp: StreamTransport) {.async.} =
|
transp: StreamTransport) {.async: (raises: []).} =
|
||||||
var udata = getUserData[CustomData](server)
|
try:
|
||||||
var line = await transp.readLine()
|
var udata = getUserData[CustomData](server)
|
||||||
var msg = line & udata.test & "\r\n"
|
var line = await transp.readLine()
|
||||||
discard await transp.write(msg)
|
var msg = line & udata.test & "\r\n"
|
||||||
transp.close()
|
discard await transp.write(msg)
|
||||||
await transp.join()
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc customServerTransport(server: StreamServer,
|
proc customServerTransport(server: StreamServer,
|
||||||
fd: AsyncFD): StreamTransport =
|
fd: AsyncFD): StreamTransport =
|
||||||
|
|
|
@ -55,124 +55,148 @@ suite "Stream Transport test suite":
|
||||||
for i in 0 ..< len(result):
|
for i in 0 ..< len(result):
|
||||||
result[i] = byte(message[i mod len(message)])
|
result[i] = byte(message[i mod len(message)])
|
||||||
|
|
||||||
proc serveClient1(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient1(server: StreamServer, transp: StreamTransport) {.
|
||||||
while not transp.atEof():
|
async: (raises: []).} =
|
||||||
var data = await transp.readLine()
|
try:
|
||||||
if len(data) == 0:
|
while not transp.atEof():
|
||||||
doAssert(transp.atEof())
|
var data = await transp.readLine()
|
||||||
break
|
if len(data) == 0:
|
||||||
doAssert(data.startsWith("REQUEST"))
|
doAssert(transp.atEof())
|
||||||
var numstr = data[7..^1]
|
break
|
||||||
var num = parseInt(numstr)
|
doAssert(data.startsWith("REQUEST"))
|
||||||
var ans = "ANSWER" & $num & "\r\n"
|
var numstr = data[7..^1]
|
||||||
var res = await transp.write(cast[pointer](addr ans[0]), len(ans))
|
var num = parseInt(numstr)
|
||||||
doAssert(res == len(ans))
|
var ans = "ANSWER" & $num & "\r\n"
|
||||||
transp.close()
|
var res = await transp.write(cast[pointer](addr ans[0]), len(ans))
|
||||||
await transp.join()
|
doAssert(res == len(ans))
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc serveClient2(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient2(server: StreamServer, transp: StreamTransport) {.
|
||||||
var buffer: array[20, char]
|
async: (raises: []).} =
|
||||||
var check = "REQUEST"
|
try:
|
||||||
while not transp.atEof():
|
var buffer: array[20, char]
|
||||||
zeroMem(addr buffer[0], MessageSize)
|
var check = "REQUEST"
|
||||||
try:
|
while not transp.atEof():
|
||||||
await transp.readExactly(addr buffer[0], MessageSize)
|
zeroMem(addr buffer[0], MessageSize)
|
||||||
except TransportIncompleteError:
|
try:
|
||||||
break
|
await transp.readExactly(addr buffer[0], MessageSize)
|
||||||
doAssert(equalMem(addr buffer[0], addr check[0], len(check)))
|
except TransportIncompleteError:
|
||||||
var numstr = ""
|
break
|
||||||
var i = 7
|
doAssert(equalMem(addr buffer[0], addr check[0], len(check)))
|
||||||
while i < MessageSize and (buffer[i] in {'0'..'9'}):
|
var numstr = ""
|
||||||
numstr.add(buffer[i])
|
var i = 7
|
||||||
inc(i)
|
while i < MessageSize and (buffer[i] in {'0'..'9'}):
|
||||||
var num = parseInt(numstr)
|
numstr.add(buffer[i])
|
||||||
var ans = "ANSWER" & $num
|
inc(i)
|
||||||
zeroMem(addr buffer[0], MessageSize)
|
var num = parseInt(numstr)
|
||||||
copyMem(addr buffer[0], addr ans[0], len(ans))
|
var ans = "ANSWER" & $num
|
||||||
var res = await transp.write(cast[pointer](addr buffer[0]), MessageSize)
|
zeroMem(addr buffer[0], MessageSize)
|
||||||
doAssert(res == MessageSize)
|
copyMem(addr buffer[0], addr ans[0], len(ans))
|
||||||
transp.close()
|
var res = await transp.write(cast[pointer](addr buffer[0]), MessageSize)
|
||||||
await transp.join()
|
doAssert(res == MessageSize)
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc serveClient3(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient3(server: StreamServer, transp: StreamTransport) {.
|
||||||
var buffer: array[20, char]
|
async: (raises: []).} =
|
||||||
var check = "REQUEST"
|
try:
|
||||||
var suffixStr = "SUFFIX"
|
var buffer: array[20, char]
|
||||||
var suffix = newSeq[byte](6)
|
var check = "REQUEST"
|
||||||
copyMem(addr suffix[0], addr suffixStr[0], len(suffixStr))
|
var suffixStr = "SUFFIX"
|
||||||
var counter = MessagesCount
|
var suffix = newSeq[byte](6)
|
||||||
while counter > 0:
|
copyMem(addr suffix[0], addr suffixStr[0], len(suffixStr))
|
||||||
zeroMem(addr buffer[0], MessageSize)
|
var counter = MessagesCount
|
||||||
var res = await transp.readUntil(addr buffer[0], MessageSize, suffix)
|
while counter > 0:
|
||||||
doAssert(equalMem(addr buffer[0], addr check[0], len(check)))
|
zeroMem(addr buffer[0], MessageSize)
|
||||||
var numstr = ""
|
var res = await transp.readUntil(addr buffer[0], MessageSize, suffix)
|
||||||
var i = 7
|
doAssert(equalMem(addr buffer[0], addr check[0], len(check)))
|
||||||
while i < MessageSize and (buffer[i] in {'0'..'9'}):
|
var numstr = ""
|
||||||
numstr.add(buffer[i])
|
var i = 7
|
||||||
inc(i)
|
while i < MessageSize and (buffer[i] in {'0'..'9'}):
|
||||||
var num = parseInt(numstr)
|
numstr.add(buffer[i])
|
||||||
doAssert(len(numstr) < 8)
|
inc(i)
|
||||||
var ans = "ANSWER" & $num & "SUFFIX"
|
var num = parseInt(numstr)
|
||||||
zeroMem(addr buffer[0], MessageSize)
|
doAssert(len(numstr) < 8)
|
||||||
copyMem(addr buffer[0], addr ans[0], len(ans))
|
var ans = "ANSWER" & $num & "SUFFIX"
|
||||||
res = await transp.write(cast[pointer](addr buffer[0]), len(ans))
|
zeroMem(addr buffer[0], MessageSize)
|
||||||
doAssert(res == len(ans))
|
copyMem(addr buffer[0], addr ans[0], len(ans))
|
||||||
dec(counter)
|
res = await transp.write(cast[pointer](addr buffer[0]), len(ans))
|
||||||
transp.close()
|
doAssert(res == len(ans))
|
||||||
await transp.join()
|
dec(counter)
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc serveClient4(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient4(server: StreamServer, transp: StreamTransport) {.
|
||||||
var pathname = await transp.readLine()
|
async: (raises: []).} =
|
||||||
var size = await transp.readLine()
|
try:
|
||||||
var sizeNum = parseInt(size)
|
var pathname = await transp.readLine()
|
||||||
doAssert(sizeNum >= 0)
|
var size = await transp.readLine()
|
||||||
var rbuffer = newSeq[byte](sizeNum)
|
var sizeNum = parseInt(size)
|
||||||
await transp.readExactly(addr rbuffer[0], sizeNum)
|
doAssert(sizeNum >= 0)
|
||||||
var lbuffer = readFile(pathname)
|
var rbuffer = newSeq[byte](sizeNum)
|
||||||
doAssert(len(lbuffer) == sizeNum)
|
await transp.readExactly(addr rbuffer[0], sizeNum)
|
||||||
doAssert(equalMem(addr rbuffer[0], addr lbuffer[0], sizeNum))
|
var lbuffer = readFile(pathname)
|
||||||
var answer = "OK\r\n"
|
doAssert(len(lbuffer) == sizeNum)
|
||||||
var res = await transp.write(cast[pointer](addr answer[0]), len(answer))
|
doAssert(equalMem(addr rbuffer[0], addr lbuffer[0], sizeNum))
|
||||||
doAssert(res == len(answer))
|
var answer = "OK\r\n"
|
||||||
transp.close()
|
var res = await transp.write(cast[pointer](addr answer[0]), len(answer))
|
||||||
await transp.join()
|
doAssert(res == len(answer))
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc serveClient7(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient7(server: StreamServer, transp: StreamTransport) {.
|
||||||
var answer = "DONE\r\n"
|
async: (raises: []).} =
|
||||||
var expect = ""
|
try:
|
||||||
var line = await transp.readLine()
|
var answer = "DONE\r\n"
|
||||||
doAssert(len(line) == BigMessageCount * len(BigMessagePattern))
|
var expect = ""
|
||||||
for i in 0..<BigMessageCount:
|
var line = await transp.readLine()
|
||||||
expect.add(BigMessagePattern)
|
doAssert(len(line) == BigMessageCount * len(BigMessagePattern))
|
||||||
doAssert(line == expect)
|
for i in 0..<BigMessageCount:
|
||||||
var res = await transp.write(answer)
|
expect.add(BigMessagePattern)
|
||||||
doAssert(res == len(answer))
|
doAssert(line == expect)
|
||||||
transp.close()
|
var res = await transp.write(answer)
|
||||||
await transp.join()
|
doAssert(res == len(answer))
|
||||||
server.stop()
|
transp.close()
|
||||||
server.close()
|
await transp.join()
|
||||||
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc serveClient8(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient8(server: StreamServer, transp: StreamTransport) {.
|
||||||
var answer = "DONE\r\n"
|
async: (raises: []).} =
|
||||||
var strpattern = BigMessagePattern
|
try:
|
||||||
var pattern = newSeq[byte](len(BigMessagePattern))
|
var answer = "DONE\r\n"
|
||||||
var expect = newSeq[byte]()
|
var strpattern = BigMessagePattern
|
||||||
var data = newSeq[byte]((BigMessageCount + 1) * len(BigMessagePattern))
|
var pattern = newSeq[byte](len(BigMessagePattern))
|
||||||
var sep = @[0x0D'u8, 0x0A'u8]
|
var expect = newSeq[byte]()
|
||||||
copyMem(addr pattern[0], addr strpattern[0], len(BigMessagePattern))
|
var data = newSeq[byte]((BigMessageCount + 1) * len(BigMessagePattern))
|
||||||
var count = await transp.readUntil(addr data[0], len(data), sep = sep)
|
var sep = @[0x0D'u8, 0x0A'u8]
|
||||||
doAssert(count == BigMessageCount * len(BigMessagePattern) + 2)
|
copyMem(addr pattern[0], addr strpattern[0], len(BigMessagePattern))
|
||||||
for i in 0..<BigMessageCount:
|
var count = await transp.readUntil(addr data[0], len(data), sep = sep)
|
||||||
expect.add(pattern)
|
doAssert(count == BigMessageCount * len(BigMessagePattern) + 2)
|
||||||
expect.add(sep)
|
for i in 0..<BigMessageCount:
|
||||||
data.setLen(count)
|
expect.add(pattern)
|
||||||
doAssert(expect == data)
|
expect.add(sep)
|
||||||
var res = await transp.write(answer)
|
data.setLen(count)
|
||||||
doAssert(res == len(answer))
|
doAssert(expect == data)
|
||||||
transp.close()
|
var res = await transp.write(answer)
|
||||||
await transp.join()
|
doAssert(res == len(answer))
|
||||||
server.stop()
|
transp.close()
|
||||||
server.close()
|
await transp.join()
|
||||||
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc swarmWorker1(address: TransportAddress): Future[int] {.async.} =
|
proc swarmWorker1(address: TransportAddress): Future[int] {.async.} =
|
||||||
var transp = await connect(address)
|
var transp = await connect(address)
|
||||||
|
@ -399,18 +423,22 @@ suite "Stream Transport test suite":
|
||||||
var res = workers[i].read()
|
var res = workers[i].read()
|
||||||
result += res
|
result += res
|
||||||
|
|
||||||
proc serveClient(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient(server: StreamServer, transp: StreamTransport) {.
|
||||||
var data = await transp.read()
|
async: (raises: []).} =
|
||||||
doAssert(len(data) == len(ConstantMessage) * MessagesCount)
|
try:
|
||||||
transp.close()
|
var data = await transp.read()
|
||||||
var expect = ""
|
doAssert(len(data) == len(ConstantMessage) * MessagesCount)
|
||||||
for i in 0..<MessagesCount:
|
transp.close()
|
||||||
expect.add(ConstantMessage)
|
var expect = ""
|
||||||
doAssert(equalMem(addr expect[0], addr data[0], len(data)))
|
for i in 0..<MessagesCount:
|
||||||
dec(counter)
|
expect.add(ConstantMessage)
|
||||||
if counter == 0:
|
doAssert(equalMem(addr expect[0], addr data[0], len(data)))
|
||||||
server.stop()
|
dec(counter)
|
||||||
server.close()
|
if counter == 0:
|
||||||
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||||
server.start()
|
server.start()
|
||||||
|
@ -420,18 +448,22 @@ suite "Stream Transport test suite":
|
||||||
proc testWCR(address: TransportAddress): Future[int] {.async.} =
|
proc testWCR(address: TransportAddress): Future[int] {.async.} =
|
||||||
var counter = ClientsCount
|
var counter = ClientsCount
|
||||||
|
|
||||||
proc serveClient(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient(server: StreamServer, transp: StreamTransport) {.
|
||||||
var expect = ConstantMessage
|
async: (raises: []).} =
|
||||||
var skip = await transp.consume(len(ConstantMessage) * (MessagesCount - 1))
|
try:
|
||||||
doAssert(skip == len(ConstantMessage) * (MessagesCount - 1))
|
var expect = ConstantMessage
|
||||||
var data = await transp.read()
|
var skip = await transp.consume(len(ConstantMessage) * (MessagesCount - 1))
|
||||||
doAssert(len(data) == len(ConstantMessage))
|
doAssert(skip == len(ConstantMessage) * (MessagesCount - 1))
|
||||||
transp.close()
|
var data = await transp.read()
|
||||||
doAssert(equalMem(addr data[0], addr expect[0], len(expect)))
|
doAssert(len(data) == len(ConstantMessage))
|
||||||
dec(counter)
|
transp.close()
|
||||||
if counter == 0:
|
doAssert(equalMem(addr data[0], addr expect[0], len(expect)))
|
||||||
server.stop()
|
dec(counter)
|
||||||
server.close()
|
if counter == 0:
|
||||||
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc swarmWorker(address: TransportAddress): Future[int] {.async.} =
|
proc swarmWorker(address: TransportAddress): Future[int] {.async.} =
|
||||||
var transp = await connect(address)
|
var transp = await connect(address)
|
||||||
|
@ -534,11 +566,15 @@ suite "Stream Transport test suite":
|
||||||
# server.close()
|
# server.close()
|
||||||
# await server.join()
|
# await server.join()
|
||||||
|
|
||||||
proc serveClient11(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient11(server: StreamServer, transp: StreamTransport) {.
|
||||||
var res = await transp.write(BigMessagePattern)
|
async: (raises: []).} =
|
||||||
doAssert(res == len(BigMessagePattern))
|
try:
|
||||||
transp.close()
|
var res = await transp.write(BigMessagePattern)
|
||||||
await transp.join()
|
doAssert(res == len(BigMessagePattern))
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc swarmWorker11(address: TransportAddress): Future[int] {.async.} =
|
proc swarmWorker11(address: TransportAddress): Future[int] {.async.} =
|
||||||
var buffer: array[len(BigMessagePattern) + 1, byte]
|
var buffer: array[len(BigMessagePattern) + 1, byte]
|
||||||
|
@ -558,11 +594,15 @@ suite "Stream Transport test suite":
|
||||||
server.close()
|
server.close()
|
||||||
await server.join()
|
await server.join()
|
||||||
|
|
||||||
proc serveClient12(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient12(server: StreamServer, transp: StreamTransport) {.
|
||||||
var res = await transp.write(BigMessagePattern)
|
async: (raises: []).} =
|
||||||
doAssert(res == len(BigMessagePattern))
|
try:
|
||||||
transp.close()
|
var res = await transp.write(BigMessagePattern)
|
||||||
await transp.join()
|
doAssert(res == len(BigMessagePattern))
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc swarmWorker12(address: TransportAddress): Future[int] {.async.} =
|
proc swarmWorker12(address: TransportAddress): Future[int] {.async.} =
|
||||||
var buffer: array[len(BigMessagePattern), byte]
|
var buffer: array[len(BigMessagePattern), byte]
|
||||||
|
@ -584,9 +624,13 @@ suite "Stream Transport test suite":
|
||||||
server.close()
|
server.close()
|
||||||
await server.join()
|
await server.join()
|
||||||
|
|
||||||
proc serveClient13(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient13(server: StreamServer, transp: StreamTransport) {.
|
||||||
transp.close()
|
async: (raises: []).} =
|
||||||
await transp.join()
|
try:
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc swarmWorker13(address: TransportAddress): Future[int] {.async.} =
|
proc swarmWorker13(address: TransportAddress): Future[int] {.async.} =
|
||||||
var transp = await connect(address)
|
var transp = await connect(address)
|
||||||
|
@ -645,11 +689,15 @@ suite "Stream Transport test suite":
|
||||||
else:
|
else:
|
||||||
return (e.code == oserrno.ECONNREFUSED) or (e.code == oserrno.ENOENT)
|
return (e.code == oserrno.ECONNREFUSED) or (e.code == oserrno.ENOENT)
|
||||||
|
|
||||||
proc serveClient16(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient16(server: StreamServer, transp: StreamTransport) {.
|
||||||
var res = await transp.write(BigMessagePattern)
|
async: (raises: []).} =
|
||||||
doAssert(res == len(BigMessagePattern))
|
try:
|
||||||
transp.close()
|
var res = await transp.write(BigMessagePattern)
|
||||||
await transp.join()
|
doAssert(res == len(BigMessagePattern))
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
proc swarmWorker16(address: TransportAddress): Future[int] {.async.} =
|
proc swarmWorker16(address: TransportAddress): Future[int] {.async.} =
|
||||||
var buffer = newString(5)
|
var buffer = newString(5)
|
||||||
|
@ -680,7 +728,8 @@ suite "Stream Transport test suite":
|
||||||
await server.join()
|
await server.join()
|
||||||
|
|
||||||
proc testCloseTransport(address: TransportAddress): Future[int] {.async.} =
|
proc testCloseTransport(address: TransportAddress): Future[int] {.async.} =
|
||||||
proc client(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc client(server: StreamServer, transp: StreamTransport) {.
|
||||||
|
async: (raises: []).} =
|
||||||
discard
|
discard
|
||||||
var server = createStreamServer(address, client, {ReuseAddr})
|
var server = createStreamServer(address, client, {ReuseAddr})
|
||||||
server.start()
|
server.start()
|
||||||
|
@ -694,9 +743,12 @@ suite "Stream Transport test suite":
|
||||||
|
|
||||||
proc testWriteConnReset(address: TransportAddress): Future[int] {.async.} =
|
proc testWriteConnReset(address: TransportAddress): Future[int] {.async.} =
|
||||||
var syncFut = newFuture[void]()
|
var syncFut = newFuture[void]()
|
||||||
proc client(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc client(server: StreamServer, transp: StreamTransport) {.async: (raises: []).} =
|
||||||
await transp.closeWait()
|
try:
|
||||||
syncFut.complete()
|
await transp.closeWait()
|
||||||
|
syncFut.complete()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
var n = 10
|
var n = 10
|
||||||
var server = createStreamServer(address, client, {ReuseAddr})
|
var server = createStreamServer(address, client, {ReuseAddr})
|
||||||
server.start()
|
server.start()
|
||||||
|
@ -721,12 +773,16 @@ suite "Stream Transport test suite":
|
||||||
var serverRemote, serverLocal: TransportAddress
|
var serverRemote, serverLocal: TransportAddress
|
||||||
var connRemote, connLocal: TransportAddress
|
var connRemote, connLocal: TransportAddress
|
||||||
|
|
||||||
proc serveClient(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient(server: StreamServer, transp: StreamTransport) {.
|
||||||
serverRemote = transp.remoteAddress()
|
async: (raises: []).} =
|
||||||
serverLocal = transp.localAddress()
|
try:
|
||||||
await transp.closeWait()
|
serverRemote = transp.remoteAddress()
|
||||||
server.stop()
|
serverLocal = transp.localAddress()
|
||||||
server.close()
|
await transp.closeWait()
|
||||||
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var ta = initTAddress("0.0.0.0:0")
|
var ta = initTAddress("0.0.0.0:0")
|
||||||
var server = createStreamServer(ta, serveClient, {ReuseAddr})
|
var server = createStreamServer(ta, serveClient, {ReuseAddr})
|
||||||
|
@ -748,13 +804,17 @@ suite "Stream Transport test suite":
|
||||||
var bigMessageSize = 10 * 1024 * 1024 - 1
|
var bigMessageSize = 10 * 1024 * 1024 - 1
|
||||||
var finishMessage = "DONE"
|
var finishMessage = "DONE"
|
||||||
var cdata = newSeqOfCap[byte](bigMessageSize)
|
var cdata = newSeqOfCap[byte](bigMessageSize)
|
||||||
proc serveClient(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient(server: StreamServer, transp: StreamTransport) {.
|
||||||
cdata = await transp.read(bigMessageSize)
|
async: (raises: []).} =
|
||||||
var size = await transp.write(finishMessage)
|
try:
|
||||||
doAssert(size == len(finishMessage))
|
cdata = await transp.read(bigMessageSize)
|
||||||
await transp.closeWait()
|
var size = await transp.write(finishMessage)
|
||||||
server.stop()
|
doAssert(size == len(finishMessage))
|
||||||
server.close()
|
await transp.closeWait()
|
||||||
|
server.stop()
|
||||||
|
server.close()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var flag = false
|
var flag = false
|
||||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||||
|
@ -787,10 +847,15 @@ suite "Stream Transport test suite":
|
||||||
result = flag
|
result = flag
|
||||||
|
|
||||||
proc testReadLine(address: TransportAddress): Future[bool] {.async.} =
|
proc testReadLine(address: TransportAddress): Future[bool] {.async.} =
|
||||||
proc serveClient(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient(server: StreamServer, transp: StreamTransport) {.
|
||||||
discard await transp.write("DATA\r\r\r\r\r\n")
|
async: (raises: []).} =
|
||||||
transp.close()
|
try:
|
||||||
await transp.join()
|
discard await transp.write("DATA\r\r\r\r\r\n")
|
||||||
|
transp.close()
|
||||||
|
await transp.join()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
|
|
||||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||||
server.start()
|
server.start()
|
||||||
|
@ -895,52 +960,56 @@ suite "Stream Transport test suite":
|
||||||
var state = 0
|
var state = 0
|
||||||
var c1, c2, c3, c4, c5, c6, c7: bool
|
var c1, c2, c3, c4, c5, c6, c7: bool
|
||||||
|
|
||||||
proc serveClient(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc serveClient(server: StreamServer, transp: StreamTransport) {.
|
||||||
if state == 0:
|
async: (raises: []).} =
|
||||||
# EOF from the beginning.
|
try:
|
||||||
state = 1
|
if state == 0:
|
||||||
await transp.closeWait()
|
# EOF from the beginning.
|
||||||
elif state == 1:
|
state = 1
|
||||||
# Message has only zero-size header.
|
await transp.closeWait()
|
||||||
var message = createLVMessage(0'u32)
|
elif state == 1:
|
||||||
discard await transp.write(message)
|
# Message has only zero-size header.
|
||||||
state = 2
|
var message = createLVMessage(0'u32)
|
||||||
await transp.closeWait()
|
discard await transp.write(message)
|
||||||
elif state == 2:
|
state = 2
|
||||||
# Message has header, but do not have any data at all.
|
await transp.closeWait()
|
||||||
var message = createLVMessage(4'u32)
|
elif state == 2:
|
||||||
message.setLen(4)
|
# Message has header, but do not have any data at all.
|
||||||
discard await transp.write(message)
|
var message = createLVMessage(4'u32)
|
||||||
state = 3
|
message.setLen(4)
|
||||||
await transp.closeWait()
|
discard await transp.write(message)
|
||||||
elif state == 3:
|
state = 3
|
||||||
# Message do not have enough data for specified size in header.
|
await transp.closeWait()
|
||||||
var message = createLVMessage(1024'u32)
|
elif state == 3:
|
||||||
message.setLen(1024)
|
# Message do not have enough data for specified size in header.
|
||||||
discard await transp.write(message)
|
var message = createLVMessage(1024'u32)
|
||||||
state = 4
|
message.setLen(1024)
|
||||||
await transp.closeWait()
|
discard await transp.write(message)
|
||||||
elif state == 4:
|
state = 4
|
||||||
# Good encoded message with oversize.
|
await transp.closeWait()
|
||||||
var message = createLVMessage(1024'u32)
|
elif state == 4:
|
||||||
discard await transp.write(message)
|
# Good encoded message with oversize.
|
||||||
state = 5
|
var message = createLVMessage(1024'u32)
|
||||||
await transp.closeWait()
|
discard await transp.write(message)
|
||||||
elif state == 5:
|
state = 5
|
||||||
# Good encoded message.
|
await transp.closeWait()
|
||||||
var message = createLVMessage(1024'u32)
|
elif state == 5:
|
||||||
discard await transp.write(message)
|
# Good encoded message.
|
||||||
state = 6
|
var message = createLVMessage(1024'u32)
|
||||||
await transp.closeWait()
|
discard await transp.write(message)
|
||||||
elif state == 6:
|
state = 6
|
||||||
# Good encoded message with additional data.
|
await transp.closeWait()
|
||||||
var message = createLVMessage(1024'u32)
|
elif state == 6:
|
||||||
discard await transp.write(message)
|
# Good encoded message with additional data.
|
||||||
discard await transp.write("DONE")
|
var message = createLVMessage(1024'u32)
|
||||||
state = 7
|
discard await transp.write(message)
|
||||||
await transp.closeWait()
|
discard await transp.write("DONE")
|
||||||
else:
|
state = 7
|
||||||
doAssert(false)
|
await transp.closeWait()
|
||||||
|
else:
|
||||||
|
doAssert(false)
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
var server = createStreamServer(address, serveClient, {ReuseAddr})
|
||||||
server.start()
|
server.start()
|
||||||
|
@ -1260,8 +1329,11 @@ suite "Stream Transport test suite":
|
||||||
|
|
||||||
proc testConnectBindLocalAddress() {.async.} =
|
proc testConnectBindLocalAddress() {.async.} =
|
||||||
|
|
||||||
proc client(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc client(server: StreamServer, transp: StreamTransport) {.async: (raises: []).} =
|
||||||
await transp.closeWait()
|
try:
|
||||||
|
await transp.closeWait()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
let server1 = createStreamServer(initTAddress("127.0.0.1:0"), client)
|
let server1 = createStreamServer(initTAddress("127.0.0.1:0"), client)
|
||||||
let server2 = createStreamServer(initTAddress("127.0.0.1:0"), client)
|
let server2 = createStreamServer(initTAddress("127.0.0.1:0"), client)
|
||||||
|
@ -1302,8 +1374,11 @@ suite "Stream Transport test suite":
|
||||||
await server3.closeWait()
|
await server3.closeWait()
|
||||||
|
|
||||||
proc testConnectCancelLeaksTest() {.async.} =
|
proc testConnectCancelLeaksTest() {.async.} =
|
||||||
proc client(server: StreamServer, transp: StreamTransport) {.async.} =
|
proc client(server: StreamServer, transp: StreamTransport) {.async: (raises: []).} =
|
||||||
await transp.closeWait()
|
try:
|
||||||
|
await transp.closeWait()
|
||||||
|
except CatchableError as exc:
|
||||||
|
raiseAssert exc.msg
|
||||||
|
|
||||||
let
|
let
|
||||||
server = createStreamServer(initTAddress("127.0.0.1:0"), client)
|
server = createStreamServer(initTAddress("127.0.0.1:0"), client)
|
||||||
|
|
Loading…
Reference in New Issue