added reply handler
This commit is contained in:
parent
69e50af80f
commit
f675835a11
672
lib/hcl-c.c
672
lib/hcl-c.c
@ -31,9 +31,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define HCL_SERVER_TOKEN_NAME_ALIGN 64
|
#define HCL_CLIENT_TOKEN_NAME_ALIGN 64
|
||||||
#define HCL_SERVER_WID_MAP_ALIGN 512
|
#define HCL_CLIENT_WID_MAP_ALIGN 512
|
||||||
#define HCL_SERVER_PROTO_REPLY_BUF_SIZE 1300
|
#define HCL_CLIENT_PROTO_REPLY_BUF_SIZE 1300
|
||||||
|
|
||||||
|
#define HCL_CLIENT_REPLY_MAX_HDRKEY_LEN 128
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
@ -78,12 +80,18 @@
|
|||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum hcl_client_reply_type_t
|
struct dummy_hcl_xtn_t
|
||||||
{
|
{
|
||||||
HCL_CLIENT_REPLY_TYPE_OK = 0,
|
hcl_client_t* client;
|
||||||
HCL_CLIENT_REPLY_TYPE_ERROR = 1
|
|
||||||
};
|
};
|
||||||
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
|
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_UNQUOTED,
|
||||||
HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED,
|
HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED,
|
||||||
HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED_TRAILER,
|
HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED_TRAILER,
|
||||||
HCL_CLIENT_STATE_IN_HEADER_NAME,
|
HCL_CLIENT_STATE_IN_ATTR_KEY,
|
||||||
HCL_CLIENT_STATE_IN_HEADER_VALUE,
|
HCL_CLIENT_STATE_IN_ATTR_VALUE_START,
|
||||||
HCL_CLIENT_STATE_IN_DATA,
|
HCL_CLIENT_STATE_IN_ATTR_VALUE_UNQUOTED,
|
||||||
HCL_CLIENT_STATE_IN_BINARY_DATA,
|
HCL_CLIENT_STATE_IN_ATTR_VALUE_QUOTED,
|
||||||
HCL_CLIENT_STATE_IN_CHUNK,
|
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;
|
typedef enum hcl_client_state_t hcl_client_state_t;
|
||||||
|
|
||||||
@ -105,7 +116,8 @@ struct hcl_client_t
|
|||||||
{
|
{
|
||||||
hcl_mmgr_t* mmgr;
|
hcl_mmgr_t* mmgr;
|
||||||
hcl_cmgr_t* cmgr;
|
hcl_cmgr_t* cmgr;
|
||||||
/*hcl_t* dummy_hcl;*/
|
hcl_client_prim_t prim;
|
||||||
|
hcl_t* dummy_hcl;
|
||||||
|
|
||||||
hcl_errnum_t errnum;
|
hcl_errnum_t errnum;
|
||||||
struct
|
struct
|
||||||
@ -119,12 +131,8 @@ struct hcl_client_t
|
|||||||
{
|
{
|
||||||
unsigned int trait;
|
unsigned int trait;
|
||||||
unsigned int logmask;
|
unsigned int logmask;
|
||||||
hcl_oow_t worker_max_count;
|
|
||||||
hcl_oow_t worker_stack_size;
|
|
||||||
hcl_ntime_t worker_idle_timeout;
|
|
||||||
} cfg;
|
} cfg;
|
||||||
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
hcl_bch_t* ptr;
|
hcl_bch_t* ptr;
|
||||||
@ -135,11 +143,6 @@ struct hcl_client_t
|
|||||||
hcl_client_state_t state;
|
hcl_client_state_t state;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
hcl_ooch_t* ptr;
|
|
||||||
hcl_oow_t len;
|
|
||||||
hcl_oow_t capa;
|
|
||||||
*/
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
hcl_ooch_t* ptr;
|
hcl_ooch_t* ptr;
|
||||||
@ -148,24 +151,77 @@ struct hcl_client_t
|
|||||||
} tok;
|
} tok;
|
||||||
|
|
||||||
hcl_client_reply_type_t type;
|
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
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
hcl_oow_t nsplen; /* length remembered when the white space was shown */
|
hcl_oow_t nsplen; /* length remembered when the white space was shown */
|
||||||
} reply_value_unquoted;
|
} reply_value_unquoted;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int escaped;
|
int escaped;
|
||||||
} reply_value_quoted;
|
} 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;
|
} u;
|
||||||
} rep;
|
} 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)
|
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;
|
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;
|
hcl_oow_t i;
|
||||||
printf ("{");
|
hcl_oow_t v = 0;
|
||||||
for (i = 0; i < client->rep.tok.len; i++)
|
|
||||||
printf ("%lc", client->rep.tok.ptr[i]);
|
|
||||||
printf ("}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
switch (client->state)
|
||||||
{
|
{
|
||||||
case HCL_CLIENT_STATE_START:
|
case HCL_CLIENT_STATE_START:
|
||||||
if (c == HCL_OOCI_EOF)
|
if (c == HCL_OOCI_EOF)
|
||||||
{
|
{
|
||||||
printf ("unexpected end of reply\n");
|
hcl_client_seterrbfmt (client, HCL_EFINIS, "unexpected end before reply name");
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
else if (c == '.')
|
else if (c == '.')
|
||||||
@ -253,8 +322,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* TODO: set error code? or log error messages? */
|
hcl_client_seterrbfmt (client, HCL_EINVAL, "reply line not starting with a period");
|
||||||
printf ("reply line not starting with .\n");
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,17 +334,17 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c)
|
|||||||
}
|
}
|
||||||
else
|
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;
|
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;
|
client->rep.type = HCL_CLIENT_REPLY_TYPE_ERROR;
|
||||||
}
|
}
|
||||||
else
|
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;
|
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:
|
case HCL_CLIENT_STATE_IN_REPLY_VALUE_START:
|
||||||
if (c == HCL_OOCI_EOF)
|
if (c == HCL_OOCI_EOF)
|
||||||
{
|
{
|
||||||
/* sudden end of EOF without NL */
|
hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of reply line without newline");
|
||||||
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*/
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
else if (is_spacechar(c))
|
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')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
/* no value is specified. switch to a long-format response */
|
/* no value is specified. even no whitespaces.
|
||||||
client->state = HCL_CLIENT_STATE_IN_HEADER_NAME;
|
* 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);
|
HCL_ASSERT (client->dummy_hcl, client->rep.tok.len == 0);
|
||||||
client->rep.u.reply_value_quoted.escaped = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (c == '\"')
|
else if (c == '\"')
|
||||||
{
|
{
|
||||||
client->state = HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED;
|
client->state = HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED;
|
||||||
HCL_ASSERT (client->dummy_hcl, client->rep.tok.len == 0);
|
HCL_ASSERT (client->dummy_hcl, client->rep.tok.len == 0);
|
||||||
|
client->rep.u.reply_value_quoted.escaped = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
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:
|
case HCL_CLIENT_STATE_IN_REPLY_VALUE_UNQUOTED:
|
||||||
if (c == HCL_OOCI_EOF)
|
if (c == HCL_OOCI_EOF)
|
||||||
{
|
{
|
||||||
/* sudden end of EOF without NL */
|
hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of reply line without newline");
|
||||||
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*/
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
else if (c == '\n')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
client->rep.tok.len = client->rep.u.reply_value_unquoted.nsplen;
|
client->rep.tok.len = client->rep.u.reply_value_unquoted.nsplen;
|
||||||
printf ("reply value....===>");
|
goto reply_value_end;
|
||||||
print_tok (client);
|
|
||||||
/* TODO: call callback */
|
|
||||||
client->state = HCL_CLIENT_STATE_START;
|
|
||||||
clear_reply_token (client);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -349,15 +411,16 @@ print_tok (client);
|
|||||||
case HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED:
|
case HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED:
|
||||||
if (c == HCL_OOCI_EOF)
|
if (c == HCL_OOCI_EOF)
|
||||||
{
|
{
|
||||||
/* sudden end of EOF without NL */
|
hcl_client_seterrbfmt (client, HCL_EFINIS, "sudden end of reply line without closing quote");
|
||||||
printf ("suddend enf of input witjpit closing quote. -> total failure\n");
|
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (client->rep.u.reply_value_quoted.escaped)
|
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';
|
else if (c == 'r') c = '\r';
|
||||||
/* TODO: more escaping handling */
|
/* TODO: more escaping handling */
|
||||||
}
|
}
|
||||||
@ -376,17 +439,23 @@ print_tok (client);
|
|||||||
if (add_to_reply_token(client, c) <= -1) goto oops;
|
if (add_to_reply_token(client, c) <= -1) goto oops;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED_TRAILER:
|
case HCL_CLIENT_STATE_IN_REPLY_VALUE_QUOTED_TRAILER:
|
||||||
if (c == HCL_OOCI_EOF)
|
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;
|
goto oops;
|
||||||
}
|
}
|
||||||
else if (c == '\n')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
printf ("reply value....===>");
|
reply_value_end:
|
||||||
print_tok (client);
|
/* 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;
|
client->state = HCL_CLIENT_STATE_START;
|
||||||
clear_reply_token (client);
|
clear_reply_token (client);
|
||||||
break;
|
break;
|
||||||
@ -398,14 +467,14 @@ print_tok (client);
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf ("garbage after a quoted reply value [%lc]\n", c);
|
hcl_client_seterrbfmt (client, HCL_EINVAL, "garbage after quoted reply value");
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
case HCL_CLIENT_STATE_IN_HEADER_NAME:
|
case HCL_CLIENT_STATE_IN_ATTR_KEY:
|
||||||
if (c == HCL_OOCI_EOF)
|
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;
|
goto oops;
|
||||||
}
|
}
|
||||||
else if (client->rep.tok.len == 0)
|
else if (client->rep.tok.len == 0)
|
||||||
@ -417,7 +486,7 @@ print_tok (client);
|
|||||||
}
|
}
|
||||||
else if (c != '.')
|
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;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,58 +495,192 @@ print_tok (client);
|
|||||||
}
|
}
|
||||||
else if (is_alphachar(c) || (client->rep.tok.len > 2 && c == '-'))
|
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;
|
if (add_to_reply_token(client, c) <= -1) goto oops;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf ("JKJJJJJJJJJ=>\n");
|
if (is_token(client, ".DATA"))
|
||||||
print_tok(client);
|
|
||||||
if (hcl_compoocharsbcstr(client->rep.tok.ptr, client->rep.tok.len, ".ENCODING") == 0)
|
|
||||||
{
|
{
|
||||||
printf ("encoding....\n");
|
client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_DATA;
|
||||||
}
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
/* PUT more known attribute handling here */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf ("unknown header ---> [%.*ls]\n", (int)client->rep.tok.len, client->rep.tok.ptr);
|
client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_UNKNOWN;
|
||||||
goto oops;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
clear_reply_token (client);
|
||||||
/* [IMPORTANT] fall thru */
|
/* [IMPORTANT] fall thru */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
case HCL_CLIENT_STATE_IN_ATTR_VALUE_START:
|
||||||
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:
|
|
||||||
if (c == HCL_OOCI_EOF)
|
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;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
else if (is_spacechar(c))
|
||||||
|
{
|
||||||
|
/* do nothing. skip it */
|
||||||
|
break;
|
||||||
|
}
|
||||||
else if (c == '\n')
|
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;
|
break;
|
||||||
}
|
}
|
||||||
else
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
return 0;
|
||||||
@ -494,18 +697,118 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
|
|||||||
ptr = data;
|
ptr = data;
|
||||||
end = ptr + len;
|
end = ptr + len;
|
||||||
|
|
||||||
//printf ("<<<%.*s>>>\n", (int)len, data);
|
while (ptr < end)
|
||||||
if (client->state == HCL_CLIENT_STATE_IN_BINARY_DATA)
|
|
||||||
{
|
{
|
||||||
}
|
if (client->state == HCL_CLIENT_STATE_IN_LENGTH_BOUNDED_DATA)
|
||||||
else
|
{
|
||||||
{
|
/* the data is treated as raw octets by this client */
|
||||||
while (ptr < end)
|
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_ooci_t c;
|
||||||
|
hcl_oow_t bcslen;
|
||||||
|
|
||||||
#if defined(HCL_OOCH_IS_UCH)
|
#if defined(HCL_OOCH_IS_UCH)
|
||||||
hcl_oow_t bcslen, ucslen;
|
hcl_oow_t ucslen;
|
||||||
hcl_ooch_t uc;
|
hcl_ooch_t uc;
|
||||||
int n;
|
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)
|
if (n == -3)
|
||||||
{
|
{
|
||||||
/* incomplete sequence */
|
/* incomplete sequence */
|
||||||
printf ("incompelete....feed me more\n");
|
|
||||||
*xlen = ptr - data;
|
*xlen = ptr - data;
|
||||||
return 0; /* feed more for incomplete sequence */
|
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;
|
ptr += bcslen;
|
||||||
c = uc;
|
c = uc;
|
||||||
#else
|
#else
|
||||||
|
bcslen = 1;
|
||||||
c = *ptr++;
|
c = *ptr++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
printf ("[%lc]\n", c);
|
//printf ("[%lc]\n", c);
|
||||||
if (handle_char(client, c) <= -1) goto oops;
|
if (handle_char(client, c, bcslen) <= -1) goto oops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,7 +843,7 @@ printf ("[%lc]\n", c);
|
|||||||
|
|
||||||
oops:
|
oops:
|
||||||
/* TODO: compute the number of processes bytes so far and return it via a parameter??? */
|
/* 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;
|
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* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_prim_t* prim, hcl_errnum_t* errnum)
|
||||||
{
|
{
|
||||||
hcl_client_t* client;
|
hcl_client_t* client;
|
||||||
#if 0
|
|
||||||
hcl_t* hcl;
|
hcl_t* hcl;
|
||||||
hcl_vmprim_t vmprim;
|
hcl_vmprim_t vmprim;
|
||||||
hcl_tmr_t* tmr;
|
|
||||||
dummy_hcl_xtn_t* xtn;
|
dummy_hcl_xtn_t* xtn;
|
||||||
int pfd[2], fcv;
|
/* unsigned int trait;*/
|
||||||
unsigned int trait;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
client = (hcl_client_t*)HCL_MMGR_ALLOC(mmgr, HCL_SIZEOF(*client) + xtnsize);
|
client = (hcl_client_t*)HCL_MMGR_ALLOC(mmgr, HCL_SIZEOF(*client) + xtnsize);
|
||||||
if (!client)
|
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;
|
return HCL_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim));
|
HCL_MEMSET (&vmprim, 0, HCL_SIZEOF(vmprim));
|
||||||
vmprim.log_write = log_write_for_dummy;
|
vmprim.log_write = log_write_for_dummy;
|
||||||
vmprim.syserrstrb = syserrstrb;
|
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);
|
hcl = hcl_open(mmgr, HCL_SIZEOF(*xtn), 2048, &vmprim, errnum);
|
||||||
if (!hcl)
|
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;
|
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 = (dummy_hcl_xtn_t*)hcl_getxtn(hcl);
|
||||||
xtn->client = client;
|
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->cmgr = hcl_get_utf8_cmgr();
|
||||||
client->prim = *prim;
|
client->prim = *prim;
|
||||||
client->dummy_hcl = hcl;
|
client->dummy_hcl = hcl;
|
||||||
client->tmr = tmr;
|
|
||||||
|
|
||||||
client->cfg.logmask = ~0u;
|
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
|
/* 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
|
* such as getting system time or logging. so the heap size doesn't
|
||||||
* need to be changed from the tiny value set above. */
|
* need to be changed from the tiny value set above. */
|
||||||
hcl_setoption (client->dummy_hcl, HCL_LOG_MASK, &client->cfg.logmask);
|
hcl_setoption (client->dummy_hcl, HCL_LOG_MASK, &client->cfg.logmask);
|
||||||
hcl_setcmgr (client->dummy_hcl, client->cmgr);
|
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;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcl_client_close (hcl_client_t* 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);
|
HCL_MMGR_FREE (client->mmgr, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int hcl_client_setoption (hcl_client_t* client, hcl_client_option_t id, const void* value)
|
int hcl_client_setoption (hcl_client_t* client, hcl_client_option_t id, const void* value)
|
||||||
{
|
{
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case HCL_CLIENT_TRAIT:
|
case HCL_CLIENT_TRAIT:
|
||||||
client->cfg.trait = *(const unsigned int*)value;
|
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;
|
return 0;
|
||||||
|
|
||||||
case HCL_CLIENT_LOG_MASK:
|
case HCL_CLIENT_LOG_MASK:
|
||||||
client->cfg.logmask = *(const unsigned int*)value;
|
client->cfg.logmask = *(const unsigned int*)value;
|
||||||
#if 0
|
|
||||||
if (client->dummy_hcl)
|
if (client->dummy_hcl)
|
||||||
{
|
{
|
||||||
/* setting this affects the dummy hcl immediately.
|
/* 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 */
|
* is supposed to use the new value */
|
||||||
hcl_setoption (client->dummy_hcl, HCL_LOG_MASK, 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;
|
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:
|
case HCL_CLIENT_LOG_MASK:
|
||||||
*(unsigned int*)value = client->cfg.logmask;
|
*(unsigned int*)value = client->cfg.logmask;
|
||||||
return 0;
|
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);
|
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;
|
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* hcl_client_allocmem (hcl_client_t* client, hcl_oow_t size)
|
||||||
{
|
{
|
||||||
void* ptr;
|
void* ptr;
|
||||||
@ -848,7 +1096,6 @@ void hcl_client_freemem (hcl_client_t* client, void* ptr)
|
|||||||
HCL_MMGR_FREE (client->mmgr, ptr);
|
HCL_MMGR_FREE (client->mmgr, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
int hcl_client_start (hcl_client_t* client, const hcl_bch_t* addrs)
|
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);
|
if (offset > 0) HCL_MEMMOVE (&buf[0], &buf[xlen], offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("hcl client start returns success\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
95
lib/hcl-c.h
95
lib/hcl-c.h
@ -36,38 +36,84 @@ enum hcl_client_option_t
|
|||||||
{
|
{
|
||||||
HCL_CLIENT_TRAIT,
|
HCL_CLIENT_TRAIT,
|
||||||
HCL_CLIENT_LOG_MASK,
|
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;
|
typedef enum hcl_client_option_t hcl_client_option_t;
|
||||||
|
|
||||||
enum hcl_client_trait_t
|
enum hcl_client_trait_t
|
||||||
{
|
{
|
||||||
#if defined(HCL_BUILD_DEBUG)
|
/* no trait defined at this moment. XXXX is just a placeholder */
|
||||||
HCL_CLIENT_TRAIT_DEBUG_GC = (1 << 0),
|
HCL_CLIENT_XXXX = (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)
|
|
||||||
};
|
};
|
||||||
typedef enum hcl_client_trait_t hcl_client_trait_t;
|
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) (
|
typedef void (*hcl_client_log_write_t) (
|
||||||
hcl_client_t* client,
|
hcl_client_t* client,
|
||||||
hcl_oow_t wid,
|
|
||||||
unsigned int mask,
|
unsigned int mask,
|
||||||
const hcl_ooch_t* msg,
|
const hcl_ooch_t* msg,
|
||||||
hcl_oow_t len
|
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
|
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;
|
typedef struct hcl_client_prim_t hcl_client_prim_t;
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -141,9 +187,33 @@ HCL_EXPORT void hcl_client_seterrnum (
|
|||||||
hcl_errnum_t errnum
|
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_EXPORT void* hcl_client_allocmem (
|
||||||
hcl_client_t* client,
|
hcl_client_t* client,
|
||||||
@ -167,7 +237,6 @@ HCL_EXPORT void hcl_client_freemem (
|
|||||||
void* ptr
|
void* ptr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
13
lib/hcl-s.c
13
lib/hcl-s.c
@ -161,7 +161,6 @@ struct dummy_hcl_xtn_t
|
|||||||
};
|
};
|
||||||
typedef struct dummy_hcl_xtn_t dummy_hcl_xtn_t;
|
typedef struct dummy_hcl_xtn_t dummy_hcl_xtn_t;
|
||||||
|
|
||||||
|
|
||||||
enum hcl_server_proto_token_type_t
|
enum hcl_server_proto_token_type_t
|
||||||
{
|
{
|
||||||
HCL_SERVER_PROTO_TOKEN_EOF,
|
HCL_SERVER_PROTO_TOKEN_EOF,
|
||||||
@ -276,7 +275,7 @@ struct hcl_server_wid_map_data_t
|
|||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
typedef struct hcl_server_wid_map_data_t hcl_server_wid_map_data_t;
|
typedef struct hcl_server_wid_map_data_t hcl_server_wid_map_data_t;
|
||||||
|
|
||||||
struct hcl_server_t
|
struct hcl_server_t
|
||||||
{
|
{
|
||||||
hcl_mmgr_t* mmgr;
|
hcl_mmgr_t* mmgr;
|
||||||
@ -1111,12 +1110,12 @@ static int write_reply_chunk (hcl_server_proto_t* proto)
|
|||||||
if (proto->reply.nchunks <= 0)
|
if (proto->reply.nchunks <= 0)
|
||||||
{
|
{
|
||||||
/* this is the first chunk */
|
/* this is the first chunk */
|
||||||
iov[count].iov_base = ".OK\n.ENCODING chunked\n.DATA\n";
|
iov[count].iov_base = ".OK\n.DATA chunked\n";
|
||||||
iov[count++].iov_len = 28;
|
iov[count++].iov_len = 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
iov[count].iov_base = cl,
|
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_base = proto->reply.buf;
|
||||||
iov[count++].iov_len = proto->reply.len;
|
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.
|
/* 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
|
* send -1: as the last chunk. the receiver must rub out the reply
|
||||||
* buffer received so far and expect the following .ERROR response */
|
* 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;
|
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.type = HCL_SERVER_PROTO_REPLY_SIMPLE; /* switch to the simple mode forcibly */
|
||||||
proto->reply.nchunks = 0;
|
proto->reply.nchunks = 0;
|
||||||
proto->reply.len = 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;
|
goto simple_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,7 @@ enum hcl_server_trait_t
|
|||||||
HCL_SERVER_TRAIT_DEBUG_BIGINT = (1 << 1),
|
HCL_SERVER_TRAIT_DEBUG_BIGINT = (1 << 1),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HCL_SERVER_TRAIT_READABLE_PROTO = (1 << 2),
|
HCL_SERVER_TRAIT_USE_LARGE_PAGES = (1 << 2)
|
||||||
HCL_SERVER_TRAIT_USE_LARGE_PAGES = (1 << 3)
|
|
||||||
};
|
};
|
||||||
typedef enum hcl_server_trait_t hcl_server_trait_t;
|
typedef enum hcl_server_trait_t hcl_server_trait_t;
|
||||||
|
|
||||||
|
141
lib/main-c.c
141
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_bch_t buf[256];
|
||||||
hcl_oow_t ucslen, bcslen;
|
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);
|
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)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HCL_BUILD_DEBUG)
|
static void start_reply (hcl_client_t* client, hcl_client_reply_type_t type, const hcl_ooch_t* dptr, hcl_oow_t dlen)
|
||||||
static int handle_dbgopt (hcl_client_t* client, const char* str)
|
|
||||||
{
|
{
|
||||||
const hcl_bch_t* cm, * flt;
|
if (dptr)
|
||||||
hcl_oow_t len;
|
|
||||||
unsigned int trait;
|
|
||||||
|
|
||||||
hcl_client_getoption (client, HCL_CLIENT_TRAIT, &trait);
|
|
||||||
|
|
||||||
cm = str - 1;
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
flt = cm + 1;
|
printf ("GOT SHORT-FORM RESPONSE[%d] with data <<%.*ls>>\n", (int)type, (int)dlen, dptr);
|
||||||
|
}
|
||||||
cm = hcl_findbcharinbcstr(flt, ',');
|
else
|
||||||
len = cm? (cm - flt): hcl_countbcstr(flt);
|
{
|
||||||
if (hcl_compbcharsbcstr(flt, len, "gc") == 0) trait |= HCL_CLIENT_TRAIT_DEBUG_GC;
|
printf ("GOT LONG_FORM RESPONSE[%d]\n", (int)type);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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
|
#define MIN_WORKER_STACK_SIZE 512000ul
|
||||||
@ -488,14 +484,7 @@ int main (int argc, char* argv[])
|
|||||||
static hcl_bopt_lng_t lopt[] =
|
static hcl_bopt_lng_t lopt[] =
|
||||||
{
|
{
|
||||||
{ ":log", 'l' },
|
{ ":log", 'l' },
|
||||||
{ "large-pages", '\0' },
|
{ HCL_NULL, '\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' }
|
|
||||||
};
|
};
|
||||||
static hcl_bopt_t opt =
|
static hcl_bopt_t opt =
|
||||||
{
|
{
|
||||||
@ -507,14 +496,7 @@ int main (int argc, char* argv[])
|
|||||||
client_xtn_t* xtn;
|
client_xtn_t* xtn;
|
||||||
hcl_client_prim_t client_prim;
|
hcl_client_prim_t client_prim;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
const char* logopt = HCL_NULL;
|
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, "");
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
@ -535,30 +517,7 @@ int main (int argc, char* argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '\0':
|
case '\0':
|
||||||
if (hcl_compbcstr(opt.lngopt, "large-pages") == 0)
|
goto print_usage;
|
||||||
{
|
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ':':
|
case ':':
|
||||||
@ -578,6 +537,10 @@ int main (int argc, char* argv[])
|
|||||||
|
|
||||||
memset (&client_prim, 0, HCL_SIZEOF(client_prim));
|
memset (&client_prim, 0, HCL_SIZEOF(client_prim));
|
||||||
client_prim.log_write = log_write;
|
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);
|
client = hcl_client_open(&sys_mmgr, HCL_SIZEOF(client_xtn_t), &client_prim, HCL_NULL);
|
||||||
if (!client)
|
if (!client)
|
||||||
@ -600,22 +563,6 @@ int main (int argc, char* argv[])
|
|||||||
xtn->logmask = HCL_LOG_ALL_TYPES | HCL_LOG_ERROR | HCL_LOG_FATAL;
|
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;
|
g_client = client;
|
||||||
set_signal (SIGINT, handle_sigint);
|
set_signal (SIGINT, handle_sigint);
|
||||||
set_signal_to_ignore (SIGPIPE);
|
set_signal_to_ignore (SIGPIPE);
|
||||||
@ -627,13 +574,15 @@ int main (int argc, char* argv[])
|
|||||||
|
|
||||||
if (n <= -1)
|
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));
|
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close (xtn->logfd);
|
if (xtn->logfd >= 0)
|
||||||
xtn->logfd = -1;
|
{
|
||||||
xtn->logfd_istty = 0;
|
close (xtn->logfd);
|
||||||
|
xtn->logfd = -1;
|
||||||
|
xtn->logfd_istty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
hcl_client_close (client);
|
hcl_client_close (client);
|
||||||
return n;
|
return n;
|
||||||
|
@ -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));
|
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);
|
if (xtn->logfd >= 0)
|
||||||
xtn->logfd = -1;
|
{
|
||||||
xtn->logfd_istty = 0;
|
close (xtn->logfd);
|
||||||
|
xtn->logfd = -1;
|
||||||
|
xtn->logfd_istty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
hcl_server_close (server);
|
hcl_server_close (server);
|
||||||
return n;
|
return n;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user