diff options
author | bptato <nincsnevem662@gmail.com> | 2024-09-23 18:07:23 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-09-23 18:08:14 +0200 |
commit | 8e8c7f0911f4a20446a83090d722fecaf203f6f3 (patch) | |
tree | 334a897643051bc6e16d564591ddecba22af565d /src/local/client.nim | |
parent | 3b3d517130bb42ec69e6f684510e3b3a3668947c (diff) | |
download | chawan-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/client.nim')
-rw-r--r-- | src/local/client.nim | 125 |
1 files changed, 66 insertions, 59 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 |