1
/* $Id: sip_transport_udp.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
20
#include <pjsip/sip_transport_udp.h>
21
#include <pjsip/sip_endpoint.h>
22
#include <pjsip/sip_errno.h>
23
#include <pj/addr_resolv.h>
24
#include <pj/assert.h>
30
#include <pj/compat/socket.h>
31
#include <pj/string.h>
34
#define THIS_FILE "sip_transport_udp.c"
37
* These are the target values for socket send and receive buffer sizes,
38
* respectively. They will be applied to UDP socket with setsockopt().
39
* When transport failed to set these size, it will decrease it until
40
* sufficiently large number has been successfully set.
42
* The buffer size is important, especially in WinXP/2000 machines.
43
* Basicly the lower the size, the more packets will be lost (dropped?)
44
* when we're sending (receiving?) packets in large volumes.
46
* The figure here is taken based on my experiment on WinXP/2000 machine,
47
* and with this value, the rate of dropped packet is about 8% when
48
* sending 1800 requests simultaneously (percentage taken as average
49
* after 50K requests or so).
51
* More experiments are needed probably.
54
* Too many people complained about seeing "Error setting SNDBUF" log,
55
* so lets just remove this. People who want to have SNDBUF set can
56
* still do so by declaring these two macros in config_site.h
58
#ifndef PJSIP_UDP_SO_SNDBUF_SIZE
59
/*# define PJSIP_UDP_SO_SNDBUF_SIZE (24*1024*1024)*/
60
# define PJSIP_UDP_SO_SNDBUF_SIZE 0
63
#ifndef PJSIP_UDP_SO_RCVBUF_SIZE
64
/*# define PJSIP_UDP_SO_RCVBUF_SIZE (24*1024*1024)*/
65
# define PJSIP_UDP_SO_RCVBUF_SIZE 0
69
/* Struct udp_transport "inherits" struct pjsip_transport */
74
pj_ioqueue_key_t *key;
76
pjsip_rx_data **rdata;
83
* Initialize transport's receive buffer from the specified pool.
85
static void init_rdata(struct udp_transport *tp, unsigned rdata_index,
86
pj_pool_t *pool, pjsip_rx_data **p_rdata)
91
//note: already done by caller
92
//pj_pool_reset(pool);
94
rdata = PJ_POOL_ZALLOC_T(pool, pjsip_rx_data);
96
/* Init tp_info part. */
97
rdata->tp_info.pool = pool;
98
rdata->tp_info.transport = &tp->base;
99
rdata->tp_info.tp_data = (void*)(long)rdata_index;
100
rdata->tp_info.op_key.rdata = rdata;
101
pj_ioqueue_op_key_init(&rdata->tp_info.op_key.op_key,
102
sizeof(pj_ioqueue_op_key_t));
104
tp->rdata[rdata_index] = rdata;
112
* udp_on_read_complete()
114
* This is callback notification from ioqueue that a pending recvfrom()
115
* operation has completed.
117
static void udp_on_read_complete( pj_ioqueue_key_t *key,
118
pj_ioqueue_op_key_t *op_key,
119
pj_ssize_t bytes_read)
121
/* See https://trac.pjsip.org/repos/ticket/1197 */
122
enum { MAX_IMMEDIATE_PACKET = 50 };
123
pjsip_rx_data_op_key *rdata_op_key = (pjsip_rx_data_op_key*) op_key;
124
pjsip_rx_data *rdata = rdata_op_key->rdata;
125
struct udp_transport *tp = (struct udp_transport*)rdata->tp_info.transport;
129
/* Don't do anything if transport is closing. */
130
if (tp->is_closing) {
135
/* Don't do anything if transport is being paused. */
140
* The idea of the loop is to process immediate data received by
141
* pj_ioqueue_recvfrom(), as long as i < MAX_IMMEDIATE_PACKET. When
142
* i is >= MAX_IMMEDIATE_PACKET, we force the recvfrom() operation to
143
* complete asynchronously, to allow other sockets to get their data.
146
enum { MIN_SIZE = 32 };
149
/* Report the packet to transport manager. Only do so if packet size
150
* is relatively big enough for a SIP packet.
152
if (bytes_read > MIN_SIZE) {
153
pj_size_t size_eaten;
154
const pj_sockaddr *src_addr = &rdata->pkt_info.src_addr;
156
/* Init pkt_info part. */
157
rdata->pkt_info.len = bytes_read;
158
rdata->pkt_info.zero = 0;
159
pj_gettimeofday(&rdata->pkt_info.timestamp);
160
if (src_addr->addr.sa_family == pj_AF_INET()) {
161
pj_ansi_strcpy(rdata->pkt_info.src_name,
162
pj_inet_ntoa(src_addr->ipv4.sin_addr));
163
rdata->pkt_info.src_port = pj_ntohs(src_addr->ipv4.sin_port);
165
pj_inet_ntop(pj_AF_INET6(),
166
pj_sockaddr_get_addr(&rdata->pkt_info.src_addr),
167
rdata->pkt_info.src_name,
168
sizeof(rdata->pkt_info.src_name));
169
rdata->pkt_info.src_port = pj_ntohs(src_addr->ipv6.sin6_port);
173
pjsip_tpmgr_receive_packet(rdata->tp_info.transport->tpmgr,
176
if (size_eaten < 0) {
177
pj_assert(!"It shouldn't happen!");
178
size_eaten = rdata->pkt_info.len;
181
/* Since this is UDP, the whole buffer is the message. */
182
rdata->pkt_info.len = 0;
184
} else if (bytes_read <= MIN_SIZE) {
188
} else if (-bytes_read != PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK) &&
189
-bytes_read != PJ_STATUS_FROM_OS(OSERR_EINPROGRESS) &&
190
-bytes_read != PJ_STATUS_FROM_OS(OSERR_ECONNRESET))
193
/* Report error to endpoint. */
194
PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt,
195
rdata->tp_info.transport->obj_name,
197
"Warning: pj_ioqueue_recvfrom()"
201
if (i >= MAX_IMMEDIATE_PACKET) {
202
/* Force ioqueue_recvfrom() to return PJ_EPENDING */
203
flags = PJ_IOQUEUE_ALWAYS_ASYNC;
209
* Need to copy rdata fields to temp variable because they will
210
* be invalid after pj_pool_reset().
213
pj_pool_t *rdata_pool = rdata->tp_info.pool;
214
struct udp_transport *rdata_tp ;
215
unsigned rdata_index;
217
rdata_tp = (struct udp_transport*)rdata->tp_info.transport;
218
rdata_index = (unsigned)(unsigned long)rdata->tp_info.tp_data;
220
pj_pool_reset(rdata_pool);
221
init_rdata(rdata_tp, rdata_index, rdata_pool, &rdata);
223
/* Change some vars to point to new location after
226
op_key = &rdata->tp_info.op_key.op_key;
229
/* Only read next packet if transport is not being paused. This
230
* check handles the case where transport is paused while endpoint
231
* is still processing a SIP message.
236
/* Read next packet. */
237
bytes_read = sizeof(rdata->pkt_info.packet);
238
rdata->pkt_info.src_addr_len = sizeof(rdata->pkt_info.src_addr);
239
status = pj_ioqueue_recvfrom(key, op_key,
240
rdata->pkt_info.packet,
242
&rdata->pkt_info.src_addr,
243
&rdata->pkt_info.src_addr_len);
245
if (status == PJ_SUCCESS) {
247
pj_assert(i < MAX_IMMEDIATE_PACKET);
249
} else if (status == PJ_EPENDING) {
254
if (i < MAX_IMMEDIATE_PACKET) {
256
/* Report error to endpoint if this is not EWOULDBLOCK error.*/
257
if (status != PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK) &&
258
status != PJ_STATUS_FROM_OS(OSERR_EINPROGRESS) &&
259
status != PJ_STATUS_FROM_OS(OSERR_ECONNRESET))
262
PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt,
263
rdata->tp_info.transport->obj_name,
265
"Warning: pj_ioqueue_recvfrom"));
271
/* This is fatal error.
272
* Ioqueue operation will stop for this transport!
274
PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt,
275
rdata->tp_info.transport->obj_name,
277
"FATAL: pj_ioqueue_recvfrom() error, "
278
"UDP transport stopping! Error"));
286
* udp_on_write_complete()
288
* This is callback notification from ioqueue that a pending sendto()
289
* operation has completed.
291
static void udp_on_write_complete( pj_ioqueue_key_t *key,
292
pj_ioqueue_op_key_t *op_key,
293
pj_ssize_t bytes_sent)
295
struct udp_transport *tp = (struct udp_transport*)
296
pj_ioqueue_get_user_data(key);
297
pjsip_tx_data_op_key *tdata_op_key = (pjsip_tx_data_op_key*)op_key;
299
tdata_op_key->tdata = NULL;
301
if (tdata_op_key->callback) {
302
tdata_op_key->callback(&tp->base, tdata_op_key->token, bytes_sent);
309
* This function is called by transport manager (by transport->send_msg())
310
* to send outgoing message.
312
static pj_status_t udp_send_msg( pjsip_transport *transport,
313
pjsip_tx_data *tdata,
314
const pj_sockaddr_t *rem_addr,
317
pjsip_transport_callback callback)
319
struct udp_transport *tp = (struct udp_transport*)transport;
323
PJ_ASSERT_RETURN(transport && tdata, PJ_EINVAL);
324
PJ_ASSERT_RETURN(tdata->op_key.tdata == NULL, PJSIP_EPENDINGTX);
326
/* Return error if transport is paused */
328
return PJSIP_ETPNOTAVAIL;
331
tdata->op_key.tdata = tdata;
332
tdata->op_key.token = token;
333
tdata->op_key.callback = callback;
335
/* Send to ioqueue! */
336
size = tdata->buf.cur - tdata->buf.start;
337
status = pj_ioqueue_sendto(tp->key, (pj_ioqueue_op_key_t*)&tdata->op_key,
338
tdata->buf.start, &size, 0,
341
if (status != PJ_EPENDING)
342
tdata->op_key.tdata = NULL;
350
* This function is called by transport manager (by transport->destroy()).
352
static pj_status_t udp_destroy( pjsip_transport *transport )
354
struct udp_transport *tp = (struct udp_transport*)transport;
357
/* Mark this transport as closing. */
360
/* Cancel all pending operations. */
362
* No need to post queued completion as we poll the ioqueue until
363
* we've got events anyway. Posting completion will only cause
364
* callback to be called twice with IOCP: one for the post completion
365
* and another one for closing the socket.
367
for (i=0; i<tp->rdata_cnt; ++i) {
368
pj_ioqueue_post_completion(tp->key,
369
&tp->rdata[i]->tp_info.op_key.op_key, -1);
373
/* Unregister from ioqueue. */
375
pj_ioqueue_unregister(tp->key);
379
if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
380
pj_sock_close(tp->sock);
381
tp->sock = PJ_INVALID_SOCKET;
385
/* Must poll ioqueue because IOCP calls the callback when socket
386
* is closed. We poll the ioqueue until all pending callbacks
389
for (i=0; i<50 && tp->is_closing < 1+tp->rdata_cnt; ++i) {
391
pj_time_val timeout = {0, 1};
393
cnt = pj_ioqueue_poll(pjsip_endpt_get_ioqueue(transport->endpt),
400
for (i=0; i<tp->rdata_cnt; ++i) {
401
pj_pool_release(tp->rdata[i]->tp_info.pool);
404
/* Destroy reference counter. */
405
if (tp->base.ref_cnt)
406
pj_atomic_destroy(tp->base.ref_cnt);
410
pj_lock_destroy(tp->base.lock);
413
pjsip_endpt_release_pool(tp->base.endpt, tp->base.pool);
422
* Start graceful UDP shutdown.
424
static pj_status_t udp_shutdown(pjsip_transport *transport)
426
return pjsip_transport_dec_ref(transport);
431
static pj_status_t create_socket(int af, const pj_sockaddr_t *local_a,
432
int addr_len, pj_sock_t *p_sock)
435
pj_sockaddr_in tmp_addr;
436
pj_sockaddr_in6 tmp_addr6;
439
status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock);
440
if (status != PJ_SUCCESS)
443
if (local_a == NULL) {
444
if (af == pj_AF_INET6()) {
445
pj_bzero(&tmp_addr6, sizeof(tmp_addr6));
446
tmp_addr6.sin6_family = (pj_uint16_t)af;
447
local_a = &tmp_addr6;
448
addr_len = sizeof(tmp_addr6);
450
pj_sockaddr_in_init(&tmp_addr, NULL, 0);
452
addr_len = sizeof(tmp_addr);
456
status = pj_sock_bind(sock, local_a, addr_len);
457
if (status != PJ_SUCCESS) {
467
/* Generate transport's published address */
468
static pj_status_t get_published_name(pj_sock_t sock,
471
pjsip_host_port *bound_name)
473
pj_sockaddr tmp_addr;
477
addr_len = sizeof(tmp_addr);
478
status = pj_sock_getsockname(sock, &tmp_addr, &addr_len);
479
if (status != PJ_SUCCESS)
482
bound_name->host.ptr = hostbuf;
483
if (tmp_addr.addr.sa_family == pj_AF_INET()) {
484
bound_name->port = pj_ntohs(tmp_addr.ipv4.sin_port);
486
/* If bound address specifies "0.0.0.0", get the IP address
489
if (tmp_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) {
492
status = pj_gethostip(pj_AF_INET(), &hostip);
493
if (status != PJ_SUCCESS)
496
pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip.ipv4.sin_addr));
498
/* Otherwise use bound address. */
499
pj_strcpy2(&bound_name->host,
500
pj_inet_ntoa(tmp_addr.ipv4.sin_addr));
505
/* If bound address specifies "INADDR_ANY" (IPv6), get the
506
* IP address of local hostname
508
pj_uint32_t loop6[4] = { 0, 0, 0, 0};
510
bound_name->port = pj_ntohs(tmp_addr.ipv6.sin6_port);
512
if (pj_memcmp(&tmp_addr.ipv6.sin6_addr, loop6, sizeof(loop6))==0) {
513
status = pj_gethostip(tmp_addr.addr.sa_family, &tmp_addr);
514
if (status != PJ_SUCCESS)
518
status = pj_inet_ntop(tmp_addr.addr.sa_family,
519
pj_sockaddr_get_addr(&tmp_addr),
521
if (status == PJ_SUCCESS) {
522
bound_name->host.slen = pj_ansi_strlen(hostbuf);
530
/* Set the published address of the transport */
531
static void udp_set_pub_name(struct udp_transport *tp,
532
const pjsip_host_port *a_name)
534
enum { INFO_LEN = 80 };
535
char local_addr[PJ_INET6_ADDRSTRLEN+10];
537
pj_assert(a_name->host.slen != 0);
538
pj_strdup_with_null(tp->base.pool, &tp->base.local_name.host,
540
tp->base.local_name.port = a_name->port;
542
/* Update transport info. */
543
if (tp->base.info == NULL) {
544
tp->base.info = (char*) pj_pool_alloc(tp->base.pool, INFO_LEN);
547
pj_sockaddr_print(&tp->base.local_addr, local_addr, sizeof(local_addr), 3);
550
tp->base.info, INFO_LEN, "udp %s [published as %s:%d]",
552
tp->base.local_name.host.ptr,
553
tp->base.local_name.port);
556
/* Set the socket handle of the transport */
557
static void udp_set_socket(struct udp_transport *tp,
559
const pjsip_host_port *a_name)
561
#if PJSIP_UDP_SO_RCVBUF_SIZE || PJSIP_UDP_SO_SNDBUF_SIZE
566
/* Adjust socket rcvbuf size */
567
#if PJSIP_UDP_SO_RCVBUF_SIZE
568
sobuf_size = PJSIP_UDP_SO_RCVBUF_SIZE;
569
status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_RCVBUF(),
570
&sobuf_size, sizeof(sobuf_size));
571
if (status != PJ_SUCCESS) {
572
char errmsg[PJ_ERR_MSG_SIZE];
573
pj_strerror(status, errmsg, sizeof(errmsg));
574
PJ_LOG(4,(THIS_FILE, "Error setting SO_RCVBUF: %s [%d]", errmsg,
579
/* Adjust socket sndbuf size */
580
#if PJSIP_UDP_SO_SNDBUF_SIZE
581
sobuf_size = PJSIP_UDP_SO_SNDBUF_SIZE;
582
status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_SNDBUF(),
583
&sobuf_size, sizeof(sobuf_size));
584
if (status != PJ_SUCCESS) {
585
char errmsg[PJ_ERR_MSG_SIZE];
586
pj_strerror(status, errmsg, sizeof(errmsg));
587
PJ_LOG(4,(THIS_FILE, "Error setting SO_SNDBUF: %s [%d]", errmsg,
592
/* Set the socket. */
595
/* Init address name (published address) */
596
udp_set_pub_name(tp, a_name);
599
/* Register socket to ioqueue */
600
static pj_status_t register_to_ioqueue(struct udp_transport *tp)
602
pj_ioqueue_t *ioqueue;
603
pj_ioqueue_callback ioqueue_cb;
605
/* Ignore if already registered */
609
/* Register to ioqueue. */
610
ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt);
611
pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb));
612
ioqueue_cb.on_read_complete = &udp_on_read_complete;
613
ioqueue_cb.on_write_complete = &udp_on_write_complete;
615
return pj_ioqueue_register_sock(tp->base.pool, ioqueue, tp->sock, tp,
616
&ioqueue_cb, &tp->key);
619
/* Start ioqueue asynchronous reading to all rdata */
620
static pj_status_t start_async_read(struct udp_transport *tp)
622
pj_ioqueue_t *ioqueue;
626
ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt);
628
/* Start reading the ioqueue. */
629
for (i=0; i<tp->rdata_cnt; ++i) {
632
size = sizeof(tp->rdata[i]->pkt_info.packet);
633
tp->rdata[i]->pkt_info.src_addr_len = sizeof(tp->rdata[i]->pkt_info.src_addr);
634
status = pj_ioqueue_recvfrom(tp->key,
635
&tp->rdata[i]->tp_info.op_key.op_key,
636
tp->rdata[i]->pkt_info.packet,
637
&size, PJ_IOQUEUE_ALWAYS_ASYNC,
638
&tp->rdata[i]->pkt_info.src_addr,
639
&tp->rdata[i]->pkt_info.src_addr_len);
640
if (status == PJ_SUCCESS) {
641
pj_assert(!"Shouldn't happen because PJ_IOQUEUE_ALWAYS_ASYNC!");
642
udp_on_read_complete(tp->key, &tp->rdata[i]->tp_info.op_key.op_key,
644
} else if (status != PJ_EPENDING) {
655
* pjsip_udp_transport_attach()
657
* Attach UDP socket and start transport.
659
static pj_status_t transport_attach( pjsip_endpoint *endpt,
660
pjsip_transport_type_e type,
662
const pjsip_host_port *a_name,
664
pjsip_transport **p_transport)
667
struct udp_transport *tp;
668
const char *format, *ipv6_quoteb, *ipv6_quotee;
672
PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0,
676
if (type & PJSIP_TRANSPORT_IPV6) {
682
ipv6_quoteb = ipv6_quotee = "";
686
pool = pjsip_endpt_create_pool(endpt, format, PJSIP_POOL_LEN_TRANSPORT,
687
PJSIP_POOL_INC_TRANSPORT);
691
/* Create the UDP transport object. */
692
tp = PJ_POOL_ZALLOC_T(pool, struct udp_transport);
695
tp->base.pool = pool;
697
pj_memcpy(tp->base.obj_name, pool->obj_name, PJ_MAX_OBJ_NAME);
699
/* Init reference counter. */
700
status = pj_atomic_create(pool, 0, &tp->base.ref_cnt);
701
if (status != PJ_SUCCESS)
705
status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
707
if (status != PJ_SUCCESS)
711
tp->base.key.type = type;
713
/* Remote address is left zero (except the family) */
714
tp->base.key.rem_addr.addr.sa_family = (pj_uint16_t)
715
((type & PJSIP_TRANSPORT_IPV6) ? pj_AF_INET6() : pj_AF_INET());
718
tp->base.type_name = "UDP";
721
tp->base.flag = pjsip_transport_get_flag_from_type(type);
724
/* Length of addressess. */
725
tp->base.addr_len = sizeof(tp->base.local_addr);
727
/* Init local address. */
728
status = pj_sock_getsockname(sock, &tp->base.local_addr,
730
if (status != PJ_SUCCESS)
733
/* Init remote name. */
734
if (type == PJSIP_TRANSPORT_UDP)
735
tp->base.remote_name.host = pj_str("0.0.0.0");
737
tp->base.remote_name.host = pj_str("::0");
738
tp->base.remote_name.port = 0;
741
tp->base.dir = PJSIP_TP_DIR_NONE;
744
tp->base.endpt = endpt;
746
/* Transport manager and timer will be initialized by tpmgr */
748
/* Attach socket and assign name. */
749
udp_set_socket(tp, sock, a_name);
751
/* Register to ioqueue */
752
status = register_to_ioqueue(tp);
753
if (status != PJ_SUCCESS)
757
tp->base.send_msg = &udp_send_msg;
758
tp->base.do_shutdown = &udp_shutdown;
759
tp->base.destroy = &udp_destroy;
761
/* This is a permanent transport, so we initialize the ref count
762
* to one so that transport manager don't destroy this transport
763
* when there's no user!
765
pj_atomic_inc(tp->base.ref_cnt);
767
/* Register to transport manager. */
768
tp->base.tpmgr = pjsip_endpt_get_tpmgr(endpt);
769
status = pjsip_transport_register( tp->base.tpmgr, (pjsip_transport*)tp);
770
if (status != PJ_SUCCESS)
774
/* Create rdata and put it in the array. */
776
tp->rdata = (pjsip_rx_data**)
777
pj_pool_calloc(tp->base.pool, async_cnt,
778
sizeof(pjsip_rx_data*));
779
for (i=0; i<async_cnt; ++i) {
780
pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p",
781
PJSIP_POOL_RDATA_LEN,
782
PJSIP_POOL_RDATA_INC);
784
pj_atomic_set(tp->base.ref_cnt, 0);
785
pjsip_transport_destroy(&tp->base);
789
init_rdata(tp, i, rdata_pool, NULL);
793
/* Start reading the ioqueue. */
794
status = start_async_read(tp);
795
if (status != PJ_SUCCESS) {
796
pjsip_transport_destroy(&tp->base);
802
*p_transport = &tp->base;
804
PJ_LOG(4,(tp->base.obj_name,
805
"SIP %s started, published address is %s%.*s%s:%d",
806
pjsip_transport_get_type_desc((pjsip_transport_type_e)tp->base.key.type),
808
(int)tp->base.local_name.host.slen,
809
tp->base.local_name.host.ptr,
811
tp->base.local_name.port));
816
udp_destroy((pjsip_transport*)tp);
821
PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
823
const pjsip_host_port *a_name,
825
pjsip_transport **p_transport)
827
return transport_attach(endpt, PJSIP_TRANSPORT_UDP, sock, a_name,
828
async_cnt, p_transport);
831
PJ_DEF(pj_status_t) pjsip_udp_transport_attach2( pjsip_endpoint *endpt,
832
pjsip_transport_type_e type,
834
const pjsip_host_port *a_name,
836
pjsip_transport **p_transport)
838
return transport_attach(endpt, type, sock, a_name,
839
async_cnt, p_transport);
843
* pjsip_udp_transport_start()
845
* Create a UDP socket in the specified address and start a transport.
847
PJ_DEF(pj_status_t) pjsip_udp_transport_start( pjsip_endpoint *endpt,
848
const pj_sockaddr_in *local_a,
849
const pjsip_host_port *a_name,
851
pjsip_transport **p_transport)
855
char addr_buf[PJ_INET6_ADDRSTRLEN];
856
pjsip_host_port bound_name;
858
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
860
status = create_socket(pj_AF_INET(), local_a, sizeof(pj_sockaddr_in),
862
if (status != PJ_SUCCESS)
865
if (a_name == NULL) {
866
/* Address name is not specified.
867
* Build a name based on bound address.
869
status = get_published_name(sock, addr_buf, sizeof(addr_buf),
871
if (status != PJ_SUCCESS) {
876
a_name = &bound_name;
879
return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt,
885
* pjsip_udp_transport_start()
887
* Create a UDP socket in the specified address and start a transport.
889
PJ_DEF(pj_status_t) pjsip_udp_transport_start6(pjsip_endpoint *endpt,
890
const pj_sockaddr_in6 *local_a,
891
const pjsip_host_port *a_name,
893
pjsip_transport **p_transport)
897
char addr_buf[PJ_INET6_ADDRSTRLEN];
898
pjsip_host_port bound_name;
900
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
902
status = create_socket(pj_AF_INET6(), local_a, sizeof(pj_sockaddr_in6),
904
if (status != PJ_SUCCESS)
907
if (a_name == NULL) {
908
/* Address name is not specified.
909
* Build a name based on bound address.
911
status = get_published_name(sock, addr_buf, sizeof(addr_buf),
913
if (status != PJ_SUCCESS) {
918
a_name = &bound_name;
921
return pjsip_udp_transport_attach2(endpt, PJSIP_TRANSPORT_UDP6,
922
sock, a_name, async_cnt, p_transport);
926
* Retrieve the internal socket handle used by the UDP transport.
928
PJ_DEF(pj_sock_t) pjsip_udp_transport_get_socket(pjsip_transport *transport)
930
struct udp_transport *tp;
932
PJ_ASSERT_RETURN(transport != NULL, PJ_INVALID_SOCKET);
934
tp = (struct udp_transport*) transport;
941
* Temporarily pause or shutdown the transport.
943
PJ_DEF(pj_status_t) pjsip_udp_transport_pause(pjsip_transport *transport,
946
struct udp_transport *tp;
949
PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL);
951
/* Flag must be specified */
952
PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL);
954
tp = (struct udp_transport*) transport;
956
/* Transport must not have been paused */
957
PJ_ASSERT_RETURN(tp->is_paused==0, PJ_EINVALIDOP);
959
/* Set transport to paused first, so that when the read callback is
960
* called by pj_ioqueue_post_completion() it will not try to
961
* re-register the rdata.
963
tp->is_paused = PJ_TRUE;
965
/* Cancel the ioqueue operation. */
966
for (i=0; i<(unsigned)tp->rdata_cnt; ++i) {
967
pj_ioqueue_post_completion(tp->key,
968
&tp->rdata[i]->tp_info.op_key.op_key, -1);
971
/* Destroy the socket? */
972
if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
974
/* This implicitly closes the socket */
975
pj_ioqueue_unregister(tp->key);
979
if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
980
pj_sock_close(tp->sock);
981
tp->sock = PJ_INVALID_SOCKET;
984
tp->sock = PJ_INVALID_SOCKET;
988
PJ_LOG(4,(tp->base.obj_name, "SIP UDP transport paused"));
997
* If option is KEEP_SOCKET, just re-activate ioqueue operation.
999
* If option is DESTROY_SOCKET:
1000
* - if socket is specified, replace.
1001
* - if socket is not specified, create and replace.
1003
PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
1006
const pj_sockaddr_in *local,
1007
const pjsip_host_port *a_name)
1009
struct udp_transport *tp;
1012
PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL);
1013
/* Flag must be specified */
1014
PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL);
1016
tp = (struct udp_transport*) transport;
1018
if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
1019
char addr_buf[PJ_INET6_ADDRSTRLEN];
1020
pjsip_host_port bound_name;
1022
/* Request to recreate transport */
1024
/* Destroy existing socket, if any. */
1026
/* This implicitly closes the socket */
1027
pj_ioqueue_unregister(tp->key);
1031
if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
1032
pj_sock_close(tp->sock);
1033
tp->sock = PJ_INVALID_SOCKET;
1036
tp->sock = PJ_INVALID_SOCKET;
1038
/* Create the socket if it's not specified */
1039
if (sock == PJ_INVALID_SOCKET) {
1040
status = create_socket(pj_AF_INET(), local,
1041
sizeof(pj_sockaddr_in), &sock);
1042
if (status != PJ_SUCCESS)
1046
/* If transport published name is not specified, calculate it
1047
* from the bound address.
1049
if (a_name == NULL) {
1050
status = get_published_name(sock, addr_buf, sizeof(addr_buf),
1052
if (status != PJ_SUCCESS) {
1053
pj_sock_close(sock);
1057
a_name = &bound_name;
1060
/* Assign the socket and published address to transport. */
1061
udp_set_socket(tp, sock, a_name);
1065
/* For KEEP_SOCKET, transport must have been paused before */
1066
PJ_ASSERT_RETURN(tp->is_paused, PJ_EINVALIDOP);
1068
/* If address name is specified, update it */
1070
udp_set_pub_name(tp, a_name);
1073
/* Re-register new or existing socket to ioqueue. */
1074
status = register_to_ioqueue(tp);
1075
if (status != PJ_SUCCESS) {
1079
/* Restart async read operation. */
1080
status = start_async_read(tp);
1081
if (status != PJ_SUCCESS)
1084
/* Everything has been set up */
1085
tp->is_paused = PJ_FALSE;
1087
PJ_LOG(4,(tp->base.obj_name,
1088
"SIP UDP transport restarted, published address is %.*s:%d",
1089
(int)tp->base.local_name.host.slen,
1090
tp->base.local_name.host.ptr,
1091
tp->base.local_name.port));