about summary refs log tree commit diff stats
path: root/src/ips
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-12-10 22:50:23 +0100
committerbptato <nincsnevem662@gmail.com>2022-12-10 22:50:23 +0100
commit940325abfc9714b06de920a2a7f8911eae22f357 (patch)
tree9651d5f1d22e3eaa6b098b6bbed97a583244375d /src/ips
parent5c267ce6c9c1add997767f5eaad248cdd829c6fc (diff)
downloadchawan-940325abfc9714b06de920a2a7f8911eae22f357.tar.gz
Fix blocking socketstream recv/send, clean up ips/serialize & types/color
Write always blocks for now, as it's too big of a footgun not to
Diffstat (limited to 'src/ips')
-rw-r--r--src/ips/serialize.nim370
-rw-r--r--src/ips/socketstream.nim17
2 files changed, 235 insertions, 152 deletions
diff --git a/src/ips/serialize.nim b/src/ips/serialize.nim
index 09754466..73320b27 100644
--- a/src/ips/serialize.nim
+++ b/src/ips/serialize.nim
@@ -1,6 +1,7 @@
 # Write data to streams.
 
 import options
+import sets
 import streams
 import tables
 
@@ -8,152 +9,122 @@ import buffer/cell
 import io/request
 import js/regex
 import types/buffersource
-import types/color
 import types/url
 
-proc slen*[T](o: T): int =
-  when T is string:
-    return slen(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 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 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)
-  elif T is tuple:
-    for f in o.fields:
-      result += slen(f)
-  elif T is object:
-    for f in o.fields:
-      result += slen(f)
-  elif T is ref object:
-    result += slen(o[])
-  else:
-    result += sizeof(o)
+proc swrite*(stream: Stream, n: SomeNumber)
+proc sread*(stream: Stream, n: var SomeNumber)
+func slen*(n: SomeNumber): int
 
-template swrite*[T](stream: Stream, o: T) =
-  stream.write(o)
+proc swrite*[T](stream: Stream, s: set[T])
+proc sread*[T](stream: Stream, s: var set[T])
+func slen*[T](s: set[T]): int
 
-proc swrite*(stream: Stream, s: string) =
-  stream.swrite(s.len)
-  stream.write(s)
+proc swrite*[T: enum](stream: Stream, x: T)
+proc sread*[T: enum](stream: Stream, x: var T)
+func slen*[T: enum](x: T): int
 
-proc swrite*(stream: Stream, b: bool) =
-  if b:
-    stream.swrite(1u8)
-  else:
-    stream.swrite(0u8)
+proc swrite*(stream: Stream, s: string)
+proc sread*(stream: Stream, s: var string)
+func slen*(s: string): int
 
-proc swrite*(stream: Stream, url: Url) =
-  stream.swrite(url.serialize())
+proc swrite*(stream: Stream, b: bool)
+proc sread*(stream: Stream, b: var bool)
+func slen*(b: bool): int
 
-proc swrite*(stream: Stream, tup: tuple) =
-  for f in tup.fields:
-    stream.swrite(f)
+proc swrite*(stream: Stream, url: Url)
+proc sread*(stream: Stream, url: var Url)
+func slen*(url: Url): int
 
-proc swrite*[T](stream: Stream, s: seq[T]) =
-  stream.swrite(s.len)
-  for m in s:
-    stream.swrite(m)
+proc swrite*(stream: Stream, tup: tuple)
+proc sread*(stream: Stream, tup: var tuple)
+func slen*(tup: tuple): int
 
-proc swrite*[U, V](stream: Stream, t: Table[U, V]) =
-  stream.swrite(t.len)
-  for k, v in t:
-    stream.swrite(k)
-    stream.swrite(v)
+proc swrite*[T](stream: Stream, s: seq[T])
+proc sread*[T](stream: Stream, s: var seq[T])
+func slen*(s: seq): int
 
-proc swrite*(stream: Stream, obj: object) =
-  for f in obj.fields:
-    stream.swrite(f)
+proc swrite*[U, V](stream: Stream, t: Table[U, V])
+proc sread*[U, V](stream: Stream, t: var Table[U, V])
+func slen*[U, V](t: Table[U, V]): int
 
