~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip/src/pjsip/sip_transport_udp.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: sip_transport_udp.c 3553 2011-05-05 06:14:19Z nanang $ */
 
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_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>
 
25
#include <pj/lock.h>
 
26
#include <pj/log.h>
 
27
#include <pj/os.h>
 
28
#include <pj/pool.h>
 
29
#include <pj/sock.h>
 
30
#include <pj/compat/socket.h>
 
31
#include <pj/string.h>
 
32
 
 
33
 
 
34
#define THIS_FILE   "sip_transport_udp.c"
 
35
 
 
36
/**
 
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.
 
41
 *
 
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.
 
45
 * 
 
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).
 
50
 *
 
51
 * More experiments are needed probably.
 
52
 */
 
53
/* 2010/01/14
 
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
 
57
 */
 
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
 
61
#endif
 
62
 
 
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
 
66
#endif
 
67
 
 
68
 
 
69
/* Struct udp_transport "inherits" struct pjsip_transport */
 
70
struct udp_transport
 
71
{
 
72
    pjsip_transport     base;
 
73
    pj_sock_t           sock;
 
74
    pj_ioqueue_key_t   *key;
 
75
    int                 rdata_cnt;
 
76
    pjsip_rx_data     **rdata;
 
77
    int                 is_closing;
 
78
    pj_bool_t           is_paused;
 
79
};
 
80
 
 
81
 
 
82
/*
 
83
 * Initialize transport's receive buffer from the specified pool.
 
84
 */
 
85
static void init_rdata(struct udp_transport *tp, unsigned rdata_index,
 
86
                       pj_pool_t *pool, pjsip_rx_data **p_rdata)
 
87
{
 
88
    pjsip_rx_data *rdata;
 
89
 
 
90
    /* Reset pool. */
 
91
    //note: already done by caller
 
92
    //pj_pool_reset(pool);
 
93
 
 
94
    rdata = PJ_POOL_ZALLOC_T(pool, pjsip_rx_data);
 
95
 
 
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));
 
103
 
 
104
    tp->rdata[rdata_index] = rdata;
 
105
 
 
106
    if (p_rdata)
 
107
        *p_rdata = rdata;
 
108
}
 
109
 
 
110
 
 
111
/*
 
112
 * udp_on_read_complete()
 
113
 *
 
114
 * This is callback notification from ioqueue that a pending recvfrom()
 
115
 * operation has completed.
 
116
 */
 
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)
 
120
{
 
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;
 
126
    int i;
 
127
    pj_status_t status;
 
128
 
 
129
    /* Don't do anything if transport is closing. */
 
130
    if (tp->is_closing) {
 
131
        tp->is_closing++;
 
132
        return;
 
133
    }
 
134
 
 
135
    /* Don't do anything if transport is being paused. */
 
136
    if (tp->is_paused)
 
137
        return;
 
138
 
 
139
    /*
 
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.
 
144
     */
 
145
    for (i=0;; ++i) {
 
146
        enum { MIN_SIZE = 32 };
 
147
        pj_uint32_t flags;
 
148
 
 
149
        /* Report the packet to transport manager. Only do so if packet size
 
150
         * is relatively big enough for a SIP packet.
 
151
         */
 
152
        if (bytes_read > MIN_SIZE) {
 
153
            pj_size_t size_eaten;
 
154
            const pj_sockaddr *src_addr = &rdata->pkt_info.src_addr;
 
155
 
 
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);
 
164
            } else {
 
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);
 
170
            }
 
171
 
 
172
            size_eaten = 
 
173
                pjsip_tpmgr_receive_packet(rdata->tp_info.transport->tpmgr, 
 
174
                                           rdata);
 
175
 
 
176
            if (size_eaten < 0) {
 
177
                pj_assert(!"It shouldn't happen!");
 
178
                size_eaten = rdata->pkt_info.len;
 
179
            }
 
180
 
 
181
            /* Since this is UDP, the whole buffer is the message. */
 
182
            rdata->pkt_info.len = 0;
 
183
 
 
184
        } else if (bytes_read <= MIN_SIZE) {
 
185
 
 
186
            /* TODO: */
 
187
 
 
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)) 
 
191
        {
 
192
 
 
193
            /* Report error to endpoint. */
 
194
            PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt,
 
195
                                   rdata->tp_info.transport->obj_name,
 
196
                                   -bytes_read, 
 
197
                                   "Warning: pj_ioqueue_recvfrom()"
 
198
                                   " callback error"));
 
