static void jsonrpc_cleanup(struct jsonrpc *rpc) { stream_close(rpc->stream); rpc->stream = NULL; json_parser_abort(rpc->parser); rpc->parser = NULL; jsonrpc_msg_destroy(rpc->received); rpc->received = NULL; ofpbuf_list_delete(&rpc->output); rpc->backlog = 0; }
static struct ovsdb_schema * fetch_schema(struct jsonrpc *rpc, const char *database) { struct jsonrpc_msg *request, *reply; struct ovsdb_schema *schema; request = jsonrpc_create_request("get_schema", json_array_create_1( json_string_create(database)), NULL); check_txn(jsonrpc_transact_block(rpc, request, &reply), &reply); check_ovsdb_error(ovsdb_schema_from_json(reply->result, &schema)); jsonrpc_msg_destroy(reply); return schema; }
/* Schedules 'msg' to be sent on 'rpc' and returns 'rpc''s status (as with * jsonrpc_get_status()). * * If 'msg' cannot be sent immediately, it is appended to a buffer. The caller * is responsible for ensuring that the amount of buffered data is somehow * limited. (jsonrpc_get_backlog() returns the amount of data currently * buffered in 'rpc'.) * * Always takes ownership of 'msg', regardless of success. */ int jsonrpc_send(struct jsonrpc *rpc, struct jsonrpc_msg *msg) { struct ofpbuf *buf; struct json *json; size_t length; char *s; if (rpc->status) { jsonrpc_msg_destroy(msg); return rpc->status; } jsonrpc_log_msg(rpc, "send", msg); json = jsonrpc_msg_to_json(msg); s = json_to_string(json, 0); length = strlen(s); json_destroy(json); buf = xmalloc(sizeof *buf); ofpbuf_use(buf, s, length); buf->size = length; list_push_back(&rpc->output, &buf->list_node); rpc->output_count++; rpc->backlog += length; if (rpc->output_count >= 50) { VLOG_INFO_RL(&rl, "excessive sending backlog, jsonrpc: %s, num of" " msgs: %"PRIuSIZE", backlog: %"PRIuSIZE".", rpc->name, rpc->output_count, rpc->backlog); } if (rpc->backlog == length) { jsonrpc_run(rpc); } return rpc->status; }
struct jsonrpc_msg * jsonrpc_session_recv(struct jsonrpc_session *s) { if (s->rpc) { unsigned int received_bytes; struct jsonrpc_msg *msg; received_bytes = jsonrpc_get_received_bytes(s->rpc); jsonrpc_recv(s->rpc, &msg); if (received_bytes != jsonrpc_get_received_bytes(s->rpc)) { /* Data was successfully received. * * Previously we only counted receiving a full message as activity, * but with large messages or a slow connection that policy could * time out the session mid-message. */ reconnect_activity(s->reconnect, time_msec()); } if (msg) { if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, "echo")) { /* Echo request. Send reply. */ struct jsonrpc_msg *reply; reply = jsonrpc_create_reply(json_clone(msg->params), msg->id); jsonrpc_session_send(s, reply); } else if (msg->type == JSONRPC_REPLY && msg->id && msg->id->type == JSON_STRING && !strcmp(msg->id->u.string, "echo")) { /* It's a reply to our echo request. Suppress it. */ } else { return msg; } jsonrpc_msg_destroy(msg); } } return NULL; }
static void do_listen(struct ovs_cmdl_context *ctx) { struct pstream *pstream; struct jsonrpc **rpcs; size_t n_rpcs, allocated_rpcs; bool done; int error; error = jsonrpc_pstream_open(ctx->argv[1], &pstream, DSCP_DEFAULT); if (error) { ovs_fatal(error, "could not listen on \"%s\"", ctx->argv[1]); } daemonize(); rpcs = NULL; n_rpcs = allocated_rpcs = 0; done = false; for (;;) { struct stream *stream; size_t i; /* Accept new connections. */ error = pstream_accept(pstream, &stream); if (!error) { if (n_rpcs >= allocated_rpcs) { rpcs = x2nrealloc(rpcs, &allocated_rpcs, sizeof *rpcs); } rpcs[n_rpcs++] = jsonrpc_open(stream); } else if (error != EAGAIN) { ovs_fatal(error, "pstream_accept failed"); } /* Service existing connections. */ for (i = 0; i < n_rpcs; ) { struct jsonrpc *rpc = rpcs[i]; struct jsonrpc_msg *msg; jsonrpc_run(rpc); if (!jsonrpc_get_backlog(rpc)) { error = jsonrpc_recv(rpc, &msg); if (!error) { error = handle_rpc(rpc, msg, &done); jsonrpc_msg_destroy(msg); } else if (error == EAGAIN) { error = 0; } } if (!error) { error = jsonrpc_get_status(rpc); } if (error) { jsonrpc_close(rpc); ovs_error(error, "connection closed"); memmove(&rpcs[i], &rpcs[i + 1], (n_rpcs - i - 1) * sizeof *rpcs); n_rpcs--; } else { i++; } } /* Wait for something to do. */ if (done && !n_rpcs) { break; } pstream_wait(pstream); for (i = 0; i < n_rpcs; i++) { struct jsonrpc *rpc = rpcs[i]; jsonrpc_wait(rpc); if (!jsonrpc_get_backlog(rpc)) { jsonrpc_recv_wait(rpc); } } poll_block(); } free(rpcs); pstream_close(pstream); }