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