use single backtick (#17166)
This commit is contained in:
parent
c274e67198
commit
47c078e29c
12 changed files with 305 additions and 305 deletions
|
|
@ -8,27 +8,27 @@
|
|||
#
|
||||
|
||||
## This module implements a high-level asynchronous sockets API based on the
|
||||
## asynchronous dispatcher defined in the ``asyncdispatch`` module.
|
||||
## asynchronous dispatcher defined in the `asyncdispatch` module.
|
||||
##
|
||||
## Asynchronous IO in Nim
|
||||
## ======================
|
||||
##
|
||||
## Async IO in Nim consists of multiple layers (from highest to lowest):
|
||||
##
|
||||
## * ``asyncnet`` module
|
||||
## * `asyncnet` module
|
||||
##
|
||||
## * Async await
|
||||
##
|
||||
## * ``asyncdispatch`` module (event loop)
|
||||
## * `asyncdispatch` module (event loop)
|
||||
##
|
||||
## * ``selectors`` module
|
||||
## * `selectors` module
|
||||
##
|
||||
## Each builds on top of the layers below it. The selectors module is an
|
||||
## abstraction for the various system ``select()`` mechanisms such as epoll or
|
||||
## abstraction for the various system `select()` mechanisms such as epoll or
|
||||
## kqueue. If you wish you can use it directly, and some people have done so
|
||||
## `successfully <http://goran.krampe.se/2014/10/25/nim-socketserver/>`_.
|
||||
## But you must be aware that on Windows it only supports
|
||||
## ``select()``.
|
||||
## `select()`.
|
||||
##
|
||||
## The async dispatcher implements the proactor pattern and also has an
|
||||
## implementation of IOCP. It implements the proactor pattern for other
|
||||
|
|
@ -45,16 +45,16 @@
|
|||
## layers interchangeably (as long as you only care about non-Windows
|
||||
## platforms).
|
||||
##
|
||||
## For most applications using ``asyncnet`` is the way to go as it builds
|
||||
## For most applications using `asyncnet` is the way to go as it builds
|
||||
## over all the layers, providing some extra features such as buffering.
|
||||
##
|
||||
## SSL
|
||||
## ===
|
||||
##
|
||||
## SSL can be enabled by compiling with the ``-d:ssl`` flag.
|
||||
## 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
|
||||
## 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
|
||||
|
|
@ -134,16 +134,16 @@ proc newAsyncSocket*(fd: AsyncFD, domain: Domain = AF_INET,
|
|||
protocol: Protocol = IPPROTO_TCP,
|
||||
buffered = true,
|
||||
inheritable = defined(nimInheritHandles)): owned(AsyncSocket) =
|
||||
## Creates a new ``AsyncSocket`` based on the supplied params.
|
||||
## Creates a new `AsyncSocket` based on the supplied params.
|
||||
##
|
||||
## The supplied ``fd``'s non-blocking state will be enabled implicitly.
|
||||
## The supplied `fd`'s non-blocking state will be enabled implicitly.
|
||||
##
|
||||
## If ``inheritable`` is false (the default), the supplied ``fd`` will not
|
||||
## If `inheritable` is false (the default), the supplied `fd` will not
|
||||
## be inheritable by child processes.
|
||||
##
|
||||
## **Note**: This procedure will **NOT** register ``fd`` with the global
|
||||
## **Note**: This procedure will **NOT** register `fd` with the global
|
||||
## async dispatcher. You need to do this manually. If you have used
|
||||
## ``newAsyncNativeSocket`` to create ``fd`` then it's already registered.
|
||||
## `newAsyncNativeSocket` to create `fd` then it's already registered.
|
||||
assert fd != osInvalidSocket.AsyncFD
|
||||
new(result)
|
||||
result.fd = fd.SocketHandle
|
||||
|
|
@ -165,7 +165,7 @@ proc newAsyncSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
|
|||
## This procedure will also create a brand new file descriptor for
|
||||
## this socket.
|
||||
##
|
||||
## If ``inheritable`` is false (the default), the new file descriptor will not
|
||||
## If `inheritable` is false (the default), the new file descriptor will not
|
||||
## be inheritable by child processes.
|
||||
let fd = createAsyncNativeSocket(domain, sockType, protocol, inheritable)
|
||||
if fd.SocketHandle == osInvalidSocket:
|
||||
|
|
@ -192,7 +192,7 @@ proc newAsyncSocket*(domain, sockType, protocol: cint,
|
|||
## This procedure will also create a brand new file descriptor for
|
||||
## this socket.
|
||||
##
|
||||
## If ``inheritable`` is false (the default), the new file descriptor will not
|
||||
## If `inheritable` is false (the default), the new file descriptor will not
|
||||
## be inheritable by child processes.
|
||||
let fd = createAsyncNativeSocket(domain, sockType, protocol, inheritable)
|
||||
if fd.SocketHandle == osInvalidSocket:
|
||||
|
|
@ -233,7 +233,7 @@ when defineSsl:
|
|||
|
||||
proc appeaseSsl(socket: AsyncSocket, flags: set[SocketFlag],
|
||||
sslError: cint): owned(Future[bool]) {.async.} =
|
||||
## Returns ``true`` if ``socket`` is still connected, otherwise ``false``.
|
||||
## Returns `true` if `socket` is still connected, otherwise `false`.
|
||||
result = true
|
||||
case sslError
|
||||
of SSL_ERROR_WANT_WRITE:
|
||||
|
|
@ -279,9 +279,9 @@ when defineSsl:
|
|||
|
||||
proc dial*(address: string, port: Port, protocol = IPPROTO_TCP,
|
||||
buffered = true): owned(Future[AsyncSocket]) {.async.} =
|
||||
## Establishes connection to the specified ``address``:``port`` pair via the
|
||||
## Establishes connection to the specified `address`:`port` pair via the
|
||||
## specified protocol. The procedure iterates through possible
|
||||
## resolutions of the ``address`` until it succeeds, meaning that it
|
||||
## resolutions of the `address` until it succeeds, meaning that it
|
||||
## seamlessly works with both IPv4 and IPv6.
|
||||
## Returns AsyncSocket ready to send or receive data.
|
||||
let asyncFd = await asyncdispatch.dial(address, port, protocol)
|
||||
|
|
@ -290,9 +290,9 @@ proc dial*(address: string, port: Port, protocol = IPPROTO_TCP,
|
|||
result = newAsyncSocket(asyncFd, domain, sockType, protocol, buffered)
|
||||
|
||||
proc connect*(socket: AsyncSocket, address: string, port: Port) {.async.} =
|
||||
## Connects ``socket`` to server at ``address:port``.
|
||||
## Connects `socket` to server at `address:port`.
|
||||
##
|
||||
## Returns a ``Future`` which will complete when the connection succeeds
|
||||
## Returns a `Future` which will complete when the connection succeeds
|
||||
## or an error occurs.
|
||||
await connect(socket.fd.AsyncFD, address, port, socket.domain)
|
||||
if socket.isSsl:
|
||||
|
|
@ -308,7 +308,7 @@ proc connect*(socket: AsyncSocket, address: string, port: Port) {.async.} =
|
|||
|
||||
template readInto(buf: pointer, size: int, socket: AsyncSocket,
|
||||
flags: set[SocketFlag]): int =
|
||||
## Reads **up to** ``size`` bytes from ``socket`` into ``buf``. Note that
|
||||
## Reads **up to** `size` bytes from `socket` into `buf`. Note that
|
||||
## this is a template and not a proc.
|
||||
assert(not socket.closed, "Cannot `recv` on a closed socket")
|
||||
var res = 0
|
||||
|
|
@ -332,10 +332,10 @@ template readIntoBuf(socket: AsyncSocket,
|
|||
|
||||
proc recvInto*(socket: AsyncSocket, buf: pointer, size: int,
|
||||
flags = {SocketFlag.SafeDisconn}): owned(Future[int]) {.async.} =
|
||||
## Reads **up to** ``size`` bytes from ``socket`` into ``buf``.
|
||||
## Reads **up to** `size` bytes from `socket` into `buf`.
|
||||
##
|
||||
## For buffered sockets this function will attempt to read all the requested
|
||||
## data. It will read this data in ``BufferSize`` chunks.
|
||||
## 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
|
||||
|
|
@ -346,7 +346,7 @@ proc recvInto*(socket: AsyncSocket, buf: pointer, size: int,
|
|||
## requested data.
|
||||
##
|
||||
## If socket is disconnected and no data is available
|
||||
## to be read then the future will complete with a value of ``0``.
|
||||
## to be read then the future will complete with a value of `0`.
|
||||
if socket.isBuffered:
|
||||
let originalBufPos = socket.currPos
|
||||
|
||||
|
|
@ -380,10 +380,10 @@ proc recvInto*(socket: AsyncSocket, buf: pointer, size: int,
|
|||
|
||||
proc recv*(socket: AsyncSocket, size: int,
|
||||
flags = {SocketFlag.SafeDisconn}): owned(Future[string]) {.async.} =
|
||||
## Reads **up to** ``size`` bytes from ``socket``.
|
||||
## 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.
|
||||
## 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
|
||||
|
|
@ -394,7 +394,7 @@ proc recv*(socket: AsyncSocket, size: int,
|
|||
## requested data.
|
||||
##
|
||||
## If socket is disconnected and no data is available
|
||||
## to be read then the future will complete with a value of ``""``.
|
||||
## to be read then the future will complete with a value of `""`.
|
||||
if socket.isBuffered:
|
||||
result = newString(size)
|
||||
shallow(result)
|
||||
|
|
@ -432,7 +432,7 @@ proc recv*(socket: AsyncSocket, size: int,
|
|||
|
||||
proc send*(socket: AsyncSocket, buf: pointer, size: int,
|
||||
flags = {SocketFlag.SafeDisconn}) {.async.} =
|
||||
## Sends ``size`` bytes from ``buf`` to ``socket``. The returned future will complete once all
|
||||
## Sends `size` bytes from `buf` to `socket`. The returned future will complete once all
|
||||
## data has been sent.
|
||||
assert socket != nil
|
||||
assert(not socket.closed, "Cannot `send` on a closed socket")
|
||||
|
|
@ -446,7 +446,7 @@ proc send*(socket: AsyncSocket, buf: pointer, size: int,
|
|||
|
||||
proc send*(socket: AsyncSocket, data: string,
|
||||
flags = {SocketFlag.SafeDisconn}) {.async.} =
|
||||
## Sends ``data`` to ``socket``. The returned future will complete once all
|
||||
## Sends `data` to `socket`. The returned future will complete once all
|
||||
## data has been sent.
|
||||
assert socket != nil
|
||||
if socket.isSsl:
|
||||
|
|
@ -464,7 +464,7 @@ proc acceptAddr*(socket: AsyncSocket, flags = {SocketFlag.SafeDisconn},
|
|||
## Accepts a new connection. Returns a future containing the client socket
|
||||
## corresponding to that connection and the remote address of the client.
|
||||
##
|
||||
## If ``inheritable`` is false (the default), the resulting client socket will
|
||||
## If `inheritable` is false (the default), the resulting client socket will
|
||||
## not be inheritable by child processes.
|
||||
##
|
||||
## The future will complete when the connection is successfully accepted.
|
||||
|
|
@ -486,7 +486,7 @@ proc accept*(socket: AsyncSocket,
|
|||
flags = {SocketFlag.SafeDisconn}): owned(Future[AsyncSocket]) =
|
||||
## Accepts a new connection. Returns a future containing the client socket
|
||||
## corresponding to that connection.
|
||||
## If ``inheritable`` is false (the default), the resulting client socket will
|
||||
## If `inheritable` is false (the default), the resulting client socket will
|
||||
## not be inheritable by child processes.
|
||||
## The future will complete when the connection is successfully accepted.
|
||||
var retFut = newFuture[AsyncSocket]("asyncnet.accept")
|
||||
|
|
@ -502,25 +502,25 @@ proc accept*(socket: AsyncSocket,
|
|||
|
||||
proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string],
|
||||
flags = {SocketFlag.SafeDisconn}, maxLength = MaxLineLength) {.async.} =
|
||||
## Reads a line of data from ``socket`` into ``resString``.
|
||||
## 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``
|
||||
## 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, `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 ``""``.
|
||||
## 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**.
|
||||
##
|
||||
## The ``maxLength`` parameter determines the maximum amount of characters
|
||||
## that can be read. ``resString`` will be truncated after that.
|
||||
## The `maxLength` parameter determines the maximum amount of characters
|
||||
## that can be read. `resString` will be truncated after that.
|
||||
##
|
||||
## **Warning**: The ``Peek`` flag is not yet implemented.
|
||||
## **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` on unbuffered sockets assumes that the
|
||||
## protocol uses `\r\L` to delimit a new line.
|
||||
assert SocketFlag.Peek notin flags ## TODO:
|
||||
result = newFuture[void]("asyncnet.recvLineInto")
|
||||
|
||||
|
|
@ -595,26 +595,26 @@ proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string],
|
|||
proc recvLine*(socket: AsyncSocket,
|
||||
flags = {SocketFlag.SafeDisconn},
|
||||
maxLength = MaxLineLength): owned(Future[string]) {.async.} =
|
||||
## Reads a line of data from ``socket``. Returned future will complete once
|
||||
## 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``
|
||||
## 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, `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 ``""``.
|
||||
## 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**.
|
||||
##
|
||||
## The ``maxLength`` parameter determines the maximum amount of characters
|
||||
## The `maxLength` parameter determines the maximum amount of characters
|
||||
## that can be read. The result is truncated after that.
|
||||
##
|
||||
## **Warning**: The ``Peek`` flag is not yet implemented.
|
||||
## **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.
|
||||
## **Warning**: `recvLine` on unbuffered sockets assumes that the protocol
|
||||
## uses `\r\L` to delimit a new line.
|
||||
assert SocketFlag.Peek notin flags ## TODO:
|
||||
|
||||
# TODO: Optimise this
|
||||
|
|
@ -625,8 +625,8 @@ proc recvLine*(socket: AsyncSocket,
|
|||
|
||||
proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [
|
||||
ReadIOEffect].} =
|
||||
## Marks ``socket`` as accepting connections.
|
||||
## ``Backlog`` specifies the maximum length of the
|
||||
## Marks `socket` as accepting connections.
|
||||
## `Backlog` specifies the maximum length of the
|
||||
## queue of pending connections.
|
||||
##
|
||||
## Raises an OSError error upon failure.
|
||||
|
|
@ -634,9 +634,9 @@ proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [
|
|||
|
||||
proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.
|
||||
tags: [ReadIOEffect].} =
|
||||
## Binds ``address``:``port`` to the socket.
|
||||
## Binds `address`:`port` to the socket.
|
||||
##
|
||||
## If ``address`` is "" then ADDR_ANY will be bound.
|
||||
## If `address` is "" then ADDR_ANY will be bound.
|
||||
var realaddr = address
|
||||
if realaddr == "":
|
||||
case socket.domain
|
||||
|
|
@ -735,7 +735,7 @@ proc close*(socket: AsyncSocket) =
|
|||
when defineSsl:
|
||||
proc wrapSocket*(ctx: SslContext, socket: AsyncSocket) =
|
||||
## Wraps a socket in an SSL context. This function effectively turns
|
||||
## ``socket`` into an SSL socket.
|
||||
## `socket` into an SSL socket.
|
||||
##
|
||||
## **Disclaimer**: This code is not well tested, may be very unsafe and
|
||||
## prone to security vulnerabilities.
|
||||
|
|
@ -755,8 +755,8 @@ when defineSsl:
|
|||
handshake: SslHandshakeType,
|
||||
hostname: string = "") =
|
||||
## Wraps a connected socket in an SSL context. This function effectively
|
||||
## turns ``socket`` into an SSL socket.
|
||||
## ``hostname`` should be specified so that the client knows which hostname
|
||||
## turns `socket` into an SSL socket.
|
||||
## `hostname` should be specified so that the client knows which hostname
|
||||
## the server certificate should be validated against.
|
||||
##
|
||||
## This should be called on a connected socket, and will perform
|
||||
|
|
@ -789,18 +789,18 @@ when defineSsl:
|
|||
|
||||
proc getSockOpt*(socket: AsyncSocket, opt: SOBool, level = SOL_SOCKET): bool {.
|
||||
tags: [ReadIOEffect].} =
|
||||
## Retrieves option ``opt`` as a boolean value.
|
||||
## Retrieves option `opt` as a boolean value.
|
||||
var res = getSockOptInt(socket.fd, cint(level), toCInt(opt))
|
||||
result = res != 0
|
||||
|
||||
proc setSockOpt*(socket: AsyncSocket, opt: SOBool, value: bool,
|
||||
level = SOL_SOCKET) {.tags: [WriteIOEffect].} =
|
||||
## Sets option ``opt`` to a boolean value specified by ``value``.
|
||||
## Sets option `opt` to a boolean value specified by `value`.
|
||||
var valuei = cint(if value: 1 else: 0)
|
||||
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
||||
|
||||
proc isSsl*(socket: AsyncSocket): bool =
|
||||
## Determines whether ``socket`` is a SSL socket.
|
||||
## Determines whether `socket` is a SSL socket.
|
||||
socket.isSsl
|
||||
|
||||
proc getFd*(socket: AsyncSocket): SocketHandle =
|
||||
|
|
@ -814,7 +814,7 @@ proc isClosed*(socket: AsyncSocket): bool =
|
|||
proc sendTo*(socket: AsyncSocket, address: string, port: Port, data: string,
|
||||
flags = {SocketFlag.SafeDisconn}): owned(Future[void])
|
||||
{.async, since: (1, 3).} =
|
||||
## This proc sends ``data`` to the specified ``address``, which may be an IP
|
||||
## This proc sends `data` to the specified `address`, which may be an IP
|
||||
## address or a hostname. If a hostname is specified this function will try
|
||||
## each IP of that hostname. The returned future will complete once all data
|
||||
## has been sent.
|
||||
|
|
@ -861,9 +861,9 @@ proc recvFrom*(socket: AsyncSocket, data: FutureVar[string], size: int,
|
|||
address: FutureVar[string], port: FutureVar[Port],
|
||||
flags = {SocketFlag.SafeDisconn}): owned(Future[int])
|
||||
{.async, since: (1, 3).} =
|
||||
## Receives a datagram data from ``socket`` into ``data``, which must be at
|
||||
## least of size ``size``. The address and port of datagram's sender will be
|
||||
## stored into ``address`` and ``port``, respectively. Returned future will
|
||||
## Receives a datagram data from `socket` into `data`, which must be at
|
||||
## least of size `size`. The address and port of datagram's sender will be
|
||||
## stored into `address` and `port`, respectively. Returned future will
|
||||
## complete once one datagram has been received, and will return size of
|
||||
## packet received.
|
||||
##
|
||||
|
|
@ -872,8 +872,8 @@ proc recvFrom*(socket: AsyncSocket, data: FutureVar[string], size: int,
|
|||
## This proc is normally used with connectionless sockets (UDP sockets).
|
||||
##
|
||||
## **Notes**
|
||||
## * ``data`` must be initialized to the length of ``size``.
|
||||
## * ``address`` must be initialized to 46 in length.
|
||||
## * `data` must be initialized to the length of `size`.
|
||||
## * `address` must be initialized to 46 in length.
|
||||
template adaptRecvFromToDomain(domain: Domain) =
|
||||
var lAddr = sizeof(sAddr).SockLen
|
||||
|
||||
|
|
@ -915,8 +915,8 @@ proc recvFrom*(socket: AsyncSocket, size: int,
|
|||
flags = {SocketFlag.SafeDisconn}):
|
||||
owned(Future[tuple[data: string, address: string, port: Port]])
|
||||
{.async, since: (1, 3).} =
|
||||
## Receives a datagram data from ``socket``, which must be at least of size
|
||||
## ``size``. Returned future will complete once one datagram has been received
|
||||
## Receives a datagram data from `socket`, which must be at least of size
|
||||
## `size`. Returned future will complete once one datagram has been received
|
||||
## and will return tuple with: data of packet received; and address and port
|
||||
## of datagram's sender.
|
||||
##
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue