about summary refs log tree commit diff stats
path: root/src/ips
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-11-25 00:32:54 +0100
committerbptato <nincsnevem662@gmail.com>2022-11-25 00:33:39 +0100
commitb086e346afeded51c94c9b77280dcea6f6b3ce8a (patch)
treee2fd9f29e77ab787f960bbd8ba190a14a6d5d7a0 /src/ips
parent896489a6c500e28f13d0237ab691622cb5c5114f (diff)
downloadchawan-b086e346afeded51c94c9b77280dcea6f6b3ce8a.tar.gz
Buffer improvements
Diffstat (limited to 'src/ips')
-rw-r--r--src/ips/serialize.nim84
-rw-r--r--src/ips/socketstream.nim42
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