Don't make UDP write event persistant.
authorLinus Nordberg <linus@nordu.net>
Wed, 9 Mar 2011 09:10:04 +0000 (10:10 +0100)
committerLinus Nordberg <linus@nordu.net>
Wed, 9 Mar 2011 09:10:04 +0000 (10:10 +0100)
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

index 3573033..c602cbd 100644 (file)
--- a/lib/udp.c
+++ b/lib/udp.c
 #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)