summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2012-03-20 12:59:54 +0100
committerYorhel <git@yorhel.nl>2012-03-20 12:59:54 +0100
commitb3e64a770271aeb0d131d241760cdd26c76ed33e (patch)
tree9d90c944dac373cb10a9c040c0c671ce3f2039c0
parent2bb953c751cee8b04dbff76bffa87c53affed303 (diff)
link: Added message handling framework + bugfix in setting NULL error
-rw-r--r--tanja.c144
1 files changed, 140 insertions, 4 deletions
diff --git a/tanja.c b/tanja.c
index 00e3688..0802368 100644
--- a/tanja.c
+++ b/tanja.c
@@ -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;
}