diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-14 15:44:32 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-14 15:44:32 +0100 |
commit | 547a492611a8d6831d88b697e2785658a9c06177 (patch) | |
tree | c5fa38683acc29e4d70396d5f4d96346f453b469 /src/io | |
parent | c2fbe0993228b2b62f8a916bae5271097254ce5c (diff) | |
download | chawan-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.nim | 71 | ||||
-rw-r--r-- | src/io/socketstream.nim | 91 |
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() |