示例#1
0
void fail_request(int code, jsonrpc_request_t* req, char* err_str)
{
	char* req_s;
	char* freeme = NULL;
	pv_value_t val;
	json_t* error;

	if(!req) {
null_req:
		WARN("%s: (null)\n", err_str);
		goto end;
	}

	if(!(req->cmd) || (req->cmd->route.len <= 0)) {
no_route:
		req_s = json_dumps(req->payload, JSON_COMPACT);
		if(req_s) {
			WARN("%s: \n%s\n", err_str, req_s);
			free(req_s);
			goto end;
		}
		goto null_req;
	}

	error = internal_error(code, req->payload);
	jsontoval(&val, &freeme, error);
	if(error) json_decref(error);
	if(send_to_script(&val, req->cmd)<0) {
		goto no_route;
	}

end:
	if(freeme) free(freeme);
	if(req) {
		if(req->cmd) free_req_cmd(req->cmd);
		free_request(req);
	}
}
示例#2
0
int handle_response(json_t* response)
{
	int retval = 0;
	jsonrpc_request_t* req = NULL;
	json_t* return_obj = NULL;
	json_t* internal = NULL;
	char* freeme = NULL;


	/* check if json object */
	if(!json_is_object(response)){
		WARN("jsonrpc response is not an object\n");
		return -1;
	}

	/* check version */
	json_t* version = json_object_get(response, "jsonrpc");
	if(!version) {
		WARN("jsonrpc response does not have a version.\n");
		retval = -1;
		goto end;
	}

	const char* version_s = json_string_value(version);
	if(!version_s){
		WARN("jsonrpc response version is not a string.\n");
		retval = -1;
		goto end;
	}

	if (strlen(version_s) != (sizeof(JSONRPC_VERSION)-1)
			|| strncmp(version_s, JSONRPC_VERSION, sizeof(JSONRPC_VERSION)-1) != 0) {
		WARN("jsonrpc response version is not %s. version: %s\n",
				JSONRPC_VERSION, version_s);
		retval = -1;
		goto end;
	}

	/* check for an id */
	json_t* _id = json_object_get(response, "id");
	if(!_id) {
		WARN("jsonrpc response does not have an id.\n");
		retval = -1;
		goto end;
	}

	int id = json_integer_value(_id);
	if (!(req = pop_request(id))) {
		/* don't fail the server for an unrecognized id */
		retval = 0;
		goto end;
	}

	return_obj = json_object();

	json_t* error = json_object_get(response, "error");
	// if the error value is null, we don't care
	bool _error = error && (json_typeof(error) != JSON_NULL);

	json_t* result = json_object_get(response, "result");

	if(_error) {
		json_object_set(return_obj, "error", error);
	}

	if(result) {
		json_object_set(return_obj, "result", result);
	}

	if ((!result && !_error) || (result && _error)) {
		WARN("bad response\n");
		internal = internal_error(JRPC_ERR_BAD_RESP, req->payload);
		json_object_update(return_obj, internal);
		if(internal) json_decref(internal);
	}

	pv_value_t val;

	if(jsontoval(&val, &freeme, return_obj)<0) {
		fail_request(
				JRPC_ERR_TO_VAL,
				req,
				"Failed to convert response json to pv\n");
		retval = -1;
		goto end;
	}

	char* error_s = NULL;

	if(send_to_script(&val, req->cmd)>=0) {
		goto free_and_end;
	}

	if(_error) {
		// get code from error
		json_t* _code = json_object_get(error, "code");
		if(_code) {
			int code = json_integer_value(_code);

			// check if code is in global_retry_ranges
			retry_range_t* tmpr;
			for(tmpr = global_retry_ranges;
					tmpr != NULL;
					tmpr = tmpr->next) {
				if((tmpr->start < tmpr->end
						&& tmpr->start <= code && code <= tmpr->end)
				|| (tmpr->end < tmpr->start
						&& tmpr->end <= code && code <= tmpr->start)
				|| (tmpr->start == tmpr->end && tmpr->start == code)) {
					if(schedule_retry(req)==0) {
						goto end;
					}
					break;
				}
			}

		}
		error_s = json_dumps(error, JSON_COMPACT);
		if(error_s) {
			WARN("Request received an error: \n%s\n", error_s);
			free(error_s);
		} else {
			fail_request(
					JRPC_ERR_BAD_RESP,
					req,
					"Could not convert 'error' response to string");
			retval = -1;
			goto end;
		}
	}


free_and_end:
	free_req_cmd(req->cmd);
	free_request(req);

end:
	if(freeme) free(freeme);
	if(return_obj) json_decref(return_obj);
	return retval;
}
示例#3
0
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);
}