static void handle_client_message(uv_stream_t* target, msgpack_packer* pac, msgpack_object* obj){ int type; uint64_t seq; request_queue_entry* me; msgpack_object* err; msgpack_object* result; if(obj->type == MSGPACK_OBJECT_ARRAY){ type = obj->via.array.ptr[0].via.i64; if(type == 1 /* Resp */){ seq = obj->via.array.ptr[1].via.u64; me = request_locate(seq); if(me){ err = &obj->via.array.ptr[2]; if(err->type == MSGPACK_OBJECT_NIL){ err = NULL; } result = &obj->via.array.ptr[3]; me->callback(me, target, pac, err, result); uvm_chime_fill(&me->chime, (void*)1); }else{ printf("ERR: Invalid sequence "); msgpack_object_print(stdout, *obj); printf("\n"); } } }else{ printf("ERR: Malformed packet "); msgpack_object_print(stdout, *obj); printf("\n"); } }
int main(void) { /* creates buffer and serializer instance. */ msgpack_sbuffer* buffer = msgpack_sbuffer_new(); msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write); /* serializes ["Hello", "MessagePack"]. */ msgpack_pack_array(pk, 2); msgpack_pack_raw(pk, 5); msgpack_pack_raw_body(pk, "Hello", 5); msgpack_pack_raw(pk, 11); msgpack_pack_raw_body(pk, "MessagePack", 11); /* deserializes it. */ msgpack_unpacked msg; msgpack_unpacked_init(&msg); bool success = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL); /* prints the deserialized object. */ msgpack_object obj = msg.data; msgpack_object_print(stdout, obj); /*=> ["Hello", "MessagePack"] */ puts(""); // msgpack_pack_object/pk /* cleaning */ msgpack_sbuffer_free(buffer); msgpack_packer_free(pk); }
void add_input_bytes(msgpack_unpacker *unpacker, char *buf, int sz) { msgpack_unpacked result; int got = 0; printf("reading %d bytes\n", sz); //getchar(); printf("ENT u(%u) f(%u) o(%u) p(%u)\n", (unsigned)unpacker->used, (unsigned)unpacker->free, (unsigned)unpacker->off, (unsigned)unpacker->parsed); msgpack_unpacker_reserve_buffer(unpacker, sz); printf("EXP u(%u) f(%u) o(%u) p(%u)\n", (unsigned)unpacker->used, (unsigned)unpacker->free, (unsigned)unpacker->off, (unsigned)unpacker->parsed); memcpy(msgpack_unpacker_buffer(unpacker), buf, sz); msgpack_unpacker_buffer_consumed(unpacker, sz); printf("CON u(%u) f(%u) o(%u) p(%u)\n", (unsigned)unpacker->used, (unsigned)unpacker->free, (unsigned)unpacker->off, (unsigned)unpacker->parsed); msgpack_unpacked_init(&result); while (msgpack_unpacker_next(unpacker, &result)) { got = 1; msgpack_object_print(stdout, result.data); printf("\n"); } if (got) { msgpack_unpacker_expand_buffer(unpacker, 0); printf("XXX u(%u) f(%u) o(%u) p(%u)\n", (unsigned)unpacker->used, (unsigned)unpacker->free, (unsigned)unpacker->off, (unsigned)unpacker->parsed); } msgpack_unpacked_destroy(&result); }
int main(void) { msgpack_sbuffer sbuf; msgpack_packer pk; msgpack_zone mempool; msgpack_object deserialized; /* msgpack::sbuffer is a simple buffer implementation. */ msgpack_sbuffer_init(&sbuf); /* serialize values into the buffer using msgpack_sbuffer_write callback function. */ msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); msgpack_pack_array(&pk, 3); msgpack_pack_int(&pk, 1); msgpack_pack_true(&pk); msgpack_pack_str(&pk, 7); msgpack_pack_str_body(&pk, "example", 7); /* deserialize the buffer into msgpack_object instance. */ /* deserialized object is valid during the msgpack_zone instance alive. */ msgpack_zone_init(&mempool, 2048); msgpack_unpack(sbuf.data, sbuf.size, NULL, &mempool, &deserialized); /* print the deserialized object. */ msgpack_object_print(stdout, deserialized); puts(""); msgpack_zone_destroy(&mempool); msgpack_sbuffer_destroy(&sbuf); return 0; }
void unpack(char const* buf, size_t len) { /* buf is allocated by client. */ msgpack_unpacked result; size_t off = 0; msgpack_unpack_return ret; int i = 0; msgpack_unpacked_init(&result); ret = msgpack_unpack_next(&result, buf, len, &off); while (ret == MSGPACK_UNPACK_SUCCESS) { msgpack_object obj = result.data; /* Use obj. */ printf("Object no %d:\n", ++i); msgpack_object_print(stdout, obj); printf("\n"); /* If you want to allocate something on the zone, you can use zone. */ /* msgpack_zone* zone = result.zone; */ /* The lifetime of the obj and the zone, */ ret = msgpack_unpack_next(&result, buf, len, &off); } msgpack_unpacked_destroy(&result); if (ret == MSGPACK_UNPACK_CONTINUE) { printf("All msgpack_object in the buffer is consumed.\n"); } else if (ret == MSGPACK_UNPACK_PARSE_ERROR) { printf("The data in the buf is invalid format.\n"); } }
int handle_rep(zmq_msg_t * msg) { msgpack_object obj; msgpack_unpacked pack; char *errmsg; msgpack_unpacked_init(&pack); if (!msgpack_unpack_next (&pack, zmq_msg_data(msg), zmq_msg_size(msg), NULL)) { LOG_ERROR("handle_rep: msgpack_unpack_next failed\n"); return (-1); } obj = pack.data; if (obj.type != MSGPACK_OBJECT_ARRAY) { LOG_ERROR("handle_rep: not an array\n"); return (-2); } if (obj.via.array.size < 1) { LOG_ERROR("handle_rep: empty array\n"); return (-3); } if (obj.via.array.ptr[0].type != MSGPACK_OBJECT_BOOLEAN) { LOG_ERROR("handle_rep: first entry is nota boolean\n"); return (-4); } if (obj.via.array.ptr[0].via.boolean == false) { if (obj.via.array.size > 1 && obj.via.array.ptr[1].type == MSGPACK_OBJECT_RAW) { errmsg = raw_to_string(&(obj.via.array.ptr[1].via.raw)); if (errmsg) { LOG_SERV("%s\n", errmsg); free(errmsg); } } msgpack_unpacked_destroy(&pack); return (1); } if (obj.via.array.size > 1) { /* Technically speaking unspecified, but I feel lazy */ msgpack_object_print(stdout, obj.via.array.ptr[1]); printf("\n"); } return (0); }
void flb_pack_print(char *data, size_t bytes) { msgpack_unpacked result; size_t off = 0, cnt = 0; msgpack_unpacked_init(&result); while (msgpack_unpack_next(&result, data, bytes, &off)) { /* FIXME: lazy output */ printf("[%zd] ", cnt++); msgpack_object_print(stdout, result.data); printf("\n"); } msgpack_unpacked_destroy(&result); }
void rpc_call_handle_response(rpc_call_t *rpc, zmq_msg_t *response) { int rc; msgpack_unpacked response_msg; msgpack_unpacked_init(&response_msg); rc = msgpack_unpack_next(&response_msg, zmq_msg_data(response), zmq_msg_size(response), NULL); insist_return(rc, (void)(0), "Failed to unpack message '%.*s'", (int)zmq_msg_size(response), (char *)zmq_msg_data(response)); msgpack_object response_obj = response_msg.data; /* TODO(sissel): Call rpc->callback */ printf("rpc call response: "); msgpack_object_print(stdout, response_obj); printf("\n"); } /* rpc_service_handle */
int main(int argc, char **argv) { g_cmd = argv[0]; if (argc > 2) usage(); if (argc == 2) g_path = argv[1]; char buf[CHK_SIZE]; int fd; ssize_t rsize; msgpack_unpacker u; msgpack_unpacked obj; if (!strcmp(g_path, "-")) fd = 0; else if (strlen(g_path) > 0) fd = open(g_path, O_RDONLY); else fd = 0; if (fd < 0) goto readerr; msgpack_unpacker_init(&u, BUF_SIZE); msgpack_unpacked_init(&obj); while ((rsize = read(fd, buf, CHK_SIZE)) > 0) { msgpack_unpacker_reserve_buffer(&u, rsize); memcpy(msgpack_unpacker_buffer(&u), buf, rsize); msgpack_unpacker_buffer_consumed(&u, rsize); while (msgpack_unpacker_next(&u, &obj)) { msgpack_object_print(stdout, obj.data); putchar('\n'); } } msgpack_unpacker_destroy(&u); msgpack_unpacked_destroy(&obj); if (fd > 0) close(fd); return 0; readerr: fprintf(stderr, "file read error\n"); exit(1); }
int main(void) { msgpack_sbuffer* buffer = msgpack_sbuffer_new(); msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write); msgpack_pack_array(pk, 2); msgpack_pack_raw(pk, 5); msgpack_pack_raw_body(pk, "hello", 5); msgpack_pack_raw(pk, 11); msgpack_pack_raw_body(pk, "messagepack", 11); msgpack_unpacked msg; msgpack_unpacked_init(&msg); bool success = msgpack_unpack_next(&msg, buffer->data, buffer->size, NULL); msgpack_object obj = msg.data; msgpack_object_print(stdout, obj); printf("\n"); msgpack_sbuffer_free(buffer); msgpack_packer_free(pk); }
// what do we expect to get out of addins? // line_id is mandatory // trigger_level is optional // reset_level is optional // anything else is ignored. int parse_addins(msgpack_object * addins_obj, triggermemory_t * target) { msgpack_object_print(stdout, *addins_obj); if (addins_obj->type != MSGPACK_OBJECT_MAP) { zclock_log("expected a hash at the top level, got %d", addins_obj->type); return 0; } msgpack_object_map addins_hash = addins_obj->via.map; int i; int success = 0; for(i=0; i<addins_hash.size; i++) { msgpack_object key = addins_hash.ptr[i].key; msgpack_object obj = addins_hash.ptr[i].val; if (key.type != MSGPACK_OBJECT_RAW) { printf("key expected raw, got %d\n", key.type); return 0; } if(obj.type != MSGPACK_OBJECT_POSITIVE_INTEGER) { printf("obj expected positive integer, got %d\n", obj.type); continue; } int size = key.via.raw.size; const char * kstr = key.via.raw.ptr; int64_t o = obj.via.i64; if (strncmp(kstr, "line", size) == 0) { target->line_id = o; printf("found line\n"); success = 1; } else if (strncmp(kstr, "trigger_level", size) == 0) { target->trigger_level = o; } else if (strncmp(kstr, "reset_level", size) == 0) { target->reset_level = o; } } return success; }
void unpack(receiver* r) { /* buf is allocated by unpacker. */ msgpack_unpacker* unp = msgpack_unpacker_new(100); msgpack_unpacked result; msgpack_unpack_return ret; size_t recv_len; int recv_count = 0; int i = 0; msgpack_unpacked_init(&result); while (true) { recv_len = receiver_to_unpacker(r, EACH_RECV_SIZE, unp); if (recv_len == 0) break; // (reached end of input) printf("receive count: %d %zd bytes received.\n", recv_count++, recv_len); ret = msgpack_unpacker_next(unp, &result); while (ret == MSGPACK_UNPACK_SUCCESS) { msgpack_object obj = result.data; /* Use obj. */ printf("Object no %d:\n", ++i); msgpack_object_print(stdout, obj); printf("\n"); /* If you want to allocate something on the zone, you can use zone. */ /* msgpack_zone* zone = result.zone; */ /* The lifetime of the obj and the zone, */ ret = msgpack_unpacker_next(unp, &result); } if (ret == MSGPACK_UNPACK_PARSE_ERROR) { printf("The data in the buf is invalid format.\n"); msgpack_unpacked_destroy(&result); return; } } msgpack_unpacked_destroy(&result); msgpack_unpacker_free(unp); }
void monitor_method_recv(void) { fd_set rfds; int retval; static const struct timespec tv = {0, 0}; ssize_t size; char strname[100]; msgpack_unpacked result; msgpack_object *name, *data; FD_ZERO(&rfds); FD_SET(sock, &rfds); retval = pselect(sock + 1, &rfds, NULL, NULL, &tv, NULL); if(retval == 0) { /* no data */ return; } else if(retval == -1) { if(errno != EINTR) { err(EXIT_FAILURE, "method_receive pselect"); } return; } /* receive */ size = read(sock, msgpack_unpacker_buffer(up), msgpack_unpacker_buffer_capacity(up)); msgpack_unpacker_buffer_consumed(up, size); msgpack_unpacked_init(&result); /* stream unpacker */ while(msgpack_unpacker_next(up, &result)) { if(DEBUG_MON) { printf("[Monitor] "); msgpack_object_print(stdout, result.data); puts(""); } /* method: ["METHODNAME", [some, method, args]] */ if(result.data.type != MSGPACK_OBJECT_ARRAY || result.data.via.array.size <= 0) { errx(EXIT_FAILURE, "invalid method"); } /* method name */ name = result.data.via.array.ptr; /* method data */ if(result.data.via.array.size == 2) { data = result.data.via.array.ptr + 1; } else { data = NULL; } if(name->type != MSGPACK_OBJECT_RAW) { errx(EXIT_FAILURE, "invalid method"); } /* convert method name */ memcpy(strname, name->via.raw.ptr, name->via.raw.size); strname[name->via.raw.size] = '\0'; /* call method */ if(!strcmp(strname, "CONNECT")) { } else if(!strcmp(strname, "DISCONNECT")) { exec_finish = true; } else if(data == NULL) { errx(EXIT_FAILURE, "invalid method (no data?)"); } else if(!strcmp(strname, "KEYBOARD_SCANCODE")) { msgpack_object *obj; unsigned int i, n; unsigned char scancode; if(data->type == MSGPACK_OBJECT_ARRAY) { obj = data->via.array.ptr; n = data->via.array.size; } else if(data->type == MSGPACK_OBJECT_POSITIVE_INTEGER) { obj = data; n = 1; } else { n = 0; } for(i = 0; i < n; i++, obj++) { /* push FIFO */ scancode = obj->via.i64 & 0xff; fifo_scancode[fifo_scancode_end++] = scancode; if(fifo_scancode_end >= KMC_FIFO_SCANCODE_SIZE) { fifo_scancode_end = 0; } if(fifo_scancode_start == fifo_scancode_end) { fifo_scancode_start++; if(fifo_scancode_start >= KMC_FIFO_SCANCODE_SIZE) { fifo_scancode_start = 0; } } gci_nodes[GCI_KMC_NUM].int_dispatch = true; DEBUGMON("[Monitor] KEYBOARD_SCANCODE %x\n", scancode); } } else { errx(EXIT_FAILURE, "unknown method '%s'", strname); } } }
void msgpack_object_print(FILE* out, msgpack_object o) { switch(o.type) { case MSGPACK_OBJECT_NIL: fprintf(out, "nil"); break; case MSGPACK_OBJECT_BOOLEAN: fprintf(out, (o.via.boolean ? "true" : "false")); break; case MSGPACK_OBJECT_POSITIVE_INTEGER: fprintf(out, "%" "I64u", o.via.u64); break; case MSGPACK_OBJECT_NEGATIVE_INTEGER: fprintf(out, "%" "I64d", o.via.i64); break; case MSGPACK_OBJECT_DOUBLE: fprintf(out, "%f", o.via.dec); break; case MSGPACK_OBJECT_RAW: fprintf(out, "\""); fwrite(o.via.raw.ptr, o.via.raw.size, 1, out); fprintf(out, "\""); break; case MSGPACK_OBJECT_ARRAY: fprintf(out, "["); if(o.via.array.size != 0) { msgpack_object* p = o.via.array.ptr; msgpack_object_print(out, *p); ++p; msgpack_object* const pend = o.via.array.ptr + o.via.array.size; for(; p < pend; ++p) { fprintf(out, ", "); msgpack_object_print(out, *p); } } fprintf(out, "]"); break; case MSGPACK_OBJECT_MAP: fprintf(out, "{"); if(o.via.map.size != 0) { msgpack_object_kv* p = o.via.map.ptr; msgpack_object_print(out, p->key); fprintf(out, "=>"); msgpack_object_print(out, p->val); ++p; msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size; for(; p < pend; ++p) { fprintf(out, ", "); msgpack_object_print(out, p->key); fprintf(out, "=>"); msgpack_object_print(out, p->val); } } fprintf(out, "}"); break; default: // FIXME fprintf(out, "#<UNKNOWN %i %" "I64u" ">", o.type, o.via.u64); } }
void yar_debug_print_data(const yar_data *data, FILE *fp) /* {{{ */ { msgpack_object_print(fp? fp : stdout, *(msgpack_object *)data); }
/// output MessagePack object to stream in text format void log_text(FILE *stream, msgpack_object *msg) { // helper macro to access a specific array element #define MEMBER(n) msg->via.array.ptr[n] //msgpack_object_print(stream, *msg); // (print msgpack array, DEBUG only) // process ID if (MEMBER(3).type != MSGPACK_OBJECT_NIL) fprintf(stream, "PID 0x%X ", (unsigned int)MEMBER(3).via.u64); // indentation (DEBUG only) //fprintf(stream, "@%u ", (unsigned int)MEMBER(1).via.u64); // serial (DEBUG only) //fprintf(stream, "#%u ", (uint32_t)MEMBER(7).via.u64); // log level LOG_LEVEL level = MEMBER(0).via.u64; putc('[', stream); fputs(log_level_string(level), stream); fputs("] ", stream); double timestamp = MEMBER(2).via.f64; if (timestamp > 0) { // log timestamp (UTC seconds since the Epoch) char time_str[16]; format_timestamp(time_str, sizeof(time_str), "%H:%M:%S.qqq ", timestamp, true); fputs(time_str, stream); } // message origin (e.g. module) if (msgpack_object_str_fwrite(MEMBER(4).via.str, stream)) fputs(": ", stream); switch (level) { case LOG_LEVEL_SEPARATOR: // no message text, no attachment fputs("----------------------------------------", stream); break; case LOG_LEVEL_CHECKPOINT: fputs("Check point '", stream); msgpack_object_str_fwrite(MEMBER(5).via.str, stream); // msg = ID/name fputs("' #", stream); msgpack_object_print(stream, MEMBER(6)); // attachment = pass count break; case LOG_LEVEL_SCRATCHPAD: msgpack_object_str_fwrite(MEMBER(5).via.str, stream); // msg = key fputs(" <- ", stream); msgpack_object_str_fwrite(MEMBER(6).via.str, stream); // attachment = value break; default: msgpack_object_str_fwrite(MEMBER(5).via.str, stream); // the actual message // optional attachment (arbitrary MessagePack object) if (MEMBER(6).type != MSGPACK_OBJECT_NIL) { fputs("\n\t", stream); // new line and TAB msgpack_object_print(stream, MEMBER(6)); } } putc('\n', stream); fflush(stream); }
void rpc_handle(rpc_io *rpcio, zmq_msg_t *request) { /* Parse the msgpack */ zmq_msg_t response; int rc; msgpack_unpacked request_msg; msgpack_unpacked_init(&request_msg); rc = msgpack_unpack_next(&request_msg, zmq_msg_data(request), zmq_msg_size(request), NULL); insist_return(rc, (void)(0), "Failed to unpack message '%.*s'", zmq_msg_size(request), zmq_msg_data(request)); msgpack_object request_obj = request_msg.data; printf("Object: "); msgpack_object_print(stdout, request_obj); /*=> ["Hello", "MessagePack"] */ printf("\n"); /* Find the method name */ char *method = NULL; size_t method_len = -1; rc = obj_get(&request_obj, "request", MSGPACK_OBJECT_RAW, &method, &method_len); msgpack_sbuffer *buffer = msgpack_sbuffer_new(); msgpack_packer *response_msg = msgpack_packer_new(buffer, msgpack_sbuffer_write); printf("Method: %.*s\n", method_len, method); if (rc != 0) { fprintf(stderr, "Message had no 'request' field. Ignoring: "); msgpack_object_print(stderr, request_obj); msgpack_pack_map(response_msg, 2); msgpack_pack_string(response_msg, "error", -1); msgpack_pack_string(response_msg, "Message had no 'request' field", -1); msgpack_pack_string(response_msg, "request", -1); msgpack_pack_object(response_msg, request_obj); } else { /* Found request */ printf("The method is: '%.*s'\n", (int)method_len, method); //msgpack_pack_map(response_msg, 2); //msgpack_pack_string(response_msg, "results", 7); void *clock = zmq_stopwatch_start(); /* TODO(sissel): Use gperf here or allow methods to register themselves */ if (!strncmp("dance", method, method_len)) { api_request_dance(rpcio, &request_obj, response_msg); } else if (!strncmp("restart", method, method_len)) { api_request_restart(rpcio, &request_obj, response_msg); } else if (!strncmp("status", method, method_len)) { api_request_status(rpcio, &request_obj, response_msg); } else if (!strncmp("create", method, method_len)) { api_request_create(rpcio, &request_obj, response_msg); } else { fprintf(stderr, "Invalid request '%.*s' (unknown method): ", method_len, method); msgpack_object_print(stderr, request_obj); msgpack_pack_map(response_msg, 2); msgpack_pack_string(response_msg, "error", -1); msgpack_pack_string(response_msg, "No such method requested", -1); msgpack_pack_string(response_msg, "request", -1); msgpack_pack_object(response_msg, request_obj); } double duration = zmq_stopwatch_stop(clock) / 1000000.; printf("method '%.*s' took %lf seconds\n", (int)method_len, method); //msgpack_pack_string(response_msg, "stats", 5); //msgpack_pack_map(response_msg, 1), //msgpack_pack_string(response_msg, "duration", 8); //msgpack_pack_double(response_msg, duration); } zmq_msg_init_data(&response, buffer->data, buffer->size, free_msgpack_buffer, buffer); zmq_send(rpcio->socket, &response, 0); zmq_msg_close(&response); //msgpack_sbuffer_free(buffer); msgpack_packer_free(response_msg); msgpack_unpacked_destroy(&request_msg); } /* rpc_handle */
void msgpack_object_print(FILE* out, msgpack_object o) { switch(o.type) { case MSGPACK_OBJECT_NIL: fprintf(out, "nil"); break; case MSGPACK_OBJECT_BOOLEAN: fprintf(out, (o.via.boolean ? "true" : "false")); break; case MSGPACK_OBJECT_POSITIVE_INTEGER: #if defined(PRIu64) fprintf(out, "%" PRIu64, o.via.u64); #else if (o.via.u64 > ULONG_MAX) fprintf(out, "over 4294967295"); else fprintf(out, "%lu", (unsigned long)o.via.u64); #endif break; case MSGPACK_OBJECT_NEGATIVE_INTEGER: #if defined(PRIi64) fprintf(out, "%" PRIi64, o.via.i64); #else if (o.via.i64 > LONG_MAX) fprintf(out, "over +2147483647"); else if (o.via.i64 < LONG_MIN) fprintf(out, "under -2147483648"); else fprintf(out, "%ld", (signed long)o.via.i64); #endif break; case MSGPACK_OBJECT_FLOAT32: case MSGPACK_OBJECT_FLOAT64: fprintf(out, "%f", o.via.f64); break; case MSGPACK_OBJECT_STR: fprintf(out, "\""); fwrite(o.via.str.ptr, o.via.str.size, 1, out); fprintf(out, "\""); break; case MSGPACK_OBJECT_BIN: fprintf(out, "\""); msgpack_object_bin_print(out, o.via.bin.ptr, o.via.bin.size); fprintf(out, "\""); break; case MSGPACK_OBJECT_EXT: #if defined(PRIi8) fprintf(out, "(ext: %" PRIi8 ")", o.via.ext.type); #else fprintf(out, "(ext: %d)", (int)o.via.ext.type); #endif fprintf(out, "\""); msgpack_object_bin_print(out, o.via.ext.ptr, o.via.ext.size); fprintf(out, "\""); break; case MSGPACK_OBJECT_ARRAY: fprintf(out, "["); if(o.via.array.size != 0) { msgpack_object* p = o.via.array.ptr; msgpack_object* const pend = o.via.array.ptr + o.via.array.size; msgpack_object_print(out, *p); ++p; for(; p < pend; ++p) { fprintf(out, ", "); msgpack_object_print(out, *p); } } fprintf(out, "]"); break; case MSGPACK_OBJECT_MAP: fprintf(out, "{"); if(o.via.map.size != 0) { msgpack_object_kv* p = o.via.map.ptr; msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size; msgpack_object_print(out, p->key); fprintf(out, "=>"); msgpack_object_print(out, p->val); ++p; for(; p < pend; ++p) { fprintf(out, ", "); msgpack_object_print(out, p->key); fprintf(out, "=>"); msgpack_object_print(out, p->val); } } fprintf(out, "}"); break; default: // FIXME #if defined(PRIu64) fprintf(out, "#<UNKNOWN %i %" PRIu64 ">", o.type, o.via.u64); #else if (o.via.u64 > ULONG_MAX) fprintf(out, "#<UNKNOWN %i over 4294967295>", o.type); else fprintf(out, "#<UNKNOWN %i %lu>", o.type, (unsigned long)o.via.u64); #endif } }
void match(msgpack_object *obj, void *pattern) { void *ctx = objpath_start(pattern); msgpack_object *cur = obj; struct { msgpack_object_kv *kv; msgpack_object *el; } iter; objpath_value_t val; int opcode; while(objpath_next(ctx, &opcode, &val, (void **)&cur, (void **)&iter)) { switch(opcode) { case OBJPATH_KEY: if(cur->type != MSGPACK_OBJECT_MAP) goto fail; int klen = strlen(val.string); msgpack_object_kv* p = cur->via.map.ptr; msgpack_object_kv* const pend = cur->via.map.ptr + cur->via.map.size; for(; p < pend; ++p) { if(p->key.type == MSGPACK_OBJECT_RAW && p->key.via.raw.size == klen && !strncmp(p->key.via.raw.ptr, val.string, klen)) { cur = &p->val; goto success; } } goto fail; case OBJPATH_INDEX: if(cur->type != MSGPACK_OBJECT_ARRAY) goto fail; if(val.index < 0 || cur->via.array.size < val.index) goto fail; cur = &cur->via.array.ptr[val.index]; goto success; case OBJPATH_KEYS: if(cur->type != MSGPACK_OBJECT_MAP) goto fail; iter.kv = cur->via.map.ptr; case OBJPATH_NEXTKEY: if(iter.kv >= cur->via.map.ptr + cur->via.map.size) goto fail; cur = &iter.kv->key; goto success; case OBJPATH_VALUES: if(cur->type != MSGPACK_OBJECT_MAP) goto fail; iter.kv = cur->via.map.ptr; case OBJPATH_NEXTVALUE: if(iter.kv >= cur->via.map.ptr + cur->via.map.size) goto fail; cur = &iter.kv->val; goto success; case OBJPATH_ELEMENTS: if(cur->type != MSGPACK_OBJECT_ARRAY) goto fail; iter.el = cur->via.array.ptr; case OBJPATH_NEXTELEMENT: if(iter.el >= cur->via.array.ptr + cur->via.array.size) goto fail; cur = iter.el; goto success; case OBJPATH_FINAL: msgpack_object_print(stdout, *cur); puts(""); goto success; } success: continue; fail: cur = NULL; continue; } objpath_free(ctx); }
void trigger(void *cvoid, zctx_t * context, void * control) { triggerconfig_t * c = (triggerconfig_t*) cvoid; //set up msgpack stuff zclock_log("watch_port started!"); msgpack_zone mempool; msgpack_zone_init(&mempool, 2048); // TODO char * user_id = "17"; // TODO get broker in somehow char * broker = "tcp://au.ninjablocks.com:5773"; mdcli_t * client = mdcli_new(broker, 1); //VERBOSE triggermemory_t trigger_memory; msgpack_object * addins_obj = parse_msgpack(&mempool, c->addins); if(!parse_addins(addins_obj, &trigger_memory)) { //bad message zclock_log("bad trigger definition"); msgpack_object_print(stdout, *addins_obj); send_sync("bad trigger", control); return; } zclock_log("Creating trigger: target %s, rule_id %s, name %s", c->target_worker, c->rule_id, c->trigger_name); dump_trigger(&trigger_memory); triggerfunction trigger_func; if(!(trigger_func = find_trigger(c->channel, c->trigger_name))) { zclock_log("no trigger found for channel %s, trigger %s", c->channel, c->trigger_name); send_sync("no such trigger", control); return; } void * line = zsocket_new(context, ZMQ_SUB); // what line are we on? // this comes in the addins. char * linesocket = to_linesocket(trigger_memory.line_id); zclock_log("trigger is connecting to listen on %s", linesocket); zsocket_connect(line, linesocket); zsockopt_set_unsubscribe(line, ""); zsockopt_set_subscribe(line, "VALUE"); recv_sync("ping", control); send_sync("pong", control); zmq_pollitem_t items [] = { { line, 0, ZMQ_POLLIN, 0 }, { control, 0, ZMQ_POLLIN, 0 } }; while(1) { // listen on control and line zmq_poll (items, 2, -1); if (items[1].revents & ZMQ_POLLIN) { zclock_log("rule %s received message on control pipe", c->rule_id); // control message // really only expecting DESTROY zmsg_t * msg = zmsg_recv(control); char * str = zmsg_popstr(msg); zmsg_destroy(&msg); if (strcmp("Destroy", str) == 0) { zclock_log("rule %s will quit on request", c->rule_id); free(str); send_sync("ok", control); zclock_log("rule %s quitting on request", c->rule_id); break; } else { zclock_log("unexpected command %s for rule %s", str, c->rule_id); free(str); send_sync("ok", control); } } if (items[0].revents & ZMQ_POLLIN) { // serial update zmsg_t * msg = zmsg_recv(line); zframe_t * cmd = zmsg_pop(msg); if(zframe_streq(cmd, "CHANNEL_CHANGE")) { // TODO // must have been dormant to have gotten this char * new_channel = zmsg_popstr(msg); if(strcmp(c->channel, new_channel) == 0) { // oh, happy day! We're relevant again. // reactivate and start looking at reset levels. zclock_log("line %d: changed channel from %s to %s: trigger coming back to life", trigger_memory.line_id, c->channel, new_channel); zsockopt_set_subscribe(line, "VALUE"); zsockopt_set_unsubscribe(line, "CHANNEL_CHANGE"); } free(new_channel); } else if (zframe_streq(cmd, "VALUE")) { zframe_t * vframe = zmsg_pop(msg); int value; memcpy(&value, zframe_data(vframe), sizeof(int)); char * update_channel = zmsg_popstr(msg); if(strcmp(c->channel, update_channel) != 0) { // channel changed, go dormant // this is legit according to my tests at // https://gist.github.com/2042350 zclock_log("line %d: changed channel from %s to %s: trigger going dormant", trigger_memory.line_id, c->channel, update_channel); zsockopt_set_subscribe(line, "CHANNEL_CHANGE"); zsockopt_set_unsubscribe(line, "VALUE"); } else if(trigger_func(&trigger_memory, value)) { send_trigger(client, c->target_worker, c->rule_id, value, user_id); } free(update_channel); } else { // shouldn't ever happen. zclock_log("shouldn't have received command %s\n", zframe_strdup(cmd)); } zmsg_destroy(&msg); zframe_destroy(&cmd); } } msgpack_zone_destroy(&mempool); }