static struct json *foo(struct jrpc_context * ctx, struct json *params, struct json *id) { struct json *reply, *item, *array; int a, b, i; char buf[1024]; json_dump(params); json_dump(id); item = json_get_object_item(params->child, "A"); a = item->valueint; item = json_get_object_item(params->child, "B"); b = item->valueint; sprintf(buf, "recv a:%d b:%d", a, b); array = json_create_array(); for(i = 0; i < a; i ++){ item = json_create_object(); json_add_number_to_object(item, "A", i); json_add_number_to_object(item, "B", b++); json_add_item_to_array(array, item); } reply = json_create_object(); json_add_item_to_object(reply, "Args", array); json_add_string_to_object(reply, "Str", buf); json_dump(reply); return reply; }
static int eval_request(struct jrpc_server *server, struct jrpc_connection *conn, struct json *root) { struct json *method, *params, *id; method = json_get_object_item(root, "method"); if (method != NULL && method->type == JSON_T_STRING) { params = json_get_object_item(root, "params"); if (params == NULL || params->type == JSON_T_ARRAY || params->type == JSON_T_OBJECT) { id = json_get_object_item(root, "id"); if (id == NULL || id->type == JSON_T_STRING || id->type == JSON_T_NUMBER) { return invoke_procedure_id(server, method, conn, id, params); } } } send_error(conn, JRPC_INVALID_REQUEST, strdup("The JSON sent is not a valid Request object."), NULL); return -1; }
int jrpc_client_call(struct jrpc_client *client, const char *method, struct json *params, struct json **response) { int fd, max_read_size; size_t bytes_read = 0; char *new_buffer, *end_ptr = NULL; struct jrpc_connection *conn; struct json *root, *request; request = json_create_object(); json_add_string_to_object(request, "method", method); json_add_item_to_object(request, "params", params); json_add_number_to_object(request, "id", client->id); send_request(&client->conn, json_to_string(request)); json_delete(request); // read conn = &client->conn; fd = conn->sock.fd; for (;;) { if (conn->pos == (conn->buffer_size - 1)) { conn->buffer_size *= 2; new_buffer = realloc(conn->buffer, conn->buffer_size); if (new_buffer == NULL) { perror("Memory error"); return -ENOMEM; } conn->buffer = new_buffer; memset(conn->buffer + conn->pos, 0, conn->buffer_size - conn->pos); } // can not fill the entire buffer, string must be NULL terminated max_read_size = conn->buffer_size - conn->pos - 1; if ((bytes_read = read(fd, conn->buffer + conn->pos, max_read_size)) == -1) { elog("read %d\n", strerror(errno)); return -EIO; } if (!bytes_read) { // client closed the sending half of the connection if (client->conn.debug_level) dlog("Client closed connection.\n"); return -EIO; } conn->pos += bytes_read; if ((root = json_parse_stream(conn->buffer, &end_ptr)) != NULL) { if (client->conn.debug_level > 1) { dlog("Valid JSON Received:\n%s\n", json_to_string(root)); } if (root->type == JSON_T_OBJECT) { struct json *id = json_get_object_item(root, "id"); if (id->type == JSON_T_STRING) { if (client->id != atoi(id->string)) goto out; } else if (id->type == JSON_T_NUMBER) { if (client->id != id->valueint) goto out; } client->id++; //shift processed request, discarding it memmove(conn->buffer, end_ptr, strlen(end_ptr) + 2); conn->pos = strlen(end_ptr); memset(conn->buffer + conn->pos, 0, conn->buffer_size - conn->pos - 1); *response = json_detach_item_from_object(root, "result"); if (*response == NULL) goto out; json_delete(root); return 0; } out: elog("INVALID JSON Received:\n---\n%s\n---\n", conn->buffer); json_delete(root); return -EINVAL; } else if (end_ptr != (conn->buffer + conn->pos)) { // did we parse the all buffer? If so, just wait for more. // else there was an error before the buffer's end if (client->conn.debug_level) { elog("INVALID JSON Received:\n---\n%s\n---\n", conn->buffer); } send_error(conn, JRPC_PARSE_ERROR, strdup("Parse error. Invalid JSON" " was received by the client."), NULL); return -EINVAL; } } }