1 /**
2  * session.cpp
3  * Yet Another RTP Stack
4  * This file is part of the YATE Project http://YATE.null.ro
5  *
6  * Yet Another Telephony Engine - a fully featured software PBX and IVR
7  * Copyright (C) 2004-2014 Null Team
8  *
9  * This software is distributed under multiple licenses;
10  * see the COPYING file in the main directory for licensing
11  * information for this specific distribution.
12  *
13  * This use of this software may be subject to additional restrictions.
14  * See the LEGAL file in the main directory for details.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #include <yatertp.h>
22 
23 #include <string.h>
24 #include <stdlib.h>
25 
26 using namespace TelEngine;
27 
28 // u_int64_t Infinity
29 #define INF_TIMEOUT ((u_int64_t)(int64_t)-1)
30 
31 // How many lost packets mean we lost sequence sync
32 #define SEQ_DESYNC_COUNT 50
33 // How many packets in a row will resync sequence
34 #define SEQ_RESYNC_COUNT 5
35 
RTPDebug(RTPSession * session)36 RTPDebug::RTPDebug(RTPSession* session)
37     : m_dbg(0)
38 {
39     if (session)
40 	setDebug(session->dbg(),session->dbgTraceId());
41 }
42 
43 
~RTPBaseIO()44 RTPBaseIO::~RTPBaseIO()
45 {
46     security(0);
47 }
48 
dataPayload(int type)49 bool RTPBaseIO::dataPayload(int type)
50 {
51     if ((type >= -1) && (type <= 127)) {
52 	m_dataType = type;
53 	return true;
54     }
55     return false;
56 }
57 
eventPayload(int type)58 bool RTPBaseIO::eventPayload(int type)
59 {
60     if ((type >= -1) && (type <= 127)) {
61 	m_eventType = type;
62 	return true;
63     }
64     return false;
65 }
66 
silencePayload(int type)67 bool RTPBaseIO::silencePayload(int type)
68 {
69     if ((type >= -1) && (type <= 127)) {
70 	m_silenceType = type;
71 	return true;
72     }
73     return false;
74 }
75 
ssrcInit()76 unsigned int RTPBaseIO::ssrcInit()
77 {
78     if (m_ssrcInit) {
79 	m_ssrcInit = false;
80 	do {
81 	    m_ssrc = Random::random();
82 	} while (0 == m_ssrc);
83     }
84     return m_ssrc;
85 }
86 
security(RTPSecure * secure)87 void RTPBaseIO::security(RTPSecure* secure)
88 {
89     DDebug(dbg(),DebugInfo,"RTPBaseIO::security(%p) old=%p [%p]",secure,m_secure,this);
90     if (secure == m_secure)
91 	return;
92     RTPSecure* tmp = m_secure;
93     m_secure = 0;
94     if (secure) {
95 	secure->owner(this);
96 	m_secure = secure;
97     }
98     else
99 	secLength(0,0);
100     TelEngine::destruct(tmp);
101 }
102 
initDebugData(bool recv,const NamedList & params)103 void RTPBaseIO::initDebugData(bool recv, const NamedList& params)
104 {
105     const String* p = params.getParam(YSTRING("debug_rtp"));
106     if (!p)
107 	return;
108     bool on = p->toBoolean();
109     String suff(recv ? "_recv" : "_send");
110     m_debugData = params.getBoolValue("debug_rtp_data" + suff,
111 	params.getBoolValue(YSTRING("debug_rtp_data"),on));
112     m_debugEvent = params.getBoolValue("debug_rtp_event" + suff,
113 	params.getBoolValue(YSTRING("debug_rtp_event"),on));
114     m_debugDataLevel = params.getIntValue(YSTRING("debug_rtp_level"),DebugAll);
115     if (m_debugDataLevel <= DebugFail)
116 	m_debugDataLevel = 1 + DebugFail;
117 }
118 
119 
~RTPReceiver()120 RTPReceiver::~RTPReceiver()
121 {
122     setDejitter(0);
123 }
124 
setDejitter(RTPDejitter * dejitter)125 void RTPReceiver::setDejitter(RTPDejitter* dejitter)
126 {
127     if (dejitter == m_dejitter)
128 	return;
129     DDebug(dbg(),DebugInfo,"RTP setting new dejitter %p [%p]",dejitter,this);
130     RTPDejitter* tmp = m_dejitter;
131     m_dejitter = 0;
132     if (tmp) {
133 	tmp->group(0);
134 	tmp->destruct();
135     }
136     // make the dejitter buffer belong to the same group as the session
137     if (dejitter && m_session)
138 	dejitter->group(m_session->group());
139     m_dejitter = dejitter;
140 }
141 
rtpData(const void * data,int len)142 void RTPReceiver::rtpData(const void* data, int len)
143 {
144     // trivial check for basic fields validity
145     if ((len < m_secLen + 12) || !data)
146 	return;
147     const unsigned char* pc = (const unsigned char*)data;
148     // check protocol version number
149     if ((pc[0] & 0xc0) != 0x80)
150 	return;
151     const unsigned char* secPtr = 0;
152     if (m_secLen) {
153 	// security info is placed after data and padding
154 	len -= m_secLen;
155 	secPtr = pc + len;
156     }
157     // check if padding is present and remove it (but remember length)
158     unsigned char padding = 0;
159     if (pc[0] & 0x20) {
160 	len -= (padding = pc[len-1]);
161 	if (len < 12)
162 	    return;
163     }
164 
165     bool ext = (pc[0] & 0x10) != 0;
166     int cc = pc[0] & 0x0f;
167     bool marker = (pc[1] & 0x80) != 0;
168     int typ = pc[1] & 0x7f;
169     u_int16_t seq = ((u_int16_t)pc[2] << 8) | pc[3];
170     u_int32_t ts = ((u_int32_t)pc[4] << 24) | ((u_int32_t)pc[5] << 16) |
171 	((u_int32_t)pc[6] << 8) | pc[7];
172     u_int32_t ss = ((u_int32_t)pc[8] << 24) | ((u_int32_t)pc[9] << 16) |
173 	((u_int32_t)pc[10] << 8) | pc[11];
174 
175     // skip over header and any CSRC
176     pc += 12+(4*cc);
177     len -= 12+(4*cc);
178     // check if extension is present and skip it
179     if (ext) {
180 	if (len < 4)
181 	    return;
182 	int xl = ((int)pc[2] << 8) | pc[3];
183 	pc += xl+4;
184 	len -= xl+4;
185     }
186     if (len < 0)
187 	return;
188     if (!len)
189 	pc = 0;
190 
191     // grab some data at the first packet received or resync
192     if (m_ssrcInit) {
193 	m_ssrcInit = false;
194 	m_ssrc = ss;
195 	m_ts = ts - m_tsLast;
196 	m_seq = seq-1;
197 	m_seqCount = 0;
198 	m_warn = true;
199 	if (m_debugData)
200 	    TraceDebug(m_traceId,dbg(),m_debugDataLevel,"RTP recv INIT SEQ=%u TS=%u TS_LAST=%u [%p]",
201 		seq,ts,m_tsLast,this);
202 	if (m_dejitter)
203 	    m_dejitter->clear();
204     }
205 
206     if (ss != m_ssrc) {
207 	rtpNewSSRC(ss,marker);
208 	// check if the SSRC is still unchanged
209 	if (ss != m_ssrc) {
210 	    if (m_warn) {
211 		m_warn = false;
212 		TraceDebug(m_traceId,dbg(),DebugWarn,"RTP Received SSRC %08X but expecting %08X [%p]",
213 		    ss,m_ssrc,this);
214 	    }
215 	    m_wrongSSRC++;
216 	    return;
217 	}
218 	// SSRC accepted, sync sequence and resync the timestamp offset
219 	m_seq = seq;
220 	m_ts = ts - m_tsLast;
221 	m_seqCount = 0;
222 	if (m_debugData)
223 	    TraceDebug(m_traceId,dbg(),m_debugDataLevel,
224 		"RTP recv SEQ=%u TS=%u TS_LAST=%u new SSRC accepted, dropping [%p]",
225 		seq,ts,m_tsLast,this);
226 	if (m_dejitter)
227 	    m_dejitter->clear();
228 	// drop this packet, next packet will come in correctly
229 	return;
230     }
231 
232     u_int32_t rollover = m_rollover;
233     // compare unsigned to detect rollovers
234     if (seq < m_seq)
235 	rollover++;
236     u_int64_t seq48 = rollover;
237     seq48 = (seq48 << 16) | seq;
238 
239     // if some security data is present authenticate the packet now
240     if (secPtr && !rtpCheckIntegrity((const unsigned char*)data,len + padding + 12,secPtr + m_mkiLen,ss,seq48)) {
241 	if (m_debugData)
242 	    TraceDebug(m_traceId,dbg(),m_debugDataLevel,
243 		"RTP recv SEQ=%u TS=%u TS_LAST=%u integrity check failed, dropping [%p]",
244 		seq,ts,m_tsLast,this);
245 	return;
246     }
247 
248     // substraction with overflow to compute sequence difference
249     int16_t ds = seq - m_seq;
250     if (ds != 1)
251 	m_seqLost++;
252     if (ds == 0) {
253 	if (m_debugData)
254 	    TraceDebug(m_traceId,dbg(),m_debugDataLevel,
255 		"RTP recv SEQ=%u TS=%u TS_LAST=%u same as our last seq, dropping [%p]",
256 		seq,ts,m_tsLast,this);
257 	return;
258     }
259 
260     // check if we received a packet too much out of sequence
261     // be much more tolerant when authenticating as we cannot resync
262     if ((ds <= -SEQ_DESYNC_COUNT) || ((ds > SEQ_DESYNC_COUNT) && !secPtr)) {
263 	m_ioLostPkt++;
264 	if (!secPtr) {
265 	    // try to resync sequence unless we need to authenticate
266 	    if (m_seqCount++) {
267 		if (seq == ++m_seqSync) {
268 		    // good - packets numbers still in sequence
269 		    if (m_seqCount >= SEQ_RESYNC_COUNT) {
270 			if (m_debugData)
271 			    TraceDebug(m_traceId,dbg(),m_debugDataLevel,
272 				"RTP recv SEQ=%u TS=%u TS_LAST=%u sequence resync from current %u [%p]",
273 				seq,ts,m_tsLast,m_seq,this);
274 			else
275 			    TraceDebug(m_traceId,dbg(),DebugNote,"RTP sequence resync: %u -> %u [%p]",m_seq,seq,this);
276 			// sync sequence but keep the timestamp offset
277 			m_seq = seq;
278 			m_seqCount = 0;
279 			if (m_warnSeq > 0)
280 			    m_warn = true;
281 			else
282 			    m_warnSeq = -1;
283 			m_syncLost++;
284 			if (m_dejitter)
285 			    m_dejitter->clear();
286 			// drop this packet, next packet will come in correctly
287 			return;
288 		    }
289 		}
290 		else
291 		    m_seqCount = 0;
292 	    }
293 	    else
294 		m_seqSync = seq;
295 	}
296 	if (m_debugData)
297 	    m_warnSeq = -1;
298 	if (m_warnSeq > 0) {
299 	    if (m_warn) {
300 		m_warn = false;
301 		TraceDebug(m_traceId,dbg(),DebugWarn,"RTP received SEQ %u while current is %u [%p]",seq,m_seq,this);
302 	    }
303 	}
304 	else if (m_warnSeq < 0) {
305 	    m_warnSeq = 0;
306 	    TraceDebug(m_traceId,dbg(),DebugInfo,"RTP received SEQ %u while current is %u [%p]",seq,m_seq,this);
307 	}
308 	return;
309     }
310 
311     if (!rtpDecipher(const_cast<unsigned char*>(pc),len + padding,secPtr,ss,seq48))
312 	return;
313 
314     if (m_debugData) {
315 	const char* extra = "";
316 	if (m_dejitter)
317 	    extra = " [DEJITTER]";
318 	else if (ds < 1)
319 	    extra = ", dropping";
320 	TraceDebug(m_traceId,dbg(),m_debugDataLevel,
321 	    "RTP recv payload=%d SEQ=%u (delta=%d) TS=%u TS_LAST %u -> %u%s [%p]",
322 	    typ,seq,ds,ts,m_tsLast,(ts - m_ts),extra,this);
323     }
324     m_tsLast = ts - m_ts;
325     m_seqCount = 0;
326     m_ioPackets++;
327     m_ioOctets += len;
328     // keep track of the last valid sequence number and timestamp we have seen
329     m_seq = seq;
330     m_rollover = rollover;
331 
332     if (m_dejitter) {
333 	if (!m_dejitter->rtpRecv(marker,typ,m_tsLast,pc,len))
334 	    m_ioLostPkt++;
335 	return;
336     }
337     if (ds > 1)
338 	m_ioLostPkt += (ds - 1);
339     if (ds >= 1)
340 	rtpRecv(marker,typ,m_tsLast,pc,len);
341 }
342 
rtcpData(const void * data,int len)343 void RTPReceiver::rtcpData(const void* data, int len)
344 {
345 }
346 
rtpRecv(bool marker,int payload,unsigned int timestamp,const void * data,int len)347 bool RTPReceiver::rtpRecv(bool marker, int payload, unsigned int timestamp, const void* data, int len)
348 {
349     if ((payload != dataPayload()) && (payload != eventPayload()) && (payload != silencePayload()))
350 	rtpNewPayload(payload,timestamp);
351     if (payload == eventPayload())
352 	return decodeEvent(marker,timestamp,data,len);
353     if (payload == silencePayload())
354 	return decodeSilence(marker,timestamp,data,len);
355     finishEvent(timestamp);
356     if (payload == dataPayload())
357 	return rtpRecvData(marker,timestamp,data,len);
358     return false;
359 }
360 
rtpRecvData(bool marker,unsigned int timestamp,const void * data,int len)361 bool RTPReceiver::rtpRecvData(bool marker, unsigned int timestamp, const void* data, int len)
362 {
363     return m_session && m_session->rtpRecvData(marker,timestamp,data,len);
364 }
365 
rtpRecvEvent(int event,char key,int duration,int volume,unsigned int timestamp)366 bool RTPReceiver::rtpRecvEvent(int event, char key, int duration, int volume, unsigned int timestamp)
367 {
368     return m_session && m_session->rtpRecvEvent(event,key,duration,volume,timestamp);
369 }
370 
rtpNewPayload(int payload,unsigned int timestamp)371 void RTPReceiver::rtpNewPayload(int payload, unsigned int timestamp)
372 {
373     if (m_session)
374 	m_session->rtpNewPayload(payload,timestamp);
375 }
376 
rtpNewSSRC(u_int32_t newSsrc,bool marker)377 void RTPReceiver::rtpNewSSRC(u_int32_t newSsrc, bool marker)
378 {
379     if (m_session)
380 	m_session->rtpNewSSRC(newSsrc,marker);
381 }
382 
decodeEvent(bool marker,unsigned int timestamp,const void * data,int len)383 bool RTPReceiver::decodeEvent(bool marker, unsigned int timestamp, const void* data, int len)
384 {
385     // we support only basic RFC2833, no RFC2198 redundancy
386     if (len < 4)
387 	return false;
388     const unsigned char* pc = (const unsigned char*)data;
389     for (; len >= 4; len-=4, pc+=4) {
390 	int event = pc[0];
391 	int vol = pc[1] & 0x3f;
392 	bool end = (pc[1] & 0x80) != 0;
393 	int duration = ((int)pc[2] << 8) | pc[3];
394 	if (m_evTs && (m_evNum >= 0)) {
395 	    if ((m_evNum != event) && (m_evTs <= timestamp)) {
396 		if (m_debugEvent)
397 		    TraceDebug(m_traceId,dbg(),m_debugDataLevel,
398 			"RTP recv ending current event (event/ts changed) event=%d (received=%d) "
399 			"ts=%u event_ts=%u duration=%u [%p]",
400 			m_evNum,event,timestamp,m_evTs,timestamp - m_evTs,this);
401 		pushEvent(m_evNum,timestamp - m_evTs,m_evVol,m_evTs);
402 	    }
403 	}
404 	m_evVol = vol;
405 	if (m_debugEvent) {
406 	    const char* oper = "start";
407 	    if (end)
408 		oper = "end";
409 	    else if (m_evNum >= 0)
410 		oper = "update";
411 	    TraceDebug(m_traceId,dbg(),m_debugDataLevel,
412 		"RTP recv event oper=%s event=%d (old=%d) ts=%u event_ts=%u duration=%u [%p]",
413 		oper,event,m_evNum,timestamp,m_evTs,duration,this);
414 	}
415 	if (!end) {
416 	    m_evTs = timestamp;
417 	    m_evNum = event;
418 	    continue;
419 	}
420 	if (m_evTs > timestamp)
421 	    return false;
422 	// make sure we don't see the same event again
423 	m_evTs = timestamp+1;
424 	m_evNum = -1;
425 	pushEvent(event,duration,vol,timestamp);
426     }
427     return true;
428 }
429 
decodeSilence(bool marker,unsigned int timestamp,const void * data,int len)430 bool RTPReceiver::decodeSilence(bool marker, unsigned int timestamp, const void* data, int len)
431 {
432     return false;
433 }
434 
finishEvent(unsigned int timestamp)435 void RTPReceiver::finishEvent(unsigned int timestamp)
436 {
437     if ((m_evNum < 0) || !m_evTs)
438 	return;
439     int duration = timestamp - m_evTs;
440     if (duration < 10000)
441 	return;
442     if (m_debugEvent)
443 	TraceDebug(m_traceId,dbg(),m_debugDataLevel,
444 	    "RTP recv finishing event=%d ts=%u event_ts=%u duration=%u [%p]",
445 	    m_evNum,timestamp,m_evTs,duration,this);
446     timestamp = m_evTs;
447     m_evTs = 0;
448     pushEvent(m_evNum,duration,m_evVol,timestamp);
449 }
450 
pushEvent(int event,int duration,int volume,unsigned int timestamp)451 bool RTPReceiver::pushEvent(int event, int duration, int volume, unsigned int timestamp)
452 {
453     static const char dtmf[] = "0123456789*#ABCDF";
454     char key = (event <= 16) ? dtmf[event] : 0;
455     return rtpRecvEvent(event,key,duration,volume,timestamp);
456 }
457 
timerTick(const Time & when)458 void RTPReceiver::timerTick(const Time& when)
459 {
460 }
461 
rtpDecipher(unsigned char * data,int len,const void * secData,u_int32_t ssrc,u_int64_t seq)462 bool RTPReceiver::rtpDecipher(unsigned char* data, int len, const void* secData, u_int32_t ssrc, u_int64_t seq)
463 {
464     return (m_secure)
465 	? m_secure->rtpDecipher(data,len,secData,ssrc,seq)
466 	: true;
467 }
468 
rtpCheckIntegrity(const unsigned char * data,int len,const void * authData,u_int32_t ssrc,u_int64_t seq)469 bool RTPReceiver::rtpCheckIntegrity(const unsigned char* data, int len, const void* authData, u_int32_t ssrc, u_int64_t seq)
470 {
471     return (m_secure)
472 	? m_secure->rtpCheckIntegrity(data,len,authData,ssrc,seq)
473 	: true;
474 }
475 
stats(NamedList & stat) const476 void RTPReceiver::stats(NamedList& stat) const
477 {
478     if (m_session)
479 	stat.setParam("remoteip",m_session->UDPSession::transport()->remoteAddr().host());
480     stat.setParam("lostpkts",String(m_ioLostPkt));
481     stat.setParam("synclost",String(m_syncLost));
482     stat.setParam("wrongssrc",String(m_wrongSSRC));
483     stat.setParam("seqslost",String(m_seqLost));
484 }
485 
486 
RTPSender(RTPSession * session,bool randomTs)487 RTPSender::RTPSender(RTPSession* session, bool randomTs)
488     : RTPBaseIO(session), m_evTime(0), m_padding(0)
489 {
490     if (randomTs) {
491 	m_ts = Random::random() & ~1;
492 	// avoid starting sequence numbers too close to zero
493 	m_seq = (uint16_t)(2500 + (Random::random() % 60000));
494     }
495 }
496 
rtpSend(bool marker,int payload,unsigned int timestamp,const void * data,int len)497 bool RTPSender::rtpSend(bool marker, int payload, unsigned int timestamp, const void* data, int len)
498 {
499     if (m_debugData) {
500 	const char* oper = "send";
501 	if (!(m_session && m_session->UDPSession::transport()))
502 	    oper = "not sending";
503 	TraceDebug(m_traceId,dbg(),m_debugDataLevel,
504 	    "RTP %s seq=%u payload=%d ts=%u len=%u  [%p]",
505 	    oper,(m_seq + 1),payload,timestamp,(data ? len : 0),this);
506     }
507 
508     if (!(m_session && m_session->UDPSession::transport()))
509 	return false;
510 
511     if (!data)
512 	len = 0;
513     payload &= 0x7f;
514     if (marker || m_ssrcInit)
515 	payload |= 0x80;
516     m_tsLast = timestamp;
517     timestamp += m_ts;
518     ssrcInit();
519     m_seq++;
520     if (m_seq == 0)
521 	m_rollover++;
522     m_ioPackets++;
523     m_ioOctets += len;
524 
525     unsigned char padding = 0;
526     unsigned char byte1 = 0x80;
527     if (m_padding > 1) {
528 	padding = len % m_padding;
529 	if (padding) {
530 	    padding = m_padding - padding;
531 	    byte1 |= 0x20;
532 	}
533     }
534 
535     m_buffer.resize(len + padding + m_secLen + 12);
536     unsigned char* pc = (unsigned char*)m_buffer.data();
537     if (padding)
538 	pc[len + padding + 11] = padding;
539     *pc++ = byte1;
540     *pc++ = payload;
541     *pc++ = (unsigned char)(m_seq >> 8);
542     *pc++ = (unsigned char)(m_seq & 0xff);
543     *pc++ = (unsigned char)(timestamp >> 24);
544     *pc++ = (unsigned char)(timestamp >> 16);
545     *pc++ = (unsigned char)(timestamp >> 8);
546     *pc++ = (unsigned char)(timestamp & 0xff);
547     *pc++ = (unsigned char)(m_ssrc >> 24);
548     *pc++ = (unsigned char)(m_ssrc >> 16);
549     *pc++ = (unsigned char)(m_ssrc >> 8);
550     *pc++ = (unsigned char)(m_ssrc & 0xff);
551     if (data && len) {
552 	::memcpy(pc,data,len);
553 	rtpEncipher(pc,len + padding);
554     }
555     if (m_secLen)
556 	rtpAddIntegrity((const unsigned char*)m_buffer.data(),len + padding + 12,pc + (len + padding + m_mkiLen));
557     static_cast<RTPProcessor*>(m_session->UDPSession::transport())->rtpData(m_buffer.data(),m_buffer.length());
558     return true;
559 }
560 
rtpSendData(bool marker,unsigned int timestamp,const void * data,int len)561 bool RTPSender::rtpSendData(bool marker, unsigned int timestamp, const void* data, int len)
562 {
563     if (dataPayload() < 0)
564 	return false;
565     if (sendEventData(timestamp))
566 	return true;
567     return rtpSend(marker,dataPayload(),timestamp,data,len);
568 }
569 
rtpSendEvent(int event,int duration,int volume,unsigned int timestamp)570 bool RTPSender::rtpSendEvent(int event, int duration, int volume, unsigned int timestamp)
571 {
572     // send as RFC2833 if we have the payload type set
573     if (eventPayload() < 0)
574 	return false;
575     if ((duration <= 50) || (duration > 10000))
576 	duration = 1600;
577     if (!timestamp)
578 	timestamp = m_tsLast;
579     if (m_evTs) {
580 	TraceDebug(m_traceId,dbg(),DebugNote,"RFC 2833 overlapped in RTP event %d, session %p, fixing.",
581 	    event,m_session);
582 	// the timestamp must always advance to avoid misdetections
583 	if (timestamp == m_evTs)
584 	    m_tsLast = timestamp = timestamp + 2;
585 	// make sure we send an event end packet
586 	m_evTime = 0;
587 	sendEventData(timestamp);
588     }
589     m_evTs = timestamp;
590     m_evNum = event;
591     m_evVol = volume;
592     m_evTime = duration;
593     m_evSeq = 0;
594     return sendEventData(timestamp);
595 }
596 
rtpSendKey(char key,int duration,int volume,unsigned int timestamp)597 bool RTPSender::rtpSendKey(char key, int duration, int volume, unsigned int timestamp)
598 {
599     int event = 0;
600     if ((key >= '0') && (key <= '9'))
601 	event = key - '0';
602     else if (key == '*')
603 	event = 10;
604     else if (key == '#')
605 	event = 11;
606     else if ((key >= 'A') && (key <= 'D'))
607 	event = key + 12 - 'A';
608     else if ((key >= 'a') && (key <= 'd'))
609 	event = key + 12 - 'a';
610     else if ((key == 'F') || (key == 'f'))
611 	event = 16;
612     else
613 	return false;
614     return rtpSendEvent(event,duration,volume,timestamp);
615 }
616 
sendEventData(unsigned int timestamp)617 bool RTPSender::sendEventData(unsigned int timestamp)
618 {
619     if (m_evTs) {
620 	if (eventPayload() < 0) {
621 	    m_evTs = 0;
622 	    return false;
623 	}
624 	if (timestamp <= m_tsLast && m_evSeq) {
625 	    if (m_debugEvent)
626 		TraceDebug(m_traceId,dbg(),m_debugDataLevel,
627 		    "RTP send event %d timestamp=%u before last ts=%u - ignoring [%p]",
628 		    m_evNum,timestamp,m_evTs,this);
629 	    else
630 		DDebug(dbg(),DebugNote,
631 		    "RTP send event %d timestamp=%u before last ts=%u - ignoring [%p]",
632 		    m_evNum,timestamp,m_evTs,this);
633 	    return true;
634 	}
635 	m_evSeq++;
636 	int duration = timestamp - m_evTs;
637 	char end = (duration >= m_evTime) ? 0x80 : 0x00;
638 	if (m_debugEvent)
639 	    TraceDebug(m_traceId,dbg(),m_debugDataLevel,
640 		"RTP send event=%d ts=%u event_ts=%u duration=%u ev_duration=%u ev_seq=%u end=%s [%p]",
641 		m_evNum,timestamp,m_evTs,duration,m_evTime,m_evSeq,String::boolText(0 != end),this);
642 	if (end)
643 	    duration = m_evTime;
644 	char buf[4];
645 	buf[0] = m_evNum;
646 	buf[1] = (m_evVol & 0x7f) | end;
647 	buf[2] = duration >> 8;
648 	buf[3] = duration & 0xff;
649 	unsigned int tstamp = m_evTs;
650 	if (end) {
651 	    m_evTs = 0;
652 	    // repeat the event end packet to increase chances it gets seen
653 	    if (rtpSend(!duration,eventPayload(),tstamp,buf,sizeof(buf)))
654 		m_seq--;
655 	}
656 	bool ok = rtpSend(!duration,eventPayload(),tstamp,buf,sizeof(buf));
657 	// have to update last timestamp since we sent the event start stamp
658 	m_tsLast = timestamp;
659 	return ok;
660     }
661     return false;
662 }
663 
padding(int chunk)664 bool RTPSender::padding(int chunk)
665 {
666     if ((chunk < 0) || (chunk > 128))
667 	return false;
668     m_padding = chunk;
669     return true;
670 }
671 
timerTick(const Time & when)672 void RTPSender::timerTick(const Time& when)
673 {
674 }
675 
rtpEncipher(unsigned char * data,int len)676 void RTPSender::rtpEncipher(unsigned char* data, int len)
677 {
678     if (m_secure)
679 	m_secure->rtpEncipher(data,len);
680 }
681 
rtpAddIntegrity(const unsigned char * data,int len,unsigned char * authData)682 void RTPSender::rtpAddIntegrity(const unsigned char* data, int len, unsigned char* authData)
683 {
684     if (m_secure)
685 	m_secure->rtpAddIntegrity(data,len,authData);
686 }
687 
stats(NamedList & stat) const688 void RTPSender::stats(NamedList& stat) const
689 {
690 }
691 
692 
UDPSession(DebugEnabler * dbg,const char * traceId)693 UDPSession::UDPSession(DebugEnabler* dbg, const char* traceId)
694     : RTPProcessor(dbg,traceId),
695     m_transport(0), m_timeoutTime(0), m_timeoutInterval(0)
696 {
697     DDebug(this->dbg(),DebugAll,"UDPSession::UDPSession() [%p]",this);
698 }
699 
~UDPSession()700 UDPSession::~UDPSession()
701 {
702     DDebug(dbg(),DebugAll,"UDPSession::~UDPSession() [%p]",this);
703     group(0);
704     transport(0);
705 }
706 
timeout(bool initial)707 void UDPSession::timeout(bool initial)
708 {
709     DDebug(dbg(),DebugNote,"UDPSession::timeout(%s) [%p]",String::boolText(initial),this);
710 }
711 
transport(RTPTransport * trans)712 void UDPSession::transport(RTPTransport* trans)
713 {
714     DDebug(dbg(),DebugInfo,"UDPSession::transport(%p) old=%p [%p]",trans,m_transport,this);
715     if (trans == m_transport)
716 	return;
717     TelEngine::destruct(m_transport);
718     m_transport = trans;
719     if (m_transport)
720 	m_transport->setProcessor(this);
721 }
722 
createTransport()723 RTPTransport* UDPSession::createTransport()
724 {
725     RTPTransport* trans = new RTPTransport(RTPTransport::RTP,dbg(),m_traceId);
726     trans->group(group());
727     return trans;
728 }
729 
initGroup(int msec,Thread::Priority prio,const String & affinity)730 bool UDPSession::initGroup(int msec, Thread::Priority prio, const String& affinity)
731 {
732     if (m_group)
733 	return true;
734     // try to pick the group from the transport if it has one
735     if (m_transport)
736 	group(m_transport->group());
737     if (!m_group)
738 	group(new RTPGroup(msec,prio,affinity));
739     if (!m_group)
740 	return false;
741     if (m_transport)
742 	m_transport->group(m_group);
743     return true;
744 }
745 
initTransport()746 bool UDPSession::initTransport()
747 {
748     if (m_transport)
749 	return true;
750     transport(createTransport());
751     return (m_transport != 0);
752 }
753 
setTimeout(int interval)754 void UDPSession::setTimeout(int interval)
755 {
756     if (interval) {
757 	if (interval < 0)
758 	    interval = 0;
759 	// force sane limits: between 500ms and 60s
760 	else if (interval < 500)
761 	    interval = 500;
762 	else if (interval > 60000)
763 	    interval = 60000;
764     }
765     m_timeoutTime = 0;
766     m_timeoutInterval = interval * (u_int64_t)1000;
767 }
768 
769 
RTPSession(DebugEnabler * dbg,const char * traceId)770 RTPSession::RTPSession(DebugEnabler* dbg, const char* traceId)
771     : UDPSession(dbg,traceId), Mutex(true,"RTPSession"),
772       m_direction(FullStop),
773       m_send(0), m_recv(0), m_secure(0),
774       m_reportTime(0), m_reportInterval(0),
775       m_warnSeq(1)
776 {
777     DDebug(this->dbg(),DebugInfo,"RTPSession::RTPSession() [%p]",this);
778 }
779 
~RTPSession()780 RTPSession::~RTPSession()
781 {
782     DDebug(dbg(),DebugInfo,"RTPSession::~RTPSession() [%p]",this);
783     direction(FullStop);
784     group(0);
785     transport(0);
786     TelEngine::destruct(m_secure);
787 }
788 
timerTick(const Time & when)789 void RTPSession::timerTick(const Time& when)
790 {
791     if (m_send)
792 	static_cast<RTPBaseIO*>(m_send)->timerTick(when);
793     if (m_recv)
794 	static_cast<RTPBaseIO*>(m_recv)->timerTick(when);
795 
796     if (m_timeoutInterval) {
797 	// only check timeout if we have a receiver
798 	if (m_timeoutTime && m_recv) {
799 	    if (when >= m_timeoutTime) {
800 		// rearm timeout next time we get a packet
801 		m_timeoutTime = INF_TIMEOUT;
802 		timeout(0 == m_recv->ssrc());
803 	    }
804 	}
805 	else
806 	    m_timeoutTime = when + m_timeoutInterval;
807     }
808     if (m_reportInterval) {
809 	if (when >= m_reportTime) {
810 	    m_reportTime = when + m_reportInterval;
811 	    sendRtcpReport(when);
812 	}
813     }
814 }
815 
rtpData(const void * data,int len)816 void RTPSession::rtpData(const void* data, int len)
817 {
818     if ((m_direction & RecvOnly) == 0)
819 	return;
820     if (m_recv) {
821 	m_timeoutTime = 0;
822 	m_recv->rtpData(data,len);
823     }
824 }
825 
rtcpData(const void * data,int len)826 void RTPSession::rtcpData(const void* data, int len)
827 {
828     if ((m_direction & RecvOnly) == 0)
829 	return;
830     if (m_recv) {
831 	if ((m_timeoutTime != INF_TIMEOUT) || m_recv->ssrc())
832 	    m_timeoutTime = 0;
833 	m_recv->rtcpData(data,len);
834     }
835 }
836 
rtpRecvData(bool marker,unsigned int timestamp,const void * data,int len)837 bool RTPSession::rtpRecvData(bool marker, unsigned int timestamp, const void* data, int len)
838 {
839     XDebug(dbg(),DebugAll,"RTPSession::rtpRecv(%s,%u,%p,%d) [%p]",
840 	String::boolText(marker),timestamp,data,len,this);
841     return false;
842 }
843 
rtpRecvEvent(int event,char key,int duration,int volume,unsigned int timestamp)844 bool RTPSession::rtpRecvEvent(int event, char key, int duration, int volume, unsigned int timestamp)
845 {
846     XDebug(dbg(),DebugAll,"RTPSession::rtpRecvEvent(%d,%02x,%d,%d,%u) [%p]",
847 	event,key,duration,volume,timestamp,this);
848     return false;
849 }
850 
rtpNewPayload(int payload,unsigned int timestamp)851 void RTPSession::rtpNewPayload(int payload, unsigned int timestamp)
852 {
853     XDebug(dbg(),DebugAll,"RTPSession::rtpNewPayload(%d,%u) [%p]",
854 	payload,timestamp,this);
855 }
856 
rtpNewSSRC(u_int32_t newSsrc,bool marker)857 void RTPSession::rtpNewSSRC(u_int32_t newSsrc,bool marker)
858 {
859     XDebug(dbg(),DebugAll,"RTPSession::rtpNewSSRC(%08X,%s) [%p]",
860 	newSsrc,String::boolText(marker),this);
861 }
862 
createSender()863 RTPSender* RTPSession::createSender()
864 {
865     return new RTPSender(this);
866 }
867 
createReceiver()868 RTPReceiver* RTPSession::createReceiver()
869 {
870     return new RTPReceiver(this);
871 }
872 
createCipher(const String & name,Cipher::Direction dir)873 Cipher* RTPSession::createCipher(const String& name, Cipher::Direction dir)
874 {
875     return 0;
876 }
877 
checkCipher(const String & name)878 bool RTPSession::checkCipher(const String& name)
879 {
880     return false;
881 }
882 
transport(RTPTransport * trans)883 void RTPSession::transport(RTPTransport* trans)
884 {
885     if (!trans)
886 	sendRtcpBye();
887     UDPSession::transport(trans);
888     if (!m_transport)
889 	m_direction = FullStop;
890 }
891 
sender(RTPSender * send)892 void RTPSession::sender(RTPSender* send)
893 {
894     DDebug(dbg(),DebugInfo,"RTPSession::sender(%p) old=%p [%p]",send,m_send,this);
895     if (send == m_send)
896 	return;
897     sendRtcpBye();
898     RTPSender* tmp = m_send;
899     m_send = send;
900     if (tmp)
901 	delete tmp;
902     if (m_send && m_secure) {
903 	RTPSecure* sec = m_secure;
904 	m_secure = 0;
905 	m_send->security(sec);
906     }
907 }
908 
receiver(RTPReceiver * recv)909 void RTPSession::receiver(RTPReceiver* recv)
910 {
911     DDebug(dbg(),DebugInfo,"RTPSession::receiver(%p) old=%p [%p]",recv,m_recv,this);
912     if (recv == m_recv)
913 	return;
914     RTPReceiver* tmp = m_recv;
915     m_recv = recv;
916     if (tmp)
917 	delete tmp;
918     if (m_recv)
919 	m_recv->m_warnSeq = m_warnSeq;
920 }
921 
security(RTPSecure * secure)922 void RTPSession::security(RTPSecure* secure)
923 {
924     if (m_send)
925 	m_send->security(secure);
926     else if (secure != m_secure) {
927 	TelEngine::destruct(m_secure);
928 	m_secure = secure;
929     }
930 }
931 
direction(Direction dir)932 bool RTPSession::direction(Direction dir)
933 {
934     DDebug(dbg(),DebugInfo,"RTPSession::direction(%d) old=%d [%p]",dir,m_direction,this);
935     if ((dir != FullStop) && !m_transport)
936 	return false;
937 
938     if (dir & RecvOnly) {
939 	if (!m_recv)
940 	    receiver(createReceiver());
941     }
942     else
943 	receiver(0);
944 
945     if (dir & SendOnly) {
946 	if (!m_send)
947 	    sender(createSender());
948     }
949     else
950 	sender(0);
951 
952     m_direction = dir;
953     return true;
954 }
955 
dataPayload(int type)956 bool RTPSession::dataPayload(int type)
957 {
958     if (m_recv || m_send) {
959 	DDebug(dbg(),DebugInfo,"RTPSession::dataPayload(%d) [%p]",type,this);
960 	bool ok = (!m_recv) || m_recv->dataPayload(type);
961 	return ((!m_send) || m_send->dataPayload(type)) && ok;
962     }
963     return false;
964 }
965 
eventPayload(int type)966 bool RTPSession::eventPayload(int type)
967 {
968     if (m_recv || m_send) {
969 	DDebug(dbg(),DebugInfo,"RTPSession::eventPayload(%d) [%p]",type,this);
970 	bool ok = (!m_recv) || m_recv->eventPayload(type);
971 	return ((!m_send) || m_send->eventPayload(type)) && ok;
972     }
973     return false;
974 }
975 
silencePayload(int type)976 bool RTPSession::silencePayload(int type)
977 {
978     if (m_recv || m_send) {
979 	DDebug(dbg(),DebugInfo,"RTPSession::silencePayload(%d) [%p]",type,this);
980 	bool ok = (!m_recv) || m_recv->silencePayload(type);
981 	return ((!m_send) || m_send->silencePayload(type)) && ok;
982     }
983     return false;
984 }
985 
getStats(String & stats) const986 void RTPSession::getStats(String& stats) const
987 {
988     DDebug(dbg(),DebugInfo,"RTPSession::getStats() tx=%p rx=%p [%p]",m_send,m_recv,this);
989     if (m_send) {
990 	stats.append("PS=",",") << m_send->ioPackets();
991 	stats << ",OS=" << m_send->ioOctets();
992     }
993     if (m_recv) {
994 	stats.append("PR=",",") << m_recv->ioPackets();
995 	stats << ",OR=" << m_recv->ioOctets();
996 	stats << ",PL=" << m_recv->ioPacketsLost();
997     }
998 }
999 
setReports(int interval)1000 void RTPSession::setReports(int interval)
1001 {
1002     if (interval > 0 && m_transport && m_transport->rtcpSock()->valid()) {
1003 	if (interval < 500)
1004 	    interval = 500;
1005 	else if (interval > 60000)
1006 	    interval = 60000;
1007 	m_reportInterval = interval * (u_int64_t)1000 + (Random::random() % 20000);
1008     }
1009     else
1010 	m_reportInterval = 0;
1011     m_reportTime = 0;
1012 }
1013 
getStats(NamedList & stats) const1014 void RTPSession::getStats(NamedList& stats) const
1015 {
1016     if (m_send)
1017 	m_send->stats(stats);
1018     if (m_recv)
1019 	m_recv->stats(stats);
1020     stats.setParam("wrongsrc",String(m_wrongSrc));
1021 }
1022 
store32(unsigned char * buf,unsigned int & len,u_int32_t val)1023 static void store32(unsigned char* buf, unsigned int& len, u_int32_t val)
1024 {
1025     buf[len++] = (unsigned char)(val >> 24);
1026     buf[len++] = (unsigned char)(val >> 16);
1027     buf[len++] = (unsigned char)(val >> 8);
1028     buf[len++] = (unsigned char)(val & 0xff);
1029 }
1030 
sendRtcpReport(const Time & when)1031 void RTPSession::sendRtcpReport(const Time& when)
1032 {
1033     if (!((m_send || m_recv) && m_transport && m_transport->rtcpSock()->valid()))
1034 	return;
1035     unsigned char buf[52];
1036     buf[0] = 0x80; // RC=0
1037     buf[1] = 0xc9; // RR
1038     buf[2] = 0;
1039     unsigned int len = 8;
1040     if (m_send && m_send->ioPackets()) {
1041 	// Include a sender report
1042 	buf[1] = 0xc8; // SR
1043 	// NTP timestamp
1044 	store32(buf,len,(uint32_t)(2208988800ULL + (when.usec() / 1000000)));
1045 	store32(buf,len,(uint32_t)(((when.usec() % 1000000) << 32) / 1000000));
1046 	// RTP timestamp
1047 	store32(buf,len,m_send->tsLast());
1048 	// Packet and octet counters
1049 	store32(buf,len,m_send->ioPackets());
1050 	store32(buf,len,m_send->ioOctets());
1051     }
1052     if (m_recv && m_recv->ioPackets()) {
1053 	// Add a single receiver report
1054 	buf[0] |= 0x01; // RC=1
1055 	store32(buf,len,m_recv->ssrc());
1056 	u_int32_t lost = m_recv->ioPacketsLost();
1057 	u_int32_t lostf = 0xff & (lost * 255 / (lost + m_recv->ioPackets()));
1058 	store32(buf,len,(lost & 0xffffff) | (lostf << 24));
1059 	store32(buf,len,(uint32_t)m_recv->fullSeq());
1060 	// TODO: Compute and store Jitter, LSR and DLSR
1061 	store32(buf,len,0);
1062 	store32(buf,len,0);
1063 	store32(buf,len,0);
1064     }
1065     // Don't send a RR with no receiver report blocks...
1066     if (len <= 8)
1067 	return;
1068     DDebug(dbg(),DebugInfo,"RTPSession sending RTCP Report [%p]",this);
1069     unsigned int lptr = 4;
1070     store32(buf,lptr,(m_send ? m_send->ssrcInit() : 0));
1071     buf[3] = (len - 1) / 4; // same as ((len + 3) / 4) - 1
1072     static_cast<RTPProcessor*>(m_transport)->rtcpData(buf,len);
1073 }
1074 
sendRtcpBye()1075 void RTPSession::sendRtcpBye()
1076 {
1077     if (!(m_send && m_transport && m_transport->rtcpSock()->valid()))
1078 	return;
1079     u_int32_t ssrc = m_send->ssrc();
1080     if (!ssrc)
1081 	return;
1082     DDebug(dbg(),DebugInfo,"RTPSession sending RTCP Bye [%p]",this);
1083     // SSRC was initialized if we sent at least one RTP or RTCP packet
1084     unsigned char buf[8];
1085     buf[0] = 0x81;
1086     buf[1] = 0xcb;
1087     buf[2] = 0;
1088     buf[3] = 1; // len = 2 x 32bit
1089     buf[4] = (unsigned char)(ssrc >> 24);
1090     buf[5] = (unsigned char)(ssrc >> 16);
1091     buf[6] = (unsigned char)(ssrc >> 8);
1092     buf[7] = (unsigned char)(0xff & ssrc);
1093     static_cast<RTPProcessor*>(m_transport)->rtcpData(buf,8);
1094 }
1095 
incWrongSrc()1096 void RTPSession::incWrongSrc()
1097 {
1098     XDebug(dbg(),DebugAll,"RTPSession::incWrongSrc() [%p]",this);
1099     m_wrongSrc++;
1100 }
1101 
1102 
UDPTLSession(u_int16_t maxLen,u_int8_t maxSec,DebugEnabler * dbg,const char * traceId)1103 UDPTLSession::UDPTLSession(u_int16_t maxLen, u_int8_t maxSec, DebugEnabler* dbg, const char* traceId)
1104     : UDPSession(dbg,traceId), Mutex(true,"UDPTLSession"),
1105       m_rxSeq(0xffff), m_txSeq(0xffff),
1106       m_maxLen(maxLen), m_maxSec(maxSec),
1107       m_warn(true)
1108 {
1109     DDebug(this->dbg(),DebugInfo,"UDPTLSession::UDPTLSession(%u,%u) [%p]",maxLen,maxSec,this);
1110     if (m_maxLen < 96)
1111 	m_maxLen = 96;
1112     else if (m_maxLen > 1492)
1113 	m_maxLen = 1492;
1114 }
1115 
~UDPTLSession()1116 UDPTLSession::~UDPTLSession()
1117 {
1118     DDebug(dbg(),DebugInfo,"UDPTLSession::~UDPTLSession() [%p]",this);
1119 }
1120 
timerTick(const Time & when)1121 void UDPTLSession::timerTick(const Time& when)
1122 {
1123     if (m_timeoutInterval) {
1124 	if (m_timeoutTime) {
1125 	    if (when >= m_timeoutTime) {
1126 		// rearm timeout next time we get a packet
1127 		m_timeoutTime = INF_TIMEOUT;
1128 		timeout(0xffff == m_rxSeq);
1129 	    }
1130 	}
1131 	else
1132 	    m_timeoutTime = when + m_timeoutInterval;
1133     }
1134 }
1135 
createTransport()1136 RTPTransport* UDPTLSession::createTransport()
1137 {
1138     RTPTransport* trans = new RTPTransport(RTPTransport::UDPTL,dbg(),m_traceId);
1139     trans->group(group());
1140     return trans;
1141 }
1142 
rtpData(const void * data,int len)1143 void UDPTLSession::rtpData(const void* data, int len)
1144 {
1145     if ((len < 6) || !data)
1146 	return;
1147     m_timeoutTime = 0;
1148     const unsigned char* pd = (const unsigned char*)data;
1149     int pLen = pd[2];
1150     if (pLen > (len-5)) {
1151 	// primary IFP does not fit in packet
1152 	if ((m_rxSeq == 0xffff) && ((pd[0] & 0xc0) == 0x80) && m_warn) {
1153 	    m_warn = false;
1154 	    TraceDebug(m_traceId,dbg(),DebugWarn,"Receiving RTP instead of UDPTL [%p]",this);
1155 	}
1156 	return;
1157     }
1158     u_int16_t seq = pd[1] + (((u_int16_t)pd[0]) << 8);
1159     // substraction with overflow
1160     int16_t ds = seq - m_rxSeq;
1161     if ((m_rxSeq == 0xffff) && (seq != 0)) {
1162 	// received sequence does not start at zero
1163 	if ((pd[0] & 0xc0) == 0x80) {
1164 	    if (m_warn) {
1165 		m_warn = false;
1166 		TraceDebug(m_traceId,dbg(),DebugWarn,"Receiving RTP instead of UDPTL [%p]",this);
1167 	    }
1168 	    return;
1169 	}
1170 	ds = 1;
1171     }
1172     if (ds < 0) {
1173 	// received old packet
1174 	if (m_warn) {
1175 	    m_warn = false;
1176 	    TraceDebug(m_traceId,dbg(),DebugWarn,"UDPTL received SEQ %u while current is %u [%p]",seq,m_rxSeq,this);
1177 	}
1178 	return;
1179     }
1180     m_warn = true;
1181     if (ds > 1) {
1182 	// some packets were lost, try to recover
1183 	if (0 == pd[pLen+3])
1184 	    // recover from secondary IFPs
1185 	    recoverSec(pd+pLen+5,len-pLen-5,seq-1,pd[pLen+4]);
1186     }
1187     m_rxSeq = seq;
1188     udptlRecv(pd+3,pLen,seq,false);
1189 }
1190 
recoverSec(const unsigned char * data,int len,u_int16_t seq,int nSec)1191 void UDPTLSession::recoverSec(const unsigned char* data, int len, u_int16_t seq, int nSec)
1192 {
1193     if ((nSec <= 0) || (len <= 1))
1194 	return;
1195     if ((int16_t)(seq - m_rxSeq) <= 0)
1196 	return;
1197     int sLen = data[0];
1198     if (sLen >= len)
1199 	return;
1200     // recursively recover from remaining secondaries
1201     recoverSec(data+sLen+1,len-sLen-1,seq-1,nSec-1);
1202     int16_t ds = seq - m_rxSeq;
1203     switch (ds) {
1204 	case 1:
1205 	    break;
1206 	case 2:
1207 	    TraceDebug(m_traceId,dbg(),DebugMild,"UDPTL lost IFP with SEQ %u [%p]",m_rxSeq+1,this);
1208 	    break;
1209 	default:
1210 	    TraceDebug(m_traceId,dbg(),DebugWarn,"UDPTL lost IFPs with SEQ %u-%u [%p]",m_rxSeq+1,seq-1,this);
1211 	    break;
1212     }
1213     TraceDebug(m_traceId,dbg(),DebugInfo,"UDPTL recovered IFP with SEQ %u [%p]",seq,this);
1214     m_rxSeq = seq;
1215     udptlRecv(data+1,sLen,seq,true);
1216 }
1217 
udptlSend(const void * data,int len,u_int16_t seq)1218 bool UDPTLSession::udptlSend(const void* data, int len, u_int16_t seq)
1219 {
1220     if (!(UDPSession::transport() && data && len))
1221 	return false;
1222     Lock lck(this);
1223     int pl = len + 5;
1224     if ((len > 255) || (pl > m_maxLen)) {
1225 	TraceDebug(m_traceId,dbg(),DebugWarn,"UDPTL could not send IFP with len=%d [%p]",len,this);
1226 	m_txQueue.clear();
1227 	return false;
1228     }
1229     // substraction with overflow
1230     int16_t ds = seq - m_txSeq;
1231     if (ds != 0) {
1232 	if (ds != 1) {
1233 	    TraceDebug(m_traceId,dbg(),DebugInfo,"UDPTL sending SEQ %u while current is %u [%p]",seq,m_txSeq,this);
1234 	    m_txQueue.clear();
1235 	}
1236 	if (m_maxSec)
1237 	    m_txQueue.insert(new DataBlock(const_cast<void*>(data),len));
1238     }
1239     DataBlock buf(0,m_maxLen);
1240     unsigned char* pd = buf.data(0,6);
1241     if (!pd)
1242 	return false;
1243     pd[0] = (seq >> 8) & 0xff;
1244     pd[1] = seq & 0xff;
1245     pd[2] = len & 0xff;
1246     ::memcpy(pd+3,data,len);
1247     pd[len+3] = 0; // secondary IFPs
1248     int nSec = 0;
1249     for (ObjList* l = m_txQueue.skipNext(); l; l = l->skipNext()) {
1250 	// truncate the TX queue when reaching maximum packet length or IFP count
1251 	if (nSec >= m_maxSec) {
1252 	    l->clear();
1253 	    break;
1254 	}
1255 	DataBlock* d = static_cast<DataBlock*>(l->get());
1256 	if ((pl+d->length()+1) > m_maxLen) {
1257 	    l->clear();
1258 	    break;
1259 	}
1260 	pd[pl] = d->length() & 0xff;
1261 	::memcpy(pd+pl+1,d->data(),d->length());
1262 	pl += d->length()+1;
1263 	nSec++;
1264     }
1265     pd[len+4] = nSec;
1266     m_txSeq = seq;
1267     static_cast<RTPProcessor*>(UDPSession::transport())->rtpData(pd,pl);
1268     return true;
1269 }
1270 
1271 /* vi: set ts=8 sw=4 sts=4 noet: */
1272