mirror of
git://git.psyced.org/git/psyclpc
synced 2024-08-15 03:20:16 +00:00
pkg-psyc: incomplete packet handling
This commit is contained in:
parent
14944d8484
commit
a27331f703
6 changed files with 131 additions and 80 deletions
|
@ -1220,7 +1220,7 @@ lp_cv_has_psyc_lib="no"
|
|||
AC_CHECK_LIB(psyc,main, lp_cv_has_psyc_lib="yes")
|
||||
|
||||
if test $lp_cv_has_psyc_lib = yes; then
|
||||
LIBS="-lpsyc"
|
||||
LIBS="-lpsyc -lm"
|
||||
AC_CACHE_CHECK(for libpsyc usability,lp_cv_has_psyc,
|
||||
AC_TRY_RUN([
|
||||
#include <psyc.h>
|
||||
|
@ -1237,7 +1237,7 @@ int main(void) {
|
|||
|
||||
if test $lp_cv_has_psyc = yes; then
|
||||
AC_DEFINE(HAS_PSYC, 1, [Does the machine offer libpsyc?])
|
||||
PKGLIBS="$PKGLIBS -lpsyc"
|
||||
PKGLIBS="$PKGLIBS -lpsyc -lm"
|
||||
echo "Congrats! libpsyc is available on this system."
|
||||
else
|
||||
echo "libpsyc not available on this system yet."
|
||||
|
|
173
src/pkg-psyc.c
173
src/pkg-psyc.c
|
@ -32,7 +32,7 @@
|
|||
# include <fcntl.h>
|
||||
|
||||
# include <psyc.h>
|
||||
# include <psyc/parser.h>
|
||||
# include <psyc/parse.h>
|
||||
# include <psyc/render.h>
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
@ -95,7 +95,7 @@ f_psyc_render(svalue_t *sp) {
|
|||
meth, mlen, body, blen,
|
||||
PSYC_PACKET_CHECK_LENGTH);
|
||||
|
||||
printf("rendering... packet.length = %d\n", packet.length);
|
||||
printf("rendering... packet.length = %ld\n", packet.length);
|
||||
// alloc_mstring creates an *untabled* string suitable for tmp data
|
||||
memsafe(out = alloc_mstring(packet.length), packet.length, "f_psyc_render");
|
||||
psyc_render(&packet, get_txt(out), packet.length);
|
||||
|
@ -117,15 +117,14 @@ f_psyc_parse (svalue_t *sp) {
|
|||
mapping_t *map;
|
||||
mp_int i;
|
||||
char oper = 0;
|
||||
psycString name = {0,0}, value = {0,0}, elem = {0,0};
|
||||
psycString name = {0,0}, value = {0,0}, elem;
|
||||
psycParseListState listState;
|
||||
int ret;
|
||||
size_t len;
|
||||
|
||||
assert_shadow_sent(current_object);
|
||||
psycState *state = O_GET_PSYC_STATE(current_object);
|
||||
psyc_state_t *state = O_GET_PSYC_STATE(current_object);
|
||||
if (!state) {
|
||||
state = pxalloc(sizeof(psycState));
|
||||
state = pxalloc(sizeof(psyc_state_t));
|
||||
if (!state) errorf("Out of memory for psyc state struct.\n");
|
||||
O_GET_PSYC_STATE(current_object) = state;
|
||||
state->parser = pxalloc(sizeof(psycParseState));
|
||||
|
@ -138,7 +137,7 @@ f_psyc_parse (svalue_t *sp) {
|
|||
errorf("\npsyc_parse got %ld int* bytes... not supported yet\n", i);
|
||||
}
|
||||
else if (sp->type == T_STRING) {
|
||||
printf("\npsyc_parse got a %d bytes long string...\n", mstrsize(sp->u.str));
|
||||
printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
|
||||
psyc_setParseBuffer(state->parser, psyc_newString(get_txt(sp->u.str),
|
||||
mstrsize(sp->u.str)));
|
||||
}
|
||||
|
@ -160,21 +159,50 @@ f_psyc_parse (svalue_t *sp) {
|
|||
svalue_t *sv;
|
||||
ret = psyc_parse(state->parser, &oper, &name, &value);
|
||||
|
||||
switch (ret) {
|
||||
case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
|
||||
if ((len = psyc_getParseValueLength(state->parser)))
|
||||
state->tmp = pxalloc(len);
|
||||
case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_BODY_CONT:
|
||||
case PSYC_PARSE_ENTITY_END: case PSYC_PARSE_BODY_END:
|
||||
memcpy(state->tmp + state->tmplen, value.ptr, value.length);
|
||||
state->tmplen += value.length;
|
||||
if (state->remaining) {
|
||||
pfree(state->remaining);
|
||||
state->remaining_len = 0;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case PSYC_PARSE_ROUTING:
|
||||
case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
|
||||
// save oper, name & value in state at the start of incomplete entity or body
|
||||
state->oper = oper;
|
||||
|
||||
state->name_len = name.length;
|
||||
state->name = pxalloc(name.length);
|
||||
memcpy(state->name, name.ptr, name.length);
|
||||
if (!state->name)
|
||||
errorf("Out of memory for name.\n");
|
||||
|
||||
state->value_len = 0;
|
||||
// allocate memory for the total length of the value
|
||||
state->value = pxalloc(psyc_getParseValueLength(state->parser));
|
||||
if (!state->value)
|
||||
errorf("Out of memory for value.\n");
|
||||
|
||||
// fall thru
|
||||
case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_BODY_CONT:
|
||||
case PSYC_PARSE_ENTITY_END: case PSYC_PARSE_BODY_END:
|
||||
// append value to tmp buffer in state
|
||||
memcpy(state->value + state->value_len, value.ptr, value.length);
|
||||
state->value_len += value.length;
|
||||
}
|
||||
|
||||
if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
|
||||
// incomplete entity or body parsing done, set oper/name/value to the ones saved in state
|
||||
oper = state->oper;
|
||||
name.ptr = state->name;
|
||||
name.length = state->name_len;
|
||||
value.ptr = state->value;
|
||||
value.length = state->value_len;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case PSYC_PARSE_ROUTING:
|
||||
if (oper != ':') {
|
||||
puts("_failure_unsupported_state");
|
||||
continue;
|
||||
puts("_failure_unsupported_state");
|
||||
continue;
|
||||
}
|
||||
sv = pxalloc(sizeof(svalue_t));
|
||||
// new_n_tabled fetches a reference of a probably existing
|
||||
|
@ -186,20 +214,16 @@ f_psyc_parse (svalue_t *sp) {
|
|||
// for values of routing variables as they repeat a lot
|
||||
put_string(sv, new_n_tabled(value.ptr, value.length));
|
||||
break;
|
||||
case PSYC_PARSE_ENTITY_START:
|
||||
case PSYC_PARSE_ENTITY_CONT:
|
||||
case PSYC_PARSE_ENTITY_END:
|
||||
case PSYC_PARSE_ENTITY:
|
||||
if (oper && oper != ':') {
|
||||
puts("_failure_unsupported_state");
|
||||
continue;
|
||||
case PSYC_PARSE_ENTITY_END:
|
||||
case PSYC_PARSE_ENTITY:
|
||||
if (oper != ':') {
|
||||
puts("_failure_unsupported_state");
|
||||
continue;
|
||||
}
|
||||
if (name.length) {
|
||||
sv = pxalloc(sizeof(svalue_t));
|
||||
put_string(sv, new_n_tabled(name.ptr, name.length));
|
||||
sv = get_map_lvalue(v->item[PSYC_ENTITY].u.map, sv);
|
||||
} else
|
||||
errorf("sv needs to point to the current map_lvalue .. FIXME!\n");
|
||||
|
||||
sv = pxalloc(sizeof(svalue_t));
|
||||
put_string(sv, new_n_tabled(name.ptr, name.length));
|
||||
sv = get_map_lvalue(v->item[PSYC_ENTITY].u.map, sv);
|
||||
|
||||
// is it good to put entity variable values into the
|
||||
// shared string table? probably yes.. but it's a guess
|
||||
|
@ -207,61 +231,76 @@ f_psyc_parse (svalue_t *sp) {
|
|||
put_string(sv, new_n_tabled(value.ptr, value.length));
|
||||
|
||||
// list parsing not supported yet.. TODO
|
||||
if (name.length >= 5 && memcmp(name.ptr, "_list", 5) == 0)
|
||||
{
|
||||
write(1, ">>> LIST START\n", 15);
|
||||
psyc_initParseListState(&listState);
|
||||
psyc_setParseListBuffer(&listState, value);
|
||||
while ((ret = psyc_parseList(&listState, &name, &value, &elem)))
|
||||
if (psyc_isListVar(&name)) {
|
||||
psyc_initParseListState(&listState);
|
||||
psyc_setParseListBuffer(&listState, value);
|
||||
elem = (psycString){0, 0};
|
||||
while ((ret = psyc_parseList(&listState, &value, &elem))) {
|
||||
switch (ret)
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case PSYC_PARSE_LIST_END:
|
||||
case PSYC_PARSE_LIST_ELEM:
|
||||
write(1, "|", 1);
|
||||
write(1, elem.ptr, elem.length);
|
||||
write(1, "\n", 1);
|
||||
break;
|
||||
default:
|
||||
errorf("Error while parsing PSYC list: %i\n", ret);
|
||||
/* NOTREACHED */
|
||||
return sp;
|
||||
}
|
||||
|
||||
if (ret == PSYC_PARSE_LIST_END)
|
||||
{
|
||||
write(1, ">>> LIST END\n", 13);
|
||||
break;
|
||||
}
|
||||
case PSYC_PARSE_LIST_END:
|
||||
case PSYC_PARSE_LIST_ELEM:
|
||||
// TODO: store elem
|
||||
//write(1, elem.ptr, elem.length);
|
||||
break;
|
||||
default:
|
||||
errorf("Error while parsing PSYC list: %i\n", ret);
|
||||
/* NOTREACHED */
|
||||
return sp;
|
||||
}
|
||||
|
||||
if (ret == PSYC_PARSE_LIST_END)
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PSYC_PARSE_BODY_START:
|
||||
case PSYC_PARSE_BODY_CONT:
|
||||
case PSYC_PARSE_BODY_END:
|
||||
case PSYC_PARSE_BODY:
|
||||
case PSYC_PARSE_BODY_END:
|
||||
case PSYC_PARSE_BODY:
|
||||
if (str) errorf("Got two PSYC methods in the same packet!?\n");
|
||||
// new_n_tabled gets the shared string for the method
|
||||
put_string(&v->item[PSYC_METHOD],
|
||||
new_n_tabled(name.ptr, name.length));
|
||||
new_n_tabled(name.ptr, name.length));
|
||||
|
||||
// allocate an untabled string for the packet body
|
||||
put_string(&v->item[PSYC_BODY],
|
||||
new_n_mstring(value.ptr, value.length));
|
||||
|
||||
break;
|
||||
case PSYC_PARSE_COMPLETE:
|
||||
case PSYC_PARSE_COMPLETE:
|
||||
ret = 0;
|
||||
break;
|
||||
case PSYC_PARSE_INSUFFICIENT:
|
||||
errorf("Insufficient PSYC data.\n");
|
||||
/* NOTREACHED */
|
||||
return sp;
|
||||
default:
|
||||
case PSYC_PARSE_INSUFFICIENT:
|
||||
// insufficient data, save remaining bytes
|
||||
state->remaining_len = psyc_getParseRemainingLength(state->parser);
|
||||
if (state->remaining_len) {
|
||||
state->remaining = pxalloc(state->remaining_len);
|
||||
memcpy(state->remaining,
|
||||
psyc_getParseRemainingBuffer(state->parser),
|
||||
state->remaining_len);
|
||||
} else
|
||||
state->remaining = NULL;
|
||||
//TODO: psyc_setRemainingBuffer2(state->parser, state->remaining, state->remaining_len);
|
||||
break;
|
||||
default:
|
||||
errorf("Error while parsing PSYC: %i\n", ret);
|
||||
/* NOTREACHED */
|
||||
return sp;
|
||||
}
|
||||
|
||||
// free tmp buffers in state when incomplete entity or body parsing is done
|
||||
if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
|
||||
oper = 0;
|
||||
|
||||
if (state->name)
|
||||
pfree(state->name);
|
||||
state->name = NULL;
|
||||
state->name_len = 0;
|
||||
|
||||
if (value.ptr)
|
||||
pfree((void*)value.ptr);
|
||||
state->value = NULL;
|
||||
state->value_len = 0;
|
||||
}
|
||||
} while (ret);
|
||||
|
||||
free_svalue(sp);
|
||||
|
|
|
@ -11,28 +11,40 @@
|
|||
# define PSYC_METHOD 2
|
||||
# define PSYC_BODY 3
|
||||
|
||||
# include <psyc/parser.h>
|
||||
# include <psyc/parse.h>
|
||||
|
||||
# include "array.h"
|
||||
# include "xalloc.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct psyc_state_s {
|
||||
psycParseState *parser;
|
||||
vector_t *packet;
|
||||
char *tmp;
|
||||
size_t tmplen;
|
||||
} psycState;
|
||||
// tmp storage for incomplete modifier/body
|
||||
char oper;
|
||||
char *name;
|
||||
size_t name_len;
|
||||
char *value;
|
||||
size_t value_len;
|
||||
// tmp storage for remaining unparsed bytes at the end of the buffer
|
||||
char *remaining;
|
||||
size_t remaining_len;
|
||||
} psyc_state_t;
|
||||
|
||||
static inline void
|
||||
psyc_free_parser (psycState *ps) {
|
||||
psyc_free_state (psyc_state_t *ps) {
|
||||
if (!ps)
|
||||
return;
|
||||
if (ps->tmp)
|
||||
pfree((void *) ps->tmp);
|
||||
if (ps->name)
|
||||
pfree((void *) ps->name);
|
||||
if (ps->value)
|
||||
pfree((void *) ps->value);
|
||||
if (ps->remaining)
|
||||
pfree((void *) ps->remaining);
|
||||
if (ps->parser)
|
||||
pfree((void *) ps->parser);
|
||||
if (ps->packet)
|
||||
free_array(ps->packet);
|
||||
ps->oper = ps->name_len = ps->value_len = ps->remaining_len = 0;
|
||||
}
|
||||
|
||||
# define PKG_PSYC_H
|
||||
|
|
|
@ -132,7 +132,7 @@ struct shadow_s
|
|||
#endif
|
||||
interactive_t *ip; /* the information for interactive objects */
|
||||
#ifdef USE_PSYC
|
||||
psycState *psyc_state; /* in case this objects parses PSYC data */
|
||||
psyc_state_t *psyc_state; /* in case this objects parses PSYC data */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -2703,7 +2703,7 @@ destruct (object_t *ob)
|
|||
|
||||
#ifdef USE_PSYC
|
||||
if (shadow_sent->psyc_state)
|
||||
psyc_free_parser(shadow_sent->psyc_state);
|
||||
psyc_free_state(shadow_sent->psyc_state);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHADOWING
|
||||
|
|
|
@ -17,7 +17,7 @@ version_longtype="stable"
|
|||
# A timestamp, to be used by bumpversion and other scripts.
|
||||
# It can be used, for example, to 'touch' this file on every build, thus
|
||||
# forcing revision control systems to add it on every checkin automatically.
|
||||
version_stamp="Sun May 8 22:11:18 CEST 2011"
|
||||
version_stamp="Mon May 9 21:22:33 CEST 2011"
|
||||
|
||||
# Okay, LDMUD is using 3.x.x so to avoid conflicts let's just use 4.x.x
|
||||
version_major=4
|
||||
|
|
Loading…
Reference in a new issue