about summary refs log tree commit diff stats
path: root/src/io
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-05-30 00:19:48 +0200
committerbptato <nincsnevem662@gmail.com>2024-06-20 17:50:22 +0200
commit60dc37269cd2dc8cdf23d9f77680f6af9490032f (patch)
tree9a72ba24daffa546f92704e7e06cf84fded2d89d /src/io
parenta146a22b11cea39bc691417d9d9a1292b7177552 (diff)
downloadchawan-60dc37269cd2dc8cdf23d9f77680f6af9490032f.tar.gz
img, loader: separate out png codec into cgi, misc improvements
* multi-processed and sandboxed PNG decoding & encoding (through local
  CGI)
* improved request body passing (including support for output id as
  response body)
* simplified & faster blob()/text() - now every request starts
  suspended, and OngoingData.buf has been replaced with loader's
  buffering capability
* image caching: we no longer pull bitmaps from the container after
  every single getLines call

Next steps: replace our bespoke PNG decoder with something more usable,
add other decoders, and make them stream.
Diffstat (limited to 'src/io')
-rw-r--r--src/io/bufreader.nim41
-rw-r--r--src/io/bufwriter.nim26
-rw-r--r--src/io/promise.nim10
-rw-r--r--src/io/urlfilter.nim2
4 files changed, 74 insertions, 5 deletions
diff --git a/src/io/bufreader.nim b/src/io/bufreader.nim
index 90940424..bd2486be 100644
--- a/src/io/bufreader.nim
+++ b/src/io/bufreader.nim
@@ -2,8 +2,10 @@ import std/options
 import std/sets
 import std/tables
 
+import img/bitmap
 import io/dynstream
 import io/socketstream
+import loader/request
 import types/blob
 import types/color
 import types/formdata
@@ -32,6 +34,8 @@ proc sread*(reader: var BufferedReader; blob: var Blob)
 proc sread*[T](reader: var BufferedReader; o: var Option[T])
 proc sread*[T, E](reader: var BufferedReader; o: var Result[T, E])
 proc sread*(reader: var BufferedReader; c: var ARGBColor) {.inline.}
+proc sread*(reader: var BufferedReader; o: var RequestBody)
+proc sread*(reader: var BufferedReader; bmp: var Bitmap)
 
 proc initReader*(stream: DynStream; len, auxLen: int): BufferedReader =
   assert len != 0
@@ -169,7 +173,7 @@ proc sread*(reader: var BufferedReader; blob: var Blob) =
     let buffer = alloc(blob.size)
     reader.readData(blob.buffer, int(blob.size))
     blob.buffer = buffer
-    blob.deallocFun = proc() = dealloc(buffer)
+    blob.deallocFun = deallocBlob
 
 proc sread*[T](reader: var BufferedReader; o: var Option[T]) =
   var x: bool
@@ -201,3 +205,38 @@ proc sread*[T, E](reader: var BufferedReader; o: var Result[T, E]) =
 
 proc sread*(reader: var BufferedReader; c: var ARGBColor) =
   reader.sread(uint32(c))
+
+proc sread*(reader: var BufferedReader; o: var RequestBody) =
+  var t: RequestBodyType
+  reader.sread(t)
+  o = RequestBody(t: t)
+  case t
+  of rbtNone: discard
+  of rbtString: reader.sread(o.s)
+  of rbtMultipart: reader.sread(o.multipart)
+  of rbtOutput: reader.sread(o.outputId)
+
+proc sread*(reader: var BufferedReader; bmp: var Bitmap) =
+  var isImageBitmap: bool
+  var width: uint64
+  var height: uint64
+  reader.sread(isImageBitmap)
+  reader.sread(width)
+  reader.sread(height)
+  if isImageBitmap:
+    bmp = ImageBitmap(
+      width: width,
+      height: height
+    )
+    reader.sread(bmp.px)
+  else:
+    var outputId: int
+    var imageId: int
+    reader.sread(outputId)
+    reader.sread(imageId)
+    bmp = NetworkBitmap(
+      width: width,
+      height: height,
+      outputId: outputId,
+      imageId: imageId
+    )
diff --git a/src/io/bufwriter.nim b/src/io/bufwriter.nim
index fd3c12a8..56e30f5b 100644
--- a/src/io/bufwriter.nim
+++ b/src/io/bufwriter.nim
@@ -5,8 +5,10 @@ import std/options
 import std/sets
 import std/tables
 
+import img/bitmap
 import io/dynstream
 import io/socketstream
+import loader/request
 import types/blob
 import types/color
 import types/formdata
