xref: /openssl/doc/designs/ddd/ddd-06-mem-uv.c (revision d1338fcf)
1 #include <sys/poll.h>
2 #include <openssl/ssl.h>
3 #include <uv.h>
4 #include <assert.h>
5 #ifdef USE_QUIC
6 # include <sys/time.h>
7 #endif
8 
9 typedef struct app_conn_st APP_CONN;
10 typedef struct upper_write_op_st UPPER_WRITE_OP;
11 typedef struct lower_write_op_st LOWER_WRITE_OP;
12 
13 typedef void (app_connect_cb)(APP_CONN *conn, int status, void *arg);
14 typedef void (app_write_cb)(APP_CONN *conn, int status, void *arg);
15 typedef void (app_read_cb)(APP_CONN *conn, void *buf, size_t buf_len, void *arg);
16 
17 #ifdef USE_QUIC
18 static void set_timer(APP_CONN *conn);
19 #else
20 static void tcp_connect_done(uv_connect_t *tcp_connect, int status);
21 #endif
22 static void net_connect_fail_close_done(uv_handle_t *handle);
23 static int handshake_ssl(APP_CONN *conn);
24 static void flush_write_buf(APP_CONN *conn);
25 static void set_rx(APP_CONN *conn);
26 static int try_write(APP_CONN *conn, UPPER_WRITE_OP *op);
27 static void handle_pending_writes(APP_CONN *conn);
28 static int write_deferred(APP_CONN *conn, const void *buf, size_t buf_len, app_write_cb *cb, void *arg);
29 static void teardown_continued(uv_handle_t *handle);
30 static int setup_ssl(APP_CONN *conn, const char *hostname);
31 
32 #ifdef USE_QUIC
timeval_to_ms(const struct timeval * t)33 static inline int timeval_to_ms(const struct timeval *t)
34 {
35     return t->tv_sec*1000 + t->tv_usec/1000;
36 }
37 #endif
38 
39 /*
40  * Structure to track an application-level write request. Only created
41  * if SSL_write does not accept the data immediately, typically because
42  * it is in WANT_READ.
43  */
44 struct upper_write_op_st {
45     struct upper_write_op_st   *prev, *next;
46     const uint8_t              *buf;
47     size_t                      buf_len, written;
48     APP_CONN                   *conn;
49     app_write_cb               *cb;
50     void                       *cb_arg;
51 };
52 
53 /*
54  * Structure to track a network-level write request.
55  */
56 struct lower_write_op_st {
57 #ifdef USE_QUIC
58     uv_udp_send_t   w;
59 #else
60     uv_write_t      w;
61 #endif
62     uv_buf_t        b;
63     uint8_t        *buf;
64     APP_CONN       *conn;
65 };
66 
67 /*
68  * Application connection object.
69  */
70 struct app_conn_st {
71     SSL_CTX        *ctx;
72     SSL            *ssl;
73     BIO            *net_bio;
74 #ifdef USE_QUIC
75     uv_udp_t        udp;
76     uv_timer_t      timer;
77 #else
78     uv_stream_t    *stream;
79     uv_tcp_t        tcp;
80     uv_connect_t    tcp_connect;
81 #endif
82     app_connect_cb *app_connect_cb;   /* called once handshake is done */
83     void           *app_connect_arg;
84     app_read_cb    *app_read_cb;      /* application's on-RX callback */
85     void           *app_read_arg;
86     const char     *hostname;
87     char            init_handshake, done_handshake, closed;
88     char           *teardown_done;
89 
90     UPPER_WRITE_OP *pending_upper_write_head, *pending_upper_write_tail;
91 };
92 
93 /*
94  * The application is initializing and wants an SSL_CTX which it will use for
95  * some number of outgoing connections, which it creates in subsequent calls to
96  * new_conn. The application may also call this function multiple times to
97  * create multiple SSL_CTX.
98  */
create_ssl_ctx(void)99 SSL_CTX *create_ssl_ctx(void)
100 {
101     SSL_CTX *ctx;
102 
103 #ifdef USE_QUIC
104     ctx = SSL_CTX_new(OSSL_QUIC_client_method());
105 #else
106     ctx = SSL_CTX_new(TLS_client_method());
107 #endif
108     if (ctx == NULL)
109         return NULL;
110 
111     /* Enable trust chain verification. */
112     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
113 
114     /* Load default root CA store. */
115     if (SSL_CTX_set_default_verify_paths(ctx) == 0) {
116         SSL_CTX_free(ctx);
117         return NULL;
118     }
119 
120     return ctx;
121 }
122 
123 /*
124  * The application wants to create a new outgoing connection using a given
125  * SSL_CTX. An outgoing TCP connection is started and the callback is called
126  * asynchronously when the TLS handshake is complete.
127  *
128  * hostname is a string like "openssl.org" used for certificate validation.
129  */
130 
new_conn(SSL_CTX * ctx,const char * hostname,struct sockaddr * sa,socklen_t sa_len,app_connect_cb * cb,void * arg)131 APP_CONN *new_conn(SSL_CTX *ctx, const char *hostname,
132                    struct sockaddr *sa, socklen_t sa_len,
133                    app_connect_cb *cb, void *arg)
134 {
135     int rc;
136     APP_CONN *conn = NULL;
137 
138     conn = calloc(1, sizeof(APP_CONN));
139     if (!conn)
140         return NULL;
141 
142 #ifdef USE_QUIC
143     uv_udp_init(uv_default_loop(), &conn->udp);
144     conn->udp.data = conn;
145 
146     uv_timer_init(uv_default_loop(), &conn->timer);
147     conn->timer.data = conn;
148 #else
149     uv_tcp_init(uv_default_loop(), &conn->tcp);
150     conn->tcp.data = conn;
151 
152     conn->stream            = (uv_stream_t *)&conn->tcp;
153 #endif
154 
155     conn->app_connect_cb    = cb;
156     conn->app_connect_arg   = arg;
157 #ifdef USE_QUIC
158     rc = uv_udp_connect(&conn->udp, sa);
159 #else
160     conn->tcp_connect.data  = conn;
161     rc = uv_tcp_connect(&conn->tcp_connect, &conn->tcp, sa, tcp_connect_done);
162 #endif
163     if (rc < 0) {
164 #ifdef USE_QUIC
165         uv_close((uv_handle_t *)&conn->udp, net_connect_fail_close_done);
166 #else
167         uv_close((uv_handle_t *)&conn->tcp, net_connect_fail_close_done);
168 #endif
169         return NULL;
170     }
171 
172     conn->ctx       = ctx;
173     conn->hostname  = hostname;
174 
175 #ifdef USE_QUIC
176     rc = setup_ssl(conn, hostname);
177     if (rc < 0) {
178         uv_close((uv_handle_t *)&conn->udp, net_connect_fail_close_done);
179         return NULL;
180     }
181 #endif
182 
183     return conn;
184 }
185 
186 /*
187  * The application wants to start reading from the SSL stream.
188  * The callback is called whenever data is available.
189  */
app_read_start(APP_CONN * conn,app_read_cb * cb,void * arg)190 int app_read_start(APP_CONN *conn, app_read_cb *cb, void *arg)
191 {
192     conn->app_read_cb  = cb;
193     conn->app_read_arg = arg;
194     set_rx(conn);
195     return 0;
196 }
197 
198 /*
199  * The application wants to write. The callback is called once the
200  * write is complete. The callback should free the buffer.
201  */
app_write(APP_CONN * conn,const void * buf,size_t buf_len,app_write_cb * cb,void * arg)202 int app_write(APP_CONN *conn, const void *buf, size_t buf_len, app_write_cb *cb, void *arg)
203 {
204     write_deferred(conn, buf, buf_len, cb, arg);
205     handle_pending_writes(conn);
206     return buf_len;
207 }
208 
209 /*
210  * The application wants to close the connection and free bookkeeping
211  * structures.
212  */
teardown(APP_CONN * conn)213 void teardown(APP_CONN *conn)
214 {
215     char teardown_done = 0;
216 
217     if (conn == NULL)
218         return;
219 
220     BIO_free_all(conn->net_bio);
221     SSL_free(conn->ssl);
222 
223 #ifndef USE_QUIC
224     uv_cancel((uv_req_t *)&conn->tcp_connect);
225 #endif
226 
227     conn->teardown_done = &teardown_done;
228 #ifdef USE_QUIC
229     uv_close((uv_handle_t *)&conn->udp, teardown_continued);
230     uv_close((uv_handle_t *)&conn->timer, teardown_continued);
231 #else
232     uv_close((uv_handle_t *)conn->stream, teardown_continued);
233 #endif
234 
235     /* Just wait synchronously until teardown completes. */
236 #ifdef USE_QUIC
237     while (teardown_done < 2)
238 #else
239     while (!teardown_done)
240 #endif
241         uv_run(uv_default_loop(), UV_RUN_DEFAULT);
242 }
243 
244 /*
245  * The application is shutting down and wants to free a previously
246  * created SSL_CTX.
247  */
teardown_ctx(SSL_CTX * ctx)248 void teardown_ctx(SSL_CTX *ctx)
249 {
250     SSL_CTX_free(ctx);
251 }
252 
253 /*
254  * ============================================================================
255  * Internal implementation functions.
256  */
enqueue_upper_write_op(APP_CONN * conn,UPPER_WRITE_OP * op)257 static void enqueue_upper_write_op(APP_CONN *conn, UPPER_WRITE_OP *op)
258 {
259     op->prev = conn->pending_upper_write_tail;
260     if (op->prev)
261         op->prev->next = op;
262 
263     conn->pending_upper_write_tail = op;
264     if (conn->pending_upper_write_head == NULL)
265         conn->pending_upper_write_head = op;
266 }
267 
dequeue_upper_write_op(APP_CONN * conn)268 static void dequeue_upper_write_op(APP_CONN *conn)
269 {
270     if (conn->pending_upper_write_head == NULL)
271         return;
272 
273     if (conn->pending_upper_write_head->next == NULL) {
274         conn->pending_upper_write_head = NULL;
275         conn->pending_upper_write_tail = NULL;
276     } else {
277         conn->pending_upper_write_head = conn->pending_upper_write_head->next;
278         conn->pending_upper_write_head->prev = NULL;
279     }
280 }
281 
net_read_alloc(uv_handle_t * handle,size_t suggested_size,uv_buf_t * buf)282 static void net_read_alloc(uv_handle_t *handle,
283                            size_t suggested_size, uv_buf_t *buf)
284 {
285 #ifdef USE_QUIC
286     if (suggested_size < 1472)
287         suggested_size = 1472;
288 #endif
289 
290     buf->base = malloc(suggested_size);
291     buf->len  = suggested_size;
292 }
293 
on_rx_push(APP_CONN * conn)294 static void on_rx_push(APP_CONN *conn)
295 {
296     int srd, rc;
297     int buf_len = 4096;
298 
299     do {
300         if (!conn->app_read_cb)
301             return;
302 
303         void *buf = malloc(buf_len);
304         if (!buf)
305             return;
306 
307         srd = SSL_read(conn->ssl, buf, buf_len);
308         flush_write_buf(conn);
309         if (srd <= 0) {
310             rc = SSL_get_error(conn->ssl, srd);
311             if (rc == SSL_ERROR_WANT_READ) {
312                 free(buf);
313                 return;
314             }
315         }
316 
317         conn->app_read_cb(conn, buf, srd, conn->app_read_arg);
318     } while (srd == buf_len);
319 }
320 
net_error(APP_CONN * conn)321 static void net_error(APP_CONN *conn)
322 {
323     conn->closed = 1;
324     set_rx(conn);
325 
326     if (conn->app_read_cb)
327         conn->app_read_cb(conn, NULL, 0, conn->app_read_arg);
328 }
329 
handle_pending_writes(APP_CONN * conn)330 static void handle_pending_writes(APP_CONN *conn)
331 {
332     int rc;
333 
334     if (conn->pending_upper_write_head == NULL)
335         return;
336 
337     do {
338         UPPER_WRITE_OP *op = conn->pending_upper_write_head;
339         rc = try_write(conn, op);
340         if (rc <= 0)
341             break;
342 
343         dequeue_upper_write_op(conn);
344         free(op);
345     } while (conn->pending_upper_write_head != NULL);
346 
347     set_rx(conn);
348 }
349 
350 #ifdef USE_QUIC
net_read_done(uv_udp_t * stream,ssize_t nr,const uv_buf_t * buf,const struct sockaddr * addr,unsigned int flags)351 static void net_read_done(uv_udp_t *stream, ssize_t nr, const uv_buf_t *buf,
352                           const struct sockaddr *addr, unsigned int flags)
353 #else
354 static void net_read_done(uv_stream_t *stream, ssize_t nr, const uv_buf_t *buf)
355 #endif
356 {
357     int rc;
358     APP_CONN *conn = (APP_CONN *)stream->data;
359 
360     if (nr < 0) {
361         free(buf->base);
362         net_error(conn);
363         return;
364     }
365 
366     if (nr > 0) {
367         int wr = BIO_write(conn->net_bio, buf->base, nr);
368         assert(wr == nr);
369     }
370 
371     free(buf->base);
372 
373     if (!conn->done_handshake) {
374         rc = handshake_ssl(conn);
375         if (rc < 0) {
376             fprintf(stderr, "handshake error: %d\n", rc);
377             return;
378         }
379 
380         if (!conn->done_handshake)
381             return;
382     }
383 
384     handle_pending_writes(conn);
385     on_rx_push(conn);
386 }
387 
set_rx(APP_CONN * conn)388 static void set_rx(APP_CONN *conn)
389 {
390 #ifdef USE_QUIC
391     if (!conn->closed)
392         uv_udp_recv_start(&conn->udp, net_read_alloc, net_read_done);
393     else
394         uv_udp_recv_stop(&conn->udp);
395 #else
396     if (!conn->closed && (conn->app_read_cb || (!conn->done_handshake && conn->init_handshake) || conn->pending_upper_write_head != NULL))
397         uv_read_start(conn->stream, net_read_alloc, net_read_done);
398     else
399         uv_read_stop(conn->stream);
400 #endif
401 }
402 
403 #ifdef USE_QUIC
net_write_done(uv_udp_send_t * req,int status)404 static void net_write_done(uv_udp_send_t *req, int status)
405 #else
406 static void net_write_done(uv_write_t *req, int status)
407 #endif
408 {
409     LOWER_WRITE_OP *op = (LOWER_WRITE_OP *)req->data;
410     APP_CONN *conn = op->conn;
411 
412     if (status < 0) {
413         fprintf(stderr, "UV write failed %d\n", status);
414         return;
415     }
416 
417     free(op->buf);
418     free(op);
419 
420     flush_write_buf(conn);
421 }
422 
flush_write_buf(APP_CONN * conn)423 static void flush_write_buf(APP_CONN *conn)
424 {
425     int rc, rd;
426     LOWER_WRITE_OP *op;
427     uint8_t *buf;
428 
429     buf = malloc(4096);
430     if (!buf)
431         return;
432 
433     rd = BIO_read(conn->net_bio, buf, 4096);
434     if (rd <= 0) {
435         free(buf);
436         return;
437     }
438 
439     op = calloc(1, sizeof(LOWER_WRITE_OP));
440     if (!op)
441         return;
442 
443     op->buf     = buf;
444     op->conn    = conn;
445     op->w.data  = op;
446     op->b.base  = (char *)buf;
447     op->b.len   = rd;
448 
449 #ifdef USE_QUIC
450     rc = uv_udp_send(&op->w, &conn->udp, &op->b, 1, NULL, net_write_done);
451 #else
452     rc = uv_write(&op->w, conn->stream, &op->b, 1, net_write_done);
453 #endif
454     if (rc < 0) {
455         free(buf);
456         free(op);
457         fprintf(stderr, "UV write failed\n");
458         return;
459     }
460 }
461 
handshake_done_ssl(APP_CONN * conn)462 static void handshake_done_ssl(APP_CONN *conn)
463 {
464 #ifdef USE_QUIC
465     set_timer(conn);
466 #endif
467     conn->app_connect_cb(conn, 0, conn->app_connect_arg);
468 }
469 
handshake_ssl(APP_CONN * conn)470 static int handshake_ssl(APP_CONN *conn)
471 {
472     int rc, rcx;
473 
474     conn->init_handshake = 1;
475 
476     rc = SSL_do_handshake(conn->ssl);
477     if (rc > 0) {
478         conn->done_handshake = 1;
479         handshake_done_ssl(conn);
480         set_rx(conn);
481         return 0;
482     }
483 
484     flush_write_buf(conn);
485     rcx = SSL_get_error(conn->ssl, rc);
486     if (rcx == SSL_ERROR_WANT_READ) {
487         set_rx(conn);
488         return 0;
489     }
490 
491     fprintf(stderr, "Handshake error: %d\n", rcx);
492     return -rcx;
493 }
494 
setup_ssl(APP_CONN * conn,const char * hostname)495 static int setup_ssl(APP_CONN *conn, const char *hostname)
496 {
497     BIO *internal_bio = NULL, *net_bio = NULL;
498     SSL *ssl = NULL;
499 #ifdef USE_QUIC
500     static const unsigned char alpn[] = {5, 'd', 'u', 'm', 'm', 'y'};
501 #endif
502 
503     ssl = SSL_new(conn->ctx);
504     if (!ssl)
505         return -1;
506 
507     SSL_set_connect_state(ssl);
508 
509 #ifdef USE_QUIC
510     if (BIO_new_bio_dgram_pair(&internal_bio, 0, &net_bio, 0) <= 0) {
511         SSL_free(ssl);
512         return -1;
513     }
514 #else
515     if (BIO_new_bio_pair(&internal_bio, 0, &net_bio, 0) <= 0) {
516         SSL_free(ssl);
517         return -1;
518     }
519 #endif
520 
521     SSL_set_bio(ssl, internal_bio, internal_bio);
522 
523     if (SSL_set1_host(ssl, hostname) <= 0) {
524         SSL_free(ssl);
525         return -1;
526     }
527 
528     if (SSL_set_tlsext_host_name(ssl, hostname) <= 0) {
529         SSL_free(ssl);
530         return -1;
531     }
532 
533 #ifdef USE_QUIC
534     /* Configure ALPN, which is required for QUIC. */
535     if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {
536         /* Note: SSL_set_alpn_protos returns 1 for failure. */
537         SSL_free(ssl);
538         return -1;
539     }
540 #endif
541 
542     conn->net_bio             = net_bio;
543     conn->ssl                 = ssl;
544     return handshake_ssl(conn);
545 }
546 
547 #ifndef USE_QUIC
tcp_connect_done(uv_connect_t * tcp_connect,int status)548 static void tcp_connect_done(uv_connect_t *tcp_connect, int status)
549 {
550     int rc;
551     APP_CONN *conn = (APP_CONN *)tcp_connect->data;
552 
553     if (status < 0) {
554         uv_stop(uv_default_loop());
555         return;
556     }
557 
558     rc = setup_ssl(conn, conn->hostname);
559     if (rc < 0) {
560         fprintf(stderr, "cannot init SSL\n");
561         uv_stop(uv_default_loop());
562         return;
563     }
564 }
565 #endif
566 
net_connect_fail_close_done(uv_handle_t * handle)567 static void net_connect_fail_close_done(uv_handle_t *handle)
568 {
569     APP_CONN *conn = (APP_CONN *)handle->data;
570 
571     free(conn);
572 }
573 
574 #ifdef USE_QUIC
575 
timer_done(uv_timer_t * timer)576 static void timer_done(uv_timer_t *timer)
577 {
578     APP_CONN *conn = (APP_CONN *)timer->data;
579 
580     SSL_handle_events(conn->ssl);
581     handle_pending_writes(conn);
582     flush_write_buf(conn);
583     set_rx(conn);
584     set_timer(conn); /* repeat timer */
585 }
586 
set_timer(APP_CONN * conn)587 static void set_timer(APP_CONN *conn)
588 {
589     struct timeval tv;
590     int ms, is_infinite;
591 
592     if (!SSL_get_event_timeout(conn->ssl, &tv, &is_infinite))
593         return;
594 
595     ms = is_infinite ? -1 : timeval_to_ms(&tv);
596     if (ms > 0)
597         uv_timer_start(&conn->timer, timer_done, ms, 0);
598 }
599 
600 #endif
601 
try_write(APP_CONN * conn,UPPER_WRITE_OP * op)602 static int try_write(APP_CONN *conn, UPPER_WRITE_OP *op)
603 {
604     int rc, rcx;
605     size_t written = op->written;
606 
607     while (written < op->buf_len) {
608         rc = SSL_write(conn->ssl, op->buf + written, op->buf_len - written);
609         if (rc <= 0) {
610             rcx = SSL_get_error(conn->ssl, rc);
611             if (rcx == SSL_ERROR_WANT_READ) {
612                 op->written = written;
613                 return 0;
614             } else {
615                 if (op->cb != NULL)
616                     op->cb(conn, -rcx, op->cb_arg);
617                 return 1; /* op should be freed */
618             }
619         }
620 
621         written += rc;
622     }
623 
624     if (op->cb != NULL)
625         op->cb(conn, 0, op->cb_arg);
626 
627     flush_write_buf(conn);
628     return 1; /* op should be freed */
629 }
630 
write_deferred(APP_CONN * conn,const void * buf,size_t buf_len,app_write_cb * cb,void * arg)631 static int write_deferred(APP_CONN *conn, const void *buf, size_t buf_len, app_write_cb *cb, void *arg)
632 {
633     UPPER_WRITE_OP *op = calloc(1, sizeof(UPPER_WRITE_OP));
634     if (!op)
635         return -1;
636 
637     op->buf     = buf;
638     op->buf_len = buf_len;
639     op->conn    = conn;
640     op->cb      = cb;
641     op->cb_arg  = arg;
642 
643     enqueue_upper_write_op(conn, op);
644     set_rx(conn);
645     flush_write_buf(conn);
646     return buf_len;
647 }
648 
teardown_continued(uv_handle_t * handle)649 static void teardown_continued(uv_handle_t *handle)
650 {
651     APP_CONN *conn = (APP_CONN *)handle->data;
652     UPPER_WRITE_OP *op, *next_op;
653     char *teardown_done = conn->teardown_done;
654 
655 #ifdef USE_QUIC
656     if (++*teardown_done < 2)
657         return;
658 #endif
659 
660     for (op=conn->pending_upper_write_head; op; op=next_op) {
661         next_op = op->next;
662         free(op);
663     }
664 
665     free(conn);
666 #ifndef USE_QUIC
667     *teardown_done = 1;
668 #endif
669 }
670 
671 /*
672  * ============================================================================
673  * Example driver for the above code. This is just to demonstrate that the code
674  * works and is not intended to be representative of a real application.
675  */
post_read(APP_CONN * conn,void * buf,size_t buf_len,void * arg)676 static void post_read(APP_CONN *conn, void *buf, size_t buf_len, void *arg)
677 {
678     if (!buf_len) {
679         free(buf);
680         uv_stop(uv_default_loop());
681         return;
682     }
683 
684     fwrite(buf, 1, buf_len, stdout);
685     free(buf);
686 }
687 
post_write_get(APP_CONN * conn,int status,void * arg)688 static void post_write_get(APP_CONN *conn, int status, void *arg)
689 {
690     if (status < 0) {
691         fprintf(stderr, "write failed: %d\n", status);
692         return;
693     }
694 
695     app_read_start(conn, post_read, NULL);
696 }
697 
698 char tx_msg[300];
699 int mlen;
700 
post_connect(APP_CONN * conn,int status,void * arg)701 static void post_connect(APP_CONN *conn, int status, void *arg)
702 {
703     int wr;
704 
705     if (status < 0) {
706         fprintf(stderr, "failed to connect: %d\n", status);
707         uv_stop(uv_default_loop());
708         return;
709     }
710 
711     wr = app_write(conn, tx_msg, mlen, post_write_get, NULL);
712     if (wr < mlen) {
713         fprintf(stderr, "error writing request");
714         return;
715     }
716 }
717 
main(int argc,char ** argv)718 int main(int argc, char **argv)
719 {
720     int rc = 1;
721     SSL_CTX *ctx = NULL;
722     APP_CONN *conn = NULL;
723     struct addrinfo hints = {0}, *result = NULL;
724 
725     if (argc < 3) {
726         fprintf(stderr, "usage: %s host port\n", argv[0]);
727         goto fail;
728     }
729 
730     mlen = snprintf(tx_msg, sizeof(tx_msg),
731                     "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", argv[1]);
732 
733     ctx = create_ssl_ctx();
734     if (!ctx)
735         goto fail;
736 
737     hints.ai_family     = AF_INET;
738     hints.ai_socktype   = SOCK_STREAM;
739     hints.ai_flags      = AI_PASSIVE;
740     rc = getaddrinfo(argv[1], argv[2], &hints, &result);
741     if (rc < 0) {
742         fprintf(stderr, "cannot resolve\n");
743         goto fail;
744     }
745 
746     conn = new_conn(ctx, argv[1], result->ai_addr, result->ai_addrlen, post_connect, NULL);
747     if (!conn)
748         goto fail;
749 
750     uv_run(uv_default_loop(), UV_RUN_DEFAULT);
751 
752     rc = 0;
753 fail:
754     teardown(conn);
755     freeaddrinfo(result);
756     uv_loop_close(uv_default_loop());
757     teardown_ctx(ctx);
758 }
759