about summary refs log tree commit diff stats
path: root/src/local
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-09-23 18:07:23 +0200
committerbptato <nincsnevem662@gmail.com>2024-09-23 18:08:14 +0200
commit8e8c7f0911f4a20446a83090d722fecaf203f6f3 (patch)
tree334a897643051bc6e16d564591ddecba22af565d /src/local
parent3b3d517130bb42ec69e6f684510e3b3a3668947c (diff)
downloadchawan-8e8c7f0911f4a20446a83090d722fecaf203f6f3.tar.gz
client, forkserver, dynstream: misc refactorings, fixes
* fix broken int conversion in dynstream
* fix EPIPE handling in forkserver
* merge fdmap and connectingContainers into loader map
Diffstat (limited to 'src/local')
-rw-r--r--src/local/client.nim125
-rw-r--r--src/local/pager.nim45
2 files changed, 84 insertions, 86 deletions
diff --git a/src/local/client.nim b/src/local/client.nim
index c20a460b..6c1d505c 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -57,13 +57,15 @@ type
     alive: bool
     config {.jsget.}: Config
     consoleWrapper: ConsoleWrapper
-    fdmap: seq[Container]
     feednext: bool
     pager {.jsget.}: Pager
-    pressed: tuple[col: int; row: int]
+    pressed: tuple[col, row: int]
     exitCode: int
     inEval: bool
 
+  ContainerData = ref object of MapData
+    container: Container
+
   ConsoleWrapper = object
     console: Console
     container: Container
@@ -380,17 +382,17 @@ proc acceptBuffers(client: Client) =
       let stream = container.iface.stream
       let fd = int(stream.source.fd)
       client.selector.unregister(fd)
-      client.fdmap[fd] = nil
+      client.loader.unset(fd)
       stream.sclose()
     elif container.process != -1: # connecting to buffer process
       let i = pager.findProcMapItem(container.process)
       pager.procmap.del(i)
-    elif (let i = pager.findConnectingContainer(container); i != -1):
+    elif (let item = pager.findConnectingContainer(container); item != nil):
       # connecting to URL
-      let stream = pager.connectingContainers[i].stream
+      let stream = item.stream
       client.selector.unregister(int(stream.fd))
       stream.sclose()
-      pager.connectingContainers.del(i)
+      client.loader.unset(item)
   let registerFun = proc(fd: int) =
     client.selector.unregister(fd)
     client.selector.registerHandle(fd, {Read, Write}, 0)
@@ -441,63 +443,67 @@ proc acceptBuffers(client: Client) =
       loader.shareCachedItem(container.cacheId, loader.clientPid)
       container.setCloneStream(stream, registerFun)
     let fd = int(stream.fd)
-    if client.fdmap.len <= fd:
-      client.fdmap.setLen(fd + 1)
-    client.fdmap[fd] = container
+    client.loader.put(ContainerData(stream: stream, container: container))
     client.selector.registerHandle(fd, {Read}, 0)
     pager.handleEvents(container)
   pager.procmap.setLen(0)
 
+proc handleStderr(client: Client) =
+  const BufferSize = 4096
+  const prefix = "STDERR: "
+  var buffer {.noinit.}: array[BufferSize, char]
+  let estream = client.forkserver.estream
+  var hadlf = true
+  while true:
+    try:
+      let n = estream.recvData(buffer)
+      if n == 0:
+        break
+      var i = 0
+      while i < n:
+        var j = n
+        var found = false
+        for k in i ..< n:
+          if buffer[k] == '\n':
+            j = k + 1
+            found = true
+            break
+        if hadlf:
+          client.console.err.write(prefix)
+        if j - i > 0:
+          client.console.err.write(buffer.toOpenArray(i, j - 1))
+        i = j
+        hadlf = found
+    except ErrorAgain:
+      break
+  if not hadlf:
+    client.console.err.write('\n')
+  client.console.err.sflush()
+
 proc handleRead(client: Client; fd: int) =
   if client.pager.term.istream != nil and fd == client.pager.term.istream.fd:
     client.input().then(proc() =
       client.pager.handleEvents()
     )
