about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-02-11 00:40:51 +0100
committerbptato <nincsnevem662@gmail.com>2024-02-11 00:40:51 +0100
commitb0583b4760a11bd062781e0ea948c61c8b66ff8f (patch)
tree5bfb46cb1aa57d62fb40d6b6869ac8a875071561
parentd0690cfea6a87c7b7d801b968b5a1c85d1e99b4f (diff)
downloadchawan-b0583b4760a11bd062781e0ea948c61c8b66ff8f.tar.gz
Get rid of LOAD_PIPE BufferSource
Instead, use a stream: scheme and associate hostnames with file
descriptors directly from the pager.
-rw-r--r--src/io/serialize.nim5
-rw-r--r--src/loader/loader.nim116
-rw-r--r--src/loader/loaderhandle.nim2
-rw-r--r--src/local/client.nim6
-rw-r--r--src/local/container.nim33
-rw-r--r--src/local/pager.nim24
-rw-r--r--src/server/buffer.nim39
-rw-r--r--src/server/forkserver.nim11
-rw-r--r--src/types/buffersource.nim4
9 files changed, 130 insertions, 110 deletions
diff --git a/src/io/serialize.nim b/src/io/serialize.nim
index 0c9cfd8e..f27fb40d 100644
--- a/src/io/serialize.nim
+++ b/src/io/serialize.nim
@@ -389,7 +389,6 @@ proc swrite*(stream: Stream, source: BufferSource) =
   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)
   stream.swrite(source.charset)
@@ -404,9 +403,6 @@ proc sread*(stream: Stream, source: var BufferSource) =
   of LOAD_REQUEST:
     source = BufferSource(t: LOAD_REQUEST)
     stream.sread(source.request)
-  of LOAD_PIPE:
-    source = BufferSource(t: LOAD_PIPE)
-    stream.sread(source.fd)
   stream.sread(source.location)
   stream.sread(source.contentType)
   stream.sread(source.charset)
@@ -416,6 +412,5 @@ func slen*(source: BufferSource): int =
   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/loader/loader.nim b/src/loader/loader.nim
index fc409a90..3ca56cba 100644
--- a/src/loader/loader.nim
+++ b/src/loader/loader.nim
@@ -81,6 +81,9 @@ type
     ADDREF
     UNREF
     SET_REFERRER_POLICY
+    PASS_FD
+
+  ClientFdMap = seq[tuple[pid, fd: int, output: OutputHandle]]
 
   LoaderContext = ref object
     refcount: int
@@ -89,10 +92,12 @@ type
     config: LoaderConfig
     handleMap: Table[int, LoaderHandle]
     outputMap: Table[int, OutputHandle]
-    clientFdMap: seq[tuple[pid, fd: int, output: OutputHandle]]
+    clientFdMap: ClientFdMap
     referrerpolicy: ReferrerPolicy
     selector: Selector[int]
     fd: int
+    # List of file descriptors passed by the pager.
+    passedFdMap: Table[string, FileHandle]
 
   LoaderConfig* = object
     defaultheaders*: Headers
@@ -124,6 +129,52 @@ proc rejectHandle(handle: LoaderHandle, code: ConnectErrorCode, msg = "") =
   handle.sendResult(code, msg)
   handle.close()
 
