summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-02-18 10:48:06 +0100
committerAraq <rumpf_a@web.de>2012-02-18 10:48:06 +0100
commitb88d98c17a00171ddc1a9d8059ad713d174b800c (patch)
tree28e2f416e6a6fc6df9ad292ab30ed260d564712b
parent330d0a92fb3e5732edba90791ee2409d61269af1 (diff)
parent9aeecaa4cf9fdc46d80ce5dd6bbcc0a9486903fb (diff)
downloadNim-b88d98c17a00171ddc1a9d8059ad713d174b800c.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod
-rw-r--r--lib/pure/asyncio.nim29
-rw-r--r--lib/pure/ftpclient.nim4
-rw-r--r--lib/pure/irc.nim22
-rwxr-xr-xlib/pure/os.nim2
-rwxr-xr-xlib/pure/sockets.nim36
5 files changed, 83 insertions, 10 deletions
diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim
index 1c366e4d9..417a220f9 100644
--- a/lib/pure/asyncio.nim
+++ b/lib/pure/asyncio.nim
@@ -61,6 +61,8 @@ type
 
     handleAccept*: proc (s:  PAsyncSocket, arg: PObject)
 
+    lineBuffer: TaintedString ## Temporary storage for ``recvLine``
+
   TInfo* = enum
     SockIdle, SockConnecting, SockConnected, SockListening, SockClosed
   
@@ -88,6 +90,8 @@ proc newAsyncSocket(userArg: PObject = nil): PAsyncSocket =
   result.handleConnect = (proc (s: PAsyncSocket, arg: PObject) = nil)
   result.handleAccept = (proc (s: PAsyncSocket, arg: PObject) = nil)
 
+  result.lineBuffer = "".TaintedString
+
 proc AsyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, 
                   protocol: TProtocol = IPPROTO_TCP, 
                   userArg: PObject = nil): PAsyncSocket =
@@ -193,6 +197,31 @@ proc isConnecting*(s: PAsyncSocket): bool =
   ## Determines whether ``s`` is connecting.  
   return s.info == SockConnecting
 
+proc recvLine*(s: PAsyncSocket, line: var TaintedString): bool =
+  ## 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
+  ## add it to the result when a full line is retrieved.
+  setLen(line.string, 0)
+  var dataReceived = "".TaintedString
+  var ret = s.socket.recvLineAsync(dataReceived)
+  case ret
+  of RecvFullLine:
+    if s.lineBuffer.len > 0:
+      string(line).add(s.lineBuffer.string)
+      setLen(s.lineBuffer.string, 0)
+    
+    string(line).add(dataReceived.string)
+    result = true
+  of RecvPartialLine:
+    string(s.lineBuffer).add(dataReceived.string)
+    result = false
+  of RecvDisconnected:
+    result = true
+  of RecvFail:
+    result = false
+
+
 proc poll*(d: PDispatcher, timeout: int = 500): bool =
   ## This function checks for events on all the sockets in the `PDispatcher`.
   ## It then proceeds to call the correct event handler.
diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim
index 6d207b98f..669499342 100644
--- a/lib/pure/ftpclient.nim
+++ b/lib/pure/ftpclient.nim
@@ -196,9 +196,9 @@ proc getLines(ftp: var TFTPClient, async: bool = false): bool =
   ## It doesn't if `async` is true, because it doesn't check for 226 then.
   if ftp.dsockStatus == SockConnected:
     var r = TaintedString""
-    if ftp.dsock.recvLine(r):
+    if ftp.dsock.recvAsync(r):
       if r.string != "":
-        ftp.job.lines.add(r.string & "\n")
+        ftp.job.lines.add(r.string)
       else:
         ftp.dsockStatus = SockClosed
   
diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim
index 09e85f234..6e9e30281 100644
--- a/lib/pure/irc.nim
+++ b/lib/pure/irc.nim
@@ -46,6 +46,7 @@ type
   TAsyncIRC* = object of TIRC
     userArg: PObject
     handleEvent: proc (irc: var TAsyncIRC, ev: TIRCEvent, userArg: PObject)
+    lineBuffer: TaintedString
 
   TIRCMType* = enum
     MUnknown,
