blob: e33505e02c44f5c3e5b0a678932e9fbeb3648895 [file] [log] [blame]
Benny Prijonof9962132006-05-16 13:20:00 +00001/* $Id$ */
2/*
Benny Prijono32177c02008-06-20 22:44:47 +00003 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijonof9962132006-05-16 13:20:00 +00004 *
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/**
21 * sipcore.c
22 *
Benny Prijonoa2914f22007-02-18 01:50:01 +000023 * A simple program to respond any incoming requests (except ACK, of course!)
24 * with any status code (taken from command line argument, with the default
25 * is 501/Not Implemented).
Benny Prijonof9962132006-05-16 13:20:00 +000026 */
27
28
29/* Include all headers. */
30#include <pjsip.h>
31#include <pjlib-util.h>
32#include <pjlib.h>
33
34
35/* If this macro is set, UDP transport will be initialized at port 5060 */
36#define HAS_UDP_TRANSPORT
37
Benny Prijonoa2914f22007-02-18 01:50:01 +000038/* If this macro is set, TCP transport will be initialized at port 5060 */
Benny Prijono3569c0d2007-04-06 10:29:20 +000039#define HAS_TCP_TRANSPORT (1 && PJ_HAS_TCP)
Benny Prijonof9962132006-05-16 13:20:00 +000040
41/* Log identification */
42#define THIS_FILE "sipstateless.c"
43
44
45/* Global SIP endpoint */
46static pjsip_endpoint *sip_endpt;
47
Benny Prijono0deef102007-02-17 00:12:15 +000048/* What response code to be sent (default is 501/Not Implemented) */
49static int code = PJSIP_SC_NOT_IMPLEMENTED;
50
Benny Prijono6e68ee62008-04-22 18:32:53 +000051/* Additional header list */
52struct pjsip_hdr hdr_list;
53
54/* usage() */
55static void usage(void)
56{
57 puts("Usage:");
58 puts(" sipstateless [code] [-H HDR] ..");
59 puts("");
60 puts("Options:");
61 puts(" code SIP status code to send (default: 501/Not Implemented");
62 puts(" -H HDR Specify additional headers to send with response");
63 puts(" This option may be specified more than once.");
64 puts(" Example:");
65 puts(" -H 'Expires: 300' -H 'Contact: <sip:localhost>'");
66}
67
Benny Prijonof9962132006-05-16 13:20:00 +000068
69/* Callback to handle incoming requests. */
70static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
71{
72 /* Respond (statelessly) all incoming requests (except ACK!)
73 * with 501 (Not Implemented)
74 */
75 if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
76 pjsip_endpt_respond_stateless( sip_endpt, rdata,
Benny Prijono0deef102007-02-17 00:12:15 +000077 code, NULL,
Benny Prijono6e68ee62008-04-22 18:32:53 +000078 &hdr_list, NULL);
Benny Prijonof9962132006-05-16 13:20:00 +000079 }
80 return PJ_TRUE;
81}
82
83
84
85/*
86 * main()
87 *
88 */
Benny Prijono0deef102007-02-17 00:12:15 +000089int main(int argc, char *argv[])
Benny Prijonof9962132006-05-16 13:20:00 +000090{
91 pj_caching_pool cp;
Benny Prijono6e68ee62008-04-22 18:32:53 +000092 pj_pool_t *pool = NULL;
Benny Prijonof9962132006-05-16 13:20:00 +000093 pjsip_module mod_app =
94 {
95 NULL, NULL, /* prev, next. */
96 { "mod-app", 7 }, /* Name. */
97 -1, /* Id */
98 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
99 NULL, /* load() */
100 NULL, /* start() */
101 NULL, /* stop() */
102 NULL, /* unload() */
103 &on_rx_request, /* on_rx_request() */
104 NULL, /* on_rx_response() */
105 NULL, /* on_tx_request. */
106 NULL, /* on_tx_response() */
107 NULL, /* on_tsx_state() */
108 };
Benny Prijono6e68ee62008-04-22 18:32:53 +0000109 int c;
Benny Prijonof9962132006-05-16 13:20:00 +0000110 pj_status_t status;
111
112 /* Must init PJLIB first: */
113 status = pj_init();
114 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
115
116
117 /* Then init PJLIB-UTIL: */
118 status = pjlib_util_init();
119 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
120
121 /* Must create a pool factory before we can allocate any memory. */
122 pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
123
Benny Prijonof9962132006-05-16 13:20:00 +0000124 /* Create global endpoint: */
125 {
Benny Prijonof9962132006-05-16 13:20:00 +0000126 /* Endpoint MUST be assigned a globally unique name.
Benny Prijono1ec70b32006-06-20 15:39:07 +0000127 * Ideally we should put hostname or public IP address, but
128 * we'll just use an arbitrary name here.
Benny Prijonof9962132006-05-16 13:20:00 +0000129 */
130
Benny Prijonof9962132006-05-16 13:20:00 +0000131 /* Create the endpoint: */
Benny Prijono1ec70b32006-06-20 15:39:07 +0000132 status = pjsip_endpt_create(&cp.factory, "sipstateless",
Benny Prijonof9962132006-05-16 13:20:00 +0000133 &sip_endpt);
134 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
135 }
136
Benny Prijono6e68ee62008-04-22 18:32:53 +0000137 /* Parse arguments */
138 pj_optind = 0;
139 pj_list_init(&hdr_list);
140 while ((c=pj_getopt(argc, argv , "H:")) != -1) {
141 switch (c) {
142 case 'H':
143 if (pool == NULL) {
144 pool = pj_pool_create(&cp.factory, "sipstateless", 1000,
145 1000, NULL);
146 }
147
148 if (pool) {
149 char *name;
150 name = strtok(pj_optarg, ":");
151 if (name == NULL) {
152 puts("Error: invalid header format");
153 return 1;
154 } else {
155 char *val = strtok(NULL, "\r\n");
156 pjsip_generic_string_hdr *h;
157 pj_str_t hname, hvalue;
158
159 hname = pj_str(name);
160 hvalue = pj_str(val);
161
162 h = pjsip_generic_string_hdr_create(pool, &hname, &hvalue);
163
164 pj_list_push_back(&hdr_list, h);
165
166 PJ_LOG(4,(THIS_FILE, "Header %s: %s added", name, val));
167 }
168 }
169 break;
170 default:
171 puts("Error: invalid argument");
172 usage();
173 return 1;
174 }
175 }
176
177 if (pj_optind != argc) {
178 code = atoi(argv[pj_optind]);
179 if (code < 200 || code > 699) {
180 puts("Error: invalid status code");
181 usage();
182 return 1;
183 }
184 }
185
186 PJ_LOG(4,(THIS_FILE, "Returning %d to incoming requests", code));
187
188
Benny Prijonof9962132006-05-16 13:20:00 +0000189 /*
190 * Add UDP transport, with hard-coded port
191 */
192#ifdef HAS_UDP_TRANSPORT
193 {
194 pj_sockaddr_in addr;
195
Benny Prijono8ab968f2007-07-20 08:08:30 +0000196 addr.sin_family = pj_AF_INET();
Benny Prijonof9962132006-05-16 13:20:00 +0000197 addr.sin_addr.s_addr = 0;
198 addr.sin_port = pj_htons(5060);
199
200 status = pjsip_udp_transport_start( sip_endpt, &addr, NULL, 1, NULL);
201 if (status != PJ_SUCCESS) {
202 PJ_LOG(3,(THIS_FILE,
203 "Error starting UDP transport (port in use?)"));
204 return 1;
205 }
206 }
207#endif
208
Benny Prijono3569c0d2007-04-06 10:29:20 +0000209#if HAS_TCP_TRANSPORT
Benny Prijonoa2914f22007-02-18 01:50:01 +0000210 /*
211 * Add UDP transport, with hard-coded port
212 */
213 {
214 pj_sockaddr_in addr;
215
Benny Prijono8ab968f2007-07-20 08:08:30 +0000216 addr.sin_family = pj_AF_INET();
Benny Prijonoa2914f22007-02-18 01:50:01 +0000217 addr.sin_addr.s_addr = 0;
218 addr.sin_port = pj_htons(5060);
219
220 status = pjsip_tcp_transport_start(sip_endpt, &addr, 1, NULL);
221 if (status != PJ_SUCCESS) {
222 PJ_LOG(3,(THIS_FILE,
223 "Error starting TCP transport (port in use?)"));
224 return 1;
225 }
226 }
227#endif
228
Benny Prijonof9962132006-05-16 13:20:00 +0000229 /*
230 * Register our module to receive incoming requests.
231 */
232 status = pjsip_endpt_register_module( sip_endpt, &mod_app);
233 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
234
235
236 /* Done. Loop forever to handle incoming events. */
237 PJ_LOG(3,(THIS_FILE, "Press Ctrl-C to quit.."));
238
239 for (;;) {
240 pjsip_endpt_handle_events(sip_endpt, NULL);
241 }
242}