199
        }
 
200
 
 
201
        if (i >= MAX_IMMEDIATE_PACKET) {
 
202
            /* Force ioqueue_recvfrom() to return PJ_EPENDING */
 
203
            flags = PJ_IOQUEUE_ALWAYS_ASYNC;
 
204
        } else {
 
205
            flags = 0;
 
206
        }
 
207
 
 
208
        /* Reset pool. 
 
209
         * Need to copy rdata fields to temp variable because they will
 
210
         * be invalid after pj_pool_reset().
 
211
         */
 
212
        {
 
213
            pj_pool_t *rdata_pool = rdata->tp_info.pool;
 
214
            struct udp_transport *rdata_tp ;
 
215
            unsigned rdata_index;
 
216
 
 
217
            rdata_tp = (struct udp_transport*)rdata->tp_info.transport;
 
218
            rdata_index = (unsigned)(unsigned long)rdata->tp_info.tp_data;
 
219
 
 
220
            pj_pool_reset(rdata_pool);
 
221
            init_rdata(rdata_tp, rdata_index, rdata_pool, &rdata);
 
222
 
 
223
            /* Change some vars to point to new location after
 
224
             * pool reset.
 
225
             */
 
226
            op_key = &rdata->tp_info.op_key.op_key;
 
227
        }
 
228
 
 
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.
 
232
         */
 
233
        if (tp->is_paused)
 
234
            return;
 
235
 
 
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,
 
241
                                     &bytes_read, flags,
 
242
                                     &rdata->pkt_info.src_addr, 
 
243
                                     &rdata->pkt_info.src_addr_len);
 
244
 
 
245
        if (status == PJ_SUCCESS) {
 
246
            /* Continue loop. */
 
247
            pj_assert(i < MAX_IMMEDIATE_PACKET);
 
248
 
 
249
        } else if (status == PJ_EPENDING) {
 
250
            break;
 
251
 
 
252
        } else {
 
253
 
 
254
            if (i < MAX_IMMEDIATE_PACKET) {
 
255
 
 
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)) 
 
260
                {
 
261
 
 
262
                    PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt,
 
263
                                           rdata->tp_info.transport->obj_name,
 
264
                                           status, 
 
265
                                           "Warning: pj_ioqueue_recvfrom"));
 
266
                }
 
267
 
 
268
                /* Continue loop. */
 
269
                bytes_read = 0;
 
270
            } else {
 
271
                /* This is fatal error.
 
272
                 * Ioqueue operation will stop for this transport!
 
273
                 */
 
274
                PJSIP_ENDPT_LOG_ERROR((rdata->tp_info.transport->endpt,
 
275
                                       rdata->tp_info.transport->obj_name,
 
276
                                       status, 
 
277
                                       "FATAL: pj_ioqueue_recvfrom() error, "
 
278
                                       "UDP transport stopping! Error"));
 
279
                break;
 
280
            }
 
281
        }
 
282
    }
 
283
}
 
284
 
 
285
/*
 
286
 * udp_on_write_complete()
 
287
 *
 
288
 * This is callback notification from ioqueue that a pending sendto()
 
289
 * operation has completed.
 
290
 */
 
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)
 
294
{
 
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;
 
298
 
 
299
    tdata_op_key->tdata = NULL;
 
300
 
 
301
    if (tdata_op_key->callback) {
 
302
        tdata_op_key->callback(&tp->base, tdata_op_key->token, bytes_sent);
 
303
    }
 
304
}
 
305
 
 
306
/*
 
307
 * udp_send_msg()
 
308
 *
 
309
 * This function is called by transport manager (by transport->send_msg())
 
310
 * to send outgoing message.
 
311
 */
 
312
static pj_status_t udp_send_msg( pjsip_transport *transport,
 
313
                                 pjsip_tx_data *tdata,
 
314
                                 const pj_sockaddr_t *rem_addr,
 
315
                                 int addr_len,
 
316
                                 void *token,
 
317
                                 pjsip_transport_callback callback)
 
