int result_cb(json_object *result, char *data, int error) { struct jsonrpc_pipe_cmd *cmd = (struct jsonrpc_pipe_cmd*)data; pv_spec_t *dst = cmd->cb_pv; pv_value_t val; const char* res = json_object_get_string(result); val.rs.s = (char*)res; val.rs.len = strlen(res); val.flags = PV_VAL_STR; dst->setf(0, &dst->pvp, (int)EQ_T, &val); int n; if (error) { n = route_get(&main_rt, cmd->err_route); } else { n = route_get(&main_rt, cmd->cb_route); } struct action *a = main_rt.rlist[n]; tmb.t_continue(cmd->t_hash, cmd->t_label, a); free_pipe_cmd(cmd); return 0; }
int send_pipe_cmd(cmd_type type, void* data) { char* name = ""; jsonrpc_pipe_cmd_t* cmd = NULL; cmd = create_pipe_cmd(); CHECK_MALLOC(cmd); cmd->type = type; switch(type) { case CMD_CONNECT: cmd->server = (jsonrpc_server_t*)data; name = "connect"; break; case CMD_RECONNECT: cmd->server = (jsonrpc_server_t*)data; name = "reconnect"; break; case CMD_CLOSE: cmd->server = (jsonrpc_server_t*)data; name = "close"; break; case CMD_UPDATE_SERVER_GROUP: cmd->new_grp = (jsonrpc_server_group_t*)data; name = "update"; break; case CMD_SEND: cmd->req_cmd = (jsonrpc_req_cmd_t*)data; name = "send"; break; default: ERR("Unknown command type %d", type); goto error; } DEBUG("sending %s command\n", name); if (write(cmd_pipe, &cmd, sizeof(cmd)) != sizeof(cmd)) { ERR("Failed to send '%s' cmd to io pipe: %s\n", name, strerror(errno)); goto error; } return 0; error: free_pipe_cmd(cmd); return -1; }
void cmd_pipe_cb(int fd, short event, void *arg) { struct jsonrpc_pipe_cmd *cmd; if (read(fd, &cmd, sizeof(cmd)) != sizeof(cmd)) { ERR("FATAL ERROR: failed to read from command pipe: %s\n", strerror(errno)); return; } switch(cmd->type) { case CMD_CLOSE: if(cmd->server) { wait_close(cmd->server); } goto end; break; case CMD_RECONNECT: if(cmd->server) { wait_reconnect(cmd->server); } goto end; break; case CMD_CONNECT: if(cmd->server) { bev_connect(cmd->server); } goto end; break; case CMD_UPDATE_SERVER_GROUP: if(cmd->new_grp) { jsonrpc_server_group_t* old_grp = *global_server_group; *global_server_group = cmd->new_grp; free_server_group(&old_grp); } lock_release(jsonrpc_server_group_lock); goto end; break; case CMD_SEND: break; default: ERR("Unrecognized pipe command: %d\n", cmd->type); goto end; break; } /* command is SEND */ jsonrpc_req_cmd_t* req_cmd = cmd->req_cmd; if(req_cmd == NULL) { ERR("req_cmd is NULL. Invalid send command\n"); goto end; } jsonrpc_request_t* req = NULL; req = create_request(req_cmd); if (!req || !req->payload) { json_t* error = internal_error(JRPC_ERR_REQ_BUILD, NULL); pv_value_t val; char* freeme = NULL; jsontoval(&val, &freeme, error); if(req_cmd->route.len <=0 && send_to_script(&val, req_cmd)<0) { ERR("Failed to build request (method: %.*s, params: %.*s)\n", STR(req_cmd->method), STR(req_cmd->params)); } if(freeme) free(freeme); if(error) json_decref(error); free_req_cmd(req_cmd); goto end; } int sent = jsonrpc_send(req_cmd->conn, req, req_cmd->notify_only); char* type; if (sent<0) { if (req_cmd->notify_only == false) { type = "Request"; } else { type = "Notification"; } WARN("%s could not be sent to connection group: %.*s\n", type, STR(req_cmd->conn)); fail_request(JRPC_ERR_SEND, req, "Failed to send request"); } end: free_pipe_cmd(cmd); }
void cmd_pipe_cb(int fd, short event, void *arg) { struct jsonrpc_pipe_cmd *cmd; char *ns = 0; size_t bytes; json_object *payload = NULL; jsonrpc_request_t *req = NULL; json_object *params; /* struct event *ev = (struct event*)arg; */ if (read(fd, &cmd, sizeof(cmd)) != sizeof(cmd)) { LM_ERR("failed to read from command pipe: %s\n", strerror(errno)); return; } cfg_update(); params = json_tokener_parse(cmd->params); if (cmd->notify_only) { payload = build_jsonrpc_notification(cmd->method, params); } else { req = build_jsonrpc_request(cmd->method, params, (char*)cmd, res_cb); if (req) payload = req->payload; } if (!payload) { LM_ERR("Failed to build jsonrpc_request_t (method: %s, params: %s)\n", cmd->method, cmd->params); goto error; } char *json = (char*)json_object_get_string(payload); bytes = netstring_encode_new(&ns, json, (size_t)strlen(json)); struct jsonrpc_server_group *g; int sent = 0; for (g = server_group; g != NULL; g = g->next_group) { struct jsonrpc_server *s, *first = NULL; for (s = g->next_server; s != first; s = s->next) { if (first == NULL) first = s; if (s->status == JSONRPC_SERVER_CONNECTED) { if (send(s->socket, ns, bytes, 0) == bytes) { sent = 1; break; } else { handle_server_failure(s); } } g->next_server = s->next; } if (sent) { break; } else { LM_WARN("Failed to send on priority group %d... proceeding to next priority group.\n", g->priority); } } if (sent && req) { int timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if (timerfd == -1) { LM_ERR("Could not create timerfd."); goto error; } req->timerfd = timerfd; struct itimerspec *itime = pkg_malloc(sizeof(struct itimerspec)); CHECK_MALLOC_VOID(itime); itime->it_interval.tv_sec = 0; itime->it_interval.tv_nsec = 0; itime->it_value.tv_sec = JSONRPC_TIMEOUT/1000; itime->it_value.tv_nsec = (JSONRPC_TIMEOUT % 1000) * 1000000; if (timerfd_settime(timerfd, 0, itime, NULL) == -1) { LM_ERR("Could not set timer."); pkg_free(itime); goto error; } pkg_free(itime); struct event *timer_ev = pkg_malloc(sizeof(struct event)); CHECK_MALLOC_VOID(timer_ev); event_set(timer_ev, timerfd, EV_READ, timeout_cb, req); if(event_add(timer_ev, NULL) == -1) { LM_ERR("event_add failed while setting request timer (%s).", strerror(errno)); goto error; } req->timer_ev = timer_ev; } else if (!sent) { LM_ERR("Request could not be sent... no more failover groups.\n"); if (req) { json_object *error = json_object_new_string("failure"); void_jsonrpc_request(req->id); req->cbfunc(error, req->cbdata, 1); } } pkg_free(ns); json_object_put(payload); if (cmd->notify_only) free_pipe_cmd(cmd); return; error: if(ns) pkg_free(ns); if(payload) json_object_put(payload); if (cmd->notify_only) free_pipe_cmd(cmd); return; }