Esempio n. 1
0
/* Attempts to parse the content of 'rpc->parser' (which is complete JSON) as a
 * JSON-RPC message.  If successful, returns the JSON-RPC message.  On failure,
 * signals an error on 'rpc' with jsonrpc_error() and returns NULL. */
static struct jsonrpc_msg *
jsonrpc_parse_received_message(struct jsonrpc *rpc)
{
    struct jsonrpc_msg *msg;
    struct json *json;
    char *error;

    json = json_parser_finish(rpc->parser);
    rpc->parser = NULL;
    if (json->type == JSON_STRING) {
        VLOG_WARN_RL(&rl, "%s: error parsing stream: %s",
                     rpc->name, json_string(json));
        jsonrpc_error(rpc, EPROTO);
        json_destroy(json);
        return NULL;
    }

    error = jsonrpc_msg_from_json(json, &msg);
    if (error) {
        VLOG_WARN_RL(&rl, "%s: received bad JSON-RPC message: %s",
                     rpc->name, error);
        free(error);
        jsonrpc_error(rpc, EPROTO);
        return NULL;
    }

    jsonrpc_log_msg(rpc, "received", msg);
    return msg;
}
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;
}
Esempio n. 3
0
/* Performs periodic maintenance on 'rpc', such as flushing output buffers. */
void
jsonrpc_run(struct jsonrpc *rpc)
{
    if (rpc->status) {
        return;
    }

    stream_run(rpc->stream);
    while (!list_is_empty(&rpc->output)) {
        struct ofpbuf *buf = ofpbuf_from_list(rpc->output.next);
        int retval;

        retval = stream_send(rpc->stream, buf->data, buf->size);
        if (retval >= 0) {
            rpc->backlog -= retval;
            ofpbuf_pull(buf, retval);
            if (!buf->size) {
                list_remove(&buf->list_node);
                rpc->output_count--;
                ofpbuf_delete(buf);
            }
        } else {
            if (retval != -EAGAIN) {
                VLOG_WARN_RL(&rl, "%s: send error: %s",
                             rpc->name, ovs_strerror(-retval));
                jsonrpc_error(rpc, -retval);
            }
            break;
        }
    }
}
Esempio n. 4
0
static void
jsonrpc_session_disconnect(struct jsonrpc_session *s)
{
    if (s->rpc) {
        jsonrpc_error(s->rpc, EOF);
        jsonrpc_close(s->rpc);
        s->rpc = NULL;
        s->seqno++;
    } else if (s->stream) {
        stream_close(s->stream);
        s->stream = NULL;
        s->seqno++;
    }
}
Esempio n. 5
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;
}
Esempio n. 6
0
File: v1.c Progetto: fahlgren/kore
int
v1(struct http_request *http_req)
{
	struct jsonrpc_request	req;
	int			ret;
	
	/* We only allow POST/PUT methods. */
	if (http_req->method != HTTP_METHOD_POST &&
	    http_req->method != HTTP_METHOD_PUT) {
		http_response_header(http_req, "allow", "POST, PUT");
		http_response(http_req, HTTP_STATUS_METHOD_NOT_ALLOWED, NULL, 0);
		return (KORE_RESULT_OK);
	}
	
	/* Read JSON-RPC request. */
	if ((ret = jsonrpc_read_request(http_req, &req)) != 0)
		return jsonrpc_error(&req, ret, NULL);
	
	/* Echo command takes and gives back params. */
	if (strcmp(req.method, "echo") == 0) {
		if (!YAJL_IS_ARRAY(req.params)) {
			jsonrpc_log(&req, LOG_ERR,
			    "Echo only accepts positional params");
			return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
		}
		for (size_t i = 0; i < req.params->u.array.len; i++) {
			yajl_val v = req.params->u.array.values[i];
			if (!YAJL_IS_STRING(v)) {
				jsonrpc_log(&req, -3,
				    "Echo only accepts strings");
				return jsonrpc_error(&req,
				    JSONRPC_INVALID_PARAMS, NULL);
			}
		}
		return jsonrpc_result(&req, write_string_array_params, NULL);
	}
	
	/* Date command displays date and time according to parameters. */
	if (strcmp(req.method, "date") == 0) {
		time_t		time_value;
		struct tm	time_info;
		char		timestamp[33];
		struct tm	*(*gettm)(const time_t *, struct tm *) =
				    localtime_r;
		
		if (YAJL_IS_OBJECT(req.params)) {
			const char	*path[] = {"local", NULL};
			yajl_val	bf;

			bf = yajl_tree_get(req.params, path, yajl_t_false);
			if (bf != NULL)
				gettm = gmtime_r;
		} else if (req.params != NULL) {
			jsonrpc_log(&req, LOG_ERR,
			    "Date only accepts named params");
			return jsonrpc_error(&req, JSONRPC_INVALID_PARAMS, NULL);
		}

		if ((time_value = time(NULL)) == -1)
			return jsonrpc_error(&req, -2,
			    "Failed to get date time");
		
		if (gettm(&time_value, &time_info) == NULL)
			return jsonrpc_error(&req, -3,
			    "Failed to get date time info");
		
		memset(timestamp, 0, sizeof(timestamp));
		if (strftime_l(timestamp, sizeof(timestamp) - 1, "%c",
		    &time_info, LC_GLOBAL_LOCALE) == 0)
			return jsonrpc_error(&req, -4,
			    "Failed to get printable date time");
		
		return jsonrpc_result(&req, write_string, timestamp);
	}
	
	return jsonrpc_error(&req, JSONRPC_METHOD_NOT_FOUND, NULL);
}