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(©)))
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(©);
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 : }
|