Bug 1297158: added a timeout for TCP connection to speed up gathering draft
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Mon, 22 Aug 2016 15:29:21 -0700
changeset 404096 4dcb95d09efee77e08103188c443532c53a8d013
parent 404063 3345f0e8ed3bd33d8af6e2b9bf1fd8bf397a45bc
child 529097 3f007ad76fb905dbe3d463fae227386d2f62225b
push id27114
push userdrno@ohlmeier.org
push dateMon, 22 Aug 2016 22:29:40 +0000
bugs1297158
milestone51.0a1
Bug 1297158: added a timeout for TCP connection to speed up gathering MozReview-Commit-ID: IHf5j1GYSDQ
media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c
--- a/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c
+++ b/media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c
@@ -42,31 +42,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
 #include "p_buf.h"
 #include "nr_socket.h"
 #include "stun.h"
 #include "nr_socket_buffered_stun.h"
 
 #define NR_MAX_FRAME_SIZE 0xFFFF
 
+#define NR_SOCKET_CONNECT_TIMEOUT 50000
+
 typedef struct nr_frame_header_ {
   UINT2 frame_length;
   char  data[0];
 } nr_frame_header;
 
 typedef struct nr_socket_buffered_stun_ {
   nr_socket *inner;
   nr_transport_addr remote_addr;
+  void *connect_timeout;
   int connected;
 
   /* Read state */
   int read_state;
 #define NR_ICE_SOCKET_READ_NONE   0
 #define NR_ICE_SOCKET_READ_HDR    1
-#define NR_ICE_SOCKET_READ_FAILED 2
+#define NR_ICE_SOCKET_FAILED      2
   UCHAR *buffer;
   size_t buffer_size;
   size_t bytes_needed;
   size_t bytes_read;
   NR_async_cb readable_cb;
   void *readable_cb_arg;
 
   /* Write state */
@@ -194,22 +197,28 @@ int nr_socket_buffered_stun_destroy(void
   NR_SOCKET fd;
 
   if (!objp || !*objp)
     return 0;
 
   sock = (nr_socket_buffered_stun *)*objp;
   *objp = 0;
 
+  if (sock->connect_timeout) {
+    NR_async_timer_cancel(sock->connect_timeout);
+    sock->connect_timeout = 0;
+  }
+
   /* Free the buffer if needed */
   RFREE(sock->buffer);
 
   /* Cancel waiting on the socket */
   if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
     NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
+    NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
   }
 
   nr_p_buf_free_chain(sock->p_bufs, &sock->pending_writes);
   nr_p_buf_ctx_destroy(&sock->p_bufs);
   nr_socket_destroy(&sock->inner);
   RFREE(sock);
 
   return 0;
@@ -258,17 +267,22 @@ abort:
   RFREE(frame);
   return _status;
 }
 
 static void nr_socket_buffered_stun_failed(nr_socket_buffered_stun *sock)
   {
     NR_SOCKET fd;
 
-    sock->read_state = NR_ICE_SOCKET_READ_FAILED;
+    sock->read_state = NR_ICE_SOCKET_FAILED;
+
+    if (sock->connect_timeout) {
+      NR_async_timer_cancel(sock->connect_timeout);
+      sock->connect_timeout = 0;
+    }
 
     /* Cancel waiting on the socket */
     if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
       NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
       NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
     }
   }
 