@@ -281,7 +282,7 @@ proc poll*(irc: var TIRC, ev: var TIRCEvent,
   var ret = socks.select(timeout)
   if socks.len() == 0 and ret != 0:
     if irc.sock.recvLine(line):
-      ev = irc.processLine(line)
+      ev = irc.processLine(line.string)
       result = true
   
   if processOther(irc, ev): result = true
@@ -320,11 +321,22 @@ proc handleConnect(h: PObject) =
 
 proc handleRead(h: PObject) =
   var irc = PAsyncIRC(h)
-  var line = ""
-  if irc.sock.recvLine(line):
-    var ev = irc[].processLine(line)
+  var line = "".TaintedString
+  var ret = irc.sock.recvLineAsync(line)
+  case ret
+  of RecvFullLine:
+    var ev = irc[].processLine(irc.lineBuffer.string & line.string)
     irc.handleEvent(irc[], ev, irc.userArg)
-
+    irc.lineBuffer = "".TaintedString
+  of RecvPartialLine:
+    if line.string != "":
+      string(irc.lineBuffer).add(line.string)
+  of RecvDisconnected:
+    var ev: TIRCEvent
+    ev.typ = EvDisconnected
+    irc.handleEvent(irc[], ev, irc.userArg)
+  of RecvFail: nil
+  
 proc handleTask(h: PObject) =
   var irc = PAsyncIRC(h)
   var ev: TIRCEvent
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 6b8176dde..5b3859bd2 100755
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -929,7 +929,7 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string =
 
 proc rawRemoveDir(dir: string) = 
   when defined(windows):
-    if RemoveDirectoryA(dir) != 0'i32 and GetLastError() != 3'i32 and 
+    if RemoveDirectoryA(dir) == 0'i32 and GetLastError() != 3'i32 and 
         GetLastError() != 18'i32: OSError()
   else:
     if rmdir(dir) != 0'i32 and errno != ENOENT: OSError()
diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim
index 564b76343..5721d79fe 100755
--- a/lib/pure/sockets.nim
+++ b/lib/pure/sockets.nim
@@ -56,6 +56,9 @@ type
     length*: int
     addrList*: seq[string]
 
+  TRecvLineResult* = enum ## result for recvLineAsync
+    RecvFullLine, RecvPartialLine, RecvDisconnected, RecvFail
+
 const
   InvalidSocket* = TSocket(-1'i32) ## invalid socket number
 
@@ -546,8 +549,7 @@ proc select*(readfds: var seq[TSocket], timeout = 500): int =
 
 proc recvLine*(socket: TSocket, line: var TaintedString): bool =
   ## returns false if no further data is available. `Line` must be initialized
-  ## and not nil! This does not throw an EOS exception, therefore
-  ## it can be used in both blocking and non-blocking sockets.
+  ## and not nil! This does not throw an EOS exception.
   ## If ``socket`` is disconnected, ``true`` will be returned and line will be
   ## set to ``""``.
   setLen(line.string, 0)
@@ -565,6 +567,31 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool =
     elif c == '\L': return true
     add(line.string, c)
 
+proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult =
+  ## similar to ``recvLine`` but for non-blocking sockets.
+  ## The values of the returned enum should be pretty self explanatory:
+  ## If a full line has been retrieved; ``RecvFullLine`` is returned.
+  ## If some data has been retrieved; ``RecvPartialLine`` is returned.
+  ## If the socket has been disconnected; ``RecvDisconncted`` is returned.
+  ## If call to ``recv`` failed; ``RecvFail`` is returned.
+  setLen(line.string, 0)
+  while true:
+    var c: char
+    var n = recv(cint(socket), addr(c), 1, 0'i32)
+    if n < 0: 
+      return (if line.len == 0: RecvFail else: RecvPartialLine)
+    elif n == 0: 
+      return (if line.len == 0: RecvDisconnected else: RecvPartialLine)
+    if c == '\r':
+      n = recv(cint(socket), addr(c), 1, MSG_PEEK)
+      if n > 0 and c == '\L':
+        discard recv(cint(socket), addr(c), 1, 0'i32)
+      elif n <= 0: 
+        return (if line.len == 0: RecvFail else: RecvPartialLine)
+      return RecvFullLine
+    elif c == '\L': return RecvFullLine
+    add(line.string, c)
+
 proc recv*(socket: TSocket, data: pointer, size: int): int =
   ## receives data from a socket
   result = recv(cint(socket), data, size, 0'i32)
@@ -664,6 +691,11 @@ proc sendAsync*(socket: TSocket, data: string): bool =
         return false
       else: OSError()
 
+proc trySend*(socket: TSocket, data: string): bool =
+  ## safe alternative to ``send``. Does not raise an EOS when an error occurs,
+  ## and instead returns ``false`` on failure.
+  result = send(socket, cstring(data), data.len) == data.len
+
 when defined(Windows):
   const 
     SOCKET_ERROR = -1
gets/exline.go?h=0.6.0&id=7160f98a9081bcab05904484eae790ec0a006b87'>7160f98 ^
ecd803a ^











661e3ec ^
5685a17 ^
661e3ec ^

1418e1b ^
8fa4583 ^
661e3ec ^

1170893 ^
8fa4583 ^
661e3ec ^

80e891a ^



cc639a1 ^
8635c70 ^
72e4b5e ^
8635c70 ^
ecd803a ^
8635c70 ^





80e891a ^
72e4b5e ^
8635c70 ^
ecd803a ^
8fa4583 ^

661e3ec ^



ecd803a ^




6838c23 ^
ecd803a ^








6838c23 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114