http_async_client_mod.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. /**
  2. * Copyright 2016 (C) Federico Cabiddu <[email protected]>
  3. * Copyright 2016 (C) Giacomo Vacca <[email protected]>
  4. * Copyright 2016 (C) Orange - Camille Oudot <[email protected]>
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * This file is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. *
  14. * This file is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. *
  23. */
  24. /*! \file
  25. * \brief Kamailio http_async_client :: The module interface file
  26. * \ingroup http_async_client
  27. */
  28. /*! \defgroup http_async_client Kamailio :: Async module interface to Curl/HTTP
  29. *
  30. * http://curl.haxx.se
  31. * A generic library for many protocols
  32. *
  33. */
  34. #include <stdio.h>
  35. #include <unistd.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include "../../globals.h"
  39. #include "../../sr_module.h"
  40. #include "../../dprint.h"
  41. #include "../../ut.h"
  42. #include "../../pt.h"
  43. #include "../../pvar.h"
  44. #include "../../mem/shm_mem.h"
  45. #include "../../mod_fix.h"
  46. #include "../../pvar.h"
  47. #include "../../cfg/cfg_struct.h"
  48. #include "../../lib/kcore/faked_msg.h"
  49. #include "../../modules/tm/tm_load.h"
  50. #include "../../modules/pv/pv_api.h"
  51. #include "async_http.h"
  52. MODULE_VERSION
  53. extern int num_workers;
  54. int http_timeout = 500; /* query timeout in ms */
  55. int hash_size = 2048;
  56. int ssl_version = 0; // Use default SSL version in HTTPS requests (see curl/curl.h)
  57. int verify_host = 1; // By default verify host in HTTPS requests
  58. int verify_peer = 1; // By default verify peer in HTTPS requests
  59. int curl_verbose = 0;
  60. str ssl_cert = STR_STATIC_INIT(""); // client SSL certificate path, defaults to NULL
  61. str ssl_key = STR_STATIC_INIT(""); // client SSL certificate key path, defaults to NULL
  62. str ca_path = STR_STATIC_INIT(""); // certificate authority dir path, defaults to NULL
  63. static char *memory_manager = "shm";
  64. extern int curl_memory_manager;
  65. static int mod_init(void);
  66. static int child_init(int);
  67. static void mod_destroy(void);
  68. static int w_http_async_get(sip_msg_t* msg, char* query, char* rt);
  69. static int w_http_async_post(sip_msg_t* msg, char* query, char* post, char* rt);
  70. static int w_http_verify_host(sip_msg_t* msg, char* vh, char*);
  71. static int w_http_verify_peer(sip_msg_t* msg, char* vp, char*);
  72. static int w_http_async_suspend_transaction(sip_msg_t* msg, char* vp, char*);
  73. static int w_http_set_timeout(sip_msg_t* msg, char* tout, char*);
  74. static int w_http_append_header(sip_msg_t* msg, char* hdr, char*);
  75. static int w_http_set_method(sip_msg_t* msg, char* method, char*);
  76. static int w_http_set_ssl_cert(sip_msg_t* msg, char* sc, char*);
  77. static int w_http_set_ssl_key(sip_msg_t* msg, char* sk, char*);
  78. static int w_http_set_ca_path(sip_msg_t* msg, char* cp, char*);
  79. static int fixup_http_async_get(void** param, int param_no);
  80. static int fixup_http_async_post(void** param, int param_no);
  81. /* pv api binding */
  82. static int ah_get_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  83. static int ah_get_hdr(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  84. static int w_pv_parse_hdr_name(pv_spec_p sp, str *in);
  85. static int ah_get_status(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  86. static int ah_get_msg_body(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  87. static int ah_get_body_size(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  88. static int ah_get_msg_buf(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  89. static int ah_get_msg_len(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  90. static str pv_str_1 = {"1", 1};
  91. static str pv_str_0 = {"0", 1};
  92. static int ah_get_ok(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  93. static int ah_get_err(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
  94. /* tm */
  95. struct tm_binds tmb;
  96. /* pv */
  97. pv_api_t pv_api;
  98. stat_var *requests;
  99. stat_var *replies;
  100. stat_var *errors;
  101. stat_var *timeouts;
  102. static cmd_export_t cmds[]={
  103. {"http_async_query", (cmd_function)w_http_async_get, 2, fixup_http_async_get,
  104. 0, ANY_ROUTE},
  105. {"http_async_query", (cmd_function)w_http_async_post, 3, fixup_http_async_post,
  106. 0, ANY_ROUTE},
  107. {"http_verify_host", (cmd_function)w_http_verify_host, 1, fixup_igp_all,
  108. 0, ANY_ROUTE},
  109. {"http_verify_peer", (cmd_function)w_http_verify_peer, 1, fixup_igp_all,
  110. 0, ANY_ROUTE},
  111. {"http_async_suspend", (cmd_function)w_http_async_suspend_transaction, 1, fixup_igp_all,
  112. 0, ANY_ROUTE},
  113. {"http_set_timeout", (cmd_function)w_http_set_timeout, 1, fixup_igp_all,
  114. 0, ANY_ROUTE},
  115. {"http_append_header", (cmd_function)w_http_append_header, 1, fixup_spve_null,
  116. 0, ANY_ROUTE},
  117. {"http_set_method", (cmd_function)w_http_set_method, 1, fixup_spve_null,
  118. 0, ANY_ROUTE},
  119. {"http_set_ssl_cert", (cmd_function)w_http_set_ssl_cert, 1, fixup_spve_null,
  120. 0, ANY_ROUTE},
  121. {"http_set_ssl_key", (cmd_function)w_http_set_ssl_key, 1, fixup_spve_null,
  122. 0, ANY_ROUTE},
  123. {"http_set_ca_path", (cmd_function)w_http_set_ca_path, 1, fixup_spve_null,
  124. 0, ANY_ROUTE},
  125. {0, 0, 0, 0, 0, 0}
  126. };
  127. static param_export_t params[]={
  128. {"workers", INT_PARAM, &num_workers},
  129. {"connection_timeout", INT_PARAM, &http_timeout},
  130. {"hash_size", INT_PARAM, &hash_size},
  131. {"tlsversion", INT_PARAM, &ssl_version},
  132. {"tlsverifyhost", INT_PARAM, &verify_host},
  133. {"tlsverifypeer", INT_PARAM, &verify_peer},
  134. {"curl_verbose", INT_PARAM, &curl_verbose},
  135. {"tlsclientcert", PARAM_STR, &ssl_cert},
  136. {"tlsclientkey", PARAM_STR, &ssl_key},
  137. {"tlscapath", PARAM_STR, &ca_path},
  138. {"memory_manager", PARAM_STRING,&memory_manager},
  139. {0, 0, 0}
  140. };
  141. /*! \brief We expose internal variables via the statistic framework below.*/
  142. stat_export_t mod_stats[] = {
  143. {"requests", STAT_NO_RESET, &requests },
  144. {"replies", STAT_NO_RESET, &replies },
  145. {"errors", STAT_NO_RESET, &errors },
  146. {"timeouts", STAT_NO_RESET, &timeouts },
  147. {0, 0, 0}
  148. };
  149. static pv_export_t pvs[] = {
  150. {STR_STATIC_INIT("http_hdr"),
  151. PVT_HDR, ah_get_hdr, 0,
  152. w_pv_parse_hdr_name, pv_parse_index, 0, 0},
  153. {STR_STATIC_INIT("http_rr"),
  154. PVT_OTHER, ah_get_reason, 0,
  155. 0, 0, 0, 0},
  156. {STR_STATIC_INIT("http_rs"),
  157. PVT_OTHER, ah_get_status, 0,
  158. 0, 0, 0, 0},
  159. {STR_STATIC_INIT("http_rb"),
  160. PVT_MSG_BODY, ah_get_msg_body, 0,
  161. 0, 0, 0, 0},
  162. {STR_STATIC_INIT("http_bs"),
  163. PVT_OTHER, ah_get_body_size, 0,
  164. 0, 0, 0, 0},
  165. {STR_STATIC_INIT("http_mb"),
  166. PVT_OTHER, ah_get_msg_buf, 0,
  167. 0, 0, 0, 0},
  168. {STR_STATIC_INIT("http_ml"),
  169. PVT_OTHER, ah_get_msg_len, 0,
  170. 0, 0, 0, 0},
  171. {STR_STATIC_INIT("http_ok"),
  172. PVT_OTHER, ah_get_ok, 0,
  173. 0, 0, 0, 0},
  174. {STR_STATIC_INIT("http_err"),
  175. PVT_OTHER, ah_get_err, 0,
  176. 0, 0, 0, 0},
  177. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  178. };
  179. struct module_exports exports = {
  180. "http_async_client",
  181. DEFAULT_DLFLAGS, /* dlopen flags */
  182. cmds,
  183. params,
  184. mod_stats, /* exported statistics */
  185. 0, /* exported MI functions */
  186. pvs, /* exported pseudo-variables */
  187. 0, /* extra processes */
  188. mod_init, /* module initialization function */
  189. 0, /* response function */
  190. mod_destroy, /* destroy function */
  191. child_init /* per child init function */
  192. };
  193. /**
  194. * init module function
  195. */
  196. static int mod_init(void)
  197. {
  198. unsigned int n;
  199. pv_register_api_t pvra;
  200. LM_INFO("Initializing Http Async module\n");
  201. #ifdef STATISTICS
  202. /* register statistics */
  203. if (register_module_stats( exports.name, mod_stats)!=0 ) {
  204. LM_ERR("failed to register core statistics\n");
  205. return -1;
  206. }
  207. #endif
  208. /* sanitize hash_size */
  209. if (hash_size < 1){
  210. LM_WARN("hash_size is smaller "
  211. "than 1 -> rounding from %d to 1\n",
  212. hash_size);
  213. hash_size = 1;
  214. }
  215. /* check that the hash table size is a power of 2 */
  216. for( n=0 ; n<(8*sizeof(n)) ; n++) {
  217. if (hash_size==(1<<n))
  218. break;
  219. if (n && hash_size<(1<<n)) {
  220. LM_WARN("hash_size is not a power "
  221. "of 2 as it should be -> rounding from %d to %d (n=%d)\n",
  222. hash_size, 1<<(n-1), n);
  223. hash_size = 1<<(n-1);
  224. break;
  225. }
  226. }
  227. /* check 'workers' param */
  228. if (num_workers < 1) {
  229. LM_ERR("the 'workers' parameter must be >= 1\n");
  230. return -1;
  231. }
  232. verify_host = verify_host?1:0;
  233. verify_peer = verify_peer?1:0;
  234. /* init http parameters list */
  235. init_query_params(&ah_params);
  236. if (strncmp("shm", memory_manager, 3) == 0) {
  237. curl_memory_manager = 0;
  238. } else if (strncmp("sys", memory_manager, 3) == 0) {
  239. curl_memory_manager = 1;
  240. } else {
  241. LM_ERR("invalid memory_manager parameter: '%s'\n", memory_manager);
  242. return -1;
  243. }
  244. if (strncmp("shm", memory_manager, 3) == 0) {
  245. curl_memory_manager = 0;
  246. } else if (strncmp("sys", memory_manager, 3) == 0) {
  247. curl_memory_manager = 1;
  248. } else {
  249. LM_ERR("invalid memory_manager parameter: '%s'\n", memory_manager);
  250. return -1;
  251. }
  252. /* init faked sip msg */
  253. if(faked_msg_init()<0) {
  254. LM_ERR("failed to init faked sip msg\n");
  255. return -1;
  256. }
  257. if(load_tm_api( &tmb ) < 0) {
  258. LM_INFO("cannot load the TM-functions - async relay disabled\n");
  259. memset(&tmb, 0, sizeof(tm_api_t));
  260. }
  261. pvra = (pv_register_api_t)find_export("pv_register_api", NO_SCRIPT, 0);
  262. if (!pvra) {
  263. LM_ERR("Cannot import pv functions (pv module must be loaded before this module)\n");
  264. return -1;
  265. }
  266. pvra(&pv_api);
  267. /* allocate workers array */
  268. workers = shm_malloc(num_workers * sizeof(*workers));
  269. if(workers == NULL) {
  270. LM_ERR("error in shm_malloc\n");
  271. return -1;
  272. }
  273. memset(workers, 0, num_workers * sizeof(*workers));
  274. register_procs(num_workers);
  275. /* add child to update local config framework structures */
  276. cfg_register_child(num_workers);
  277. return 0;
  278. }
  279. /**
  280. * @brief Initialize async module children
  281. */
  282. static int child_init(int rank)
  283. {
  284. int pid;
  285. int i;
  286. LM_DBG("child initializing async http\n");
  287. if(num_workers<=0)
  288. return 0;
  289. if (rank==PROC_INIT) {
  290. for(i=0; i<num_workers; i++) {
  291. LM_DBG("initializing worker notification socket: %d\n", i);
  292. if(async_http_init_sockets(&workers[i])<0) {
  293. LM_ERR("failed to initialize tasks sockets\n");
  294. return -1;
  295. }
  296. }
  297. return 0;
  298. }
  299. if(rank>0) {
  300. for(i=0; i<num_workers; i++) {
  301. close(workers[i].notication_socket[0]);
  302. }
  303. return 0;
  304. }
  305. if (rank!=PROC_MAIN)
  306. return 0;
  307. for(i=0; i<num_workers; i++) {
  308. if(async_http_init_worker(i+1, &workers[i])<0) {
  309. LM_ERR("failed to initialize worker process: %d\n", i);
  310. return -1;
  311. }
  312. pid=fork_process(PROC_RPC, "Http Worker", 1);
  313. if (pid<0)
  314. return -1; /* error */
  315. if(pid==0) {
  316. /* child */
  317. /* enforce http_reply_parse=yes */
  318. http_reply_parse = 1;
  319. /* initialize the config framework */
  320. if (cfg_child_init())
  321. return -1;
  322. /* init msg structure for http reply parsing */
  323. ah_reply = pkg_malloc(sizeof(struct sip_msg));
  324. if(!ah_reply) {
  325. LM_ERR("failed to allocate pkg memory\n");
  326. return -1;
  327. }
  328. memset(ah_reply, 0, sizeof(struct sip_msg));
  329. /* main function for workers */
  330. async_http_run_worker(&workers[i]);
  331. }
  332. }
  333. return 0;
  334. }
  335. /**
  336. * destroy module function
  337. */
  338. static void mod_destroy(void)
  339. {
  340. }
  341. /**
  342. *
  343. */
  344. static int w_http_async_get(sip_msg_t *msg, char *query, char* rt)
  345. {
  346. str sdata;
  347. cfg_action_t *act;
  348. str rn;
  349. int ri;
  350. if(msg==NULL)
  351. return -1;
  352. if(fixup_get_svalue(msg, (gparam_t*)query, &sdata)!=0) {
  353. LM_ERR("unable to get data\n");
  354. return -1;
  355. }
  356. if(sdata.s==NULL || sdata.len == 0) {
  357. LM_ERR("invalid data parameter\n");
  358. return -1;
  359. }
  360. if(fixup_get_svalue(msg, (gparam_t*)rt, &rn)!=0)
  361. {
  362. LM_ERR("no route block name\n");
  363. return -1;
  364. }
  365. ri = route_get(&main_rt, rn.s);
  366. if(ri<0)
  367. {
  368. LM_ERR("unable to find route block [%.*s]\n", rn.len, rn.s);
  369. return -1;
  370. }
  371. act = main_rt.rlist[ri];
  372. if(act==NULL)
  373. {
  374. LM_ERR("empty action lists in route block [%.*s]\n", rn.len, rn.s);
  375. return -1;
  376. }
  377. return async_send_query(msg, &sdata, NULL, act);
  378. }
  379. /**
  380. *
  381. */
  382. static int w_http_async_post(sip_msg_t *msg, char *query, char* post, char* rt)
  383. {
  384. str sdata;
  385. str post_data;
  386. cfg_action_t *act;
  387. str rn;
  388. int ri;
  389. if(msg==NULL)
  390. return -1;
  391. if(fixup_get_svalue(msg, (gparam_t*)query, &sdata)!=0) {
  392. LM_ERR("unable to get data\n");
  393. return -1;
  394. }
  395. if(sdata.s==NULL || sdata.len == 0) {
  396. LM_ERR("invalid data parameter\n");
  397. return -1;
  398. }
  399. if(fixup_get_svalue(msg, (gparam_t*)post, &post_data)!=0) {
  400. LM_ERR("unable to get post data\n");
  401. return -1;
  402. }
  403. if(post_data.s==NULL || post_data.len == 0) {
  404. LM_ERR("invalid post data parameter\n");
  405. return -1;
  406. }
  407. if(fixup_get_svalue(msg, (gparam_t*)rt, &rn)!=0)
  408. {
  409. LM_ERR("no route block name\n");
  410. return -1;
  411. }
  412. ri = route_get(&main_rt, rn.s);
  413. if(ri<0)
  414. {
  415. LM_ERR("unable to find route block [%.*s]\n", rn.len, rn.s);
  416. return -1;
  417. }
  418. act = main_rt.rlist[ri];
  419. if(act==NULL)
  420. {
  421. LM_ERR("empty action lists in route block [%.*s]\n", rn.len, rn.s);
  422. return -1;
  423. }
  424. if(async_send_query(msg, &sdata, &post_data, act)<0)
  425. return -1;
  426. /* force exit in config */
  427. return 0;
  428. }
  429. #define _IVALUE_ERROR(NAME) LM_ERR("invalid parameter '" #NAME "' (must be a number)\n")
  430. #define _IVALUE(NAME)\
  431. int i_##NAME ;\
  432. if(fixup_get_ivalue(msg, (gparam_t*)NAME, &( i_##NAME))!=0)\
  433. { \
  434. _IVALUE_ERROR(NAME);\
  435. return -1;\
  436. }
  437. static int w_http_verify_host(sip_msg_t* msg, char* vh, char*foo)
  438. {
  439. _IVALUE (vh);
  440. ah_params.verify_host = i_vh?1:0;
  441. return 1;
  442. }
  443. static int w_http_verify_peer(sip_msg_t* msg, char* vp, char*foo)
  444. {
  445. _IVALUE (vp);
  446. ah_params.verify_peer = i_vp?1:0;
  447. return 1;
  448. }
  449. static int w_http_async_suspend_transaction(sip_msg_t* msg, char* vp, char*foo)
  450. {
  451. _IVALUE (vp);
  452. ah_params.suspend_transaction = i_vp?1:0;
  453. return 1;
  454. }
  455. static int w_http_set_timeout(sip_msg_t* msg, char* tout, char*foo)
  456. {
  457. _IVALUE (tout);
  458. if (i_tout < 0) {
  459. LM_ERR("timeout must be >= 0 (got %d)\n", i_tout);
  460. return -1;
  461. }
  462. ah_params.timeout = i_tout;
  463. return 1;
  464. }
  465. static int w_http_append_header(sip_msg_t* msg, char* hdr, char*foo)
  466. {
  467. str shdr;
  468. if(fixup_get_svalue(msg, (gparam_t*)hdr, &shdr)!=0) {
  469. LM_ERR("unable to get header value\n");
  470. return -1;
  471. }
  472. ah_params.headers.len++;
  473. ah_params.headers.t = shm_realloc(ah_params.headers.t, ah_params.headers.len * sizeof(char*));
  474. if (!ah_params.headers.t) {
  475. LM_ERR("shm memory allocation failure\n");
  476. return -1;
  477. }
  478. ah_params.headers.t[ah_params.headers.len - 1] = shm_malloc(shdr.len + 1);
  479. if (!ah_params.headers.t[ah_params.headers.len - 1]) {
  480. LM_ERR("shm memory allocation failure\n");
  481. return -1;
  482. }
  483. memcpy(ah_params.headers.t[ah_params.headers.len - 1], shdr.s, shdr.len);
  484. *(ah_params.headers.t[ah_params.headers.len - 1] + shdr.len) = '\0';
  485. LM_DBG("stored new http header: [%s]\n",
  486. ah_params.headers.t[ah_params.headers.len - 1]);
  487. return 1;
  488. }
  489. static int w_http_set_method(sip_msg_t* msg, char* meth, char*foo)
  490. {
  491. str smeth;
  492. if(fixup_get_svalue(msg, (gparam_t*)meth, &smeth)!=0) {
  493. LM_ERR("unable to get method value\n");
  494. return -1;
  495. }
  496. if (strncasecmp(smeth.s, "GET", smeth.len) == 0) {
  497. ah_params.method = AH_METH_GET;
  498. } else if (strncasecmp(smeth.s, "POST", smeth.len) == 0) {
  499. ah_params.method = AH_METH_POST;
  500. } else if (strncasecmp(smeth.s, "PUT", smeth.len) == 0) {
  501. ah_params.method = AH_METH_PUT;
  502. } else if (strncasecmp(smeth.s, "DELETE", smeth.len) == 0) {
  503. ah_params.method = AH_METH_DELETE;
  504. } else {
  505. LM_ERR("Unsupported method: %.*s\n", smeth.len, smeth.s);
  506. return -1;
  507. }
  508. return 1;
  509. }
  510. static int w_http_set_ssl_cert(sip_msg_t* msg, char* sc, char*foo)
  511. {
  512. str _ssl_cert;
  513. if(fixup_get_svalue(msg, (gparam_t*)sc, &_ssl_cert)!=0) {
  514. LM_ERR("unable to get method value\n");
  515. return -1;
  516. }
  517. if (ah_params.ssl_cert.s) {
  518. shm_free(ah_params.ssl_cert.s);
  519. ah_params.ssl_cert.s = NULL;
  520. ah_params.ssl_cert.len = 0;
  521. }
  522. if (_ssl_cert.s && _ssl_cert.len > 0) {
  523. if (shm_str_dup(&ah_params.ssl_cert, &_ssl_cert) < 0) {
  524. LM_ERR("Error allocating ah_params.ssl_cert\n");
  525. return -1;
  526. }
  527. }
  528. return 1;
  529. }
  530. static int w_http_set_ssl_key(sip_msg_t* msg, char* sk, char*foo)
  531. {
  532. str _ssl_key;
  533. if(fixup_get_svalue(msg, (gparam_t*)sk, &_ssl_key)!=0) {
  534. LM_ERR("unable to get method value\n");
  535. return -1;
  536. }
  537. if (ah_params.ssl_key.s) {
  538. shm_free(ah_params.ssl_key.s);
  539. ah_params.ssl_key.s = NULL;
  540. ah_params.ssl_key.len = 0;
  541. }
  542. if (_ssl_key.s && _ssl_key.len > 0) {
  543. if (shm_str_dup(&ah_params.ssl_key, &_ssl_key) < 0) {
  544. LM_ERR("Error allocating ah_params.ssl_key\n");
  545. return -1;
  546. }
  547. }
  548. return 1;
  549. }
  550. static int w_http_set_ca_path(sip_msg_t* msg, char* cp, char*foo)
  551. {
  552. str _ca_path;
  553. if(fixup_get_svalue(msg, (gparam_t*)cp, &_ca_path)!=0) {
  554. LM_ERR("unable to get method value\n");
  555. return -1;
  556. }
  557. if (ah_params.ca_path.s) {
  558. shm_free(ah_params.ca_path.s);
  559. ah_params.ca_path.s = NULL;
  560. ah_params.ca_path.len = 0;
  561. }
  562. if (_ca_path.s && _ca_path.len > 0) {
  563. if (shm_str_dup(&ah_params.ca_path, &_ca_path) < 0) {
  564. LM_ERR("Error allocating ah_params.ca_path\n");
  565. return -1;
  566. }
  567. }
  568. return 1;
  569. }
  570. /**
  571. *
  572. */
  573. static int fixup_http_async_get(void** param, int param_no)
  574. {
  575. if (param_no == 1) {
  576. return fixup_spve_null(param, 1);
  577. }
  578. if (param_no == 2) {
  579. return fixup_var_str_12(param, param_no);
  580. }
  581. LM_ERR("invalid parameter number <%d>\n", param_no);
  582. return -1;
  583. }
  584. /**
  585. *
  586. */
  587. static int fixup_http_async_post(void** param, int param_no)
  588. {
  589. if (param_no == 1 || param_no == 2) {
  590. return fixup_spve_null(param, 1);
  591. }
  592. if (param_no == 3) {
  593. return fixup_var_str_12(param, param_no);
  594. }
  595. LM_ERR("invalid parameter number <%d>\n", param_no);
  596. return -1;
  597. }
  598. /* module PVs */
  599. #define AH_WRAP_GET_PV(AH_F, PV_F) static int AH_F(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) \
  600. { \
  601. if (ah_reply) { \
  602. if (ah_error.s) { \
  603. LM_WARN("an async_http variable was read after http error, use $ah_ok to check the request's status\n"); \
  604. return pv_get_null(msg, param, res); \
  605. } else { \
  606. return pv_api.PV_F(ah_reply, param, res); \
  607. } \
  608. } else { \
  609. LM_ERR("the async_http variables can only be read from an async http worker\n"); \
  610. return pv_get_null(msg, param, res); \
  611. } \
  612. }
  613. AH_WRAP_GET_PV(ah_get_reason, get_reason)
  614. AH_WRAP_GET_PV(ah_get_hdr, get_hdr)
  615. AH_WRAP_GET_PV(ah_get_status, get_status)
  616. AH_WRAP_GET_PV(ah_get_msg_body, get_msg_body)
  617. AH_WRAP_GET_PV(ah_get_body_size, get_body_size)
  618. AH_WRAP_GET_PV(ah_get_msg_buf, get_msg_buf)
  619. AH_WRAP_GET_PV(ah_get_msg_len, get_msg_len)
  620. static int w_pv_parse_hdr_name(pv_spec_p sp, str *in) {
  621. return pv_api.parse_hdr_name(sp, in);
  622. }
  623. static int ah_get_ok(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
  624. if (ah_reply) {
  625. if (ah_error.s) {
  626. return pv_get_intstrval(msg, param, res, 0, &pv_str_0);
  627. } else {
  628. return pv_get_intstrval(msg, param, res, 1, &pv_str_1);
  629. }
  630. } else {
  631. LM_ERR("the async_http variables can only be read from an async http worker\n");
  632. return pv_get_null(msg, param, res);
  633. }
  634. }
  635. static int ah_get_err(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
  636. if (ah_reply) {
  637. if (ah_error.s) {
  638. return pv_get_strval(msg, param, res, &ah_error);
  639. } else {
  640. return pv_get_null(msg, param, res);
  641. }
  642. } else {
  643. LM_ERR("the async_http variables can only be read from an async http worker\n");
  644. return pv_get_null(msg, param, res);
  645. }
  646. }