Bug 1117984: added proxy connection state enum. r=bwc
--- 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))) {