sipstateless.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. /**
  20. * sipcore.c
  21. *
  22. * A simple program to respond any incoming requests (except ACK, of course!)
  23. * with any status code (taken from command line argument, with the default
  24. * is 501/Not Implemented).
  25. */
  26. /* Include all headers. */
  27. #include <pjsip.h>
  28. #include <pjlib-util.h>
  29. #include <pjlib.h>
  30. /* If this macro is set, UDP transport will be initialized at port 5060 */
  31. #define HAS_UDP_TRANSPORT
  32. /* If this macro is set, TCP transport will be initialized at port 5060 */
  33. #define HAS_TCP_TRANSPORT (1 && PJ_HAS_TCP)
  34. /* Log identification */
  35. #define THIS_FILE "sipstateless.c"
  36. /* Global SIP endpoint */
  37. static pjsip_endpoint *sip_endpt;
  38. /* What response code to be sent (default is 501/Not Implemented) */
  39. static int code = PJSIP_SC_NOT_IMPLEMENTED;
  40. /* Additional header list */
  41. struct pjsip_hdr hdr_list;
  42. /* usage() */
  43. static void usage(void)
  44. {
  45. puts("Usage:");
  46. puts(" sipstateless [code] [-H HDR] ..");
  47. puts("");
  48. puts("Options:");
  49. puts(" code SIP status code to send (default: 501/Not Implemented");
  50. puts(" -H HDR Specify additional headers to send with response");
  51. puts(" This option may be specified more than once.");
  52. puts(" Example:");
  53. puts(" -H 'Expires: 300' -H 'Contact: <sip:localhost>'");
  54. }
  55. /* Callback to handle incoming requests. */
  56. static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
  57. {
  58. /* Respond (statelessly) all incoming requests (except ACK!)
  59. * with 501 (Not Implemented)
  60. */
  61. if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
  62. pjsip_endpt_respond_stateless( sip_endpt, rdata,
  63. code, NULL,
  64. &hdr_list, NULL);
  65. }
  66. return PJ_TRUE;
  67. }
  68. /*
  69. * main()
  70. *
  71. */
  72. int main(int argc, char *argv[])
  73. {
  74. pj_caching_pool cp;
  75. pj_pool_t *pool = NULL;
  76. pjsip_module mod_app =
  77. {
  78. NULL, NULL, /* prev, next. */
  79. { "mod-app", 7 }, /* Name. */
  80. -1, /* Id */
  81. PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
  82. NULL, /* load() */
  83. NULL, /* start() */
  84. NULL, /* stop() */
  85. NULL, /* unload() */
  86. &on_rx_request, /* on_rx_request() */
  87. NULL, /* on_rx_response() */
  88. NULL, /* on_tx_request. */
  89. NULL, /* on_tx_response() */
  90. NULL, /* on_tsx_state() */
  91. };
  92. int c;
  93. pj_status_t status;
  94. /* Must init PJLIB first: */
  95. status = pj_init();
  96. PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
  97. /* Then init PJLIB-UTIL: */
  98. status = pjlib_util_init();
  99. PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
  100. /* Must create a pool factory before we can allocate any memory. */
  101. pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
  102. /* Create global endpoint: */
  103. {
  104. /* Endpoint MUST be assigned a globally unique name.
  105. * Ideally we should put hostname or public IP address, but
  106. * we'll just use an arbitrary name here.
  107. */
  108. /* Create the endpoint: */
  109. status = pjsip_endpt_create(&cp.factory, "sipstateless",
  110. &sip_endpt);
  111. PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
  112. }
  113. /* Parse arguments */
  114. pj_optind = 0;
  115. pj_list_init(&hdr_list);
  116. while ((c=pj_getopt(argc, argv , "H:")) != -1) {
  117. switch (c) {
  118. case 'H':
  119. if (pool == NULL) {
  120. pool = pj_pool_create(&cp.factory, "sipstateless", 1000,
  121. 1000, NULL);
  122. }
  123. if (pool) {
  124. char *name;
  125. name = strtok(pj_optarg, ":");
  126. if (name == NULL) {
  127. puts("Error: invalid header format");
  128. return 1;
  129. } else {
  130. char *val = strtok(NULL, "\r\n");
  131. pjsip_generic_string_hdr *h;
  132. pj_str_t hname, hvalue;
  133. hname = pj_str(name);
  134. hvalue = pj_str(val);
  135. h = pjsip_generic_string_hdr_create(pool, &hname, &hvalue);
  136. pj_list_push_back(&hdr_list, h);
  137. PJ_LOG(4,(THIS_FILE, "Header %s: %s added", name, val));
  138. }
  139. }
  140. break;
  141. default:
  142. puts("Error: invalid argument");
  143. usage();
  144. return 1;
  145. }
  146. }
  147. if (pj_optind != argc) {
  148. code = atoi(argv[pj_optind]);
  149. if (code < 200 || code > 699) {
  150. puts("Error: invalid status code");
  151. usage();
  152. return 1;
  153. }
  154. }
  155. PJ_LOG(4,(THIS_FILE, "Returning %d to incoming requests", code));
  156. /*
  157. * Add UDP transport, with hard-coded port
  158. */
  159. #ifdef HAS_UDP_TRANSPORT
  160. {
  161. pj_sockaddr_in addr;
  162. addr.sin_family = pj_AF_INET();
  163. addr.sin_addr.s_addr = 0;
  164. addr.sin_port = pj_htons(5060);
  165. status = pjsip_udp_transport_start( sip_endpt, &addr, NULL, 1, NULL);
  166. if (status != PJ_SUCCESS) {
  167. PJ_LOG(3,(THIS_FILE,
  168. "Error starting UDP transport (port in use?)"));
  169. return 1;
  170. }
  171. }
  172. #endif
  173. #if HAS_TCP_TRANSPORT
  174. /*
  175. * Add UDP transport, with hard-coded port
  176. */
  177. {
  178. pj_sockaddr_in addr;
  179. addr.sin_family = pj_AF_INET();
  180. addr.sin_addr.s_addr = 0;
  181. addr.sin_port = pj_htons(5060);
  182. status = pjsip_tcp_transport_start(sip_endpt, &addr, 1, NULL);
  183. if (status != PJ_SUCCESS) {
  184. PJ_LOG(3,(THIS_FILE,
  185. "Error starting TCP transport (port in use?)"));
  186. return 1;
  187. }
  188. }
  189. #endif
  190. /*
  191. * Register our module to receive incoming requests.
  192. */
  193. status = pjsip_endpt_register_module( sip_endpt, &mod_app);
  194. PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
  195. /* Done. Loop forever to handle incoming events. */
  196. PJ_LOG(3,(THIS_FILE, "Press Ctrl-C to quit.."));
  197. for (;;) {
  198. pjsip_endpt_handle_events(sip_endpt, NULL);
  199. }
  200. }