-  elif (let i = client.pager.findConnectingContainer(fd); i != -1):
-    client.pager.handleConnectingContainer(i)
   elif fd == client.forkserver.estream.fd:
-    const BufferSize = 4096
-    const prefix = "STDERR: "
-    var buffer {.noinit.}: array[BufferSize, char]
-    let estream = client.forkserver.estream
-    var hadlf = true
-    while true:
-      try:
-        let n = estream.recvData(buffer)
-        if n == 0:
-          break
-        var i = 0
-        while i < n:
-          var j = n
-          var found = false
-          for k in i ..< n:
-            if buffer[k] == '\n':
-              j = k + 1
-              found = true
-              break
-          if hadlf:
-            client.console.err.write(prefix)
-          if j - i > 0:
-            client.console.err.write(buffer.toOpenArray(i, j - 1))
-          i = j
-          hadlf = found
-      except ErrorAgain:
-        break
-    if not hadlf:
-      client.console.err.write('\n')
-    client.console.err.sflush()
+    client.handleStderr()
   elif (let data = client.loader.get(fd); data != nil):
-    client.loader.onRead(fd)
-    if data of ConnectData:
-      client.runJSJobs()
+    if data of ConnectingContainer:
+      client.pager.handleRead(ConnectingContainer(data))
+    elif data of ContainerData:
+      let container = ContainerData(data).container
+      client.pager.handleEvent(container)
+    else:
+      client.loader.onRead(fd)
+      if data of ConnectData:
+        client.runJSJobs()
   elif fd in client.loader.unregistered:
     discard # ignore
   else:
-    let container = client.fdmap[fd]
-    client.pager.handleEvent(container)
+    assert false
 
 proc handleWrite(client: Client; fd: int) =
-  let container = client.fdmap[fd]
+  let container = ContainerData(client.loader.get(fd)).container
   if container.iface.stream.flushWrite():
     client.selector.unregister(fd)
     client.selector.registerHandle(fd, {Read}, 0)
@@ -519,25 +525,26 @@ proc handleError(client: Client; fd: int) =
     #TODO do something here...
     stderr.write("Fork server crashed :(\n")
     client.quit(1)
-  elif client.loader.get(fd) != nil:
-    discard client.loader.onError(fd) #TODO handle connection error?
-  elif fd in client.loader.unregistered:
-    discard # already unregistered...
-  elif (let i = client.pager.findConnectingContainer(fd); i != -1):
-    client.pager.handleConnectingContainerError(i)
-  else:
-    if fd < client.fdmap.len and client.fdmap[fd] != nil:
-      let container = client.fdmap[fd]
+  elif (let data = client.loader.get(fd); data != nil):
+    if data of ConnectingContainer:
+      client.pager.handleError(ConnectingContainer(data))
+    elif data of ContainerData:
+      let container = ContainerData(data).container
       if container != client.consoleWrapper.container:
         client.console.error("Error in buffer", $container.url)
       else:
         client.consoleWrapper.container = nil
       client.selector.unregister(fd)
-      client.fdmap[fd] = nil
-    if client.consoleWrapper.container != nil:
+      client.loader.unset(fd)
+      doAssert client.consoleWrapper.container != nil
       client.showConsole()
     else:
-      doAssert false
+      discard client.loader.onError(fd) #TODO handle connection error?
+  elif fd in client.loader.unregistered:
+    discard # already unregistered...
+  else:
+    doAssert client.consoleWrapper.container != nil
+    client.showConsole()
 
 proc inputLoop(client: Client) =
   let selector = client.selector
diff --git a/src/local/pager.nim b/src/local/pager.nim
index edcf614b..35f6ab4c 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -85,10 +85,9 @@ type
   ContainerConnectionState = enum
     ccsBeforeResult, ccsBeforeStatus, ccsBeforeHeaders
 
-  ConnectingContainerItem = ref object
+  ConnectingContainer* = ref object of MapData
     state: ContainerConnectionState
     container: Container
-    stream*: SocketStream
     res: int
     outputId: int
     status: uint16
@@ -124,7 +123,6 @@ type
     askprompt: string
     commandMode {.jsget.}: bool
     config*: Config
