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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjmedia/src/pjmedia/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: transport_udp.c 3841 2011-10-24 09:28:13Z ming $ */
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 <pjmedia/transport_udp.h>
21
 
#include <pj/addr_resolv.h>
22
 
#include <pj/assert.h>
23
 
#include <pj/errno.h>
24
 
#include <pj/ioqueue.h>
25
 
#include <pj/log.h>
26
 
#include <pj/pool.h>
27
 
#include <pj/rand.h>
28
 
#include <pj/string.h>
29
 
 
30
 
 
31
 
/* Maximum size of incoming RTP packet */
32
 
#define RTP_LEN     PJMEDIA_MAX_MTU
33
 
 
34
 
/* Maximum size of incoming RTCP packet */
35
 
#define RTCP_LEN    600
36
 
 
37
 
/* Maximum pending write operations */
38
 
#define MAX_PENDING 4
39
 
 
40
 
static const pj_str_t ID_RTP_AVP  = { "RTP/AVP", 7 };
41
 
 
42
 
/* Pending write buffer */
43
 
typedef struct pending_write
44
 
{
45
 
    char                buffer[RTP_LEN];
46
 
    pj_ioqueue_op_key_t op_key;
47
 
} pending_write;
48
 
 
49
 
 
50
 
struct transport_udp
51
 
{
52
 
    pjmedia_transport   base;           /**< Base transport.                */
53
 
 
54
 
    pj_pool_t          *pool;           /**< Memory pool                    */
55
 
    unsigned            options;        /**< Transport options.             */
56
 
    unsigned            media_options;  /**< Transport media options.       */
57
 
    void               *user_data;      /**< Only valid when attached       */
58
 
    pj_bool_t           attached;       /**< Has attachment?                */
59
 
    pj_sockaddr         rem_rtp_addr;   /**< Remote RTP address             */
60
 
    pj_sockaddr         rem_rtcp_addr;  /**< Remote RTCP address            */
61
 
    int                 addr_len;       /**< Length of addresses.           */
62
 
    void  (*rtp_cb)(    void*,          /**< To report incoming RTP.        */
63
 
                        void*,
64
 
                        pj_ssize_t);
65
 
    void  (*rtcp_cb)(   void*,          /**< To report incoming RTCP.       */
66
 
                        void*,
67
 
                        pj_ssize_t);
68
 
 
69
 
    unsigned            tx_drop_pct;    /**< Percent of tx pkts to drop.    */
70
 
    unsigned            rx_drop_pct;    /**< Percent of rx pkts to drop.    */
71
 
 
72
 
    pj_sock_t           rtp_sock;       /**< RTP socket                     */
73
 
    pj_sockaddr         rtp_addr_name;  /**< Published RTP address.         */
74
 
    pj_ioqueue_key_t   *rtp_key;        /**< RTP socket key in ioqueue      */
75
 
    pj_ioqueue_op_key_t rtp_read_op;    /**< Pending read operation         */
76
 
    unsigned            rtp_write_op_id;/**< Next write_op to use           */
77
 
    pending_write       rtp_pending_write[MAX_PENDING];  /**< Pending write */
78
 
    pj_sockaddr         rtp_src_addr;   /**< Actual packet src addr.        */
79
 
    unsigned            rtp_src_cnt;    /**< How many pkt from this addr.   */
80
 
    int                 rtp_addrlen;    /**< Address length.                */
81
 
    char                rtp_pkt[RTP_LEN];/**< Incoming RTP packet buffer    */
82
 
 
83
 
    pj_sock_t           rtcp_sock;      /**< RTCP socket                    */
84
 
    pj_sockaddr         rtcp_addr_name; /**< Published RTCP address.        */
85
 
    pj_sockaddr         rtcp_src_addr;  /**< Actual source RTCP address.    */
86
 
    unsigned            rtcp_src_cnt;   /**< How many pkt from this addr.   */
87
 
    int                 rtcp_addr_len;  /**< Length of RTCP src address.    */
88
 
    pj_ioqueue_key_t   *rtcp_key;       /**< RTCP socket key in ioqueue     */
89
 
    pj_ioqueue_op_key_t rtcp_read_op;   /**< Pending read operation         */
90
 
    pj_ioqueue_op_key_t rtcp_write_op;  /**< Pending write operation        */
91
 
    char                rtcp_pkt[RTCP_LEN];/**< Incoming RTCP packet buffer */
92
 
};
93
 
 
94
 
 
95
 
 
96
 
static void on_rx_rtp( pj_ioqueue_key_t *key,
97
 
                       pj_ioqueue_op_key_t *op_key,
98
 
                       pj_ssize_t bytes_read);
99
 
static void on_rx_rtcp(pj_ioqueue_key_t *key,
100
 
                       pj_ioqueue_op_key_t *op_key,
101
 
                       pj_ssize_t bytes_read);
102
 
 
103
 
/*
104
 
 * These are media transport operations.
105
 
 */
106
 
static pj_status_t transport_get_info (pjmedia_transport *tp,
107
 
                                       pjmedia_transport_info *info);
108
 
static pj_status_t transport_attach   (pjmedia_transport *tp,
109
 
                                       void *user_data,
110
 
                                       const pj_sockaddr_t *rem_addr,
111
 
                                       const pj_sockaddr_t *rem_rtcp,
112
 
                                       unsigned addr_len,
113
 
                                       void (*rtp_cb)(void*,
114
 
                                                      void*,
115
 
                                                      pj_ssize_t),
116
 
                                       void (*rtcp_cb)(void*,
117
 
                                                       void*,
118
 
                                                       pj_ssize_t));
119
 
static void        transport_detach   (pjmedia_transport *tp,
120
 
                                       void *strm);
121
 
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
122
 
                                       const void *pkt,
123
 
                                       pj_size_t size);
124
 
static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
125
 
                                       const void *pkt,
126
 
                                       pj_size_t size);
127
 
static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
128
 
                                       const pj_sockaddr_t *addr,
129
 
                                       unsigned addr_len,
130
 
                                       const void *pkt,
131
 
                                       pj_size_t size);
132
 
static pj_status_t transport_media_create(pjmedia_transport *tp,
133
 
                                       pj_pool_t *pool,
134
 
                                       unsigned options,
135
 
                                       const pjmedia_sdp_session *sdp_remote,
136
 
                                       unsigned media_index);
137
 
static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
138
 
                                        pj_pool_t *pool,
139
 
                                        pjmedia_sdp_session *sdp_local,
140
 
                                        const pjmedia_sdp_session *rem_sdp,
141
 
                                        unsigned media_index);
142
 
static pj_status_t transport_media_start (pjmedia_transport *tp,
143
 
                                       pj_pool_t *pool,
144
 
                                       const pjmedia_sdp_session *sdp_local,
145
 
                                       const pjmedia_sdp_session *sdp_remote,
146
 
                                       unsigned media_index);
147
 
static pj_status_t transport_media_stop(pjmedia_transport *tp);
148
 
static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
149
 
                                       pjmedia_dir dir,
150
 
                                       unsigned pct_lost);
151
 
static pj_status_t transport_destroy  (pjmedia_transport *tp);
152
 
 
153
 
 
154
 
static pjmedia_transport_op transport_udp_op =
155
 
{
156
 
    &transport_get_info,
157
 
    &transport_attach,
158
 
    &transport_detach,
159
 
    &transport_send_rtp,
160
 
    &transport_send_rtcp,
161
 
    &transport_send_rtcp2,
162
 
    &transport_media_create,
163
 
    &transport_encode_sdp,
164
 
    &transport_media_start,
165
 
    &transport_media_stop,
166
 
    &transport_simulate_lost,
167
 
    &transport_destroy
168
 
};
169
 
 
170
 
 
171
 
/**
172
 
 * Create UDP stream transport.
173
 
 */
174
 
PJ_DEF(pj_status_t) pjmedia_transport_udp_create( pjmedia_endpt *endpt,
175
 
                                                  const char *name,
176
 
                                                  int port,
177
 
                                                  unsigned options,
178
 
                                                  pjmedia_transport **p_tp)
179
 
{
180
 
    return pjmedia_transport_udp_create2(endpt, name, NULL, port, options,
181
 
                                        p_tp);
182
 
}
183
 
 
184
 
/**
185
 
 * Create UDP stream transport.
186
 
 */
187
 
PJ_DEF(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt,
188
 
                                                  const char *name,
189
 
                                                  const pj_str_t *addr,
190
 
                                                  int port,
191
 
                                                  unsigned options,
192
 
                                                  pjmedia_transport **p_tp)
193
 
{
194
 
    return pjmedia_transport_udp_create3(endpt, pj_AF_INET(), name,
195
 
                                         addr, port, options, p_tp);
196
 
}
197
 
 
198
 
/**
199
 
 * Create UDP stream transport.
200
 
 */
201
 
PJ_DEF(pj_status_t) pjmedia_transport_udp_create3(pjmedia_endpt *endpt,
202
 
                                                  int af,
203
 
                                                  const char *name,
204
 
                                                  const pj_str_t *addr,
205
 
                                                  int port,
206
 
                                                  unsigned options,
207
 
                                                  pjmedia_transport **p_tp)
208
 
{
209
 
    pjmedia_sock_info si;
210
 
    pj_status_t status;
211
 
 
212
 
 
213
 
    /* Sanity check */
214
 
    PJ_ASSERT_RETURN(endpt && port && p_tp, PJ_EINVAL);
215
 
 
216
 
 
217
 
    pj_bzero(&si, sizeof(pjmedia_sock_info));
218
 
    si.rtp_sock = si.rtcp_sock = PJ_INVALID_SOCKET;
219
 
 
220
 
    /* Create RTP socket */
221
 
    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtp_sock);
222
 
    if (status != PJ_SUCCESS)
223
 
        goto on_error;
224
 
 
225
 
    /* Bind RTP socket */
226
 
    status = pj_sockaddr_init(af, &si.rtp_addr_name, addr, (pj_uint16_t)port);
227
 
    if (status != PJ_SUCCESS)
228
 
        goto on_error;
229
 
 
230
 
    status = pj_sock_bind(si.rtp_sock, &si.rtp_addr_name,
231
 
                          pj_sockaddr_get_len(&si.rtp_addr_name));
232
 
    if (status != PJ_SUCCESS)
233
 
        goto on_error;
234
 
 
235
 
 
236
 
    /* Create RTCP socket */
237
 
    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtcp_sock);
238
 
    if (status != PJ_SUCCESS)
239
 
        goto on_error;
240
 
 
241
 
    /* Bind RTCP socket */
242
 
    status = pj_sockaddr_init(af, &si.rtcp_addr_name, addr,
243
 
                              (pj_uint16_t)(port+1));
244
 
    if (status != PJ_SUCCESS)
245
 
        goto on_error;
246
 
 
247
 
    status = pj_sock_bind(si.rtcp_sock, &si.rtcp_addr_name,
248
 
                          pj_sockaddr_get_len(&si.rtcp_addr_name));
249
 
    if (status != PJ_SUCCESS)
250
 
        goto on_error;
251
 
 
252
 
 
253
 
    /* Create UDP transport by attaching socket info */
254
 
    return pjmedia_transport_udp_attach( endpt, name, &si, options, p_tp);
255
 
 
256
 
 
257
 
on_error:
258
 
    if (si.rtp_sock != PJ_INVALID_SOCKET)
259
 
        pj_sock_close(si.rtp_sock);
260
 
    if (si.rtcp_sock != PJ_INVALID_SOCKET)
261
 
        pj_sock_close(si.rtcp_sock);
262
 
    return status;
263
 
}
264
 
 
265
 
 
266
 
/**
267
 
 * Create UDP stream transport from existing socket info.
268
 
 */
269
 
PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt,
270
 
                                                  const char *name,
271
 
                                                  const pjmedia_sock_info *si,
272
 
                                                  unsigned options,
273
 
                                                  pjmedia_transport **p_tp)
274
 
{
275
 
    struct transport_udp *tp;
276
 
    pj_pool_t *pool;
277
 
    pj_ioqueue_t *ioqueue;
278
 
    pj_ioqueue_callback rtp_cb, rtcp_cb;
279
 
    pj_ssize_t size;
280
 
    unsigned i;
281
 
    pj_status_t status;
282
 
 
283
 
 
284
 
    /* Sanity check */
285
 
    PJ_ASSERT_RETURN(endpt && si && p_tp, PJ_EINVAL);
286
 
 
287
 
    /* Get ioqueue instance */
288
 
    ioqueue = pjmedia_endpt_get_ioqueue(endpt);
289
 
 
290
 
    if (name==NULL)
291
 
        name = "udp%p";
292
 
 
293
 
    /* Create transport structure */
294
 
    pool = pjmedia_endpt_create_pool(endpt, name, 512, 512);
295
 
    if (!pool)
296
 
        return PJ_ENOMEM;
297
 
 
298
 
    tp = PJ_POOL_ZALLOC_T(pool, struct transport_udp);
299
 
    tp->pool = pool;
300
 
    tp->options = options;
301
 
    pj_memcpy(tp->base.name, pool->obj_name, PJ_MAX_OBJ_NAME);
302
 
    tp->base.op = &transport_udp_op;
303
 
    tp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP;
304
 
 
305
 
    /* Copy socket infos */
306
 
    tp->rtp_sock = si->rtp_sock;
307
 
    tp->rtp_addr_name = si->rtp_addr_name;
308
 
    tp->rtcp_sock = si->rtcp_sock;
309
 
    tp->rtcp_addr_name = si->rtcp_addr_name;
310
 
 
311
 
    /* If address is 0.0.0.0, use host's IP address */
312
 
    if (!pj_sockaddr_has_addr(&tp->rtp_addr_name)) {
313
 
        pj_sockaddr hostip;
314
 
 
315
 
        status = pj_gethostip(tp->rtp_addr_name.addr.sa_family, &hostip);
316
 
        if (status != PJ_SUCCESS)
317
 
            goto on_error;
318
 
 
319
 
        pj_memcpy(pj_sockaddr_get_addr(&tp->rtp_addr_name),
320
 
                  pj_sockaddr_get_addr(&hostip),
321
 
                  pj_sockaddr_get_addr_len(&hostip));
322
 
    }
323
 
 
324
 
    /* Same with RTCP */
325
 
    if (!pj_sockaddr_has_addr(&tp->rtcp_addr_name)) {
326
 
        pj_memcpy(pj_sockaddr_get_addr(&tp->rtcp_addr_name),
327
 
                  pj_sockaddr_get_addr(&tp->rtp_addr_name),
328
 
                  pj_sockaddr_get_addr_len(&tp->rtp_addr_name));
329
 
    }
330
 
 
331
 
    /* Setup RTP socket with the ioqueue */
332
 
    pj_bzero(&rtp_cb, sizeof(rtp_cb));
333
 
    rtp_cb.on_read_complete = &on_rx_rtp;
334
 
 
335
 
    status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtp_sock, tp,
336
 
                                      &rtp_cb, &tp->rtp_key);
337
 
    if (status != PJ_SUCCESS)
338
 
        goto on_error;
339
 
 
340
 
    /* Disallow concurrency so that detach() and destroy() are
341
 
     * synchronized with the callback.
342
 
     */
343
 
    status = pj_ioqueue_set_concurrency(tp->rtp_key, PJ_FALSE);
344
 
    if (status != PJ_SUCCESS)
