1 /*
2 * The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) implementation with additional features.
3 * Copyright (C) 2017 Belledonne Communications SARL
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20
21 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE
23 #endif
24
25 #if __APPLE__
26 #include "TargetConditionals.h"
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include "ortp-config.h" /*needed for HAVE_SYS_UIO_H and HAVE_ARC4RANDOM */
31 #endif
32 #include <bctoolbox/port.h>
33 #include "ortp/ortp.h"
34 #include "utils.h"
35 #include "ortp/rtpsession.h"
36 #include "rtpsession_priv.h"
37
38 #if (_WIN32_WINNT >= 0x0600)
39 #include <delayimp.h>
40 #undef ExternC
41 #ifdef ORTP_WINDOWS_DESKTOP
42 #include <QOS2.h>
43 #include <VersionHelpers.h>
44 #endif
45 #endif
46
47 #if (defined(_WIN32) || defined(_WIN32_WCE)) && defined(ORTP_WINDOWS_DESKTOP)
48 #include <mswsock.h>
49 #endif
50
51 #ifdef HAVE_SYS_UIO_H
52 #include <sys/uio.h>
53 #define USE_SENDMSG 1
54 #endif
55
56 #define can_connect(s) ( (s)->use_connect && !(s)->symmetric_rtp)
57
58 #if defined(_WIN32) || defined(_WIN32_WCE)
59 #ifndef WSAID_WSARECVMSG
60 /* http://source.winehq.org/git/wine.git/blob/HEAD:/include/mswsock.h */
61 #define WSAID_WSARECVMSG {0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
62 #ifndef MAX_NATURAL_ALIGNMENT
63 #define MAX_NATURAL_ALIGNMENT sizeof(DWORD)
64 #endif
65 #ifndef TYPE_ALIGNMENT
66 #define TYPE_ALIGNMENT(t) FIELD_OFFSET(struct { char x; t test; },test)
67 #endif
68 typedef WSACMSGHDR *LPWSACMSGHDR;
69 #ifndef WSA_CMSGHDR_ALIGN
70 #define WSA_CMSGHDR_ALIGN(length) (((length) + TYPE_ALIGNMENT(WSACMSGHDR)-1) & (~(TYPE_ALIGNMENT(WSACMSGHDR)-1)))
71 #endif
72 #ifndef WSA_CMSGDATA_ALIGN
73 #define WSA_CMSGDATA_ALIGN(length) (((length) + MAX_NATURAL_ALIGNMENT-1) & (~(MAX_NATURAL_ALIGNMENT-1)))
74 #endif
75 #ifndef WSA_CMSG_FIRSTHDR
76 #define WSA_CMSG_FIRSTHDR(msg) (((msg)->Control.len >= sizeof(WSACMSGHDR)) ? (LPWSACMSGHDR)(msg)->Control.buf : (LPWSACMSGHDR)NULL)
77 #endif
78 #ifndef WSA_CMSG_NXTHDR
79 #define WSA_CMSG_NXTHDR(msg,cmsg) ((!(cmsg)) ? WSA_CMSG_FIRSTHDR(msg) : ((((u_char *)(cmsg) + WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len) + sizeof(WSACMSGHDR)) > (u_char *)((msg)->Control.buf) + (msg)->Control.len) ? (LPWSACMSGHDR)NULL : (LPWSACMSGHDR)((u_char *)(cmsg) + WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len))))
80 #endif
81 #ifndef WSA_CMSG_DATA
82 #define WSA_CMSG_DATA(cmsg) ((u_char *)(cmsg) + WSA_CMSGDATA_ALIGN(sizeof(WSACMSGHDR)))
83 #endif
84 #endif
85 #undef CMSG_FIRSTHDR
86 #define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
87 #undef CMSG_NXTHDR
88 #define CMSG_NXTHDR WSA_CMSG_NXTHDR
89 #undef CMSG_DATA
90 #define CMSG_DATA WSA_CMSG_DATA
91 typedef INT (WINAPI * LPFN_WSARECVMSG)(SOCKET, LPWSAMSG, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
92 static LPFN_WSARECVMSG ortp_WSARecvMsg = NULL;
93
94 #endif
95
96 #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__QNX__)
97 /* Mingw32 does not define AI_V4MAPPED, however it is supported starting from Windows Vista. QNX also does not define AI_V4MAPPED. */
98 # ifndef AI_V4MAPPED
99 # define AI_V4MAPPED 0x00000800
100 # endif
101 # ifndef AI_ALL
102 # define AI_ALL 0x00000100
103 # endif
104 # ifndef IPV6_V6ONLY
105 # define IPV6_V6ONLY 27
106 # endif
107 #endif
108
109 #ifndef IN6_IS_ADDR_MULTICAST
110 #define IN6_IS_ADDR_MULTICAST(i) (((uint8_t *) (i))[0] == 0xff)
111 #endif
112
113 static int
114 _rtp_session_set_remote_addr_full (RtpSession * session, const char * rtp_addr, int rtp_port, const char * rtcp_addr, int rtcp_port, bool_t is_aux);
115
try_connect(ortp_socket_t fd,const struct sockaddr * dest,socklen_t addrlen)116 static bool_t try_connect(ortp_socket_t fd, const struct sockaddr *dest, socklen_t addrlen){
117 if (connect(fd,dest,addrlen)<0){
118 ortp_warning("Could not connect() socket: %s",getSocketError());
119 return FALSE;
120 }
121 return TRUE;
122 }
123
set_multicast_group(ortp_socket_t sock,const char * addr)124 static int set_multicast_group(ortp_socket_t sock, const char *addr){
125 #ifndef __hpux
126 struct addrinfo *res;
127 int err;
128
129 res = bctbx_name_to_addrinfo(AF_UNSPEC, SOCK_DGRAM, addr, 0);
130 if (res == NULL) return -1;
131
132 switch (res->ai_family){
133 case AF_INET:
134 if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr)))
135 {
136 struct ip_mreq mreq;
137 mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr;
138 mreq.imr_interface.s_addr = INADDR_ANY;
139 err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (SOCKET_OPTION_VALUE) &mreq, sizeof(mreq));
140 if (err < 0){
141 ortp_warning ("Fail to join address group: %s.", getSocketError());
142 } else {
143 ortp_message ("RTP socket [%i] has joined address group [%s]",sock, addr);
144 }
145 }
146 break;
147 case AF_INET6:
148 if IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr))
149 {
150 struct ipv6_mreq mreq;
151 mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
152 mreq.ipv6mr_interface = 0;
153 err = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (SOCKET_OPTION_VALUE)&mreq, sizeof(mreq));
154 if (err < 0 ){
155 ortp_warning ("Fail to join address group: %s.", getSocketError());
156 } else {
157 ortp_message ("RTP socket 6 [%i] has joined address group [%s]",sock, addr);
158 }
159 }
160 break;
161 }
162 freeaddrinfo(res);
163 return 0;
164 #else
165 return -1;
166 #endif
167 }
168
create_and_bind(const char * addr,int * port,int * sock_family,bool_t reuse_addr,struct sockaddr_storage * bound_addr,socklen_t * bound_addr_len)169 static ortp_socket_t create_and_bind(const char *addr, int *port, int *sock_family, bool_t reuse_addr,struct sockaddr_storage* bound_addr,socklen_t *bound_addr_len){
170 int err;
171 int optval = 1;
172 ortp_socket_t sock=-1;
173 struct addrinfo *res0, *res;
174
175 if (*port==-1) *port=0;
176 if (*port==0) reuse_addr=FALSE;
177
178 res0 = bctbx_name_to_addrinfo(AF_UNSPEC, SOCK_DGRAM, addr, *port);
179 if (res0 == NULL) return -1;
180
181 for (res = res0; res; res = res->ai_next) {
182 sock = socket(res->ai_family, res->ai_socktype, 0);
183 if (sock==-1)
184 continue;
185
186 if (reuse_addr){
187 err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
188 (SOCKET_OPTION_VALUE)&optval, sizeof (optval));
189 if (err < 0)
190 {
191 ortp_warning ("Fail to set rtp address reusable: %s.", getSocketError());
192 }
193 #ifdef SO_REUSEPORT
194 /*SO_REUSEPORT is required on mac and ios especially for doing multicast*/
195 err = setsockopt (sock, SOL_SOCKET, SO_REUSEPORT,
196 (SOCKET_OPTION_VALUE)&optval, sizeof (optval));
197 if (err < 0)
198 {
199 ortp_warning ("Fail to set rtp port reusable: %s.", getSocketError());
200 }
201 #endif
202 }
203 /*enable dual stack operation, default is enabled on unix, disabled on windows.*/
204 if (res->ai_family==AF_INET6){
205 optval=0;
206 err=setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&optval, sizeof(optval));
207 if (err < 0){
208 ortp_warning ("Fail to IPV6_V6ONLY: %s.",getSocketError());
209 }
210 }
211
212 #ifdef SO_TIMESTAMP
213 optval=1;
214 err = setsockopt (sock, SOL_SOCKET, SO_TIMESTAMP,
215 (SOCKET_OPTION_VALUE)&optval, sizeof (optval));
216 if (err < 0)
217 {
218 ortp_warning ("Fail to set rtp timestamp: %s.",getSocketError());
219 }
220 #endif
221 err = 0;
222 optval=1;
223 switch (res->ai_family) {
224 default:
225 case AF_INET:
226 #ifdef IP_RECVTTL
227 err = setsockopt(sock, IPPROTO_IP, IP_RECVTTL, (SOCKET_OPTION_VALUE)&optval, sizeof(optval));
228 #endif
229 break;
230 case AF_INET6:
231 #ifdef IPV6_RECVHOPLIMIT
232 err = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, (SOCKET_OPTION_VALUE)&optval, sizeof(optval));
233 #endif
234 break;
235 }
236 if (err < 0) {
237 ortp_warning("Fail to set recv TTL/HL socket option: %s.", getSocketError());
238 }
239
240 *sock_family=res->ai_family;
241 err = bind(sock, res->ai_addr, (int)res->ai_addrlen);
242 if (err != 0){
243 ortp_error ("Fail to bind rtp socket to (addr=%s port=%i) : %s.", addr, *port, getSocketError());
244 close_socket(sock);
245 sock=-1;
246 continue;
247 }
248 /*compatibility mode. New applications should use rtp_session_set_multicast_group() instead*/
249 set_multicast_group(sock, addr);
250 break;
251 }
252 memcpy(bound_addr,res0->ai_addr,res0->ai_addrlen);
253 *bound_addr_len=(socklen_t)res0->ai_addrlen;
254
255 bctbx_freeaddrinfo(res0);
256
257 #if defined(_WIN32) || defined(_WIN32_WCE)
258 if (ortp_WSARecvMsg == NULL) {
259 GUID guid = WSAID_WSARECVMSG;
260 DWORD bytes_returned;
261 if (WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
262 &ortp_WSARecvMsg, sizeof(ortp_WSARecvMsg), &bytes_returned, NULL, NULL) == SOCKET_ERROR) {
263 ortp_warning("WSARecvMsg function not found.");
264 }
265 }
266 #endif
267 if (sock!=-1){
268 set_non_blocking_socket (sock);
269 if (*port==0){
270 struct sockaddr_storage saddr;
271 socklen_t slen=sizeof(saddr);
272 err=getsockname(sock,(struct sockaddr*)&saddr,&slen);
273 if (err==-1){
274 ortp_error("getsockname(): %s",getSocketError());
275 close_socket(sock);
276 return (ortp_socket_t)-1;
277 }
278 err = bctbx_sockaddr_to_ip_address((struct sockaddr *)&saddr, slen, NULL, 0, port);
279 if (err!=0){
280 close_socket(sock);
281 return (ortp_socket_t)-1;
282 }
283 }
284
285 }
286 return sock;
287 }
288
_rtp_session_apply_socket_sizes(RtpSession * session)289 void _rtp_session_apply_socket_sizes(RtpSession * session){
290 int err;
291 bool_t done=FALSE;
292 ortp_socket_t sock = session->rtp.gs.socket;
293 unsigned int sndbufsz = session->rtp.snd_socket_size;
294 unsigned int rcvbufsz = session->rtp.rcv_socket_size;
295
296 if (sock == (ortp_socket_t)-1) return;
297
298 if (sndbufsz>0){
299 #ifdef SO_SNDBUFFORCE
300 err = setsockopt(sock, SOL_SOCKET, SO_SNDBUFFORCE, (void *)&sndbufsz, sizeof(sndbufsz));
301 if (err == -1) {
302 ortp_warning("Fail to increase socket's send buffer size with SO_SNDBUFFORCE: %s.", getSocketError());
303 }else done=TRUE;
304 #endif
305 if (!done){
306 err = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&sndbufsz, sizeof(sndbufsz));
307 if (err == -1) {
308 ortp_error("Fail to increase socket's send buffer size with SO_SNDBUF: %s.", getSocketError());
309 }
310 }
311 }
312 done=FALSE;
313 if (rcvbufsz>0){
314 #ifdef SO_RCVBUFFORCE
315 err = setsockopt(sock, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&rcvbufsz, sizeof(rcvbufsz));
316 if (err == -1) {
317 ortp_warning("Fail to increase socket's recv buffer size with SO_RCVBUFFORCE: %s.", getSocketError());
318 }
319 #endif
320 if (!done){
321 err = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbufsz, sizeof(rcvbufsz));
322 if (err == -1) {
323 ortp_error("Fail to increase socket's recv buffer size with SO_RCVBUF: %s.", getSocketError());
324 }
325 }
326
327 }
328 }
329
330 /**
331 *rtp_session_set_local_addr:
332 *@param session: a rtp session freshly created.
333 *@param addr: a local IP address in the xxx.xxx.xxx.xxx form.
334 *@param rtp_port: a local port or -1 to let oRTP choose the port randomly
335 *@param rtcp_port: a local port or -1 to let oRTP choose the port randomly
336 *
337 * Specify the local addr to be use to listen for rtp packets or to send rtp packet from.
338 * In case where the rtp session is send-only, then it is not required to call this function:
339 * when calling rtp_session_set_remote_addr(), if no local address has been set, then the
340 * default INADRR_ANY (0.0.0.0) IP address with a random port will be used. Calling
341 * rtp_session_set_local_addr() is mandatory when the session is recv-only or duplex.
342 *
343 * Returns: 0 on success.
344 **/
345
346 int
rtp_session_set_local_addr(RtpSession * session,const char * addr,int rtp_port,int rtcp_port)347 rtp_session_set_local_addr (RtpSession * session, const char * addr, int rtp_port, int rtcp_port)
348 {
349 ortp_socket_t sock;
350 int sockfamily;
351 if (session->rtp.gs.socket!=(ortp_socket_t)-1){
352 /* don't rebind, but close before*/
353 _rtp_session_release_sockets(session, FALSE);
354 }
355 /* try to bind the rtp port */
356
357 sock=create_and_bind(addr,&rtp_port,&sockfamily,session->reuseaddr,&session->rtp.gs.loc_addr,&session->rtp.gs.loc_addrlen);
358 if (sock!=-1){
359 session->rtp.gs.sockfamily=sockfamily;
360 session->rtp.gs.socket=sock;
361 session->rtp.gs.loc_port=rtp_port;
362 _rtp_session_apply_socket_sizes(session);
363 /*try to bind rtcp port */
364 sock=create_and_bind(addr,&rtcp_port,&sockfamily,session->reuseaddr,&session->rtcp.gs.loc_addr,&session->rtcp.gs.loc_addrlen);
365 if (sock!=(ortp_socket_t)-1){
366 session->rtcp.gs.sockfamily=sockfamily;
367 session->rtcp.gs.socket=sock;
368 session->rtcp.gs.loc_port=rtcp_port;
369 }else {
370 ortp_error("Could not create and bind rtcp socket for session [%p]",session);
371 return -1;
372 }
373
374 /* set socket options (but don't change chosen states) */
375 rtp_session_set_multicast_ttl( session, -1 );
376 rtp_session_set_multicast_loopback( session, -1 );
377 if (session->use_pktinfo) rtp_session_set_pktinfo(session, TRUE);
378 ortp_message("RtpSession bound to [%s] ports [%i] [%i]", addr, rtp_port, rtcp_port);
379 return 0;
380 }
381 ortp_error("Could not bind RTP socket to %s on port %i for session [%p]",addr,rtp_port,session);
382 return -1;
383 }
384
_rtp_session_recreate_sockets(RtpSession * session)385 static void _rtp_session_recreate_sockets(RtpSession *session){
386 char addr[NI_MAXHOST];
387 int err = bctbx_sockaddr_to_ip_address((struct sockaddr *)&session->rtp.gs.loc_addr, session->rtp.gs.loc_addrlen, addr, sizeof(addr), NULL);
388 if (err != 0) return;
389 /*re create and bind sockets as they were done previously*/
390 ortp_message("RtpSession %p is going to re-create its socket.", session);
391 rtp_session_set_local_addr(session, addr, session->rtp.gs.loc_port, session->rtcp.gs.loc_port);
392 }
393
_rtp_session_check_socket_refresh(RtpSession * session)394 static void _rtp_session_check_socket_refresh(RtpSession *session){
395 if (session->flags & RTP_SESSION_SOCKET_REFRESH_REQUESTED){
396 session->flags &= ~RTP_SESSION_SOCKET_REFRESH_REQUESTED;
397 _rtp_session_recreate_sockets(session);
398 }
399 }
400
401 /**
402 * Requests the session to re-create and bind its RTP and RTCP sockets same as they are currently.
403 * This is used when a change in the routing rules of the host or process was made, in order to have
404 * this routing rules change taking effect on the RTP/RTCP packets sent by the session.
405 **/
rtp_session_refresh_sockets(RtpSession * session)406 void rtp_session_refresh_sockets(RtpSession *session){
407 if (session->rtp.gs.socket != (ortp_socket_t) -1){
408 session->flags |= RTP_SESSION_SOCKET_REFRESH_REQUESTED;
409 }
410 }
411
rtp_session_join_multicast_group(RtpSession * session,const char * ip)412 int rtp_session_join_multicast_group(RtpSession *session, const char *ip){
413 int err;
414 if (session->rtp.gs.socket==(ortp_socket_t)-1){
415 ortp_error("rtp_session_set_multicast_group() must be done only on bound sockets, use rtp_session_set_local_addr() first");
416 return -1;
417 }
418 err=set_multicast_group(session->rtp.gs.socket,ip);
419 set_multicast_group(session->rtcp.gs.socket,ip);
420 return err;
421 }
422
423 /**
424 *rtp_session_set_pktinfo:
425 *@param session: a rtp session
426 *@param activate: activation flag (0 to deactivate, other value to activate)
427 *
428 * (De)activates packet info for incoming and outgoing packets.
429 *
430 * Returns: 0 on success.
431 *
432 **/
rtp_session_set_pktinfo(RtpSession * session,int activate)433 int rtp_session_set_pktinfo(RtpSession *session, int activate)
434 {
435 int retval;
436 int optname;
437 #if defined(_WIN32) || defined(_WIN32_WCE)
438 char optval[sizeof(DWORD)];
439 int optlen = sizeof(optval);
440 #else
441 int *optval = &activate;
442 int optlen = sizeof(activate);
443 #endif
444 session->use_pktinfo = activate;
445 // Dont't do anything if socket hasn't been created yet
446 if (session->rtp.gs.socket == (ortp_socket_t)-1) return 0;
447
448 #if defined(_WIN32) || defined(_WIN32_WCE)
449 memset(optval, activate, sizeof(optval));
450 #endif
451
452 #ifdef IP_PKTINFO
453 optname = IP_PKTINFO;
454 #else
455 optname = IP_RECVDSTADDR;
456 #endif
457 retval = setsockopt(session->rtp.gs.socket, IPPROTO_IP, optname, optval, optlen);
458 if (retval < 0) {
459 ortp_warning ("Fail to set IPv4 packet info on RTP socket: %s.", getSocketError());
460 }
461 retval = setsockopt(session->rtcp.gs.socket, IPPROTO_IP, optname, optval, optlen);
462 if (retval < 0) {
463 ortp_warning ("Fail to set IPv4 packet info on RTCP socket: %s.", getSocketError());
464 }
465
466 if (session->rtp.gs.sockfamily != AF_INET) {
467 #if defined(_WIN32) || defined(_WIN32_WCE)
468 memset(optval, activate, sizeof(optval));
469 #endif
470
471 #ifdef IPV6_RECVPKTINFO
472 optname = IPV6_RECVPKTINFO;
473 #else
474 optname = IPV6_RECVDSTADDR;
475 #endif
476 retval = setsockopt(session->rtp.gs.socket, IPPROTO_IPV6, optname, optval, optlen);
477 if (retval < 0) {
478 ortp_warning("Fail to set IPv6 packet info on RTP socket: %s.", getSocketError());
479 }
480 retval = setsockopt(session->rtcp.gs.socket, IPPROTO_IPV6, optname, optval, optlen);
481 if (retval < 0) {
482 ortp_warning("Fail to set IPv6 packet info on RTCP socket: %s.", getSocketError());
483 }
484 }
485
486 return retval;
487 }
488
489
490 /**
491 *rtp_session_set_multicast_ttl:
492 *@param session: a rtp session
493 *@param ttl: desired Multicast Time-To-Live
494 *
495 * Sets the TTL (Time-To-Live) for outgoing multicast packets.
496 *
497 * Returns: 0 on success.
498 *
499 **/
rtp_session_set_multicast_ttl(RtpSession * session,int ttl)500 int rtp_session_set_multicast_ttl(RtpSession *session, int ttl)
501 {
502 int retval;
503
504 // Store new TTL if one is specified
505 if (ttl>0) session->multicast_ttl = ttl;
506
507 // Don't do anything if socket hasn't been created yet
508 if (session->rtp.gs.socket == (ortp_socket_t)-1) return 0;
509
510 switch (session->rtp.gs.sockfamily) {
511 case AF_INET: {
512
513 retval= setsockopt(session->rtp.gs.socket, IPPROTO_IP, IP_MULTICAST_TTL,
514 (SOCKET_OPTION_VALUE) &session->multicast_ttl, sizeof(session->multicast_ttl));
515
516 if (retval<0) break;
517
518 retval= setsockopt(session->rtcp.gs.socket, IPPROTO_IP, IP_MULTICAST_TTL,
519 (SOCKET_OPTION_VALUE) &session->multicast_ttl, sizeof(session->multicast_ttl));
520
521 } break;
522 case AF_INET6: {
523
524 retval= setsockopt(session->rtp.gs.socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
525 (SOCKET_OPTION_VALUE)&session->multicast_ttl, sizeof(session->multicast_ttl));
526
527 if (retval<0) break;
528
529 retval= setsockopt(session->rtcp.gs.socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
530 (SOCKET_OPTION_VALUE) &session->multicast_ttl, sizeof(session->multicast_ttl));
531 } break;
532 default:
533 retval=-1;
534 }
535
536 if (retval<0)
537 ortp_warning("Failed to set multicast TTL on socket.");
538
539
540 return retval;
541 }
542
543
544 /**
545 *rtp_session_get_multicast_ttl:
546 *@param session: a rtp session
547 *
548 * Returns the TTL (Time-To-Live) for outgoing multicast packets.
549 *
550 **/
rtp_session_get_multicast_ttl(RtpSession * session)551 int rtp_session_get_multicast_ttl(RtpSession *session)
552 {
553 return session->multicast_ttl;
554 }
555
556
557 /**
558 *@param session: a rtp session
559 *@param yesno: enable multicast loopback
560 *
561 * Enable multicast loopback.
562 *
563 * Returns: 0 on success.
564 *
565 **/
rtp_session_set_multicast_loopback(RtpSession * session,int yesno)566 int rtp_session_set_multicast_loopback(RtpSession *session, int yesno)
567 {
568 int retval;
569
570 // Store new loopback state if one is specified
571 if (yesno==0) {
572 // Don't loop back
573 session->multicast_loopback = 0;
574 } else if (yesno>0) {
575 // Do loop back
576 session->multicast_loopback = 1;
577 }
578
579 // Don't do anything if socket hasn't been created yet
580 if (session->rtp.gs.socket == (ortp_socket_t)-1) return 0;
581
582 switch (session->rtp.gs.sockfamily) {
583 case AF_INET: {
584
585 retval= setsockopt(session->rtp.gs.socket, IPPROTO_IP, IP_MULTICAST_LOOP,
586 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
587
588 if (retval<0) break;
589
590 retval= setsockopt(session->rtcp.gs.socket, IPPROTO_IP, IP_MULTICAST_LOOP,
591 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
592
593 } break;
594 case AF_INET6: {
595
596 retval= setsockopt(session->rtp.gs.socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
597 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
598
599 if (retval<0) break;
600
601 retval= setsockopt(session->rtcp.gs.socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
602 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
603 } break;
604 default:
605 retval=-1;
606 }
607
608 if (retval<0)
609 ortp_warning("Failed to set multicast loopback on socket.");
610
611 return retval;
612 }
613
614
615 /**
616 *rtp_session_get_multicast_loopback:
617 *@param session: a rtp session
618 *
619 * Returns the multicast loopback state of rtp session (true or false).
620 *
621 **/
rtp_session_get_multicast_loopback(RtpSession * session)622 int rtp_session_get_multicast_loopback(RtpSession *session)
623 {
624 return session->multicast_loopback;
625 }
626
627 /**
628 *rtp_session_set_dscp:
629 *@param session: a rtp session
630 *@param dscp: desired DSCP PHB value
631 *
632 * Sets the DSCP (Differentiated Services Code Point) for outgoing RTP packets.
633 *
634 * Returns: 0 on success.
635 *
636 **/
rtp_session_set_dscp(RtpSession * session,int dscp)637 int rtp_session_set_dscp(RtpSession *session, int dscp){
638 int retval=0;
639 int tos;
640 int proto;
641 int value_type;
642
643 // Store new DSCP value if one is specified
644 if (dscp>=0) session->dscp = dscp;
645
646 // Don't do anything if socket hasn't been created yet
647 if (session->rtp.gs.socket == (ortp_socket_t)-1) return 0;
648
649 #if (_WIN32_WINNT >= 0x0600) && defined(ORTP_WINDOWS_DESKTOP)
650 ortp_message("check OS support for qwave.lib");
651 if (IsWindowsVistaOrGreater()) {
652 if (session->dscp==0)
653 tos=QOSTrafficTypeBestEffort;
654 else if (session->dscp==0x8)
655 tos=QOSTrafficTypeBackground;
656 else if (session->dscp==0x28)
657 tos=QOSTrafficTypeAudioVideo;
658 else if (session->dscp==0x38)
659 tos=QOSTrafficTypeVoice;
660 else
661 tos=QOSTrafficTypeExcellentEffort; /* 0x28 */
662
663 if (session->rtp.QoSHandle==NULL) {
664 QOS_VERSION version;
665 BOOL QoSResult;
666
667 version.MajorVersion = 1;
668 version.MinorVersion = 0;
669
670 QoSResult = QOSCreateHandle(&version, &session->rtp.QoSHandle);
671
672 if (QoSResult != TRUE){
673 ortp_error("QOSCreateHandle failed to create handle with error %d", GetLastError());
674 retval=-1;
675 }
676 }
677 if (session->rtp.QoSHandle!=NULL) {
678 BOOL QoSResult;
679 QoSResult = QOSAddSocketToFlow(
680 session->rtp.QoSHandle,
681 session->rtp.gs.socket,
682 (struct sockaddr*)&session->rtp.gs.rem_addr,
683 tos,
684 QOS_NON_ADAPTIVE_FLOW,
685 &session->rtp.QoSFlowID);
686
687 if (QoSResult != TRUE){
688 ortp_error("QOSAddSocketToFlow failed to add a flow with error %d", GetLastError());
689 retval=-1;
690 }
691 }
692 } else {
693 #endif
694 // DSCP value is in the upper six bits of the TOS field
695 tos = (session->dscp << 2) & 0xFC;
696 switch (session->rtp.gs.sockfamily) {
697 case AF_INET:
698 proto=IPPROTO_IP;
699 value_type=IP_TOS;
700 break;
701 case AF_INET6:
702 proto=IPPROTO_IPV6;
703 # ifdef IPV6_TCLASS /*seems not defined by my libc*/
704 value_type=IPV6_TCLASS;
705 # else
706 value_type=IP_TOS;
707 # endif
708 break;
709 default:
710 ortp_error("Cannot set DSCP because socket family is unspecified.");
711 return -1;
712 }
713 retval = setsockopt(session->rtp.gs.socket, proto, value_type, (SOCKET_OPTION_VALUE)&tos, sizeof(tos));
714 if (retval==-1)
715 ortp_error("Fail to set DSCP value on rtp socket: %s",getSocketError());
716 if (session->rtcp.gs.socket != (ortp_socket_t)-1){
717 if (setsockopt(session->rtcp.gs.socket, proto, value_type, (SOCKET_OPTION_VALUE)&tos, sizeof(tos))==-1){
718 ortp_error("Fail to set DSCP value on rtcp socket: %s",getSocketError());
719 }
720 }
721 #if (_WIN32_WINNT >= 0x0600) && defined(ORTP_WINDOWS_DESKTOP)
722 }
723 #endif
724 return retval;
725 }
726
727
728 /**
729 *rtp_session_get_dscp:
730 *@param session: a rtp session
731 *
732 * Returns the DSCP (Differentiated Services Code Point) for outgoing RTP packets.
733 *
734 **/
rtp_session_get_dscp(const RtpSession * session)735 int rtp_session_get_dscp(const RtpSession *session)
736 {
737 return session->dscp;
738 }
739
740
741 /**
742 *rtp_session_get_local_port:
743 *@param session: a rtp session for which rtp_session_set_local_addr() or rtp_session_set_remote_addr() has been called
744 *
745 * This function can be useful to retrieve the local port that was randomly choosen by
746 * rtp_session_set_remote_addr() when rtp_session_set_local_addr() was not called.
747 *
748 * Returns: the local port used to listen for rtp packets, -1 if not set.
749 **/
750
rtp_session_get_local_port(const RtpSession * session)751 int rtp_session_get_local_port(const RtpSession *session){
752 return (session->rtp.gs.loc_port>0) ? session->rtp.gs.loc_port : -1;
753 }
754
rtp_session_get_local_rtcp_port(const RtpSession * session)755 int rtp_session_get_local_rtcp_port(const RtpSession *session){
756 return (session->rtcp.gs.loc_port>0) ? session->rtcp.gs.loc_port : -1;
757 }
758
759 /**
760 *rtp_session_set_remote_addr:
761 *@param session: a rtp session freshly created.
762 *@param addr: a remote IP address in the xxx.xxx.xxx.xxx form.
763 *@param port: a remote port.
764 *
765 * Sets the remote address of the rtp session, ie the destination address where rtp packet
766 * are sent. If the session is recv-only or duplex, it also sets the origin of incoming RTP
767 * packets. Rtp packets that don't come from addr:port are discarded.
768 *
769 * Returns: 0 on success.
770 **/
771 int
rtp_session_set_remote_addr(RtpSession * session,const char * addr,int port)772 rtp_session_set_remote_addr (RtpSession * session, const char * addr, int port){
773 return rtp_session_set_remote_addr_full(session, addr, port, addr, port+1);
774 }
775
776 /**
777 *rtp_session_set_remote_addr_full:
778 *@param session: a rtp session freshly created.
779 *@param rtp_addr: a remote IP address in the xxx.xxx.xxx.xxx form.
780 *@param rtp_port: a remote rtp port.
781 *@param rtcp_addr: a remote IP address in the xxx.xxx.xxx.xxx form.
782 *@param rtcp_port: a remote rtcp port.
783 *
784 * Sets the remote address of the rtp session, ie the destination address where rtp packet
785 * are sent. If the session is recv-only or duplex, it also sets the origin of incoming RTP
786 * packets. Rtp packets that don't come from addr:port are discarded.
787 *
788 * Returns: 0 on success.
789 **/
790
791 int
rtp_session_set_remote_addr_full(RtpSession * session,const char * rtp_addr,int rtp_port,const char * rtcp_addr,int rtcp_port)792 rtp_session_set_remote_addr_full (RtpSession * session, const char * rtp_addr, int rtp_port, const char * rtcp_addr, int rtcp_port){
793 return _rtp_session_set_remote_addr_full(session,rtp_addr,rtp_port,rtcp_addr,rtcp_port,FALSE);
794 }
795
796 static int
_rtp_session_set_remote_addr_full(RtpSession * session,const char * rtp_addr,int rtp_port,const char * rtcp_addr,int rtcp_port,bool_t is_aux)797 _rtp_session_set_remote_addr_full (RtpSession * session, const char * rtp_addr, int rtp_port, const char * rtcp_addr, int rtcp_port, bool_t is_aux){
798 char rtp_printable_addr[64];
799 char rtcp_printable_addr[64];
800 int err;
801 struct addrinfo *res0, *res;
802 struct sockaddr_storage *rtp_saddr=&session->rtp.gs.rem_addr;
803 socklen_t *rtp_saddr_len=&session->rtp.gs.rem_addrlen;
804 struct sockaddr_storage *rtcp_saddr=&session->rtcp.gs.rem_addr;
805 socklen_t *rtcp_saddr_len=&session->rtcp.gs.rem_addrlen;
806 OrtpAddress *aux_rtp=NULL,*aux_rtcp=NULL;
807
808 if (is_aux){
809 aux_rtp=ortp_malloc0(sizeof(OrtpAddress));
810 rtp_saddr=&aux_rtp->addr;
811 rtp_saddr_len=&aux_rtp->len;
812 aux_rtcp=ortp_malloc0(sizeof(OrtpAddress));
813 rtcp_saddr=&aux_rtcp->addr;
814 rtcp_saddr_len=&aux_rtcp->len;
815 }
816
817 res0 = bctbx_name_to_addrinfo((session->rtp.gs.socket == -1) ? AF_UNSPEC : session->rtp.gs.sockfamily, SOCK_DGRAM, rtp_addr, rtp_port);
818 if (res0 == NULL) {
819 ortp_error("_rtp_session_set_remote_addr_full(): cannot set RTP destination to %s port %i.", rtp_addr, rtp_port);
820 err=-1;
821 goto end;
822 } else {
823 bctbx_addrinfo_to_printable_ip_address(res0, rtp_printable_addr, sizeof(rtp_printable_addr));
824 }
825 if (session->rtp.gs.socket == -1){
826 /* the session has not its socket bound, do it */
827 ortp_message ("Setting random local addresses.");
828 /* bind to an address type that matches the destination address */
829 if (res0->ai_addr->sa_family==AF_INET6)
830 err = rtp_session_set_local_addr (session, "::", -1, -1);
831 else err=rtp_session_set_local_addr (session, "0.0.0.0", -1, -1);
832 if (err<0) {
833 err=-1;
834 goto end;
835 }
836 }
837
838 err=-1;
839 for (res = res0; res; res = res->ai_next) {
840 /* set a destination address that has the same type as the local address */
841 if (res->ai_family==session->rtp.gs.sockfamily ) {
842 memcpy(rtp_saddr, res->ai_addr, res->ai_addrlen);
843 *rtp_saddr_len=(socklen_t)res->ai_addrlen;
844 err=0;
845 break;
846 }
847 }
848 bctbx_freeaddrinfo(res0);
849 if (err) {
850 ortp_warning("Could not set destination for RTP socket to %s:%i.",rtp_addr,rtp_port);
851 goto end;
852 }
853
854 if ((rtcp_addr != NULL) && (rtcp_port > 0)) {
855 res0 = bctbx_name_to_addrinfo((session->rtcp.gs.socket == -1) ? AF_UNSPEC : session->rtcp.gs.sockfamily, SOCK_DGRAM, rtcp_addr, rtcp_port);
856 if (res0 == NULL) {
857 ortp_error("_rtp_session_set_remote_addr_full(): cannot set RTCP destination to %s port %i.", rtcp_addr, rtcp_port);
858 err=-1;
859 goto end;
860 } else {
861 bctbx_addrinfo_to_printable_ip_address(res0, rtcp_printable_addr, sizeof(rtcp_printable_addr));
862 }
863 err=-1;
864 for (res = res0; res; res = res->ai_next) {
865 /* set a destination address that has the same type as the local address */
866 if (res->ai_family==session->rtcp.gs.sockfamily ) {
867 err=0;
868 memcpy(rtcp_saddr, res->ai_addr, res->ai_addrlen);
869 *rtcp_saddr_len=(socklen_t)res->ai_addrlen;
870 break;
871 }
872 }
873 bctbx_freeaddrinfo(res0);
874 if (err) {
875 ortp_warning("Could not set destination for RCTP socket to %s:%i.",rtcp_addr,rtcp_port);
876 goto end;
877 }
878
879 if (can_connect(session)){
880 if (try_connect(session->rtp.gs.socket,(struct sockaddr*)&session->rtp.gs.rem_addr,session->rtp.gs.rem_addrlen))
881 session->flags|=RTP_SOCKET_CONNECTED;
882 if (session->rtcp.gs.socket!=(ortp_socket_t)-1){
883 if (try_connect(session->rtcp.gs.socket,(struct sockaddr*)&session->rtcp.gs.rem_addr,session->rtcp.gs.rem_addrlen))
884 session->flags|=RTCP_SOCKET_CONNECTED;
885 }
886 }else if (session->flags & RTP_SOCKET_CONNECTED){
887 /*must dissolve association done by connect().
888 See connect(2) manpage*/
889 struct sockaddr sa;
890 sa.sa_family=AF_UNSPEC;
891 if (connect(session->rtp.gs.socket,&sa,sizeof(sa))<0){
892 ortp_error("Cannot dissolve connect() association for rtp socket: %s", getSocketError());
893 }
894 if (connect(session->rtcp.gs.socket,&sa,sizeof(sa))<0){
895 ortp_error("Cannot dissolve connect() association for rtcp socket: %s", getSocketError());
896 }
897 session->flags&=~RTP_SOCKET_CONNECTED;
898 session->flags&=~RTCP_SOCKET_CONNECTED;
899 }
900
901 ortp_message("RtpSession [%p] sending to rtp %s rtcp %s %s", session, rtp_printable_addr, rtcp_printable_addr, is_aux ? "as auxiliary destination" : "");
902 } else {
903 ortp_message("RtpSession [%p] sending to rtp %s %s", session, rtp_printable_addr, is_aux ? "as auxiliary destination" : "");
904 }
905 /*Apply DSCP setting. On windows the destination address is required for doing this.*/
906 rtp_session_set_dscp(session, -1);
907 end:
908 if (is_aux){
909 if (err==-1){
910 ortp_free(aux_rtp);
911 ortp_free(aux_rtcp);
912 }else{
913 session->rtp.gs.aux_destinations=o_list_append(session->rtp.gs.aux_destinations,aux_rtp);
914 session->rtcp.gs.aux_destinations=o_list_append(session->rtcp.gs.aux_destinations,aux_rtcp);
915 }
916 }
917 return err;
918 }
919
rtp_session_set_remote_addr_and_port(RtpSession * session,const char * addr,int rtp_port,int rtcp_port)920 int rtp_session_set_remote_addr_and_port(RtpSession * session, const char * addr, int rtp_port, int rtcp_port){
921 return rtp_session_set_remote_addr_full(session,addr,rtp_port,addr,rtcp_port);
922 }
923
924 /**
925 *rtp_session_add_remote_aux_addr_full:
926 *@param session: a rtp session freshly created.
927 *@param rtp_addr: a local IP address in the xxx.xxx.xxx.xxx form.
928 *@param rtp_port: a local rtp port.
929 *@param rtcp_addr: a local IP address in the xxx.xxx.xxx.xxx form.
930 *@param rtcp_port: a local rtcp port.
931 *
932 * Add an auxiliary remote address for the rtp session, ie a destination address where rtp packet
933 * are sent.
934 *
935 * Returns: 0 on success.
936 **/
937
938 int
rtp_session_add_aux_remote_addr_full(RtpSession * session,const char * rtp_addr,int rtp_port,const char * rtcp_addr,int rtcp_port)939 rtp_session_add_aux_remote_addr_full(RtpSession * session, const char * rtp_addr, int rtp_port, const char * rtcp_addr, int rtcp_port){
940 return _rtp_session_set_remote_addr_full(session,rtp_addr,rtp_port,rtcp_addr,rtcp_port,TRUE);
941 }
942
rtp_session_clear_aux_remote_addr(RtpSession * session)943 void rtp_session_clear_aux_remote_addr(RtpSession * session){
944 ortp_stream_clear_aux_addresses(&session->rtp.gs);
945 ortp_stream_clear_aux_addresses(&session->rtcp.gs);
946 }
947
rtp_session_set_sockets(RtpSession * session,int rtpfd,int rtcpfd)948 void rtp_session_set_sockets(RtpSession *session, int rtpfd, int rtcpfd){
949 if (rtpfd!=-1) set_non_blocking_socket(rtpfd);
950 if (rtcpfd!=-1) set_non_blocking_socket(rtcpfd);
951 session->rtp.gs.socket=rtpfd;
952 session->rtcp.gs.socket=rtcpfd;
953 if (rtpfd!=-1 || rtcpfd!=-1 )
954 session->flags|=(RTP_SESSION_USING_EXT_SOCKETS|RTP_SOCKET_CONNECTED|RTCP_SOCKET_CONNECTED);
955 else session->flags&=~(RTP_SESSION_USING_EXT_SOCKETS|RTP_SOCKET_CONNECTED|RTCP_SOCKET_CONNECTED);
956 }
957
rtp_session_set_transports(RtpSession * session,struct _RtpTransport * rtptr,struct _RtpTransport * rtcptr)958 void rtp_session_set_transports(RtpSession *session, struct _RtpTransport *rtptr, struct _RtpTransport *rtcptr)
959 {
960 session->rtp.gs.tr = rtptr;
961 session->rtcp.gs.tr = rtcptr;
962 if (rtptr)
963 rtptr->session=session;
964 if (rtcptr)
965 rtcptr->session=session;
966
967 if (rtptr || rtcptr )
968 session->flags|=(RTP_SESSION_USING_TRANSPORT);
969 else session->flags&=~(RTP_SESSION_USING_TRANSPORT);
970 }
971
rtp_session_get_transports(const RtpSession * session,RtpTransport ** rtptr,RtpTransport ** rtcptr)972 void rtp_session_get_transports(const RtpSession *session, RtpTransport **rtptr, RtpTransport **rtcptr){
973 if (rtptr) *rtptr=session->rtp.gs.tr;
974 if (rtcptr) *rtcptr=session->rtcp.gs.tr;
975 }
976
977
978 /**
979 *rtp_session_flush_sockets:
980 *@param session: a rtp session
981 *
982 * Flushes the sockets for all pending incoming packets.
983 * This can be usefull if you did not listen to the stream for a while
984 * and wishes to start to receive again. During the time no receive is made
985 * packets get bufferised into the internal kernel socket structure.
986 *
987 **/
rtp_session_flush_sockets(RtpSession * session)988 void rtp_session_flush_sockets(RtpSession *session){
989 rtp_session_set_flag(session, RTP_SESSION_FLUSH);
990 rtp_session_rtp_recv(session, 0);
991 rtp_session_unset_flag(session, RTP_SESSION_FLUSH);
992 }
993
994
995 #ifdef USE_SENDMSG
996 #define MAX_IOV 30
rtp_sendmsg(int sock,mblk_t * m,const struct sockaddr * rem_addr,socklen_t addr_len)997 static int rtp_sendmsg(int sock,mblk_t *m, const struct sockaddr *rem_addr, socklen_t addr_len){
998 int error;
999 struct msghdr msg;
1000 struct iovec iov[MAX_IOV];
1001 int iovlen;
1002 for(iovlen=0; iovlen<MAX_IOV && m!=NULL; m=m->b_cont,iovlen++){
1003 iov[iovlen].iov_base=m->b_rptr;
1004 iov[iovlen].iov_len=m->b_wptr-m->b_rptr;
1005 }
1006 if (iovlen==MAX_IOV){
1007 ortp_error("Too long msgb, didn't fit into iov, end discarded.");
1008 }
1009 msg.msg_name=(void*)rem_addr;
1010 msg.msg_namelen=addr_len;
1011 msg.msg_iov=&iov[0];
1012 msg.msg_iovlen=iovlen;
1013 msg.msg_control=NULL;
1014 msg.msg_controllen=0;
1015 msg.msg_flags=0;
1016 error=sendmsg(sock,&msg,0);
1017 return error;
1018 }
1019 #endif
1020
rtp_session_get_socket(RtpSession * session,bool_t is_rtp)1021 ortp_socket_t rtp_session_get_socket(RtpSession *session, bool_t is_rtp){
1022 return is_rtp ? session->rtp.gs.socket : session->rtcp.gs.socket;
1023 }
1024
_ortp_sendto(ortp_socket_t sockfd,mblk_t * m,int flags,const struct sockaddr * destaddr,socklen_t destlen)1025 int _ortp_sendto(ortp_socket_t sockfd, mblk_t *m, int flags, const struct sockaddr *destaddr, socklen_t destlen){
1026 int error;
1027 #ifdef USE_SENDMSG
1028 error=rtp_sendmsg(sockfd,m,destaddr,destlen);
1029 #else
1030 if (m->b_cont!=NULL)
1031 msgpullup(m,-1);
1032 error = sendto (sockfd, (char*)m->b_rptr, (int) (m->b_wptr - m->b_rptr),
1033 0,destaddr,destlen);
1034 #endif
1035 return error;
1036 }
1037
rtp_session_sendto(RtpSession * session,bool_t is_rtp,mblk_t * m,int flags,const struct sockaddr * destaddr,socklen_t destlen)1038 int rtp_session_sendto(RtpSession *session, bool_t is_rtp, mblk_t *m, int flags, const struct sockaddr *destaddr, socklen_t destlen){
1039 int ret;
1040
1041 _rtp_session_check_socket_refresh(session);
1042
1043 if (session->net_sim_ctx && (session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutbound
1044 || session->net_sim_ctx->params.mode==OrtpNetworkSimulatorOutboundControlled)){
1045 ret=(int)msgdsize(m);
1046 m=dupmsg(m);
1047 memcpy(&m->net_addr,destaddr,destlen);
1048 m->net_addrlen=destlen;
1049 m->reserved1=is_rtp;
1050 ortp_mutex_lock(&session->net_sim_ctx->mutex);
1051 putq(&session->net_sim_ctx->send_q, m);
1052 ortp_mutex_unlock(&session->net_sim_ctx->mutex);
1053 }else{
1054 ortp_socket_t sockfd = rtp_session_get_socket(session, is_rtp);
1055 ret=_ortp_sendto(sockfd, m, flags, destaddr, destlen);
1056 }
1057 return ret;
1058 }
1059
lookup_recv_addr(RtpSession * session,struct sockaddr * from,socklen_t fromlen)1060 static const ortp_recv_addr_t * lookup_recv_addr(RtpSession *session, struct sockaddr *from, socklen_t fromlen) {
1061 const ortp_recv_addr_t *result = NULL;
1062 bctbx_list_t *iterator = session->recv_addr_map;
1063 while (iterator != NULL) {
1064 ortp_recv_addr_map_t *item = (ortp_recv_addr_map_t *)bctbx_list_get_data(iterator);
1065 uint64_t curtime = ortp_get_cur_time_ms();
1066 if ((curtime - item->ts) > 2000) {
1067 bctbx_list_t *to_remove = iterator;
1068 iterator = bctbx_list_next(iterator);
1069 session->recv_addr_map = bctbx_list_erase_link(session->recv_addr_map, to_remove);
1070 } else {
1071 if (memcmp(&item->ss, from, fromlen) == 0) result = &item->recv_addr;
1072 iterator = bctbx_list_next(iterator);
1073 }
1074 }
1075 return result;
1076 }
1077
get_recv_addr(RtpSession * session,struct sockaddr * from,socklen_t fromlen)1078 static const ortp_recv_addr_t * get_recv_addr(RtpSession *session, struct sockaddr *from, socklen_t fromlen) {
1079 char result[NI_MAXHOST] = { 0 };
1080 char dest[NI_MAXHOST] = { 0 };
1081 struct addrinfo *ai = NULL;
1082 int port = 0;
1083 int family = from->sa_family;
1084 int err;
1085 err = bctbx_sockaddr_to_ip_address(from, fromlen, dest, sizeof(dest), &port);
1086 if (err != 0) {
1087 ortp_error("bctbx_sockaddr_to_ip_address failed");
1088 return NULL;
1089 }
1090 err = bctbx_get_local_ip_for(family, dest, port, result, sizeof(result));
1091 if (err != 0) {
1092 ortp_error("bctbx_get_local_ip_for failed: dest=%s, port=%d", dest, port);
1093 return NULL;
1094 }
1095 ai = bctbx_ip_address_to_addrinfo(family, SOCK_DGRAM, result, port);
1096 if (ai == NULL) {
1097 ortp_error("bctbx_ip_address_to_addrinfo failed: result=%s, port=%d", result, port);
1098 return NULL;
1099 } else {
1100 ortp_recv_addr_map_t *item = bctbx_new0(ortp_recv_addr_map_t, 1);
1101 memcpy(&item->ss, from, fromlen);
1102 item->recv_addr.family = family;
1103 if (family == AF_INET) {
1104 memcpy(&item->recv_addr.addr.ipi_addr, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(item->recv_addr.addr.ipi_addr));
1105 } else if (family == AF_INET6) {
1106 memcpy(&item->recv_addr.addr.ipi6_addr, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, sizeof(item->recv_addr.addr.ipi6_addr));
1107 }
1108 bctbx_freeaddrinfo(ai);
1109 item->ts = ortp_get_cur_time_ms();
1110 session->recv_addr_map = bctbx_list_append(session->recv_addr_map, item);
1111 return &item->recv_addr;
1112 }
1113 }
1114
rtp_session_recvfrom(RtpSession * session,bool_t is_rtp,mblk_t * m,int flags,struct sockaddr * from,socklen_t * fromlen)1115 int rtp_session_recvfrom(RtpSession *session, bool_t is_rtp, mblk_t *m, int flags, struct sockaddr *from, socklen_t *fromlen) {
1116 int ret = rtp_session_rtp_recv_abstract(is_rtp ? session->rtp.gs.socket : session->rtcp.gs.socket, m, flags, from, fromlen);
1117 if ((ret >= 0) && (session->use_pktinfo == TRUE)) {
1118 if (m->recv_addr.family == AF_UNSPEC) {
1119 /* The receive address has not been filled, this typically happens on Mac OS X when receiving an IPv4 packet on
1120 * a dual stack socket. Try to guess the address because it is mandatory for ICE. */
1121 const ortp_recv_addr_t *recv_addr = lookup_recv_addr(session, from, *fromlen);
1122 if (recv_addr == NULL) {
1123 recv_addr = get_recv_addr(session, from, *fromlen);
1124 }
1125 if (recv_addr != NULL) {
1126 memcpy(&m->recv_addr, recv_addr, sizeof(ortp_recv_addr_t));
1127 } else {
1128 ortp_error("Did not succeed to fill the receive address, this should not happen! [family=%d, len=%d]", from->sa_family, (int)*fromlen);
1129 }
1130 }
1131 /* Store the local port in the recv_addr of the mblk_t, the address is already filled in rtp_session_rtp_recv_abstract */
1132 m->recv_addr.port = htons(is_rtp ? session->rtp.gs.loc_port : session->rtcp.gs.loc_port);
1133 }
1134 return ret;
1135 }
1136
update_sent_bytes(OrtpStream * os,int nbytes)1137 void update_sent_bytes(OrtpStream *os, int nbytes) {
1138 int overhead = ortp_stream_is_ipv6(os) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
1139 if ((os->sent_bytes == 0) && (os->send_bw_start.tv_sec == 0) && (os->send_bw_start.tv_usec == 0)) {
1140 /* Initialize bandwidth computing time when has not been started yet. */
1141 ortp_gettimeofday(&os->send_bw_start, NULL);
1142 }
1143 os->sent_bytes += nbytes + overhead;
1144 }
1145
update_recv_bytes(OrtpStream * os,size_t nbytes,const struct timeval * recv_time)1146 static void update_recv_bytes(OrtpStream *os, size_t nbytes, const struct timeval *recv_time) {
1147 int overhead = ortp_stream_is_ipv6(os) ? IP6_UDP_OVERHEAD : IP_UDP_OVERHEAD;
1148 if ((os->recv_bytes == 0) && (os->recv_bw_start.tv_sec == 0) && (os->recv_bw_start.tv_usec == 0)) {
1149 ortp_gettimeofday(&os->recv_bw_start, NULL);
1150 }
1151 os->recv_bytes += (unsigned int)(nbytes + overhead);
1152 ortp_bw_estimator_packet_received(&os->recv_bw_estimator, nbytes + overhead, recv_time);
1153 }
1154
log_send_error(RtpSession * session,const char * type,mblk_t * m,struct sockaddr * destaddr,socklen_t destlen)1155 static void log_send_error(RtpSession *session, const char *type, mblk_t *m, struct sockaddr *destaddr, socklen_t destlen){
1156 char printable_ip_address[65]={0};
1157 int errnum = getSocketErrorCode();
1158 const char *errstr = getSocketError();
1159 bctbx_sockaddr_to_printable_ip_address(destaddr, destlen, printable_ip_address, sizeof(printable_ip_address));
1160 ortp_error ("RtpSession [%p] error sending [%s] packet [%p] to %s: %s [%d]",
1161 session, type, m, printable_ip_address, errstr, errnum);
1162 }
1163
rtp_session_rtp_sendto(RtpSession * session,mblk_t * m,struct sockaddr * destaddr,socklen_t destlen,bool_t is_aux)1164 static int rtp_session_rtp_sendto(RtpSession * session, mblk_t * m, struct sockaddr *destaddr, socklen_t destlen, bool_t is_aux){
1165 int error;
1166
1167 if (rtp_session_using_transport(session, rtp)){
1168 error = (session->rtp.gs.tr->t_sendto) (session->rtp.gs.tr,m,0,destaddr,destlen);
1169 }else{
1170 error=rtp_session_sendto(session, TRUE,m,0,destaddr,destlen);
1171 }
1172 if (!is_aux){
1173 /*errors to auxiliary destinations are not notified*/
1174 if (error < 0){
1175 if (session->on_network_error.count>0){
1176 rtp_signal_table_emit3(&session->on_network_error,"Error sending RTP packet",ORTP_INT_TO_POINTER(getSocketErrorCode()));
1177 }else log_send_error(session,"rtp",m,destaddr,destlen);
1178 session->rtp.send_errno=getSocketErrorCode();
1179 }else{
1180 update_sent_bytes(&session->rtp.gs, error);
1181 }
1182 }
1183 return error;
1184 }
1185
rtp_session_rtp_send(RtpSession * session,mblk_t * m)1186 int rtp_session_rtp_send (RtpSession * session, mblk_t * m){
1187 int error=0;
1188 int i;
1189 rtp_header_t *hdr;
1190 struct sockaddr *destaddr=(struct sockaddr*)&session->rtp.gs.rem_addr;
1191 socklen_t destlen=session->rtp.gs.rem_addrlen;
1192 OList *elem=NULL;
1193
1194 if (session->is_spliced) {
1195 freemsg(m);
1196 return 0;
1197 }
1198
1199 hdr = (rtp_header_t *) m->b_rptr;
1200 if (hdr->version == 0) {
1201 /* We are probably trying to send a STUN packet so don't change its content. */
1202 } else {
1203 /* perform host to network conversions */
1204 hdr->ssrc = htonl (hdr->ssrc);
1205 hdr->timestamp = htonl (hdr->timestamp);
1206 hdr->seq_number = htons (hdr->seq_number);
1207 for (i = 0; i < hdr->cc; i++)
1208 hdr->csrc[i] = htonl (hdr->csrc[i]);
1209 }
1210
1211 if (session->flags & RTP_SOCKET_CONNECTED) {
1212 destaddr=NULL;
1213 destlen=0;
1214 }
1215 /*first send to main destination*/
1216 error=rtp_session_rtp_sendto(session,m,destaddr,destlen,FALSE);
1217 /*then iterate over auxiliary destinations*/
1218 for(elem=session->rtp.gs.aux_destinations;elem!=NULL;elem=elem->next){
1219 OrtpAddress *addr=(OrtpAddress*)elem->data;
1220 rtp_session_rtp_sendto(session,m,(struct sockaddr*)&addr->addr,addr->len,TRUE);
1221 }
1222 freemsg(m);
1223 return error;
1224 }
1225
rtp_session_rtcp_sendto(RtpSession * session,mblk_t * m,struct sockaddr * destaddr,socklen_t destlen,bool_t is_aux)1226 static int rtp_session_rtcp_sendto(RtpSession * session, mblk_t * m, struct sockaddr *destaddr, socklen_t destlen, bool_t is_aux){
1227 int error=0;
1228
1229 /* Even in RTCP mux, we send through the RTCP RtpTransport, which will itself take in charge to do the sending of the packet
1230 * through the RTP endpoint*/
1231 if (rtp_session_using_transport(session, rtcp)){
1232 error = (session->rtcp.gs.tr->t_sendto) (session->rtcp.gs.tr, m, 0, destaddr, destlen);
1233 }else{
1234 error=_ortp_sendto(rtp_session_get_socket(session, session->rtcp_mux),m,0,destaddr,destlen);
1235 }
1236
1237 if (!is_aux){
1238 if (error < 0){
1239 if (session->on_network_error.count>0){
1240 rtp_signal_table_emit3(&session->on_network_error,"Error sending RTCP packet",ORTP_INT_TO_POINTER(getSocketErrorCode()));
1241 }else{
1242 log_send_error(session,"rtcp",m,destaddr,destlen);
1243 }
1244 } else {
1245 update_sent_bytes(&session->rtcp.gs, error);
1246 update_avg_rtcp_size(session, error);
1247 }
1248 }
1249 return error;
1250 }
1251
1252 int
rtp_session_rtcp_send(RtpSession * session,mblk_t * m)1253 rtp_session_rtcp_send (RtpSession * session, mblk_t * m){
1254 int error=0;
1255 ortp_socket_t sockfd=session->rtcp.gs.socket;
1256 struct sockaddr *destaddr=session->rtcp_mux ? (struct sockaddr*)&session->rtp.gs.rem_addr : (struct sockaddr*)&session->rtcp.gs.rem_addr;
1257 socklen_t destlen=session->rtcp_mux ? session->rtp.gs.rem_addrlen : session->rtcp.gs.rem_addrlen;
1258 OList *elem=NULL;
1259 bool_t using_connected_socket=(session->flags & RTCP_SOCKET_CONNECTED)!=0;
1260
1261 if (session->is_spliced) {
1262 freemsg(m);
1263 return 0;
1264 }
1265 if (using_connected_socket) {
1266 destaddr=NULL;
1267 destlen=0;
1268 }
1269
1270 if (session->rtcp.enabled){
1271 if ( (sockfd!=(ortp_socket_t)-1 && (destlen>0 || using_connected_socket))
1272 || rtp_session_using_transport(session, rtcp) ) {
1273 rtp_session_rtcp_sendto(session,m,destaddr,destlen,FALSE);
1274 }
1275 for(elem=session->rtcp.gs.aux_destinations;elem!=NULL;elem=elem->next){
1276 OrtpAddress *addr=(OrtpAddress*)elem->data;
1277 rtp_session_rtcp_sendto(session,m,(struct sockaddr*)&addr->addr,addr->len,TRUE);
1278 }
1279 }else ortp_message("Not sending rtcp report, rtcp disabled.");
1280 freemsg(m);
1281 return error;
1282 }
1283
rtp_session_rtp_recv_abstract(ortp_socket_t socket,mblk_t * msg,int flags,struct sockaddr * from,socklen_t * fromlen)1284 int rtp_session_rtp_recv_abstract(ortp_socket_t socket, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen) {
1285 int ret;
1286 int bufsz = (int) (msg->b_datap->db_lim - msg->b_datap->db_base);
1287 #ifndef _WIN32
1288 struct iovec iov;
1289 struct msghdr msghdr;
1290 struct cmsghdr *cmsghdr;
1291 char control[512];
1292 memset(&msghdr, 0, sizeof(msghdr));
1293 memset(&iov, 0, sizeof(iov));
1294 iov.iov_base = msg->b_wptr;
1295 iov.iov_len = bufsz;
1296 if(from != NULL && fromlen != NULL) {
1297 msghdr.msg_name = from;
1298 msghdr.msg_namelen = *fromlen;
1299 }
1300 msghdr.msg_iov = &iov;
1301 msghdr.msg_iovlen = 1;
1302 msghdr.msg_control = &control;
1303 msghdr.msg_controllen = sizeof(control);
1304 ret = recvmsg(socket, &msghdr, flags);
1305 if(fromlen != NULL)
1306 *fromlen = msghdr.msg_namelen;
1307 if(ret >= 0) {
1308 #else
1309 char control[512];
1310 WSAMSG msghdr;
1311 WSACMSGHDR *cmsghdr;
1312 WSABUF data_buf;
1313 DWORD bytes_received;
1314
1315 if (ortp_WSARecvMsg == NULL) {
1316 return recvfrom(socket, (char *)msg->b_wptr, bufsz, flags, from, fromlen);
1317 }
1318
1319 memset(&msghdr, 0, sizeof(msghdr));
1320 memset(control, 0, sizeof(control));
1321 if(from != NULL && fromlen != NULL) {
1322 msghdr.name = from;
1323 msghdr.namelen = *fromlen;
1324 }
1325 data_buf.buf = (char *)msg->b_wptr;
1326 data_buf.len = bufsz;
1327 msghdr.lpBuffers = &data_buf;
1328 msghdr.dwBufferCount = 1;
1329 msghdr.Control.buf = control;
1330 msghdr.Control.len = sizeof(control);
1331 msghdr.dwFlags = flags;
1332 ret = ortp_WSARecvMsg(socket, &msghdr, &bytes_received, NULL, NULL);
1333 if(fromlen != NULL)
1334 *fromlen = msghdr.namelen;
1335 if(ret >= 0) {
1336 ret = bytes_received;
1337 #endif
1338 for (cmsghdr = CMSG_FIRSTHDR(&msghdr); cmsghdr != NULL ; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) {
1339 #ifdef SO_TIMESTAMP
1340 if (cmsghdr->cmsg_level == SOL_SOCKET && cmsghdr->cmsg_type == SCM_TIMESTAMP) {
1341 memcpy(&msg->timestamp, (struct timeval *)CMSG_DATA(cmsghdr), sizeof(struct timeval));
1342 }
1343 #endif
1344 #ifdef IP_PKTINFO
1345 if ((cmsghdr->cmsg_level == IPPROTO_IP) && (cmsghdr->cmsg_type == IP_PKTINFO)) {
1346 struct in_pktinfo *pi = (struct in_pktinfo *)CMSG_DATA(cmsghdr);
1347 memcpy(&msg->recv_addr.addr.ipi_addr, &pi->ipi_addr, sizeof(msg->recv_addr.addr.ipi_addr));
1348 msg->recv_addr.family = AF_INET;
1349 }
1350 #endif
1351 #ifdef IPV6_PKTINFO
1352 if ((cmsghdr->cmsg_level == IPPROTO_IPV6) && (cmsghdr->cmsg_type == IPV6_PKTINFO)) {
1353 struct in6_pktinfo *pi = (struct in6_pktinfo *)CMSG_DATA(cmsghdr);
1354 memcpy(&msg->recv_addr.addr.ipi6_addr, &pi->ipi6_addr, sizeof(msg->recv_addr.addr.ipi6_addr));
1355 msg->recv_addr.family = AF_INET6;
1356 }
1357 #endif
1358 #ifdef IP_RECVDSTADDR
1359 if ((cmsghdr->cmsg_level == IPPROTO_IP) && (cmsghdr->cmsg_type == IP_RECVDSTADDR)) {
1360 struct in_addr *ia = (struct in_addr *)CMSG_DATA(cmsghdr);
1361 memcpy(&msg->recv_addr.addr.ipi_addr, ia, sizeof(msg->recv_addr.addr.ipi_addr));
1362 msg->recv_addr.family = AF_INET;
1363 }
1364 #endif
1365 #ifdef IPV6_RECVDSTADDR
1366 if ((cmsghdr->cmsg_level == IPPROTO_IPV6) && (cmsghdr->cmsg_type == IPV6_RECVDSTADDR)) {
1367 struct in6_addr *ia = (struct in6_addr *)CMSG_DATA(cmsghdr);
1368 memcpy(&msg->recv_addr.addr.ipi6_addr, ia, sizeof(msg->recv_addr.addr.ipi6_addr));
1369 msg->recv_addr.family = AF_INET6;
1370 }
1371 #endif
1372 #ifdef IP_RECVTTL
1373 if ((cmsghdr->cmsg_level == IPPROTO_IP) && (cmsghdr->cmsg_type == IP_TTL)) {
1374 uint32_t *ptr = (uint32_t *)CMSG_DATA(cmsghdr);
1375 msg->ttl_or_hl = (*ptr & 0xFF);
1376 }
1377 #endif
1378 #ifdef IPV6_RECVHOPLIMIT
1379 if ((cmsghdr->cmsg_level == IPPROTO_IPV6) && (cmsghdr->cmsg_type == IPV6_HOPLIMIT)) {
1380 uint32_t *ptr = (uint32_t *)CMSG_DATA(cmsghdr);
1381 msg->ttl_or_hl = (*ptr & 0xFF);
1382 }
1383 #endif
1384 }
1385
1386 if (msg->timestamp.tv_sec == 0){
1387 static int warn_once = 1; /*VERY BAD to use a static but there is no context in this function to hold this variable*/
1388 if (warn_once){
1389 ortp_warning("This platform doesn't implement SO_TIMESTAMP, will use gettimeofday() instead.");
1390 warn_once = 0;
1391 }
1392 ortp_gettimeofday(&msg->timestamp, NULL);
1393 }
1394 /*store recv addr for use by modifiers*/
1395 if (from && fromlen) {
1396 memcpy(&msg->net_addr,from,*fromlen);
1397 msg->net_addrlen = *fromlen;
1398 }
1399 }
1400 return ret;
1401 }
1402
1403 void rtp_session_notify_inc_rtcp(RtpSession *session, mblk_t *m, bool_t received_via_rtcp_mux){
1404 if (session->eventqs!=NULL){
1405 OrtpEvent *ev=ortp_event_new(ORTP_EVENT_RTCP_PACKET_RECEIVED);
1406 OrtpEventData *d=ortp_event_get_data(ev);
1407 d->packet=m;
1408 d->info.socket_type = received_via_rtcp_mux ? OrtpRTPSocket : OrtpRTCPSocket;
1409 rtp_session_dispatch_event(session,ev);
1410 }
1411 else freemsg(m); /* avoid memory leak */
1412 }
1413
1414 static void compute_rtt(RtpSession *session, const struct timeval *now, uint32_t lrr, uint32_t dlrr){
1415 uint64_t curntp=ortp_timeval_to_ntp(now);
1416 uint32_t approx_ntp=(curntp>>16) & 0xFFFFFFFF;
1417 /*ortp_message("rtt approx_ntp=%u, lrr=%u, dlrr=%u",approx_ntp,lrr,dlrr);*/
1418 if (lrr!=0 && dlrr!=0){
1419 /*we cast to int32_t to check for crazy RTT time (negative)*/
1420 double rtt_frac=(int32_t)(approx_ntp-lrr-dlrr);
1421 if (rtt_frac>=0){
1422 rtt_frac/=65536.0;
1423
1424 session->rtt=(float)rtt_frac;
1425 /*ortp_message("rtt estimated to %f s",session->rtt);*/
1426 }else ortp_warning("Negative RTT computation, maybe due to clock adjustments.");
1427 }
1428 }
1429
1430 static void compute_rtt_from_report_block(RtpSession *session, const struct timeval *now, const report_block_t *rb) {
1431 uint32_t last_sr_time = report_block_get_last_SR_time(rb);
1432 uint32_t sr_delay = report_block_get_last_SR_delay(rb);
1433 compute_rtt(session, now, last_sr_time, sr_delay);
1434 session->cum_loss = report_block_get_cum_packet_lost(rb);
1435 }
1436
1437 static void compute_rtcp_xr_statistics(RtpSession *session, mblk_t *block, const struct timeval *now) {
1438 uint64_t ntp_timestamp;
1439 OrtpRtcpXrStats *stats = &session->rtcp_xr_stats;
1440
1441 switch (rtcp_XR_get_block_type(block)) {
1442 case RTCP_XR_RCVR_RTT:
1443 ntp_timestamp = rtcp_XR_rcvr_rtt_get_ntp_timestamp(block);
1444 stats->last_rcvr_rtt_ts = (ntp_timestamp >> 16) & 0xffffffff;
1445 stats->last_rcvr_rtt_time.tv_sec = now->tv_sec;
1446 stats->last_rcvr_rtt_time.tv_usec = now->tv_usec;
1447 break;
1448 case RTCP_XR_DLRR:
1449 compute_rtt(session, now, rtcp_XR_dlrr_get_lrr(block), rtcp_XR_dlrr_get_dlrr(block));
1450 break;
1451 default:
1452 break;
1453 }
1454 }
1455
1456 static void handle_rtcp_rtpfb_packet(RtpSession *session, mblk_t *block) {
1457 switch (rtcp_RTPFB_get_type(block)) {
1458 case RTCP_RTPFB_TMMBR:
1459 if (session->rtcp.tmmbr_info.received) freemsg(session->rtcp.tmmbr_info.received);
1460 session->rtcp.tmmbr_info.received = copymsg(block);
1461 rtp_session_send_rtcp_fb_tmmbn(session, rtcp_RTPFB_get_packet_sender_ssrc(block));
1462 break;
1463 case RTCP_RTPFB_TMMBN:
1464 if (session->rtcp.tmmbr_info.sent) {
1465 rtcp_fb_tmmbr_fci_t *tmmbn_fci = rtcp_RTPFB_tmmbr_get_fci(block);
1466 rtcp_fb_tmmbr_fci_t *tmmbr_fci = rtcp_RTPFB_tmmbr_get_fci(session->rtcp.tmmbr_info.sent);
1467 if ((ntohl(tmmbn_fci->ssrc) == rtp_session_get_send_ssrc(session)) && (tmmbn_fci->value == tmmbr_fci->value)) {
1468 freemsg(session->rtcp.tmmbr_info.sent);
1469 session->rtcp.tmmbr_info.sent = NULL;
1470 }
1471 }
1472 break;
1473 default:
1474 break;
1475 }
1476 }
1477
1478 /*
1479 * @brief : for SR packets, retrieves their timestamp, gets the date, and stores these information into the session descriptor. The date values may be used for setting some fields of the report block of the next RTCP packet to be sent.
1480 * @param session : the current session descriptor.
1481 * @param block : the block descriptor that may contain a SR RTCP message.
1482 * @return 0 if the packet is a real RTCP packet, -1 otherwise.
1483 * @note a basic parsing is done on the block structure. However, if it fails, no error is returned, and the session descriptor is left as is, so it does not induce any change in the caller procedure behaviour.
1484 * @note the packet is freed or is taken ownership if -1 is returned
1485 */
1486 static int process_rtcp_packet( RtpSession *session, mblk_t *block, struct sockaddr *addr, socklen_t addrlen ) {
1487 rtcp_common_header_t *rtcp;
1488 RtpStream * rtpstream = &session->rtp;
1489
1490 int msgsize = (int) ( block->b_wptr - block->b_rptr );
1491 if ( msgsize < RTCP_COMMON_HEADER_SIZE ) {
1492 ortp_warning( "Receiving a too short RTCP packet" );
1493 freemsg(block);
1494 return -1;
1495 }
1496
1497 rtcp = (rtcp_common_header_t *)block->b_rptr;
1498
1499 if (rtcp->version != 2){
1500 /* try to see if it is a STUN packet */
1501 uint16_t stunlen = *((uint16_t *)(block->b_rptr + sizeof(uint16_t)));
1502 stunlen = ntohs(stunlen);
1503 if (stunlen + 20 == block->b_wptr - block->b_rptr) {
1504 /* this looks like a stun packet */
1505 rtp_session_update_remote_sock_addr(session, block, FALSE, TRUE);
1506
1507 if (session->eventqs != NULL) {
1508 OrtpEvent *ev = ortp_event_new(ORTP_EVENT_STUN_PACKET_RECEIVED);
1509 OrtpEventData *ed = ortp_event_get_data(ev);
1510 ed->packet = block;
1511 ed->source_addrlen=addrlen;
1512 memcpy(&ed->source_addr,addr,addrlen);
1513 ed->info.socket_type = OrtpRTCPSocket;
1514 rtp_session_dispatch_event(session, ev);
1515 return -1;
1516 }
1517 }else{
1518 ortp_warning("RtpSession [%p] receiving rtcp packet with version number != 2, discarded", session);
1519 }
1520 freemsg(block);
1521 return -1;
1522 }
1523
1524 update_recv_bytes(&session->rtcp.gs, (int)(block->b_wptr - block->b_rptr), &block->timestamp);
1525
1526 /* compound rtcp packet can be composed by more than one rtcp message */
1527 do{
1528 struct timeval reception_date;
1529 const report_block_t *rb;
1530
1531 /* Getting the reception date from the main clock */
1532 ortp_gettimeofday( &reception_date, NULL );
1533
1534 if (rtcp_is_SR(block) ) {
1535 rtcp_sr_t *sr = (rtcp_sr_t *) rtcp;
1536
1537 /* The session descriptor values are reset in case there is an error in the SR block parsing */
1538 rtpstream->last_rcv_SR_ts = 0;
1539 rtpstream->last_rcv_SR_time.tv_usec = 0;
1540 rtpstream->last_rcv_SR_time.tv_sec = 0;
1541
1542 if ( ntohl( sr->ssrc ) != session->rcv.ssrc ) {
1543 ortp_debug( "Receiving a RTCP SR packet from an unknown ssrc" );
1544 return 0;
1545 }
1546
1547 if ( msgsize < RTCP_COMMON_HEADER_SIZE + RTCP_SSRC_FIELD_SIZE + RTCP_SENDER_INFO_SIZE + ( RTCP_REPORT_BLOCK_SIZE * sr->ch.rc ) ) {
1548 ortp_debug( "Receiving a too short RTCP SR packet" );
1549 return 0;
1550 }
1551
1552 /* Saving the data to fill LSR and DLSR field in next RTCP report to be transmitted */
1553 /* This value will be the LSR field of the next RTCP report (only the central 32 bits are kept, as described in par.4 of RC3550) */
1554 rtpstream->last_rcv_SR_ts = ( ntohl( sr->si.ntp_timestamp_msw ) << 16 ) | ( ntohl( sr->si.ntp_timestamp_lsw ) >> 16 );
1555 /* This value will help in processing the DLSR of the next RTCP report ( see report_block_init() in rtcp.cc ) */
1556 rtpstream->last_rcv_SR_time.tv_usec = reception_date.tv_usec;
1557 rtpstream->last_rcv_SR_time.tv_sec = reception_date.tv_sec;
1558 rb=rtcp_SR_get_report_block(block,0);
1559 if (rb) compute_rtt_from_report_block(session,&reception_date,rb);
1560 }else if ( rtcp_is_RR(block)){
1561 rb=rtcp_RR_get_report_block(block,0);
1562 if (rb) compute_rtt_from_report_block(session,&reception_date,rb);
1563 } else if (rtcp_is_XR(block)) {
1564 compute_rtcp_xr_statistics(session, block, &reception_date);
1565 } else if (rtcp_is_RTPFB(block)) {
1566 handle_rtcp_rtpfb_packet(session, block);
1567 }
1568 }while (rtcp_next_packet(block));
1569 rtcp_rewind(block);
1570
1571 rtp_session_update_remote_sock_addr(session, block, FALSE, FALSE);
1572 return 0;
1573 }
1574
1575 static void reply_to_collaborative_rtcp_xr_packet(RtpSession *session, mblk_t *block) {
1576 if (rtcp_is_XR(block) && (rtcp_XR_get_block_type(block) == RTCP_XR_RCVR_RTT)) {
1577 session->rtcp.rtcp_xr_dlrr_to_send = TRUE;
1578 }
1579 }
1580
1581 static void rtp_process_incoming_packet(RtpSession * session, mblk_t * mp, bool_t is_rtp_packet, uint32_t user_ts, bool_t received_via_rtcp_mux) {
1582 bool_t sock_connected=(is_rtp_packet && !!(session->flags & RTP_SOCKET_CONNECTED))
1583 || (!is_rtp_packet && !!(session->flags & RTCP_SOCKET_CONNECTED));
1584
1585 struct sockaddr *remaddr = NULL;
1586 socklen_t addrlen;
1587 remaddr = (struct sockaddr *)&mp->net_addr;
1588 addrlen = mp->net_addrlen;
1589
1590
1591 if (session->spliced_session){
1592 /*this will forward all traffic to the spliced session*/
1593 rtp_session_do_splice(session, mp, is_rtp_packet);
1594 }
1595
1596 /*
1597 * Symmetric RTP policy
1598 * - if a STUN packet is received AND it is the first packet received, switch destination.
1599 * - if a RTP or RTCP packet is received, switch destination.
1600 * In all other cases, we don't switch.
1601 * This logic is implemented in rtp_session_rtp_parse() and process_rtcp_packet().
1602 **/
1603
1604 if (is_rtp_packet){
1605 if (session->use_connect && session->symmetric_rtp && !sock_connected ){
1606 /* In the case where use_connect is false, */
1607 if (try_connect(session->rtp.gs.socket,remaddr,addrlen)) {
1608 session->flags|=RTP_SOCKET_CONNECTED;
1609 }
1610 }
1611 /* then parse the message and put on jitter buffer queue */
1612 update_recv_bytes(&session->rtp.gs, (size_t)(mp->b_wptr - mp->b_rptr), &mp->timestamp);
1613 rtp_session_rtp_parse(session, mp, user_ts, remaddr,addrlen);
1614 /*for bandwidth measurements:*/
1615 }else {
1616 if (session->use_connect && session->symmetric_rtp && !sock_connected){
1617 if (try_connect(session->rtcp.gs.socket,remaddr,addrlen)) {
1618 session->flags|=RTCP_SOCKET_CONNECTED;
1619 }
1620 }
1621 if (process_rtcp_packet(session, mp, remaddr, addrlen) == 0){
1622 /* a copy is needed since rtp_session_notify_inc_rtcp will free the mp,
1623 and we don't want to send RTCP XR packet before notifying the application
1624 that a message has been received*/
1625 mblk_t * copy = copymsg(mp);
1626 session->stats.recv_rtcp_packets++;
1627 /* post an event to notify the application */
1628 rtp_session_notify_inc_rtcp(session, mp, received_via_rtcp_mux);
1629 /* reply to collaborative RTCP XR packets if needed. */
1630 if (session->rtcp.xr_conf.enabled == TRUE){
1631 reply_to_collaborative_rtcp_xr_packet(session, copy);
1632 }
1633 freemsg(copy);
1634 }
1635 }
1636 }
1637
1638 void rtp_session_process_incoming(RtpSession * session, mblk_t *mp, bool_t is_rtp_packet, uint32_t ts, bool_t received_via_rtcp_mux) {
1639 if (session->net_sim_ctx && session->net_sim_ctx->params.mode == OrtpNetworkSimulatorInbound) {
1640 /*drain possible packets queued in the network simulator*/
1641 mp = rtp_session_network_simulate(session, mp, &is_rtp_packet);
1642 if (mp) rtp_process_incoming_packet(session, mp, is_rtp_packet, ts, received_via_rtcp_mux); /*BUG here: received_via_rtcp_mux is not preserved by network simulator*/
1643 } else if (mp != NULL) {
1644 rtp_process_incoming_packet(session, mp, is_rtp_packet, ts, received_via_rtcp_mux);
1645 }
1646 }
1647
1648 int rtp_session_rtp_recv (RtpSession * session, uint32_t user_ts) {
1649 int error;
1650 struct sockaddr_storage remaddr;
1651 socklen_t addrlen = sizeof (remaddr);
1652 mblk_t *mp;
1653
1654 if ((session->rtp.gs.socket==(ortp_socket_t)-1) && !rtp_session_using_transport(session, rtp)) return -1; /*session has no sockets for the moment*/
1655
1656 while (1)
1657 {
1658 bool_t sock_connected=!!(session->flags & RTP_SOCKET_CONNECTED);
1659
1660 mp = msgb_allocator_alloc(&session->rtp.gs.allocator, session->recv_buf_size);
1661 mp->reserved1 = user_ts;
1662
1663 if (sock_connected){
1664 error=rtp_session_recvfrom(session, TRUE, mp, 0, NULL, NULL);
1665 }else if (rtp_session_using_transport(session, rtp)) {
1666 error = (session->rtp.gs.tr->t_recvfrom)(session->rtp.gs.tr, mp, 0, (struct sockaddr *) &remaddr, &addrlen);
1667 } else {
1668 error = rtp_session_recvfrom(session, TRUE, mp, 0, (struct sockaddr *) &remaddr, &addrlen);
1669 }
1670 if (error > 0){
1671 mp->b_wptr+=error;
1672 rtp_session_process_incoming(session, mp, TRUE, user_ts, FALSE);
1673 }
1674 else
1675 {
1676 int errnum;
1677 if (error==-1 && !is_would_block_error((errnum=getSocketErrorCode())) )
1678 {
1679 if (session->on_network_error.count>0){
1680 rtp_signal_table_emit3(&session->on_network_error,"Error receiving RTP packet",ORTP_INT_TO_POINTER(getSocketErrorCode()));
1681 }else ortp_warning("Error receiving RTP packet: %s, err num [%i],error [%i]",getSocketError(),errnum,error);
1682 #if TARGET_OS_IPHONE
1683 /*hack for iOS and non-working socket because of background mode*/
1684 if (errnum==ENOTCONN){
1685 /*re-create new sockets */
1686 rtp_session_set_local_addr(session,session->rtp.gs.sockfamily==AF_INET ? "0.0.0.0" : "::0",session->rtp.gs.loc_port,session->rtcp.gs.loc_port);
1687 }
1688 #endif
1689 }else{
1690 /*EWOULDBLOCK errors or transports returning 0 are ignored.*/
1691 rtp_session_process_incoming(session, NULL, TRUE, user_ts, FALSE);
1692 }
1693 freemsg(mp);
1694 return -1;
1695 }
1696 }
1697 return error;
1698 }
1699
1700 int rtp_session_rtcp_recv (RtpSession * session) {
1701 int error;
1702 struct sockaddr_storage remaddr;
1703
1704 socklen_t addrlen = sizeof (remaddr);
1705 mblk_t *mp;
1706
1707 if (session->rtcp.gs.socket==(ortp_socket_t)-1 && !rtp_session_using_transport(session, rtcp)) return -1; /*session has no RTCP sockets for the moment*/
1708
1709
1710 while (1)
1711 {
1712 bool_t sock_connected=!!(session->flags & RTCP_SOCKET_CONNECTED);
1713
1714 mp = msgb_allocator_alloc(&session->rtp.gs.allocator, RTCP_MAX_RECV_BUFSIZE);
1715 mp->reserved1 = session->rtp.rcv_last_app_ts;
1716
1717 if (sock_connected){
1718 error=rtp_session_recvfrom(session, FALSE, mp, 0, NULL, NULL);
1719 }else{
1720 addrlen=sizeof (remaddr);
1721
1722 if (rtp_session_using_transport(session, rtcp)){
1723 error=(session->rtcp.gs.tr->t_recvfrom)(session->rtcp.gs.tr, mp, 0,
1724 (struct sockaddr *) &remaddr,
1725 &addrlen);
1726 }else{
1727 error=rtp_session_recvfrom(session, FALSE, mp, 0,
1728 (struct sockaddr *) &remaddr,
1729 &addrlen);
1730 }
1731 }
1732 if (error > 0)
1733 {
1734 mp->b_wptr += error;
1735 rtp_session_process_incoming(session, mp, FALSE, session->rtp.rcv_last_app_ts, FALSE);
1736 }
1737 else
1738 {
1739 int errnum;
1740 if (error==-1 && !is_would_block_error((errnum=getSocketErrorCode())) )
1741 {
1742 if (session->on_network_error.count>0){
1743 rtp_signal_table_emit3(&session->on_network_error,"Error receiving RTCP packet",ORTP_INT_TO_POINTER(getSocketErrorCode()));
1744 }else ortp_warning("Error receiving RTCP packet: %s, err num [%i],error [%i]",getSocketError(),errnum,error);
1745 #if TARGET_OS_IPHONE
1746 /*hack for iOS and non-working socket because of background mode*/
1747 if (errnum==ENOTCONN){
1748 /*re-create new sockets */
1749 rtp_session_set_local_addr(session,session->rtcp.gs.sockfamily==AF_INET ? "0.0.0.0" : "::0",session->rtcp.gs.loc_port,session->rtcp.gs.loc_port);
1750 }
1751 #endif
1752 session->rtp.recv_errno=errnum;
1753 }else{
1754 /*EWOULDBLOCK errors or transports returning 0 are ignored.*/
1755 rtp_session_process_incoming(session, NULL, FALSE, session->rtp.rcv_last_app_ts, FALSE);
1756 }
1757
1758 freemsg(mp);
1759 return -1; /* avoids an infinite loop ! */
1760 }
1761 }
1762 return error;
1763 }
1764
1765 int rtp_session_update_remote_sock_addr(RtpSession * session, mblk_t * mp, bool_t is_rtp,bool_t only_at_start) {
1766 struct sockaddr_storage * rem_addr = NULL;
1767 socklen_t *rem_addrlen;
1768 const char* socket_type;
1769 bool_t sock_connected;
1770 bool_t do_address_change = /*(rtp_get_version(mp) == 2 && */ !only_at_start;
1771
1772 if (!rtp_session_get_symmetric_rtp(session))
1773 return -1; /*nothing to try if not rtp symetric*/
1774
1775 if (is_rtp) {
1776 rem_addr = &session->rtp.gs.rem_addr;
1777 rem_addrlen = &session->rtp.gs.rem_addrlen;
1778 socket_type = "rtp";
1779 sock_connected = session->flags & RTP_SOCKET_CONNECTED;
1780 do_address_change = session->rtp.gs.socket != (ortp_socket_t)-1 && ( do_address_change || rtp_session_get_stats(session)->packet_recv == 0);
1781 } else {
1782 rem_addr = &session->rtcp.gs.rem_addr;
1783 rem_addrlen = &session->rtcp.gs.rem_addrlen;
1784 sock_connected = session->flags & RTCP_SOCKET_CONNECTED;
1785 socket_type = "rtcp";
1786 do_address_change = session->rtcp.gs.socket != (ortp_socket_t)-1 && (do_address_change || rtp_session_get_stats(session)->recv_rtcp_packets == 0);
1787 }
1788
1789 if (do_address_change
1790 && rem_addr
1791 && !sock_connected
1792 && !ortp_is_multicast_addr((const struct sockaddr*)rem_addr)
1793 && memcmp(rem_addr,&mp->net_addr,mp->net_addrlen) !=0) {
1794 char current_ip_address[64]={0};
1795 char new_ip_address[64]={0};
1796
1797 bctbx_sockaddr_to_printable_ip_address((struct sockaddr *)rem_addr, *rem_addrlen, current_ip_address, sizeof(current_ip_address));
1798 bctbx_sockaddr_to_printable_ip_address((struct sockaddr *)&mp->net_addr, mp->net_addrlen, new_ip_address, sizeof(new_ip_address));
1799 ortp_message("Switching %s destination from %s to %s for session [%p]"
1800 , socket_type
1801 , current_ip_address
1802 , new_ip_address
1803 , session);
1804
1805 memcpy(rem_addr,&mp->net_addr,mp->net_addrlen);
1806 *rem_addrlen = mp->net_addrlen;
1807 #ifdef WIN32
1808 if (is_rtp){
1809 /*re-apply dscp settings for the new destination (windows specific).*/
1810 rtp_session_set_dscp( session, -1 );
1811 }
1812 #endif
1813 return 0;
1814 }
1815 return -1;
1816 }
1817