static int handle_rpc(struct jsonrpc *rpc, struct jsonrpc_msg *msg, bool *done) { if (msg->type == JSONRPC_REQUEST) { struct jsonrpc_msg *reply = NULL; if (!strcmp(msg->method, "echo")) { reply = jsonrpc_create_reply(json_clone(msg->params), msg->id); } else { struct json *error = json_object_create(); json_object_put_string(error, "error", "unknown method"); reply = jsonrpc_create_error(error, msg->id); ovs_error(0, "unknown request %s", msg->method); } jsonrpc_send(rpc, reply); return 0; } else if (msg->type == JSONRPC_NOTIFY) { if (!strcmp(msg->method, "shutdown")) { *done = true; return 0; } else { ovs_error(0, "unknown notification %s", msg->method); return ENOTTY; } } else { ovs_error(0, "unsolicited JSON-RPC reply or error"); return EPROTO; } }
/* Always takes ownership of 'msg', regardless of success. */ int jsonrpc_session_send(struct jsonrpc_session *s, struct jsonrpc_msg *msg) { if (s->rpc) { return jsonrpc_send(s->rpc, msg); } else { jsonrpc_msg_destroy(msg); return ENOTCONN; } }
/* Sends 'msg' on 'rpc' and waits for it to be successfully queued to the * underlying stream. Returns 0 if 'msg' was sent successfully, otherwise a * status value (see jsonrpc_get_status()). * * Always takes ownership of 'msg', regardless of success. */ int jsonrpc_send_block(struct jsonrpc *rpc, struct jsonrpc_msg *msg) { int error; fatal_signal_run(); error = jsonrpc_send(rpc, msg); if (error) { return error; } for (;;) { jsonrpc_run(rpc); if (list_is_empty(&rpc->output) || rpc->status) { return rpc->status; } jsonrpc_wait(rpc); poll_block(); } }
static void do_request(struct ovs_cmdl_context *ctx) { struct jsonrpc_msg *msg; struct jsonrpc *rpc; struct json *params; struct stream *stream; const char *method; char *string; int error; method = ctx->argv[2]; params = parse_json(ctx->argv[3]); msg = jsonrpc_create_request(method, params, NULL); string = jsonrpc_msg_is_valid(msg); if (string) { ovs_fatal(0, "not a valid JSON-RPC request: %s", string); } error = stream_open_block(jsonrpc_stream_open(ctx->argv[1], &stream, DSCP_DEFAULT), &stream); if (error) { ovs_fatal(error, "could not open \"%s\"", ctx->argv[1]); } rpc = jsonrpc_open(stream); error = jsonrpc_send(rpc, msg); if (error) { ovs_fatal(error, "could not send request"); } error = jsonrpc_recv_block(rpc, &msg); if (error) { ovs_fatal(error, "error waiting for reply"); } print_and_free_json(jsonrpc_msg_to_json(msg)); jsonrpc_close(rpc); }
void retry_cb(int fd, short event, void* arg) { if(!arg) return; jsonrpc_request_t* req = (jsonrpc_request_t*)arg; if(!(req->cmd)) { ERR("request has no cmd\n"); goto error; } DEBUG("retrying request: id=%d\n", req->id); if(jsonrpc_send(req->cmd->conn, req, 0)<0) { goto error; } CHECK_AND_FREE_EV(req->retry_ev); return; error: fail_request(JRPC_ERR_SEND, req, "Retry failed to send request"); }
void jsonrpc_session_run(struct jsonrpc_session *s) { if (s->pstream) { struct stream *stream; int error; error = pstream_accept(s->pstream, &stream); if (!error) { if (s->rpc || s->stream) { VLOG_INFO_RL(&rl, "%s: new connection replacing active connection", reconnect_get_name(s->reconnect)); jsonrpc_session_disconnect(s); } reconnect_connected(s->reconnect, time_msec()); s->rpc = jsonrpc_open(stream); } else if (error != EAGAIN) { reconnect_listen_error(s->reconnect, time_msec(), error); pstream_close(s->pstream); s->pstream = NULL; } } if (s->rpc) { size_t backlog; int error; backlog = jsonrpc_get_backlog(s->rpc); jsonrpc_run(s->rpc); if (jsonrpc_get_backlog(s->rpc) < backlog) { /* Data previously caught in a queue was successfully sent (or * there's an error, which we'll catch below.) * * We don't count data that is successfully sent immediately as * activity, because there's a lot of queuing downstream from us, * which means that we can push a lot of data into a connection * that has stalled and won't ever recover. */ reconnect_activity(s->reconnect, time_msec()); } error = jsonrpc_get_status(s->rpc); if (error) { reconnect_disconnected(s->reconnect, time_msec(), error); jsonrpc_session_disconnect(s); s->last_error = error; } } else if (s->stream) { int error; stream_run(s->stream); error = stream_connect(s->stream); if (!error) { reconnect_connected(s->reconnect, time_msec()); s->rpc = jsonrpc_open(s->stream); s->stream = NULL; } else if (error != EAGAIN) { reconnect_connect_failed(s->reconnect, time_msec(), error); stream_close(s->stream); s->stream = NULL; s->last_error = error; } } switch (reconnect_run(s->reconnect, time_msec())) { case RECONNECT_CONNECT: jsonrpc_session_connect(s); break; case RECONNECT_DISCONNECT: reconnect_disconnected(s->reconnect, time_msec(), 0); jsonrpc_session_disconnect(s); break; case RECONNECT_PROBE: if (s->rpc) { struct json *params; struct jsonrpc_msg *request; params = json_array_create_empty(); request = jsonrpc_create_request("echo", params, NULL); json_destroy(request->id); request->id = json_string_create("echo"); jsonrpc_send(s->rpc, request); } break; } }
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 jsonrpc_session_run(struct jsonrpc_session *s) { if (s->pstream) { struct stream *stream; int error; error = pstream_accept(s->pstream, &stream); if (!error) { if (s->rpc || s->stream) { VLOG_INFO_RL(&rl, "%s: new connection replacing active connection", reconnect_get_name(s->reconnect)); jsonrpc_session_disconnect(s); } reconnect_connected(s->reconnect, time_msec()); s->rpc = jsonrpc_open(stream); } else if (error != EAGAIN) { reconnect_listen_error(s->reconnect, time_msec(), error); pstream_close(s->pstream); s->pstream = NULL; } } if (s->rpc) { int error; jsonrpc_run(s->rpc); error = jsonrpc_get_status(s->rpc); if (error) { reconnect_disconnected(s->reconnect, time_msec(), error); jsonrpc_session_disconnect(s); } } else if (s->stream) { int error; stream_run(s->stream); error = stream_connect(s->stream); if (!error) { reconnect_connected(s->reconnect, time_msec()); s->rpc = jsonrpc_open(s->stream); s->stream = NULL; } else if (error != EAGAIN) { reconnect_connect_failed(s->reconnect, time_msec(), error); stream_close(s->stream); s->stream = NULL; } } switch (reconnect_run(s->reconnect, time_msec())) { case RECONNECT_CONNECT: jsonrpc_session_connect(s); break; case RECONNECT_DISCONNECT: reconnect_disconnected(s->reconnect, time_msec(), 0); jsonrpc_session_disconnect(s); break; case RECONNECT_PROBE: if (s->rpc) { struct json *params; struct jsonrpc_msg *request; params = json_array_create_empty(); request = jsonrpc_create_request("echo", params, NULL); json_destroy(request->id); request->id = json_string_create("echo"); jsonrpc_send(s->rpc, request); } break; } }