345
 
        goto on_error;
346
 
 
347
 
    pj_ioqueue_op_key_init(&tp->rtp_read_op, sizeof(tp->rtp_read_op));
348
 
    for (i=0; i<PJ_ARRAY_SIZE(tp->rtp_pending_write); ++i)
349
 
        pj_ioqueue_op_key_init(&tp->rtp_pending_write[i].op_key,
350
 
                               sizeof(tp->rtp_pending_write[i].op_key));
351
 
 
352
 
    /* Kick of pending RTP read from the ioqueue */
353
 
    tp->rtp_addrlen = sizeof(tp->rtp_src_addr);
354
 
    size = sizeof(tp->rtp_pkt);
355
 
    status = pj_ioqueue_recvfrom(tp->rtp_key, &tp->rtp_read_op,
356
 
                                 tp->rtp_pkt, &size, PJ_IOQUEUE_ALWAYS_ASYNC,
357
 
                                 &tp->rtp_src_addr, &tp->rtp_addrlen);
358
 
    if (status != PJ_EPENDING)
359
 
        goto on_error;
360
 
 
361
 
 
362
 
    /* Setup RTCP socket with ioqueue */
363
 
    pj_bzero(&rtcp_cb, sizeof(rtcp_cb));
364
 
    rtcp_cb.on_read_complete = &on_rx_rtcp;
365
 
 
366
 
    status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtcp_sock, tp,
367
 
                                      &rtcp_cb, &tp->rtcp_key);
368
 
    if (status != PJ_SUCCESS)
369
 
        goto on_error;
370
 
 
371
 
    status = pj_ioqueue_set_concurrency(tp->rtcp_key, PJ_FALSE);
372
 
    if (status != PJ_SUCCESS)
373
 
        goto on_error;
374
 
 
375
 
    pj_ioqueue_op_key_init(&tp->rtcp_read_op, sizeof(tp->rtcp_read_op));
376
 
    pj_ioqueue_op_key_init(&tp->rtcp_write_op, sizeof(tp->rtcp_write_op));
377
 
 
378
 
 
379
 
    /* Kick of pending RTCP read from the ioqueue */
380
 
    size = sizeof(tp->rtcp_pkt);
381
 
    tp->rtcp_addr_len = sizeof(tp->rtcp_src_addr);
382
 
    status = pj_ioqueue_recvfrom( tp->rtcp_key, &tp->rtcp_read_op,
383
 
                                  tp->rtcp_pkt, &size, PJ_IOQUEUE_ALWAYS_ASYNC,
384
 
                                  &tp->rtcp_src_addr, &tp->rtcp_addr_len);
385
 
    if (status != PJ_EPENDING)
386
 
        goto on_error;
387
 
 
388
 
 
389
 
    /* Done */
390
 
    *p_tp = &tp->base;
391
 
    return PJ_SUCCESS;
392
 
 
393
 
 
394
 
on_error:
395
 
    transport_destroy(&tp->base);
396
 
    return status;
397
 
}
398
 
 
399
 
 
400
 
/**
401
 
 * Close UDP transport.
402
 
 */
403
 
static pj_status_t transport_destroy(pjmedia_transport *tp)
404
 
{
405
 
    struct transport_udp *udp = (struct transport_udp*) tp;
406
 
 
407
 
    /* Sanity check */
408
 
    PJ_ASSERT_RETURN(tp, PJ_EINVAL);
409
 
 
410
 
    /* Must not close while application is using this */
411
 
    //PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP);
412
 
 
413
 
 
414
 
    if (udp->rtp_key) {
415
 
        /* This will block the execution if callback is still
416
 
         * being called.
417
 
         */
418
 
        pj_ioqueue_unregister(udp->rtp_key);
419
 
        udp->rtp_key = NULL;
420
 
        udp->rtp_sock = PJ_INVALID_SOCKET;
421
 
    } else if (udp->rtp_sock != PJ_INVALID_SOCKET) {
422
 
        pj_sock_close(udp->rtp_sock);
423
 
        udp->rtp_sock = PJ_INVALID_SOCKET;
424
 
    }
425
 
 
426
 
    if (udp->rtcp_key) {
427
 
        pj_ioqueue_unregister(udp->rtcp_key);
428
 
        udp->rtcp_key = NULL;
429
 
        udp->rtcp_sock = PJ_INVALID_SOCKET;
430
 
    } else if (udp->rtcp_sock != PJ_INVALID_SOCKET) {
431
 
        pj_sock_close(udp->rtcp_sock);
432
 
        udp->rtcp_sock = PJ_INVALID_SOCKET;
433
 
    }
434
 
 
435
 
    pj_pool_release(udp->pool);
436
 
 
437
 
    return PJ_SUCCESS;
438
 
}
439
 
 
440
 
 
441
 
/* Notification from ioqueue about incoming RTP packet */
442
 
static void on_rx_rtp( pj_ioqueue_key_t *key,
443
 
                       pj_ioqueue_op_key_t *op_key,
444
 
                       pj_ssize_t bytes_read)
445
 
