functions.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * script functions of utils module
  3. *
  4. * Copyright (C) 2008 Juha Heinanen
  5. * Copyright (C) 2013-2015 Carsten Bock, ng-voice GmbH
  6. *
  7. * This file is part of Kamailio, a free SIP server.
  8. *
  9. * Kamailio is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * Kamailio 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. */
  24. /*!
  25. * \file
  26. * \brief Kamailio utils ::
  27. * \ingroup utils
  28. * Module: \ref utils
  29. */
  30. #include <curl/curl.h>
  31. #include "../../mod_fix.h"
  32. #include "../../pvar.h"
  33. #include "../../route_struct.h"
  34. #include "../../ut.h"
  35. #include "../../mem/mem.h"
  36. #include "../../parser/msg_parser.h"
  37. #include "../../lvalue.h"
  38. #include "utils.h"
  39. /*
  40. * curl write function that saves received data as zero terminated
  41. * to stream. Returns the amount of data taken care of.
  42. *
  43. * This function may be called multiple times for larger responses,
  44. * so it reallocs + concatenates the buffer as needed.
  45. */
  46. size_t write_function( void *ptr, size_t size, size_t nmemb, void *stream_ptr)
  47. {
  48. http_res_stream_t *stream = (http_res_stream_t *) stream_ptr;
  49. stream->buf = (char *) pkg_realloc(stream->buf, stream->curr_size +
  50. (size * nmemb));
  51. if (stream->buf == NULL) {
  52. LM_ERR("cannot allocate memory for stream\n");
  53. return CURLE_WRITE_ERROR;
  54. }
  55. memcpy(&stream->buf[stream->pos], (char *) ptr, (size * nmemb));
  56. stream->curr_size += (size * nmemb);
  57. stream->pos += (size * nmemb);
  58. return size * nmemb;
  59. }
  60. /*
  61. * Performs http_query and saves possible result (first body line of reply)
  62. * to pvar.
  63. */
  64. int http_query(struct sip_msg* _m, char* _url, char* _dst, char* _post)
  65. {
  66. CURL *curl;
  67. CURLcode res;
  68. str value, post_value;
  69. char *url, *at, *post;
  70. http_res_stream_t stream;
  71. long stat;
  72. pv_spec_t *dst;
  73. pv_value_t val;
  74. double download_size;
  75. memset(&stream, 0, sizeof(http_res_stream_t));
  76. if (fixup_get_svalue(_m, (gparam_p)_url, &value) != 0) {
  77. LM_ERR("cannot get page value\n");
  78. return -1;
  79. }
  80. curl = curl_easy_init();
  81. if (curl == NULL) {
  82. LM_ERR("failed to initialize curl\n");
  83. return -1;
  84. }
  85. url = pkg_malloc(value.len + 1);
  86. if (url == NULL) {
  87. curl_easy_cleanup(curl);
  88. LM_ERR("cannot allocate pkg memory for url\n");
  89. return -1;
  90. }
  91. memcpy(url, value.s, value.len);
  92. *(url + value.len) = (char)0;
  93. curl_easy_setopt(curl, CURLOPT_URL, url);
  94. if (_post) {
  95. /* Now specify we want to POST data */
  96. curl_easy_setopt(curl, CURLOPT_POST, 1L);
  97. if (fixup_get_svalue(_m, (gparam_p)_post, &post_value) != 0) {
  98. LM_ERR("cannot get post value\n");
  99. curl_easy_cleanup(curl);
  100. pkg_free(url);
  101. return -1;
  102. }
  103. post = pkg_malloc(post_value.len + 1);
  104. if (post == NULL) {
  105. curl_easy_cleanup(curl);
  106. pkg_free(url);
  107. LM_ERR("cannot allocate pkg memory for post\n");
  108. return -1;
  109. }
  110. memcpy(post, post_value.s, post_value.len);
  111. *(post + post_value.len) = (char)0;
  112. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
  113. }
  114. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
  115. curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)http_query_timeout);
  116. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);
  117. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream);
  118. res = curl_easy_perform(curl);
  119. pkg_free(url);
  120. if (_post) {
  121. pkg_free(post);
  122. }
  123. if (res != CURLE_OK) {
  124. /* http://curl.haxx.se/libcurl/c/libcurl-errors.html */
  125. if (res == CURLE_COULDNT_CONNECT) {
  126. LM_WARN("failed to connect() to host\n");
  127. } else if ( res == CURLE_COULDNT_RESOLVE_HOST ) {
  128. LM_WARN("couldn't resolve host\n");
  129. } else {
  130. LM_ERR("failed to perform curl (%d)\n", res);
  131. }
  132. curl_easy_cleanup(curl);
  133. if(stream.buf)
  134. pkg_free(stream.buf);
  135. return -1;
  136. }
  137. curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &stat);
  138. if ((stat >= 200) && (stat < 500)) {
  139. curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &download_size);
  140. LM_DBG("http_query download size: %u\n", (unsigned int)download_size);
  141. /* search for line feed */
  142. at = memchr(stream.buf, (char)10, download_size);
  143. if (at == NULL) {
  144. /* not found: use whole stream */
  145. at = stream.buf + (unsigned int)download_size;
  146. }
  147. val.rs.s = stream.buf;
  148. val.rs.len = at - stream.buf;
  149. LM_DBG("http_query result: %.*s\n", val.rs.len, val.rs.s);
  150. val.flags = PV_VAL_STR;
  151. dst = (pv_spec_t *)_dst;
  152. dst->setf(_m, &dst->pvp, (int)EQ_T, &val);
  153. }
  154. curl_easy_cleanup(curl);
  155. pkg_free(stream.buf);
  156. return stat;
  157. }