318
{
 
319
    struct udp_transport *tp = (struct udp_transport*)transport;
 
320
    pj_ssize_t size;
 
321
    pj_status_t status;
 
322
 
 
323
    PJ_ASSERT_RETURN(transport && tdata, PJ_EINVAL);
 
324
    PJ_ASSERT_RETURN(tdata->op_key.tdata == NULL, PJSIP_EPENDINGTX);
 
325
    
 
326
    /* Return error if transport is paused */
 
327
    if (tp->is_paused)
 
328
        return PJSIP_ETPNOTAVAIL;
 
329
 
 
330
    /* Init op key. */
 
331
    tdata->op_key.tdata = tdata;
 
332
    tdata->op_key.token = token;
 
333
    tdata->op_key.callback = callback;
 
334
 
 
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,
 
339
                               rem_addr, addr_len);
 
340
 
 
341
    if (status != PJ_EPENDING)
 
342
        tdata->op_key.tdata = NULL;
 
343
 
 
344
    return status;
 
345
}
 
346
 
 
347
/*
 
348
 * udp_destroy()
 
349
 *
 
350
 * This function is called by transport manager (by transport->destroy()).
 
351
 */
 
352
static pj_status_t udp_destroy( pjsip_transport *transport )
 
353
{
 
354
    struct udp_transport *tp = (struct udp_transport*)transport;
 
355
    int i;
 
356
 
 
357
    /* Mark this transport as closing. */
 
358
    tp->is_closing = 1;
 
359
 
 
360
    /* Cancel all pending operations. */
 
361
    /* blp: NO NO NO...
 
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.
 
366
     *
 
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);
 
370
    }
 
371
    */
 
372
 
 
373
    /* Unregister from ioqueue. */
 
374
    if (tp->key) {
 
375
        pj_ioqueue_unregister(tp->key);
 
376
        tp->key = NULL;
 
377
    } else {
 
378
        /* Close socket. */
 
379
        if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
 
380
            pj_sock_close(tp->sock);
 
381
            tp->sock = PJ_INVALID_SOCKET;
 
382
        }
 
383
    }
 
384
 
 
385
    /* Must poll ioqueue because IOCP calls the callback when socket
 
386
     * is closed. We poll the ioqueue until all pending callbacks 
 
387
     * have been called.
 
388
     */
 
389
    for (i=0; i<50 && tp->is_closing < 1+tp->rdata_cnt; ++i) {
 
390
        int cnt;
 
391
        pj_time_val timeout = {0, 1};
 
392
 
 
393
        cnt = pj_ioqueue_poll(pjsip_endpt_get_ioqueue(transport->endpt), 
 
394
                              &timeout);
 
395
        if (cnt == 0)
 
396
            break;
 
397
    }
 
398
 
 
399
    /* Destroy rdata */
 
400
    for (i=0; i<tp->rdata_cnt; ++i) {
 
401
        pj_pool_release(tp->rdata[i]->tp_info.pool);
 
402
    }
 
403
 
 
404
    /* Destroy reference counter. */
 
405
    if (tp->base.ref_cnt)
 
406
        pj_atomic_destroy(tp->base.ref_cnt);
 
407
 
 
408
    /* Destroy lock */
 
409
    if (tp->base.lock)
 
410
        pj_lock_destroy(tp->base.lock);
 
411
 
 
412
    /* Destroy pool. */
 
413
    pjsip_endpt_release_pool(tp->base.endpt, tp->base.pool);
 
414
 
 
415
    return PJ_SUCCESS;
 
416
}
 
417
 
 
418
 
 
419
/*
 
420
 * udp_shutdown()
 
421
 *
 
422
 * Start graceful UDP shutdown.
 
423
 */
 
424
static pj_status_t udp_shutdown(pjsip_transport *transport)
 
425
{
 
426
    return pjsip_transport_dec_ref(transport);
 
427
}
 
428
 
 
429
 
 
430
/* Create socket */
 
431
static pj_status_t create_socket(int af, const pj_sockaddr_t *local_a,
 
432
                                 int addr_len, pj_sock_t *p_sock)
 
433
{
 
434
    pj_sock_t sock;
 
435
    pj_sockaddr_in tmp_addr;
 
436
    pj_sockaddr_in6 tmp_addr6;
 
437
    pj_status_t status;
 
438
 
 
439
    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock);
 
440
    if (status != PJ_SUCCESS)
 
441
        return status;
 
442
 
 
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);
 
449
        } else {
 
450
            pj_sockaddr_in_init(&tmp_addr, NULL, 0);
 
451
            local_a = &tmp_addr;
 
452
            addr_len = sizeof(tmp_addr);
 
453
        }
 
