From 7385db38d82b26736ba56bc7aec4c79acc420824 Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Wed, 9 Mar 2011 10:10:04 +0100 Subject: Don't make UDP write event persistant. rs_packet_send() adds the event again when there's a packet to send and the write callback does the same if it doesn't drain the queue. --- lib/udp.c | 68 ++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/lib/udp.c b/lib/udp.c index 3573033..c602cbd 100644 --- a/lib/udp.c +++ b/lib/udp.c @@ -14,6 +14,44 @@ #include "compat.h" #include "udp.h" +/* Send one packet, the first in queue. */ +static void +_send (struct rs_connection *conn, int fd) +{ + ssize_t r = 0; + struct rs_packet *pkt = conn->out_queue; + + assert (pkt->rpkt); + assert (pkt->rpkt->data); + + /* Send. */ + r = compat_send (fd, pkt->rpkt->data, pkt->rpkt->data_len, 0); + if (r == -1) + { + int sockerr = evutil_socket_geterror (pkt->conn->fd); + if (sockerr != EAGAIN) + rs_err_conn_push_fl (pkt->conn, RSE_SOCKERR, __FILE__, __LINE__, + "%d: send: %d (%s)", fd, sockerr, + evutil_socket_error_to_string (sockerr)); + return; /* Don't unlink packet. */ + } + + /* Unlink the packet. */ + conn->out_queue = pkt->next; + + /* If there are more packets in queue, add the write event again. */ + if (pkt->conn->out_queue) + { + r = event_add (pkt->conn->wev, NULL); + if (r < 0) + { + rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__, + "event_add: %s", evutil_gai_strerror (r)); + return; + } + } +} + /* Callback for conn->wev and conn->rev. FIXME: Rename. */ static void _evcb (evutil_socket_t fd, short what, void *user_data) @@ -33,36 +71,22 @@ _evcb (evutil_socket_t fd, short what, void *user_data) /* read a single UDP packet and stick it in a new struct rs_packet */ + /* TODO: Verify that reception of an unsolicited response packet + results in connection being closed. */ rs_debug (("%s: UDP read NYI", __func__)); + + /* TODO: delete retransmit timer */ } else if (what & EV_WRITE) { struct rs_packet *pkt = (struct rs_packet *) user_data; assert (pkt); - /* Socket ready for writing, possibly as a result of a - successful connect. */ + if (!pkt->conn->is_connected) event_on_connect (pkt->conn, pkt); - if (pkt->conn->out_queue) - { - /* Send one packet, the first. */ - ssize_t r = 0; - struct rs_packet *p = pkt->conn->out_queue; - assert (p->rpkt); - assert (p->rpkt->data); - r = compat_send (fd, p->rpkt->data, p->rpkt->data_len, 0); - if (r == -1) - { - int sockerr = evutil_socket_geterror (p->conn->fd); - if (sockerr != EAGAIN) - rs_err_conn_push_fl (p->conn, RSE_SOCKERR, __FILE__, __LINE__, - "%d: send: %d (%s)", fd, sockerr, - evutil_socket_error_to_string (sockerr)); - return; /* Don't unlink packet. */ - } - pkt->conn->out_queue = p->next; - } + if (pkt->conn->out_queue) + _send (pkt->conn, fd); } } @@ -72,7 +96,7 @@ udp_init (struct rs_connection *conn, struct rs_packet *pkt) assert (!conn->bev); conn->rev = event_new (conn->evb, conn->fd, EV_READ|EV_PERSIST, _evcb, conn); - conn->wev = event_new (conn->evb, conn->fd, EV_WRITE|EV_PERSIST, _evcb, pkt); + conn->wev = event_new (conn->evb, conn->fd, EV_WRITE, _evcb, pkt); if (!conn->rev || !conn->wev) { if (conn->rev) -- cgit v1.1