void api_respond_error(msgpack_object *request_obj, msgpack_packer *response_msg, const char *error) { msgpack_pack_map(response_msg, 2); msgpack_pack_string(response_msg, "error", -1); msgpack_pack_string(response_msg, error, -1); msgpack_pack_string(response_msg, "request", -1); msgpack_pack_object(response_msg, *request_obj); }
/** * plume_req_init_route - Initialize a route request, additionally packing our * peer's handle and an opcode for our peer. */ void plume_req_init_route(struct yakyak *yy, struct plume_client *client, char *op, char *peer_handle, unsigned n) { plume_req_init(yy, client, "route", n + 2); msgpack_pack_string(yy->pk, peer_handle); msgpack_pack_string(yy->pk, op); }
void api_request_dance(rpc_io *rpcio, msgpack_object *request, msgpack_packer *response_msg) { printf("Dance dance dance. La la la.\n"); msgpack_pack_map(response_msg, 1); msgpack_pack_string(response_msg, "danced", 6); msgpack_pack_true(response_msg); }
void rpc_m_list_methods(void *context, msgpack_object *request, msgpack_packer *result, msgpack_packer *error, void *data) { //msgpack_pack_array(result, 1); msgpack_pack_string(result, "danced", 6); msgpack_pack_nil(error); } /* rpc_m_list_methods */
/** * plume_req_route_connect - Send a peer our calling card. */ int plume_req_route_connect(struct plume_client *client, char *peer_handle) { struct yakyak yy; plume_req_init_route(&yy, client, "connect", peer_handle, 1); msgpack_pack_string(yy.pk, "callingcard"); return plume_send(client, yakyak_data(&yy), yakyak_size(&yy)); }
void dump_oid_info(msgpack_packer *pk, struct oid_info *oi) { #define DUMPi(field) msgpack_pack_named_int(pk, #field, oi->field) msgpack_pack_map(pk, 6); DUMPi(sid); DUMPi(cid); DUMPi(fd); DUMPi(max_repetitions); msgpack_pack_string(pk, "oid"); msgpack_pack_oid(pk, oi->oid); msgpack_pack_string(pk, "value"); if (!oi->value.buf) msgpack_pack_nil(pk); else msgpack_pack_ber(pk, oi->value); #undef DUMPi }
/** * plume_req_init - Initialize a yakyak, then pack an opcode and our cert. */ void plume_req_init(struct yakyak *yy, struct plume_client *client, char *op, unsigned n) { yakyak_init(yy, 2); msgpack_pack_string(yy->pk, op); msgpack_pack_array(yy->pk, n + 1); msgpack_pack_raw(yy->pk, client->pc_cert_size); msgpack_pack_raw_body(yy->pk, client->pc_cert, client->pc_cert_size); }
void publish_output(process_t *process, struct proc_data *procdata, const char *ioname, const char *data, ssize_t length) { /* TODO(sissel): move this to a separate file for 'event' streaming */ zmq_msg_t event; int rc; size_t msgsize; program_t *program = pn_proc_program(process); procnanny_t *pn = program->data; fprintf(stdout, "%s[%d]: (%d bytes) %.*s\n", pn_proc_program(process)->name, pn_proc_instance(process), length, length, data); /* Fields: * - data (the string read) * - program name * - process instance * - stdout or stderr */ msgpack_sbuffer *buffer = msgpack_sbuffer_new(); msgpack_packer *output_msg = msgpack_packer_new(buffer, msgpack_sbuffer_write); msgpack_pack_map(output_msg, 5); /* "event" => "data" */ msgpack_pack_string(output_msg, "event", -1); msgpack_pack_string(output_msg, "data", -1); msgpack_pack_string(output_msg, "program", -1); msgpack_pack_string(output_msg, program->name, program->name_len); msgpack_pack_string(output_msg, "instance", -1); msgpack_pack_int(output_msg, process->instance); msgpack_pack_string(output_msg, "source", -1); msgpack_pack_string(output_msg, ioname, -1); msgpack_pack_string(output_msg, "data", -1); msgpack_pack_string(output_msg, data, length); zmq_msg_init_data(&event, buffer->data, buffer->size, free_msgpack_buffer, buffer); zmq_send(pn->eventsocket, &event, 0); zmq_msg_close(&event); msgpack_packer_free(output_msg); } /* publish_output */
rpc_call_t *rpc_call_new(void *zmq, struct ev_loop *ev, const char *address, const char *method) { rpc_call_t *rpc = calloc(1, sizeof(rpc_call_t)); rpc->zmq = zmq; rpc->ev = ev; rpc->address = address; rpc->pack_buffer = msgpack_sbuffer_new(); rpc->request = msgpack_packer_new(rpc->pack_buffer, msgpack_sbuffer_write); msgpack_pack_map(rpc->request, 2); /* method and args */ msgpack_pack_string(rpc->request, "method", 6); msgpack_pack_string(rpc->request, method, strlen(method)); msgpack_pack_string(rpc->request, "args", 4); /* The rest of the packing is up to the invoker of the rpc call. * Add whatever arguments are necessary later to rpc->request */ printf("Created new rpc call object targeting %s method %s\n", address, method); return rpc; } /* rpc_call_new */
int msgpack_pack_vstringf(msgpack_packer *pk, char const *fmt, va_list ap) { char buf[1024]; vsnprintf(buf, sizeof buf, fmt, ap); return msgpack_pack_string(pk, buf); }
void api_request_status(rpc_io *rpcio, msgpack_object *request_obj, msgpack_packer *response_msg) { int rc; char *program_name = NULL; size_t program_len = 0; rc = obj_get(request_obj, "program", MSGPACK_OBJECT_RAW, &program_name, &program_len); /* A missing 'program' field is OK. It means we want all programs */ msgpack_pack_map(response_msg, 1); msgpack_pack_string(response_msg, "programs", -1); /* programs is a map of: * programname => { * command: "string", * args: "string", * uid: uid, * gid: gid, * nice: nice, * ionice: ionice, * is_running: boolean * instances: { * pid: ... * state: ... * admin_state: ... * start: ... * duration: ... * } * } */ msgpack_pack_map(response_msg, rpcio->procnanny->programs_len); pn_prog_each(rpcio->procnanny, i, program, { if (program_name != NULL && strncmp(program->name, program_name, program_len)) { continue; } msgpack_pack_string(response_msg, program->name, program->name_len); msgpack_pack_map(response_msg, 8); /* 8 fields */ msgpack_pack_string(response_msg, "command", -1); msgpack_pack_string(response_msg, program->command, program->command_len); msgpack_pack_string(response_msg, "args", -1); msgpack_pack_array(response_msg, program->args_len); int argind = 0; for (argind = 0; argind < program->args_len; argind++) { msgpack_pack_string(response_msg, program->args[argind], -1); } msgpack_pack_string(response_msg, "uid", -1); msgpack_pack_uint32(response_msg, program->uid); msgpack_pack_string(response_msg, "gid", -1); msgpack_pack_uint32(response_msg, program->gid); msgpack_pack_string(response_msg, "nice", -1); msgpack_pack_int32(response_msg, program->nice); msgpack_pack_string(response_msg, "ionice", -1); msgpack_pack_int32(response_msg, program->ionice); msgpack_pack_string(response_msg, "active", -1); msgpack_pack_true(response_msg); msgpack_pack_string(response_msg, "instances", -1); msgpack_pack_map(response_msg, program->nprocs); pn_prog_proc_each(program, instance, process, { msgpack_pack_uint32(response_msg, instance); msgpack_pack_map(response_msg, 5); msgpack_pack_string(response_msg, "pid", -1); msgpack_pack_uint32(response_msg, process->pid); msgpack_pack_string(response_msg, "state", -1); switch (process->state) { case PROCESS_STATE_STARTING: msgpack_pack_string(response_msg, "starting", -1); break; case PROCESS_STATE_RUNNING: msgpack_pack_string(response_msg, "running", -1); break; case PROCESS_STATE_STOPPING: msgpack_pack_string(response_msg, "stopping", -1); break; case PROCESS_STATE_EXITED: msgpack_pack_string(response_msg, "exited", -1); break; case PROCESS_STATE_BACKOFF: msgpack_pack_string(response_msg, "backoff", -1); break; case PROCESS_STATE_NEW: msgpack_pack_string(response_msg, "new", -1); break; default: msgpack_pack_string(response_msg, "unknown", -1); break; } msgpack_pack_string(response_msg, "exitcode", -1); msgpack_pack_uint8(response_msg, process->exit_status); msgpack_pack_string(response_msg, "exitsignal", -1); msgpack_pack_uint8(response_msg, process->exit_signal); msgpack_pack_string(response_msg, "admin_state", -1); switch (process->admin_state) { case ADMIN_STATE_DOWN: msgpack_pack_string(response_msg, "down", -1); break; case ADMIN_STATE_UP: msgpack_pack_string(response_msg, "up", -1); break; default: msgpack_pack_string(response_msg, "unknown", -1); break; } }) });
void publish_proc_event(process_t *process, const char *name) { /* TODO(sissel): move this to a separate file for 'event' streaming */ zmq_msg_t event; int rc; size_t msgsize; program_t *program = pn_proc_program(process); procnanny_t *pn = program->data; /* Fields: * - program name * - process instance * - exit status * - duration ? */ msgpack_sbuffer *buffer = msgpack_sbuffer_new(); msgpack_packer *output_msg = msgpack_packer_new(buffer, msgpack_sbuffer_write); msgpack_pack_map(output_msg, 5); msgpack_pack_string(output_msg, "event", -1); msgpack_pack_string(output_msg, name, -1); msgpack_pack_string(output_msg, "program", -1); msgpack_pack_string(output_msg, program->name, program->name_len); msgpack_pack_string(output_msg, "instance", -1); msgpack_pack_int(output_msg, process->instance); msgpack_pack_string(output_msg, "state", -1); switch (process->state) { case PROCESS_STATE_STARTING: msgpack_pack_string(output_msg, "starting", -1); break; case PROCESS_STATE_RUNNING: msgpack_pack_string(output_msg, "running", -1); break; case PROCESS_STATE_STOPPING: msgpack_pack_string(output_msg, "stopping", -1); break; case PROCESS_STATE_EXITED: msgpack_pack_string(output_msg, "exited", -1); break; case PROCESS_STATE_BACKOFF: msgpack_pack_string(output_msg, "backoff", -1); break; case PROCESS_STATE_NEW: msgpack_pack_string(output_msg, "new", -1); break; default: msgpack_pack_string(output_msg, "unknown", -1); break; } if (process->state == PROCESS_STATE_EXITED || process->state == PROCESS_STATE_BACKOFF) { msgpack_pack_string(output_msg, "code", -1); msgpack_pack_nil(output_msg); } else if (process->exit_signal == 0) { msgpack_pack_string(output_msg, "code", -1); msgpack_pack_int(output_msg, process->exit_status); } else { msgpack_pack_string(output_msg, "signal", -1); /* lol. */ switch (process->exit_signal) { case SIGHUP: msgpack_pack_string(output_msg, "HUP", 3); break; case SIGINT: msgpack_pack_string(output_msg, "INT", 3); break; case SIGQUIT: msgpack_pack_string(output_msg, "QUIT", 4); break; case SIGILL: msgpack_pack_string(output_msg, "ILL", 3); break; case SIGTRAP: msgpack_pack_string(output_msg, "TRAP", 4); break; case SIGABRT: msgpack_pack_string(output_msg, "ABRT", 4); break; case SIGBUS: msgpack_pack_string(output_msg, "BUS", 3); break; case SIGFPE: msgpack_pack_string(output_msg, "FPE", 3); break; case SIGKILL: msgpack_pack_string(output_msg, "KILL", 4); break; case SIGUSR1: msgpack_pack_string(output_msg, "USR1", 4); break; case SIGSEGV: msgpack_pack_string(output_msg, "SEGV", 4); break; case SIGUSR2: msgpack_pack_string(output_msg, "USR2", 4); break; case SIGPIPE: msgpack_pack_string(output_msg, "PIPE", 4); break; case SIGALRM: msgpack_pack_string(output_msg, "ALRM", 4); break; case SIGTERM: msgpack_pack_string(output_msg, "TERM", 4); break; case SIGSTKFLT: msgpack_pack_string(output_msg, "STKFLT", 6); break; case SIGCHLD: msgpack_pack_string(output_msg, "CHLD", 4); break; case SIGCONT: msgpack_pack_string(output_msg, "CONT", 4); break; case SIGSTOP: msgpack_pack_string(output_msg, "STOP", 4); break; case SIGTSTP: msgpack_pack_string(output_msg, "TSTP", 4); break; case SIGTTIN: msgpack_pack_string(output_msg, "TTIN", 4); break; case SIGTTOU: msgpack_pack_string(output_msg, "TTOU", 4); break; case SIGURG: msgpack_pack_string(output_msg, "URG", 3); break; case SIGXCPU: msgpack_pack_string(output_msg, "XCPU", 4); break; case SIGXFSZ: msgpack_pack_string(output_msg, "XFSZ", 4); break; case SIGVTALRM: msgpack_pack_string(output_msg, "VTALRM", 5); break; case SIGPROF: msgpack_pack_string(output_msg, "PROF", 4); break; case SIGWINCH: msgpack_pack_string(output_msg, "WINCH", 5); break; case SIGPOLL: msgpack_pack_string(output_msg, "POLL", 4); break; case SIGPWR: msgpack_pack_string(output_msg, "PWR", 3); break; case SIGSYS: msgpack_pack_string(output_msg, "SYS", 3); break; default: msgpack_pack_string(output_msg, "unknown", -1); break; } /* switch process->exit_signal */ } /* if process was killed by a signal */ zmq_msg_init_data(&event, buffer->data, buffer->size, free_msgpack_buffer, buffer); zmq_send(pn->eventsocket, &event, 0); zmq_msg_close(&event); msgpack_packer_free(output_msg); } /* publish_output */
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 rpc_service_handle(rpc_service_t *service, 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'", (int)zmq_msg_size(request), (char *)zmq_msg_data(request)); msgpack_object request_obj = request_msg.data; /* Find the method name */ char *method = NULL; size_t method_len = -1; rc = obj_get(&request_obj, "method", MSGPACK_OBJECT_RAW, &method, &method_len); msgpack_sbuffer *response_buffer = msgpack_sbuffer_new(); msgpack_sbuffer *result_buffer = msgpack_sbuffer_new(); msgpack_sbuffer *error_buffer = msgpack_sbuffer_new(); msgpack_packer *response_msg = msgpack_packer_new(response_buffer, msgpack_sbuffer_write); msgpack_packer *result = msgpack_packer_new(result_buffer, msgpack_sbuffer_write); msgpack_packer *error = msgpack_packer_new(error_buffer, msgpack_sbuffer_write); //printf("Method: %.*s\n", method_len, method); void *clock = zmq_stopwatch_start(); double duration; if (rc != 0) { /* method not found */ msgpack_pack_nil(result); /* result is nil on error */ msgpack_pack_map(error, 2); msgpack_pack_string(error, "error", -1); msgpack_pack_string(error, "Message had no 'method' field", -1); msgpack_pack_string(error, "request", -1); msgpack_pack_object(error, request_obj); } else { /* valid method, keep going */ //printf("The method is: '%.*s'\n", (int)method_len, method); rpc_name name; name.name = method; name.len = method_len; rpc_method *rpcmethod = g_tree_lookup(service->methods, &name); /* if we found a valid rpc method and the args check passed ... */ if (rpcmethod != NULL) { /* the callback is responsible for filling in the 'result' and 'error' * objects. */ rpcmethod->callback(NULL, &request_obj, result, error, rpcmethod->data); } else { msgpack_pack_nil(result); /* result is nil on error */ /* TODO(sissel): allow methods to register themselves */ //fprintf(stderr, "Invalid request '%.*s' (unknown method): ", //method_len, method); //msgpack_object_print(stderr, request_obj); //fprintf(stderr, "\n"); msgpack_pack_map(error, 2); msgpack_pack_string(error, "error", -1); msgpack_pack_string(error, "No such method requested", -1); msgpack_pack_string(error, "request", -1); msgpack_pack_object(error, request_obj); } } /* valid/invalid method handling */ duration = zmq_stopwatch_stop(clock) / 1000000.; //printf("method '%.*s' took %lf seconds\n", (int)method_len, method); msgpack_unpacked result_unpacked; msgpack_unpacked error_unpacked; msgpack_unpacked response_unpacked; msgpack_unpacked_init(&result_unpacked); msgpack_unpacked_init(&error_unpacked); msgpack_unpacked_init(&response_unpacked); /* TODO(sissel): If this unpack test fails, we should return an error to the calling * client indicating that some internal error has occurred */ //fprintf(stderr, "Result payload: '%.*s'\n", result_buffer->size, //result_buffer->data); rc = msgpack_unpack_next(&result_unpacked, result_buffer->data, result_buffer->size, NULL); insist(rc == true, "msgpack_unpack_next failed on 'result' buffer" " of request '%.*s'", (int)method_len, method); rc = msgpack_unpack_next(&error_unpacked, error_buffer->data, error_buffer->size, NULL); insist(rc == true, "msgpack_unpack_next failed on 'error' buffer" " of request '%.*s'", (int)method_len, method); msgpack_pack_map(response_msg, 3); /* result, error, duration */ msgpack_pack_string(response_msg, "result", 6); msgpack_pack_object(response_msg, result_unpacked.data); msgpack_pack_string(response_msg, "error", 5); msgpack_pack_object(response_msg, error_unpacked.data); msgpack_pack_string(response_msg, "duration", 8); msgpack_pack_double(response_msg, duration); rc = msgpack_unpack_next(&response_unpacked, response_buffer->data, response_buffer->size, NULL); insist(rc == true, "msgpack_unpack_next failed on full response buffer" " of request '%.*s'", (int)method_len, method); //printf("request: "); //msgpack_object_print(stdout, request_obj); //printf("\n"); //printf("response: "); //msgpack_object_print(stdout, response_unpacked.data); //printf("\n"); zmq_msg_init_data(&response, response_buffer->data, response_buffer->size, free_msgpack_buffer, response_buffer); zmq_send(service->socket, &response, 0); zmq_msg_close(&response); msgpack_packer_free(error); msgpack_packer_free(result); msgpack_sbuffer_free(error_buffer); msgpack_sbuffer_free(result_buffer); msgpack_packer_free(response_msg); msgpack_unpacked_destroy(&request_msg); } /* rpc_service_handle */