blob: 70f16d6d73e86f8abceefedd0f08da3bc863054c [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <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_MRU
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
40static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
41
42/* Pending write buffer */
43typedef struct pending_write
44{
45 char buffer[PJMEDIA_MAX_MTU];
46 pj_ioqueue_op_key_t op_key;
47} pending_write;
48
49
50struct 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
96static void on_rx_rtp( pj_ioqueue_key_t *key,
97 pj_ioqueue_op_key_t *op_key,
98 pj_ssize_t bytes_read);
99static 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 */
106static pj_status_t transport_get_info (pjmedia_transport *tp,
107 pjmedia_transport_info *info);
108static 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));
119static void transport_detach (pjmedia_transport *tp,
120 void *strm);
121static pj_status_t transport_send_rtp( pjmedia_transport *tp,
122 const void *pkt,
123 pj_size_t size);
124static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
125 const void *pkt,
126 pj_size_t size);
127static 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);
132static 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);
137static 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);
142static 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);
147static pj_status_t transport_media_stop(pjmedia_transport *tp);
148static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
149 pjmedia_dir dir,
150 unsigned pct_lost);
151static pj_status_t transport_destroy (pjmedia_transport *tp);
152
153
154static 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 */
174PJ_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 */
187PJ_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 */
201PJ_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
257on_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 */
269PJ_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
394on_error:
395 transport_destroy(&tp->base);
396 return status;
397}
398
399
400/**
401 * Close UDP transport.
402 */
403static 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 */
442static 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 */
550static 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 */
613static 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 */
633static 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 /* Set buffer size for RTP socket */
697#if PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE
698 {
699 unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE;
700 pj_status_t status;
701 status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(),
702 PJ_TRUE, &sobuf_size);
703 if (status != PJ_SUCCESS) {
704 pj_perror(3, tp->name, status, "Failed setting SO_RCVBUF");
705 } else {
706 if (sobuf_size < PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE) {
707 PJ_LOG(4, (tp->name,
708 "Warning! Cannot set SO_RCVBUF as configured, "
709 "now=%d, configured=%d",
710 sobuf_size, PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE));
711 } else {
712 PJ_LOG(5, (tp->name, "SO_RCVBUF set to %d", sobuf_size));
713 }
714 }
715 }
716#endif
717#if PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE
718 {
719 unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE;
720 pj_status_t status;
721 status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(),
722 PJ_TRUE, &sobuf_size);
723 if (status != PJ_SUCCESS) {
724 pj_perror(3, tp->name, status, "Failed setting SO_SNDBUF");
725 } else {
726 if (sobuf_size < PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE) {
727 PJ_LOG(4, (tp->name,
728 "Warning! Cannot set SO_SNDBUF as configured, "
729 "now=%d, configured=%d",
730 sobuf_size, PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE));
731 } else {
732 PJ_LOG(5, (tp->name, "SO_SNDBUF set to %d", sobuf_size));
733 }
734 }
735 }
736#endif
737
738 /* Unlock keys */
739 pj_ioqueue_unlock_key(udp->rtcp_key);
740 pj_ioqueue_unlock_key(udp->rtp_key);
741
742 return PJ_SUCCESS;
743}
744
745
746/* Called by application when it no longer needs the transport */
747static void transport_detach( pjmedia_transport *tp,
748 void *user_data)
749{
750 struct transport_udp *udp = (struct transport_udp*) tp;
751
752 pj_assert(tp);
753
754 if (udp->attached) {
755 /* Lock the ioqueue keys to make sure that callbacks are
756 * not executed. See ticket #460 for details.
757 */
758 pj_ioqueue_lock_key(udp->rtp_key);
759 pj_ioqueue_lock_key(udp->rtcp_key);
760
761 /* User data is unreferenced on Release build */
762 PJ_UNUSED_ARG(user_data);
763
764 /* As additional checking, check if the same user data is specified */
765 pj_assert(user_data == udp->user_data);
766
767 /* First, mark transport as unattached */
768 udp->attached = PJ_FALSE;
769
770 /* Clear up application infos from transport */
771 udp->rtp_cb = NULL;
772 udp->rtcp_cb = NULL;
773 udp->user_data = NULL;
774
775 /* Unlock keys */
776 pj_ioqueue_unlock_key(udp->rtcp_key);
777 pj_ioqueue_unlock_key(udp->rtp_key);
778 }
779}
780
781
782/* Called by application to send RTP packet */
783static pj_status_t transport_send_rtp( pjmedia_transport *tp,
784 const void *pkt,
785 pj_size_t size)
786{
787 struct transport_udp *udp = (struct transport_udp*)tp;
788 pj_ssize_t sent;
789 unsigned id;
790 struct pending_write *pw;
791 pj_status_t status;
792
793 /* Must be attached */
794 PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
795
796 /* Check that the size is supported */
797 PJ_ASSERT_RETURN(size <= PJMEDIA_MAX_MTU, PJ_ETOOBIG);
798
799 /* Simulate packet lost on TX direction */
800 if (udp->tx_drop_pct) {
801 if ((pj_rand() % 100) <= (int)udp->tx_drop_pct) {
802 PJ_LOG(5,(udp->base.name,
803 "TX RTP packet dropped because of pkt lost "
804 "simulation"));
805 return PJ_SUCCESS;
806 }
807 }
808
809
810 id = udp->rtp_write_op_id;
811 pw = &udp->rtp_pending_write[id];
812
813 /* We need to copy packet to our buffer because when the
814 * operation is pending, caller might write something else
815 * to the original buffer.
816 */
817 pj_memcpy(pw->buffer, pkt, size);
818
819 sent = size;
820 status = pj_ioqueue_sendto( udp->rtp_key,
821 &udp->rtp_pending_write[id].op_key,
822 pw->buffer, &sent, 0,
823 &udp->rem_rtp_addr,
824 udp->addr_len);
825
826 udp->rtp_write_op_id = (udp->rtp_write_op_id + 1) %
827 PJ_ARRAY_SIZE(udp->rtp_pending_write);
828
829 if (status==PJ_SUCCESS || status==PJ_EPENDING)
830 return PJ_SUCCESS;
831
832 return status;
833}
834
835/* Called by application to send RTCP packet */
836static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
837 const void *pkt,
838 pj_size_t size)
839{
840 return transport_send_rtcp2(tp, NULL, 0, pkt, size);
841}
842
843
844/* Called by application to send RTCP packet */
845static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
846 const pj_sockaddr_t *addr,
847 unsigned addr_len,
848 const void *pkt,
849 pj_size_t size)
850{
851 struct transport_udp *udp = (struct transport_udp*)tp;
852 pj_ssize_t sent;
853 pj_status_t status;
854
855 PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
856
857 if (addr == NULL) {
858 addr = &udp->rem_rtcp_addr;
859 addr_len = udp->addr_len;
860 }
861
862 sent = size;
863 status = pj_ioqueue_sendto( udp->rtcp_key, &udp->rtcp_write_op,
864 pkt, &sent, 0, addr, addr_len);
865
866 if (status==PJ_SUCCESS || status==PJ_EPENDING)
867 return PJ_SUCCESS;
868
869 return status;
870}
871
872
873static pj_status_t transport_media_create(pjmedia_transport *tp,
874 pj_pool_t *pool,
875 unsigned options,
876 const pjmedia_sdp_session *sdp_remote,
877 unsigned media_index)
878{
879 struct transport_udp *udp = (struct transport_udp*)tp;
880
881 PJ_ASSERT_RETURN(tp && pool, PJ_EINVAL);
882 udp->media_options = options;
883
884 PJ_UNUSED_ARG(sdp_remote);
885 PJ_UNUSED_ARG(media_index);
886
887 return PJ_SUCCESS;
888}
889
890static pj_status_t transport_encode_sdp(pjmedia_transport *tp,
891 pj_pool_t *pool,
892 pjmedia_sdp_session *sdp_local,
893 const pjmedia_sdp_session *rem_sdp,
894 unsigned media_index)
895{
896 struct transport_udp *udp = (struct transport_udp*)tp;
897
898 /* Validate media transport */
899 /* By now, this transport only support RTP/AVP transport */
900 if ((udp->media_options & PJMEDIA_TPMED_NO_TRANSPORT_CHECKING) == 0) {
901 pjmedia_sdp_media *m_rem, *m_loc;
902
903 m_rem = rem_sdp? rem_sdp->media[media_index] : NULL;
904 m_loc = sdp_local->media[media_index];
905
906 if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) ||
907 (m_rem && pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP)))
908 {
909 pjmedia_sdp_media_deactivate(pool, m_loc);
910 return PJMEDIA_SDP_EINPROTO;
911 }
912 }
913
914 return PJ_SUCCESS;
915}
916
917static pj_status_t transport_media_start(pjmedia_transport *tp,
918 pj_pool_t *pool,
919 const pjmedia_sdp_session *sdp_local,
920 const pjmedia_sdp_session *sdp_remote,
921 unsigned media_index)
922{
923 PJ_ASSERT_RETURN(tp && pool && sdp_local, PJ_EINVAL);
924
925 PJ_UNUSED_ARG(tp);
926 PJ_UNUSED_ARG(pool);
927 PJ_UNUSED_ARG(sdp_local);
928 PJ_UNUSED_ARG(sdp_remote);
929 PJ_UNUSED_ARG(media_index);
930
931 return PJ_SUCCESS;
932}
933
934static pj_status_t transport_media_stop(pjmedia_transport *tp)
935{
936 PJ_UNUSED_ARG(tp);
937
938 return PJ_SUCCESS;
939}
940
941static pj_status_t transport_simulate_lost(pjmedia_transport *tp,
942 pjmedia_dir dir,
943 unsigned pct_lost)
944{
945 struct transport_udp *udp = (struct transport_udp*)tp;
946
947 PJ_ASSERT_RETURN(tp && pct_lost <= 100, PJ_EINVAL);
948
949 if (dir & PJMEDIA_DIR_ENCODING)
950 udp->tx_drop_pct = pct_lost;
951
952 if (dir & PJMEDIA_DIR_DECODING)
953 udp->rx_drop_pct = pct_lost;
954
955 return PJ_SUCCESS;
956}
957