diff options
author | bptato <nincsnevem662@gmail.com> | 2022-11-25 00:32:54 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-11-25 00:33:39 +0100 |
commit | b086e346afeded51c94c9b77280dcea6f6b3ce8a (patch) | |
tree | e2fd9f29e77ab787f960bbd8ba190a14a6d5d7a0 /src/ips | |
parent | 896489a6c500e28f13d0237ab691622cb5c5114f (diff) | |
download | chawan-b086e346afeded51c94c9b77280dcea6f6b3ce8a.tar.gz |
Buffer improvements
Diffstat (limited to 'src/ips')
-rw-r--r-- | src/ips/serialize.nim | 84 | ||||
-rw-r--r-- | src/ips/socketstream.nim | 42 |
2 files changed, 122 insertions, 4 deletions
diff --git a/src/ips/serialize.nim b/src/ips/serialize.nim index 82003715..2114cec0 100644 --- a/src/ips/serialize.nim +++ b/src/ips/serialize.nim @@ -11,10 +11,84 @@ import types/buffersource import types/color import types/url +proc slen*[T](o: T): int = + when T is string: + return sizeof(o.len) + o.len + elif T is bool: + return sizeof(char) + elif T is URL: + return ($o).slen + elif T is seq: + result = slen(o.len) + for x in o: + result += slen(x) + elif T is Option: + result = slen(o.isSome) + if o.isSome: + result += slen(o.get) + elif T is HeaderList: + result += slen(o.table.len) + for k, v in o.table: + result += slen(k) + result += slen(v.len) + for s in v: + result += slen(s) + elif T is MimePart: + result += slen(o.isFile) + result += slen(o.name) + result += slen(o.content) + if o.isFile: + result += slen(o.filename) + result += slen(o.contentType) + result += slen(o.fileSize) + result += slen(o.isStream) + elif T is Request: + result += slen(o.httpmethod) + result += slen(o.url) + result += slen(o.headers) + result += slen(o.body) + result += slen(o.multipart) + elif T is CellColor: + result += slen(o.rgb) + if o.rgb: + result += slen(o.rgbcolor) + else: + result += slen(o.color) + elif T is Format: + result += slen(o.fgcolor) + result += slen(o.bgcolor) + result += slen(o.flags) + elif T is SimpleFormatCell: + result += slen(o.format) + result += slen(o.pos) + elif T is SimpleFlexibleLine: + result += slen(o.str) + result += slen(o.formats) + elif T is FormatCell: + result += slen(o.format) + result += slen(o.pos) + elif T is FlexibleLine: + result += slen(o.str) + result += slen(o.formats) + elif T is Regex: + result += slen(o.plen) + result += o.plen + result += slen(o.buf) + elif T is BufferSource: + result += slen(o.t) + case o.t + of CLONE: result += slen(o.clonepid) + of LOAD_REQUEST: result += slen(o.request) + of LOAD_PIPE: result += slen(o.fd) + result += slen(o.location) + result += slen(o.contenttype) + else: + result += sizeof(o) + template swrite*[T](stream: Stream, o: T) = stream.write(o) -proc swrite*(stream: Stream, s: string) = +proc swrite*(stream: Stream, s: string, maxlen = 8192) = stream.swrite(s.len) stream.write(s) @@ -107,9 +181,11 @@ proc swrite*(stream: Stream, source: BufferSource) = template sread*[T](stream: Stream, o: T) = stream.read(o) -proc sread*(stream: Stream, s: var string) = +proc sread*(stream: Stream, s: var string, maxlen = 8192) = var len: int stream.sread(len) + if maxlen != -1: + len = min(maxlen, len) stream.readStr(len, s) proc sread*(stream: Stream, b: var bool) = @@ -123,8 +199,8 @@ proc sread*(stream: Stream, b: var bool) = proc sread*(stream: Stream, url: var Url) = var s: string - stream.sread(s) - url = parseUrl(s).get + stream.sread(s, 2048) + url = newURL(s) proc sread*(stream: Stream, headers: var HeaderList) = new(headers) diff --git a/src/ips/socketstream.nim b/src/ips/socketstream.nim index efc226bd..3918fe2c 100644 --- a/src/ips/socketstream.nim +++ b/src/ips/socketstream.nim @@ -30,6 +30,48 @@ proc sockClose(s: Stream) = {.cast(tags: []).}: #...sigh let s = SocketStream(s) s.source.close() +# See https://stackoverflow.com/a/4491203 +proc sendFileHandle*(s: SocketStream, fd: FileHandle) = + var hdr: Tmsghdr + var iov: IOVec + var cmsgbuf = alloc(CMSG_SPACE(csize_t(sizeof(FileHandle)))) + var buf = char(0) + iov.iov_base = addr buf + iov.iov_len = csize_t(1) + zeroMem(addr hdr, sizeof(hdr)) + hdr.msg_iov = addr iov + hdr.msg_iovlen = 1 + hdr.msg_control = cmsgbuf + hdr.msg_controllen = CMSG_LEN(csize_t(sizeof(FileHandle))) + let cmsg = CMSG_FIRSTHDR(addr hdr) + cmsg.cmsg_len = CMSG_LEN(csize_t(sizeof(FileHandle))) + cmsg.cmsg_level = SOL_SOCKET + cmsg.cmsg_type = SCM_RIGHTS + cast[ptr FileHandle](CMSG_DATA(cmsg))[] = fd + let n = sendmsg(s.source.getFd(), addr hdr, 0) + dealloc(cmsgbuf) + assert n == int(iov.iov_len) #TODO remove this + +proc recvFileHandle*(s: SocketStream): FileHandle = + var iov: IOVec + var hdr: Tmsghdr + let space = CMSG_SPACE(csize_t(sizeof(FileHandle))) + var buf: char + var cmsgbuf = alloc(space) + iov.iov_base = addr buf + iov.iov_len = 1 + zeroMem(addr hdr, sizeof(hdr)) + hdr.msg_iov = addr iov + hdr.msg_iovlen = 1 + hdr.msg_control = cmsgbuf + hdr.msg_controllen = space + let n = recvmsg(s.source.getFd(), addr hdr, 0) + assert n != 0, "Unexpected EOF" #TODO remove this + assert n > 0, "Failed to receive message " & $osLastError() #TODO remove this + var cmsg = CMSG_FIRSTHDR(addr hdr) + result = cast[ptr FileHandle](CMSG_DATA(cmsg))[] + dealloc(cmsgbuf) + func newSocketStream*(): SocketStream = new(result) result.readDataImpl = cast[proc (s: Stream, buffer: pointer, bufLen: int): int |