From 63cdf7b3bb69312200c067e8fb8d40b13262a30e Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 6 Aug 2021 03:23:48 +0000 Subject: [PATCH] enhanced hio_svc_htts_start() to accept multiple binding addresses. added hio_skad_init_for_qx() defined HIO_AF_QX changed hio-skad to defined HIO_AF_UNIX to a fake value if it's not defined. fixed skad conversion functions to handle unix addresses more consistently --- hio/bin/t01.c | 2 +- hio/bin/t06.c | 73 +++++++------ hio/lib/hio-http.h | 18 +++- hio/lib/hio-sck.h | 2 +- hio/lib/hio-skad.h | 11 ++ hio/lib/http-prv.h | 11 +- hio/lib/http-svr.c | 254 +++++++++++++++++++++++++++++++++------------ hio/lib/sck.c | 24 +++-- hio/lib/skad.c | 103 ++++++++++++++---- 9 files changed, 370 insertions(+), 128 deletions(-) diff --git a/hio/bin/t01.c b/hio/bin/t01.c index 9cccde5..253896c 100644 --- a/hio/bin/t01.c +++ b/hio/bin/t01.c @@ -1237,7 +1237,7 @@ for (i = 0; i < 5; i++) HIO_INFO1 (hio, "UNABLE TO START DNC - %js\n", hio_geterrmsg(hio)); } - htts = hio_svc_htts_start(hio, &htts_bind_info, process_http_request); + htts = hio_svc_htts_start(hio, &htts_bind_info, 1, process_http_request); if (htts) hio_svc_htts_setservernamewithbcstr (htts, "HIO-HTTP"); else HIO_INFO1 (hio, "UNABLE TO START HTTS - %js\n", hio_geterrmsg(hio)); diff --git a/hio/bin/t06.c b/hio/bin/t06.c index 88893b6..be37ab3 100644 --- a/hio/bin/t06.c +++ b/hio/bin/t06.c @@ -11,7 +11,6 @@ #include #define MAX_NUM_THRS 256 -static int g_reuse_port = 0; static int g_num_thrs = 2; static hio_svc_htts_t* g_htts[MAX_NUM_THRS]; static int g_htts_no = 0; @@ -216,7 +215,7 @@ void* thr_func (void* arg) { hio_t* hio = HIO_NULL; hio_svc_htts_t* htts = HIO_NULL; - hio_dev_sck_bind_t htts_bind_info; + hio_dev_sck_bind_t htts_bind_info[2]; int htts_no = -1; hio = hio_open(HIO_NULL, 0, HIO_NULL, HIO_FEATURE_ALL, 512, HIO_NULL); @@ -229,16 +228,17 @@ void* thr_func (void* arg) hio_setoption (hio, HIO_LOG_TARGET_BCSTR, "/dev/stderr"); memset (&htts_bind_info, 0, HIO_SIZEOF(htts_bind_info)); - if (g_reuse_port) - { - hio_bcstrtoskad (hio, "0.0.0.0:9987", &htts_bind_info.localaddr); - htts_bind_info.options = HIO_DEV_SCK_BIND_REUSEADDR | HIO_DEV_SCK_BIND_REUSEPORT | HIO_DEV_SCK_BIND_IGNERR; - //htts_bind_info.options |= HIO_DEV_SCK_BIND_SSL; - htts_bind_info.ssl_certfile = "localhost.crt"; - htts_bind_info.ssl_keyfile = "localhost.key"; - } + hio_skad_init_for_qx (&htts_bind_info[0].localaddr); - htts = hio_svc_htts_start(hio, &htts_bind_info, process_http_request); + hio_bcstrtoskad (hio, "0.0.0.0:9988", &htts_bind_info[1].localaddr); + htts_bind_info[1].options = HIO_DEV_SCK_BIND_REUSEADDR | HIO_DEV_SCK_BIND_REUSEPORT | HIO_DEV_SCK_BIND_IGNERR; +#if 0 + htts_bind_info[1].options |= HIO_DEV_SCK_BIND_SSL; + htts_bind_info[1].ssl_certfile = "localhost.crt"; + htts_bind_info[1].ssl_keyfile = "localhost.key"; +#endif + + htts = hio_svc_htts_start(hio, &htts_bind_info, HIO_COUNTOF(htts_bind_info), process_http_request); if (!htts) { printf ("Unable to start htts\n"); @@ -251,9 +251,7 @@ void* thr_func (void* arg) g_htts_no = (g_htts_no + 1) % g_num_thrs; pthread_mutex_unlock (&g_htts_mutex); -printf ("entering the loop for %d\n", htts_no); hio_loop (hio); -printf ("exiting the loop for %d\n", htts_no); oops: pthread_mutex_lock (&g_htts_mutex); @@ -387,7 +385,7 @@ static int try_to_accept (hio_dev_sck_t* sck, hio_dev_sck_qxmsg_t* qxmsg, int in g_htts_no = (g_htts_no + 1) % g_num_thrs; pthread_mutex_unlock (&g_htts_mutex); - if (hio_svc_htts_writetosidechan(htts, qxmsg, HIO_SIZEOF(*qxmsg)) <= -1) + if (hio_svc_htts_writetosidechan(htts, 0, qxmsg, HIO_SIZEOF(*qxmsg)) <= -1) { hio_bch_t buf[128]; @@ -470,6 +468,7 @@ static int add_listener (hio_t* hio, hio_bch_t* addrstr) hio_dev_sck_t* tcp; hio_dev_sck_bind_t bi; hio_dev_sck_listen_t li; + int f; memset (&bi, 0, HIO_SIZEOF(bi)); if (hio_bcstrtoskad(hio, addrstr, &bi.localaddr) <= -1) @@ -485,7 +484,16 @@ static int add_listener (hio_t* hio, hio_bch_t* addrstr) #endif memset (&mi, 0, HIO_SIZEOF(mi)); - mi.type = (hio_skad_family(&bi.localaddr) == HIO_AF_INET? HIO_DEV_SCK_TCP4: HIO_DEV_SCK_TCP6); + f = hio_skad_family(&bi.localaddr); + if (f == HIO_AF_INET) mi.type = HIO_DEV_SCK_TCP4; + else if (f == HIO_AF_INET6) mi.type = HIO_DEV_SCK_TCP6; + else if (f == HIO_AF_UNIX) mi.type = HIO_DEV_SCK_UNIX; + else + { + HIO_INFO1 (hio, "unsupported address type - %hs\n", addrstr); + return -1; + } + mi.options = HIO_DEV_SCK_MAKE_LENIENT; mi.on_write = tcp_sck_on_write; mi.on_read = tcp_sck_on_read; @@ -496,17 +504,14 @@ static int add_listener (hio_t* hio, hio_bch_t* addrstr) tcp = hio_dev_sck_make(hio, 0, &mi); if (!tcp) { - HIO_INFO1 (hio, "Cannot make tcp - %js\n", hio_geterrmsg(hio)); + HIO_INFO2 (hio, "Cannot make tcp for %hs - %js\n", addrstr, hio_geterrmsg(hio)); return -1; } - if (!g_reuse_port) + if (hio_dev_sck_bind(tcp, &bi) <= -1) { - if (hio_dev_sck_bind(tcp, &bi) <= -1) - { - HIO_INFO1 (hio, "tcp hio_dev_sck_bind() failed - %js\n", hio_geterrmsg(hio)); - return -1; - } + HIO_INFO2 (hio, "tcp hio_dev_sck_bind() failed with %hs - %js\n", addrstr, hio_geterrmsg(hio)); + return -1; } memset (&li, 0, HIO_SIZEOF(li)); @@ -514,9 +519,17 @@ static int add_listener (hio_t* hio, hio_bch_t* addrstr) HIO_INIT_NTIME (&li.accept_tmout, 5, 1); if (hio_dev_sck_listen(tcp, &li) <= -1) { - HIO_INFO1 (hio, "tcp[2] hio_dev_sck_listen() failed - %js\n", hio_geterrmsg(hio)); + HIO_INFO2 (hio, "tcp hio_dev_sck_listen() failed on %hs - %js\n", addrstr, hio_geterrmsg(hio)); return -1; } + else + { + hio_skad_t skad; + hio_bch_t buf[HIO_SKAD_IP_STRLEN + 1]; + hio_dev_sck_getsockaddr (tcp, &skad); + hio_skadtobcstr (hio, &skad, buf, HIO_COUNTOF(buf), HIO_SKAD_TO_BCSTR_ADDR | HIO_SKAD_TO_BCSTR_PORT); + HIO_INFO1 (hio, "main listener on %hs\n", buf); + } return 0; } @@ -540,12 +553,7 @@ int main (int argc, char* argv[]) // TODO: use getopt() or something similar for (i = 1; i < argc; ) { - if (strcmp(argv[i], "-r") == 0) - { - g_reuse_port = 1; - i++; - } - else if (strcmp(argv[i], "-t") == 0) + if (strcmp(argv[i], "-t") == 0) { i++; if (i < argc) @@ -602,9 +610,12 @@ int main (int argc, char* argv[]) if (add_listener(hio, "[::]:9987") <= -1 || add_listener(hio, "0.0.0.0:9987") <= -1) goto oops; -printf ("entering the main loop\n"); + /* add a unix socket listener. + * don't check for an error to continue without it in case it fails. */ + unlink ("t06.sck"); + add_listener(hio, "@t06.sck"); + hio_loop (hio); -printf ("exiting the main loop\n"); xret = 0; diff --git a/hio/lib/hio-http.h b/hio/lib/hio-http.h index 90872aa..2afaaf7 100644 --- a/hio/lib/hio-http.h +++ b/hio/lib/hio-http.h @@ -250,7 +250,8 @@ HIO_EXPORT int hio_scan_http_qparam ( HIO_EXPORT hio_svc_htts_t* hio_svc_htts_start ( hio_t* hio, - hio_dev_sck_bind_t* sck_bind, + hio_dev_sck_bind_t* binds, + hio_oow_t nbinds, hio_svc_htts_proc_req_t proc_req ); @@ -266,6 +267,7 @@ static HIO_INLINE hio_t* hio_svc_htts_gethio(hio_svc_htts_t* svc) { return hio_s HIO_EXPORT int hio_svc_htts_writetosidechan ( hio_svc_htts_t* htts, + hio_oow_t idx, /* listener index */ const void* dptr, hio_oow_t dlen ); @@ -275,8 +277,22 @@ HIO_EXPORT int hio_svc_htts_setservernamewithbcstr ( const hio_bch_t* server_name ); +/* return the listening device at the given position. + * not all devices may be up and running */ +HIO_EXPORT hio_dev_sck_t* hio_svc_htts_getlistendev ( + hio_svc_htts_t* htts, + hio_oow_t idx +); + +/* return the total number of listening devices requested to start. + * not all devices may be up and running */ +HIO_EXPORT hio_oow_t hio_sv_htts_getnlistendevs ( + hio_svc_htts_t* htts +); + HIO_EXPORT int hio_svc_htts_getsockaddr ( hio_svc_htts_t* htts, + hio_oow_t idx, /* listener index */ hio_skad_t* skad ); diff --git a/hio/lib/hio-sck.h b/hio/lib/hio-sck.h index d68d4cc..b4d1b65 100644 --- a/hio/lib/hio-sck.h +++ b/hio/lib/hio-sck.h @@ -262,7 +262,7 @@ typedef void (*hio_dev_sck_on_raw_accept_t) ( enum hio_dev_sck_type_t { HIO_DEV_SCK_QX, - + HIO_DEV_SCK_UNIX, HIO_DEV_SCK_TCP4, HIO_DEV_SCK_TCP6, diff --git a/hio/lib/hio-skad.h b/hio/lib/hio-skad.h index 423f562..1a16211 100644 --- a/hio/lib/hio-skad.h +++ b/hio/lib/hio-skad.h @@ -52,6 +52,13 @@ # define HIO_SIZEOF_SKAD_T HIO_SIZEOF_STRUCT_SOCKADDR_UN #endif +#if !defined(HIO_AF_UNIX) + /* this is a fake value */ +# define HIO_AF_UNIX (65534) +#endif +/* this is HIO specific. No AF_XXXX definitions must overlap with this */ +#define HIO_AF_QX (65530) + struct hio_skad_t { hio_uint8_t data[HIO_SIZEOF_SKAD_T]; @@ -173,6 +180,10 @@ HIO_EXPORT void hio_skad_init_for_eth ( hio_ethad_t* ethad ); +HIO_EXPORT void hio_skad_init_for_qx ( + hio_skad_t* skad +); + HIO_EXPORT int hio_skad_family ( const hio_skad_t* skad ); diff --git a/hio/lib/http-prv.h b/hio/lib/http-prv.h index 8c8166f..f11a2a8 100644 --- a/hio/lib/http-prv.h +++ b/hio/lib/http-prv.h @@ -38,10 +38,11 @@ struct hio_svc_htts_cli_t hio_svc_htts_cli_t* cli_prev; hio_svc_htts_cli_t* cli_next; - /* a listener socket sets htts and sck fields only */ + /* a listener socket sets htts, sck, and l_idx fields only */ /* a client sockets uses all the fields in this struct */ hio_svc_htts_t* htts; hio_dev_sck_t* sck; + hio_oow_t l_idx; /* listening socket: < htts->l.count, client socket: >= htts->l.count */ hio_htrd_t* htrd; hio_becs_t* sbuf; /* temporary buffer for status line formatting */ @@ -62,7 +63,13 @@ struct hio_svc_htts_t hio_svc_htts_proc_req_t proc_req; - hio_dev_sck_t* lsck; + struct + { + hio_dev_sck_t** sck; + hio_oow_t count; + } l; + /*hio_dev_sck_t* lsck;*/ + hio_svc_htts_cli_t cli; /* list head for client list */ hio_tmridx_t idle_tmridx; diff --git a/hio/lib/http-svr.c b/hio/lib/http-svr.c index 38cfb6b..4074e74 100644 --- a/hio/lib/http-svr.c +++ b/hio/lib/http-svr.c @@ -48,10 +48,11 @@ static int init_client (hio_svc_htts_cli_t* cli, hio_dev_sck_t* sck) /* the htts field must be filled with the same field in the listening socket upon accept() */ HIO_ASSERT (sck->hio, cli->htts != HIO_NULL); - HIO_ASSERT (sck->hio, cli->sck == cli->htts->lsck); /* the field should still point to the listner socket */ + //HIO_ASSERT (sck->hio, cli->sck == cli->htts->lsck); /* the field should still point to the listner socket */ HIO_ASSERT (sck->hio, sck->hio == cli->htts->hio); cli->sck = sck; + cli->l_idx = HIO_TYPE_MAX(hio_oow_t); cli->htrd = HIO_NULL; cli->sbuf = HIO_NULL; cli->rsrc = HIO_NULL; @@ -138,7 +139,7 @@ static int listener_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t le hio_oow_t rem; int x; - HIO_ASSERT (hio, sck != cli->htts->lsck); + //HIO_ASSERT (hio, sck != cli->htts->lsck); HIO_ASSERT (hio, cli->rsrc == HIO_NULL); /* if a resource has been set, the resource must take over this handler */ if (len <= -1) @@ -182,7 +183,7 @@ oops: static int listener_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr) { hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); - HIO_ASSERT (sck->hio, sck != cli->htts->lsck); + //HIO_ASSERT (sck->hio, sck != cli->htts->lsck); HIO_ASSERT (sck->hio, cli->rsrc == HIO_NULL); /* if a resource has been set, the resource must take over this handler */ return 0; } @@ -214,7 +215,7 @@ static void listener_on_connect (hio_dev_sck_t* sck) static void listener_on_disconnect (hio_dev_sck_t* sck) { hio_t* hio = sck->hio; - hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); + hio_svc_htts_cli_t* xtn = hio_dev_sck_getxtn(sck); switch (HIO_DEV_SCK_GET_PROGRESS(sck)) { @@ -241,8 +242,8 @@ static void listener_on_disconnect (hio_dev_sck_t* sck) /* this progress code indicates that the ssl-level accept failed. * on_disconnected() with this code is called without corresponding on_connect(). * the cli extension are is not initialized yet */ - HIO_ASSERT (hio, sck != cli->sck); - HIO_ASSERT (hio, cli->sck == cli->htts->lsck); /* the field is a copy of the extension are of the listener socket. so it should point to the listner socket */ + HIO_ASSERT (hio, sck != xtn->sck); + //HIO_ASSERT (hio, cli->sck == cli->htts->lsck); /* the field is a copy of the extension are of the listener socket. so it should point to the listner socket */ HIO_DEBUG2 (hio, "LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p\n", sck, (int)sck->hnd); return; @@ -257,21 +258,21 @@ static void listener_on_disconnect (hio_dev_sck_t* sck) break; } - if (sck == cli->htts->lsck) + if (xtn->l_idx < xtn->htts->l.count) { /* the listener socket has these fields set to NULL */ - HIO_ASSERT (hio, cli->htrd == HIO_NULL); - HIO_ASSERT (hio, cli->sbuf == HIO_NULL); + HIO_ASSERT (hio, xtn->htrd == HIO_NULL); + HIO_ASSERT (hio, xtn->sbuf == HIO_NULL); - HIO_DEBUG2 (hio, "HTTS(%p) - listener socket disconnect %p\n", cli->htts, sck); - cli->htts->lsck = HIO_NULL; /* let the htts service forget about this listening socket */ + HIO_DEBUG2 (hio, "HTTS(%p) - listener socket disconnect %p\n", xtn->htts, sck); + xtn->htts->l.sck[xtn->l_idx] = HIO_NULL; /* let the htts service forget about this listening socket */ } else { /* client socket */ - HIO_DEBUG2 (hio, "HTTS(%p) - client socket disconnect %p\n", cli->htts, sck); - HIO_ASSERT (hio, cli->sck == sck); - fini_client (cli); + HIO_DEBUG2 (hio, "HTTS(%p) - client socket disconnect %p\n", xtn->htts, sck); + HIO_ASSERT (hio, xtn->sck == sck); + fini_client (xtn); } } @@ -315,7 +316,7 @@ static void halt_idle_clients (hio_t* hio, const hio_ntime_t* now, hio_tmrjob_t* /* ------------------------------------------------------------------------ */ -hio_svc_htts_t* hio_svc_htts_start (hio_t* hio, hio_dev_sck_bind_t* sck_bind, hio_svc_htts_proc_req_t proc_req) +hio_svc_htts_t* hio_svc_htts_start (hio_t* hio, hio_dev_sck_bind_t* binds, hio_oow_t nbinds, hio_svc_htts_proc_req_t proc_req) { hio_svc_htts_t* htts = HIO_NULL; union @@ -324,68 +325,130 @@ hio_svc_htts_t* hio_svc_htts_start (hio_t* hio, hio_dev_sck_bind_t* sck_bind, hi hio_dev_sck_listen_t l; } info; hio_svc_htts_cli_t* cli; + hio_oow_t i, noks; + + if (HIO_UNLIKELY(nbinds <= 0)) + { + hio_seterrnum (hio, HIO_EINVAL); + goto oops; + } htts = (hio_svc_htts_t*)hio_callocmem(hio, HIO_SIZEOF(*htts)); if (HIO_UNLIKELY(!htts)) goto oops; + HIO_DEBUG1 (hio, "HTTS - STARTING SERVICE %p\n", htts); + htts->hio = hio; htts->svc_stop = hio_svc_htts_stop; htts->proc_req = proc_req; htts->idle_tmridx = HIO_TMRIDX_INVALID; - HIO_MEMSET (&info, 0, HIO_SIZEOF(info)); - switch (hio_skad_family(&sck_bind->localaddr)) + htts->l.sck = (hio_dev_sck_t**)hio_callocmem(hio, HIO_SIZEOF(*htts->l.sck) * nbinds); + if (HIO_UNLIKELY(!htts->l.sck)) goto oops; + htts->l.count = nbinds; + + for (i = 0, noks = 0; i < nbinds; i++) { - case HIO_AF_INET: - info.m.type = HIO_DEV_SCK_TCP4; - break; - - case HIO_AF_INET6: - info.m.type = HIO_DEV_SCK_TCP6; - break; - - default: - /*hio_seterrnum (hio, HIO_EINVAL); - goto oops;*/ - info.m.type = HIO_DEV_SCK_QX; - break; - - } - info.m.options = HIO_DEV_SCK_MAKE_LENIENT; - info.m.on_write = listener_on_write; - info.m.on_read = listener_on_read; - info.m.on_connect = listener_on_connect; - info.m.on_disconnect = listener_on_disconnect; - htts->lsck = hio_dev_sck_make(hio, HIO_SIZEOF(*cli), &info.m); - if (HIO_UNLIKELY(!htts->lsck)) goto oops; - - /* the name 'cli' for the listening socket is awkward. - * the listening socket will use the htts and sck fields for tracking only. - * each accepted client socket gets the extension size for this size as well. - * most of other fields are used for client management */ - cli = (hio_svc_htts_cli_t*)hio_dev_sck_getxtn(htts->lsck); - cli->htts = htts; - cli->sck = htts->lsck; - - if (htts->lsck->type != HIO_DEV_SCK_QX) - { - if (hio_dev_sck_bind(htts->lsck, sck_bind) <= -1) goto oops; + hio_dev_sck_t* sck; HIO_MEMSET (&info, 0, HIO_SIZEOF(info)); - info.l.backlogs = 4096; /* TODO: use configuration? */ - HIO_INIT_NTIME (&info.l.accept_tmout, 5, 1); /* usedd for ssl accept */ - if (hio_dev_sck_listen(htts->lsck, &info.l) <= -1) goto oops; + switch (hio_skad_family(&binds[i].localaddr)) + { + case HIO_AF_INET: + info.m.type = HIO_DEV_SCK_TCP4; + break; + + case HIO_AF_INET6: + info.m.type = HIO_DEV_SCK_TCP6; + break; + + #if defined(HIO_AF_UNIX) + case HIO_AF_UNIX: + info.m.type = HIO_DEV_SCK_UNIX; + break; + #endif + + case HIO_AF_QX: + info.m.type = HIO_DEV_SCK_QX; + break; + + default: + /* ignore this */ + continue; + } + info.m.options = HIO_DEV_SCK_MAKE_LENIENT; + info.m.on_write = listener_on_write; + info.m.on_read = listener_on_read; + info.m.on_connect = listener_on_connect; + info.m.on_disconnect = listener_on_disconnect; + sck = hio_dev_sck_make(hio, HIO_SIZEOF(*cli), &info.m); + if (HIO_UNLIKELY(!sck)) continue; + + /* the name 'cli' for the listening socket is awkward. + * the listening socket will use the htts, sck, and listening fields for tracking only. + * each accepted client socket gets the extension size for this size as well. + * most of other fields are used for client management. init_client() will set + * the sck field to the client socket and the listening field to 0. */ + cli = (hio_svc_htts_cli_t*)hio_dev_sck_getxtn(sck); + cli->htts = htts; + cli->sck = sck; + cli->l_idx = i; + + if (sck->type != HIO_DEV_SCK_QX) + { + if (hio_dev_sck_bind(sck, &binds[i]) <= -1) + { + if (HIO_LOG_ENABLED(hio, HIO_LOG_DEBUG)) + { + hio_bch_t tmpbuf[HIO_SKAD_IP_STRLEN + 1]; + hio_skadtobcstr(hio, &binds[i].localaddr, tmpbuf, HIO_COUNTOF(tmpbuf), HIO_SKAD_TO_BCSTR_ADDR | HIO_SKAD_TO_BCSTR_PORT); + HIO_DEBUG3 (hio, "HTTS(%p) - [%zd] unable to bind to %hs\n", htts, i, tmpbuf); + } + + hio_dev_sck_kill (sck); + continue; + } + + HIO_MEMSET (&info, 0, HIO_SIZEOF(info)); + info.l.backlogs = 4096; /* TODO: use configuration? */ + HIO_INIT_NTIME (&info.l.accept_tmout, 5, 1); /* usedd for ssl accept */ + if (hio_dev_sck_listen(sck, &info.l) <= -1) + { + if (HIO_LOG_ENABLED(hio, HIO_LOG_DEBUG)) + { + hio_bch_t tmpbuf[HIO_SKAD_IP_STRLEN + 1]; + hio_skadtobcstr(hio, &binds[i].localaddr, tmpbuf, HIO_COUNTOF(tmpbuf), HIO_SKAD_TO_BCSTR_ADDR | HIO_SKAD_TO_BCSTR_PORT); + HIO_DEBUG3 (hio, "HTTS(%p) - [%zd] unable to bind to %hs\n", htts, i, tmpbuf); + } + + hio_dev_sck_kill (sck); + goto oops; + } + } + + if (HIO_LOG_ENABLED(hio, HIO_LOG_DEBUG)) + { + hio_skad_t tmpad; + hio_bch_t tmpbuf[HIO_SKAD_IP_STRLEN + 1]; + hio_dev_sck_getsockaddr(sck, &tmpad); + hio_skadtobcstr(hio, &tmpad, tmpbuf, HIO_COUNTOF(tmpbuf), HIO_SKAD_TO_BCSTR_ADDR | HIO_SKAD_TO_BCSTR_PORT); + HIO_DEBUG3 (hio, "HTTS(%p) - [%zd] listening on %hs\n", htts, i, tmpbuf); + } + + htts->l.sck[i] = sck; + noks++; } + if (noks <= 0) goto oops; + hio_fmttobcstr (htts->hio, htts->server_name_buf, HIO_COUNTOF(htts->server_name_buf), "%s-%d.%d.%d", HIO_PACKAGE_NAME, (int)HIO_PACKAGE_VERSION_MAJOR, (int)HIO_PACKAGE_VERSION_MINOR, (int)HIO_PACKAGE_VERSION_PATCH); htts->server_name = htts->server_name_buf; - HIO_SVCL_APPEND_SVC (&hio->actsvc, (hio_svc_t*)htts); HIO_SVC_HTTS_CLIL_INIT (&htts->cli); - HIO_DEBUG3 (hio, "HTTS - STARTED SERVICE %p - LISTENER SOCKET %p(%d)\n", htts, htts->lsck, (int)htts->lsck->hnd); + HIO_DEBUG1 (hio, "HTTS - STARTED SERVICE %p\n", htts); { hio_ntime_t t; @@ -403,7 +466,13 @@ hio_svc_htts_t* hio_svc_htts_start (hio_t* hio, hio_dev_sck_bind_t* sck_bind, hi oops: if (htts) { - if (htts->lsck) hio_dev_sck_kill (htts->lsck); + if (htts->l.sck) + { + for (i = 0; i < htts->l.count; i++) + hio_dev_sck_kill (htts->l.sck[i]); + hio_freemem (hio, htts->l.sck); + } + hio_freemem (hio, htts); } return HIO_NULL; @@ -412,12 +481,17 @@ oops: void hio_svc_htts_stop (hio_svc_htts_t* htts) { hio_t* hio = htts->hio; + hio_oow_t i; - HIO_DEBUG3 (hio, "HTTS - STOPPING SERVICE %p - LISTENER SOCKET %p(%d)\n", htts, htts->lsck, (int)(htts->lsck? htts->lsck->hnd: -1)); + HIO_DEBUG1 (hio, "HTTS - STOPPING SERVICE %p\n", htts); - /* htts->lsck may be null if the socket has been destroyed for operational error and - * forgotten in the disconnect callback thereafter */ - if (htts->lsck) hio_dev_sck_kill (htts->lsck); + for (i = 0; i < htts->l.count; i++) + { + /* the socket may be null: + * if it has been destroyed for operation errors and forgotten in the disconnect callback thereafter + * if it has never been created successfully */ + if (htts->l.sck[i]) hio_dev_sck_kill (htts->l.sck[i]); + } while (!HIO_SVC_HTTS_CLIL_IS_EMPTY(&htts->cli)) { @@ -430,6 +504,7 @@ void hio_svc_htts_stop (hio_svc_htts_t* htts) if (htts->idle_tmridx != HIO_TMRIDX_INVALID) hio_deltmrjob (hio, htts->idle_tmridx); + if (htts->l.sck) hio_freemem (hio, htts->l.sck); hio_freemem (hio, htts); } @@ -453,10 +528,47 @@ int hio_svc_htts_setservernamewithbcstr (hio_svc_htts_t* htts, const hio_bch_t* return 0; } -int hio_svc_htts_getsockaddr (hio_svc_htts_t* htts, hio_skad_t* skad) +hio_dev_sck_t* hio_svc_htts_getlistendev (hio_svc_htts_t* htts, hio_oow_t idx) +{ + if (idx >= htts->l.count) + { + hio_seterrbfmt (htts->hio, HIO_EINVAL, "index out of range"); + return HIO_NULL; + } + + if (!htts->l.sck[idx]) + { + hio_seterrbfmt (htts->hio, HIO_EINVAL, "no listener at the given index"); + return HIO_NULL; + } + + return htts->l.sck[idx]; +} + +hio_oow_t hio_svc_htts_getnlistendevs (hio_svc_htts_t* htts) +{ + /* return the total number of listening socket devices. + * not all devices may be up and working */ + return htts->l.count; +} + +int hio_svc_htts_getsockaddr (hio_svc_htts_t* htts, hio_oow_t idx, hio_skad_t* skad) { /* return the socket address of the listening socket. */ - return hio_dev_sck_getsockaddr(htts->lsck, skad); + + if (idx >= htts->l.count) + { + hio_seterrbfmt (htts->hio, HIO_EINVAL, "index out of range"); + return -1; + } + + if (!htts->l.sck[idx]) + { + hio_seterrbfmt (htts->hio, HIO_EINVAL, "no listener at the given index"); + return -1; + } + + return hio_dev_sck_getsockaddr(htts->l.sck[idx], skad); } /* ----------------------------------------------------------------- */ @@ -550,9 +662,21 @@ hio_bch_t* hio_svc_htts_dupmergepaths (hio_svc_htts_t* htts, const hio_bch_t* ba return xpath; } -int hio_svc_htts_writetosidechan (hio_svc_htts_t* htts, const void* dptr, hio_oow_t dlen) +int hio_svc_htts_writetosidechan (hio_svc_htts_t* htts, hio_oow_t idx, const void* dptr, hio_oow_t dlen) { - return hio_dev_sck_writetosidechan(htts->lsck, dptr, dlen); + if (idx >= htts->l.count) + { + hio_seterrbfmt (htts->hio, HIO_EINVAL, "index out of range"); + return -1; + } + + if (!htts->l.sck[idx]) + { + hio_seterrbfmt (htts->hio, HIO_EINVAL, "no listener at the given index"); + return -1; + } + + return hio_dev_sck_writetosidechan(htts->l.sck[idx], dptr, dlen); } diff --git a/hio/lib/sck.c b/hio/lib/sck.c index 1666ab9..ed04d01 100644 --- a/hio/lib/sck.c +++ b/hio/lib/sck.c @@ -224,13 +224,18 @@ struct sck_type_map_t int extra_dev_cap; }; -#define __AF_QX 999999 #define __AF_BPF 999998 static struct sck_type_map_t sck_type_map[] = { /* HIO_DEV_SCK_QX */ - { __AF_QX, 0, 0, 0 }, + { HIO_AF_QX, 0, 0, 0 }, + +#if defined(AF_UNIX) + { AF_UNIX, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, +#else + { -1, 0, 0, 0 }, +#endif /* HIO_DEV_SCK_TCP4 */ { AF_INET, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, @@ -278,7 +283,6 @@ static struct sck_type_map_t sck_type_map[] = { -1, 0, 0, 0 }, #endif - /* HIO_DEV_SCK_BPF - arp */ { __AF_BPF, 0, 0, 0 } /* not implemented yet */ }; @@ -397,7 +401,7 @@ static int dev_sck_make (hio_dev_t* dev, void* ctx) goto oops; } - if (HIO_UNLIKELY(sck_type_map[arg->type].domain == __AF_QX)) + if (HIO_UNLIKELY(sck_type_map[arg->type].domain == HIO_AF_QX)) { hnd = open_async_qx(hio, &side_chan); if (hnd == HIO_SYSHND_INVALID) goto oops; @@ -2200,7 +2204,11 @@ int hio_dev_sck_getsockopt (hio_dev_sck_t* dev, int level, int optname, void* op int hio_dev_sck_getsockaddr (hio_dev_sck_t* dev, hio_skad_t* skad) { hio_scklen_t addrlen = HIO_SIZEOF(*skad); - if (getsockname(dev->hnd, (struct sockaddr*)skad, &addrlen) <= -1) + if (dev->type == HIO_DEV_SCK_QX) + { + hio_skad_init_for_qx (skad); + } + else if (getsockname(dev->hnd, (struct sockaddr*)skad, &addrlen) <= -1) { hio_seterrwithsyserr (dev->hio, 0, errno); return -1; @@ -2211,7 +2219,11 @@ int hio_dev_sck_getsockaddr (hio_dev_sck_t* dev, hio_skad_t* skad) int hio_dev_sck_getpeeraddr (hio_dev_sck_t* dev, hio_skad_t* skad) { hio_scklen_t addrlen = HIO_SIZEOF(*skad); - if (getpeername(dev->hnd, (struct sockaddr*)skad, &addrlen) <= -1) + if (dev->type == HIO_DEV_SCK_QX) + { + hio_skad_init_for_qx (skad); + } + else if (getpeername(dev->hnd, (struct sockaddr*)skad, &addrlen) <= -1) { hio_seterrwithsyserr (dev->hio, 0, errno); return -1; diff --git a/hio/lib/skad.c b/hio/lib/skad.c index d7815c7..45a9c35 100644 --- a/hio/lib/skad.c +++ b/hio/lib/skad.c @@ -382,17 +382,30 @@ int hio_ucharstoskad (hio_t* hio, const hio_uch_t* str, hio_oow_t len, hio_skad_ /* use HIO_SIZEOF(*_skad) instead of HIO_SIZEOF(*skad) in case they are different */ HIO_MEMSET (skad, 0, HIO_SIZEOF(*_skad)); -#if defined(AF_UNIX) - if (*p == '/' && len >= 2) + if (p[0] == '<' && p[1] == 'q' && p[2] == 'x' && p[3] == '>' && p[4] == '\0') { - hio_oow_t dstlen; + /* this is HIO specific. the rest isn't important */ + skad->sa.sa_family = HIO_AF_QX; + return 0; + } + + if (*p == '@') + { +#if defined(AF_UNIX) && (HIO_SIZEOF_STRUCT_SOCKADDR_UN > 0) + /* @aaa, @/tmp/aaa ... */ + hio_oow_t srclen, dstlen; dstlen = HIO_COUNTOF(skad->un.sun_path) - 1; - if (hio_convutobchars(hio, p, &len, skad->un.sun_path, &dstlen) <= -1) return -1; + srclen = len - 1; + if (hio_convutobchars(hio, p + 1, &srclen, skad->un.sun_path, &dstlen) <= -1) return -1; skad->un.sun_path[dstlen] = '\0'; skad->un.sun_family = AF_UNIX; return 0; - } +#else + hio_seterrbfmt (hio, HIO_ENOIMPL, "unix address not supported"); + return -1; #endif + } + #if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) if (*p == '[') @@ -596,14 +609,25 @@ int hio_bcharstoskad (hio_t* hio, const hio_bch_t* str, hio_oow_t len, hio_skad_ /* use HIO_SIZEOF(*_skad) instead of HIO_SIZEOF(*skad) in case they are different */ HIO_MEMSET (skad, 0, HIO_SIZEOF(*_skad)); -#if defined(AF_UNIX) - if (*p == '/' && len >= 2) + if (p[0] == '<' && p[1] == 'q' && p[2] == 'x' && p[3] == '>' && p[4] == '\0') { - hio_copy_bcstr (skad->un.sun_path, HIO_COUNTOF(skad->un.sun_path), str); - skad->un.sun_family = AF_UNIX; + /* this is HIO specific. the rest isn't important */ + skad->sa.sa_family = HIO_AF_QX; return 0; } + + if (*p == '@') + { +#if defined(AF_UNIX) && (HIO_SIZEOF_STRUCT_SOCKADDR_UN > 0) + /* @aaa, @/tmp/aaa ... */ + hio_copy_bchars_to_bcstr (skad->un.sun_path, HIO_COUNTOF(skad->un.sun_path), str + 1, len - 1); + skad->un.sun_family = HIO_AF_UNIX; + return 0; +#else + hio_seterrbfmt (hio, HIO_ENOIMPL, "unix address not supported"); + return -1; #endif + } #if (HIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) if (*p == '[') @@ -959,17 +983,17 @@ hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, switch (hio_skad_family(_skad)) { case HIO_AF_INET: - if (flags & HIO_SKAD_TO_BCSTR_ADDR) + if (flags & HIO_SKAD_TO_UCSTR_ADDR) { if (xlen + 1 >= len) goto done; xlen += ip4ad_to_ucstr(&skad->in4.sin_addr, buf, len); } - if (flags & HIO_SKAD_TO_BCSTR_PORT) + if (flags & HIO_SKAD_TO_UCSTR_PORT) { - if (!(flags & HIO_SKAD_TO_BCSTR_ADDR) || skad->in4.sin_port != 0) + if (!(flags & HIO_SKAD_TO_UCSTR_ADDR) || skad->in4.sin_port != 0) { - if (flags & HIO_SKAD_TO_BCSTR_ADDR) + if (flags & HIO_SKAD_TO_UCSTR_ADDR) { if (xlen + 1 >= len) goto done; buf[xlen++] = ':'; @@ -982,11 +1006,11 @@ hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, break; case HIO_AF_INET6: - if (flags & HIO_SKAD_TO_BCSTR_PORT) + if (flags & HIO_SKAD_TO_UCSTR_PORT) { - if (!(flags & HIO_SKAD_TO_BCSTR_ADDR) || skad->in6.sin6_port != 0) + if (!(flags & HIO_SKAD_TO_UCSTR_ADDR) || skad->in6.sin6_port != 0) { - if (flags & HIO_SKAD_TO_BCSTR_ADDR) + if (flags & HIO_SKAD_TO_UCSTR_ADDR) { if (xlen + 1 >= len) goto done; buf[xlen++] = '['; @@ -994,7 +1018,7 @@ hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, } } - if (flags & HIO_SKAD_TO_BCSTR_ADDR) + if (flags & HIO_SKAD_TO_UCSTR_ADDR) { if (xlen + 1 >= len) goto done; xlen += ip6ad_to_ucstr(&skad->in6.sin6_addr, &buf[xlen], len - xlen); @@ -1017,11 +1041,11 @@ hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, } } - if (flags & HIO_SKAD_TO_BCSTR_PORT) + if (flags & HIO_SKAD_TO_UCSTR_PORT) { - if (!(flags & HIO_SKAD_TO_BCSTR_ADDR) || skad->in6.sin6_port != 0) + if (!(flags & HIO_SKAD_TO_UCSTR_ADDR) || skad->in6.sin6_port != 0) { - if (flags & HIO_SKAD_TO_BCSTR_ADDR) + if (flags & HIO_SKAD_TO_UCSTR_ADDR) { if (xlen + 1 >= len) goto done; buf[xlen++] = ']'; @@ -1038,7 +1062,7 @@ hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, break; case HIO_AF_UNIX: - if (flags & HIO_SKAD_TO_BCSTR_ADDR) + if (flags & HIO_SKAD_TO_UCSTR_ADDR) { if (xlen + 1 >= len) goto done; buf[xlen++] = '@'; @@ -1053,6 +1077,21 @@ hio_oow_t hio_skadtoucstr (hio_t* hio, const hio_skad_t* _skad, hio_uch_t* buf, } } + break; + + case HIO_AF_QX: + if (flags & HIO_SKAD_TO_UCSTR_ADDR) + { + if (xlen + 1 >= len) goto done; + buf[xlen++] = '<'; + if (xlen + 1 >= len) goto done; + buf[xlen++] = 'q'; + if (xlen + 1 >= len) goto done; + buf[xlen++] = 'x'; + if (xlen + 1 >= len) goto done; + buf[xlen++] = '>'; + } + break; } @@ -1294,6 +1333,21 @@ hio_oow_t hio_skadtobcstr (hio_t* hio, const hio_skad_t* _skad, hio_bch_t* buf, xlen += hio_copy_bcstr(&buf[xlen], len - xlen, skad->un.sun_path); } + break; + + case HIO_AF_QX: + if (flags & HIO_SKAD_TO_BCSTR_ADDR) + { + if (xlen + 1 >= len) goto done; + buf[xlen++] = '<'; + if (xlen + 1 >= len) goto done; + buf[xlen++] = 'q'; + if (xlen + 1 >= len) goto done; + buf[xlen++] = 'x'; + if (xlen + 1 >= len) goto done; + buf[xlen++] = '>'; + } + break; } @@ -1454,6 +1508,13 @@ void hio_skad_init_for_eth (hio_skad_t* skad, int ifindex, hio_ethad_t* ethad) #endif } +void hio_skad_init_for_qx (hio_skad_t* _skad) +{ + hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad; + HIO_MEMSET (skad, 0, HIO_SIZEOF(*_skad)); + skad->sa.sa_family = HIO_AF_QX; +} + void hio_clear_skad (hio_skad_t* _skad) { hio_skad_alt_t* skad = (hio_skad_alt_t*)_skad;