{
446
 
    struct transport_udp *udp;
447
 
    pj_status_t status;
448
 
 
449
 
    PJ_UNUSED_ARG(op_key);
450
 
 
451
 
    udp = (struct transport_udp*) pj_ioqueue_get_user_data(key);
452
 
 
453
 
    do {
454
 
        void (*cb)(void*,void*,pj_ssize_t);
455
 
        void *user_data;
456
 
        pj_bool_t discard = PJ_FALSE;
457
 
 
458
 
        cb = udp->rtp_cb;
459
 
        user_data = udp->user_data;
460
 
 
461
 
        /* Simulate packet lost on RX direction */
462
 
        if (udp->rx_drop_pct) {
463
 
            if ((pj_rand() % 100) <= (int)udp->rx_drop_pct) {
464
 
                PJ_LOG(5,(udp->base.name,
465
 
                          "RX RTP packet dropped because of pkt lost "
466
 
                          "simulation"));
467
 
                discard = PJ_TRUE;
468
 
            }
469
 
        }
470
 
 
471
 
        /* See if source address of RTP packet is different than the
472
 
         * configured address, and switch RTP remote address to
473
 
         * source packet address after several consecutive packets
474
 
         * have been received.
475
 
         */
476
 
        if (bytes_read>0 &&
477
 
            (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0)
478
 
        {
479
 
            if (pj_sockaddr_cmp(&udp->rem_rtp_addr, &udp->rtp_src_addr) == 0) {
480
 
                /* We're still receiving from rem_rtp_addr. Don't switch. */
481
 
                udp->rtp_src_cnt = 0;
482
 
            } else {
483
 
                udp->rtp_src_cnt++;
484
 
 
485
 
                if (udp->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) {
486
 
                    discard = PJ_TRUE;
487
 
                } else {
488
 
 
489
 
                    char addr_text[80];
490
 
 
491
 
                    /* Set remote RTP address to source address */
492
 
                    pj_memcpy(&udp->rem_rtp_addr, &udp->rtp_src_addr,
493
 
                              sizeof(pj_sockaddr));
494
 
 
495
 
                    /* Reset counter */
496
 
                    udp->rtp_src_cnt = 0;
497
 
 
498
 
                    PJ_LOG(4,(udp->base.name,
499
 
                              "Remote RTP address switched to %s",
500
 
                              pj_sockaddr_print(&udp->rtp_src_addr, addr_text,
501
 
                                                sizeof(addr_text), 3)));
502
 
 
503
 
                    /* Also update remote RTCP address if actual RTCP source
504
 
                     * address is not heard yet.
505
 
                     */
506
 
                    if (!pj_sockaddr_has_addr(&udp->rtcp_src_addr)) {
507
 
                        pj_uint16_t port;
508
 
 
509
 
                        pj_memcpy(&udp->rem_rtcp_addr, &udp->rem_rtp_addr,
510
 
                                  sizeof(pj_sockaddr));
511
 
                        pj_sockaddr_copy_addr(&udp->rem_rtcp_addr,
512
 
                                              &udp->rem_rtp_addr);
513
 
                        port = (pj_uint16_t)
514
 
                               (pj_sockaddr_get_port(&udp->rem_rtp_addr)+1);
515
 
                        pj_sockaddr_set_port(&udp->rem_rtcp_addr, port);
516
 
 
517
 
                        pj_memcpy(&udp->rtcp_src_addr, &udp->rem_rtcp_addr,
518
 
                                  sizeof(pj_sockaddr));
519
 
 
520
 
                        PJ_LOG(4,(udp->base.name,
521
 
                                  "Remote RTCP address switched to predicted"
522
 
                                  " address %s",
523
 
                                  pj_sockaddr_print(&udp->rtcp_src_addr,
524
 
                                                    addr_text,
525
 
                                                    sizeof(addr_text), 3)));
526
 
 
527
 
                    }
528
 
                }
529
 
            }
530
 
        }
531
 
 
532
 
        if (!discard && udp->attached && cb)
533
 
            (*cb)(user_data, udp->rtp_pkt, bytes_read);
534
 
 
535
 
        bytes_read = sizeof(udp->rtp_pkt);
536
 
        udp->rtp_addrlen = sizeof(udp->rtp_src_addr);
537
 
        status = pj_ioqueue_recvfrom(udp->rtp_key, &udp->rtp_read_op,
538
 
                                     udp->rtp_pkt, &bytes_read, 0,
539
 
                                     &udp->rtp_src_addr,
540
 
                                     &udp->rtp_addrlen);
541
 
 
542
 
        if (status != PJ_EPENDING && status != PJ_SUCCESS)
543
 
            bytes_read = -status;
544
 
 
545
 
    } while (status != PJ_EPENDING && status != PJ_ECANCELLED);
546
 
}
547
 
 
548
 
 
549
 
/* Notification from ioqueue about incoming RTCP packet */
550
 
static void on_rx_rtcp(pj_ioqueue_key_t *key,
551
 
                       pj_ioqueue_op_key_t *op_key,
552
 
                       pj_ssize_t bytes_read)
553
 
{
554
 
    struct transport_udp *udp;
555
 
    pj_status_t status;
556
 
 
557
 
    PJ_UNUSED_ARG(op_key);
558
 
 
559
 
    udp = (struct transport_udp*) pj_ioqueue_get_user_data(key);
560
 
 
561
 
    do {
562
 
        void (*cb)(void*,void*,pj_ssize_t);
563
 
        void *user_data;
564
 
 
565
 
        cb = udp->rtcp_cb;
566
 
        user_data = udp->user_data;
567
 
 
568
 
        if (udp->attached && cb)
569
 
            (*cb)(user_data, udp->rtcp_pkt, bytes_read);
570
 
 
571
 
        /* Check if RTCP source address is the same as the configured
572
 
         * remote address, and switch the address when they are
573
 
         * different.
574
 
         */
575
 
        if (bytes_read>0 &&
576
 
            (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0)
577
 
        {
578
 
            if (pj_sockaddr_cmp(&udp->rem_rtcp_addr, &udp->rtcp_src_addr) == 0) {
579
 
                /* Still receiving from rem_rtcp_addr, don't switch */
580
 
                udp->rtcp_src_cnt = 0;
581
 
            } else {
582
 
                ++udp->rtcp_src_cnt;
583
 
 
584
 
                if (udp->rtcp_src_cnt >= PJMEDIA_RTCP_NAT_PROBATION_CNT ) {
585
 
                    char addr_text[80];
586
 
 
587
 
                    udp->rtcp_src_cnt = 0;
588
 
                    pj_memcpy(&udp->rem_rtcp_addr, &udp->rtcp_src_addr,
589
 
                              sizeof(pj_sockaddr));
590
 
 
591
 
                    PJ_LOG(4,(udp->base.name,
592
 
                              "Remote RTCP address switched to %s",
593
 
                              pj_sockaddr_print(&udp->rtcp_src_addr, addr_text,
594
 
                                                sizeof(addr_text), 3)));
595
 
                }
596
 
            }
597
 
        }
598
 
 
599
 
        bytes_read = sizeof(udp->rtcp_pkt);
600
 
        udp->rtcp_addr_len = sizeof(udp->rtcp_src_addr);
601
 
        status = pj_ioqueue_recvfrom(udp->rtcp_key, &udp->rtcp_read_op,
602
 
                                     udp->rtcp_pkt, &bytes_read, 0,
603
 
                                     &udp->rtcp_src_addr,
604
 
                                     &udp->rtcp_addr_len);
605
 
        if (status != PJ_EPENDING && status != PJ_SUCCESS)
606
 
            bytes_read = -status;
607
 
 
608
 
    } while (status != PJ_EPENDING && status != PJ_ECANCELLED);
609
 
}
610
 
 
611
 
 
612
 
/* Called to get the transport info */
613
 
static pj_status_t transport_get_info(pjmedia_transport *tp,
614
 
                                      pjmedia_transport_info *info)
615
 
{
616
 
    struct transport_udp *udp = (struct transport_udp*)tp;
617
 
    PJ_ASSERT_RETURN(tp && info, PJ_EINVAL);
618
 
 
619
 
    info->sock_info.rtp_sock = udp->rtp_sock;
620
 
    info->sock_info.rtp_addr_name = udp->rtp_addr_name;
621
 
    info->sock_info.rtcp_sock = udp->rtcp_sock;
622
 
    info->sock_info.rtcp_addr_name = udp->rtcp_addr_name;
623
 
 
624
 
    /* Get remote address originating RTP & RTCP. */
625
 
    info->src_rtp_name  = udp->rtp_src_addr;
626
 
    info->src_rtcp_name = udp->rtcp_src_addr;
627
 
 
628
 
    return PJ_SUCCESS;
629
 
}
630
 
 
631
 
 
632
 
/* Called by application to initialize the transport */
633
 
static pj_status_t transport_attach(   pjmedia_transport *tp,
634
 
                                       void *user_data,
635
 
                                       const pj_sockaddr_t *rem_addr,
636
 
                                       const pj_sockaddr_t *rem_rtcp,
637
 
                                       unsigned addr_len,
638
 
                                       void (*rtp_cb)(void*,
639
 
                                                      void*,
640
 
                                                      pj_ssize_t),
641
 
                                       void (*rtcp_cb)(void*,
642
 
                                                       void*,
643
 
                                                       pj_ssize_t))
644
 
{
645
 
    struct transport_udp *udp = (struct transport_udp*) tp;
646
 
    const pj_sockaddr *rtcp_addr;
647
 
 
648
 
    /* Validate arguments */
649
 
    PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL);
650
 
 
651
 
    /* Must not be "attached" to existing application */
652
 
    PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP);
653
 
 
654
 
    /* Lock the ioqueue keys to make sure that callbacks are
655
 
     * not executed. See ticket #844 for details.
656
 
     */
657
 
    pj_ioqueue_lock_key(udp->rtp_key);
658
 
    pj_ioqueue_lock_key(udp->rtcp_key);
659
 
 
660
 
    /* "Attach" the application: */
661
 
 
662
 
    /* Copy remote RTP address */
663
 
    pj_memcpy(&udp->rem_rtp_addr, rem_addr, addr_len);
664
 
 
665
 
    /* Copy remote RTP address, if one is specified. */
666
 
    rtcp_addr = (const pj_sockaddr*) rem_rtcp;
667
 
    if (rtcp_addr && pj_sockaddr_has_addr(rtcp_addr)) {
668
 
        pj_memcpy(&udp->rem_rtcp_addr, rem_rtcp, addr_len);
669
 
 
670
 
    } else {
671
 
        unsigned rtcp_port;
672
 
 
673
 
        /* Otherwise guess the RTCP address from the RTP address */
674
 
        pj_memcpy(&udp->rem_rtcp_addr, rem_addr, addr_len);
675
 
        rtcp_port = pj_sockaddr_get_port(&udp->rem_rtp_addr) + 1;
676
 
        pj_sockaddr_set_port(&udp->rem_rtcp_addr, (pj_uint16_t)rtcp_port);
677
 
    }
678
 
 
679
 
    /* Save the callbacks */
680
 
    udp->rtp_cb = rtp_cb;
681
 
    udp->rtcp_cb = rtcp_cb;
682
 
    udp->user_data = user_data;
683
 
 
684
 
    /* Save address length */
685
 
    udp->addr_len = addr_len;
686
 
 
687
 
    /* Last, mark transport as attached */
688
 
    udp->attached = PJ_TRUE;
689
 
 
690
 
    /* Reset source RTP & RTCP addresses and counter */
691
 
    pj_bzero(&udp->rtp_src_addr, sizeof(udp->rtp_src_addr));
692
 
    pj_bzero(&udp->rtcp_src_addr, sizeof(udp->rtcp_src_addr));
693
 
    udp->rtp_src_cnt = 0;
694
 
    udp->rtcp_src_cnt = 0;
695
 
 
696
 
    /* Unlock keys */
697
 
    pj_ioqueue_unlock_key(udp->rtcp_key);
698
 
    pj_ioqueue_unlock_key(udp->rtp_key);
699
 
 
700
 
    return PJ_SUCCESS;
701
 
}
702
 
 
703
 
 
704
 
