Bug 1117984: added proxy connection state enum. r=bwc
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Wed, 20 Jan 2016 15:55:35 -0800
changeset 281441 2351ccd7fe59b5aef156ed04ed9dda370db9aa5d
parent 281440 f41f716ccf4f2f91498b0443306859d515c77d7a
child 281442 0df7afe205c5329c91ebd2f4f8d78cee58ffe139
push id70792
push userdrno@ohlmeier.org
push dateMon, 25 Jan 2016 00:44:11 +0000
treeherdermozilla-inbound@2351ccd7fe59 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbwc
bugs1117984
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1117984: added proxy connection state enum. r=bwc
media/mtransport/third_party/nICEr/src/ice/ice_socket.c
media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
media/mtransport/third_party/nICEr/src/stun/nr_socket_buffered_stun.c
--- a/media/mtransport/third_party/nICEr/src/ice/ice_socket.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_socket.c
@@ -60,17 +60,17 @@ static void nr_ice_socket_readable_cb(NR
 
     r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Socket ready to read",sock->ctx->label);
 
     /* Re-arm first! */
     if (sock->type != NR_ICE_SOCKET_TYPE_STREAM_TCP)
       NR_ASYNC_WAIT(s,how,nr_ice_socket_readable_cb,cb_arg);
 
     if(r=nr_socket_recvfrom(sock->sock,buf,sizeof(buf),&len_s,0,&addr)){
-      if (r != R_WOULDBLOCK && (sock->type == NR_ICE_SOCKET_TYPE_STREAM_TURN)) {
+      if (r != R_WOULDBLOCK && (sock->type != NR_ICE_SOCKET_TYPE_DGRAM)) {
         /* Report this error upward. Bug 946423 */
         r_log(LOG_ICE,LOG_ERR,"ICE(%s): Error %d on reliable socket. Abandoning.",sock->ctx->label, r);
         NR_ASYNC_CANCEL(s, NR_ASYNC_WAIT_READ);
       }
       return;
     }
 
     /* Deal with the fact that sizeof(int) and sizeof(size_t) may not
--- a/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
+++ b/media/mtransport/third_party/nICEr/src/net/nr_proxy_tunnel.c
@@ -42,23 +42,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #define MAX_HTTP_CONNECT_ADDR_SIZE 256
 #define MAX_HTTP_CONNECT_BUFFER_SIZE 1024
 #define MAX_ALPN_LENGTH 64
 #ifndef CRLF
 #define CRLF "\r\n"
 #endif
 #define END_HEADERS CRLF CRLF
 
+typedef enum {
+  PROXY_TUNNEL_NONE=0,
+  PROXY_TUNNEL_REQUESTED,
+  PROXY_TUNNEL_CONNECTED,
+  PROXY_TUNNEL_CLOSED,
+  PROXY_TUNNEL_FAILED
+} nr_socket_proxy_tunnel_state;
+
 typedef struct nr_socket_proxy_tunnel_ {
   nr_proxy_tunnel_config *config;
   nr_socket *inner;
   nr_transport_addr remote_addr;
-  int connect_requested;
-  int connect_answered;
-  int connect_failed;
+  nr_socket_proxy_tunnel_state state;
   char buffer[MAX_HTTP_CONNECT_BUFFER_SIZE];
   size_t buffered_bytes;
   void *resolver_handle;
 } nr_socket_proxy_tunnel;
 
 typedef struct nr_socket_wrapper_factory_proxy_tunnel_ {
   nr_proxy_tunnel_config *config;
 } nr_socket_wrapper_factory_proxy_tunnel;
@@ -138,17 +144,17 @@ static int send_http_connect(nr_socket_p
   }
 
   if (bytes_sent < offset) {
     /* TODO(bug 1116583): buffering and wait for */
     r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect should be buffering %lu", (unsigned long)bytes_sent);
     ABORT(R_IO_ERROR);
   }
 
-  sock->connect_requested = 1;
+  sock->state = PROXY_TUNNEL_REQUESTED;
 
   _status = 0;
 abort:
   return(_status);
 }
 
 static char *find_http_terminator(char *response, size_t len)
 {
@@ -168,16 +174,19 @@ static char *find_http_terminator(char *
 static int parse_http_response(char *begin, char *end, unsigned int *status)
 {
   size_t len = end - begin;
   char response[MAX_HTTP_CONNECT_BUFFER_SIZE + 1];
 
   // len should *never* be greater than nr_socket_proxy_tunnel::buffered_bytes.
   // Which in turn should never be greater nr_socket_proxy_tunnel::buffer size.
   assert(len <= MAX_HTTP_CONNECT_BUFFER_SIZE);
+  if (len > MAX_HTTP_CONNECT_BUFFER_SIZE) {
+    return R_BAD_DATA;
+  }
 
   memcpy(response, begin, len);
   response[len] = '\0';
 
   // http://www.rfc-editor.org/rfc/rfc7230.txt
   // status-line    = HTTP-version SP status-code SP reason-phrase CRLF
   // HTTP-version   = HTTP-name "/" DIGIT "." DIGIT
   // HTTP-name      = "HTTP" ; "HTTP", case-sensitive
@@ -244,16 +253,20 @@ static int nr_socket_proxy_tunnel_resolv
 
   if (proxy_addr) {
     r_log(LOG_GENERIC,LOG_DEBUG,"Resolved proxy address %s -> %s",
         sock->config->proxy_host, proxy_addr->as_string);
   }
   else {
     r_log(LOG_GENERIC,LOG_WARNING,"Failed to resolve proxy %s",
         sock->config->proxy_host);
+    /* TODO: Mozilla bug 1241758: because of the callback the return value goes
+     * nowhere, so we can't mark the candidate as failed, so everything depends
+     * on the overall timeouts in this case. */
+    sock->state = PROXY_TUNNEL_FAILED;
     ABORT(R_NOT_FOUND);
   }
 
   if ((r=nr_socket_connect(sock->inner, proxy_addr))) {
     ABORT(r);
   }
 
   _status = 0;
@@ -331,23 +344,30 @@ abort:
 int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len,
                                  size_t *written)
 {
   int r, _status;
   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
 
   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_write");
 
-  if (!sock->connect_requested) {
+  if (sock->state >= PROXY_TUNNEL_CLOSED) {
+    return R_FAILED;
+  }
+
+  if (sock->state == PROXY_TUNNEL_NONE) {
     if ((r=send_http_connect(sock))) {
       ABORT(r);
     }
   }
 
-  /* TODO (bug 1117984): we cannot assume it's safe to write until we receive a response. */
+  if (sock->state != PROXY_TUNNEL_CONNECTED) {
+    return R_WOULDBLOCK;
+  }
+
   if ((r=nr_socket_write(sock->inner, msg, len, written, 0))) {
     ABORT(r);
   }
 
   _status=0;
 abort:
   return(_status);
 }
@@ -361,21 +381,21 @@ int nr_socket_proxy_tunnel_read(void *ob
   size_t pending;
   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
   unsigned int http_status;
 
   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_read");
 
   *len = 0;
 
-  if (sock->connect_failed) {
+  if (sock->state >= PROXY_TUNNEL_CLOSED) {
     return R_FAILED;
   }
 
-  if (sock->connect_answered) {
+  if (sock->state == PROXY_TUNNEL_CONNECTED) {
     return nr_socket_read(sock->inner, buf, maxlen, len, 0);
   }
 
   if (sock->buffered_bytes >= sizeof(sock->buffer)) {
     r_log(LOG_GENERIC,LOG_ERR,"buffer filled waiting for CONNECT response");
     assert(sock->buffered_bytes == sizeof(sock->buffer));
     ABORT(R_INTERNAL);
   }
@@ -386,61 +406,63 @@ int nr_socket_proxy_tunnel_read(void *ob
   if ((r=nr_socket_read(sock->inner, sock->buffer + sock->buffered_bytes,
           maxlen_int, &bytes_read, 0))) {
     ABORT(r);
   }
 
   sock->buffered_bytes += bytes_read;
 
   if (http_term = find_http_terminator(sock->buffer, sock->buffered_bytes)) {
-    sock->connect_answered = 1;
-
     if ((r = parse_http_response(sock->buffer, http_term, &http_status))) {
       ABORT(r);
     }
 
     /* TODO (bug 1115934): Handle authentication challenges. */
     if (http_status < 200 || http_status >= 300) {
       r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_read unable to connect %u",
             http_status);
       ABORT(R_FAILED);
     }
 
+    sock->state = PROXY_TUNNEL_CONNECTED;
+
     ptr = http_term + strlen(END_HEADERS);
     pending = sock->buffered_bytes - (ptr - sock->buffer);
 
     if (pending == 0) {
       ABORT(R_WOULDBLOCK);
     }
 
     assert(pending <= maxlen);
     *len = pending;
 
     memcpy(buf, ptr, *len);
   }
 
   _status=0;
 abort:
   if (_status && _status != R_WOULDBLOCK) {
-      sock->connect_failed = 1;
+      sock->state = PROXY_TUNNEL_FAILED;
   }
   return(_status);
 }
 
 int nr_socket_proxy_tunnel_close(void *obj)
 {
   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
 
   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_close");
 
   if (sock->resolver_handle) {
     nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
     sock->resolver_handle = 0;
   }
 
+  sock->state = PROXY_TUNNEL_CLOSED;
+
   return nr_socket_close(sock->inner);
 }
 
 int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **configpp)
 {
   int _status;
   nr_proxy_tunnel_config *configp=0;
 
--- 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
@@ -519,16 +519,20 @@ 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) {
+    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,
                            n1->length - n1->r_offset,
                            &written, 0))) {