From 8be5e3fd838861ce7db587601cb9748732d7f85a Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 22 Mar 2018 03:42:17 +0000 Subject: [PATCH] moved the socket address convertion functions to the main hcl library enhanced the client library and samples --- lib/hcl-s.c | 34 ++------------ lib/hcl-utl.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++---- lib/main-c.c | 117 +++++++++++++++++++++++++++++++++++++++++------- lib/sa-utl.h | 29 ++++++------ lib/utl.c | 39 ++++++++++++++++ 5 files changed, 267 insertions(+), 72 deletions(-) diff --git a/lib/hcl-s.c b/lib/hcl-s.c index 471a6de..69ec027 100644 --- a/lib/hcl-s.c +++ b/lib/hcl-s.c @@ -992,34 +992,6 @@ static void fini_hcl (hcl_t* hcl) */ /* ========================================================================= */ - -#undef ooch_t -#undef oocs_t -#undef str_to_ipv4 -#undef str_to_ipv6 -#undef str_to_sockaddr - -#define ooch_t hcl_bch_t -#define oocs_t hcl_bcs_t -#define str_to_ipv4 bchars_to_ipv4 -#define str_to_ipv6 bchars_to_ipv6 -#define str_to_sockaddr bchars_to_sockaddr -#include "sa-utl.h" - -#undef ooch_t -#undef oocs_t -#undef str_to_ipv4 -#undef str_to_ipv6 -#undef str_to_sockaddr - -#define ooch_t hcl_uch_t -#define oocs_t hcl_ucs_t -#define str_to_ipv4 uchars_to_ipv4 -#define str_to_ipv6 uchars_to_ipv6 -#define str_to_sockaddr uchars_to_sockaddr -#include "sa-utl.h" -/* ========================================================================= */ - #define SERVER_LOGMASK_INFO (HCL_LOG_INFO | HCL_LOG_APP) #define SERVER_LOGMASK_ERROR (HCL_LOG_ERROR | HCL_LOG_APP) @@ -2276,7 +2248,7 @@ static void set_err_with_syserr (hcl_server_t* server, int syserr, const char* b int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs) { - sockaddr_t srv_addr; + hcl_sckaddr_t srv_addr; int srv_fd, sck_fam, optval, xret = 0; socklen_t srv_len; pthread_attr_t thr_attr; @@ -2284,7 +2256,7 @@ int hcl_server_start (hcl_server_t* server, const hcl_bch_t* addrs) /* TODO: interprete 'addrs' as a command-separated address list * 192.168.1.1:20,[::1]:20,127.0.0.1:345 */ - sck_fam = bchars_to_sockaddr(server, addrs, hcl_countbcstr(addrs), &srv_addr, &srv_len); + sck_fam = hcl_bchars_to_sckaddr(addrs, hcl_countbcstr(addrs), &srv_addr, &srv_len); if (sck_fam <= -1) { hcl_server_seterrbfmt (server, HCL_EINVAL, "unable to convert address - %hs", addrs); @@ -2519,7 +2491,7 @@ int hcl_server_getoption (hcl_server_t* server, hcl_server_option_t id, void* va case HCL_SERVER_ACTOR_MAX_RUNTIME: *(hcl_ntime_t*)value = server->cfg.actor_max_runtime; return 0; - + case HCL_SERVER_SCRIPT_INCLUDE_PATH: *(hcl_ooch_t**)value = server->cfg.script_include_path; return 0; diff --git a/lib/hcl-utl.h b/lib/hcl-utl.h index 1637091..5f10a1d 100644 --- a/lib/hcl-utl.h +++ b/lib/hcl-utl.h @@ -102,20 +102,83 @@ (((qse_uint32_t)(x) & (qse_uint32_t)0xff000000UL) >> 24) )) #if defined(HCL_ENDIAN_LITTLE) -# define HCL_CONST_NTOH16(x) HCL_CONST_SWAP16(x) -# define HCL_CONST_HTON16(x) HCL_CONST_SWAP16(x) -# define HCL_CONST_NTOH32(x) HCL_CONST_SWAP32(x) -# define HCL_CONST_HTON32(x) HCL_CONST_SWAP32(x) +# define HCL_CONST_NTOH16(x) HCL_CONST_SWAP16(x) +# define HCL_CONST_HTON16(x) HCL_CONST_SWAP16(x) +# define HCL_CONST_NTOH32(x) HCL_CONST_SWAP32(x) +# define HCL_CONST_HTON32(x) HCL_CONST_SWAP32(x) #elif defined(HCL_ENDIAN_BIG) -# define HCL_CONST_NTOH16(x) (x) -# define HCL_CONST_HTON16(x) (x) -# define HCL_CONST_NTOH32(x) (x) -# define HCL_CONST_HTON32(x) (x) +# define HCL_CONST_NTOH16(x) (x) +# define HCL_CONST_HTON16(x) (x) +# define HCL_CONST_NTOH32(x) (x) +# define HCL_CONST_HTON32(x) (x) #else -# error UNKNOWN ENDIAN +# error UNKNOWN ENDIAN #endif + + +#if (HCL_SIZEOF_SOCKLEN_T == 1) + #if defined(HCL_SOCKLEN_T_IS_SIGNED) + typedef hcl_int8_t hcl_scklen_t; + #else + typedef hcl_uint8_t hcl_scklen_t; + #endif +#elif (HCL_SIZEOF_SOCKLEN_T == 2) + #if defined(HCL_SOCKLEN_T_IS_SIGNED) + typedef hcl_int16_t hcl_scklen_t; + #else + typedef hcl_uint16_t hcl_scklen_t; + #endif +#elif (HCL_SIZEOF_SOCKLEN_T == 4) + #if defined(HCL_SOCKLEN_T_IS_SIGNED) + typedef hcl_int32_t hcl_scklen_t; + #else + typedef hcl_uint32_t hcl_scklen_t; + #endif +#elif (HCL_SIZEOF_SOCKLEN_T == 8) + #if defined(HCL_SOCKLEN_T_IS_SIGNED) + typedef hcl_int64_t hcl_scklen_t; + #else + typedef hcl_uint64_t hcl_scklen_t; + #endif +#else + #undef HCL_SIZEOF_SOCKLEN_T + #define HCL_SIZEOF_SOCKLEN_T HCL_SIZEOF_INT + #define HCL_SOCKLEN_T_IS_SIGNED + typedef int hcl_scklen_t; +#endif + + +struct hcl_sckaddr_t +{ +#define HCL_SCKADDR_DATA_SIZE 0 + +#if (HCL_SIZEOF_STRUCT_SOCKADDR_IN > HCL_SCKADDR_DATA_SIZE) + #undef HCL_SCKADDR_DATA_SIZE + #define HCL_SCKADDR_DATA_SIZE HCL_SIZEOF_STRUCT_SOCKADDR_IN +#endif +#if (HCL_SIZEOF_STRUCT_SOCKADDR_IN6 > HCL_SCKADDR_DATA_SIZE) + #undef HCL_SCKADDR_DATA_SIZE + #define HCL_SCKADDR_DATA_SIZE HCL_SIZEOF_STRUCT_SOCKADDR_IN6 +#endif +#if (HCL_SIZEOF_STRUCT_SOCKADDR_UN > HCL_SCKADDR_DATA_SIZE) + #undef HCL_SCKADDR_DATA_SIZE + #define HCL_SCKADDR_DATA_SIZE HCL_SIZEOF_STRUCT_SOCKADDR_UN +#endif +#if (HCL_SIZEOF_STRUCT_SOCKADDR_LL > HCL_SCKADDR_DATA_SIZE) + #undef HCL_SCKADDR_DATA_SIZE + #define HCL_SCKADDR_DATA_SIZE HCL_SIZEOF_STRUCT_SOCKADDR_LL +#endif + +#if (HCL_SCKADDR_DATA_SIZE == 0) + #undef HCL_SCKADDR_DATA_SIZE + #define HCL_SCKADDR_DATA_SIZE 64 +#endif + hcl_uint8_t storage[HCL_SCKADDR_DATA_SIZE]; +}; +typedef struct hcl_sckaddr_t hcl_sckaddr_t; + #if defined(__cplusplus) extern "C" { #endif @@ -534,6 +597,45 @@ HCL_EXPORT hcl_uint128_t hcl_hton128 ( ); #endif + +HCL_EXPORT int hcl_ucharstosckaddr ( + hcl_t* hcl, + const hcl_uch_t* str, + hcl_oow_t len, + hcl_sckaddr_t* sckaddr, + hcl_scklen_t* scklen +); + +HCL_EXPORT int hcl_bcharstosckaddr ( + hcl_t* hcl, + const hcl_bch_t* str, + hcl_oow_t len, + hcl_sckaddr_t* sckaddr, + hcl_scklen_t* scklen +); + +#if defined(HCL_HAVE_INLINE) + static HCL_INLINE int hcl_uchars_to_sckaddr (const hcl_uch_t* str, hcl_oow_t len, hcl_sckaddr_t* sckaddr, hcl_scklen_t* scklen) + { + return hcl_ucharstosckaddr(HCL_NULL, str, len, sckaddr, scklen); + } + static HCL_INLINE int hcl_bchars_to_sckaddr (const hcl_bch_t* str, hcl_oow_t len, hcl_sckaddr_t* sckaddr, hcl_scklen_t* scklen) + { + return hcl_bcharstosckaddr(HCL_NULL, str, len, sckaddr, scklen); + } +#else + #define hcl_uchars_to_sckaddr(str,len,sckaddr,scklen) hcl_ucharstosckaddr(HCL_NULL,str,len,sckaddr,scklen) + #define hcl_bchars_to_sckaddr(str,len,sckaddr,scklen) hcl_bcharstosckaddr(HCL_NULL,str,len,sckaddr,scklen) +#endif + +#if defined(HCL_OOCH_IS_UCH) +# define hcl_oocharstosckaddr hcl_ucharstosckaddr +# define hcl_oochars_to_sckaddr hcl_uchars_to_sckaddr +#else +# define hcl_oocharstosckaddr hcl_bcharstosckaddr +# define hcl_oochars_to_sckaddr hcl_bchars_to_sckaddr +#endif + #if defined(__cplusplus) } #endif diff --git a/lib/main-c.c b/lib/main-c.c index 2ab6ac1..0b4ae99 100644 --- a/lib/main-c.c +++ b/lib/main-c.c @@ -47,6 +47,8 @@ # include #endif +#include +#include #include #include @@ -64,6 +66,8 @@ struct client_xtn_t hcl_bch_t buf[4096]; hcl_oow_t len; } logbuf; + + int reply_count; }; /* ========================================================================= */ @@ -451,12 +455,16 @@ static int start_reply (hcl_client_t* client, hcl_client_reply_type_t type, cons static int end_reply (hcl_client_t* client, hcl_client_end_reply_state_t state) { + client_xtn_t* client_xtn; + client_xtn = hcl_client_getxtn(client); + if (state == HCL_CLIENT_END_REPLY_STATE_REVOKED) { printf (">>>>>>>>>>>>>>>>>>>>>> REPLY revoked....\n"); } else { + client_xtn->reply_count++; printf (">>>>>>>>>>>>>>>>>>>>> REPLY ENDED OK....\n"); } return 0; @@ -470,55 +478,128 @@ printf ("GOT HEADER ====> [%.*ls] ===> [%.*ls]\n", (int)key->len, key->ptr, (int static int feed_data (hcl_client_t* client, const void* ptr, hcl_oow_t len) { -printf ("GOT DATA>>>>>>>>>[%.*s]>>>>>>>\n", (int)len, ptr); +//printf ("GOT DATA>>>>>>>>>[%.*s]>>>>>>>\n", (int)len, ptr); +printf ("%.*s", (int)len, ptr); return 0; } /* ========================================================================= */ -static int process_reply (hcl_client_t* client, const hcl_bch_t* addrs) +static int handle_request (hcl_client_t* client, const char* ipaddr, const char* script) { - - /* connect */ - /* send request */ + hcl_sckaddr_t sckaddr; + hcl_scklen_t scklen; + int sckfam; + int sck; + struct iovec iov[10]; + int index, count; hcl_oow_t xlen, offset; int x; - int fd = 0; /* read from stdin for testing */ hcl_bch_t buf[256]; ssize_t n; - offset = 0; + client_xtn_t* client_xtn; + client_xtn = hcl_client_getxtn(client); + + sckfam = hcl_bchars_to_sckaddr(ipaddr, strlen(ipaddr), &sckaddr, &scklen); + if (sckfam <= -1) + { + fprintf (stderr, "cannot convert ip address - %s\n", ipaddr); + return -1; + } + + sck = socket (sckfam, SOCK_STREAM, 0); + if (sck <= -1) + { + fprintf (stderr, "cannot create a socket for %s\n", ipaddr); + return -1; + } + + + if (connect(sck, (struct sockaddr*)&sckaddr, scklen) <= -1) + { + fprintf (stderr, "cannot connect to %s\n", ipaddr); + close (sck); + return -1; + } + + count = 0; + iov[count].iov_base = ".SCRIPT (do "; + iov[count++].iov_len = 12; + iov[count].iov_base = (char*)script; + iov[count++].iov_len = strlen(script); + /* the script above must not include trailing newlines */ + iov[count].iov_base = ")\n"; + iov[count++].iov_len = 2; + + index = 0; while (1) { - n = read(fd, &buf[offset], HCL_SIZEOF(buf) - offset); /* switch to recv */ + ssize_t nwritten; + struct msghdr msg; + + memset (&msg, 0, HCL_SIZEOF(msg)); + msg.msg_iov = (struct iovec*)&iov[index]; + msg.msg_iovlen = count - index; + nwritten = sendmsg(sck, &msg, 0); + /*nwritten = writev(proto->worker->sck, (const struct iovec*)&iov[index], count - index);*/ + if (nwritten <= -1) + { + /* error occurred inside the worker thread shouldn't affect the error information + * in the server object. so here, i just log a message */ + fprintf (stderr, "Unable to sendmsg on %d - %s\n", sck, strerror(errno)); + goto oops; + } + + while (index < count && (size_t)nwritten >= iov[index].iov_len) + nwritten -= iov[index++].iov_len; + + if (index == count) break; + + iov[index].iov_base = (void*)((hcl_uint8_t*)iov[index].iov_base + nwritten); + iov[index].iov_len -= nwritten; + } + + client_xtn->reply_count = 0; + +/* TODO: implement timeout? */ + offset = 0; + while (client_xtn->reply_count == 0) + { + n = read(sck, &buf[offset], HCL_SIZEOF(buf) - offset); /* switch to recv */ if (n <= -1) { - printf ("error....%s\n", strerror(n)); - return -1; + fprintf (stderr, "Unable to read from %d - %s\n", sck, strerror(n)); + goto oops; } if (n == 0) { if (hcl_client_getstate(client) != HCL_CLIENT_STATE_START) { - printf ("sudden end??? \n"); + fprintf (stderr, "Sudden end of reply\n"); + goto oops; } break; } x = hcl_client_feed(client, buf, n, &xlen); - if (x <= -1) return -1; + if (x <= -1) goto oops; offset = n - xlen; if (offset > 0) memmove (&buf[0], &buf[xlen], offset); } - +/* TODO: we can check if the buffer has all been consumed. if not, there is trailing garbage.. */ + close (sck); return 0; + +oops: + if (sck >= 0) close (sck); + return -1; } - int main (int argc, char* argv[]) { hcl_bci_t c; @@ -545,7 +626,7 @@ int main (int argc, char* argv[]) if (argc < 2) { print_usage: - fprintf (stderr, "Usage: %s bind-address:port\n", argv[0]); + fprintf (stderr, "Usage: %s bind-address:port script-to-run\n", argv[0]); return -1; } @@ -574,7 +655,8 @@ int main (int argc, char* argv[]) } } - if (opt.ind >= argc) goto print_usage; + /* needs 2 fixed arguments */ + if (opt.ind + 1 >= argc) goto print_usage; memset (&client_prim, 0, HCL_SIZEOF(client_prim)); client_prim.log_write = log_write; @@ -608,7 +690,8 @@ int main (int argc, char* argv[]) set_signal (SIGINT, handle_sigint); set_signal_to_ignore (SIGPIPE); - n = process_reply(client, argv[opt.ind]); + + n = handle_request (client, argv[opt.ind], argv[opt.ind + 1]); set_signal_to_default (SIGINT); set_signal_to_default (SIGPIPE); diff --git a/lib/sa-utl.h b/lib/sa-utl.h index 761083d..c0f72a6 100644 --- a/lib/sa-utl.h +++ b/lib/sa-utl.h @@ -2,7 +2,7 @@ static int str_to_ipv4 (const ooch_t* str, hcl_oow_t len, struct in_addr* inaddr { const ooch_t* end; int dots = 0, digits = 0; - hcl_uint32_t acc = 0, addr = 0; + hcl_uint32_t acc = 0, addr = 0; ooch_t c; end = str + len; @@ -153,18 +153,19 @@ static int str_to_ipv6 (const ooch_t* src, hcl_oow_t len, struct in6_addr* inadd #endif -static int str_to_sockaddr (hcl_server_t* server, const ooch_t* str, hcl_oow_t len, sockaddr_t* nwad, socklen_t* socklen) +int str_to_sockaddr (hcl_t* hcl, const ooch_t* str, hcl_oow_t len, hcl_sckaddr_t* sckaddr, hcl_scklen_t* scklen) { const ooch_t* p; const ooch_t* end; oocs_t tmp; + sockaddr_t* nwad = (hcl_sckaddr_t*)sckaddr; p = str; end = str + len; if (p >= end) { - hcl_server_seterrbfmt (server, HCL_EINVAL, "blank address"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "blank address"); return -1; } @@ -190,7 +191,7 @@ static int str_to_sockaddr (hcl_server_t* server, const ooch_t* str, hcl_oow_t l if (p >= end) { /* premature end */ - hcl_server_seterrbfmt (server, HCL_EINVAL, "scope id blank"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "scope id blank"); return -1; } @@ -203,7 +204,7 @@ static int str_to_sockaddr (hcl_server_t* server, const ooch_t* str, hcl_oow_t l x = nwad->in6.sin6_scope_id * 10 + (*p - '0'); if (x < nwad->in6.sin6_scope_id) { - hcl_server_seterrbfmt (server, HCL_EINVAL, "scope id too large"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "scope id too large"); return -1; /* overflow */ } nwad->in6.sin6_scope_id = x; @@ -250,7 +251,6 @@ TODO: goto unrecog; } - while (p < end && *p != '%') p++; tmp.len = p - tmp.ptr; @@ -266,7 +266,7 @@ TODO: if (p >= end) { /* premature end */ - hcl_server_seterrbfmt (server, HCL_EINVAL, "scope id blank"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "scope id blank"); return -1; } @@ -279,7 +279,7 @@ TODO: x = nwad->in6.sin6_scope_id * 10 + (*p - '0'); if (x < nwad->in6.sin6_scope_id) { - hcl_server_seterrbfmt (server, HCL_EINVAL, "scope id too large"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "scope id too large"); return -1; /* overflow */ } nwad->in6.sin6_scope_id = x; @@ -304,7 +304,7 @@ TODO if (p < end) goto unrecog; /* some gargage after the end? */ nwad->in6.sin6_family = AF_INET6; - *socklen = HCL_SIZEOF(nwad->in6); + *scklen = HCL_SIZEOF(nwad->in6); return nwad->in6.sin6_family; #else goto unrecog; @@ -334,7 +334,7 @@ TODO if (tmp.len <= 0 || tmp.len >= 6 || port > HCL_TYPE_MAX(hcl_uint16_t)) { - hcl_server_seterrbfmt (server, HCL_EINVAL, "port number blank or too large"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "port number blank or too large"); return -1; } @@ -348,15 +348,14 @@ TODO #endif } - *socklen = (nwad->in4.sin_family == AF_INET)? HCL_SIZEOF(nwad->in4): HCL_SIZEOF(nwad->in6); + *scklen = (nwad->in4.sin_family == AF_INET)? HCL_SIZEOF(nwad->in4): HCL_SIZEOF(nwad->in6); return nwad->in4.sin_family; - - + unrecog: - hcl_server_seterrbfmt (server, HCL_EINVAL, "unrecognized address"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "unrecognized address"); return -1; no_rbrack: - hcl_server_seterrbfmt (server, HCL_EINVAL, "missing right bracket"); + if (hcl) hcl_seterrbfmt (hcl, HCL_EINVAL, "missing right bracket"); return -1; } diff --git a/lib/utl.c b/lib/utl.c index 7a2cd54..93527d3 100644 --- a/lib/utl.c +++ b/lib/utl.c @@ -1108,3 +1108,42 @@ hcl_uint128_t hcl_hton128 (hcl_uint128_t x) } #endif + +/* --------------------------------------------------------------- */ + +#include + +union sockaddr_t +{ + struct sockaddr_in in4; +#if (HCL_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) + struct sockaddr_in6 in6; +#endif +}; +typedef union sockaddr_t sockaddr_t; + +#undef ooch_t +#undef oocs_t +#undef str_to_ipv4 +#undef str_to_ipv6 +#undef str_to_sockaddr + +#define ooch_t hcl_bch_t +#define oocs_t hcl_bcs_t +#define str_to_ipv4 bchars_to_ipv4 +#define str_to_ipv6 bchars_to_ipv6 +#define str_to_sockaddr hcl_bcharstosckaddr +#include "sa-utl.h" + +#undef ooch_t +#undef oocs_t +#undef str_to_ipv4 +#undef str_to_ipv6 +#undef str_to_sockaddr + +#define ooch_t hcl_uch_t +#define oocs_t hcl_ucs_t +#define str_to_ipv4 uchars_to_ipv4 +#define str_to_ipv6 uchars_to_ipv6 +#define str_to_sockaddr hcl_ucharstosckaddr +#include "sa-utl.h"