/* Called by application when it no longer needs the transport */
705
 
static void transport_detach( pjmedia_transport *tp,
706
 
                              void *user_data)
707
 
{
708
 
    struct transport_udp *udp = (struct transport_udp*) tp;
709
 
 
710
 
    pj_assert(tp);
711
 
 
712
 
    if (udp->attached) {
713
 
        /* Lock the ioqueue keys to make sure that callbacks are
714
 
         * not executed. See ticket #460 for details.
715
 
         */
716
 
        pj_ioqueue_lock_key(udp->rtp_key);
717
 
        pj_ioqueue_lock_key(udp->rtcp_key);
718
 
 
719
 
        /* User data is unreferenced on Release build */
720
 
        PJ_UNUSED_ARG(user_data);
721
 
 
722
 
        /* As additional checking, check if the same user data is specified */
723
 
        pj_assert(user_data == udp->user_data);
724
 
 
725
 
        /* First, mark transport as unattached */
726
 
        udp->attached = PJ_FALSE;
727
 
 
728
 
        /* Clear up application infos from transport */
729
 
        udp->rtp_cb = NULL;
730
 
        udp->rtcp_cb = NULL;
731
 
        udp->user_data = NULL;
732
 
 
733
 
        /* Unlock keys */
734
 
        pj_ioqueue_unlock_key(udp->rtcp_key);
735
 
        pj_ioqueue_unlock_key(udp->rtp_key);
736
 
    }
737
 
}
738
 
 
739
 
 
740
 
