wip - more reworking on hcl server/client code
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
59dfe8cbb7
commit
003ebb1b94
13
bin/main-c.c
13
bin/main-c.c
@ -24,7 +24,6 @@
|
|||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hcl-c.h"
|
|
||||||
#include "hcl-x.h"
|
#include "hcl-x.h"
|
||||||
#include "hcl-opt.h"
|
#include "hcl-opt.h"
|
||||||
#include "hcl-utl.h"
|
#include "hcl-utl.h"
|
||||||
@ -527,8 +526,6 @@ static int receive_raw_bytes (hcl_xproto_t* proto, int sck, hcl_ntime_t* idle_tm
|
|||||||
ssize_t x;
|
ssize_t x;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
HCL_ASSERT (hcl, proto->rcv.len < proto->rcv.len_needed);
|
|
||||||
|
|
||||||
if (HCL_UNLIKELY(proto->rcv.eof))
|
if (HCL_UNLIKELY(proto->rcv.eof))
|
||||||
{
|
{
|
||||||
hcl_seterrbfmt (hcl, HCL_EGENERIC, "connection closed");
|
hcl_seterrbfmt (hcl, HCL_EGENERIC, "connection closed");
|
||||||
@ -711,6 +708,16 @@ static int handle_request (hcl_client_t* client, const char* ipaddr, const char*
|
|||||||
|
|
||||||
scptr = sccur;
|
scptr = sccur;
|
||||||
|
|
||||||
|
if (!sccur == '\0')
|
||||||
|
{
|
||||||
|
hdr.type = HCL_XPKT_EXECUTE;
|
||||||
|
hdr.id = 1; /* TODO: */
|
||||||
|
hdr.len = sccur - scptr;
|
||||||
|
|
||||||
|
iov[0].iov_base = &hdr;
|
||||||
|
iov[0].iov_len = HCL_SIZEOF(hdr);
|
||||||
|
send_iov (sck, iov, 1);
|
||||||
|
}
|
||||||
if (*sccur == '\0' && shut_wr_after_req) shutdown (sck, SHUT_WR);
|
if (*sccur == '\0' && shut_wr_after_req) shutdown (sck, SHUT_WR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +544,7 @@ int main (int argc, char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((c = hcl_getbopt (argc, argv, &opt)) != HCL_BCI_EOF)
|
while ((c = hcl_getbopt(argc, argv, &opt)) != HCL_BCI_EOF)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
@ -837,7 +837,7 @@ int main (int argc, char* argv[])
|
|||||||
/*trait |= HCL_TRAIT_NOGC;*/
|
/*trait |= HCL_TRAIT_NOGC;*/
|
||||||
trait |= HCL_TRAIT_AWAIT_PROCS;
|
trait |= HCL_TRAIT_AWAIT_PROCS;
|
||||||
if (enable_block) trait |= HCL_TRAIT_LANG_ENABLE_BLOCK;
|
if (enable_block) trait |= HCL_TRAIT_LANG_ENABLE_BLOCK;
|
||||||
if (nl_terminator) trait |= HCL_TRAIT_LANG_ENABLE_EOL;;
|
if (nl_terminator) trait |= HCL_TRAIT_LANG_ENABLE_EOL;
|
||||||
hcl_setoption (hcl, HCL_TRAIT, &trait);
|
hcl_setoption (hcl, HCL_TRAIT, &trait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
294
lib/hcl-x.c
294
lib/hcl-x.c
@ -131,14 +131,10 @@ struct hcl_server_proto_t
|
|||||||
hcl_xpkt_hdr_t hdr;
|
hcl_xpkt_hdr_t hdr;
|
||||||
} rcv;
|
} rcv;
|
||||||
|
|
||||||
/*
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
hcl_oow_t nchunks;
|
|
||||||
hcl_bch_t buf[HCL_SERVER_PROTO_REPLY_BUF_SIZE];
|
} snd;
|
||||||
hcl_oow_t len;
|
|
||||||
} reply;
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -277,6 +273,15 @@ struct hcl_server_t
|
|||||||
pthread_mutex_t log_mutex;
|
pthread_mutex_t log_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
static int send_stdout_bytes (hcl_server_proto_t* proto, const hcl_bch_t* data, hcl_oow_t len);
|
||||||
|
|
||||||
|
#if defined(HCL_OOCH_IS_UCH)
|
||||||
|
static int send_stdout_chars (hcl_server_proto_t* proto, const hcl_ooch_t* data, hcl_oow_t len);
|
||||||
|
#else
|
||||||
|
#define send_stdout_chars(proto,data,len) send_stdout_bytes(proto,data,len)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
static const hcl_bch_t* get_base_name (const hcl_bch_t* path)
|
static const hcl_bch_t* get_base_name (const hcl_bch_t* path)
|
||||||
@ -571,9 +576,11 @@ static int print_handler (hcl_t* hcl, hcl_io_cmd_t cmd, void* arg)
|
|||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case HCL_IO_OPEN:
|
case HCL_IO_OPEN:
|
||||||
|
printf ("IO OPEN SOMETHING...........\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HCL_IO_CLOSE:
|
case HCL_IO_CLOSE:
|
||||||
|
printf ("IO CLOSE SOMETHING...........\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case HCL_IO_WRITE:
|
case HCL_IO_WRITE:
|
||||||
@ -582,8 +589,7 @@ static int print_handler (hcl_t* hcl, hcl_io_cmd_t cmd, void* arg)
|
|||||||
hcl_io_udoarg_t* outarg = (hcl_io_udoarg_t*)arg;
|
hcl_io_udoarg_t* outarg = (hcl_io_udoarg_t*)arg;
|
||||||
|
|
||||||
printf ("IO WRITE SOMETHING...........\n");
|
printf ("IO WRITE SOMETHING...........\n");
|
||||||
#if 0
|
if (send_stdout_chars(xtn->proto, outarg->ptr, outarg->len) <= -1)
|
||||||
if (hcl_server_proto_feed_reply(xtn->proto, outarg->ptr, outarg->len, 0) <= -1)
|
|
||||||
{
|
{
|
||||||
/* TODO: change error code and message. propagage the errormessage from proto */
|
/* TODO: change error code and message. propagage the errormessage from proto */
|
||||||
hcl_seterrbfmt (hcl, HCL_EIOERR, "failed to write message via proto");
|
hcl_seterrbfmt (hcl, HCL_EIOERR, "failed to write message via proto");
|
||||||
@ -593,7 +599,7 @@ printf ("IO WRITE SOMETHING...........\n");
|
|||||||
hcl_abort (hcl);
|
hcl_abort (hcl);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
outarg->xlen = outarg->len;
|
outarg->xlen = outarg->len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -604,7 +610,7 @@ printf ("IO WRITE SOMETHING...........\n");
|
|||||||
|
|
||||||
printf ("IO WRITE SOMETHING BYTES...........\n");
|
printf ("IO WRITE SOMETHING BYTES...........\n");
|
||||||
#if 0
|
#if 0
|
||||||
if (hcl_server_proto_feed_reply_bytes(xtn->proto, outarg->ptr, outarg->len) <= -1)
|
if (send_stdout_bytes(xtn->proto, outarg->ptr, outarg->len) <= -1)
|
||||||
{
|
{
|
||||||
/* TODO: change error code and message. propagage the errormessage from proto */
|
/* TODO: change error code and message. propagage the errormessage from proto */
|
||||||
hcl_seterrbfmt (hcl, HCL_EIOERR, "failed to write message via proto");
|
hcl_seterrbfmt (hcl, HCL_EIOERR, "failed to write message via proto");
|
||||||
@ -705,48 +711,19 @@ printf ("on_fed_cnode......\n");
|
|||||||
* arrange to clear byte-codes before compiling the expression. */
|
* arrange to clear byte-codes before compiling the expression. */
|
||||||
flags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK;
|
flags = HCL_COMPILE_CLEAR_CODE | HCL_COMPILE_CLEAR_FNBLK;
|
||||||
proto->feed.ongoing = 1;
|
proto->feed.ongoing = 1;
|
||||||
|
printf ("CLEARING...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("hcl_copingll......\n");
|
printf ("COMPILING hcl_copingll......\n");
|
||||||
if (hcl_compile(hcl, obj, flags) <= -1)
|
if (hcl_compile(hcl, obj, flags) <= -1)
|
||||||
{
|
{
|
||||||
|
hcl_logbfmt (hcl, HCL_LOG_STDERR, "COMPILER ERROR - %js\n", hcl_geterrmsg(hcl));
|
||||||
#if 0
|
#if 0
|
||||||
print_error(hcl, "failed to compile");
|
print_error(hcl, "failed to compile");
|
||||||
xtn->feed.pos = xtn->feed.len; /* arrange to discard the rest of the line */
|
xtn->feed.pos = xtn->feed.len; /* arrange to discard the rest of the line */
|
||||||
show_prompt (hcl, 0);
|
show_prompt (hcl, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
hcl_oow_t i;
|
|
||||||
|
|
||||||
for (i = xtn->feed.pos; i < xtn->feed.len; i++)
|
|
||||||
{
|
|
||||||
/* this loop is kind of weird. it is to check the current feed buffer is left with
|
|
||||||
* spaces only and to execute the compiled bytecodes so far if the check is true.
|
|
||||||
* the check is performed because a single line of the user input can have multiple
|
|
||||||
* expressions joined with a semicolon or contains trailing spaces. */
|
|
||||||
if (!hcl_is_bch_space(xtn->feed.buf[i])) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i >= xtn->feed.len || xtn->feed.pos >= xtn->feed.len)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
hcl_oop_t retv;
|
|
||||||
|
|
||||||
/* nothing more to feed */
|
|
||||||
|
|
||||||
printf ("hcl_executing.....\n");
|
|
||||||
retv = hcl_execute(hcl);
|
|
||||||
hcl_flushudio (hcl);
|
|
||||||
|
|
||||||
proto->feed.ongoing = 0;
|
|
||||||
/*show_prompt (hcl, 0);*/
|
|
||||||
#if 0
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -787,6 +764,8 @@ hcl_server_proto_t* hcl_server_proto_open (hcl_oow_t xtnsize, hcl_server_worker_
|
|||||||
if (proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_GC) trait |= HCL_TRAIT_DEBUG_GC;
|
if (proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_GC) trait |= HCL_TRAIT_DEBUG_GC;
|
||||||
if (proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_BIGINT) trait |= HCL_TRAIT_DEBUG_BIGINT;
|
if (proto->worker->server->cfg.trait & HCL_SERVER_TRAIT_DEBUG_BIGINT) trait |= HCL_TRAIT_DEBUG_BIGINT;
|
||||||
#endif
|
#endif
|
||||||
|
trait |= HCL_TRAIT_LANG_ENABLE_BLOCK;
|
||||||
|
trait |= HCL_TRAIT_LANG_ENABLE_EOL;
|
||||||
hcl_setoption (proto->hcl, HCL_TRAIT, &trait);
|
hcl_setoption (proto->hcl, HCL_TRAIT, &trait);
|
||||||
|
|
||||||
HCL_MEMSET (&hclcb, 0, HCL_SIZEOF(hclcb));
|
HCL_MEMSET (&hclcb, 0, HCL_SIZEOF(hclcb));
|
||||||
@ -837,7 +816,7 @@ static int write_stdout (hcl_server_proto_t* proto, const hcl_bch_t* ptr, hcl_oo
|
|||||||
|
|
||||||
iov[0].iov_base = &hdr;
|
iov[0].iov_base = &hdr;
|
||||||
iov[0].iov_len = HCL_SIZEOF(hdr);
|
iov[0].iov_len = HCL_SIZEOF(hdr);
|
||||||
iov[1].iov_base = ptr;
|
iov[1].iov_base = (hcl_bch_t*)ptr;
|
||||||
iov[1].iov_len = len;
|
iov[1].iov_len = len;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@ -1160,20 +1139,12 @@ static int receive_raw_request (hcl_server_proto_t* proto)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int hcl_server_proto_handle_incoming (hcl_server_proto_t* proto)
|
static int handle_received_data (hcl_server_proto_t* proto)
|
||||||
{
|
{
|
||||||
hcl_server_worker_t* worker = proto->worker;
|
hcl_server_worker_t* worker = proto->worker;
|
||||||
hcl_t* hcl = proto->hcl;
|
hcl_t* hcl = proto->hcl;
|
||||||
hcl_xpkt_hdr_t* hdr;
|
hcl_xpkt_hdr_t* hdr;
|
||||||
|
|
||||||
if (proto->rcv.len < proto->rcv.len_needed)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
n = receive_raw_request(proto);
|
|
||||||
if (n <= -1) goto fail_with_errmsg; // TODO: backup error message...and create a new message
|
|
||||||
else if (n == 0) return 0; /* not enough data has been read */
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (proto->rcv.state)
|
switch (proto->rcv.state)
|
||||||
{
|
{
|
||||||
case HCL_SERVER_PROTO_RCV_HEADER:
|
case HCL_SERVER_PROTO_RCV_HEADER:
|
||||||
@ -1182,22 +1153,14 @@ int hcl_server_proto_handle_incoming (hcl_server_proto_t* proto)
|
|||||||
HCL_MEMCPY (&proto->rcv.hdr, proto->rcv.buf, HCL_SIZEOF(proto->rcv.hdr));
|
HCL_MEMCPY (&proto->rcv.hdr, proto->rcv.buf, HCL_SIZEOF(proto->rcv.hdr));
|
||||||
//proto->rcv.hdr.len = hcl_ntoh16(proto->rcv.hdr.len); /* keep this in the host byte order */
|
//proto->rcv.hdr.len = hcl_ntoh16(proto->rcv.hdr.len); /* keep this in the host byte order */
|
||||||
|
|
||||||
printf ("req.hdr = %d %d %d\n", proto->rcv.hdr.type, proto->rcv.hdr.id, proto->rcv.hdr.len);
|
|
||||||
/* consume the header */
|
/* consume the header */
|
||||||
HCL_MEMMOVE (proto->rcv.buf, &proto->rcv.buf[HCL_SIZEOF(proto->rcv.hdr)], proto->rcv.len - HCL_SIZEOF(proto->rcv.hdr));
|
HCL_MEMMOVE (proto->rcv.buf, &proto->rcv.buf[HCL_SIZEOF(proto->rcv.hdr)], proto->rcv.len - HCL_SIZEOF(proto->rcv.hdr));
|
||||||
proto->rcv.len -= HCL_SIZEOF(proto->rcv.hdr);
|
proto->rcv.len -= HCL_SIZEOF(proto->rcv.hdr);
|
||||||
|
|
||||||
if (proto->rcv.hdr.len > 0)
|
|
||||||
{
|
|
||||||
/* switch to the payload mode */
|
/* switch to the payload mode */
|
||||||
proto->rcv.state = HCL_SERVER_PROTO_RCV_PAYLOAD;
|
proto->rcv.state = HCL_SERVER_PROTO_RCV_PAYLOAD;
|
||||||
proto->rcv.len_needed = proto->rcv.hdr.len;
|
proto->rcv.len_needed = proto->rcv.hdr.len;
|
||||||
return 0; /* need data for payload */
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* payload length is zero in the header. */
|
|
||||||
HCL_ASSERT (hcl, proto->rcv.len_needed == HCL_SIZEOF(proto->rcv.hdr));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HCL_SERVER_PROTO_RCV_PAYLOAD:
|
case HCL_SERVER_PROTO_RCV_PAYLOAD:
|
||||||
if (proto->rcv.len < proto->rcv.hdr.len) return 0; /* need more payload data */
|
if (proto->rcv.len < proto->rcv.hdr.len) return 0; /* need more payload data */
|
||||||
@ -1211,6 +1174,22 @@ printf ("FEEDING [%.*s]\n", proto->rcv.hdr.len, proto->rcv.buf);
|
|||||||
goto fail_with_errmsg;
|
goto fail_with_errmsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (proto->rcv.hdr.type == HCL_XPKT_EXECUTE)
|
||||||
|
{
|
||||||
|
hcl_oop_t retv;
|
||||||
|
printf ("EXECUTING hcl_executing......\n");
|
||||||
|
proto->feed.ongoing = 0;
|
||||||
|
|
||||||
|
hcl_decode (hcl, hcl_getcode(hcl), 0, hcl_getbclen(hcl));
|
||||||
|
|
||||||
|
retv = hcl_execute(hcl);
|
||||||
|
hcl_flushudio (hcl);
|
||||||
|
if (!retv)
|
||||||
|
{
|
||||||
|
/* TODO: backup error message...and create a new message */
|
||||||
|
goto fail_with_errmsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (proto->rcv.hdr.type == HCL_XPKT_STDIN)
|
else if (proto->rcv.hdr.type == HCL_XPKT_STDIN)
|
||||||
{
|
{
|
||||||
/* store ... push stdin pipe... */
|
/* store ... push stdin pipe... */
|
||||||
@ -1229,8 +1208,11 @@ printf ("FEEDING [%.*s]\n", proto->rcv.hdr.len, proto->rcv.buf);
|
|||||||
|
|
||||||
/* TODO: minimize the use of HCL_MEMOVE... use the buffer */
|
/* TODO: minimize the use of HCL_MEMOVE... use the buffer */
|
||||||
/* switch to the header mode */
|
/* switch to the header mode */
|
||||||
|
if (proto->rcv.hdr.len > 0)
|
||||||
|
{
|
||||||
HCL_MEMMOVE (proto->rcv.buf, &proto->rcv.buf[proto->rcv.hdr.len], proto->rcv.len - proto->rcv.hdr.len);
|
HCL_MEMMOVE (proto->rcv.buf, &proto->rcv.buf[proto->rcv.hdr.len], proto->rcv.len - proto->rcv.hdr.len);
|
||||||
proto->rcv.len -= proto->rcv.hdr.len;
|
proto->rcv.len -= proto->rcv.hdr.len;
|
||||||
|
}
|
||||||
proto->rcv.state = HCL_SERVER_PROTO_RCV_HEADER;
|
proto->rcv.state = HCL_SERVER_PROTO_RCV_HEADER;
|
||||||
proto->rcv.len_needed = HCL_SIZEOF(proto->rcv.hdr);
|
proto->rcv.len_needed = HCL_SIZEOF(proto->rcv.hdr);
|
||||||
|
|
||||||
@ -1251,6 +1233,102 @@ fail_with_errmsg:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int send_iov (int sck, struct iovec* iov, int count)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ssize_t nwritten;
|
||||||
|
struct msghdr msg;
|
||||||
|
|
||||||
|
memset (&msg, 0, HCL_SIZEOF(msg));
|
||||||
|
msg.msg_iov = (struct iovec*)&iov[index];
|
||||||
|
msg.msg_iovlen = count - index;
|
||||||
|
nwritten = sendmsg(sck, &msg, 0);
|
||||||
|
/*nwritten = writev(proto->worker->sck, (const struct iovec*)&iov[index], count - index);*/
|
||||||
|
if (nwritten <= -1)
|
||||||
|
{
|
||||||
|
/* error occurred inside the worker thread shouldn't affect the error information
|
||||||
|
* in the server object. so here, i just log a message */
|
||||||
|
fprintf (stderr, "Unable to sendmsg on %d - %s\n", sck, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (index < count && (size_t)nwritten >= iov[index].iov_len)
|
||||||
|
nwritten -= iov[index++].iov_len;
|
||||||
|
|
||||||
|
if (index == count) break;
|
||||||
|
|
||||||
|
iov[index].iov_base = (void*)((hcl_uint8_t*)iov[index].iov_base + nwritten);
|
||||||
|
iov[index].iov_len -= nwritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_stdout_bytes (hcl_server_proto_t* proto, const hcl_bch_t* data, hcl_oow_t len)
|
||||||
|
{
|
||||||
|
hcl_xpkt_hdr_t hdr;
|
||||||
|
struct iovec iov[2];
|
||||||
|
const hcl_bch_t* ptr, * cur, * end;
|
||||||
|
|
||||||
|
ptr = cur = data;
|
||||||
|
end = data + len;
|
||||||
|
|
||||||
|
while (ptr < end)
|
||||||
|
{
|
||||||
|
while (cur != end && cur - ptr < 255) cur++;
|
||||||
|
|
||||||
|
hdr.type = HCL_XPKT_STDOUT;
|
||||||
|
hdr.id = 1; /* TODO: */
|
||||||
|
hdr.len = cur - ptr;
|
||||||
|
|
||||||
|
iov[0].iov_base = &hdr;
|
||||||
|
iov[0].iov_len = HCL_SIZEOF(hdr);
|
||||||
|
iov[1].iov_base = ptr;
|
||||||
|
iov[1].iov_len = cur - ptr;
|
||||||
|
|
||||||
|
if (send_iov(proto->worker->sck, iov, 2) <= -1)
|
||||||
|
{
|
||||||
|
/* TODO: error message */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HCL_OOCH_IS_UCH)
|
||||||
|
static int send_stdout_chars (hcl_server_proto_t* proto, const hcl_ooch_t* data, hcl_oow_t len)
|
||||||
|
{
|
||||||
|
const hcl_ooch_t* ptr, * end;
|
||||||
|
hcl_bch_t tmp[256];
|
||||||
|
hcl_oow_t tln, pln;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
ptr = data;
|
||||||
|
end = data + len;
|
||||||
|
|
||||||
|
while (ptr < end)
|
||||||
|
{
|
||||||
|
pln = end - ptr;
|
||||||
|
tln = HCL_COUNTOF(tmp);
|
||||||
|
n = hcl_convutobchars(proto->hcl, ptr, &pln, tmp, &tln);
|
||||||
|
if (n <= -1 && n != -2) return -1;
|
||||||
|
|
||||||
|
if (send_stdout_bytes(proto, tmp, tln) <= -1) return -1;
|
||||||
|
ptr += pln;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_prim_t* prim, hcl_errnum_t* errnum)
|
hcl_server_t* hcl_server_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, hcl_server_prim_t* prim, hcl_errnum_t* errnum)
|
||||||
@ -1574,6 +1652,97 @@ static void zap_worker_in_server (hcl_server_t* server, hcl_server_worker_t* wor
|
|||||||
worker->next_worker = HCL_NULL;
|
worker->next_worker = HCL_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int worker_step (hcl_server_worker_t* worker)
|
||||||
|
{
|
||||||
|
hcl_server_proto_t* proto = worker->proto;
|
||||||
|
hcl_server_t* server = worker->server;
|
||||||
|
hcl_t* hcl = proto->hcl;
|
||||||
|
struct pollfd pfd;
|
||||||
|
int tmout, actual_tmout;
|
||||||
|
ssize_t x;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
//HCL_ASSERT (hcl, proto->rcv.len < proto->rcv.len_needed);
|
||||||
|
|
||||||
|
if (HCL_UNLIKELY(proto->rcv.eof))
|
||||||
|
{
|
||||||
|
// TODO: may not be an error if writable needs to be checked...
|
||||||
|
hcl_seterrbfmt (hcl, HCL_EGENERIC, "connection closed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmout = HCL_SECNSEC_TO_MSEC(server->cfg.worker_idle_timeout.sec, server->cfg.worker_idle_timeout.nsec);
|
||||||
|
actual_tmout = (tmout <= 0)? 10000: tmout;
|
||||||
|
|
||||||
|
pfd.fd = worker->sck;
|
||||||
|
pfd.events = 0;
|
||||||
|
if (proto->rcv.len < proto->rcv.len_needed) pfd.events |= POLLIN;
|
||||||
|
//if (proto->snd.len > 0) pfd.events |= POLLOUT;
|
||||||
|
|
||||||
|
if (pfd.events)
|
||||||
|
{
|
||||||
|
n = poll(&pfd, 1, actual_tmout);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
if (errno == EINTR) return 0;
|
||||||
|
hcl_seterrwithsyserr (hcl, 0, errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (n == 0)
|
||||||
|
{
|
||||||
|
/* timed out - no activity on the pfd */
|
||||||
|
if (tmout > 0)
|
||||||
|
{
|
||||||
|
/* timeout explicity set. no activity for that duration. considered idle */
|
||||||
|
hcl_seterrbfmt (hcl, HCL_EGENERIC, "no activity on the worker socket %d", worker->sck);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* didn't read yet */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pfd.revents & POLLERR)
|
||||||
|
{
|
||||||
|
hcl_seterrbfmt (hcl, HCL_EGENERIC, "error condition detected on workder socket %d", worker->sck);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pfd.revents & POLLOUT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pfd.revents & POLLIN)
|
||||||
|
{
|
||||||
|
x = recv(worker->sck, &proto->rcv.buf[proto->rcv.len], HCL_COUNTOF(proto->rcv.buf) - proto->rcv.len, 0);
|
||||||
|
if (x <= -1)
|
||||||
|
{
|
||||||
|
if (errno == EINTR) return 0; /* didn't read read */
|
||||||
|
|
||||||
|
proto->rcv.polled = 0;
|
||||||
|
hcl_seterrwithsyserr (hcl, 0, errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x == 0) proto->rcv.eof = 1;
|
||||||
|
proto->rcv.len += x;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* the receiver buffer has enough data */
|
||||||
|
while (proto->rcv.len >= proto->rcv.len_needed)
|
||||||
|
{
|
||||||
|
if (handle_received_data(proto) <= -1)
|
||||||
|
{
|
||||||
|
/* TODO: proper error message */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void* worker_main (void* ctx)
|
static void* worker_main (void* ctx)
|
||||||
{
|
{
|
||||||
hcl_server_worker_t* worker = (hcl_server_worker_t*)ctx;
|
hcl_server_worker_t* worker = (hcl_server_worker_t*)ctx;
|
||||||
@ -1595,11 +1764,12 @@ static void* worker_main (void* ctx)
|
|||||||
add_worker_to_server (server, HCL_SERVER_WORKER_STATE_ALIVE, worker);
|
add_worker_to_server (server, HCL_SERVER_WORKER_STATE_ALIVE, worker);
|
||||||
pthread_mutex_unlock (&server->worker_mutex);
|
pthread_mutex_unlock (&server->worker_mutex);
|
||||||
|
|
||||||
|
/* the worker loop */
|
||||||
while (!server->stopreq)
|
while (!server->stopreq)
|
||||||
{
|
{
|
||||||
worker->opstate = HCL_SERVER_WORKER_OPSTATE_WAIT;
|
worker->opstate = HCL_SERVER_WORKER_OPSTATE_WAIT;
|
||||||
|
|
||||||
if (hcl_server_proto_handle_incoming(worker->proto) <= -1)
|
if (worker_step(worker) <= -1)
|
||||||
{
|
{
|
||||||
worker->opstate = HCL_SERVER_WORKER_OPSTATE_ERROR;
|
worker->opstate = HCL_SERVER_WORKER_OPSTATE_ERROR;
|
||||||
break;
|
break;
|
||||||
|
20
lib/hcl-x.h
20
lib/hcl-x.h
@ -31,6 +31,8 @@
|
|||||||
enum hcl_xpkt_type_t
|
enum hcl_xpkt_type_t
|
||||||
{
|
{
|
||||||
HCL_XPKT_CODEIN,
|
HCL_XPKT_CODEIN,
|
||||||
|
HCL_XPKT_EXECUTE,
|
||||||
|
|
||||||
HCL_XPKT_CODEOUT, /* return value is passed over this? */
|
HCL_XPKT_CODEOUT, /* return value is passed over this? */
|
||||||
HCL_XPKT_STDIN,
|
HCL_XPKT_STDIN,
|
||||||
HCL_XPKT_STDOUT,
|
HCL_XPKT_STDOUT,
|
||||||
@ -96,7 +98,6 @@ struct hcl_server_prim_t
|
|||||||
typedef struct hcl_server_prim_t hcl_server_prim_t;
|
typedef struct hcl_server_prim_t hcl_server_prim_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
@ -255,23 +256,6 @@ HCL_EXPORT void hcl_server_freemem (
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
HCL_EXPORT int hcl_server_proto_feed_reply (
|
|
||||||
hcl_server_proto_t* proto,
|
|
||||||
const hcl_ooch_t* ptr,
|
|
||||||
hcl_oow_t len,
|
|
||||||
int escape
|
|
||||||
);
|
|
||||||
|
|
||||||
HCL_EXPORT int hcl_server_proto_feed_reply_bytes (
|
|
||||||
hcl_server_proto_t* proto,
|
|
||||||
const hcl_bch_t* ptr,
|
|
||||||
hcl_oow_t len
|
|
||||||
);
|
|
||||||
|
|
||||||
HCL_EXPORT int hcl_server_proto_handle_incoming (
|
|
||||||
hcl_server_proto_t* proto
|
|
||||||
);
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
HCL_EXPORT hcl_client_t* hcl_client_open (
|
HCL_EXPORT hcl_client_t* hcl_client_open (
|
||||||
|
@ -686,7 +686,7 @@ int hcl_conv_bcstr_to_ucstr_with_cmgr (const hcl_bch_t* bcs, hcl_oow_t* bcslen,
|
|||||||
for (bp = bcs; *bp != '\0'; bp++) /* nothing */ ;
|
for (bp = bcs; *bp != '\0'; bp++) /* nothing */ ;
|
||||||
|
|
||||||
mlen = bp - bcs; wlen = *ucslen;
|
mlen = bp - bcs; wlen = *ucslen;
|
||||||
n = hcl_conv_bchars_to_uchars_with_cmgr (bcs, &mlen, ucs, &wlen, cmgr, all);
|
n = hcl_conv_bchars_to_uchars_with_cmgr(bcs, &mlen, ucs, &wlen, cmgr, all);
|
||||||
if (ucs)
|
if (ucs)
|
||||||
{
|
{
|
||||||
/* null-terminate the target buffer if it has room for it. */
|
/* null-terminate the target buffer if it has room for it. */
|
||||||
|
@ -4,6 +4,17 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## you must enclose the binary expression with parentheses
|
||||||
|
## i := (i + 20)
|
||||||
|
|
||||||
|
i:=0;
|
||||||
|
while(i < 20) {
|
||||||
|
printf "hello world 안녕하신가\n"
|
||||||
|
i := i + 20 ##ERROR: syntax error - prohibited binary operator - +
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
if ##ERROR: syntax error - no conditional expression after if
|
if ##ERROR: syntax error - no conditional expression after if
|
||||||
|
|
||||||
---
|
---
|
||||||
|
Loading…
Reference in New Issue
Block a user