--- 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,