454
    }
 
455
 
 
456
    status = pj_sock_bind(sock, local_a, addr_len);
 
457
    if (status != PJ_SUCCESS) {
 
458
        pj_sock_close(sock);
 
459
        return status;
 
460
    }
 
461
 
 
462
    *p_sock = sock;
 
463
    return PJ_SUCCESS;
 
464
}
 
465
 
 
466
 
 
467
/* Generate transport's published address */
 
468
static pj_status_t get_published_name(pj_sock_t sock,
 
469
                                      char hostbuf[],
 
470
                                      int hostbufsz,
 
471
                                      pjsip_host_port *bound_name)
 
472
{
 
473
    pj_sockaddr tmp_addr;
 
474
    int addr_len;
 
475
    pj_status_t status;
 
476
 
 
477
    addr_len = sizeof(tmp_addr);
 
478
    status = pj_sock_getsockname(sock, &tmp_addr, &addr_len);
 
479
    if (status != PJ_SUCCESS)
 
480
        return status;
 
481
 
 
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);
 
485
 
 
486
        /* If bound address specifies "0.0.0.0", get the IP address
 
487
         * of local hostname.
 
488
         */
 
489
        if (tmp_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) {
 
490
            pj_sockaddr hostip;
 
491
 
 
492
            status = pj_gethostip(pj_AF_INET(), &hostip);
 
493
            if (status != PJ_SUCCESS)
 
494
                return status;
 
495
 
 
496
            pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip.ipv4.sin_addr));
 
497
        } else {
 
498
            /* Otherwise use bound address. */
 
499
            pj_strcpy2(&bound_name->host, 
 
500
                       pj_inet_ntoa(tmp_addr.ipv4.sin_addr));
 
501
            status = PJ_SUCCESS;
 
502
        }
 
503
 
 
504
    } else {
 
505
        /* If bound address specifies "INADDR_ANY" (IPv6), get the
 
506
         * IP address of local hostname
 
507
         */
 
508
        pj_uint32_t loop6[4] = { 0, 0, 0, 0};
 
509
 
 
510
        bound_name->port = pj_ntohs(tmp_addr.ipv6.sin6_port);
 
511
 
 
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)
 
515
                return status;
 
516
        }
 
517
 
 
518
        status = pj_inet_ntop(tmp_addr.addr.sa_family, 
 
519
                              pj_sockaddr_get_addr(&tmp_addr),
 
520
                              hostbuf, hostbufsz);
 
521
        if (status == PJ_SUCCESS) {
 
522
            bound_name->host.slen = pj_ansi_strlen(hostbuf);
 
523
        }
 
524
    }
 
525
 
 
526
 
 
527
    return status;
 
528
}
 
529
 
 
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)
 
533
{
 
534
    enum { INFO_LEN = 80 };
 
535
    char local_addr[PJ_INET6_ADDRSTRLEN+10];
 
536
 
 
537
    pj_assert(a_name->host.slen != 0);
 
538
    pj_strdup_with_null(tp->base.pool, &tp->base.local_name.host, 
 
539
                        &a_name->host);
 
540
    tp->base.local_name.port = a_name->port;
 
541
 
 
542
    /* Update transport info. */
 
543
    if (tp->base.info == NULL) {
 
544
        tp->base.info = (char*) pj_pool_alloc(tp->base.pool, INFO_LEN);
 
545
    }
 
546
 
 
547
    pj_sockaddr_print(&tp->base.local_addr, local_addr, sizeof(local_addr), 3);
 
548
 
 
549
    pj_ansi_snprintf( 
 
550
        tp->base.info, INFO_LEN, "udp %s [published as %s:%d]",
 
551
        local_addr,
 
552
        tp->base.local_name.host.ptr,
 
553
        tp->base.local_name.port);
 
554
}
 
555
 
 
556
/* Set the socket handle of the transport */
 
557
static void udp_set_socket(struct udp_transport *tp,
 
558
                           pj_sock_t sock,
 
559
                           const pjsip_host_port *a_name)
 
560
{
 
561
#if PJSIP_UDP_SO_RCVBUF_SIZE || PJSIP_UDP_SO_SNDBUF_SIZE
 
562
    long sobuf_size;
 
563
    pj_status_t status;
 
564
#endif
 
565
 
 
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,
 
575
                  status));
 
