static struct ovsdb_error * parse_body(struct ovsdb_log *file, off_t offset, unsigned long int length, uint8_t sha1[SHA1_DIGEST_SIZE], struct json **jsonp) { struct json_parser *parser; struct sha1_ctx ctx; sha1_init(&ctx); parser = json_parser_create(JSPF_TRAILER); while (length > 0) { char input[BUFSIZ]; int chunk; chunk = MIN(length, sizeof input); if (fread(input, 1, chunk, file->stream) != chunk) { json_parser_abort(parser); return ovsdb_io_error(ferror(file->stream) ? errno : EOF, "%s: error reading %lu bytes " "starting at offset %lld", file->name, length, (long long int) offset); } sha1_update(&ctx, input, chunk); json_parser_feed(parser, input, chunk); length -= chunk; } sha1_final(&ctx, sha1); *jsonp = json_parser_finish(parser); return NULL; }
int jsonrpc_recv(struct jsonrpc *rpc, struct jsonrpc_msg **msgp) { *msgp = NULL; if (rpc->status) { return rpc->status; } while (!rpc->received) { if (byteq_is_empty(&rpc->input)) { size_t chunk; int retval; chunk = byteq_headroom(&rpc->input); retval = stream_recv(rpc->stream, byteq_head(&rpc->input), chunk); if (retval < 0) { if (retval == -EAGAIN) { return EAGAIN; } else { VLOG_WARN_RL(&rl, "%s: receive error: %s", rpc->name, strerror(-retval)); jsonrpc_error(rpc, -retval); return rpc->status; } } else if (retval == 0) { jsonrpc_error(rpc, EOF); return EOF; } byteq_advance_head(&rpc->input, retval); } else { size_t n, used; if (!rpc->parser) { rpc->parser = json_parser_create(0); } n = byteq_tailroom(&rpc->input); used = json_parser_feed(rpc->parser, (char *) byteq_tail(&rpc->input), n); byteq_advance_tail(&rpc->input, used); if (json_parser_is_done(rpc->parser)) { jsonrpc_received(rpc); if (rpc->status) { const struct byteq *q = &rpc->input; if (q->head <= BYTEQ_SIZE) { stream_report_content(q->buffer, q->head, STREAM_JSONRPC, THIS_MODULE, rpc->name); } return rpc->status; } } } } *msgp = rpc->received; rpc->received = NULL; return 0; }
/* Attempts to receive a message from 'rpc'. * * If successful, stores the received message in '*msgp' and returns 0. The * caller takes ownership of '*msgp' and must eventually destroy it with * jsonrpc_msg_destroy(). * * Otherwise, stores NULL in '*msgp' and returns one of the following: * * - EAGAIN: No message has been received. * * - EOF: The remote end closed the connection gracefully. * * - Otherwise an errno value that represents a JSON-RPC protocol violation * or another error fatal to the connection. 'rpc' will not send or * receive any more messages. */ int jsonrpc_recv(struct jsonrpc *rpc, struct jsonrpc_msg **msgp) { int i; *msgp = NULL; if (rpc->status) { return rpc->status; } for (i = 0; i < 50; i++) { size_t n, used; /* Fill our input buffer if it's empty. */ if (byteq_is_empty(&rpc->input)) { size_t chunk; int retval; chunk = byteq_headroom(&rpc->input); retval = stream_recv(rpc->stream, byteq_head(&rpc->input), chunk); if (retval < 0) { if (retval == -EAGAIN) { return EAGAIN; } else { VLOG_WARN_RL(&rl, "%s: receive error: %s", rpc->name, ovs_strerror(-retval)); jsonrpc_error(rpc, -retval); return rpc->status; } } else if (retval == 0) { jsonrpc_error(rpc, EOF); return EOF; } byteq_advance_head(&rpc->input, retval); } /* We have some input. Feed it into the JSON parser. */ if (!rpc->parser) { rpc->parser = json_parser_create(0); } n = byteq_tailroom(&rpc->input); used = json_parser_feed(rpc->parser, (char *) byteq_tail(&rpc->input), n); byteq_advance_tail(&rpc->input, used); /* If we have complete JSON, attempt to parse it as JSON-RPC. */ if (json_parser_is_done(rpc->parser)) { *msgp = jsonrpc_parse_received_message(rpc); if (*msgp) { return 0; } if (rpc->status) { const struct byteq *q = &rpc->input; if (q->head <= q->size) { stream_report_content(q->buffer, q->head, STREAM_JSONRPC, THIS_MODULE, rpc->name); } return rpc->status; } } } return EAGAIN; }