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.

00001 /* $Id: sipstateless.c 3553 2011-05-05 06:14:19Z nanang $ */
00002 /* 
00003  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
00004  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00019  */
00020 
00030 /* Include all headers. */
00031 #include <pjsip.h>
00032 #include <pjlib-util.h>
00033 #include <pjlib.h>
00034 
00035 
00036 /* If this macro is set, UDP transport will be initialized at port 5060 */
00037 #define HAS_UDP_TRANSPORT
00038 
00039 /* If this macro is set, TCP transport will be initialized at port 5060 */
00040 #define HAS_TCP_TRANSPORT   (1 && PJ_HAS_TCP)
00041 
00042 /* Log identification */
00043 #define THIS_FILE       "sipstateless.c"
00044 
00045 
00046 /* Global SIP endpoint */
00047 static pjsip_endpoint *sip_endpt;
00048 
00049 /* What response code to be sent (default is 501/Not Implemented) */
00050 static int code = PJSIP_SC_NOT_IMPLEMENTED;
00051 
00052 /* Additional header list */
00053 struct pjsip_hdr hdr_list;
00054 
00055 /* usage() */
00056 static void usage(void)
00057 {
00058     puts("Usage:");
00059     puts("  sipstateless [code] [-H HDR] ..");
00060     puts("");
00061     puts("Options:");
00062     puts("  code     SIP status code to send (default: 501/Not Implemented");
00063     puts("  -H HDR   Specify additional headers to send with response");
00064     puts("           This option may be specified more than once.");
00065     puts("           Example:");
00066     puts("              -H 'Expires: 300' -H 'Contact: <sip:localhost>'"); 
00067 }
00068 
00069 
00070 /* Callback to handle incoming requests. */
00071 static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
00072 {
00073     /* Respond (statelessly) all incoming requests (except ACK!) 
00074      * with 501 (Not Implemented)
00075      */
00076     if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
00077         pjsip_endpt_respond_stateless( sip_endpt, rdata, 
00078                                        code, NULL,
00079                                        &hdr_list, NULL);
00080     }
00081     return PJ_TRUE;
00082 }
00083 
00084 
00085 
00086 /*
00087  * main()
00088  *
00089  */
00090 int main(int argc, char *argv[])
00091 {
00092     pj_caching_pool cp;
00093     pj_pool_t *pool = NULL;
00094     pjsip_module mod_app =
00095     {
00096         NULL, NULL,                 /* prev, next.              */
00097         { "mod-app", 7 },           /* Name.                    */
00098         -1,                                 /* Id               */
00099         PJSIP_MOD_PRIORITY_APPLICATION, /* Priority             */
00100         NULL,                       /* load()                   */
00101         NULL,                       /* start()                  */
00102         NULL,                       /* stop()                   */
00103         NULL,                       /* unload()                 */
00104         &on_rx_request,             /* on_rx_request()          */
00105         NULL,                       /* on_rx_response()         */
00106         NULL,                       /* on_tx_request.           */
00107         NULL,                       /* on_tx_response()         */
00108         NULL,                       /* on_tsx_state()           */
00109     };
00110     int c;
00111     pj_status_t status;
00112     
00113     /* Must init PJLIB first: */
00114     status = pj_init();
00115     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00116 
00117 
00118     /* Then init PJLIB-UTIL: */
00119     status = pjlib_util_init();
00120     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00121 
00122     /* Must create a pool factory before we can allocate any memory. */
00123     pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
00124 
00125     /* Create global endpoint: */
00126     {
00127         /* Endpoint MUST be assigned a globally unique name.
00128          * Ideally we should put hostname or public IP address, but
00129          * we'll just use an arbitrary name here.
00130          */
00131 
00132         /* Create the endpoint: */
00133         status = pjsip_endpt_create(&cp.factory, "sipstateless", 
00134                                     &sip_endpt);
00135         PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00136     }
00137 
00138     /* Parse arguments */
00139     pj_optind = 0;
00140     pj_list_init(&hdr_list);
00141     while ((c=pj_getopt(argc, argv , "H:")) != -1) {
00142         switch (c) {
00143         case 'H':
00144             if (pool == NULL) {
00145                 pool = pj_pool_create(&cp.factory, "sipstateless", 1000, 
00146                                       1000, NULL);
00147             } 
00148             
00149             if (pool) {
00150                 char *name;
00151                 name = strtok(pj_optarg, ":");
00152                 if (name == NULL) {
00153                     puts("Error: invalid header format");
00154                     return 1;
00155                 } else {
00156                     char *val = strtok(NULL, "\r\n");
00157                     pjsip_generic_string_hdr *h;
00158                     pj_str_t hname, hvalue;
00159 
00160                     hname = pj_str(name);
00161                     hvalue = pj_str(val);
00162 
00163                     h = pjsip_generic_string_hdr_create(pool, &hname, &hvalue);
00164 
00165                     pj_list_push_back(&hdr_list, h);
00166 
00167                     PJ_LOG(4,(THIS_FILE, "Header %s: %s added", name, val));
00168                 }
00169             }
00170             break;
00171         default:
00172             puts("Error: invalid argument");
00173             usage();
00174             return 1;
00175         }
00176     }
00177 
00178     if (pj_optind != argc) {
00179         code = atoi(argv[pj_optind]);
00180         if (code < 200 || code > 699) {
00181             puts("Error: invalid status code");
00182             usage();
00183             return 1;
00184         }
00185     }
00186 
00187     PJ_LOG(4,(THIS_FILE, "Returning %d to incoming requests", code));
00188 
00189 
00190     /* 
00191      * Add UDP transport, with hard-coded port 
00192      */
00193 #ifdef HAS_UDP_TRANSPORT
00194     {
00195         pj_sockaddr_in addr;
00196 
00197         addr.sin_family = pj_AF_INET();
00198         addr.sin_addr.s_addr = 0;
00199         addr.sin_port = pj_htons(5060);
00200 
00201         status = pjsip_udp_transport_start( sip_endpt, &addr, NULL, 1, NULL);
00202         if (status != PJ_SUCCESS) {
00203             PJ_LOG(3,(THIS_FILE, 
00204                       "Error starting UDP transport (port in use?)"));
00205             return 1;
00206         }
00207     }
00208 #endif
00209 
00210 #if HAS_TCP_TRANSPORT
00211     /* 
00212      * Add UDP transport, with hard-coded port 
00213      */
00214     {
00215         pj_sockaddr_in addr;
00216 
00217         addr.sin_family = pj_AF_INET();
00218         addr.sin_addr.s_addr = 0;
00219         addr.sin_port = pj_htons(5060);
00220 
00221         status = pjsip_tcp_transport_start(sip_endpt, &addr, 1, NULL);
00222         if (status != PJ_SUCCESS) {
00223             PJ_LOG(3,(THIS_FILE, 
00224                       "Error starting TCP transport (port in use?)"));
00225             return 1;
00226         }
00227     }
00228 #endif
00229 
00230     /*
00231      * Register our module to receive incoming requests.
00232      */
00233     status = pjsip_endpt_register_module( sip_endpt, &mod_app);
00234     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
00235 
00236 
00237     /* Done. Loop forever to handle incoming events. */
00238     PJ_LOG(3,(THIS_FILE, "Press Ctrl-C to quit.."));
00239 
00240     for (;;) {
00241         pjsip_endpt_handle_events(sip_endpt, NULL);
00242     }
00243 }

 


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