1
/* $Id: transport_udp.c 3841 2011-10-24 09:28:13Z ming $ */
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 <pjmedia/transport_udp.h>
21
#include <pj/addr_resolv.h>
22
#include <pj/assert.h>
24
#include <pj/ioqueue.h>
28
#include <pj/string.h>
31
/* Maximum size of incoming RTP packet */
32
#define RTP_LEN PJMEDIA_MAX_MTU
34
/* Maximum size of incoming RTCP packet */
37
/* Maximum pending write operations */
40
static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
42
/* Pending write buffer */
43
typedef struct pending_write
46
pj_ioqueue_op_key_t op_key;
52
pjmedia_transport base; /**< Base transport. */
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. */
65
void (*rtcp_cb)( void*, /**< To report incoming RTCP. */
69
unsigned tx_drop_pct; /**< Percent of tx pkts to drop. */
70
unsigned rx_drop_pct; /**< Percent of rx pkts to drop. */
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 */
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 */
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);
104
* These are media transport operations.
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,
110
const pj_sockaddr_t *rem_addr,
111
const pj_sockaddr_t *rem_rtcp,
113
void (*rtp_cb)(void*,
116
void (*rtcp_cb)(void*,
119
static void transport_detach (pjmedia_transport *tp,
121
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
124
static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
127
static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
128
const pj_sockaddr_t *addr,
132
static pj_status_t transport_media_create(pjmedia_transport *tp,
135
const pjmedia_sdp_session *sdp_remote,
136
unsigned media_index);
137
static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
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,
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,
151
static pj_status_t transport_destroy (pjmedia_transport *tp);
154
static pjmedia_transport_op transport_udp_op =
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,
172
* Create UDP stream transport.
174
PJ_DEF(pj_status_t) pjmedia_transport_udp_create( pjmedia_endpt *endpt,
178
pjmedia_transport **p_tp)
180
return pjmedia_transport_udp_create2(endpt, name, NULL, port, options,
185
* Create UDP stream transport.
187
PJ_DEF(pj_status_t) pjmedia_transport_udp_create2(pjmedia_endpt *endpt,
189
const pj_str_t *addr,
192
pjmedia_transport **p_tp)
194
return pjmedia_transport_udp_create3(endpt, pj_AF_INET(), name,
195
addr, port, options, p_tp);
199
* Create UDP stream transport.
201
PJ_DEF(pj_status_t) pjmedia_transport_udp_create3(pjmedia_endpt *endpt,
204
const pj_str_t *addr,
207
pjmedia_transport **p_tp)
209
pjmedia_sock_info si;
214
PJ_ASSERT_RETURN(endpt && port && p_tp, PJ_EINVAL);
217
pj_bzero(&si, sizeof(pjmedia_sock_info));
218
si.rtp_sock = si.rtcp_sock = PJ_INVALID_SOCKET;
220
/* Create RTP socket */
221
status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtp_sock);
222
if (status != PJ_SUCCESS)
225
/* Bind RTP socket */
226
status = pj_sockaddr_init(af, &si.rtp_addr_name, addr, (pj_uint16_t)port);
227
if (status != PJ_SUCCESS)
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)
236
/* Create RTCP socket */
237
status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtcp_sock);
238
if (status != PJ_SUCCESS)
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)
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)
253
/* Create UDP transport by attaching socket info */
254
return pjmedia_transport_udp_attach( endpt, name, &si, options, p_tp);
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);
267
* Create UDP stream transport from existing socket info.
269
PJ_DEF(pj_status_t) pjmedia_transport_udp_attach( pjmedia_endpt *endpt,
271
const pjmedia_sock_info *si,
273
pjmedia_transport **p_tp)
275
struct transport_udp *tp;
277
pj_ioqueue_t *ioqueue;
278
pj_ioqueue_callback rtp_cb, rtcp_cb;
285
PJ_ASSERT_RETURN(endpt && si && p_tp, PJ_EINVAL);
287
/* Get ioqueue instance */
288
ioqueue = pjmedia_endpt_get_ioqueue(endpt);
293
/* Create transport structure */
294
pool = pjmedia_endpt_create_pool(endpt, name, 512, 512);
298
tp = PJ_POOL_ZALLOC_T(pool, struct transport_udp);
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;
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;
311
/* If address is 0.0.0.0, use host's IP address */
312
if (!pj_sockaddr_has_addr(&tp->rtp_addr_name)) {
315
status = pj_gethostip(tp->rtp_addr_name.addr.sa_family, &hostip);
316
if (status != PJ_SUCCESS)
319
pj_memcpy(pj_sockaddr_get_addr(&tp->rtp_addr_name),
320
pj_sockaddr_get_addr(&hostip),
321
pj_sockaddr_get_addr_len(&hostip));
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));
331
/* Setup RTP socket with the ioqueue */
332
pj_bzero(&rtp_cb, sizeof(rtp_cb));
333
rtp_cb.on_read_complete = &on_rx_rtp;
335
status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtp_sock, tp,
336
&rtp_cb, &tp->rtp_key);
337
if (status != PJ_SUCCESS)
340
/* Disallow concurrency so that detach() and destroy() are
341
* synchronized with the callback.
343
status = pj_ioqueue_set_concurrency(tp->rtp_key, PJ_FALSE);
344
if (status != PJ_SUCCESS)
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));
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)
362
/* Setup RTCP socket with ioqueue */
363
pj_bzero(&rtcp_cb, sizeof(rtcp_cb));
364
rtcp_cb.on_read_complete = &on_rx_rtcp;
366
status = pj_ioqueue_register_sock(pool, ioqueue, tp->rtcp_sock, tp,
367
&rtcp_cb, &tp->rtcp_key);
368
if (status != PJ_SUCCESS)
371
status = pj_ioqueue_set_concurrency(tp->rtcp_key, PJ_FALSE);
372
if (status != PJ_SUCCESS)
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));
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)
395
transport_destroy(&tp->base);
401
* Close UDP transport.
403
static pj_status_t transport_destroy(pjmedia_transport *tp)
405
struct transport_udp *udp = (struct transport_udp*) tp;
408
PJ_ASSERT_RETURN(tp, PJ_EINVAL);
410
/* Must not close while application is using this */
411
//PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP);
415
/* This will block the execution if callback is still
418
pj_ioqueue_unregister(udp->rtp_key);
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;
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;
435
pj_pool_release(udp->pool);
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)
446
struct transport_udp *udp;
449
PJ_UNUSED_ARG(op_key);
451
udp = (struct transport_udp*) pj_ioqueue_get_user_data(key);
454
void (*cb)(void*,void*,pj_ssize_t);
456
pj_bool_t discard = PJ_FALSE;
459
user_data = udp->user_data;
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 "
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.
477
(udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0)
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;
485
if (udp->rtp_src_cnt < PJMEDIA_RTP_NAT_PROBATION_CNT) {
491
/* Set remote RTP address to source address */
492
pj_memcpy(&udp->rem_rtp_addr, &udp->rtp_src_addr,
493
sizeof(pj_sockaddr));
496
udp->rtp_src_cnt = 0;
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)));
503
/* Also update remote RTCP address if actual RTCP source
504
* address is not heard yet.
506
if (!pj_sockaddr_has_addr(&udp->rtcp_src_addr)) {
509
pj_memcpy(&udp->rem_rtcp_addr, &udp->rem_rtp_addr,
510
sizeof(pj_sockaddr));
511
pj_sockaddr_copy_addr(&udp->rem_rtcp_addr,
514
(pj_sockaddr_get_port(&udp->rem_rtp_addr)+1);
515
pj_sockaddr_set_port(&udp->rem_rtcp_addr, port);
517
pj_memcpy(&udp->rtcp_src_addr, &udp->rem_rtcp_addr,
518
sizeof(pj_sockaddr));
520
PJ_LOG(4,(udp->base.name,
521
"Remote RTCP address switched to predicted"
523
pj_sockaddr_print(&udp->rtcp_src_addr,
525
sizeof(addr_text), 3)));
532
if (!discard && udp->attached && cb)
533
(*cb)(user_data, udp->rtp_pkt, bytes_read);
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,
542
if (status != PJ_EPENDING && status != PJ_SUCCESS)
543
bytes_read = -status;
545
} while (status != PJ_EPENDING && status != PJ_ECANCELLED);
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)
554
struct transport_udp *udp;
557
PJ_UNUSED_ARG(op_key);
559
udp = (struct transport_udp*) pj_ioqueue_get_user_data(key);
562
void (*cb)(void*,void*,pj_ssize_t);
566
user_data = udp->user_data;
568
if (udp->attached && cb)
569
(*cb)(user_data, udp->rtcp_pkt, bytes_read);
571
/* Check if RTCP source address is the same as the configured
572
* remote address, and switch the address when they are
576
(udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0)
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;
584
if (udp->rtcp_src_cnt >= PJMEDIA_RTCP_NAT_PROBATION_CNT ) {
587
udp->rtcp_src_cnt = 0;
588
pj_memcpy(&udp->rem_rtcp_addr, &udp->rtcp_src_addr,
589
sizeof(pj_sockaddr));
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)));
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,
604
&udp->rtcp_addr_len);
605
if (status != PJ_EPENDING && status != PJ_SUCCESS)
606
bytes_read = -status;
608
} while (status != PJ_EPENDING && status != PJ_ECANCELLED);
612
/* Called to get the transport info */
613
static pj_status_t transport_get_info(pjmedia_transport *tp,
614
pjmedia_transport_info *info)
616
struct transport_udp *udp = (struct transport_udp*)tp;
617
PJ_ASSERT_RETURN(tp && info, PJ_EINVAL);
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;
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;
632
/* Called by application to initialize the transport */
633
static pj_status_t transport_attach( pjmedia_transport *tp,
635
const pj_sockaddr_t *rem_addr,
636
const pj_sockaddr_t *rem_rtcp,
638
void (*rtp_cb)(void*,
641
void (*rtcp_cb)(void*,
645
struct transport_udp *udp = (struct transport_udp*) tp;
646
const pj_sockaddr *rtcp_addr;
648
/* Validate arguments */
649
PJ_ASSERT_RETURN(tp && rem_addr && addr_len, PJ_EINVAL);
651
/* Must not be "attached" to existing application */
652
PJ_ASSERT_RETURN(!udp->attached, PJ_EINVALIDOP);
654
/* Lock the ioqueue keys to make sure that callbacks are
655
* not executed. See ticket #844 for details.
657
pj_ioqueue_lock_key(udp->rtp_key);
658
pj_ioqueue_lock_key(udp->rtcp_key);
660
/* "Attach" the application: */
662
/* Copy remote RTP address */
663
pj_memcpy(&udp->rem_rtp_addr, rem_addr, addr_len);
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);
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);
679
/* Save the callbacks */
680
udp->rtp_cb = rtp_cb;
681
udp->rtcp_cb = rtcp_cb;
682
udp->user_data = user_data;
684
/* Save address length */
685
udp->addr_len = addr_len;
687
/* Last, mark transport as attached */
688
udp->attached = PJ_TRUE;
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;
697
pj_ioqueue_unlock_key(udp->rtcp_key);
698
pj_ioqueue_unlock_key(udp->rtp_key);
704
/* Called by application when it no longer needs the transport */
705
static void transport_detach( pjmedia_transport *tp,
708
struct transport_udp *udp = (struct transport_udp*) tp;
713
/* Lock the ioqueue keys to make sure that callbacks are
714
* not executed. See ticket #460 for details.
716
pj_ioqueue_lock_key(udp->rtp_key);
717
pj_ioqueue_lock_key(udp->rtcp_key);
719
/* User data is unreferenced on Release build */
720
PJ_UNUSED_ARG(user_data);
722
/* As additional checking, check if the same user data is specified */
723
pj_assert(user_data == udp->user_data);
725
/* First, mark transport as unattached */
726
udp->attached = PJ_FALSE;
728
/* Clear up application infos from transport */
731
udp->user_data = NULL;
734
pj_ioqueue_unlock_key(udp->rtcp_key);
735
pj_ioqueue_unlock_key(udp->rtp_key);
740
/* Called by application to send RTP packet */
741
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
745
struct transport_udp *udp = (struct transport_udp*)tp;
748
struct pending_write *pw;
751
/* Must be attached */
752
PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
754
/* Check that the size is supported */
755
PJ_ASSERT_RETURN(size <= RTP_LEN, PJ_ETOOBIG);
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 "
768
id = udp->rtp_write_op_id;
769
pw = &udp->rtp_pending_write[id];
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.
775
pj_memcpy(pw->buffer, pkt, size);
778
status = pj_ioqueue_sendto( udp->rtp_key,
779
&udp->rtp_pending_write[id].op_key,
780
pw->buffer, &sent, 0,
784
udp->rtp_write_op_id = (udp->rtp_write_op_id + 1) %
785
PJ_ARRAY_SIZE(udp->rtp_pending_write);
787
if (status==PJ_SUCCESS || status==PJ_EPENDING)
793
/* Called by application to send RTCP packet */
794
static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
798
return transport_send_rtcp2(tp, NULL, 0, pkt, size);
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,
809
struct transport_udp *udp = (struct transport_udp*)tp;
813
PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
816
addr = &udp->rem_rtcp_addr;
817
addr_len = udp->addr_len;
821
status = pj_ioqueue_sendto( udp->rtcp_key, &udp->rtcp_write_op,
822
pkt, &sent, 0, addr, addr_len);
824
if (status==PJ_SUCCESS || status==PJ_EPENDING)
831
static pj_status_t transport_media_create(pjmedia_transport *tp,
834
const pjmedia_sdp_session *sdp_remote,
835
unsigned media_index)
837
struct transport_udp *udp = (struct transport_udp*)tp;
839
PJ_ASSERT_RETURN(tp && pool, PJ_EINVAL);
840
udp->media_options = options;
842
PJ_UNUSED_ARG(sdp_remote);
843
PJ_UNUSED_ARG(media_index);
848
static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
850
pjmedia_sdp_session *sdp_local,
851
const pjmedia_sdp_session *rem_sdp,
852
unsigned media_index)
854
struct transport_udp *udp = (struct transport_udp*)tp;
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;
861
m_rem = rem_sdp? rem_sdp->media[media_index] : NULL;
862
m_loc = sdp_local->media[media_index];
864
if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) ||
865
(m_rem && pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP)))
867
pjmedia_sdp_media_deactivate(pool, m_loc);
868
return PJMEDIA_SDP_EINPROTO;
875
static pj_status_t transport_media_start(pjmedia_transport *tp,
877
const pjmedia_sdp_session *sdp_local,
878
const pjmedia_sdp_session *sdp_remote,
879
unsigned media_index)
881
PJ_ASSERT_RETURN(tp && pool && sdp_local, PJ_EINVAL);
885
PJ_UNUSED_ARG(sdp_local);
886
PJ_UNUSED_ARG(sdp_remote);
887
PJ_UNUSED_ARG(media_index);
892
static pj_status_t transport_media_stop(pjmedia_transport *tp)
899
static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
903
struct transport_udp *udp = (struct transport_udp*)tp;
905
PJ_ASSERT_RETURN(tp && pct_lost <= 100, PJ_EINVAL);
907
if (dir & PJMEDIA_DIR_ENCODING)
908
udp->tx_drop_pct = pct_lost;
910
if (dir & PJMEDIA_DIR_DECODING)
911
udp->rx_drop_pct = pct_lost;