-proc swrite*(stream: Stream, obj: ref object) =
-  stream.swrite(obj[])
+proc swrite*(stream: Stream, obj: object)
+proc sread*(stream: Stream, obj: var object)
+func slen*(obj: object): int
 
-proc swrite*(stream: Stream, part: MimePart) =
-  stream.swrite(part.isFile)
-  stream.swrite(part.name)
-  stream.swrite(part.content)
-  if part.isFile:
-    stream.swrite(part.filename)
-    stream.swrite(part.contentType)
-    stream.swrite(part.fileSize)
-    stream.swrite(part.isStream)
+proc swrite*(stream: Stream, obj: ref object)
+proc sread*(stream: Stream, obj: var ref object)
+func slen*(obj: ref object): int
 
-proc swrite*[T](stream: Stream, o: Option[T]) =
-  stream.swrite(o.issome)
-  if o.issome:
-    stream.swrite(o.get)
+proc swrite*(stream: Stream, part: MimePart)
+proc sread*(stream: Stream, part: var MimePart)
+func slen*(part: MimePart): int
 
-proc swrite*(stream: Stream, request: Request) =
-  stream.swrite(request[])
+proc swrite*[T](stream: Stream, o: Option[T])
+proc sread*[T](stream: Stream, o: var Option[T])
+func slen*[T](o: Option[T]): int
 
-proc swrite*(stream: Stream, color: CellColor) =
-  stream.swrite(color.rgb)
-  if color.rgb:
-    stream.swrite(color.rgbcolor)
-  else:
-    stream.swrite(color.color)
+proc swrite*(stream: Stream, regex: Regex)
+proc sread*(stream: Stream, regex: var Regex)
+func slen*(regex: Regex): int
 
-proc swrite*(stream: Stream, regex: Regex) =
-  stream.swrite(regex.plen)
-  stream.writeData(regex.bytecode, regex.plen)
-  stream.swrite(regex.buf)
+proc swrite*(stream: Stream, source: BufferSource)
+proc sread*(stream: Stream, source: var BufferSource)
+func slen*(source: BufferSource): int
 
-proc swrite*(stream: Stream, source: BufferSource) =
-  stream.swrite(source.t)
-  case source.t
-  of CLONE: stream.swrite(source.clonepid)
-  of LOAD_REQUEST: stream.swrite(source.request)
-  of LOAD_PIPE: stream.swrite(source.fd)
-  stream.swrite(source.location)
-  stream.swrite(source.contenttype)
+proc swrite*(stream: Stream, n: SomeNumber) =
+  stream.write(n)
+
+proc sread*(stream: Stream, n: var SomeNumber) =
+  stream.read(n)
 
-template sread*[T](stream: Stream, o: T) =
-  stream.read(o)
+func slen*(n: SomeNumber): int =
+  return sizeof(n)
+
+proc swrite*[T: enum](stream: Stream, x: T) =
+  stream.swrite(cast[int](x))
+
+proc sread*[T: enum](stream: Stream, x: var T) =
+  var i: int
+  stream.sread(i)
+  x = cast[T](i)
+
+func slen*[T: enum](x: T): int =
+  return sizeof(int)
+
+proc swrite*[T](stream: Stream, s: set[T]) =
+  stream.swrite(s.card)
+  for e in s:
+    stream.swrite(e)
+
+proc sread*[T](stream: Stream, s: var set[T]) =
+  var len: int
+  stream.sread(len)
+  for i in 0 ..< len:
+    var x: T
+    stream.sread(x)
+    s.incl(x)
+
+func slen*[T](s: set[T]): int =
+  result = slen(s.card)
+  for x in s:
+    result += slen(x)
+
+proc swrite*(stream: Stream, s: string) =
+  stream.swrite(s.len)
+  stream.write(s)
 
 proc sread*(stream: Stream, s: var string) =
   var len: int
   stream.sread(len)
   stream.readStr(len, s)
+func slen*(s: string): int =
+  slen(s.len) + s.len
+
+proc swrite*(stream: Stream, b: bool) =
+  if b:
+    stream.swrite(1u8)
+  else:
+    stream.swrite(0u8)
 
 proc sread*(stream: Stream, b: var bool) =
   var n: uint8
@@ -164,6 +135,39 @@ proc sread*(stream: Stream, b: var bool) =
     assert n == 0u8
     b = false
 
