WARNING: The online documentation has moved to https://docs.pjsip.org.

Visit the new documentation at https://docs.pjsip.org:

BLOG | DOCUMENTATION | GITHUB

Home --> Documentations --> PJSIP Reference

Samples: Simple UA

This is a very simple SIP User Agent application that only use PJSIP (without PJSIP-UA). It's able to make and receive call, and play media to the sound device.

1/*
2 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
3 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
4 *
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
53/* Include all headers. */
54#include <pjsip.h>
55#include <pjmedia.h>
56#include <pjmedia-codec.h>
57#include <pjsip_ua.h>
58#include <pjsip_simple.h>
59#include <pjlib-util.h>
60#include <pjlib.h>
61
62/* For logging purpose. */
63#define THIS_FILE "simpleua.c"
64
65#include "util.h"
66
67
68/* Settings */
69#define AF pj_AF_INET() /* Change to pj_AF_INET6() for IPv6.
70 * PJ_HAS_IPV6 must be enabled and
71 * your system must support IPv6. */
72#if 0
73#define SIP_PORT 5080 /* Listening SIP port */
74#define RTP_PORT 5000 /* RTP port */
75#else
76#define SIP_PORT 5060 /* Listening SIP port */
77#define RTP_PORT 4000 /* RTP port */
78#endif
79
80#define MAX_MEDIA_CNT 2 /* Media count, set to 1 for audio
81 * only or 2 for audio and video */
82
83/*
84 * Static variables.
85 */
86
87static pj_bool_t g_complete; /* Quit flag. */
88static pjsip_endpoint *g_endpt; /* SIP endpoint. */
89static pj_caching_pool cp; /* Global pool factory. */
90
91static pjmedia_endpt *g_med_endpt; /* Media endpoint. */
92
93static pjmedia_transport_info g_med_tpinfo[MAX_MEDIA_CNT];
94 /* Socket info for media */
95static pjmedia_transport *g_med_transport[MAX_MEDIA_CNT];
96 /* Media stream transport */
97static pjmedia_sock_info g_sock_info[MAX_MEDIA_CNT];
98 /* Socket info array */
99
100/* Call variables: */
101static pjsip_inv_session *g_inv; /* Current invite session. */
102static pjmedia_stream *g_med_stream; /* Call's audio stream. */
103static pjmedia_snd_port *g_snd_port; /* Sound device. */
104
105#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
106static pjmedia_vid_stream *g_med_vstream; /* Call's video stream. */
107static pjmedia_vid_port *g_vid_capturer;/* Call's video capturer. */
108static pjmedia_vid_port *g_vid_renderer;/* Call's video renderer. */
109#endif /* PJMEDIA_HAS_VIDEO */
110
111/*
112 * Prototypes:
113 */
114
115/* Callback to be called when SDP negotiation is done in the call: */
116static void call_on_media_update( pjsip_inv_session *inv,
117 pj_status_t status);
118
119/* Callback to be called when invite session's state has changed: */
120static void call_on_state_changed( pjsip_inv_session *inv,
121 pjsip_event *e);
122
123/* Callback to be called when dialog has forked: */
124static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e);
125
126/* Callback to be called to handle incoming requests outside dialogs: */
127static pj_bool_t on_rx_request( pjsip_rx_data *rdata );
128
129
130
131
132/* This is a PJSIP module to be registered by application to handle
133 * incoming requests outside any dialogs/transactions. The main purpose
134 * here is to handle incoming INVITE request message, where we will
135 * create a dialog and INVITE session for it.
136 */
137static pjsip_module mod_simpleua =
138{
139 NULL, NULL, /* prev, next. */
140 { "mod-simpleua", 12 }, /* Name. */
141 -1, /* Id */
142 PJSIP_MOD_PRIORITY_APPLICATION, /* Priority */
143 NULL, /* load() */
144 NULL, /* start() */
145 NULL, /* stop() */
146 NULL, /* unload() */
147 &on_rx_request, /* on_rx_request() */
148 NULL, /* on_rx_response() */
149 NULL, /* on_tx_request. */
150 NULL, /* on_tx_response() */
151 NULL, /* on_tsx_state() */
152};
153
154
155/* Notification on incoming messages */
156static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
157{
158 PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s %s:%d:\n"
159 "%.*s\n"
160 "--end msg--",
161 rdata->msg_info.len,
164 rdata->pkt_info.src_name,
165 rdata->pkt_info.src_port,
166 (int)rdata->msg_info.len,
167 rdata->msg_info.msg_buf));
168
169 /* Always return false, otherwise messages will not get processed! */
170 return PJ_FALSE;
171}
172
173/* Notification on outgoing messages */
174static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
175{
176
177 /* Important note:
178 * tp_info field is only valid after outgoing messages has passed
179 * transport layer. So don't try to access tp_info when the module
180 * has lower priority than transport layer.
181 */
182
183 PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s %s:%d:\n"
184 "%.*s\n"
185 "--end msg--",
186 (tdata->buf.cur - tdata->buf.start),
189 tdata->tp_info.dst_name,
190 tdata->tp_info.dst_port,
191 (int)(tdata->buf.cur - tdata->buf.start),
192 tdata->buf.start));
193
194 /* Always return success, otherwise message will not get sent! */
195 return PJ_SUCCESS;
196}
197
198/* The module instance. */
199static pjsip_module msg_logger =
200{
201 NULL, NULL, /* prev, next. */
202 { "mod-msg-log", 13 }, /* Name. */
203 -1, /* Id */
205 NULL, /* load() */
206 NULL, /* start() */
207 NULL, /* stop() */
208 NULL, /* unload() */
209 &logging_on_rx_msg, /* on_rx_request() */
210 &logging_on_rx_msg, /* on_rx_response() */
211 &logging_on_tx_msg, /* on_tx_request. */
212 &logging_on_tx_msg, /* on_tx_response() */
213 NULL, /* on_tsx_state() */
214
215};
216
217
218/*
219 * main()
220 *
221 * If called with argument, treat argument as SIP URL to be called.
222 * Otherwise wait for incoming calls.
223 */
224int main(int argc, char *argv[])
225{
226 pj_pool_t *pool = NULL;
227 pj_status_t status;
228 unsigned i;
229
230 /* Must init PJLIB first: */
231 status = pj_init();
232 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
233
235
236 /* Then init PJLIB-UTIL: */
237 status = pjlib_util_init();
238 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
239
240
241 /* Must create a pool factory before we can allocate any memory. */
243
244
245 /* Create global endpoint: */
246 {
247 const pj_str_t *hostname;
248 const char *endpt_name;
249
250 /* Endpoint MUST be assigned a globally unique name.
251 * The name will be used as the hostname in Warning header.
252 */
253
254 /* For this implementation, we'll use hostname for simplicity */
255 hostname = pj_gethostname();
256 endpt_name = hostname->ptr;
257
258 /* Create the endpoint: */
259
260 status = pjsip_endpt_create(&cp.factory, endpt_name,
261 &g_endpt);
262 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
263 }
264
265
266 /*
267 * Add UDP transport, with hard-coded port
268 * Alternatively, application can use pjsip_udp_transport_attach() to
269 * start UDP transport, if it already has an UDP socket (e.g. after it
270 * resolves the address with STUN).
271 */
272 {
273 pj_sockaddr addr;
274 int af = AF;
275
276 pj_sockaddr_init(af, &addr, NULL, (pj_uint16_t)SIP_PORT);
277
278 if (af == pj_AF_INET()) {
279 status = pjsip_udp_transport_start( g_endpt, &addr.ipv4, NULL,
280 1, NULL);
281 } else if (af == pj_AF_INET6()) {
282 status = pjsip_udp_transport_start6(g_endpt, &addr.ipv6, NULL,
283 1, NULL);
284 } else {
285 status = PJ_EAFNOTSUP;
286 }
287
288 if (status != PJ_SUCCESS) {
289 app_perror(THIS_FILE, "Unable to start UDP transport", status);
290 return 1;
291 }
292 }
293
294
295 /*
296 * Init transaction layer.
297 * This will create/initialize transaction hash tables etc.
298 */
299 status = pjsip_tsx_layer_init_module(g_endpt);
300 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
301
302
303 /*
304 * Initialize UA layer module.
305 * This will create/initialize dialog hash tables etc.
306 */
307 status = pjsip_ua_init_module( g_endpt, NULL );
308 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
309
310
311 /*
312 * Init invite session module.
313 * The invite session module initialization takes additional argument,
314 * i.e. a structure containing callbacks to be called on specific
315 * occurence of events.
316 *
317 * The on_state_changed and on_new_session callbacks are mandatory.
318 * Application must supply the callback function.
319 *
320 * We use on_media_update() callback in this application to start
321 * media transmission.
322 */
323 {
324 pjsip_inv_callback inv_cb;
325
326 /* Init the callback for INVITE session: */
327 pj_bzero(&inv_cb, sizeof(inv_cb));
328 inv_cb.on_state_changed = &call_on_state_changed;
329 inv_cb.on_new_session = &call_on_forked;
330 inv_cb.on_media_update = &call_on_media_update;
331
332 /* Initialize invite session module: */
333 status = pjsip_inv_usage_init(g_endpt, &inv_cb);
334 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
335 }
336
337 /* Initialize 100rel support */
338 status = pjsip_100rel_init_module(g_endpt);
339 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
340
341 /*
342 * Register our module to receive incoming requests.
343 */
344 status = pjsip_endpt_register_module( g_endpt, &mod_simpleua);
345 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
346
347 /*
348 * Register message logger module.
349 */
350 status = pjsip_endpt_register_module( g_endpt, &msg_logger);
351 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
352
353
354 /*
355 * Initialize media endpoint.
356 * This will implicitly initialize PJMEDIA too.
357 */
358#if PJ_HAS_THREADS
359 status = pjmedia_endpt_create(&cp.factory, NULL, 1, &g_med_endpt);
360#else
361 status = pjmedia_endpt_create(&cp.factory,
362 pjsip_endpt_get_ioqueue(g_endpt),
363 0, &g_med_endpt);
364#endif
365 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
366
367 /* Create pool. */
368 pool = pjmedia_endpt_create_pool(g_med_endpt, "Media pool", 512, 512);
369
370 /*
371 * Add PCMA/PCMU codec to the media endpoint.
372 */
373#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
374 status = pjmedia_codec_g711_init(g_med_endpt);
375 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
376#endif
377
378
379#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
380 /* Init video subsystem */
381 status = pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
382 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
383 status = pjmedia_converter_mgr_create(pool, NULL);
384 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
385 status = pjmedia_vid_codec_mgr_create(pool, NULL);
386 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
388 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
389
390#if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_VID_TOOLBOX_CODEC
391 status = pjmedia_codec_vid_toolbox_init(NULL, &cp.factory);
392 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
393#endif
394
395# if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
396 status = pjmedia_codec_openh264_vid_init(NULL, &cp.factory);
397 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
398# endif
399
400# if defined(PJMEDIA_HAS_VPX_CODEC) && PJMEDIA_HAS_VPX_CODEC != 0
401 status = pjmedia_codec_vpx_vid_init(NULL, &cp.factory);
402 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
403# endif
404
405# if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
406 /* Init ffmpeg video codecs */
407 status = pjmedia_codec_ffmpeg_vid_init(NULL, &cp.factory);
408 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
409# endif /* PJMEDIA_HAS_FFMPEG_VID_CODEC */
410
411#endif /* PJMEDIA_HAS_VIDEO */
412
413 /* Create event manager */
414 status = pjmedia_event_mgr_create(pool, 0, NULL);
415 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
416
417 /*
418 * Create media transport used to send/receive RTP/RTCP socket.
419 * One media transport is needed for each call. Application may
420 * opt to re-use the same media transport for subsequent calls.
421 */
422 for (i = 0; i < PJ_ARRAY_SIZE(g_med_transport); ++i) {
423 status = pjmedia_transport_udp_create3(g_med_endpt, AF, NULL, NULL,
424 RTP_PORT + i*2, 0,
425 &g_med_transport[i]);
426 if (status != PJ_SUCCESS) {
427 app_perror(THIS_FILE, "Unable to create media transport", status);
428 return 1;
429 }
430
431 /*
432 * Get socket info (address, port) of the media transport. We will
433 * need this info to create SDP (i.e. the address and port info in
434 * the SDP).
435 */
436 pjmedia_transport_info_init(&g_med_tpinfo[i]);
437 pjmedia_transport_get_info(g_med_transport[i], &g_med_tpinfo[i]);
438
439 pj_memcpy(&g_sock_info[i], &g_med_tpinfo[i].sock_info,
440 sizeof(pjmedia_sock_info));
441 }
442
443 /*
444 * If URL is specified, then make call immediately.
445 */
446 if (argc > 1) {
447 pj_sockaddr hostaddr;
448 char hostip[PJ_INET6_ADDRSTRLEN+2];
449 char temp[80];
450 pj_str_t dst_uri = pj_str(argv[1]);
451 pj_str_t local_uri;
452 pjsip_dialog *dlg;
453 pjmedia_sdp_session *local_sdp;
454 pjsip_tx_data *tdata;
455
456 if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) {
457 app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
458 return 1;
459 }
460 pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
461
462 pj_ansi_sprintf(temp, "<sip:simpleuac@%s:%d>",
463 hostip, SIP_PORT);
464 local_uri = pj_str(temp);
465
466 /* Create UAC dialog */
468 &local_uri, /* local URI */
469 &local_uri, /* local Contact */
470 &dst_uri, /* remote URI */
471 &dst_uri, /* remote target */
472 &dlg); /* dialog */
473 if (status != PJ_SUCCESS) {
474 app_perror(THIS_FILE, "Unable to create UAC dialog", status);
475 return 1;
476 }
477
478 /* If we expect the outgoing INVITE to be challenged, then we should
479 * put the credentials in the dialog here, with something like this:
480 *
481 {
482 pjsip_cred_info cred[1];
483
484 cred[0].realm = pj_str("sip.server.realm");
485 cred[0].scheme = pj_str("digest");
486 cred[0].username = pj_str("theuser");
487 cred[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
488 cred[0].data = pj_str("thepassword");
489
490 pjsip_auth_clt_set_credentials( &dlg->auth_sess, 1, cred);
491 }
492 *
493 */
494
495
496 /* Get the SDP body to be put in the outgoing INVITE, by asking
497 * media endpoint to create one for us.
498 */
499 status = pjmedia_endpt_create_sdp( g_med_endpt, /* the media endpt */
500 dlg->pool, /* pool. */
501 MAX_MEDIA_CNT, /* # of streams */
502 g_sock_info, /* RTP sock info */
503 &local_sdp); /* the SDP result */
504 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
505
506
507
508 /* Create the INVITE session, and pass the SDP returned earlier
509 * as the session's initial capability.
510 */
511 status = pjsip_inv_create_uac( dlg, local_sdp, 0, &g_inv);
512 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
513
514 /* If we want the initial INVITE to travel to specific SIP proxies,
515 * then we should put the initial dialog's route set here. The final
516 * route set will be updated once a dialog has been established.
517 * To set the dialog's initial route set, we do it with something
518 * like this:
519 *
520 {
521 pjsip_route_hdr route_set;
522 pjsip_route_hdr *route;
523 const pj_str_t hname = { "Route", 5 };
524 char *uri = "sip:proxy.server;lr";
525
526 pj_list_init(&route_set);
527
528 route = pjsip_parse_hdr( dlg->pool, &hname,
529 uri, strlen(uri),
530 NULL);
531 PJ_ASSERT_RETURN(route != NULL, 1);
532 pj_list_push_back(&route_set, route);
533
534 pjsip_dlg_set_route_set(dlg, &route_set);
535 }
536 *
537 * Note that Route URI SHOULD have an ";lr" parameter!
538 */
539
540 /* Create initial INVITE request.
541 * This INVITE request will contain a perfectly good request and
542 * an SDP body as well.
543 */
544 status = pjsip_inv_invite(g_inv, &tdata);
545 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
546
547
548
549 /* Send initial INVITE request.
550 * From now on, the invite session's state will be reported to us
551 * via the invite session callbacks.
552 */
553 status = pjsip_inv_send_msg(g_inv, tdata);
554 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
555
556
557 } else {
558
559 /* No URL to make call to */
560
561 PJ_LOG(3,(THIS_FILE, "Ready to accept incoming calls..."));
562 }
563
564
565 /* Loop until one call is completed */
566 for (;!g_complete;) {
567 pj_time_val timeout = {0, 10};
568 pjsip_endpt_handle_events(g_endpt, &timeout);
569 }
570
571 /* On exit, dump current memory usage: */
572 dump_pool_usage(THIS_FILE, &cp);
573
574 /* Destroy audio ports. Destroy the audio port first
575 * before the stream since the audio port has threads
576 * that get/put frames to the stream.
577 */
578 if (g_snd_port)
579 pjmedia_snd_port_destroy(g_snd_port);
580
581#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
582 /* Destroy video ports */
583 if (g_vid_capturer)
584 pjmedia_vid_port_destroy(g_vid_capturer);
585 if (g_vid_renderer)
586 pjmedia_vid_port_destroy(g_vid_renderer);
587#endif
588
589 /* Destroy streams */
590 if (g_med_stream)
591 pjmedia_stream_destroy(g_med_stream);
592#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
593 if (g_med_vstream)
594 pjmedia_vid_stream_destroy(g_med_vstream);
595
596 /* Deinit ffmpeg codec */
597# if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
599# endif
600# if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
602# endif
603# if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_VID_TOOLBOX_CODEC
605# endif
606# if defined(PJMEDIA_HAS_VPX_CODEC) && PJMEDIA_HAS_VPX_CODEC != 0
608# endif
609
610#endif
611
612 /* Destroy media transports */
613 for (i = 0; i < MAX_MEDIA_CNT; ++i) {
614 if (g_med_transport[i])
615 pjmedia_transport_close(g_med_transport[i]);
616 }
617
618 /* Destroy event manager */
620
621 /* Deinit pjmedia endpoint */
622 if (g_med_endpt)
623 pjmedia_endpt_destroy(g_med_endpt);
624
625 /* Deinit pjsip endpoint */
626 if (g_endpt)
627 pjsip_endpt_destroy(g_endpt);
628
629 /* Release pool */
630 if (pool)
631 pj_pool_release(pool);
632
633 return 0;
634}
635
636
637
638/*
639 * Callback when INVITE session state has changed.
640 * This callback is registered when the invite session module is initialized.
641 * We mostly want to know when the invite session has been disconnected,
642 * so that we can quit the application.
643 */
644static void call_on_state_changed( pjsip_inv_session *inv,
645 pjsip_event *e)
646{
647 PJ_UNUSED_ARG(e);
648
650
651 PJ_LOG(3,(THIS_FILE, "Call DISCONNECTED [reason=%d (%s)]",
652 inv->cause,
654
655 PJ_LOG(3,(THIS_FILE, "One call completed, application quitting..."));
656 g_complete = 1;
657
658 } else {
659
660 PJ_LOG(3,(THIS_FILE, "Call state changed to %s",
662
663 }
664}
665
666
667/* This callback is called when dialog has forked. */
668static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e)
669{
670 /* To be done... */
671 PJ_UNUSED_ARG(inv);
672 PJ_UNUSED_ARG(e);
673}
674
675
676/*
677 * Callback when incoming requests outside any transactions and any
678 * dialogs are received. We're only interested to hande incoming INVITE
679 * request, and we'll reject any other requests with 500 response.
680 */
681static pj_bool_t on_rx_request( pjsip_rx_data *rdata )
682{
683 pj_sockaddr hostaddr;
684 char temp[80], hostip[PJ_INET6_ADDRSTRLEN];
685 pj_str_t local_uri;
686 pjsip_dialog *dlg;
687 pjmedia_sdp_session *local_sdp;
688 pjsip_tx_data *tdata;
689 unsigned options = 0;
690 pj_status_t status;
691
692
693 /*
694 * Respond (statelessly) any non-INVITE requests with 500
695 */
697
698 if (rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) {
699 pj_str_t reason = pj_str("Simple UA unable to handle "
700 "this request");
701
702 pjsip_endpt_respond_stateless( g_endpt, rdata,
703 500, &reason,
704 NULL, NULL);
705 }
706 return PJ_TRUE;
707 }
708
709
710 /*
711 * Reject INVITE if we already have an INVITE session in progress.
712 */
713 if (g_inv) {
714
715 pj_str_t reason = pj_str("Another call is in progress");
716
717 pjsip_endpt_respond_stateless( g_endpt, rdata,
718 500, &reason,
719 NULL, NULL);
720 return PJ_TRUE;
721
722 }
723
724 /* Verify that we can handle the request. */
725 status = pjsip_inv_verify_request(rdata, &options, NULL, NULL,
726 g_endpt, NULL);
727 if (status != PJ_SUCCESS) {
728
729 pj_str_t reason = pj_str("Sorry Simple UA can not handle this INVITE");
730
731 pjsip_endpt_respond_stateless( g_endpt, rdata,
732 500, &reason,
733 NULL, NULL);
734 return PJ_TRUE;
735 }
736
737 /*
738 * Generate Contact URI
739 */
740 if (pj_gethostip(AF, &hostaddr) != PJ_SUCCESS) {
741 app_perror(THIS_FILE, "Unable to retrieve local host IP", status);
742 return PJ_TRUE;
743 }
744 pj_sockaddr_print(&hostaddr, hostip, sizeof(hostip), 2);
745
746 pj_ansi_sprintf(temp, "<sip:simpleuas@%s:%d>",
747 hostip, SIP_PORT);
748 local_uri = pj_str(temp);
749
750 /*
751 * Create UAS dialog.
752 */
754 rdata,
755 &local_uri, /* contact */
756 &dlg);
757 if (status != PJ_SUCCESS) {
758 pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL,
759 NULL, NULL);
760 return PJ_TRUE;
761 }
762
763 /*
764 * Get media capability from media endpoint:
765 */
766
767 status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool,
768 MAX_MEDIA_CNT, g_sock_info, &local_sdp);
769 pj_assert(status == PJ_SUCCESS);
770 if (status != PJ_SUCCESS) {
772 return PJ_TRUE;
773 }
774
775
776 /*
777 * Create invite session, and pass both the UAS dialog and the SDP
778 * capability to the session.
779 */
780 status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv);
781 pj_assert(status == PJ_SUCCESS);
782 if (status != PJ_SUCCESS) {
784 return PJ_TRUE;
785 }
786
787 /*
788 * Invite session has been created, decrement & release dialog lock.
789 */
791
792
793 /*
794 * Initially send 180 response.
795 *
796 * The very first response to an INVITE must be created with
797 * pjsip_inv_initial_answer(). Subsequent responses to the same
798 * transaction MUST use pjsip_inv_answer().
799 */
800 status = pjsip_inv_initial_answer(g_inv, rdata,
801 180,
802 NULL, NULL, &tdata);
804
805
806 /* Send the 180 response. */
807 status = pjsip_inv_send_msg(g_inv, tdata);
809
810
811 /*
812 * Now create 200 response.
813 */
814 status = pjsip_inv_answer( g_inv,
815 200, NULL, /* st_code and st_text */
816 NULL, /* SDP already specified */
817 &tdata);
819
820 /*
821 * Send the 200 response.
822 */
823 status = pjsip_inv_send_msg(g_inv, tdata);
825
826
827 /* Done.
828 * When the call is disconnected, it will be reported via the callback.
829 */
830
831 return PJ_TRUE;
832}
833
834
835
836/*
837 * Callback when SDP negotiation has completed.
838 * We are interested with this callback because we want to start media
839 * as soon as SDP negotiation is completed.
840 */
841static void call_on_media_update( pjsip_inv_session *inv,
842 pj_status_t status)
843{
844 pjmedia_stream_info stream_info;
845 const pjmedia_sdp_session *local_sdp;
846 const pjmedia_sdp_session *remote_sdp;
847 pjmedia_port *media_port;
848
849 if (status != PJ_SUCCESS) {
850
851 app_perror(THIS_FILE, "SDP negotiation has failed", status);
852
853 /* Here we should disconnect call if we're not in the middle
854 * of initializing an UAS dialog and if this is not a re-INVITE.
855 */
856 return;
857 }
858
859 /* Get local and remote SDP.
860 * We need both SDPs to create a media session.
861 */
862 status = pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp);
863
864 status = pjmedia_sdp_neg_get_active_remote(inv->neg, &remote_sdp);
865
866
867 /* Create stream info based on the media audio SDP. */
868 status = pjmedia_stream_info_from_sdp(&stream_info, inv->dlg->pool,
869 g_med_endpt,
870 local_sdp, remote_sdp, 0);
871 if (status != PJ_SUCCESS) {
872 app_perror(THIS_FILE,"Unable to create audio stream info",status);
873 return;
874 }
875
876 /* If required, we can also change some settings in the stream info,
877 * (such as jitter buffer settings, codec settings, etc) before we
878 * create the stream.
879 */
880
881 /* Create new audio media stream, passing the stream info, and also the
882 * media socket that we created earlier.
883 */
884 status = pjmedia_stream_create(g_med_endpt, inv->dlg->pool, &stream_info,
885 g_med_transport[0], NULL, &g_med_stream);
886 if (status != PJ_SUCCESS) {
887 app_perror( THIS_FILE, "Unable to create audio stream", status);
888 return;
889 }
890
891 /* Start the audio stream */
892 status = pjmedia_stream_start(g_med_stream);
893 if (status != PJ_SUCCESS) {
894 app_perror( THIS_FILE, "Unable to start audio stream", status);
895 return;
896 }
897
898 /* Start the UDP media transport */
899 pjmedia_transport_media_start(g_med_transport[0], 0, 0, 0, 0);
900
901 /* Get the media port interface of the audio stream.
902 * Media port interface is basicly a struct containing get_frame() and
903 * put_frame() function. With this media port interface, we can attach
904 * the port interface to conference bridge, or directly to a sound
905 * player/recorder device.
906 */
907 pjmedia_stream_get_port(g_med_stream, &media_port);
908
909 /* Create sound port */
911 PJMEDIA_AUD_DEFAULT_CAPTURE_DEV,
912 PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV,
913 PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */
914 PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */
915 PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/
916 PJMEDIA_PIA_BITS(&media_port->info),/* bits per sample */
917 0,
918 &g_snd_port);
919
920 if (status != PJ_SUCCESS) {
921 app_perror( THIS_FILE, "Unable to create sound port", status);
922 PJ_LOG(3,(THIS_FILE, "%d %d %d %d",
923 PJMEDIA_PIA_SRATE(&media_port->info),/* clock rate */
924 PJMEDIA_PIA_CCNT(&media_port->info),/* channel count */
925 PJMEDIA_PIA_SPF(&media_port->info), /* samples per frame*/
926 PJMEDIA_PIA_BITS(&media_port->info) /* bits per sample */
927 ));
928 return;
929 }
930
931 status = pjmedia_snd_port_connect(g_snd_port, media_port);
932
933
934 /* Get the media port interface of the second stream in the session,
935 * which is video stream. With this media port interface, we can attach
936 * the port directly to a renderer/capture video device.
937 */
938#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
939 if (local_sdp->media_count > 1) {
940 pjmedia_vid_stream_info vstream_info;
941 pjmedia_vid_port_param vport_param;
942
943 pjmedia_vid_port_param_default(&vport_param);
944
945 /* Create stream info based on the media video SDP. */
946 status = pjmedia_vid_stream_info_from_sdp(&vstream_info,
947 inv->dlg->pool, g_med_endpt,
948 local_sdp, remote_sdp, 1);
949 if (status != PJ_SUCCESS) {
950 app_perror(THIS_FILE,"Unable to create video stream info",status);
951 return;
952 }
953
954 /* If required, we can also change some settings in the stream info,
955 * (such as jitter buffer settings, codec settings, etc) before we
956 * create the video stream.
957 */
958
959 /* Create new video media stream, passing the stream info, and also the
960 * media socket that we created earlier.
961 */
962 status = pjmedia_vid_stream_create(g_med_endpt, NULL, &vstream_info,
963 g_med_transport[1], NULL,
964 &g_med_vstream);
965 if (status != PJ_SUCCESS) {
966 app_perror( THIS_FILE, "Unable to create video stream", status);
967 return;
968 }
969
970 /* Start the video stream */
971 status = pjmedia_vid_stream_start(g_med_vstream);
972 if (status != PJ_SUCCESS) {
973 app_perror( THIS_FILE, "Unable to start video stream", status);
974 return;
975 }
976
977 /* Start the UDP media transport */
978 pjmedia_transport_media_start(g_med_transport[1], 0, 0, 0, 0);
979
980 if (vstream_info.dir & PJMEDIA_DIR_DECODING) {
983 &vport_param.vidparam);
984 if (status != PJ_SUCCESS) {
985 app_perror(THIS_FILE, "Unable to get default param of video "
986 "renderer device", status);
987 return;
988 }
989
990 /* Get video stream port for decoding direction */
992 &media_port);
993
994 /* Set format */
995 pjmedia_format_copy(&vport_param.vidparam.fmt,
996 &media_port->info.fmt);
997 vport_param.vidparam.dir = PJMEDIA_DIR_RENDER;
998 vport_param.active = PJ_TRUE;
999
1000 /* Create renderer */
1001 status = pjmedia_vid_port_create(inv->pool, &vport_param,
1002 &g_vid_renderer);
1003 if (status != PJ_SUCCESS) {
1004 app_perror(THIS_FILE, "Unable to create video renderer device",
1005 status);
1006 return;
1007 }
1008
1009 /* Connect renderer to media_port */
1010 status = pjmedia_vid_port_connect(g_vid_renderer, media_port,
1011 PJ_FALSE);
1012 if (status != PJ_SUCCESS) {
1013 app_perror(THIS_FILE, "Unable to connect renderer to stream",
1014 status);
1015 return;
1016 }
1017 }
1018
1019 /* Create capturer */
1020 if (vstream_info.dir & PJMEDIA_DIR_ENCODING) {
1023 &vport_param.vidparam);
1024 if (status != PJ_SUCCESS) {
1025 app_perror(THIS_FILE, "Unable to get default param of video "
1026 "capture device", status);
1027 return;
1028 }
1029
1030 /* Get video stream port for decoding direction */
1032 &media_port);
1033
1034 /* Get capturer format from stream info */
1035 pjmedia_format_copy(&vport_param.vidparam.fmt,
1036 &media_port->info.fmt);
1037 vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE;
1038 vport_param.active = PJ_TRUE;
1039
1040 /* Create capturer */
1041 status = pjmedia_vid_port_create(inv->pool, &vport_param,
1042 &g_vid_capturer);
1043 if (status != PJ_SUCCESS) {
1044 app_perror(THIS_FILE, "Unable to create video capture device",
1045 status);
1046 return;
1047 }
1048
1049 /* Connect capturer to media_port */
1050 status = pjmedia_vid_port_connect(g_vid_capturer, media_port,
1051 PJ_FALSE);
1052 if (status != PJ_SUCCESS) {
1053 app_perror(THIS_FILE, "Unable to connect capturer to stream",
1054 status);
1055 return;
1056 }
1057 }
1058
1059 /* Start streaming */
1060 if (g_vid_renderer) {
1061 status = pjmedia_vid_port_start(g_vid_renderer);
1062 if (status != PJ_SUCCESS) {
1063 app_perror(THIS_FILE, "Unable to start video renderer",
1064 status);
1065 return;
1066 }
1067 }
1068 if (g_vid_capturer) {
1069 status = pjmedia_vid_port_start(g_vid_capturer);
1070 if (status != PJ_SUCCESS) {
1071 app_perror(THIS_FILE, "Unable to start video capturer",
1072 status);
1073 return;
1074 }
1075 }
1076 }
1077#endif /* PJMEDIA_HAS_VIDEO */
1078
1079 /* Done with media. */
1080}
1081
1082
pj_status_t pjlib_util_init(void)
pj_status_t pjmedia_codec_openh264_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_openh264_vid_deinit(void)
pj_status_t pjmedia_codec_ffmpeg_vid_deinit(void)
pj_status_t pjmedia_codec_ffmpeg_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_vid_toolbox_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_vid_toolbox_deinit(void)
pj_status_t pjmedia_codec_vpx_vid_init(pjmedia_vid_codec_mgr *mgr, pj_pool_factory *pf)
pj_status_t pjmedia_codec_vpx_vid_deinit(void)
pj_status_t pjmedia_converter_mgr_create(pj_pool_t *pool, pjmedia_converter_mgr **mgr)
pj_status_t pjmedia_event_mgr_create(pj_pool_t *pool, unsigned options, pjmedia_event_mgr **mgr)
void pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr)
pjmedia_format * pjmedia_format_copy(pjmedia_format *dst, const pjmedia_format *src)
pj_status_t pjmedia_video_format_mgr_create(pj_pool_t *pool, unsigned max_fmt, unsigned options, pjmedia_video_format_mgr **p_mgr)
unsigned PJMEDIA_PIA_BITS(const pjmedia_port_info *pia)
unsigned PJMEDIA_PIA_SPF(const pjmedia_port_info *pia)
unsigned PJMEDIA_PIA_CCNT(const pjmedia_port_info *pia)
unsigned PJMEDIA_PIA_SRATE(const pjmedia_port_info *pia)
pj_status_t pjmedia_sdp_neg_get_active_local(pjmedia_sdp_neg *neg, const pjmedia_sdp_session **local)
pj_status_t pjmedia_sdp_neg_get_active_remote(pjmedia_sdp_neg *neg, const pjmedia_sdp_session **remote)
pj_status_t pjmedia_stream_info_from_sdp(pjmedia_stream_info *si, pj_pool_t *pool, pjmedia_endpt *endpt, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote, unsigned stream_idx)
pj_status_t pjmedia_transport_udp_create3(pjmedia_endpt *endpt, int af, const char *name, const pj_str_t *addr, int port, unsigned options, pjmedia_transport **p_tp)
pj_status_t pjmedia_transport_close(pjmedia_transport *tp)
pj_status_t pjmedia_transport_get_info(pjmedia_transport *tp, pjmedia_transport_info *info)
pj_status_t pjmedia_transport_media_start(pjmedia_transport *tp, pj_pool_t *tmp_pool, const pjmedia_sdp_session *sdp_local, const pjmedia_sdp_session *sdp_remote, unsigned media_index)
void pjmedia_transport_info_init(pjmedia_transport_info *info)
struct pjmedia_endpt pjmedia_endpt
PJMEDIA_DIR_RENDER
PJMEDIA_DIR_ENCODING
PJMEDIA_DIR_CAPTURE
PJMEDIA_DIR_DECODING
void pjmedia_vid_port_destroy(pjmedia_vid_port *vid_port)
pj_status_t pjmedia_vid_port_connect(pjmedia_vid_port *vid_port, pjmedia_port *port, pj_bool_t destroy)
struct pjmedia_vid_port pjmedia_vid_port
pj_status_t pjmedia_vid_port_create(pj_pool_t *pool, const pjmedia_vid_port_param *prm, pjmedia_vid_port **p_vp)
void pjmedia_vid_port_param_default(pjmedia_vid_port_param *prm)
pj_status_t pjmedia_vid_port_start(pjmedia_vid_port *vid_port)
pj_status_t pjmedia_vid_codec_mgr_create(pj_pool_t *pool, pjmedia_vid_codec_mgr **mgr)
pj_status_t pjmedia_endpt_create(pj_pool_factory *pf, pj_ioqueue_t *ioqueue, unsigned worker_cnt, pjmedia_endpt **p_endpt)
pj_status_t pjmedia_endpt_create_sdp(pjmedia_endpt *endpt, pj_pool_t *pool, unsigned stream_cnt, const pjmedia_sock_info sock_info[], pjmedia_sdp_session **p_sdp)
pj_pool_t * pjmedia_endpt_create_pool(pjmedia_endpt *endpt, const char *name, pj_size_t initial, pj_size_t increment)
pj_status_t pjmedia_endpt_destroy(pjmedia_endpt *endpt)
pj_status_t pjmedia_codec_g711_init(pjmedia_endpt *endpt)
pj_status_t pjmedia_snd_port_connect(pjmedia_snd_port *snd_port, pjmedia_port *port)
pj_status_t pjmedia_snd_port_create(pj_pool_t *pool, int rec_id, int play_id, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, unsigned options, pjmedia_snd_port **p_port)
pj_status_t pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port)
struct pjmedia_snd_port pjmedia_snd_port
pj_status_t pjmedia_stream_create(pjmedia_endpt *endpt, pj_pool_t *pool, const pjmedia_stream_info *info, pjmedia_transport *tp, void *user_data, pjmedia_stream **p_stream)
pj_status_t pjmedia_stream_start(pjmedia_stream *stream)
pj_status_t pjmedia_stream_destroy(pjmedia_stream *stream)
pj_status_t pjmedia_stream_get_port(pjmedia_stream *stream, pjmedia_port **p_port)
pj_status_t pjmedia_vid_stream_info_from_sdp(pjmedia_vid_stream_info *si, pj_pool_t *pool, pjmedia_endpt *endpt, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote, unsigned stream_idx)
pj_status_t pjmedia_vid_stream_destroy(pjmedia_vid_stream *stream)
pj_status_t pjmedia_vid_stream_get_port(pjmedia_vid_stream *stream, pjmedia_dir dir, pjmedia_port **p_port)
pj_status_t pjmedia_vid_stream_start(pjmedia_vid_stream *stream)
pj_status_t pjmedia_vid_stream_create(pjmedia_endpt *endpt, pj_pool_t *pool, pjmedia_vid_stream_info *info, pjmedia_transport *tp, void *user_data, pjmedia_vid_stream **p_stream)
pj_status_t pjsip_100rel_init_module(pjsip_endpoint *endpt)
void pjsip_dlg_dec_lock(pjsip_dialog *dlg)
pj_status_t pjsip_dlg_create_uac(pjsip_user_agent *ua, const pj_str_t *local_uri, const pj_str_t *local_contact, const pj_str_t *remote_uri, const pj_str_t *target, pjsip_dialog **p_dlg)
pj_status_t pjsip_dlg_create_uas_and_inc_lock(pjsip_user_agent *ua, pjsip_rx_data *rdata, const pj_str_t *contact, pjsip_dialog **p_dlg)
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)
void pjsip_endpt_destroy(pjsip_endpoint *endpt)
pj_status_t pjsip_endpt_register_module(pjsip_endpoint *endpt, pjsip_module *module)
pj_ioqueue_t * pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt)
pj_status_t pjsip_endpt_handle_events(pjsip_endpoint *endpt, const pj_time_val *max_timeout)
pj_status_t pjsip_endpt_create(pj_pool_factory *pf, const char *name, pjsip_endpoint **endpt)
pj_status_t pjsip_inv_send_msg(pjsip_inv_session *inv, pjsip_tx_data *tdata)
const char * pjsip_inv_state_name(pjsip_inv_state state)
pj_status_t pjsip_inv_create_uas(pjsip_dialog *dlg, pjsip_rx_data *rdata, const pjmedia_sdp_session *local_sdp, unsigned options, pjsip_inv_session **p_inv)
pj_status_t pjsip_inv_create_uac(pjsip_dialog *dlg, const pjmedia_sdp_session *local_sdp, unsigned options, pjsip_inv_session **p_inv)
pj_status_t pjsip_inv_invite(pjsip_inv_session *inv, pjsip_tx_data **p_tdata)
pj_status_t pjsip_inv_initial_answer(pjsip_inv_session *inv, pjsip_rx_data *rdata, int st_code, const pj_str_t *st_text, const pjmedia_sdp_session *sdp, pjsip_tx_data **p_tdata)
pj_status_t pjsip_inv_verify_request(pjsip_rx_data *rdata, unsigned *options, const pjmedia_sdp_session *sdp, pjsip_dialog *dlg, pjsip_endpoint *endpt, pjsip_tx_data **tdata)
pj_status_t pjsip_inv_answer(pjsip_inv_session *inv, int st_code, const pj_str_t *st_text, const pjmedia_sdp_session *local_sdp, pjsip_tx_data **p_tdata)
pj_status_t pjsip_inv_usage_init(pjsip_endpoint *endpt, const pjsip_inv_callback *cb)
@ PJSIP_INV_STATE_DISCONNECTED
Definition: sip_inv.h:95
@ PJSIP_MOD_PRIORITY_APPLICATION
Definition: sip_module.h:210
@ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER
Definition: sip_module.h:190
const pj_str_t * pjsip_get_status_text(int status_code)
@ PJSIP_ACK_METHOD
Definition: sip_msg.h:58
@ PJSIP_INVITE_METHOD
Definition: sip_msg.h:56
pj_status_t pjsip_tsx_layer_init_module(pjsip_endpoint *endpt)
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)
pj_status_t pjsip_udp_transport_start6(pjsip_endpoint *endpt, const pj_sockaddr_in6 *local, const pjsip_host_port *a_name, unsigned async_cnt, pjsip_transport **p_transport)
char * pjsip_rx_data_get_info(pjsip_rx_data *rdata)
char * pjsip_tx_data_get_info(pjsip_tx_data *tdata)
struct pjsip_endpoint pjsip_endpoint
Definition: sip_types.h:111
pj_status_t pjsip_ua_init_module(pjsip_endpoint *endpt, const pjsip_ua_init_param *prm)
pjsip_user_agent * pjsip_ua_instance(void)
pj_status_t pj_init(void)
int pj_bool_t
unsigned short pj_uint16_t
int pj_status_t
#define PJ_ARRAY_SIZE(a)
PJ_SUCCESS
PJ_TRUE
PJ_FALSE
void pj_caching_pool_init(pj_caching_pool *ch_pool, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
#define PJ_LOG(level, arg)
void pj_log_set_level(int level)
pj_pool_factory_policy pj_pool_factory_default_policy
void pj_pool_release(pj_pool_t *pool)
void * pj_memcpy(void *dst, const void *src, pj_size_t size)
pj_str_t pj_str(char *str)
void pj_bzero(void *dst, pj_size_t size)
pj_status_t pj_sockaddr_init(int af, pj_sockaddr *addr, const pj_str_t *cp, pj_uint16_t port)
char * pj_sockaddr_print(const pj_sockaddr_t *addr, char *buf, int size, unsigned flags)
#define PJ_INET6_ADDRSTRLEN
const pj_str_t * pj_gethostname(void)
#define pj_AF_INET6()
#define pj_AF_INET()
pj_status_t pj_gethostip(int af, pj_sockaddr *addr)
#define pj_assert(expr)
#define PJ_ASSERT_RETURN(expr, retval)
#define PJ_UNUSED_ARG(arg)
#define PJ_EAFNOTSUP
pj_status_t pjmedia_vid_dev_default_param(pj_pool_t *pool, pjmedia_vid_dev_index id, pjmedia_vid_dev_param *param)
pj_status_t pjmedia_vid_dev_subsys_init(pj_pool_factory *pf)
PJMEDIA_VID_DEFAULT_CAPTURE_DEV
PJMEDIA_VID_DEFAULT_RENDER_DEV
SIP SIMPLE Extension.
pj_pool_factory factory
char * ptr
pjmedia_format fmt
pjmedia_port_info info
pjmedia_format fmt
pjmedia_vid_dev_param vidparam
char * start
Definition: sip_types.h:207
char * cur
Definition: sip_types.h:212
Definition: sip_dialog.h:136
pj_pool_t * pool
Definition: sip_dialog.h:142
Definition: sip_event.h:81
Definition: sip_inv.h:115
void(* on_new_session)(pjsip_inv_session *inv, pjsip_event *e)
Definition: sip_inv.h:141
void(* on_state_changed)(pjsip_inv_session *inv, pjsip_event *e)
Definition: sip_inv.h:127
void(* on_media_update)(pjsip_inv_session *inv_ses, pj_status_t status)
Definition: sip_inv.h:243
Definition: sip_inv.h:431
pjsip_status_code cause
Definition: sip_inv.h:440
pjsip_dialog * dlg
Definition: sip_inv.h:446
pjmedia_sdp_neg * neg
Definition: sip_inv.h:449
pjsip_inv_state state
Definition: sip_inv.h:436
pj_pool_t * pool
Definition: sip_inv.h:433
pjsip_method_e id
Definition: sip_msg.h:78
Definition: sip_module.h:54
struct pjsip_request_line req
Definition: sip_msg.h:868
union pjsip_msg::@19 line
pjsip_method method
Definition: sip_msg.h:434
Definition: sip_transport.h:295
pjsip_transport * transport
Definition: sip_transport.h:307
int src_port
Definition: sip_transport.h:346
struct pjsip_rx_data::@26 msg_info
char src_name[PJ_INET6_ADDRSTRLEN]
Definition: sip_transport.h:343
struct pjsip_rx_data::@25 pkt_info
struct pjsip_rx_data::@24 tp_info
pj_pool_t * pool
Definition: sip_transport.h:304
pj_ssize_t len
Definition: sip_transport.h:334
pjsip_msg * msg
Definition: sip_transport.h:364
char * msg_buf
Definition: sip_transport.h:358
char * type_name
Definition: sip_transport.h:821
Definition: sip_transport.h:522
char dst_name[PJ_INET6_ADDRSTRLEN]
Definition: sip_transport.h:614
pjsip_transport * transport
Definition: sip_transport.h:611
int dst_port
Definition: sip_transport.h:615
struct pjsip_tx_data::@29 tp_info
pjsip_buffer buf
Definition: sip_transport.h:568
pj_sockaddr_in6 ipv6
pj_sockaddr_in ipv4

 


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