576
    }
 
577
#endif
 
578
 
 
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,
 
588
                  status));
 
589
    }
 
590
#endif
 
591
 
 
592
    /* Set the socket. */
 
593
    tp->sock = sock;
 
594
 
 
595
    /* Init address name (published address) */
 
596
    udp_set_pub_name(tp, a_name);
 
597
}
 
598
 
 
599
/* Register socket to ioqueue */
 
600
static pj_status_t register_to_ioqueue(struct udp_transport *tp)
 
601
{
 
602
    pj_ioqueue_t *ioqueue;
 
603
    pj_ioqueue_callback ioqueue_cb;
 
604
 
 
605
    /* Ignore if already registered */
 
606
    if (tp->key != NULL)
 
607
        return PJ_SUCCESS;
 
608
    
 
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;
 
614
 
 
615
    return pj_ioqueue_register_sock(tp->base.pool, ioqueue, tp->sock, tp,
 
616
                                    &ioqueue_cb, &tp->key);
 
617
}
 
618
 
 
619
/* Start ioqueue asynchronous reading to all rdata */
 
620
static pj_status_t start_async_read(struct udp_transport *tp)
 
621
{
 
622
    pj_ioqueue_t *ioqueue;
 
623
    int i;
 
624
    pj_status_t status;
 
625
 
 
626
    ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt);
 
627
 
 
628
    /* Start reading the ioqueue. */
 
629
    for (i=0; i<tp->rdata_cnt; ++i) {
 
630
        pj_ssize_t size;
 
631
 
 
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,
 
643
                                 size);
 
644
        } else if (status != PJ_EPENDING) {
 
645
            /* Error! */
 
646
            return status;
 
647
        }
 
648
    }
 
649
 
 
650
    return PJ_SUCCESS;
 
651
}
 
652
 
 
653
 
 
654
/*
 
655
 * pjsip_udp_transport_attach()
 
656
 *
 
657
 * Attach UDP socket and start transport.
 
658
 */
 
659
static pj_status_t transport_attach( pjsip_endpoint *endpt,
 
660
                                     pjsip_transport_type_e type,
 
661
                                     pj_sock_t sock,
 
662
                                     const pjsip_host_port *a_name,
 
663
                                     unsigned async_cnt,
 
664
                                     pjsip_transport **p_transport)
 
665
{
 
666
    pj_pool_t *pool;
 
667
    struct udp_transport *tp;
 
668
    const char *format, *ipv6_quoteb, *ipv6_quotee;
 
669
    unsigned i;
 
670
    pj_status_t status;
 
671
 
 
672
    PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0,
 
673
                     PJ_EINVAL);
 
674
 
 
675
    /* Object name. */
 
676
    if (type & PJSIP_TRANSPORT_IPV6) {
 
677
        format = "udpv6%p";
 
678
        ipv6_quoteb = "[";
 
679
        ipv6_quotee = "]";
 
680
    } else {
 
681
        format = "udp%p";
 
682
        ipv6_quoteb = ipv6_quotee = "";
 
683
    }
 
684
 
 
685
    /* Create pool. */
 
686
    pool = pjsip_endpt_create_pool(endpt, format, PJSIP_POOL_LEN_TRANSPORT, 
 
687
                                   PJSIP_POOL_INC_TRANSPORT);
 
688
    if (!pool)
 
689
        return PJ_ENOMEM;
 
690
 
 
691
    /* Create the UDP transport object. */
 
692
    tp = PJ_POOL_ZALLOC_T(pool, struct udp_transport);
 
693
 
 
694
    /* Save pool. */
 
695
    tp->base.pool = pool;
 
696
 
 
697
    pj_memcpy(tp->base.obj_name, pool->obj_name, PJ_MAX_OBJ_NAME);
 
698
 
 
699
    /* Init reference counter. */
 
700
    status = pj_atomic_create(pool, 0, &tp->base.ref_cnt);
 
701
    if (status != PJ_SUCCESS)
 
702
        goto on_error;
 
703
 
 
704
    /* Init lock. */
 
705
    status = pj_lock_create_recursive_mutex(pool, pool->obj_name, 
 
706
                                            &tp->base.lock);
 
707
    if (status != PJ_SUCCESS)
 
708
        goto on_error;
 
709
 
 
710
    /* Set type. */
 
711
    tp->base.key.type = type;
 
712
 
 
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());
 
