blob: 4851be5cf28e16b00e57c3f7b4c2361104b19497 [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $Id$ */
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#include <pjsip/sip_transport.h>
21#include <pjsip/sip_endpoint.h>
22#include <pjsip/sip_parser.h>
23#include <pjsip/sip_msg.h>
24#include <pjsip/sip_private.h>
25#include <pjsip/sip_errno.h>
26#include <pjsip/sip_module.h>
27#include <pj/addr_resolv.h>
28#include <pj/except.h>
29#include <pj/os.h>
30#include <pj/log.h>
31#include <pj/ioqueue.h>
32#include <pj/hash.h>
33#include <pj/string.h>
34#include <pj/pool.h>
35#include <pj/assert.h>
36#include <pj/lock.h>
37#include <pj/list.h>
38
39
40#define THIS_FILE "sip_transport.c"
41
42#if 0
43# define TRACE_(x) PJ_LOG(5,x)
44
45static const char *addr_string(const pj_sockaddr_t *addr)
46{
47 static char str[PJ_INET6_ADDRSTRLEN];
48 pj_inet_ntop(((const pj_sockaddr*)addr)->addr.sa_family,
49 pj_sockaddr_get_addr(addr),
50 str, sizeof(str));
51 return str;
52}
53#else
54# define TRACE_(x)
55#endif
56
57/* Prototype. */
58static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata);
59
60/* This module has sole purpose to print transmit data to contigous buffer
61 * before actually transmitted to the wire.
62 */
63static pjsip_module mod_msg_print =
64{
65 NULL, NULL, /* prev and next */
66 { "mod-msg-print", 13}, /* Name. */
67 -1, /* Id */
68 PJSIP_MOD_PRIORITY_TRANSPORT_LAYER, /* Priority */
69 NULL, /* load() */
70 NULL, /* start() */
71 NULL, /* stop() */
72 NULL, /* unload() */
73 NULL, /* on_rx_request() */
74 NULL, /* on_rx_response() */
75 &mod_on_tx_msg, /* on_tx_request() */
76 &mod_on_tx_msg, /* on_tx_response() */
77 NULL, /* on_tsx_state() */
78};
79
80/*
81 * Transport manager.
82 */
83struct pjsip_tpmgr
84{
85 pj_hash_table_t *table;
86 pj_lock_t *lock;
87 pjsip_endpoint *endpt;
88 pjsip_tpfactory factory_list;
89#if defined(PJ_DEBUG) && PJ_DEBUG!=0
90 pj_atomic_t *tdata_counter;
91#endif
92 void (*on_rx_msg)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*);
93 pj_status_t (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*);
94 pjsip_tp_state_callback tp_state_cb;
95
96 /* Transmit data list, for transmit data cleanup when transport manager
97 * is destroyed.
98 */
99 pjsip_tx_data tdata_list;
100};
101
102
103/* Transport state listener list type */
104typedef struct tp_state_listener
105{
106 PJ_DECL_LIST_MEMBER(struct tp_state_listener);
107
108 pjsip_tp_state_callback cb;
109 void *user_data;
110} tp_state_listener;
111
112
113/*
114 * Transport data.
115 */
116typedef struct transport_data
117{
118 /* Transport listeners */
119 tp_state_listener st_listeners;
120 tp_state_listener st_listeners_empty;
121} transport_data;
122
123
124/*****************************************************************************
125 *
126 * GENERAL TRANSPORT (NAMES, TYPES, ETC.)
127 *
128 *****************************************************************************/
129
130/*
131 * Transport names.
132 */
133struct transport_names_t
134{
135 pjsip_transport_type_e type; /* Transport type */
136 pj_uint16_t port; /* Default port number */
137 pj_str_t name; /* Id tag */
138 const char *description; /* Longer description */
139 unsigned flag; /* Flags */
140 char name_buf[16]; /* For user's transport */
141} transport_names[16] =
142{
143 {
144 PJSIP_TRANSPORT_UNSPECIFIED,
145 0,
146 {"Unspecified", 11},
147 "Unspecified",
148 0
149 },
150 {
151 PJSIP_TRANSPORT_UDP,
152 5060,
153 {"UDP", 3},
154 "UDP transport",
155 PJSIP_TRANSPORT_DATAGRAM
156 },
157 {
158 PJSIP_TRANSPORT_TCP,
159 5060,
160 {"TCP", 3},
161 "TCP transport",
162 PJSIP_TRANSPORT_RELIABLE
163 },
164 {
165 PJSIP_TRANSPORT_TLS,
166 5061,
167 {"TLS", 3},
168 "TLS transport",
169 PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE
170 },
171 {
172 PJSIP_TRANSPORT_SCTP,
173 5060,
174 {"SCTP", 4},
175 "SCTP transport",
176 PJSIP_TRANSPORT_RELIABLE
177 },
178 {
179 PJSIP_TRANSPORT_LOOP,
180 15060,
181 {"LOOP", 4},
182 "Loopback transport",
183 PJSIP_TRANSPORT_RELIABLE
184 },
185 {
186 PJSIP_TRANSPORT_LOOP_DGRAM,
187 15060,
188 {"LOOP-DGRAM", 10},
189 "Loopback datagram transport",
190 PJSIP_TRANSPORT_DATAGRAM
191 },
192 {
193 PJSIP_TRANSPORT_UDP6,
194 5060,
195 {"UDP", 3},
196 "UDP IPv6 transport",
197 PJSIP_TRANSPORT_DATAGRAM
198 },
199 {
200 PJSIP_TRANSPORT_TCP6,
201 5060,
202 {"TCP", 3},
203 "TCP IPv6 transport",
204 PJSIP_TRANSPORT_RELIABLE
205 },
206 {
207 PJSIP_TRANSPORT_TLS6,
208 5061,
209 {"TLS", 3},
210 "TLS IPv6 transport",
211 PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE
212 },
213};
214
215static void tp_state_callback(pjsip_transport *tp,
216 pjsip_transport_state state,
217 const pjsip_transport_state_info *info);
218
219
220struct transport_names_t *get_tpname(pjsip_transport_type_e type)
221{
222 unsigned i;
223 for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
224 if (transport_names[i].type == type)
225 return &transport_names[i];
226 }
227 pj_assert(!"Invalid transport type!");
228 return NULL;
229}
230
231
232
233/*
234 * Register new transport type to PJSIP.
235 */
236PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag,
237 const char *tp_name,
238 int def_port,
239 int *p_tp_type)
240{
241 unsigned i;
242
243 PJ_ASSERT_RETURN(tp_flag && tp_name && def_port, PJ_EINVAL);
244 PJ_ASSERT_RETURN(pj_ansi_strlen(tp_name) <
245 PJ_ARRAY_SIZE(transport_names[0].name_buf),
246 PJ_ENAMETOOLONG);
247
248 for (i=1; i<PJ_ARRAY_SIZE(transport_names); ++i) {
249 if (transport_names[i].type == 0)
250 break;
251 }
252
253 if (i == PJ_ARRAY_SIZE(transport_names))
254 return PJ_ETOOMANY;
255
256 transport_names[i].type = (pjsip_transport_type_e)i;
257 transport_names[i].port = (pj_uint16_t)def_port;
258 pj_ansi_strcpy(transport_names[i].name_buf, tp_name);
259 transport_names[i].name = pj_str(transport_names[i].name_buf);
260 transport_names[i].flag = tp_flag;
261
262 if (p_tp_type)
263 *p_tp_type = i;
264
265 return PJ_SUCCESS;
266}
267
268
269/*
270 * Get transport type from name.
271 */
272PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_name(const pj_str_t *name)
273{
274 unsigned i;
275
276 if (name->slen == 0)
277 return PJSIP_TRANSPORT_UNSPECIFIED;
278
279 /* Get transport type from name. */
280 for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
281 if (pj_stricmp(name, &transport_names[i].name) == 0) {
282 return transport_names[i].type;
283 }
284 }
285
286 pj_assert(!"Invalid transport name");
287 return PJSIP_TRANSPORT_UNSPECIFIED;
288}
289
290
291/*
292 * Get the transport type for the specified flags.
293 */
294PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_flag(unsigned flag)
295{
296 unsigned i;
297
298 /* Get the transport type for the specified flags. */
299 for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
300 if (transport_names[i].flag == flag) {
301 return transport_names[i].type;
302 }
303 }
304
305 pj_assert(!"Invalid transport type");
306 return PJSIP_TRANSPORT_UNSPECIFIED;
307}
308
309/*
310 * Get the socket address family of a given transport type.
311 */
312PJ_DEF(int) pjsip_transport_type_get_af(pjsip_transport_type_e type)
313{
314 if (type & PJSIP_TRANSPORT_IPV6)
315 return pj_AF_INET6();
316 else
317 return pj_AF_INET();
318}
319
320PJ_DEF(unsigned) pjsip_transport_get_flag_from_type(pjsip_transport_type_e type)
321{
322 /* Return transport flag. */
323 return get_tpname(type)->flag;
324}
325
326/*
327 * Get the default SIP port number for the specified type.
328 */
329PJ_DEF(int) pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type)
330{
331 /* Return the port. */
332 return get_tpname(type)->port;
333}
334
335/*
336 * Get transport name.
337 */
338PJ_DEF(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e type)
339{
340 /* Return the name. */
341 return get_tpname(type)->name.ptr;
342}
343
344/*
345 * Get transport description.
346 */
347PJ_DEF(const char*) pjsip_transport_get_type_desc(pjsip_transport_type_e type)
348{
349 /* Return the description. */
350 return get_tpname(type)->description;
351}
352
353
354/*****************************************************************************
355 *
356 * TRANSPORT SELECTOR
357 *
358 *****************************************************************************/
359
360/*
361 * Add transport/listener reference in the selector.
362 */
363PJ_DEF(void) pjsip_tpselector_add_ref(pjsip_tpselector *sel)
364{
365 if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL)
366 pjsip_transport_add_ref(sel->u.transport);
367 else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL)
368 ; /* Hmm.. looks like we don't have reference counter for listener */
369}
370
371
372/*
373 * Decrement transport/listener reference in the selector.
374 */
375PJ_DEF(void) pjsip_tpselector_dec_ref(pjsip_tpselector *sel)
376{
377 if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL)
378 pjsip_transport_dec_ref(sel->u.transport);
379 else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL)
380 ; /* Hmm.. looks like we don't have reference counter for listener */
381}
382
383
384/*****************************************************************************
385 *
386 * TRANSMIT DATA BUFFER MANIPULATION.
387 *
388 *****************************************************************************/
389
390/*
391 * Create new transmit buffer.
392 */
393PJ_DEF(pj_status_t) pjsip_tx_data_create( pjsip_tpmgr *mgr,
394 pjsip_tx_data **p_tdata )
395{
396 pj_pool_t *pool;
397 pjsip_tx_data *tdata;
398 pj_status_t status;
399
400 PJ_ASSERT_RETURN(mgr && p_tdata, PJ_EINVAL);
401
402 pool = pjsip_endpt_create_pool( mgr->endpt, "tdta%p",
403 PJSIP_POOL_LEN_TDATA,
404 PJSIP_POOL_INC_TDATA );
405 if (!pool)
406 return PJ_ENOMEM;
407
408 tdata = PJ_POOL_ZALLOC_T(pool, pjsip_tx_data);
409 tdata->pool = pool;
410 tdata->mgr = mgr;
411 pj_memcpy(tdata->obj_name, pool->obj_name, PJ_MAX_OBJ_NAME);
412
413 status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt);
414 if (status != PJ_SUCCESS) {
415 pjsip_endpt_release_pool( mgr->endpt, tdata->pool );
416 return status;
417 }
418
419 //status = pj_lock_create_simple_mutex(pool, "tdta%p", &tdata->lock);
420 status = pj_lock_create_null_mutex(pool, "tdta%p", &tdata->lock);
421 if (status != PJ_SUCCESS) {
422 pjsip_endpt_release_pool( mgr->endpt, tdata->pool );
423 return status;
424 }
425
426 pj_ioqueue_op_key_init(&tdata->op_key.key, sizeof(tdata->op_key.key));
427 pj_list_init(tdata);
428
429#if defined(PJSIP_HAS_TX_DATA_LIST) && PJSIP_HAS_TX_DATA_LIST!=0
430 /* Append this just created tdata to transmit buffer list */
431 pj_lock_acquire(mgr->lock);
432 pj_list_push_back(&mgr->tdata_list, tdata);
433 pj_lock_release(mgr->lock);
434#endif
435
436#if defined(PJ_DEBUG) && PJ_DEBUG!=0
437 pj_atomic_inc( tdata->mgr->tdata_counter );
438#endif
439
440 *p_tdata = tdata;
441 return PJ_SUCCESS;
442}
443
444
445/*
446 * Add reference to tx buffer.
447 */
448PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata )
449{
450 pj_atomic_inc(tdata->ref_cnt);
451}
452
453static void tx_data_destroy(pjsip_tx_data *tdata)
454{
455 PJ_LOG(5,(tdata->obj_name, "Destroying txdata %s",
456 pjsip_tx_data_get_info(tdata)));
457 pjsip_tpselector_dec_ref(&tdata->tp_sel);
458#if defined(PJ_DEBUG) && PJ_DEBUG!=0
459 pj_atomic_dec( tdata->mgr->tdata_counter );
460#endif
461
462#if defined(PJSIP_HAS_TX_DATA_LIST) && PJSIP_HAS_TX_DATA_LIST!=0
463 /* Remove this tdata from transmit buffer list */
464 pj_lock_acquire(tdata->mgr->lock);
465 pj_list_erase(tdata);
466 pj_lock_release(tdata->mgr->lock);
467#endif
468
469 pj_atomic_destroy( tdata->ref_cnt );
470 pj_lock_destroy( tdata->lock );
471 pjsip_endpt_release_pool( tdata->mgr->endpt, tdata->pool );
472}
473
474/*
475 * Decrease transport data reference, destroy it when the reference count
476 * reaches zero.
477 */
478PJ_DEF(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata )
479{
480 pj_assert( pj_atomic_get(tdata->ref_cnt) > 0);
481 if (pj_atomic_dec_and_get(tdata->ref_cnt) <= 0) {
482 tx_data_destroy(tdata);
483 return PJSIP_EBUFDESTROYED;
484 } else {
485 return PJ_SUCCESS;
486 }
487}
488
489/*
490 * Invalidate the content of the print buffer to force the message to be
491 * re-printed when sent.
492 */
493PJ_DEF(void) pjsip_tx_data_invalidate_msg( pjsip_tx_data *tdata )
494{
495 tdata->buf.cur = tdata->buf.start;
496 tdata->info = NULL;
497}
498
499/*
500 * Print the SIP message to transmit data buffer's internal buffer.
501 */
502PJ_DEF(pj_status_t) pjsip_tx_data_encode(pjsip_tx_data *tdata)
503{
504 /* Allocate buffer if necessary. */
505 if (tdata->buf.start == NULL) {
506 PJ_USE_EXCEPTION;
507
508 PJ_TRY {
509 tdata->buf.start = (char*)
510 pj_pool_alloc(tdata->pool, PJSIP_MAX_PKT_LEN);
511 }
512 PJ_CATCH_ANY {
513 return PJ_ENOMEM;
514 }
515 PJ_END
516
517 tdata->buf.cur = tdata->buf.start;
518 tdata->buf.end = tdata->buf.start + PJSIP_MAX_PKT_LEN;
519 }
520
521 /* Do we need to reprint? */
522 if (!pjsip_tx_data_is_valid(tdata)) {
523 pj_ssize_t size;
524
525 size = pjsip_msg_print( tdata->msg, tdata->buf.start,
526 tdata->buf.end - tdata->buf.start);
527 if (size < 0) {
528 return PJSIP_EMSGTOOLONG;
529 }
530 pj_assert(size != 0);
531 tdata->buf.cur[size] = '\0';
532 tdata->buf.cur += size;
533 }
534
535 return PJ_SUCCESS;
536}
537
538PJ_DEF(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata )
539{
540 return tdata->buf.cur != tdata->buf.start;
541}
542
543static char *get_msg_info(pj_pool_t *pool, const char *obj_name,
544 const pjsip_msg *msg)
545{
546 char info_buf[128], *info;
547 const pjsip_cseq_hdr *cseq;
548 int len;
549
550 cseq = (const pjsip_cseq_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL);
551 PJ_ASSERT_RETURN(cseq != NULL, "INVALID MSG");
552
553 if (msg->type == PJSIP_REQUEST_MSG) {
554 len = pj_ansi_snprintf(info_buf, sizeof(info_buf),
555 "Request msg %.*s/cseq=%d (%s)",
556 (int)msg->line.req.method.name.slen,
557 msg->line.req.method.name.ptr,
558 cseq->cseq, obj_name);
559 } else {
560 len = pj_ansi_snprintf(info_buf, sizeof(info_buf),
561 "Response msg %d/%.*s/cseq=%d (%s)",
562 msg->line.status.code,
563 (int)cseq->method.name.slen,
564 cseq->method.name.ptr,
565 cseq->cseq, obj_name);
566 }
567
568 if (len < 1 || len >= (int)sizeof(info_buf)) {
569 return (char*)obj_name;
570 }
571
572 info = (char*) pj_pool_alloc(pool, len+1);
573 pj_memcpy(info, info_buf, len+1);
574
575 return info;
576}
577
578PJ_DEF(char*) pjsip_tx_data_get_info( pjsip_tx_data *tdata )
579{
580 PJ_ASSERT_RETURN(tdata, "NULL");
581
582 /* tdata->info may be assigned by application so if it exists
583 * just return it.
584 */
585 if (tdata->info)
586 return tdata->info;
587
588 if (tdata->msg==NULL)
589 return "NULL";
590
591 pj_lock_acquire(tdata->lock);
592 tdata->info = get_msg_info(tdata->pool, tdata->obj_name, tdata->msg);
593 pj_lock_release(tdata->lock);
594
595 return tdata->info;
596}
597
598PJ_DEF(pj_status_t) pjsip_tx_data_set_transport(pjsip_tx_data *tdata,
599 const pjsip_tpselector *sel)
600{
601 PJ_ASSERT_RETURN(tdata && sel, PJ_EINVAL);
602
603 pj_lock_acquire(tdata->lock);
604
605 pjsip_tpselector_dec_ref(&tdata->tp_sel);
606
607 pj_memcpy(&tdata->tp_sel, sel, sizeof(*sel));
608 pjsip_tpselector_add_ref(&tdata->tp_sel);
609
610 pj_lock_release(tdata->lock);
611
612 return PJ_SUCCESS;
613}
614
615
616PJ_DEF(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata)
617{
618 char obj_name[PJ_MAX_OBJ_NAME];
619
620 PJ_ASSERT_RETURN(rdata->msg_info.msg, "INVALID MSG");
621
622 if (rdata->msg_info.info)
623 return rdata->msg_info.info;
624
625 pj_ansi_strcpy(obj_name, "rdata");
626 pj_ansi_snprintf(obj_name+5, sizeof(obj_name)-5, "%p", rdata);
627
628 rdata->msg_info.info = get_msg_info(rdata->tp_info.pool, obj_name,
629 rdata->msg_info.msg);
630 return rdata->msg_info.info;
631}
632
633/* Clone pjsip_rx_data. */
634PJ_DEF(pj_status_t) pjsip_rx_data_clone( const pjsip_rx_data *src,
635 unsigned flags,
636 pjsip_rx_data **p_rdata)
637{
638 pj_pool_t *pool;
639 pjsip_rx_data *dst;
640 pjsip_hdr *hdr;
641
642 PJ_ASSERT_RETURN(src && flags==0 && p_rdata, PJ_EINVAL);
643
644 pool = pj_pool_create(src->tp_info.pool->factory,
645 "rtd%p",
646 PJSIP_POOL_RDATA_LEN,
647 PJSIP_POOL_RDATA_INC,
648 NULL);
649 if (!pool)
650 return PJ_ENOMEM;
651
652 dst = PJ_POOL_ZALLOC_T(pool, pjsip_rx_data);
653
654 /* Parts of tp_info */
655 dst->tp_info.pool = pool;
656 dst->tp_info.transport = (pjsip_transport*)src->tp_info.transport;
657
658 /* pkt_info can be memcopied */
659 pj_memcpy(&dst->pkt_info, &src->pkt_info, sizeof(src->pkt_info));
660
661 /* msg_info needs deep clone */
662 dst->msg_info.msg_buf = dst->pkt_info.packet;
663 dst->msg_info.len = src->msg_info.len;
664 dst->msg_info.msg = pjsip_msg_clone(pool, src->msg_info.msg);
665 pj_list_init(&dst->msg_info.parse_err);
666
667#define GET_MSG_HDR2(TYPE, type, var) \
668 case PJSIP_H_##TYPE: \
669 if (!dst->msg_info.var) { \
670 dst->msg_info.var = (pjsip_##type##_hdr*)hdr; \
671 } \
672 break
673#define GET_MSG_HDR(TYPE, var_type) GET_MSG_HDR2(TYPE, var_type, var_type)
674
675 hdr = dst->msg_info.msg->hdr.next;
676 while (hdr != &dst->msg_info.msg->hdr) {
677 switch (hdr->type) {
678 GET_MSG_HDR(CALL_ID, cid);
679 GET_MSG_HDR(FROM, from);
680 GET_MSG_HDR(TO, to);
681 GET_MSG_HDR(VIA, via);
682 GET_MSG_HDR(CSEQ, cseq);
683 GET_MSG_HDR(MAX_FORWARDS, max_fwd);
684 GET_MSG_HDR(ROUTE, route);
685 GET_MSG_HDR2(RECORD_ROUTE, rr, record_route);
686 GET_MSG_HDR(CONTENT_TYPE, ctype);
687 GET_MSG_HDR(CONTENT_LENGTH, clen);
688 GET_MSG_HDR(REQUIRE, require);
689 GET_MSG_HDR(SUPPORTED, supported);
690 default:
691 break;
692 }
693 hdr = hdr->next;
694 }
695
696#undef GET_MSG_HDR
697#undef GET_MSG_HDR2
698
699 *p_rdata = dst;
700
701 /* Finally add transport ref */
702 return pjsip_transport_add_ref(dst->tp_info.transport);
703}
704
705/* Free previously cloned pjsip_rx_data. */
706PJ_DEF(pj_status_t) pjsip_rx_data_free_cloned(pjsip_rx_data *rdata)
707{
708 PJ_ASSERT_RETURN(rdata, PJ_EINVAL);
709
710 pjsip_transport_dec_ref(rdata->tp_info.transport);
711 pj_pool_release(rdata->tp_info.pool);
712
713 return PJ_SUCCESS;
714}
715
716/*****************************************************************************
717 *
718 * TRANSPORT KEY
719 *
720 *****************************************************************************/
721
722
723/*****************************************************************************
724 *
725 * TRANSPORT
726 *
727 *****************************************************************************/
728
729static void transport_send_callback(pjsip_transport *transport,
730 void *token,
731 pj_ssize_t size)
732{
733 pjsip_tx_data *tdata = (pjsip_tx_data*) token;
734
735 PJ_UNUSED_ARG(transport);
736
737 /* Mark pending off so that app can resend/reuse txdata from inside
738 * the callback.
739 */
740 tdata->is_pending = 0;
741
742 /* Call callback, if any. */
743 if (tdata->cb) {
744 (*tdata->cb)(tdata->token, tdata, size);
745 }
746
747 /* Decrement reference count. */
748 pjsip_tx_data_dec_ref(tdata);
749}
750
751/* This function is called by endpoint for on_tx_request() and on_tx_response()
752 * notification.
753 */
754static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata)
755{
756 return pjsip_tx_data_encode(tdata);
757}
758
759/*
760 * Send a SIP message using the specified transport.
761 */
762PJ_DEF(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
763 pjsip_tx_data *tdata,
764 const pj_sockaddr_t *addr,
765 int addr_len,
766 void *token,
767 pjsip_tp_send_callback cb)
768{
769 pj_status_t status;
770
771 PJ_ASSERT_RETURN(tr && tdata && addr, PJ_EINVAL);
772
773 /* Is it currently being sent? */
774 if (tdata->is_pending) {
775 pj_assert(!"Invalid operation step!");
776 PJ_LOG(2,(THIS_FILE, "Unable to send %s: message is pending",
777 pjsip_tx_data_get_info(tdata)));
778 return PJSIP_EPENDINGTX;
779 }
780
781 /* Add reference to prevent deletion, and to cancel idle timer if
782 * it's running.
783 */
784 pjsip_transport_add_ref(tr);
785
786 /* Fill in tp_info. */
787 tdata->tp_info.transport = tr;
788 pj_memcpy(&tdata->tp_info.dst_addr, addr, addr_len);
789 tdata->tp_info.dst_addr_len = addr_len;
790
791 pj_inet_ntop(((pj_sockaddr*)addr)->addr.sa_family,
792 pj_sockaddr_get_addr(addr),
793 tdata->tp_info.dst_name,
794 sizeof(tdata->tp_info.dst_name));
795 tdata->tp_info.dst_port = pj_sockaddr_get_port(addr);
796
797 /* Distribute to modules.
798 * When the message reach mod_msg_print, the contents of the message will
799 * be "printed" to contiguous buffer.
800 */
801 if (tr->tpmgr->on_tx_msg) {
802 status = (*tr->tpmgr->on_tx_msg)(tr->endpt, tdata);
803 if (status != PJ_SUCCESS) {
804 pjsip_transport_dec_ref(tr);
805 return status;
806 }
807 }
808
809 /* Save callback data. */
810 tdata->token = token;
811 tdata->cb = cb;
812
813 /* Add reference counter. */
814 pjsip_tx_data_add_ref(tdata);
815
816 /* Mark as pending. */
817 tdata->is_pending = 1;
818
819 /* Send to transport. */
820 status = (*tr->send_msg)(tr, tdata, addr, addr_len, (void*)tdata,
821 &transport_send_callback);
822
823 if (status != PJ_EPENDING) {
824 tdata->is_pending = 0;
825 pjsip_tx_data_dec_ref(tdata);
826 }
827
828 pjsip_transport_dec_ref(tr);
829 return status;
830}
831
832
833/* send_raw() callback */
834static void send_raw_callback(pjsip_transport *transport,
835 void *token,
836 pj_ssize_t size)
837{
838 pjsip_tx_data *tdata = (pjsip_tx_data*) token;
839
840 /* Mark pending off so that app can resend/reuse txdata from inside
841 * the callback.
842 */
843 tdata->is_pending = 0;
844
845 /* Call callback, if any. */
846 if (tdata->cb) {
847 (*tdata->cb)(tdata->token, tdata, size);
848 }
849
850 /* Decrement tdata reference count. */
851 pjsip_tx_data_dec_ref(tdata);
852
853 /* Decrement transport reference count */
854 pjsip_transport_dec_ref(transport);
855}
856
857
858/* Send raw data */
859PJ_DEF(pj_status_t) pjsip_tpmgr_send_raw(pjsip_tpmgr *mgr,
860 pjsip_transport_type_e tp_type,
861 const pjsip_tpselector *sel,
862 pjsip_tx_data *tdata,
863 const void *raw_data,
864 pj_size_t data_len,
865 const pj_sockaddr_t *addr,
866 int addr_len,
867 void *token,
868 pjsip_tp_send_callback cb)
869{
870 pjsip_transport *tr;
871 pj_status_t status;
872
873 /* Acquire the transport */
874 status = pjsip_tpmgr_acquire_transport(mgr, tp_type, addr, addr_len,
875 sel, &tr);
876 if (status != PJ_SUCCESS)
877 return status;
878
879 /* Create transmit data buffer if one is not specified */
880 if (tdata == NULL) {
881 status = pjsip_endpt_create_tdata(tr->endpt, &tdata);
882 if (status != PJ_SUCCESS) {
883 pjsip_transport_dec_ref(tr);
884 return status;
885 }
886
887 tdata->info = "raw";
888
889 /* Add reference counter. */
890 pjsip_tx_data_add_ref(tdata);
891 }
892
893 /* Allocate buffer */
894 if (tdata->buf.start == NULL ||
895 (tdata->buf.end - tdata->buf.start) < (int)data_len)
896 {
897 /* Note: data_len may be zero, so allocate +1 */
898 tdata->buf.start = (char*) pj_pool_alloc(tdata->pool, data_len+1);
899 tdata->buf.end = tdata->buf.start + data_len + 1;
900 }
901
902 /* Copy data, if any! (application may send zero len packet) */
903 if (data_len) {
904 pj_memcpy(tdata->buf.start, raw_data, data_len);
905 }
906 tdata->buf.cur = tdata->buf.start + data_len;
907
908 /* Save callback data. */
909 tdata->token = token;
910 tdata->cb = cb;
911
912 /* Mark as pending. */
913 tdata->is_pending = 1;
914
915 /* Send to transport */
916 status = tr->send_msg(tr, tdata, addr, addr_len,
917 tdata, &send_raw_callback);
918
919 if (status != PJ_EPENDING) {
920 /* callback will not be called, so destroy tdata now. */
921 pjsip_tx_data_dec_ref(tdata);
922 pjsip_transport_dec_ref(tr);
923 }
924
925 return status;
926}
927
928
929static void transport_idle_callback(pj_timer_heap_t *timer_heap,
930 struct pj_timer_entry *entry)
931{
932 pjsip_transport *tp = (pjsip_transport*) entry->user_data;
933 pj_assert(tp != NULL);
934
935 PJ_UNUSED_ARG(timer_heap);
936
937 entry->id = PJ_FALSE;
938 pjsip_transport_destroy(tp);
939}
940
941/*
942 * Add ref.
943 */
944PJ_DEF(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp )
945{
946 PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL);
947
948 if (pj_atomic_inc_and_get(tp->ref_cnt) == 1) {
949 pj_lock_acquire(tp->tpmgr->lock);
950 /* Verify again. */
951 if (pj_atomic_get(tp->ref_cnt) == 1) {
952 if (tp->idle_timer.id != PJ_FALSE) {
953 pjsip_endpt_cancel_timer(tp->tpmgr->endpt, &tp->idle_timer);
954 tp->idle_timer.id = PJ_FALSE;
955 }
956 }
957 pj_lock_release(tp->tpmgr->lock);
958 }
959
960 return PJ_SUCCESS;
961}
962
963/*
964 * Dec ref.
965 */
966PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp )
967{
968 PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL);
969
970 pj_assert(pj_atomic_get(tp->ref_cnt) > 0);
971
972 if (pj_atomic_dec_and_get(tp->ref_cnt) == 0) {
973 pj_lock_acquire(tp->tpmgr->lock);
974 /* Verify again. Do not register timer if the transport is
975 * being destroyed.
976 */
977 if (pj_atomic_get(tp->ref_cnt) == 0 && !tp->is_destroying) {
978 pj_time_val delay;
979
980 /* If transport is in graceful shutdown, then this is the
981 * last user who uses the transport. Schedule to destroy the
982 * transport immediately. Otherwise schedule idle timer.
983 */
984 if (tp->is_shutdown) {
985 delay.sec = delay.msec = 0;
986 } else {
987 delay.sec = (tp->dir==PJSIP_TP_DIR_OUTGOING) ?
988 PJSIP_TRANSPORT_IDLE_TIME :
989 PJSIP_TRANSPORT_SERVER_IDLE_TIME;
990 delay.msec = 0;
991 }
992
993 pj_assert(tp->idle_timer.id == 0);
994 tp->idle_timer.id = PJ_TRUE;
995 pjsip_endpt_schedule_timer(tp->tpmgr->endpt, &tp->idle_timer,
996 &delay);
997 }
998 pj_lock_release(tp->tpmgr->lock);
999 }
1000
1001 return PJ_SUCCESS;
1002}
1003
1004
1005/**
1006 * Register a transport.
1007 */
1008PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
1009 pjsip_transport *tp )
1010{
1011 int key_len;
1012 pj_uint32_t hval;
1013 void *entry;
1014
1015 /* Init. */
1016 tp->tpmgr = mgr;
1017 pj_bzero(&tp->idle_timer, sizeof(tp->idle_timer));
1018 tp->idle_timer.user_data = tp;
1019 tp->idle_timer.cb = &transport_idle_callback;
1020
1021 /*
1022 * Register to hash table (see Trac ticket #42).
1023 */
1024 key_len = sizeof(tp->key.type) + tp->addr_len;
1025 pj_lock_acquire(mgr->lock);
1026
1027 /* If entry already occupied, unregister previous entry */
1028 hval = 0;
1029 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
1030 if (entry != NULL)
1031 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
1032
1033 /* Register new entry */
1034 pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, hval, tp);
1035
1036 pj_lock_release(mgr->lock);
1037
1038 TRACE_((THIS_FILE,"Transport %s registered: type=%s, remote=%s:%d",
1039 tp->obj_name,
1040 pjsip_transport_get_type_name(tp->key.type),
1041 addr_string(&tp->key.rem_addr),
1042 pj_sockaddr_get_port(&tp->key.rem_addr)));
1043
1044 return PJ_SUCCESS;
1045}
1046
1047/* Force destroy transport (e.g. during transport manager shutdown. */
1048static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
1049 pjsip_transport *tp )
1050{
1051 int key_len;
1052 pj_uint32_t hval;
1053 void *entry;
1054
1055 TRACE_((THIS_FILE, "Transport %s is being destroyed", tp->obj_name));
1056
1057 pj_lock_acquire(tp->lock);
1058 pj_lock_acquire(mgr->lock);
1059
1060 tp->is_destroying = PJ_TRUE;
1061
1062 /*
1063 * Unregister timer, if any.
1064 */
1065 //pj_assert(tp->idle_timer.id == PJ_FALSE);
1066 if (tp->idle_timer.id != PJ_FALSE) {
1067 pjsip_endpt_cancel_timer(mgr->endpt, &tp->idle_timer);
1068 tp->idle_timer.id = PJ_FALSE;
1069 }
1070
1071 /*
1072 * Unregister from hash table (see Trac ticket #42).
1073 */
1074 key_len = sizeof(tp->key.type) + tp->addr_len;
1075 hval = 0;
1076 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
1077 if (entry == (void*)tp)
1078 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
1079
1080 pj_lock_release(mgr->lock);
1081
1082 /* Destroy. */
1083 return tp->destroy(tp);
1084}
1085
1086
1087/*
1088 * Start graceful shutdown procedure for this transport.
1089 */
1090PJ_DEF(pj_status_t) pjsip_transport_shutdown(pjsip_transport *tp)
1091{
1092 pjsip_tpmgr *mgr;
1093 pj_status_t status;
1094
1095 TRACE_((THIS_FILE, "Transport %s shutting down", tp->obj_name));
1096
1097 pj_lock_acquire(tp->lock);
1098
1099 mgr = tp->tpmgr;
1100 pj_lock_acquire(mgr->lock);
1101
1102 /* Do nothing if transport is being shutdown already */
1103 if (tp->is_shutdown) {
1104 pj_lock_release(tp->lock);
1105 pj_lock_release(mgr->lock);
1106 return PJ_SUCCESS;
1107 }
1108
1109 status = PJ_SUCCESS;
1110
1111 /* Instruct transport to shutdown itself */
1112 if (tp->do_shutdown)
1113 status = tp->do_shutdown(tp);
1114
1115 if (status == PJ_SUCCESS)
1116 tp->is_shutdown = PJ_TRUE;
1117
1118 /* If transport reference count is zero, start timer count-down */
1119 if (pj_atomic_get(tp->ref_cnt) == 0) {
1120 pjsip_transport_add_ref(tp);
1121 pjsip_transport_dec_ref(tp);
1122 }
1123
1124 pj_lock_release(tp->lock);
1125 pj_lock_release(mgr->lock);
1126
1127 return status;
1128}
1129
1130
1131/**
1132 * Unregister transport.
1133 */
1134PJ_DEF(pj_status_t) pjsip_transport_destroy( pjsip_transport *tp)
1135{
1136 /* Must have no user. */
1137 PJ_ASSERT_RETURN(pj_atomic_get(tp->ref_cnt) == 0, PJSIP_EBUSY);
1138
1139 /* Destroy. */
1140 return destroy_transport(tp->tpmgr, tp);
1141}
1142
1143
1144
1145/*****************************************************************************
1146 *
1147 * TRANSPORT FACTORY
1148 *
1149 *****************************************************************************/
1150
1151
1152PJ_DEF(pj_status_t) pjsip_tpmgr_register_tpfactory( pjsip_tpmgr *mgr,
1153 pjsip_tpfactory *tpf)
1154{
1155 pjsip_tpfactory *p;
1156 pj_status_t status;
1157
1158 pj_lock_acquire(mgr->lock);
1159
1160 /* Check that no factory with the same type has been registered. */
1161 status = PJ_SUCCESS;
1162 for (p=mgr->factory_list.next; p!=&mgr->factory_list; p=p->next) {
1163 if (p->type == tpf->type) {
1164 status = PJSIP_ETYPEEXISTS;
1165 break;
1166 }
1167 if (p == tpf) {
1168 status = PJ_EEXISTS;
1169 break;
1170 }
1171 }
1172
1173 if (status != PJ_SUCCESS) {
1174 pj_lock_release(mgr->lock);
1175 return status;
1176 }
1177
1178 pj_list_insert_before(&mgr->factory_list, tpf);
1179
1180 pj_lock_release(mgr->lock);
1181
1182 return PJ_SUCCESS;
1183}
1184
1185
1186/**
1187 * Unregister factory.
1188 */
1189PJ_DEF(pj_status_t) pjsip_tpmgr_unregister_tpfactory( pjsip_tpmgr *mgr,
1190 pjsip_tpfactory *tpf)
1191{
1192 pj_lock_acquire(mgr->lock);
1193
1194 pj_assert(pj_list_find_node(&mgr->factory_list, tpf) == tpf);
1195 pj_list_erase(tpf);
1196
1197 pj_lock_release(mgr->lock);
1198
1199 return PJ_SUCCESS;
1200}
1201
1202PJ_DECL(void) pjsip_tpmgr_fla2_param_default(pjsip_tpmgr_fla2_param *prm)
1203{
1204 pj_bzero(prm, sizeof(*prm));
1205}
1206
1207/*****************************************************************************
1208 *
1209 * TRANSPORT MANAGER
1210 *
1211 *****************************************************************************/
1212
1213/*
1214 * Create a new transport manager.
1215 */
1216PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
1217 pjsip_endpoint *endpt,
1218 pjsip_rx_callback rx_cb,
1219 pjsip_tx_callback tx_cb,
1220 pjsip_tpmgr **p_mgr)
1221{
1222 pjsip_tpmgr *mgr;
1223 pj_status_t status;
1224
1225 PJ_ASSERT_RETURN(pool && endpt && rx_cb && p_mgr, PJ_EINVAL);
1226
1227 /* Register mod_msg_print module. */
1228 status = pjsip_endpt_register_module(endpt, &mod_msg_print);
1229 if (status != PJ_SUCCESS)
1230 return status;
1231
1232 /* Create and initialize transport manager. */
1233 mgr = PJ_POOL_ZALLOC_T(pool, pjsip_tpmgr);
1234 mgr->endpt = endpt;
1235 mgr->on_rx_msg = rx_cb;
1236 mgr->on_tx_msg = tx_cb;
1237 pj_list_init(&mgr->factory_list);
1238 pj_list_init(&mgr->tdata_list);
1239
1240 mgr->table = pj_hash_create(pool, PJSIP_TPMGR_HTABLE_SIZE);
1241 if (!mgr->table)
1242 return PJ_ENOMEM;
1243
1244 status = pj_lock_create_recursive_mutex(pool, "tmgr%p", &mgr->lock);
1245 if (status != PJ_SUCCESS)
1246 return status;
1247
1248#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1249 status = pj_atomic_create(pool, 0, &mgr->tdata_counter);
1250 if (status != PJ_SUCCESS) {
1251 pj_lock_destroy(mgr->lock);
1252 return status;
1253 }
1254#endif
1255
1256 /* Set transport state callback */
1257 pjsip_tpmgr_set_state_cb(mgr, &tp_state_callback);
1258
1259 PJ_LOG(5, (THIS_FILE, "Transport manager created."));
1260
1261 *p_mgr = mgr;
1262 return PJ_SUCCESS;
1263}
1264
1265/* Get the interface to send packet to the specified address */
1266static pj_status_t get_net_interface(pjsip_transport_type_e tp_type,
1267 const pj_str_t *dst,
1268 pj_str_t *itf_str_addr)
1269{
1270 int af;
1271 pj_sockaddr itf_addr;
1272 pj_status_t status;
1273
1274 af = (tp_type & PJSIP_TRANSPORT_IPV6)? PJ_AF_INET6 : PJ_AF_INET;
1275 status = pj_getipinterface(af, dst, &itf_addr, PJ_FALSE, NULL);
1276 if (status != PJ_SUCCESS) {
1277 /* If it fails, e.g: on WM6 (http://support.microsoft.com/kb/129065),
1278 * just fallback using pj_gethostip(), see ticket #1660.
1279 */
1280 PJ_LOG(5,(THIS_FILE,"Warning: unable to determine local "
1281 "interface, fallback to default interface!"));
1282 status = pj_gethostip(af, &itf_addr);
1283 if (status != PJ_SUCCESS)
1284 return status;
1285 }
1286
1287 /* Print address */
1288 pj_sockaddr_print(&itf_addr, itf_str_addr->ptr,
1289 PJ_INET6_ADDRSTRLEN, 0);
1290 itf_str_addr->slen = pj_ansi_strlen(itf_str_addr->ptr);
1291
1292 return PJ_SUCCESS;
1293}
1294
1295/*
1296 * Find out the appropriate local address info (IP address and port) to
1297 * advertise in Contact header based on the remote address to be
1298 * contacted. The local address info would be the address name of the
1299 * transport or listener which will be used to send the request.
1300 *
1301 * In this implementation, it will only select the transport based on
1302 * the transport type in the request.
1303 */
1304PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr2(pjsip_tpmgr *tpmgr,
1305 pj_pool_t *pool,
1306 pjsip_tpmgr_fla2_param *prm)
1307{
1308 char tmp_buf[PJ_INET6_ADDRSTRLEN+10];
1309 pj_str_t tmp_str;
1310 pj_status_t status = PJSIP_EUNSUPTRANSPORT;
1311 unsigned flag;
1312
1313 /* Sanity checks */
1314 PJ_ASSERT_RETURN(tpmgr && pool && prm, PJ_EINVAL);
1315
1316 pj_strset(&tmp_str, tmp_buf, 0);
1317 prm->ret_addr.slen = 0;
1318 prm->ret_port = 0;
1319 prm->ret_tp = NULL;
1320
1321 flag = pjsip_transport_get_flag_from_type(prm->tp_type);
1322
1323 if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
1324 prm->tp_sel->u.transport)
1325 {
1326 const pjsip_transport *tp = prm->tp_sel->u.transport;
1327 if (prm->local_if) {
1328 status = get_net_interface((pjsip_transport_type_e)tp->key.type,
1329 &prm->dst_host, &tmp_str);
1330 if (status != PJ_SUCCESS)
1331 goto on_return;
1332 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1333 prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
1334 prm->ret_tp = tp;
1335 } else {
1336 pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
1337 prm->ret_port = (pj_uint16_t)tp->local_name.port;
1338 }
1339 status = PJ_SUCCESS;
1340
1341 } else if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_LISTENER &&
1342 prm->tp_sel->u.listener)
1343 {
1344 if (prm->local_if) {
1345 status = get_net_interface(prm->tp_sel->u.listener->type,
1346 &prm->dst_host, &tmp_str);
1347 if (status != PJ_SUCCESS)
1348 goto on_return;
1349 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1350 } else {
1351 pj_strdup(pool, &prm->ret_addr,
1352 &prm->tp_sel->u.listener->addr_name.host);
1353 }
1354 prm->ret_port = (pj_uint16_t)prm->tp_sel->u.listener->addr_name.port;
1355 status = PJ_SUCCESS;
1356
1357 } else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
1358 pj_sockaddr remote;
1359 int addr_len;
1360 pjsip_transport *tp;
1361
1362 pj_bzero(&remote, sizeof(remote));
1363 if (prm->tp_type & PJSIP_TRANSPORT_IPV6) {
1364 addr_len = sizeof(pj_sockaddr_in6);
1365 remote.addr.sa_family = pj_AF_INET6();
1366 } else {
1367 addr_len = sizeof(pj_sockaddr_in);
1368 remote.addr.sa_family = pj_AF_INET();
1369 }
1370
1371 status = pjsip_tpmgr_acquire_transport(tpmgr, prm->tp_type, &remote,
1372 addr_len, NULL, &tp);
1373
1374 if (status == PJ_SUCCESS) {
1375 if (prm->local_if) {
1376 status = get_net_interface((pjsip_transport_type_e)
1377 tp->key.type,
1378 &prm->dst_host, &tmp_str);
1379 if (status != PJ_SUCCESS)
1380 goto on_return;
1381 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1382 prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
1383 prm->ret_tp = tp;
1384 } else {
1385 pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
1386 prm->ret_port = (pj_uint16_t)tp->local_name.port;
1387 }
1388
1389 pjsip_transport_dec_ref(tp);
1390 }
1391
1392 } else {
1393 /* For connection oriented transport, enum the factories */
1394 pjsip_tpfactory *f;
1395
1396 pj_lock_acquire(tpmgr->lock);
1397
1398 f = tpmgr->factory_list.next;
1399 while (f != &tpmgr->factory_list) {
1400 if (f->type == prm->tp_type)
1401 break;
1402 f = f->next;
1403 }
1404
1405 if (f != &tpmgr->factory_list) {
1406 if (prm->local_if) {
1407 status = get_net_interface(f->type, &prm->dst_host,
1408 &tmp_str);
1409 if (status == PJ_SUCCESS) {
1410 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1411 } else {
1412 /* It could fail "normally" on certain cases, e.g.
1413 * when connecting to IPv6 link local address, it
1414 * will wail with EINVAL.
1415 * In this case, fallback to use the default interface
1416 * rather than failing the call.
1417 */
1418 PJ_PERROR(5,(THIS_FILE, status, "Warning: unable to "
1419 "determine local interface"));
1420 pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
1421 status = PJ_SUCCESS;
1422 }
1423 } else {
1424 pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
1425 }
1426 prm->ret_port = (pj_uint16_t)f->addr_name.port;
1427 status = PJ_SUCCESS;
1428 }
1429 pj_lock_release(tpmgr->lock);
1430 }
1431
1432on_return:
1433 return status;
1434}
1435
1436PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
1437 pj_pool_t *pool,
1438 pjsip_transport_type_e type,
1439 const pjsip_tpselector *sel,
1440 pj_str_t *ip_addr,
1441 int *port)
1442{
1443 pjsip_tpmgr_fla2_param prm;
1444 pj_status_t status;
1445
1446 pjsip_tpmgr_fla2_param_default(&prm);
1447 prm.tp_type = type;
1448 prm.tp_sel = sel;
1449
1450 status = pjsip_tpmgr_find_local_addr2(tpmgr, pool, &prm);
1451 if (status != PJ_SUCCESS)
1452 return status;
1453
1454 *ip_addr = prm.ret_addr;
1455 *port = prm.ret_port;
1456
1457 return PJ_SUCCESS;
1458}
1459
1460/*
1461 * Return number of transports currently registered to the transport
1462 * manager.
1463 */
1464PJ_DEF(unsigned) pjsip_tpmgr_get_transport_count(pjsip_tpmgr *mgr)
1465{
1466 pj_hash_iterator_t itr_val;
1467 pj_hash_iterator_t *itr;
1468 int nr_of_transports = 0;
1469
1470 pj_lock_acquire(mgr->lock);
1471
1472 itr = pj_hash_first(mgr->table, &itr_val);
1473 while (itr) {
1474 nr_of_transports++;
1475 itr = pj_hash_next(mgr->table, itr);
1476 }
1477
1478 pj_lock_release(mgr->lock);
1479
1480 return nr_of_transports;
1481}
1482
1483/*
1484 * pjsip_tpmgr_destroy()
1485 *
1486 * Destroy transport manager.
1487 */
1488PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
1489{
1490 pj_hash_iterator_t itr_val;
1491 pj_hash_iterator_t *itr;
1492 pjsip_tpfactory *factory;
1493 pjsip_endpoint *endpt = mgr->endpt;
1494
1495 PJ_LOG(5, (THIS_FILE, "Destroying transport manager"));
1496
1497 pj_lock_acquire(mgr->lock);
1498
1499 /*
1500 * Destroy all transports.
1501 */
1502 itr = pj_hash_first(mgr->table, &itr_val);
1503 while (itr != NULL) {
1504 pj_hash_iterator_t *next;
1505 pjsip_transport *transport;
1506
1507 transport = (pjsip_transport*) pj_hash_this(mgr->table, itr);
1508
1509 next = pj_hash_next(mgr->table, itr);
1510
1511 destroy_transport(mgr, transport);
1512
1513 itr = next;
1514 }
1515
1516 /*
1517 * Destroy all factories/listeners.
1518 */
1519 factory = mgr->factory_list.next;
1520 while (factory != &mgr->factory_list) {
1521 pjsip_tpfactory *next = factory->next;
1522
1523 factory->destroy(factory);
1524
1525 factory = next;
1526 }
1527
1528 pj_lock_release(mgr->lock);
1529
1530#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1531 /* If you encounter assert error on this line, it means there are
1532 * leakings in transmit data (i.e. some transmit data have not been
1533 * destroyed).
1534 */
1535 //pj_assert(pj_atomic_get(mgr->tdata_counter) == 0);
1536 if (pj_atomic_get(mgr->tdata_counter) != 0) {
1537 PJ_LOG(3,(THIS_FILE, "Warning: %d transmit buffer(s) not freed!",
1538 pj_atomic_get(mgr->tdata_counter)));
1539 }
1540#endif
1541
1542 /*
1543 * Destroy any dangling transmit buffer.
1544 */
1545 if (!pj_list_empty(&mgr->tdata_list)) {
1546 pjsip_tx_data *tdata = mgr->tdata_list.next;
1547 while (tdata != &mgr->tdata_list) {
1548 pjsip_tx_data *next = tdata->next;
1549 tx_data_destroy(tdata);
1550 tdata = next;
1551 }
1552 PJ_LOG(3,(THIS_FILE, "Cleaned up dangling transmit buffer(s)."));
1553 }
1554
1555#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1556 pj_atomic_destroy(mgr->tdata_counter);
1557#endif
1558
1559 pj_lock_destroy(mgr->lock);
1560
1561 /* Unregister mod_msg_print. */
1562 if (mod_msg_print.id != -1) {
1563 pjsip_endpt_unregister_module(endpt, &mod_msg_print);
1564 }
1565
1566 return PJ_SUCCESS;
1567}
1568
1569
1570/*
1571 * pjsip_tpmgr_receive_packet()
1572 *
1573 * Called by tranports when they receive a new packet.
1574 */
1575PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr,
1576 pjsip_rx_data *rdata)
1577{
1578 pjsip_transport *tr = rdata->tp_info.transport;
1579
1580 char *current_pkt;
1581 pj_size_t remaining_len;
1582 pj_size_t total_processed = 0;
1583
1584 /* Check size. */
1585 pj_assert(rdata->pkt_info.len > 0);
1586 if (rdata->pkt_info.len <= 0)
1587 return -1;
1588
1589 current_pkt = rdata->pkt_info.packet;
1590 remaining_len = rdata->pkt_info.len;
1591
1592 /* Must NULL terminate buffer. This is the requirement of the
1593 * parser etc.
1594 */
1595 current_pkt[remaining_len] = '\0';
1596
1597 /* Process all message fragments. */
1598 while (remaining_len > 0) {
1599
1600 pjsip_msg *msg;
1601 char *p, *end;
1602 char saved;
1603 pj_size_t msg_fragment_size;
1604
1605 /* Skip leading newlines as pjsip_find_msg() currently can't
1606 * handle leading newlines.
1607 */
1608 for (p=current_pkt, end=p+remaining_len; p!=end; ++p) {
1609 if (*p != '\r' && *p != '\n')
1610 break;
1611 }
1612 if (p!=current_pkt) {
1613 remaining_len -= (p - current_pkt);
1614 total_processed += (p - current_pkt);
1615 current_pkt = p;
1616 if (remaining_len == 0) {
1617 return total_processed;
1618 }
1619 }
1620
1621 /* Initialize default fragment size. */
1622 msg_fragment_size = remaining_len;
1623
1624 /* Clear and init msg_info in rdata.
1625 * Endpoint might inspect the values there when we call the callback
1626 * to report some errors.
1627 */
1628 pj_bzero(&rdata->msg_info, sizeof(rdata->msg_info));
1629 pj_list_init(&rdata->msg_info.parse_err);
1630 rdata->msg_info.msg_buf = current_pkt;
1631 rdata->msg_info.len = (int)remaining_len;
1632
1633 /* For TCP transport, check if the whole message has been received. */
1634 if ((tr->flag & PJSIP_TRANSPORT_DATAGRAM) == 0) {
1635 pj_status_t msg_status;
1636 msg_status = pjsip_find_msg(current_pkt, remaining_len, PJ_FALSE,
1637 &msg_fragment_size);
1638 if (msg_status != PJ_SUCCESS) {
1639 if (remaining_len == PJSIP_MAX_PKT_LEN) {
1640 mgr->on_rx_msg(mgr->endpt, PJSIP_ERXOVERFLOW, rdata);
1641 /* Exhaust all data. */
1642 return rdata->pkt_info.len;
1643 } else {
1644 /* Not enough data in packet. */
1645 return total_processed;
1646 }
1647 }
1648 }
1649
1650 /* Update msg_info. */
1651 rdata->msg_info.len = (int)msg_fragment_size;
1652
1653 /* Null terminate packet */
1654 saved = current_pkt[msg_fragment_size];
1655 current_pkt[msg_fragment_size] = '\0';
1656
1657 /* Parse the message. */
1658 rdata->msg_info.msg = msg =
1659 pjsip_parse_rdata( current_pkt, msg_fragment_size, rdata);
1660
1661 /* Restore null termination */
1662 current_pkt[msg_fragment_size] = saved;
1663
1664 /* Check for parsing syntax error */
1665 if (msg==NULL || !pj_list_empty(&rdata->msg_info.parse_err)) {
1666 pjsip_parser_err_report *err;
1667 char buf[128];
1668 pj_str_t tmp;
1669
1670 /* Gather syntax error information */
1671 tmp.ptr = buf; tmp.slen = 0;
1672 err = rdata->msg_info.parse_err.next;
1673 while (err != &rdata->msg_info.parse_err) {
1674 int len;
1675 len = pj_ansi_snprintf(tmp.ptr+tmp.slen, sizeof(buf)-tmp.slen,
1676 ": %s exception when parsing '%.*s' "
1677 "header on line %d col %d",
1678 pj_exception_id_name(err->except_code),
1679 (int)err->hname.slen, err->hname.ptr,
1680 err->line, err->col);
1681 if (len > 0 && len < (int) (sizeof(buf)-tmp.slen)) {
1682 tmp.slen += len;
1683 }
1684 err = err->next;
1685 }
1686
1687 /* Only print error message if there's error.
1688 * Sometimes we receive blank packets (packets with only CRLF)
1689 * which were sent to keep NAT bindings.
1690 */
1691 if (tmp.slen) {
1692 PJ_LOG(1, (THIS_FILE,
1693 "Error processing %d bytes packet from %s %s:%d %.*s:\n"
1694 "%.*s\n"
1695 "-- end of packet.",
1696 msg_fragment_size,
1697 rdata->tp_info.transport->type_name,
1698 rdata->pkt_info.src_name,
1699 rdata->pkt_info.src_port,
1700 (int)tmp.slen, tmp.ptr,
1701 (int)msg_fragment_size,
1702 rdata->msg_info.msg_buf));
1703 }
1704
1705 goto finish_process_fragment;
1706 }
1707
1708 /* Perform basic header checking. */
1709 if (rdata->msg_info.cid == NULL ||
1710 rdata->msg_info.cid->id.slen == 0 ||
1711 rdata->msg_info.from == NULL ||
1712 rdata->msg_info.to == NULL ||
1713 rdata->msg_info.via == NULL ||
1714 rdata->msg_info.cseq == NULL)
1715 {
1716 mgr->on_rx_msg(mgr->endpt, PJSIP_EMISSINGHDR, rdata);
1717 goto finish_process_fragment;
1718 }
1719
1720 /* For request: */
1721 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
1722 /* always add received parameter to the via. */
1723 pj_strdup2(rdata->tp_info.pool,
1724 &rdata->msg_info.via->recvd_param,
1725 rdata->pkt_info.src_name);
1726
1727 /* RFC 3581:
1728 * If message contains "rport" param, put the received port there.
1729 */
1730 if (rdata->msg_info.via->rport_param == 0) {
1731 rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
1732 }
1733 } else {
1734 /* Drop malformed responses */
1735 if (rdata->msg_info.msg->line.status.code < 100 ||
1736 rdata->msg_info.msg->line.status.code >= 700)
1737 {
1738 mgr->on_rx_msg(mgr->endpt, PJSIP_EINVALIDSTATUS, rdata);
1739 goto finish_process_fragment;
1740 }
1741 }
1742
1743 /* Drop response message if it has more than one Via.
1744 */
1745 /* This is wrong. Proxy DOES receive responses with multiple
1746 * Via headers! Thanks Aldo <acampi at deis.unibo.it> for pointing
1747 * this out.
1748
1749 if (msg->type == PJSIP_RESPONSE_MSG) {
1750 pjsip_hdr *hdr;
1751 hdr = (pjsip_hdr*)rdata->msg_info.via->next;
1752 if (hdr != &msg->hdr) {
1753 hdr = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, hdr);
1754 if (hdr) {
1755 mgr->on_rx_msg(mgr->endpt, PJSIP_EMULTIPLEVIA, rdata);
1756 goto finish_process_fragment;
1757 }
1758 }
1759 }
1760 */
1761
1762 /* Call the transport manager's upstream message callback.
1763 */
1764 mgr->on_rx_msg(mgr->endpt, PJ_SUCCESS, rdata);
1765
1766
1767finish_process_fragment:
1768 total_processed += msg_fragment_size;
1769 current_pkt += msg_fragment_size;
1770 remaining_len -= msg_fragment_size;
1771
1772 } /* while (rdata->pkt_info.len > 0) */
1773
1774
1775 return total_processed;
1776}
1777
1778
1779/*
1780 * pjsip_tpmgr_acquire_transport()
1781 *
1782 * Get transport suitable to communicate to remote. Create a new one
1783 * if necessary.
1784 */
1785PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
1786 pjsip_transport_type_e type,
1787 const pj_sockaddr_t *remote,
1788 int addr_len,
1789 const pjsip_tpselector *sel,
1790 pjsip_transport **tp)
1791{
1792 return pjsip_tpmgr_acquire_transport2(mgr, type, remote, addr_len, sel,
1793 NULL, tp);
1794}
1795
1796/*
1797 * pjsip_tpmgr_acquire_transport2()
1798 *
1799 * Get transport suitable to communicate to remote. Create a new one
1800 * if necessary.
1801 */
1802PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
1803 pjsip_transport_type_e type,
1804 const pj_sockaddr_t *remote,
1805 int addr_len,
1806 const pjsip_tpselector *sel,
1807 pjsip_tx_data *tdata,
1808 pjsip_transport **tp)
1809{
1810 pjsip_tpfactory *factory;
1811 pj_status_t status;
1812
1813 TRACE_((THIS_FILE,"Acquiring transport type=%s, remote=%s:%d",
1814 pjsip_transport_get_type_name(type),
1815 addr_string(remote),
1816 pj_sockaddr_get_port(remote)));
1817
1818 pj_lock_acquire(mgr->lock);
1819
1820 /* If transport is specified, then just use it if it is suitable
1821 * for the destination.
1822 */
1823 if (sel && sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
1824 sel->u.transport)
1825 {
1826 pjsip_transport *seltp = sel->u.transport;
1827
1828 /* See if the transport is (not) suitable */
1829 if (seltp->key.type != type) {
1830 pj_lock_release(mgr->lock);
1831 return PJSIP_ETPNOTSUITABLE;
1832 }
1833
1834 /* We could also verify that the destination address is reachable
1835 * from this transport (i.e. both are equal), but if application
1836 * has requested a specific transport to be used, assume that
1837 * it knows what to do.
1838 *
1839 * In other words, I don't think destination verification is a good
1840 * idea for now.
1841 */
1842
1843 /* Transport looks to be suitable to use, so just use it. */
1844 pjsip_transport_add_ref(seltp);
1845 pj_lock_release(mgr->lock);
1846 *tp = seltp;
1847
1848 TRACE_((THIS_FILE, "Transport %s acquired", seltp->obj_name));
1849 return PJ_SUCCESS;
1850
1851
1852 } else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
1853 sel->u.listener)
1854 {
1855 /* Application has requested that a specific listener is to
1856 * be used. In this case, skip transport hash table lookup.
1857 */
1858
1859 /* Verify that the listener type matches the destination type */
1860 if (sel->u.listener->type != type) {
1861 pj_lock_release(mgr->lock);
1862 return PJSIP_ETPNOTSUITABLE;
1863 }
1864
1865 /* We'll use this listener to create transport */
1866 factory = sel->u.listener;
1867
1868 } else {
1869
1870 /*
1871 * This is the "normal" flow, where application doesn't specify
1872 * specific transport/listener to be used to send message to.
1873 * In this case, lookup the transport from the hash table.
1874 */
1875 pjsip_transport_key key;
1876 int key_len;
1877 pjsip_transport *transport;
1878
1879 pj_bzero(&key, sizeof(key));
1880 key_len = sizeof(key.type) + addr_len;
1881
1882 /* First try to get exact destination. */
1883 key.type = type;
1884 pj_memcpy(&key.rem_addr, remote, addr_len);
1885
1886 transport = (pjsip_transport*)
1887 pj_hash_get(mgr->table, &key, key_len, NULL);
1888
1889 if (transport == NULL) {
1890 unsigned flag = pjsip_transport_get_flag_from_type(type);
1891 const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote;
1892
1893
1894 /* Ignore address for loop transports. */
1895 if (type == PJSIP_TRANSPORT_LOOP ||
1896 type == PJSIP_TRANSPORT_LOOP_DGRAM)
1897 {
1898 pj_sockaddr *addr = &key.rem_addr;
1899
1900 pj_bzero(addr, addr_len);
1901 key_len = sizeof(key.type) + addr_len;
1902 transport = (pjsip_transport*)
1903 pj_hash_get(mgr->table, &key, key_len, NULL);
1904 }
1905 /* For datagram transports, try lookup with zero address.
1906 */
1907 else if (flag & PJSIP_TRANSPORT_DATAGRAM)
1908 {
1909 pj_sockaddr *addr = &key.rem_addr;
1910
1911 pj_bzero(addr, addr_len);
1912 addr->addr.sa_family = remote_addr->addr.sa_family;
1913
1914 key_len = sizeof(key.type) + addr_len;
1915 transport = (pjsip_transport*)
1916 pj_hash_get(mgr->table, &key, key_len, NULL);
1917 }
1918 }
1919
1920 if (transport!=NULL && !transport->is_shutdown) {
1921 /*
1922 * Transport found!
1923 */
1924 pjsip_transport_add_ref(transport);
1925 pj_lock_release(mgr->lock);
1926 *tp = transport;
1927
1928 TRACE_((THIS_FILE, "Transport %s acquired", transport->obj_name));
1929 return PJ_SUCCESS;
1930 }
1931
1932 /*
1933 * Transport not found!
1934 * Find factory that can create such transport.
1935 */
1936 factory = mgr->factory_list.next;
1937 while (factory != &mgr->factory_list) {
1938 if (factory->type == type)
1939 break;
1940 factory = factory->next;
1941 }
1942
1943 if (factory == &mgr->factory_list) {
1944 /* No factory can create the transport! */
1945 pj_lock_release(mgr->lock);
1946 TRACE_((THIS_FILE, "No suitable factory was found either"));
1947 return PJSIP_EUNSUPTRANSPORT;
1948 }
1949 }
1950
1951 TRACE_((THIS_FILE, "Creating new transport from factory"));
1952
1953 /* Request factory to create transport. */
1954 if (factory->create_transport2) {
1955 status = factory->create_transport2(factory, mgr, mgr->endpt,
1956 (const pj_sockaddr*) remote,
1957 addr_len, tdata, tp);
1958 } else {
1959 status = factory->create_transport(factory, mgr, mgr->endpt,
1960 (const pj_sockaddr*) remote,
1961 addr_len, tp);
1962 }
1963 if (status == PJ_SUCCESS) {
1964 PJ_ASSERT_ON_FAIL(tp!=NULL,
1965 {pj_lock_release(mgr->lock); return PJ_EBUG;});
1966 pjsip_transport_add_ref(*tp);
1967 }
1968 pj_lock_release(mgr->lock);
1969 return status;
1970}
1971
1972/**
1973 * Dump transport info.
1974 */
1975PJ_DEF(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr)
1976{
1977#if PJ_LOG_MAX_LEVEL >= 3
1978 pj_hash_iterator_t itr_val;
1979 pj_hash_iterator_t *itr;
1980 pjsip_tpfactory *factory;
1981
1982 pj_lock_acquire(mgr->lock);
1983
1984#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1985 PJ_LOG(3,(THIS_FILE, " Outstanding transmit buffers: %d",
1986 pj_atomic_get(mgr->tdata_counter)));
1987#endif
1988
1989 PJ_LOG(3, (THIS_FILE, " Dumping listeners:"));
1990 factory = mgr->factory_list.next;
1991 while (factory != &mgr->factory_list) {
1992 PJ_LOG(3, (THIS_FILE, " %s %s:%.*s:%d",
1993 factory->obj_name,
1994 factory->type_name,
1995 (int)factory->addr_name.host.slen,
1996 factory->addr_name.host.ptr,
1997 (int)factory->addr_name.port));
1998 factory = factory->next;
1999 }
2000
2001 itr = pj_hash_first(mgr->table, &itr_val);
2002 if (itr) {
2003 PJ_LOG(3, (THIS_FILE, " Dumping transports:"));
2004
2005 do {
2006 pjsip_transport *t = (pjsip_transport*)
2007 pj_hash_this(mgr->table, itr);
2008
2009 PJ_LOG(3, (THIS_FILE, " %s %s (refcnt=%d%s)",
2010 t->obj_name,
2011 t->info,
2012 pj_atomic_get(t->ref_cnt),
2013 (t->idle_timer.id ? " [idle]" : "")));
2014
2015 itr = pj_hash_next(mgr->table, itr);
2016 } while (itr);
2017 }
2018
2019 pj_lock_release(mgr->lock);
2020#else
2021 PJ_UNUSED_ARG(mgr);
2022#endif
2023}
2024
2025/**
2026 * Set callback of global transport state notification.
2027 */
2028PJ_DEF(pj_status_t) pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr,
2029 pjsip_tp_state_callback cb)
2030{
2031 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
2032
2033 mgr->tp_state_cb = cb;
2034
2035 return PJ_SUCCESS;
2036}
2037
2038/**
2039 * Get callback of global transport state notification.
2040 */
2041PJ_DEF(pjsip_tp_state_callback) pjsip_tpmgr_get_state_cb(
2042 const pjsip_tpmgr *mgr)
2043{
2044 PJ_ASSERT_RETURN(mgr, NULL);
2045
2046 return mgr->tp_state_cb;
2047}
2048
2049
2050/**
2051 * Allocate and init transport data.
2052 */
2053static void init_tp_data(pjsip_transport *tp)
2054{
2055 transport_data *tp_data;
2056
2057 pj_assert(tp && !tp->data);
2058
2059 tp_data = PJ_POOL_ZALLOC_T(tp->pool, transport_data);
2060 pj_list_init(&tp_data->st_listeners);
2061 pj_list_init(&tp_data->st_listeners_empty);
2062 tp->data = tp_data;
2063}
2064
2065
2066static void tp_state_callback(pjsip_transport *tp,
2067 pjsip_transport_state state,
2068 const pjsip_transport_state_info *info)
2069{
2070 transport_data *tp_data;
2071
2072 pj_lock_acquire(tp->lock);
2073
2074 tp_data = (transport_data*)tp->data;
2075
2076 /* Notify the transport state listeners, if any. */
2077 if (!tp_data || pj_list_empty(&tp_data->st_listeners)) {
2078 goto on_return;
2079 } else {
2080 pjsip_transport_state_info st_info;
2081 tp_state_listener *st_listener = tp_data->st_listeners.next;
2082
2083 /* As we need to put the user data into the transport state info,
2084 * let's use a copy of transport state info.
2085 */
2086 pj_memcpy(&st_info, info, sizeof(st_info));
2087 while (st_listener != &tp_data->st_listeners) {
2088 st_info.user_data = st_listener->user_data;
2089 (*st_listener->cb)(tp, state, &st_info);
2090
2091 st_listener = st_listener->next;
2092 }
2093 }
2094
2095on_return:
2096 pj_lock_release(tp->lock);
2097}
2098
2099
2100/**
2101 * Add a listener to the specified transport for transport state notification.
2102 */
2103PJ_DEF(pj_status_t) pjsip_transport_add_state_listener (
2104 pjsip_transport *tp,
2105 pjsip_tp_state_callback cb,
2106 void *user_data,
2107 pjsip_tp_state_listener_key **key)
2108{
2109 transport_data *tp_data;
2110 tp_state_listener *entry;
2111
2112 PJ_ASSERT_RETURN(tp && cb && key, PJ_EINVAL);
2113
2114 pj_lock_acquire(tp->lock);
2115
2116 /* Init transport data, if it hasn't */
2117 if (!tp->data)
2118 init_tp_data(tp);
2119
2120 tp_data = (transport_data*)tp->data;
2121
2122 /* Init the new listener entry. Use available empty slot, if any,
2123 * otherwise allocate it using the transport pool.
2124 */
2125 if (!pj_list_empty(&tp_data->st_listeners_empty)) {
2126 entry = tp_data->st_listeners_empty.next;
2127 pj_list_erase(entry);
2128 } else {
2129 entry = PJ_POOL_ZALLOC_T(tp->pool, tp_state_listener);
2130 }
2131 entry->cb = cb;
2132 entry->user_data = user_data;
2133
2134 /* Add the new listener entry to the listeners list */
2135 pj_list_push_back(&tp_data->st_listeners, entry);
2136
2137 *key = entry;
2138
2139 pj_lock_release(tp->lock);
2140
2141 return PJ_SUCCESS;
2142}
2143
2144/**
2145 * Remove a listener from the specified transport for transport state
2146 * notification.
2147 */
2148PJ_DEF(pj_status_t) pjsip_transport_remove_state_listener (
2149 pjsip_transport *tp,
2150 pjsip_tp_state_listener_key *key,
2151 const void *user_data)
2152{
2153 transport_data *tp_data;
2154 tp_state_listener *entry;
2155
2156 PJ_ASSERT_RETURN(tp && key, PJ_EINVAL);
2157
2158 pj_lock_acquire(tp->lock);
2159
2160 tp_data = (transport_data*)tp->data;
2161
2162 /* Transport data is NULL or no registered listener? */
2163 if (!tp_data || pj_list_empty(&tp_data->st_listeners)) {
2164 pj_lock_release(tp->lock);
2165 return PJ_ENOTFOUND;
2166 }
2167
2168 entry = (tp_state_listener*)key;
2169
2170 /* Validate the user data */
2171 if (entry->user_data != user_data) {
2172 pj_assert(!"Invalid transport state listener key");
2173 pj_lock_release(tp->lock);
2174 return PJ_EBUG;
2175 }
2176
2177 /* Reset the entry and move it to the empty list */
2178 entry->cb = NULL;
2179 entry->user_data = NULL;
2180 pj_list_erase(entry);
2181 pj_list_push_back(&tp_data->st_listeners_empty, entry);
2182
2183 pj_lock_release(tp->lock);
2184
2185 return PJ_SUCCESS;
2186}