diff options
author | bptato <nincsnevem662@gmail.com> | 2023-09-14 00:58:33 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-09-14 00:58:33 +0200 |
commit | c2004e4aba182473e79100759a2d58e1bd7d184c (patch) | |
tree | 1c3ebe2ee06471053656e7ee7da1fb27a576c691 | |
parent | f4a169ebca315246dd547efce181668d83c73d0b (diff) | |
download | chawan-c2004e4aba182473e79100759a2d58e1bd7d184c.tar.gz |
Switch buffer -> client connection to client -> buffer
We now connect to buffers from the client, instead of connecting buffers to the client. This has the following advantages: * Simplifies the client event loop. * Makes the client a real client (no more serversocket dependency). * Slightly more secure, as we no longer have to trust buffers not lying about their process ids. * Facilitates the potential future addition of connections from several clients to a single buffer.
-rw-r--r-- | src/buffer/buffer.nim | 11 | ||||
-rw-r--r-- | src/display/client.nim | 41 | ||||
-rw-r--r-- | src/ips/forkserver.nim | 14 |
3 files changed, 29 insertions, 37 deletions
diff --git a/src/buffer/buffer.nim b/src/buffer/buffer.nim index 4b37a604..4616704e 100644 --- a/src/buffer/buffer.nim +++ b/src/buffer/buffer.nim @@ -1447,12 +1447,9 @@ proc runBuffer(buffer: Buffer, rfd: int) = assert buffer.window.timeouts.runTimeoutFd(event.fd) buffer.window.runJSJobs() buffer.loader.unregistered.setLen(0) - buffer.pstream.close() - buffer.loader.quit() - quit(0) proc launchBuffer*(config: BufferConfig, source: BufferSource, - attrs: WindowAttributes, loader: FileLoader, mainproc: Pid) = + attrs: WindowAttributes, loader: FileLoader, ssock: ServerSocket) = let buffer = Buffer( alive: true, userstyle: parseStylesheet(config.userstyle), @@ -1473,10 +1470,12 @@ proc launchBuffer*(config: BufferConfig, source: BufferSource, if buffer.config.scripting: buffer.window = newWindow(buffer.config.scripting, buffer.selector, buffer.attrs, proc(url: URL) = buffer.navigate(url), some(buffer.loader)) - let socks = connectSocketStream(mainproc, false) + let socks = ssock.acceptSocketStream() buffer.estream = newFileStream(stderr) - socks.swrite(getpid()) buffer.pstream = socks let rfd = int(socks.source.getFd()) buffer.selector.registerHandle(rfd, {Read}, 0) buffer.runBuffer(rfd) + buffer.pstream.close() + buffer.loader.quit() + quit(0) diff --git a/src/display/client.nim b/src/display/client.nim index 302cdd4a..3236732d 100644 --- a/src/display/client.nim +++ b/src/display/client.nim @@ -31,8 +31,6 @@ import io/promise import io/request import io/window import ips/forkserver -import ips/serialize -import ips/serversocket import ips/socketstream import js/base64 import js/domexception @@ -54,8 +52,7 @@ import xhr/xmlhttprequest import chakasu/charset type - Client* = ref ClientObj - ClientObj* = object + Client* = ref object alive: bool attrs: WindowAttributes config {.jsget.}: Config @@ -75,7 +72,6 @@ type precnum: int32 # current number prefix (when vi-numeric-prefix is true) s: string # current input buffer selector: Selector[Container] - ssock: ServerSocket store {.jsget, jsset.}: Document timeouts: TimeoutState[Container] userstyle: CSSStylesheet @@ -316,26 +312,14 @@ proc acceptBuffers(client: Client) = else: client.pager.procmap.del(pid) stream.close() - while client.pager.procmap.len > 0: - try: - let stream = client.ssock.acceptSocketStream() - var pid: Pid - #TODO if this returns EAGAIN then we're stuck - stream.sread(pid) - if pid in client.pager.procmap: - let container = client.pager.procmap[pid] - client.pager.procmap.del(pid) - container.setStream(stream) - let fd = stream.source.getFd() - client.fdmap[int(fd)] = container - client.selector.registerHandle(fd, {Read}, nil) - client.pager.handleEvents(container) - else: - #TODO uh what? - client.console.log("???") - stream.close() - except OSError: # EAGAIN, probably. TODO - break + for pid, container in client.pager.procmap: + let stream = connectSocketStream(pid, buffered = false, blocking = true) + container.setStream(stream) + let fd = stream.source.getFd() + client.fdmap[int(fd)] = container + client.selector.registerHandle(fd, {Read}, nil) + client.pager.handleEvents(container) + client.pager.procmap.clear() proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize_t): cint {. importc: "setvbuf", header: "<stdio.h>", tags: [].} @@ -369,8 +353,6 @@ proc handleRead(client: Client, fd: int) = client.loader.onRead(fd) elif fd in client.loader.unregistered: discard # ignore - elif fd == client.fd: - client.acceptBuffers() else: let container = client.fdmap[fd] client.pager.handleEvent(container) @@ -430,6 +412,7 @@ proc inputLoop(client: Client) = client.console.container.requestLines().then(proc() = client.console.container.cursorLastLine()) client.loader.unregistered.setLen(0) + client.acceptBuffers() if client.pager.scommand != "": client.command(client.pager.scommand) client.pager.scommand = "" @@ -546,10 +529,7 @@ proc launchClient*(client: Client, pages: seq[string], dump = not open(tty, "/dev/tty", fmRead) else: dump = true - client.ssock = initServerSocket(false, false) - client.fd = int(client.ssock.sock.getFd()) let selector = newSelector[Container]() - selector.registerHandle(client.fd, {Read}, nil) let efd = int(client.forkserver.estream.fd) selector.registerHandle(efd, {Read}, nil) client.loader.registerFun = proc(fd: int) = @@ -581,6 +561,7 @@ proc launchClient*(client: Client, pages: seq[string], for page in pages: client.pager.loadURL(page, ctype = contentType, cs = cs) client.pager.showAlerts() + client.acceptBuffers() if not dump: client.inputLoop() else: diff --git a/src/ips/forkserver.nim b/src/ips/forkserver.nim index 681b3aa5..cc2d91e0 100644 --- a/src/ips/forkserver.nim +++ b/src/ips/forkserver.nim @@ -120,6 +120,9 @@ proc forkBuffer(ctx: var ForkServerContext): Pid = proxy: config.proxy, ) ) + var pipefd: array[2, cint] + if pipe(pipefd) == -1: + raise newException(Defect, "Failed to open pipe.") let pid = fork() if pid == -1: raise newException(Defect, "Failed to fork process.") @@ -129,11 +132,16 @@ proc forkBuffer(ctx: var ForkServerContext): Pid = for i in 0 ..< ctx.children.len: ctx.children[i] = (Pid(0), Pid(0)) ctx.children.setLen(0) zeroMem(addr ctx, sizeof(ctx)) + discard close(pipefd[0]) # close read + let ssock = initServerSocket(buffered = false) + let ps = newPosixStream(pipefd[1]) + ps.write(char(0)) + ps.close() discard close(stdin.getFileHandle()) discard close(stdout.getFileHandle()) let loader = FileLoader(process: loaderPid) try: - launchBuffer(config, source, attrs, loader, mainproc) + launchBuffer(config, source, attrs, loader, ssock) except CatchableError: let e = getCurrentException() # taken from system/excpt.nim @@ -142,6 +150,10 @@ proc forkBuffer(ctx: var ForkServerContext): Pid = stderr.write(msg) quit(1) doAssert false + discard close(pipefd[1]) # close write + let ps = newPosixStream(pipefd[0]) + assert ps.readChar() == char(0) + ps.close() ctx.children.add((pid, loaderPid)) return pid |