/* Called by application to send RTP packet */
741
 
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
742
 
                                       const void *pkt,
743
 
                                       pj_size_t size)
744
 
{
745
 
    struct transport_udp *udp = (struct transport_udp*)tp;
746
 
    pj_ssize_t sent;
747
 
    unsigned id;
748
 
    struct pending_write *pw;
749
 
    pj_status_t status;
750
 
 
751
 
    /* Must be attached */
752
 
    PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
753
 
 
754
 
    /* Check that the size is supported */
755
 
    PJ_ASSERT_RETURN(size <= RTP_LEN, PJ_ETOOBIG);
756
 
 
757
 
    /* Simulate packet lost on TX direction */
758
 
    if (udp->tx_drop_pct) {
759
 
        if ((pj_rand() % 100) <= (int)udp->tx_drop_pct) {
760
 
            PJ_LOG(5,(udp->base.name,
761
 
                      "TX RTP packet dropped because of pkt lost "
762
 
                      "simulation"));
763
 
            return PJ_SUCCESS;
764
 
        }
765
 
    }
766
 
 
767
 
 
768
 
    id = udp->rtp_write_op_id;
769
 
    pw = &udp->rtp_pending_write[id];
770
 
 
771
 
    /* We need to copy packet to our buffer because when the
772
 
     * operation is pending, caller might write something else
773
 
     * to the original buffer.
774
 
     */
775
 
    pj_memcpy(pw->buffer, pkt, size);
776
 
 
777
 
    sent = size;
778
 
    status = pj_ioqueue_sendto( udp->rtp_key,
779
 
                                &udp->rtp_pending_write[id].op_key,
780
 
                                pw->buffer, &sent, 0,
781
 
                                &udp->rem_rtp_addr,
782
 
                                udp->addr_len);
783
 
 
784
 
    udp->rtp_write_op_id = (udp->rtp_write_op_id + 1) %
785
 
                           PJ_ARRAY_SIZE(udp->rtp_pending_write);
786
 
 
787
 
    if (status==PJ_SUCCESS || status==PJ_EPENDING)
788
 
        return PJ_SUCCESS;
789
 
 
790
 
    return status;
791
 
}
792
 
 
793
 
