iodine 0.7.57 → 0.7.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,7 +32,7 @@ typedef struct {
32
32
  /* *****************************************************************************
33
33
  The SSL/TLS helper data types (can be left as is)
34
34
  ***************************************************************************** */
35
- #define FIO_INCLUDE_STR 1
35
+ #define FIO_INCLUDE_STR 1
36
36
  #define FIO_FORCE_MALLOC_TMP 1
37
37
  #include <fio.h>
38
38
 
@@ -65,12 +65,12 @@ static inline void fio_tls_cert_destroy(cert_s *obj) {
65
65
  fio_str_free(&obj->password);
66
66
  }
67
67
 
68
- #define FIO_ARY_NAME cert_ary
69
- #define FIO_ARY_TYPE cert_s
68
+ #define FIO_ARY_NAME cert_ary
69
+ #define FIO_ARY_TYPE cert_s
70
70
  #define FIO_ARY_COMPARE(k1, k2) (fio_tls_cert_cmp(&(k1), &(k2)))
71
71
  #define FIO_ARY_COPY(dest, obj) fio_tls_cert_copy(&(dest), &(obj))
72
- #define FIO_ARY_DESTROY(key) fio_tls_cert_destroy(&(key))
73
- #define FIO_FORCE_MALLOC_TMP 1
72
+ #define FIO_ARY_DESTROY(key) fio_tls_cert_destroy(&(key))
73
+ #define FIO_FORCE_MALLOC_TMP 1
74
74
  #include <fio.h>
75
75
 
76
76
  typedef struct {
@@ -90,12 +90,12 @@ static inline void fio_tls_trust_destroy(trust_s *obj) {
90
90
  fio_str_free(&obj->pem);
91
91
  }
92
92
 
93
- #define FIO_ARY_NAME trust_ary
94
- #define FIO_ARY_TYPE trust_s
93
+ #define FIO_ARY_NAME trust_ary
94
+ #define FIO_ARY_TYPE trust_s
95
95
  #define FIO_ARY_COMPARE(k1, k2) (fio_tls_trust_cmp(&(k1), &(k2)))
96
96
  #define FIO_ARY_COPY(dest, obj) fio_tls_trust_copy(&(dest), &(obj))
97
- #define FIO_ARY_DESTROY(key) fio_tls_trust_destroy(&(key))
98
- #define FIO_FORCE_MALLOC_TMP 1
97
+ #define FIO_ARY_DESTROY(key) fio_tls_trust_destroy(&(key))
98
+ #define FIO_FORCE_MALLOC_TMP 1
99
99
  #include <fio.h>
100
100
 
101
101
  typedef struct {
@@ -123,12 +123,12 @@ static inline void fio_alpn_destroy(alpn_s *obj) {
123
123
  fio_str_free(&obj->name);
124
124
  }
125
125
 
126
- #define FIO_SET_NAME alpn_list
127
- #define FIO_SET_OBJ_TYPE alpn_s
126
+ #define FIO_SET_NAME alpn_list
127
+ #define FIO_SET_OBJ_TYPE alpn_s
128
128
  #define FIO_SET_OBJ_COMPARE(k1, k2) fio_alpn_cmp(&(k1), &(k2))
129
129
  #define FIO_SET_OBJ_COPY(dest, obj) fio_alpn_copy(&(dest), &(obj))
130
- #define FIO_SET_OBJ_DESTROY(key) fio_alpn_destroy(&(key))
131
- #define FIO_FORCE_MALLOC_TMP 1
130
+ #define FIO_SET_OBJ_DESTROY(key) fio_alpn_destroy(&(key))
131
+ #define FIO_FORCE_MALLOC_TMP 1
132
132
  #include <fio.h>
133
133
 
134
134
  /* *****************************************************************************
@@ -167,10 +167,13 @@ FIO_FUNC inline alpn_s *alpn_find(fio_tls_s *tls, char *name, size_t len) {
167
167
  }
168
168
 
169
169
  /** Adds an ALPN data object to the ALPN "list" (set) */
170
- FIO_FUNC inline void alpn_add(
171
- fio_tls_s *tls, const char *protocol_name,
172
- void (*on_selected)(intptr_t uuid, void *udata_connection, void *udata_tls),
173
- void *udata_tls, void (*on_cleanup)(void *udata_tls)) {
170
+ FIO_FUNC inline void alpn_add(fio_tls_s *tls,
171
+ const char *protocol_name,
172
+ void (*on_selected)(intptr_t uuid,
173
+ void *udata_connection,
174
+ void *udata_tls),
175
+ void *udata_tls,
176
+ void (*on_cleanup)(void *udata_tls)) {
174
177
  alpn_s tmp = {
175
178
  .name = FIO_STR_INIT_STATIC(protocol_name),
176
179
  .on_selected = on_selected,
@@ -212,7 +215,8 @@ FIO_FUNC inline void alpn_select___task(void *t_, void *ignr_) {
212
215
  }
213
216
 
214
217
  /** Schedules the ALPN protocol callback. */
215
- FIO_FUNC inline void alpn_select(alpn_s *alpn, intptr_t uuid,
218
+ FIO_FUNC inline void alpn_select(alpn_s *alpn,
219
+ intptr_t uuid,
216
220
  void *udata_connection) {
217
221
  if (!alpn || !alpn->on_selected)
218
222
  return;
@@ -257,7 +261,8 @@ static void fio_tls_make_root_key(void) {
257
261
  "OpenSSL failed to create RSA key.");
258
262
  BN_free(e);
259
263
  EVP_PKEY_assign_RSA(fio_tls_pkey, rsa);
260
- fio_state_callback_add(FIO_CALL_AT_EXIT, fio_tls_clear_root_key,
264
+ fio_state_callback_add(FIO_CALL_AT_EXIT,
265
+ fio_tls_clear_root_key,
261
266
  fio_tls_pkey);
262
267
  finish:
263
268
  fio_unlock(&lock);
@@ -284,12 +289,27 @@ static X509 *fio_tls_create_self_signed(char *server_name) {
284
289
  /* set identity details */
285
290
  X509_NAME *s = X509_get_subject_name(cert);
286
291
  size_t srv_name_len = strlen(server_name);
287
- X509_NAME_add_entry_by_txt(s, "O", MBSTRING_ASC, (unsigned char *)server_name,
288
- srv_name_len, -1, 0);
289
- X509_NAME_add_entry_by_txt(s, "CN", MBSTRING_ASC,
290
- (unsigned char *)server_name, srv_name_len, -1, 0);
291
- X509_NAME_add_entry_by_txt(s, "CA", MBSTRING_ASC,
292
- (unsigned char *)server_name, srv_name_len, -1, 0);
292
+ X509_NAME_add_entry_by_txt(s,
293
+ "O",
294
+ MBSTRING_ASC,
295
+ (unsigned char *)server_name,
296
+ srv_name_len,
297
+ -1,
298
+ 0);
299
+ X509_NAME_add_entry_by_txt(s,
300
+ "CN",
301
+ MBSTRING_ASC,
302
+ (unsigned char *)server_name,
303
+ srv_name_len,
304
+ -1,
305
+ 0);
306
+ X509_NAME_add_entry_by_txt(s,
307
+ "CA",
308
+ MBSTRING_ASC,
309
+ (unsigned char *)server_name,
310
+ srv_name_len,
311
+ -1,
312
+ 0);
293
313
  X509_set_issuer_name(cert, s);
294
314
 
295
315
  /* sign certificate */
@@ -324,12 +344,15 @@ static void fio_tls_alpn_fallback(fio_tls_connection_s *c) {
324
344
  return;
325
345
  /* set protocol to default protocol */
326
346
  FIO_LOG_DEBUG("TLS ALPN handshake missing, falling back on %s for %p",
327
- fio_str_info(&alpn->name).data, (void *)c->uuid);
347
+ fio_str_info(&alpn->name).data,
348
+ (void *)c->uuid);
328
349
  alpn_select(alpn, c->uuid, c->alpn_arg);
329
350
  }
330
- static int fio_tls_alpn_selector_cb(SSL *ssl, const unsigned char **out,
351
+ static int fio_tls_alpn_selector_cb(SSL *ssl,
352
+ const unsigned char **out,
331
353
  unsigned char *outlen,
332
- const unsigned char *in, unsigned int inlen,
354
+ const unsigned char *in,
355
+ unsigned int inlen,
333
356
  void *tls_) {
334
357
  fio_tls_s *tls = tls_;
335
358
  alpn_s *alpn;
@@ -358,7 +381,8 @@ static int fio_tls_alpn_selector_cb(SSL *ssl, const unsigned char **out,
358
381
  alpn_select(alpn, c->uuid, c->alpn_arg);
359
382
  FIO_LOG_DEBUG(
360
383
  "TLS ALPN handshake failed, falling back on default (%s) for %p",
361
- fio_str_data(&alpn->name), (void *)c->uuid);
384
+ fio_str_data(&alpn->name),
385
+ (void *)c->uuid);
362
386
  return SSL_TLSEXT_ERR_NOACK;
363
387
  (void)ssl;
364
388
  (void)out;
@@ -380,7 +404,9 @@ static void fio_tls_destroy_context(fio_tls_s *tls) {
380
404
  FIO_LOG_DEBUG("destroyed TLS context for OpenSSL %p", (void *)tls);
381
405
  }
382
406
 
383
- static int fio_tls_pem_passwd_cb(char *buf, int size, int rwflag,
407
+ static int fio_tls_pem_passwd_cb(char *buf,
408
+ int size,
409
+ int rwflag,
384
410
  void *password) {
385
411
  fio_str_info_s *p = password;
386
412
  if (!p || !p->len || !size)
@@ -407,7 +433,8 @@ static void fio_tls_build_context(fio_tls_s *tls) {
407
433
  /* attach certificates */
408
434
  FIO_ARY_FOR(&tls->sni, pos) {
409
435
  fio_str_info_s keys[4] = {
410
- fio_str_info(&pos->private_key), fio_str_info(&pos->public_key),
436
+ fio_str_info(&pos->private_key),
437
+ fio_str_info(&pos->public_key),
411
438
  fio_str_info(&pos->password),
412
439
  /* empty password slot for public key */
413
440
  };
@@ -416,8 +443,10 @@ static void fio_tls_build_context(fio_tls_s *tls) {
416
443
  /* Extract private key from private key file */
417
444
  BIO *bio = BIO_new_mem_buf(keys[0].data, keys[0].len);
418
445
  if (bio) {
419
- EVP_PKEY *k = PEM_read_bio_PrivateKey(
420
- bio, NULL, fio_tls_pem_passwd_cb, keys + 2);
446
+ EVP_PKEY *k = PEM_read_bio_PrivateKey(bio,
447
+ NULL,
448
+ fio_tls_pem_passwd_cb,
449
+ keys + 2);
421
450
  if (k) {
422
451
  FIO_LOG_DEBUG("TLS read private key from PEM file.");
423
452
  SSL_CTX_use_PrivateKey(tls->ctx, k);
@@ -430,15 +459,21 @@ static void fio_tls_build_context(fio_tls_s *tls) {
430
459
  /* Extract as much data as possible from each file */
431
460
  BIO *bio = BIO_new_mem_buf(keys[ki].data, keys[ki].len);
432
461
  FIO_ASSERT(bio, "OpenSSL error allocating BIO.");
433
- STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(
434
- bio, NULL, fio_tls_pem_passwd_cb, keys + ki + 2);
462
+ STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(bio,
463
+ NULL,
464
+ fio_tls_pem_passwd_cb,
465
+ keys + ki + 2);
435
466
  if (inf) {
436
467
  for (int i = 0; i < sk_X509_INFO_num(inf); ++i) {
437
468
  /* for each element in PEM */
438
469
  X509_INFO *tmp = sk_X509_INFO_value(inf, i);
439
470
  if (tmp->x509) {
440
471
  FIO_LOG_DEBUG("TLS adding certificate from PEM file.");
441
- SSL_CTX_use_certificate(tls->ctx, tmp->x509);
472
+ if (i == 0) {
473
+ SSL_CTX_use_certificate(tls->ctx, tmp->x509);
474
+ } else {
475
+ SSL_CTX_add1_chain_cert(tls->ctx, tmp->x509);
476
+ }
442
477
  }
443
478
  if (tmp->x_pkey) {
444
479
  FIO_LOG_DEBUG("TLS adding private key from PEM file.");
@@ -541,7 +576,9 @@ static void fio_tls_delayed_close(void *uuid, void *ignr_) {
541
576
  * Note: facil.io library functions MUST NEVER be called by any r/w hook, or a
542
577
  * deadlock might occur.
543
578
  */
544
- static ssize_t fio_tls_read(intptr_t uuid, void *udata, void *buf,
579
+ static ssize_t fio_tls_read(intptr_t uuid,
580
+ void *udata,
581
+ void *buf,
545
582
  size_t count) {
546
583
  fio_tls_connection_s *c = udata;
547
584
  ssize_t ret = SSL_read(c->ssl, buf, count);
@@ -549,23 +586,19 @@ static ssize_t fio_tls_read(intptr_t uuid, void *udata, void *buf,
549
586
  return ret;
550
587
  ret = SSL_get_error(c->ssl, ret);
551
588
  switch (ret) {
552
- case SSL_ERROR_SSL: /* overflow */
553
- case SSL_ERROR_ZERO_RETURN:
554
- return 0; /* EOF */
555
- case SSL_ERROR_SYSCALL: /* allow errno to inform us */
556
- break; /* return -1 */
557
- case SSL_ERROR_NONE: /* overflow */
558
- case SSL_ERROR_WANT_CONNECT: /* overflow */
559
- case SSL_ERROR_WANT_ACCEPT: /* overflow */
560
- case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
561
- case SSL_ERROR_WANT_WRITE: /* overflow */
562
- case SSL_ERROR_WANT_READ: /* overflow */
589
+ case SSL_ERROR_SSL: /* overflow */
590
+ case SSL_ERROR_ZERO_RETURN: return 0; /* EOF */
591
+ case SSL_ERROR_SYSCALL: /* allow errno to inform us */ break; /* return -1 */
592
+ case SSL_ERROR_NONE: /* overflow */
593
+ case SSL_ERROR_WANT_CONNECT: /* overflow */
594
+ case SSL_ERROR_WANT_ACCEPT: /* overflow */
595
+ case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
596
+ case SSL_ERROR_WANT_WRITE: /* overflow */
597
+ case SSL_ERROR_WANT_READ: /* overflow */
563
598
  #ifdef SSL_ERROR_WANT_ASYNC
564
- case SSL_ERROR_WANT_ASYNC: /* overflow */
599
+ case SSL_ERROR_WANT_ASYNC: /* overflow */
565
600
  #endif
566
- default:
567
- errno = EWOULDBLOCK;
568
- break;
601
+ default: errno = EWOULDBLOCK; break;
569
602
  }
570
603
  return -1;
571
604
  (void)uuid;
@@ -597,7 +630,9 @@ static ssize_t fio_tls_flush(intptr_t uuid, void *udata) {
597
630
  * Note: facil.io library functions MUST NEVER be called by any r/w hook, or a
598
631
  * deadlock might occur.
599
632
  */
600
- static ssize_t fio_tls_write(intptr_t uuid, void *udata, const void *buf,
633
+ static ssize_t fio_tls_write(intptr_t uuid,
634
+ void *udata,
635
+ const void *buf,
601
636
  size_t count) {
602
637
  fio_tls_connection_s *c = udata;
603
638
  ssize_t ret = SSL_write(c->ssl, buf, count);
@@ -605,23 +640,19 @@ static ssize_t fio_tls_write(intptr_t uuid, void *udata, const void *buf,
605
640
  return ret;
606
641
  ret = SSL_get_error(c->ssl, ret);
607
642
  switch (ret) {
608
- case SSL_ERROR_SSL: /* overflow */
609
- case SSL_ERROR_ZERO_RETURN:
610
- return 0; /* EOF */
611
- case SSL_ERROR_SYSCALL: /* allow errno to inform us */
612
- break; /* return -1 */
613
- case SSL_ERROR_NONE: /* overflow */
614
- case SSL_ERROR_WANT_CONNECT: /* overflow */
615
- case SSL_ERROR_WANT_ACCEPT: /* overflow */
616
- case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
617
- case SSL_ERROR_WANT_WRITE: /* overflow */
618
- case SSL_ERROR_WANT_READ: /* overflow */
643
+ case SSL_ERROR_SSL: /* overflow */
644
+ case SSL_ERROR_ZERO_RETURN: return 0; /* EOF */
645
+ case SSL_ERROR_SYSCALL: /* allow errno to inform us */ break; /* return -1 */
646
+ case SSL_ERROR_NONE: /* overflow */
647
+ case SSL_ERROR_WANT_CONNECT: /* overflow */
648
+ case SSL_ERROR_WANT_ACCEPT: /* overflow */
649
+ case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
650
+ case SSL_ERROR_WANT_WRITE: /* overflow */
651
+ case SSL_ERROR_WANT_READ: /* overflow */
619
652
  #ifdef SSL_ERROR_WANT_ASYNC
620
- case SSL_ERROR_WANT_ASYNC: /* overflow */
653
+ case SSL_ERROR_WANT_ASYNC: /* overflow */
621
654
  #endif
622
- default:
623
- errno = EWOULDBLOCK;
624
- break;
655
+ default: errno = EWOULDBLOCK; break;
625
656
  }
626
657
  return -1;
627
658
  (void)uuid;
@@ -664,9 +695,9 @@ static fio_rw_hook_s FIO_TLS_HOOKS = {
664
695
  .cleanup = fio_tls_cleanup,
665
696
  };
666
697
 
667
- #define FIO_TLS_HANDSHAKE_ERROR 0
668
- #define FIO_TLS_HANDSHAKE_OK 1
669
- #define FIO_TLS_HANDSHAKE_NEED_READ 2
698
+ #define FIO_TLS_HANDSHAKE_ERROR 0
699
+ #define FIO_TLS_HANDSHAKE_OK 1
700
+ #define FIO_TLS_HANDSHAKE_NEED_READ 2
670
701
  #define FIO_TLS_HANDSHAKE_NEED_WRITE 4
671
702
 
672
703
  static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
@@ -701,7 +732,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
701
732
  if (errno) {
702
733
  FIO_LOG_DEBUG(
703
734
  "SSL_accept/SSL_connect %p error: SSL_ERROR_SYSCALL, errno: %s",
704
- (void *)uuid, strerror(errno));
735
+ (void *)uuid,
736
+ strerror(errno));
705
737
  }
706
738
  break;
707
739
  case SSL_ERROR_SSL:
@@ -741,7 +773,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
741
773
  #endif
742
774
  default:
743
775
  FIO_LOG_DEBUG("SSL_accept/SSL_connect %p error: unknown (%d).",
744
- (void *)uuid, ri);
776
+ (void *)uuid,
777
+ ri);
745
778
  break;
746
779
  }
747
780
  fio_rw_hook_replace_unsafe(uuid, &FIO_TLS_HOOKS, udata);
@@ -766,7 +799,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
766
799
  }
767
800
  if (alpn)
768
801
  FIO_LOG_DEBUG("setting ALPN %s for TLS client %p",
769
- fio_str_data(&alpn->name), (void *)uuid);
802
+ fio_str_data(&alpn->name),
803
+ (void *)uuid);
770
804
  alpn_select(alpn, c->uuid, c->alpn_arg);
771
805
  }
772
806
  }
@@ -783,7 +817,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
783
817
  #if FIO_TLS_PRINT_SECRET
784
818
  if (FIO_LOG_LEVEL >= FIO_LOG_LEVEL_DEBUG) {
785
819
  unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH + 2];
786
- size_t ret = SSL_SESSION_get_master_key(SSL_get_session(c->ssl), buff,
820
+ size_t ret = SSL_SESSION_get_master_key(SSL_get_session(c->ssl),
821
+ buff,
787
822
  SSL_MAX_MASTER_KEY_LENGTH + 1);
788
823
  buff[ret] = 0;
789
824
  unsigned char buff2[(SSL_MAX_MASTER_KEY_LENGTH + 2) << 1];
@@ -794,7 +829,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
794
829
  : ('0' + (buff[i] & 15));
795
830
  }
796
831
  buff2[(ret << 1)] = 0;
797
- FIO_LOG_DEBUG("OpenSSL Master Key for uuid %p:\n\t\t%s", (void *)uuid,
832
+ FIO_LOG_DEBUG("OpenSSL Master Key for uuid %p:\n\t\t%s",
833
+ (void *)uuid,
798
834
  buff2);
799
835
  }
800
836
  #endif
@@ -802,7 +838,9 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
802
838
  return status;
803
839
  }
804
840
 
805
- static ssize_t fio_tls_read4handshake(intptr_t uuid, void *udata, void *buf,
841
+ static ssize_t fio_tls_read4handshake(intptr_t uuid,
842
+ void *udata,
843
+ void *buf,
806
844
  size_t count) {
807
845
  // FIO_LOG_DEBUG("TLS handshake from read %p", (void *)uuid);
808
846
  size_t s = fio_tls_handshake(uuid, udata);
@@ -814,8 +852,10 @@ static ssize_t fio_tls_read4handshake(intptr_t uuid, void *udata, void *buf,
814
852
  return -1;
815
853
  }
816
854
 
817
- static ssize_t fio_tls_write4handshake(intptr_t uuid, void *udata,
818
- const void *buf, size_t count) {
855
+ static ssize_t fio_tls_write4handshake(intptr_t uuid,
856
+ void *udata,
857
+ const void *buf,
858
+ size_t count) {
819
859
  // FIO_LOG_DEBUG("TLS handshake from write %p", (void *)uuid);
820
860
  size_t s = fio_tls_handshake(uuid, udata);
821
861
  if (s == FIO_TLS_HANDSHAKE_OK)
@@ -845,8 +885,10 @@ static fio_rw_hook_s FIO_TLS_HANDSHAKE_HOOKS = {
845
885
  .flush = fio_tls_flush4handshake,
846
886
  .cleanup = fio_tls_cleanup,
847
887
  };
848
- static inline void fio_tls_attach2uuid(intptr_t uuid, fio_tls_s *tls,
849
- void *udata, uint8_t is_server) {
888
+ static inline void fio_tls_attach2uuid(intptr_t uuid,
889
+ fio_tls_s *tls,
890
+ void *udata,
891
+ uint8_t is_server) {
850
892
  fio_atomic_add(&tls->ref, 1);
851
893
  /* create SSL connection context from global context */
852
894
  fio_tls_connection_s *c = malloc(sizeof(*c));
@@ -891,8 +933,10 @@ SSL/TLS API implementation - this can be pretty much used as is...
891
933
  * Creates a new SSL/TLS context / settings object with a default certificate
892
934
  * (if any).
893
935
  */
894
- fio_tls_s *FIO_TLS_WEAK fio_tls_new(const char *server_name, const char *cert,
895
- const char *key, const char *pk_password) {
936
+ fio_tls_s *FIO_TLS_WEAK fio_tls_new(const char *server_name,
937
+ const char *cert,
938
+ const char *key,
939
+ const char *pk_password) {
896
940
  REQUIRE_LIBRARY();
897
941
  fio_tls_s *tls = calloc(sizeof(*tls), 1);
898
942
  tls->ref = 1;
@@ -903,8 +947,10 @@ fio_tls_s *FIO_TLS_WEAK fio_tls_new(const char *server_name, const char *cert,
903
947
  /**
904
948
  * Adds a certificate a new SSL/TLS context / settings object.
905
949
  */
906
- void FIO_TLS_WEAK fio_tls_cert_add(fio_tls_s *tls, const char *server_name,
907
- const char *cert, const char *key,
950
+ void FIO_TLS_WEAK fio_tls_cert_add(fio_tls_s *tls,
951
+ const char *server_name,
952
+ const char *cert,
953
+ const char *key,
908
954
  const char *pk_password) {
909
955
  REQUIRE_LIBRARY();
910
956
  cert_s c = {
@@ -929,7 +975,8 @@ void FIO_TLS_WEAK fio_tls_cert_add(fio_tls_s *tls, const char *server_name,
929
975
  return;
930
976
  file_missing:
931
977
  FIO_LOG_FATAL("TLS certificate file missing for either %s or %s or both.",
932
- key, cert);
978
+ key,
979
+ cert);
933
980
  exit(-1);
934
981
  }
935
982
 
@@ -950,10 +997,13 @@ file_missing:
950
997
  * Except for the `tls` and `protocol_name` arguments, all arguments can be
951
998
  * NULL.
952
999
  */
953
- void FIO_TLS_WEAK fio_tls_alpn_add(
954
- fio_tls_s *tls, const char *protocol_name,
955
- void (*on_selected)(intptr_t uuid, void *udata_connection, void *udata_tls),
956
- void *udata_tls, void (*on_cleanup)(void *udata_tls)) {
1000
+ void FIO_TLS_WEAK fio_tls_alpn_add(fio_tls_s *tls,
1001
+ const char *protocol_name,
1002
+ void (*on_selected)(intptr_t uuid,
1003
+ void *udata_connection,
1004
+ void *udata_tls),
1005
+ void *udata_tls,
1006
+ void (*on_cleanup)(void *udata_tls)) {
957
1007
  REQUIRE_LIBRARY();
958
1008
  alpn_add(tls, protocol_name, on_selected, udata_tls, on_cleanup);
959
1009
  fio_tls_build_context(tls);
@@ -63,6 +63,17 @@ Object required VTable and functions
63
63
  } \
64
64
  } while (0)
65
65
 
66
+ static inline int64_t fiobj_data_get_fd_size(const FIOBJ o) {
67
+ struct stat stat;
68
+ retry:
69
+ if (fstat(obj2io(o)->fd, &stat)) {
70
+ if (errno == EINTR)
71
+ goto retry;
72
+ return -1;
73
+ }
74
+ return stat.st_size;
75
+ }
76
+
66
77
  static void fiobj_data_copy_buffer(FIOBJ o) {
67
78
  obj2io(o)->capa = (((obj2io(o)->len) >> 12) + 1) << 12;
68
79
  void *tmp = fio_malloc(obj2io(o)->capa);
@@ -145,17 +156,6 @@ static inline void fiobj_data_pre_write(FIOBJ o, uintptr_t length) {
145
156
  REQUIRE_MEM(obj2io(o)->buffer);
146
157
  }
147
158
 
148
- static inline int64_t fiobj_data_get_fd_size(const FIOBJ o) {
149
- struct stat stat;
150
- retry:
151
- if (fstat(obj2io(o)->fd, &stat)) {
152
- if (errno == EINTR)
153
- goto retry;
154
- return -1;
155
- }
156
- return stat.st_size;
157
- }
158
-
159
159
  static FIOBJ fiobj_data_alloc(void *buffer, int fd) {
160
160
  fiobj_data_s *io = fio_malloc(sizeof(*io));
161
161
  REQUIRE_MEM(io);
@@ -963,6 +963,7 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
963
963
  /* Unslice slices */
964
964
  if (obj2io(io)->fd == -2)
965
965
  fiobj_data_assert_dynamic(io);
966
+
966
967
  if (obj2io(io)->fd == -1) {
967
968
  /* String Code */
968
969
  fiobj_data_pre_write(io, length + 1);
@@ -971,6 +972,7 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
971
972
  obj2io(io)->buffer[obj2io(io)->len] = 0;
972
973
  return length;
973
974
  }
975
+
974
976
  /* File Code */
975
977
  return pwrite(obj2io(io)->fd, buffer, length, fiobj_data_get_fd_size(io));
976
978
  }
@@ -38,7 +38,7 @@ static inline __attribute__((unused)) FIOBJ fiobj_str_copy(FIOBJ src) {
38
38
  /**
39
39
  * Creates a String object. Remember to use `fiobj_free`.
40
40
  *
41
- * It's possible to wrap a previosly allocated memory block in a FIOBJ String
41
+ * It's possible to wrap a previously allocated memory block in a FIOBJ String
42
42
  * object, as long as it was allocated using `fio_malloc`.
43
43
  *
44
44
  * The ownership of the memory indicated by `str` will "move" to the object and
@@ -147,10 +147,10 @@ FIO_INLINE double fiobj_obj2float(const FIOBJ obj);
147
147
  /**
148
148
  * Returns a C String (NUL terminated) using the `fio_str_info_s` data type.
149
149
  *
150
- * The Sting in binary safe and might contain NUL bytes in the middle as well as
151
- * a terminating NUL.
150
+ * The String is binary safe and might contain NUL bytes in the middle as well
151
+ * as a terminating NUL.
152
152
  *
153
- * If a a Number or a Float are passed to the function, they
153
+ * If a Number or a Float are passed to the function, they
154
154
  * will be parsed as a *temporary*, thread-safe, String.
155
155
  *
156
156
  * Numbers will be represented in base 10 numerical data.
@@ -270,7 +270,8 @@ FIO_INLINE size_t fiobj_type_is(FIOBJ o, fiobj_type_enum type) {
270
270
  switch (type) {
271
271
  case FIOBJ_T_NUMBER:
272
272
  return (o & FIOBJECT_NUMBER_FLAG) ||
273
- ((fiobj_type_enum *)o)[0] == FIOBJ_T_NUMBER;
273
+ (o && !(o & FIOBJECT_PRIMITIVE_FLAG) &&
274
+ ((fiobj_type_enum *)o)[0] == FIOBJ_T_NUMBER);
274
275
  case FIOBJ_T_NULL:
275
276
  return !o || o == fiobj_null();
276
277
  case FIOBJ_T_TRUE:
data/ext/iodine/http1.c CHANGED
@@ -45,6 +45,8 @@ inline static void h1_reset(http1pr_s *p) { p->header_size = 0; }
45
45
  #define http1_pr2handle(pr) (((http1pr_s *)(pr))->request)
46
46
  #define handle2pr(h) ((http1pr_s *)h->private_data.flag)
47
47
 
48
+ static fio_str_info_s http1pr_status2str(uintptr_t status);
49
+
48
50
  /* cleanup an HTTP/1.1 handler object */
49
51
  static inline void http1_after_finish(http_s *h) {
50
52
  http1pr_s *p = handle2pr(h);
@@ -110,10 +112,8 @@ static FIOBJ headers2str(http_s *h, uintptr_t padding) {
110
112
  http1pr_s *p = handle2pr(h);
111
113
 
112
114
  if (p->is_client == 0) {
113
- fio_str_info_s t = http_status2str(h->status);
114
- fiobj_str_write(w.dest, "HTTP/1.1 ", 9);
115
+ fio_str_info_s t = http1pr_status2str(h->status);
115
116
  fiobj_str_write(w.dest, t.data, t.len);
116
- fiobj_str_write(w.dest, "\r\n", 2);
117
117
  FIOBJ tmp = fiobj_hash_get2(h->private_data.out_headers, connection_hash);
118
118
  if (tmp) {
119
119
  t = fiobj_obj2cstr(tmp);
@@ -787,8 +787,7 @@ fio_protocol_s *http1_new(uintptr_t uuid, http_settings_s *settings,
787
787
  if (unread_data && unread_length > HTTP_MAX_HEADER_LENGTH)
788
788
  return NULL;
789
789
  http1pr_s *p = fio_malloc(sizeof(*p) + HTTP_MAX_HEADER_LENGTH);
790
- // FIO_LOG_DEBUG("Allocated HTTP/1.1 protocol %p(%d)=>%p", (void *)uuid,
791
- // (int)fio_uuid2fd(uuid), (void *)p);
790
+ // FIO_LOG_DEBUG("Allocated HTTP/1.1 protocol at. %p", (void *)p);
792
791
  FIO_ASSERT_ALLOC(p);
793
792
  *p = (http1pr_s){
794
793
  .p.protocol =
@@ -819,7 +818,93 @@ void http1_destroy(fio_protocol_s *pr) {
819
818
  http1pr_s *p = (http1pr_s *)pr;
820
819
  http1_pr2handle(p).status = 0;
821
820
  http_s_destroy(&http1_pr2handle(p), 0);
822
- // FIO_LOG_DEBUG("Deallocating HTTP/1.1 protocol %p(%d)=>%p", (void
823
- // *)p->p.uuid, (int)fio_uuid2fd(p->p.uuid), (void *)p);
824
821
  fio_free(p); // occasional Windows crash bug
822
+ // FIO_LOG_DEBUG("Deallocated HTTP/1.1 protocol at. %p", (void *)p);
823
+ }
824
+
825
+ /* *****************************************************************************
826
+ Protocol Data
827
+ ***************************************************************************** */
828
+
829
+ // clang-format off
830
+ #define HTTP_SET_STATUS_STR(status, str) [((status)-100)] = { .data = (char*)("HTTP/1.1 " #status " " str "\r\n"), .len = (sizeof("HTTP/1.1 " #status " " str "\r\n") - 1) }
831
+ // #undef HTTP_SET_STATUS_STR
832
+ // clang-format on
833
+
834
+ static fio_str_info_s http1pr_status2str(uintptr_t status) {
835
+ static fio_str_info_s status2str[] = {
836
+ HTTP_SET_STATUS_STR(100, "Continue"),
837
+ HTTP_SET_STATUS_STR(101, "Switching Protocols"),
838
+ HTTP_SET_STATUS_STR(102, "Processing"),
839
+ HTTP_SET_STATUS_STR(103, "Early Hints"),
840
+ HTTP_SET_STATUS_STR(200, "OK"),
841
+ HTTP_SET_STATUS_STR(201, "Created"),
842
+ HTTP_SET_STATUS_STR(202, "Accepted"),
843
+ HTTP_SET_STATUS_STR(203, "Non-Authoritative Information"),
844
+ HTTP_SET_STATUS_STR(204, "No Content"),
845
+ HTTP_SET_STATUS_STR(205, "Reset Content"),
846
+ HTTP_SET_STATUS_STR(206, "Partial Content"),
847
+ HTTP_SET_STATUS_STR(207, "Multi-Status"),
848
+ HTTP_SET_STATUS_STR(208, "Already Reported"),
849
+ HTTP_SET_STATUS_STR(226, "IM Used"),
850
+ HTTP_SET_STATUS_STR(300, "Multiple Choices"),
851
+ HTTP_SET_STATUS_STR(301, "Moved Permanently"),
852
+ HTTP_SET_STATUS_STR(302, "Found"),
853
+ HTTP_SET_STATUS_STR(303, "See Other"),
854
+ HTTP_SET_STATUS_STR(304, "Not Modified"),
855
+ HTTP_SET_STATUS_STR(305, "Use Proxy"),
856
+ HTTP_SET_STATUS_STR(306, "(Unused), "),
857
+ HTTP_SET_STATUS_STR(307, "Temporary Redirect"),
858
+ HTTP_SET_STATUS_STR(308, "Permanent Redirect"),
859
+ HTTP_SET_STATUS_STR(400, "Bad Request"),
860
+ HTTP_SET_STATUS_STR(403, "Forbidden"),
861
+ HTTP_SET_STATUS_STR(404, "Not Found"),
862
+ HTTP_SET_STATUS_STR(401, "Unauthorized"),
863
+ HTTP_SET_STATUS_STR(402, "Payment Required"),
864
+ HTTP_SET_STATUS_STR(405, "Method Not Allowed"),
865
+ HTTP_SET_STATUS_STR(406, "Not Acceptable"),
866
+ HTTP_SET_STATUS_STR(407, "Proxy Authentication Required"),
867
+ HTTP_SET_STATUS_STR(408, "Request Timeout"),
868
+ HTTP_SET_STATUS_STR(409, "Conflict"),
869
+ HTTP_SET_STATUS_STR(410, "Gone"),
870
+ HTTP_SET_STATUS_STR(411, "Length Required"),
871
+ HTTP_SET_STATUS_STR(412, "Precondition Failed"),
872
+ HTTP_SET_STATUS_STR(413, "Payload Too Large"),
873
+ HTTP_SET_STATUS_STR(414, "URI Too Long"),
874
+ HTTP_SET_STATUS_STR(415, "Unsupported Media Type"),
875
+ HTTP_SET_STATUS_STR(416, "Range Not Satisfiable"),
876
+ HTTP_SET_STATUS_STR(417, "Expectation Failed"),
877
+ HTTP_SET_STATUS_STR(421, "Misdirected Request"),
878
+ HTTP_SET_STATUS_STR(422, "Unprocessable Entity"),
879
+ HTTP_SET_STATUS_STR(423, "Locked"),
880
+ HTTP_SET_STATUS_STR(424, "Failed Dependency"),
881
+ HTTP_SET_STATUS_STR(425, "Unassigned"),
882
+ HTTP_SET_STATUS_STR(426, "Upgrade Required"),
883
+ HTTP_SET_STATUS_STR(427, "Unassigned"),
884
+ HTTP_SET_STATUS_STR(428, "Precondition Required"),
885
+ HTTP_SET_STATUS_STR(429, "Too Many Requests"),
886
+ HTTP_SET_STATUS_STR(430, "Unassigned"),
887
+ HTTP_SET_STATUS_STR(431, "Request Header Fields Too Large"),
888
+ HTTP_SET_STATUS_STR(500, "Internal Server Error"),
889
+ HTTP_SET_STATUS_STR(501, "Not Implemented"),
890
+ HTTP_SET_STATUS_STR(502, "Bad Gateway"),
891
+ HTTP_SET_STATUS_STR(503, "Service Unavailable"),
892
+ HTTP_SET_STATUS_STR(504, "Gateway Timeout"),
893
+ HTTP_SET_STATUS_STR(505, "HTTP Version Not Supported"),
894
+ HTTP_SET_STATUS_STR(506, "Variant Also Negotiates"),
895
+ HTTP_SET_STATUS_STR(507, "Insufficient Storage"),
896
+ HTTP_SET_STATUS_STR(508, "Loop Detected"),
897
+ HTTP_SET_STATUS_STR(509, "Unassigned"),
898
+ HTTP_SET_STATUS_STR(510, "Not Extended"),
899
+ HTTP_SET_STATUS_STR(511, "Network Authentication Required"),
900
+ };
901
+ fio_str_info_s ret = (fio_str_info_s){.len = 0, .data = NULL};
902
+ if (status >= 100 &&
903
+ (status - 100) < sizeof(status2str) / sizeof(status2str[0]))
904
+ ret = status2str[status - 100];
905
+ if (!ret.data) {
906
+ ret = status2str[400];
907
+ }
908
+ return ret;
825
909
  }
910
+ #undef HTTP_SET_STATUS_STR