ddd-04-fd-nonblocking.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. #include <sys/poll.h>
  2. #include <openssl/ssl.h>
  3. /*
  4. * Demo 4: Client — Client Creates FD — Nonblocking
  5. * ================================================
  6. *
  7. * This is an example of (part of) an application which uses libssl in an
  8. * asynchronous, nonblocking fashion. The client is responsible for creating the
  9. * socket and passing it to libssl. The functions show all interactions with
  10. * libssl the application makes, and would hypothetically be linked into a
  11. * larger application.
  12. */
  13. typedef struct app_conn_st {
  14. SSL *ssl;
  15. int fd;
  16. int rx_need_tx, tx_need_rx;
  17. } APP_CONN;
  18. /*
  19. * The application is initializing and wants an SSL_CTX which it will use for
  20. * some number of outgoing connections, which it creates in subsequent calls to
  21. * new_conn. The application may also call this function multiple times to
  22. * create multiple SSL_CTX.
  23. */
  24. SSL_CTX *create_ssl_ctx(void)
  25. {
  26. SSL_CTX *ctx;
  27. #ifdef USE_QUIC
  28. ctx = SSL_CTX_new(OSSL_QUIC_client_method());
  29. #else
  30. ctx = SSL_CTX_new(TLS_client_method());
  31. #endif
  32. if (ctx == NULL)
  33. return NULL;
  34. /* Enable trust chain verification. */
  35. SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
  36. /* Load default root CA store. */
  37. if (SSL_CTX_set_default_verify_paths(ctx) == 0) {
  38. SSL_CTX_free(ctx);
  39. return NULL;
  40. }
  41. return ctx;
  42. }
  43. /*
  44. * The application wants to create a new outgoing connection using a given
  45. * SSL_CTX.
  46. *
  47. * hostname is a string like "openssl.org" used for certificate validation.
  48. */
  49. APP_CONN *new_conn(SSL_CTX *ctx, int fd, const char *bare_hostname)
  50. {
  51. APP_CONN *conn;
  52. SSL *ssl;
  53. #ifdef USE_QUIC
  54. static const unsigned char alpn[] = {5, 'd', 'u', 'm', 'm', 'y'};
  55. #endif
  56. conn = calloc(1, sizeof(APP_CONN));
  57. if (conn == NULL)
  58. return NULL;
  59. ssl = conn->ssl = SSL_new(ctx);
  60. if (ssl == NULL) {
  61. free(conn);
  62. return NULL;
  63. }
  64. SSL_set_connect_state(ssl); /* cannot fail */
  65. if (SSL_set_fd(ssl, fd) <= 0) {
  66. SSL_free(ssl);
  67. free(conn);
  68. return NULL;
  69. }
  70. if (SSL_set1_host(ssl, bare_hostname) <= 0) {
  71. SSL_free(ssl);
  72. free(conn);
  73. return NULL;
  74. }
  75. if (SSL_set_tlsext_host_name(ssl, bare_hostname) <= 0) {
  76. SSL_free(ssl);
  77. free(conn);
  78. return NULL;
  79. }
  80. #ifdef USE_QUIC
  81. /* Configure ALPN, which is required for QUIC. */
  82. if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {
  83. /* Note: SSL_set_alpn_protos returns 1 for failure. */
  84. SSL_free(ssl);
  85. free(conn);
  86. return NULL;
  87. }
  88. #endif
  89. conn->fd = fd;
  90. return conn;
  91. }
  92. /*
  93. * Non-blocking transmission.
  94. *
  95. * Returns -1 on error. Returns -2 if the function would block (corresponds to
  96. * EWOULDBLOCK).
  97. */
  98. int tx(APP_CONN *conn, const void *buf, int buf_len)
  99. {
  100. int rc, l;
  101. conn->tx_need_rx = 0;
  102. l = SSL_write(conn->ssl, buf, buf_len);
  103. if (l <= 0) {
  104. rc = SSL_get_error(conn->ssl, l);
  105. switch (rc) {
  106. case SSL_ERROR_WANT_READ:
  107. conn->tx_need_rx = 1;
  108. case SSL_ERROR_WANT_CONNECT:
  109. case SSL_ERROR_WANT_WRITE:
  110. return -2;
  111. default:
  112. return -1;
  113. }
  114. }
  115. return l;
  116. }
  117. /*
  118. * Non-blocking reception.
  119. *
  120. * Returns -1 on error. Returns -2 if the function would block (corresponds to
  121. * EWOULDBLOCK).
  122. */
  123. int rx(APP_CONN *conn, void *buf, int buf_len)
  124. {
  125. int rc, l;
  126. conn->rx_need_tx = 0;
  127. l = SSL_read(conn->ssl, buf, buf_len);
  128. if (l <= 0) {
  129. rc = SSL_get_error(conn->ssl, l);
  130. switch (rc) {
  131. case SSL_ERROR_WANT_WRITE:
  132. conn->rx_need_tx = 1;
  133. case SSL_ERROR_WANT_READ:
  134. return -2;
  135. default:
  136. return -1;
  137. }
  138. }
  139. return l;
  140. }
  141. /*
  142. * The application wants to know a fd it can poll on to determine when the
  143. * SSL state machine needs to be pumped.
  144. *
  145. * If the fd returned has:
  146. *
  147. * POLLIN: SSL_read *may* return data;
  148. * if application does not want to read yet, it should call pump().
  149. *
  150. * POLLOUT: SSL_write *may* accept data
  151. *
  152. * POLLERR: An application should call pump() if it is not likely to call
  153. * SSL_read or SSL_write soon.
  154. *
  155. */
  156. int get_conn_fd(APP_CONN *conn)
  157. {
  158. return conn->fd;
  159. }
  160. /*
  161. * These functions returns zero or more of:
  162. *
  163. * POLLIN: The SSL state machine is interested in socket readability events.
  164. *
  165. * POLLOUT: The SSL state machine is interested in socket writeability events.
  166. *
  167. * POLLERR: The SSL state machine is interested in socket error events.
  168. *
  169. * get_conn_pending_tx returns events which may cause SSL_write to make
  170. * progress and get_conn_pending_rx returns events which may cause SSL_read
  171. * to make progress.
  172. */
  173. int get_conn_pending_tx(APP_CONN *conn)
  174. {
  175. #ifdef USE_QUIC
  176. return (SSL_net_read_desired(conn->ssl) ? POLLIN : 0)
  177. | (SSL_net_write_desired(conn->ssl) ? POLLOUT : 0)
  178. | POLLERR;
  179. #else
  180. return (conn->tx_need_rx ? POLLIN : 0) | POLLOUT | POLLERR;
  181. #endif
  182. }
  183. int get_conn_pending_rx(APP_CONN *conn)
  184. {
  185. return get_conn_pending_tx(conn);
  186. }
  187. #ifdef USE_QUIC
  188. /*
  189. * Returns the number of milliseconds after which some call to libssl must be
  190. * made. Any call (SSL_read/SSL_write/SSL_pump) will do. Returns -1 if there is
  191. * no need for such a call. This may change after the next call
  192. * to libssl.
  193. */
  194. static inline int timeval_to_ms(const struct timeval *t);
  195. int get_conn_pump_timeout(APP_CONN *conn)
  196. {
  197. struct timeval tv;
  198. int is_infinite;
  199. if (!SSL_get_event_timeout(conn->ssl, &tv, &is_infinite))
  200. return -1;
  201. return is_infinite ? -1 : timeval_to_ms(&tv);
  202. }
  203. /*
  204. * Called to advance internals of libssl state machines without having to
  205. * perform an application-level read/write.
  206. */
  207. void pump(APP_CONN *conn)
  208. {
  209. SSL_handle_events(conn->ssl);
  210. }
  211. #endif
  212. /*
  213. * The application wants to close the connection and free bookkeeping
  214. * structures.
  215. */
  216. void teardown(APP_CONN *conn)
  217. {
  218. SSL_shutdown(conn->ssl);
  219. SSL_free(conn->ssl);
  220. free(conn);
  221. }
  222. /*
  223. * The application is shutting down and wants to free a previously
  224. * created SSL_CTX.
  225. */
  226. void teardown_ctx(SSL_CTX *ctx)
  227. {
  228. SSL_CTX_free(ctx);
  229. }
  230. /*
  231. * ============================================================================
  232. * Example driver for the above code. This is just to demonstrate that the code
  233. * works and is not intended to be representative of a real application.
  234. */
  235. #include <sys/types.h>
  236. #include <sys/socket.h>
  237. #include <sys/signal.h>
  238. #ifdef USE_QUIC
  239. # include <sys/time.h>
  240. #endif
  241. #include <netdb.h>
  242. #include <unistd.h>
  243. #include <fcntl.h>
  244. #ifdef USE_QUIC
  245. static inline void ms_to_timeval(struct timeval *t, int ms)
  246. {
  247. t->tv_sec = ms < 0 ? -1 : ms/1000;
  248. t->tv_usec = ms < 0 ? 0 : (ms%1000)*1000;
  249. }
  250. static inline int timeval_to_ms(const struct timeval *t)
  251. {
  252. return t->tv_sec*1000 + t->tv_usec/1000;
  253. }
  254. #endif
  255. int main(int argc, char **argv)
  256. {
  257. int rc, fd = -1, res = 1;
  258. static char tx_msg[300];
  259. const char *tx_p = tx_msg;
  260. char rx_buf[2048];
  261. int l, tx_len;
  262. #ifdef USE_QUIC
  263. struct timeval timeout;
  264. #else
  265. int timeout = 2000 /* ms */;
  266. #endif
  267. APP_CONN *conn = NULL;
  268. struct addrinfo hints = {0}, *result = NULL;
  269. SSL_CTX *ctx = NULL;
  270. #ifdef USE_QUIC
  271. ms_to_timeval(&timeout, 2000);
  272. #endif
  273. if (argc < 3) {
  274. fprintf(stderr, "usage: %s host port\n", argv[0]);
  275. goto fail;
  276. }
  277. tx_len = snprintf(tx_msg, sizeof(tx_msg),
  278. "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", argv[1]);
  279. ctx = create_ssl_ctx();
  280. if (ctx == NULL) {
  281. fprintf(stderr, "cannot create SSL context\n");
  282. goto fail;
  283. }
  284. hints.ai_family = AF_INET;
  285. hints.ai_socktype = SOCK_STREAM;
  286. hints.ai_flags = AI_PASSIVE;
  287. rc = getaddrinfo(argv[1], argv[2], &hints, &result);
  288. if (rc < 0) {
  289. fprintf(stderr, "cannot resolve\n");
  290. goto fail;
  291. }
  292. signal(SIGPIPE, SIG_IGN);
  293. #ifdef USE_QUIC
  294. fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  295. #else
  296. fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  297. #endif
  298. if (fd < 0) {
  299. fprintf(stderr, "cannot create socket\n");
  300. goto fail;
  301. }
  302. rc = connect(fd, result->ai_addr, result->ai_addrlen);
  303. if (rc < 0) {
  304. fprintf(stderr, "cannot connect\n");
  305. goto fail;
  306. }
  307. rc = fcntl(fd, F_SETFL, O_NONBLOCK);
  308. if (rc < 0) {
  309. fprintf(stderr, "cannot make socket nonblocking\n");
  310. goto fail;
  311. }
  312. conn = new_conn(ctx, fd, argv[1]);
  313. if (conn == NULL) {
  314. fprintf(stderr, "cannot establish connection\n");
  315. goto fail;
  316. }
  317. /* TX */
  318. while (tx_len != 0) {
  319. l = tx(conn, tx_p, tx_len);
  320. if (l > 0) {
  321. tx_p += l;
  322. tx_len -= l;
  323. } else if (l == -1) {
  324. fprintf(stderr, "tx error\n");
  325. goto fail;
  326. } else if (l == -2) {
  327. #ifdef USE_QUIC
  328. struct timeval start, now, deadline, t;
  329. #endif
  330. struct pollfd pfd = {0};
  331. #ifdef USE_QUIC
  332. ms_to_timeval(&t, get_conn_pump_timeout(conn));
  333. if (t.tv_sec < 0 || timercmp(&t, &timeout, >))
  334. t = timeout;
  335. gettimeofday(&start, NULL);
  336. timeradd(&start, &timeout, &deadline);
  337. #endif
  338. pfd.fd = get_conn_fd(conn);
  339. pfd.events = get_conn_pending_tx(conn);
  340. #ifdef USE_QUIC
  341. if (poll(&pfd, 1, timeval_to_ms(&t)) == 0)
  342. #else
  343. if (poll(&pfd, 1, timeout) == 0)
  344. #endif
  345. {
  346. #ifdef USE_QUIC
  347. pump(conn);
  348. gettimeofday(&now, NULL);
  349. if (timercmp(&now, &deadline, >=))
  350. #endif
  351. {
  352. fprintf(stderr, "tx timeout\n");
  353. goto fail;
  354. }
  355. }
  356. }
  357. }
  358. /* RX */
  359. for (;;) {
  360. l = rx(conn, rx_buf, sizeof(rx_buf));
  361. if (l > 0) {
  362. fwrite(rx_buf, 1, l, stdout);
  363. } else if (l == -1) {
  364. break;
  365. } else if (l == -2) {
  366. #ifdef USE_QUIC
  367. struct timeval start, now, deadline, t;
  368. #endif
  369. struct pollfd pfd = {0};
  370. #ifdef USE_QUIC
  371. ms_to_timeval(&t, get_conn_pump_timeout(conn));
  372. if (t.tv_sec < 0 || timercmp(&t, &timeout, >))
  373. t = timeout;
  374. gettimeofday(&start, NULL);
  375. timeradd(&start, &timeout, &deadline);
  376. #endif
  377. pfd.fd = get_conn_fd(conn);
  378. pfd.events = get_conn_pending_rx(conn);
  379. #ifdef USE_QUIC
  380. if (poll(&pfd, 1, timeval_to_ms(&t)) == 0)
  381. #else
  382. if (poll(&pfd, 1, timeout) == 0)
  383. #endif
  384. {
  385. #ifdef USE_QUIC
  386. pump(conn);
  387. gettimeofday(&now, NULL);
  388. if (timercmp(&now, &deadline, >=))
  389. #endif
  390. {
  391. fprintf(stderr, "rx timeout\n");
  392. goto fail;
  393. }
  394. }
  395. }
  396. }
  397. res = 0;
  398. fail:
  399. if (conn != NULL)
  400. teardown(conn);
  401. if (ctx != NULL)
  402. teardown_ctx(ctx);
  403. if (result != NULL)
  404. freeaddrinfo(result);
  405. return res;
  406. }