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