diff --git a/test/Makefile b/test/Makefile index 3574c63..cdbbaaa 100644 --- a/test/Makefile +++ b/test/Makefile @@ -13,13 +13,16 @@ test: $(TARGETS) for f in packets/full-* packets/error-*; do echo ">> $$f"; ./testParser $$f; done nettest: - for f in packets/full-* packets/error-*; do echo ">> $$f"; cat $$f | nc localhost $(PORT); done + for f in packets/full-*; do echo ">> $$f"; cat $$f | nc localhost $(PORT) | diff -u $$f -; done + +nettesterr: + for f in packets/error-*; do echo ">> $$f"; cat $$f | nc localhost $(PORT); done nettestp1: - (for f in packets/part-1-p*; do cat $$f; done) | nc localhost $(PORT) + (for f in packets/part-1-p*; do cat $$f; done) | nc localhost $(PORT) | diff -u packets/full-1 - nettestp2: - (for f in packets/part-1-length-p*; do cat $$f; done) | nc localhost $(PORT) + (for f in packets/part-1-length-p*; do cat $$f; done) | nc localhost $(PORT) | diff -u packets/full-1-length - clean: rm -f $(TARGETS) diff --git a/test/testServer.c b/test/testServer.c index 78b9eb1..aef8d81 100644 --- a/test/testServer.c +++ b/test/testServer.c @@ -14,14 +14,20 @@ #include #include #include +#include #include #include #include +#include const size_t RECV_BUF_SIZE = 256; +const size_t CONT_BUF_SIZE = 512; const size_t SEND_BUF_SIZE = 1024; const size_t NUM_PARSERS = 100; +// max size for routing & entity header +const size_t ROUTING_LINES = 16; +const size_t ENTITY_LINES = 32; // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa) @@ -47,9 +53,9 @@ int main(int argc, char **argv) struct sockaddr_storage remoteaddr; // client address socklen_t addrlen; - char buf[2*RECV_BUF_SIZE]; // cont buf + recv buf: [ ccrrrr] - char *recvbuf = buf + RECV_BUF_SIZE; // recv buf: ^^^^ - char *parsebuf; // parse buf: ^^^^^^ + char buf[CONT_BUF_SIZE + RECV_BUF_SIZE]; // cont buf + recv buf: [ ccrrrr] + char *recvbuf = buf + CONT_BUF_SIZE; // recv buf: ^^^^ + char *parsebuf; // parse buf: ^^^^^^ char sendbuf[SEND_BUF_SIZE]; size_t nbytes, contbytes = 0; @@ -62,10 +68,14 @@ int main(int argc, char **argv) psycParseState parsers[NUM_PARSERS]; psycPacket packets[NUM_PARSERS]; + psycModifier routing[NUM_PARSERS][ROUTING_LINES]; + psycModifier entity[NUM_PARSERS][ENTITY_LINES]; + psycModifier *mod; int ret, retl; char oper; psycString name, value, elem; + psycString *pname, *pvalue; psycParseListState listState; FD_ZERO(&master); // clear the master and temp sets @@ -148,6 +158,10 @@ int main(int argc, char **argv) // reset parser state & packet psyc_initParseState(&parsers[newfd]); memset(&packets[newfd], 0, sizeof(psycPacket)); + memset(&routing[newfd], 0, sizeof(psycModifier) * ROUTING_LINES); + memset(&entity[newfd], 0, sizeof(psycModifier) * ENTITY_LINES); + packets[newfd].routing.modifiers = routing[newfd]; + packets[newfd].entity.modifiers = entity[newfd]; printf("# New connection from %s on socket %d\n", inet_ntop(remoteaddr.ss_family, @@ -172,29 +186,101 @@ int main(int argc, char **argv) parsebuf = recvbuf - contbytes; psyc_nextParseBuffer(&parsers[i], psyc_newString(parsebuf, contbytes + nbytes)); contbytes = 0; + oper = 0; + name.length = 0; + value.length = 0; do { ret = psyc_parse(&parsers[i], &oper, &name, &value); switch (ret) { case PSYC_PARSE_ROUTING: - case PSYC_PARSE_ENTITY: + assert(packets[i].routing.lines < ROUTING_LINES); + mod = &(packets[i].routing.modifiers[packets[i].routing.lines]); + pname = &mod->name; + pvalue = &mod->value; + mod->flag = PSYC_MODIFIER_ROUTING; + packets[i].routing.lines++; + break; case PSYC_PARSE_ENTITY_INCOMPLETE: - if (verbose) - write(1, &oper, 1); - case PSYC_PARSE_BODY: - case PSYC_PARSE_BODY_INCOMPLETE: - if (ret == PSYC_PARSE_BODY_INCOMPLETE || - ret == PSYC_PARSE_ENTITY_INCOMPLETE) - ret = 0; - - // printf("the string is '%.*s'\n", name); - if (verbose) { - write(1, name.ptr, name.length); - write(1, " = ", 3); - write(1, value.ptr, value.length); - write(1, "\n", 1); + case PSYC_PARSE_ENTITY: + assert(packets[i].entity.lines < ENTITY_LINES); + mod = &(packets[i].entity.modifiers[packets[i].entity.lines]); + pname = &mod->name; + pvalue = &mod->value; + if (ret == PSYC_PARSE_ENTITY) { + packets[i].entity.lines++; + mod->flag = parsers[i].valueLength ? PSYC_MODIFIER_NEED_LENGTH : PSYC_MODIFIER_NO_LENGTH; } - if (memcmp(name.ptr, "_list", 5) == 0) { + break; + case PSYC_PARSE_BODY_INCOMPLETE: + case PSYC_PARSE_BODY: + pname = &(packets[i].method); + pvalue = &(packets[i].data); + break; + case PSYC_PARSE_COMPLETE: + printf("# Done parsing.\n"); + packets[i].flag = parsers[i].contentLengthFound ? PSYC_PACKET_NEED_LENGTH : PSYC_PACKET_NO_LENGTH; + psyc_setPacketLength(&packets[i]); + psyc_render(&packets[i], sendbuf, SEND_BUF_SIZE); + if (send(i, sendbuf, packets[i].length, 0) == -1) { + perror("send"); + } + ret = -1; + break; + case PSYC_PARSE_INSUFFICIENT: + printf("# Insufficient data.\n"); + contbytes = parsers[i].buffer.length - parsers[i].cursor; + if (contbytes > 0) { // copy end of parsebuf before start of recvbuf + assert(recvbuf - contbytes >= buf); // make sure it's still in the buffer + memcpy(recvbuf - contbytes, parsebuf + parsers[i].cursor, contbytes); + } + ret = 0; + break; + default: + printf("# Error while parsing: %i\n", ret); + ret = -1; + } + + switch (ret) { + case PSYC_PARSE_ENTITY_INCOMPLETE: + case PSYC_PARSE_BODY_INCOMPLETE: + ret = 0; + case PSYC_PARSE_ENTITY: + case PSYC_PARSE_ROUTING: + case PSYC_PARSE_BODY: + if (oper) { + mod->oper = oper; + if (verbose) write(1, &oper, 1); + } + + if (name.length) { + pname->ptr = malloc(name.length); + pname->length = name.length; + assert(pname->ptr != NULL); + memcpy((void*)pname->ptr, name.ptr, name.length); + name.length = 0; + if (verbose) { + write(1, pname->ptr, pname->length); + write(1, " = ", 3); + } + } + + if (value.length) { + if (!pvalue->ptr) + pvalue->ptr = malloc(parsers[i].valueLength ? parsers[i].valueLength : value.length); + assert(pvalue->ptr != NULL); + memcpy((void*)pvalue->ptr + pvalue->length, value.ptr, value.length); + pvalue->length += value.length; + value.length = 0; + if (verbose) { + write(1, pvalue->ptr, pvalue->length); + if (parsers[i].valueLength > pvalue->length) + write(1, "...", 3); + write(1, "\n", 1); + } + } + + if (name.length >= 5 && memcmp(name.ptr, "_list", 5) == 0) { if (verbose) write(1, ">>> LIST START\n", 15); psyc_initParseListState(&listState); @@ -219,29 +305,6 @@ int main(int argc, char **argv) } } while (retl > 0); } - break; - case PSYC_PARSE_COMPLETE: - printf("# Done parsing.\n"); -#ifdef RENDER_WORKS - psyc_render(&packets[i], sendbuf, SEND_BUF_SIZE); - if (send(i, sendbuf, packets[i].length, 0) == -1) { - perror("send"); - } -#endif - ret = -1; - break; - case PSYC_PARSE_INSUFFICIENT: - printf("# Insufficient data.\n"); - contbytes = parsers[i].buffer.length - parsers[i].cursor; - if (contbytes > 0) { // copy end of parsebuf before start of recvbuf - assert(recvbuf - contbytes >= buf); // make sure it's still in the buffer - memcpy(recvbuf - contbytes, parsebuf + parsers[i].cursor, contbytes); - } - ret = 0; - break; - default: - printf("# Error while parsing: %i\n", ret); - ret = -1; } } while (ret > 0); if (ret < 0) {