From f675835a11f6c7f65f1e14c76282d8f3adb3670a Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 21 Mar 2018 10:38:10 +0000 Subject: [PATCH] added reply handler --- lib/hcl-c.c | 672 +++++++++++++++++++++++++++++++++++---------------- lib/hcl-c.h | 95 +++++++- lib/hcl-s.c | 13 +- lib/hcl-s.h | 3 +- lib/main-c.c | 141 ++++------- lib/main-s.c | 9 +- 6 files changed, 599 insertions(+), 334 deletions(-) diff --git a/lib/hcl-c.c b/lib/hcl-c.c index 26ec5fb..38a7598 100644 --- a/lib/hcl-c.c +++ b/lib/hcl-c.c @@ -31,9 +31,11 @@ #include #include -#define HCL_SERVER_TOKEN_NAME_ALIGN 64 -#define HCL_SERVER_WID_MAP_ALIGN 512 -#define HCL_SERVER_PROTO_REPLY_BUF_SIZE 1300 +#define HCL_CLIENT_TOKEN_NAME_ALIGN 64 +#define HCL_CLIENT_WID_MAP_ALIGN 512 +#define HCL_CLIENT_PROTO_REPLY_BUF_SIZE 1300 + +#define HCL_CLIENT_REPLY_MAX_HDRKEY_LEN 128 #if defined(_WIN32) # include @@ -78,12 +80,18 @@ # include #endif -enum hcl_client_reply_type_t +struct dummy_hcl_xtn_t { - HCL_CLIENT_REPLY_TYPE_OK = 0, - HCL_CLIENT_REPLY_TYPE_ERROR = 1 + hcl_client_t* client; }; -typedef enum hcl_client_reply_type_t hcl_client_reply_type_t; +typedef struct dummy_hcl_xtn_t dummy_hcl_xtn_t; + +enum hcl_client_reply_attr_type_t +{ + HCL_CLIENT_REPLY_ATTR_TYPE_UNKNOWN, + HCL_CLIENT_REPLY_ATTR_TYPE_DATA +}; +typedef enum hcl_client_reply_attr_type_t hcl_client_reply_attr_type_t; enum hcl_client_state_t { @@ -93,11 +101,14 @@ enum hcl_client_state_t HCL_CLIENT_STATE_IN_REPLY_VALUE_UNQUOTED, HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED, HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED_TRAILER, - HCL_CLIENT_STATE_IN_HEADER_NAME, - HCL_CLIENT_STATE_IN_HEADER_VALUE, - HCL_CLIENT_STATE_IN_DATA, - HCL_CLIENT_STATE_IN_BINARY_DATA, - HCL_CLIENT_STATE_IN_CHUNK, + HCL_CLIENT_STATE_IN_ATTR_KEY, + HCL_CLIENT_STATE_IN_ATTR_VALUE_START, + HCL_CLIENT_STATE_IN_ATTR_VALUE_UNQUOTED, + HCL_CLIENT_STATE_IN_ATTR_VALUE_QUOTED, + HCL_CLIENT_STATE_IN_ATTR_VALUE_QUOTED_TRAILER, + + HCL_CLIENT_STATE_IN_LENGTH_BOUNDED_DATA, + HCL_CLIENT_STATE_IN_CHUNKED_DATA }; typedef enum hcl_client_state_t hcl_client_state_t; @@ -105,7 +116,8 @@ struct hcl_client_t { hcl_mmgr_t* mmgr; hcl_cmgr_t* cmgr; - /*hcl_t* dummy_hcl;*/ + hcl_client_prim_t prim; + hcl_t* dummy_hcl; hcl_errnum_t errnum; struct @@ -119,12 +131,8 @@ struct hcl_client_t { unsigned int trait; unsigned int logmask; - hcl_oow_t worker_max_count; - hcl_oow_t worker_stack_size; - hcl_ntime_t worker_idle_timeout; } cfg; - struct { hcl_bch_t* ptr; @@ -135,11 +143,6 @@ struct hcl_client_t hcl_client_state_t state; struct { - /* - hcl_ooch_t* ptr; - hcl_oow_t len; - hcl_oow_t capa; - */ struct { hcl_ooch_t* ptr; @@ -148,24 +151,77 @@ struct hcl_client_t } tok; hcl_client_reply_type_t type; - + hcl_client_reply_attr_type_t last_attr_type; + struct + { + hcl_ooch_t buf[HCL_CLIENT_REPLY_MAX_HDRKEY_LEN]; + hcl_oow_t len; + } last_attr_key; /* the last attr key shown */ + union { struct { hcl_oow_t nsplen; /* length remembered when the white space was shown */ } reply_value_unquoted; - + struct { int escaped; } reply_value_quoted; + + struct + { + hcl_oow_t nsplen; /* length remembered when the white space was shown */ + } attr_value_unquoted; + + struct + { + int escaped; + } attr_value_quoted; + + struct + { + hcl_oow_t max; + hcl_oow_t tally; + } length_bounded_data; + + struct + { + int in_data_part; + int negated; + hcl_oow_t max; /* chunk length */ + hcl_oow_t tally; + hcl_oow_t total; + hcl_oow_t clcount; + } chunked_data; } u; } rep; }; + /* ========================================================================= */ +static void log_write_for_dummy (hcl_t* hcl, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) +{ + dummy_hcl_xtn_t* xtn = (dummy_hcl_xtn_t*)hcl_getxtn(hcl); + hcl_client_t* client; + + client = xtn->client; + client->prim.log_write (client, mask, msg, len); +} + +static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len) +{ +#if defined(HAVE_STRERROR_R) + strerror_r (syserr, buf, len); +#else + /* this may not be thread safe */ + hcl_copybcstr (buf, len, strerror(syserr)); +#endif +} + +/* ========================================================================= */ static HCL_INLINE int is_spacechar (hcl_bch_t c) { @@ -220,23 +276,36 @@ static int add_to_reply_token (hcl_client_t* client, hcl_ooch_t ch) return 0; } -static void print_tok (hcl_client_t* client) +static HCL_INLINE int is_token (hcl_client_t* client, const hcl_bch_t* str) +{ + return hcl_compoocharsbcstr(client->rep.tok.ptr, client->rep.tok.len, str) == 0; +} + +static HCL_INLINE int is_token_integer (hcl_client_t* client, hcl_oow_t* value) { hcl_oow_t i; - printf ("{"); - for (i = 0; i < client->rep.tok.len; i++) - printf ("%lc", client->rep.tok.ptr[i]); - printf ("}\n"); -} + hcl_oow_t v = 0; -static int handle_char (hcl_client_t* client, hcl_ooci_t c) + if (client->rep.tok.len <= 0) return 0; + + for (i = 0; i < client->rep.tok.len; i++) + { + if (!is_digitchar(client->rep.tok.ptr[i])) return 0; + v = v * 10 + (client->rep.tok.ptr[i] - '0'); + } + + *value = v; + return 1; +} + +static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes) { switch (client->state) { case HCL_CLIENT_STATE_START: if (c == HCL_OOCI_EOF) { - printf ("unexpected end of reply\n"); + hcl_client_seterrbfmt (client, HCL_EFINIS, "unexpected end before reply name"); goto oops; } else if (c == '.') @@ -253,8 +322,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c) } else { - /* TODO: set error code? or log error messages? */ - printf ("reply line not starting with .\n"); + hcl_client_seterrbfmt (client, HCL_EINVAL, "reply line not starting with a period"); goto oops; } @@ -266,17 +334,17 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c) } else { - if (hcl_compoocharsbcstr(client->rep.tok.ptr, client->rep.tok.len, ".OK") == 0) + if (is_token(client, ".OK")) { client->rep.type = HCL_CLIENT_REPLY_TYPE_OK; } - else if (hcl_compoocharsbcstr(client->rep.tok.ptr, client->rep.tok.len, ".ERROR") == 0) + else if (is_token(client, ".ERROR")) { client->rep.type = HCL_CLIENT_REPLY_TYPE_ERROR; } else { - printf ("unknown reply name - [%.*ls]", (int)client->rep.tok.len, client->rep.tok.ptr); + hcl_client_seterrbfmt (client, HCL_EINVAL, "unknown reply name %.*js", client->rep.tok.len, client->rep.tok.ptr); goto oops; } @@ -288,9 +356,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c) case HCL_CLIENT_STATE_IN_REPLY_VALUE_START: if (c == HCL_OOCI_EOF) { - /* sudden end of EOF without NL */ - printf ("suddend enf of input without NL\n"); - /* TOOD: call call back as it it's just a normal reply. and don't goto oops*/ + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of reply line without newline"); goto oops; } else if (is_spacechar(c)) @@ -300,16 +366,19 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c) } else if (c == '\n') { - /* no value is specified. switch to a long-format response */ - client->state = HCL_CLIENT_STATE_IN_HEADER_NAME; + /* no value is specified. even no whitespaces. + * switch to a long-format response */ + client->prim.start_reply (client, client->rep.type, HCL_NULL, 0); + + client->state = HCL_CLIENT_STATE_IN_ATTR_KEY; HCL_ASSERT (client->dummy_hcl, client->rep.tok.len == 0); - client->rep.u.reply_value_quoted.escaped = 0; break; } else if (c == '\"') { client->state = HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED; HCL_ASSERT (client->dummy_hcl, client->rep.tok.len == 0); + client->rep.u.reply_value_quoted.escaped = 0; break; } else @@ -324,20 +393,13 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c) case HCL_CLIENT_STATE_IN_REPLY_VALUE_UNQUOTED: if (c == HCL_OOCI_EOF) { - /* sudden end of EOF without NL */ - printf ("suddend enf of input without NL\n"); - /* TOOD: call call back as it it's just a normal reply. and don't goto oops*/ + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of reply line without newline"); goto oops; } else if (c == '\n') { client->rep.tok.len = client->rep.u.reply_value_unquoted.nsplen; -printf ("reply value....===>"); -print_tok (client); -/* TODO: call callback */ - client->state = HCL_CLIENT_STATE_START; - clear_reply_token (client); - break; + goto reply_value_end; } else { @@ -349,15 +411,16 @@ print_tok (client); case HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED: if (c == HCL_OOCI_EOF) { - /* sudden end of EOF without NL */ - printf ("suddend enf of input witjpit closing quote. -> total failure\n"); + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of reply line without closing quote"); goto oops; } else { if (client->rep.u.reply_value_quoted.escaped) { - if (c == 'n') c = '\n'; + if (c == '\\') c = '\\'; + else if (c == '\"') c = '\"'; + else if (c == 'n') c = '\n'; else if (c == 'r') c = '\r'; /* TODO: more escaping handling */ } @@ -376,17 +439,23 @@ print_tok (client); if (add_to_reply_token(client, c) <= -1) goto oops; break; } - + case HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED_TRAILER: if (c == HCL_OOCI_EOF) { - printf ("suddend enf of input witjpit closing quote. -> total failure\n"); + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of reply line without newline"); goto oops; } else if (c == '\n') { -printf ("reply value....===>"); -print_tok (client); + reply_value_end: + /* short-form format. the data pointer is passed to the start_reply + * callback. no end_reply callback is invoked. the data is assumed + * to be in UTF-8 encoding. this is different from the data in the + * long-format reply which is treated as octet stream */ + client->prim.start_reply (client, client->rep.type, client->rep.tok.ptr, client->rep.tok.len); + /* no end_reply() callback for the short-form reply */ + client->state = HCL_CLIENT_STATE_START; clear_reply_token (client); break; @@ -398,14 +467,14 @@ print_tok (client); } else { - printf ("garbage after a quoted reply value [%lc]\n", c); + hcl_client_seterrbfmt (client, HCL_EINVAL, "garbage after quoted reply value"); goto oops; } - case HCL_CLIENT_STATE_IN_HEADER_NAME: + case HCL_CLIENT_STATE_IN_ATTR_KEY: if (c == HCL_OOCI_EOF) { - printf ("suddend end of input without a header name\n"); + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of attribute line"); goto oops; } else if (client->rep.tok.len == 0) @@ -417,7 +486,7 @@ print_tok (client); } else if (c != '.') { - printf ("header not starting with a period\n"); + hcl_client_seterrbfmt (client, HCL_EINVAL, "attribute name not starting with a period"); goto oops; } @@ -426,58 +495,192 @@ print_tok (client); } else if (is_alphachar(c) || (client->rep.tok.len > 2 && c == '-')) { + if (client->rep.tok.len >= HCL_CLIENT_REPLY_MAX_HDRKEY_LEN) + { + hcl_client_seterrbfmt (client, HCL_EINVAL, "attribute name too long"); + goto oops; + } if (add_to_reply_token(client, c) <= -1) goto oops; break; } else { - printf ("JKJJJJJJJJJ=>\n"); - print_tok(client); - if (hcl_compoocharsbcstr(client->rep.tok.ptr, client->rep.tok.len, ".ENCODING") == 0) + if (is_token(client, ".DATA")) { - printf ("encoding....\n"); - } - else if (hcl_compoocharsbcstr(client->rep.tok.ptr, client->rep.tok.len, ".LENGTH") == 0) - { - printf ("length....\n"); - } - else if (hcl_compoocharsbcstr(client->rep.tok.ptr, client->rep.tok.len, ".DATA") == 0) - { - printf ("data....\n"); + client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_DATA; } + /* PUT more known attribute handling here */ else { - printf ("unknown header ---> [%.*ls]\n", (int)client->rep.tok.len, client->rep.tok.ptr); - goto oops; + client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_UNKNOWN; } - client->state = HCL_CLIENT_STATE_IN_HEADER_VALUE; + HCL_ASSERT (client->dummy_hcl, client->rep.tok.len <= HCL_COUNTOF(client->rep.last_attr_key.buf)); + hcl_copyoochars (client->rep.last_attr_key.buf, client->rep.tok.ptr, client->rep.tok.len); + client->rep.last_attr_key.len = client->rep.tok.len; + + client->state = HCL_CLIENT_STATE_IN_ATTR_VALUE_START; clear_reply_token (client); /* [IMPORTANT] fall thru */ } -/* -echo -n -e '.OK"YOYO bc\n\" abc" \n .ERROR "XYZ"\n.OK\n.ENCODING chunked\n' |~/xxx/bin/hclc 11111 - */ - - case HCL_CLIENT_STATE_IN_HEADER_VALUE: + case HCL_CLIENT_STATE_IN_ATTR_VALUE_START: if (c == HCL_OOCI_EOF) { - printf ("sudden end of input whthout header value\n"); + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end without attribute value"); goto oops; } + else if (is_spacechar(c)) + { + /* do nothing. skip it */ + break; + } else if (c == '\n') { - printf ("XXXXXXXXXXXXXXxx\n"); + hcl_client_seterrbfmt (client, HCL_EINVAL, "no attribute value for %.*js\n", client->rep.last_attr_key.len, client->rep.last_attr_key.buf); + goto oops; + } + else if (c == '\"') + { + client->state = HCL_CLIENT_STATE_IN_ATTR_VALUE_QUOTED; + HCL_ASSERT (client->dummy_hcl, client->rep.tok.len == 0); + client->rep.u.attr_value_quoted.escaped = 0; break; } else { - printf ("add to header value....\n"); + /* the first value character has been encountered */ + client->state = HCL_CLIENT_STATE_IN_ATTR_VALUE_UNQUOTED; + HCL_ASSERT (client->dummy_hcl, client->rep.tok.len == 0); + client->rep.u.attr_value_unquoted.nsplen = 0; + /* [IMPORTANT] fall thru */ + } + + case HCL_CLIENT_STATE_IN_ATTR_VALUE_UNQUOTED: + if (c == HCL_OOCI_EOF) + { + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of attribute line without newline"); + goto oops; + } + else if (c == '\n') + { + client->rep.tok.len = client->rep.u.attr_value_unquoted.nsplen; + goto attr_value_end; + } + else + { + if (add_to_reply_token(client, c) <= -1) goto oops; + if (!is_spacechar(c)) client->rep.u.attr_value_unquoted.nsplen = client->rep.tok.len; break; } - break; + case HCL_CLIENT_STATE_IN_ATTR_VALUE_QUOTED: + if (c == HCL_OOCI_EOF) + { + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of attribute value without closing quote"); + goto oops; + } + else + { + if (client->rep.u.attr_value_quoted.escaped) + { + if (c == '\\') c = '\\'; + else if (c == '\"') c = '\"'; + else if (c == 'n') c = '\n'; + else if (c == 'r') c = '\r'; + /* TODO: more escaping handling */ + } + else if (c == '\\') + { + client->rep.u.attr_value_quoted.escaped = 1; + break; + } + else if (c == '\"') + { + client->state = HCL_CLIENT_STATE_IN_ATTR_VALUE_QUOTED_TRAILER; + break; + } + + client->rep.u.attr_value_quoted.escaped = 0; + if (add_to_reply_token(client, c) <= -1) goto oops; + break; + } + + case HCL_CLIENT_STATE_IN_ATTR_VALUE_QUOTED_TRAILER: + if (c == HCL_OOCI_EOF) + { + hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of attribute line without newline"); + goto oops; + } + else if (c == '\n') + { + attr_value_end: + if (client->prim.feed_attr) + { + hcl_oocs_t key, val; + key.ptr = client->rep.last_attr_key.buf; + key.len = client->rep.last_attr_key.len; + val.ptr = client->rep.tok.ptr; + val.len = client->rep.tok.len; + client->prim.feed_attr (client, &key, &val); + } + + if (client->rep.last_attr_type == HCL_CLIENT_REPLY_ATTR_TYPE_DATA) + { + hcl_oow_t length; + + /* this must be the last attr. the trailing part are all data */ + if (is_token(client, "chunked")) + { + client->state = HCL_CLIENT_STATE_IN_CHUNKED_DATA; + HCL_MEMSET (&client->rep.u.chunked_data, 0, HCL_SIZEOF(client->rep.u.chunked_data)); + } + else if (is_token_integer(client, &length)) + { + if (length > 0) + { + client->state = HCL_CLIENT_STATE_IN_LENGTH_BOUNDED_DATA; + /* [NOTE] the max length for the length-bounded transfer scheme is limited + * by the system word size as of this implementation */ + client->rep.u.length_bounded_data.max = length; + client->rep.u.length_bounded_data.tally = 0; + } + else + { + /* .DATA 0 has been received. this should be end of the reply */ + client->state = HCL_CLIENT_STATE_START; + } + } + else + { + hcl_client_seterrbfmt (client, HCL_EINVAL, "invalid attribute value for .DATA - %.*js", client->rep.tok.len, client->rep.tok.ptr); + goto oops; + } + } + else + { + /* continue processing the next attr */ + client->state = HCL_CLIENT_STATE_IN_ATTR_KEY; + } + + clear_reply_token (client); + break; + } + else if (is_spacechar(c)) + { + /* skip white spaces after the closing quote */ + break; + } + else + { + hcl_client_seterrbfmt (client, HCL_EINVAL, "garbage after quoted attribute value for %.*js", client->rep.last_attr_key.len, client->rep.last_attr_key.buf); + goto oops; + } + + default: + /* this function must not be called for .DATA */ + hcl_client_seterrbfmt (client, HCL_EINTERN, "internal error - must not be called for state %d", client->state); + goto oops; } return 0; @@ -494,18 +697,118 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow ptr = data; end = ptr + len; -//printf ("<<<%.*s>>>\n", (int)len, data); - if (client->state == HCL_CLIENT_STATE_IN_BINARY_DATA) + while (ptr < end) { - } - else - { - while (ptr < end) + if (client->state == HCL_CLIENT_STATE_IN_LENGTH_BOUNDED_DATA) + { + /* the data is treated as raw octets by this client */ + hcl_oow_t capa, avail, taken; + + capa = client->rep.u.length_bounded_data.max - client->rep.u.length_bounded_data.tally; + avail = end - ptr; + taken = (avail < capa)? avail: capa; + + if (client->prim.feed_data) + { + client->prim.feed_data (client, ptr, taken); + } + + ptr += taken; + client->rep.u.length_bounded_data.tally = taken; + if (taken == capa) + { + /* read all data. no more */ + client->state = HCL_CLIENT_STATE_START; + client->prim.end_reply (client, HCL_CLIENT_END_REPLY_STATE_OK); + } + } + else if (client->state == HCL_CLIENT_STATE_IN_CHUNKED_DATA) + { + /* the data is treated as raw octets by this client */ + if (client->rep.u.chunked_data.in_data_part) + { + hcl_oow_t capa, avail, taken; + + capa = client->rep.u.chunked_data.max - client->rep.u.chunked_data.tally; + avail = end - ptr; + taken = (avail < capa)? avail: capa; + + if (client->prim.feed_data) + { + client->prim.feed_data (client, ptr, taken); + } + + ptr += taken; + client->rep.u.chunked_data.tally += taken; + client->rep.u.chunked_data.total += taken; + if (taken == capa) + { + /* finished one chunk */ + client->rep.u.chunked_data.negated = 0; + client->rep.u.chunked_data.max = 0; + client->rep.u.chunked_data.tally = 0; + client->rep.u.chunked_data.clcount = 0; + client->rep.u.chunked_data.in_data_part = 0; + } + } + else + { + while (ptr < end) + { + hcl_bchu_t bc = (hcl_bchu_t)*ptr; + if (bc == '-' && client->rep.u.chunked_data.clcount == 0 && !client->rep.u.chunked_data.negated) + { + client->rep.u.chunked_data.negated = 1; + } + else if (bc == ':') + { + ptr++; + + if (client->rep.u.chunked_data.clcount == 0) + { + hcl_client_seterrbfmt (client, HCL_EINVAL, "clone without valid chunk length"); + goto oops; + } + + if (client->rep.u.chunked_data.negated) + { + client->prim.end_reply (client, HCL_CLIENT_END_REPLY_STATE_REVOKED); + client->state = HCL_CLIENT_STATE_START; + + } + if (client->rep.u.chunked_data.max == 0) + { + client->prim.end_reply (client, HCL_CLIENT_END_REPLY_STATE_OK); + client->state = HCL_CLIENT_STATE_START; + } + else + { + client->rep.u.chunked_data.in_data_part = 1; + client->rep.u.chunked_data.tally = 0; + } + break; + } + else if (is_digitchar(bc)) + { + client->rep.u.chunked_data.max = client->rep.u.chunked_data.max * 10 + (bc - '0'); + client->rep.u.chunked_data.clcount++; + ptr++; + } + else + { + hcl_client_seterrbfmt (client, HCL_EINVAL, "invalid chunk length character - code[%#x]", bc); + goto oops; + } + } + } + } + else { hcl_ooci_t c; + hcl_oow_t bcslen; #if defined(HCL_OOCH_IS_UCH) - hcl_oow_t bcslen, ucslen; + hcl_oow_t ucslen; hcl_ooch_t uc; int n; @@ -518,7 +821,6 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow if (n == -3) { /* incomplete sequence */ - printf ("incompelete....feed me more\n"); *xlen = ptr - data; return 0; /* feed more for incomplete sequence */ } @@ -527,11 +829,12 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow ptr += bcslen; c = uc; #else + bcslen = 1; c = *ptr++; #endif -printf ("[%lc]\n", c); - if (handle_char(client, c) <= -1) goto oops; +//printf ("[%lc]\n", c); + if (handle_char(client, c, bcslen) <= -1) goto oops; } } @@ -540,7 +843,7 @@ printf ("[%lc]\n", c); oops: /* TODO: compute the number of processes bytes so far and return it via a parameter??? */ -printf ("feed oops....\n"); +/*printf ("feed oops....\n");*/ return -1; } @@ -571,14 +874,10 @@ static int feed_all_reply_data (hcl_client_t* client, hcl_bch_t* buf, hcl_oow_t hcl_client_t* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_prim_t* prim, hcl_errnum_t* errnum) { hcl_client_t* client; -#if 0 hcl_t* hcl; hcl_vmprim_t vmprim; - hcl_tmr_t* tmr; dummy_hcl_xtn_t* xtn; - int pfd[2], fcv; - unsigned int trait; -#endif +/* unsigned int trait;*/ client = (hcl_client_t*)HCL_MMGR_ALLOC(mmgr, HCL_SIZEOF(*client) + xtnsize); if (!client) @@ -587,15 +886,9 @@ hcl_client_t* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_p return HCL_NULL; } -#if 0 HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim)); vmprim.log_write = log_write_for_dummy; vmprim.syserrstrb = syserrstrb; - vmprim.dl_open = dl_open; - vmprim.dl_close = dl_close; - vmprim.dl_getsym = dl_getsym; - vmprim.vm_gettime = vm_gettime; - vmprim.vm_sleep = vm_sleep; hcl = hcl_open(mmgr, HCL_SIZEOF(*xtn), 2048, &vmprim, errnum); if (!hcl) @@ -604,35 +897,6 @@ hcl_client_t* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_p return HCL_NULL; } - tmr = hcl_tmr_open(hcl, 0, 1024); /* TOOD: make the timer's default size configurable */ - if (!tmr) - { - hcl_close (hcl); - HCL_MMGR_FREE (mmgr, client); - return HCL_NULL; - } - - if (pipe(pfd) <= -1) - { - hcl_tmr_close (tmr); - hcl_close (hcl); - HCL_MMGR_FREE (mmgr, client); - return HCL_NULL; - } - -#if defined(O_CLOEXEC) - fcv = fcntl(pfd[0], F_GETFD, 0); - if (fcv >= 0) fcntl(pfd[0], F_SETFD, fcv | O_CLOEXEC); - fcv = fcntl(pfd[1], F_GETFD, 0); - if (fcv >= 0) fcntl(pfd[1], F_SETFD, fcv | O_CLOEXEC); -#endif -#if defined(O_NONBLOCK) - fcv = fcntl(pfd[0], F_GETFL, 0); - if (fcv >= 0) fcntl(pfd[0], F_SETFL, fcv | O_NONBLOCK); - fcv = fcntl(pfd[1], F_GETFL, 0); - if (fcv >= 0) fcntl(pfd[1], F_SETFL, fcv | O_NONBLOCK); -#endif - xtn = (dummy_hcl_xtn_t*)hcl_getxtn(hcl); xtn->client = client; @@ -641,81 +905,42 @@ hcl_client_t* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_p client->cmgr = hcl_get_utf8_cmgr(); client->prim = *prim; client->dummy_hcl = hcl; - client->tmr = tmr; client->cfg.logmask = ~0u; - client->cfg.worker_stack_size = 512000UL; - client->cfg.actor_heap_size = 512000UL; - - HCL_INITNTIME (&client->cfg.worker_idle_timeout, 0, 0); - HCL_INITNTIME (&client->cfg.actor_max_runtime, 0, 0); - - client->mux_pipe[0] = pfd[0]; - client->mux_pipe[1] = pfd[1]; - - client->wid_map.free_first = HCL_SERVER_WID_INVALID; - client->wid_map.free_last = HCL_SERVER_WID_INVALID; - - pthread_mutex_init (&client->worker_mutex, HCL_NULL); - pthread_mutex_init (&client->tmr_mutex, HCL_NULL); - pthread_mutex_init (&client->log_mutex, HCL_NULL); /* the dummy hcl is used for this client to perform primitive operations * such as getting system time or logging. so the heap size doesn't * need to be changed from the tiny value set above. */ hcl_setoption (client->dummy_hcl, HCL_LOG_MASK, &client->cfg.logmask); hcl_setcmgr (client->dummy_hcl, client->cmgr); - hcl_getoption (client->dummy_hcl, HCL_TRAIT, &trait); -#if defined(HCL_BUILD_DEBUG) - if (client->cfg.trait & HCL_SERVER_TRAIT_DEBUG_GC) trait |= HCL_DEBUG_GC; - if (client->cfg.trait & HCL_SERVER_TRAIT_DEBUG_BIGINT) trait |= HCL_DEBUG_BIGINT; -#endif - hcl_setoption (client->dummy_hcl, HCL_TRAIT, &trait); -#else - - HCL_MEMSET (client, 0, HCL_SIZEOF(*client) + xtnsize); - client->mmgr = mmgr; - client->cmgr = hcl_get_utf8_cmgr(); - -#endif return client; } void hcl_client_close (hcl_client_t* client) { + if (client->rep.tok.ptr) + { + hcl_client_freemem (client, client->rep.tok.ptr); + client->rep.tok.ptr = HCL_NULL; + client->rep.tok.len = 0; + client->rep.tok.capa = 0; + } + + hcl_close (client->dummy_hcl); HCL_MMGR_FREE (client->mmgr, client); } - int hcl_client_setoption (hcl_client_t* client, hcl_client_option_t id, const void* value) { switch (id) { case HCL_CLIENT_TRAIT: client->cfg.trait = *(const unsigned int*)value; - #if 0 - if (client->dummy_hcl) - { - /* setting this affects the dummy hcl immediately. - * existing hcl instances inside worker threads won't get - * affected. new hcl instances to be created later - * is supposed to use the new value */ - unsigned int trait; - - hcl_getoption (client->dummy_hcl, HCL_TRAIT, &trait); - #if defined(HCL_BUILD_DEBUG) - if (client->cfg.trait & HCL_CLIENT_TRAIT_DEBUG_GC) trait |= HCL_DEBUG_GC; - if (client->cfg.trait & HCL_CLIENT_TRAIT_DEBUG_BIGINT) trait |= HCL_DEBUG_BIGINT; - #endif - hcl_setoption (client->dummy_hcl, HCL_TRAIT, &trait); - } - #endif return 0; case HCL_CLIENT_LOG_MASK: client->cfg.logmask = *(const unsigned int*)value; - #if 0 if (client->dummy_hcl) { /* setting this affects the dummy hcl immediately. @@ -724,19 +949,6 @@ int hcl_client_setoption (hcl_client_t* client, hcl_client_option_t id, const vo * is supposed to use the new value */ hcl_setoption (client->dummy_hcl, HCL_LOG_MASK, value); } - #endif - return 0; - - case HCL_CLIENT_WORKER_MAX_COUNT: - client->cfg.worker_max_count = *(hcl_oow_t*)value; - return 0; - - case HCL_CLIENT_WORKER_STACK_SIZE: - client->cfg.worker_stack_size = *(hcl_oow_t*)value; - return 0; - - case HCL_CLIENT_WORKER_IDLE_TIMEOUT: - client->cfg.worker_idle_timeout = *(hcl_ntime_t*)value; return 0; } @@ -755,18 +967,6 @@ int hcl_client_getoption (hcl_client_t* client, hcl_client_option_t id, void* va case HCL_CLIENT_LOG_MASK: *(unsigned int*)value = client->cfg.logmask; return 0; - - case HCL_CLIENT_WORKER_MAX_COUNT: - *(hcl_oow_t*)value = client->cfg.worker_max_count; - return 0; - - case HCL_CLIENT_WORKER_STACK_SIZE: - *(hcl_oow_t*)value = client->cfg.worker_stack_size; - return 0; - - case HCL_CLIENT_WORKER_IDLE_TIMEOUT: - *(hcl_ntime_t*)value = client->cfg.worker_idle_timeout; - return 0; }; hcl_client_seterrnum (client, HCL_EINVAL); @@ -817,6 +1017,54 @@ void hcl_client_seterrnum (hcl_client_t* client, hcl_errnum_t errnum) client->errmsg.len = 0; } +void hcl_client_seterrbfmt (hcl_client_t* client, hcl_errnum_t errnum, const hcl_bch_t* fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + hcl_seterrbfmtv (client->dummy_hcl, errnum, fmt, ap); + va_end (ap); + + HCL_ASSERT (client->dummy_hcl, HCL_COUNTOF(client->errmsg.buf) == HCL_COUNTOF(client->dummy_hcl->errmsg.buf)); + client->errnum = errnum; + hcl_copyoochars (client->errmsg.buf, client->dummy_hcl->errmsg.buf, HCL_COUNTOF(client->errmsg.buf)); + client->errmsg.len = client->dummy_hcl->errmsg.len; +} + +void hcl_client_seterrufmt (hcl_client_t* client, hcl_errnum_t errnum, const hcl_uch_t* fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + hcl_seterrufmtv (client->dummy_hcl, errnum, fmt, ap); + va_end (ap); + + HCL_ASSERT (client->dummy_hcl, HCL_COUNTOF(client->errmsg.buf) == HCL_COUNTOF(client->dummy_hcl->errmsg.buf)); + client->errnum = errnum; + hcl_copyoochars (client->errmsg.buf, client->dummy_hcl->errmsg.buf, HCL_COUNTOF(client->errmsg.buf)); + client->errmsg.len = client->dummy_hcl->errmsg.len; +} + +/* ========================================================================= */ + +void hcl_client_logbfmt (hcl_client_t* client, unsigned int mask, const hcl_bch_t* fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + hcl_logbfmtv (client->dummy_hcl, mask, fmt, ap); + va_end (ap); +} + +void hcl_client_logufmt (hcl_client_t* client, unsigned int mask, const hcl_uch_t* fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + hcl_logufmtv (client->dummy_hcl, mask, fmt, ap); + va_end (ap); +} + +/* ========================================================================= */ + void* hcl_client_allocmem (hcl_client_t* client, hcl_oow_t size) { void* ptr; @@ -848,7 +1096,6 @@ void hcl_client_freemem (hcl_client_t* client, void* ptr) HCL_MMGR_FREE (client->mmgr, ptr); } - /* ========================================================================= */ int hcl_client_start (hcl_client_t* client, const hcl_bch_t* addrs) @@ -887,7 +1134,6 @@ int hcl_client_start (hcl_client_t* client, const hcl_bch_t* addrs) if (offset > 0) HCL_MEMMOVE (&buf[0], &buf[xlen], offset); } -printf ("hcl client start returns success\n"); return 0; } diff --git a/lib/hcl-c.h b/lib/hcl-c.h index e81c8ed..621cd3f 100644 --- a/lib/hcl-c.h +++ b/lib/hcl-c.h @@ -36,38 +36,84 @@ enum hcl_client_option_t { HCL_CLIENT_TRAIT, HCL_CLIENT_LOG_MASK, - HCL_CLIENT_WORKER_MAX_COUNT, - HCL_CLIENT_WORKER_STACK_SIZE, - HCL_CLIENT_WORKER_IDLE_TIMEOUT }; typedef enum hcl_client_option_t hcl_client_option_t; enum hcl_client_trait_t { -#if defined(HCL_BUILD_DEBUG) - HCL_CLIENT_TRAIT_DEBUG_GC = (1 << 0), - HCL_CLIENT_TRAIT_DEBUG_BIGINT = (1 << 1), -#endif - - HCL_CLIENT_TRAIT_READABLE_PROTO = (1 << 2), - HCL_CLIENT_TRAIT_USE_LARGE_PAGES = (1 << 3) + /* no trait defined at this moment. XXXX is just a placeholder */ + HCL_CLIENT_XXXX = (1 << 0) }; typedef enum hcl_client_trait_t hcl_client_trait_t; +/* ========================================================================= */ + +enum hcl_client_reply_type_t +{ + HCL_CLIENT_REPLY_TYPE_OK = 0, + HCL_CLIENT_REPLY_TYPE_ERROR = 1 +}; +typedef enum hcl_client_reply_type_t hcl_client_reply_type_t; + typedef void (*hcl_client_log_write_t) ( hcl_client_t* client, - hcl_oow_t wid, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len ); +typedef void (*hcl_client_start_reply_t) ( + hcl_client_t* client, + hcl_client_reply_type_t type, + const hcl_ooch_t* dptr, + hcl_oow_t dlen +); + +typedef void (*hcl_client_feed_attr_t) ( + hcl_client_t* client, + const hcl_oocs_t* key, + const hcl_oocs_t* val +); + +typedef void (*hcl_client_start_data_t) ( + hcl_client_t* client +); + +typedef void (*hcl_client_feed_data_t) ( + hcl_client_t* client, + const void* ptr, + hcl_oow_t len +); + +typedef void (*hcl_client_end_data_t) ( + hcl_client_t* client +); + +enum hcl_client_end_reply_state_t +{ + HCL_CLIENT_END_REPLY_STATE_OK, + HCL_CLIENT_END_REPLY_STATE_REVOKED, + HCL_CLIENT_END_REPLY_STATE_ERROR +}; +typedef enum hcl_client_end_reply_state_t hcl_client_end_reply_state_t; + +typedef void (*hcl_client_end_reply_t) ( + hcl_client_t* client, + hcl_client_end_reply_state_t state +); + struct hcl_client_prim_t { - hcl_client_log_write_t log_write; + hcl_client_log_write_t log_write; + + hcl_client_start_reply_t start_reply; /* mandatory */ + hcl_client_feed_attr_t feed_attr; /* optional */ + hcl_client_feed_data_t feed_data; /* optional */ + hcl_client_end_reply_t end_reply; /* mandatory */ }; typedef struct hcl_client_prim_t hcl_client_prim_t; +/* ========================================================================= */ #if defined(__cplusplus) extern "C" { @@ -141,9 +187,33 @@ HCL_EXPORT void hcl_client_seterrnum ( hcl_errnum_t errnum ); +HCL_EXPORT void hcl_client_seterrbfmt ( + hcl_client_t* client, + hcl_errnum_t errnum, + const hcl_bch_t* fmt, + ... +); +HCL_EXPORT void hcl_client_seterrufmt ( + hcl_client_t* client, + hcl_errnum_t errnum, + const hcl_uch_t* fmt, + ... +); +HCL_EXPORT void hcl_client_logbfmt ( + hcl_client_t* client, + unsigned int mask, + const hcl_bch_t* fmt, + ... +); +HCL_EXPORT void hcl_client_logufmt ( + hcl_client_t* client, + unsigned int mask, + const hcl_uch_t* fmt, + ... +); HCL_EXPORT void* hcl_client_allocmem ( hcl_client_t* client, @@ -167,7 +237,6 @@ HCL_EXPORT void hcl_client_freemem ( void* ptr ); - #if defined(__cplusplus) } #endif diff --git a/lib/hcl-s.c b/lib/hcl-s.c index 6b74b7e..471a6de 100644 --- a/lib/hcl-s.c +++ b/lib/hcl-s.c @@ -161,7 +161,6 @@ struct dummy_hcl_xtn_t }; typedef struct dummy_hcl_xtn_t dummy_hcl_xtn_t; - enum hcl_server_proto_token_type_t { HCL_SERVER_PROTO_TOKEN_EOF, @@ -276,7 +275,7 @@ struct hcl_server_wid_map_data_t } u; }; typedef struct hcl_server_wid_map_data_t hcl_server_wid_map_data_t; - + struct hcl_server_t { hcl_mmgr_t* mmgr; @@ -1111,12 +1110,12 @@ static int write_reply_chunk (hcl_server_proto_t* proto) if (proto->reply.nchunks <= 0) { /* this is the first chunk */ - iov[count].iov_base = ".OK\n.ENCODING chunked\n.DATA\n"; - iov[count++].iov_len = 28; + iov[count].iov_base = ".OK\n.DATA chunked\n"; + iov[count++].iov_len = 18; } iov[count].iov_base = cl, - iov[count++].iov_len = snprintf(cl, HCL_SIZEOF(cl), "%s%zu:", (((proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_READABLE_PROTO) && proto->reply.nchunks > 0)? "\n": ""), proto->reply.len); + iov[count++].iov_len = snprintf(cl, HCL_SIZEOF(cl), "%zu:", proto->reply.len); } iov[count].iov_base = proto->reply.buf; iov[count++].iov_len = proto->reply.len; @@ -1245,14 +1244,14 @@ int hcl_server_proto_end_reply (hcl_server_proto_t* proto, const hcl_ooch_t* fai /* some chunks have beed emitted. but at the end, an error has occurred. * send -1: as the last chunk. the receiver must rub out the reply * buffer received so far and expect the following .ERROR response */ - static hcl_ooch_t err0[] = { '-','1',':','\n' }; + static hcl_ooch_t err0[] = { '-','1',':' }; if (proto->reply.len > 0 && write_reply_chunk(proto) <= -1) return -1; proto->reply.type = HCL_SERVER_PROTO_REPLY_SIMPLE; /* switch to the simple mode forcibly */ proto->reply.nchunks = 0; proto->reply.len = 0; - if (hcl_server_proto_feed_reply(proto, err0, 4, 0) <= -1) return -1; + if (hcl_server_proto_feed_reply(proto, err0, 3, 0) <= -1) return -1; goto simple_error; } } diff --git a/lib/hcl-s.h b/lib/hcl-s.h index 30211f3..99f6522 100644 --- a/lib/hcl-s.h +++ b/lib/hcl-s.h @@ -53,8 +53,7 @@ enum hcl_server_trait_t HCL_SERVER_TRAIT_DEBUG_BIGINT = (1 << 1), #endif - HCL_SERVER_TRAIT_READABLE_PROTO = (1 << 2), - HCL_SERVER_TRAIT_USE_LARGE_PAGES = (1 << 3) + HCL_SERVER_TRAIT_USE_LARGE_PAGES = (1 << 2) }; typedef enum hcl_server_trait_t hcl_server_trait_t; diff --git a/lib/main-c.c b/lib/main-c.c index 80ac838..b0de14e 100644 --- a/lib/main-c.c +++ b/lib/main-c.c @@ -190,7 +190,7 @@ static void flush_log (hcl_client_t* client, int fd) } } -static void log_write (hcl_client_t* client, hcl_oow_t wid, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) +static void log_write (hcl_client_t* client, unsigned int mask, const hcl_ooch_t* msg, hcl_oow_t len) { hcl_bch_t buf[256]; hcl_oow_t ucslen, bcslen; @@ -242,15 +242,6 @@ static void log_write (hcl_client_t* client, hcl_oow_t wid, unsigned int mask, c } write_log (client, logfd, ts, tslen); - -#if 0 - if (wid != HCL_CLIENT_WID_INVALID) - { - /* TODO: check if the underlying snprintf support %zd */ - tslen = snprintf (ts, sizeof(ts), "[%zu] ", wid); - write_log (client, logfd, ts, tslen); - } -#endif } if (logfd == xtn->logfd && xtn->logfd_istty) @@ -445,38 +436,43 @@ static int handle_logopt (hcl_client_t* client, const hcl_bch_t* str) return 0; } -#if defined(HCL_BUILD_DEBUG) -static int handle_dbgopt (hcl_client_t* client, const char* str) +static void start_reply (hcl_client_t* client, hcl_client_reply_type_t type, const hcl_ooch_t* dptr, hcl_oow_t dlen) { - const hcl_bch_t* cm, * flt; - hcl_oow_t len; - unsigned int trait; - - hcl_client_getoption (client, HCL_CLIENT_TRAIT, &trait); - - cm = str - 1; - do + if (dptr) { - flt = cm + 1; - - cm = hcl_findbcharinbcstr(flt, ','); - len = cm? (cm - flt): hcl_countbcstr(flt); - if (hcl_compbcharsbcstr(flt, len, "gc") == 0) trait |= HCL_CLIENT_TRAIT_DEBUG_GC; - else if (hcl_compbcharsbcstr(flt, len, "bigint") == 0) trait |= HCL_CLIENT_TRAIT_DEBUG_BIGINT; - else - { - fprintf (stderr, "ERROR: unknown debug option value - %.*s\n", (int)len, flt); - return -1; - } + printf ("GOT SHORT-FORM RESPONSE[%d] with data <<%.*ls>>\n", (int)type, (int)dlen, dptr); + } + else + { + printf ("GOT LONG_FORM RESPONSE[%d]\n", (int)type); } - while (cm); - - hcl_client_setoption (client, HCL_CLIENT_TRAIT, &trait); - return 0; } -#endif +static void end_reply (hcl_client_t* client, hcl_client_end_reply_state_t state) +{ + if (state == HCL_CLIENT_END_REPLY_STATE_ERROR) + { +printf (">>>>>>>>>>>>>>>>>>>>> reply error....\n"); + } + else if (state == HCL_CLIENT_END_REPLY_STATE_REVOKED) + { +printf (">>>>>>>>>>>>>>>>>>>>>> REPLY revoked....\n"); + } + else + { +printf (">>>>>>>>>>>>>>>>>>>>> REPLY ENDED OK....\n"); + } +} +static void feed_attr (hcl_client_t* client, const hcl_oocs_t* key, const hcl_oocs_t* val) +{ +printf ("GOT HEADER ====> [%.*ls] ===> [%.*ls]\n", (int)key->len, key->ptr, (int)val->len, val->ptr); +} + +static void feed_data (hcl_client_t* client, const void* ptr, hcl_oow_t len) +{ +printf ("GOT DATA>>>>>>>>>[%.*s]>>>>>>>\n", (int)len, ptr); +} /* ========================================================================= */ #define MIN_WORKER_STACK_SIZE 512000ul @@ -488,14 +484,7 @@ int main (int argc, char* argv[]) static hcl_bopt_lng_t lopt[] = { { ":log", 'l' }, - { "large-pages", '\0' }, - { ":worker-max-count", '\0' }, - { ":worker-stack-size", '\0' }, - { ":worker-idle-timeout", '\0' }, - #if defined(HCL_BUILD_DEBUG) - { ":debug", '\0' }, /* NOTE: there is no short option for --debug */ - #endif - { HCL_NULL, '\0' } + { HCL_NULL, '\0' } }; static hcl_bopt_t opt = { @@ -507,14 +496,7 @@ int main (int argc, char* argv[]) client_xtn_t* xtn; hcl_client_prim_t client_prim; int n; - const char* logopt = HCL_NULL; - const char* dbgopt = HCL_NULL; - hcl_oow_t worker_max_count = 0; - hcl_oow_t worker_stack_size = MIN_ACTOR_HEAP_SIZE; - hcl_ntime_t worker_idle_timeout = { 0, 0 }; - int large_pages = 0; - unsigned int trait; setlocale (LC_ALL, ""); @@ -535,30 +517,7 @@ int main (int argc, char* argv[]) break; case '\0': - if (hcl_compbcstr(opt.lngopt, "large-pages") == 0) - { - large_pages = 1; - } - else if (hcl_compbcstr(opt.lngopt, "worker-max-count") == 0) - { - worker_max_count = strtoul(opt.arg, HCL_NULL, 0); - } - else if (hcl_compbcstr(opt.lngopt, "worker-stack-size") == 0) - { - worker_stack_size = strtoul(opt.arg, HCL_NULL, 0); - if (worker_stack_size <= MIN_WORKER_STACK_SIZE) worker_stack_size = MIN_WORKER_STACK_SIZE; - } - else if (hcl_compbcstr(opt.lngopt, "worker-idle-timeout") == 0) - { - worker_idle_timeout.sec = strtoul(opt.arg, HCL_NULL, 0); - } - #if defined(HCL_BUILD_DEBUG) - else if (hcl_compbcstr(opt.lngopt, "debug") == 0) - { - dbgopt = opt.arg; - } - #endif - else goto print_usage; + goto print_usage; break; case ':': @@ -578,6 +537,10 @@ int main (int argc, char* argv[]) memset (&client_prim, 0, HCL_SIZEOF(client_prim)); client_prim.log_write = log_write; + client_prim.start_reply = start_reply; + client_prim.feed_attr = feed_attr; + client_prim.feed_data = feed_data; + client_prim.end_reply = end_reply; client = hcl_client_open(&sys_mmgr, HCL_SIZEOF(client_xtn_t), &client_prim, HCL_NULL); if (!client) @@ -600,22 +563,6 @@ int main (int argc, char* argv[]) xtn->logmask = HCL_LOG_ALL_TYPES | HCL_LOG_ERROR | HCL_LOG_FATAL; } -#if defined(HCL_BUILD_DEBUG) - if (dbgopt) - { - if (handle_dbgopt(client, dbgopt) <= -1) goto oops; - } -#endif - - hcl_client_getoption (client, HCL_CLIENT_TRAIT, &trait); - if (large_pages) trait |= HCL_CLIENT_TRAIT_USE_LARGE_PAGES; - else trait &= ~HCL_CLIENT_TRAIT_USE_LARGE_PAGES; - hcl_client_setoption (client, HCL_CLIENT_TRAIT, &trait); - - hcl_client_setoption (client, HCL_CLIENT_WORKER_MAX_COUNT, &worker_max_count); - hcl_client_setoption (client, HCL_CLIENT_WORKER_STACK_SIZE, &worker_stack_size); - hcl_client_setoption (client, HCL_CLIENT_WORKER_IDLE_TIMEOUT, &worker_idle_timeout); - g_client = client; set_signal (SIGINT, handle_sigint); set_signal_to_ignore (SIGPIPE); @@ -627,13 +574,15 @@ int main (int argc, char* argv[]) if (n <= -1) { - // hcl_client_logbfmt (client, HCL_LOG_APP | HCL_LOG_FATAL, "client error[%d] - %js\n", hcl_client_geterrnum(client), hcl_client_geterrmsg(client)); -printf ("hcl client error... = %d\n", hcl_client_geterrnum(client)); + hcl_client_logbfmt (client, HCL_LOG_APP | HCL_LOG_FATAL, "client error[%d] - %js\n", hcl_client_geterrnum(client), hcl_client_geterrmsg(client)); } - close (xtn->logfd); - xtn->logfd = -1; - xtn->logfd_istty = 0; + if (xtn->logfd >= 0) + { + close (xtn->logfd); + xtn->logfd = -1; + xtn->logfd_istty = 0; + } hcl_client_close (client); return n; diff --git a/lib/main-s.c b/lib/main-s.c index c23344d..2c584b2 100644 --- a/lib/main-s.c +++ b/lib/main-s.c @@ -667,9 +667,12 @@ int main (int argc, char* argv[]) hcl_server_logbfmt (server, HCL_LOG_APP | HCL_LOG_FATAL, "server error[%d] - %js\n", hcl_server_geterrnum(server), hcl_server_geterrmsg(server)); } - close (xtn->logfd); - xtn->logfd = -1; - xtn->logfd_istty = 0; + if (xtn->logfd >= 0) + { + close (xtn->logfd); + xtn->logfd = -1; + xtn->logfd_istty = 0; + } hcl_server_close (server); return n;