commit 4adcdc5d20042ac1cd1afa491db8ae82a919ea1e
parent b553458289d3ba0983b1bba51f07c588100ad8e6
Author: erai <erai@omiltem.net>
Date: Wed, 5 Jun 2024 00:06:07 -0400
sshd event loop
Diffstat:
M | sshd.c | | | 140 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
M | syscall.c | | | 8 | ++++++-- |
2 files changed, 122 insertions(+), 26 deletions(-)
diff --git a/sshd.c b/sshd.c
@@ -1540,36 +1540,124 @@ struct pfd4 {
p3: int;
}
-reset_pfd(pfd: *int, ctx: *sshd_ctx) {
- pfd[0] = ctx.fd | (POLLIN << 32);
- pfd[1] = ctx.child_stdin | (POLLOUT << 32);
- pfd[2] = ctx.child_stdout | (POLLIN << 32);
- pfd[3] = ctx.child_stderr | (POLLIN << 32);
+reset_pfd(pfd: *int, ctx: *sshd_ctx): int {
+ var n: int;
+
+ n = 0;
+
+ pfd[n] = ctx.fd | (POLLIN << 32);
+ n = n + 1;
+
+ if ctx.child_stdin >= 0 {
+ pfd[n] = ctx.child_stdin | (POLLOUT << 32);
+ n = n + 1;
+ }
+
+ if ctx.child_stdout >= 0 {
+ pfd[n] = ctx.child_stdout | (POLLIN << 32);
+ n = n + 1;
+ }
+
+ if ctx.child_stderr >= 0 {
+ pfd[n] = ctx.child_stderr | (POLLIN << 32);
+ n = n + 1;
+ }
+
+ return n;
}
-client_loop(ctx: *sshd_ctx) {
+poll_client(revents: int, ctx: *sshd_ctx) {
var tag: int;
+ read_frame(ctx);
+
+ tag = ctx.frame[0]:int;
+ if tag == SSH_MSG_DISCONNECT {
+ dodisconnect(ctx);
+ } else if tag == SSH_MSG_KEXINIT {
+ dokex(ctx);
+ } else if tag == SSH_MSG_CHANNEL_WINDOW_ADJUST {
+ dowindow(ctx);
+ } else if tag == SSH_MSG_CHANNEL_DATA {
+ dodata(ctx);
+ } else if tag == SSH_MSG_CHANNEL_EOF {
+ doeof(ctx);
+ } else if tag == SSH_MSG_CHANNEL_CLOSE {
+ doclose(ctx);
+ } else if tag == SSH_MSG_CHANNEL_REQUEST {
+ dorequest(ctx);
+ } else {
+ die("invalid packet");
+ }
+}
+
+poll_stdin(ctx: *sshd_ctx) {
+ if revents & POLLERR {
+ close(ctx.child_stdin);
+ ctx.child_stdin = -1;
+ }
+}
+
+poll_stdout(ctx: *sshd_ctx) {
+ var a: byte;
+ if read(ctx.child_stdout, &a, 1) == 0 {
+ close(ctx.child_stdout);
+ ctx.child_stdout = -1;
+ }
+}
+
+poll_stderr(ctx: *sshd_ctx) {
+ if read(ctx.child_stderr, &a, 1) == 0 {
+ close(ctx.child_stderr);
+ ctx.child_stderr = -1;
+ }
+}
+
+client_loop(ctx: *sshd_ctx) {
+ var _p: pfd4;
+ var p: *int;
+ var n: int;
+ var i: int;
+ var fd: int;
+ var revents: int;
+
+ p = &_p.p0;
+
loop {
- read_frame(ctx);
+ n = reset_pfd(p, ctx);
+ if poll(p, n, -1) == -EINTR {
+ continue;
+ }
- tag = ctx.frame[0]:int;
- if tag == SSH_MSG_DISCONNECT {
- dodisconnect(ctx);
- } else if tag == SSH_MSG_KEXINIT {
- dokex(ctx);
- } else if tag == SSH_MSG_CHANNEL_WINDOW_ADJUST {
- dowindow(ctx);
- } else if tag == SSH_MSG_CHANNEL_DATA {
- dodata(ctx);
- } else if tag == SSH_MSG_CHANNEL_EOF {
- doeof(ctx);
- } else if tag == SSH_MSG_CHANNEL_CLOSE {
- doclose(ctx);
- } else if tag == SSH_MSG_CHANNEL_REQUEST {
- dorequest(ctx);
- } else {
- die("invalid packet");
+ i = 0;
+ loop {
+ if i == n {
+ break;
+ }
+
+ fd = p[i] & (-1 >> 32);
+ revents = p[i] >> 48;
+ i = i + 1;
+
+ if !revents {
+ continue;
+ }
+
+ if fd == ctx.fd {
+ poll_client(revents, ctx);
+ }
+
+ if fd == ctx.child_stdin {
+ poll_stdin(revents, ctx);
+ }
+
+ if fd == ctx.child_stdout {
+ poll_stdout(revents, ctx);
+ }
+
+ if fd == ctx.child_stderr {
+ poll_stderr(revents, ctx);
+ }
}
}
}
@@ -1691,6 +1779,10 @@ main(argc: int, argv: **byte, envp: **byte) {
ed25519_pub((&ctx.pub):*byte, (&ctx.priv):*byte);
+ ctx.child_stdin = -1;
+ ctx.child_stdout = -1;
+ ctx.child_stderr = -1;
+
ctx.a = &a;
ctx.bufsz = 64 * 1024;
ctx.buf = alloc(ctx.a, ctx.bufsz);
diff --git a/syscall.c b/syscall.c
@@ -12,8 +12,12 @@ enum {
AF_INET = 2,
SOCK_STREAM = 1,
- POLLIN = 1,
- POLLOUT = 4,
+ POLLIN = 0x01,
+ POLLPRI = 0x02,
+ POLLOUT = 0x04,
+ POLLERR = 0x08,
+ POLLHUP = 0x10,
+ POLLNVAL = 0x20,
WNOHANG = 1,