os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit 4adcdc5d20042ac1cd1afa491db8ae82a919ea1e
parent b553458289d3ba0983b1bba51f07c588100ad8e6
Author: erai <erai@omiltem.net>
Date:   Wed,  5 Jun 2024 00:06:07 -0400

sshd event loop

Diffstat:
Msshd.c | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msyscall.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,