diff --git a/lib/coroutine.h b/lib/coroutine.h index f64a9540..93a41233 100644 --- a/lib/coroutine.h +++ b/lib/coroutine.h @@ -18,5 +18,6 @@ void coro_resume(coroutine *c); struct birdsock; int coro_sk_read(struct birdsock *s); +void coro_sk_write(struct birdsock *s, unsigned len); #endif diff --git a/lib/socket.h b/lib/socket.h index 00e4a29c..d961841e 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -83,6 +83,7 @@ typedef struct birdsock { struct ssh_sock *ssh; /* Used in SK_SSH */ struct coroutine *rx_coroutine; + struct coroutine *tx_coroutine; } sock; sock *sock_new(pool *); /* Allocate new socket */ diff --git a/nest/cli.c b/nest/cli.c index 986b2880..f4b7628c 100644 --- a/nest/cli.c +++ b/nest/cli.c @@ -245,8 +245,7 @@ cli_write(cli *c) s->tbuf = o->outpos; o->outpos = o->wpos; - if (sk_send(s, len) <= 0) - return; + coro_sk_write(s, len); c->tx_pos = o->next; } @@ -264,12 +263,6 @@ cli_write_trigger(cli *c) cli_write(c); } -static void -cli_tx_hook(sock *s) -{ - cli_write(s->data); -} - static void cli_err_hook(sock *s, int err) { @@ -540,7 +533,6 @@ cli_new(sock *s) s->pool = c->pool; /* We need to have all the socket buffers allocated in the cli pool */ rmove(s, c->pool); - s->tx_hook = cli_tx_hook; s->err_hook = cli_err_hook; s->data = c; diff --git a/sysdep/unix/coroutine.c b/sysdep/unix/coroutine.c index c5a2ba73..fc650a57 100644 --- a/sysdep/unix/coroutine.c +++ b/sysdep/unix/coroutine.c @@ -146,6 +146,7 @@ static void coro_free(resource *r) { coroutine *c = (coroutine *) r; + ASSERT(coro_current != c); pthread_cancel(c->thread); pthread_join(c->thread, NULL); } @@ -246,6 +247,14 @@ coro_sk_rx_hook(sock *sk, uint size UNUSED) return 0; } +static void +coro_sk_tx_hook(sock *sk) +{ + ASSERT(sk->tx_coroutine); + ASSERT(!coro_current); + coro_resume(sk->tx_coroutine); +} + int coro_sk_read(sock *s) { @@ -256,3 +265,15 @@ coro_sk_read(sock *s) s->rx_hook = NULL; return s->rpos - s->rbuf; } + +void +coro_sk_write(sock *s, unsigned len) +{ + ASSERT(coro_current); + s->tx_coroutine = coro_current; + s->tx_hook = coro_sk_tx_hook; + s->ttx = s->tbuf; + s->tpos = s->tbuf + len; + coro_suspend(); + s->tx_hook = NULL; +}