diff --git a/lib/socket.h b/lib/socket.h index 54d87384..0417a5aa 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -58,6 +58,7 @@ typedef struct birdsock { uint fast_rx; /* RX has higher priority in event loop */ uint rbsize; int (*rx_hook)(struct birdsock *, uint size); /* NULL=receiving turned off, returns 1 to clear rx buffer */ + int (*rx_paused)(struct birdsock *, uint size); /* stored rx_hook when paused */ byte *tbuf, *tpos; /* NULL=allocate automatically */ byte *ttx; /* Internal */ @@ -65,6 +66,7 @@ typedef struct birdsock { void (*tx_hook)(struct birdsock *); void (*err_hook)(struct birdsock *, int); /* errno or zero if EOF */ + void (*err_paused)(struct birdsock *, int); /* called first when paused */ /* Information about received datagrams (UDP, RAW), valid in rx_hook */ ip_addr faddr, laddr; /* src (From) and dst (Local) address of the datagram */ @@ -98,7 +100,7 @@ int sk_send(sock *, uint len); /* Send data, <0=err, >0=ok, 0=sleep */ int sk_send_to(sock *, uint len, ip_addr to, uint port); /* sk_send to given destination */ void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */ void sk_pause_rx(struct birdloop *loop, sock *s); -void sk_resume_rx(struct birdloop *loop, sock *s, int (*hook)(sock *, uint)); +void sk_resume_rx(struct birdloop *loop, sock *s); void sk_set_rbsize(sock *s, uint val); /* Resize RX buffer */ void sk_set_tbsize(sock *s, uint val); /* Resize TX buffer, keeping content */ void sk_set_tbuf(sock *s, void *tbuf); /* Switch TX buffer, NULL-> return to internal */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index c9cfbf22..1f961e6a 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -3474,7 +3474,7 @@ bgp_do_uncork(callback *cb) { struct birdsock *sk = p->conn->sk; ASSERT_DIE(sk->rpos > sk->rbuf); - sk_resume_rx(p->p.loop, sk, bgp_rx); + sk_resume_rx(p->p.loop, sk); bgp_rx(sk, sk->rpos - sk->rbuf); BGP_TRACE(D_PACKETS, "Uncorked"); } diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index bef17714..3f9c3fd9 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -460,16 +460,21 @@ void sk_pause_rx(struct birdloop *loop, sock *s) { ASSERT_DIE(birdloop_inside(loop)); + ASSERT_DIE(!s->rx_paused); + ASSERT_DIE(s->rx_hook); + s->rx_paused = s->rx_hook; s->rx_hook = NULL; socket_changed(s); } void -sk_resume_rx(struct birdloop *loop, sock *s, int (*hook)(sock *, uint)) +sk_resume_rx(struct birdloop *loop, sock *s) { ASSERT_DIE(birdloop_inside(loop)); - ASSERT_DIE(hook); - s->rx_hook = hook; + ASSERT_DIE(s->rx_paused); + ASSERT_DIE(!s->rx_hook); + s->rx_hook = s->rx_paused; + s->rx_paused = NULL; socket_changed(s); } diff --git a/sysdep/unix/socket.c b/sysdep/unix/socket.c index c50ed60b..a497e40f 100644 --- a/sysdep/unix/socket.c +++ b/sysdep/unix/socket.c @@ -895,6 +895,9 @@ sk_setup(sock *s) static void sk_err_hook(sock *s, int e) { + if (s->rx_paused) + CALL(s->err_paused, s, e); + s->err_hook(s, e); }