/* Called by application to send RTCP packet */
794
 
static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
795
 
                                       const void *pkt,
796
 
                                       pj_size_t size)
797
 
{
798
 
    return transport_send_rtcp2(tp, NULL, 0, pkt, size);
799
 
}
800
 
 
801
 
 
802
 
/* Called by application to send RTCP packet */
803
 
static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
804
 
                                        const pj_sockaddr_t *addr,
805
 
                                        unsigned addr_len,
806
 
                                        const void *pkt,
807
 
                                        pj_size_t size)
808
 
{
809
 
    struct transport_udp *udp = (struct transport_udp*)tp;
810
 
    pj_ssize_t sent;
811
 
    pj_status_t status;
812
 
 
813
 
    PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
814
 
 
815
 
    if (addr == NULL) {
816
 
        addr = &udp->rem_rtcp_addr;
817
 
        addr_len = udp->addr_len;
818
 
    }
819
 
 
820
 
    sent = size;
821
 
    status = pj_ioqueue_sendto( udp->rtcp_key, &udp->rtcp_write_op,
822
 
                                pkt, &sent, 0, addr, addr_len);
823
 
 
824
 
    if (status==PJ_SUCCESS || status==PJ_EPENDING)
825
 
        return PJ_SUCCESS;
826
 
 
827
 
    return status;
828
 
}
829
 
 
830
 
 
831
 
static pj_status_t transport_media_create(pjmedia_transport *tp,
832
 
                                  pj_pool_t *pool,
833
 
                                  unsigned options,
834
 
                                  const pjmedia_sdp_session *sdp_remote,
835
 
                                  unsigned media_index)
836
 
{
837
 
    struct transport_udp *udp = (struct transport_udp*)tp;
838
 
 
839
 
    PJ_ASSERT_RETURN(tp && pool, PJ_EINVAL);
840
 
    udp->media_options = options;
841
 
 
842
 
    PJ_UNUSED_ARG(sdp_remote);
843
 
    PJ_UNUSED_ARG(media_index);
844
 
 
845
 
    return PJ_SUCCESS;
846
 
}
847
 
 
848
 
static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
849
 
                                        pj_pool_t *pool,
850
 
                                        pjmedia_sdp_session *sdp_local,
851
 
                                        const pjmedia_sdp_session *rem_sdp,
852
 
                                        unsigned media_index)
853
 
{
854
 
    struct transport_udp *udp = (struct transport_udp*)tp;
855
 
 
856
 
    /* Validate media transport */
857
 
    /* By now, this transport only support RTP/AVP transport */
858
 
    if ((udp->media_options & PJMEDIA_TPMED_NO_TRANSPORT_CHECKING) == 0) {
859
 
        pjmedia_sdp_media *m_rem, *m_loc;
860
 
 
861
 
        m_rem = rem_sdp? rem_sdp->media[media_index] : NULL;
862
 
        m_loc = sdp_local->media[media_index];
863
 
 
864
 
        if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) ||
865
 
           (m_rem && pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP)))
866
 
        {
867
 
            pjmedia_sdp_media_deactivate(pool, m_loc);
868
 
            return PJMEDIA_SDP_EINPROTO;
869
 
        }
870
 
    }
871
 
 
872
 
    return PJ_SUCCESS;
873
 
}
874
 
 
875
 
static pj_status_t transport_media_start(pjmedia_transport *tp,
876
 
                                  pj_pool_t *pool,
877
 
                                  const pjmedia_sdp_session *sdp_local,
878
 
                                  const pjmedia_sdp_session *sdp_remote,
879
 
                                  unsigned media_index)
880
 
{
881
 
    PJ_ASSERT_RETURN(tp && pool && sdp_local, PJ_EINVAL);
882
 
 
883
 
    PJ_UNUSED_ARG(tp);
884
 
    PJ_UNUSED_ARG(pool);
885
 
    PJ_UNUSED_ARG(sdp_local);
886
 
    PJ_UNUSED_ARG(sdp_remote);
887
 
    PJ_UNUSED_ARG(media_index);
888
 
 
889
 
    return PJ_SUCCESS;
890
 
}
891
 
 
892
 
static pj_status_t transport_media_stop(pjmedia_transport *tp)
893
 
{
894
 
    PJ_UNUSED_ARG(tp);
895
 
 
896
 
    return PJ_SUCCESS;
897
 
}
898
 
 
899
 
static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
900
 
                                           pjmedia_dir dir,
901
 
                                           unsigned pct_lost)
902
 
{
903
 
    struct transport_udp *udp = (struct transport_udp*)tp;
904
 
 
905
 
    PJ_ASSERT_RETURN(tp && pct_lost <= 100, PJ_EINVAL);
906
 
 
907
 
    if (dir & PJMEDIA_DIR_ENCODING)
908
 
        udp->tx_drop_pct = pct_lost;
909
 
 
910
 
    if (dir & PJMEDIA_DIR_DECODING)
911
 
        udp->rx_drop_pct = pct_lost;
912
 
 
913
 
    return PJ_SUCCESS;
914
 
}