LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nICEr/src/net - nr_proxy_tunnel.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 281 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 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             : 
       5             : All rights reserved.
       6             : 
       7             : Redistribution and use in source and binary forms, with or without
       8             : modification, are permitted provided that the following conditions are
       9             : met:
      10             : 
      11             : * Redistributions of source code must retain the above copyright
      12             :   notice, this list of conditions and the following disclaimer.
      13             : 
      14             : * Redistributions in binary form must reproduce the above copyright
      15             :   notice, this list of conditions and the following disclaimer in the
      16             :   documentation and/or other materials provided with the distribution.
      17             : 
      18             : * Neither the name of Adobe Systems, Network Resonance, Mozilla nor
      19             :   the names of its contributors may be used to endorse or promote
      20             :   products derived from this software without specific prior written
      21             :   permission.
      22             : 
      23             : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      24             : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      25             : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      26             : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      27             : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      28             : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      29             : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      30             : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      31             : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      32             : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      33             : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      34             : */
      35             : 
      36             : #include <nr_api.h>
      37             : 
      38             : #include <assert.h>
      39             : 
      40             : #include "nr_proxy_tunnel.h"
      41             : 
      42             : #define MAX_HTTP_CONNECT_ADDR_SIZE 256
      43             : #define MAX_HTTP_CONNECT_BUFFER_SIZE 1024
      44             : #define MAX_ALPN_LENGTH 64
      45             : #ifndef CRLF
      46             : #define CRLF "\r\n"
      47             : #endif
      48             : #define END_HEADERS CRLF CRLF
      49             : 
      50             : typedef enum {
      51             :   PROXY_TUNNEL_NONE=0,
      52             :   PROXY_TUNNEL_REQUESTED,
      53             :   PROXY_TUNNEL_CONNECTED,
      54             :   PROXY_TUNNEL_CLOSED,
      55             :   PROXY_TUNNEL_FAILED
      56             : } nr_socket_proxy_tunnel_state;
      57             : 
      58             : typedef struct nr_socket_proxy_tunnel_ {
      59             :   nr_proxy_tunnel_config *config;
      60             :   nr_socket *inner;
      61             :   nr_transport_addr remote_addr;
      62             :   nr_socket_proxy_tunnel_state state;
      63             :   char buffer[MAX_HTTP_CONNECT_BUFFER_SIZE];
      64             :   size_t buffered_bytes;
      65             :   void *resolver_handle;
      66             : } nr_socket_proxy_tunnel;
      67             : 
      68             : typedef struct nr_socket_wrapper_factory_proxy_tunnel_ {
      69             :   nr_proxy_tunnel_config *config;
      70             : } nr_socket_wrapper_factory_proxy_tunnel;
      71             : 
      72             : static int nr_socket_proxy_tunnel_destroy(void **objpp);
      73             : static int nr_socket_proxy_tunnel_getfd(void *obj, NR_SOCKET *fd);
      74             : static int nr_socket_proxy_tunnel_getaddr(void *obj, nr_transport_addr *addrp);
      75             : static int nr_socket_proxy_tunnel_connect(void *sock, nr_transport_addr *addr);
      76             : static int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len, size_t *written);
      77             : static int nr_socket_proxy_tunnel_read(void *obj, void * restrict buf, size_t maxlen, size_t *len);
      78             : static int nr_socket_proxy_tunnel_close(void *obj);
      79             : 
      80             : int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp);
      81             : 
      82             : int nr_socket_wrapper_factory_proxy_tunnel_wrap(void *obj,
      83             :                                                 nr_socket *inner,
      84             :                                                 nr_socket **socketpp);
      85             : 
      86             : int nr_socket_wrapper_factory_proxy_tunnel_destroy(void **objpp);
      87             : 
      88             : static nr_socket_vtbl nr_socket_proxy_tunnel_vtbl={
      89             :   1,
      90             :   nr_socket_proxy_tunnel_destroy,
      91             :   0,
      92             :   0,
      93             :   nr_socket_proxy_tunnel_getfd,
      94             :   nr_socket_proxy_tunnel_getaddr,
      95             :   nr_socket_proxy_tunnel_connect,
      96             :   nr_socket_proxy_tunnel_write,
      97             :   nr_socket_proxy_tunnel_read,
      98             :   nr_socket_proxy_tunnel_close
      99             : };
     100             : 
     101           0 : static int send_http_connect(nr_socket_proxy_tunnel *sock)
     102             : {
     103             :   int r, _status;
     104             :   int port;
     105             :   int printed;
     106             :   char addr[MAX_HTTP_CONNECT_ADDR_SIZE];
     107             :   char mesg[MAX_HTTP_CONNECT_ADDR_SIZE + MAX_ALPN_LENGTH + 128];
     108           0 :   size_t offset = 0;
     109             :   size_t bytes_sent;
     110             : 
     111           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect");
     112             : 
     113           0 :   if ((r=nr_transport_addr_get_port(&sock->remote_addr, &port))) {
     114           0 :     ABORT(r);
     115             :   }
     116             : 
     117           0 :   if ((r=nr_transport_addr_get_addrstring(&sock->remote_addr, addr, sizeof(addr)))) {
     118           0 :     ABORT(r);
     119             :   }
     120             : 
     121           0 :   printed = snprintf(mesg + offset, sizeof(mesg) - offset,
     122             :                      "CONNECT %s:%d HTTP/1.0", addr, port);
     123           0 :   offset += printed;
     124           0 :   if (printed < 0 || (offset >= sizeof(mesg))) {
     125           0 :     ABORT(R_FAILED);
     126             :   }
     127             : 
     128           0 :   if (sock->config->alpn) {
     129           0 :     printed = snprintf(mesg + offset, sizeof(mesg) - offset,
     130           0 :                        CRLF "ALPN: %s", sock->config->alpn);
     131           0 :     offset += printed;
     132           0 :     if (printed < 0 || (offset >= sizeof(mesg))) {
     133           0 :       ABORT(R_FAILED);
     134             :     }
     135             :   }
     136           0 :   if (offset + sizeof(END_HEADERS) >= sizeof(mesg)) {
     137           0 :     ABORT(R_FAILED);
     138             :   }
     139           0 :   memcpy(mesg + offset, END_HEADERS, strlen(END_HEADERS));
     140           0 :   offset += strlen(END_HEADERS);
     141             : 
     142           0 :   if ((r=nr_socket_write(sock->inner, mesg, offset, &bytes_sent, 0))) {
     143           0 :     ABORT(r);
     144             :   }
     145             : 
     146           0 :   if (bytes_sent < offset) {
     147             :     /* TODO(bug 1116583): buffering and wait for */
     148           0 :     r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect should be buffering %lu", (unsigned long)bytes_sent);
     149           0 :     ABORT(R_IO_ERROR);
     150             :   }
     151             : 
     152           0 :   sock->state = PROXY_TUNNEL_REQUESTED;
     153             : 
     154           0 :   _status = 0;
     155             : abort:
     156           0 :   return(_status);
     157             : }
     158             : 
     159           0 : static char *find_http_terminator(char *response, size_t len)
     160             : {
     161           0 :   char *term = response;
     162           0 :   char *end = response + len;
     163           0 :   int N = strlen(END_HEADERS);
     164             : 
     165           0 :   for (; term = memchr(term, '\r', end - term); ++term) {
     166           0 :     if (end - term >= N && memcmp(term, END_HEADERS, N) == 0) {
     167           0 :       return term;
     168             :     }
     169             :   }
     170             : 
     171           0 :   return NULL;
     172             : }
     173             : 
     174           0 : static int parse_http_response(char *begin, char *end, unsigned int *status)
     175             : {
     176           0 :   size_t len = end - begin;
     177             :   char response[MAX_HTTP_CONNECT_BUFFER_SIZE + 1];
     178             : 
     179             :   // len should *never* be greater than nr_socket_proxy_tunnel::buffered_bytes.
     180             :   // Which in turn should never be greater nr_socket_proxy_tunnel::buffer size.
     181           0 :   assert(len <= MAX_HTTP_CONNECT_BUFFER_SIZE);
     182           0 :   if (len > MAX_HTTP_CONNECT_BUFFER_SIZE) {
     183           0 :     return R_BAD_DATA;
     184             :   }
     185             : 
     186           0 :   memcpy(response, begin, len);
     187           0 :   response[len] = '\0';
     188             : 
     189             :   // http://www.rfc-editor.org/rfc/rfc7230.txt
     190             :   // status-line    = HTTP-version SP status-code SP reason-phrase CRLF
     191             :   // HTTP-version   = HTTP-name "/" DIGIT "." DIGIT
     192             :   // HTTP-name      = "HTTP" ; "HTTP", case-sensitive
     193             :   // status-code    = 3DIGIT
     194             : 
     195           0 :   if (sscanf(response, "HTTP/%*u.%*u %u", status) != 1) {
     196           0 :     r_log(LOG_GENERIC,LOG_WARNING,"parse_http_response failed to find status (%s)", response);
     197           0 :     return R_BAD_DATA;
     198             :   }
     199             : 
     200           0 :   return 0;
     201             : }
     202             : 
     203           0 : static int nr_socket_proxy_tunnel_destroy(void **objpp)
     204             : {
     205             :   nr_socket_proxy_tunnel *sock;
     206             : 
     207           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_destroy");
     208             : 
     209           0 :   if (!objpp || !*objpp)
     210           0 :     return 0;
     211             : 
     212           0 :   sock = (nr_socket_proxy_tunnel *)*objpp;
     213           0 :   *objpp = 0;
     214             : 
     215           0 :   if (sock->resolver_handle) {
     216           0 :     nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
     217             :   }
     218             : 
     219           0 :   nr_proxy_tunnel_config_destroy(&sock->config);
     220           0 :   nr_socket_destroy(&sock->inner);
     221           0 :   RFREE(sock);
     222             : 
     223           0 :   return 0;
     224             : }
     225             : 
     226           0 : static int nr_socket_proxy_tunnel_getfd(void *obj, NR_SOCKET *fd)
     227             : {
     228           0 :   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
     229             : 
     230           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getfd");
     231             : 
     232           0 :   return nr_socket_getfd(sock->inner, fd);
     233             : }
     234             : 
     235           0 : static int nr_socket_proxy_tunnel_getaddr(void *obj, nr_transport_addr *addrp)
     236             : {
     237           0 :   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
     238             : 
     239           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getaddr");
     240             : 
     241           0 :   return nr_socket_getaddr(sock->inner, addrp);
     242             : }
     243             : 
     244           0 : static int nr_socket_proxy_tunnel_resolved_cb(void *obj, nr_transport_addr *proxy_addr)
     245             : {
     246             :   int r, _status;
     247           0 :   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
     248             : 
     249           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_resolved_cb");
     250             : 
     251             :   /* Mark the socket resolver as completed */
     252           0 :   sock->resolver_handle = 0;
     253             : 
     254           0 :   if (proxy_addr) {
     255           0 :     r_log(LOG_GENERIC,LOG_DEBUG,"Resolved proxy address %s -> %s",
     256           0 :         sock->config->proxy_host, proxy_addr->as_string);
     257             :   }
     258             :   else {
     259           0 :     r_log(LOG_GENERIC,LOG_WARNING,"Failed to resolve proxy %s",
     260           0 :         sock->config->proxy_host);
     261             :     /* TODO: Mozilla bug 1241758: because of the callback the return value goes
     262             :      * nowhere, so we can't mark the candidate as failed, so everything depends
     263             :      * on the overall timeouts in this case. */
     264           0 :     sock->state = PROXY_TUNNEL_FAILED;
     265           0 :     ABORT(R_NOT_FOUND);
     266             :   }
     267             : 
     268           0 :   if ((r=nr_socket_connect(sock->inner, proxy_addr))) {
     269           0 :     ABORT(r);
     270             :   }
     271             : 
     272           0 :   _status = 0;
     273             : abort:
     274           0 :   return(_status);
     275             : }
     276             : 
     277           0 : int nr_socket_proxy_tunnel_connect(void *obj, nr_transport_addr *addr)
     278             : {
     279             :   int r, _status;
     280             :   int has_addr;
     281           0 :   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
     282           0 :   nr_proxy_tunnel_config *config = sock->config;
     283             :   nr_transport_addr proxy_addr, local_addr;
     284             :   nr_resolver_resource resource;
     285             : 
     286           0 :   if ((r=nr_transport_addr_copy(&sock->remote_addr, addr))) {
     287           0 :     ABORT(r);
     288             :   }
     289             : 
     290           0 :   assert(config->proxy_host);
     291             : 
     292             :   /* Check if the proxy_host is already an IP address */
     293           0 :   has_addr = !nr_str_port_to_transport_addr(config->proxy_host,
     294           0 :       config->proxy_port, IPPROTO_TCP, &proxy_addr);
     295             : 
     296           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: %s", config->proxy_host);
     297             : 
     298           0 :   if (!has_addr && !config->resolver) {
     299           0 :     r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect name resolver not configured");
     300           0 :     ABORT(R_NOT_FOUND);
     301             :   }
     302             : 
     303           0 :   if (!has_addr) {
     304           0 :     resource.domain_name=config->proxy_host;
     305           0 :     resource.port=config->proxy_port;
     306           0 :     resource.stun_turn=NR_RESOLVE_PROTOCOL_TURN;
     307           0 :     resource.transport_protocol=IPPROTO_TCP;
     308             : 
     309           0 :     if ((r=nr_socket_getaddr(sock->inner, &local_addr))) {
     310           0 :       r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect failed to get local address");
     311           0 :       ABORT(r);
     312             :     }
     313             : 
     314           0 :     switch(local_addr.ip_version) {
     315             :       case NR_IPV4:
     316           0 :         resource.address_family=AF_INET;
     317           0 :         break;
     318             :       case NR_IPV6:
     319           0 :         resource.address_family=AF_INET6;
     320           0 :         break;
     321             :       default:
     322           0 :         ABORT(R_BAD_ARGS);
     323             :     }
     324             : 
     325           0 :     r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: nr_resolver_resolve");
     326           0 :     if ((r=nr_resolver_resolve(config->resolver, &resource,
     327             :             nr_socket_proxy_tunnel_resolved_cb, (void *)sock, &sock->resolver_handle))) {
     328           0 :       r_log(LOG_GENERIC,LOG_ERR,"Could not invoke DNS resolver");
     329           0 :       ABORT(r);
     330             :     }
     331             : 
     332           0 :     ABORT(R_WOULDBLOCK);
     333             :   }
     334             : 
     335           0 :   if ((r=nr_socket_connect(sock->inner, &proxy_addr))) {
     336           0 :     ABORT(r);
     337             :   }
     338             : 
     339           0 :   _status=0;
     340             : abort:
     341           0 :   return(_status);
     342             : }
     343             : 
     344           0 : int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len,
     345             :                                  size_t *written)
     346             : {
     347             :   int r, _status;
     348           0 :   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
     349             : 
     350           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_write");
     351             : 
     352           0 :   if (sock->state >= PROXY_TUNNEL_CLOSED) {
     353           0 :     return R_FAILED;
     354             :   }
     355             : 
     356           0 :   if (sock->state == PROXY_TUNNEL_NONE) {
     357           0 :     if ((r=send_http_connect(sock))) {
     358           0 :       ABORT(r);
     359             :     }
     360             :   }
     361             : 
     362           0 :   if (sock->state != PROXY_TUNNEL_CONNECTED) {
     363           0 :     return R_WOULDBLOCK;
     364             :   }
     365             : 
     366           0 :   if ((r=nr_socket_write(sock->inner, msg, len, written, 0))) {
     367           0 :     ABORT(r);
     368             :   }
     369             : 
     370           0 :   _status=0;
     371             : abort:
     372           0 :   return(_status);
     373             : }
     374             : 
     375           0 : int nr_socket_proxy_tunnel_read(void *obj, void * restrict buf, size_t maxlen,
     376             :                                 size_t *len)
     377             : {
     378             :   int r, _status;
     379             :   char *ptr, *http_term;
     380             :   size_t bytes_read, available_buffer_len, maxlen_int;
     381             :   size_t pending;
     382           0 :   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
     383             :   unsigned int http_status;
     384             : 
     385           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_read");
     386             : 
     387           0 :   *len = 0;
     388             : 
     389           0 :   if (sock->state >= PROXY_TUNNEL_CLOSED) {
     390           0 :     return R_FAILED;
     391             :   }
     392             : 
     393           0 :   if (sock->state == PROXY_TUNNEL_CONNECTED) {
     394           0 :     return nr_socket_read(sock->inner, buf, maxlen, len, 0);
     395             :   }
     396             : 
     397           0 :   if (sock->buffered_bytes >= sizeof(sock->buffer)) {
     398           0 :     r_log(LOG_GENERIC,LOG_ERR,"buffer filled waiting for CONNECT response");
     399           0 :     assert(sock->buffered_bytes == sizeof(sock->buffer));
     400           0 :     ABORT(R_INTERNAL);
     401             :   }
     402             : 
     403             :   /* Do not read more than maxlen bytes */
     404           0 :   available_buffer_len = sizeof(sock->buffer) - sock->buffered_bytes;
     405           0 :   maxlen_int = maxlen < available_buffer_len ? maxlen : available_buffer_len;
     406           0 :   if ((r=nr_socket_read(sock->inner, sock->buffer + sock->buffered_bytes,
     407             :           maxlen_int, &bytes_read, 0))) {
     408           0 :     ABORT(r);
     409             :   }
     410             : 
     411           0 :   sock->buffered_bytes += bytes_read;
     412             : 
     413           0 :   if (http_term = find_http_terminator(sock->buffer, sock->buffered_bytes)) {
     414           0 :     if ((r = parse_http_response(sock->buffer, http_term, &http_status))) {
     415           0 :       ABORT(r);
     416             :     }
     417             : 
     418             :     /* TODO (bug 1115934): Handle authentication challenges. */
     419           0 :     if (http_status < 200 || http_status >= 300) {
     420           0 :       r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_read unable to connect %u",
     421             :             http_status);
     422           0 :       ABORT(R_FAILED);
     423             :     }
     424             : 
     425           0 :     sock->state = PROXY_TUNNEL_CONNECTED;
     426             : 
     427           0 :     ptr = http_term + strlen(END_HEADERS);
     428           0 :     pending = sock->buffered_bytes - (ptr - sock->buffer);
     429             : 
     430           0 :     if (pending == 0) {
     431           0 :       ABORT(R_WOULDBLOCK);
     432             :     }
     433             : 
     434           0 :     assert(pending <= maxlen);
     435           0 :     *len = pending;
     436             : 
     437           0 :     memcpy(buf, ptr, *len);
     438             :   }
     439             : 
     440           0 :   _status=0;
     441             : abort:
     442           0 :   if (_status && _status != R_WOULDBLOCK) {
     443           0 :       sock->state = PROXY_TUNNEL_FAILED;
     444             :   }
     445           0 :   return(_status);
     446             : }
     447             : 
     448           0 : int nr_socket_proxy_tunnel_close(void *obj)
     449             : {
     450           0 :   nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
     451             : 
     452           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_close");
     453             : 
     454           0 :   if (sock->resolver_handle) {
     455           0 :     nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
     456           0 :     sock->resolver_handle = 0;
     457             :   }
     458             : 
     459           0 :   sock->state = PROXY_TUNNEL_CLOSED;
     460             : 
     461           0 :   return nr_socket_close(sock->inner);
     462             : }
     463             : 
     464           0 : int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **configpp)
     465             : {
     466             :   int _status;
     467           0 :   nr_proxy_tunnel_config *configp=0;
     468             : 
     469           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_create");
     470             : 
     471           0 :   if (!(configp=RCALLOC(sizeof(nr_proxy_tunnel_config))))
     472           0 :     ABORT(R_NO_MEMORY);
     473             : 
     474           0 :   *configpp=configp;
     475           0 :   _status=0;
     476             : abort:
     477           0 :   return(_status);
     478             : }
     479             : 
     480           0 : int nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config **configpp)
     481             : {
     482             :   nr_proxy_tunnel_config *configp;
     483             : 
     484           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_destroy");
     485             : 
     486           0 :   if (!configpp || !*configpp)
     487           0 :     return 0;
     488             : 
     489           0 :   configp = *configpp;
     490           0 :   *configpp = 0;
     491             : 
     492           0 :   RFREE(configp->proxy_host);
     493           0 :   RFREE(configp->alpn);
     494           0 :   RFREE(configp);
     495             : 
     496           0 :   return 0;
     497             : }
     498             : 
     499           0 : int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
     500             :                                      const char *host, UINT2 port)
     501             : {
     502             :   char *hostdup;
     503             : 
     504           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_proxy %s %d", host, port);
     505             : 
     506           0 :   if (!host) {
     507           0 :     return R_BAD_ARGS;
     508             :   }
     509             : 
     510           0 :   if (!(hostdup = r_strdup(host))) {
     511           0 :     return R_NO_MEMORY;
     512             :   }
     513             : 
     514           0 :   if (config->proxy_host) {
     515           0 :     RFREE(config->proxy_host);
     516             :   }
     517             : 
     518           0 :   config->proxy_host = hostdup;
     519           0 :   config->proxy_port = port;
     520             : 
     521           0 :   return 0;
     522             : }
     523             : 
     524           0 : int nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config *config,
     525             :                                         nr_resolver *resolver)
     526             : {
     527           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_resolver");
     528             : 
     529           0 :   config->resolver = resolver;
     530             : 
     531           0 :   return 0;
     532             : }
     533             : 
     534           0 : int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
     535             :                                     const char *alpn)
     536             : {
     537           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_alpn");
     538             : 
     539           0 :   if (alpn && (strlen(alpn) > MAX_ALPN_LENGTH)) {
     540           0 :     return R_BAD_ARGS;
     541             :   }
     542             : 
     543           0 :   if (config->alpn) {
     544           0 :     RFREE(config->alpn);
     545             :   }
     546             : 
     547           0 :   config->alpn = NULL;
     548             : 
     549           0 :   if (alpn) {
     550           0 :     char *alpndup = r_strdup(alpn);
     551             : 
     552           0 :     if (!alpndup) {
     553           0 :       return R_NO_MEMORY;
     554             :     }
     555             : 
     556           0 :     config->alpn = alpndup;
     557             :   }
     558             : 
     559           0 :   return 0;
     560             : }
     561             : 
     562           0 : int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp)
     563             : {
     564             :   int r,_status;
     565           0 :   nr_proxy_tunnel_config *copy = 0;
     566             : 
     567           0 :   if ((r=nr_proxy_tunnel_config_create(&copy)))
     568           0 :     ABORT(r);
     569             : 
     570           0 :   if ((r=nr_proxy_tunnel_config_set_proxy(copy, config->proxy_host, config->proxy_port)))
     571           0 :     ABORT(r);
     572             : 
     573           0 :   if ((r=nr_proxy_tunnel_config_set_resolver(copy, config->resolver)))
     574           0 :     ABORT(r);
     575             : 
     576           0 :   if ((r=nr_proxy_tunnel_config_set_alpn(copy, config->alpn)))
     577           0 :     ABORT(r);
     578             : 
     579           0 :   *copypp = copy;
     580             : 
     581           0 :   _status=0;
     582             : abort:
     583           0 :   if (_status) {
     584           0 :     nr_proxy_tunnel_config_destroy(&copy);
     585             :   }
     586           0 :   return(_status);
     587             : }
     588             : 
     589             : 
     590           0 : int nr_socket_proxy_tunnel_create(nr_proxy_tunnel_config *config,
     591             :                                   nr_socket *inner,
     592             :                                   nr_socket **socketpp)
     593             : {
     594             :   int r, _status;
     595           0 :   nr_socket_proxy_tunnel *sock=0;
     596             :   void *sockv;
     597             : 
     598           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_create");
     599             : 
     600           0 :   if (!config) {
     601           0 :     ABORT(R_BAD_ARGS);
     602             :   }
     603             : 
     604           0 :   if (!(sock=RCALLOC(sizeof(nr_socket_proxy_tunnel)))) {
     605           0 :     ABORT(R_NO_MEMORY);
     606             :   }
     607             : 
     608           0 :   sock->inner = inner;
     609             : 
     610           0 :   if ((r=nr_proxy_tunnel_config_copy(config, &sock->config)))
     611           0 :     ABORT(r);
     612             : 
     613           0 :   if ((r=nr_socket_create_int(sock, &nr_socket_proxy_tunnel_vtbl, socketpp))) {
     614           0 :     ABORT(r);
     615             :   }
     616             : 
     617           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_created");
     618             : 
     619           0 :   _status=0;
     620             : abort:
     621           0 :   if (_status) {
     622           0 :     sockv = sock;
     623           0 :     nr_socket_proxy_tunnel_destroy(&sockv);
     624             :   }
     625           0 :   return(_status);
     626             : }
     627             : 
     628           0 : int nr_socket_wrapper_factory_proxy_tunnel_wrap(void *obj,
     629             :                                                 nr_socket *inner,
     630             :                                                 nr_socket **socketpp)
     631             : {
     632           0 :   nr_socket_wrapper_factory_proxy_tunnel *wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)obj;
     633             : 
     634           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_wrap");
     635             : 
     636           0 :   return nr_socket_proxy_tunnel_create(wrapper->config, inner, socketpp);
     637             : }
     638             : 
     639             : 
     640           0 : int nr_socket_wrapper_factory_proxy_tunnel_destroy(void **objpp) {
     641             :   nr_socket_wrapper_factory_proxy_tunnel *wrapper;
     642             : 
     643           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_destroy");
     644             : 
     645           0 :   if (!objpp || !*objpp)
     646           0 :     return 0;
     647             : 
     648           0 :   wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)*objpp;
     649           0 :   *objpp = 0;
     650             : 
     651           0 :   nr_proxy_tunnel_config_destroy(&wrapper->config);
     652           0 :   RFREE(wrapper);
     653             : 
     654           0 :   return 0;
     655             : }
     656             : 
     657             : static nr_socket_wrapper_factory_vtbl proxy_tunnel_wrapper_vtbl = {
     658             :   nr_socket_wrapper_factory_proxy_tunnel_wrap,
     659             :   nr_socket_wrapper_factory_proxy_tunnel_destroy
     660             : };
     661             : 
     662           0 : int nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config *config,
     663             :                                                   nr_socket_wrapper_factory **factory) {
     664             :   int r,_status;
     665           0 :   nr_socket_wrapper_factory_proxy_tunnel *wrapper=0;
     666             :   void *wrapperv;
     667             : 
     668           0 :   r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_create");
     669             : 
     670           0 :   if (!(wrapper=RCALLOC(sizeof(nr_socket_wrapper_factory_proxy_tunnel))))
     671           0 :     ABORT(R_NO_MEMORY);
     672             : 
     673           0 :   if ((r=nr_proxy_tunnel_config_copy(config, &wrapper->config)))
     674           0 :     ABORT(r);
     675             : 
     676           0 :   if ((r=nr_socket_wrapper_factory_create_int(wrapper, &proxy_tunnel_wrapper_vtbl, factory)))
     677           0 :     ABORT(r);
     678             : 
     679           0 :   _status=0;
     680             : abort:
     681           0 :   if (_status) {
     682           0 :     wrapperv = wrapper;
     683           0 :     nr_socket_wrapper_factory_proxy_tunnel_destroy(&wrapperv);
     684             :   }
     685           0 :   return(_status);
     686             : }

Generated by: LCOV version 1.13