blob: df88809d4013c977cacdf6850710f29e2294ba19 [file] [log] [blame]
Benny Prijonof9962132006-05-16 13:20:00 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
Benny Prijono32177c02008-06-20 22:44:47 +00004 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonof9962132006-05-16 13:20:00 +00005 *
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 *
Benny Prijonoa2914f22007-02-18 01:50:01 +000024 * 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).
Benny Prijonof9962132006-05-16 13:20:00 +000027 */
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
Benny Prijonoa2914f22007-02-18 01:50:01 +000039/* If this macro is set, TCP transport will be initialized at port 5060 */
Benny Prijono3569c0d2007-04-06 10:29:20 +000040#define HAS_TCP_TRANSPORT (1 && PJ_HAS_TCP)
Benny Prijonof9962132006-05-16 13:20:00 +000041
42/* Log identification */
43#define THIS_FILE "sipstateless.c"
44
45
46/* Global SIP endpoint */
47static pjsip_endpoint *sip_endpt;
48
Benny Prijono0deef102007-02-17 00:12:15 +000049/* What response code to be sent (default is 501/Not Implemented) */
50static int code = PJSIP_SC_NOT_IMPLEMENTED;
51
Benny Prijono6e68ee62008-04-22 18:32:53 +000052/* 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
Benny Prijonof9962132006-05-16 13:20:00 +000069
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,
Benny Prijono0deef102007-02-17 00:12:15 +000078 code, NULL,
Benny Prijono6e68ee62008-04-22 18:32:53 +000079 &hdr_list, NULL);
Benny Prijonof9962132006-05-16 13:20:00 +000080 }
81 return PJ_TRUE;
82}
83
84
85
86/*
87 * main()
88 *
89 */
Benny Prijono0deef102007-02-17 00:12:15 +000090int main(int argc, char *argv[])
Benny Prijonof9962132006-05-16 13:20:00 +000091{
92 pj_caching_pool cp;
Benny Prijono6e68ee62008-04-22 18:32:53 +000093 pj_pool_t *pool = NULL;
Benny Prijonof9962132006-05-16 13:20:00 +000094 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 };
Benny Prijono6e68ee62008-04-22 18:32:53 +0000110 int c;
Benny Prijonof9962132006-05-16 13:20:00 +0000111 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
Benny Prijonof9962132006-05-16 13:20:00 +0000125 /* Create global endpoint: */
126 {
Benny Prijonof9962132006-05-16 13:20:00 +0000127 /* Endpoint MUST be assigned a globally unique name.
Benny Prijono1ec70b32006-06-20 15:39:07 +0000128 * Ideally we should put hostname or public IP address, but
129 * we'll just use an arbitrary name here.
Benny Prijonof9962132006-05-16 13:20:00 +0000130 */
131
Benny Prijonof9962132006-05-16 13:20:00 +0000132 /* Create the endpoint: */
Benny Prijono1ec70b32006-06-20 15:39:07 +0000133 status = pjsip_endpt_create(&cp.factory, "sipstateless",
Benny Prijonof9962132006-05-16 13:20:00 +0000134 &sip_endpt);
135 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
136 }
137
Benny Prijono6e68ee62008-04-22 18:32:53 +0000138 /* 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
Benny Prijonof9962132006-05-16 13:20:00 +0000190 /*
191 * Add UDP transport, with hard-coded port
192 */
193#ifdef HAS_UDP_TRANSPORT
194 {
195 pj_sockaddr_in addr;
196
Benny Prijono8ab968f2007-07-20 08:08:30 +0000197 addr.sin_family = pj_AF_INET();
Benny Prijonof9962132006-05-16 13:20:00 +0000198 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
Benny Prijono3569c0d2007-04-06 10:29:20 +0000210#if HAS_TCP_TRANSPORT
Benny Prijonoa2914f22007-02-18 01:50:01 +0000211 /*
212 * Add UDP transport, with hard-coded port
213 */
214 {
215 pj_sockaddr_in addr;
216
Benny Prijono8ab968f2007-07-20 08:08:30 +0000217 addr.sin_family = pj_AF_INET();
Benny Prijonoa2914f22007-02-18 01:50:01 +0000218 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
Benny Prijonof9962132006-05-16 13:20:00 +0000230 /*
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}