touched up hcl client code

This commit is contained in:
hyung-hwan 2018-03-21 15:17:46 +00:00
parent f675835a11
commit 57f8c8969a
3 changed files with 173 additions and 196 deletions

View File

@ -27,58 +27,10 @@
#include "hcl-c.h" #include "hcl-c.h"
#include "hcl-prv.h" #include "hcl-prv.h"
#include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#define HCL_CLIENT_TOKEN_NAME_ALIGN 64 #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 <windows.h>
# include <tchar.h>
# if defined(HCL_HAVE_CFG_H) && defined(HCL_ENABLE_LIBLTDL)
# include <ltdl.h>
# define USE_LTDL
# endif
#elif defined(__OS2__)
# define INCL_DOSMODULEMGR
# define INCL_DOSPROCESS
# define INCL_DOSERRORS
# include <os2.h>
#elif defined(__MSDOS__)
# include <dos.h>
# include <time.h>
#elif defined(macintosh)
# include <Timer.h>
#else
# if defined(HAVE_TIME_H)
# include <time.h>
# endif
# if defined(HAVE_SYS_TIME_H)
# include <sys/time.h>
# endif
# if defined(HAVE_SIGNAL_H)
# include <signal.h>
# endif
# if defined(HAVE_SYS_MMAN_H)
# include <sys/mman.h>
# endif
# if defined(HAVE_SYS_UIO_H)
# include <sys/uio.h>
# endif
# include <unistd.h>
# include <fcntl.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <pthread.h>
# include <poll.h>
#endif
struct dummy_hcl_xtn_t struct dummy_hcl_xtn_t
{ {
@ -93,25 +45,6 @@ enum hcl_client_reply_attr_type_t
}; };
typedef enum hcl_client_reply_attr_type_t hcl_client_reply_attr_type_t; typedef enum hcl_client_reply_attr_type_t hcl_client_reply_attr_type_t;
enum hcl_client_state_t
{
HCL_CLIENT_STATE_START,
HCL_CLIENT_STATE_IN_REPLY_NAME,
HCL_CLIENT_STATE_IN_REPLY_VALUE_START,
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_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;
struct hcl_client_t struct hcl_client_t
{ {
hcl_mmgr_t* mmgr; hcl_mmgr_t* mmgr;
@ -125,7 +58,6 @@ struct hcl_client_t
hcl_ooch_t buf[HCL_ERRMSG_CAPA]; hcl_ooch_t buf[HCL_ERRMSG_CAPA];
hcl_oow_t len; hcl_oow_t len;
} errmsg; } errmsg;
int stopreq;
struct struct
{ {
@ -154,8 +86,9 @@ struct hcl_client_t
hcl_client_reply_attr_type_t last_attr_type; hcl_client_reply_attr_type_t last_attr_type;
struct struct
{ {
hcl_ooch_t buf[HCL_CLIENT_REPLY_MAX_HDRKEY_LEN]; hcl_ooch_t* ptr;
hcl_oow_t len; hcl_oow_t len;
hcl_oow_t capa;
} last_attr_key; /* the last attr key shown */ } last_attr_key; /* the last attr key shown */
union union
@ -264,7 +197,7 @@ static int add_to_reply_token (hcl_client_t* client, hcl_ooch_t ch)
hcl_ooch_t* tmp; hcl_ooch_t* tmp;
hcl_oow_t newcapa; hcl_oow_t newcapa;
newcapa = HCL_ALIGN_POW2(client->rep.tok.len + 1, 128); newcapa = HCL_ALIGN_POW2(client->rep.tok.len + 1, HCL_CLIENT_TOKEN_NAME_ALIGN);
tmp = hcl_client_reallocmem(client, client->rep.tok.ptr, newcapa * HCL_SIZEOF(*tmp)); tmp = hcl_client_reallocmem(client, client->rep.tok.ptr, newcapa * HCL_SIZEOF(*tmp));
if (!tmp) return -1; if (!tmp) return -1;
@ -298,6 +231,19 @@ static HCL_INLINE int is_token_integer (hcl_client_t* client, hcl_oow_t* value)
return 1; return 1;
} }
static HCL_INLINE hcl_ooch_t escape (hcl_ooch_t c)
{
switch (c)
{
case 'n': return '\n';
case 'r': return '\r';
case 'f': return '\f';
case 't': return '\t';
case 'v': return '\v';
default: return c;
}
}
static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes) static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
{ {
switch (client->state) switch (client->state)
@ -322,7 +268,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
} }
else else
{ {
hcl_client_seterrbfmt (client, HCL_EINVAL, "reply line not starting with a period"); hcl_client_seterrbfmt (client, HCL_EINVAL, "reply line not starting with a period - %jc", (hcl_ooch_t)c);
goto oops; goto oops;
} }
@ -368,7 +314,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
{ {
/* no value is specified. even no whitespaces. /* no value is specified. even no whitespaces.
* switch to a long-format response */ * switch to a long-format response */
client->prim.start_reply (client, client->rep.type, HCL_NULL, 0); if (client->prim.start_reply(client, client->rep.type, HCL_NULL, 0) <= -1) goto oops;
client->state = HCL_CLIENT_STATE_IN_ATTR_KEY; 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);
@ -418,11 +364,8 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
{ {
if (client->rep.u.reply_value_quoted.escaped) if (client->rep.u.reply_value_quoted.escaped)
{ {
if (c == '\\') c = '\\'; c = escape(c);
else if (c == '\"') c = '\"'; /* TODO: more escaping handling \xXXX \uXXXX \UXXXXX */
else if (c == 'n') c = '\n';
else if (c == 'r') c = '\r';
/* TODO: more escaping handling */
} }
else if (c == '\\') else if (c == '\\')
{ {
@ -453,7 +396,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
* callback. no end_reply callback is invoked. the data is assumed * 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 * to be in UTF-8 encoding. this is different from the data in the
* long-format reply which is treated as octet stream */ * 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); if (client->prim.start_reply(client, client->rep.type, client->rep.tok.ptr, client->rep.tok.len) <= -1) goto oops;
/* no end_reply() callback for the short-form reply */ /* no end_reply() callback for the short-form reply */
client->state = HCL_CLIENT_STATE_START; client->state = HCL_CLIENT_STATE_START;
@ -479,6 +422,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
} }
else if (client->rep.tok.len == 0) else if (client->rep.tok.len == 0)
{ {
if (is_spacechar(c)) if (is_spacechar(c))
{ {
/* skip whitespaces at the beginning of the start line before the reply name */ /* skip whitespaces at the beginning of the start line before the reply name */
@ -486,7 +430,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
} }
else if (c != '.') else if (c != '.')
{ {
hcl_client_seterrbfmt (client, HCL_EINVAL, "attribute name not starting with a period"); hcl_client_seterrbfmt (client, HCL_EINVAL, "attribute name not starting with a period - [%jc]", (hcl_ooch_t)c);
goto oops; goto oops;
} }
@ -495,16 +439,17 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
} }
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
{ {
if (client->rep.tok.len <= 1)
{
hcl_client_seterrbfmt (client, HCL_EINVAL, "attribute name too short");
goto oops;
}
if (is_token(client, ".DATA")) if (is_token(client, ".DATA"))
{ {
client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_DATA; client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_DATA;
@ -515,8 +460,19 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_UNKNOWN; client->rep.last_attr_type = HCL_CLIENT_REPLY_ATTR_TYPE_UNKNOWN;
} }
HCL_ASSERT (client->dummy_hcl, client->rep.tok.len <= HCL_COUNTOF(client->rep.last_attr_key.buf)); /* remember the attribute name */
hcl_copyoochars (client->rep.last_attr_key.buf, client->rep.tok.ptr, client->rep.tok.len); if (client->rep.tok.len > client->rep.last_attr_key.capa)
{
hcl_ooch_t* tmp;
tmp = hcl_client_reallocmem(client, client->rep.last_attr_key.ptr, client->rep.tok.capa * HCL_SIZEOF(*tmp));
if (!tmp) goto oops;
client->rep.last_attr_key.ptr = tmp;
client->rep.last_attr_key.capa = client->rep.tok.capa;
}
hcl_copyoochars (client->rep.last_attr_key.ptr, client->rep.tok.ptr, client->rep.tok.len);
client->rep.last_attr_key.len = client->rep.tok.len; client->rep.last_attr_key.len = client->rep.tok.len;
client->state = HCL_CLIENT_STATE_IN_ATTR_VALUE_START; client->state = HCL_CLIENT_STATE_IN_ATTR_VALUE_START;
@ -537,7 +493,7 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
} }
else if (c == '\n') else if (c == '\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); hcl_client_seterrbfmt (client, HCL_EINVAL, "no attribute value for %.*js\n", client->rep.last_attr_key.len, client->rep.last_attr_key.ptr);
goto oops; goto oops;
} }
else if (c == '\"') else if (c == '\"')
@ -584,11 +540,8 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
{ {
if (client->rep.u.attr_value_quoted.escaped) if (client->rep.u.attr_value_quoted.escaped)
{ {
if (c == '\\') c = '\\'; c = escape(c);
else if (c == '\"') c = '\"'; /* TODO: more escaping handling like \0NNN \xXXXX \uXXXX \UXXXX */
else if (c == 'n') c = '\n';
else if (c == 'r') c = '\r';
/* TODO: more escaping handling */
} }
else if (c == '\\') else if (c == '\\')
{ {
@ -618,11 +571,11 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
if (client->prim.feed_attr) if (client->prim.feed_attr)
{ {
hcl_oocs_t key, val; hcl_oocs_t key, val;
key.ptr = client->rep.last_attr_key.buf; key.ptr = client->rep.last_attr_key.ptr;
key.len = client->rep.last_attr_key.len; key.len = client->rep.last_attr_key.len;
val.ptr = client->rep.tok.ptr; val.ptr = client->rep.tok.ptr;
val.len = client->rep.tok.len; val.len = client->rep.tok.len;
client->prim.feed_attr (client, &key, &val); if (client->prim.feed_attr (client, &key, &val) <= -1) goto oops;
} }
if (client->rep.last_attr_type == HCL_CLIENT_REPLY_ATTR_TYPE_DATA) if (client->rep.last_attr_type == HCL_CLIENT_REPLY_ATTR_TYPE_DATA)
@ -673,13 +626,12 @@ static int handle_char (hcl_client_t* client, hcl_ooci_t c, hcl_oow_t nbytes)
} }
else 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); hcl_client_seterrbfmt (client, HCL_EINVAL, "garbage after quoted attribute value for %.*js", client->rep.last_attr_key.len, client->rep.last_attr_key.ptr);
goto oops; goto oops;
} }
default: default:
/* this function must not be called for .DATA */ hcl_client_seterrbfmt (client, HCL_EINTERN, "internal error - must not be called for state %d", (int)client->state);
hcl_client_seterrbfmt (client, HCL_EINTERN, "internal error - must not be called for state %d", client->state);
goto oops; goto oops;
} }
@ -710,7 +662,7 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
if (client->prim.feed_data) if (client->prim.feed_data)
{ {
client->prim.feed_data (client, ptr, taken); if (client->prim.feed_data(client, ptr, taken) <= -1) goto oops;
} }
ptr += taken; ptr += taken;
@ -719,7 +671,7 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
{ {
/* read all data. no more */ /* read all data. no more */
client->state = HCL_CLIENT_STATE_START; client->state = HCL_CLIENT_STATE_START;
client->prim.end_reply (client, HCL_CLIENT_END_REPLY_STATE_OK); if (client->prim.end_reply(client, HCL_CLIENT_END_REPLY_STATE_OK) <= -1) goto oops;
} }
} }
else if (client->state == HCL_CLIENT_STATE_IN_CHUNKED_DATA) else if (client->state == HCL_CLIENT_STATE_IN_CHUNKED_DATA)
@ -735,7 +687,7 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
if (client->prim.feed_data) if (client->prim.feed_data)
{ {
client->prim.feed_data (client, ptr, taken); if (client->prim.feed_data(client, ptr, taken) <= -1) goto oops;
} }
ptr += taken; ptr += taken;
@ -755,15 +707,13 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
{ {
while (ptr < end) while (ptr < end)
{ {
hcl_bchu_t bc = (hcl_bchu_t)*ptr; hcl_bchu_t bc = (hcl_bchu_t)*ptr++;
if (bc == '-' && client->rep.u.chunked_data.clcount == 0 && !client->rep.u.chunked_data.negated) if (bc == '-' && client->rep.u.chunked_data.clcount == 0 && !client->rep.u.chunked_data.negated)
{ {
client->rep.u.chunked_data.negated = 1; client->rep.u.chunked_data.negated = 1;
} }
else if (bc == ':') else if (bc == ':')
{ {
ptr++;
if (client->rep.u.chunked_data.clcount == 0) if (client->rep.u.chunked_data.clcount == 0)
{ {
hcl_client_seterrbfmt (client, HCL_EINVAL, "clone without valid chunk length"); hcl_client_seterrbfmt (client, HCL_EINVAL, "clone without valid chunk length");
@ -772,13 +722,13 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
if (client->rep.u.chunked_data.negated) if (client->rep.u.chunked_data.negated)
{ {
client->prim.end_reply (client, HCL_CLIENT_END_REPLY_STATE_REVOKED); if (client->prim.end_reply(client, HCL_CLIENT_END_REPLY_STATE_REVOKED) <= -1) goto oops;
client->state = HCL_CLIENT_STATE_START; client->state = HCL_CLIENT_STATE_START;
} }
if (client->rep.u.chunked_data.max == 0) if (client->rep.u.chunked_data.max == 0)
{ {
client->prim.end_reply (client, HCL_CLIENT_END_REPLY_STATE_OK); if (client->prim.end_reply(client, HCL_CLIENT_END_REPLY_STATE_OK) <= -1) goto oops;
client->state = HCL_CLIENT_STATE_START; client->state = HCL_CLIENT_STATE_START;
} }
else else
@ -792,11 +742,10 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
{ {
client->rep.u.chunked_data.max = client->rep.u.chunked_data.max * 10 + (bc - '0'); client->rep.u.chunked_data.max = client->rep.u.chunked_data.max * 10 + (bc - '0');
client->rep.u.chunked_data.clcount++; client->rep.u.chunked_data.clcount++;
ptr++;
} }
else else
{ {
hcl_client_seterrbfmt (client, HCL_EINVAL, "invalid chunk length character - code[%#x]", bc); hcl_client_seterrbfmt (client, HCL_EINVAL, "invalid chunk length character - [%jc]", (hcl_ooch_t)bc);
goto oops; goto oops;
} }
} }
@ -807,7 +756,7 @@ static int feed_reply_data (hcl_client_t* client, const hcl_bch_t* data, hcl_oow
hcl_ooci_t c; hcl_ooci_t c;
hcl_oow_t bcslen; hcl_oow_t bcslen;
#if defined(HCL_OOCH_IS_UCH) #if defined(HCL_OOCH_IS_UCH)
hcl_oow_t ucslen; hcl_oow_t ucslen;
hcl_ooch_t uc; hcl_ooch_t uc;
int n; int n;
@ -828,12 +777,11 @@ 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; bcslen = 1;
c = *ptr++; c = *ptr++;
#endif #endif
//printf ("[%lc]\n", c);
if (handle_char(client, c, bcslen) <= -1) goto oops; if (handle_char(client, c, bcslen) <= -1) goto oops;
} }
} }
@ -848,27 +796,6 @@ oops:
} }
static int feed_all_reply_data (hcl_client_t* client, hcl_bch_t* buf, hcl_oow_t n, hcl_oow_t* xlen)
{
int x;
hcl_oow_t total, ylen;
total = 0;
while (total < n)
{
x = feed_reply_data(client, &buf[total], n - total, &ylen);
if (x <= -1) return -1;
total += ylen;
/*if (ylen == 0) break;*/
if (x == 0) break; /* incomplete sequence encountered */
}
*xlen = total;
return 0;
}
/* ========================================================================= */ /* ========================================================================= */
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)
@ -919,14 +846,8 @@ hcl_client_t* hcl_client_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_client_p
void hcl_client_close (hcl_client_t* client) void hcl_client_close (hcl_client_t* client)
{ {
if (client->rep.tok.ptr) if (client->rep.tok.ptr) hcl_client_freemem (client, client->rep.tok.ptr);
{ if (client->rep.last_attr_key.ptr) hcl_client_freemem (client, client->rep.last_attr_key.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_close (client->dummy_hcl);
HCL_MMGR_FREE (client->mmgr, client); HCL_MMGR_FREE (client->mmgr, client);
} }
@ -1098,46 +1019,34 @@ void hcl_client_freemem (hcl_client_t* client, void* ptr)
/* ========================================================================= */ /* ========================================================================= */
int hcl_client_start (hcl_client_t* client, const hcl_bch_t* addrs) hcl_client_state_t hcl_client_getstate (hcl_client_t* client)
{ {
return client->state;
}
/* connect */ void hcl_client_reset (hcl_client_t* client)
/* send request */ {
/* TODO: reset XXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxx */
client->state = HCL_CLIENT_STATE_START;
}
hcl_oow_t xlen, offset; int hcl_client_feed (hcl_client_t* client, const void* ptr, hcl_oow_t len, hcl_oow_t* xlen)
{
int x; int x;
int fd = 0; /* read from stdin for testing */ hcl_oow_t total, ylen;
hcl_bch_t buf[256]; const hcl_bch_t* buf;
ssize_t n;
client->stopreq = 0; buf = (const hcl_bch_t*)ptr;
offset = 0; total = 0;
while (total < len)
while (1)
{ {
n = read(fd, &buf[offset], HCL_SIZEOF(buf) - offset); /* switch to recv */ x = feed_reply_data(client, &buf[total], len - total, &ylen);
if (n <= -1)
{
printf ("error....%s\n", strerror(n));
return -1;
}
if (n == 0)
{
/* TODO: check if there is residue in the receiv buffer */
break;
}
x = feed_all_reply_data (client, buf, n, &xlen);
if (x <= -1) return -1; if (x <= -1) return -1;
offset = n - xlen; total += ylen;
if (offset > 0) HCL_MEMMOVE (&buf[0], &buf[xlen], offset); if (x == 0) break; /* incomplete sequence encountered */
} }
*xlen = total;
return 0; return 0;
} }
void hcl_client_stop (hcl_client_t* client)
{
client->stopreq = 1;
}

View File

@ -48,6 +48,27 @@ typedef enum hcl_client_trait_t hcl_client_trait_t;
/* ========================================================================= */ /* ========================================================================= */
enum hcl_client_state_t
{
HCL_CLIENT_STATE_START,
HCL_CLIENT_STATE_IN_REPLY_NAME,
HCL_CLIENT_STATE_IN_REPLY_VALUE_START,
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_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;
/* ========================================================================= */
enum hcl_client_reply_type_t enum hcl_client_reply_type_t
{ {
HCL_CLIENT_REPLY_TYPE_OK = 0, HCL_CLIENT_REPLY_TYPE_OK = 0,
@ -62,42 +83,41 @@ typedef void (*hcl_client_log_write_t) (
hcl_oow_t len hcl_oow_t len
); );
typedef void (*hcl_client_start_reply_t) ( typedef int (*hcl_client_start_reply_t) (
hcl_client_t* client, hcl_client_t* client,
hcl_client_reply_type_t type, hcl_client_reply_type_t type,
const hcl_ooch_t* dptr, const hcl_ooch_t* dptr,
hcl_oow_t dlen hcl_oow_t dlen
); );
typedef void (*hcl_client_feed_attr_t) ( typedef int (*hcl_client_feed_attr_t) (
hcl_client_t* client, hcl_client_t* client,
const hcl_oocs_t* key, const hcl_oocs_t* key,
const hcl_oocs_t* val const hcl_oocs_t* val
); );
typedef void (*hcl_client_start_data_t) ( typedef int (*hcl_client_start_data_t) (
hcl_client_t* client hcl_client_t* client
); );
typedef void (*hcl_client_feed_data_t) ( typedef int (*hcl_client_feed_data_t) (
hcl_client_t* client, hcl_client_t* client,
const void* ptr, const void* ptr,
hcl_oow_t len hcl_oow_t len
); );
typedef void (*hcl_client_end_data_t) ( typedef int (*hcl_client_end_data_t) (
hcl_client_t* client hcl_client_t* client
); );
enum hcl_client_end_reply_state_t enum hcl_client_end_reply_state_t
{ {
HCL_CLIENT_END_REPLY_STATE_OK, HCL_CLIENT_END_REPLY_STATE_OK,
HCL_CLIENT_END_REPLY_STATE_REVOKED, 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 enum hcl_client_end_reply_state_t hcl_client_end_reply_state_t;
typedef void (*hcl_client_end_reply_t) ( typedef int (*hcl_client_end_reply_t) (
hcl_client_t* client, hcl_client_t* client,
hcl_client_end_reply_state_t state hcl_client_end_reply_state_t state
); );
@ -130,12 +150,18 @@ HCL_EXPORT void hcl_client_close (
hcl_client_t* client hcl_client_t* client
); );
HCL_EXPORT int hcl_client_start ( HCL_EXPORT void hcl_client_reset (
hcl_client_t* client, hcl_client_t* client
const hcl_bch_t* addrs
); );
HCL_EXPORT void hcl_client_stop ( HCL_EXPORT int hcl_client_feed (
hcl_client_t* client,
const void* ptr,
hcl_oow_t len,
hcl_oow_t* xlen
);
HCL_EXPORT hcl_client_state_t hcl_client_getstate (
hcl_client_t* client hcl_client_t* client
); );

View File

@ -436,7 +436,7 @@ static int handle_logopt (hcl_client_t* client, const hcl_bch_t* str)
return 0; return 0;
} }
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 start_reply (hcl_client_t* client, hcl_client_reply_type_t type, const hcl_ooch_t* dptr, hcl_oow_t dlen)
{ {
if (dptr) if (dptr)
{ {
@ -446,15 +446,12 @@ static void start_reply (hcl_client_t* client, hcl_client_reply_type_t type, con
{ {
printf ("GOT LONG_FORM RESPONSE[%d]\n", (int)type); printf ("GOT LONG_FORM RESPONSE[%d]\n", (int)type);
} }
return 0;
} }
static void end_reply (hcl_client_t* client, hcl_client_end_reply_state_t state) static int end_reply (hcl_client_t* client, hcl_client_end_reply_state_t state)
{ {
if (state == HCL_CLIENT_END_REPLY_STATE_ERROR) if (state == HCL_CLIENT_END_REPLY_STATE_REVOKED)
{
printf (">>>>>>>>>>>>>>>>>>>>> reply error....\n");
}
else if (state == HCL_CLIENT_END_REPLY_STATE_REVOKED)
{ {
printf (">>>>>>>>>>>>>>>>>>>>>> REPLY revoked....\n"); printf (">>>>>>>>>>>>>>>>>>>>>> REPLY revoked....\n");
} }
@ -462,21 +459,65 @@ printf (">>>>>>>>>>>>>>>>>>>>>> REPLY revoked....\n");
{ {
printf (">>>>>>>>>>>>>>>>>>>>> REPLY ENDED OK....\n"); printf (">>>>>>>>>>>>>>>>>>>>> REPLY ENDED OK....\n");
} }
return 0;
} }
static void feed_attr (hcl_client_t* client, const hcl_oocs_t* key, const hcl_oocs_t* val) static int 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); printf ("GOT HEADER ====> [%.*ls] ===> [%.*ls]\n", (int)key->len, key->ptr, (int)val->len, val->ptr);
return 0;
} }
static void feed_data (hcl_client_t* client, const void* ptr, hcl_oow_t len) static int feed_data (hcl_client_t* client, const void* ptr, hcl_oow_t len)
{ {
printf ("GOT DATA>>>>>>>>>[%.*s]>>>>>>>\n", (int)len, ptr); printf ("GOT DATA>>>>>>>>>[%.*s]>>>>>>>\n", (int)len, ptr);
return 0;
} }
/* ========================================================================= */ /* ========================================================================= */
#define MIN_WORKER_STACK_SIZE 512000ul static int process_reply (hcl_client_t* client, const hcl_bch_t* addrs)
#define MIN_ACTOR_HEAP_SIZE 512000ul {
/* connect */
/* send request */
hcl_oow_t xlen, offset;
int x;
int fd = 0; /* read from stdin for testing */
hcl_bch_t buf[256];
ssize_t n;
offset = 0;
while (1)
{
n = read(fd, &buf[offset], HCL_SIZEOF(buf) - offset); /* switch to recv */
if (n <= -1)
{
printf ("error....%s\n", strerror(n));
return -1;
}
if (n == 0)
{
if (hcl_client_getstate(client) != HCL_CLIENT_STATE_START)
{
printf ("sudden end??? \n");
}
break;
}
x = hcl_client_feed(client, buf, n, &xlen);
if (x <= -1) return -1;
offset = n - xlen;
if (offset > 0) memmove (&buf[0], &buf[xlen], offset);
}
return 0;
}
int main (int argc, char* argv[]) int main (int argc, char* argv[])
{ {
@ -567,7 +608,8 @@ int main (int argc, char* argv[])
set_signal (SIGINT, handle_sigint); set_signal (SIGINT, handle_sigint);
set_signal_to_ignore (SIGPIPE); set_signal_to_ignore (SIGPIPE);
n = hcl_client_start(client, argv[opt.ind]); n = process_reply(client, argv[opt.ind]);
set_signal_to_default (SIGINT); set_signal_to_default (SIGINT);
set_signal_to_default (SIGPIPE); set_signal_to_default (SIGPIPE);
g_client = NULL; g_client = NULL;