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(¤t,NULL);
1851
1852 compute_recv_bandwidth(&session->rtp.gs, ¤t);
1853 compute_recv_bandwidth(&session->rtcp.gs, ¤t);
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(¤t,NULL);
1860
1861 compute_send_bandwidth(&session->rtp.gs, ¤t);
1862 compute_send_bandwidth(&session->rtcp.gs, ¤t);
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