blob: 7caa2e9956008e1e04fd010c86cfa07e031409bf [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $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 /* tdata->info may be assigned by application so if it exists
581 * just return it.
582 */
583 if (tdata->info)
584 return tdata->info;
585
586 if (tdata==NULL || tdata->msg==NULL)
587 return "NULL";
588
589 pj_lock_acquire(tdata->lock);
590 tdata->info = get_msg_info(tdata->pool, tdata->obj_name, tdata->msg);
591 pj_lock_release(tdata->lock);
592
593 return tdata->info;
594}
595
596PJ_DEF(pj_status_t) pjsip_tx_data_set_transport(pjsip_tx_data *tdata,
597 const pjsip_tpselector *sel)
598{
599 PJ_ASSERT_RETURN(tdata && sel, PJ_EINVAL);
600
601 pj_lock_acquire(tdata->lock);
602
603 pjsip_tpselector_dec_ref(&tdata->tp_sel);
604
605 pj_memcpy(&tdata->tp_sel, sel, sizeof(*sel));
606 pjsip_tpselector_add_ref(&tdata->tp_sel);
607
608 pj_lock_release(tdata->lock);
609
610 return PJ_SUCCESS;
611}
612
613
614PJ_DEF(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata)
615{
616 char obj_name[PJ_MAX_OBJ_NAME];
617
618 PJ_ASSERT_RETURN(rdata->msg_info.msg, "INVALID MSG");
619
620 if (rdata->msg_info.info)
621 return rdata->msg_info.info;
622
623 pj_ansi_strcpy(obj_name, "rdata");
624 pj_ansi_snprintf(obj_name+5, sizeof(obj_name)-5, "%p", rdata);
625
626 rdata->msg_info.info = get_msg_info(rdata->tp_info.pool, obj_name,
627 rdata->msg_info.msg);
628 return rdata->msg_info.info;
629}
630
631/* Clone pjsip_rx_data. */
632PJ_DEF(pj_status_t) pjsip_rx_data_clone( const pjsip_rx_data *src,
633 unsigned flags,
634 pjsip_rx_data **p_rdata)
635{
636 pj_pool_t *pool;
637 pjsip_rx_data *dst;
638 pjsip_hdr *hdr;
639
640 PJ_ASSERT_RETURN(src && flags==0 && p_rdata, PJ_EINVAL);
641
642 pool = pj_pool_create(src->tp_info.pool->factory,
643 "rtd%p",
644 PJSIP_POOL_RDATA_LEN,
645 PJSIP_POOL_RDATA_INC,
646 NULL);
647 if (!pool)
648 return PJ_ENOMEM;
649
650 dst = PJ_POOL_ZALLOC_T(pool, pjsip_rx_data);
651
652 /* Parts of tp_info */
653 dst->tp_info.pool = pool;
654 dst->tp_info.transport = (pjsip_transport*)src->tp_info.transport;
655
656 /* pkt_info can be memcopied */
657 pj_memcpy(&dst->pkt_info, &src->pkt_info, sizeof(src->pkt_info));
658
659 /* msg_info needs deep clone */
660 dst->msg_info.msg_buf = dst->pkt_info.packet;
661 dst->msg_info.len = src->msg_info.len;
662 dst->msg_info.msg = pjsip_msg_clone(pool, src->msg_info.msg);
663 pj_list_init(&dst->msg_info.parse_err);
664
665#define GET_MSG_HDR2(TYPE, type, var) \
666 case PJSIP_H_##TYPE: \
667 if (!dst->msg_info.var) { \
668 dst->msg_info.var = (pjsip_##type##_hdr*)hdr; \
669 } \
670 break
671#define GET_MSG_HDR(TYPE, var_type) GET_MSG_HDR2(TYPE, var_type, var_type)
672
673 hdr = dst->msg_info.msg->hdr.next;
674 while (hdr != &dst->msg_info.msg->hdr) {
675 switch (hdr->type) {
676 GET_MSG_HDR(CALL_ID, cid);
677 GET_MSG_HDR(FROM, from);
678 GET_MSG_HDR(TO, to);
679 GET_MSG_HDR(VIA, via);
680 GET_MSG_HDR(CSEQ, cseq);
681 GET_MSG_HDR(MAX_FORWARDS, max_fwd);
682 GET_MSG_HDR(ROUTE, route);
683 GET_MSG_HDR2(RECORD_ROUTE, rr, record_route);
684 GET_MSG_HDR(CONTENT_TYPE, ctype);
685 GET_MSG_HDR(CONTENT_LENGTH, clen);
686 GET_MSG_HDR(REQUIRE, require);
687 GET_MSG_HDR(SUPPORTED, supported);
688 default:
689 break;
690 }
691 hdr = hdr->next;
692 }
693
694#undef GET_MSG_HDR
695#undef GET_MSG_HDR2
696
697 *p_rdata = dst;
698
699 /* Finally add transport ref */
700 return pjsip_transport_add_ref(dst->tp_info.transport);
701}
702
703/* Free previously cloned pjsip_rx_data. */
704PJ_DEF(pj_status_t) pjsip_rx_data_free_cloned(pjsip_rx_data *rdata)
705{
706 PJ_ASSERT_RETURN(rdata, PJ_EINVAL);
707
708 pjsip_transport_dec_ref(rdata->tp_info.transport);
709 pj_pool_release(rdata->tp_info.pool);
710
711 return PJ_SUCCESS;
712}
713
714/*****************************************************************************
715 *
716 * TRANSPORT KEY
717 *
718 *****************************************************************************/
719
720
721/*****************************************************************************
722 *
723 * TRANSPORT
724 *
725 *****************************************************************************/
726
727static void transport_send_callback(pjsip_transport *transport,
728 void *token,
729 pj_ssize_t size)
730{
731 pjsip_tx_data *tdata = (pjsip_tx_data*) token;
732
733 PJ_UNUSED_ARG(transport);
734
735 /* Mark pending off so that app can resend/reuse txdata from inside
736 * the callback.
737 */
738 tdata->is_pending = 0;
739
740 /* Call callback, if any. */
741 if (tdata->cb) {
742 (*tdata->cb)(tdata->token, tdata, size);
743 }
744
745 /* Decrement reference count. */
746 pjsip_tx_data_dec_ref(tdata);
747}
748
749/* This function is called by endpoint for on_tx_request() and on_tx_response()
750 * notification.
751 */
752static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata)
753{
754 return pjsip_tx_data_encode(tdata);
755}
756
757/*
758 * Send a SIP message using the specified transport.
759 */
760PJ_DEF(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
761 pjsip_tx_data *tdata,
762 const pj_sockaddr_t *addr,
763 int addr_len,
764 void *token,
765 pjsip_tp_send_callback cb)
766{
767 pj_status_t status;
768
769 PJ_ASSERT_RETURN(tr && tdata && addr, PJ_EINVAL);
770
771 /* Is it currently being sent? */
772 if (tdata->is_pending) {
773 pj_assert(!"Invalid operation step!");
774 PJ_LOG(2,(THIS_FILE, "Unable to send %s: message is pending",
775 pjsip_tx_data_get_info(tdata)));
776 return PJSIP_EPENDINGTX;
777 }
778
779 /* Add reference to prevent deletion, and to cancel idle timer if
780 * it's running.
781 */
782 pjsip_transport_add_ref(tr);
783
784 /* Fill in tp_info. */
785 tdata->tp_info.transport = tr;
786 pj_memcpy(&tdata->tp_info.dst_addr, addr, addr_len);
787 tdata->tp_info.dst_addr_len = addr_len;
788
789 pj_inet_ntop(((pj_sockaddr*)addr)->addr.sa_family,
790 pj_sockaddr_get_addr(addr),
791 tdata->tp_info.dst_name,
792 sizeof(tdata->tp_info.dst_name));
793 tdata->tp_info.dst_port = pj_sockaddr_get_port(addr);
794
795 /* Distribute to modules.
796 * When the message reach mod_msg_print, the contents of the message will
797 * be "printed" to contiguous buffer.
798 */
799 if (tr->tpmgr->on_tx_msg) {
800 status = (*tr->tpmgr->on_tx_msg)(tr->endpt, tdata);
801 if (status != PJ_SUCCESS) {
802 pjsip_transport_dec_ref(tr);
803 return status;
804 }
805 }
806
807 /* Save callback data. */
808 tdata->token = token;
809 tdata->cb = cb;
810
811 /* Add reference counter. */
812 pjsip_tx_data_add_ref(tdata);
813
814 /* Mark as pending. */
815 tdata->is_pending = 1;
816
817 /* Send to transport. */
818 status = (*tr->send_msg)(tr, tdata, addr, addr_len, (void*)tdata,
819 &transport_send_callback);
820
821 if (status != PJ_EPENDING) {
822 tdata->is_pending = 0;
823 pjsip_tx_data_dec_ref(tdata);
824 }
825
826 pjsip_transport_dec_ref(tr);
827 return status;
828}
829
830
831/* send_raw() callback */
832static void send_raw_callback(pjsip_transport *transport,
833 void *token,
834 pj_ssize_t size)
835{
836 pjsip_tx_data *tdata = (pjsip_tx_data*) token;
837
838 /* Mark pending off so that app can resend/reuse txdata from inside
839 * the callback.
840 */
841 tdata->is_pending = 0;
842
843 /* Call callback, if any. */
844 if (tdata->cb) {
845 (*tdata->cb)(tdata->token, tdata, size);
846 }
847
848 /* Decrement tdata reference count. */
849 pjsip_tx_data_dec_ref(tdata);
850
851 /* Decrement transport reference count */
852 pjsip_transport_dec_ref(transport);
853}
854
855
856/* Send raw data */
857PJ_DEF(pj_status_t) pjsip_tpmgr_send_raw(pjsip_tpmgr *mgr,
858 pjsip_transport_type_e tp_type,
859 const pjsip_tpselector *sel,
860 pjsip_tx_data *tdata,
861 const void *raw_data,
862 pj_size_t data_len,
863 const pj_sockaddr_t *addr,
864 int addr_len,
865 void *token,
866 pjsip_tp_send_callback cb)
867{
868 pjsip_transport *tr;
869 pj_status_t status;
870
871 /* Acquire the transport */
872 status = pjsip_tpmgr_acquire_transport(mgr, tp_type, addr, addr_len,
873 sel, &tr);
874 if (status != PJ_SUCCESS)
875 return status;
876
877 /* Create transmit data buffer if one is not specified */
878 if (tdata == NULL) {
879 status = pjsip_endpt_create_tdata(tr->endpt, &tdata);
880 if (status != PJ_SUCCESS) {
881 pjsip_transport_dec_ref(tr);
882 return status;
883 }
884
885 tdata->info = "raw";
886
887 /* Add reference counter. */
888 pjsip_tx_data_add_ref(tdata);
889 }
890
891 /* Allocate buffer */
892 if (tdata->buf.start == NULL ||
893 (tdata->buf.end - tdata->buf.start) < (int)data_len)
894 {
895 /* Note: data_len may be zero, so allocate +1 */
896 tdata->buf.start = (char*) pj_pool_alloc(tdata->pool, data_len+1);
897 tdata->buf.end = tdata->buf.start + data_len + 1;
898 }
899
900 /* Copy data, if any! (application may send zero len packet) */
901 if (data_len) {
902 pj_memcpy(tdata->buf.start, raw_data, data_len);
903 }
904 tdata->buf.cur = tdata->buf.start + data_len;
905
906 /* Save callback data. */
907 tdata->token = token;
908 tdata->cb = cb;
909
910 /* Mark as pending. */
911 tdata->is_pending = 1;
912
913 /* Send to transport */
914 status = tr->send_msg(tr, tdata, addr, addr_len,
915 tdata, &send_raw_callback);
916
917 if (status != PJ_EPENDING) {
918 /* callback will not be called, so destroy tdata now. */
919 pjsip_tx_data_dec_ref(tdata);
920 pjsip_transport_dec_ref(tr);
921 }
922
923 return status;
924}
925
926
927static void transport_idle_callback(pj_timer_heap_t *timer_heap,
928 struct pj_timer_entry *entry)
929{
930 pjsip_transport *tp = (pjsip_transport*) entry->user_data;
931 pj_assert(tp != NULL);
932
933 PJ_UNUSED_ARG(timer_heap);
934
935 entry->id = PJ_FALSE;
936 pjsip_transport_destroy(tp);
937}
938
939/*
940 * Add ref.
941 */
942PJ_DEF(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp )
943{
944 PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL);
945
946 if (pj_atomic_inc_and_get(tp->ref_cnt) == 1) {
947 pj_lock_acquire(tp->tpmgr->lock);
948 /* Verify again. */
949 if (pj_atomic_get(tp->ref_cnt) == 1) {
950 if (tp->idle_timer.id != PJ_FALSE) {
951 pjsip_endpt_cancel_timer(tp->tpmgr->endpt, &tp->idle_timer);
952 tp->idle_timer.id = PJ_FALSE;
953 }
954 }
955 pj_lock_release(tp->tpmgr->lock);
956 }
957
958 return PJ_SUCCESS;
959}
960
961/*
962 * Dec ref.
963 */
964PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp )
965{
966 PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL);
967
968 pj_assert(pj_atomic_get(tp->ref_cnt) > 0);
969
970 if (pj_atomic_dec_and_get(tp->ref_cnt) == 0) {
971 pj_lock_acquire(tp->tpmgr->lock);
972 /* Verify again. Do not register timer if the transport is
973 * being destroyed.
974 */
975 if (pj_atomic_get(tp->ref_cnt) == 0 && !tp->is_destroying) {
976 pj_time_val delay;
977
978 /* If transport is in graceful shutdown, then this is the
979 * last user who uses the transport. Schedule to destroy the
980 * transport immediately. Otherwise schedule idle timer.
981 */
982 if (tp->is_shutdown) {
983 delay.sec = delay.msec = 0;
984 } else {
985 delay.sec = (tp->dir==PJSIP_TP_DIR_OUTGOING) ?
986 PJSIP_TRANSPORT_IDLE_TIME :
987 PJSIP_TRANSPORT_SERVER_IDLE_TIME;
988 delay.msec = 0;
989 }
990
991 pj_assert(tp->idle_timer.id == 0);
992 tp->idle_timer.id = PJ_TRUE;
993 pjsip_endpt_schedule_timer(tp->tpmgr->endpt, &tp->idle_timer,
994 &delay);
995 }
996 pj_lock_release(tp->tpmgr->lock);
997 }
998
999 return PJ_SUCCESS;
1000}
1001
1002
1003/**
1004 * Register a transport.
1005 */
1006PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
1007 pjsip_transport *tp )
1008{
1009 int key_len;
1010 pj_uint32_t hval;
1011 void *entry;
1012
1013 /* Init. */
1014 tp->tpmgr = mgr;
1015 pj_bzero(&tp->idle_timer, sizeof(tp->idle_timer));
1016 tp->idle_timer.user_data = tp;
1017 tp->idle_timer.cb = &transport_idle_callback;
1018
1019 /*
1020 * Register to hash table (see Trac ticket #42).
1021 */
1022 key_len = sizeof(tp->key.type) + tp->addr_len;
1023 pj_lock_acquire(mgr->lock);
1024
1025 /* If entry already occupied, unregister previous entry */
1026 hval = 0;
1027 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
1028 if (entry != NULL)
1029 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
1030
1031 /* Register new entry */
1032 pj_hash_set(tp->pool, mgr->table, &tp->key, key_len, hval, tp);
1033
1034 pj_lock_release(mgr->lock);
1035
1036 TRACE_((THIS_FILE,"Transport %s registered: type=%s, remote=%s:%d",
1037 tp->obj_name,
1038 pjsip_transport_get_type_name(tp->key.type),
1039 addr_string(&tp->key.rem_addr),
1040 pj_sockaddr_get_port(&tp->key.rem_addr)));
1041
1042 return PJ_SUCCESS;
1043}
1044
1045/* Force destroy transport (e.g. during transport manager shutdown. */
1046static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
1047 pjsip_transport *tp )
1048{
1049 int key_len;
1050 pj_uint32_t hval;
1051 void *entry;
1052
1053 TRACE_((THIS_FILE, "Transport %s is being destroyed", tp->obj_name));
1054
1055 pj_lock_acquire(tp->lock);
1056 pj_lock_acquire(mgr->lock);
1057
1058 tp->is_destroying = PJ_TRUE;
1059
1060 /*
1061 * Unregister timer, if any.
1062 */
1063 //pj_assert(tp->idle_timer.id == PJ_FALSE);
1064 if (tp->idle_timer.id != PJ_FALSE) {
1065 pjsip_endpt_cancel_timer(mgr->endpt, &tp->idle_timer);
1066 tp->idle_timer.id = PJ_FALSE;
1067 }
1068
1069 /*
1070 * Unregister from hash table (see Trac ticket #42).
1071 */
1072 key_len = sizeof(tp->key.type) + tp->addr_len;
1073 hval = 0;
1074 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
1075 if (entry == (void*)tp)
1076 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval, NULL);
1077
1078 pj_lock_release(mgr->lock);
1079
1080 /* Destroy. */
1081 return tp->destroy(tp);
1082}
1083
1084
1085/*
1086 * Start graceful shutdown procedure for this transport.
1087 */
1088PJ_DEF(pj_status_t) pjsip_transport_shutdown(pjsip_transport *tp)
1089{
1090 pjsip_tpmgr *mgr;
1091 pj_status_t status;
1092
1093 TRACE_((THIS_FILE, "Transport %s shutting down", tp->obj_name));
1094
1095 pj_lock_acquire(tp->lock);
1096
1097 mgr = tp->tpmgr;
1098 pj_lock_acquire(mgr->lock);
1099
1100 /* Do nothing if transport is being shutdown already */
1101 if (tp->is_shutdown) {
1102 pj_lock_release(tp->lock);
1103 pj_lock_release(mgr->lock);
1104 return PJ_SUCCESS;
1105 }
1106
1107 status = PJ_SUCCESS;
1108
1109 /* Instruct transport to shutdown itself */
1110 if (tp->do_shutdown)
1111 status = tp->do_shutdown(tp);
1112
1113 if (status == PJ_SUCCESS)
1114 tp->is_shutdown = PJ_TRUE;
1115
1116 /* If transport reference count is zero, start timer count-down */
1117 if (pj_atomic_get(tp->ref_cnt) == 0) {
1118 pjsip_transport_add_ref(tp);
1119 pjsip_transport_dec_ref(tp);
1120 }
1121
1122 pj_lock_release(tp->lock);
1123 pj_lock_release(mgr->lock);
1124
1125 return status;
1126}
1127
1128
1129/**
1130 * Unregister transport.
1131 */
1132PJ_DEF(pj_status_t) pjsip_transport_destroy( pjsip_transport *tp)
1133{
1134 /* Must have no user. */
1135 PJ_ASSERT_RETURN(pj_atomic_get(tp->ref_cnt) == 0, PJSIP_EBUSY);
1136
1137 /* Destroy. */
1138 return destroy_transport(tp->tpmgr, tp);
1139}
1140
1141
1142
1143/*****************************************************************************
1144 *
1145 * TRANSPORT FACTORY
1146 *
1147 *****************************************************************************/
1148
1149
1150PJ_DEF(pj_status_t) pjsip_tpmgr_register_tpfactory( pjsip_tpmgr *mgr,
1151 pjsip_tpfactory *tpf)
1152{
1153 pjsip_tpfactory *p;
1154 pj_status_t status;
1155
1156 pj_lock_acquire(mgr->lock);
1157
1158 /* Check that no factory with the same type has been registered. */
1159 status = PJ_SUCCESS;
1160 for (p=mgr->factory_list.next; p!=&mgr->factory_list; p=p->next) {
1161 if (p->type == tpf->type) {
1162 status = PJSIP_ETYPEEXISTS;
1163 break;
1164 }
1165 if (p == tpf) {
1166 status = PJ_EEXISTS;
1167 break;
1168 }
1169 }
1170
1171 if (status != PJ_SUCCESS) {
1172 pj_lock_release(mgr->lock);
1173 return status;
1174 }
1175
1176 pj_list_insert_before(&mgr->factory_list, tpf);
1177
1178 pj_lock_release(mgr->lock);
1179
1180 return PJ_SUCCESS;
1181}
1182
1183
1184/**
1185 * Unregister factory.
1186 */
1187PJ_DEF(pj_status_t) pjsip_tpmgr_unregister_tpfactory( pjsip_tpmgr *mgr,
1188 pjsip_tpfactory *tpf)
1189{
1190 pj_lock_acquire(mgr->lock);
1191
1192 pj_assert(pj_list_find_node(&mgr->factory_list, tpf) == tpf);
1193 pj_list_erase(tpf);
1194
1195 pj_lock_release(mgr->lock);
1196
1197 return PJ_SUCCESS;
1198}
1199
1200PJ_DECL(void) pjsip_tpmgr_fla2_param_default(pjsip_tpmgr_fla2_param *prm)
1201{
1202 pj_bzero(prm, sizeof(*prm));
1203}
1204
1205/*****************************************************************************
1206 *
1207 * TRANSPORT MANAGER
1208 *
1209 *****************************************************************************/
1210
1211/*
1212 * Create a new transport manager.
1213 */
1214PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
1215 pjsip_endpoint *endpt,
1216 pjsip_rx_callback rx_cb,
1217 pjsip_tx_callback tx_cb,
1218 pjsip_tpmgr **p_mgr)
1219{
1220 pjsip_tpmgr *mgr;
1221 pj_status_t status;
1222
1223 PJ_ASSERT_RETURN(pool && endpt && rx_cb && p_mgr, PJ_EINVAL);
1224
1225 /* Register mod_msg_print module. */
1226 status = pjsip_endpt_register_module(endpt, &mod_msg_print);
1227 if (status != PJ_SUCCESS)
1228 return status;
1229
1230 /* Create and initialize transport manager. */
1231 mgr = PJ_POOL_ZALLOC_T(pool, pjsip_tpmgr);
1232 mgr->endpt = endpt;
1233 mgr->on_rx_msg = rx_cb;
1234 mgr->on_tx_msg = tx_cb;
1235 pj_list_init(&mgr->factory_list);
1236 pj_list_init(&mgr->tdata_list);
1237
1238 mgr->table = pj_hash_create(pool, PJSIP_TPMGR_HTABLE_SIZE);
1239 if (!mgr->table)
1240 return PJ_ENOMEM;
1241
1242 status = pj_lock_create_recursive_mutex(pool, "tmgr%p", &mgr->lock);
1243 if (status != PJ_SUCCESS)
1244 return status;
1245
1246#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1247 status = pj_atomic_create(pool, 0, &mgr->tdata_counter);
1248 if (status != PJ_SUCCESS) {
1249 pj_lock_destroy(mgr->lock);
1250 return status;
1251 }
1252#endif
1253
1254 /* Set transport state callback */
1255 pjsip_tpmgr_set_state_cb(mgr, &tp_state_callback);
1256
1257 PJ_LOG(5, (THIS_FILE, "Transport manager created."));
1258
1259 *p_mgr = mgr;
1260 return PJ_SUCCESS;
1261}
1262
1263/* Get the interface to send packet to the specified address */
1264static pj_status_t get_net_interface(pjsip_transport_type_e tp_type,
1265 const pj_str_t *dst,
1266 pj_str_t *itf_str_addr)
1267{
1268 int af;
1269 pj_sockaddr itf_addr;
1270 pj_status_t status;
1271
1272 af = (tp_type & PJSIP_TRANSPORT_IPV6)? PJ_AF_INET6 : PJ_AF_INET;
1273 status = pj_getipinterface(af, dst, &itf_addr, PJ_FALSE, NULL);
1274 if (status != PJ_SUCCESS) {
1275 /* If it fails, e.g: on WM6 (http://support.microsoft.com/kb/129065),
1276 * just fallback using pj_gethostip(), see ticket #1660.
1277 */
1278 PJ_LOG(5,(THIS_FILE,"Warning: unable to determine local "
1279 "interface, fallback to default interface!"));
1280 status = pj_gethostip(af, &itf_addr);
1281 if (status != PJ_SUCCESS)
1282 return status;
1283 }
1284
1285 /* Print address */
1286 pj_sockaddr_print(&itf_addr, itf_str_addr->ptr,
1287 PJ_INET6_ADDRSTRLEN, 0);
1288 itf_str_addr->slen = pj_ansi_strlen(itf_str_addr->ptr);
1289
1290 return PJ_SUCCESS;
1291}
1292
1293/*
1294 * Find out the appropriate local address info (IP address and port) to
1295 * advertise in Contact header based on the remote address to be
1296 * contacted. The local address info would be the address name of the
1297 * transport or listener which will be used to send the request.
1298 *
1299 * In this implementation, it will only select the transport based on
1300 * the transport type in the request.
1301 */
1302PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr2(pjsip_tpmgr *tpmgr,
1303 pj_pool_t *pool,
1304 pjsip_tpmgr_fla2_param *prm)
1305{
1306 char tmp_buf[PJ_INET6_ADDRSTRLEN+10];
1307 pj_str_t tmp_str;
1308 pj_status_t status = PJSIP_EUNSUPTRANSPORT;
1309 unsigned flag;
1310
1311 /* Sanity checks */
1312 PJ_ASSERT_RETURN(tpmgr && pool && prm, PJ_EINVAL);
1313
1314 pj_strset(&tmp_str, tmp_buf, 0);
1315 prm->ret_addr.slen = 0;
1316 prm->ret_port = 0;
1317 prm->ret_tp = NULL;
1318
1319 flag = pjsip_transport_get_flag_from_type(prm->tp_type);
1320
1321 if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
1322 prm->tp_sel->u.transport)
1323 {
1324 const pjsip_transport *tp = prm->tp_sel->u.transport;
1325 if (prm->local_if) {
1326 status = get_net_interface((pjsip_transport_type_e)tp->key.type,
1327 &prm->dst_host, &tmp_str);
1328 if (status != PJ_SUCCESS)
1329 goto on_return;
1330 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1331 prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
1332 prm->ret_tp = tp;
1333 } else {
1334 pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
1335 prm->ret_port = (pj_uint16_t)tp->local_name.port;
1336 }
1337 status = PJ_SUCCESS;
1338
1339 } else if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_LISTENER &&
1340 prm->tp_sel->u.listener)
1341 {
1342 if (prm->local_if) {
1343 status = get_net_interface(prm->tp_sel->u.listener->type,
1344 &prm->dst_host, &tmp_str);
1345 if (status != PJ_SUCCESS)
1346 goto on_return;
1347 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1348 } else {
1349 pj_strdup(pool, &prm->ret_addr,
1350 &prm->tp_sel->u.listener->addr_name.host);
1351 }
1352 prm->ret_port = (pj_uint16_t)prm->tp_sel->u.listener->addr_name.port;
1353 status = PJ_SUCCESS;
1354
1355 } else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
1356 pj_sockaddr remote;
1357 int addr_len;
1358 pjsip_transport *tp;
1359
1360 pj_bzero(&remote, sizeof(remote));
1361 if (prm->tp_type & PJSIP_TRANSPORT_IPV6) {
1362 addr_len = sizeof(pj_sockaddr_in6);
1363 remote.addr.sa_family = pj_AF_INET6();
1364 } else {
1365 addr_len = sizeof(pj_sockaddr_in);
1366 remote.addr.sa_family = pj_AF_INET();
1367 }
1368
1369 status = pjsip_tpmgr_acquire_transport(tpmgr, prm->tp_type, &remote,
1370 addr_len, NULL, &tp);
1371
1372 if (status == PJ_SUCCESS) {
1373 if (prm->local_if) {
1374 status = get_net_interface((pjsip_transport_type_e)
1375 tp->key.type,
1376 &prm->dst_host, &tmp_str);
1377 if (status != PJ_SUCCESS)
1378 goto on_return;
1379 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1380 prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
1381 prm->ret_tp = tp;
1382 } else {
1383 pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
1384 prm->ret_port = (pj_uint16_t)tp->local_name.port;
1385 }
1386
1387 pjsip_transport_dec_ref(tp);
1388 }
1389
1390 } else {
1391 /* For connection oriented transport, enum the factories */
1392 pjsip_tpfactory *f;
1393
1394 pj_lock_acquire(tpmgr->lock);
1395
1396 f = tpmgr->factory_list.next;
1397 while (f != &tpmgr->factory_list) {
1398 if (f->type == prm->tp_type)
1399 break;
1400 f = f->next;
1401 }
1402
1403 if (f != &tpmgr->factory_list) {
1404 if (prm->local_if) {
1405 status = get_net_interface(f->type, &prm->dst_host,
1406 &tmp_str);
1407 if (status == PJ_SUCCESS) {
1408 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1409 } else {
1410 /* It could fail "normally" on certain cases, e.g.
1411 * when connecting to IPv6 link local address, it
1412 * will wail with EINVAL.
1413 * In this case, fallback to use the default interface
1414 * rather than failing the call.
1415 */
1416 PJ_PERROR(5,(THIS_FILE, status, "Warning: unable to "
1417 "determine local interface"));
1418 pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
1419 status = PJ_SUCCESS;
1420 }
1421 } else {
1422 pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
1423 }
1424 prm->ret_port = (pj_uint16_t)f->addr_name.port;
1425 status = PJ_SUCCESS;
1426 }
1427 pj_lock_release(tpmgr->lock);
1428 }
1429
1430on_return:
1431 return status;
1432}
1433
1434PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
1435 pj_pool_t *pool,
1436 pjsip_transport_type_e type,
1437 const pjsip_tpselector *sel,
1438 pj_str_t *ip_addr,
1439 int *port)
1440{
1441 pjsip_tpmgr_fla2_param prm;
1442 pj_status_t status;
1443
1444 pjsip_tpmgr_fla2_param_default(&prm);
1445 prm.tp_type = type;
1446 prm.tp_sel = sel;
1447
1448 status = pjsip_tpmgr_find_local_addr2(tpmgr, pool, &prm);
1449 if (status != PJ_SUCCESS)
1450 return status;
1451
1452 *ip_addr = prm.ret_addr;
1453 *port = prm.ret_port;
1454
1455 return PJ_SUCCESS;
1456}
1457
1458/*
1459 * Return number of transports currently registered to the transport
1460 * manager.
1461 */
1462PJ_DEF(unsigned) pjsip_tpmgr_get_transport_count(pjsip_tpmgr *mgr)
1463{
1464 pj_hash_iterator_t itr_val;
1465 pj_hash_iterator_t *itr;
1466 int nr_of_transports = 0;
1467
1468 pj_lock_acquire(mgr->lock);
1469
1470 itr = pj_hash_first(mgr->table, &itr_val);
1471 while (itr) {
1472 nr_of_transports++;
1473 itr = pj_hash_next(mgr->table, itr);
1474 }
1475
1476 pj_lock_release(mgr->lock);
1477
1478 return nr_of_transports;
1479}
1480
1481/*
1482 * pjsip_tpmgr_destroy()
1483 *
1484 * Destroy transport manager.
1485 */
1486PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
1487{
1488 pj_hash_iterator_t itr_val;
1489 pj_hash_iterator_t *itr;
1490 pjsip_tpfactory *factory;
1491 pjsip_endpoint *endpt = mgr->endpt;
1492
1493 PJ_LOG(5, (THIS_FILE, "Destroying transport manager"));
1494
1495 pj_lock_acquire(mgr->lock);
1496
1497 /*
1498 * Destroy all transports.
1499 */
1500 itr = pj_hash_first(mgr->table, &itr_val);
1501 while (itr != NULL) {
1502 pj_hash_iterator_t *next;
1503 pjsip_transport *transport;
1504
1505 transport = (pjsip_transport*) pj_hash_this(mgr->table, itr);
1506
1507 next = pj_hash_next(mgr->table, itr);
1508
1509 destroy_transport(mgr, transport);
1510
1511 itr = next;
1512 }
1513
1514 /*
1515 * Destroy all factories/listeners.
1516 */
1517 factory = mgr->factory_list.next;
1518 while (factory != &mgr->factory_list) {
1519 pjsip_tpfactory *next = factory->next;
1520
1521 factory->destroy(factory);
1522
1523 factory = next;
1524 }
1525
1526 pj_lock_release(mgr->lock);
1527
1528#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1529 /* If you encounter assert error on this line, it means there are
1530 * leakings in transmit data (i.e. some transmit data have not been
1531 * destroyed).
1532 */
1533 //pj_assert(pj_atomic_get(mgr->tdata_counter) == 0);
1534 if (pj_atomic_get(mgr->tdata_counter) != 0) {
1535 PJ_LOG(3,(THIS_FILE, "Warning: %d transmit buffer(s) not freed!",
1536 pj_atomic_get(mgr->tdata_counter)));
1537 }
1538#endif
1539
1540 /*
1541 * Destroy any dangling transmit buffer.
1542 */
1543 if (!pj_list_empty(&mgr->tdata_list)) {
1544 pjsip_tx_data *tdata = mgr->tdata_list.next;
1545 while (tdata != &mgr->tdata_list) {
1546 pjsip_tx_data *next = tdata->next;
1547 tx_data_destroy(tdata);
1548 tdata = next;
1549 }
1550 PJ_LOG(3,(THIS_FILE, "Cleaned up dangling transmit buffer(s)."));
1551 }
1552
1553#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1554 pj_atomic_destroy(mgr->tdata_counter);
1555#endif
1556
1557 pj_lock_destroy(mgr->lock);
1558
1559 /* Unregister mod_msg_print. */
1560 if (mod_msg_print.id != -1) {
1561 pjsip_endpt_unregister_module(endpt, &mod_msg_print);
1562 }
1563
1564 return PJ_SUCCESS;
1565}
1566
1567
1568/*
1569 * pjsip_tpmgr_receive_packet()
1570 *
1571 * Called by tranports when they receive a new packet.
1572 */
1573PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr,
1574 pjsip_rx_data *rdata)
1575{
1576 pjsip_transport *tr = rdata->tp_info.transport;
1577
1578 char *current_pkt;
1579 pj_size_t remaining_len;
1580 pj_size_t total_processed = 0;
1581
1582 /* Check size. */
1583 pj_assert(rdata->pkt_info.len > 0);
1584 if (rdata->pkt_info.len <= 0)
1585 return -1;
1586
1587 current_pkt = rdata->pkt_info.packet;
1588 remaining_len = rdata->pkt_info.len;
1589
1590 /* Must NULL terminate buffer. This is the requirement of the
1591 * parser etc.
1592 */
1593 current_pkt[remaining_len] = '\0';
1594
1595 /* Process all message fragments. */
1596 while (remaining_len > 0) {
1597
1598 pjsip_msg *msg;
1599 char *p, *end;
1600 char saved;
1601 pj_size_t msg_fragment_size;
1602
1603 /* Skip leading newlines as pjsip_find_msg() currently can't
1604 * handle leading newlines.
1605 */
1606 for (p=current_pkt, end=p+remaining_len; p!=end; ++p) {
1607 if (*p != '\r' && *p != '\n')
1608 break;
1609 }
1610 if (p!=current_pkt) {
1611 remaining_len -= (p - current_pkt);
1612 total_processed += (p - current_pkt);
1613 current_pkt = p;
1614 if (remaining_len == 0) {
1615 return total_processed;
1616 }
1617 }
1618
1619 /* Initialize default fragment size. */
1620 msg_fragment_size = remaining_len;
1621
1622 /* Clear and init msg_info in rdata.
1623 * Endpoint might inspect the values there when we call the callback
1624 * to report some errors.
1625 */
1626 pj_bzero(&rdata->msg_info, sizeof(rdata->msg_info));
1627 pj_list_init(&rdata->msg_info.parse_err);
1628 rdata->msg_info.msg_buf = current_pkt;
1629 rdata->msg_info.len = (int)remaining_len;
1630
1631 /* For TCP transport, check if the whole message has been received. */
1632 if ((tr->flag & PJSIP_TRANSPORT_DATAGRAM) == 0) {
1633 pj_status_t msg_status;
1634 msg_status = pjsip_find_msg(current_pkt, remaining_len, PJ_FALSE,
1635 &msg_fragment_size);
1636 if (msg_status != PJ_SUCCESS) {
1637 if (remaining_len == PJSIP_MAX_PKT_LEN) {
1638 mgr->on_rx_msg(mgr->endpt, PJSIP_ERXOVERFLOW, rdata);
1639 /* Exhaust all data. */
1640 return rdata->pkt_info.len;
1641 } else {
1642 /* Not enough data in packet. */
1643 return total_processed;
1644 }
1645 }
1646 }
1647
1648 /* Update msg_info. */
1649 rdata->msg_info.len = (int)msg_fragment_size;
1650
1651 /* Null terminate packet */
1652 saved = current_pkt[msg_fragment_size];
1653 current_pkt[msg_fragment_size] = '\0';
1654
1655 /* Parse the message. */
1656 rdata->msg_info.msg = msg =
1657 pjsip_parse_rdata( current_pkt, msg_fragment_size, rdata);
1658
1659 /* Restore null termination */
1660 current_pkt[msg_fragment_size] = saved;
1661
1662 /* Check for parsing syntax error */
1663 if (msg==NULL || !pj_list_empty(&rdata->msg_info.parse_err)) {
1664 pjsip_parser_err_report *err;
1665 char buf[128];
1666 pj_str_t tmp;
1667
1668 /* Gather syntax error information */
1669 tmp.ptr = buf; tmp.slen = 0;
1670 err = rdata->msg_info.parse_err.next;
1671 while (err != &rdata->msg_info.parse_err) {
1672 int len;
1673 len = pj_ansi_snprintf(tmp.ptr+tmp.slen, sizeof(buf)-tmp.slen,
1674 ": %s exception when parsing '%.*s' "
1675 "header on line %d col %d",
1676 pj_exception_id_name(err->except_code),
1677 (int)err->hname.slen, err->hname.ptr,
1678 err->line, err->col);
1679 if (len > 0 && len < (int) (sizeof(buf)-tmp.slen)) {
1680 tmp.slen += len;
1681 }
1682 err = err->next;
1683 }
1684
1685 /* Only print error message if there's error.
1686 * Sometimes we receive blank packets (packets with only CRLF)
1687 * which were sent to keep NAT bindings.
1688 */
1689 if (tmp.slen) {
1690 PJ_LOG(1, (THIS_FILE,
1691 "Error processing %d bytes packet from %s %s:%d %.*s:\n"
1692 "%.*s\n"
1693 "-- end of packet.",
1694 msg_fragment_size,
1695 rdata->tp_info.transport->type_name,
1696 rdata->pkt_info.src_name,
1697 rdata->pkt_info.src_port,
1698 (int)tmp.slen, tmp.ptr,
1699 (int)msg_fragment_size,
1700 rdata->msg_info.msg_buf));
1701 }
1702
1703 goto finish_process_fragment;
1704 }
1705
1706 /* Perform basic header checking. */
1707 if (rdata->msg_info.cid == NULL ||
1708 rdata->msg_info.cid->id.slen == 0 ||
1709 rdata->msg_info.from == NULL ||
1710 rdata->msg_info.to == NULL ||
1711 rdata->msg_info.via == NULL ||
1712 rdata->msg_info.cseq == NULL)
1713 {
1714 mgr->on_rx_msg(mgr->endpt, PJSIP_EMISSINGHDR, rdata);
1715 goto finish_process_fragment;
1716 }
1717
1718 /* For request: */
1719 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
1720 /* always add received parameter to the via. */
1721 pj_strdup2(rdata->tp_info.pool,
1722 &rdata->msg_info.via->recvd_param,
1723 rdata->pkt_info.src_name);
1724
1725 /* RFC 3581:
1726 * If message contains "rport" param, put the received port there.
1727 */
1728 if (rdata->msg_info.via->rport_param == 0) {
1729 rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
1730 }
1731 } else {
1732 /* Drop malformed responses */
1733 if (rdata->msg_info.msg->line.status.code < 100 ||
1734 rdata->msg_info.msg->line.status.code >= 700)
1735 {
1736 mgr->on_rx_msg(mgr->endpt, PJSIP_EINVALIDSTATUS, rdata);
1737 goto finish_process_fragment;
1738 }
1739 }
1740
1741 /* Drop response message if it has more than one Via.
1742 */
1743 /* This is wrong. Proxy DOES receive responses with multiple
1744 * Via headers! Thanks Aldo <acampi at deis.unibo.it> for pointing
1745 * this out.
1746
1747 if (msg->type == PJSIP_RESPONSE_MSG) {
1748 pjsip_hdr *hdr;
1749 hdr = (pjsip_hdr*)rdata->msg_info.via->next;
1750 if (hdr != &msg->hdr) {
1751 hdr = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, hdr);
1752 if (hdr) {
1753 mgr->on_rx_msg(mgr->endpt, PJSIP_EMULTIPLEVIA, rdata);
1754 goto finish_process_fragment;
1755 }
1756 }
1757 }
1758 */
1759
1760 /* Call the transport manager's upstream message callback.
1761 */
1762 mgr->on_rx_msg(mgr->endpt, PJ_SUCCESS, rdata);
1763
1764
1765finish_process_fragment:
1766 total_processed += msg_fragment_size;
1767 current_pkt += msg_fragment_size;
1768 remaining_len -= msg_fragment_size;
1769
1770 } /* while (rdata->pkt_info.len > 0) */
1771
1772
1773 return total_processed;
1774}
1775
1776
1777/*
1778 * pjsip_tpmgr_acquire_transport()
1779 *
1780 * Get transport suitable to communicate to remote. Create a new one
1781 * if necessary.
1782 */
1783PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
1784 pjsip_transport_type_e type,
1785 const pj_sockaddr_t *remote,
1786 int addr_len,
1787 const pjsip_tpselector *sel,
1788 pjsip_transport **tp)
1789{
1790 return pjsip_tpmgr_acquire_transport2(mgr, type, remote, addr_len, sel,
1791 NULL, tp);
1792}
1793
1794/*
1795 * pjsip_tpmgr_acquire_transport2()
1796 *
1797 * Get transport suitable to communicate to remote. Create a new one
1798 * if necessary.
1799 */
1800PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
1801 pjsip_transport_type_e type,
1802 const pj_sockaddr_t *remote,
1803 int addr_len,
1804 const pjsip_tpselector *sel,
1805 pjsip_tx_data *tdata,
1806 pjsip_transport **tp)
1807{
1808 pjsip_tpfactory *factory;
1809 pj_status_t status;
1810
1811 TRACE_((THIS_FILE,"Acquiring transport type=%s, remote=%s:%d",
1812 pjsip_transport_get_type_name(type),
1813 addr_string(remote),
1814 pj_sockaddr_get_port(remote)));
1815
1816 pj_lock_acquire(mgr->lock);
1817
1818 /* If transport is specified, then just use it if it is suitable
1819 * for the destination.
1820 */
1821 if (sel && sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
1822 sel->u.transport)
1823 {
1824 pjsip_transport *seltp = sel->u.transport;
1825
1826 /* See if the transport is (not) suitable */
1827 if (seltp->key.type != type) {
1828 pj_lock_release(mgr->lock);
1829 return PJSIP_ETPNOTSUITABLE;
1830 }
1831
1832 /* We could also verify that the destination address is reachable
1833 * from this transport (i.e. both are equal), but if application
1834 * has requested a specific transport to be used, assume that
1835 * it knows what to do.
1836 *
1837 * In other words, I don't think destination verification is a good
1838 * idea for now.
1839 */
1840
1841 /* Transport looks to be suitable to use, so just use it. */
1842 pjsip_transport_add_ref(seltp);
1843 pj_lock_release(mgr->lock);
1844 *tp = seltp;
1845
1846 TRACE_((THIS_FILE, "Transport %s acquired", seltp->obj_name));
1847 return PJ_SUCCESS;
1848
1849
1850 } else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
1851 sel->u.listener)
1852 {
1853 /* Application has requested that a specific listener is to
1854 * be used. In this case, skip transport hash table lookup.
1855 */
1856
1857 /* Verify that the listener type matches the destination type */
1858 if (sel->u.listener->type != type) {
1859 pj_lock_release(mgr->lock);
1860 return PJSIP_ETPNOTSUITABLE;
1861 }
1862
1863 /* We'll use this listener to create transport */
1864 factory = sel->u.listener;
1865
1866 } else {
1867
1868 /*
1869 * This is the "normal" flow, where application doesn't specify
1870 * specific transport/listener to be used to send message to.
1871 * In this case, lookup the transport from the hash table.
1872 */
1873 pjsip_transport_key key;
1874 int key_len;
1875 pjsip_transport *transport;
1876
1877 pj_bzero(&key, sizeof(key));
1878 key_len = sizeof(key.type) + addr_len;
1879
1880 /* First try to get exact destination. */
1881 key.type = type;
1882 pj_memcpy(&key.rem_addr, remote, addr_len);
1883
1884 transport = (pjsip_transport*)
1885 pj_hash_get(mgr->table, &key, key_len, NULL);
1886
1887 if (transport == NULL) {
1888 unsigned flag = pjsip_transport_get_flag_from_type(type);
1889 const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote;
1890
1891
1892 /* Ignore address for loop transports. */
1893 if (type == PJSIP_TRANSPORT_LOOP ||
1894 type == PJSIP_TRANSPORT_LOOP_DGRAM)
1895 {
1896 pj_sockaddr *addr = &key.rem_addr;
1897
1898 pj_bzero(addr, addr_len);
1899 key_len = sizeof(key.type) + addr_len;
1900 transport = (pjsip_transport*)
1901 pj_hash_get(mgr->table, &key, key_len, NULL);
1902 }
1903 /* For datagram transports, try lookup with zero address.
1904 */
1905 else if (flag & PJSIP_TRANSPORT_DATAGRAM)
1906 {
1907 pj_sockaddr *addr = &key.rem_addr;
1908
1909 pj_bzero(addr, addr_len);
1910 addr->addr.sa_family = remote_addr->addr.sa_family;
1911
1912 key_len = sizeof(key.type) + addr_len;
1913 transport = (pjsip_transport*)
1914 pj_hash_get(mgr->table, &key, key_len, NULL);
1915 }
1916 }
1917
1918 if (transport!=NULL && !transport->is_shutdown) {
1919 /*
1920 * Transport found!
1921 */
1922 pjsip_transport_add_ref(transport);
1923 pj_lock_release(mgr->lock);
1924 *tp = transport;
1925
1926 TRACE_((THIS_FILE, "Transport %s acquired", transport->obj_name));
1927 return PJ_SUCCESS;
1928 }
1929
1930 /*
1931 * Transport not found!
1932 * Find factory that can create such transport.
1933 */
1934 factory = mgr->factory_list.next;
1935 while (factory != &mgr->factory_list) {
1936 if (factory->type == type)
1937 break;
1938 factory = factory->next;
1939 }
1940
1941 if (factory == &mgr->factory_list) {
1942 /* No factory can create the transport! */
1943 pj_lock_release(mgr->lock);
1944 TRACE_((THIS_FILE, "No suitable factory was found either"));
1945 return PJSIP_EUNSUPTRANSPORT;
1946 }
1947 }
1948
1949 TRACE_((THIS_FILE, "Creating new transport from factory"));
1950
1951 /* Request factory to create transport. */
1952 if (factory->create_transport2) {
1953 status = factory->create_transport2(factory, mgr, mgr->endpt,
1954 (const pj_sockaddr*) remote,
1955 addr_len, tdata, tp);
1956 } else {
1957 status = factory->create_transport(factory, mgr, mgr->endpt,
1958 (const pj_sockaddr*) remote,
1959 addr_len, tp);
1960 }
1961 if (status == PJ_SUCCESS) {
1962 PJ_ASSERT_ON_FAIL(tp!=NULL,
1963 {pj_lock_release(mgr->lock); return PJ_EBUG;});
1964 pjsip_transport_add_ref(*tp);
1965 }
1966 pj_lock_release(mgr->lock);
1967 return status;
1968}
1969
1970/**
1971 * Dump transport info.
1972 */
1973PJ_DEF(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr)
1974{
1975#if PJ_LOG_MAX_LEVEL >= 3
1976 pj_hash_iterator_t itr_val;
1977 pj_hash_iterator_t *itr;
1978 pjsip_tpfactory *factory;
1979
1980 pj_lock_acquire(mgr->lock);
1981
1982#if defined(PJ_DEBUG) && PJ_DEBUG!=0
1983 PJ_LOG(3,(THIS_FILE, " Outstanding transmit buffers: %d",
1984 pj_atomic_get(mgr->tdata_counter)));
1985#endif
1986
1987 PJ_LOG(3, (THIS_FILE, " Dumping listeners:"));
1988 factory = mgr->factory_list.next;
1989 while (factory != &mgr->factory_list) {
1990 PJ_LOG(3, (THIS_FILE, " %s %s:%.*s:%d",
1991 factory->obj_name,
1992 factory->type_name,
1993 (int)factory->addr_name.host.slen,
1994 factory->addr_name.host.ptr,
1995 (int)factory->addr_name.port));
1996 factory = factory->next;
1997 }
1998
1999 itr = pj_hash_first(mgr->table, &itr_val);
2000 if (itr) {
2001 PJ_LOG(3, (THIS_FILE, " Dumping transports:"));
2002
2003 do {
2004 pjsip_transport *t = (pjsip_transport*)
2005 pj_hash_this(mgr->table, itr);
2006
2007 PJ_LOG(3, (THIS_FILE, " %s %s (refcnt=%d%s)",
2008 t->obj_name,
2009 t->info,
2010 pj_atomic_get(t->ref_cnt),
2011 (t->idle_timer.id ? " [idle]" : "")));
2012
2013 itr = pj_hash_next(mgr->table, itr);
2014 } while (itr);
2015 }
2016
2017 pj_lock_release(mgr->lock);
2018#else
2019 PJ_UNUSED_ARG(mgr);
2020#endif
2021}
2022
2023/**
2024 * Set callback of global transport state notification.
2025 */
2026PJ_DEF(pj_status_t) pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr,
2027 pjsip_tp_state_callback cb)
2028{
2029 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
2030
2031 mgr->tp_state_cb = cb;
2032
2033 return PJ_SUCCESS;
2034}
2035
2036/**
2037 * Get callback of global transport state notification.
2038 */
2039PJ_DEF(pjsip_tp_state_callback) pjsip_tpmgr_get_state_cb(
2040 const pjsip_tpmgr *mgr)
2041{
2042 PJ_ASSERT_RETURN(mgr, NULL);
2043
2044 return mgr->tp_state_cb;
2045}
2046
2047
2048/**
2049 * Allocate and init transport data.
2050 */
2051static void init_tp_data(pjsip_transport *tp)
2052{
2053 transport_data *tp_data;
2054
2055 pj_assert(tp && !tp->data);
2056
2057 tp_data = PJ_POOL_ZALLOC_T(tp->pool, transport_data);
2058 pj_list_init(&tp_data->st_listeners);
2059 pj_list_init(&tp_data->st_listeners_empty);
2060 tp->data = tp_data;
2061}
2062
2063
2064static void tp_state_callback(pjsip_transport *tp,
2065 pjsip_transport_state state,
2066 const pjsip_transport_state_info *info)
2067{
2068 transport_data *tp_data;
2069
2070 pj_lock_acquire(tp->lock);
2071
2072 tp_data = (transport_data*)tp->data;
2073
2074 /* Notify the transport state listeners, if any. */
2075 if (!tp_data || pj_list_empty(&tp_data->st_listeners)) {
2076 goto on_return;
2077 } else {
2078 pjsip_transport_state_info st_info;
2079 tp_state_listener *st_listener = tp_data->st_listeners.next;
2080
2081 /* As we need to put the user data into the transport state info,
2082 * let's use a copy of transport state info.
2083 */
2084 pj_memcpy(&st_info, info, sizeof(st_info));
2085 while (st_listener != &tp_data->st_listeners) {
2086 st_info.user_data = st_listener->user_data;
2087 (*st_listener->cb)(tp, state, &st_info);
2088
2089 st_listener = st_listener->next;
2090 }
2091 }
2092
2093on_return:
2094 pj_lock_release(tp->lock);
2095}
2096
2097
2098/**
2099 * Add a listener to the specified transport for transport state notification.
2100 */
2101PJ_DEF(pj_status_t) pjsip_transport_add_state_listener (
2102 pjsip_transport *tp,
2103 pjsip_tp_state_callback cb,
2104 void *user_data,
2105 pjsip_tp_state_listener_key **key)
2106{
2107 transport_data *tp_data;
2108 tp_state_listener *entry;
2109
2110 PJ_ASSERT_RETURN(tp && cb && key, PJ_EINVAL);
2111
2112 pj_lock_acquire(tp->lock);
2113
2114 /* Init transport data, if it hasn't */
2115 if (!tp->data)
2116 init_tp_data(tp);
2117
2118 tp_data = (transport_data*)tp->data;
2119
2120 /* Init the new listener entry. Use available empty slot, if any,
2121 * otherwise allocate it using the transport pool.
2122 */
2123 if (!pj_list_empty(&tp_data->st_listeners_empty)) {
2124 entry = tp_data->st_listeners_empty.next;
2125 pj_list_erase(entry);
2126 } else {
2127 entry = PJ_POOL_ZALLOC_T(tp->pool, tp_state_listener);
2128 }
2129 entry->cb = cb;
2130 entry->user_data = user_data;
2131
2132 /* Add the new listener entry to the listeners list */
2133 pj_list_push_back(&tp_data->st_listeners, entry);
2134
2135 *key = entry;
2136
2137 pj_lock_release(tp->lock);
2138
2139 return PJ_SUCCESS;
2140}
2141
2142/**
2143 * Remove a listener from the specified transport for transport state
2144 * notification.
2145 */
2146PJ_DEF(pj_status_t) pjsip_transport_remove_state_listener (
2147 pjsip_transport *tp,
2148 pjsip_tp_state_listener_key *key,
2149 const void *user_data)
2150{
2151 transport_data *tp_data;
2152 tp_state_listener *entry;
2153
2154 PJ_ASSERT_RETURN(tp && key, PJ_EINVAL);
2155
2156 pj_lock_acquire(tp->lock);
2157
2158 tp_data = (transport_data*)tp->data;
2159
2160 /* Transport data is NULL or no registered listener? */
2161 if (!tp_data || pj_list_empty(&tp_data->st_listeners)) {
2162 pj_lock_release(tp->lock);
2163 return PJ_ENOTFOUND;
2164 }
2165
2166 entry = (tp_state_listener*)key;
2167
2168 /* Validate the user data */
2169 if (entry->user_data != user_data) {
2170 pj_assert(!"Invalid transport state listener key");
2171 pj_lock_release(tp->lock);
2172 return PJ_EBUG;
2173 }
2174
2175 /* Reset the entry and move it to the empty list */
2176 entry->cb = NULL;
2177 entry->user_data = NULL;
2178 pj_list_erase(entry);
2179 pj_list_push_back(&tp_data->st_listeners_empty, entry);
2180
2181 pj_lock_release(tp->lock);
2182
2183 return PJ_SUCCESS;
2184}