BLOG | DOCUMENTATION | TRAC

Home --> Documentations --> PJSIP Reference

Samples: Stateless SIP Endpoint

This is about the simplest SIP application with PJSIP, all it does is respond all incoming requests with 501 (Not Implemented) response statelessly.

1 /* $Id: sipstateless.c 3553 2011-05-05 06:14:19Z nanang $ */
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 
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 */
47 static pjsip_endpoint *sip_endpt;
48 
49 /* What response code to be sent (default is 501/Not Implemented) */
50 static int code = PJSIP_SC_NOT_IMPLEMENTED;
51 
52 /* Additional header list */
53 struct pjsip_hdr hdr_list;
54 
55 /* usage() */
56 static 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. */
71 static 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  */
90 int 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. */
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");
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 }
pj_uint16_t sin_family
struct pjsip_request_line req
Definition: sip_msg.h:792
#define PJ_ASSERT_RETURN(expr, retval)
pj_in_addr sin_addr
int pj_bool_t
void pj_list_push_back(pj_list_type *list, pj_list_type *node)
pj_uint16_t sin_port
pjsip_method_e id
Definition: sip_msg.h:79
#define pj_AF_INET()
pj_status_t pjsip_endpt_respond_stateless(pjsip_endpoint *endpt, pjsip_rx_data *rdata, int st_code, const pj_str_t *st_text, const pjsip_hdr *hdr_list, const pjsip_msg_body *body)
pj_status_t pjsip_udp_transport_start(pjsip_endpoint *endpt, const pj_sockaddr_in *local, const pjsip_host_port *a_name, unsigned async_cnt, pjsip_transport **p_transport)
#define PJ_LOG(level, arg)
int pj_status_t
pj_uint16_t pj_htons(pj_uint16_t hostshort)
pj_str_t name
Definition: sip_msg.h:326
pj_pool_factory_policy pj_pool_factory_default_policy
pj_status_t pjsip_endpt_create(pj_pool_factory *pf, const char *name, pjsip_endpoint **endpt)
Definition: sip_msg.h:59
pj_status_t pjsip_endpt_handle_events(pjsip_endpoint *endpt, const pj_time_val *max_timeout)
pj_pool_factory factory
Definition: sip_transport.h:281
pj_status_t pjsip_endpt_register_module(pjsip_endpoint *endpt, pjsip_module *module)
pj_str_t pj_str(char *str)
pjsip_msg * msg
Definition: sip_transport.h:351
void pj_caching_pool_init(pj_caching_pool *ch_pool, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
struct pjsip_rx_data::@22 msg_info
PJ_BEGIN_DECL pj_status_t pjlib_util_init(void)
void pj_list_init(pj_list_type *node)
struct pjsip_endpoint pjsip_endpoint
Definition: sip_types.h:106
union pjsip_msg::@15 line
pj_uint32_t s_addr
Definition: sip_msg.h:993
pj_pool_t * pj_pool_create(pj_pool_factory *factory, const char *name, pj_size_t initial_size, pj_size_t increment_size, pj_pool_callback *callback)
Definition: sip_msg.h:324
Definition: sip_module.h:54
pjsip_generic_string_hdr * pjsip_generic_string_hdr_create(pj_pool_t *pool, const pj_str_t *hname, const pj_str_t *hvalue)
pj_status_t pj_init(void)
pjsip_method method
Definition: sip_msg.h:382
Definition: sip_module.h:211

 


PJSIP Open Source, high performance, small footprint, and very very portable SIP stack
Copyright (C) 2006-2008 Teluu Inc.