mirror of
git://git.psyced.org/git/psyclpc
synced 2024-08-15 03:20:16 +00:00
pkg-psyc: parsing incomplete packets
This commit is contained in:
parent
a4825c7a97
commit
39b7facd19
3 changed files with 128 additions and 87 deletions
196
src/pkg-psyc.c
196
src/pkg-psyc.c
|
@ -4,14 +4,23 @@
|
||||||
* test LPC code:
|
* test LPC code:
|
||||||
*
|
*
|
||||||
// doesn't work with (int *) yet
|
// doesn't work with (int *) yet
|
||||||
mixed* x = psyc_parse(":_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n");
|
mixed *f = psyc_parse(":_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n");
|
||||||
mixed y = psyc_render(x);
|
mixed fr = psyc_render(f);
|
||||||
mixed z = ({ ([ "_context": "test" ]), ([ "_topic": "testing" ]), "_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
mixed r = ({ ([ "_context": "test" ]), ([ "_topic": "testing" ]),
|
||||||
z = psyc_render(z);
|
"_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
||||||
// psyc_render currently having some memory corruption problems
|
mixed rr = psyc_render(r);
|
||||||
debug_message(sprintf("libpsyc returned %O, %O and %O (%s)\n", x, y, z,
|
|
||||||
y == z? "success": "FAIL!"));
|
debug_message(sprintf("libpsyc returned %O, %O and %O (%s)\n", f, fr, rr,
|
||||||
*
|
fr == rr ? "success": "FAIL!"));
|
||||||
|
mixed *p1 = psyc_parse(":_context\ttest\n\n:_topic\ttest");
|
||||||
|
debug_message(sprintf("p1: libpsyc returned %O\n", p1));
|
||||||
|
mixed *p2 = psyc_parse("ing\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n");
|
||||||
|
debug_message(sprintf("p2: libpsyc returned %O\n", p2));
|
||||||
|
mixed *p = ({ p1[0]+p2[0], p1[1]+p2[1],
|
||||||
|
(p1[2]||"") + p2[2], (p1[3]||"") + p2[3] });
|
||||||
|
mixed pr = psyc_render(p);
|
||||||
|
debug_message(sprintf("libpsyc returned %O (%s)\n", p,
|
||||||
|
pr == rr ? "success": "FAIL!"));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
@ -113,6 +122,7 @@ f_psyc_render(svalue_t *sp) {
|
||||||
svalue_t *
|
svalue_t *
|
||||||
f_psyc_parse (svalue_t *sp) {
|
f_psyc_parse (svalue_t *sp) {
|
||||||
string_t *str = NULL;
|
string_t *str = NULL;
|
||||||
|
char *buffer = NULL;
|
||||||
vector_t *v;
|
vector_t *v;
|
||||||
mapping_t *map;
|
mapping_t *map;
|
||||||
mp_int i;
|
mp_int i;
|
||||||
|
@ -137,10 +147,25 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
i = 0;
|
i = 0;
|
||||||
if (sp->type == T_POINTER) {
|
if (sp->type == T_POINTER) {
|
||||||
errorf("\npsyc_parse got %ld int* bytes... not supported yet\n", i);
|
errorf("\npsyc_parse got %ld int* bytes... not supported yet\n", i);
|
||||||
}
|
} else if (sp->type == T_STRING) {
|
||||||
else if (sp->type == T_STRING) {
|
|
||||||
printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
|
printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
|
||||||
psyc_setParseBuffer2(state->parser, get_txt(sp->u.str), mstrsize(sp->u.str));
|
|
||||||
|
if (state->remaining) {
|
||||||
|
// there are remaining bytes from the previous call to psyc_parse,
|
||||||
|
// copy them together with the newly arrived data
|
||||||
|
buffer = pxalloc(state->remaining_len + mstrsize(sp->u.str));
|
||||||
|
if (!buffer) errorf("Out of memory for psyc_parse buffer.\n");
|
||||||
|
memcpy(buffer, state->remaining, state->remaining_len);
|
||||||
|
memcpy(buffer + state->remaining_len, get_txt(sp->u.str), mstrsize(sp->u.str));
|
||||||
|
psyc_setParseBuffer2(state->parser, buffer, state->remaining_len + mstrsize(sp->u.str));
|
||||||
|
pfree(state->remaining);
|
||||||
|
state->remaining = NULL;
|
||||||
|
state->remaining_len = 0;
|
||||||
|
} else {
|
||||||
|
psyc_setParseBuffer2(state->parser, get_txt(sp->u.str), mstrsize(sp->u.str));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errorf("\npsyc_parse got type %d, not supported\n", sp->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state->packet) {
|
if (!state->packet) {
|
||||||
|
@ -160,26 +185,20 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
svalue_t *sv;
|
svalue_t *sv;
|
||||||
ret = psyc_parse(state->parser, &oper, &name, &value);
|
ret = psyc_parse(state->parser, &oper, &name, &value);
|
||||||
|
|
||||||
if (state->remaining) {
|
printf("#%2d %c%.*s = %.*s\n", ret, oper ? oper : ' ', name.length, name.ptr, value.length, value.ptr);
|
||||||
pfree(state->remaining);
|
|
||||||
state->remaining = NULL;
|
|
||||||
state->remaining_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
|
case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
|
||||||
// save oper, name & value in state at the start of incomplete entity or body
|
// save oper, name & value in state at the start of incomplete entity or body
|
||||||
state->oper = oper;
|
state->oper = oper;
|
||||||
|
state->name = mstring_alloc_string(name.length);
|
||||||
state->name_len = name.length;
|
memcpy(get_txt(state->name), name.ptr, name.length);
|
||||||
state->name = pxalloc(name.length);
|
|
||||||
memcpy(state->name, name.ptr, name.length);
|
|
||||||
if (!state->name)
|
if (!state->name)
|
||||||
errorf("Out of memory for name.\n");
|
errorf("Out of memory for name.\n");
|
||||||
|
|
||||||
state->value_len = 0;
|
|
||||||
// allocate memory for the total length of the value
|
// allocate memory for the total length of the value
|
||||||
state->value = pxalloc(psyc_getParseValueLength(state->parser));
|
state->value_len = 0;
|
||||||
|
state->value = mstring_alloc_string(psyc_getParseValueLength(state->parser));
|
||||||
if (!state->value)
|
if (!state->value)
|
||||||
errorf("Out of memory for value.\n");
|
errorf("Out of memory for value.\n");
|
||||||
|
|
||||||
|
@ -187,17 +206,17 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_BODY_CONT:
|
case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_BODY_CONT:
|
||||||
case PSYC_PARSE_ENTITY_END: case PSYC_PARSE_BODY_END:
|
case PSYC_PARSE_ENTITY_END: case PSYC_PARSE_BODY_END:
|
||||||
// append value to tmp buffer in state
|
// append value to tmp buffer in state
|
||||||
memcpy(state->value + state->value_len, value.ptr, value.length);
|
memcpy(get_txt(state->value) + state->value_len, value.ptr, value.length);
|
||||||
state->value_len += value.length;
|
state->value_len += value.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
|
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
|
// incomplete entity or body parsing done, set oper/name/value to the ones saved in state
|
||||||
oper = state->oper;
|
oper = state->oper;
|
||||||
name.ptr = state->name;
|
name.ptr = get_txt(state->name);
|
||||||
name.length = state->name_len;
|
name.length = mstrsize(state->name);
|
||||||
value.ptr = state->value;
|
value.ptr = get_txt(state->value);
|
||||||
value.length = state->value_len;
|
value.length = mstrsize(state->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
|
@ -216,10 +235,23 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
// for values of routing variables as they repeat a lot
|
// for values of routing variables as they repeat a lot
|
||||||
put_string(sv, new_n_tabled(value.ptr, value.length));
|
put_string(sv, new_n_tabled(value.ptr, value.length));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PSYC_PARSE_ENTITY_START:
|
case PSYC_PARSE_ENTITY_START:
|
||||||
case PSYC_PARSE_ENTITY_CONT:
|
case PSYC_PARSE_ENTITY_CONT:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PSYC_PARSE_ENTITY_END:
|
case PSYC_PARSE_ENTITY_END:
|
||||||
|
if (oper != ':') {
|
||||||
|
puts("_failure_unsupported_state");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sv = pxalloc(sizeof(svalue_t));
|
||||||
|
put_string(sv, make_tabled(state->name));
|
||||||
|
sv = get_map_lvalue(v->item[PSYC_ENTITY].u.map, sv);
|
||||||
|
put_string(sv, state->value);
|
||||||
|
break;
|
||||||
|
|
||||||
case PSYC_PARSE_ENTITY:
|
case PSYC_PARSE_ENTITY:
|
||||||
if (oper != ':') {
|
if (oper != ':') {
|
||||||
puts("_failure_unsupported_state");
|
puts("_failure_unsupported_state");
|
||||||
|
@ -234,7 +266,63 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
// shared string table? probably yes.. but it's a guess
|
// shared string table? probably yes.. but it's a guess
|
||||||
//t_string(sv, new_n_mstring(value.ptr, value.length));
|
//t_string(sv, new_n_mstring(value.ptr, value.length));
|
||||||
put_string(sv, new_n_tabled(value.ptr, value.length));
|
put_string(sv, new_n_tabled(value.ptr, value.length));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSYC_PARSE_BODY_START:
|
||||||
|
case PSYC_PARSE_BODY_CONT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSYC_PARSE_BODY_END:
|
||||||
|
put_string(&v->item[PSYC_METHOD], make_tabled(state->name));
|
||||||
|
put_string(&v->item[PSYC_BODY], state->value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
state->packet = NULL;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorf("Error while parsing PSYC: %i\n", ret);
|
||||||
|
/* NOTREACHED */
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case PSYC_PARSE_BODY_END:
|
||||||
|
case PSYC_PARSE_ENTITY_END:
|
||||||
|
// reset tmp buffers in state when incomplete entity or body parsing is done
|
||||||
|
state->oper = 0;
|
||||||
|
state->name = NULL;
|
||||||
|
state->value = NULL;
|
||||||
|
if (ret == PSYC_PARSE_BODY_END)
|
||||||
|
break;
|
||||||
|
case PSYC_PARSE_ENTITY:
|
||||||
// list parsing not supported yet.. TODO
|
// list parsing not supported yet.. TODO
|
||||||
if (psyc_isListVar(&name)) {
|
if (psyc_isListVar(&name)) {
|
||||||
psyc_initParseListState(&listState);
|
psyc_initParseListState(&listState);
|
||||||
|
@ -258,60 +346,12 @@ f_psyc_parse (svalue_t *sp) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case PSYC_PARSE_BODY_START:
|
|
||||||
case PSYC_PARSE_BODY_CONT:
|
|
||||||
break;
|
|
||||||
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));
|
|
||||||
|
|
||||||
// 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:
|
|
||||||
state->packet = NULL;
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
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);
|
} while (ret);
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
pfree(buffer);
|
||||||
|
|
||||||
free_svalue(sp);
|
free_svalue(sp);
|
||||||
put_array(sp, v);
|
put_array(sp, v);
|
||||||
state->packet = 0;
|
state->packet = 0;
|
||||||
|
|
|
@ -6,24 +6,25 @@
|
||||||
* or int* where necessary.
|
* or int* where necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# define PSYC_ROUTING 0
|
|
||||||
# define PSYC_ENTITY 1
|
|
||||||
# define PSYC_METHOD 2
|
|
||||||
# define PSYC_BODY 3
|
|
||||||
|
|
||||||
# include <psyc/parse.h>
|
# include <psyc/parse.h>
|
||||||
|
|
||||||
# include "array.h"
|
# include "array.h"
|
||||||
# include "xalloc.h"
|
# include "xalloc.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PSYC_ROUTING = 0,
|
||||||
|
PSYC_ENTITY = 1,
|
||||||
|
PSYC_METHOD = 2,
|
||||||
|
PSYC_BODY = 3,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct psyc_state_s {
|
typedef struct psyc_state_s {
|
||||||
psycParseState *parser;
|
psycParseState *parser;
|
||||||
vector_t *packet;
|
vector_t *packet;
|
||||||
// tmp storage for incomplete modifier/body
|
// tmp storage for incomplete modifier/body
|
||||||
char oper;
|
char oper;
|
||||||
char *name;
|
string_t *name;
|
||||||
size_t name_len;
|
string_t *value;
|
||||||
char *value;
|
|
||||||
size_t value_len;
|
size_t value_len;
|
||||||
// tmp storage for remaining unparsed bytes at the end of the buffer
|
// tmp storage for remaining unparsed bytes at the end of the buffer
|
||||||
char *remaining;
|
char *remaining;
|
||||||
|
|
|
@ -17,7 +17,7 @@ version_longtype="stable"
|
||||||
# A timestamp, to be used by bumpversion and other scripts.
|
# A timestamp, to be used by bumpversion and other scripts.
|
||||||
# It can be used, for example, to 'touch' this file on every build, thus
|
# 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.
|
# forcing revision control systems to add it on every checkin automatically.
|
||||||
version_stamp="Tue May 10 14:07:26 CEST 2011"
|
version_stamp="Wed May 11 16:44:23 CEST 2011"
|
||||||
|
|
||||||
# Okay, LDMUD is using 3.x.x so to avoid conflicts let's just use 4.x.x
|
# Okay, LDMUD is using 3.x.x so to avoid conflicts let's just use 4.x.x
|
||||||
version_major=4
|
version_major=4
|
||||||
|
|
Loading…
Reference in a new issue