+func findOutputIdx(clientFdMap: ClientFdMap, pid, fd: int): int =
+  for i, (itpid, itfd, _) in clientFdMap:
+    if pid == itpid and fd == itfd:
+      return i
+  return -1
+
+proc delOutput(clientFdMap: var ClientFdMap, pid, fd: int) =
+  let i = clientFdMap.findOutputIdx(pid, fd)
+  if i != -1:
+    clientFdMap.del(i)
+
+func findOutput(clientFdMap: ClientFdMap, pid, fd: int): OutputHandle =
+  let i = clientFdMap.findOutputIdx(pid, fd)
+  if i != -1:
+    return clientFdMap[i].output
+  return nil
+
+proc addFd(ctx: LoaderContext, handle: LoaderHandle) =
+  let output = handle.output
+  output.ostream.setBlocking(false)
+  ctx.selector.registerHandle(handle.istream.fd, {Read}, 0)
+  ctx.selector.registerHandle(output.ostream.fd, {Write}, 0)
+  let ofl = fcntl(handle.istream.fd, F_GETFL, 0)
+  discard fcntl(handle.istream.fd, F_SETFL, ofl or O_NONBLOCK)
+  ctx.handleMap[handle.istream.fd] = handle
+  if output.sostream != nil:
+    # replace the fd with the new one in outputMap if stream was
+    # redirected
+    # (kind of a hack, but should always work)
+    ctx.outputMap[output.ostream.fd] = output
+    ctx.outputMap.del(output.sostream.fd)
+    if output.clientPid != -1:
+      ctx.clientFdMap.delOutput(output.clientPid, output.clientFd)
+      output.clientFd = -1
+      output.clientPid = -1
+
+proc loadStream(ctx: LoaderContext, handle: LoaderHandle, request: Request) =
+  ctx.passedFdMap.withValue(request.url.host, fdp):
+    handle.sendResult(0)
+    handle.sendStatus(200)
+    handle.sendHeaders(newHeaders())
+    handle.istream = newPosixStream(fdp[])
+    ctx.passedFdMap.del(request.url.host)
+  do:
+    handle.rejectHandle(ERROR_FILE_NOT_FOUND, "stream not found")
+
 proc loadResource(ctx: LoaderContext, request: Request, handle: LoaderHandle) =
   var redo = true
   var tries = 0
@@ -141,26 +192,14 @@ proc loadResource(ctx: LoaderContext, request: Request, handle: LoaderHandle) =
           continue
     if request.url.scheme == "cgi-bin":
       handle.loadCGI(request, ctx.config.cgiDir, ctx.config.libexecPath, prevurl)
-      if handle.istream == nil:
-        handle.close()
+      if handle.istream != nil:
+        ctx.addFd(handle)
       else:
-        let output = handle.output
-        output.ostream.setBlocking(false)
-        ctx.selector.registerHandle(handle.istream.fd, {Read}, 0)
-        ctx.selector.registerHandle(output.ostream.fd, {Write}, 0)
-        let ofl = fcntl(handle.istream.fd, F_GETFL, 0)
-        discard fcntl(handle.istream.fd, F_SETFL, ofl or O_NONBLOCK)
-        ctx.handleMap[handle.istream.fd] = handle
-        if output.sostream != nil:
-          # replace the fd with the new one in outputMap if stream was
-          # redirected
-          # (kind of a hack, but should always work)
-          ctx.outputMap[output.ostream.fd] = output
-          ctx.outputMap.del(output.sostream.fd)
-          # currently only the main buffer stream can have redirects, and we
-          # don't suspend/resume it; if we did, we would have to put the new
-          # output stream's clientFd in clientFdMap too.
-          ctx.clientFdMap.del(output.sostream.fd)
+        handle.close()
+    elif request.url.scheme == "stream":
+      ctx.loadStream(handle, request)
+      if handle.istream != nil:
+        ctx.addFd(handle)
     else:
       prevurl = request.url
       case ctx.config.uriMethodMap.findAndRewrite(request.url)
@@ -208,18 +247,6 @@ proc onLoad(ctx: LoaderContext, stream: SocketStream) =
     ctx.clientFdMap.add((request.clientPid, request.clientFd, handle.output))
     ctx.loadResource(request, handle)
 
-func findClientFdEntry(ctx: LoaderContext, pid, fd: int): int =
-  for i, (itpid, itfd, _) in ctx.clientFdMap:
-    if pid == itpid and fd == itfd:
-      return i
-  return -1
-
-func findOutputByClientFd(ctx: LoaderContext, pid, fd: int): OutputHandle =
-  let i = ctx.findClientFdEntry(pid, fd)
-  if i != -1:
-    return ctx.clientFdMap[i].output
-  return nil
-
 proc acceptConnection(ctx: LoaderContext) =
   let stream = ctx.ssock.acceptSocketStream()
   try:
@@ -237,7 +264,7 @@ proc acceptConnection(ctx: LoaderContext) =
       stream.sread(fd)
       stream.sread(clientPid)
       stream.sread(clientFd)
-      let output = ctx.findOutputByClientFd(pid, fd)
+      let output = ctx.clientFdMap.findOutput(pid, fd)
       if output != nil:
         output.tee(stream, clientPid, clientFd)
       stream.swrite(output != nil)
@@ -247,7 +274,7 @@ proc acceptConnection(ctx: LoaderContext) =
       stream.sread(pid)
       stream.sread(fds)
       for fd in fds:
-        let output = ctx.findOutputByClientFd(pid, fd)
+        let output = ctx.clientFdMap.findOutput(pid, fd)
         if output != nil:
           # remove from the selector, so any new reads will be just placed
           # in the handle's buffer
@@ -258,7 +285,7 @@ proc acceptConnection(ctx: LoaderContext) =
       stream.sread(pid)
       stream.sread(fds)
       for fd in fds:
-        let output = ctx.findOutputByClientFd(pid, fd)
+        let output = ctx.clientFdMap.findOutput(pid, fd)
         if output != nil:
           # place the stream back into the selector, so we can write to it
           # again
@@ -275,6 +302,12 @@ proc acceptConnection(ctx: LoaderContext) =
     of SET_REFERRER_POLICY:
       stream.sread(ctx.referrerpolicy)
       stream.close()
+    of PASS_FD:
+      var id: string
+      stream.sread(id)
+      let fd = stream.recvFileHandle()
+      ctx.passedFdMap[id] = fd
+      stream.close()
   except ErrorBrokenPipe:
     # receiving end died while reading the file; give up.
     stream.close()
@@ -386,8 +419,7 @@ proc runFileLoader*(fd: cint, config: LoaderConfig) =
         ctx.selector.unregister(output.ostream.fd)
         ctx.outputMap.del(output.ostream.fd)
         if output.clientFd != -1:
-          let i = ctx.findClientFdEntry(output.clientPid, output.clientFd)
-          ctx.clientFdMap.del(i)
+          ctx.clientFdMap.delOutput(output.clientPid, output.clientFd)
         output.ostream.close()
         output.ostream = nil
         let handle = output.parent
@@ -666,4 +698,12 @@ proc setReferrerPolicy*(loader: FileLoader, referrerpolicy: ReferrerPolicy) =
   if stream != nil:
     stream.swrite(SET_REFERRER_POLICY)
     stream.swrite(referrerpolicy)
-  stream.close()
+    stream.close()
+
+proc passFd*(pid: Pid, id: string, fd: FileHandle) =
+  let stream = connectSocketStream(pid, buffered = false)
+  if stream != nil:
+    stream.swrite(PASS_FD)
+    stream.swrite(id)
+    stream.sendFileHandle(fd)
+    stream.close()
diff --git a/src/loader/loaderhandle.nim b/src/loader/loaderhandle.nim
index 6cdfd19f..7f583d2b 100644
--- a/src/loader/loaderhandle.nim
+++ b/src/loader/loaderhandle.nim
@@ -137,8 +137,6 @@ proc sendHeaders*(handle: LoaderHandle, headers: Headers) =
       let fd = SocketStream(output.ostream).recvFileHandle()
       output.sostream = output.ostream
       output.ostream = newPosixStream(fd)
-      output.clientFd = -1
-      output.clientPid = -1
 
 proc sendData*(output: OutputHandle, p: pointer, nmemb: int): int =
   return output.ostream.sendData(p, nmemb)
diff --git a/src/local/client.nim b/src/local/client.nim
index ae838360..76cbd4e7 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -516,7 +516,7 @@ proc addConsole(pager: Pager, interactive: bool, clearFun, showFun, hideFun:
     var pipefd: array[0..1, cint]
     if pipe(pipefd) == -1:
       raise newException(Defect, "Failed to open console pipe.")
-    let url = newURL("javascript:console.show()").get
+    let url = newURL("stream:console").get
     let container = pager.readPipe0(some("text/plain"), CHARSET_UNKNOWN,
       pipefd[0], some(url), ConsoleTitle, canreinterpret = false)
     let err = newPosixStream(pipefd[1])
@@ -543,7 +543,7 @@ proc clearConsole(client: Client) =
   var pipefd: array[0..1, cint]
   if pipe(pipefd) == -1:
     raise newException(Defect, "Failed to open console pipe.")
-  let url = newURL("javascript:console.show()").get
+  let url = newURL("stream:console").get
   let pager = client.pager
   let replacement = pager.readPipe0(some("text/plain"), CHARSET_UNKNOWN,
     pipefd[0], some(url), ConsoleTitle, canreinterpret = false)
@@ -613,7 +613,7 @@ proc launchClient*(client: Client, pages: seq[string],
       module = ismodule)
 
   if not stdin.isatty():
-    client.pager.readPipe(contentType, cs, stdin.getFileHandle())
+    client.pager.readPipe(contentType, cs, stdin.getFileHandle(), "*stdin*")
 
   for page in pages:
     client.pager.loadURL(page, ctype = contentType, cs = cs)
diff --git a/src/local/container.nim b/src/local/container.nim
index 2bf53756..770297f4 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -15,6 +15,7 @@ import js/javascript
 import js/jstypes
 import js/regex
 import loader/connecterror
+import loader/loader
 import loader/request
 import local/select
 import server/buffer
@@ -99,6 +100,7 @@ type
     bpos: seq[CursorPosition]
     highlights: seq[Highlight]
     process* {.jsget.}: Pid
+    loaderPid* {.jsget.}: Pid
     loadinfo*: string
     lines: SimpleFlexibleGrid
     lineshift: int
@@ -129,10 +131,19 @@ jsDestructor(Container)
 
 proc newBuffer*(forkserver: ForkServer, config: BufferConfig,
     source: BufferSource, title = "", redirectdepth = 0,
-    canreinterpret = true): Container =
+    canreinterpret = true, fd = FileHandle(-1)): Container =
   let attrs = getWindowAttributes(stdout)