@@ -34,7 +36,7 @@ proc swrite*(writer: var BufferedWriter; b: bool)
 proc swrite*(writer: var BufferedWriter; url: URL)
 proc swrite*(writer: var BufferedWriter; tup: tuple)
 proc swrite*[I, T](writer: var BufferedWriter; a: array[I, T])
-proc swrite*(writer: var BufferedWriter; s: seq)
+proc swrite*[T](writer: var BufferedWriter; s: openArray[T])
 proc swrite*[U, V](writer: var BufferedWriter; t: Table[U, V])
 proc swrite*(writer: var BufferedWriter; obj: object)
 proc swrite*(writer: var BufferedWriter; obj: ref object)
@@ -43,6 +45,8 @@ proc swrite*(writer: var BufferedWriter; blob: Blob)
 proc swrite*[T](writer: var BufferedWriter; o: Option[T])
 proc swrite*[T, E](writer: var BufferedWriter; o: Result[T, E])
 proc swrite*(writer: var BufferedWriter; c: ARGBColor) {.inline.}
+proc swrite*(writer: var BufferedWriter; o: RequestBody)
+proc swrite*(writer: var BufferedWriter; bmp: Bitmap)
 
 const InitLen = sizeof(int) * 2
 const SizeInit = max(64, InitLen)
@@ -130,7 +134,7 @@ proc swrite*[I, T](writer: var BufferedWriter; a: array[I, T]) =
   for x in a:
     writer.swrite(x)
 
-proc swrite*(writer: var BufferedWriter; s: seq) =
+proc swrite*[T](writer: var BufferedWriter; s: openArray[T]) =
   writer.swrite(s.len)
   for x in s:
     writer.swrite(x)
@@ -188,3 +192,21 @@ proc swrite*[T, E](writer: var BufferedWriter; o: Result[T, E]) =
 
 proc swrite*(writer: var BufferedWriter; c: ARGBColor) =
   writer.swrite(uint32(c))
+
+proc swrite*(writer: var BufferedWriter; o: RequestBody) =
+  writer.swrite(o.t)
+  case o.t
+  of rbtNone: discard
+  of rbtString: writer.swrite(o.s)
+  of rbtMultipart: writer.swrite(o.multipart)
+  of rbtOutput: writer.swrite(o.outputId)
+
+proc swrite*(writer: var BufferedWriter; bmp: Bitmap) =
+  writer.swrite(bmp of ImageBitmap)
+  writer.swrite(bmp.width)
+  writer.swrite(bmp.height)
+  if bmp of ImageBitmap:
+    writer.swrite(bmp.px)
+  else:
+    writer.swrite(NetworkBitmap(bmp).outputId)
+    writer.swrite(NetworkBitmap(bmp).imageId)
diff --git a/src/io/promise.nim b/src/io/promise.nim
index 183091cb..a1a5cfc9 100644
--- a/src/io/promise.nim
+++ b/src/io/promise.nim
@@ -132,6 +132,14 @@ proc then*[T](promise: Promise[T]; cb: (proc(x: T): EmptyPromise)): EmptyPromise
       next.resolve())
   return next
 
+proc then*[T](promise: EmptyPromise; cb: (proc(): T)): Promise[T]
+    {.discardable.} =
+  let next = Promise[T]()
+  promise.then(proc() =
+    next.res = cb()
+    next.resolve())
+  return next
+
 proc then*[T, U](promise: Promise[T]; cb: (proc(x: T): U)): Promise[U]
     {.discardable.} =
   let next = Promise[U]()
@@ -195,7 +203,7 @@ proc promiseThenCallback(ctx: JSContext; this_val: JSValue; argc: cint;
 
 proc fromJSEmptyPromise*(ctx: JSContext; val: JSValue): JSResult[EmptyPromise] =
   if not JS_IsObject(val):
-    return err(newTypeError("Value is not an object"))
+    return errTypeError("Value is not an object")
   var p = EmptyPromise()
   GC_ref(p)
   let tmp = JS_NewObject(ctx)
diff --git a/src/io/urlfilter.nim b/src/io/urlfilter.nim
index e86e0e6b..20983498 100644
--- a/src/io/urlfilter.nim
+++ b/src/io/urlfilter.nim
@@ -6,7 +6,7 @@ import types/url
 #TODO add denyhost/s for blocklists
 type URLFilter* = object
   scheme: Option[string]
-  allowschemes: seq[string]
+  allowschemes*: seq[string]
   allowhost*: Option[string]
   allowhosts: seq[Regex]
   default: bool