716
 
 
717
    /* Type name. */
 
718
    tp->base.type_name = "UDP";
 
719
 
 
720
    /* Transport flag */
 
721
    tp->base.flag = pjsip_transport_get_flag_from_type(type);
 
722
 
 
723
 
 
724
    /* Length of addressess. */
 
725
    tp->base.addr_len = sizeof(tp->base.local_addr);
 
726
 
 
727
    /* Init local address. */
 
728
    status = pj_sock_getsockname(sock, &tp->base.local_addr, 
 
729
                                 &tp->base.addr_len);
 
730
    if (status != PJ_SUCCESS)
 
731
        goto on_error;
 
732
 
 
733
    /* Init remote name. */
 
734
    if (type == PJSIP_TRANSPORT_UDP)
 
735
        tp->base.remote_name.host = pj_str("0.0.0.0");
 
736
    else
 
737
        tp->base.remote_name.host = pj_str("::0");
 
738
    tp->base.remote_name.port = 0;
 
739
 
 
740
    /* Init direction */
 
741
    tp->base.dir = PJSIP_TP_DIR_NONE;
 
742
 
 
743
    /* Set endpoint. */
 
744
    tp->base.endpt = endpt;
 
745
 
 
746
    /* Transport manager and timer will be initialized by tpmgr */
 
747
 
 
748
    /* Attach socket and assign name. */
 
749
    udp_set_socket(tp, sock, a_name);
 
750
 
 
751
    /* Register to ioqueue */
 
752
    status = register_to_ioqueue(tp);
 
753
    if (status != PJ_SUCCESS)
 
754
        goto on_error;
 
755
 
 
756
    /* Set functions. */
 
757
    tp->base.send_msg = &udp_send_msg;
 
758
    tp->base.do_shutdown = &udp_shutdown;
 
759
    tp->base.destroy = &udp_destroy;
 
760
 
 
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!
 
764
     */
 
765
    pj_atomic_inc(tp->base.ref_cnt);
 
766
 
 
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)
 
771
        goto on_error;
 
772
 
 
773
 
 
774
    /* Create rdata and put it in the array. */
 
775
    tp->rdata_cnt = 0;
 
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);
 
783
        if (!rdata_pool) {
 
784
            pj_atomic_set(tp->base.ref_cnt, 0);
 
785
            pjsip_transport_destroy(&tp->base);
 
786
            return PJ_ENOMEM;
 
787
        }
 
788
 
 
789
        init_rdata(tp, i, rdata_pool, NULL);
 
790
        tp->rdata_cnt++;
 
791
    }
 
792
 
 
793
    /* Start reading the ioqueue. */
 
794
    status = start_async_read(tp);
 
795
    if (status != PJ_SUCCESS) {
 
796
        pjsip_transport_destroy(&tp->base);
 
797
        return status;
 
798
    }
 
799
 
 
800
    /* Done. */
 
801
    if (p_transport)
 
802
        *p_transport = &tp->base;
 
803
    
 
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),
 
807
              ipv6_quoteb,
 
808
              (int)tp->base.local_name.host.slen,
 
809
              tp->base.local_name.host.ptr,
 
810
              ipv6_quotee,
 
811
              tp->base.local_name.port));
 
812
 
 
813
    return PJ_SUCCESS;
 
814
 
 
815
on_error:
 
816
    udp_destroy((pjsip_transport*)tp);
 
817
    return status;
 
818
}
 
819
 
 
820
 
 
821
PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
 
822
                                                pj_sock_t sock,
 
823
                                                const pjsip_host_port *a_name,
 
824
                                                unsigned async_cnt,
 
825
                                                pjsip_transport **p_transport)
 
826
{
 
827
    return transport_attach(endpt, PJSIP_TRANSPORT_UDP, sock, a_name,
 
828
                            async_cnt, p_transport);
 
829
}
 
830
 
 
831
PJ_DEF(pj_status_t) pjsip_udp_transport_attach2( pjsip_endpoint *endpt,
 
832
                                                 pjsip_transport_type_e type,
 
833
                                                 pj_sock_t sock,
 
834
                                                 const pjsip_host_port *a_name,
 
835
                                                 unsigned async_cnt,
 
836
                                                 pjsip_transport **p_transport)
 
837
{
 
838
    return transport_attach(endpt, type, sock, a_name,
 
839
                            async_cnt, p_transport);
 
840
}
 
