diff options
author | Yorhel <git@yorhel.nl> | 2012-03-20 12:59:54 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2012-03-20 12:59:54 +0100 |
commit | b3e64a770271aeb0d131d241760cdd26c76ed33e (patch) | |
tree | 9d90c944dac373cb10a9c040c0c671ce3f2039c0 | |
parent | 2bb953c751cee8b04dbff76bffa87c53affed303 (diff) |
link: Added message handling framework + bugfix in setting NULL error
-rw-r--r-- | tanja.c | 144 |
1 files changed, 140 insertions, 4 deletions
@@ -1313,7 +1313,7 @@ static void tn_link_set_error_lock(tn_link *l, int code, const char *msg) { lbuf_free(l->tbuf); lbuf_init(l->tbuf); l->errcode = code; - l->errmsg = strdup(msg); + l->errmsg = msg ? strdup(msg) : NULL; l->active = 0; l->ctx->dispatch(l, l->data); } @@ -1479,13 +1479,144 @@ static inline void tn_link_handlehandshake(tn_link *l, const char *buf, int len) if(ok != (1|2|4)) { int c = !(ok&1) ? 1 : !(ok&2)? 2 : 3; - tn_link_set_error_lock(l, c << 24, + tn_link_set_error_lock(l, -c, c==1 ? "No or invalid protocol version" : c==2 ? "No common input format" : "No common output format"); } else l->handshaked = 1; } + +#define incs() do { while(len > 0 && (*buf == 0x20 || *buf == 0x09 || *buf == 0x0A || *buf == 0x0D)) { inc(1); } } while(0) + +static int tn_link_parsemessage(tn_link *l, const char *buf, int len, int32_t *arg, tn_tuple **tup) { + if(len < 2 || *buf != '[') { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + inc(1); + incs(); + if(!len) { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + // Message type + if(*buf < '1' || *buf > '7') { + tn_link_set_error_lock(l, -5, "Invalid message type."); + return 0; + } + int type = *buf-'0'; + inc(1); + incs(); + // Boolean argument + if(type == 1) { + // Comma + if(*buf != ',') { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + inc(1); + // Bool + if(len >= 4 && strncmp(buf, "true", 4) == 0) { + *arg = 1; + inc(4); + } else if(len >= 5 && strncmp(buf, "false", 5) == 0) { + *arg = 0; + inc(5); + } else { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + incs(); + } + // Integer argument + if(type == 2 || type == 4 || type == 5 || type == 6 || type == 7) { + // Comma + if(*buf != ',') { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + inc(1); + incs(); + // Integer (this parser only handles positive integers and isn't as strict as the above JSON parser) + *arg = 0; + while(len > 0 && *buf >= '0' && *buf <= '9') { + int n = (*arg)*10 + (*buf-'0'); + if(n < *arg) { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + *arg = n; + inc(1); + } + incs(); + } + // Tuple argument + if(type == 2 || type == 5 || type == 6) { + // Comma + if(*buf != ',') { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + inc(1); + incs(); + // Tuple + int rd = 0; + *tup = tn_json_parse(buf, len, &rd); + if(!*tup) { + tn_link_set_error_lock(l, -6, "Invalid JSON tuple."); + return 0; + } + buf += rd; + len -= rd; + incs(); + } + // End-of-message + if(!len || *buf != ']') { + tn_link_set_error_lock(l, -4, "Invalid message format."); + return 0; + } + inc(1); + incs(); + if(len) { + tn_link_set_error_lock(l, -7, "Excessive data after message."); + return 0; + } + return type; +} + #undef inc +#undef incs + + +static void tn_link_handlemessage(tn_link *l, int type, int32_t arg, tn_tuple *tup) { + arg++; + switch(type) { + case 1: // patternsync 1/0 + // TODO + break; + case 2: // register pid pat + // TODO + break; + case 3: // regdone + // TODO + break; + case 4: // unregister pid + // TODO + break; + case 5: // tuple tid tuple + // TODO: create a return path if tid > 0 + tn_node_send(l->node, tup, NULL); + break; + case 6: // reply tid tuple + // TODO + break; + case 7: // close tid + // TODO + break; + default: + assert(0); + } +} // Tries to read a single message from the buffer, returns the number of bytes @@ -1501,8 +1632,13 @@ static int tn_link_handleread(tn_link *l, const char *buf, int len) { int msglen = len > 0 && buf[len-1] == '\r' ? len-1 : len; if(!l->handshaked) tn_link_handlehandshake(l, buf, msglen); - else - {} // TODO: regular message handling + else { + int32_t arg = 0; + tn_tuple *tup = NULL; + int type = tn_link_parsemessage(l, buf, msglen, &arg, &tup); + if(type) + tn_link_handlemessage(l, type, arg, tup); + } return len+1; } |