1
0

ossl-nghttp3-demo-server.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385
  1. /*
  2. * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <assert.h>
  10. #include <netinet/in.h>
  11. #include <nghttp3/nghttp3.h>
  12. #include <openssl/err.h>
  13. #include <openssl/quic.h>
  14. #include <openssl/ssl.h>
  15. #include <unistd.h>
  16. #include <sys/stat.h>
  17. #include <fcntl.h>
  18. #include <sys/socket.h>
  19. #ifndef PATH_MAX
  20. # define PATH_MAX 255
  21. #endif
  22. #define nghttp3_arraylen(A) (sizeof(A) / sizeof(*(A)))
  23. /* The crappy test wants 20 bytes */
  24. #define NULL_PAYLOAD "12345678901234567890"
  25. static uint8_t *nulldata = (uint8_t *) NULL_PAYLOAD;
  26. static size_t nulldata_sz = sizeof(NULL_PAYLOAD) - 1;
  27. /* The nghttp3 variable we need in the main part and read_from_ssl_ids */
  28. static nghttp3_settings settings;
  29. static const nghttp3_mem *mem;
  30. static nghttp3_callbacks callbacks = {0};
  31. /* 3 streams created by the server and 4 by the client (one is bidi) */
  32. struct ssl_id {
  33. SSL *s; /* the stream openssl uses in SSL_read(), SSL_write etc */
  34. uint64_t id; /* the stream identifier the nghttp3 uses */
  35. int status; /* 0 or one the below status and origin */
  36. };
  37. /* status and origin of the streams the possible values are: */
  38. #define CLIENTUNIOPEN 0x01 /* unidirectional open by the client (2, 6 and 10) */
  39. #define CLIENTCLOSED 0x02 /* closed by the client */
  40. #define CLIENTBIDIOPEN 0x04 /* bidirectional open by the client (something like 0, 4, 8 ...) */
  41. #define SERVERUNIOPEN 0x08 /* unidirectional open by the server (3, 7 and 11) */
  42. #define SERVERCLOSED 0x10 /* closed by the server (us) */
  43. #define TOBEREMOVED 0x20 /* marked for removing in read_from_ssl_ids, */
  44. /* it will be removed after processing all events */
  45. #define ISLISTENER 0x40 /* the stream is a listener from SSL_new_listener() */
  46. #define ISCONNECTION 0x80 /* the stream is a connection from SSL_accept_connection() */
  47. #define MAXSSL_IDS 20
  48. #define MAXURL 255
  49. struct h3ssl {
  50. struct ssl_id ssl_ids[MAXSSL_IDS];
  51. int end_headers_received; /* h3 header received call back called */
  52. int datadone; /* h3 has given openssl all the data of the response */
  53. int has_uni; /* we have the 3 uni directional stream needed */
  54. int close_done; /* connection begins terminating EVENT_EC */
  55. int close_wait; /* we are waiting for a close or a new request */
  56. int done; /* connection terminated EVENT_ECD, after EVENT_EC */
  57. int new_conn; /* a new connection has been received */
  58. int received_from_two; /* workaround for -607 on nghttp3_conn_read_stream on stream 2 */
  59. int restart; /* new request/response cycle started */
  60. uint64_t id_bidi; /* the id of the stream used to read request and send response */
  61. char *fileprefix; /* prefix of the directory to fetch files from */
  62. char url[MAXURL]; /* url to serve the request */
  63. uint8_t *ptr_data; /* pointer to the data to send */
  64. size_t ldata; /* amount of bytes to send */
  65. int offset_data; /* offset to next data to send */
  66. };
  67. static void make_nv(nghttp3_nv *nv, const char *name, const char *value)
  68. {
  69. nv->name = (uint8_t *)name;
  70. nv->value = (uint8_t *)value;
  71. nv->namelen = strlen(name);
  72. nv->valuelen = strlen(value);
  73. nv->flags = NGHTTP3_NV_FLAG_NONE;
  74. }
  75. static void init_ids(struct h3ssl *h3ssl)
  76. {
  77. struct ssl_id *ssl_ids;
  78. int i;
  79. char *prior_fileprefix = h3ssl->fileprefix;
  80. if (h3ssl->ptr_data != NULL && h3ssl->ptr_data != nulldata)
  81. free(h3ssl->ptr_data);
  82. memset(h3ssl, 0, sizeof(struct h3ssl));
  83. ssl_ids = h3ssl->ssl_ids;
  84. for (i = 0; i < MAXSSL_IDS; i++)
  85. ssl_ids[i].id = UINT64_MAX;
  86. h3ssl->id_bidi = UINT64_MAX;
  87. /* restore the fileprefix */
  88. h3ssl->fileprefix = prior_fileprefix;
  89. }
  90. static void reuse_h3ssl(struct h3ssl *h3ssl)
  91. {
  92. h3ssl->end_headers_received = 0;
  93. h3ssl->datadone = 0;
  94. h3ssl->close_done = 0;
  95. h3ssl->close_wait = 0;
  96. h3ssl->done = 0;
  97. memset(h3ssl->url, '\0', sizeof(h3ssl->url));
  98. if (h3ssl->ptr_data != NULL && h3ssl->ptr_data != nulldata)
  99. free(h3ssl->ptr_data);
  100. h3ssl->ptr_data = NULL;
  101. h3ssl->offset_data = 0;
  102. h3ssl->ldata = 0;
  103. }
  104. static void add_id_status(uint64_t id, SSL *ssl, struct h3ssl *h3ssl, int status)
  105. {
  106. struct ssl_id *ssl_ids;
  107. int i;
  108. ssl_ids = h3ssl->ssl_ids;
  109. for (i = 0; i < MAXSSL_IDS; i++) {
  110. if (ssl_ids[i].s == NULL) {
  111. ssl_ids[i].s = ssl;
  112. ssl_ids[i].id = id;
  113. ssl_ids[i].status = status;
  114. return;
  115. }
  116. }
  117. printf("Oops too many streams to add!!!\n");
  118. exit(1);
  119. }
  120. static void add_id(uint64_t id, SSL *ssl, struct h3ssl *h3ssl)
  121. {
  122. add_id_status(id, ssl, h3ssl, 0);
  123. }
  124. /* Add listener and connection */
  125. static void add_ids_listener(SSL *ssl, struct h3ssl *h3ssl)
  126. {
  127. add_id_status(UINT64_MAX, ssl, h3ssl, ISLISTENER);
  128. }
  129. static void add_ids_connection(struct h3ssl *h3ssl, SSL *ssl)
  130. {
  131. add_id_status(UINT64_MAX, ssl, h3ssl, ISCONNECTION);
  132. }
  133. static SSL *get_ids_connection(struct h3ssl *h3ssl)
  134. {
  135. struct ssl_id *ssl_ids;
  136. int i;
  137. ssl_ids = h3ssl->ssl_ids;
  138. for (i = 0; i < MAXSSL_IDS; i++) {
  139. if (ssl_ids[i].status & ISCONNECTION) {
  140. printf("get_ids_connection\n");
  141. return ssl_ids[i].s;
  142. }
  143. }
  144. return NULL;
  145. }
  146. static void replace_ids_connection(struct h3ssl *h3ssl, SSL *oldstream, SSL *newstream)
  147. {
  148. struct ssl_id *ssl_ids;
  149. int i;
  150. ssl_ids = h3ssl->ssl_ids;
  151. for (i = 0; i < MAXSSL_IDS; i++) {
  152. if (ssl_ids[i].status & ISCONNECTION && ssl_ids[i].s == oldstream) {
  153. printf("replace_ids_connection\n");
  154. ssl_ids[i].s = newstream;
  155. }
  156. }
  157. }
  158. /* remove the ids marked for removal */
  159. static void remove_marked_ids(struct h3ssl *h3ssl)
  160. {
  161. struct ssl_id *ssl_ids;
  162. int i;
  163. ssl_ids = h3ssl->ssl_ids;
  164. for (i = 0; i < MAXSSL_IDS; i++) {
  165. if (ssl_ids[i].status & TOBEREMOVED) {
  166. printf("remove_id %llu\n", (unsigned long long) ssl_ids[i].id);
  167. SSL_free(ssl_ids[i].s);
  168. ssl_ids[i].s = NULL;
  169. ssl_ids[i].id = UINT64_MAX;
  170. ssl_ids[i].status = 0;
  171. return;
  172. }
  173. }
  174. }
  175. /* add the status bytes to the status */
  176. static void set_id_status(uint64_t id, int status, struct h3ssl *h3ssl)
  177. {
  178. struct ssl_id *ssl_ids;
  179. int i;
  180. ssl_ids = h3ssl->ssl_ids;
  181. for (i = 0; i < MAXSSL_IDS; i++) {
  182. if (ssl_ids[i].id == id) {
  183. printf("set_id_status: %llu to %d\n", (unsigned long long) ssl_ids[i].id, status);
  184. ssl_ids[i].status = ssl_ids[i].status | status;
  185. return;
  186. }
  187. }
  188. printf("Oops can't set status, can't find stream!!!\n");
  189. assert(0);
  190. }
  191. static int get_id_status(uint64_t id, struct h3ssl *h3ssl)
  192. {
  193. struct ssl_id *ssl_ids;
  194. int i;
  195. ssl_ids = h3ssl->ssl_ids;
  196. for (i = 0; i < MAXSSL_IDS; i++) {
  197. if (ssl_ids[i].id == id) {
  198. printf("get_id_status: %llu to %d\n",
  199. (unsigned long long) ssl_ids[i].id, ssl_ids[i].status);
  200. return ssl_ids[i].status;
  201. }
  202. }
  203. printf("Oops can't get status, can't find stream!!!\n");
  204. assert(0);
  205. return -1;
  206. }
  207. /* check that all streams opened by the client are closed */
  208. static int are_all_clientid_closed(struct h3ssl *h3ssl)
  209. {
  210. struct ssl_id *ssl_ids;
  211. int i;
  212. ssl_ids = h3ssl->ssl_ids;
  213. for (i = 0; i < MAXSSL_IDS; i++) {
  214. if (ssl_ids[i].id == UINT64_MAX)
  215. continue;
  216. printf("are_all_clientid_closed: %llu status %d : %d\n",
  217. (unsigned long long) ssl_ids[i].id, ssl_ids[i].status, CLIENTUNIOPEN | CLIENTCLOSED);
  218. if (ssl_ids[i].status & CLIENTUNIOPEN) {
  219. if (ssl_ids[i].status & CLIENTCLOSED) {
  220. printf("are_all_clientid_closed: %llu closed\n",
  221. (unsigned long long) ssl_ids[i].id);
  222. SSL_free(ssl_ids[i].s);
  223. ssl_ids[i].s = NULL;
  224. ssl_ids[i].id = UINT64_MAX;
  225. continue;
  226. }
  227. printf("are_all_clientid_closed: %llu open\n", (unsigned long long) ssl_ids[i].id);
  228. return 0;
  229. }
  230. }
  231. return 1;
  232. }
  233. /* free all the ids except listener and connection */
  234. static void close_all_ids(struct h3ssl *h3ssl)
  235. {
  236. struct ssl_id *ssl_ids;
  237. int i;
  238. ssl_ids = h3ssl->ssl_ids;
  239. for (i = 0; i < MAXSSL_IDS; i++) {
  240. if (ssl_ids[i].id == UINT64_MAX)
  241. continue;
  242. SSL_free(ssl_ids[i].s);
  243. ssl_ids[i].s = NULL;
  244. ssl_ids[i].id = UINT64_MAX;
  245. }
  246. }
  247. static int on_recv_header(nghttp3_conn *conn, int64_t stream_id, int32_t token,
  248. nghttp3_rcbuf *name, nghttp3_rcbuf *value,
  249. uint8_t flags, void *user_data,
  250. void *stream_user_data)
  251. {
  252. nghttp3_vec vname, vvalue;
  253. struct h3ssl *h3ssl = (struct h3ssl *)user_data;
  254. /* Received a single HTTP header. */
  255. vname = nghttp3_rcbuf_get_buf(name);
  256. vvalue = nghttp3_rcbuf_get_buf(value);
  257. fwrite(vname.base, vname.len, 1, stdout);
  258. fprintf(stdout, ": ");
  259. fwrite(vvalue.base, vvalue.len, 1, stdout);
  260. fprintf(stdout, "\n");
  261. if (token == NGHTTP3_QPACK_TOKEN__PATH) {
  262. int len = (((vvalue.len) < (MAXURL)) ? (vvalue.len) : (MAXURL));
  263. memset(h3ssl->url, 0, sizeof(h3ssl->url));
  264. if (vvalue.base[0] == '/') {
  265. if (vvalue.base[1] == '\0') {
  266. strncpy(h3ssl->url, "index.html", MAXURL);
  267. } else {
  268. memcpy(h3ssl->url, vvalue.base + 1, len - 1);
  269. h3ssl->url[len - 1] = '\0';
  270. }
  271. } else {
  272. memcpy(h3ssl->url, vvalue.base, len);
  273. }
  274. }
  275. return 0;
  276. }
  277. static int on_end_headers(nghttp3_conn *conn, int64_t stream_id, int fin,
  278. void *user_data, void *stream_user_data)
  279. {
  280. struct h3ssl *h3ssl = (struct h3ssl *)user_data;
  281. fprintf(stderr, "on_end_headers!\n");
  282. h3ssl->end_headers_received = 1;
  283. return 0;
  284. }
  285. static int on_recv_data(nghttp3_conn *conn, int64_t stream_id,
  286. const uint8_t *data, size_t datalen,
  287. void *conn_user_data, void *stream_user_data)
  288. {
  289. fprintf(stderr, "on_recv_data! %ld\n", (unsigned long)datalen);
  290. fprintf(stderr, "on_recv_data! %.*s\n", (int)datalen, data);
  291. return 0;
  292. }
  293. static int on_end_stream(nghttp3_conn *h3conn, int64_t stream_id,
  294. void *conn_user_data, void *stream_user_data)
  295. {
  296. struct h3ssl *h3ssl = (struct h3ssl *)conn_user_data;
  297. printf("on_end_stream!\n");
  298. h3ssl->done = 1;
  299. return 0;
  300. }
  301. /* Read from the stream and push to the h3conn */
  302. static int quic_server_read(nghttp3_conn *h3conn, SSL *stream, uint64_t id, struct h3ssl *h3ssl)
  303. {
  304. int ret, r;
  305. uint8_t msg2[16000];
  306. size_t l = sizeof(msg2);
  307. if (!SSL_has_pending(stream))
  308. return 0; /* Nothing to read */
  309. ret = SSL_read(stream, msg2, l);
  310. if (ret <= 0) {
  311. fprintf(stderr, "SSL_read %d on %llu failed\n",
  312. SSL_get_error(stream, ret),
  313. (unsigned long long) id);
  314. switch (SSL_get_error(stream, ret)) {
  315. case SSL_ERROR_WANT_READ:
  316. return 0;
  317. case SSL_ERROR_ZERO_RETURN:
  318. return 1;
  319. default:
  320. ERR_print_errors_fp(stderr);
  321. return -1;
  322. }
  323. return -1;
  324. }
  325. /* XXX: work around nghttp3_conn_read_stream returning -607 on stream 2 */
  326. if (!h3ssl->received_from_two && id != 2) {
  327. r = nghttp3_conn_read_stream(h3conn, id, msg2, ret, 0);
  328. } else {
  329. r = ret; /* ignore it for the moment ... */
  330. }
  331. printf("nghttp3_conn_read_stream used %d of %d on %llu\n", r,
  332. ret, (unsigned long long) id);
  333. if (r != ret) {
  334. /* chrome returns -607 on stream 2 */
  335. if (!nghttp3_err_is_fatal(r)) {
  336. printf("nghttp3_conn_read_stream used %d of %d (not fatal) on %llu\n", r,
  337. ret, (unsigned long long) id);
  338. if (id == 2)
  339. h3ssl->received_from_two = 1;
  340. return 1;
  341. }
  342. return -1;
  343. }
  344. return 1;
  345. }
  346. /*
  347. * creates the control stream, the encoding and decoding streams.
  348. * nghttp3_conn_bind_control_stream() is for the control stream.
  349. */
  350. static int quic_server_h3streams(nghttp3_conn *h3conn, struct h3ssl *h3ssl)
  351. {
  352. SSL *rstream = NULL;
  353. SSL *pstream = NULL;
  354. SSL *cstream = NULL;
  355. SSL *conn;
  356. uint64_t r_streamid, p_streamid, c_streamid;
  357. conn = get_ids_connection(h3ssl);
  358. if (conn == NULL) {
  359. fprintf(stderr, "quic_server_h3streams no connection\n");
  360. fflush(stderr);
  361. return -1;
  362. }
  363. rstream = SSL_new_stream(conn, SSL_STREAM_FLAG_UNI);
  364. if (rstream != NULL) {
  365. printf("=> Opened on %llu\n",
  366. (unsigned long long)SSL_get_stream_id(rstream));
  367. } else {
  368. fprintf(stderr, "=> Stream == NULL!\n");
  369. goto err;
  370. }
  371. pstream = SSL_new_stream(conn, SSL_STREAM_FLAG_UNI);
  372. if (pstream != NULL) {
  373. printf("=> Opened on %llu\n",
  374. (unsigned long long)SSL_get_stream_id(pstream));
  375. } else {
  376. fprintf(stderr, "=> Stream == NULL!\n");
  377. goto err;
  378. }
  379. cstream = SSL_new_stream(conn, SSL_STREAM_FLAG_UNI);
  380. if (cstream != NULL) {
  381. fprintf(stderr, "=> Opened on %llu\n",
  382. (unsigned long long)SSL_get_stream_id(cstream));
  383. fflush(stderr);
  384. } else {
  385. fprintf(stderr, "=> Stream == NULL!\n");
  386. goto err;
  387. }
  388. r_streamid = SSL_get_stream_id(rstream);
  389. p_streamid = SSL_get_stream_id(pstream);
  390. c_streamid = SSL_get_stream_id(cstream);
  391. if (nghttp3_conn_bind_qpack_streams(h3conn, p_streamid, r_streamid)) {
  392. fprintf(stderr, "nghttp3_conn_bind_qpack_streams failed!\n");
  393. goto err;
  394. }
  395. if (nghttp3_conn_bind_control_stream(h3conn, c_streamid)) {
  396. fprintf(stderr, "nghttp3_conn_bind_qpack_streams failed!\n");
  397. goto err;
  398. }
  399. printf("control: %llu enc %llu dec %llu\n",
  400. (unsigned long long)c_streamid,
  401. (unsigned long long)p_streamid,
  402. (unsigned long long)r_streamid);
  403. add_id(SSL_get_stream_id(rstream), rstream, h3ssl);
  404. add_id(SSL_get_stream_id(pstream), pstream, h3ssl);
  405. add_id(SSL_get_stream_id(cstream), cstream, h3ssl);
  406. return 0;
  407. err:
  408. fflush(stderr);
  409. SSL_free(rstream);
  410. SSL_free(pstream);
  411. SSL_free(cstream);
  412. return -1;
  413. }
  414. /* Try to read from the streams we have */
  415. static int read_from_ssl_ids(nghttp3_conn **curh3conn, struct h3ssl *h3ssl)
  416. {
  417. int hassomething = 0, i;
  418. struct ssl_id *ssl_ids = h3ssl->ssl_ids;
  419. SSL_POLL_ITEM items[MAXSSL_IDS] = {0}, *item = items;
  420. static const struct timeval nz_timeout = {0, 0};
  421. size_t result_count = SIZE_MAX;
  422. int numitem = 0, ret;
  423. uint64_t processed_event = 0;
  424. int has_ids_to_remove = 0;
  425. nghttp3_conn *h3conn = *curh3conn;
  426. /*
  427. * Process all the streams
  428. * the first one is the connection if we get something here is a new stream
  429. */
  430. for (i = 0; i < MAXSSL_IDS; i++) {
  431. if (ssl_ids[i].s != NULL) {
  432. item->desc = SSL_as_poll_descriptor(ssl_ids[i].s);
  433. item->events = UINT64_MAX; /* TODO adjust to the event we need process */
  434. item->revents = UINT64_MAX; /* TODO adjust to the event we need process */
  435. numitem++;
  436. item++;
  437. }
  438. }
  439. /*
  440. * SSL_POLL_FLAG_NO_HANDLE_EVENTS would require to use:
  441. * SSL_get_event_timeout on the connection stream
  442. * select/wait using the timeout value (which could be no wait time)
  443. * SSL_handle_events
  444. * SSL_poll
  445. * for the moment we let SSL_poll to performs ticking internally
  446. * on an automatic basis.
  447. */
  448. ret = SSL_poll(items, numitem, sizeof(SSL_POLL_ITEM), &nz_timeout,
  449. SSL_POLL_FLAG_NO_HANDLE_EVENTS, &result_count);
  450. if (!ret) {
  451. fprintf(stderr, "SSL_poll failed\n");
  452. printf("SSL_poll failed\n");
  453. return -1; /* something is wrong */
  454. }
  455. printf("read_from_ssl_ids %ld events\n", (unsigned long)result_count);
  456. if (result_count == 0) {
  457. /* Timeout may be something somewhere */
  458. return 0;
  459. }
  460. /* reset the states */
  461. h3ssl->new_conn = 0;
  462. h3ssl->restart = 0;
  463. h3ssl->done = 0;
  464. /* Process all the item we have polled */
  465. for (i = 0, item = items; i < numitem; i++, item++) {
  466. SSL *s;
  467. if (item->revents == SSL_POLL_EVENT_NONE)
  468. continue;
  469. processed_event = 0;
  470. /* get the stream */
  471. s = item->desc.value.ssl;
  472. /* New connection */
  473. if (item->revents & SSL_POLL_EVENT_IC) {
  474. SSL *conn = SSL_accept_connection(item->desc.value.ssl, 0);
  475. SSL *oldconn;
  476. printf("SSL_accept_connection\n");
  477. if (conn == NULL) {
  478. fprintf(stderr, "error while accepting connection\n");
  479. ret = -1;
  480. goto err;
  481. }
  482. /* the previous might be still there */
  483. oldconn = get_ids_connection(h3ssl);
  484. if (oldconn != NULL) {
  485. /* XXX we support only one connection for the moment */
  486. printf("SSL_accept_connection closing previous\n");
  487. SSL_free(oldconn);
  488. replace_ids_connection(h3ssl, oldconn, conn);
  489. reuse_h3ssl(h3ssl);
  490. close_all_ids(h3ssl);
  491. h3ssl->id_bidi = UINT64_MAX;
  492. h3ssl->has_uni = 0;
  493. } else {
  494. printf("SSL_accept_connection first connection\n");
  495. add_ids_connection(h3ssl, conn);
  496. }
  497. h3ssl->new_conn = 1;
  498. /* create the new h3conn */
  499. nghttp3_conn_del(*curh3conn);
  500. nghttp3_settings_default(&settings);
  501. if (nghttp3_conn_server_new(curh3conn, &callbacks, &settings, mem,
  502. h3ssl)) {
  503. fprintf(stderr, "nghttp3_conn_client_new failed!\n");
  504. exit(1);
  505. }
  506. h3conn = *curh3conn;
  507. hassomething++;
  508. if (!SSL_set_incoming_stream_policy(conn,
  509. SSL_INCOMING_STREAM_POLICY_ACCEPT, 0)) {
  510. fprintf(stderr, "error while setting inccoming stream policy\n");
  511. ret = -1;
  512. goto err;
  513. }
  514. printf("SSL_accept_connection\n");
  515. processed_event = processed_event | SSL_POLL_EVENT_IC;
  516. }
  517. /* SSL_accept_stream if SSL_POLL_EVENT_ISB or SSL_POLL_EVENT_ISU */
  518. if ((item->revents & SSL_POLL_EVENT_ISB) ||
  519. (item->revents & SSL_POLL_EVENT_ISU)) {
  520. SSL *stream = SSL_accept_stream(item->desc.value.ssl, 0);
  521. uint64_t new_id;
  522. int r;
  523. if (stream == NULL) {
  524. ret = -1;
  525. goto err;
  526. }
  527. new_id = SSL_get_stream_id(stream);
  528. printf("=> Received connection on %lld %d\n", (unsigned long long) new_id,
  529. SSL_get_stream_type(stream));
  530. add_id(new_id, stream, h3ssl);
  531. if (h3ssl->close_wait) {
  532. printf("in close_wait so we will have a new request\n");
  533. reuse_h3ssl(h3ssl);
  534. h3ssl->restart = 1; /* Checked in wait_close loop */
  535. }
  536. if (SSL_get_stream_type(stream) == SSL_STREAM_TYPE_BIDI) {
  537. /* bidi that is the id where we have to send the response */
  538. if (h3ssl->id_bidi != UINT64_MAX) {
  539. set_id_status(h3ssl->id_bidi, TOBEREMOVED, h3ssl);
  540. has_ids_to_remove++;
  541. }
  542. h3ssl->id_bidi = new_id;
  543. reuse_h3ssl(h3ssl);
  544. h3ssl->restart = 1;
  545. } else {
  546. set_id_status(new_id, CLIENTUNIOPEN, h3ssl);
  547. }
  548. r = quic_server_read(h3conn, stream, new_id, h3ssl);
  549. if (r == -1) {
  550. ret = -1;
  551. goto err;
  552. }
  553. if (r == 1)
  554. hassomething++;
  555. if (item->revents & SSL_POLL_EVENT_ISB)
  556. processed_event = processed_event | SSL_POLL_EVENT_ISB;
  557. if (item->revents & SSL_POLL_EVENT_ISU)
  558. processed_event = processed_event | SSL_POLL_EVENT_ISU;
  559. }
  560. if (item->revents & SSL_POLL_EVENT_OSB) {
  561. /* Create new streams when allowed */
  562. /* at least one bidi */
  563. processed_event = processed_event | SSL_POLL_EVENT_OSB;
  564. printf("Create bidi?\n");
  565. }
  566. if (item->revents & SSL_POLL_EVENT_OSU) {
  567. /* at least one uni */
  568. /* we have 4 streams from the client 2, 6 , 10 and 0 */
  569. /* need 3 streams to the client */
  570. printf("Create uni?\n");
  571. processed_event = processed_event | SSL_POLL_EVENT_OSU;
  572. if (!h3ssl->has_uni) {
  573. printf("Create uni\n");
  574. ret = quic_server_h3streams(h3conn, h3ssl);
  575. if (ret == -1) {
  576. fprintf(stderr, "quic_server_h3streams failed!\n");
  577. goto err;
  578. }
  579. h3ssl->has_uni = 1;
  580. hassomething++;
  581. }
  582. }
  583. if (item->revents & SSL_POLL_EVENT_EC) {
  584. /* the connection begins terminating */
  585. printf("Connection terminating\n");
  586. printf("Connection terminating restart %d\n", h3ssl->restart);
  587. if (!h3ssl->close_done) {
  588. h3ssl->close_done = 1;
  589. } else {
  590. h3ssl->done = 1;
  591. }
  592. hassomething++;
  593. processed_event = processed_event | SSL_POLL_EVENT_EC;
  594. }
  595. if (item->revents & SSL_POLL_EVENT_ECD) {
  596. /* the connection is terminated */
  597. printf("Connection terminated\n");
  598. h3ssl->done = 1;
  599. hassomething++;
  600. processed_event = processed_event | SSL_POLL_EVENT_ECD;
  601. }
  602. if (item->revents & SSL_POLL_EVENT_R) {
  603. /* try to read */
  604. uint64_t id = UINT64_MAX;
  605. int r;
  606. /* get the id, well the connection has no id... */
  607. id = SSL_get_stream_id(item->desc.value.ssl);
  608. printf("revent READ on %llu\n", (unsigned long long)id);
  609. r = quic_server_read(h3conn, s, id, h3ssl);
  610. if (r == 0) {
  611. uint8_t msg[1];
  612. size_t l = sizeof(msg);
  613. /* check that the other side is closed */
  614. r = SSL_read(s, msg, l);
  615. printf("SSL_read tells %d\n", r);
  616. if (r > 0) {
  617. ret = -1;
  618. goto err;
  619. }
  620. r = SSL_get_error(s, r);
  621. if (r != SSL_ERROR_ZERO_RETURN) {
  622. ret = -1;
  623. goto err;
  624. }
  625. set_id_status(id, TOBEREMOVED, h3ssl);
  626. has_ids_to_remove++;
  627. continue;
  628. }
  629. if (r == -1) {
  630. ret = -1;
  631. goto err;
  632. }
  633. hassomething++;
  634. processed_event = processed_event | SSL_POLL_EVENT_R;
  635. }
  636. if (item->revents & SSL_POLL_EVENT_ER) {
  637. /* mark it closed */
  638. uint64_t id = UINT64_MAX;
  639. int status;
  640. id = SSL_get_stream_id(item->desc.value.ssl);
  641. status = get_id_status(id, h3ssl);
  642. printf("revent exception READ on %llu\n", (unsigned long long)id);
  643. if (status & CLIENTUNIOPEN) {
  644. set_id_status(id, CLIENTCLOSED, h3ssl);
  645. hassomething++;
  646. }
  647. processed_event = processed_event | SSL_POLL_EVENT_ER;
  648. }
  649. if (item->revents & SSL_POLL_EVENT_W) {
  650. /* we ignore those for the moment */
  651. processed_event = processed_event | SSL_POLL_EVENT_W;
  652. }
  653. if (item->revents & SSL_POLL_EVENT_EW) {
  654. /* write part received a STOP_SENDING */
  655. uint64_t id = UINT64_MAX;
  656. int status;
  657. id = SSL_get_stream_id(item->desc.value.ssl);
  658. status = get_id_status(id, h3ssl);
  659. if (status & SERVERCLOSED) {
  660. printf("both sides closed on %llu\n", (unsigned long long)id);
  661. set_id_status(id, TOBEREMOVED, h3ssl);
  662. has_ids_to_remove++;
  663. hassomething++;
  664. }
  665. processed_event = processed_event | SSL_POLL_EVENT_EW;
  666. }
  667. if (item->revents != processed_event) {
  668. /* Figure out ??? */
  669. uint64_t id = UINT64_MAX;
  670. id = SSL_get_stream_id(item->desc.value.ssl);
  671. printf("revent %llu (%d) on %llu NOT PROCESSED!\n",
  672. (unsigned long long)item->revents, SSL_POLL_EVENT_W,
  673. (unsigned long long)id);
  674. }
  675. }
  676. ret = hassomething;
  677. err:
  678. if (has_ids_to_remove)
  679. remove_marked_ids(h3ssl);
  680. return ret;
  681. }
  682. static void handle_events_from_ids(struct h3ssl *h3ssl)
  683. {
  684. struct ssl_id *ssl_ids = h3ssl->ssl_ids;
  685. int i;
  686. ssl_ids = h3ssl->ssl_ids;
  687. for (i = 0; i < MAXSSL_IDS; i++) {
  688. if (ssl_ids[i].s != NULL &&
  689. (ssl_ids[i].status & ISCONNECTION || ssl_ids[i].status & ISLISTENER)) {
  690. if (SSL_handle_events(ssl_ids[i].s))
  691. ERR_print_errors_fp(stderr);
  692. }
  693. }
  694. }
  695. static size_t get_file_length(struct h3ssl *h3ssl)
  696. {
  697. char filename[PATH_MAX];
  698. struct stat st;
  699. memset(filename, 0, PATH_MAX);
  700. if (h3ssl->fileprefix != NULL)
  701. strcat(filename, h3ssl->fileprefix);
  702. strcat(filename, h3ssl->url);
  703. if (strcmp(h3ssl->url, "big") == 0) {
  704. printf("big!!!\n");
  705. return (size_t)INT_MAX;
  706. }
  707. if (stat(filename, &st) == 0) {
  708. /* Only process regular files */
  709. if (S_ISREG(st.st_mode)) {
  710. printf("get_file_length %s %lld\n", filename, (unsigned long long) st.st_size);
  711. return (size_t)st.st_size;
  712. }
  713. }
  714. printf("Can't get_file_length %s\n", filename);
  715. return 0;
  716. }
  717. static char *get_file_data(struct h3ssl *h3ssl)
  718. {
  719. char filename[PATH_MAX];
  720. size_t size = get_file_length(h3ssl);
  721. char *res;
  722. int fd;
  723. if (size == 0)
  724. return NULL;
  725. memset(filename, 0, PATH_MAX);
  726. if (h3ssl->fileprefix != NULL)
  727. strcat(filename, h3ssl->fileprefix);
  728. strcat(filename, h3ssl->url);
  729. res = malloc(size+1);
  730. res[size] = '\0';
  731. fd = open(filename, O_RDONLY);
  732. if (read(fd, res, size) == -1) {
  733. close(fd);
  734. free(res);
  735. return NULL;
  736. }
  737. close(fd);
  738. printf("read from %s : %zu\n", filename, size);
  739. return res;
  740. }
  741. static nghttp3_ssize step_read_data(nghttp3_conn *conn, int64_t stream_id,
  742. nghttp3_vec *vec, size_t veccnt,
  743. uint32_t *pflags, void *user_data,
  744. void *stream_user_data)
  745. {
  746. struct h3ssl *h3ssl = (struct h3ssl *)user_data;
  747. if (h3ssl->datadone) {
  748. *pflags = NGHTTP3_DATA_FLAG_EOF;
  749. return 0;
  750. }
  751. /* send the data */
  752. printf("step_read_data for %s %zu\n", h3ssl->url, h3ssl->ldata);
  753. if (h3ssl->ldata <= 4096) {
  754. vec[0].base = &(h3ssl->ptr_data[h3ssl->offset_data]);
  755. vec[0].len = h3ssl->ldata;
  756. h3ssl->datadone++;
  757. *pflags = NGHTTP3_DATA_FLAG_EOF;
  758. } else {
  759. vec[0].base = &(h3ssl->ptr_data[h3ssl->offset_data]);
  760. vec[0].len = 4096;
  761. if (h3ssl->ldata == INT_MAX) {
  762. printf("big = endless!\n");
  763. } else {
  764. h3ssl->offset_data = h3ssl->offset_data + 4096;
  765. h3ssl->ldata = h3ssl->ldata - 4096;
  766. }
  767. }
  768. return 1;
  769. }
  770. static int quic_server_write(struct h3ssl *h3ssl, uint64_t streamid,
  771. uint8_t *buff, size_t len, uint64_t flags,
  772. size_t *written)
  773. {
  774. struct ssl_id *ssl_ids;
  775. int i;
  776. ssl_ids = h3ssl->ssl_ids;
  777. for (i = 0; i < MAXSSL_IDS; i++) {
  778. if (ssl_ids[i].id == streamid) {
  779. if (!SSL_write_ex2(ssl_ids[i].s, buff, len, flags, written) ||
  780. *written != len) {
  781. fprintf(stderr, "couldn't write on connection\n");
  782. ERR_print_errors_fp(stderr);
  783. return 0;
  784. }
  785. printf("written %lld on %lld flags %lld\n", (unsigned long long)len,
  786. (unsigned long long)streamid, (unsigned long long)flags);
  787. return 1;
  788. }
  789. }
  790. printf("quic_server_write %lld on %lld (NOT FOUND!)\n", (unsigned long long)len,
  791. (unsigned long long)streamid);
  792. return 0;
  793. }
  794. #define OSSL_NELEM(x) (sizeof(x) / sizeof((x)[0]))
  795. /*
  796. * This is a basic demo of QUIC server functionality in which one connection at
  797. * a time is accepted in a blocking loop.
  798. */
  799. /* ALPN string for TLS handshake. We pretent h3-29 and h3 */
  800. static const unsigned char alpn_ossltest[] = { 5, 'h', '3', '-', '2',
  801. '9', 2, 'h', '3' };
  802. /*
  803. * This callback validates and negotiates the desired ALPN on the server side.
  804. */
  805. static int select_alpn(SSL *ssl, const unsigned char **out,
  806. unsigned char *out_len, const unsigned char *in,
  807. unsigned int in_len, void *arg)
  808. {
  809. if (SSL_select_next_proto((unsigned char **)out, out_len, alpn_ossltest,
  810. sizeof(alpn_ossltest), in,
  811. in_len) != OPENSSL_NPN_NEGOTIATED)
  812. return SSL_TLSEXT_ERR_ALERT_FATAL;
  813. return SSL_TLSEXT_ERR_OK;
  814. }
  815. /* Create SSL_CTX. */
  816. static SSL_CTX *create_ctx(const char *cert_path, const char *key_path)
  817. {
  818. SSL_CTX *ctx;
  819. ctx = SSL_CTX_new(OSSL_QUIC_server_method());
  820. if (ctx == NULL)
  821. goto err;
  822. /* Load certificate and corresponding private key. */
  823. if (SSL_CTX_use_certificate_chain_file(ctx, cert_path) <= 0) {
  824. fprintf(stderr, "couldn't load certificate file: %s\n", cert_path);
  825. goto err;
  826. }
  827. if (SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0) {
  828. fprintf(stderr, "couldn't load key file: %s\n", key_path);
  829. goto err;
  830. }
  831. if (!SSL_CTX_check_private_key(ctx)) {
  832. fprintf(stderr, "private key check failed\n");
  833. goto err;
  834. }
  835. /* Setup ALPN negotiation callback. */
  836. SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
  837. return ctx;
  838. err:
  839. SSL_CTX_free(ctx);
  840. return NULL;
  841. }
  842. /* Create UDP socket using given port. */
  843. static int create_socket(uint16_t port)
  844. {
  845. int fd = -1;
  846. struct sockaddr_in sa = {0};
  847. if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  848. fprintf(stderr, "cannot create socket");
  849. goto err;
  850. }
  851. sa.sin_family = AF_INET;
  852. sa.sin_port = htons(port);
  853. if (bind(fd, (const struct sockaddr *)&sa, sizeof(sa)) < 0) {
  854. fprintf(stderr, "cannot bind to %u\n", port);
  855. goto err;
  856. }
  857. return fd;
  858. err:
  859. if (fd >= 0)
  860. BIO_closesocket(fd);
  861. return -1;
  862. }
  863. /* Copied from demos/guide/quic-server-non-block.c */
  864. /**
  865. * @brief Waits for activity on the SSL socket, either for reading or writing.
  866. *
  867. * This function monitors the underlying file descriptor of the given SSL
  868. * connection to determine when it is ready for reading or writing, or both.
  869. * It uses the select function to wait until the socket is either readable
  870. * or writable, depending on what the SSL connection requires.
  871. *
  872. * @param ssl A pointer to the SSL object representing the connection.
  873. *
  874. * @note This function blocks until there is activity on the socket. In a real
  875. * application, you might want to perform other tasks while waiting, such as
  876. * updating a GUI or handling other connections.
  877. *
  878. * @note This function uses select for simplicity and portability. Depending
  879. * on your application's requirements, you might consider using other
  880. * mechanisms like poll or epoll for handling multiple file descriptors.
  881. */
  882. static int wait_for_activity(SSL *ssl)
  883. {
  884. int sock, isinfinite;
  885. fd_set read_fd, write_fd;
  886. struct timeval tv;
  887. struct timeval *tvp = NULL;
  888. /* Get hold of the underlying file descriptor for the socket */
  889. if ((sock = SSL_get_fd(ssl)) == -1) {
  890. fprintf(stderr, "Unable to get file descriptor");
  891. return -1;
  892. }
  893. /* Initialize the fd_set structure */
  894. FD_ZERO(&read_fd);
  895. FD_ZERO(&write_fd);
  896. /*
  897. * Determine if we would like to write to the socket, read from it, or both.
  898. */
  899. if (SSL_net_write_desired(ssl))
  900. FD_SET(sock, &write_fd);
  901. if (SSL_net_read_desired(ssl))
  902. FD_SET(sock, &read_fd);
  903. /* Add the socket file descriptor to the fd_set */
  904. FD_SET(sock, &read_fd);
  905. /*
  906. * Find out when OpenSSL would next like to be called, regardless of
  907. * whether the state of the underlying socket has changed or not.
  908. */
  909. if (SSL_get_event_timeout(ssl, &tv, &isinfinite) && !isinfinite)
  910. tvp = &tv;
  911. /*
  912. * Wait until the socket is writeable or readable. We use select here
  913. * for the sake of simplicity and portability, but you could equally use
  914. * poll/epoll or similar functions
  915. *
  916. * NOTE: For the purposes of this demonstration code this effectively
  917. * makes this demo block until it has something more useful to do. In a
  918. * real application you probably want to go and do other work here (e.g.
  919. * update a GUI, or service other connections).
  920. *
  921. * Let's say for example that you want to update the progress counter on
  922. * a GUI every 100ms. One way to do that would be to use the timeout in
  923. * the last parameter to "select" below. If the tvp value is greater
  924. * than 100ms then use 100ms instead. Then, when select returns, you
  925. * check if it did so because of activity on the file descriptors or
  926. * because of the timeout. If the 100ms GUI timeout has expired but the
  927. * tvp timeout has not then go and update the GUI and then restart the
  928. * "select" (with updated timeouts).
  929. */
  930. return (select(sock + 1, &read_fd, &write_fd, NULL, tvp));
  931. }
  932. /* Main loop for server to accept QUIC connections. */
  933. static int run_quic_server(SSL_CTX *ctx, int fd)
  934. {
  935. int ok = 0;
  936. int hassomething = 0;
  937. SSL *listener = NULL;
  938. nghttp3_conn *h3conn = NULL;
  939. struct h3ssl h3ssl;
  940. SSL *ssl;
  941. char *fileprefix = getenv("FILEPREFIX");
  942. /* Create a new QUIC listener. */
  943. if ((listener = SSL_new_listener(ctx, 0)) == NULL)
  944. goto err;
  945. /* Provide the listener with our UDP socket. */
  946. if (!SSL_set_fd(listener, fd))
  947. goto err;
  948. /* Begin listening. */
  949. if (!SSL_listen(listener))
  950. goto err;
  951. /*
  952. * Listeners, and other QUIC objects, default to operating in blocking mode.
  953. * The configured behaviour is inherited by child objects.
  954. * Make sure we won't block as we use select().
  955. */
  956. if (!SSL_set_blocking_mode(listener, 0))
  957. goto err;
  958. /* Setup callbacks. */
  959. callbacks.recv_header = on_recv_header;
  960. callbacks.end_headers = on_end_headers;
  961. callbacks.recv_data = on_recv_data;
  962. callbacks.end_stream = on_end_stream;
  963. /* mem default */
  964. mem = nghttp3_mem_default();
  965. for (;;) {
  966. nghttp3_nv resp[10];
  967. size_t num_nv;
  968. nghttp3_data_reader dr;
  969. int ret;
  970. int numtimeout;
  971. char slength[22];
  972. int hasnothing;
  973. init_ids(&h3ssl);
  974. h3ssl.fileprefix = fileprefix;
  975. printf("listener: %p\n", (void *)listener);
  976. add_ids_listener(listener, &h3ssl);
  977. if (!hassomething) {
  978. printf("waiting on socket\n");
  979. fflush(stdout);
  980. ret = wait_for_activity(listener);
  981. if (ret == -1) {
  982. fprintf(stderr, "wait_for_activity failed!\n");
  983. goto err;
  984. }
  985. }
  986. /*
  987. * Service the connection. In a real application this would be done
  988. * concurrently. In this demonstration program a single connection is
  989. * accepted and serviced at a time.
  990. */
  991. newconn:
  992. printf("process_server starting...\n");
  993. fflush(stdout);
  994. /* wait until we have received the headers */
  995. restart:
  996. numtimeout = 0;
  997. num_nv = 0;
  998. while (!h3ssl.end_headers_received) {
  999. if (!hassomething) {
  1000. if (wait_for_activity(listener) == 0) {
  1001. printf("waiting for end_headers_received timeout %d\n", numtimeout);
  1002. numtimeout++;
  1003. if (numtimeout == 25)
  1004. goto err;
  1005. }
  1006. handle_events_from_ids(&h3ssl);
  1007. }
  1008. hassomething = read_from_ssl_ids(&h3conn, &h3ssl);
  1009. if (hassomething == -1) {
  1010. fprintf(stderr, "read_from_ssl_ids hassomething failed\n");
  1011. goto err;
  1012. } else if (hassomething == 0) {
  1013. printf("read_from_ssl_ids hassomething nothing...\n");
  1014. } else {
  1015. numtimeout = 0;
  1016. printf("read_from_ssl_ids hassomething %d...\n", hassomething);
  1017. if (h3ssl.close_done) {
  1018. /* Other side has closed */
  1019. break;
  1020. }
  1021. h3ssl.restart = 0;
  1022. }
  1023. }
  1024. if (h3ssl.close_done) {
  1025. printf("Other side close without request\n");
  1026. goto wait_close;
  1027. }
  1028. printf("end_headers_received!!!\n");
  1029. if (!h3ssl.has_uni) {
  1030. /* time to create those otherwise we can't push anything to the client */
  1031. printf("Create uni\n");
  1032. if (quic_server_h3streams(h3conn, &h3ssl) == -1) {
  1033. fprintf(stderr, "quic_server_h3streams failed!\n");
  1034. goto err;
  1035. }
  1036. h3ssl.has_uni = 1;
  1037. }
  1038. /* we have receive the request build the response and send it */
  1039. /* XXX add MAKE_NV("connection", "close"), to resp[] and recheck */
  1040. make_nv(&resp[num_nv++], ":status", "200");
  1041. h3ssl.ldata = get_file_length(&h3ssl);
  1042. if (h3ssl.ldata == 0) {
  1043. /* We don't find the file: use default test string */
  1044. h3ssl.ptr_data = nulldata;
  1045. h3ssl.ldata = nulldata_sz;
  1046. sprintf(slength, "%zu", h3ssl.ldata);
  1047. /* content-type: text/html */
  1048. make_nv(&resp[num_nv++], "content-type", "text/html");
  1049. } else if (h3ssl.ldata == INT_MAX) {
  1050. /* endless file for tests */
  1051. sprintf(slength, "%zu", h3ssl.ldata);
  1052. h3ssl.ptr_data = (uint8_t *) malloc(4096);
  1053. memset(h3ssl.ptr_data, 'A', 4096);
  1054. } else {
  1055. /* normal file we have opened */
  1056. sprintf(slength, "%zu", h3ssl.ldata);
  1057. h3ssl.ptr_data = (uint8_t *) get_file_data(&h3ssl);
  1058. if (h3ssl.ptr_data == NULL)
  1059. abort();
  1060. printf("before nghttp3_conn_submit_response on %llu for %s ...\n",
  1061. (unsigned long long) h3ssl.id_bidi, h3ssl.url);
  1062. if (strstr(h3ssl.url, ".png"))
  1063. make_nv(&resp[num_nv++], "content-type", "image/png");
  1064. else if (strstr(h3ssl.url, ".ico"))
  1065. make_nv(&resp[num_nv++], "content-type", "image/vnd.microsoft.icon");
  1066. else if (strstr(h3ssl.url, ".htm"))
  1067. make_nv(&resp[num_nv++], "content-type", "text/html");
  1068. else
  1069. make_nv(&resp[num_nv++], "content-type", "application/octet-stream");
  1070. make_nv(&resp[num_nv++], "content-length", slength);
  1071. }
  1072. dr.read_data = step_read_data;
  1073. if (nghttp3_conn_submit_response(h3conn, h3ssl.id_bidi, resp, num_nv, &dr)) {
  1074. fprintf(stderr, "nghttp3_conn_submit_response failed!\n");
  1075. goto err;
  1076. }
  1077. printf("nghttp3_conn_submit_response on %llu...\n", (unsigned long long) h3ssl.id_bidi);
  1078. for (;;) {
  1079. nghttp3_vec vec[256];
  1080. nghttp3_ssize sveccnt;
  1081. int fin, i;
  1082. int64_t streamid;
  1083. sveccnt = nghttp3_conn_writev_stream(h3conn, &streamid, &fin, vec,
  1084. nghttp3_arraylen(vec));
  1085. if (sveccnt <= 0) {
  1086. printf("nghttp3_conn_writev_stream done: %ld stream: %llu fin %d\n",
  1087. (long int)sveccnt,
  1088. (unsigned long long)streamid,
  1089. fin);
  1090. if (streamid != -1 && fin) {
  1091. printf("Sending end data on %llu fin %d\n",
  1092. (unsigned long long) streamid, fin);
  1093. nghttp3_conn_add_write_offset(h3conn, streamid, 0);
  1094. continue;
  1095. }
  1096. if (!h3ssl.datadone)
  1097. goto err;
  1098. else
  1099. break; /* Done */
  1100. }
  1101. printf("nghttp3_conn_writev_stream: %ld fin: %d\n", (long int)sveccnt, fin);
  1102. for (i = 0; i < sveccnt; i++) {
  1103. size_t numbytes = vec[i].len;
  1104. int flagwrite = 0;
  1105. printf("quic_server_write on %llu for %ld\n",
  1106. (unsigned long long)streamid, (unsigned long)vec[i].len);
  1107. if (fin && i == sveccnt - 1)
  1108. flagwrite = SSL_WRITE_FLAG_CONCLUDE;
  1109. if (!quic_server_write(&h3ssl, streamid, vec[i].base,
  1110. vec[i].len, flagwrite, &numbytes)) {
  1111. fprintf(stderr, "quic_server_write failed!\n");
  1112. goto err;
  1113. }
  1114. }
  1115. if (nghttp3_conn_add_write_offset(
  1116. h3conn, streamid,
  1117. (size_t)nghttp3_vec_len(vec, (size_t)sveccnt))) {
  1118. fprintf(stderr, "nghttp3_conn_add_write_offset failed!\n");
  1119. goto err;
  1120. }
  1121. }
  1122. printf("nghttp3_conn_submit_response DONE!!!\n");
  1123. if (h3ssl.datadone) {
  1124. /*
  1125. * All the data was sent.
  1126. * close stream zero
  1127. */
  1128. if (!h3ssl.close_done) {
  1129. set_id_status(h3ssl.id_bidi, SERVERCLOSED, &h3ssl);
  1130. h3ssl.close_wait = 1;
  1131. }
  1132. } else {
  1133. printf("nghttp3_conn_submit_response still not finished\n");
  1134. }
  1135. /* wait until closed */
  1136. wait_close:
  1137. hasnothing = 0;
  1138. for (;;) {
  1139. if (!hasnothing) {
  1140. SSL *newssl = get_ids_connection(&h3ssl);
  1141. printf("hasnothing nothing WAIT %d!!!\n", h3ssl.close_done);
  1142. if (newssl == NULL)
  1143. newssl = listener;
  1144. ret = wait_for_activity(newssl);
  1145. if (ret == -1)
  1146. goto err;
  1147. if (ret == 0)
  1148. printf("hasnothing timeout\n");
  1149. /* we have something or a timeout */
  1150. handle_events_from_ids(&h3ssl);
  1151. }
  1152. hasnothing = read_from_ssl_ids(&h3conn, &h3ssl);
  1153. if (hasnothing == -1) {
  1154. printf("hasnothing failed\n");
  1155. break;
  1156. /* goto err; well in fact not */
  1157. } else if (hasnothing == 0) {
  1158. printf("hasnothing nothing\n");
  1159. continue;
  1160. } else {
  1161. printf("hasnothing something\n");
  1162. if (h3ssl.done) {
  1163. printf("hasnothing something... DONE\n");
  1164. /* we might already have the next connection to accept */
  1165. hassomething = 1;
  1166. break;
  1167. }
  1168. if (h3ssl.new_conn) {
  1169. printf("hasnothing something... NEW CONN\n");
  1170. h3ssl.new_conn = 0;
  1171. goto newconn;
  1172. }
  1173. if (h3ssl.restart) {
  1174. printf("hasnothing something... RESTART\n");
  1175. h3ssl.restart = 0;
  1176. goto restart;
  1177. }
  1178. if (are_all_clientid_closed(&h3ssl)) {
  1179. printf("hasnothing something... DONE other side closed\n");
  1180. /* there might 2 or 3 message we will ignore */
  1181. hassomething = 0;
  1182. break;
  1183. }
  1184. }
  1185. }
  1186. /*
  1187. * Free the streams, then loop again, accepting another connection.
  1188. */
  1189. close_all_ids(&h3ssl);
  1190. ssl = get_ids_connection(&h3ssl);
  1191. if (ssl != NULL) {
  1192. SSL_free(ssl);
  1193. replace_ids_connection(&h3ssl, ssl, NULL);
  1194. }
  1195. hassomething = 0;
  1196. }
  1197. ok = 1;
  1198. err:
  1199. if (!ok)
  1200. ERR_print_errors_fp(stderr);
  1201. SSL_free(listener);
  1202. return ok;
  1203. }
  1204. /*
  1205. * demo server... just return a 20 bytes ascii string as response for any
  1206. * request single h3 connection and single threaded.
  1207. */
  1208. int main(int argc, char **argv)
  1209. {
  1210. int rc = 1;
  1211. SSL_CTX *ctx = NULL;
  1212. int fd = -1;
  1213. unsigned long port;
  1214. if (argc < 4) {
  1215. fprintf(stderr, "usage: %s <port> <server.crt> <server.key>\n",
  1216. argv[0]);
  1217. goto err;
  1218. }
  1219. /* Create SSL_CTX. */
  1220. if ((ctx = create_ctx(argv[2], argv[3])) == NULL)
  1221. goto err;
  1222. /* Parse port number from command line arguments. */
  1223. port = strtoul(argv[1], NULL, 0);
  1224. if (port == 0 || port > UINT16_MAX) {
  1225. fprintf(stderr, "invalid port: %lu\n", port);
  1226. goto err;
  1227. }
  1228. /* Create UDP socket. */
  1229. if ((fd = create_socket((uint16_t)port)) < 0)
  1230. goto err;
  1231. /* Enter QUIC server connection acceptance loop. */
  1232. if (!run_quic_server(ctx, fd))
  1233. goto err;
  1234. rc = 0;
  1235. err:
  1236. if (rc != 0)
  1237. ERR_print_errors_fp(stderr);
  1238. SSL_CTX_free(ctx);
  1239. if (fd != -1)
  1240. BIO_closesocket(fd);
  1241. return rc;
  1242. }