mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-20 16:01:29 +00:00
Deprecated recvLine and added an improved version named readLine to the
sockets module.
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
|
||||
import sockets, os
|
||||
|
||||
## This module implements an asynchronous event loop for sockets.
|
||||
## This module implements an asynchronous event loop together with asynchronous sockets
|
||||
## which use this event loop.
|
||||
## It is akin to Python's asyncore module. Many modules that use sockets
|
||||
## have an implementation for this module, those modules should all have a
|
||||
## ``register`` function which you should use to add the desired objects to a
|
||||
@@ -435,7 +436,8 @@ proc delHandleWrite*(s: PAsyncSocket) =
|
||||
## Removes the ``handleWrite`` event handler on ``s``.
|
||||
s.handleWrite = nil
|
||||
|
||||
proc recvLine*(s: PAsyncSocket, line: var TaintedString): bool =
|
||||
{.push warning[deprecated]: off.}
|
||||
proc recvLine*(s: PAsyncSocket, line: var TaintedString): bool {.deprecated.} =
|
||||
## Behaves similar to ``sockets.recvLine``, however it handles non-blocking
|
||||
## sockets properly. This function guarantees that ``line`` is a full line,
|
||||
## if this function can only retrieve some data; it will save this data and
|
||||
@@ -443,6 +445,9 @@ proc recvLine*(s: PAsyncSocket, line: var TaintedString): bool =
|
||||
##
|
||||
## Unlike ``sockets.recvLine`` this function will raise an EOS or ESSL
|
||||
## exception if an error occurs.
|
||||
##
|
||||
## **Deprecated since version 0.9.2**: This function has been deprecated in
|
||||
## favour of readLine.
|
||||
setLen(line.string, 0)
|
||||
var dataReceived = "".TaintedString
|
||||
var ret = s.socket.recvLineAsync(dataReceived)
|
||||
@@ -463,6 +468,37 @@ proc recvLine*(s: PAsyncSocket, line: var TaintedString): bool =
|
||||
of RecvFail:
|
||||
s.SocketError(async = true)
|
||||
result = false
|
||||
{.pop.}
|
||||
|
||||
proc readLine*(s: PAsyncSocket, line: var TaintedString): bool =
|
||||
## Behaves similar to ``sockets.readLine``, however it handles non-blocking
|
||||
## sockets properly. This function guarantees that ``line`` is a full line,
|
||||
## if this function can only retrieve some data; it will save this data and
|
||||
## add it to the result when a full line is retrieved, when this happens
|
||||
## False will be returned. True will only be returned if a full line has been
|
||||
## retrieved or the socket has been disconnected in which case ``line`` will
|
||||
## be set to "".
|
||||
##
|
||||
## This function will raise an EOS exception when a socket error occurs.
|
||||
setLen(line.string, 0)
|
||||
var dataReceived = "".TaintedString
|
||||
var ret = s.socket.readLineAsync(dataReceived)
|
||||
case ret
|
||||
of ReadFullLine:
|
||||
if s.lineBuffer.len > 0:
|
||||
string(line).add(s.lineBuffer.string)
|
||||
setLen(s.lineBuffer.string, 0)
|
||||
string(line).add(dataReceived.string)
|
||||
if string(line) == "":
|
||||
line = "\c\L".TaintedString
|
||||
result = true
|
||||
of ReadPartialLine:
|
||||
string(s.lineBuffer).add(dataReceived.string)
|
||||
result = false
|
||||
of ReadNone:
|
||||
result = false
|
||||
of ReadDisconnected:
|
||||
result = true
|
||||
|
||||
proc send*(sock: PAsyncSocket, data: string) =
|
||||
## Sends ``data`` to socket ``sock``. This is basically a nicer implementation
|
||||
|
||||
@@ -121,6 +121,9 @@ type
|
||||
TRecvLineResult* = enum ## result for recvLineAsync
|
||||
RecvFullLine, RecvPartialLine, RecvDisconnected, RecvFail
|
||||
|
||||
TReadLineResult* = enum ## result for readLineAsync
|
||||
ReadFullLine, ReadPartialLine, ReadDisconnected, ReadNone
|
||||
|
||||
ETimeout* = object of ESynch
|
||||
|
||||
proc newTSocket(fd: int32, isBuff: bool): TSocket =
|
||||
@@ -1180,7 +1183,7 @@ proc peekChar(socket: TSocket, c: var char): int {.tags: [FReadIO].} =
|
||||
result = recv(socket.fd, addr(c), 1, MSG_PEEK)
|
||||
|
||||
proc recvLine*(socket: TSocket, line: var TaintedString, timeout = -1): bool {.
|
||||
tags: [FReadIO, FTime].} =
|
||||
tags: [FReadIO, FTime], deprecated.} =
|
||||
## Receive a line of data from ``socket``.
|
||||
##
|
||||
## If a full line is received ``\r\L`` is not
|
||||
@@ -1196,6 +1199,10 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout = -1): bool {.
|
||||
##
|
||||
## A timeout can be specified in miliseconds, if data is not received within
|
||||
## the specified time an ETimeout exception will be raised.
|
||||
##
|
||||
## **Deprecated since version 0.9.2**: This function has been deprecated in
|
||||
## favour of readLine.
|
||||
|
||||
template addNLIfEmpty(): stmt =
|
||||
if line.len == 0:
|
||||
line.add("\c\L")
|
||||
@@ -1222,8 +1229,49 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout = -1): bool {.
|
||||
return true
|
||||
add(line.string, c)
|
||||
|
||||
proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {.
|
||||
tags: [FReadIO, FTime].} =
|
||||
## Reads a line of data from ``socket``.
|
||||
##
|
||||
## 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 ``""``.
|
||||
##
|
||||
## An EOS exception will be raised in the case of a socket error.
|
||||
##
|
||||
## A timeout can be specified in miliseconds, if data is not received within
|
||||
## the specified time an ETimeout exception will be raised.
|
||||
|
||||
template addNLIfEmpty(): stmt =
|
||||
if line.len == 0:
|
||||
line.add("\c\L")
|
||||
|
||||
var waited = 0.0
|
||||
|
||||
setLen(line.string, 0)
|
||||
while true:
|
||||
var c: char
|
||||
discard waitFor(socket, waited, timeout, 1, "readLine")
|
||||
var n = recv(socket, addr(c), 1)
|
||||
if n < 0: OSError()
|
||||
elif n == 0: return
|
||||
if c == '\r':
|
||||
discard waitFor(socket, waited, timeout, 1, "readLine")
|
||||
n = peekChar(socket, c)
|
||||
if n > 0 and c == '\L':
|
||||
discard recv(socket, addr(c), 1)
|
||||
elif n <= 0: OSError()
|
||||
addNlIfEmpty()
|
||||
return
|
||||
elif c == '\L':
|
||||
addNlIfEmpty()
|
||||
return
|
||||
add(line.string, c)
|
||||
|
||||
proc recvLineAsync*(socket: TSocket,
|
||||
line: var TaintedString): TRecvLineResult {.tags: [FReadIO].} =
|
||||
line: var TaintedString): TRecvLineResult {.tags: [FReadIO], deprecated.} =
|
||||
## Similar to ``recvLine`` but designed for non-blocking sockets.
|
||||
##
|
||||
## The values of the returned enum should be pretty self explanatory:
|
||||
@@ -1232,6 +1280,10 @@ proc recvLineAsync*(socket: TSocket,
|
||||
## * If some data has been retrieved; ``RecvPartialLine`` is returned.
|
||||
## * If the socket has been disconnected; ``RecvDisconnected`` is returned.
|
||||
## * If call to ``recv`` failed; ``RecvFail`` is returned.
|
||||
##
|
||||
## **Deprecated since version 0.9.2**: This function has been deprecated in
|
||||
## favour of readLineAsync.
|
||||
|
||||
setLen(line.string, 0)
|
||||
while true:
|
||||
var c: char
|
||||
@@ -1250,6 +1302,40 @@ proc recvLineAsync*(socket: TSocket,
|
||||
elif c == '\L': return RecvFullLine
|
||||
add(line.string, c)
|
||||
|
||||
proc readLineAsync*(socket: TSocket,
|
||||
line: var TaintedString): TReadLineResult {.tags: [FReadIO].} =
|
||||
## Similar to ``recvLine`` but designed for non-blocking sockets.
|
||||
##
|
||||
## The values of the returned enum should be pretty self explanatory:
|
||||
##
|
||||
## * If a full line has been retrieved; ``ReadFullLine`` is returned.
|
||||
## * If some data has been retrieved; ``ReadPartialLine`` is returned.
|
||||
## * If the socket has been disconnected; ``ReadDisconnected`` is returned.
|
||||
## * If no data could be retrieved; ``ReadNone`` is returned.
|
||||
## * If call to ``recv`` failed; **an EOS exception is raised.**
|
||||
setLen(line.string, 0)
|
||||
|
||||
template errorOrNone =
|
||||
socket.SocketError(async = true)
|
||||
return ReadNone
|
||||
|
||||
while true:
|
||||
var c: char
|
||||
var n = recv(socket, addr(c), 1)
|
||||
if n < 0:
|
||||
if line.len == 0: errorOrNone else: return ReadPartialLine
|
||||
elif n == 0:
|
||||
return (if line.len == 0: ReadDisconnected else: ReadPartialLine)
|
||||
if c == '\r':
|
||||
n = peekChar(socket, c)
|
||||
if n > 0 and c == '\L':
|
||||
discard recv(socket, addr(c), 1)
|
||||
elif n <= 0:
|
||||
if line.len == 0: errorOrNone else: return ReadPartialLine
|
||||
return ReadFullLine
|
||||
elif c == '\L': return ReadFullLine
|
||||
add(line.string, c)
|
||||
|
||||
proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO], deprecated.} =
|
||||
## receives all the available data from the socket.
|
||||
## Socket errors will result in an ``EOS`` error.
|
||||
|
||||
@@ -26,7 +26,7 @@ proc swarmConnect(s: PAsyncSocket) =
|
||||
|
||||
proc serverRead(s: PAsyncSocket) =
|
||||
var line = ""
|
||||
assert s.recvLine(line)
|
||||
assert s.readLine(line)
|
||||
if line != "":
|
||||
#echo(line)
|
||||
if line.startsWith("Message "):
|
||||
|
||||
Reference in New Issue
Block a user