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 #ifdef HAVE_CONFIG_H
22 #include "ortp-config.h"
23 #endif
24 
25 #include "ortp/ortp.h"
26 #include "ortp/telephonyevents.h"
27 #include "ortp/rtcp.h"
28 #include "jitterctl.h"
29 #include "scheduler.h"
30 #include "utils.h"
31 #include "rtpsession_priv.h"
32 #include "congestiondetector.h"
33 #include "videobandwidthestimator.h"
34 
35 #if (_WIN32_WINNT >= 0x0600)
36 #include <delayimp.h>
37 #undef ExternC /* avoid redefinition... */
38 #ifdef ORTP_WINDOWS_DESKTOP
39 #include <QOS2.h>
40 #include <VersionHelpers.h>
41 #endif
42 #endif
43 
44 /**
45  * #_RtpTransport object which can handle multiples security protocols. You can for instance use this object
46  * to use both sRTP and tunnel transporter. mblk_t messages received and sent from the endpoint
47  * will pass through the list of modifiers given. First modifier in list will be first to modify the message
48  * in send mode and last in receive mode.
49  * @param[in] endpoint #_RtpTransport object in charge of sending/receiving packets. If NULL, it will use standards sendto and recvfrom functions.
50  * @param[in] modifiers_count number of #_RtpTransport object given in the variadic list. Must be 0 if none are given.
51  * @returns #_RtpTransport object that will be generated or NULL.
52 **/
53 RtpTransport* meta_rtp_transport_new(RtpTransport *endpoint, unsigned modifiers_count, ...);
54 RtpTransport* meta_rtcp_transport_new(RtpTransport *endpoint, unsigned modifiers_count, ...);
55 void meta_rtp_transport_link(RtpTransport *rtp, RtpTransport *rtcp);
56 
57 /* this function initialize all session parameter's that depend on the payload type */
payload_type_changed(RtpSession * session,PayloadType * pt)58 static void payload_type_changed(RtpSession *session, PayloadType *pt){
59 	jitter_control_set_payload(&session->rtp.jittctl,pt);
60 	rtp_session_set_time_jump_limit(session,session->rtp.time_jump);
61 	if (pt->type==PAYLOAD_VIDEO){
62 		session->permissive=TRUE;
63 		ortp_message("Using permissive algorithm");
64 	}
65 	else session->permissive=FALSE;
66 }
67 
wait_point_init(WaitPoint * wp)68 void wait_point_init(WaitPoint *wp){
69 	ortp_mutex_init(&wp->lock,NULL);
70 	ortp_cond_init(&wp->cond,NULL);
71 	wp->time=0;
72 	wp->wakeup=FALSE;
73 }
wait_point_uninit(WaitPoint * wp)74 void wait_point_uninit(WaitPoint *wp){
75 	ortp_cond_destroy(&wp->cond);
76 	ortp_mutex_destroy(&wp->lock);
77 }
78 
79 #define wait_point_lock(wp) ortp_mutex_lock(&(wp)->lock)
80 #define wait_point_unlock(wp) ortp_mutex_unlock(&(wp)->lock)
81 
wait_point_wakeup_at(WaitPoint * wp,uint32_t t,bool_t dosleep)82 void wait_point_wakeup_at(WaitPoint *wp, uint32_t t, bool_t dosleep){
83 	wp->time=t;
84 	wp->wakeup=TRUE;
85 	if (dosleep) ortp_cond_wait(&wp->cond,&wp->lock);
86 }
87 
88 
wait_point_check(WaitPoint * wp,uint32_t t)89 bool_t wait_point_check(WaitPoint *wp, uint32_t t){
90 	bool_t ok=FALSE;
91 
92 	if (wp->wakeup){
93 		if (TIME_IS_NEWER_THAN(t,wp->time)){
94 			wp->wakeup=FALSE;
95 			ok=TRUE;
96 
97 		}
98 	}
99 	return ok;
100 }
101 #define wait_point_wakeup(wp) ortp_cond_signal(&(wp)->cond);
102 
103 extern void rtp_parse(RtpSession *session, mblk_t *mp, uint32_t local_str_ts,
104 		struct sockaddr *addr, socklen_t addrlen);
105 
106 
uint32_t_random(void)107 static uint32_t uint32_t_random(void){
108 	return ortp_random();
109 }
110 
111 
112 /* put an rtp packet in queue. It is called by rtp_parse()
113    A return value of -1 means the packet was a duplicate, 0 means the packet was ok */
rtp_putq(queue_t * q,mblk_t * mp)114 int rtp_putq(queue_t *q, mblk_t *mp)
115 {
116 	mblk_t *tmp;
117 	rtp_header_t *rtp=(rtp_header_t*)mp->b_rptr,*tmprtp;
118 	/* insert message block by increasing time stamp order : the last (at the bottom)
119 		message of the queue is the newest*/
120 	ortp_debug("rtp_putq(): Enqueuing packet with ts=%i and seq=%i",rtp->timestamp,rtp->seq_number);
121 
122 	if (qempty(q)) {
123 		putq(q,mp);
124 		return 0;
125 	}
126 	tmp=qlast(q);
127 	/* we look at the queue from bottom to top, because enqueued packets have a better chance
128 	to be enqueued at the bottom, since there are surely newer */
129 	while (!qend(q,tmp))
130 	{
131 		tmprtp=(rtp_header_t*)tmp->b_rptr;
132 		ortp_debug("rtp_putq(): Seeing packet with seq=%i",tmprtp->seq_number);
133 
134 		if (rtp->seq_number == tmprtp->seq_number)
135 		{
136 			/* this is a duplicated packet. Don't queue it */
137 			ortp_debug("rtp_putq: duplicated message.");
138 			freemsg(mp);
139 			return -1;
140 		}else if (RTP_SEQ_IS_STRICTLY_GREATER_THAN(rtp->seq_number,tmprtp->seq_number)){
141 
142 			insq(q,tmp->b_next,mp);
143 			return 0;
144 		}
145 		tmp=tmp->b_prev;
146 	}
147 	/* this packet is the oldest, it has to be
148 	placed on top of the queue */
149 	insq(q,qfirst(q),mp);
150 	return 0;
151 }
152 
153 
rtp_getq(queue_t * q,uint32_t timestamp,int * rejected)154 mblk_t *rtp_getq(queue_t *q,uint32_t timestamp, int *rejected)
155 {
156 	mblk_t *tmp,*ret=NULL,*old=NULL;
157 	rtp_header_t *tmprtp;
158 	uint32_t ts_found=0;
159 
160 	*rejected=0;
161 	ortp_debug("rtp_getq(): Timestamp %i wanted.",timestamp);
162 	if (qempty(q))
163 	{
164 		/*ortp_debug("rtp_getq: q is empty.");*/
165 		return NULL;
166 	}
167 	/* return the packet with ts just equal or older than the asked timestamp */
168 	/* packets with older timestamps are discarded */
169 	while ((tmp=qfirst(q))!=NULL)
170 	{
171 		tmprtp=(rtp_header_t*)tmp->b_rptr;
172 		ortp_debug("rtp_getq: Seeing packet with ts=%i",tmprtp->timestamp);
173 
174 		if ( RTP_TIMESTAMP_IS_NEWER_THAN(timestamp,tmprtp->timestamp) )
175 		{
176 			if (ret!=NULL && tmprtp->timestamp==ts_found) {
177 				/* we've found two packets with same timestamp. return the first one */
178 				break;
179 			}
180 			if (old!=NULL) {
181 				ortp_debug("rtp_getq: discarding too old packet with ts=%u",ts_found);
182 				(*rejected)++;
183 				freemsg(old);
184 			}
185 			ret=getq(q); /* dequeue the packet, since it has an interesting timestamp*/
186 			ts_found=tmprtp->timestamp;
187 			ortp_debug("rtp_getq: Found packet with ts=%u",tmprtp->timestamp);
188 
189 			old=ret;
190 		}
191 		else
192 		{
193 			break;
194 		}
195 	}
196 	return ret;
197 }
198 
rtp_getq_permissive(queue_t * q,uint32_t timestamp,int * rejected)199 mblk_t *rtp_getq_permissive(queue_t *q,uint32_t timestamp, int *rejected)
200 {
201 	mblk_t *tmp,*ret=NULL;
202 	rtp_header_t *tmprtp;
203 
204 	*rejected=0;
205 	ortp_debug("rtp_getq_permissive(): Timestamp %i wanted.",timestamp);
206 
207 	if (qempty(q))
208 	{
209 		/*ortp_debug("rtp_getq: q is empty.");*/
210 		return NULL;
211 	}
212 	/* return the packet with the older timestamp (provided that it is older than
213 	the asked timestamp) */
214 	tmp=qfirst(q);
215 	tmprtp=(rtp_header_t*)tmp->b_rptr;
216 	ortp_debug("rtp_getq_permissive: Seeing packet with ts=%i",tmprtp->timestamp);
217 	if ( RTP_TIMESTAMP_IS_NEWER_THAN(timestamp,tmprtp->timestamp) )
218 	{
219 		ret=getq(q); /* dequeue the packet, since it has an interesting timestamp*/
220 		ortp_debug("rtp_getq_permissive: Found packet with ts=%i",tmprtp->timestamp);
221 	}
222 	return ret;
223 }
224 
225 
226 void
rtp_session_init(RtpSession * session,int mode)227 rtp_session_init (RtpSession * session, int mode)
228 {
229 	JBParameters jbp;
230 	if (session == NULL)
231 	{
232 		ortp_debug("rtp_session_init: Invalid paramter (session=NULL)");
233 		return;
234 	}
235 	memset (session, 0, sizeof (RtpSession));
236 	session->mode = (RtpSessionMode) mode;
237 	if ((mode == RTP_SESSION_RECVONLY) || (mode == RTP_SESSION_SENDRECV))
238 	{
239 		rtp_session_set_flag (session, RTP_SESSION_RECV_SYNC);
240 		rtp_session_set_flag (session, RTP_SESSION_RECV_NOT_STARTED);
241 
242 	}
243 	if ((mode == RTP_SESSION_SENDONLY) || (mode == RTP_SESSION_SENDRECV))
244 	{
245 		rtp_session_set_flag (session, RTP_SESSION_SEND_NOT_STARTED);
246 		session->snd.ssrc=uint32_t_random();
247 		/* set default source description */
248 		rtp_session_set_source_description(session,"unknown@unknown",NULL,NULL,
249 				NULL,NULL,"oRTP-" ORTP_VERSION,NULL);
250 	}
251 	rtp_session_set_profile (session, &av_profile); /*the default profile to work with */
252 	session->rtp.gs.socket=-1;
253 	session->rtcp.gs.socket=-1;
254 #ifndef _WIN32
255 	session->rtp.snd_socket_size=0;	/*use OS default value unless on windows where they are definitely too short*/
256 	session->rtp.rcv_socket_size=0;
257 #else
258 	session->rtp.snd_socket_size=session->rtp.rcv_socket_size=65536;
259 #endif
260 	session->rtp.ssrc_changed_thres=50;
261 	session->dscp=RTP_DEFAULT_DSCP;
262 	session->multicast_ttl=RTP_DEFAULT_MULTICAST_TTL;
263 	session->multicast_loopback=RTP_DEFAULT_MULTICAST_LOOPBACK;
264 	qinit(&session->rtp.rq);
265 	qinit(&session->rtp.tev_rq);
266 	qinit(&session->contributing_sources);
267 	session->eventqs=NULL;
268 
269 	/* Initialize RTCP send algorithm */
270 	session->target_upload_bandwidth = 80000; /* 80kbits/s to have 4kbits/s dedicated to RTCP if rtp_session_set_target_upload_bandwidth() is not called. */
271 	session->rtcp.send_algo.initial = TRUE;
272 	session->rtcp.send_algo.allow_early = TRUE;
273 
274 	/* init signal tables */
275 	rtp_signal_table_init (&session->on_ssrc_changed, session,"ssrc_changed");
276 	rtp_signal_table_init (&session->on_payload_type_changed, session,"payload_type_changed");
277 	rtp_signal_table_init (&session->on_telephone_event, session,"telephone-event");
278 	rtp_signal_table_init (&session->on_telephone_event_packet, session,"telephone-event_packet");
279 	rtp_signal_table_init (&session->on_timestamp_jump,session,"timestamp_jump");
280 	rtp_signal_table_init (&session->on_network_error,session,"network_error");
281 	rtp_signal_table_init (&session->on_rtcp_bye,session,"rtcp_bye");
282 	wait_point_init(&session->snd.wp);
283 	wait_point_init(&session->rcv.wp);
284 	/*defaults send payload type to 0 (pcmu)*/
285 	rtp_session_set_send_payload_type(session,0);
286 	/*sets supposed recv payload type to undefined */
287 	rtp_session_set_recv_payload_type(session,-1);
288 
289 	rtp_session_enable_jitter_buffer(session,TRUE);
290 	jb_parameters_init(&jbp);
291 	rtp_session_set_jitter_buffer_params(session,&jbp);
292 	rtp_session_set_time_jump_limit(session,5000);
293 	rtp_session_enable_rtcp(session,TRUE);
294 	rtp_session_set_rtcp_report_interval(session,RTCP_DEFAULT_REPORT_INTERVAL);
295 	session->recv_buf_size = UDP_MAX_SIZE;
296 	session->symmetric_rtp = FALSE;
297 	session->permissive=FALSE;
298 	session->reuseaddr=TRUE;
299 	msgb_allocator_init(&session->rtp.gs.allocator);
300 	msgb_allocator_init(&session->rtcp.gs.allocator);
301 	/*set default rtptransport*/
302 
303 	{
304 		RtpTransport *rtp_tr = meta_rtp_transport_new(NULL, 0);
305 		RtpTransport *rtcp_tr = meta_rtcp_transport_new(NULL, 0);
306 		meta_rtp_transport_link(rtp_tr, rtcp_tr);
307 		rtp_session_set_transports(session, rtp_tr, rtcp_tr);
308 	}
309 	session->tev_send_pt = -1; /*check in rtp profile when needed*/
310 
311 	ortp_bw_estimator_init(&session->rtp.gs.recv_bw_estimator, 0.95f, 0.01f);
312 	ortp_bw_estimator_init(&session->rtcp.gs.recv_bw_estimator, 0.95f, 0.01f);
313 }
314 
rtp_session_enable_congestion_detection(RtpSession * session,bool_t enabled)315 void rtp_session_enable_congestion_detection(RtpSession *session, bool_t enabled){
316 	if (enabled){
317 		if (session->rtp.jittctl.params.buffer_algorithm != OrtpJitterBufferRecursiveLeastSquare){
318 			ortp_error("rtp_session_enable_congestion_detection(): cannot use congestion control without RLS jitter buffer algorithm");
319 			return;
320 		}
321 		if (!session->rtp.congdetect){
322 			session->rtp.congdetect = ortp_congestion_detector_new(session);
323 		}else{
324 			if (!session->congestion_detector_enabled) ortp_congestion_detector_reset(session->rtp.congdetect);
325 		}
326 	}
327 	session->congestion_detector_enabled = enabled;
328 }
329 
rtp_session_enable_video_bandwidth_estimator(RtpSession * session,const OrtpVideoBandwidthEstimatorParams * params)330 void rtp_session_enable_video_bandwidth_estimator(RtpSession *session, const OrtpVideoBandwidthEstimatorParams *params) {
331 	if (params->enabled) {
332 		if (!session->rtp.video_bw_estimator) {
333 			session->rtp.video_bw_estimator = ortp_video_bandwidth_estimator_new(session);
334 		}
335 		if (params->packet_count_min > 0) session->rtp.video_bw_estimator->packet_count_min = params->packet_count_min;
336 		if (params->packets_size_max > 0) session->rtp.video_bw_estimator->packets_size_max = params->packets_size_max;
337 		if (params->trust_percentage > 0) session->rtp.video_bw_estimator->trust_percentage = params->trust_percentage;
338 		if (!session->video_bandwidth_estimator_enabled) ortp_video_bandwidth_estimator_reset(session->rtp.video_bw_estimator);
339 	}
340 	session->video_bandwidth_estimator_enabled = params->enabled;
341 }
342 
jb_parameters_init(JBParameters * jbp)343 void jb_parameters_init(JBParameters *jbp) {
344 	/* configure jitter buffer with working default parameters */
345 	jbp->min_size=RTP_DEFAULT_JITTER_TIME;
346 	jbp->nom_size=RTP_DEFAULT_JITTER_TIME;
347 	jbp->max_size=500;
348 	jbp->max_packets= 200;/* maximum number of packet allowed to be queued */
349 	jbp->adaptive=TRUE;
350 	jbp->enabled=TRUE;
351 	jbp->buffer_algorithm = OrtpJitterBufferRecursiveLeastSquare;
352 	jbp->refresh_ms=5000;
353 	jbp->ramp_threshold=70;
354 	jbp->ramp_step_ms=20;
355 	jbp->ramp_refresh_ms=5000;
356 }
357 
358 /**
359  * Creates a new rtp session.
360  * If the session is able to send data (RTP_SESSION_SENDONLY or
361  * RTP_SESSION_SENDRECV), then a random SSRC number is choosed for
362  * the outgoing stream.
363  * @param mode One of the RtpSessionMode flags.
364  *
365  * @return the newly created rtp session.
366 **/
367 RtpSession *
rtp_session_new(int mode)368 rtp_session_new (int mode)
369 {
370 	RtpSession *session;
371 	session = (RtpSession *) ortp_malloc (sizeof (RtpSession));
372 	if (session == NULL)
373 	{
374 		ortp_error("rtp_session_new: Memory allocation failed");
375 		return NULL;
376 	}
377 	rtp_session_init (session, mode);
378 	return session;
379 }
380 
381 /**
382  * Sets the scheduling mode of the rtp session. If \a yesno is TRUE, the rtp session is in
383  *	the scheduled mode, that means that you can use session_set_select() to block until it's time
384  *	to receive or send on this session according to the timestamp passed to the respective functions.
385  *  You can also use blocking mode (see rtp_session_set_blocking_mode() ), to simply block within
386  *	the receive and send functions.
387  *	If \a yesno is FALSE, the ortp scheduler will not manage those sessions, meaning that blocking mode
388  *  and the use of session_set_select() for this session are disabled.
389  *@param session a rtp session.
390  *@param yesno 	a boolean to indicate the scheduling mode.
391  *
392  *
393 **/
394 void
rtp_session_set_scheduling_mode(RtpSession * session,int yesno)395 rtp_session_set_scheduling_mode (RtpSession * session, int yesno)
396 {
397 	if (yesno)
398 	{
399 		RtpScheduler *sched;
400 		sched = ortp_get_scheduler ();
401 		if (sched != NULL)
402 		{
403 			rtp_session_set_flag (session, RTP_SESSION_SCHEDULED);
404 			session->sched = sched;
405 			rtp_scheduler_add_session (sched, session);
406 		}
407 		else
408 			ortp_warning
409 				("rtp_session_set_scheduling_mode: Cannot use scheduled mode because the "
410 				 "scheduler is not started. Use ortp_scheduler_init() before.");
411 	}
412 	else
413 		rtp_session_unset_flag (session, RTP_SESSION_SCHEDULED);
414 }
415 
416 
417 /**
418  *	This function implicitely enables the scheduling mode if yesno is TRUE.
419  *	rtp_session_set_blocking_mode() defines the behaviour of the rtp_session_recv_with_ts() and
420  *	rtp_session_send_with_ts() functions. If \a yesno is TRUE, rtp_session_recv_with_ts()
421  *	will block until it is time for the packet to be received, according to the timestamp
422  *	passed to the function. After this time, the function returns.
423  *	For rtp_session_send_with_ts(), it will block until it is time for the packet to be sent.
424  *	If \a yesno is FALSE, then the two functions will return immediately.
425  *
426  *  @param session a rtp session
427  *  @param yesno a boolean
428 **/
429 void
rtp_session_set_blocking_mode(RtpSession * session,int yesno)430 rtp_session_set_blocking_mode (RtpSession * session, int yesno)
431 {
432 	if (yesno){
433 		rtp_session_set_scheduling_mode(session,TRUE);
434 		rtp_session_set_flag (session, RTP_SESSION_BLOCKING_MODE);
435 	}else
436 		rtp_session_unset_flag (session, RTP_SESSION_BLOCKING_MODE);
437 }
438 
439 /**
440  *	Set the RTP profile to be used for the session. By default, all session are created by
441  *	rtp_session_new() are initialized with the AV profile, as defined in RFC 3551. The application
442  *	can set any other profile instead using that function.
443  *
444  * @param session a rtp session
445  * @param profile a rtp profile
446 **/
447 
448 void
rtp_session_set_profile(RtpSession * session,RtpProfile * profile)449 rtp_session_set_profile (RtpSession * session, RtpProfile * profile)
450 {
451 	session->snd.profile = profile;
452 	session->rcv.profile = profile;
453 	rtp_session_telephone_events_supported(session);
454 }
455 
456 /**
457  *	By default oRTP automatically sends RTCP SR or RR packets. If
458  *	yesno is set to FALSE, the RTCP sending of packet is disabled.
459  *	This functionality might be needed for some equipments that do not
460  *	support RTCP, leading to a traffic of ICMP errors on the network.
461  *	It can also be used to save bandwidth despite the RTCP bandwidth is
462  *	actually and usually very very low.
463 **/
rtp_session_enable_rtcp(RtpSession * session,bool_t yesno)464 void rtp_session_enable_rtcp(RtpSession *session, bool_t yesno){
465 	session->rtcp.enabled=yesno;
466 }
467 
rtp_session_rtcp_enabled(const RtpSession * session)468 bool_t rtp_session_rtcp_enabled(const RtpSession *session) {
469 	return  session->rtcp.enabled;
470 }
471 
472 /**
473  * Sets the default interval in milliseconds for RTCP reports emitted by the session
474  *
475 **/
rtp_session_set_rtcp_report_interval(RtpSession * session,int value_ms)476 void rtp_session_set_rtcp_report_interval(RtpSession *session, int value_ms) {
477 	if (value_ms <= 0) session->rtcp.send_algo.T_rr_interval = 0;
478 	else session->rtcp.send_algo.T_rr_interval = (uint32_t)value_ms;
479 }
480 
rtp_session_set_target_upload_bandwidth(RtpSession * session,int target_bandwidth)481 void rtp_session_set_target_upload_bandwidth(RtpSession *session, int target_bandwidth) {
482 	session->target_upload_bandwidth = target_bandwidth;
483 }
rtp_session_get_target_upload_bandwidth(RtpSession * session)484 int rtp_session_get_target_upload_bandwidth(RtpSession *session) {
485 	return session->target_upload_bandwidth;
486 }
487 
488 /**
489  *	Set the RTP profile to be used for the sending by this session. By default, all session are created by
490  *	rtp_session_new() are initialized with the AV profile, as defined in RFC 3551. The application
491  *	can set any other profile instead using that function.
492  * @param session a rtp session
493  * @param profile a rtp profile
494  *
495 **/
496 
497 void
rtp_session_set_send_profile(RtpSession * session,RtpProfile * profile)498 rtp_session_set_send_profile (RtpSession * session, RtpProfile * profile)
499 {
500 	session->snd.profile = profile;
501 	rtp_session_send_telephone_events_supported(session);
502 }
503 
504 
505 
506 /**
507  *	Set the RTP profile to be used for the receiveing by this session. By default, all session are created by
508  *	rtp_session_new() are initialized with the AV profile, as defined in RFC 3551. The application
509  *	can set any other profile instead using that function.
510  *
511  * @param session a rtp session
512  * @param profile a rtp profile
513 **/
514 
515 void
rtp_session_set_recv_profile(RtpSession * session,RtpProfile * profile)516 rtp_session_set_recv_profile (RtpSession * session, RtpProfile * profile)
517 {
518 	session->rcv.profile = profile;
519 	rtp_session_recv_telephone_events_supported(session);
520 }
521 
522 /**
523  *@param session a rtp session
524  *
525  *	DEPRECATED! Returns current send profile.
526  *	Use rtp_session_get_send_profile() or rtp_session_get_recv_profile()
527  *
528 **/
rtp_session_get_profile(RtpSession * session)529 RtpProfile *rtp_session_get_profile(RtpSession *session){
530 	return session->snd.profile;
531 }
532 
533 
534 /**
535  *@param session a rtp session
536  *
537  *	Returns current send profile.
538  *
539 **/
rtp_session_get_send_profile(RtpSession * session)540 RtpProfile *rtp_session_get_send_profile(RtpSession *session){
541 	return session->snd.profile;
542 }
543 
544 /**
545  *@param session a rtp session
546  *
547  *	Returns current receive profile.
548  *
549 **/
rtp_session_get_recv_profile(RtpSession * session)550 RtpProfile *rtp_session_get_recv_profile(RtpSession *session){
551 	return session->rcv.profile;
552 }
553 
rtp_session_set_send_ts_offset(RtpSession * s,uint32_t offset)554 void rtp_session_set_send_ts_offset(RtpSession *s, uint32_t offset){
555 	s->send_ts_offset = offset;
556 }
557 
rtp_session_get_send_ts_offset(RtpSession * s)558 uint32_t rtp_session_get_send_ts_offset(RtpSession *s){
559 	return s->send_ts_offset;
560 }
561 
562 /**
563  *	The default value is UDP_MAX_SIZE bytes, a value which is working for mostly everyone.
564  *	However if your application can make assumption on the sizes of received packet,
565  *	it can be interesting to set it to a lower value in order to save memory.
566  *
567  * @param session a rtp session
568  * @param bufsize max size in bytes for receiving packets
569 **/
rtp_session_set_recv_buf_size(RtpSession * session,int bufsize)570 void rtp_session_set_recv_buf_size(RtpSession *session, int bufsize){
571 	session->recv_buf_size=bufsize;
572 }
573 
574 /**
575  *	Set kernel send maximum buffer size for the rtp socket.
576  *	A value of zero defaults to the operating system default.
577 **/
rtp_session_set_rtp_socket_send_buffer_size(RtpSession * session,unsigned int size)578 void rtp_session_set_rtp_socket_send_buffer_size(RtpSession * session, unsigned int size){
579 	session->rtp.snd_socket_size=size;
580 	_rtp_session_apply_socket_sizes(session);
581 }
582 
583 /**
584  *	Set kernel recv maximum buffer size for the rtp socket.
585  *	A value of zero defaults to the operating system default.
586 **/
rtp_session_set_rtp_socket_recv_buffer_size(RtpSession * session,unsigned int size)587 void rtp_session_set_rtp_socket_recv_buffer_size(RtpSession * session, unsigned int size){
588 	session->rtp.rcv_socket_size=size;
589 	_rtp_session_apply_socket_sizes(session);
590 }
591 
592 /**
593  *	This function provides the way for an application to be informed of various events that
594  *	may occur during a rtp session. \a signal_name is a string identifying the event, and \a cb is
595  *	a user supplied function in charge of processing it. The application can register
596  *	several callbacks for the same signal, in the limit of \a RTP_CALLBACK_TABLE_MAX_ENTRIES.
597  *	Here are name and meaning of supported signals types:
598  *
599  *	"ssrc_changed": the SSRC of the incoming stream has changed.
600  *
601  *	"payload_type_changed": the payload type of the incoming stream has changed.
602  *
603  *	"telephone-event_packet": a telephone-event rtp packet (RFC2833) is received.
604  *
605  *	"telephone-event": a telephone event has occurred. This is a high-level shortcut for "telephone-event_packet".
606  *
607  *	"network_error": a network error happened on a socket. Arguments of the callback functions are
608  *						a const char * explaining the error, an int errno error code and the user_data as usual.
609  *
610  *	"timestamp_jump": we have received a packet with timestamp in far future compared to last timestamp received.
611  *						The farness of far future is set by rtp_sesssion_set_time_jump_limit()
612  *  "rtcp_bye": we have received a RTCP bye packet. Arguments of the callback
613  *              functions are a const char * containing the leaving reason and
614  *              the user_data.
615  *	"congestion_state_changed": congestion detector object changed its internal state. Arguments of
616  *								the callback function are previous and new states.
617  *	Returns: 0 on success, -EOPNOTSUPP if the signal does not exists, -1 if no more callbacks
618  *	can be assigned to the signal type.
619  *
620  * @param session 	a rtp session
621  * @param signal_name	the name of a signal
622  * @param cb		a RtpCallback
623  * @param user_data	a pointer to any data to be passed when invoking the callback.
624  *
625 **/
626 int
rtp_session_signal_connect(RtpSession * session,const char * signal_name,RtpCallback cb,void * user_data)627 rtp_session_signal_connect (RtpSession * session, const char *signal_name,
628 				RtpCallback cb, void *user_data)
629 {
630 	bctbx_list_t *elem;
631 	for (elem=session->signal_tables;elem!=NULL;elem=o_list_next(elem)){
632 		RtpSignalTable *s=(RtpSignalTable*) elem->data;
633 		if (strcmp(signal_name,s->signal_name)==0){
634 			return rtp_signal_table_add(s,cb,user_data);
635 		}
636 	}
637 	ortp_warning ("rtp_session_signal_connect: inexistent signal %s",signal_name);
638 	return -1;
639 }
640 
641 
642 /**
643  *	Removes callback function \a cb to the list of callbacks for signal \a signal.
644  *
645  * @param session a rtp session
646  * @param signal_name	a signal name
647  * @param cb	a callback function.
648  * @return: 0 on success, a negative value if the callback was not found.
649 **/
650 int
rtp_session_signal_disconnect_by_callback(RtpSession * session,const char * signal_name,RtpCallback cb)651 rtp_session_signal_disconnect_by_callback (RtpSession * session, const char *signal_name,
652 					   RtpCallback cb)
653 {
654 	OList *elem;
655 	for (elem=session->signal_tables;elem!=NULL;elem=o_list_next(elem)){
656 		RtpSignalTable *s=(RtpSignalTable*) elem->data;
657 		if (strcmp(signal_name,s->signal_name)==0){
658 			return rtp_signal_table_remove_by_callback(s,cb);
659 		}
660 	}
661 	ortp_warning ("rtp_session_signal_connect: inexistant signal %s",signal_name);
662 	return -1;
663 }
664 
665 
666 /**
667  * Set the initial sequence number for outgoing stream..
668  * @param session		a rtp session freshly created.
669  * @param seq			a 16 bit unsigned number.
670  *
671 **/
rtp_session_set_seq_number(RtpSession * session,uint16_t seq)672 void rtp_session_set_seq_number(RtpSession *session, uint16_t seq){
673 	session->rtp.snd_seq=seq;
674 }
675 
rtp_session_set_duplication_ratio(RtpSession * session,float ratio)676 void rtp_session_set_duplication_ratio(RtpSession *session, float ratio){
677 	session->duplication_ratio=ratio;
678 }
679 
680 
681 
682 /**
683  * Get the current sequence number for outgoing stream.
684 **/
rtp_session_get_seq_number(RtpSession * session)685 uint16_t rtp_session_get_seq_number(RtpSession *session){
686 	return session->rtp.snd_seq;
687 }
688 
689 /**
690  * Returns the highest extended sequence number received.
691 **/
rtp_session_get_rcv_ext_seq_number(RtpSession * session)692 uint32_t rtp_session_get_rcv_ext_seq_number(RtpSession *session){
693 	return session->rtp.hwrcv_extseq;
694 }
695 
696 /**
697  * Returns the latest cumulative loss value computed
698  **/
rtp_session_get_cum_loss(RtpSession * session)699 int rtp_session_get_cum_loss(RtpSession *session){
700 	return session->cum_loss;
701 }
702 
703 /**
704  *	Sets the SSRC for the outgoing stream.
705  *  If not done, a random ssrc is used.
706  *
707  * @param session a rtp session.
708  * @param ssrc an unsigned 32bit integer representing the synchronisation source identifier (SSRC).
709 **/
710 void
rtp_session_set_ssrc(RtpSession * session,uint32_t ssrc)711 rtp_session_set_ssrc (RtpSession * session, uint32_t ssrc)
712 {
713 	session->snd.ssrc = ssrc;
714 }
715 
716 /**
717  *	Get the SSRC for the outgoing stream.
718  *
719  * @param session a rtp session.
720 **/
721 uint32_t
rtp_session_get_send_ssrc(RtpSession * session)722 rtp_session_get_send_ssrc (RtpSession* session)
723 {
724 	return session->snd.ssrc;
725 }
726 
727 /**
728  * Get the SSRC for the incoming stream.
729  *
730  * If no packets have been received yet, 0 is returned.
731 **/
rtp_session_get_recv_ssrc(RtpSession * session)732 uint32_t rtp_session_get_recv_ssrc(RtpSession *session){
733 	return session->rcv.ssrc;
734 }
735 
736 
rtp_session_update_payload_type(RtpSession * session,int paytype)737 void rtp_session_update_payload_type(RtpSession *session, int paytype){
738 	/* check if we support this payload type */
739 	PayloadType *pt=rtp_profile_get_payload(session->rcv.profile,paytype);
740 	if (pt!=0){
741 		session->hw_recv_pt=paytype;
742 		ortp_message ("payload type changed to %i(%s) !",
743 				 paytype,pt->mime_type);
744 		payload_type_changed(session,pt);
745 	}else{
746 		ortp_warning("Receiving packet with unknown payload type %i.",paytype);
747 	}
748 }
749 /**
750  *	Sets the payload type of the rtp session. It decides of the payload types written in the
751  *	of the rtp header for the outgoing stream, if the session is SENDRECV or SENDONLY.
752  *	For payload type in incoming packets, the application can be informed by registering
753  *	for the "payload_type_changed" signal, so that it can make the necessary changes
754  *	on the downstream decoder that deals with the payload of the packets.
755  *
756  * @param session a rtp session
757  * @param paytype the payload type number
758  * @return 0 on success, -1 if the payload is not defined.
759 **/
760 
761 int
rtp_session_set_send_payload_type(RtpSession * session,int paytype)762 rtp_session_set_send_payload_type (RtpSession * session, int paytype)
763 {
764 	session->snd.pt=paytype;
765 	return 0;
766 }
767 
768 /**
769  *@param session a rtp session
770  *
771  *@return the payload type currently used in outgoing rtp packets
772 **/
rtp_session_get_send_payload_type(const RtpSession * session)773 int rtp_session_get_send_payload_type(const RtpSession *session){
774 	return session->snd.pt;
775 }
776 
777 /**
778  * Assign the payload type number for sending telephone-event.
779  * It is required that a "telephone-event" PayloadType is assigned in the RtpProfile set for the RtpSession.
780  * This function is in most of cases useless, unless there is an ambiguity where several PayloadType for "telephone-event" are present in the RtpProfile.
781  * This might happen during SIP offeranswer scenarios. This function allows to remove any ambiguity by letting the application choose the one to be used.
782  * @param session the RtpSession
783  * @param paytype the payload type number
784  * @returns 0, -1 on error.
785 **/
rtp_session_set_send_telephone_event_payload_type(RtpSession * session,int paytype)786 int rtp_session_set_send_telephone_event_payload_type(RtpSession *session, int paytype){
787 	session->tev_send_pt = paytype;
788 	return 0;
789 }
790 
791 /**
792  *
793  *	Sets the expected payload type for incoming packets.
794  *	If the actual payload type in incoming packets is different that this expected payload type, thus
795  *	the "payload_type_changed" signal is emitted.
796  *
797  *@param session a rtp session
798  *@param paytype the payload type number
799  *@return 0 on success, -1 if the payload is not defined.
800 **/
801 
802 int
rtp_session_set_recv_payload_type(RtpSession * session,int paytype)803 rtp_session_set_recv_payload_type (RtpSession * session, int paytype)
804 {
805 	PayloadType *pt;
806 	session->rcv.pt=paytype;
807 	session->hw_recv_pt=paytype;
808 	pt=rtp_profile_get_payload(session->rcv.profile,paytype);
809 	if (pt!=NULL){
810 		payload_type_changed(session,pt);
811 	}
812 	return 0;
813 }
814 
815 /**
816  *@param session a rtp session
817  *
818  * @return the payload type currently used in incoming rtp packets
819 **/
rtp_session_get_recv_payload_type(const RtpSession * session)820 int rtp_session_get_recv_payload_type(const RtpSession *session){
821 	return session->rcv.pt;
822 }
823 
824 /**
825  *	Sets the expected payload type for incoming packets and payload type to be used for outgoing packets.
826  *	If the actual payload type in incoming packets is different that this expected payload type, thus
827  *	the "payload_type_changed" signal is emitted.
828  *
829  * @param session a rtp session
830  * @param pt the payload type number
831  * @return 0 on success, -1 if the payload is not defined.
832 **/
rtp_session_set_payload_type(RtpSession * session,int pt)833 int rtp_session_set_payload_type(RtpSession *session, int pt){
834 	if (rtp_session_set_send_payload_type(session,pt)<0) return -1;
835 	if (rtp_session_set_recv_payload_type(session,pt)<0) return -1;
836 	return 0;
837 }
838 
839 
rtp_header_init_from_session(rtp_header_t * rtp,RtpSession * session)840 static void rtp_header_init_from_session(rtp_header_t *rtp, RtpSession *session){
841 	rtp->version = 2;
842 	rtp->padbit = 0;
843 	rtp->extbit = 0;
844 	rtp->markbit= 0;
845 	rtp->cc = 0;
846 	rtp->paytype = session->snd.pt;
847 	rtp->ssrc = session->snd.ssrc;
848 	rtp->timestamp = 0;	/* set later, when packet is sended */
849 	/* set a seq number */
850 	rtp->seq_number=session->rtp.snd_seq;
851 }
852 
853 /**
854  *	Allocates a new rtp packet. In the header, ssrc and payload_type according to the session's
855  *	context. Timestamp is not set, it will be set when the packet is going to be
856  *	sent with rtp_session_sendm_with_ts(). Sequence number is initalized to previous sequence number sent + 1
857  *	If payload_size is zero, thus an empty packet (just a RTP header) is returned.
858  *
859  *@param session a rtp session.
860  *@param header_size the rtp header size. For standart size (without extensions), it is RTP_FIXED_HEADER_SIZE
861  *@param payload data to be copied into the rtp packet.
862  *@param payload_size size of data carried by the rtp packet.
863  *@return a rtp packet in a mblk_t (message block) structure.
864 **/
rtp_session_create_packet(RtpSession * session,size_t header_size,const uint8_t * payload,size_t payload_size)865 mblk_t * rtp_session_create_packet(RtpSession *session,size_t header_size, const uint8_t *payload, size_t payload_size)
866 {
867 	mblk_t *mp;
868 	size_t msglen=header_size+payload_size;
869 	rtp_header_t *rtp;
870 
871 	mp=allocb(msglen,BPRI_MED);
872 	rtp=(rtp_header_t*)mp->b_rptr;
873 	rtp_header_init_from_session(rtp,session);
874 	/*copy the payload, if any */
875 	mp->b_wptr+=header_size;
876 	if (payload_size){
877 		memcpy(mp->b_wptr,payload,payload_size);
878 		mp->b_wptr+=payload_size;
879 	}
880 	return mp;
881 }
882 
883 
884 /**
885  * Create a packet already including headers
886  */
rtp_session_create_packet_raw(const uint8_t * packet,size_t packet_size)887 mblk_t * rtp_session_create_packet_raw(const uint8_t *packet, size_t packet_size) {
888 	mblk_t *mp;
889 
890 	mp=allocb(packet_size,BPRI_MED);
891 	if (packet_size){
892 		memcpy(mp->b_wptr,packet,packet_size);
893 		mp->b_wptr+=packet_size;
894 	}
895 	return mp;
896 }
897 
898 /**
899  *	Creates a new rtp packet using the given payload buffer (no copy). The header will be allocated separetely.
900  *  In the header, ssrc and payload_type according to the session's
901  *	context. Timestamp and seq number are not set, there will be set when the packet is going to be
902  *	sent with rtp_session_sendm_with_ts().
903  *	oRTP will send this packet using libc's sendmsg() (if this function is availlable!) so that there will be no
904  *	packet concatenation involving copies to be done in user-space.
905  *  \a freefn can be NULL, in that case payload will be kept untouched.
906  *
907  * @param session a rtp session.
908  * @param payload the data to be sent with this packet
909  * @param payload_size size of data
910  * @param freefn a function that will be called when the payload buffer is no more needed.
911  * @return: a rtp packet in a mblk_t (message block) structure.
912 **/
913 
rtp_session_create_packet_with_data(RtpSession * session,uint8_t * payload,size_t payload_size,void (* freefn)(void *))914 mblk_t * rtp_session_create_packet_with_data(RtpSession *session, uint8_t *payload, size_t payload_size, void (*freefn)(void*))
915 {
916 	mblk_t *mp,*mpayload;
917 	int header_size=RTP_FIXED_HEADER_SIZE; /* revisit when support for csrc is done */
918 	rtp_header_t *rtp;
919 
920 	mp=allocb(header_size,BPRI_MED);
921 	rtp=(rtp_header_t*)mp->b_rptr;
922 	rtp_header_init_from_session(rtp,session);
923 	mp->b_wptr+=header_size;
924 	/* create a mblk_t around the user supplied payload buffer */
925 	mpayload=esballoc(payload,payload_size,BPRI_MED,freefn);
926 	mpayload->b_wptr+=payload_size;
927 	/* link it with the header */
928 	mp->b_cont=mpayload;
929 	return mp;
930 }
931 
932 
933 /**
934  * Creates a new rtp packet using the buffer given in arguments (no copy).
935  * In the header, ssrc and payload_type according to the session's
936  *context. Timestamp and seq number are not set, there will be set when the packet is going to be
937  *	sent with rtp_session_sendm_with_ts().
938  * \a freefn can be NULL, in that case payload will be kept untouched.
939  *
940  * @param session a rtp session.
941  * @param buffer a buffer that contains first just enough place to write a RTP header, then the data to send.
942  * @param size the size of the buffer
943  * @param freefn a function that will be called once the buffer is no more needed (the data has been sent).
944  * @return a rtp packet in a mblk_t (message block) structure.
945 **/
rtp_session_create_packet_in_place(RtpSession * session,uint8_t * buffer,size_t size,void (* freefn)(void *))946 mblk_t * rtp_session_create_packet_in_place(RtpSession *session,uint8_t *buffer, size_t size, void (*freefn)(void*) )
947 {
948 	mblk_t *mp;
949 	rtp_header_t *rtp;
950 
951 	mp=esballoc(buffer,size,BPRI_MED,freefn);
952 
953 	rtp=(rtp_header_t*)mp->b_rptr;
954 	rtp_header_init_from_session(rtp,session);
955 	return mp;
956 }
957 
958 
__rtp_session_sendm_with_ts(RtpSession * session,mblk_t * mp,uint32_t packet_ts,uint32_t send_ts)959 ORTP_PUBLIC int __rtp_session_sendm_with_ts (RtpSession * session, mblk_t *mp, uint32_t packet_ts, uint32_t send_ts)
960 {
961 	rtp_header_t *rtp;
962 	uint32_t packet_time;
963 	int error = 0;
964 	size_t packsize;
965 	RtpScheduler *sched=session->sched;
966 	RtpStream *stream=&session->rtp;
967 
968 	if (session->flags & RTP_SESSION_SEND_NOT_STARTED)
969 	{
970 		session->rtp.snd_ts_offset = send_ts;
971 		/* Set initial last_rcv_time to first send time. */
972 		if ((session->flags & RTP_SESSION_RECV_NOT_STARTED)
973 		|| session->mode == RTP_SESSION_SENDONLY) {
974 			ortp_gettimeofday(&session->last_recv_time, NULL);
975 		}
976 		if (session->flags & RTP_SESSION_SCHEDULED) {
977 			session->rtp.snd_time_offset = sched->time_;
978 		}
979 		rtp_session_unset_flag (session,RTP_SESSION_SEND_NOT_STARTED);
980 	}
981 	/* if we are in blocking mode, then suspend the process until the scheduler it's time to send  the
982 	 * next packet */
983 	/* if the timestamp of the packet queued is older than current time, then you we must
984 	 * not block */
985 	if (session->flags & RTP_SESSION_SCHEDULED)
986 	{
987 		wait_point_lock(&session->snd.wp);
988 		packet_time =
989 			rtp_session_ts_to_time (session,
990 					 send_ts -
991 					 session->rtp.snd_ts_offset) +
992 					session->rtp.snd_time_offset;
993 		/*ortp_message("rtp_session_send_with_ts: packet_time=%i time=%i",packet_time,sched->time_);*/
994 		if (TIME_IS_STRICTLY_NEWER_THAN (packet_time, sched->time_))
995 		{
996 			wait_point_wakeup_at(&session->snd.wp,packet_time,(session->flags & RTP_SESSION_BLOCKING_MODE)!=0);
997 			session_set_clr(&sched->w_sessions,session);	/* the session has written */
998 		}
999 		else session_set_set(&sched->w_sessions,session);	/*to indicate select to return immediately */
1000 		wait_point_unlock(&session->snd.wp);
1001 	}
1002 
1003 	if(mp==NULL) {/*for people who just want to be blocked but
1004 		 do not want to send anything.*/
1005 		session->rtp.snd_last_ts = packet_ts;
1006 		return 0;
1007 	}
1008 
1009 	rtp=(rtp_header_t*)mp->b_rptr;
1010 
1011 	packsize = msgdsize(mp) ;
1012 	session->duplication_left += session->duplication_ratio;
1013 	if (rtp->version == 0) {
1014 		/* We are probably trying to send a STUN packet so don't change its content. */
1015 	} else {
1016 		rtp->timestamp=packet_ts;
1017 		if (rtp_profile_is_telephone_event(session->snd.profile, rtp->paytype)){
1018 			rtp->seq_number = session->rtp.snd_seq;
1019 			session->rtp.snd_seq++;
1020 		}
1021 		else
1022 		{
1023 			session->rtp.snd_seq=rtp->seq_number+1;
1024 		}
1025 		session->rtp.snd_last_ts = packet_ts;
1026 
1027 		stream->sent_payload_bytes+=(uint32_t)(packsize-RTP_FIXED_HEADER_SIZE);
1028 
1029 		ortp_global_stats.sent += (1+(int)session->duplication_left) * packsize;
1030 		session->stats.sent += (1+(int)session->duplication_left) * packsize;
1031 
1032 		ortp_global_stats.packet_sent++;
1033 		session->stats.packet_sent++;
1034 
1035 		session->stats.packet_dup_sent+=(int)session->duplication_left;
1036 		ortp_global_stats.packet_sent+=(int)session->duplication_left;;
1037 	}
1038 
1039 	while (session->duplication_left>=1.f) {
1040 		error = rtp_session_rtp_send (session, copymsg(mp));
1041 		session->duplication_left -= 1.f;
1042 	}
1043 	error = rtp_session_rtp_send (session, mp);
1044 
1045 	/*send RTCP packet if needed */
1046 	rtp_session_run_rtcp_send_scheduler(session);
1047 	/* receives rtcp packet if session is send-only*/
1048 	/*otherwise it is done in rtp_session_recvm_with_ts */
1049 	if (session->mode==RTP_SESSION_SENDONLY) rtp_session_rtcp_recv(session);
1050 	return error;
1051 }
1052 
1053 /**
1054  *	Send the rtp datagram \a packet to the destination set by rtp_session_set_remote_addr()
1055  *	with timestamp \a timestamp. For audio data, the timestamp is the number
1056  *	of the first sample resulting of the data transmitted. See rfc1889 for details.
1057  *  The packet (\a packet) is freed once it is sent.
1058  *
1059  *@param session a rtp session.
1060  *@param packet a rtp packet presented as a mblk_t.
1061  *@param timestamp the timestamp of the data to be sent.
1062  * @return the number of bytes sent over the network.
1063 **/
1064 
rtp_session_sendm_with_ts(RtpSession * session,mblk_t * packet,uint32_t timestamp)1065 int rtp_session_sendm_with_ts(RtpSession *session, mblk_t *packet, uint32_t timestamp){
1066 	return __rtp_session_sendm_with_ts(session,packet,timestamp+session->send_ts_offset,timestamp+session->send_ts_offset);
1067 }
1068 
1069 
1070 
1071 
1072 /**
1073  *	Send a rtp datagram to the destination set by rtp_session_set_remote_addr() containing
1074  *	the data from \a buffer with timestamp \a userts. This is a high level function that uses
1075  *	rtp_session_create_packet() and rtp_session_sendm_with_ts() to send the data.
1076  *
1077  *@param session a rtp session.
1078  *@param buffer a buffer containing the data to be sent in a rtp packet.
1079  *@param len the length of the data buffer, in bytes.
1080  *@param userts	the timestamp of the data to be sent. Refer to the rfc to know what it is.
1081  *@return the number of bytes sent over the network.
1082 **/
1083 int
rtp_session_send_with_ts(RtpSession * session,const uint8_t * buffer,int len,uint32_t userts)1084 rtp_session_send_with_ts (RtpSession * session, const uint8_t * buffer, int len,
1085 			  uint32_t userts)
1086 {
1087 	mblk_t *m;
1088 	int err;
1089 #ifdef USE_SENDMSG
1090 	m=rtp_session_create_packet_with_data(session,(uint8_t*)buffer,len,NULL);
1091 #else
1092 	m = rtp_session_create_packet(session,RTP_FIXED_HEADER_SIZE,(uint8_t*)buffer,len);
1093 #endif
1094 	err=rtp_session_sendm_with_ts(session,m,userts);
1095 	return err;
1096 }
1097 
1098 
payload_type_changed_notify(RtpSession * session,int paytype)1099 static void payload_type_changed_notify(RtpSession *session, int paytype){
1100 	PayloadType *pt = rtp_profile_get_payload(session->rcv.profile,paytype);
1101 	if (pt) {
1102 		session->rcv.pt = paytype;
1103 		rtp_signal_table_emit (&session->on_payload_type_changed);
1104 	}
1105 }
1106 /**
1107  *	Try to get an rtp packet presented as a mblk_t structure from the rtp session at a given sequence number.
1108  *	This function is very usefull for codec with Forward error correction capabilities
1109  *
1110  *	This function returns the entire packet (with header).
1111  *
1112  *	 *
1113  * @param session a rtp session.
1114  * @param sequence_number a sequence number.
1115  *
1116  * @return a rtp packet presented as a mblk_t, or NULL if not found.
1117  **/
1118 
1119 mblk_t *
rtp_session_pick_with_cseq(RtpSession * session,const uint16_t sequence_number)1120 rtp_session_pick_with_cseq (RtpSession * session, const uint16_t sequence_number) {
1121 	queue_t* q= &session->rtp.rq;
1122 	mblk_t* mb;
1123 	for (mb=qbegin(q); !qend(q,mb); mb=qnext(q,mb)){
1124 		if (rtp_get_seqnumber(mb)==sequence_number) {
1125 			return mb;
1126 		}
1127 	}
1128 	return NULL;
1129 }
1130 
check_for_seq_number_gap(RtpSession * session,rtp_header_t * rtp)1131 static void check_for_seq_number_gap(RtpSession *session, rtp_header_t *rtp) {
1132 	uint16_t pid;
1133 	uint16_t i;
1134 	/*don't check anything before first packet delivered*/
1135 	if (session->flags & RTP_SESSION_FIRST_PACKET_DELIVERED && RTP_SEQ_IS_STRICTLY_GREATER_THAN(rtp->seq_number, session->rtp.rcv_last_seq + 1)) {
1136 		uint16_t first_missed_seq = session->rtp.rcv_last_seq + 1;
1137 		uint16_t diff = rtp->seq_number - first_missed_seq;
1138 		pid = first_missed_seq;
1139 		for (i = 0; i <= (diff / 16); i++) {
1140 			uint16_t seq;
1141 			uint16_t blp = 0;
1142 			for (seq = pid + 1; (seq < rtp->seq_number) && ((seq - pid) < 16); seq++) {
1143 				blp |= (1 << (seq - pid - 1));
1144 			}
1145 			rtp_session_send_rtcp_fb_generic_nack(session, pid, blp);
1146 			pid = seq;
1147 		}
1148 	}
1149 }
1150 
1151 /**
1152  *	Try to get a rtp packet presented as a mblk_t structure from the rtp session.
1153  *	The \a user_ts parameter is relative to the first timestamp of the incoming stream. In other
1154  *	words, the application does not have to know the first timestamp of the stream, it can
1155  *	simply call for the first time this function with \a user_ts=0, and then incrementing it
1156  *	as it want. The RtpSession takes care of synchronisation between the stream timestamp
1157  *	and the user timestamp given here.
1158  *
1159  *	This function returns the entire packet (with header).
1160  *
1161  *	The behaviour of this function has changed since version 0.15.0. Previously the payload data could be
1162  *	accessed using  mblk_t::b_cont::b_rptr field of the returned mblk_t.
1163  *	This is no more the case.
1164  *	The convenient way of accessing the payload data is to use rtp_get_payload() :
1165  *	@code
1166  *	unsigned char *payload;
1167  *	int payload_size;
1168  *	payload_size=rtp_get_payload(mp,&payload);
1169  *	@endcode
1170  *	OR simply skip the header this way, the data is then comprised between mp->b_rptr and mp->b_wptr:
1171  *	@code
1172  *	rtp_get_payload(mp,&mp->b_rptr);
1173  *	@endcode
1174  *
1175  *
1176  * @param session a rtp session.
1177  * @param user_ts a timestamp.
1178  *
1179  * @return a rtp packet presented as a mblk_t.
1180 **/
1181 
1182 mblk_t *
rtp_session_recvm_with_ts(RtpSession * session,uint32_t user_ts)1183 rtp_session_recvm_with_ts (RtpSession * session, uint32_t user_ts)
1184 {
1185 	mblk_t *mp = NULL;
1186 	rtp_header_t *rtp = NULL;
1187 	uint32_t ts;
1188 	uint32_t packet_time;
1189 	RtpScheduler *sched=session->sched;
1190 	int rejected=0;
1191 	bool_t read_socket=TRUE;
1192 
1193 	/* if we are scheduled, remember the scheduler time at which the application has
1194 	 * asked for its first timestamp */
1195 
1196 	if (session->flags & RTP_SESSION_RECV_NOT_STARTED)
1197 	{
1198 		session->rtp.rcv_query_ts_offset = user_ts;
1199 		/* Set initial last_rcv_time to first recv time. */
1200 		if ((session->flags & RTP_SESSION_SEND_NOT_STARTED)
1201 		|| session->mode == RTP_SESSION_RECVONLY) {
1202 			ortp_gettimeofday(&session->last_recv_time, NULL);
1203 		}
1204 		if (session->flags & RTP_SESSION_SCHEDULED) {
1205 			session->rtp.rcv_time_offset = sched->time_;
1206 			//ortp_message("setting snd_time_offset=%i",session->rtp.snd_time_offset);
1207 		}
1208 		rtp_session_unset_flag (session,RTP_SESSION_RECV_NOT_STARTED);
1209 	}else{
1210 		/*prevent reading from the sockets when two
1211 		consecutives calls for a same timestamp*/
1212 		if (user_ts==session->rtp.rcv_last_app_ts)
1213 			read_socket=FALSE;
1214 	}
1215 	session->rtp.rcv_last_app_ts = user_ts;
1216 	if (read_socket){
1217 		rtp_session_rtp_recv (session, user_ts);
1218 		rtp_session_rtcp_recv(session);
1219 	}
1220 	/* check for telephone event first */
1221 	mp=getq(&session->rtp.tev_rq);
1222 	if (mp!=NULL){
1223 		size_t msgsize=msgdsize(mp);
1224 		ortp_global_stats.recv += msgsize;
1225 		session->stats.recv += msgsize;
1226 		rtp_signal_table_emit2(&session->on_telephone_event_packet,mp);
1227 		rtp_session_check_telephone_events(session,mp);
1228 		freemsg(mp);
1229 		mp=NULL;
1230 	}
1231 
1232 	/* then now try to return a media packet, if possible */
1233 	/* first condition: if the session is starting, don't return anything
1234 	 * until the queue size reaches jitt_comp */
1235 
1236 	if (session->flags & RTP_SESSION_RECV_SYNC)
1237 	{
1238 		queue_t *q = &session->rtp.rq;
1239 		if (qempty(q))
1240 		{
1241 			ortp_debug ("Queue is empty.");
1242 			goto end;
1243 		}
1244 		rtp = (rtp_header_t *) qfirst(q)->b_rptr;
1245 		session->rtp.rcv_ts_offset = rtp->timestamp;
1246 		session->rtp.rcv_last_ret_ts = user_ts;	/* just to have an init value */
1247 		session->rcv.ssrc = rtp->ssrc;
1248 		/* delete the recv synchronisation flag */
1249 		rtp_session_unset_flag (session, RTP_SESSION_RECV_SYNC);
1250 	}
1251 
1252 	/*calculate the stream timestamp from the user timestamp */
1253 	ts = jitter_control_get_compensated_timestamp(&session->rtp.jittctl,user_ts);
1254 	if (session->rtp.jittctl.params.enabled==TRUE){
1255 		if (session->permissive)
1256 			mp = rtp_getq_permissive(&session->rtp.rq, ts,&rejected);
1257 		else{
1258 			mp = rtp_getq(&session->rtp.rq, ts,&rejected);
1259 		}
1260 	}else mp=getq(&session->rtp.rq);/*no jitter buffer at all*/
1261 
1262 	session->stats.outoftime+=rejected;
1263 	ortp_global_stats.outoftime+=rejected;
1264 	session->rtcp_xr_stats.discarded_count += rejected;
1265 
1266 	end:
1267 	if (mp != NULL)
1268 	{
1269 		size_t msgsize = msgdsize(mp);	/* evaluate how much bytes (including header) is received by app */
1270 		uint32_t packet_ts;
1271 		ortp_global_stats.recv += msgsize;
1272 		session->stats.recv += msgsize;
1273 		rtp = (rtp_header_t *) mp->b_rptr;
1274 		packet_ts=rtp->timestamp;
1275 		ortp_debug("Returning mp with ts=%i", packet_ts);
1276 		/* check for payload type changes */
1277 		if (session->rcv.pt != rtp->paytype)
1278 		{
1279 			payload_type_changed_notify(session, rtp->paytype);
1280 		}
1281 		check_for_seq_number_gap(session, rtp);
1282 		/* update the packet's timestamp so that it corrected by the
1283 		adaptive jitter buffer mechanism */
1284 		if (session->rtp.jittctl.params.adaptive){
1285 			uint32_t changed_ts;
1286 			/* only update correction offset between packets of different
1287 			timestamps*/
1288 			if (packet_ts!=session->rtp.rcv_last_ts)
1289 				jitter_control_update_corrective_slide(&session->rtp.jittctl);
1290 			changed_ts=packet_ts+session->rtp.jittctl.corrective_slide;
1291 			rtp->timestamp=changed_ts;
1292 			/*ortp_debug("Returned packet has timestamp %u, with clock slide compensated it is %u",packet_ts,rtp->timestamp);*/
1293 		}
1294 		session->rtp.rcv_last_ts = packet_ts;
1295 		session->rtp.rcv_last_seq = rtp->seq_number;
1296 		if (!(session->flags & RTP_SESSION_FIRST_PACKET_DELIVERED)){
1297 			rtp_session_set_flag(session,RTP_SESSION_FIRST_PACKET_DELIVERED);
1298 		}
1299 	}
1300 	else
1301 	{
1302 		ortp_debug ("No mp for timestamp queried");
1303 	}
1304 	rtp_session_rtcp_process_recv(session);
1305 
1306 	if (session->flags & RTP_SESSION_SCHEDULED)
1307 	{
1308 		/* if we are in blocking mode, then suspend the calling process until timestamp
1309 		 * wanted expires */
1310 		/* but we must not block the process if the timestamp wanted by the application is older
1311 		 * than current time */
1312 		wait_point_lock(&session->rcv.wp);
1313 		packet_time =
1314 			rtp_session_ts_to_time (session,
1315 					 user_ts -
1316 					 session->rtp.rcv_query_ts_offset) +
1317 			session->rtp.rcv_time_offset;
1318 		ortp_debug ("rtp_session_recvm_with_ts: packet_time=%i, time=%i",packet_time, sched->time_);
1319 
1320 		if (TIME_IS_STRICTLY_NEWER_THAN (packet_time, sched->time_))
1321 		{
1322 			wait_point_wakeup_at(&session->rcv.wp,packet_time, (session->flags & RTP_SESSION_BLOCKING_MODE)!=0);
1323 			session_set_clr(&sched->r_sessions,session);
1324 		}
1325 		else session_set_set(&sched->r_sessions,session);	/*to unblock _select() immediately */
1326 		wait_point_unlock(&session->rcv.wp);
1327 	}
1328 	return mp;
1329 }
1330 
1331 
1332 /**
1333  *	NOTE: use of this function is discouraged when sending payloads other than
1334  *	pcm/pcmu/pcma/adpcm types.
1335  *	rtp_session_recvm_with_ts() does better job.
1336  *
1337  *	Tries to read the bytes of the incoming rtp stream related to timestamp ts. In case
1338  *	where the user supplied buffer \a buffer is not large enough to get all the data
1339  *	related to timestamp ts, then *( have_more) is set to 1 to indicate that the application
1340  *	should recall the function with the same timestamp to get more data.
1341  *
1342  *  When the rtp session is scheduled (see rtp_session_set_scheduling_mode() ), and the
1343  *	blocking mode is on (see rtp_session_set_blocking_mode() ), then the calling thread
1344  *	is suspended until the timestamp given as argument expires, whatever a received packet
1345  *	fits the query or not.
1346  *
1347  *	Important note: it is clear that the application cannot know the timestamp of the first
1348  *	packet of the incoming stream, because it can be random. The \a ts timestamp given to the
1349  *	function is used relatively to first timestamp of the stream. In simple words, 0 is a good
1350  *	value to start calling this function.
1351  *
1352  *	This function internally calls rtp_session_recvm_with_ts() to get a rtp packet. The content
1353  *	of this packet is then copied into the user supplied buffer in an intelligent manner:
1354  *	the function takes care of the size of the supplied buffer and the timestamp given in
1355  *	argument. Using this function it is possible to read continous audio data (e.g. pcma,pcmu...)
1356  *	with for example a standart buffer of size of 160 with timestamp incrementing by 160 while the incoming
1357  *	stream has a different packet size.
1358  *
1359  *Returns: if a packet was availlable with the corresponding timestamp supplied in argument
1360  *	then the number of bytes written in the user supplied buffer is returned. If no packets
1361  *	are availlable, either because the sender has not started to send the stream, or either
1362  *	because silence packet are not transmitted, or either because the packet was lost during
1363  *	network transport, then the function returns zero.
1364  *@param session a rtp session.
1365  *@param buffer a user supplied buffer to write the data.
1366  *@param len the length in bytes of the user supplied buffer.
1367  *@param ts the timestamp wanted.
1368  *@param have_more the address of an integer to indicate if more data is availlable for the given timestamp.
1369  *
1370 **/
rtp_session_recv_with_ts(RtpSession * session,uint8_t * buffer,int len,uint32_t ts,int * have_more)1371 int rtp_session_recv_with_ts (RtpSession * session, uint8_t * buffer,
1372 				   int len, uint32_t ts, int * have_more){
1373 	mblk_t *mp=NULL;
1374 	int plen,blen=0;
1375 	*have_more=0;
1376 	while(1){
1377 		if (session->pending){
1378 			mp=session->pending;
1379 			session->pending=NULL;
1380 		}else {
1381 			mp=rtp_session_recvm_with_ts(session,ts);
1382 			if (mp!=NULL) rtp_get_payload(mp,&mp->b_rptr);
1383 		}
1384 		if (mp){
1385 			plen=(int)(mp->b_wptr-mp->b_rptr);
1386 			if (plen<=len){
1387 				memcpy(buffer,mp->b_rptr,plen);
1388 				buffer+=plen;
1389 				blen+=plen;
1390 				len-=plen;
1391 				freemsg(mp);
1392 				mp=NULL;
1393 			}else{
1394 				memcpy(buffer,mp->b_rptr,len);
1395 				mp->b_rptr+=len;
1396 				buffer+=len;
1397 				blen+=len;
1398 				len=0;
1399 				session->pending=mp;
1400 				*have_more=1;
1401 				break;
1402 			}
1403 		}else break;
1404 	}
1405 	return blen;
1406 }
1407 /**
1408  *	When the rtp session is scheduled and has started to send packets, this function
1409  *	computes the timestamp that matches to the present time. Using this function can be
1410  *	usefull when sending discontinuous streams. Some time can be elapsed between the end
1411  *	of a stream burst and the begin of a new stream burst, and the application may be not
1412  *	not aware of this elapsed time. In order to get a valid (current) timestamp to pass to
1413  *	#rtp_session_send_with_ts() or #rtp_session_sendm_with_ts(), the application may
1414  *	use rtp_session_get_current_send_ts().
1415  *
1416  * @param session a rtp session.
1417  * @return the current send timestamp for the rtp session.
1418 **/
rtp_session_get_current_send_ts(RtpSession * session)1419 uint32_t rtp_session_get_current_send_ts(RtpSession *session)
1420 {
1421 	uint32_t userts;
1422 	uint32_t session_time;
1423 	RtpScheduler *sched=session->sched;
1424 	PayloadType *payload;
1425 	payload=rtp_profile_get_payload(session->snd.profile,session->snd.pt);
1426 	return_val_if_fail(payload!=NULL, 0);
1427 	if ( (session->flags & RTP_SESSION_SCHEDULED)==0 ){
1428 		ortp_warning("can't guess current timestamp because session is not scheduled.");
1429 		return 0;
1430 	}
1431 	session_time=sched->time_-session->rtp.snd_time_offset;
1432 	userts=  (uint32_t)( ( (double)(session_time) * (double) payload->clock_rate )/ 1000.0)
1433 				+ session->rtp.snd_ts_offset;
1434 	return userts;
1435 }
1436 
1437 /**
1438  * Same thing as rtp_session_get_current_send_ts() except that it's for an incoming stream.
1439  * Works only on scheduled mode.
1440  *
1441  * @param session a rtp session.
1442  * @return the theoritical that would have to be receive now.
1443  *
1444 **/
rtp_session_get_current_recv_ts(RtpSession * session)1445 uint32_t rtp_session_get_current_recv_ts(RtpSession *session){
1446 	uint32_t userts;
1447 	uint32_t session_time;
1448 	RtpScheduler *sched=ortp_get_scheduler();
1449 	PayloadType *payload;
1450 	payload=rtp_profile_get_payload(session->rcv.profile,session->rcv.pt);
1451 	return_val_if_fail(payload!=NULL, 0);
1452 	if ( (session->flags & RTP_SESSION_SCHEDULED)==0 ){
1453 		ortp_warning("can't guess current timestamp because session is not scheduled.");
1454 		return 0;
1455 	}
1456 	session_time=sched->time_-session->rtp.rcv_time_offset;
1457 	userts=  (uint32_t)( ( (double)(session_time) * (double) payload->clock_rate )/ 1000.0)
1458 				+ session->rtp.rcv_ts_offset;
1459 	return userts;
1460 }
1461 
1462 /**
1463  * oRTP has the possibility to inform the application through a callback registered
1464  * with rtp_session_signal_connect about crazy incoming RTP stream that jumps from
1465  * a timestamp N to N+some_crazy_value. This lets the opportunity for the application
1466  * to reset the session in order to resynchronize, or any other action like stopping the call
1467  * and reporting an error.
1468  * @param session the rtp session
1469  * @param milisecs a time interval in miliseconds
1470  *
1471 **/
rtp_session_set_time_jump_limit(RtpSession * session,int milisecs)1472 void rtp_session_set_time_jump_limit(RtpSession *session, int milisecs){
1473 	uint32_t ts;
1474 	session->rtp.time_jump=milisecs;
1475 	ts=rtp_session_time_to_ts(session,milisecs);
1476 	if (ts==0) session->rtp.ts_jump=1<<31;	/* do not detect ts jump */
1477 	else session->rtp.ts_jump=ts;
1478 }
1479 
_rtp_session_release_sockets(RtpSession * session,bool_t release_transports)1480 void _rtp_session_release_sockets(RtpSession *session, bool_t release_transports){
1481 
1482 	if (release_transports){
1483 		if (session->rtp.gs.tr) {
1484 			if (session->rtp.gs.tr->t_close)
1485 				session->rtp.gs.tr->t_close(session->rtp.gs.tr);
1486 			session->rtp.gs.tr->t_destroy(session->rtp.gs.tr);
1487 
1488 		}
1489 		session->rtp.gs.tr = 0;
1490 
1491 		if (session->rtcp.gs.tr)  {
1492 			if (session->rtcp.gs.tr->t_close)
1493 				session->rtcp.gs.tr->t_close(session->rtcp.gs.tr);
1494 			session->rtcp.gs.tr->t_destroy(session->rtcp.gs.tr);
1495 		}
1496 		session->rtcp.gs.tr = 0;
1497 	}
1498 
1499 	if (session->rtp.gs.socket!=(ortp_socket_t)-1) close_socket (session->rtp.gs.socket);
1500 	if (session->rtcp.gs.socket!=(ortp_socket_t)-1) close_socket (session->rtcp.gs.socket);
1501 	session->rtp.gs.socket=-1;
1502 	session->rtcp.gs.socket=-1;
1503 
1504 	/* don't discard remote addresses, then can be preserved for next use.
1505 	session->rtp.gs.rem_addrlen=0;
1506 	session->rtcp.gs.rem_addrlen=0;
1507 	*/
1508 }
1509 
1510 /**
1511  * Closes the rtp and rtcp sockets, and associated RtpTransport.
1512 **/
rtp_session_release_sockets(RtpSession * session)1513 void rtp_session_release_sockets(RtpSession *session){
1514 	_rtp_session_release_sockets(session, TRUE);
1515 }
1516 
rtp_session_get_rtp_socket(const RtpSession * session)1517 ortp_socket_t rtp_session_get_rtp_socket(const RtpSession *session){
1518 	return rtp_session_using_transport(session, rtp) ? (session->rtp.gs.tr->t_getsocket)(session->rtp.gs.tr) : session->rtp.gs.socket;
1519 }
1520 
rtp_session_get_rtcp_socket(const RtpSession * session)1521 ortp_socket_t rtp_session_get_rtcp_socket(const RtpSession *session){
1522 	return rtp_session_using_transport(session, rtcp) ? (session->rtcp.gs.tr->t_getsocket)(session->rtcp.gs.tr) : session->rtcp.gs.socket;
1523 }
1524 
1525 /**
1526  * Register an event queue.
1527  * An application can use an event queue to get informed about various RTP events.
1528 **/
rtp_session_register_event_queue(RtpSession * session,OrtpEvQueue * q)1529 void rtp_session_register_event_queue(RtpSession *session, OrtpEvQueue *q){
1530 	session->eventqs=o_list_append(session->eventqs,q);
1531 }
1532 
rtp_session_unregister_event_queue(RtpSession * session,OrtpEvQueue * q)1533 void rtp_session_unregister_event_queue(RtpSession *session, OrtpEvQueue *q){
1534 	session->eventqs=o_list_remove(session->eventqs,q);
1535 }
1536 
rtp_session_dispatch_event(RtpSession * session,OrtpEvent * ev)1537 void rtp_session_dispatch_event(RtpSession *session, OrtpEvent *ev){
1538 	OList *it;
1539 	int i;
1540 	for(i=0,it=session->eventqs;it!=NULL;it=it->next,++i){
1541 		ortp_ev_queue_put((OrtpEvQueue*)it->data,ortp_event_dup(ev));
1542 	}
1543 	ortp_event_destroy(ev);
1544 }
1545 
ortp_stream_clear_aux_addresses(OrtpStream * os)1546 void ortp_stream_clear_aux_addresses(OrtpStream *os){
1547 	OList *elem;
1548 	for (elem=os->aux_destinations;elem!=NULL;elem=elem->next){
1549 		OrtpAddress *addr=(OrtpAddress*)elem->data;
1550 		ortp_free(addr);
1551 	}
1552 	os->aux_destinations=o_list_free(os->aux_destinations);
1553 }
1554 
ortp_stream_uninit(OrtpStream * os)1555 static void ortp_stream_uninit(OrtpStream *os){
1556 	msgb_allocator_uninit(&os->allocator);
1557 	ortp_stream_clear_aux_addresses(os);
1558 }
1559 
rtp_session_uninit(RtpSession * session)1560 void rtp_session_uninit (RtpSession * session)
1561 {
1562 	RtpTransport *rtp_meta_transport = NULL;
1563 	RtpTransport *rtcp_meta_transport = NULL;
1564 	/* first of all remove the session from the scheduler */
1565 	if (session->flags & RTP_SESSION_SCHEDULED)
1566 	{
1567 		rtp_scheduler_remove_session (session->sched,session);
1568 	}
1569 	/*flush all queues */
1570 	flushq(&session->rtp.rq, FLUSHALL);
1571 	flushq(&session->rtp.tev_rq, FLUSHALL);
1572 
1573 	if (session->eventqs!=NULL) o_list_free(session->eventqs);
1574 	/* close sockets */
1575 	rtp_session_release_sockets(session);
1576 
1577 	wait_point_uninit(&session->snd.wp);
1578 	wait_point_uninit(&session->rcv.wp);
1579 	if (session->current_tev!=NULL) freemsg(session->current_tev);
1580 	ortp_stream_uninit(&session->rtp.gs);
1581 	ortp_stream_uninit(&session->rtcp.gs);
1582 	if (session->full_sdes != NULL)
1583 		freemsg(session->full_sdes);
1584 	if (session->minimal_sdes != NULL)
1585 		freemsg(session->minimal_sdes);
1586 	bctbx_list_free_with_data(session->recv_addr_map, (bctbx_list_free_func)bctbx_free);
1587 
1588 	session->signal_tables = o_list_free(session->signal_tables);
1589 
1590 	if (session->net_sim_ctx)
1591 		ortp_network_simulator_destroy(session->net_sim_ctx);
1592 
1593 	if (session->rtp.congdetect){
1594 		ortp_congestion_detector_destroy(session->rtp.congdetect);
1595 	}
1596 
1597 	if (session->rtp.video_bw_estimator){
1598 		ortp_video_bandwidth_estimator_destroy(session->rtp.video_bw_estimator);
1599 	}
1600 
1601 	rtp_session_get_transports(session,&rtp_meta_transport,&rtcp_meta_transport);
1602 	if (rtp_meta_transport)
1603 		meta_rtp_transport_destroy(rtp_meta_transport);
1604 	if (rtcp_meta_transport)
1605 		meta_rtp_transport_destroy(rtcp_meta_transport);
1606 
1607 #if (_WIN32_WINNT >= 0x0600) && defined(ORTP_WINDOWS_DESKTOP)
1608 	if (session->rtp.QoSFlowID != 0)
1609 	{
1610 		ortp_message("check OS support for qwave.lib");
1611 		if (IsWindowsVistaOrGreater()) {
1612 			BOOL QoSResult;
1613 			QoSResult = QOSRemoveSocketFromFlow(session->rtp.QoSHandle, 0, session->rtp.QoSFlowID, 0);
1614 			if (QoSResult != TRUE){
1615 				ortp_error("QOSRemoveSocketFromFlow failed to end a flow with error %d", GetLastError());
1616 			}
1617 			session->rtp.QoSFlowID = 0;
1618 		}
1619 	}
1620 
1621 	if (session->rtp.QoSHandle != NULL)
1622 	{
1623 		QOSCloseHandle(session->rtp.QoSHandle);
1624 		session->rtp.QoSHandle=NULL;
1625 	}
1626 #endif
1627 }
1628 
1629 /**
1630  * Sets the number of packets containing a new SSRC that will trigger the
1631  * "ssrc_changed" callback.
1632 **/
rtp_session_set_ssrc_changed_threshold(RtpSession * session,int numpackets)1633 void rtp_session_set_ssrc_changed_threshold(RtpSession *session, int numpackets){
1634 	session->rtp.ssrc_changed_thres=numpackets;
1635 }
1636 
1637 /**
1638  * Resynchronize to the incoming RTP streams.
1639  * This can be useful to handle discontinuous timestamps.
1640  * For example, call this function from the timestamp_jump signal handler.
1641  * @param session the rtp session
1642 **/
rtp_session_resync(RtpSession * session)1643 void rtp_session_resync(RtpSession *session){
1644 	flushq (&session->rtp.rq, FLUSHALL);
1645 	rtp_session_set_flag(session, RTP_SESSION_RECV_SYNC);
1646 	rtp_session_unset_flag(session,RTP_SESSION_FIRST_PACKET_DELIVERED);
1647 	rtp_session_init_jitter_buffer(session);
1648 	if (session->rtp.congdetect) ortp_congestion_detector_reset(session->rtp.congdetect);
1649 	if (session->rtp.video_bw_estimator) ortp_video_bandwidth_estimator_reset(session->rtp.video_bw_estimator);
1650 
1651 	/* Since multiple streams might share the same session (fixed RTCP port for example),
1652 	RTCP values might be erroneous (number of packets received is computed
1653 	over all streams, ...). There should be only one stream per RTP session*/
1654 	session->rtp.hwrcv_extseq = 0;
1655 	session->rtp.hwrcv_since_last_SR = 0;
1656 	session->rtp.hwrcv_seq_at_last_SR = 0;
1657 	rtp_session_unset_flag(session, RTP_SESSION_RECV_SEQ_INIT);
1658 }
1659 
1660 /**
1661  * Reset the session: local and remote addresses are kept. It resets timestamp, sequence
1662  * number, and calls rtp_session_resync().
1663  *
1664  * @param session a rtp session.
1665 **/
rtp_session_reset(RtpSession * session)1666 void rtp_session_reset (RtpSession * session)
1667 {
1668 	rtp_session_set_flag (session, RTP_SESSION_RECV_NOT_STARTED);
1669 	rtp_session_set_flag (session, RTP_SESSION_SEND_NOT_STARTED);
1670 	//session->ssrc=0;
1671 	session->rtp.snd_time_offset = 0;
1672 	session->rtp.snd_ts_offset = 0;
1673 	session->rtp.snd_rand_offset = 0;
1674 	session->rtp.snd_last_ts = 0;
1675 	session->rtp.rcv_time_offset = 0;
1676 	session->rtp.rcv_ts_offset = 0;
1677 	session->rtp.rcv_query_ts_offset = 0;
1678 	session->rtp.rcv_last_ts = 0;
1679 	session->rtp.rcv_last_seq = 0;
1680 	session->rtp.rcv_last_app_ts = 0;
1681 	session->rtp.hwrcv_extseq = 0;
1682 	session->rtp.hwrcv_since_last_SR=0;
1683 	session->rtp.snd_seq = 0;
1684 	session->rtp.sent_payload_bytes=0;
1685 	rtp_session_clear_send_error_code(session);
1686 	rtp_session_clear_recv_error_code(session);
1687 	rtp_stats_reset(&session->stats);
1688 	rtp_session_resync(session);
1689 	session->ssrc_set=FALSE;
1690 }
1691 
1692 /**
1693  * Retrieve the session's statistics.
1694 **/
rtp_session_get_stats(const RtpSession * session)1695 const rtp_stats_t * rtp_session_get_stats(const RtpSession *session){
1696 	return &session->stats;
1697 }
1698 
1699 /**
1700  * Retrieves the session's jitter specific statistics.
1701 **/
rtp_session_get_jitter_stats(const RtpSession * session)1702 const jitter_stats_t * rtp_session_get_jitter_stats( const RtpSession *session ) {
1703 	return &session->rtp.jitter_stats;
1704 }
1705 
1706 /**
1707  * @brief For <b>test purpose only</b>, sets a constant lost packet value within <b>all</b> RTCP output packets.@n
1708  *
1709  * The SR or RR RTCP packet contain a lost packet field. After this procedure is called, the lost packet field will be set to a constant value in all output SR or RR packets. This parameter will overridden the actual number of lost packets in the input RTP stream that the RTCP stack had previously processed.
1710  * @param s : the rtp session.
1711  * @param value : the lost packets test vector value.
1712 **/
rtp_session_rtcp_set_lost_packet_value(struct _RtpSession * s,const int value)1713 void rtp_session_rtcp_set_lost_packet_value( struct _RtpSession *s, const int value ) {
1714 	s->lost_packets_test_vector = value;
1715 	s->flags|=RTCP_OVERRIDE_LOST_PACKETS;
1716 }
1717 
1718 /**
1719  * @brief For <b>test purpose only</b>, sets a constant interarrival_jitter value within <b>all</b> RTCP output packets.@n
1720  *
1721  * The SR or RR RTCP packet contain an interarrival jitter field. After this procedure is called, the interarrival jitter field will be set to a constant value in all output SR or RR packets. This parameter will overridden the actual interarrival jitter value that was processed by the RTCP stack.
1722  * @param s : the rtp session.
1723  * @param value : the interarrival jitter test vector value.
1724 **/
rtp_session_rtcp_set_jitter_value(struct _RtpSession * s,const unsigned int value)1725 void rtp_session_rtcp_set_jitter_value( struct _RtpSession *s, const unsigned int value ) {
1726 	s->interarrival_jitter_test_vector = value;
1727 	s->flags|=RTCP_OVERRIDE_JITTER;
1728 }
1729 
1730 /**
1731  * @brief For <b>test purpose only</b>, simulates a constant RTT (Round Trip Time) value by setting the LSR field within <b>all</b> returned RTCP output packets.@n
1732  *
1733  * The RTT processing involves two RTCP packets exchanged between two different devices.@n
1734  * In a <b>normal</b> operation the device 1 issues a SR packets at time T0, hence this packet has a timestamp field set to T0.
1735  * The LSR and DLSR fiels of that packet are not considered here. This packet is received by the Device 2 at T1.
1736  * In response, the Device 2 issues another SR or RR packets at T2 with the following fields;
1737  * - a timestamp set to T2.
1738  * - a LSR (Last SR packet timestamp) field set to T0 ( this value has been extracted from the first packet).
1739  * - a DLSR (Delay since Last SR packet) field set to (T2 - T1).
1740  * .
1741  * This packet is received by The Device 1 at T3. So the Device 1 is now able to process the RTT using the formula :
1742  * RTT = T3 - LSR - DLSR = (T1 - T0) - (T3 - T2).@n
1743  * This way of processing is described in par. 6.4 of the RFC3550 standard.
1744  *
1745  * In the <b>test</b> mode that is enabled by this procedure, the RTCP stack is considered as beeing part of the device 2. For setting the RTT to a constant RTT0 value, the Device 2 artificially sets the LSR field of the second packet to (T1 - RTT0), instead of T0 in normal mode. The two other fields (timestamp and DLSR) are set as in the normal mode. So the Device 1 will process :
1746  * RTT = T3 - LSR - DLSR = RTT0 + (T3 - T2) that is near to RTT0 is T3 - T2 is small enough.
1747  * @note It is impossible to actually make the mesured RTT strictly equal to RTT0, as the packet trip time (T3 - T2) is unknown when this packet is issued by the Device 2.
1748  * @param s : the rtp session.
1749  * @param value : The desired RTT test vector value (RTT0).
1750 **/
rtp_session_rtcp_set_delay_value(struct _RtpSession * s,const unsigned int value)1751 void rtp_session_rtcp_set_delay_value( struct _RtpSession *s, const unsigned int value ) {
1752 	s->delay_test_vector= value;
1753 	s->flags|=RTCP_OVERRIDE_DELAY;
1754 }
1755 
rtp_session_reset_stats(RtpSession * session)1756 void rtp_session_reset_stats(RtpSession *session){
1757 	memset(&session->stats,0,sizeof(rtp_stats_t));
1758 }
1759 
1760 /**
1761  * Stores some application specific data into the session, so that it is easy to retrieve it from the signal callbacks using rtp_session_get_data().
1762  * @param session a rtp session
1763  * @param data an opaque pointer to be stored in the session
1764 **/
1765 
rtp_session_set_data(RtpSession * session,void * data)1766 void rtp_session_set_data(RtpSession *session, void *data){
1767 	session->user_data=data;
1768 }
1769 
1770 /**
1771  * @param session a rtp session
1772  * @return the void pointer previously set using rtp_session_set_data()
1773 **/
rtp_session_get_data(const RtpSession * session)1774 void *rtp_session_get_data(const RtpSession *session){
1775 	return session->user_data;
1776 }
1777 
1778 /**
1779  * Enable or disable the "rtp symmetric" hack which consists of the following:
1780  * after the first packet is received, the source address of the packet
1781  * is set to be the destination address for all next packets.
1782  * This is useful to pass-through firewalls.
1783  * @param session a rtp session
1784  * @param yesno a boolean to enable or disable the feature
1785  *
1786 **/
1787 void
rtp_session_set_symmetric_rtp(RtpSession * session,bool_t yesno)1788 rtp_session_set_symmetric_rtp (RtpSession * session, bool_t yesno)
1789 {
1790 	session->symmetric_rtp =yesno;
1791 }
1792 
rtp_session_enable_rtcp_mux(RtpSession * session,bool_t yesno)1793 void rtp_session_enable_rtcp_mux(RtpSession *session, bool_t yesno){
1794 	session->rtcp_mux = yesno;
1795 }
1796 
rtp_session_rtcp_mux_enabled(RtpSession * session)1797 bool_t rtp_session_rtcp_mux_enabled(RtpSession *session){
1798 	return session->rtcp_mux;
1799 }
1800 
1801 /**
1802  *	If yesno is TRUE, thus a connect() syscall is done on the socket to
1803  *	the destination address set by rtp_session_set_remote_addr(), or
1804  *	if the session does symmetric rtp (see rtp_session_set_symmetric_rtp())
1805  *	a the connect() is done to the source address of the first packet received.
1806  *	Connecting a socket has effect of rejecting all incoming packets that
1807  *	don't come from the address specified in connect().
1808  *	It also makes ICMP errors (such as connection refused) available to the
1809  *	application.
1810  *	@param session a rtp session
1811  *	@param yesno a boolean to enable or disable the feature
1812  *
1813 **/
rtp_session_set_connected_mode(RtpSession * session,bool_t yesno)1814 void rtp_session_set_connected_mode(RtpSession *session, bool_t yesno){
1815 	session->use_connect=yesno;
1816 }
1817 
compute_bw(struct timeval * orig,unsigned int * bytes,const struct timeval * current)1818 static float compute_bw(struct timeval *orig, unsigned int *bytes, const struct timeval *current){
1819 	float bw;
1820 	float time;
1821 
1822 	time=(float)((double)(current->tv_sec - orig->tv_sec) +
1823 		((double)(current->tv_usec - orig->tv_usec)*1e-6));
1824 	bw=((float)*bytes)*8/(time+0.0001f);
1825 	/*+0.0001 avoids a division by zero without changing the results significatively*/
1826 	*orig=*current;
1827 	return bw;
1828 }
1829 
1830 #define BW_GAMMA 0.5f
1831 
compute_recv_bandwidth(OrtpStream * os,const struct timeval * current)1832 static void compute_recv_bandwidth(OrtpStream *os, const struct timeval *current) {
1833 	os->download_bw = compute_bw(&os->recv_bw_start, &os->recv_bytes, current);
1834 	os->recv_bytes = 0;
1835 	os->average_download_bw = (os->average_download_bw==0) ?
1836 							os->download_bw :
1837 							(1 - BW_GAMMA) * os->average_download_bw + BW_GAMMA * os->download_bw;
1838 }
1839 
compute_send_bandwidth(OrtpStream * os,const struct timeval * current)1840 static void compute_send_bandwidth(OrtpStream *os, const struct timeval *current) {
1841 	os->upload_bw = compute_bw(&os->send_bw_start, &os->sent_bytes, current);
1842 	os->sent_bytes = 0;
1843 	os->average_upload_bw = (os->average_upload_bw==0) ?
1844 							os->upload_bw :
1845 							(1 - BW_GAMMA) * os->average_upload_bw + BW_GAMMA * os->upload_bw;
1846 }
1847 
rtp_session_compute_recv_bandwidth(RtpSession * session)1848 float rtp_session_compute_recv_bandwidth(RtpSession *session) {
1849 	struct timeval current;
1850 	ortp_gettimeofday(&current,NULL);
1851 
1852 	compute_recv_bandwidth(&session->rtp.gs, &current);
1853 	compute_recv_bandwidth(&session->rtcp.gs, &current);
1854 	return session->rtp.gs.download_bw + session->rtcp.gs.download_bw;
1855 }
1856 
rtp_session_compute_send_bandwidth(RtpSession * session)1857 float rtp_session_compute_send_bandwidth(RtpSession *session) {
1858 	struct timeval current;
1859 	ortp_gettimeofday(&current,NULL);
1860 
1861 	compute_send_bandwidth(&session->rtp.gs, &current);
1862 	compute_send_bandwidth(&session->rtcp.gs, &current);
1863 	return session->rtp.gs.upload_bw + session->rtcp.gs.upload_bw;
1864 }
1865 
1866 /**
1867  * Get last computed recv bandwidth.
1868  * Computation must have been done with rtp_session_compute_recv_bandwidth()
1869 **/
rtp_session_get_recv_bandwidth(RtpSession * session)1870 float rtp_session_get_recv_bandwidth(RtpSession *session){
1871 	//return session->rtp.gs.download_bw + session->rtcp.gs.download_bw;
1872 	return ortp_bw_estimator_get_value(&session->rtp.gs.recv_bw_estimator) + ortp_bw_estimator_get_value(&session->rtcp.gs.recv_bw_estimator);
1873 }
1874 
rtp_session_get_recv_bandwidth_smooth(RtpSession * session)1875 float rtp_session_get_recv_bandwidth_smooth(RtpSession *session){
1876 	return session->rtp.gs.average_download_bw + session->rtcp.gs.average_download_bw;
1877 }
1878 
1879 /**
1880  * Get last computed send bandwidth.
1881  * Computation must have been done with rtp_session_compute_send_bandwidth()
1882 **/
rtp_session_get_send_bandwidth(RtpSession * session)1883 float rtp_session_get_send_bandwidth(RtpSession *session){
1884 	return session->rtp.gs.upload_bw + session->rtcp.gs.upload_bw;
1885 }
1886 
rtp_session_get_send_bandwidth_smooth(RtpSession * session)1887 float rtp_session_get_send_bandwidth_smooth(RtpSession *session){
1888 	return session->rtp.gs.average_upload_bw + session->rtcp.gs.average_upload_bw;
1889 }
1890 
rtp_session_get_rtp_recv_bandwidth(RtpSession * session)1891 float rtp_session_get_rtp_recv_bandwidth(RtpSession *session) {
1892 	//return session->rtp.gs.download_bw;
1893 	return ortp_bw_estimator_get_value(&session->rtp.gs.recv_bw_estimator);
1894 }
1895 
rtp_session_get_rtp_send_bandwidth(RtpSession * session)1896 float rtp_session_get_rtp_send_bandwidth(RtpSession *session) {
1897 	return session->rtp.gs.upload_bw;
1898 }
1899 
rtp_session_get_rtcp_recv_bandwidth(RtpSession * session)1900 float rtp_session_get_rtcp_recv_bandwidth(RtpSession *session) {
1901 	//return session->rtcp.gs.download_bw;
1902 	return ortp_bw_estimator_get_value(&session->rtcp.gs.recv_bw_estimator);
1903 }
1904 
rtp_session_get_rtcp_send_bandwidth(RtpSession * session)1905 float rtp_session_get_rtcp_send_bandwidth(RtpSession *session) {
1906 	return session->rtcp.gs.upload_bw;
1907 }
1908 
rtp_session_get_last_send_error_code(RtpSession * session)1909 int rtp_session_get_last_send_error_code(RtpSession *session){
1910 	return session->rtp.send_errno;
1911 }
1912 
rtp_session_clear_send_error_code(RtpSession * session)1913 void rtp_session_clear_send_error_code(RtpSession *session){
1914 	session->rtp.send_errno=0;
1915 }
1916 
rtp_session_get_last_recv_error_code(RtpSession * session)1917 int rtp_session_get_last_recv_error_code(RtpSession *session){
1918 	return session->rtp.recv_errno;
1919 }
1920 
rtp_session_clear_recv_error_code(RtpSession * session)1921 void rtp_session_clear_recv_error_code(RtpSession *session){
1922 	session->rtp.send_errno=0;
1923 }
1924 
1925 /**
1926  * Returns the last known round trip propagation delay.
1927  *
1928  * This value is known after successful RTCP SR or RR exchanged between a sender and a receiver.
1929  * oRTP automatically takes care of sending SR or RR packets.
1930  * You might want to call this function when you receive an RTCP event (see rtp_session_register_event_queue() ).
1931  * This value might not be known: at the beginning when no RTCP packets have been exchanged yet, or simply because the
1932  * rtcp channel is broken due to firewall problematics, or because the remote implementation does not support RTCP.
1933  *
1934  * @return the round trip propagation time in seconds if known, -1 if unknown.
1935 **/
rtp_session_get_round_trip_propagation(RtpSession * session)1936 float rtp_session_get_round_trip_propagation(RtpSession *session){
1937 	return session->rtt;
1938 }
1939 
1940 /**
1941  * Destroys a rtp session.
1942  * All memory allocated for the RtpSession is freed.
1943  *
1944  * @param session a rtp session.
1945 **/
rtp_session_destroy(RtpSession * session)1946 void rtp_session_destroy (RtpSession * session)
1947 {
1948 	rtp_session_uninit (session);
1949 	ortp_free (session);
1950 }
1951 
rtp_session_make_time_distorsion(RtpSession * session,int milisec)1952 void rtp_session_make_time_distorsion(RtpSession *session, int milisec)
1953 {
1954 	session->rtp.snd_time_offset+=milisec;
1955 }
1956 
1957 
1958 /* packet api */
1959 
rtp_add_csrc(mblk_t * mp,uint32_t csrc)1960 void rtp_add_csrc(mblk_t *mp, uint32_t csrc)
1961 {
1962 	rtp_header_t *hdr=(rtp_header_t*)mp->b_rptr;
1963 	hdr->csrc[hdr->cc]=csrc;
1964 	hdr->cc++;
1965 }
1966 
1967 /**
1968  * Get a pointer to the beginning of the payload data of the RTP packet.
1969  * @param packet a RTP packet represented as a mblk_t
1970  * @param start a pointer to the beginning of the payload data, pointing inside the packet.
1971  * @return the length of the payload data.
1972 **/
rtp_get_payload(mblk_t * packet,unsigned char ** start)1973 int rtp_get_payload(mblk_t *packet, unsigned char **start){
1974 	unsigned char *tmp;
1975 	int header_len=RTP_FIXED_HEADER_SIZE+(rtp_get_cc(packet)*4);
1976 	tmp=packet->b_rptr+header_len;
1977 	if (tmp>packet->b_wptr){
1978 		if (packet->b_cont!=NULL){
1979 			tmp=packet->b_cont->b_rptr+(header_len- (packet->b_wptr-packet->b_rptr));
1980 			if (tmp<=packet->b_cont->b_wptr){
1981 				*start=tmp;
1982 				return (int)(packet->b_cont->b_wptr-tmp);
1983 			}
1984 		}
1985 		ortp_warning("Invalid RTP packet");
1986 		return -1;
1987 	}
1988 	if (rtp_get_extbit(packet)){
1989 		int extsize=rtp_get_extheader(packet,NULL,NULL);
1990 		if (extsize>=0){
1991 			tmp+=4+extsize;
1992 		}
1993 	}
1994 	*start=tmp;
1995 	return (int)(packet->b_wptr-tmp);
1996 }
1997 
1998 /**
1999  * Obtain the extension header if any.
2000  * @param packet the RTP packet.
2001  * @param profile the profile field of the extension header
2002  * @param start_ext pointer that will be set to the beginning of the payload of the extension header.
2003  * @return the size of the extension in bytes (the payload size, it can be 0), -1 if parsing of the extension header failed or if no extension is present.
2004 **/
rtp_get_extheader(mblk_t * packet,uint16_t * profile,uint8_t ** start_ext)2005 int rtp_get_extheader(mblk_t *packet, uint16_t *profile, uint8_t **start_ext){
2006 	int size=0;
2007 	uint8_t *ext_header;
2008 	if (rtp_get_extbit(packet)){
2009 		ext_header=packet->b_rptr+RTP_FIXED_HEADER_SIZE+(rtp_get_cc(packet)*4);
2010 		if (ext_header+4 <= packet->b_wptr){
2011 			uint32_t h=ntohl(*(uint32_t*)ext_header);
2012 			size=(int)(h & 0xFFFF);
2013 			if (profile) *profile=(h>>16);
2014 			size=(size*4); /*the size is given in the packet as multiple of 32 bit words, excluding the 4 byte header*/
2015 			if ((ext_header+4+size)> packet->b_wptr){
2016 				ortp_warning("Inconsistent size for rtp extension header");
2017 				return -1;
2018 			}
2019 			if (start_ext) *start_ext=ext_header+4;
2020 			return size;
2021 		}else{
2022 			ortp_warning("Insufficient size for rtp extension header.");
2023 			return -1;
2024 		}
2025 	}
2026 	return -1;
2027 }
2028 
2029 
2030 /**
2031  *  Gets last time a valid RTP or RTCP packet was received.
2032  * @param session RtpSession to get last receive time from.
2033  * @param tv Pointer to struct timeval to fill.
2034  *
2035 **/
2036 void
rtp_session_get_last_recv_time(RtpSession * session,struct timeval * tv)2037 rtp_session_get_last_recv_time(RtpSession *session, struct timeval *tv)
2038 {
2039 #ifdef PERF
2040 	ortp_error("rtp_session_get_last_recv_time() feature disabled.");
2041 #else
2042 	*tv = session->last_recv_time;
2043 #endif
2044 }
2045 
2046 
2047 
rtp_session_time_to_ts(RtpSession * session,int millisecs)2048 uint32_t rtp_session_time_to_ts(RtpSession *session, int millisecs){
2049 	PayloadType *payload;
2050 	payload =
2051 		rtp_profile_get_payload (session->snd.profile,
2052 					 session->snd.pt);
2053 	if (payload == NULL)
2054 	{
2055 		ortp_warning
2056 			("rtp_session_time_to_ts: use of unsupported payload type %d.", session->snd.pt);
2057 		return 0;
2058 	}
2059 	/* the return value is in milisecond */
2060 	return (uint32_t) (payload->clock_rate*(double) (millisecs/1000.0f));
2061 }
2062 
2063 /* function used by the scheduler only:*/
rtp_session_ts_to_time(RtpSession * session,uint32_t timestamp)2064 uint32_t rtp_session_ts_to_time (RtpSession * session, uint32_t timestamp)
2065 {
2066 	PayloadType *payload;
2067 	payload =
2068 		rtp_profile_get_payload (session->snd.profile,
2069 					 session->snd.pt);
2070 	if (payload == NULL)
2071 	{
2072 		ortp_warning
2073 			("rtp_session_ts_to_t: use of unsupported payload type %d.", session->snd.pt);
2074 		return 0;
2075 	}
2076 	/* the return value is in milisecond */
2077 	return (uint32_t) (1000.0 *
2078 			  ((double) timestamp /
2079 			   (double) payload->clock_rate));
2080 }
2081 
2082 
2083 /* time is the number of miliseconds elapsed since the start of the scheduler */
rtp_session_process(RtpSession * session,uint32_t time,RtpScheduler * sched)2084 void rtp_session_process (RtpSession * session, uint32_t time, RtpScheduler *sched)
2085 {
2086 	wait_point_lock(&session->snd.wp);
2087 	if (wait_point_check(&session->snd.wp,time)){
2088 		session_set_set(&sched->w_sessions,session);
2089 		wait_point_wakeup(&session->snd.wp);
2090 	}
2091 	wait_point_unlock(&session->snd.wp);
2092 
2093 	wait_point_lock(&session->rcv.wp);
2094 	if (wait_point_check(&session->rcv.wp,time)){
2095 		session_set_set(&sched->r_sessions,session);
2096 		wait_point_wakeup(&session->rcv.wp);
2097 	}
2098 	wait_point_unlock(&session->rcv.wp);
2099 }
2100 
rtp_session_set_reuseaddr(RtpSession * session,bool_t yes)2101 void rtp_session_set_reuseaddr(RtpSession *session, bool_t yes) {
2102 	session->reuseaddr=yes;
2103 }
2104 
2105 
2106 typedef struct _MetaRtpTransportImpl{
2107 	RtpTransport *other_meta_rtp; /*pointer to the "other" meta RtpTransport, that is the RTCP transport if we are RTP, and the RTP transport
2108 		if we are RTCP. This is used only for RTCP-mux*/
2109 	OList *modifiers;
2110 	RtpTransport *endpoint;
2111 	bool_t is_rtp;
2112 	bool_t has_set_session;
2113 } MetaRtpTransportImpl;
2114 
meta_rtp_transport_getsocket(RtpTransport * t)2115 ortp_socket_t meta_rtp_transport_getsocket(RtpTransport *t) {
2116 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2117 
2118 	if (m->endpoint!=NULL){
2119 		return m->endpoint->t_getsocket(m->endpoint);
2120 	}
2121 	return (m->is_rtp ? t->session->rtp.gs.socket : t->session->rtcp.gs.socket);
2122 }
2123 
meta_rtp_set_session(RtpSession * s,MetaRtpTransportImpl * m)2124 void meta_rtp_set_session(RtpSession *s,MetaRtpTransportImpl *m){
2125 	OList *elem;
2126 	/*if session has not been set yet, do nothing*/
2127 	if (s==NULL){
2128 		return;
2129 	}
2130 
2131 	if (m->endpoint!=NULL){
2132 		m->endpoint->session=s;
2133 	}
2134 	for (elem=m->modifiers;elem!=NULL;elem=o_list_next(elem)){
2135 		RtpTransportModifier *rtm=(RtpTransportModifier*)elem->data;
2136 		rtm->session=s;
2137 	}
2138 	m->has_set_session=TRUE;
2139 }
2140 
_meta_rtp_transport_send_through_endpoint(RtpTransport * t,mblk_t * msg,int flags,const struct sockaddr * to,socklen_t tolen)2141 static int _meta_rtp_transport_send_through_endpoint(RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
2142 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2143 	int ret;
2144 
2145 	if (m->endpoint!=NULL){
2146 		ret=m->endpoint->t_sendto(m->endpoint, msg, flags, to, tolen);
2147 	}else{
2148 		ret=rtp_session_sendto(t->session, m->is_rtp,msg,flags,to,tolen);
2149 	}
2150 	return ret;
2151 }
2152 
meta_rtp_transport_sendto(RtpTransport * t,mblk_t * msg,int flags,const struct sockaddr * to,socklen_t tolen)2153 int meta_rtp_transport_sendto(RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen) {
2154 	size_t prev_ret;
2155 	int ret = 0;
2156 	OList *elem;
2157 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2158 
2159 	if (!m->has_set_session){
2160 		meta_rtp_set_session(t->session,m);
2161 	}
2162 	prev_ret=msgdsize(msg);
2163 	for (elem=m->modifiers;elem!=NULL;elem=o_list_next(elem)){
2164 		RtpTransportModifier *rtm=(RtpTransportModifier*)elem->data;
2165 		ret = rtm->t_process_on_send(rtm,msg);
2166 
2167 		if (ret<=0){
2168 			// something went wrong in the modifier (failed to encrypt for instance)
2169 			return ret;
2170 		}
2171 		msg->b_wptr+=(ret-prev_ret);
2172 		prev_ret=ret;
2173 	}
2174 	if (!m->is_rtp && t->session->rtcp_mux){ /*if this meta transport is handling RTCP and using rtcp-mux, then we should expedite the packet
2175 		through the rtp endpoint.*/
2176 		if (m->other_meta_rtp){
2177 			ret = _meta_rtp_transport_send_through_endpoint(m->other_meta_rtp, msg, flags, to, tolen);
2178 		}else{
2179 			ortp_error("meta_rtp_transport_sendto(): rtcp-mux enabled but no RTP meta transport is specified !");
2180 		}
2181 	} else ret = _meta_rtp_transport_send_through_endpoint(t, msg, flags, to, tolen);
2182 	return ret;
2183 }
2184 
2185 /**
2186  * allow a modifier to inject a packet which will be treated by successive modifiers
2187  */
meta_rtp_transport_modifier_inject_packet_to_send(RtpTransport * t,RtpTransportModifier * tpm,mblk_t * msg,int flags)2188 int meta_rtp_transport_modifier_inject_packet_to_send(RtpTransport *t, RtpTransportModifier *tpm, mblk_t *msg, int flags) {
2189 	struct sockaddr *to;
2190 	socklen_t tolen;
2191 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2192 
2193 	if (!m->has_set_session){
2194 		meta_rtp_set_session(t->session,m);
2195 	}
2196 
2197 	/* get back socket from transport session */
2198 	if (m->is_rtp) {
2199 		to=(struct sockaddr*)&t->session->rtp.gs.rem_addr;
2200 		tolen=t->session->rtp.gs.rem_addrlen;
2201 	} else {
2202 		to = (struct sockaddr*)&t->session->rtcp.gs.rem_addr;
2203 		tolen = t->session->rtcp.gs.rem_addrlen;
2204 	}
2205 	return meta_rtp_transport_modifier_inject_packet_to_send_to(t, tpm, msg, flags, to, tolen);
2206 }
2207 
2208 /**
2209  * allow a modifier to inject a packet which will be treated by successive modifiers
2210  */
meta_rtp_transport_modifier_inject_packet_to_send_to(RtpTransport * t,RtpTransportModifier * tpm,mblk_t * msg,int flags,const struct sockaddr * to,socklen_t tolen)2211 int meta_rtp_transport_modifier_inject_packet_to_send_to(RtpTransport *t, RtpTransportModifier *tpm, mblk_t *msg, int flags, const struct sockaddr *to, socklen_t tolen) {
2212 	size_t prev_ret;
2213 	int ret;
2214 	bool_t foundMyself = tpm ? FALSE : TRUE; /*if no modifier, start from the beginning*/
2215 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2216 	OList *elem = m->modifiers;
2217 
2218 	if (!m->has_set_session) {
2219 		meta_rtp_set_session(t->session, m);
2220 	}
2221 
2222 	prev_ret = msgdsize(msg);
2223 	for (;elem != NULL; elem = o_list_next(elem)) {
2224 		/* run modifiers only after packet injection, the modifier given in parameter is not applied */
2225 		RtpTransportModifier *rtm = (RtpTransportModifier*)elem->data;
2226 		if (foundMyself == TRUE) {
2227 			ret = rtm->t_process_on_send(rtm, msg);
2228 
2229 			if (ret <= 0) {
2230 				// something went wrong in the modifier (failed to encrypt for instance)
2231 				return ret;
2232 			}
2233 			msg->b_wptr += (ret - prev_ret);
2234 			prev_ret = ret;
2235 		}
2236 
2237 		/* check if we must inject the packet */
2238 		if (rtm == tpm) {
2239 			foundMyself = TRUE;
2240 		}
2241 	}
2242 
2243 	if (m->endpoint != NULL) {
2244 		ret = m->endpoint->t_sendto(m->endpoint, msg, flags, to, tolen);
2245 	} else {
2246 		ret = rtp_session_sendto(t->session, m->is_rtp, msg, flags, to, tolen);
2247 	}
2248 	update_sent_bytes(&t->session->rtp.gs, ret);
2249 	return ret;
2250 }
2251 
_meta_rtp_transport_recv_through_modifiers(RtpTransport * t,RtpTransportModifier * tpm,mblk_t * msg,int flags)2252 static int _meta_rtp_transport_recv_through_modifiers(RtpTransport *t, RtpTransportModifier *tpm, mblk_t *msg, int flags){
2253 	int ret = 0;
2254 	size_t prev_ret;
2255 	bool_t foundMyself = tpm ? FALSE : TRUE; /*if no modifier, start from the beginning*/
2256 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2257 	OList *elem = m->modifiers;
2258 	OList *last_elem = NULL;
2259 
2260 	for (;elem != NULL; elem = o_list_next(elem)) {
2261 		last_elem = elem;
2262 	}
2263 
2264 	prev_ret = msgdsize(msg);
2265 	ret = (int)prev_ret;
2266 	for (;last_elem != NULL; last_elem = o_list_prev(last_elem)) {
2267 		/* run modifiers only after packet injection, the modifier given in parameter is not applied */
2268 		RtpTransportModifier *rtm = (RtpTransportModifier*)last_elem->data;
2269 		if (foundMyself == TRUE) {
2270 			ret = rtm->t_process_on_receive(rtm, msg);
2271 			if (ret < 0) {
2272 				// something went wrong in the modifier (failed to decrypt for instance)
2273 				break;
2274 			}
2275 			msg->b_wptr += ((size_t)ret - prev_ret);
2276 			prev_ret = (size_t)ret;
2277 		}
2278 
2279 		/* check if we must inject the packet */
2280 		if (rtm == tpm) {
2281 			foundMyself = TRUE;
2282 		}
2283 	}
2284 	return ret;
2285 }
2286 
2287 /**
2288  * allow a modifier to inject a packet which will be treated by successive modifiers
2289  */
meta_rtp_transport_modifier_inject_packet_to_recv(RtpTransport * t,RtpTransportModifier * tpm,mblk_t * msg,int flags)2290 int meta_rtp_transport_modifier_inject_packet_to_recv(RtpTransport *t, RtpTransportModifier *tpm, mblk_t *msg, int flags) {
2291 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2292 	int ret = _meta_rtp_transport_recv_through_modifiers(t, tpm, msg, flags);
2293 	rtp_session_process_incoming(t->session, msg, m->is_rtp, msg->reserved1, FALSE);
2294 	return ret;
2295 }
2296 
2297 
meta_rtp_transport_recvfrom(RtpTransport * t,mblk_t * msg,int flags,struct sockaddr * from,socklen_t * fromlen)2298 int meta_rtp_transport_recvfrom(RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen) {
2299 	int ret;
2300 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2301 	OList *elem;
2302 	bool_t received_via_rtcp_mux = FALSE;
2303 
2304 	if (!m->has_set_session){
2305 		meta_rtp_set_session(t->session,m);
2306 	}
2307 
2308 	/*invoke on schedule on every modifier first, regardless of if a packet is actually received.*/
2309 	for (elem=m->modifiers;elem!=NULL;elem=o_list_next(elem)){
2310 		RtpTransportModifier *rtm=(RtpTransportModifier*)elem->data;
2311 
2312 		if (rtm->t_process_on_schedule) rtm->t_process_on_schedule(rtm);
2313 	}
2314 
2315 	if (m->endpoint!=NULL){
2316 		ret=m->endpoint->t_recvfrom(m->endpoint,msg,flags,from,fromlen);
2317 		if (ret > 0) {
2318 			/*store recv addr for use by modifiers*/
2319 			if (from && fromlen) {
2320 				memcpy(&msg->net_addr,from,*fromlen);
2321 				msg->net_addrlen = *fromlen;
2322 			}
2323 		}
2324 	}else{
2325 		ret=rtp_session_recvfrom(t->session,m->is_rtp,msg,flags,from,fromlen);
2326 	}
2327 
2328 	if (ret <= 0){
2329 		return ret;
2330 	}
2331 	msg->b_wptr+=ret;
2332 
2333 	/*in case of rtcp-mux, we are allowed to reconsider whether it is an RTP or RTCP packet*/
2334 	if (t->session->rtcp_mux && m->is_rtp){
2335 		if (ret >= RTP_FIXED_HEADER_SIZE && rtp_get_version(msg) == 2){
2336 			int pt = rtp_get_payload_type(msg);
2337 			if (pt >= 64 && pt <= 95){
2338 				/*this is assumed to be an RTCP packet*/
2339 				received_via_rtcp_mux = TRUE;
2340 			}
2341 		}
2342 	}
2343 
2344 	if (received_via_rtcp_mux){
2345 		if (m->other_meta_rtp){
2346 			_meta_rtp_transport_recv_through_modifiers(m->other_meta_rtp, NULL, msg, flags);
2347 			rtp_session_process_incoming(t->session, dupmsg(msg),FALSE, msg->reserved1, received_via_rtcp_mux);
2348 			ret = 0; /*since we directly inject in the RtpSession this RTCP packet, we shall return 0 and pass a duplicate of the message,
2349 			because rtp_session_rtp_recv() is going to free it.*/
2350 		}else{
2351 			ortp_error("RTCP packet received via rtcp-mux but RTCP transport is not set !");
2352 		}
2353 	}else ret = _meta_rtp_transport_recv_through_modifiers(t, NULL, msg, flags);
2354 
2355 	// subtract last written value since it will be rewritten by rtp_session_rtp_recv
2356 	msg->b_wptr-= ret;
2357 
2358 	return ret;
2359 }
2360 
meta_rtp_transport_close(RtpTransport * t)2361 void  meta_rtp_transport_close(RtpTransport *t) {
2362 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)t->data;
2363 	if (m->endpoint!=NULL){
2364 		m->endpoint->t_close(m->endpoint);
2365 	}
2366 }
2367 
_meta_rtp_transport_new(bool_t is_rtp,RtpTransport * endpoint,unsigned modifiers_count,va_list arguments)2368 static RtpTransport* _meta_rtp_transport_new(bool_t is_rtp, RtpTransport *endpoint, unsigned modifiers_count, va_list arguments) {
2369 	MetaRtpTransportImpl *m;
2370 	RtpTransport *t = ortp_new0(RtpTransport,1);
2371 	m=t->data=ortp_new0(MetaRtpTransportImpl,1);
2372 
2373 	t->t_getsocket=meta_rtp_transport_getsocket;
2374 	t->t_sendto=meta_rtp_transport_sendto;
2375 	t->t_recvfrom=meta_rtp_transport_recvfrom;
2376 	t->t_close=meta_rtp_transport_close;
2377 	t->t_destroy=meta_rtp_transport_destroy;
2378 
2379 	m->is_rtp = is_rtp;
2380 	m->endpoint=endpoint;
2381 	while (modifiers_count != 0){
2382 		m->modifiers=o_list_append(m->modifiers, va_arg(arguments,RtpTransportModifier*));
2383 		modifiers_count--;
2384 	}
2385 
2386 	return t;
2387 }
2388 
meta_rtp_transport_new(RtpTransport * endpoint,unsigned modifiers_count,...)2389 RtpTransport* meta_rtp_transport_new(RtpTransport *endpoint, unsigned modifiers_count, ...){
2390 	RtpTransport *tr;
2391 	va_list args;
2392 	va_start (args, modifiers_count);
2393 	tr = _meta_rtp_transport_new(TRUE, endpoint, modifiers_count, args);
2394 	va_end(args);
2395 	return tr;
2396 }
2397 
meta_rtcp_transport_new(RtpTransport * endpoint,unsigned modifiers_count,...)2398 RtpTransport* meta_rtcp_transport_new(RtpTransport *endpoint, unsigned modifiers_count, ...){
2399 	RtpTransport *tr;
2400 	va_list args;
2401 	va_start (args, modifiers_count);
2402 	tr = _meta_rtp_transport_new(FALSE, endpoint, modifiers_count, args);
2403 	va_end(args);
2404 	return tr;
2405 }
2406 
2407 /*this links both meta rtp transport, which is necessary for rtcp-mux to work*/
meta_rtp_transport_link(RtpTransport * rtp,RtpTransport * rtcp)2408 void meta_rtp_transport_link(RtpTransport *rtp, RtpTransport *rtcp){
2409 	MetaRtpTransportImpl *mrtp = (MetaRtpTransportImpl*)rtp->data;
2410 	MetaRtpTransportImpl *mrtcp = (MetaRtpTransportImpl*)rtcp->data;
2411 	mrtp->other_meta_rtp = rtcp;
2412 	mrtcp->other_meta_rtp = rtp;
2413 }
2414 
meta_rtp_transport_get_endpoint(const RtpTransport * transport)2415 RtpTransport* meta_rtp_transport_get_endpoint(const RtpTransport *transport) {
2416 	return transport->data ? ((MetaRtpTransportImpl *)transport->data)->endpoint:NULL;
2417 }
2418 
meta_rtp_transport_set_endpoint(RtpTransport * transport,RtpTransport * endpoint)2419 void meta_rtp_transport_set_endpoint(RtpTransport *transport,RtpTransport *endpoint) {
2420 	if (transport->data) {
2421 		((MetaRtpTransportImpl *)transport->data)->endpoint=endpoint;
2422 	} else
2423 		ortp_error("Cannot set endpoint [%p] on rtp transport [%p]",transport,endpoint);
2424 }
2425 
meta_rtp_transport_destroy(RtpTransport * tp)2426 void meta_rtp_transport_destroy(RtpTransport *tp) {
2427 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)tp->data;
2428 	OList *elem;
2429 
2430 	if (m->endpoint!=NULL){
2431 		m->endpoint->t_destroy(m->endpoint);
2432 	}
2433 
2434 	for (elem=m->modifiers;elem!=NULL;elem=o_list_next(elem)){
2435 		RtpTransportModifier *rtm=(RtpTransportModifier*)elem->data;
2436 		rtm->transport = NULL;
2437 		rtm->t_destroy(rtm);
2438 	}
2439 	o_list_free(m->modifiers);
2440 
2441 	ortp_free(m);
2442 	ortp_free(tp);
2443 }
2444 
meta_rtp_transport_append_modifier(RtpTransport * tp,RtpTransportModifier * tpm)2445 void meta_rtp_transport_append_modifier(RtpTransport *tp,RtpTransportModifier *tpm) {
2446 	MetaRtpTransportImpl *m = (MetaRtpTransportImpl*)tp->data;
2447 	tpm->transport = tp;
2448 	m->modifiers=o_list_append(m->modifiers, tpm);
2449 	if(m->has_set_session) {
2450 		tpm->session = tp->session;
2451 	}
2452 }
rtp_session_get_symmetric_rtp(const RtpSession * session)2453 bool_t rtp_session_get_symmetric_rtp(const RtpSession *session) {
2454 	return session->symmetric_rtp;
2455 }
2456 
rtp_session_splice(RtpSession * session,RtpSession * to_session)2457 int rtp_session_splice(RtpSession *session, RtpSession *to_session){
2458 	if (session->spliced_session){
2459 		ortp_error("rtp_session_splice(): session %p already splicing into session %p", session, session->spliced_session);
2460 		return -1;
2461 	}
2462 	session->spliced_session = to_session;
2463 	to_session->is_spliced = TRUE;
2464 	ortp_message("rtp_session_splice(): session %p splicing to %p", session, to_session);
2465 	return 0;
2466 }
2467 
rtp_session_unsplice(RtpSession * session,RtpSession * to_session)2468 int rtp_session_unsplice(RtpSession *session, RtpSession *to_session){
2469 	if (session->spliced_session != to_session){
2470 		ortp_error("rtp_session_unsplice() session %p is not spliced to session %p", session, to_session);
2471 		return -1;
2472 	}
2473 	session->spliced_session = NULL;
2474 	to_session->is_spliced = FALSE;
2475 	ortp_message("rtp_session_unsplice(): session %p no longer splicing to %p", session, to_session);
2476 	return 0;
2477 }
2478 
2479 /*
2480  * send packet through the peered session, the mblk_t is not freed.
2481 **/
rtp_session_do_splice(RtpSession * session,mblk_t * packet,bool_t is_rtp)2482 void rtp_session_do_splice(RtpSession *session, mblk_t *packet, bool_t is_rtp){
2483 	RtpSession *peer = session->spliced_session;
2484 	if (peer){
2485 		OrtpStream *os = is_rtp ? &peer->rtp.gs : &peer->rtcp.gs;
2486 		_ortp_sendto(os->socket, packet, 0, (struct sockaddr*)&os->rem_addr, os->rem_addrlen);
2487 	}
2488 }
2489 
ortp_stream_is_ipv6(OrtpStream * os)2490 bool_t ortp_stream_is_ipv6(OrtpStream *os) {
2491 	if (os->sockfamily == AF_INET6) {
2492 		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&os->rem_addr;
2493 		return !IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr);
2494 	}
2495 	return FALSE;
2496 }
2497