841
 
 
842
/*
 
843
 * pjsip_udp_transport_start()
 
844
 *
 
845
 * Create a UDP socket in the specified address and start a transport.
 
846
 */
 
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,
 
850
                                               unsigned async_cnt,
 
851
                                               pjsip_transport **p_transport)
 
852
{
 
853
    pj_sock_t sock;
 
854
    pj_status_t status;
 
855
    char addr_buf[PJ_INET6_ADDRSTRLEN];
 
856
    pjsip_host_port bound_name;
 
857
 
 
858
    PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
 
859
 
 
860
    status = create_socket(pj_AF_INET(), local_a, sizeof(pj_sockaddr_in), 
 
861
                           &sock);
 
862
    if (status != PJ_SUCCESS)
 
863
        return status;
 
864
 
 
865
    if (a_name == NULL) {
 
866
        /* Address name is not specified. 
 
867
         * Build a name based on bound address.
 
868
         */
 
869
        status = get_published_name(sock, addr_buf, sizeof(addr_buf), 
 
870
                                    &bound_name);
 
871
        if (status != PJ_SUCCESS) {
 
872
            pj_sock_close(sock);
 
873
            return status;
 
874
        }
 
875
 
 
876
        a_name = &bound_name;
 
877
    }
 
878
 
 
879
    return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt, 
 
880
                                       p_transport );
 
881
}
 
882
 
 
883
 
 
884
/*
 
885
 * pjsip_udp_transport_start()
 
886
 *
 
887
 * Create a UDP socket in the specified address and start a transport.
 
888
 */
 
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,
 
892
                                               unsigned async_cnt,
 
893
                                               pjsip_transport **p_transport)
 
894
{
 
895
    pj_sock_t sock;
 
896
    pj_status_t status;
 
897
    char addr_buf[PJ_INET6_ADDRSTRLEN];
 
898
    pjsip_host_port bound_name;
 
899
 
 
900
    PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
 
901
 
 
902
    status = create_socket(pj_AF_INET6(), local_a, sizeof(pj_sockaddr_in6), 
 
903
                           &sock);
 
904
    if (status != PJ_SUCCESS)
 
905
        return status;
 
906
 
 
907
    if (a_name == NULL) {
 
908
        /* Address name is not specified. 
 
909
         * Build a name based on bound address.
 
910
         */
 
911
        status = get_published_name(sock, addr_buf, sizeof(addr_buf), 
 
912
                                    &bound_name);
 
913
        if (status != PJ_SUCCESS) {
 
914
            pj_sock_close(sock);
 
915
            return status;
 
916
        }
 
917
 
 
918
        a_name = &bound_name;
 
919
    }
 
920
 
 
921
    return pjsip_udp_transport_attach2(endpt, PJSIP_TRANSPORT_UDP6,
 
922
                                       sock, a_name, async_cnt, p_transport);
 
923
}
 
924
 
 
925
/*
 
926
 * Retrieve the internal socket handle used by the UDP transport.
 
927
 */
 
928
PJ_DEF(pj_sock_t) pjsip_udp_transport_get_socket(pjsip_transport *transport)
 
929
{
 
930
    struct udp_transport *tp;
 
931
 
 
932
    PJ_ASSERT_RETURN(transport != NULL, PJ_INVALID_SOCKET);
 
933
 
 
934
    tp = (struct udp_transport*) transport;
 
935
 
 
936
    return tp->sock;
 
937
}
 
938
 
 
939
 
 
940
/*
 
941
 * Temporarily pause or shutdown the transport. 
 
942
 */
 
943
PJ_DEF(pj_status_t) pjsip_udp_transport_pause(pjsip_transport *transport,
 
944
                                              unsigned option)
 
945
{
 
946
    struct udp_transport *tp;
 
947
    unsigned i;
 
948
 
 
949
    PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL);
 
950
 
 
951
    /* Flag must be specified */
 
952
    PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL);
 
953
 
 
954
    tp = (struct udp_transport*) transport;
 
955
 
 
956
    /* Transport must not have been paused */
 
957
    PJ_ASSERT_RETURN(tp->is_paused==0, PJ_EINVALIDOP);
 
958
 
 
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.
 
962
     */
 
963
    tp->is_paused = PJ_TRUE;
 
964
 
 
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);
 
969
    }
 
970
 
 
971
    /* Destroy the socket? */
 
