1 /* $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
45 static 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 static const char* print_tpsel_info(const pjsip_tpselector *sel)
54 {
55 static char tpsel_info_buf[80];
56 if (!sel) return "(null)";
57 if (sel->type==PJSIP_TPSELECTOR_LISTENER)
58 pj_ansi_snprintf(tpsel_info_buf, sizeof(tpsel_info_buf),
59 "listener[%s], reuse=%d", sel->u.listener->obj_name,
60 !sel->disable_connection_reuse);
61 else if (sel->type==PJSIP_TPSELECTOR_TRANSPORT)
62 pj_ansi_snprintf(tpsel_info_buf, sizeof(tpsel_info_buf),
63 "transport[%s], reuse=%d", sel->u.transport->info,
64 !sel->disable_connection_reuse);
65 else
66 pj_ansi_snprintf(tpsel_info_buf, sizeof(tpsel_info_buf),
67 "unknown[%p], reuse=%d", sel->u.ptr,
68 !sel->disable_connection_reuse);
69 return tpsel_info_buf;
70 }
71 #else
72 # define TRACE_(x)
73 #endif
74
75 /* Specify the initial size of the transport manager's pool. */
76 #ifndef TPMGR_POOL_INIT_SIZE
77 # define TPMGR_POOL_INIT_SIZE 64
78 #endif
79
80 /* Specify the increment size of the transport manager's pool. */
81 #ifndef TPMGR_POOL_INC_SIZE
82 #define TPMGR_POOL_INC_SIZE 64
83 #endif
84
85 /* Specify transport entry allocation count. When registering a new transport,
86 * a new entry will be picked from a free list. This setting will determine
87 * the size of the free list size. If all entry is used, then the same number
88 * of entry will be allocated.
89 */
90 #ifndef PJSIP_TRANSPORT_ENTRY_ALLOC_CNT
91 # define PJSIP_TRANSPORT_ENTRY_ALLOC_CNT 16
92 #endif
93
94 /* Prototype. */
95 static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata);
96
97 /* This module has sole purpose to print transmit data to contigous buffer
98 * before actually transmitted to the wire.
99 */
100 static pjsip_module mod_msg_print =
101 {
102 NULL, NULL, /* prev and next */
103 { "mod-msg-print", 13}, /* Name. */
104 -1, /* Id */
105 PJSIP_MOD_PRIORITY_TRANSPORT_LAYER, /* Priority */
106 NULL, /* load() */
107 NULL, /* start() */
108 NULL, /* stop() */
109 NULL, /* unload() */
110 NULL, /* on_rx_request() */
111 NULL, /* on_rx_response() */
112 &mod_on_tx_msg, /* on_tx_request() */
113 &mod_on_tx_msg, /* on_tx_response() */
114 NULL, /* on_tsx_state() */
115 };
116
117 /* Transport list item */
118 typedef struct transport
119 {
120 PJ_DECL_LIST_MEMBER(struct transport);
121 pj_hash_entry_buf tp_buf;
122 pjsip_transport *tp;
123 } transport;
124
125 /*
126 * Transport manager.
127 */
128 struct pjsip_tpmgr
129 {
130 pj_hash_table_t *table;
131 pj_lock_t *lock;
132 pjsip_endpoint *endpt;
133 pjsip_tpfactory factory_list;
134 pj_pool_t *pool;
135 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
136 pj_atomic_t *tdata_counter;
137 #endif
138 void (*on_rx_msg)(pjsip_endpoint*, pj_status_t, pjsip_rx_data*);
139 pj_status_t (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*);
140 pjsip_tp_state_callback tp_state_cb;
141 pjsip_tp_on_rx_dropped_cb tp_drop_data_cb;
142
143 /* Transmit data list, for transmit data cleanup when transport manager
144 * is destroyed.
145 */
146 pjsip_tx_data tdata_list;
147
148 /* List of free transport entry. */
149 transport tp_entry_freelist;
150 };
151
152
153 /* Transport state listener list type */
154 typedef struct tp_state_listener
155 {
156 PJ_DECL_LIST_MEMBER(struct tp_state_listener);
157
158 pjsip_tp_state_callback cb;
159 void *user_data;
160 } tp_state_listener;
161
162
163 /*
164 * Transport data.
165 */
166 typedef struct transport_data
167 {
168 /* Transport listeners */
169 tp_state_listener st_listeners;
170 tp_state_listener st_listeners_empty;
171 } transport_data;
172
173
174 /*****************************************************************************
175 *
176 * GENERAL TRANSPORT (NAMES, TYPES, ETC.)
177 *
178 *****************************************************************************/
179
180 /*
181 * Transport names.
182 */
183 static struct transport_names_t
184 {
185 pjsip_transport_type_e type; /* Transport type */
186 pj_uint16_t port; /* Default port number */
187 pj_str_t name; /* Id tag */
188 const char *description; /* Longer description */
189 unsigned flag; /* Flags */
190 char name_buf[16]; /* For user's transport */
191 } transport_names[16] =
192 {
193 {
194 PJSIP_TRANSPORT_UNSPECIFIED,
195 0,
196 {"Unspecified", 11},
197 "Unspecified",
198 0
199 },
200 {
201 PJSIP_TRANSPORT_UDP,
202 5060,
203 {"UDP", 3},
204 "UDP transport",
205 PJSIP_TRANSPORT_DATAGRAM
206 },
207 {
208 PJSIP_TRANSPORT_TCP,
209 5060,
210 {"TCP", 3},
211 "TCP transport",
212 PJSIP_TRANSPORT_RELIABLE
213 },
214 {
215 PJSIP_TRANSPORT_TLS,
216 5061,
217 {"TLS", 3},
218 "TLS transport",
219 PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE
220 },
221 {
222 PJSIP_TRANSPORT_DTLS,
223 5061,
224 {"DTLS", 4},
225 "DTLS transport",
226 PJSIP_TRANSPORT_SECURE
227 },
228 {
229 PJSIP_TRANSPORT_SCTP,
230 5060,
231 {"SCTP", 4},
232 "SCTP transport",
233 PJSIP_TRANSPORT_RELIABLE
234 },
235 {
236 PJSIP_TRANSPORT_LOOP,
237 15060,
238 {"LOOP", 4},
239 "Loopback transport",
240 PJSIP_TRANSPORT_RELIABLE
241 },
242 {
243 PJSIP_TRANSPORT_LOOP_DGRAM,
244 15060,
245 {"LOOP-DGRAM", 10},
246 "Loopback datagram transport",
247 PJSIP_TRANSPORT_DATAGRAM
248 },
249 {
250 PJSIP_TRANSPORT_UDP6,
251 5060,
252 {"UDP", 3},
253 "UDP IPv6 transport",
254 PJSIP_TRANSPORT_DATAGRAM
255 },
256 {
257 PJSIP_TRANSPORT_TCP6,
258 5060,
259 {"TCP", 3},
260 "TCP IPv6 transport",
261 PJSIP_TRANSPORT_RELIABLE
262 },
263 {
264 PJSIP_TRANSPORT_TLS6,
265 5061,
266 {"TLS", 3},
267 "TLS IPv6 transport",
268 PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE
269 },
270 {
271 PJSIP_TRANSPORT_DTLS6,
272 5061,
273 {"DTLS", 4},
274 "DTLS IPv6 transport",
275 PJSIP_TRANSPORT_SECURE
276 },
277 };
278
279 static void tp_state_callback(pjsip_transport *tp,
280 pjsip_transport_state state,
281 const pjsip_transport_state_info *info);
282
283
get_tpname(pjsip_transport_type_e type)284 static struct transport_names_t *get_tpname(pjsip_transport_type_e type)
285 {
286 unsigned i;
287 for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
288 if (transport_names[i].type == type)
289 return &transport_names[i];
290 }
291 pj_assert(!"Invalid transport type!");
292 return NULL;
293 }
294
295
296
297 /*
298 * Register new transport type to PJSIP.
299 */
pjsip_transport_register_type(unsigned tp_flag,const char * tp_name,int def_port,int * p_tp_type)300 PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag,
301 const char *tp_name,
302 int def_port,
303 int *p_tp_type)
304 {
305 unsigned i;
306 pjsip_transport_type_e parent = 0;
307
308 PJ_ASSERT_RETURN(tp_flag && tp_name && def_port, PJ_EINVAL);
309 PJ_ASSERT_RETURN(pj_ansi_strlen(tp_name) <
310 PJ_ARRAY_SIZE(transport_names[0].name_buf),
311 PJ_ENAMETOOLONG);
312
313 for (i=1; i<PJ_ARRAY_SIZE(transport_names); ++i) {
314 if (tp_flag & PJSIP_TRANSPORT_IPV6 &&
315 pj_stricmp2(&transport_names[i].name, tp_name) == 0)
316 {
317 parent = transport_names[i].type;
318 }
319 if (transport_names[i].type == 0)
320 break;
321 }
322
323 if (i == PJ_ARRAY_SIZE(transport_names))
324 return PJ_ETOOMANY;
325
326 if (tp_flag & PJSIP_TRANSPORT_IPV6 && parent) {
327 transport_names[i].type = parent | PJSIP_TRANSPORT_IPV6;
328 } else {
329 transport_names[i].type = (pjsip_transport_type_e)i;
330 }
331
332 transport_names[i].port = (pj_uint16_t)def_port;
333 pj_ansi_strcpy(transport_names[i].name_buf, tp_name);
334 transport_names[i].name = pj_str(transport_names[i].name_buf);
335 transport_names[i].flag = tp_flag;
336
337 if (p_tp_type)
338 *p_tp_type = transport_names[i].type;
339
340 return PJ_SUCCESS;
341 }
342
343
344 /*
345 * Get transport type from name.
346 */
pjsip_transport_get_type_from_name(const pj_str_t * name)347 PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_name(const pj_str_t *name)
348 {
349 unsigned i;
350
351 if (name->slen == 0)
352 return PJSIP_TRANSPORT_UNSPECIFIED;
353
354 /* Get transport type from name. */
355 for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
356 if (pj_stricmp(name, &transport_names[i].name) == 0) {
357 return transport_names[i].type;
358 }
359 }
360
361 pj_assert(!"Invalid transport name");
362 return PJSIP_TRANSPORT_UNSPECIFIED;
363 }
364
365
366 /*
367 * Get the transport type for the specified flags.
368 */
pjsip_transport_get_type_from_flag(unsigned flag)369 PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_flag(unsigned flag)
370 {
371 unsigned i;
372
373 /* Get the transport type for the specified flags. */
374 for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
375 if (transport_names[i].flag == flag) {
376 return transport_names[i].type;
377 }
378 }
379
380 pj_assert(!"Invalid transport type");
381 return PJSIP_TRANSPORT_UNSPECIFIED;
382 }
383
384 /*
385 * Get the socket address family of a given transport type.
386 */
pjsip_transport_type_get_af(pjsip_transport_type_e type)387 PJ_DEF(int) pjsip_transport_type_get_af(pjsip_transport_type_e type)
388 {
389 if (type & PJSIP_TRANSPORT_IPV6)
390 return pj_AF_INET6();
391 else
392 return pj_AF_INET();
393 }
394
pjsip_transport_get_flag_from_type(pjsip_transport_type_e type)395 PJ_DEF(unsigned) pjsip_transport_get_flag_from_type(pjsip_transport_type_e type)
396 {
397 /* Return transport flag. */
398 return get_tpname(type)->flag;
399 }
400
401 /*
402 * Get the default SIP port number for the specified type.
403 */
pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type)404 PJ_DEF(int) pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type)
405 {
406 /* Return the port. */
407 return get_tpname(type)->port;
408 }
409
410 /*
411 * Get transport name.
412 */
pjsip_transport_get_type_name(pjsip_transport_type_e type)413 PJ_DEF(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e type)
414 {
415 /* Return the name. */
416 return get_tpname(type)->name.ptr;
417 }
418
419 /*
420 * Get transport description.
421 */
pjsip_transport_get_type_desc(pjsip_transport_type_e type)422 PJ_DEF(const char*) pjsip_transport_get_type_desc(pjsip_transport_type_e type)
423 {
424 /* Return the description. */
425 return get_tpname(type)->description;
426 }
427
428
429 /*****************************************************************************
430 *
431 * TRANSPORT SELECTOR
432 *
433 *****************************************************************************/
434
435 /*
436 * Add transport/listener reference in the selector.
437 */
pjsip_tpselector_add_ref(pjsip_tpselector * sel)438 PJ_DEF(void) pjsip_tpselector_add_ref(pjsip_tpselector *sel)
439 {
440 if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL)
441 pjsip_transport_add_ref(sel->u.transport);
442 else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL)
443 ; /* Hmm.. looks like we don't have reference counter for listener */
444 }
445
446
447 /*
448 * Decrement transport/listener reference in the selector.
449 */
pjsip_tpselector_dec_ref(pjsip_tpselector * sel)450 PJ_DEF(void) pjsip_tpselector_dec_ref(pjsip_tpselector *sel)
451 {
452 if (sel->type == PJSIP_TPSELECTOR_TRANSPORT && sel->u.transport != NULL)
453 pjsip_transport_dec_ref(sel->u.transport);
454 else if (sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener != NULL)
455 ; /* Hmm.. looks like we don't have reference counter for listener */
456 }
457
458
459 /*****************************************************************************
460 *
461 * TRANSMIT DATA BUFFER MANIPULATION.
462 *
463 *****************************************************************************/
464
465 /*
466 * Create new transmit buffer.
467 */
pjsip_tx_data_create(pjsip_tpmgr * mgr,pjsip_tx_data ** p_tdata)468 PJ_DEF(pj_status_t) pjsip_tx_data_create( pjsip_tpmgr *mgr,
469 pjsip_tx_data **p_tdata )
470 {
471 pj_pool_t *pool;
472 pjsip_tx_data *tdata;
473 pj_status_t status;
474
475 PJ_ASSERT_RETURN(mgr && p_tdata, PJ_EINVAL);
476
477 pool = pjsip_endpt_create_pool( mgr->endpt, "tdta%p",
478 PJSIP_POOL_LEN_TDATA,
479 PJSIP_POOL_INC_TDATA );
480 if (!pool)
481 return PJ_ENOMEM;
482
483 tdata = PJ_POOL_ZALLOC_T(pool, pjsip_tx_data);
484 tdata->pool = pool;
485 tdata->mgr = mgr;
486 pj_ansi_snprintf(tdata->obj_name, sizeof(tdata->obj_name), "tdta%p", tdata);
487 pj_memcpy(pool->obj_name, tdata->obj_name, sizeof(pool->obj_name));
488
489 status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt);
490 if (status != PJ_SUCCESS) {
491 pjsip_endpt_release_pool( mgr->endpt, tdata->pool );
492 return status;
493 }
494
495 //status = pj_lock_create_simple_mutex(pool, "tdta%p", &tdata->lock);
496 status = pj_lock_create_null_mutex(pool, "tdta%p", &tdata->lock);
497 if (status != PJ_SUCCESS) {
498 pjsip_endpt_release_pool( mgr->endpt, tdata->pool );
499 return status;
500 }
501
502 pj_ioqueue_op_key_init(&tdata->op_key.key, sizeof(tdata->op_key.key));
503 pj_list_init(tdata);
504
505 #if defined(PJSIP_HAS_TX_DATA_LIST) && PJSIP_HAS_TX_DATA_LIST!=0
506 /* Append this just created tdata to transmit buffer list */
507 pj_lock_acquire(mgr->lock);
508 pj_list_push_back(&mgr->tdata_list, tdata);
509 pj_lock_release(mgr->lock);
510 #endif
511
512 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
513 pj_atomic_inc( tdata->mgr->tdata_counter );
514 #endif
515
516 *p_tdata = tdata;
517 return PJ_SUCCESS;
518 }
519
520
521 /*
522 * Add reference to tx buffer.
523 */
pjsip_tx_data_add_ref(pjsip_tx_data * tdata)524 PJ_DEF(void) pjsip_tx_data_add_ref( pjsip_tx_data *tdata )
525 {
526 pj_atomic_inc(tdata->ref_cnt);
527 }
528
tx_data_destroy(pjsip_tx_data * tdata)529 static void tx_data_destroy(pjsip_tx_data *tdata)
530 {
531 PJ_LOG(5,(tdata->obj_name, "Destroying txdata %s",
532 pjsip_tx_data_get_info(tdata)));
533 pjsip_tpselector_dec_ref(&tdata->tp_sel);
534 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
535 pj_atomic_dec( tdata->mgr->tdata_counter );
536 #endif
537
538 #if defined(PJSIP_HAS_TX_DATA_LIST) && PJSIP_HAS_TX_DATA_LIST!=0
539 /* Remove this tdata from transmit buffer list */
540 pj_lock_acquire(tdata->mgr->lock);
541 pj_list_erase(tdata);
542 pj_lock_release(tdata->mgr->lock);
543 #endif
544
545 pj_atomic_destroy( tdata->ref_cnt );
546 pj_lock_destroy( tdata->lock );
547 pjsip_endpt_release_pool( tdata->mgr->endpt, tdata->pool );
548 }
549
550 /*
551 * Decrease transport data reference, destroy it when the reference count
552 * reaches zero.
553 */
pjsip_tx_data_dec_ref(pjsip_tx_data * tdata)554 PJ_DEF(pj_status_t) pjsip_tx_data_dec_ref( pjsip_tx_data *tdata )
555 {
556 pj_atomic_value_t ref_cnt;
557
558 PJ_ASSERT_RETURN(tdata && tdata->ref_cnt, PJ_EINVAL);
559
560 ref_cnt = pj_atomic_dec_and_get(tdata->ref_cnt);
561 pj_assert( ref_cnt >= 0);
562 if (ref_cnt == 0) {
563 tx_data_destroy(tdata);
564 return PJSIP_EBUFDESTROYED;
565 } else {
566 return PJ_SUCCESS;
567 }
568 }
569
570 /*
571 * Invalidate the content of the print buffer to force the message to be
572 * re-printed when sent.
573 */
pjsip_tx_data_invalidate_msg(pjsip_tx_data * tdata)574 PJ_DEF(void) pjsip_tx_data_invalidate_msg( pjsip_tx_data *tdata )
575 {
576 tdata->buf.cur = tdata->buf.start;
577 tdata->info = NULL;
578 }
579
580 /*
581 * Print the SIP message to transmit data buffer's internal buffer.
582 */
pjsip_tx_data_encode(pjsip_tx_data * tdata)583 PJ_DEF(pj_status_t) pjsip_tx_data_encode(pjsip_tx_data *tdata)
584 {
585 /* Allocate buffer if necessary. */
586 if (tdata->buf.start == NULL) {
587 PJ_USE_EXCEPTION;
588
589 PJ_TRY {
590 tdata->buf.start = (char*)
591 pj_pool_alloc(tdata->pool, PJSIP_MAX_PKT_LEN);
592 }
593 PJ_CATCH_ANY {
594 return PJ_ENOMEM;
595 }
596 PJ_END
597
598 tdata->buf.cur = tdata->buf.start;
599 tdata->buf.end = tdata->buf.start + PJSIP_MAX_PKT_LEN;
600 }
601
602 /* Do we need to reprint? */
603 if (!pjsip_tx_data_is_valid(tdata)) {
604 pj_ssize_t size;
605
606 size = pjsip_msg_print( tdata->msg, tdata->buf.start,
607 tdata->buf.end - tdata->buf.start);
608 if (size < 0) {
609 return PJSIP_EMSGTOOLONG;
610 }
611 pj_assert(size != 0);
612 tdata->buf.cur[size] = '\0';
613 tdata->buf.cur += size;
614 }
615
616 return PJ_SUCCESS;
617 }
618
pjsip_tx_data_is_valid(pjsip_tx_data * tdata)619 PJ_DEF(pj_bool_t) pjsip_tx_data_is_valid( pjsip_tx_data *tdata )
620 {
621 return tdata->buf.cur != tdata->buf.start;
622 }
623
get_msg_info(pj_pool_t * pool,const char * obj_name,const pjsip_msg * msg)624 static char *get_msg_info(pj_pool_t *pool, const char *obj_name,
625 const pjsip_msg *msg)
626 {
627 char info_buf[128], *info;
628 const pjsip_cseq_hdr *cseq;
629 int len;
630
631 cseq = (const pjsip_cseq_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL);
632 PJ_ASSERT_RETURN(cseq != NULL, "INVALID MSG");
633
634 if (msg->type == PJSIP_REQUEST_MSG) {
635 len = pj_ansi_snprintf(info_buf, sizeof(info_buf),
636 "Request msg %.*s/cseq=%d (%s)",
637 (int)msg->line.req.method.name.slen,
638 msg->line.req.method.name.ptr,
639 cseq->cseq, obj_name);
640 } else {
641 len = pj_ansi_snprintf(info_buf, sizeof(info_buf),
642 "Response msg %d/%.*s/cseq=%d (%s)",
643 msg->line.status.code,
644 (int)cseq->method.name.slen,
645 cseq->method.name.ptr,
646 cseq->cseq, obj_name);
647 }
648
649 if (len < 1 || len >= (int)sizeof(info_buf)) {
650 return (char*)obj_name;
651 }
652
653 info = (char*) pj_pool_alloc(pool, len+1);
654 pj_memcpy(info, info_buf, len+1);
655
656 return info;
657 }
658
pjsip_tx_data_get_info(pjsip_tx_data * tdata)659 PJ_DEF(char*) pjsip_tx_data_get_info( pjsip_tx_data *tdata )
660 {
661 PJ_ASSERT_RETURN(tdata, "NULL");
662
663 /* tdata->info may be assigned by application so if it exists
664 * just return it.
665 */
666 if (tdata->info)
667 return tdata->info;
668
669 if (tdata->msg==NULL)
670 return "NULL";
671
672 pj_lock_acquire(tdata->lock);
673 tdata->info = get_msg_info(tdata->pool, tdata->obj_name, tdata->msg);
674 pj_lock_release(tdata->lock);
675
676 return tdata->info;
677 }
678
pjsip_tx_data_set_transport(pjsip_tx_data * tdata,const pjsip_tpselector * sel)679 PJ_DEF(pj_status_t) pjsip_tx_data_set_transport(pjsip_tx_data *tdata,
680 const pjsip_tpselector *sel)
681 {
682 PJ_ASSERT_RETURN(tdata && sel, PJ_EINVAL);
683
684 pj_lock_acquire(tdata->lock);
685
686 pjsip_tpselector_dec_ref(&tdata->tp_sel);
687
688 pj_memcpy(&tdata->tp_sel, sel, sizeof(*sel));
689 pjsip_tpselector_add_ref(&tdata->tp_sel);
690
691 pj_lock_release(tdata->lock);
692
693 return PJ_SUCCESS;
694 }
695
696 /* Clone pjsip_tx_data. */
pjsip_tx_data_clone(const pjsip_tx_data * src,unsigned flags,pjsip_tx_data ** p_tdata)697 PJ_DEF(pj_status_t) pjsip_tx_data_clone(const pjsip_tx_data *src,
698 unsigned flags,
699 pjsip_tx_data ** p_tdata)
700 {
701 pjsip_tx_data *dst;
702 const pjsip_hdr *hsrc;
703 pjsip_msg *msg;
704 pj_status_t status;
705
706 PJ_UNUSED_ARG(flags);
707
708 status = pjsip_tx_data_create(src->mgr, p_tdata);
709 if (status != PJ_SUCCESS)
710 return status;
711
712 dst = *p_tdata;
713
714 msg = pjsip_msg_create(dst->pool, PJSIP_RESPONSE_MSG);
715 dst->msg = msg;
716 pjsip_tx_data_add_ref(dst);
717
718 /* Duplicate status line */
719 msg->line.status.code = src->msg->line.status.code;
720 pj_strdup(dst->pool, &msg->line.status.reason,
721 &src->msg->line.status.reason);
722
723 /* Duplicate all headers */
724 hsrc = src->msg->hdr.next;
725 while (hsrc != &src->msg->hdr) {
726 pjsip_hdr *h = (pjsip_hdr*) pjsip_hdr_clone(dst->pool, hsrc);
727 pjsip_msg_add_hdr(msg, h);
728 hsrc = hsrc->next;
729 }
730
731 /* Duplicate message body */
732 if (src->msg->body)
733 msg->body = pjsip_msg_body_clone(dst->pool, src->msg->body);
734
735 /* We shouldn't copy is_pending since it's src's internal state,
736 * indicating that it's currently being sent by the transport.
737 * While the cloned tdata is of course not.
738 */
739 //dst->is_pending = src->is_pending;
740
741 PJ_LOG(5,(THIS_FILE,
742 "Tx data %s cloned",
743 pjsip_tx_data_get_info(dst)));
744
745 return PJ_SUCCESS;
746 }
747
pjsip_rx_data_get_info(pjsip_rx_data * rdata)748 PJ_DEF(char*) pjsip_rx_data_get_info(pjsip_rx_data *rdata)
749 {
750 char obj_name[PJ_MAX_OBJ_NAME];
751
752 PJ_ASSERT_RETURN(rdata->msg_info.msg, "INVALID MSG");
753
754 if (rdata->msg_info.info)
755 return rdata->msg_info.info;
756
757 pj_ansi_strcpy(obj_name, "rdata");
758 pj_ansi_snprintf(obj_name+5, sizeof(obj_name)-5, "%p", rdata);
759
760 rdata->msg_info.info = get_msg_info(rdata->tp_info.pool, obj_name,
761 rdata->msg_info.msg);
762 return rdata->msg_info.info;
763 }
764
765 /* Clone pjsip_rx_data. */
pjsip_rx_data_clone(const pjsip_rx_data * src,unsigned flags,pjsip_rx_data ** p_rdata)766 PJ_DEF(pj_status_t) pjsip_rx_data_clone( const pjsip_rx_data *src,
767 unsigned flags,
768 pjsip_rx_data **p_rdata)
769 {
770 pj_pool_t *pool;
771 pjsip_rx_data *dst;
772 pjsip_hdr *hdr;
773
774 PJ_ASSERT_RETURN(src && flags==0 && p_rdata, PJ_EINVAL);
775
776 pool = pj_pool_create(src->tp_info.pool->factory,
777 "rtd%p",
778 PJSIP_POOL_RDATA_LEN,
779 PJSIP_POOL_RDATA_INC,
780 NULL);
781 if (!pool)
782 return PJ_ENOMEM;
783
784 dst = PJ_POOL_ZALLOC_T(pool, pjsip_rx_data);
785
786 /* Parts of tp_info */
787 dst->tp_info.pool = pool;
788 dst->tp_info.transport = (pjsip_transport*)src->tp_info.transport;
789
790 /* pkt_info can be memcopied */
791 pj_memcpy(&dst->pkt_info, &src->pkt_info, sizeof(src->pkt_info));
792
793 /* msg_info needs deep clone */
794 dst->msg_info.msg_buf = dst->pkt_info.packet +
795 (src->msg_info.msg_buf - src->pkt_info.packet);
796 dst->msg_info.len = src->msg_info.len;
797 dst->msg_info.msg = pjsip_msg_clone(pool, src->msg_info.msg);
798 pj_list_init(&dst->msg_info.parse_err);
799
800 #define GET_MSG_HDR2(TYPE, type, var) \
801 case PJSIP_H_##TYPE: \
802 if (!dst->msg_info.var) { \
803 dst->msg_info.var = (pjsip_##type##_hdr*)hdr; \
804 } \
805 break
806 #define GET_MSG_HDR(TYPE, var_type) GET_MSG_HDR2(TYPE, var_type, var_type)
807
808 hdr = dst->msg_info.msg->hdr.next;
809 while (hdr != &dst->msg_info.msg->hdr) {
810 switch (hdr->type) {
811 GET_MSG_HDR(CALL_ID, cid);
812 GET_MSG_HDR(FROM, from);
813 GET_MSG_HDR(TO, to);
814 GET_MSG_HDR(VIA, via);
815 GET_MSG_HDR(CSEQ, cseq);
816 GET_MSG_HDR(MAX_FORWARDS, max_fwd);
817 GET_MSG_HDR(ROUTE, route);
818 GET_MSG_HDR2(RECORD_ROUTE, rr, record_route);
819 GET_MSG_HDR(CONTENT_TYPE, ctype);
820 GET_MSG_HDR(CONTENT_LENGTH, clen);
821 GET_MSG_HDR(REQUIRE, require);
822 GET_MSG_HDR(SUPPORTED, supported);
823 default:
824 break;
825 }
826 hdr = hdr->next;
827 }
828
829 #undef GET_MSG_HDR
830 #undef GET_MSG_HDR2
831
832 *p_rdata = dst;
833
834 /* Finally add transport ref */
835 return pjsip_transport_add_ref(dst->tp_info.transport);
836 }
837
838 /* Free previously cloned pjsip_rx_data. */
pjsip_rx_data_free_cloned(pjsip_rx_data * rdata)839 PJ_DEF(pj_status_t) pjsip_rx_data_free_cloned(pjsip_rx_data *rdata)
840 {
841 PJ_ASSERT_RETURN(rdata, PJ_EINVAL);
842
843 pjsip_transport_dec_ref(rdata->tp_info.transport);
844 pj_pool_release(rdata->tp_info.pool);
845
846 return PJ_SUCCESS;
847 }
848
849 /*****************************************************************************
850 *
851 * TRANSPORT KEY
852 *
853 *****************************************************************************/
854
855
856 /*****************************************************************************
857 *
858 * TRANSPORT
859 *
860 *****************************************************************************/
861
transport_send_callback(pjsip_transport * transport,void * token,pj_ssize_t size)862 static void transport_send_callback(pjsip_transport *transport,
863 void *token,
864 pj_ssize_t size)
865 {
866 pjsip_tx_data *tdata = (pjsip_tx_data*) token;
867
868 PJ_UNUSED_ARG(transport);
869
870 /* Mark pending off so that app can resend/reuse txdata from inside
871 * the callback.
872 */
873 tdata->is_pending = 0;
874
875 /* Call callback, if any. */
876 if (tdata->cb) {
877 (*tdata->cb)(tdata->token, tdata, size);
878 }
879
880 /* Decrement reference count. */
881 pjsip_tx_data_dec_ref(tdata);
882 }
883
884 /* This function is called by endpoint for on_tx_request() and on_tx_response()
885 * notification.
886 */
mod_on_tx_msg(pjsip_tx_data * tdata)887 static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata)
888 {
889 return pjsip_tx_data_encode(tdata);
890 }
891
892 /*
893 * Send a SIP message using the specified transport.
894 */
pjsip_transport_send(pjsip_transport * tr,pjsip_tx_data * tdata,const pj_sockaddr_t * addr,int addr_len,void * token,pjsip_tp_send_callback cb)895 PJ_DEF(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
896 pjsip_tx_data *tdata,
897 const pj_sockaddr_t *addr,
898 int addr_len,
899 void *token,
900 pjsip_tp_send_callback cb)
901 {
902 pj_status_t status;
903
904 PJ_ASSERT_RETURN(tr && tdata && addr, PJ_EINVAL);
905
906 /* Is it currently being sent? */
907 if (tdata->is_pending) {
908 pj_assert(!"Invalid operation step!");
909 PJ_LOG(2,(THIS_FILE, "Unable to send %s: message is pending",
910 pjsip_tx_data_get_info(tdata)));
911 return PJSIP_EPENDINGTX;
912 }
913
914 /* Add reference to prevent deletion, and to cancel idle timer if
915 * it's running.
916 */
917 pjsip_transport_add_ref(tr);
918
919 /* Fill in tp_info. */
920 tdata->tp_info.transport = tr;
921 pj_memcpy(&tdata->tp_info.dst_addr, addr, addr_len);
922 tdata->tp_info.dst_addr_len = addr_len;
923
924 pj_inet_ntop(((pj_sockaddr*)addr)->addr.sa_family,
925 pj_sockaddr_get_addr(addr),
926 tdata->tp_info.dst_name,
927 sizeof(tdata->tp_info.dst_name));
928 tdata->tp_info.dst_port = pj_sockaddr_get_port(addr);
929
930 /* Distribute to modules.
931 * When the message reach mod_msg_print, the contents of the message will
932 * be "printed" to contiguous buffer.
933 */
934 if (tr->tpmgr->on_tx_msg) {
935 status = (*tr->tpmgr->on_tx_msg)(tr->endpt, tdata);
936 if (status != PJ_SUCCESS) {
937 pjsip_transport_dec_ref(tr);
938 return status;
939 }
940 }
941
942 /* Save callback data. */
943 tdata->token = token;
944 tdata->cb = cb;
945
946 /* Add reference counter. */
947 pjsip_tx_data_add_ref(tdata);
948
949 /* Mark as pending. */
950 tdata->is_pending = 1;
951
952 /* Send to transport. */
953 status = (*tr->send_msg)(tr, tdata, addr, addr_len, (void*)tdata,
954 &transport_send_callback);
955
956 if (status != PJ_EPENDING) {
957 tdata->is_pending = 0;
958 pjsip_tx_data_dec_ref(tdata);
959 }
960
961 pjsip_transport_dec_ref(tr);
962 return status;
963 }
964
965
966 /* send_raw() callback */
send_raw_callback(pjsip_transport * transport,void * token,pj_ssize_t size)967 static void send_raw_callback(pjsip_transport *transport,
968 void *token,
969 pj_ssize_t size)
970 {
971 pjsip_tx_data *tdata = (pjsip_tx_data*) token;
972
973 /* Mark pending off so that app can resend/reuse txdata from inside
974 * the callback.
975 */
976 tdata->is_pending = 0;
977
978 /* Call callback, if any. */
979 if (tdata->cb) {
980 (*tdata->cb)(tdata->token, tdata, size);
981 }
982
983 /* Decrement tdata reference count. */
984 pjsip_tx_data_dec_ref(tdata);
985
986 /* Decrement transport reference count */
987 pjsip_transport_dec_ref(transport);
988 }
989
990
991 /* Send raw data */
pjsip_tpmgr_send_raw(pjsip_tpmgr * mgr,pjsip_transport_type_e tp_type,const pjsip_tpselector * sel,pjsip_tx_data * tdata,const void * raw_data,pj_size_t data_len,const pj_sockaddr_t * addr,int addr_len,void * token,pjsip_tp_send_callback cb)992 PJ_DEF(pj_status_t) pjsip_tpmgr_send_raw(pjsip_tpmgr *mgr,
993 pjsip_transport_type_e tp_type,
994 const pjsip_tpselector *sel,
995 pjsip_tx_data *tdata,
996 const void *raw_data,
997 pj_size_t data_len,
998 const pj_sockaddr_t *addr,
999 int addr_len,
1000 void *token,
1001 pjsip_tp_send_callback cb)
1002 {
1003 pjsip_transport *tr;
1004 pj_status_t status;
1005
1006 /* Acquire the transport */
1007 status = pjsip_tpmgr_acquire_transport(mgr, tp_type, addr, addr_len,
1008 sel, &tr);
1009 if (status != PJ_SUCCESS)
1010 return status;
1011
1012 /* Create transmit data buffer if one is not specified */
1013 if (tdata == NULL) {
1014 status = pjsip_endpt_create_tdata(tr->endpt, &tdata);
1015 if (status != PJ_SUCCESS) {
1016 pjsip_transport_dec_ref(tr);
1017 return status;
1018 }
1019
1020 tdata->info = "raw";
1021
1022 /* Add reference counter. */
1023 pjsip_tx_data_add_ref(tdata);
1024 }
1025
1026 /* Allocate buffer */
1027 if (tdata->buf.start == NULL ||
1028 (tdata->buf.end - tdata->buf.start) < (int)data_len)
1029 {
1030 /* Note: data_len may be zero, so allocate +1 */
1031 tdata->buf.start = (char*) pj_pool_alloc(tdata->pool, data_len+1);
1032 tdata->buf.end = tdata->buf.start + data_len + 1;
1033 }
1034
1035 /* Copy data, if any! (application may send zero len packet) */
1036 if (data_len) {
1037 pj_memcpy(tdata->buf.start, raw_data, data_len);
1038 }
1039 tdata->buf.cur = tdata->buf.start + data_len;
1040
1041 /* Save callback data. */
1042 tdata->token = token;
1043 tdata->cb = cb;
1044
1045 /* Mark as pending. */
1046 tdata->is_pending = 1;
1047
1048 /* Send to transport */
1049 status = tr->send_msg(tr, tdata, addr, addr_len,
1050 tdata, &send_raw_callback);
1051
1052 if (status != PJ_EPENDING) {
1053 /* callback will not be called, so destroy tdata now. */
1054 pjsip_tx_data_dec_ref(tdata);
1055 pjsip_transport_dec_ref(tr);
1056 }
1057
1058 return status;
1059 }
1060
1061
transport_idle_callback(pj_timer_heap_t * timer_heap,struct pj_timer_entry * entry)1062 static void transport_idle_callback(pj_timer_heap_t *timer_heap,
1063 struct pj_timer_entry *entry)
1064 {
1065 pjsip_transport *tp = (pjsip_transport*) entry->user_data;
1066 pj_assert(tp != NULL);
1067
1068 PJ_UNUSED_ARG(timer_heap);
1069
1070 if (entry->id == PJ_FALSE)
1071 return;
1072
1073 entry->id = PJ_FALSE;
1074
1075 /* Set is_destroying flag under transport manager mutex to avoid
1076 * race condition with pjsip_tpmgr_acquire_transport2().
1077 */
1078 pj_lock_acquire(tp->tpmgr->lock);
1079 if (pj_atomic_get(tp->ref_cnt) == 0) {
1080 tp->is_destroying = PJ_TRUE;
1081 } else {
1082 pj_lock_release(tp->tpmgr->lock);
1083 return;
1084 }
1085 pj_lock_release(tp->tpmgr->lock);
1086
1087 pjsip_transport_destroy(tp);
1088 }
1089
1090
is_transport_valid(pjsip_transport * tp,pjsip_tpmgr * tpmgr,const pjsip_transport_key * key,int key_len)1091 static pj_bool_t is_transport_valid(pjsip_transport *tp, pjsip_tpmgr *tpmgr,
1092 const pjsip_transport_key *key,
1093 int key_len)
1094 {
1095 transport *tp_entry;
1096
1097 tp_entry = (transport *)pj_hash_get(tpmgr->table, key, key_len, NULL);
1098 if (tp_entry != NULL) {
1099
1100 transport *tp_iter = tp_entry;
1101 do {
1102 if (tp_iter->tp == tp) {
1103 return PJ_TRUE;
1104 }
1105 tp_iter = tp_iter->next;
1106 } while (tp_iter != tp_entry);
1107 }
1108
1109 return PJ_FALSE;
1110 }
1111
1112 /*
1113 * Add ref.
1114 */
pjsip_transport_add_ref(pjsip_transport * tp)1115 PJ_DEF(pj_status_t) pjsip_transport_add_ref( pjsip_transport *tp )
1116 {
1117 pjsip_tpmgr *tpmgr;
1118 pjsip_transport_key key;
1119 int key_len;
1120
1121 PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL);
1122
1123 /* Add ref transport group lock, if any */
1124 if (tp->grp_lock)
1125 pj_grp_lock_add_ref(tp->grp_lock);
1126
1127 /* Cache some vars for checking transport validity later */
1128 tpmgr = tp->tpmgr;
1129 key_len = sizeof(tp->key.type) + tp->addr_len;
1130 pj_memcpy(&key, &tp->key, key_len);
1131
1132 if (pj_atomic_inc_and_get(tp->ref_cnt) == 1) {
1133 pj_lock_acquire(tpmgr->lock);
1134 /* Verify again. But first, make sure transport is still valid
1135 * (see #1883).
1136 */
1137 if (is_transport_valid(tp, tpmgr, &key, key_len) &&
1138 pj_atomic_get(tp->ref_cnt) == 1)
1139 {
1140 if (tp->idle_timer.id != PJ_FALSE) {
1141 tp->idle_timer.id = PJ_FALSE;
1142 pjsip_endpt_cancel_timer(tp->tpmgr->endpt, &tp->idle_timer);
1143 }
1144 }
1145 pj_lock_release(tpmgr->lock);
1146 }
1147
1148 return PJ_SUCCESS;
1149 }
1150
1151 /*
1152 * Dec ref.
1153 */
pjsip_transport_dec_ref(pjsip_transport * tp)1154 PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp )
1155 {
1156 pjsip_tpmgr *tpmgr;
1157 pjsip_transport_key key;
1158 int key_len;
1159
1160 PJ_ASSERT_RETURN(tp != NULL, PJ_EINVAL);
1161 pj_assert(pj_atomic_get(tp->ref_cnt) > 0);
1162
1163 /* Cache some vars for checking transport validity later */
1164 tpmgr = tp->tpmgr;
1165 key_len = sizeof(tp->key.type) + tp->addr_len;
1166 pj_memcpy(&key, &tp->key, key_len);
1167
1168 if (pj_atomic_dec_and_get(tp->ref_cnt) == 0) {
1169 pj_lock_acquire(tpmgr->lock);
1170 /* Verify again. Do not register timer if the transport is
1171 * being destroyed. But first, make sure transport is still valid
1172 * (see #1883).
1173 */
1174 if (is_transport_valid(tp, tpmgr, &key, key_len) &&
1175 !tp->is_destroying && pj_atomic_get(tp->ref_cnt) == 0)
1176 {
1177 pj_time_val delay;
1178
1179 /* If transport is in graceful shutdown, then this is the
1180 * last user who uses the transport. Schedule to destroy the
1181 * transport immediately. Otherwise schedule idle timer.
1182 */
1183 if (tp->is_shutdown) {
1184 delay.sec = delay.msec = 0;
1185 } else {
1186 delay.sec = (tp->dir==PJSIP_TP_DIR_OUTGOING) ?
1187 PJSIP_TRANSPORT_IDLE_TIME :
1188 PJSIP_TRANSPORT_SERVER_IDLE_TIME;
1189 delay.msec = 0;
1190 }
1191
1192 /* Avoid double timer entry scheduling */
1193 if (pj_timer_entry_running(&tp->idle_timer))
1194 pjsip_endpt_cancel_timer(tp->tpmgr->endpt, &tp->idle_timer);
1195
1196 pjsip_endpt_schedule_timer_w_grp_lock(tp->tpmgr->endpt,
1197 &tp->idle_timer,
1198 &delay,
1199 PJ_TRUE,
1200 tp->grp_lock);
1201 }
1202 pj_lock_release(tpmgr->lock);
1203 }
1204
1205 /* Dec ref transport group lock, if any */
1206 if (tp->grp_lock) {
1207 pj_grp_lock_dec_ref(tp->grp_lock);
1208 }
1209
1210 return PJ_SUCCESS;
1211 }
1212
1213
1214 /**
1215 * Register a transport.
1216 */
pjsip_transport_register(pjsip_tpmgr * mgr,pjsip_transport * tp)1217 PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
1218 pjsip_transport *tp )
1219 {
1220 int key_len;
1221 pj_uint32_t hval;
1222 transport *tp_ref = NULL;
1223 transport *tp_add = NULL;
1224
1225 /* Init. */
1226 tp->tpmgr = mgr;
1227 pj_bzero(&tp->idle_timer, sizeof(tp->idle_timer));
1228 tp->idle_timer.user_data = tp;
1229 tp->idle_timer.cb = &transport_idle_callback;
1230
1231 /*
1232 * Register to hash table (see Trac ticket #42).
1233 */
1234 key_len = sizeof(tp->key.type) + tp->addr_len;
1235 pj_lock_acquire(mgr->lock);
1236
1237 hval = 0;
1238 tp_ref = (transport *)pj_hash_get(mgr->table, &tp->key, key_len, &hval);
1239
1240 /* Get an empty entry from the freelist. */
1241 if (pj_list_empty(&mgr->tp_entry_freelist)) {
1242 unsigned i = 0;
1243
1244 TRACE_((THIS_FILE, "Transport list is full, allocate new entry"));
1245 /* Allocate new entry for the freelist. */
1246 for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) {
1247 tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport);
1248 if (!tp_add)
1249 return PJ_ENOMEM;
1250 pj_list_init(tp_add);
1251 pj_list_push_back(&mgr->tp_entry_freelist, tp_add);
1252 }
1253 }
1254 tp_add = mgr->tp_entry_freelist.next;
1255 tp_add->tp = tp;
1256 pj_list_erase(tp_add);
1257
1258 if (tp_ref) {
1259 /* There'a already a transport list from the hash table. Add the
1260 * new transport to the list.
1261 */
1262 pj_list_push_back(tp_ref, tp_add);
1263 TRACE_((THIS_FILE, "Remote address already registered, "
1264 "appended the transport to the list"));
1265 } else {
1266 /* Transport list not found, add it to the hash table. */
1267 pj_hash_set_np(mgr->table, &tp->key, key_len, hval, tp_add->tp_buf,
1268 tp_add);
1269 TRACE_((THIS_FILE, "Remote address not registered, "
1270 "added the transport to the hash"));
1271 }
1272
1273 /* Add ref transport group lock, if any */
1274 if (tp->grp_lock)
1275 pj_grp_lock_add_ref(tp->grp_lock);
1276
1277 pj_lock_release(mgr->lock);
1278
1279 TRACE_((THIS_FILE, "Transport %s registered: type=%s, remote=%s:%d",
1280 tp->obj_name,
1281 pjsip_transport_get_type_name(tp->key.type),
1282 pj_sockaddr_has_addr(&tp->key.rem_addr)?
1283 addr_string(&tp->key.rem_addr):"",
1284 pj_sockaddr_has_addr(&tp->key.rem_addr)?
1285 pj_sockaddr_get_port(&tp->key.rem_addr):0));
1286
1287 return PJ_SUCCESS;
1288 }
1289
1290 /* Force destroy transport (e.g. during transport manager shutdown. */
destroy_transport(pjsip_tpmgr * mgr,pjsip_transport * tp)1291 static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
1292 pjsip_transport *tp )
1293 {
1294 int key_len;
1295 pj_uint32_t hval;
1296 void *entry;
1297
1298 tp->is_destroying = PJ_TRUE;
1299
1300 TRACE_((THIS_FILE, "Transport %s is being destroyed", tp->obj_name));
1301
1302 pj_lock_acquire(tp->lock);
1303 pj_lock_acquire(mgr->lock);
1304
1305 /*
1306 * Unregister timer, if any.
1307 */
1308 //pj_assert(tp->idle_timer.id == PJ_FALSE);
1309 if (tp->idle_timer.id != PJ_FALSE) {
1310 tp->idle_timer.id = PJ_FALSE;
1311 pjsip_endpt_cancel_timer(mgr->endpt, &tp->idle_timer);
1312 }
1313
1314 /*
1315 * Unregister from hash table (see Trac ticket #42).
1316 */
1317 key_len = sizeof(tp->key.type) + tp->addr_len;
1318 hval = 0;
1319 entry = pj_hash_get(mgr->table, &tp->key, key_len, &hval);
1320 if (entry) {
1321 transport *tp_ref = (transport *)entry;
1322 transport *tp_iter = tp_ref;
1323 /* Search the matching entry from the transport list. */
1324 do {
1325 if (tp_iter->tp == tp) {
1326 transport *tp_next = tp_iter->next;
1327
1328 /* Update hash table :
1329 * - transport list only contain single element, or
1330 * - the entry is the first element of the transport list.
1331 */
1332 if (tp_iter == tp_ref) {
1333 pj_hash_set(NULL, mgr->table, &tp->key, key_len, hval,
1334 NULL);
1335
1336 if (tp_ref->next != tp_ref) {
1337 /* The transport list has multiple entry. */
1338 pj_hash_set_np(mgr->table, &tp_next->tp->key, key_len,
1339 hval, tp_next->tp_buf, tp_next);
1340 TRACE_((THIS_FILE, "Hash entry updated after "
1341 "transport %d being destroyed",
1342 tp->obj_name));
1343 } else {
1344 TRACE_((THIS_FILE, "Hash entry deleted after "
1345 "transport %d being destroyed",
1346 tp->obj_name));
1347 }
1348 }
1349
1350 pj_list_erase(tp_iter);
1351 /* Put back to the transport freelist. */
1352 pj_list_push_back(&mgr->tp_entry_freelist, tp_iter);
1353
1354 break;
1355 }
1356 tp_iter = tp_iter->next;
1357 } while (tp_iter != tp_ref);
1358
1359 if (tp_iter->tp != tp) {
1360 PJ_LOG(3, (THIS_FILE, "Warning: transport %s being destroyed is "
1361 "not registered", tp->obj_name));
1362 }
1363 } else {
1364 PJ_LOG(3, (THIS_FILE, "Warning: transport %s being destroyed is "
1365 "not found in the hash table", tp->obj_name));
1366 }
1367
1368 pj_lock_release(mgr->lock);
1369 pj_lock_release(tp->lock);
1370
1371 /* Dec ref transport group lock, if any */
1372 if (tp->grp_lock) {
1373 pj_grp_lock_dec_ref(tp->grp_lock);
1374 }
1375
1376 /* Destroy. */
1377 return tp->destroy(tp);
1378 }
1379
1380
1381 /*
1382 * Start graceful shutdown procedure for this transport.
1383 */
pjsip_transport_shutdown(pjsip_transport * tp)1384 PJ_DEF(pj_status_t) pjsip_transport_shutdown(pjsip_transport *tp)
1385 {
1386 return pjsip_transport_shutdown2(tp, PJ_FALSE);
1387 }
1388
1389
1390 /*
1391 * Start shutdown procedure for this transport.
1392 */
pjsip_transport_shutdown2(pjsip_transport * tp,pj_bool_t force)1393 PJ_DEF(pj_status_t) pjsip_transport_shutdown2(pjsip_transport *tp,
1394 pj_bool_t force)
1395 {
1396 pjsip_tpmgr *mgr;
1397 pj_status_t status;
1398 pjsip_tp_state_callback state_cb;
1399
1400 PJ_LOG(4, (THIS_FILE, "Transport %s shutting down, force=%d",
1401 tp->obj_name, force));
1402
1403 pj_lock_acquire(tp->lock);
1404
1405 mgr = tp->tpmgr;
1406 pj_lock_acquire(mgr->lock);
1407
1408 /* Do nothing if transport is being shutdown/destroyed already */
1409 if (tp->is_shutdown || tp->is_destroying) {
1410 pj_lock_release(mgr->lock);
1411 pj_lock_release(tp->lock);
1412 return PJ_SUCCESS;
1413 }
1414
1415 status = PJ_SUCCESS;
1416
1417 /* Instruct transport to shutdown itself */
1418 if (tp->do_shutdown)
1419 status = tp->do_shutdown(tp);
1420
1421 if (status == PJ_SUCCESS)
1422 tp->is_shutdown = PJ_TRUE;
1423
1424 /* Notify application of transport shutdown */
1425 state_cb = pjsip_tpmgr_get_state_cb(tp->tpmgr);
1426 if (state_cb) {
1427 pjsip_transport_state_info state_info;
1428
1429 pj_bzero(&state_info, sizeof(state_info));
1430 state_info.status = PJ_ECANCELLED;
1431 (*state_cb)(tp, (force? PJSIP_TP_STATE_DISCONNECTED:
1432 PJSIP_TP_STATE_SHUTDOWN), &state_info);
1433 }
1434
1435 /* If transport reference count is zero, start timer count-down */
1436 if (pj_atomic_get(tp->ref_cnt) == 0) {
1437 pjsip_transport_add_ref(tp);
1438 pjsip_transport_dec_ref(tp);
1439 }
1440
1441 pj_lock_release(mgr->lock);
1442 pj_lock_release(tp->lock);
1443
1444 return status;
1445 }
1446
1447
1448 /**
1449 * Unregister transport.
1450 */
pjsip_transport_destroy(pjsip_transport * tp)1451 PJ_DEF(pj_status_t) pjsip_transport_destroy( pjsip_transport *tp)
1452 {
1453 pjsip_tp_state_callback state_cb;
1454
1455 /* Must have no user. */
1456 PJ_ASSERT_RETURN(pj_atomic_get(tp->ref_cnt) == 0, PJSIP_EBUSY);
1457
1458 /* Notify application of transport destroy */
1459 state_cb = pjsip_tpmgr_get_state_cb(tp->tpmgr);
1460 if (state_cb) {
1461 pjsip_transport_state_info state_info;
1462
1463 pj_bzero(&state_info, sizeof(state_info));
1464 (*state_cb)(tp, PJSIP_TP_STATE_DESTROY, &state_info);
1465 }
1466
1467 /* Destroy. */
1468 return destroy_transport(tp->tpmgr, tp);
1469 }
1470
1471
1472
1473 /*****************************************************************************
1474 *
1475 * TRANSPORT FACTORY
1476 *
1477 *****************************************************************************/
1478
1479
pjsip_tpmgr_register_tpfactory(pjsip_tpmgr * mgr,pjsip_tpfactory * tpf)1480 PJ_DEF(pj_status_t) pjsip_tpmgr_register_tpfactory( pjsip_tpmgr *mgr,
1481 pjsip_tpfactory *tpf)
1482 {
1483 pjsip_tpfactory *p;
1484 pj_status_t status;
1485
1486 pj_lock_acquire(mgr->lock);
1487
1488 /* Check that no same factory has been registered. */
1489 status = PJ_SUCCESS;
1490 for (p=mgr->factory_list.next; p!=&mgr->factory_list; p=p->next) {
1491 if (p == tpf) {
1492 status = PJ_EEXISTS;
1493 break;
1494 }
1495 }
1496
1497 if (status != PJ_SUCCESS) {
1498 pj_lock_release(mgr->lock);
1499 return status;
1500 }
1501
1502 pj_list_insert_before(&mgr->factory_list, tpf);
1503
1504 pj_lock_release(mgr->lock);
1505
1506 return PJ_SUCCESS;
1507 }
1508
1509
1510 /**
1511 * Unregister factory.
1512 */
pjsip_tpmgr_unregister_tpfactory(pjsip_tpmgr * mgr,pjsip_tpfactory * tpf)1513 PJ_DEF(pj_status_t) pjsip_tpmgr_unregister_tpfactory( pjsip_tpmgr *mgr,
1514 pjsip_tpfactory *tpf)
1515 {
1516 pj_lock_acquire(mgr->lock);
1517
1518 pj_assert(pj_list_find_node(&mgr->factory_list, tpf) == tpf);
1519 pj_list_erase(tpf);
1520
1521 pj_lock_release(mgr->lock);
1522
1523 return PJ_SUCCESS;
1524 }
1525
pjsip_tpmgr_fla2_param_default(pjsip_tpmgr_fla2_param * prm)1526 PJ_DECL(void) pjsip_tpmgr_fla2_param_default(pjsip_tpmgr_fla2_param *prm)
1527 {
1528 pj_bzero(prm, sizeof(*prm));
1529 }
1530
pjsip_tpmgr_is_tpfactory_valid(pjsip_tpmgr * mgr,pjsip_tpfactory * tpf)1531 static pj_bool_t pjsip_tpmgr_is_tpfactory_valid(pjsip_tpmgr *mgr,
1532 pjsip_tpfactory *tpf)
1533 {
1534 pjsip_tpfactory *p;
1535
1536 pj_lock_acquire(mgr->lock);
1537 for (p=mgr->factory_list.next; p!=&mgr->factory_list; p=p->next) {
1538 if (p == tpf) {
1539 pj_lock_release(mgr->lock);
1540 return PJ_TRUE;
1541 }
1542 }
1543 pj_lock_release(mgr->lock);
1544
1545 return PJ_FALSE;
1546 }
1547
1548 /*****************************************************************************
1549 *
1550 * TRANSPORT MANAGER
1551 *
1552 *****************************************************************************/
1553
1554 /*
1555 * Create a new transport manager.
1556 */
pjsip_tpmgr_create(pj_pool_t * pool,pjsip_endpoint * endpt,pjsip_rx_callback rx_cb,pjsip_tx_callback tx_cb,pjsip_tpmgr ** p_mgr)1557 PJ_DEF(pj_status_t) pjsip_tpmgr_create( pj_pool_t *pool,
1558 pjsip_endpoint *endpt,
1559 pjsip_rx_callback rx_cb,
1560 pjsip_tx_callback tx_cb,
1561 pjsip_tpmgr **p_mgr)
1562 {
1563 pjsip_tpmgr *mgr;
1564 pj_status_t status;
1565 unsigned i = 0;
1566 pj_pool_t *mgr_pool;
1567
1568 PJ_ASSERT_RETURN(pool && endpt && rx_cb && p_mgr, PJ_EINVAL);
1569
1570 /* Register mod_msg_print module. */
1571 status = pjsip_endpt_register_module(endpt, &mod_msg_print);
1572 if (status != PJ_SUCCESS)
1573 return status;
1574
1575 /* Create and initialize transport manager. */
1576 mgr_pool = pjsip_endpt_create_pool(endpt, "tpmgr",
1577 TPMGR_POOL_INIT_SIZE,
1578 TPMGR_POOL_INC_SIZE);
1579 mgr = PJ_POOL_ZALLOC_T(mgr_pool, pjsip_tpmgr);
1580 mgr->endpt = endpt;
1581 mgr->on_rx_msg = rx_cb;
1582 mgr->on_tx_msg = tx_cb;
1583 mgr->pool = mgr_pool;
1584
1585 if (!mgr->pool)
1586 return PJ_ENOMEM;
1587
1588 pj_list_init(&mgr->factory_list);
1589 pj_list_init(&mgr->tdata_list);
1590 pj_list_init(&mgr->tp_entry_freelist);
1591
1592 mgr->table = pj_hash_create(mgr->pool, PJSIP_TPMGR_HTABLE_SIZE);
1593 if (!mgr->table)
1594 return PJ_ENOMEM;
1595
1596 status = pj_lock_create_recursive_mutex(mgr->pool, "tmgr%p", &mgr->lock);
1597 if (status != PJ_SUCCESS)
1598 return status;
1599
1600 for (; i < PJSIP_TRANSPORT_ENTRY_ALLOC_CNT; ++i) {
1601 transport *tp_add = NULL;
1602
1603 tp_add = PJ_POOL_ZALLOC_T(mgr->pool, transport);
1604 if (!tp_add)
1605 return PJ_ENOMEM;
1606 pj_list_init(tp_add);
1607 pj_list_push_back(&mgr->tp_entry_freelist, tp_add);
1608 }
1609
1610 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
1611 status = pj_atomic_create(mgr->pool, 0, &mgr->tdata_counter);
1612 if (status != PJ_SUCCESS) {
1613 pj_lock_destroy(mgr->lock);
1614 return status;
1615 }
1616 #endif
1617
1618 /* Set transport state callback */
1619 pjsip_tpmgr_set_state_cb(mgr, &tp_state_callback);
1620
1621 PJ_LOG(5, (THIS_FILE, "Transport manager created."));
1622
1623 *p_mgr = mgr;
1624 return PJ_SUCCESS;
1625 }
1626
1627 /* Get the interface to send packet to the specified address */
get_net_interface(pjsip_transport_type_e tp_type,const pj_str_t * dst,pj_str_t * itf_str_addr)1628 static pj_status_t get_net_interface(pjsip_transport_type_e tp_type,
1629 const pj_str_t *dst,
1630 pj_str_t *itf_str_addr)
1631 {
1632 int af;
1633 pj_sockaddr itf_addr;
1634 pj_status_t status = -1;
1635
1636 af = (tp_type & PJSIP_TRANSPORT_IPV6)? pj_AF_INET6() : pj_AF_INET();
1637
1638 if (pjsip_cfg()->endpt.resolve_hostname_to_get_interface) {
1639 status = pj_getipinterface(af, dst, &itf_addr, PJ_TRUE, NULL);
1640 }
1641
1642 if (status != PJ_SUCCESS) {
1643 status = pj_getipinterface(af, dst, &itf_addr, PJ_FALSE, NULL);
1644 if (status != PJ_SUCCESS) {
1645 /* If it fails, e.g: on WM6(http://support.microsoft.com/kb/129065),
1646 * just fallback using pj_gethostip(), see ticket #1660.
1647 */
1648 PJ_PERROR(5,(THIS_FILE, status,
1649 "Warning: unable to determine local interface, "
1650 "fallback to default interface!"));
1651 status = pj_gethostip(af, &itf_addr);
1652 if (status != PJ_SUCCESS)
1653 return status;
1654 }
1655 }
1656
1657 /* Print address */
1658 pj_sockaddr_print(&itf_addr, itf_str_addr->ptr,
1659 PJ_INET6_ADDRSTRLEN, 0);
1660 itf_str_addr->slen = pj_ansi_strlen(itf_str_addr->ptr);
1661
1662 return PJ_SUCCESS;
1663 }
1664
1665 /*
1666 * Find out the appropriate local address info (IP address and port) to
1667 * advertise in Contact header based on the remote address to be
1668 * contacted. The local address info would be the address name of the
1669 * transport or listener which will be used to send the request.
1670 *
1671 * In this implementation, it will only select the transport based on
1672 * the transport type in the request.
1673 */
pjsip_tpmgr_find_local_addr2(pjsip_tpmgr * tpmgr,pj_pool_t * pool,pjsip_tpmgr_fla2_param * prm)1674 PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr2(pjsip_tpmgr *tpmgr,
1675 pj_pool_t *pool,
1676 pjsip_tpmgr_fla2_param *prm)
1677 {
1678 char tmp_buf[PJ_INET6_ADDRSTRLEN+10];
1679 pj_str_t tmp_str;
1680 pj_status_t status = PJSIP_EUNSUPTRANSPORT;
1681 unsigned flag;
1682
1683 /* Sanity checks */
1684 PJ_ASSERT_RETURN(tpmgr && pool && prm, PJ_EINVAL);
1685
1686 pj_strset(&tmp_str, tmp_buf, 0);
1687 prm->ret_addr.slen = 0;
1688 prm->ret_port = 0;
1689 prm->ret_tp = NULL;
1690
1691 flag = pjsip_transport_get_flag_from_type(prm->tp_type);
1692
1693 if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
1694 prm->tp_sel->u.transport)
1695 {
1696 const pjsip_transport *tp = prm->tp_sel->u.transport;
1697 if (prm->local_if) {
1698 status = get_net_interface((pjsip_transport_type_e)tp->key.type,
1699 &prm->dst_host, &tmp_str);
1700 if (status != PJ_SUCCESS)
1701 goto on_return;
1702 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1703 prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
1704 prm->ret_tp = tp;
1705 } else {
1706 pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
1707 prm->ret_port = (pj_uint16_t)tp->local_name.port;
1708 }
1709 status = PJ_SUCCESS;
1710
1711 } else if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_LISTENER &&
1712 prm->tp_sel->u.listener)
1713 {
1714 if (prm->local_if) {
1715 status = get_net_interface(prm->tp_sel->u.listener->type,
1716 &prm->dst_host, &tmp_str);
1717 if (status != PJ_SUCCESS)
1718 goto on_return;
1719 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1720 } else {
1721 pj_strdup(pool, &prm->ret_addr,
1722 &prm->tp_sel->u.listener->addr_name.host);
1723 }
1724 prm->ret_port = (pj_uint16_t)prm->tp_sel->u.listener->addr_name.port;
1725 status = PJ_SUCCESS;
1726
1727 } else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
1728 pj_sockaddr remote;
1729 int addr_len;
1730 pjsip_transport *tp;
1731
1732 pj_bzero(&remote, sizeof(remote));
1733 if (prm->tp_type & PJSIP_TRANSPORT_IPV6) {
1734 addr_len = sizeof(pj_sockaddr_in6);
1735 remote.addr.sa_family = pj_AF_INET6();
1736 } else {
1737 addr_len = sizeof(pj_sockaddr_in);
1738 remote.addr.sa_family = pj_AF_INET();
1739 }
1740
1741 status = pjsip_tpmgr_acquire_transport(tpmgr, prm->tp_type, &remote,
1742 addr_len, NULL, &tp);
1743
1744 if (status == PJ_SUCCESS) {
1745 if (prm->local_if) {
1746 status = get_net_interface((pjsip_transport_type_e)
1747 tp->key.type,
1748 &prm->dst_host, &tmp_str);
1749 if (status != PJ_SUCCESS)
1750 goto on_return;
1751 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1752 prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
1753 prm->ret_tp = tp;
1754 } else {
1755 pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
1756 prm->ret_port = (pj_uint16_t)tp->local_name.port;
1757 }
1758
1759 pjsip_transport_dec_ref(tp);
1760 }
1761
1762 } else {
1763 /* For connection oriented transport, enum the factories */
1764 pjsip_tpfactory *f;
1765
1766 pj_lock_acquire(tpmgr->lock);
1767
1768 f = tpmgr->factory_list.next;
1769 while (f != &tpmgr->factory_list) {
1770 if (f->type == prm->tp_type)
1771 break;
1772 f = f->next;
1773 }
1774
1775 if (f != &tpmgr->factory_list) {
1776 if (prm->local_if) {
1777 status = get_net_interface(f->type, &prm->dst_host,
1778 &tmp_str);
1779 if (status == PJ_SUCCESS) {
1780 pj_strdup(pool, &prm->ret_addr, &tmp_str);
1781 } else {
1782 /* It could fail "normally" on certain cases, e.g.
1783 * when connecting to IPv6 link local address, it
1784 * will wail with EINVAL.
1785 * In this case, fallback to use the default interface
1786 * rather than failing the call.
1787 */
1788 PJ_PERROR(5,(THIS_FILE, status, "Warning: unable to "
1789 "determine local interface"));
1790 pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
1791 status = PJ_SUCCESS;
1792 }
1793 } else {
1794 pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
1795 }
1796 prm->ret_port = (pj_uint16_t)f->addr_name.port;
1797 status = PJ_SUCCESS;
1798 }
1799 pj_lock_release(tpmgr->lock);
1800 }
1801
1802 on_return:
1803 return status;
1804 }
1805
pjsip_tpmgr_find_local_addr(pjsip_tpmgr * tpmgr,pj_pool_t * pool,pjsip_transport_type_e type,const pjsip_tpselector * sel,pj_str_t * ip_addr,int * port)1806 PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
1807 pj_pool_t *pool,
1808 pjsip_transport_type_e type,
1809 const pjsip_tpselector *sel,
1810 pj_str_t *ip_addr,
1811 int *port)
1812 {
1813 pjsip_tpmgr_fla2_param prm;
1814 pj_status_t status;
1815
1816 pjsip_tpmgr_fla2_param_default(&prm);
1817 prm.tp_type = type;
1818 prm.tp_sel = sel;
1819
1820 status = pjsip_tpmgr_find_local_addr2(tpmgr, pool, &prm);
1821 if (status != PJ_SUCCESS)
1822 return status;
1823
1824 *ip_addr = prm.ret_addr;
1825 *port = prm.ret_port;
1826
1827 return PJ_SUCCESS;
1828 }
1829
1830 /*
1831 * Return number of transports currently registered to the transport
1832 * manager.
1833 */
pjsip_tpmgr_get_transport_count(pjsip_tpmgr * mgr)1834 PJ_DEF(unsigned) pjsip_tpmgr_get_transport_count(pjsip_tpmgr *mgr)
1835 {
1836 pj_hash_iterator_t itr_val;
1837 pj_hash_iterator_t *itr;
1838 int nr_of_transports = 0;
1839
1840 pj_lock_acquire(mgr->lock);
1841
1842 itr = pj_hash_first(mgr->table, &itr_val);
1843 while (itr) {
1844 transport *tp_entry = (transport *)pj_hash_this(mgr->table, itr);
1845 nr_of_transports += pj_list_size(tp_entry);
1846 itr = pj_hash_next(mgr->table, itr);
1847 }
1848
1849 pj_lock_release(mgr->lock);
1850
1851 return nr_of_transports;
1852 }
1853
1854 /*
1855 * pjsip_tpmgr_destroy()
1856 *
1857 * Destroy transport manager.
1858 */
pjsip_tpmgr_destroy(pjsip_tpmgr * mgr)1859 PJ_DEF(pj_status_t) pjsip_tpmgr_destroy( pjsip_tpmgr *mgr )
1860 {
1861 pj_hash_iterator_t itr_val;
1862 pj_hash_iterator_t *itr;
1863 pjsip_tpfactory *factory;
1864 pjsip_endpoint *endpt = mgr->endpt;
1865
1866 PJ_LOG(5, (THIS_FILE, "Destroying transport manager"));
1867
1868 pj_lock_acquire(mgr->lock);
1869
1870 /*
1871 * Destroy all transports in the hash table.
1872 */
1873 for (itr = pj_hash_first(mgr->table, &itr_val); itr;
1874 itr = pj_hash_first(mgr->table, &itr_val))
1875 {
1876 transport *tp_ref;
1877 tp_ref = pj_hash_this(mgr->table, itr);
1878 destroy_transport(mgr, tp_ref->tp);
1879 }
1880
1881 /*
1882 * Destroy all factories/listeners.
1883 */
1884 factory = mgr->factory_list.next;
1885 while (factory != &mgr->factory_list) {
1886 pjsip_tpfactory *next = factory->next;
1887
1888 factory->destroy(factory);
1889
1890 factory = next;
1891 }
1892
1893 pj_lock_release(mgr->lock);
1894
1895 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
1896 /* If you encounter assert error on this line, it means there are
1897 * leakings in transmit data (i.e. some transmit data have not been
1898 * destroyed).
1899 */
1900 //pj_assert(pj_atomic_get(mgr->tdata_counter) == 0);
1901 if (pj_atomic_get(mgr->tdata_counter) != 0) {
1902 PJ_LOG(3,(THIS_FILE, "Warning: %d transmit buffer(s) not freed!",
1903 pj_atomic_get(mgr->tdata_counter)));
1904 }
1905 #endif
1906
1907 /*
1908 * Destroy any dangling transmit buffer.
1909 */
1910 if (!pj_list_empty(&mgr->tdata_list)) {
1911 pjsip_tx_data *tdata = mgr->tdata_list.next;
1912 while (tdata != &mgr->tdata_list) {
1913 pjsip_tx_data *next = tdata->next;
1914 tx_data_destroy(tdata);
1915 tdata = next;
1916 }
1917 PJ_LOG(3,(THIS_FILE, "Cleaned up dangling transmit buffer(s)."));
1918 }
1919
1920 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
1921 pj_atomic_destroy(mgr->tdata_counter);
1922 #endif
1923
1924 pj_lock_destroy(mgr->lock);
1925
1926 /* Unregister mod_msg_print. */
1927 if (mod_msg_print.id != -1) {
1928 pjsip_endpt_unregister_module(endpt, &mod_msg_print);
1929 }
1930
1931 if (mgr->pool) {
1932 pjsip_endpt_release_pool( mgr->endpt, mgr->pool );
1933 }
1934
1935 return PJ_SUCCESS;
1936 }
1937
1938
1939 /*
1940 * pjsip_tpmgr_receive_packet()
1941 *
1942 * Called by tranports when they receive a new packet.
1943 */
pjsip_tpmgr_receive_packet(pjsip_tpmgr * mgr,pjsip_rx_data * rdata)1944 PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr,
1945 pjsip_rx_data *rdata)
1946 {
1947 pjsip_transport *tr = rdata->tp_info.transport;
1948
1949 char *current_pkt;
1950 pj_size_t remaining_len;
1951 pj_size_t total_processed = 0;
1952
1953 /* Check size. */
1954 pj_assert(rdata->pkt_info.len > 0);
1955 if (rdata->pkt_info.len <= 0)
1956 return -1;
1957
1958 current_pkt = rdata->pkt_info.packet;
1959 remaining_len = rdata->pkt_info.len;
1960
1961 tr->last_recv_len = rdata->pkt_info.len;
1962 pj_get_timestamp(&tr->last_recv_ts);
1963
1964 /* Must NULL terminate buffer. This is the requirement of the
1965 * parser etc.
1966 */
1967 current_pkt[remaining_len] = '\0';
1968
1969 /* Process all message fragments. */
1970 while (remaining_len > 0) {
1971
1972 pjsip_msg *msg;
1973 char *p, *end;
1974 char saved;
1975 pj_size_t msg_fragment_size;
1976
1977 /* Skip leading newlines as pjsip_find_msg() currently can't
1978 * handle leading newlines.
1979 */
1980 for (p=current_pkt, end=p+remaining_len; p!=end; ++p) {
1981 if (*p != '\r' && *p != '\n')
1982 break;
1983 }
1984 if (p!=current_pkt) {
1985 remaining_len -= (p - current_pkt);
1986 total_processed += (p - current_pkt);
1987
1988 /* Notify application about the dropped newlines */
1989 if (mgr->tp_drop_data_cb) {
1990 pjsip_tp_dropped_data dd;
1991 pj_bzero(&dd, sizeof(dd));
1992 dd.tp = tr;
1993 dd.data = current_pkt;
1994 dd.len = p - current_pkt;
1995 dd.status = PJ_EIGNORED;
1996 (*mgr->tp_drop_data_cb)(&dd);
1997 }
1998
1999 current_pkt = p;
2000 if (remaining_len == 0) {
2001 return total_processed;
2002 }
2003 }
2004
2005 /* Initialize default fragment size. */
2006 msg_fragment_size = remaining_len;
2007
2008 /* Clear and init msg_info in rdata.
2009 * Endpoint might inspect the values there when we call the callback
2010 * to report some errors.
2011 */
2012 pj_bzero(&rdata->msg_info, sizeof(rdata->msg_info));
2013 pj_list_init(&rdata->msg_info.parse_err);
2014 rdata->msg_info.msg_buf = current_pkt;
2015 rdata->msg_info.len = (int)remaining_len;
2016
2017 /* For TCP transport, check if the whole message has been received. */
2018 if ((tr->flag & PJSIP_TRANSPORT_DATAGRAM) == 0) {
2019 pj_status_t msg_status;
2020 msg_status = pjsip_find_msg(current_pkt, remaining_len, PJ_FALSE,
2021 &msg_fragment_size);
2022 if (msg_status != PJ_SUCCESS) {
2023 if (remaining_len == PJSIP_MAX_PKT_LEN) {
2024 mgr->on_rx_msg(mgr->endpt, PJSIP_ERXOVERFLOW, rdata);
2025
2026 /* Notify application about the message overflow */
2027 if (mgr->tp_drop_data_cb) {
2028 pjsip_tp_dropped_data dd;
2029 pj_bzero(&dd, sizeof(dd));
2030 dd.tp = tr;
2031 dd.data = current_pkt;
2032 dd.len = msg_fragment_size;
2033 dd.status = PJSIP_ERXOVERFLOW;
2034 (*mgr->tp_drop_data_cb)(&dd);
2035 }
2036
2037 /* Exhaust all data. */
2038 return rdata->pkt_info.len;
2039 } else {
2040 /* Not enough data in packet. */
2041 return total_processed;
2042 }
2043 }
2044 }
2045
2046 /* Update msg_info. */
2047 rdata->msg_info.len = (int)msg_fragment_size;
2048
2049 /* Null terminate packet */
2050 saved = current_pkt[msg_fragment_size];
2051 current_pkt[msg_fragment_size] = '\0';
2052
2053 /* Parse the message. */
2054 rdata->msg_info.msg = msg =
2055 pjsip_parse_rdata( current_pkt, msg_fragment_size, rdata);
2056
2057 /* Restore null termination */
2058 current_pkt[msg_fragment_size] = saved;
2059
2060 /* Check for parsing syntax error */
2061 if (msg==NULL || !pj_list_empty(&rdata->msg_info.parse_err)) {
2062 pjsip_parser_err_report *err;
2063 char buf[256];
2064 pj_str_t tmp;
2065
2066 /* Gather syntax error information */
2067 tmp.ptr = buf; tmp.slen = 0;
2068 err = rdata->msg_info.parse_err.next;
2069 while (err != &rdata->msg_info.parse_err) {
2070 int len;
2071 len = pj_ansi_snprintf(tmp.ptr+tmp.slen, sizeof(buf)-tmp.slen,
2072 ": %s exception when parsing '%.*s' "
2073 "header on line %d col %d",
2074 pj_exception_id_name(err->except_code),
2075 (int)err->hname.slen, err->hname.ptr,
2076 err->line, err->col);
2077 if (len >= (int)sizeof(buf)-tmp.slen) {
2078 len = (int)sizeof(buf)-tmp.slen;
2079 }
2080 if (len > 0) {
2081 tmp.slen += len;
2082 }
2083 err = err->next;
2084 }
2085
2086 /* Only print error message if there's error.
2087 * Sometimes we receive blank packets (packets with only CRLF)
2088 * which were sent to keep NAT bindings.
2089 */
2090 if (tmp.slen) {
2091 PJ_LOG(1, (THIS_FILE,
2092 "Error processing %d bytes packet from %s %s:%d %.*s:\n"
2093 "%.*s\n"
2094 "-- end of packet.",
2095 msg_fragment_size,
2096 rdata->tp_info.transport->type_name,
2097 rdata->pkt_info.src_name,
2098 rdata->pkt_info.src_port,
2099 (int)tmp.slen, tmp.ptr,
2100 (int)msg_fragment_size,
2101 rdata->msg_info.msg_buf));
2102 }
2103
2104 /* Notify application about the dropped data (syntax error) */
2105 if (tmp.slen && mgr->tp_drop_data_cb) {
2106 pjsip_tp_dropped_data dd;
2107 pj_bzero(&dd, sizeof(dd));
2108 dd.tp = tr;
2109 dd.data = current_pkt;
2110 dd.len = msg_fragment_size;
2111 dd.status = PJSIP_EINVALIDMSG;
2112 (*mgr->tp_drop_data_cb)(&dd);
2113
2114 if (dd.len > 0 && dd.len < msg_fragment_size)
2115 msg_fragment_size = dd.len;
2116 }
2117
2118 goto finish_process_fragment;
2119 }
2120
2121 /* Perform basic header checking. */
2122 if (rdata->msg_info.cid == NULL ||
2123 rdata->msg_info.cid->id.slen == 0 ||
2124 rdata->msg_info.from == NULL ||
2125 rdata->msg_info.to == NULL ||
2126 rdata->msg_info.via == NULL ||
2127 rdata->msg_info.cseq == NULL)
2128 {
2129 mgr->on_rx_msg(mgr->endpt, PJSIP_EMISSINGHDR, rdata);
2130
2131 /* Notify application about the missing header. */
2132 if (mgr->tp_drop_data_cb) {
2133 pjsip_tp_dropped_data dd;
2134 pj_bzero(&dd, sizeof(dd));
2135 dd.tp = tr;
2136 dd.data = current_pkt;
2137 dd.len = msg_fragment_size;
2138 dd.status = PJSIP_EMISSINGHDR;
2139 (*mgr->tp_drop_data_cb)(&dd);
2140 }
2141 goto finish_process_fragment;
2142 }
2143
2144 /* For request: */
2145 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
2146 /* always add received parameter to the via. */
2147 pj_strdup2(rdata->tp_info.pool,
2148 &rdata->msg_info.via->recvd_param,
2149 rdata->pkt_info.src_name);
2150
2151 /* RFC 3581:
2152 * If message contains "rport" param, put the received port there.
2153 */
2154 if (rdata->msg_info.via->rport_param == 0) {
2155 rdata->msg_info.via->rport_param = rdata->pkt_info.src_port;
2156 }
2157 } else {
2158 /* Drop malformed responses */
2159 if (rdata->msg_info.msg->line.status.code < 100 ||
2160 rdata->msg_info.msg->line.status.code >= 700)
2161 {
2162 mgr->on_rx_msg(mgr->endpt, PJSIP_EINVALIDSTATUS, rdata);
2163
2164 /* Notify application about the invalid status. */
2165 if (mgr->tp_drop_data_cb) {
2166 pjsip_tp_dropped_data dd;
2167 pj_bzero(&dd, sizeof(dd));
2168 dd.tp = tr;
2169 dd.data = current_pkt;
2170 dd.len = msg_fragment_size;
2171 dd.status = PJSIP_EINVALIDSTATUS;
2172 (*mgr->tp_drop_data_cb)(&dd);
2173 }
2174 goto finish_process_fragment;
2175 }
2176 }
2177
2178 /* Drop response message if it has more than one Via.
2179 */
2180 /* This is wrong. Proxy DOES receive responses with multiple
2181 * Via headers! Thanks Aldo <acampi at deis.unibo.it> for pointing
2182 * this out.
2183
2184 if (msg->type == PJSIP_RESPONSE_MSG) {
2185 pjsip_hdr *hdr;
2186 hdr = (pjsip_hdr*)rdata->msg_info.via->next;
2187 if (hdr != &msg->hdr) {
2188 hdr = pjsip_msg_find_hdr(msg, PJSIP_H_VIA, hdr);
2189 if (hdr) {
2190 mgr->on_rx_msg(mgr->endpt, PJSIP_EMULTIPLEVIA, rdata);
2191 goto finish_process_fragment;
2192 }
2193 }
2194 }
2195 */
2196
2197 /* Call the transport manager's upstream message callback.
2198 */
2199 mgr->on_rx_msg(mgr->endpt, PJ_SUCCESS, rdata);
2200
2201
2202 finish_process_fragment:
2203 total_processed += msg_fragment_size;
2204 current_pkt += msg_fragment_size;
2205 remaining_len -= msg_fragment_size;
2206
2207 } /* while (rdata->pkt_info.len > 0) */
2208
2209
2210 return total_processed;
2211 }
2212
2213
2214 /*
2215 * pjsip_tpmgr_acquire_transport()
2216 *
2217 * Get transport suitable to communicate to remote. Create a new one
2218 * if necessary.
2219 */
pjsip_tpmgr_acquire_transport(pjsip_tpmgr * mgr,pjsip_transport_type_e type,const pj_sockaddr_t * remote,int addr_len,const pjsip_tpselector * sel,pjsip_transport ** tp)2220 PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
2221 pjsip_transport_type_e type,
2222 const pj_sockaddr_t *remote,
2223 int addr_len,
2224 const pjsip_tpselector *sel,
2225 pjsip_transport **tp)
2226 {
2227 return pjsip_tpmgr_acquire_transport2(mgr, type, remote, addr_len, sel,
2228 NULL, tp);
2229 }
2230
2231
2232 /*
2233 * pjsip_tpmgr_acquire_transport2()
2234 *
2235 * Get transport suitable to communicate to remote. Create a new one
2236 * if necessary.
2237 */
pjsip_tpmgr_acquire_transport2(pjsip_tpmgr * mgr,pjsip_transport_type_e type,const pj_sockaddr_t * remote,int addr_len,const pjsip_tpselector * sel,pjsip_tx_data * tdata,pjsip_transport ** tp)2238 PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
2239 pjsip_transport_type_e type,
2240 const pj_sockaddr_t *remote,
2241 int addr_len,
2242 const pjsip_tpselector *sel,
2243 pjsip_tx_data *tdata,
2244 pjsip_transport **tp)
2245 {
2246 pjsip_tpfactory *factory;
2247 pj_status_t status;
2248
2249 TRACE_((THIS_FILE,"Acquiring transport type=%s, sel=%s remote=%s:%d",
2250 pjsip_transport_get_type_name(type),
2251 print_tpsel_info(sel),
2252 addr_string(remote),
2253 pj_sockaddr_get_port(remote)));
2254
2255 pj_lock_acquire(mgr->lock);
2256
2257 /* If transport is specified, then just use it if it is suitable
2258 * for the destination.
2259 */
2260 if (sel && sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
2261 sel->u.transport)
2262 {
2263 pjsip_transport *seltp = sel->u.transport;
2264
2265 /* See if the transport is (not) suitable */
2266 if (seltp->key.type != type) {
2267 pj_lock_release(mgr->lock);
2268 TRACE_((THIS_FILE, "Transport type in tpsel not matched"));
2269 return PJSIP_ETPNOTSUITABLE;
2270 }
2271
2272 /* Make sure the transport is not being destroyed */
2273 if (seltp->is_destroying) {
2274 pj_lock_release(mgr->lock);
2275 TRACE_((THIS_FILE,"Transport to be acquired is being destroyed"));
2276 return PJ_ENOTFOUND;
2277 }
2278
2279 /* We could also verify that the destination address is reachable
2280 * from this transport (i.e. both are equal), but if application
2281 * has requested a specific transport to be used, assume that
2282 * it knows what to do.
2283 *
2284 * In other words, I don't think destination verification is a good
2285 * idea for now.
2286 */
2287
2288 /* Transport looks to be suitable to use, so just use it. */
2289 pjsip_transport_add_ref(seltp);
2290 pj_lock_release(mgr->lock);
2291 *tp = seltp;
2292
2293 TRACE_((THIS_FILE, "Transport %s acquired", seltp->obj_name));
2294 return PJ_SUCCESS;
2295
2296 } else {
2297
2298 /*
2299 * This is the "normal" flow, where application doesn't specify
2300 * specific transport to be used to send message to.
2301 * In this case, lookup the transport from the hash table.
2302 */
2303 pjsip_transport_key key;
2304 int key_len;
2305 pjsip_transport *tp_ref = NULL;
2306 transport *tp_entry = NULL;
2307 unsigned flag = pjsip_transport_get_flag_from_type(type);
2308
2309 /* If listener is specified, verify that the listener type matches
2310 * the destination type.
2311 */
2312 if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener)
2313 {
2314 if (sel->u.listener->type != type) {
2315 pj_lock_release(mgr->lock);
2316 TRACE_((THIS_FILE, "Listener type in tpsel not matched"));
2317 return PJSIP_ETPNOTSUITABLE;
2318 }
2319 }
2320
2321 if (!sel || sel->disable_connection_reuse == PJ_FALSE) {
2322 pj_bzero(&key, sizeof(key));
2323 key_len = sizeof(key.type) + addr_len;
2324
2325 /* First try to get exact destination. */
2326 key.type = type;
2327 pj_memcpy(&key.rem_addr, remote, addr_len);
2328
2329 tp_entry = (transport *)pj_hash_get(mgr->table, &key, key_len,
2330 NULL);
2331 if (tp_entry) {
2332 transport *tp_iter = tp_entry;
2333 do {
2334 /* Don't use transport being shutdown/destroyed */
2335 if (!tp_iter->tp->is_shutdown &&
2336 !tp_iter->tp->is_destroying)
2337 {
2338 if ((flag & PJSIP_TRANSPORT_SECURE) && tdata) {
2339 /* For secure transport, make sure tdata's
2340 * destination host matches the transport's
2341 * remote host.
2342 */
2343 if (pj_stricmp(&tdata->dest_info.name,
2344 &tp_iter->tp->remote_name.host))
2345 {
2346 tp_iter = tp_iter->next;
2347 continue;
2348 }
2349 }
2350
2351 if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
2352 sel->u.listener)
2353 {
2354 /* Match listener if selector is set */
2355 if (tp_iter->tp->factory == sel->u.listener) {
2356 tp_ref = tp_iter->tp;
2357 break;
2358 }
2359 } else {
2360 tp_ref = tp_iter->tp;
2361 break;
2362 }
2363 }
2364 tp_iter = tp_iter->next;
2365 } while (tp_iter != tp_entry);
2366 }
2367 }
2368
2369 if (tp_ref == NULL &&
2370 (!sel || sel->disable_connection_reuse == PJ_FALSE))
2371 {
2372 const pj_sockaddr *remote_addr = (const pj_sockaddr*)remote;
2373
2374
2375 /* Ignore address for loop transports. */
2376 if (type == PJSIP_TRANSPORT_LOOP ||
2377 type == PJSIP_TRANSPORT_LOOP_DGRAM)
2378 {
2379 pj_sockaddr *addr = &key.rem_addr;
2380
2381 pj_bzero(addr, addr_len);
2382 key_len = sizeof(key.type) + addr_len;
2383 tp_entry = (transport *) pj_hash_get(mgr->table, &key,
2384 key_len, NULL);
2385 if (tp_entry) {
2386 tp_ref = tp_entry->tp;
2387 }
2388 }
2389 /* For datagram transports, try lookup with zero address.
2390 */
2391 else if (flag & PJSIP_TRANSPORT_DATAGRAM)
2392 {
2393 pj_sockaddr *addr = &key.rem_addr;
2394
2395 pj_bzero(addr, addr_len);
2396 addr->addr.sa_family = remote_addr->addr.sa_family;
2397
2398 key_len = sizeof(key.type) + addr_len;
2399 tp_entry = (transport *) pj_hash_get(mgr->table, &key,
2400 key_len, NULL);
2401 if (tp_entry) {
2402 tp_ref = tp_entry->tp;
2403 }
2404 }
2405 }
2406
2407 /* If transport is found and listener is specified, verify listener */
2408 else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
2409 sel->u.listener && tp_ref->factory != sel->u.listener)
2410 {
2411 tp_ref = NULL;
2412 /* This will cause a new transport to be created which will be a
2413 * 'duplicate' of the existing transport (same type & remote addr,
2414 * but different factory).
2415 */
2416 TRACE_((THIS_FILE, "Transport found but from different listener"));
2417 }
2418
2419 if (tp_ref!=NULL && !tp_ref->is_shutdown && !tp_ref->is_destroying) {
2420 /*
2421 * Transport found!
2422 */
2423 pjsip_transport_add_ref(tp_ref);
2424 pj_lock_release(mgr->lock);
2425 *tp = tp_ref;
2426
2427 TRACE_((THIS_FILE, "Transport %s acquired", tp_ref->obj_name));
2428 return PJ_SUCCESS;
2429 }
2430
2431
2432 /*
2433 * Either transport not found, or we don't want to use the existing
2434 * transport (such as in the case of different factory or
2435 * if connection reuse is disabled). So we need to create one,
2436 * find factory that can create such transport.
2437 *
2438 * If there's an existing transport, its place in the hash table
2439 * will be replaced by this new one. And eventually the existing
2440 * transport will still be freed (by application or #1774).
2441 */
2442 if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER && sel->u.listener)
2443 {
2444 /* Application has requested that a specific listener is to
2445 * be used.
2446 */
2447
2448 /* Verify that the listener type matches the destination type */
2449 /* Already checked above. */
2450 /*
2451 if (sel->u.listener->type != type) {
2452 pj_lock_release(mgr->lock);
2453 return PJSIP_ETPNOTSUITABLE;
2454 }
2455 */
2456
2457 /* We'll use this listener to create transport */
2458 factory = sel->u.listener;
2459
2460 /* Verify if listener is still valid */
2461 if (!pjsip_tpmgr_is_tpfactory_valid(mgr, factory)) {
2462 pj_lock_release(mgr->lock);
2463 PJ_LOG(3,(THIS_FILE, "Specified factory for creating "
2464 "transport is not found"));
2465 return PJ_ENOTFOUND;
2466 }
2467
2468 } else {
2469
2470 /* Find factory with type matches the destination type */
2471 factory = mgr->factory_list.next;
2472 while (factory != &mgr->factory_list) {
2473 if (factory->type == type)
2474 break;
2475 factory = factory->next;
2476 }
2477
2478 if (factory == &mgr->factory_list) {
2479 /* No factory can create the transport! */
2480 pj_lock_release(mgr->lock);
2481 TRACE_((THIS_FILE, "No suitable factory was found either"));
2482 return PJSIP_EUNSUPTRANSPORT;
2483 }
2484 }
2485 }
2486
2487 TRACE_((THIS_FILE, "Creating new transport from factory"));
2488
2489 /* Request factory to create transport. */
2490 if (factory->create_transport2) {
2491 status = factory->create_transport2(factory, mgr, mgr->endpt,
2492 (const pj_sockaddr*) remote,
2493 addr_len, tdata, tp);
2494 } else {
2495 status = factory->create_transport(factory, mgr, mgr->endpt,
2496 (const pj_sockaddr*) remote,
2497 addr_len, tp);
2498 }
2499 if (status == PJ_SUCCESS) {
2500 PJ_ASSERT_ON_FAIL(tp!=NULL,
2501 {pj_lock_release(mgr->lock); return PJ_EBUG;});
2502 pjsip_transport_add_ref(*tp);
2503 (*tp)->factory = factory;
2504 }
2505 pj_lock_release(mgr->lock);
2506 return status;
2507 }
2508
2509 /**
2510 * Dump transport info.
2511 */
pjsip_tpmgr_dump_transports(pjsip_tpmgr * mgr)2512 PJ_DEF(void) pjsip_tpmgr_dump_transports(pjsip_tpmgr *mgr)
2513 {
2514 #if PJ_LOG_MAX_LEVEL >= 3
2515 pj_hash_iterator_t itr_val;
2516 pj_hash_iterator_t *itr;
2517 pjsip_tpfactory *factory;
2518
2519 pj_lock_acquire(mgr->lock);
2520
2521 #if defined(PJ_DEBUG) && PJ_DEBUG!=0
2522 PJ_LOG(3,(THIS_FILE, " Outstanding transmit buffers: %d",
2523 pj_atomic_get(mgr->tdata_counter)));
2524 #endif
2525
2526 PJ_LOG(3, (THIS_FILE, " Dumping listeners:"));
2527 factory = mgr->factory_list.next;
2528 while (factory != &mgr->factory_list) {
2529 PJ_LOG(3, (THIS_FILE, " %s %s:%.*s:%d",
2530 factory->obj_name,
2531 factory->type_name,
2532 (int)factory->addr_name.host.slen,
2533 factory->addr_name.host.ptr,
2534 (int)factory->addr_name.port));
2535 factory = factory->next;
2536 }
2537
2538 itr = pj_hash_first(mgr->table, &itr_val);
2539 if (itr) {
2540 PJ_LOG(3, (THIS_FILE, " Dumping transports:"));
2541
2542 do {
2543 transport *tp_entry = (transport *) pj_hash_this(mgr->table, itr);
2544 if (tp_entry) {
2545 transport *tp_iter = tp_entry;
2546
2547 do {
2548 pjsip_transport *tp_ref = tp_iter->tp;
2549
2550 PJ_LOG(3, (THIS_FILE, " %s %s%s%s%s(refcnt=%d%s)",
2551 tp_ref->obj_name,
2552 tp_ref->info,
2553 (tp_ref->factory)?" listener[":"",
2554 (tp_ref->factory)?tp_ref->factory->obj_name:"",
2555 (tp_ref->factory)?"]":"",
2556 pj_atomic_get(tp_ref->ref_cnt),
2557 (tp_ref->idle_timer.id ? " [idle]" : "")));
2558
2559 tp_iter = tp_iter->next;
2560 } while (tp_iter != tp_entry);
2561 }
2562 itr = pj_hash_next(mgr->table, itr);
2563 } while (itr);
2564 }
2565
2566 pj_lock_release(mgr->lock);
2567 #else
2568 PJ_UNUSED_ARG(mgr);
2569 #endif
2570 }
2571
2572 /**
2573 * Set callback of global transport state notification.
2574 */
pjsip_tpmgr_set_state_cb(pjsip_tpmgr * mgr,pjsip_tp_state_callback cb)2575 PJ_DEF(pj_status_t) pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr,
2576 pjsip_tp_state_callback cb)
2577 {
2578 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
2579
2580 mgr->tp_state_cb = cb;
2581
2582 return PJ_SUCCESS;
2583 }
2584
2585 /**
2586 * Get callback of global transport state notification.
2587 */
pjsip_tpmgr_get_state_cb(const pjsip_tpmgr * mgr)2588 PJ_DEF(pjsip_tp_state_callback) pjsip_tpmgr_get_state_cb(
2589 const pjsip_tpmgr *mgr)
2590 {
2591 PJ_ASSERT_RETURN(mgr, NULL);
2592
2593 return mgr->tp_state_cb;
2594 }
2595
2596
2597 /**
2598 * Allocate and init transport data.
2599 */
init_tp_data(pjsip_transport * tp)2600 static void init_tp_data(pjsip_transport *tp)
2601 {
2602 transport_data *tp_data;
2603
2604 pj_assert(tp && !tp->data);
2605
2606 tp_data = PJ_POOL_ZALLOC_T(tp->pool, transport_data);
2607 pj_list_init(&tp_data->st_listeners);
2608 pj_list_init(&tp_data->st_listeners_empty);
2609 tp->data = tp_data;
2610 }
2611
2612
tp_state_callback(pjsip_transport * tp,pjsip_transport_state state,const pjsip_transport_state_info * info)2613 static void tp_state_callback(pjsip_transport *tp,
2614 pjsip_transport_state state,
2615 const pjsip_transport_state_info *info)
2616 {
2617 transport_data *tp_data;
2618
2619 pj_lock_acquire(tp->lock);
2620
2621 tp_data = (transport_data*)tp->data;
2622
2623 /* Notify the transport state listeners, if any. */
2624 if (!tp_data || pj_list_empty(&tp_data->st_listeners)) {
2625 goto on_return;
2626 } else {
2627 pjsip_transport_state_info st_info;
2628 tp_state_listener *st_listener = tp_data->st_listeners.next;
2629
2630 /* As we need to put the user data into the transport state info,
2631 * let's use a copy of transport state info.
2632 */
2633 pj_memcpy(&st_info, info, sizeof(st_info));
2634 while (st_listener != &tp_data->st_listeners) {
2635 st_info.user_data = st_listener->user_data;
2636 (*st_listener->cb)(tp, state, &st_info);
2637
2638 st_listener = st_listener->next;
2639 }
2640 }
2641
2642 on_return:
2643 pj_lock_release(tp->lock);
2644 }
2645
2646
2647 /**
2648 * Add a listener to the specified transport for transport state notification.
2649 */
pjsip_transport_add_state_listener(pjsip_transport * tp,pjsip_tp_state_callback cb,void * user_data,pjsip_tp_state_listener_key ** key)2650 PJ_DEF(pj_status_t) pjsip_transport_add_state_listener (
2651 pjsip_transport *tp,
2652 pjsip_tp_state_callback cb,
2653 void *user_data,
2654 pjsip_tp_state_listener_key **key)
2655 {
2656 transport_data *tp_data;
2657 tp_state_listener *entry;
2658
2659 PJ_ASSERT_RETURN(tp && cb && key, PJ_EINVAL);
2660
2661 if (tp->is_shutdown || tp->is_destroying) {
2662 *key = NULL;
2663 return PJ_EINVALIDOP;
2664 }
2665
2666 pj_lock_acquire(tp->lock);
2667
2668 /* Init transport data, if it hasn't */
2669 if (!tp->data)
2670 init_tp_data(tp);
2671
2672 tp_data = (transport_data*)tp->data;
2673
2674 /* Init the new listener entry. Use available empty slot, if any,
2675 * otherwise allocate it using the transport pool.
2676 */
2677 if (!pj_list_empty(&tp_data->st_listeners_empty)) {
2678 entry = tp_data->st_listeners_empty.next;
2679 pj_list_erase(entry);
2680 } else {
2681 entry = PJ_POOL_ZALLOC_T(tp->pool, tp_state_listener);
2682 }
2683 entry->cb = cb;
2684 entry->user_data = user_data;
2685
2686 /* Add the new listener entry to the listeners list */
2687 pj_list_push_back(&tp_data->st_listeners, entry);
2688
2689 *key = entry;
2690
2691 pj_lock_release(tp->lock);
2692
2693 return PJ_SUCCESS;
2694 }
2695
2696 /**
2697 * Remove a listener from the specified transport for transport state
2698 * notification.
2699 */
pjsip_transport_remove_state_listener(pjsip_transport * tp,pjsip_tp_state_listener_key * key,const void * user_data)2700 PJ_DEF(pj_status_t) pjsip_transport_remove_state_listener (
2701 pjsip_transport *tp,
2702 pjsip_tp_state_listener_key *key,
2703 const void *user_data)
2704 {
2705 transport_data *tp_data;
2706 tp_state_listener *entry;
2707
2708 PJ_ASSERT_RETURN(tp && key, PJ_EINVAL);
2709
2710 pj_lock_acquire(tp->lock);
2711
2712 tp_data = (transport_data*)tp->data;
2713
2714 /* Transport data is NULL or no registered listener? */
2715 if (!tp_data || pj_list_empty(&tp_data->st_listeners)) {
2716 pj_lock_release(tp->lock);
2717 return PJ_ENOTFOUND;
2718 }
2719
2720 entry = (tp_state_listener*)key;
2721
2722 /* Validate the user data */
2723 if (entry->user_data != user_data) {
2724 pj_assert(!"Invalid transport state listener key");
2725 pj_lock_release(tp->lock);
2726 return PJ_EBUG;
2727 }
2728
2729 /* Reset the entry and move it to the empty list */
2730 entry->cb = NULL;
2731 entry->user_data = NULL;
2732 pj_list_erase(entry);
2733 pj_list_push_back(&tp_data->st_listeners_empty, entry);
2734
2735 pj_lock_release(tp->lock);
2736
2737 return PJ_SUCCESS;
2738 }
2739
2740 /*
2741 * Set callback of data dropping.
2742 */
pjsip_tpmgr_set_drop_data_cb(pjsip_tpmgr * mgr,pjsip_tp_on_rx_dropped_cb cb)2743 PJ_DEF(pj_status_t) pjsip_tpmgr_set_drop_data_cb(pjsip_tpmgr *mgr,
2744 pjsip_tp_on_rx_dropped_cb cb)
2745 {
2746 PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
2747
2748 mgr->tp_drop_data_cb = cb;
2749
2750 return PJ_SUCCESS;
2751 }
2752