@@ -276,17 +290,17 @@ static int nr_socket_buffered_stun_recvf
   size_t maxlen, size_t *len, int flags, nr_transport_addr *from)
 {
   int r, _status;
   size_t bytes_read;
   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
   nr_frame_header *frame = (nr_frame_header *)sock->buffer;
   size_t skip_hdr_size = (sock->framing_type == ICE_TCP_FRAMING) ? sizeof(nr_frame_header) : 0;
 
-  if (sock->read_state == NR_ICE_SOCKET_READ_FAILED) {
+  if (sock->read_state == NR_ICE_SOCKET_FAILED) {
     ABORT(R_FAILED);
   }
 
 reread:
   /* Read all the expected bytes */
   assert(sock->bytes_needed <= sock->buffer_size - sock->bytes_read);
 
   if(r=nr_socket_read(sock->inner,
@@ -379,16 +393,17 @@ static int nr_socket_buffered_stun_getad
 static int nr_socket_buffered_stun_close(void *obj)
 {
   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
   NR_SOCKET fd;
 
   /* Cancel waiting on the socket */
   if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
     NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
+    NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
   }
 
   return nr_socket_close(sock->inner);
 }
 
 static int nr_socket_buffered_stun_listen(void *obj, int backlog)
 {
   int r, _status;
@@ -418,36 +433,55 @@ static void nr_socket_buffered_stun_conn
   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)arg;
   int r, _status;
   NR_SOCKET fd;
 
   assert(!sock->connected);
 
   sock->connected = 1;
 
-  if ((r=nr_socket_getfd(sock->inner, &fd)))
+  if (sock->connect_timeout) {
+    NR_async_timer_cancel(sock->connect_timeout);
+    sock->connect_timeout = 0;
+  }
+
+  if ((r=nr_socket_getfd(sock->inner, &fd))) {
     ABORT(r);
+  }
   NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
 
   // once connected arm for read
   if (sock->readable_cb) {
     NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, sock->readable_cb, sock->readable_cb_arg);
   }
 
   if (sock->pending) {
     r_log(LOG_GENERIC, LOG_INFO, "Invoking writable_cb on connected (%u)", (uint32_t) sock->pending);
     nr_socket_buffered_stun_writable_cb(s, how, arg);
   }
 
   _status=0;
 abort:
   if (_status) {
     r_log(LOG_GENERIC, LOG_ERR, "Failure in nr_socket_buffered_stun_connected_cb: %d", _status);
+    nr_socket_buffered_stun_failed(sock);
+  }
+}
 
-  }
+static void nr_socket_buffered_stun_connect_timeout_cb(NR_SOCKET s, int how,
+                                                       void *arg)
+{
+  nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)arg;
+
+  assert(!sock->connected);
+
+  if (sock->connected)
+    return;
+
+  nr_socket_buffered_stun_failed(sock);
 }
 
 static int nr_socket_buffered_stun_connect(void *obj, nr_transport_addr *addr)
 {
   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
   int r, _status;
 
   if ((r=nr_transport_addr_copy(&sock->remote_addr, addr)))
@@ -455,17 +489,21 @@ static int nr_socket_buffered_stun_conne
 
   if ((r=nr_socket_connect(sock->inner, addr))) {
     if (r == R_WOULDBLOCK) {
       NR_SOCKET fd;
 
       if ((r=nr_socket_getfd(sock->inner, &fd)))
         ABORT(r);
 
-      NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_WRITE, nr_socket_buffered_stun_connected_cb, sock);
+      NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_WRITE,
+                    nr_socket_buffered_stun_connected_cb, sock);
+      NR_ASYNC_TIMER_SET(NR_SOCKET_CONNECT_TIMEOUT,
+                         nr_socket_buffered_stun_connect_timeout_cb, sock,
+                         &sock->connect_timeout);
       ABORT(R_WOULDBLOCK);
     }
     ABORT(r);
   } else {
     r_log(LOG_GENERIC, LOG_INFO, "Connected without blocking");
     sock->connected = 1;
   }
 
@@ -558,17 +596,17 @@ abort:
 }
 
 static void nr_socket_buffered_stun_writable_cb(NR_SOCKET s, int how, void *arg)
 {
   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)arg;
   int r,_status;
   nr_p_buf *n1, *n2;
 
-  if (sock->read_state == NR_ICE_SOCKET_READ_FAILED) {
+  if (sock->read_state == NR_ICE_SOCKET_FAILED) {
     ABORT(R_FAILED);
   }
 
   /* Try to flush */
   STAILQ_FOREACH_SAFE(n1, &sock->pending_writes, entry, n2) {
     size_t written = 0;
 
     if ((r=nr_socket_write(sock->inner, n1->data + n1->r_offset,