Module asyncnet

This module implements a high-level asynchronous sockets API based on the asynchronous dispatcher defined in the asyncdispatch module.

SSL ---

SSL can be enabled by compiling with the -d:ssl flag.

You must create a new SSL context with the newContext function defined in the net module. You may then call wrapSocket on your socket using the newly created SSL context to get an SSL socket.

Examples

Chat server

The following example demonstrates a simple chat server.

import asyncnet, asyncdispatch

var clients {.threadvar.}: seq[AsyncSocket]

proc processClient(client: AsyncSocket) {.async.} =
  while true:
    let line = await client.recvLine()
    for c in clients:
      await c.send(line & "\c\L")

proc serve() {.async.} =
  clients = @[]
  var server = newAsyncSocket()
  server.bindAddr(Port(12345))
  server.listen()
  
  while true:
    let client = await server.accept()
    clients.add client
    
    asyncCheck processClient(client)

asyncCheck serve()
runForever()

Types

AsyncSocket = ref AsyncSocketDesc
  Source

Procs

proc newAsyncSocket(fd: TAsyncFD; isBuff: bool): AsyncSocket {.raises: [], 
    tags: [].}
Creates a new AsyncSocket based on the supplied params.   Source
proc newAsyncSocket(domain: Domain = AF_INET; typ: SockType = SOCK_STREAM; 
                    protocol: Protocol = IPPROTO_TCP; buffered = true): AsyncSocket {.
    raises: [OSError], tags: [].}

Creates a new asynchronous socket.

This procedure will also create a brand new file descriptor for this socket.

  Source
proc newAsyncSocket(domain, typ, protocol: cint; buffered = true): AsyncSocket {.
    raises: [OSError], tags: [].}

Creates a new asynchronous socket.

This procedure will also create a brand new file descriptor for this socket.

  Source
proc connect(socket: AsyncSocket; address: string; port: Port; af = AF_INET): Future[
    void] {.raises: [], tags: [RootEffect].}

Connects socket to server at address:port.

Returns a Future which will complete when the connection succeeds or an error occurs.

  Source
proc recv(socket: AsyncSocket; size: int; flags = {SafeDisconn}): Future[string] {.
    raises: [], tags: [RootEffect].}

Reads up to size bytes from socket.

For buffered sockets this function will attempt to read all the requested data. It will read this data in BufferSize chunks.

For unbuffered sockets this function makes no effort to read all the data requested. It will return as much data as the operating system gives it.

If socket is disconnected during the recv operation then the future may complete with only a part of the requested data.

If socket is disconnected and no data is available to be read then the future will complete with a value of "".

  Source
proc send(socket: AsyncSocket; data: string; flags = {SafeDisconn}): Future[void] {.
    raises: [], tags: [RootEffect].}
Sends data to socket. The returned future will complete once all data has been sent.   Source
proc acceptAddr(socket: AsyncSocket; flags = {SafeDisconn}): Future[
    tuple[address: string, client: AsyncSocket]] {.
    raises: [ValueError, OSError, Exception], tags: [RootEffect].}
Accepts a new connection. Returns a future containing the client socket corresponding to that connection and the remote address of the client. The future will complete when the connection is successfully accepted.   Source
proc accept(socket: AsyncSocket; flags = {SafeDisconn}): Future[AsyncSocket] {.
    raises: [ValueError, OSError, Exception], tags: [RootEffect].}
Accepts a new connection. Returns a future containing the client socket corresponding to that connection. The future will complete when the connection is successfully accepted.   Source
proc recvLineInto(socket: AsyncSocket; resString: ptr string; 
                  flags = {SafeDisconn}): Future[void] {.raises: [], 
    tags: [RootEffect].}

Reads a line of data from socket into resString.

If a full line is read \r\L is not added to line, however if solely \r\L is read then line will be set to it.

If the socket is disconnected, line will be set to "".

If the socket is disconnected in the middle of a line (before \r\L is read) then line will be set to "". The partial line will be lost.

Warning: The Peek flag is not yet implemented.

Warning: recvLineInto on unbuffered sockets assumes that the protocol uses \r\L to delimit a new line.

Warning: recvLineInto currently uses a raw pointer to a string for performance reasons. This will likely change soon to use FutureVars.

  Source
proc recvLine(socket: AsyncSocket; flags = {SafeDisconn}): Future[string] {.
    raises: [], tags: [RootEffect].}

Reads a line of data from socket. Returned future will complete once a full line is read or an error occurs.

If a full line is read \r\L is not added to line, however if solely \r\L is read then line will be set to it.

If the socket is disconnected, line will be set to "".

If the socket is disconnected in the middle of a line (before \r\L is read) then line will be set to "". The partial line will be lost.

Warning: The Peek flag is not yet implemented.

Warning: recvLine on unbuffered sockets assumes that the protocol uses \r\L to delimit a new line.

  Source
proc listen(socket: AsyncSocket; backlog = SOMAXCONN) {.tags: [ReadIOEffect], 
    raises: [OSError].}

Marks socket as accepting connections. Backlog specifies the maximum length of the queue of pending connections.

Raises an EOS error upon failure.

  Source
proc bindAddr(socket: AsyncSocket; port = Port(0); address = "") {.
    tags: [ReadIOEffect], raises: [OSError].}

Binds address:port to the socket.

If address is "" then ADDR_ANY will be bound.

  Source
proc close(socket: AsyncSocket) {.raises: [], tags: [].}
Closes the socket.   Source
proc getSockOpt(socket: AsyncSocket; opt: SOBool; level = SOL_SOCKET): bool {.
    tags: [ReadIOEffect], raises: [OSError].}
Retrieves option opt as a boolean value.   Source
proc setSockOpt(socket: AsyncSocket; opt: SOBool; value: bool; 
                level = SOL_SOCKET) {.tags: [WriteIOEffect], raises: [OSError].}
Sets option opt to a boolean value specified by value.   Source
proc isSsl(socket: AsyncSocket): bool {.raises: [], tags: [].}
Determines whether socket is a SSL socket.   Source
proc getFd(socket: AsyncSocket): SocketHandle {.raises: [], tags: [].}
Returns the socket's file descriptor.   Source
proc isClosed(socket: AsyncSocket): bool {.raises: [], tags: [].}
Determines whether the socket has been closed.   Source