972
    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
 
973
        if (tp->key) {
 
974
            /* This implicitly closes the socket */
 
975
            pj_ioqueue_unregister(tp->key);
 
976
            tp->key = NULL;
 
977
        } else {
 
978
            /* Close socket. */
 
979
            if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
 
980
                pj_sock_close(tp->sock);
 
981
                tp->sock = PJ_INVALID_SOCKET;
 
982
            }
 
983
        }
 
984
        tp->sock = PJ_INVALID_SOCKET;
 
985
        
 
986
    }
 
987
 
 
988
    PJ_LOG(4,(tp->base.obj_name, "SIP UDP transport paused"));
 
989
 
 
990
    return PJ_SUCCESS;
 
991
}
 
992
 
 
993
 
 
994
/*
 
995
 * Restart transport.
 
996
 *
 
997
 * If option is KEEP_SOCKET, just re-activate ioqueue operation.
 
998
 *
 
999
 * If option is DESTROY_SOCKET:
 
1000
 *  - if socket is specified, replace.
 
1001
 *  - if socket is not specified, create and replace.
 
1002
 */
 
1003
PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
 
1004
                                                unsigned option,
 
1005
                                                pj_sock_t sock,
 
1006
                                                const pj_sockaddr_in *local,
 
1007
                                                const pjsip_host_port *a_name)
 
1008
{
 
1009
    struct udp_transport *tp;
 
1010
    pj_status_t status;
 
1011
 
 
1012
    PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL);
 
1013
    /* Flag must be specified */
 
1014
    PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL);
 
1015
 
 
1016
    tp = (struct udp_transport*) transport;
 
1017
 
 
1018
    if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
 
1019
        char addr_buf[PJ_INET6_ADDRSTRLEN];
 
1020
        pjsip_host_port bound_name;
 
1021
 
 
1022
        /* Request to recreate transport */
 
1023
 
 
1024
        /* Destroy existing socket, if any. */
 
1025
        if (tp->key) {
 
1026
            /* This implicitly closes the socket */
 
1027
            pj_ioqueue_unregister(tp->key);
 
1028
            tp->key = NULL;
 
1029
        } else {
 
1030
            /* Close socket. */
 
1031
            if (tp->sock && tp->sock != PJ_INVALID_SOCKET) {
 
1032
                pj_sock_close(tp->sock);
 
1033
                tp->sock = PJ_INVALID_SOCKET;
 
1034
            }
 
1035
        }
 
1036
        tp->sock = PJ_INVALID_SOCKET;
 
1037
 
 
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)
 
1043
                return status;
 
1044
        }
 
1045
 
 
1046
        /* If transport published name is not specified, calculate it
 
1047
         * from the bound address.
 
1048
         */
 
1049
        if (a_name == NULL) {
 
1050
            status = get_published_name(sock, addr_buf, sizeof(addr_buf),
 
1051
                                        &bound_name);
 
1052
            if (status != PJ_SUCCESS) {
 
1053
                pj_sock_close(sock);
 
1054
                return status;
 
1055
            }
 
1056
 
 
1057
            a_name = &bound_name;
 
1058
        }
 
1059
 
 
1060
        /* Assign the socket and published address to transport. */
 
1061
        udp_set_socket(tp, sock, a_name);
 
1062
 
 
1063
    } else {
 
1064
 
 
1065
        /* For KEEP_SOCKET, transport must have been paused before */
 
1066
        PJ_ASSERT_RETURN(tp->is_paused, PJ_EINVALIDOP);
 
1067
 
 
1068
        /* If address name is specified, update it */
 
1069
        if (a_name != NULL)
 
1070
            udp_set_pub_name(tp, a_name);
 
1071
    }
 
1072
 
 
1073
    /* Re-register new or existing socket to ioqueue. */
 
1074
    status = register_to_ioqueue(tp);
 
1075
    if (status != PJ_SUCCESS) {
 
1076
        return status;
 
1077
    }
 
1078
 
 
1079
    /* Restart async read operation. */
 
1080
    status = start_async_read(tp);
 
1081
    if (status != PJ_SUCCESS)
 
1082
        return status;
 
1083
 
 
1084
    /* Everything has been set up */
 
1085
    tp->is_paused = PJ_FALSE;
 
1086
 
 
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));
 
1092
 
 
1093
    return PJ_SUCCESS;
 
1094
}
 
1095