about summary refs log tree commit diff stats
path: root/src/io
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-02-14 15:44:32 +0100
committerbptato <nincsnevem662@gmail.com>2024-02-14 15:44:32 +0100
commit547a492611a8d6831d88b697e2785658a9c06177 (patch)
treec5fa38683acc29e4d70396d5f4d96346f453b469 /src/io
parentc2fbe0993228b2b62f8a916bae5271097254ce5c (diff)
downloadchawan-547a492611a8d6831d88b697e2785658a9c06177.tar.gz
Various refactorings & fixes
* disallow Stream interface usage on non-blocking PosixStreams
* do not read estream of forkserver byte-by-byte (it's slow)
* do not call writeData with a zero len in formdata
* do not quote numbers in mailcap quoteFile
* remove some unused stuff
Diffstat (limited to 'src/io')
-rw-r--r--src/io/posixstream.nim71
-rw-r--r--src/io/socketstream.nim91
2 files changed, 53 insertions, 109 deletions
diff --git a/src/io/posixstream.nim b/src/io/posixstream.nim
index 3aa14191..683d72b8 100644
--- a/src/io/posixstream.nim
+++ b/src/io/posixstream.nim
@@ -6,6 +6,7 @@ type
   PosixStream* = ref object of Stream
     fd*: cint
     isend*: bool
+    blocking*: bool
 
   ErrorAgain* = object of IOError
   ErrorBadFD* = object of IOError
@@ -33,32 +34,6 @@ proc raisePosixIOError*() =
   else:
     raise newException(IOError, $strerror(errno))
 
-proc psClose(s: Stream) =
-  let s = cast[PosixStream](s)
-  discard close(s.fd)
-
-proc psReadData(s: Stream, buffer: pointer, len: int): int =
-  assert len != 0
-  let s = cast[PosixStream](s)
-  let wasend = s.isend
-  let buffer = cast[ptr UncheckedArray[uint8]](buffer)
-  while result < len:
-    let n = read(s.fd, addr buffer[result], len - result)
-    if n < 0:
-      if result == 0:
-        result = n
-      break
-    elif n == 0:
-      s.isend = true
-      break
-    result += n
-  if result == 0:
-    if wasend:
-      raise newException(EOFError, "eof")
-    s.isend = true
-  if result == -1:
-    raisePosixIOError()
-
 method recvData*(s: PosixStream, buffer: pointer, len: int): int {.base.} =
   let n = read(s.fd, buffer, len)
   if n < 0:
@@ -69,6 +44,12 @@ method recvData*(s: PosixStream, buffer: pointer, len: int): int {.base.} =
     s.isend = true
   return n
 
+proc recvData*(s: PosixStream, buffer: var openArray[uint8]): int {.inline.} =
+  return s.recvData(addr buffer[0], buffer.len)
+
+proc recvData*(s: PosixStream, buffer: var openArray[char]): int {.inline.} =
+  return s.recvData(addr buffer[0], buffer.len)
+
 method sendData*(s: PosixStream, buffer: pointer, len: int): int {.base.} =
   #TODO use sendData instead
   let n = write(s.fd, buffer, len)
@@ -77,30 +58,42 @@ method sendData*(s: PosixStream, buffer: pointer, len: int): int {.base.} =
   return n
 
 method setBlocking*(s: PosixStream, blocking: bool) {.base.} =
+  s.blocking = blocking
   let ofl = fcntl(s.fd, F_GETFL, 0)
   if blocking:
     discard fcntl(s.fd, F_SETFL, ofl and not O_NONBLOCK)
   else:
     discard fcntl(s.fd, F_SETFL, ofl or O_NONBLOCK)
 
+method sclose*(s: PosixStream) {.base.} =
+  discard close(s.fd)
+
+proc psClose(s: Stream) =
+  PosixStream(s).sclose()
+
+proc psReadData(s: Stream, buffer: pointer, len: int): int =
+  let s = PosixStream(s)
+  assert len != 0 and s.blocking
+  return s.recvData(buffer, len)
+
 proc psWriteData(s: Stream, buffer: pointer, len: int) =
-  #TODO use sendData instead
-  let s = cast[PosixStream](s)
-  let res = write(s.fd, buffer, len)
-  if res == -1:
-    raisePosixIOError()
+  let s = PosixStream(s)
+  assert len != 0 and s.blocking
+  discard s.sendData(buffer, len)
 
 proc psAtEnd(s: Stream): bool =
-  return cast[PosixStream](s).isend
+  return PosixStream(s).isend
+
+proc addStreamIface*(ps: PosixStream) =
+  ps.closeImpl = cast[typeof(ps.closeImpl)](psClose)
+  ps.readDataImpl = cast[typeof(ps.readDataImpl)](psReadData)
+  ps.writeDataImpl = cast[typeof(ps.writeDataImpl)](psWriteData)
+  ps.atEndImpl = psAtEnd
 
 proc newPosixStream*(fd: FileHandle): PosixStream =
-  return PosixStream(
-    fd: fd,
-    closeImpl: psClose,
-    readDataImpl: psReadData,
-    writeDataImpl: psWriteData,
-    atEndImpl: psAtEnd
-  )
+  let ps = PosixStream(fd: fd, blocking: true)
+  ps.addStreamIface()
+  return ps
 
 proc newPosixStream*(path: string, flags, mode: cint): PosixStream =
   let fd = open(cstring(path), flags, mode)
diff --git a/src/io/socketstream.nim b/src/io/socketstream.nim
index dd391f21..99f7c2c9 100644
--- a/src/io/socketstream.nim
+++ b/src/io/socketstream.nim
@@ -1,7 +1,6 @@
 import std/nativesockets
 import std/net
 import std/os
-import std/streams
 
 when defined(posix):
   import std/posix
@@ -11,43 +10,6 @@ import io/serversocket
 
 type SocketStream* = ref object of PosixStream
   source*: Socket
-  blk*: bool
-
-proc sockReadData(s: Stream, buffer: pointer, len: int): int =
-  assert len != 0
-  let s = SocketStream(s)
-  let wasend = s.isend
-  let buffer = cast[ptr UncheckedArray[uint8]](buffer)
-  if s.blk:
-    while result < len:
-      let n = s.source.recv(addr buffer[result], len - result)
-      if n < 0:
-        if result == 0:
-          result = n
-        break
-      elif n == 0:
-        s.isend = true
-        break
-      result += n
-  else:
-    result = s.source.recv(buffer, len)
-  if result == 0:
-    if wasend:
-      raise newException(EOFError, "eof")
-    s.isend = true
-  if result < 0:
-    raisePosixIOError()
-  elif result == 0:
-    s.isend = true
-
-proc sockWriteData(s: Stream, buffer: pointer, len: int) =
-  var i = 0
-  let buffer = cast[ptr UncheckedArray[uint8]](buffer)
-  while i < len:
-    let n = SocketStream(s).source.send(addr buffer[i], len - i)
-    if n < 0:
-      raisePosixIOError()
-    i += n
 
 method recvData*(s: SocketStream, buffer: pointer, len: int): int =
   let n = s.source.recv(buffer, len)
@@ -65,49 +27,34 @@ method sendData*(s: SocketStream, buffer: pointer, len: int): int =
     raisePosixIOError()
   return n
 
-proc sockAtEnd(s: Stream): bool =
-  SocketStream(s).isend
-
-proc sockClose(s: Stream) = {.cast(tags: []).}: #...sigh
-  let s = SocketStream(s)
-  s.source.close()
-
 {.compile: "sendfd.c".}
-proc sendfd(sock: SocketHandle, fd: cint): int {.importc.}
+proc sendfd(sock, fd: cint): int {.importc.}
 
-# See https://stackoverflow.com/a/4491203
 proc sendFileHandle*(s: SocketStream, fd: FileHandle) =
   assert not s.source.hasDataBuffered
-  let n = sendfd(s.source.getFd(), cint(fd))
+  let n = sendfd(s.fd, cint(fd))
   if n < 0:
     raisePosixIOError()
   assert n == 1 # we send a single nul byte as buf
 
 {.compile: "recvfd.c".}
-proc recvfd(sock: SocketHandle, fdout: ptr cint): int {.importc.}
+proc recvfd(sock: cint, fdout: ptr cint): int {.importc.}
 
 proc recvFileHandle*(s: SocketStream): FileHandle =
   assert not s.source.hasDataBuffered
   var fd: cint
-  let n = recvfd(s.source.getFd(), addr fd)
+  let n = recvfd(s.fd, addr fd)
   if n < 0:
     raisePosixIOError()
   return FileHandle(fd)
 
-func newSocketStream*(): SocketStream =
-  return SocketStream(
-    readDataImpl: cast[proc (s: Stream, buffer: pointer, bufLen: int): int
-        {.nimcall, raises: [Defect, IOError, OSError], tags: [ReadIOEffect],
-        gcsafe.}
-    ](sockReadData), # ... ???
-    writeDataImpl: sockWriteData,
-    atEndImpl: sockAtEnd,
-    closeImpl: sockClose
-  )
-
 method setBlocking*(s: SocketStream, blocking: bool) =
+  s.blocking = blocking
   s.source.getFd().setBlocking(blocking)
 
+method sclose*(s: SocketStream) =
+  s.source.close()
+
 # see serversocket.nim for an explanation
 {.compile: "connect_unix.c".}
 proc connect_unix_from_c(fd: cint, path: cstring, pathlen: cint): cint
@@ -115,8 +62,6 @@ proc connect_unix_from_c(fd: cint, path: cstring, pathlen: cint): cint
 
 proc connectSocketStream*(path: string, buffered = true, blocking = true):
     SocketStream =
-  result = newSocketStream()
-  result.blk = blocking
   let sock = newSocket(Domain.AF_UNIX, SockType.SOCK_STREAM,
     Protocol.IPPROTO_IP, buffered)
   if not blocking:
@@ -124,22 +69,28 @@ proc connectSocketStream*(path: string, buffered = true, blocking = true):
   if connect_unix_from_c(cint(sock.getFd()), cstring(path),
       cint(path.len)) != 0:
     raiseOSError(osLastError())
-  result.source = sock
-  result.fd = cint(sock.getFd())
+  result = SocketStream(
+    source: sock,
+    fd: cint(sock.getFd()),
+    blocking: blocking
+  )
+  result.addStreamIface()
 
 proc connectSocketStream*(pid: Pid, buffered = true, blocking = true):
     SocketStream =
   try:
-    connectSocketStream(getSocketPath(pid), buffered, blocking)
+    return connectSocketStream(getSocketPath(pid), buffered, blocking)
   except OSError:
     return nil
 
 proc acceptSocketStream*(ssock: ServerSocket, blocking = true): SocketStream =
-  result = newSocketStream()
-  result.blk = blocking
   var sock: Socket
   ssock.sock.accept(sock, inheritable = true)
-  result.source = sock
   if not blocking:
     sock.getFd().setBlocking(false)
-  result.fd = cint(sock.getFd())
+  result = SocketStream(
+    blocking: blocking,
+    source: sock,
+    fd: cint(sock.getFd())
+  )
+  result.addStreamIface()