+  let (process, loaderPid) = forkserver.forkBuffer(source, config, attrs)
+  if fd != -1:
+    loaderPid.passFd(source.location.host, fd)
+    if fd == 0:
+      # We are passing stdin.
+      closeStdin()
+    else:
+      discard close(fd)
   return Container(
-    process: forkserver.forkBuffer(source, config, attrs),
+    process: process,
+    loaderPid: loaderPid,
     source: source,
     width: attrs.width,
     height: attrs.height - 1,
@@ -1377,10 +1388,12 @@ proc redirectToFd*(container: Container, fdin: FileHandle, wait: bool):
     EmptyPromise =
   return container.iface.redirectToFd(fdin, wait)
 
-proc readFromFd*(container: Container, fdout: FileHandle, ishtml: bool):
-    EmptyPromise =
+proc readFromFd*(container: Container, fdout: FileHandle, id: string,
+    ishtml: bool): EmptyPromise =
   container.ishtml = ishtml
-  return container.iface.readFromFd(fdout, ishtml)
+  let url = newURL("stream:" & id).get
+  container.loaderPid.passFd(url.host, fdout)
+  return container.iface.readFromFd(url, ishtml)
 
 proc quit*(container: Container) =
   container.triggerEvent(QUIT)
@@ -1510,16 +1523,6 @@ proc handleCommand(container: Container) =
 proc setStream*(container: Container, stream: Stream) =
   if not container.cloned:
     container.iface = newBufferInterface(stream)
-    if container.source.t == LOAD_PIPE:
-      container.iface.passFd(container.source.fd).then(proc() =
-        if container.source.fd == 0:
-          # We are closing stdin.
-          # Leaving the stdin fileno open to grab is a bad idea.
-          closeStdin()
-        else:
-          discard close(container.source.fd)
-      )
-      stream.flush()
     container.load()
   else:
     container.iface = cloneInterface(stream)
diff --git a/src/local/pager.nim b/src/local/pager.nim
index 9633293a..6a4f3522 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -444,14 +444,16 @@ proc addContainer*(pager: Pager, container: Container) =
   pager.setContainer(container)
 
 proc newBuffer(pager: Pager, bufferConfig: BufferConfig, source: BufferSource,
-    title = "", redirectdepth = 0, canreinterpret = true): Container =
+    title = "", redirectdepth = 0, canreinterpret = true,
+    fd = FileHandle(-1)): Container =
   return newBuffer(
     pager.forkserver,
     bufferConfig,
     source,
     title,
     redirectdepth,
-    canreinterpret
+    canreinterpret,
+    fd
   )
 
 proc dupeBuffer2(pager: Pager, container: Container, location: URL,
@@ -772,21 +774,21 @@ proc loadURL*(pager: Pager, url: string, ctype = none(string),
 proc readPipe0*(pager: Pager, ctype: Option[string], cs: Charset,
     fd: FileHandle, location: Option[URL], title: string,
     canreinterpret: bool): Container =
-  var location = location.get(newURL("file://-").get)
+  var location = location.get(newURL("stream:-").get)
   let bufferconfig = pager.applySiteconf(location)
   let source = BufferSource(
-    t: LOAD_PIPE,
-    fd: fd,
+    t: LOAD_REQUEST,
+    request: newRequest(location),
     contentType: some(ctype.get("text/plain")),
     charset: cs,
     location: location
   )
   return pager.newBuffer(bufferconfig, source, title = title,
-    canreinterpret = canreinterpret)
+    canreinterpret = canreinterpret, fd = fd)
 
-proc readPipe*(pager: Pager, ctype: Option[string], cs: Charset,
-    fd: FileHandle) =
-  let container = pager.readPipe0(ctype, cs, fd, none(URL), "*pipe*", true)
+proc readPipe*(pager: Pager, ctype: Option[string], cs: Charset, fd: FileHandle,
+    title: string) =
+  let container = pager.readPipe0(ctype, cs, fd, none(URL), title, true)
   pager.addContainer(container)
 
 proc command(pager: Pager) {.jsfunc.} =
@@ -973,7 +975,7 @@ proc runMailcapReadPipe(pager: Pager, container: Container,
   let p2 = p.then(proc(): auto =
     discard close(fdin)
     let ishtml = HTMLOUTPUT in entry.flags
-    return container.readFromFd(fdout, ishtml)
+    return container.readFromFd(fdout, $pid, ishtml)
   ).then(proc() =
     discard close(fdout)
   )
@@ -1045,7 +1047,7 @@ proc runMailcapReadFile(pager: Pager, container: Container,
     discard close(pipefd[1])
     let fdout = pipefd[0]
     let ishtml = HTMLOUTPUT in entry.flags
-    return container.readFromFd(fdout, ishtml).then(proc() =
+    return container.readFromFd(fdout, $pid, ishtml).then(proc() =
       discard close(fdout)
     )
   )
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index 851f04f1..817dae82 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -64,8 +64,8 @@ type
     LOAD, RENDER, WINDOW_CHANGE, FIND_ANCHOR, READ_SUCCESS, READ_CANCELED,
     CLICK, FIND_NEXT_LINK, FIND_PREV_LINK, FIND_NTH_LINK, FIND_REV_NTH_LINK,
     FIND_NEXT_MATCH, FIND_PREV_MATCH, GET_SOURCE, GET_LINES, UPDATE_HOVER,
-    PASS_FD, CONNECT, CONNECT2, GOTO_ANCHOR, CANCEL, GET_TITLE, SELECT,
-    REDIRECT_TO_FD, READ_FROM_FD, SET_CONTENT_TYPE, CLONE, FIND_PREV_PARAGRAPH,
+    CONNECT, CONNECT2, GOTO_ANCHOR, CANCEL, GET_TITLE, SELECT, REDIRECT_TO_FD,
+    READ_FROM_FD, SET_CONTENT_TYPE, CLONE, FIND_PREV_PARAGRAPH,
     FIND_NEXT_PARAGRAPH
 
   # LOADING_PAGE: istream open
@@ -774,12 +774,6 @@ proc connect*(buffer: Buffer): ConnectResult {.proxy.} =
       return ConnectResult(code: ERROR_SOURCE_NOT_FOUND)
     if buffer.source.contentType.isNone:
       buffer.source.contentType = some("text/plain")
-  of LOAD_PIPE:
-    discard fcntl(source.fd, F_SETFL, fcntl(source.fd, F_GETFL, 0) or O_NONBLOCK)
-    buffer.istream = newPosixStream(source.fd)
-    buffer.fd = source.fd
-    if buffer.source.contentType.isNone:
-      buffer.source.contentType = some("text/plain")
   of LOAD_REQUEST:
     let request = source.request
     let response = buffer.loader.doRequest(request, blocking = true, canredir = true)
@@ -844,37 +838,27 @@ proc redirectToFd*(buffer: Buffer, fd: FileHandle, wait: bool) {.proxy.} =
       ss.sread(dummy)
     discard close(fd)
     ss.close()
-  of LOAD_PIPE:
-    let ps = newPosixStream(fd)
-    let bfd = cint(buffer.fd)
-    #TODO make it work without wait
-    discard fcntl(bfd, F_SETFL, fcntl(bfd, F_GETFL, 0) and not O_NONBLOCK)
-    var buf: array[4096, uint8]
-    while not buffer.istream.atEnd:
-      let n = buffer.istream.readData(addr buf[0], buf.len)
-      ps.writeData(addr buf[0], n)
-    ps.close()
-    buffer.fd = -1
-    buffer.istream.close()
   of CLONE:
     discard
 
-proc readFromFd*(buffer: Buffer, fd: FileHandle, ishtml: bool) {.proxy.} =
+proc readFromFd*(buffer: Buffer, url: URL, ishtml: bool) {.proxy.} =
   let contentType = if ishtml:
     "text/html"
   else:
     "text/plain"
+  let request = newRequest(url)
   buffer.source = BufferSource(
-    t: LOAD_PIPE,
-    fd: fd,
+    t: LOAD_REQUEST,
+    request: request,
     location: buffer.source.location,
     contentType: some(contentType),
     charset: buffer.source.charset
   )
   buffer.setHTML(ishtml)
-  discard fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) or O_NONBLOCK)
-  buffer.istream = newPosixStream(fd)
-  buffer.fd = fd
+  let response = buffer.loader.doRequest(request, blocking = true,
+    canredir = false)
+  buffer.istream = response.body
+  buffer.fd = int(SocketStream(response.body).source.getFd())
   buffer.selector.registerHandle(buffer.fd, {Read}, 0)
 
 proc setContentType*(buffer: Buffer, contentType: string) {.proxy.} =
@@ -1635,9 +1619,6 @@ proc getLines*(buffer: Buffer, w: Slice[int]): GetLinesResult {.proxy.} =
     result.lines.add(line)
   result.numLines = buffer.lines.len
 
-proc passFd*(buffer: Buffer, fd: FileHandle) {.proxy.} =
-  buffer.source.fd = fd
-
 #TODO this is mostly broken
 proc getSource*(buffer: Buffer) {.proxy.} =
   let ssock = initServerSocket()
diff --git a/src/server/forkserver.nim b/src/server/forkserver.nim
index 9ad9c8a9..ced32341 100644
--- a/src/server/forkserver.nim
+++ b/src/server/forkserver.nim
@@ -63,15 +63,18 @@ proc removeChild*(forkserver: ForkServer, pid: Pid) =
   forkserver.ostream.flush()
 
 proc forkBuffer*(forkserver: ForkServer, source: BufferSource,
-    config: BufferConfig, attrs: WindowAttributes): Pid =
+    config: BufferConfig, attrs: WindowAttributes):
+    tuple[process, loaderPid: Pid] =
   forkserver.ostream.swrite(FORK_BUFFER)
   forkserver.ostream.swrite(source)
   forkserver.ostream.swrite(config)
   forkserver.ostream.swrite(attrs)
   forkserver.ostream.flush()
   var process: Pid
