LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nICEr/src/stun - nr_socket_buffered_stun.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 266 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : Copyright (c) 2007, Adobe Systems, Incorporated
       3             : Copyright (c) 2013, Mozilla
       4             : All rights reserved.
       5             : 
       6             : Redistribution and use in source and binary forms, with or without
       7             : modification, are permitted provided that the following conditions are
       8             : met:
       9             : 
      10             : * Redistributions of source code must retain the above copyright
      11             :   notice, this list of conditions and the following disclaimer.
      12             : 
      13             : * Redistributions in binary form must reproduce the above copyright
      14             :   notice, this list of conditions and the following disclaimer in the
      15             :   documentation and/or other materials provided with the distribution.
      16             : 
      17             : * Neither the name of Adobe Systems, Network Resonance nor the names of its
      18             :   contributors may be used to endorse or promote products derived from
      19             :   this software without specific prior written permission.
      20             : 
      21             : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      22             : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      23             : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      24             : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      25             : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      26             : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      27             : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      28             : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      29             : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      30             : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      31             : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      32             : */
      33             : 
      34             : #include <nr_api.h>
      35             : 
      36             : #include <stdio.h>
      37             : #include <string.h>
      38             : #include <sys/types.h>
      39             : #include <sys/queue.h>
      40             : #include <assert.h>
      41             : #include <inttypes.h>
      42             : 
      43             : #include "p_buf.h"
      44             : #include "nr_socket.h"
      45             : #include "stun.h"
      46             : #include "nr_socket_buffered_stun.h"
      47             : 
      48             : #define NR_MAX_FRAME_SIZE 0xFFFF
      49             : 
      50             : typedef struct nr_frame_header_ {
      51             :   UINT2 frame_length;
      52             :   char  data[0];
      53             : } nr_frame_header;
      54             : 
      55             : typedef struct nr_socket_buffered_stun_ {
      56             :   nr_socket *inner;
      57             :   nr_transport_addr remote_addr;
      58             :   int connected;
      59             : 
      60             :   /* Read state */
      61             :   int read_state;
      62             : #define NR_ICE_SOCKET_READ_NONE   0
      63             : #define NR_ICE_SOCKET_READ_HDR    1
      64             : #define NR_ICE_SOCKET_READ_FAILED 2
      65             :   UCHAR *buffer;
      66             :   size_t buffer_size;
      67             :   size_t bytes_needed;
      68             :   size_t bytes_read;
      69             :   NR_async_cb readable_cb;
      70             :   void *readable_cb_arg;
      71             : 
      72             :   /* Write state */
      73             :   nr_p_buf_ctx *p_bufs;
      74             :   nr_p_buf_head pending_writes;
      75             :   size_t pending;
      76             :   size_t max_pending;
      77             :   nr_framing_type framing_type;
      78             : } nr_socket_buffered_stun;
      79             : 
      80             : static int nr_socket_buffered_stun_destroy(void **objp);
      81             : static int nr_socket_buffered_stun_sendto(void *obj,const void *msg, size_t len,
      82             :   int flags, nr_transport_addr *to);
      83             : static int nr_socket_buffered_stun_recvfrom(void *obj,void * restrict buf,
      84             :   size_t maxlen, size_t *len, int flags, nr_transport_addr *from);
      85             : static int nr_socket_buffered_stun_getfd(void *obj, NR_SOCKET *fd);
      86             : static int nr_socket_buffered_stun_getaddr(void *obj, nr_transport_addr *addrp);
      87             : static int nr_socket_buffered_stun_close(void *obj);
      88             : static int nr_socket_buffered_stun_connect(void *sock, nr_transport_addr *addr);
      89             : static int nr_socket_buffered_stun_write(void *obj,const void *msg, size_t len, size_t *written);
      90             : static void nr_socket_buffered_stun_writable_cb(NR_SOCKET s, int how, void *arg);
      91             : static int nr_socket_buffered_stun_listen(void *obj, int backlog);
      92             : static int nr_socket_buffered_stun_accept(void *obj, nr_transport_addr *addrp, nr_socket **sockp);
      93             : 
      94             : static nr_socket_vtbl nr_socket_buffered_stun_vtbl={
      95             :   2,
      96             :   nr_socket_buffered_stun_destroy,
      97             :   nr_socket_buffered_stun_sendto,
      98             :   nr_socket_buffered_stun_recvfrom,
      99             :   nr_socket_buffered_stun_getfd,
     100             :   nr_socket_buffered_stun_getaddr,
     101             :   nr_socket_buffered_stun_connect,
     102             :   0,
     103             :   0,
     104             :   nr_socket_buffered_stun_close,
     105             :   nr_socket_buffered_stun_listen,
     106             :   nr_socket_buffered_stun_accept
     107             : };
     108             : 
     109           0 : void nr_socket_buffered_stun_set_readable_cb(nr_socket *sock,
     110             :   NR_async_cb readable_cb, void *readable_cb_arg)
     111             : {
     112           0 :   nr_socket_buffered_stun *buf_sock = (nr_socket_buffered_stun *)sock->obj;
     113             : 
     114           0 :   buf_sock->readable_cb = readable_cb;
     115           0 :   buf_sock->readable_cb_arg = readable_cb_arg;
     116           0 : }
     117             : 
     118           0 : int nr_socket_buffered_set_connected_to(nr_socket *sock, nr_transport_addr *remote_addr)
     119             : {
     120           0 :   nr_socket_buffered_stun *buf_sock = (nr_socket_buffered_stun *)sock->obj;
     121             :   int r, _status;
     122             : 
     123           0 :   if ((r=nr_transport_addr_copy(&buf_sock->remote_addr, remote_addr)))
     124           0 :     ABORT(r);
     125             : 
     126           0 :   buf_sock->connected = 1;
     127             : 
     128           0 :   _status=0;
     129             : abort:
     130           0 :   return(_status);
     131             : }
     132             : 
     133           0 : int nr_socket_buffered_stun_create(nr_socket *inner, int max_pending,
     134             :   nr_framing_type framing_type, nr_socket **sockp)
     135             : {
     136             :   int r, _status;
     137           0 :   nr_socket_buffered_stun *sock = 0;
     138             :   size_t frame_size;
     139             : 
     140           0 :   if (!(sock = RCALLOC(sizeof(nr_socket_buffered_stun))))
     141           0 :     ABORT(R_NO_MEMORY);
     142             : 
     143           0 :   sock->inner = inner;
     144           0 :   sock->framing_type = framing_type;
     145             : 
     146           0 :   if ((r=nr_ip4_port_to_transport_addr(INADDR_ANY, 0, IPPROTO_UDP, &sock->remote_addr)))
     147           0 :     ABORT(r);
     148             : 
     149           0 :   switch (framing_type) {
     150             :     case ICE_TCP_FRAMING:
     151           0 :       frame_size = sizeof(nr_frame_header);
     152           0 :       sock->buffer_size = sizeof(nr_frame_header) + NR_MAX_FRAME_SIZE;
     153           0 :       sock->bytes_needed = sizeof(nr_frame_header);
     154           0 :       break;
     155             :     case TURN_TCP_FRAMING:
     156           0 :       frame_size = 0;
     157           0 :       sock->buffer_size = NR_STUN_MAX_MESSAGE_SIZE;
     158           0 :       sock->bytes_needed = sizeof(nr_stun_message_header);
     159           0 :       break;
     160             :     default:
     161           0 :       assert(0);
     162             :       ABORT(R_BAD_ARGS);
     163             :   }
     164             : 
     165             :   /* TODO(ekr@rtfm.com): Check this */
     166           0 :   if (!(sock->buffer = RMALLOC(sock->buffer_size)))
     167           0 :     ABORT(R_NO_MEMORY);
     168             : 
     169           0 :   sock->read_state = NR_ICE_SOCKET_READ_NONE;
     170           0 :   sock->connected = 0;
     171             : 
     172           0 :   STAILQ_INIT(&sock->pending_writes);
     173           0 :   if ((r=nr_p_buf_ctx_create(sock->buffer_size, &sock->p_bufs)))
     174           0 :     ABORT(r);
     175           0 :   sock->max_pending = max_pending + frame_size;
     176             : 
     177           0 :   if ((r=nr_socket_create_int(sock, &nr_socket_buffered_stun_vtbl, sockp)))
     178           0 :     ABORT(r);
     179             : 
     180           0 :   _status=0;
     181             : abort:
     182           0 :   if (_status && sock) {
     183           0 :     void *sock_v = sock;
     184           0 :     sock->inner = 0;  /* Give up ownership so we don't destroy */
     185           0 :     nr_socket_buffered_stun_destroy(&sock_v);
     186             :   }
     187           0 :   return(_status);
     188             : }
     189             : 
     190             : /* Note: This destroys the inner socket */
     191           0 : int nr_socket_buffered_stun_destroy(void **objp)
     192             : {
     193             :   nr_socket_buffered_stun *sock;
     194             :   NR_SOCKET fd;
     195             : 
     196           0 :   if (!objp || !*objp)
     197           0 :     return 0;
     198             : 
     199           0 :   sock = (nr_socket_buffered_stun *)*objp;
     200           0 :   *objp = 0;
     201             : 
     202             :   /* Free the buffer if needed */
     203           0 :   RFREE(sock->buffer);
     204             : 
     205             :   /* Cancel waiting on the socket */
     206           0 :   if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
     207           0 :     NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
     208             :   }
     209             : 
     210           0 :   nr_p_buf_free_chain(sock->p_bufs, &sock->pending_writes);
     211           0 :   nr_p_buf_ctx_destroy(&sock->p_bufs);
     212           0 :   nr_socket_destroy(&sock->inner);
     213           0 :   RFREE(sock);
     214             : 
     215           0 :   return 0;
     216             : }
     217             : 
     218           0 : static int nr_socket_buffered_stun_sendto(void *obj,const void *msg, size_t len,
     219             :   int flags, nr_transport_addr *to)
     220             : {
     221           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     222             :   int r, _status;
     223             :   size_t written;
     224           0 :   nr_frame_header *frame = NULL;
     225             : 
     226             :   /* Check that we are writing to the connected address if
     227             :      connected */
     228           0 :   if (!nr_transport_addr_is_wildcard(&sock->remote_addr)) {
     229           0 :     if (nr_transport_addr_cmp(&sock->remote_addr, to, NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
     230           0 :       r_log(LOG_GENERIC, LOG_ERR, "Sendto on connected socket doesn't match");
     231           0 :       ABORT(R_BAD_DATA);
     232             :     }
     233             :   }
     234             : 
     235           0 :   if (sock->framing_type == ICE_TCP_FRAMING) {
     236             : 
     237           0 :     assert(len <= NR_MAX_FRAME_SIZE);
     238           0 :     if (len > NR_MAX_FRAME_SIZE)
     239           0 :       ABORT(R_FAILED);
     240             : 
     241           0 :     if (!(frame = RMALLOC(len + sizeof(nr_frame_header))))
     242           0 :       ABORT(R_NO_MEMORY);
     243             : 
     244           0 :     frame->frame_length = htons(len);
     245           0 :     memcpy(frame->data, msg, len);
     246           0 :     len += sizeof(nr_frame_header);
     247           0 :     msg = frame;
     248             :   }
     249             : 
     250           0 :   if ((r=nr_socket_buffered_stun_write(obj, msg, len, &written)))
     251           0 :     ABORT(r);
     252             : 
     253           0 :   if (len != written)
     254           0 :     ABORT(R_IO_ERROR);
     255             : 
     256           0 :   _status=0;
     257             : abort:
     258           0 :   RFREE(frame);
     259           0 :   return _status;
     260             : }
     261             : 
     262           0 : static void nr_socket_buffered_stun_failed(nr_socket_buffered_stun *sock)
     263             :   {
     264             :     NR_SOCKET fd;
     265             : 
     266           0 :     sock->read_state = NR_ICE_SOCKET_READ_FAILED;
     267             : 
     268             :     /* Cancel waiting on the socket */
     269           0 :     if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
     270           0 :       NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
     271           0 :       NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
     272             :     }
     273           0 :   }
     274             : 
     275           0 : static int nr_socket_buffered_stun_recvfrom(void *obj,void * restrict buf,
     276             :   size_t maxlen, size_t *len, int flags, nr_transport_addr *from)
     277             : {
     278             :   int r, _status;
     279             :   size_t bytes_read;
     280           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     281           0 :   nr_frame_header *frame = (nr_frame_header *)sock->buffer;
     282           0 :   size_t skip_hdr_size = (sock->framing_type == ICE_TCP_FRAMING) ? sizeof(nr_frame_header) : 0;
     283             : 
     284           0 :   if (sock->read_state == NR_ICE_SOCKET_READ_FAILED) {
     285           0 :     ABORT(R_FAILED);
     286             :   }
     287             : 
     288           0 :   while (sock->bytes_needed) {
     289             :     /* Read all the expected bytes */
     290           0 :     assert(sock->bytes_needed <= sock->buffer_size - sock->bytes_read);
     291             : 
     292           0 :     if(r=nr_socket_read(sock->inner,
     293           0 :                         sock->buffer + sock->bytes_read,
     294             :                         sock->bytes_needed, &bytes_read, 0))
     295           0 :       ABORT(r);
     296             : 
     297           0 :     assert(bytes_read <= sock->bytes_needed);
     298           0 :     sock->bytes_needed -= bytes_read;
     299           0 :     sock->bytes_read += bytes_read;
     300             : 
     301             :     /* Unfinished */
     302           0 :     if (sock->bytes_needed)
     303           0 :       ABORT(R_WOULDBLOCK);
     304             : 
     305             :     /* No more bytes expected */
     306           0 :     if (sock->read_state == NR_ICE_SOCKET_READ_NONE) {
     307             :       size_t remaining_length;
     308           0 :       if (sock->framing_type == ICE_TCP_FRAMING) {
     309           0 :         if (sock->bytes_read < sizeof(nr_frame_header))
     310           0 :           ABORT(R_BAD_DATA);
     311           0 :         remaining_length = ntohs(frame->frame_length);
     312             :       } else {
     313             :         int tmp_length;
     314             : 
     315             :         /* Parse the header */
     316           0 :         if (r = nr_stun_message_length(sock->buffer, sock->bytes_read, &tmp_length))
     317           0 :           ABORT(r);
     318           0 :         assert(tmp_length >= 0);
     319           0 :         if (tmp_length < 0)
     320           0 :           ABORT(R_BAD_DATA);
     321           0 :         remaining_length = tmp_length;
     322             : 
     323             :       }
     324             :       /* Check to see if we have enough room */
     325           0 :       if ((sock->buffer_size - sock->bytes_read) < remaining_length)
     326           0 :         ABORT(R_BAD_DATA);
     327             : 
     328           0 :       sock->read_state = NR_ICE_SOCKET_READ_HDR;
     329             :       /* Set ourselves up to read the rest of the data */
     330           0 :       sock->bytes_needed = remaining_length;
     331             :     }
     332             :   }
     333             : 
     334           0 :   assert(skip_hdr_size <= sock->bytes_read);
     335           0 :   if (skip_hdr_size > sock->bytes_read)
     336           0 :     ABORT(R_BAD_DATA);
     337           0 :   sock->bytes_read -= skip_hdr_size;
     338             : 
     339           0 :   if (maxlen < sock->bytes_read)
     340           0 :     ABORT(R_BAD_ARGS);
     341             : 
     342           0 :   *len = sock->bytes_read;
     343           0 :   memcpy(buf, sock->buffer + skip_hdr_size, sock->bytes_read);
     344             : 
     345           0 :   sock->bytes_read = 0;
     346           0 :   sock->read_state = NR_ICE_SOCKET_READ_NONE;
     347           0 :   sock->bytes_needed = (sock->framing_type == ICE_TCP_FRAMING) ? sizeof(nr_frame_header) : sizeof(nr_stun_message_header);
     348             : 
     349           0 :   assert(!nr_transport_addr_is_wildcard(&sock->remote_addr));
     350           0 :   if (!nr_transport_addr_is_wildcard(&sock->remote_addr)) {
     351           0 :     if ((r=nr_transport_addr_copy(from, &sock->remote_addr)))
     352           0 :       ABORT(r);
     353             :   }
     354             : 
     355           0 :   _status=0;
     356             : abort:
     357           0 :   if (_status && (_status != R_WOULDBLOCK)) {
     358           0 :     nr_socket_buffered_stun_failed(sock);
     359             :   }
     360             : 
     361           0 :   return(_status);
     362             : }
     363             : 
     364           0 : static int nr_socket_buffered_stun_getfd(void *obj, NR_SOCKET *fd)
     365             : {
     366           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     367             : 
     368           0 :   return nr_socket_getfd(sock->inner, fd);
     369             : }
     370             : 
     371           0 : static int nr_socket_buffered_stun_getaddr(void *obj, nr_transport_addr *addrp)
     372             : {
     373           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     374             : 
     375           0 :   return nr_socket_getaddr(sock->inner, addrp);
     376             : }
     377             : 
     378           0 : static int nr_socket_buffered_stun_close(void *obj)
     379             : {
     380           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     381             :   NR_SOCKET fd;
     382             : 
     383             :   /* Cancel waiting on the socket */
     384           0 :   if (sock->inner && !nr_socket_getfd(sock->inner, &fd)) {
     385           0 :     NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
     386             :   }
     387             : 
     388           0 :   return nr_socket_close(sock->inner);
     389             : }
     390             : 
     391           0 : static int nr_socket_buffered_stun_listen(void *obj, int backlog)
     392             : {
     393             :   int r, _status;
     394           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     395             : 
     396           0 :   if (!sock->inner)
     397           0 :     ABORT(R_FAILED);
     398             : 
     399           0 :   if ((r=nr_socket_listen(sock->inner, backlog)))
     400           0 :     ABORT(r);
     401             : 
     402           0 :   _status=0;
     403             : abort:
     404           0 :   return(_status);
     405             : }
     406             : 
     407             : 
     408           0 : static int nr_socket_buffered_stun_accept(void *obj, nr_transport_addr *addrp, nr_socket **sockp)
     409             : {
     410           0 :   nr_socket_buffered_stun *bsock = (nr_socket_buffered_stun *)obj;
     411             : 
     412           0 :   return nr_socket_accept(bsock->inner, addrp, sockp);
     413             : }
     414             : 
     415           0 : static void nr_socket_buffered_stun_connected_cb(NR_SOCKET s, int how, void *arg)
     416             : {
     417           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)arg;
     418             :   int r, _status;
     419             :   NR_SOCKET fd;
     420             : 
     421           0 :   assert(!sock->connected);
     422             : 
     423           0 :   sock->connected = 1;
     424             : 
     425           0 :   if ((r=nr_socket_getfd(sock->inner, &fd)))
     426           0 :     ABORT(r);
     427           0 :   NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_WRITE);
     428             : 
     429             :   // once connected arm for read
     430           0 :   if (sock->readable_cb) {
     431           0 :     NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, sock->readable_cb, sock->readable_cb_arg);
     432             :   }
     433             : 
     434           0 :   if (sock->pending) {
     435           0 :     r_log(LOG_GENERIC, LOG_INFO, "Invoking writable_cb on connected (%u)", (uint32_t) sock->pending);
     436           0 :     nr_socket_buffered_stun_writable_cb(s, how, arg);
     437             :   }
     438             : 
     439           0 :   _status=0;
     440             : abort:
     441           0 :   if (_status) {
     442           0 :     r_log(LOG_GENERIC, LOG_ERR, "Failure in nr_socket_buffered_stun_connected_cb: %d", _status);
     443             : 
     444             :   }
     445           0 : }
     446             : 
     447           0 : static int nr_socket_buffered_stun_connect(void *obj, nr_transport_addr *addr)
     448             : {
     449           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     450             :   int r, _status;
     451             : 
     452           0 :   if ((r=nr_transport_addr_copy(&sock->remote_addr, addr)))
     453           0 :     ABORT(r);
     454             : 
     455           0 :   if ((r=nr_socket_connect(sock->inner, addr))) {
     456           0 :     if (r == R_WOULDBLOCK) {
     457             :       NR_SOCKET fd;
     458             : 
     459           0 :       if ((r=nr_socket_getfd(sock->inner, &fd)))
     460           0 :         ABORT(r);
     461             : 
     462           0 :       NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_WRITE, nr_socket_buffered_stun_connected_cb, sock);
     463           0 :       ABORT(R_WOULDBLOCK);
     464             :     }
     465           0 :     ABORT(r);
     466             :   } else {
     467           0 :     r_log(LOG_GENERIC, LOG_INFO, "Connected without blocking");
     468           0 :     sock->connected = 1;
     469             :   }
     470             : 
     471           0 :   _status=0;
     472             : abort:
     473           0 :   return(_status);
     474             : }
     475             : 
     476           0 : static int nr_socket_buffered_stun_arm_writable_cb(nr_socket_buffered_stun *sock)
     477             : {
     478             :   int r, _status;
     479             :   NR_SOCKET fd;
     480             : 
     481           0 :   if ((r=nr_socket_getfd(sock->inner, &fd)))
     482           0 :     ABORT(r);
     483             : 
     484           0 :   NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_WRITE, nr_socket_buffered_stun_writable_cb, sock);
     485             : 
     486           0 :   _status=0;
     487             : abort:
     488           0 :   return(_status);
     489             : }
     490             : 
     491           0 : static int nr_socket_buffered_stun_write(void *obj,const void *msg, size_t len, size_t *written)
     492             : {
     493           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)obj;
     494           0 :   int already_armed = 0;
     495             :   int r,_status;
     496           0 :   size_t written2 = 0;
     497           0 :   size_t original_len = len;
     498             : 
     499             :   /* Buffers are close to full, report error. Do this now so we never
     500             :      get partial writes */
     501           0 :   if ((sock->pending + len) > sock->max_pending) {
     502           0 :     r_log(LOG_GENERIC, LOG_INFO, "Write buffer for %s full (%u + %u > %u) - re-arming @%p",
     503           0 :           sock->remote_addr.as_string, (uint32_t)sock->pending, (uint32_t)len, (uint32_t)sock->max_pending,
     504             :           &(sock->pending));
     505           0 :     ABORT(R_WOULDBLOCK);
     506             :   }
     507             : 
     508             : 
     509           0 :   if (sock->connected && !sock->pending) {
     510           0 :     r = nr_socket_write(sock->inner, msg, len, &written2, 0);
     511           0 :     if (r) {
     512           0 :       if (r != R_WOULDBLOCK) {
     513           0 :         r_log(LOG_GENERIC, LOG_ERR, "Write error for %s - %d",
     514           0 :               sock->remote_addr.as_string, r);
     515           0 :         ABORT(r);
     516             :       }
     517           0 :       r_log(LOG_GENERIC, LOG_INFO, "Write of %" PRIu64 " blocked for %s",
     518           0 :             (uint64_t) len, sock->remote_addr.as_string);
     519             : 
     520           0 :       written2=0;
     521             :     }
     522             :   } else {
     523           0 :     already_armed = 1;
     524             :   }
     525             : 
     526             :   /* Buffer what's left */
     527           0 :   len -= written2;
     528             : 
     529           0 :   if (len) {
     530           0 :     if ((r=nr_p_buf_write_to_chain(sock->p_bufs, &sock->pending_writes,
     531             :                                    ((UCHAR *)msg) + written2, len))) {
     532           0 :       r_log(LOG_GENERIC, LOG_ERR, "Write_to_chain error for %s - %d",
     533           0 :             sock->remote_addr.as_string, r);
     534             : 
     535           0 :       ABORT(r);
     536             :     }
     537             : 
     538           0 :     sock->pending += len;
     539             :   }
     540             : 
     541           0 :   if (sock->pending) {
     542           0 :     if (!already_armed) {
     543           0 :       if ((r=nr_socket_buffered_stun_arm_writable_cb(sock)))
     544           0 :         ABORT(r);
     545             :     }
     546           0 :     r_log(LOG_GENERIC, LOG_INFO, "Write buffer not empty for %s  %u - %s armed (@%p),%s connected",
     547           0 :           sock->remote_addr.as_string, (uint32_t)sock->pending,
     548             :           already_armed ? "already" : "", &sock->pending,
     549           0 :           sock->connected ? "" : " not");
     550             :   }
     551             : 
     552           0 :   *written = original_len;
     553             : 
     554           0 :   _status=0;
     555             : abort:
     556           0 :   return _status;
     557             : }
     558             : 
     559           0 : static void nr_socket_buffered_stun_writable_cb(NR_SOCKET s, int how, void *arg)
     560             : {
     561           0 :   nr_socket_buffered_stun *sock = (nr_socket_buffered_stun *)arg;
     562             :   int r,_status;
     563             :   nr_p_buf *n1, *n2;
     564             : 
     565           0 :   if (sock->read_state == NR_ICE_SOCKET_READ_FAILED) {
     566           0 :     ABORT(R_FAILED);
     567             :   }
     568             : 
     569             :   /* Try to flush */
     570           0 :   STAILQ_FOREACH_SAFE(n1, &sock->pending_writes, entry, n2) {
     571           0 :     size_t written = 0;
     572             : 
     573           0 :     if ((r=nr_socket_write(sock->inner, n1->data + n1->r_offset,
     574           0 :                            n1->length - n1->r_offset,
     575             :                            &written, 0))) {
     576             : 
     577           0 :       r_log(LOG_GENERIC, LOG_ERR, "Write error for %s - %d",
     578           0 :             sock->remote_addr.as_string, r);
     579           0 :       ABORT(r);
     580             :     }
     581             : 
     582           0 :     n1->r_offset += written;
     583           0 :     assert(sock->pending >= written);
     584           0 :     sock->pending -= written;
     585             : 
     586           0 :     if (n1->r_offset < n1->length) {
     587             :       /* We wrote something, but not everything */
     588           0 :       r_log(LOG_GENERIC, LOG_INFO, "Write in callback didn't write all (remaining %u of %u) for %s",
     589           0 :             n1->length - n1->r_offset, n1->length,
     590           0 :             sock->remote_addr.as_string);
     591           0 :       ABORT(R_WOULDBLOCK);
     592             :     }
     593             : 
     594             :     /* We are done with this p_buf */
     595           0 :     STAILQ_REMOVE_HEAD(&sock->pending_writes, entry);
     596           0 :     nr_p_buf_free(sock->p_bufs, n1);
     597             :   }
     598             : 
     599           0 :   assert(!sock->pending);
     600           0 :   _status=0;
     601             : abort:
     602           0 :   r_log(LOG_GENERIC, LOG_INFO, "Writable_cb %s (%u (%p) pending)",
     603           0 :         sock->remote_addr.as_string, (uint32_t)sock->pending, &(sock->pending));
     604           0 :   if (_status && _status != R_WOULDBLOCK) {
     605           0 :     r_log(LOG_GENERIC, LOG_ERR, "Failure in writable_cb: %d", _status);
     606           0 :     nr_socket_buffered_stun_failed(sock);
     607           0 :   } else if (sock->pending) {
     608           0 :     nr_socket_buffered_stun_arm_writable_cb(sock);
     609             :   }
     610           0 : }

Generated by: LCOV version 1.13