janssonrpc_funcs.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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 "../../mod_fix.h"
  23. #include "../../pvar.h"
  24. #include "../../lvalue.h"
  25. #include "../tm/tm_load.h"
  26. #include "janssonrpc.h"
  27. #include "janssonrpc_request.h"
  28. #include "janssonrpc_io.h"
  29. #include "janssonrpc_funcs.h"
  30. struct tm_binds tmb;
  31. int jsonrpc_request(struct sip_msg* _m,
  32. char* _conn,
  33. char* _method,
  34. char* _params,
  35. char* _options)
  36. {
  37. str conn;
  38. str method;
  39. str params;
  40. str options;
  41. str route;
  42. param_hooks_t phooks;
  43. param_t* pit=NULL;
  44. param_t* freeme=NULL;
  45. int retry;
  46. int timeout;
  47. int retval = -1;
  48. /* defaults */
  49. options = null_str;
  50. route = null_str;
  51. timeout = JSONRPC_DEFAULT_TIMEOUT;
  52. retry = JSONRPC_DEFAULT_RETRY;
  53. if (get_str_fparam(&conn, _m, (fparam_t*)_conn) != 0) {
  54. ERR("cannot get connection value\n");
  55. return -1;
  56. }
  57. if (get_str_fparam(&method, _m, (fparam_t*)_method) != 0) {
  58. ERR("cannot get method value\n");
  59. return -1;
  60. }
  61. if (get_str_fparam(&params, _m, (fparam_t*)_params) != 0) {
  62. ERR("cannot get params value\n");
  63. return -1;
  64. }
  65. if(_options == NULL) {
  66. } else if (get_str_fparam(&options, _m, (fparam_t*)_options) != 0) {
  67. ERR("cannot get options value\n");
  68. return -1;
  69. } else {
  70. if(options.len == 0) {
  71. goto skip_parse;
  72. }else if (options.len > 0 && options.s[options.len-1] == ';') {
  73. options.len--;
  74. }
  75. if (parse_params(&options, CLASS_ANY, &phooks, &pit)<0) {
  76. ERR("failed parsing params value\n");
  77. return -1;
  78. }
  79. freeme = pit;
  80. for (; pit;pit=pit->next)
  81. {
  82. if PIT_MATCHES("route") {
  83. route = pkg_strdup(pit->body);
  84. CHECK_MALLOC_GOTO(route.s, end);
  85. } else if PIT_MATCHES("timeout") {
  86. timeout = atoi(pit->body.s);
  87. } else if PIT_MATCHES("retry") {
  88. retry = atoi(pit->body.s);
  89. } else {
  90. ERR("Unrecognized option: %.*s\n", STR(pit->name));
  91. goto end;
  92. }
  93. }
  94. }
  95. skip_parse:
  96. /* check options */
  97. if(timeout < 1) {
  98. ERR("invalid timeout option (%d). Must be > 0.\n", timeout);
  99. goto end;
  100. }
  101. if(retry < -1) {
  102. ERR("invalid retry option (%d). Must be > -2.\n", retry);
  103. goto end;
  104. }
  105. retval = 0;
  106. retval = mod_jsonrpc_request(
  107. _m, /* sip_msg */
  108. conn, /* connection group */
  109. method, /* RPC method */
  110. params, /* JSON param */
  111. route, /* result route */
  112. false, /* notify only */
  113. retry, /* retry attempts */
  114. (unsigned int)timeout /* request timeout */
  115. );
  116. end:
  117. if(freeme) free_params(freeme);
  118. if(route.s) pkg_free(route.s);
  119. return retval;
  120. }
  121. int jsonrpc_notification(struct sip_msg* _m,
  122. char* _conn,
  123. char* _method,
  124. char* _params)
  125. {
  126. str conn;
  127. str method;
  128. str params;
  129. if (get_str_fparam(&conn, _m, (fparam_t*)_conn) != 0) {
  130. ERR("cannot get connection value\n");
  131. return -1;
  132. }
  133. if (get_str_fparam(&method, _m, (fparam_t*)_method) != 0) {
  134. ERR("cannot get method value\n");
  135. return -1;
  136. }
  137. if (get_str_fparam(&params, _m, (fparam_t*)_params) != 0) {
  138. ERR("cannot get params value\n");
  139. return -1;
  140. }
  141. return mod_jsonrpc_request(
  142. _m, /* sip_msg */
  143. conn, /* connection group */
  144. method, /* RPC method */
  145. params, /* JSON param */
  146. null_str, /* result route */
  147. true, /* notify only */
  148. 0, /* retry attempts */
  149. 0 /* request timeout */
  150. );
  151. }
  152. int mod_jsonrpc_request(
  153. struct sip_msg* msg,
  154. str conn,
  155. str method,
  156. str params,
  157. str route,
  158. bool notify_only,
  159. int retry,
  160. unsigned int timeout
  161. )
  162. {
  163. unsigned int hash_index;
  164. unsigned int label;
  165. if(retry < -1) {
  166. ERR("retry can't be less than -1\n");
  167. return -1;
  168. }
  169. jsonrpc_req_cmd_t* req_cmd = create_req_cmd();
  170. CHECK_MALLOC(req_cmd);
  171. req_cmd->conn = shm_strdup(conn);
  172. CHECK_MALLOC_GOTO(req_cmd->conn.s, error);
  173. req_cmd->method = shm_strdup(method);
  174. CHECK_MALLOC_GOTO(req_cmd->conn.s, error);
  175. if(params.s) {
  176. req_cmd->params = shm_strdup(params);
  177. CHECK_MALLOC_GOTO(req_cmd->params.s, error);
  178. }
  179. if(route.s) {
  180. req_cmd->route = shm_strdup(route);
  181. CHECK_MALLOC_GOTO(req_cmd->route.s, error);
  182. }
  183. req_cmd->msg = msg;
  184. req_cmd->retry = retry;
  185. req_cmd->notify_only = notify_only;
  186. req_cmd->timeout = timeout;
  187. if(notify_only || route.len <= 0) {
  188. req_cmd->route = null_str;
  189. if(send_pipe_cmd(CMD_SEND, req_cmd)<0) goto error;
  190. return 1; /* continue script execution */
  191. }
  192. tm_cell_t *t = 0;
  193. t = tmb.t_gett();
  194. if (t==NULL || t==T_UNDEFINED)
  195. {
  196. if(tmb.t_newtran(msg)<0)
  197. {
  198. ERR("cannot create the transaction\n");
  199. goto error;
  200. }
  201. t = tmb.t_gett();
  202. if (t==NULL || t==T_UNDEFINED)
  203. {
  204. ERR("cannot look up the transaction\n");
  205. goto error;
  206. }
  207. }
  208. if (tmb.t_suspend(msg, &hash_index, &label) < 0) {
  209. ERR("t_suspend() failed\n");
  210. goto error;
  211. }
  212. req_cmd->t_hash = hash_index;
  213. req_cmd->t_label = label;
  214. if(send_pipe_cmd(CMD_SEND, req_cmd)<0) goto error;
  215. return 0;
  216. error:
  217. free_req_cmd(req_cmd);
  218. ERR("failed to send request to io process\n");
  219. return -1;
  220. }