+  var loaderPid: Pid
   forkserver.istream.sread(process)
-  return process
+  forkserver.istream.sread(loaderPid)
+  return (process, loaderPid)
 
 proc trapSIGINT() =
   # trap SIGINT, so e.g. an external editor receiving an interrupt in the
@@ -114,7 +117,7 @@ proc forkLoader(ctx: var ForkServerContext, config: LoaderConfig): Pid =
   return pid
 
 var gssock: ServerSocket
-proc forkBuffer(ctx: var ForkServerContext): Pid =
+proc forkBuffer(ctx: var ForkServerContext): tuple[process, loaderPid: Pid] =
   var source: BufferSource
   var config: BufferConfig
   var attrs: WindowAttributes
@@ -164,7 +167,7 @@ proc forkBuffer(ctx: var ForkServerContext): Pid =
   assert c == char(0)
   ps.close()
   ctx.children.add((pid, loaderPid))
-  return pid
+  return (pid, loaderPid)
 
 proc runForkServer() =
   var ctx = ForkServerContext(
diff --git a/src/types/buffersource.nim b/src/types/buffersource.nim
index 40b0f5a7..6377464e 100644
--- a/src/types/buffersource.nim
+++ b/src/types/buffersource.nim
@@ -10,7 +10,7 @@ import chakasu/charset
 
 type
   BufferSourceType* = enum
-    CLONE, LOAD_REQUEST, LOAD_PIPE
+    CLONE, LOAD_REQUEST
 
   BufferSource* = object
     location*: URL
@@ -21,5 +21,3 @@ type
       clonepid*: Pid
     of LOAD_REQUEST:
       request*: Request
-    of LOAD_PIPE:
-      fd*: FileHandle