+func slen*(b: bool): int =
+  return sizeof(uint8)
+
+proc swrite*(stream: Stream, url: Url) =
+  stream.swrite(url.serialize())
+
+proc sread*(stream: Stream, url: var Url) =
+  var s: string
+  stream.sread(s)
+  url = newURL(s)
+
+func slen*(url: Url): int =
+  slen(url.serialize())
+
+proc swrite*(stream: Stream, tup: tuple) =
+  for f in tup.fields:
+    stream.swrite(f)
+
+proc sread*(stream: Stream, tup: var tuple) =
+  for f in tup.fields:
+    stream.sread(f)
+
+func slen*(tup: tuple): int =
+  for f in tup.fields:
+    result += slen(f)
+
+proc swrite*[T](stream: Stream, s: seq[T]) =
+  stream.swrite(s.len)
+  var i = 0
+  for m in s:
+    stream.swrite(m)
+    inc i
+
 proc sread*[T](stream: Stream, s: var seq[T]) =
   var len: int
   stream.sread(len)
@@ -171,15 +175,16 @@ proc sread*[T](stream: Stream, s: var seq[T]) =
   for i in 0..<len:
     stream.sread(s[i])
 
-proc sread*[T](stream: Stream, o: var Option[T]) =
-  var x: bool
-  stream.sread(x)
-  if x:
-    var m: T
-    stream.sread(m)
-    o = some(m)
-  else:
-    o = none(T)
+func slen*(s: seq): int =
+  result = slen(s.len)
+  for x in s:
+    result += slen(x)
+
+proc swrite*[U, V](stream: Stream, t: Table[U, V]) =
+  stream.swrite(t.len)
+  for k, v in t:
+    stream.swrite(k)
+    stream.swrite(v)
 
 proc sread*[U, V](stream: Stream, t: var Table[U, V]) =
   var len: int
@@ -191,22 +196,43 @@ proc sread*[U, V](stream: Stream, t: var Table[U, V]) =
     stream.sread(v)
     t[k] = v
 
+func slen*[U, V](t: Table[U, V]): int =
+  result = slen(t.len)
+  for k, v in t:
+    result += slen(k)
+    result += slen(v)
+
+proc swrite*(stream: Stream, obj: object) =
+  for f in obj.fields:
+    stream.swrite(f)
+
 proc sread*(stream: Stream, obj: var object) =
   for f in obj.fields:
     stream.sread(f)
 
-proc sread*(stream: Stream, tup: var tuple) =
-  for f in tup.fields:
-    stream.sread(f)
+func slen*(obj: object): int =
+  for f in obj.fields:
+    result += slen(f)
+
+proc swrite*(stream: Stream, obj: ref object) =
+  stream.swrite(obj[])
 
-proc read*(stream: Stream, obj: var ref object) =
+proc sread*(stream: Stream, obj: var ref object) =
   new(obj)
   stream.sread(obj[])
 
-proc sread*(stream: Stream, url: var Url) =
-  var s: string
-  stream.sread(s)
-  url = newURL(s)
+func slen*(obj: ref object): int =
+  slen(obj[])
+
+proc swrite*(stream: Stream, part: MimePart) =
+  stream.swrite(part.isFile)
+  stream.swrite(part.name)
+  stream.swrite(part.content)
+  if part.isFile:
+    stream.swrite(part.filename)
+    stream.swrite(part.contentType)
+    stream.swrite(part.fileSize)
+    stream.swrite(part.isStream)
 
 proc sread*(stream: Stream, part: var MimePart) =
   var isFile: bool
@@ -223,15 +249,40 @@ proc sread*(stream: Stream, part: var MimePart) =
     stream.sread(part.fileSize)
     stream.sread(part.isStream)
 
-proc sread*(stream: Stream, color: var CellColor) =
-  var rgb: bool
-  stream.sread(rgb)
-  if rgb:
-    color = CellColor(rgb: true)
-    stream.sread(color.rgbcolor)
+func slen*(part: MimePart): int =
+  result += slen(part.isFile)
+  result += slen(part.name)
+  result += slen(part.content)
+  if part.isFile:
+    result += slen(part.filename)
+    result += slen(part.contentType)
+    result += slen(part.fileSize)
+    result += slen(part.isStream)
+
+proc swrite*[T](stream: Stream, o: Option[T]) =
+  stream.swrite(o.issome)
+  if o.isSome:
+    stream.swrite(o.get)
+
+proc sread*[T](stream: Stream, o: var Option[T]) =
+  var x: bool
+  stream.sread(x)
+  if x:
+    var m: T
+    stream.sread(m)
+    o = some(m)
   else:
-    color = CellColor(rgb: false)
-    stream.sread(color.color)
+    o = none(T)
+
+func slen*[T](o: Option[T]): int =
+  result = slen(o.isSome)
+  if o.isSome:
+    result += slen(o.get)
+
+proc swrite*(stream: Stream, regex: Regex) =
+  stream.swrite(regex.plen)
+  stream.writeData(regex.bytecode, regex.plen)
+  stream.swrite(regex.buf)
 
 proc sread*(stream: Stream, regex: var Regex) =
   assert regex.bytecode == nil
@@ -243,6 +294,20 @@ proc sread*(stream: Stream, regex: var Regex) =
   if l != regex.plen:
     `=destroy`(regex)
 
+func slen*(regex: Regex): int =
+  result += slen(regex.plen)
+  result += regex.plen
+  result += slen(regex.buf)
+
+proc swrite*(stream: Stream, source: BufferSource) =
+  stream.swrite(source.t)
+  case source.t
+  of CLONE: stream.swrite(source.clonepid)
+  of LOAD_REQUEST: stream.swrite(source.request)
+  of LOAD_PIPE: stream.swrite(source.fd)
+  stream.swrite(source.location)
+  stream.swrite(source.contenttype)
+
 proc sread*(stream: Stream, source: var BufferSource) =
   var t: BufferSourceType
   stream.sread(t)
@@ -258,3 +323,12 @@ proc sread*(stream: Stream, source: var BufferSource) =
     stream.sread(source.fd)
   stream.sread(source.location)
   stream.sread(source.contenttype)
+
+func slen*(source: BufferSource): int =
+  result += slen(source.t)
+  case source.t
+  of CLONE: result += slen(source.clonepid)
+  of LOAD_REQUEST: result += slen(source.request)
+  of LOAD_PIPE: result += slen(source.fd)
+  result += slen(source.location)
+  result += slen(source.contenttype)
diff --git a/src/ips/socketstream.nim b/src/ips/socketstream.nim
index c0abf07f..5d0485fa 100644
--- a/src/ips/socketstream.nim
+++ b/src/ips/socketstream.nim
@@ -11,12 +11,16 @@ import ips/serversocket
 
 type SocketStream* = ref object of Stream
   source*: Socket
-  recvw*: bool
+  blk*: bool
   isend: bool
 
 proc sockReadData(s: Stream, buffer: pointer, len: int): int =
   let s = SocketStream(s)
-  result = s.source.recv(buffer, len)
+  if s.blk:
+    while result < len:
+      result += s.source.recv(cast[pointer](cast[int](buffer) + result), len - result)
+  else:
+    result = s.source.recv(buffer, len)
   if result < 0:
     if errno == EAGAIN:
       raise newException(ErrorAgain, "")
@@ -30,7 +34,10 @@ proc sockReadData(s: Stream, buffer: pointer, len: int): int =
     s.isend = true
 
 proc sockWriteData(s: Stream, buffer: pointer, len: int) =
-  discard SocketStream(s).source.send(buffer, len)
+  #TODO maybe don't block if blk is false?
+  var i = 0
+  while i < len:
+    i += SocketStream(s).source.send(cast[pointer](cast[int](buffer) + i), len - i)
 
 proc sockAtEnd(s: Stream): bool =
   SocketStream(s).isend
@@ -94,6 +101,7 @@ func newSocketStream*(): SocketStream =
 
 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:
   #  sock.getFd().setBlocking(false)
@@ -106,8 +114,9 @@ proc connectSocketStream*(pid: Pid, buffered = true, blocking = true): SocketStr
   except OSError:
     return nil
 
-proc acceptSocketStream*(ssock: ServerSocket): SocketStream =
+proc acceptSocketStream*(ssock: ServerSocket, blocking = true): SocketStream =
   result = newSocketStream()
+  result.blk = blocking
   var sock: Socket
   ssock.sock.accept(sock, inheritable = true)
   result.source = sock