-    connectingContainers*: seq[ConnectingContainerItem]
     container*: Container
     cookiejars: Table[string, CookieJar]
     devRandom: PosixStream
@@ -788,7 +786,7 @@ proc newContainer(pager: Pager; bufferConfig: BufferConfig;
     cacheId,
     pager.config
   )
-  pager.connectingContainers.add(ConnectingContainerItem(
+  pager.loader.put(ConnectingContainer(
     state: ccsBeforeResult,
     container: container,
     stream: stream
@@ -808,17 +806,14 @@ proc newContainerFrom(pager: Pager; container: Container; contentType: string):
     url = container.url
   )
 
-func findConnectingContainer*(pager: Pager; fd: int): int =
-  for i, item in pager.connectingContainers:
-    if item.stream.fd == fd:
-      return i
-  -1
-
-func findConnectingContainer*(pager: Pager; container: Container): int =
-  for i, item in pager.connectingContainers:
-    if item.container == container:
-      return i
-  -1
+func findConnectingContainer*(pager: Pager; container: Container):
+    ConnectingContainer =
+  for item in pager.loader.data:
+    if item of ConnectingContainer:
+      let item = ConnectingContainer(item)
+      if item.container == container:
+        return item
+  return nil
 
 func findProcMapItem*(pager: Pager; pid: int): int =
   for i, item in pager.procmap:
@@ -2053,9 +2048,7 @@ proc unregisterFd(pager: Pager; fd: int) =
   pager.selector.unregister(fd)
   pager.loader.unregistered.add(fd)
 
-# true if done, false if keep
-proc handleConnectingContainer*(pager: Pager; i: int) =
-  let item = pager.connectingContainers[i]
+proc handleRead*(pager: Pager; item: ConnectingContainer) =
   let container = item.container
   let stream = item.stream
   case item.state
@@ -2076,7 +2069,7 @@ proc handleConnectingContainer*(pager: Pager; i: int) =
         msg = getLoaderErrorMessage(res)
       pager.fail(container, msg)
       # done
-      pager.connectingContainers.del(i)
+      pager.loader.unset(item)
       pager.unregisterFd(int(item.stream.fd))
       stream.sclose()
   of ccsBeforeStatus:
@@ -2090,7 +2083,7 @@ proc handleConnectingContainer*(pager: Pager; i: int) =
     var r = stream.initPacketReader()
     r.sread(response.headers)
     # done
-    pager.connectingContainers.del(i)
+    pager.loader.unset(item)
     pager.unregisterFd(int(item.stream.fd))
     let redirect = response.getRedirect(container.request)
     if redirect != nil:
@@ -2099,12 +2092,11 @@ proc handleConnectingContainer*(pager: Pager; i: int) =
     else:
       pager.connected(container, response)
 
-proc handleConnectingContainerError*(pager: Pager; i: int) =
-  let item = pager.connectingContainers[i]
+proc handleError*(pager: Pager; item: ConnectingContainer) =
   pager.fail(item.container, "loader died while loading")
   pager.unregisterFd(int(item.stream.fd))
   item.stream.sclose()
-  pager.connectingContainers.del(i)
+  pager.loader.unset(item)
 
 proc metaRefresh(pager: Pager; container: Container; n: int; url: URL) =
   let ctx = pager.jsctx
@@ -2174,16 +2166,15 @@ proc handleEvent0(pager: Pager; container: Container; event: ContainerEvent):
     if pager.container == container:
       pager.alert(event.msg)
   of cetCancel:
-    let i = pager.findConnectingContainer(container)
-    if i == -1:
+    let item = pager.findConnectingContainer(container)
+    if item == nil:
       # whoops. we tried to cancel, but the event loop did not favor us...
       # at least cancel it in the buffer
       container.remoteCancel()
     else:
-      let item = pager.connectingContainers[i]
       dec pager.numload
       pager.deleteContainer(container, container.find(ndAny))
-      pager.connectingContainers.del(i)
+      pager.loader.unset(item)
       pager.unregisterFd(int(item.stream.fd))
       item.stream.sclose()
   of cetMetaRefresh: