janssonrpc_request.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /**
  2. * Copyright (C) 2013 Flowroute LLC (flowroute.com)
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * This file is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. *
  12. * This file is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <errno.h>
  25. #include <string.h>
  26. #include "../../sr_module.h"
  27. #include "../../mem/mem.h"
  28. #include "janssonrpc.h"
  29. #include "janssonrpc_request.h"
  30. #include "janssonrpc_io.h"
  31. int next_id = 1;
  32. int store_request(jsonrpc_request_t* req);
  33. /* for debugging only */
  34. void print_request(jsonrpc_request_t* req)
  35. {
  36. if(!req) {
  37. INFO("request is (null)\n");
  38. return;
  39. }
  40. INFO("------request------\n");
  41. INFO("| id: %d\n", req->id);
  42. if(req->type == RPC_NOTIFICATION) {
  43. INFO("| type: notification\n");
  44. } else if(req->type == RPC_REQUEST) {
  45. INFO("| type: request\n");
  46. } else {
  47. INFO("| type: unknown (%d)\n", (int)req->type);
  48. }
  49. if(!(req->server)) {
  50. INFO("| server: (null)\n");
  51. } else {
  52. print_server(req->server);
  53. }
  54. if(!(req->cmd)) {
  55. INFO("| cmd: (null)\n");
  56. } else {
  57. INFO("| cmd->route: %.*s\n", STR(req->cmd->route));
  58. }
  59. INFO("| payload: %s\n", json_dumps(req->payload, 0));
  60. INFO("| retry: %d\n", req->retry);
  61. INFO("| ntries: %d\n", req->ntries);
  62. INFO("| timeout: %d\n", req->timeout);
  63. INFO("\t-------------------\n");
  64. }
  65. void free_request(jsonrpc_request_t* req)
  66. {
  67. if(!req)
  68. return;
  69. pop_request(req->id);
  70. CHECK_AND_FREE_EV(req->retry_ev);
  71. CHECK_AND_FREE_EV(req->timeout_ev);
  72. if(req->payload) json_decref(req->payload);
  73. pkg_free(req);
  74. }
  75. jsonrpc_request_t* create_request(jsonrpc_req_cmd_t* cmd)
  76. {
  77. if (cmd == NULL) {
  78. ERR("cmd is (null). Cannot build request.\n");
  79. return NULL;
  80. }
  81. if (cmd->params.s == NULL) {
  82. ERR("params is (null). Cannot build request.\n");
  83. return NULL;
  84. }
  85. jsonrpc_request_t* req = (jsonrpc_request_t*)pkg_malloc(sizeof(jsonrpc_request_t));
  86. if (!req) {
  87. ERR("Out of memory!");
  88. return NULL;
  89. }
  90. memset(req, 0, sizeof(jsonrpc_request_t));
  91. if (cmd->notify_only) {
  92. req->type = RPC_NOTIFICATION;
  93. } else {
  94. req->type = RPC_REQUEST;
  95. }
  96. /* settings for both notifications and requests */
  97. req->ntries = 0;
  98. req->next = NULL;
  99. req->payload = json_object();
  100. if(!(req->payload)) {
  101. ERR("Failed to create request payload\n");
  102. goto fail;
  103. }
  104. if(req->type == RPC_REQUEST) {
  105. if (next_id>JSONRPC_MAX_ID) {
  106. next_id = 1;
  107. } else {
  108. next_id++;
  109. }
  110. req->id = next_id;
  111. req->timeout = cmd->timeout;
  112. json_t* id_js = json_integer(next_id);
  113. if(id_js) {
  114. json_object_set(req->payload, "id", id_js);
  115. json_decref(id_js);
  116. } else {
  117. ERR("Failed to create request id\n");
  118. goto fail;
  119. }
  120. req->retry = cmd->retry;
  121. req->timeout = cmd->timeout;
  122. if (!store_request(req)) {
  123. ERR("store_request failed\n");
  124. goto fail;
  125. }
  126. } else if (req->type == RPC_NOTIFICATION) {
  127. req->id = 0;
  128. req->retry = 0;
  129. } else {
  130. ERR("Unknown RPC type: %d\n", (int)req->type);
  131. goto fail;
  132. }
  133. json_t* version_js = json_string(JSONRPC_VERSION);
  134. if(version_js) {
  135. json_object_set(req->payload, "jsonrpc", version_js);
  136. json_decref(version_js);
  137. } else {
  138. ERR("Failed to create request version\n");
  139. goto fail;
  140. }
  141. json_t* method_js = json_string(cmd->method.s);
  142. if(method_js) {
  143. json_object_set(req->payload, "method", method_js);
  144. json_decref(method_js);
  145. } else {
  146. ERR("Failed to create request method\n");
  147. goto fail;
  148. }
  149. json_t* params = NULL;
  150. json_error_t error;
  151. if(cmd->params.len > 0) {
  152. params = json_loads(cmd->params.s, 0, &error);
  153. if(!params) {
  154. ERR("Failed to parse json: %.*s\n", STR(cmd->params));
  155. ERR("PARSE ERROR: %s at %d,%d\n",
  156. error.text, error.line, error.column);
  157. goto fail;
  158. }
  159. }
  160. json_object_set(req->payload, "params", params);
  161. if(!(req->payload)) {
  162. ERR("Failed to add request payload params\n");
  163. goto fail;
  164. }
  165. if(params) json_decref(params);
  166. req->cmd = cmd;
  167. return req;
  168. fail:
  169. ERR("Failed to create request\n");
  170. free_request(req);
  171. return NULL;
  172. }
  173. void retry_cb(int fd, short event, void* arg)
  174. {
  175. if(!arg)
  176. return;
  177. jsonrpc_request_t* req = (jsonrpc_request_t*)arg;
  178. if(!(req->cmd)) {
  179. ERR("request has no cmd\n");
  180. goto error;
  181. }
  182. DEBUG("retrying request: id=%d\n", req->id);
  183. if(jsonrpc_send(req->cmd->conn, req, 0)<0) {
  184. goto error;
  185. }
  186. CHECK_AND_FREE_EV(req->retry_ev);
  187. return;
  188. error:
  189. fail_request(JRPC_ERR_SEND, req, "Retry failed to send request");
  190. }
  191. int schedule_retry(jsonrpc_request_t* req)
  192. {
  193. if(!req) {
  194. ERR("Trying to schedule retry for a null request.\n");
  195. return -1;
  196. }
  197. if(req->retry == 0) {
  198. return -1;
  199. }
  200. req->ntries++;
  201. if(req->retry > 0 && req->ntries > req->retry) {
  202. WARN("Number of retries exceeded. Failing request.\n");
  203. return -1;
  204. }
  205. /* next retry in milliseconds */
  206. unsigned int time = req->ntries * req->ntries * req->timeout;
  207. if(time > RETRY_MAX_TIME) {
  208. time = RETRY_MAX_TIME;
  209. }
  210. jsonrpc_request_t* new_req = create_request(req->cmd);
  211. new_req->ntries = req->ntries;
  212. free_request(req);
  213. const struct timeval tv = ms_to_tv(time);
  214. new_req->retry_ev = evtimer_new(global_ev_base, retry_cb, (void*)new_req);
  215. if(evtimer_add(new_req->retry_ev, &tv)<0) {
  216. ERR("event_add failed while setting request retry timer (%s).",
  217. strerror(errno));
  218. goto error;
  219. }
  220. return 0;
  221. error:
  222. ERR("schedule_retry failed.\n");
  223. return -1;
  224. }
  225. int id_hash(int id) {
  226. return (id % JSONRPC_DEFAULT_HTABLE_SIZE);
  227. }
  228. jsonrpc_request_t* pop_request(int id)
  229. {
  230. int key = id_hash(id);
  231. jsonrpc_request_t* req = request_table[key];
  232. jsonrpc_request_t* prev_req = NULL;
  233. while (req && req->id != id) {
  234. prev_req = req;
  235. if (!(req = req->next)) {
  236. break;
  237. };
  238. }
  239. if (req && req->id == id) {
  240. if (prev_req != NULL) {
  241. prev_req->next = req->next;
  242. } else {
  243. request_table[key] = NULL;
  244. }
  245. return req;
  246. }
  247. return 0;
  248. }
  249. int store_request(jsonrpc_request_t* req)
  250. {
  251. int key = id_hash(req->id);
  252. jsonrpc_request_t* existing;
  253. if ((existing = request_table[key])) { /* collision */
  254. jsonrpc_request_t* i;
  255. for(i=existing; i; i=i->next) {
  256. if (i == NULL) {
  257. i = req;
  258. LM_ERR("!!!!!!!");
  259. return 1;
  260. }
  261. if (i->next == NULL) {
  262. i->next = req;
  263. return 1;
  264. }
  265. }
  266. } else {
  267. request_table[key] = req;
  268. }
  269. return 1;
  270. }
  271. unsigned int requests_using_server(jsonrpc_server_t* server)
  272. {
  273. unsigned int count = 0;
  274. jsonrpc_request_t* req = NULL;
  275. int key = 0;
  276. for (key=0; key < JSONRPC_DEFAULT_HTABLE_SIZE; key++) {
  277. for (req = request_table[key]; req != NULL; req = req->next) {
  278. if(req->server
  279. && req->server == server) {
  280. count++;
  281. }
  282. }
  283. }
  284. return count;
  285. }