ddd-06-mem-uv.c 18 KB

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