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
send_http_connect(nr_socket_proxy_tunnel * sock)101 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 size_t offset = 0;
109 size_t bytes_sent;
110
111 r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect");
112
113 if ((r=nr_transport_addr_get_port(&sock->remote_addr, &port))) {
114 ABORT(r);
115 }
116
117 if ((r=nr_transport_addr_get_addrstring(&sock->remote_addr, addr, sizeof(addr)))) {
118 ABORT(r);
119 }
120
121 printed = snprintf(mesg + offset, sizeof(mesg) - offset,
122 "CONNECT %s:%d HTTP/1.0", addr, port);
123 offset += printed;
124 if (printed < 0 || (offset >= sizeof(mesg))) {
125 ABORT(R_FAILED);
126 }
127
128 if (sock->config->alpn) {
129 printed = snprintf(mesg + offset, sizeof(mesg) - offset,
130 CRLF "ALPN: %s", sock->config->alpn);
131 offset += printed;
132 if (printed < 0 || (offset >= sizeof(mesg))) {
133 ABORT(R_FAILED);
134 }
135 }
136 if (offset + sizeof(END_HEADERS) >= sizeof(mesg)) {
137 ABORT(R_FAILED);
138 }
139 memcpy(mesg + offset, END_HEADERS, strlen(END_HEADERS));
140 offset += strlen(END_HEADERS);
141
142 if ((r=nr_socket_write(sock->inner, mesg, offset, &bytes_sent, 0))) {
143 ABORT(r);
144 }
145
146 if (bytes_sent < offset) {
147 /* TODO(bug 1116583): buffering and wait for */
148 r_log(LOG_GENERIC,LOG_DEBUG,"send_http_connect should be buffering %lu", (unsigned long)bytes_sent);
149 ABORT(R_IO_ERROR);
150 }
151
152 sock->state = PROXY_TUNNEL_REQUESTED;
153
154 _status = 0;
155 abort:
156 return(_status);
157 }
158
find_http_terminator(char * response,size_t len)159 static char *find_http_terminator(char *response, size_t len)
160 {
161 char *term = response;
162 char *end = response + len;
163 int N = strlen(END_HEADERS);
164
165 for (; term = memchr(term, '\r', end - term); ++term) {
166 if (end - term >= N && memcmp(term, END_HEADERS, N) == 0) {
167 return term;
168 }
169 }
170
171 return NULL;
172 }
173
parse_http_response(char * begin,char * end,unsigned int * status)174 static int parse_http_response(char *begin, char *end, unsigned int *status)
175 {
176 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 assert(len <= MAX_HTTP_CONNECT_BUFFER_SIZE);
182 if (len > MAX_HTTP_CONNECT_BUFFER_SIZE) {
183 return R_BAD_DATA;
184 }
185
186 memcpy(response, begin, len);
187 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 if (sscanf(response, "HTTP/%*u.%*u %u", status) != 1) {
196 r_log(LOG_GENERIC,LOG_WARNING,"parse_http_response failed to find status (%s)", response);
197 return R_BAD_DATA;
198 }
199
200 return 0;
201 }
202
nr_socket_proxy_tunnel_destroy(void ** objpp)203 static int nr_socket_proxy_tunnel_destroy(void **objpp)
204 {
205 nr_socket_proxy_tunnel *sock;
206
207 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_destroy");
208
209 if (!objpp || !*objpp)
210 return 0;
211
212 sock = (nr_socket_proxy_tunnel *)*objpp;
213 *objpp = 0;
214
215 if (sock->resolver_handle) {
216 nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
217 }
218
219 nr_proxy_tunnel_config_destroy(&sock->config);
220 nr_socket_destroy(&sock->inner);
221 RFREE(sock);
222
223 return 0;
224 }
225
nr_socket_proxy_tunnel_getfd(void * obj,NR_SOCKET * fd)226 static int nr_socket_proxy_tunnel_getfd(void *obj, NR_SOCKET *fd)
227 {
228 nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
229
230 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getfd");
231
232 return nr_socket_getfd(sock->inner, fd);
233 }
234
nr_socket_proxy_tunnel_getaddr(void * obj,nr_transport_addr * addrp)235 static int nr_socket_proxy_tunnel_getaddr(void *obj, nr_transport_addr *addrp)
236 {
237 nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel *)obj;
238
239 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_getaddr");
240
241 return nr_socket_getaddr(sock->inner, addrp);
242 }
243
nr_socket_proxy_tunnel_resolved_cb(void * obj,nr_transport_addr * proxy_addr)244 static int nr_socket_proxy_tunnel_resolved_cb(void *obj, nr_transport_addr *proxy_addr)
245 {
246 int r, _status;
247 nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
248
249 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_resolved_cb");
250
251 /* Mark the socket resolver as completed */
252 sock->resolver_handle = 0;
253
254 if (proxy_addr) {
255 r_log(LOG_GENERIC,LOG_DEBUG,"Resolved proxy address %s -> %s",
256 sock->config->proxy_host, proxy_addr->as_string);
257 }
258 else {
259 r_log(LOG_GENERIC,LOG_WARNING,"Failed to resolve proxy %s",
260 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 sock->state = PROXY_TUNNEL_FAILED;
265 ABORT(R_NOT_FOUND);
266 }
267
268 if ((r=nr_socket_connect(sock->inner, proxy_addr))) {
269 ABORT(r);
270 }
271
272 _status = 0;
273 abort:
274 return(_status);
275 }
276
nr_socket_proxy_tunnel_connect(void * obj,nr_transport_addr * addr)277 int nr_socket_proxy_tunnel_connect(void *obj, nr_transport_addr *addr)
278 {
279 int r, _status;
280 int has_addr;
281 nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
282 nr_proxy_tunnel_config *config = sock->config;
283 nr_transport_addr proxy_addr, local_addr;
284 nr_resolver_resource resource;
285
286 if ((r=nr_transport_addr_copy(&sock->remote_addr, addr))) {
287 ABORT(r);
288 }
289
290 assert(config->proxy_host);
291
292 /* Check if the proxy_host is already an IP address */
293 has_addr = !nr_str_port_to_transport_addr(config->proxy_host,
294 config->proxy_port, IPPROTO_TCP, &proxy_addr);
295
296 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: %s", config->proxy_host);
297
298 if (!has_addr && !config->resolver) {
299 r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect name resolver not configured");
300 ABORT(R_NOT_FOUND);
301 }
302
303 if (!has_addr) {
304 resource.domain_name=config->proxy_host;
305 resource.port=config->proxy_port;
306 resource.stun_turn=NR_RESOLVE_PROTOCOL_TURN;
307 resource.transport_protocol=IPPROTO_TCP;
308
309 if ((r=nr_socket_getaddr(sock->inner, &local_addr))) {
310 r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_connect failed to get local address");
311 ABORT(r);
312 }
313
314 switch(local_addr.ip_version) {
315 case NR_IPV4:
316 resource.address_family=AF_INET;
317 break;
318 case NR_IPV6:
319 resource.address_family=AF_INET6;
320 break;
321 default:
322 ABORT(R_BAD_ARGS);
323 }
324
325 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_connect: nr_resolver_resolve");
326 if ((r=nr_resolver_resolve(config->resolver, &resource,
327 nr_socket_proxy_tunnel_resolved_cb, (void *)sock, &sock->resolver_handle))) {
328 r_log(LOG_GENERIC,LOG_ERR,"Could not invoke DNS resolver");
329 ABORT(r);
330 }
331
332 ABORT(R_WOULDBLOCK);
333 }
334
335 if ((r=nr_socket_connect(sock->inner, &proxy_addr))) {
336 ABORT(r);
337 }
338
339 _status=0;
340 abort:
341 return(_status);
342 }
343
nr_socket_proxy_tunnel_write(void * obj,const void * msg,size_t len,size_t * written)344 int nr_socket_proxy_tunnel_write(void *obj, const void *msg, size_t len,
345 size_t *written)
346 {
347 int r, _status;
348 nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
349
350 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_write");
351
352 if (sock->state >= PROXY_TUNNEL_CLOSED) {
353 return R_FAILED;
354 }
355
356 if (sock->state == PROXY_TUNNEL_NONE) {
357 if ((r=send_http_connect(sock))) {
358 ABORT(r);
359 }
360 }
361
362 if (sock->state != PROXY_TUNNEL_CONNECTED) {
363 return R_WOULDBLOCK;
364 }
365
366 if ((r=nr_socket_write(sock->inner, msg, len, written, 0))) {
367 ABORT(r);
368 }
369
370 _status=0;
371 abort:
372 return(_status);
373 }
374
nr_socket_proxy_tunnel_read(void * obj,void * restrict buf,size_t maxlen,size_t * len)375 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 nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
383 unsigned int http_status;
384
385 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_read");
386
387 *len = 0;
388
389 if (sock->state >= PROXY_TUNNEL_CLOSED) {
390 return R_FAILED;
391 }
392
393 if (sock->state == PROXY_TUNNEL_CONNECTED) {
394 return nr_socket_read(sock->inner, buf, maxlen, len, 0);
395 }
396
397 if (sock->buffered_bytes >= sizeof(sock->buffer)) {
398 r_log(LOG_GENERIC,LOG_ERR,"buffer filled waiting for CONNECT response");
399 assert(sock->buffered_bytes == sizeof(sock->buffer));
400 ABORT(R_INTERNAL);
401 }
402
403 /* Do not read more than maxlen bytes */
404 available_buffer_len = sizeof(sock->buffer) - sock->buffered_bytes;
405 maxlen_int = maxlen < available_buffer_len ? maxlen : available_buffer_len;
406 if ((r=nr_socket_read(sock->inner, sock->buffer + sock->buffered_bytes,
407 maxlen_int, &bytes_read, 0))) {
408 ABORT(r);
409 }
410
411 sock->buffered_bytes += bytes_read;
412
413 if (http_term = find_http_terminator(sock->buffer, sock->buffered_bytes)) {
414 if ((r = parse_http_response(sock->buffer, http_term, &http_status))) {
415 ABORT(r);
416 }
417
418 /* TODO (bug 1115934): Handle authentication challenges. */
419 if (http_status < 200 || http_status >= 300) {
420 r_log(LOG_GENERIC,LOG_ERR,"nr_socket_proxy_tunnel_read unable to connect %u",
421 http_status);
422 ABORT(R_FAILED);
423 }
424
425 sock->state = PROXY_TUNNEL_CONNECTED;
426
427 ptr = http_term + strlen(END_HEADERS);
428 pending = sock->buffered_bytes - (ptr - sock->buffer);
429
430 if (pending == 0) {
431 ABORT(R_WOULDBLOCK);
432 }
433
434 assert(pending <= maxlen);
435 *len = pending;
436
437 memcpy(buf, ptr, *len);
438 }
439
440 _status=0;
441 abort:
442 if (_status && _status != R_WOULDBLOCK) {
443 sock->state = PROXY_TUNNEL_FAILED;
444 }
445 return(_status);
446 }
447
nr_socket_proxy_tunnel_close(void * obj)448 int nr_socket_proxy_tunnel_close(void *obj)
449 {
450 nr_socket_proxy_tunnel *sock = (nr_socket_proxy_tunnel*)obj;
451
452 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_close");
453
454 if (sock->resolver_handle) {
455 nr_resolver_cancel(sock->config->resolver, sock->resolver_handle);
456 sock->resolver_handle = 0;
457 }
458
459 sock->state = PROXY_TUNNEL_CLOSED;
460
461 return nr_socket_close(sock->inner);
462 }
463
nr_proxy_tunnel_config_create(nr_proxy_tunnel_config ** configpp)464 int nr_proxy_tunnel_config_create(nr_proxy_tunnel_config **configpp)
465 {
466 int _status;
467 nr_proxy_tunnel_config *configp=0;
468
469 r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_create");
470
471 if (!(configp=RCALLOC(sizeof(nr_proxy_tunnel_config))))
472 ABORT(R_NO_MEMORY);
473
474 *configpp=configp;
475 _status=0;
476 abort:
477 return(_status);
478 }
479
nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config ** configpp)480 int nr_proxy_tunnel_config_destroy(nr_proxy_tunnel_config **configpp)
481 {
482 nr_proxy_tunnel_config *configp;
483
484 r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_destroy");
485
486 if (!configpp || !*configpp)
487 return 0;
488
489 configp = *configpp;
490 *configpp = 0;
491
492 RFREE(configp->proxy_host);
493 RFREE(configp->alpn);
494 RFREE(configp);
495
496 return 0;
497 }
498
nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config * config,const char * host,UINT2 port)499 int nr_proxy_tunnel_config_set_proxy(nr_proxy_tunnel_config *config,
500 const char *host, UINT2 port)
501 {
502 char *hostdup;
503
504 r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_proxy %s %d", host, port);
505
506 if (!host) {
507 return R_BAD_ARGS;
508 }
509
510 if (!(hostdup = r_strdup(host))) {
511 return R_NO_MEMORY;
512 }
513
514 if (config->proxy_host) {
515 RFREE(config->proxy_host);
516 }
517
518 config->proxy_host = hostdup;
519 config->proxy_port = port;
520
521 return 0;
522 }
523
nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config * config,nr_resolver * resolver)524 int nr_proxy_tunnel_config_set_resolver(nr_proxy_tunnel_config *config,
525 nr_resolver *resolver)
526 {
527 r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_resolver");
528
529 config->resolver = resolver;
530
531 return 0;
532 }
533
nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config * config,const char * alpn)534 int nr_proxy_tunnel_config_set_alpn(nr_proxy_tunnel_config *config,
535 const char *alpn)
536 {
537 r_log(LOG_GENERIC,LOG_DEBUG,"nr_proxy_tunnel_config_set_alpn");
538
539 if (alpn && (strlen(alpn) > MAX_ALPN_LENGTH)) {
540 return R_BAD_ARGS;
541 }
542
543 if (config->alpn) {
544 RFREE(config->alpn);
545 }
546
547 config->alpn = NULL;
548
549 if (alpn) {
550 char *alpndup = r_strdup(alpn);
551
552 if (!alpndup) {
553 return R_NO_MEMORY;
554 }
555
556 config->alpn = alpndup;
557 }
558
559 return 0;
560 }
561
nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config * config,nr_proxy_tunnel_config ** copypp)562 int nr_proxy_tunnel_config_copy(nr_proxy_tunnel_config *config, nr_proxy_tunnel_config **copypp)
563 {
564 int r,_status;
565 nr_proxy_tunnel_config *copy = 0;
566
567 if ((r=nr_proxy_tunnel_config_create(©)))
568 ABORT(r);
569
570 if ((r=nr_proxy_tunnel_config_set_proxy(copy, config->proxy_host, config->proxy_port)))
571 ABORT(r);
572
573 if ((r=nr_proxy_tunnel_config_set_resolver(copy, config->resolver)))
574 ABORT(r);
575
576 if ((r=nr_proxy_tunnel_config_set_alpn(copy, config->alpn)))
577 ABORT(r);
578
579 *copypp = copy;
580
581 _status=0;
582 abort:
583 if (_status) {
584 nr_proxy_tunnel_config_destroy(©);
585 }
586 return(_status);
587 }
588
589
nr_socket_proxy_tunnel_create(nr_proxy_tunnel_config * config,nr_socket * inner,nr_socket ** socketpp)590 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 nr_socket_proxy_tunnel *sock=0;
596 void *sockv;
597
598 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_create");
599
600 if (!config) {
601 ABORT(R_BAD_ARGS);
602 }
603
604 if (!(sock=RCALLOC(sizeof(nr_socket_proxy_tunnel)))) {
605 ABORT(R_NO_MEMORY);
606 }
607
608 sock->inner = inner;
609
610 if ((r=nr_proxy_tunnel_config_copy(config, &sock->config)))
611 ABORT(r);
612
613 if ((r=nr_socket_create_int(sock, &nr_socket_proxy_tunnel_vtbl, socketpp))) {
614 ABORT(r);
615 }
616
617 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_proxy_tunnel_created");
618
619 _status=0;
620 abort:
621 if (_status) {
622 sockv = sock;
623 nr_socket_proxy_tunnel_destroy(&sockv);
624 }
625 return(_status);
626 }
627
nr_socket_wrapper_factory_proxy_tunnel_wrap(void * obj,nr_socket * inner,nr_socket ** socketpp)628 int nr_socket_wrapper_factory_proxy_tunnel_wrap(void *obj,
629 nr_socket *inner,
630 nr_socket **socketpp)
631 {
632 nr_socket_wrapper_factory_proxy_tunnel *wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)obj;
633
634 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_wrap");
635
636 return nr_socket_proxy_tunnel_create(wrapper->config, inner, socketpp);
637 }
638
639
nr_socket_wrapper_factory_proxy_tunnel_destroy(void ** objpp)640 int nr_socket_wrapper_factory_proxy_tunnel_destroy(void **objpp) {
641 nr_socket_wrapper_factory_proxy_tunnel *wrapper;
642
643 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_destroy");
644
645 if (!objpp || !*objpp)
646 return 0;
647
648 wrapper = (nr_socket_wrapper_factory_proxy_tunnel *)*objpp;
649 *objpp = 0;
650
651 nr_proxy_tunnel_config_destroy(&wrapper->config);
652 RFREE(wrapper);
653
654 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
nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config * config,nr_socket_wrapper_factory ** factory)662 int nr_socket_wrapper_factory_proxy_tunnel_create(nr_proxy_tunnel_config *config,
663 nr_socket_wrapper_factory **factory) {
664 int r,_status;
665 nr_socket_wrapper_factory_proxy_tunnel *wrapper=0;
666 void *wrapperv;
667
668 r_log(LOG_GENERIC,LOG_DEBUG,"nr_socket_wrapper_factory_proxy_tunnel_create");
669
670 if (!(wrapper=RCALLOC(sizeof(nr_socket_wrapper_factory_proxy_tunnel))))
671 ABORT(R_NO_MEMORY);
672
673 if ((r=nr_proxy_tunnel_config_copy(config, &wrapper->config)))
674 ABORT(r);
675
676 if ((r=nr_socket_wrapper_factory_create_int(wrapper, &proxy_tunnel_wrapper_vtbl, factory)))
677 ABORT(r);
678
679 _status=0;
680 abort:
681 if (_status) {
682 wrapperv = wrapper;
683 nr_socket_wrapper_factory_proxy_tunnel_destroy(&wrapperv);
684 }
685 return(_status);
686 }
687