1 /*
2  *
3  * Copyright (C) 2011 Flowroute LLC (flowroute.com)
4  *
5  * This file is part of Kamailio, a free SIP server.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  *
13  * This file is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28 
29 #include "../../core/sr_module.h"
30 #include "../../core/mem/mem.h"
31 
32 #include "jsonrpc.h"
33 
34 
35 jsonrpc_request_t * request_table[JSONRPC_DEFAULT_HTABLE_SIZE] = {0};
36 int next_id = 1;
37 
38 jsonrpc_request_t* get_request(int id);
39 int store_request(jsonrpc_request_t* req);
40 
41 
build_jsonrpc_request(char * method,json_object * params,char * cbdata,int (* cbfunc)(json_object *,char *,int))42 jsonrpc_request_t* build_jsonrpc_request(char *method, json_object *params, char *cbdata, int (*cbfunc)(json_object*, char*, int))
43 {
44 	if (next_id>JSONRPC_MAX_ID) {
45 		next_id = 1;
46 	} else {
47 		next_id++;
48 	}
49 
50 	jsonrpc_request_t *req = pkg_malloc(sizeof(jsonrpc_request_t));
51 	if (!req) {
52 		LM_ERR("Out of memory!");
53 		return 0;
54 	}
55 	req->id = next_id;
56 	req->cbfunc = cbfunc;
57 	req->cbdata = cbdata;
58 	req->next = NULL;
59 	req->timer_ev = NULL;
60 	if (!store_request(req))
61 		return 0;
62 
63 	req->payload = json_object_new_object();
64 
65 	json_object_object_add(req->payload, "id", json_object_new_int(next_id));
66 	json_object_object_add(req->payload, "jsonrpc", json_object_new_string("2.0"));
67 	json_object_object_add(req->payload, "method", json_object_new_string(method));
68 	json_object_object_add(req->payload, "params", params);
69 
70 	return req;
71 }
72 
build_jsonrpc_notification(char * method,json_object * params)73 json_object* build_jsonrpc_notification(char *method, json_object *params)
74 {
75 	json_object *req = json_object_new_object();
76 	json_object_object_add(req, "jsonrpc", json_object_new_string("2.0"));
77 	json_object_object_add(req, "method", json_object_new_string(method));
78 	json_object_object_add(req, "params", params);
79 
80 	return req;
81 }
82 
83 
handle_jsonrpc_response(json_object * response)84 int handle_jsonrpc_response(json_object *response)
85 {
86 	jsonrpc_request_t *req;
87 	json_object *_id = NULL;
88 	int id = 0;
89 	json_object *result = NULL;
90 
91 	json_object_object_get_ex(response, "id", &_id);
92 	id = json_object_get_int(_id);
93 	if (!(req = get_request(id))) {
94 		json_object_put(response);
95 		return -1;
96 	}
97 
98 	json_object_object_get_ex(response, "result", &result);
99 
100 	if (result) {
101 		req->cbfunc(result, req->cbdata, 0);
102 	} else {
103 		json_object *error = NULL;
104 		json_object_object_get_ex(response, "error", &error);
105 		if (error) {
106 			req->cbfunc(error, req->cbdata, 1);
107 		} else {
108 			LM_ERR("Response received with neither a result nor an error.\n");
109 			return -1;
110 		}
111 	}
112 
113 	if (req->timer_ev) {
114 		close(req->timerfd);
115 		event_del(req->timer_ev);
116 		pkg_free(req->timer_ev);
117 	} else {
118 		LM_ERR("No timer for req id %d\n", id);
119 	}
120 	pkg_free(req);
121 	return 1;
122 }
123 
id_hash(int id)124 int id_hash(int id) {
125 	return (id % JSONRPC_DEFAULT_HTABLE_SIZE);
126 }
127 
get_request(int id)128 jsonrpc_request_t* get_request(int id) {
129 	int key = id_hash(id);
130 	jsonrpc_request_t *req, *prev_req = NULL;
131 	req = request_table[key];
132 
133 	while (req && req->id != id) {
134 		prev_req = req;
135 		if (!(req = req->next)) {
136 			break;
137 		};
138 	}
139 
140 	if (req && req->id == id) {
141 		if (prev_req != NULL) {
142 			prev_req-> next = req->next;
143 		} else {
144 			request_table[key] = NULL;
145 		}
146 		return req;
147 	}
148 	return 0;
149 }
150 
void_jsonrpc_request(int id)151 void void_jsonrpc_request(int id) {
152 	get_request(id);
153 }
154 
store_request(jsonrpc_request_t * req)155 int store_request(jsonrpc_request_t* req) {
156 	int key = id_hash(req->id);
157 	jsonrpc_request_t* existing;
158 
159 	if ((existing = request_table[key])) { /* collision */
160 		jsonrpc_request_t* i;
161 		for(i=existing; i; i=i->next) {
162 			if (i == NULL) {
163 				i = req;
164 				LM_ERR("!!!!!!!");
165 				return 1;
166 			}
167 			if (i->next == NULL) {
168 				i->next = req;
169 				return 1;
170 			}
171 		}
172 	} else {
173 		request_table[key] = req;
174 	}
175 	return 1;
176 }
177 
178