blob: b08e7628dd40f21d5d8dd0a83f4366c6f6b805fc [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation; either version 2 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16//
17// As a special exception, you may use this file as part of a free software
18// library without restriction. Specifically, if other files instantiate
19// templates or use macros or inline functions from this file, or you compile
20// this file and link it with other files to produce an executable, this
21// file does not by itself cause the resulting executable to be covered by
22// the GNU General Public License. This exception does not however
23// invalidate any other reasons why the executable file might be covered by
24// the GNU General Public License.
25//
26// This exception applies only to the code released under the name GNU
27// ccRTP. If you copy code from other releases into a copy of GNU
28// ccRTP, as the General Public License permits, the exception does
29// not apply to the code that you add in this way. To avoid misleading
30// anyone as to the status of such modified files, you must delete
31// this exception notice from them.
32//
33// If you write modifications of your own for GNU ccRTP, it is your choice
34// whether to permit this exception to apply to your modifications.
35// If you do not wish that, delete this exception notice.
36//
37
38/**
39 * @file rtp.h
40 *
41 * @short Generic and audio/video profile specific RTP interface of
42 * ccRTP.
43 *
44 * The classes and types in this header provide general RTP
45 * functionality (following RFC 3550) as well as audio/video RTP
46 * profile specific functionality (following RFC 3551).
47 **/
48
Alexandre Lisionddd731e2014-01-31 11:50:08 -050049#ifndef CCXX_RTP_RTP_H_
Emeric Vigier2f625822012-08-06 11:09:52 -040050#define CCXX_RTP_RTP_H_
51
52#include <ccrtp/cqueue.h>
53#include <ccrtp/channel.h>
54
Alexandre Lisionddd731e2014-01-31 11:50:08 -050055NAMESPACE_COMMONCPP
Emeric Vigier2f625822012-08-06 11:09:52 -040056
57/**
58 * @defgroup sessions RTP sessions.
59 * @{
60 **/
61
62/**
63 * @class RTPSessionBase
64 *
65 * Generic RTP protocol stack for exchange of realtime data. This
66 * stack uses the concept of packet send and receive queues to schedule
67 * and buffer outgoing packets and to arrange or reorder incoming packets
68 * as they arrive.
69 *
70 * This is a template class that allows customization of two aspects:
71 * the underlying network and the control protocol. The RTPDataChannel
72 * and RTCPChannel template parameters specify the socket types to
73 * use. The ServiceQueue template parameter specify which packet queue
74 * is used.
75 *
76 * RTPSessionBase objects do not have any threading policy, thus
77 * allowing to customize this aspect in derived classes (see
78 * SingleThreadRTPSession or RTPSessionPoolBase).
79 *
80 * @author David Sugar <dyfet@ostel.com>
81 * @short RTP protocol stack based on Common C++.
82 **/
Alexandre Lisionddd731e2014-01-31 11:50:08 -050083 template <class RTPDataChannel = DualRTPUDPIPv4Channel,
84 class RTCPChannel = DualRTPUDPIPv4Channel,
85 class ServiceQueue = AVPQueue>
86 class __EXPORT TRTPSessionBase : public ServiceQueue
87 {
88 public:
89 /**
90 * Builds a session waiting for packets in a host address.
91 *
92 * @param ia Network address this socket is to be bound.
93 * @param dataPort Transport port the data socket is to be bound.
94 * @param controlPort Transport port the control socket is to be bound.
95 * @param membersSize Initial size of the membership table.
96 * @param app Application this session is associated to.
97 * */
98 TRTPSessionBase(const InetHostAddress& ia, tpport_t dataPort,
99 tpport_t controlPort, uint32 membersSize,
100 RTPApplication& app) :
101 ServiceQueue(membersSize,app)
102 { build(ia,dataPort,controlPort); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400103
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500104 /**
105 * Builds a session with the specified ssrc identifier for the
106 * local source.
107 *
108 * @param ssrc SSRC identifier for the local source.
109 * @param ia Network address this socket is to be bound.
110 * @param dataPort Transport port the data socket is to be bound.
111 * @param controlPort Transport port the control socket is to be bound.
112 * @param membersSize Initial size of the membership table.
113 * @param app Application this session is associated to.
114 **/
115 TRTPSessionBase(uint32 ssrc,
116 const InetHostAddress& ia,
117 tpport_t dataPort, tpport_t controlPort,
118 uint32 membersSize, RTPApplication& app):
119 ServiceQueue(ssrc,membersSize,app)
120 { build(ia,dataPort,controlPort); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400121
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500122 /**
123 * Builds a session waiting for packets in a multicast address.
124 * TODO: ssrc constructor for multicast!
125 *
126 * @param ia Multicast address this socket is to be bound.
127 * @param dataPort Transport port the data socket is to be bound.
128 * @param controlPort Transport port the control socket is to be bound.
129 * @param membersSize Initial size of the membership table.
130 * @param app Application this session is associated to.
131 * @param iface Index (from 0 to n) of network interface to join to
132 * multicast group.
133 **/
134 TRTPSessionBase(const InetMcastAddress& ia, tpport_t dataPort,
135 tpport_t controlPort, uint32 membersSize,
136 RTPApplication& app, uint32 iface) :
137 ServiceQueue(membersSize,app)
138 { build(ia,dataPort,controlPort,iface); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400139
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500140 /**
141 * Builds a session waiting for packets in a multicast
142 * address, with the specified ssrc identifier for the local
143 * source.
144 *
145 * @param ssrc SSRC identifier for the local source.
146 * @param ia Multicast address this socket is to be bound.
147 * @param dataPort Transport port the data socket is to be bound.
148 * @param controlPort Transport port the control socket is to be bound.
149 * @param membersSize Initial size of the membership table.
150 * @param app Application this session is associated to.
151 * @param iface Index (from 0 to n) of network interface to join to
152 * multicast group.
153 **/
154 TRTPSessionBase(uint32 ssrc,
155 const InetMcastAddress& ia, tpport_t dataPort,
156 tpport_t controlPort, uint32 membersSize,
157 RTPApplication& app, uint32 iface) :
158 ServiceQueue(ssrc,membersSize,app)
159 { build(ia,dataPort,controlPort,iface); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400160
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500161 virtual size_t dispatchBYE(const std::string &str)
162 {
163 return QueueRTCPManager::dispatchBYE(str);
164 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400165
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500166 /**
167 * Set the value of the TTL field in the sent packets.
168 *
169 * @param ttl Time To Live
170 * @return error code from the socket operation
171 */
172 inline Socket::Error
173 setMcastTTL(uint8 ttl)
174 {
175 Socket::Error error = dso->setMulticast(true);
176 if ( error ) return error;
177 error = dso->setTimeToLive(ttl);
178 if ( error ) return error;
179 error = cso->setMulticast(true);
180 if ( error ) return error;
181 return cso->setTimeToLive(ttl);
182 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400183
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500184 inline virtual
185 ~TRTPSessionBase()
186 {
187 endSocket();
188 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400189
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500190 inline RTPDataChannel *getDSO(void)
191 {return dso;}
Emeric Vigier2f625822012-08-06 11:09:52 -0400192
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500193 protected:
194 /**
195 * @param timeout maximum timeout to wait, in microseconds
196 */
197 inline bool
198 isPendingData(microtimeout_t timeout)
199 { return dso->isPendingRecv(timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400200
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500201 InetHostAddress
202 getDataSender(tpport_t *port = NULL) const
203 { return dso->getSender(port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400204
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500205 inline size_t
206 getNextDataPacketSize() const
207 { return dso->getNextPacketSize(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400208
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500209 /**
210 * Receive data from the data channel/socket.
211 *
212 * @param buffer Memory region to read to.
213 * @param len Maximum number of octets to get.
214 * @param na Source network address.
215 * @param tp Source transport port.
216 * @return Number of octets actually read.
217 */
218 inline size_t
219 recvData(unsigned char* buffer, size_t len,
220 InetHostAddress& na, tpport_t& tp)
221 { na = dso->getSender(tp); return dso->recv(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400222
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500223 inline void
224 setDataPeer(const InetAddress &host, tpport_t port)
225 { dso->setPeer(host,port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400226
227
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500228 /**
229 * @param buffer memory region to write from
230 * @param len number of octets to write
231 */
232 inline size_t
233 sendData(const unsigned char* const buffer, size_t len)
234 { return dso->send(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400235
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500236 inline SOCKET getDataRecvSocket() const
237 { return dso->getRecvSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400238
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500239 /**
240 * @param timeout maximum timeout to wait, in microseconds
241 * @return whether there are packets waiting to be picked
242 */
243 inline bool
244 isPendingControl(microtimeout_t timeout)
245 { return cso->isPendingRecv(timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400246
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500247 InetHostAddress
248 getControlSender(tpport_t *port = NULL) const
249 { return cso->getSender(port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400250
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500251 /**
252 * Receive data from the control channel/socket.
253 *
254 * @param buffer Buffer where to get data.
255 * @param len Maximum number of octets to get.
256 * @param na Source network address.
257 * @param tp Source transport port.
258 * @return Number of octets actually read.
259 **/
260 inline size_t
261 recvControl(unsigned char *buffer, size_t len,
262 InetHostAddress& na, tpport_t& tp)
263 { na = cso->getSender(tp); return cso->recv(buffer,len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400264
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500265 inline void
266 setControlPeer(const InetAddress &host, tpport_t port)
267 { cso->setPeer(host,port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400268
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500269 /**
270 * @return number of octets actually written
271 * @param buffer
272 * @param len
273 */
274 inline size_t
275 sendControl(const unsigned char* const buffer, size_t len)
276 { return cso->send(buffer,len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400277
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500278 inline SOCKET getControlRecvSocket() const
279 { return cso->getRecvSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400280
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500281 /**
282 * Join a multicast group.
283 *
284 * @param ia address of the multicast group
285 * @return error code from the socket operation
286 */
287 inline Socket::Error
288 joinGroup(const InetMcastAddress& ia, uint32 iface)
289 {
290 Socket::Error error = dso->setMulticast(true);
291 if ( error ) return error;
292 error = dso->join(ia,iface);
293 if ( error ) return error;
294 error = cso->setMulticast(true);
295 if ( error ) {
296 dso->drop(ia);
297 return error;
298 }
299 error = cso->join(ia,iface);
300 if ( error ) {
301 dso->drop(ia);
302 return error;
303 }
304 return Socket::errSuccess;
305 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400306
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500307 /**
308 * Leave a multicast group.
309 *
310 * @param ia address of the multicast group
311 * @return error code from the socket operation
312 */
313 inline Socket::Error
314 leaveGroup(const InetMcastAddress& ia)
315 {
316 Socket::Error error = dso->setMulticast(false);
317 if ( error ) return error;
318 error = dso->leaveGroup(ia);
319 if ( error ) return error;
320 error = cso->setMulticast(false);
321 if ( error ) return error;
322 return cso->leaveGroup(ia);
323 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400324
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500325 inline void
326 endSocket()
327 {
328 if (dso) {
329 dso->endSocket();
330 delete dso;
331 }
332 dso = NULL;
333 if (cso) {
334 cso->endSocket();
335 delete cso;
336 }
337 cso = NULL;
338 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400339
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500340 private:
341 void
342 build(const InetHostAddress& ia, tpport_t dataPort,
343 tpport_t controlPort)
344 {
345 if ( 0 == controlPort ) {
346 dataBasePort = even_port(dataPort);
347 controlBasePort = dataBasePort + 1;
348 } else {
349 dataBasePort = dataPort;
350 controlBasePort = controlPort;
351 }
352 dso = new RTPDataChannel(ia,dataBasePort);
353 cso = new RTCPChannel(ia,controlBasePort);
354 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400355
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500356 void
357 build(const InetMcastAddress& ia, tpport_t dataPort,
358 tpport_t controlPort, uint32 iface)
359 {
360 if ( 0 == controlPort ) {
361 dataBasePort = even_port(dataPort);
362 controlBasePort = dataBasePort + 1;
363 } else {
364 dataBasePort = dataPort;
365 controlBasePort = controlPort;
366 }
367 dso = new RTPDataChannel(InetHostAddress("0.0.0.0"),dataBasePort);
368 cso = new RTCPChannel(InetHostAddress("0.0.0.0"),controlBasePort);
369 joinGroup(ia,iface);
370 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400371
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500372 /**
373 * Ensure a port number is odd. If it is an even number, return
374 * the next lower (odd) port number.
375 *
376 * @param port number to filter
377 * @return filtered (odd) port number
378 */
379 inline tpport_t
380 odd_port(tpport_t port)
381 { return (port & 0x01)? (port) : (port - 1); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400382
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500383 /**
384 * Ensure a port number is even. If it is an odd number, return
385 * the next lower (even) port number.
386 *
387 * @param port number to filter
388 * @return filtered (even) port number
389 */
390 inline tpport_t
391 even_port(tpport_t port)
392 { return (port & 0x01)? (port - 1) : (port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400393
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500394 tpport_t dataBasePort;
395 tpport_t controlBasePort;
Emeric Vigier2f625822012-08-06 11:09:52 -0400396
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500397 protected:
398 RTPDataChannel* dso;
399 RTCPChannel* cso;
400 friend class RTPSessionBaseHandler;
401 };
Emeric Vigier2f625822012-08-06 11:09:52 -0400402
403/**
404 * @class SingleThreadRTPSession
405 *
406 * This template class adds the threading aspect to the RTPSessionBase
407 * template in one of the many possible ways. It inherits from a
408 * single execution thread that schedules sending of outgoing packets
409 * and receipt of incoming packets.
410 *
411 * @author Federico Montesino Pouzols <fedemp@altern.org>
412 **/
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500413 template
414 <class RTPDataChannel = DualRTPUDPIPv4Channel,
415 class RTCPChannel = DualRTPUDPIPv4Channel,
416 class ServiceQueue = AVPQueue>
417 class __EXPORT SingleThreadRTPSession :
418 protected Thread,
419 public TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
420 {
421 public:
422 SingleThreadRTPSession(const InetHostAddress& ia,
423 tpport_t dataPort = DefaultRTPDataPort,
424 tpport_t controlPort = 0,
425 int pri = 0,
426 uint32 memberssize =
427 MembershipBookkeeping::defaultMembersHashSize,
428 RTPApplication& app = defaultApplication()
Emeric Vigier2f625822012-08-06 11:09:52 -0400429#if defined(_MSC_VER) && _MSC_VER >= 1300
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500430 );
Emeric Vigier2f625822012-08-06 11:09:52 -0400431#else
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500432 ):
433 Thread(pri),
434 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
435 (ia,dataPort,controlPort,memberssize,app)
436 { }
Emeric Vigier2f625822012-08-06 11:09:52 -0400437#endif
438
439 SingleThreadRTPSession(uint32 ssrc, const InetHostAddress& ia,
440 tpport_t dataPort = DefaultRTPDataPort,
441 tpport_t controlPort = 0,
442 int pri = 0,
443 uint32 memberssize =
444 MembershipBookkeeping::defaultMembersHashSize,
445 RTPApplication& app = defaultApplication()
446#if defined(_MSC_VER) && _MSC_VER >= 1300
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500447 );
Emeric Vigier2f625822012-08-06 11:09:52 -0400448#else
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500449 ):
450 Thread(pri),
451 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
452 (ssrc, ia,dataPort,controlPort,memberssize,app)
Emeric Vigier2f625822012-08-06 11:09:52 -0400453{ }
454#endif
455
456SingleThreadRTPSession(const InetMcastAddress& ia,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500457 tpport_t dataPort = DefaultRTPDataPort,
458 tpport_t controlPort = 0,
459 int pri = 0,
460 uint32 memberssize =
461 MembershipBookkeeping::defaultMembersHashSize,
462 RTPApplication& app = defaultApplication(),
463 uint32 iface = 0
Emeric Vigier2f625822012-08-06 11:09:52 -0400464#if defined(_MSC_VER) && _MSC_VER >= 1300
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500465 );
Emeric Vigier2f625822012-08-06 11:09:52 -0400466#else
467 ):
468 Thread(pri),
469 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
470 (ia,dataPort,controlPort,memberssize,app,iface)
471 { }
472#endif
473
474SingleThreadRTPSession(uint32 ssrc, const InetMcastAddress& ia,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500475 tpport_t dataPort = DefaultRTPDataPort,
476 tpport_t controlPort = 0,
477 int pri = 0,
478 uint32 memberssize =
479 MembershipBookkeeping::defaultMembersHashSize,
480 RTPApplication& app = defaultApplication(),
481 uint32 iface = 0
Emeric Vigier2f625822012-08-06 11:09:52 -0400482#if defined(_MSC_VER) && _MSC_VER >= 1300
483 );
484#else
485 ):
486 Thread(pri),
487 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
488 (ssrc,ia,dataPort,controlPort,memberssize,app,iface)
489{ }
490#endif
491
492
493~SingleThreadRTPSession()
494{
495 if (isRunning()) {
496 disableStack(); Thread::join();
497 }
498}
499
500#if defined(_MSC_VER) && _MSC_VER >= 1300
501virtual void startRunning();
502#else
503/**
504 * Activate stack and start service thread.
505 **/
506void
507startRunning()
508{ enableStack(); Thread::start(); }
509#endif
510
511
512protected:
513inline void disableStack(void)
514{TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();}
515
516inline void enableStack(void)
517{TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();}
518
519inline microtimeout_t getSchedulingTimeout(void)
520{return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();}
521
522inline void controlReceptionService(void)
523{TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();}
524
525inline void controlTransmissionService(void)
526{TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();}
527
528inline timeval getRTCPCheckInterval(void)
529{return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();}
530
531inline size_t dispatchDataPacket(void)
532{return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();}
533
534#if defined(_MSC_VER) && _MSC_VER >= 1300
535virtual void run(void);
536
537virtual void timerTick(void);
538
539virtual bool isPendingData(microtimeout_t timeout);
540#else
541
542virtual void timerTick(void)
543{return;}
544
545virtual bool isPendingData(microtimeout_t timeout)
546{return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);}
547
548/**
549 * Single runnable method for this RTP stacks, schedules
550 * outgoing and incoming RTP data and RTCP packets.
551 **/
552virtual void run(void)
553{
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500554 microtimeout_t timeout = 0;
555 while ( ServiceQueue::isActive() ) {
556 if ( timeout < 1000 ){ // !(timeout/1000)
557 timeout = getSchedulingTimeout();
558 }
559 controlReceptionService();
560 controlTransmissionService();
561 microtimeout_t maxWait =
562 timeval2microtimeout(getRTCPCheckInterval());
563 // make sure the scheduling timeout is
564 // <= the check interval for RTCP
565 // packets
566 timeout = (timeout > maxWait)? maxWait : timeout;
567 if ( timeout < 1000 ) { // !(timeout/1000)
568 dispatchDataPacket();
569 timerTick();
570 } else {
571 if ( isPendingData(timeout/1000) ) {
Emeric Vigier2f625822012-08-06 11:09:52 -0400572 if (ServiceQueue::isActive()) { // take in only if active
573 takeInDataPacket();
574 }
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500575 }
576 timeout = 0;
577 }
578 }
579 dispatchBYE("GNU ccRTP stack finishing.");
Emeric Vigier2f625822012-08-06 11:09:52 -0400580// Thread::exit();
581}
582
583#endif
584
585inline size_t takeInDataPacket(void)
586{return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();}
587
588inline size_t dispatchBYE(const std::string &str)
589{return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);}
590};
591
592/**
593 * @typedef RTPSession
594 *
595 * Uses two pairs of sockets for RTP data and RTCP
596 * transmission/reception.
597 *
598 * @short UDP/IPv4 RTP Session scheduled by one thread of execution.
599 **/
600typedef SingleThreadRTPSession<> RTPSession;
601
602/**
603 * @typedef RTPSocket
604 *
605 * Alias for RTPSession.
606 **/
607typedef RTPSession RTPSocket;
608
609/**
610 * @typedef SymmetricRTPSession
611 *
612 * Uses one pair of sockets, (1) for RTP data and (2) for RTCP
613 * transmission/reception.
614 *
615 * @short Symmetric UDP/IPv4 RTP session scheduled by one thread of execution.
616 **/
617typedef SingleThreadRTPSession<SymmetricRTPChannel,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500618 SymmetricRTPChannel> SymmetricRTPSession;
Emeric Vigier2f625822012-08-06 11:09:52 -0400619
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500620#ifdef CCXX_IPV6
Emeric Vigier2f625822012-08-06 11:09:52 -0400621
622/**
623 * @class RTPSessionBaseIPV6
624 *
625 * Generic RTP protocol stack for exchange of realtime data. This
626 * stack uses the concept of packet send and receive queues to schedule
627 * and buffer outgoing packets and to arrange or reorder incoming packets
628 * as they arrive.
629 *
630 * This is a template class that allows customization of two aspects:
631 * the underlying network and the control protocol. The RTPDataChannel
632 * and RTCPChannel template parameters specify the socket types to
633 * use. The ServiceQueue template parameter specify which packet queue
634 * is used.
635 *
636 * RTPSessionBase objects do not have any threading policy, thus
637 * allowing to customize this aspect in derived classes (see
638 * SingleThreadRTPSession or RTPSessionPoolBase).
639 *
640 * @author David Sugar <dyfet@ostel.com>
641 * @short RTP protocol stack based on Common C++.
642 **/
643template <class RTPDataChannel = DualRTPUDPIPv6Channel,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500644 class RTCPChannel = DualRTPUDPIPv6Channel,
645 class ServiceQueue = AVPQueue>
Emeric Vigier2f625822012-08-06 11:09:52 -0400646class __EXPORT TRTPSessionBaseIPV6 : public ServiceQueue
647{
648public:
649/**
650 * Builds a session waiting for packets in a host address.
651 *
652 * @param ia Network address this socket is to be bound.
653 * @param dataPort Transport port the data socket is to be bound.
654 * @param controlPort Transport port the control socket is to be bound.
655 * @param membersSize Initial size of the membership table.
656 * @param app Application this session is associated to.
657 * */
658TRTPSessionBaseIPV6(const IPV6Host& ia, tpport_t dataPort,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500659 tpport_t controlPort, uint32 membersSize,
660 RTPApplication& app) :
661 ServiceQueue(membersSize,app)
Emeric Vigier2f625822012-08-06 11:09:52 -0400662{ build(ia,dataPort,controlPort); }
663
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500664 /**
665 * Builds a session with the specified ssrc identifier for the
666 * local source.
667 *
668 * @param ssrc SSRC identifier for the local source.
669 * @param ia Network address this socket is to be bound.
670 * @param dataPort Transport port the data socket is to be bound.
671 * @param controlPort Transport port the control socket is to be bound.
672 * @param membersSize Initial size of the membership table.
673 * @param app Application this session is associated to.
674 **/
675 TRTPSessionBaseIPV6(uint32 ssrc,
676 const IPV6Host& ia,
677 tpport_t dataPort, tpport_t controlPort,
678 uint32 membersSize, RTPApplication& app):
679 ServiceQueue(ssrc,membersSize,app)
680 { build(ia,dataPort,controlPort); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400681
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500682 /**
683 * Builds a session waiting for packets in a multicast address.
684 * TODO: ssrc constructor for multicast!
685 *
686 * @param ia Multicast address this socket is to be bound.
687 * @param dataPort Transport port the data socket is to be bound.
688 * @param controlPort Transport port the control socket is to be bound.
689 * @param membersSize Initial size of the membership table.
690 * @param app Application this session is associated to.
691 * @param iface Index (from 0 to n) of network interface to join to
692 * multicast group.
693 **/
694 TRTPSessionBaseIPV6(const IPV6Multicast& ia, tpport_t dataPort,
695 tpport_t controlPort, uint32 membersSize,
696 RTPApplication& app, uint32 iface) :
697 ServiceQueue(membersSize,app)
698 { build(ia,dataPort,controlPort,iface); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400699
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500700 /**
701 * Builds a session waiting for packets in a multicast
702 * address, with the specified ssrc identifier for the local
703 * source.
704 *
705 * @param ssrc SSRC identifier for the local source.
706 * @param ia Multicast address this socket is to be bound.
707 * @param dataPort Transport port the data socket is to be bound.
708 * @param controlPort Transport port the control socket is to be bound.
709 * @param membersSize Initial size of the membership table.
710 * @param app Application this session is associated to.
711 * @param iface Index (from 0 to n) of network interface to join to
712 * multicast group.
713 **/
714 TRTPSessionBaseIPV6(uint32 ssrc,
715 const IPV6Multicast& ia, tpport_t dataPort,
716 tpport_t controlPort, uint32 membersSize,
717 RTPApplication& app, uint32 iface) :
718 ServiceQueue(ssrc,membersSize,app)
719 { build(ia,dataPort,controlPort,iface); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400720
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500721 virtual size_t dispatchBYE(const std::string &str)
722 {
723 return QueueRTCPManager::dispatchBYE(str);
724 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400725
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500726 inline virtual
727 ~TRTPSessionBaseIPV6()
728 {
729 endSocket();
730 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400731
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500732 inline RTPDataChannel *getDSO(void)
733 {return dso;}
Emeric Vigier2f625822012-08-06 11:09:52 -0400734
735protected:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500736 /**
737 * @param timeout maximum timeout to wait, in microseconds
738 */
739 inline bool
740 isPendingData(microtimeout_t timeout)
741 { return dso->isPendingRecv(timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400742
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500743 inline IPV6Host
744 getDataSender(tpport_t *port = NULL) const
745 { return dso->getSender(port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400746
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500747 inline size_t
748 getNextDataPacketSize() const
749 { return dso->getNextPacketSize(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400750
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500751 /**
752 * Receive data from the data channel/socket.
753 *
754 * @param buffer Memory region to read to.
755 * @param len Maximum number of octets to get.
756 * @param na Source network address.
757 * @param tp Source transport port.
758 * @return Number of octets actually read.
759 */
760 inline size_t
761 recvData(unsigned char* buffer, size_t len,
762 IPV6Host& na, tpport_t& tp)
763 { na = dso->getSender(tp); return dso->recv(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400764
765 inline void
766 setDataPeerIPV6(const IPV6Host &host, tpport_t port)
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500767 { dso->setPeer(host,port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400768
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500769 /**
770 * @param buffer memory region to write from
771 * @param len number of octets to write
772 */
773 inline size_t
774 sendDataIPV6(const unsigned char* const buffer, size_t len)
775 { return dso->send(buffer, len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400776
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500777 inline SOCKET getDataRecvSocket() const
778 { return dso->getRecvSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400779
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500780 /**
781 * @param timeout maximum timeout to wait, in microseconds
782 * @return whether there are packets waiting to be picked
783 */
Emeric Vigier2f625822012-08-06 11:09:52 -0400784 inline bool
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500785 isPendingControl(microtimeout_t timeout)
786 { return cso->isPendingRecv(timeout); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400787
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500788 inline IPV6Host
789 getControlSender(tpport_t *port = NULL) const
790 { return cso->getSender(port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400791
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500792 /**
793 * Receive data from the control channel/socket.
794 *
795 * @param buffer Buffer where to get data.
796 * @param len Maximum number of octets to get.
797 * @param na Source network address.
798 * @param tp Source transport port.
799 * @return Number of octets actually read.
800 **/
Emeric Vigier2f625822012-08-06 11:09:52 -0400801 inline size_t
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500802 recvControl(unsigned char *buffer, size_t len,
803 IPV6Host& na, tpport_t& tp)
804 { na = cso->getSender(tp); return cso->recv(buffer,len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400805
806 inline void
807 setControlPeerIPV6(const IPV6Host &host, tpport_t port)
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500808 { cso->setPeer(host,port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400809
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500810 /**
811 * @return number of octets actually written
812 * @param buffer
813 * @param len
814 */
Emeric Vigier2f625822012-08-06 11:09:52 -0400815 inline size_t
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500816 sendControl(const unsigned char* const buffer, size_t len)
817 { return cso->send(buffer,len); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400818
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500819 inline SOCKET getControlRecvSocket() const
820 { return cso->getRecvSocket(); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400821
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500822 inline void
823 endSocket()
824 {
825 dso->endSocket();
826 cso->endSocket();
827 if (dso) delete dso;
828 dso = NULL;
829 if (cso) delete cso;
830 cso = NULL;
831 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400832
833private:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500834 void
835 build(const IPV6Host& ia, tpport_t dataPort,
836 tpport_t controlPort)
837 {
838 if ( 0 == controlPort ) {
839 dataBasePort = even_port(dataPort);
840 controlBasePort = dataBasePort + 1;
841 } else {
842 dataBasePort = dataPort;
843 controlBasePort = controlPort;
844 }
845 dso = new RTPDataChannel(ia,dataBasePort);
846 cso = new RTCPChannel(ia,controlBasePort);
847 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400848
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500849 void
850 build(const IPV6Multicast& ia, tpport_t dataPort,
851 tpport_t controlPort, uint32 iface)
852 {
853 if ( 0 == controlPort ) {
854 dataBasePort = even_port(dataPort);
855 controlBasePort = dataBasePort + 1;
856 } else {
857 dataBasePort = dataPort;
858 controlBasePort = controlPort;
859 }
860 dso = new RTPDataChannel(IPV6Host("0.0.0.0"),dataBasePort);
861 cso = new RTCPChannel(IPV6Host("0.0.0.0"),controlBasePort);
862 joinGroup(ia,iface);
863 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400864
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500865 /**
866 * Join a multicast group.
867 *
868 * @param ia address of the multicast group
869 * @return error code from the socket operation
870 */
871 inline Socket::Error
872 joinGroup(const IPV6Multicast& ia, uint32 iface)
873 {
874 Socket::Error error = dso->setMulticast(true);
875 if ( error ) return error;
876 error = dso->join(ia,iface);
877 if ( error ) return error;
878 error = cso->setMulticast(true);
879 if ( error ) {
880 dso->drop(ia);
881 return error;
882 }
883 error = cso->join(ia,iface);
884 if ( error ) {
885 dso->drop(ia);
886 return error;
887 }
888 return Socket::errSuccess;
889 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400890
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500891 /**
892 * Leave a multicast group.
893 *
894 * @param ia address of the multicast group
895 * @return error code from the socket operation
896 */
897 inline Socket::Error
898 leaveGroup(const IPV6Multicast& ia)
899 {
900 Socket::Error error = dso->setMulticast(false);
901 if ( error ) return error;
902 error = dso->leaveGroup(ia);
903 if ( error ) return error;
904 error = cso->setMulticast(false);
905 if ( error ) return error;
906 return cso->leaveGroup(ia);
907 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400908
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500909 /**
910 * Set the value of the TTL field in the sent packets.
911 *
912 * @param ttl Time To Live
913 * @return error code from the socket operation
914 */
915 inline Socket::Error
916 setMcastTTL(uint8 ttl)
917 {
918 Socket::Error error = dso->setMulticast(true);
919 if ( error ) return error;
920 error = dso->setTimeToLive(ttl);
921 if ( error ) return error;
922 error = cso->setMulticast(true);
923 if ( error ) return error;
924 return cso->setTimeToLive(ttl);
925 }
Emeric Vigier2f625822012-08-06 11:09:52 -0400926
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500927 /**
928 * Ensure a port number is odd. If it is an even number, return
929 * the next lower (odd) port number.
930 *
931 * @param port number to filter
932 * @return filtered (odd) port number
933 */
934 inline tpport_t
935 odd_port(tpport_t port)
936 { return (port & 0x01)? (port) : (port - 1); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400937
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500938 /**
939 * Ensure a port number is even. If it is an odd number, return
940 * the next lower (even) port number.
941 *
942 * @param port number to filter
943 * @return filtered (even) port number
944 */
945 inline tpport_t
946 even_port(tpport_t port)
947 { return (port & 0x01)? (port - 1) : (port); }
Emeric Vigier2f625822012-08-06 11:09:52 -0400948
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500949 tpport_t dataBasePort;
950 tpport_t controlBasePort;
Emeric Vigier2f625822012-08-06 11:09:52 -0400951
952protected:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500953 RTPDataChannel* dso;
954 RTCPChannel* cso;
955 friend class RTPSessionBaseHandler;
Emeric Vigier2f625822012-08-06 11:09:52 -0400956};
957
958/**
959 * @class SingleThreadRTPSessionIPV6
960 *
961 * This template class adds the threading aspect to the RTPSessionBase
962 * template in one of the many possible ways. It inherits from a
963 * single execution thread that schedules sending of outgoing packets
964 * and receipt of incoming packets.
965 *
966 * @author David Sugar <dyfet@gnutelephony.org>
967 **/
968template
969<class RTPDataChannel = DualRTPUDPIPv6Channel,
970 class RTCPChannel = DualRTPUDPIPv6Channel,
971 class ServiceQueue = AVPQueue>
972class __EXPORT SingleThreadRTPSessionIPV6 :
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500973 protected Thread,
974 public TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
Emeric Vigier2f625822012-08-06 11:09:52 -0400975{
976public:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500977 SingleThreadRTPSessionIPV6(const IPV6Host& ia,
978 tpport_t dataPort = DefaultRTPDataPort,
979 tpport_t controlPort = 0,
980 int pri = 0,
981 uint32 memberssize =
982 MembershipBookkeeping::defaultMembersHashSize,
983 RTPApplication& app = defaultApplication()
Emeric Vigier2f625822012-08-06 11:09:52 -0400984#if defined(_MSC_VER) && _MSC_VER >= 1300
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500985 );
Emeric Vigier2f625822012-08-06 11:09:52 -0400986#else
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500987 ):
988 Thread(pri),
989 TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
990 (ia,dataPort,controlPort,memberssize,app)
Emeric Vigier2f625822012-08-06 11:09:52 -0400991{ }
992#endif
993
994SingleThreadRTPSessionIPV6(const IPV6Multicast& ia,
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500995 tpport_t dataPort = DefaultRTPDataPort,
996 tpport_t controlPort = 0,
997 int pri = 0,
998 uint32 memberssize =
999 MembershipBookkeeping::defaultMembersHashSize,
1000 RTPApplication& app = defaultApplication(),
1001 uint32 iface = 0
Emeric Vigier2f625822012-08-06 11:09:52 -04001002#if defined(_MSC_VER) && _MSC_VER >= 1300
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001003 );
Emeric Vigier2f625822012-08-06 11:09:52 -04001004#else
1005 ):
1006 Thread(pri),
1007 TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
1008 (ia,dataPort,controlPort,memberssize,app,iface)
1009{ }
1010#endif
1011
1012~SingleThreadRTPSessionIPV6()
1013{
1014 if (isRunning()) {
1015 disableStack(); Thread::join();
1016 }
1017}
1018
1019#if defined(_MSC_VER) && _MSC_VER >= 1300
1020virtual void startRunning();
1021#else
1022/**
1023 * Activate stack and start service thread.
1024 **/
1025void
1026startRunning()
1027{ enableStack(); Thread::start(); }
1028#endif
1029
1030
1031protected:
1032inline void enableStack(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001033{TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001034
1035inline void disableStack(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001036{TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001037
1038inline microtimeout_t getSchedulingTimeout(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001039{return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001040
1041inline void controlReceptionService(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001042{TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001043
1044inline void controlTransmissionService(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001045{TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001046
1047inline timeval getRTCPCheckInterval(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001048{return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001049
1050inline size_t dispatchDataPacket(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001051{return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001052
1053#if defined(_MSC_VER) && _MSC_VER >= 1300
1054virtual void run(void);
1055
1056virtual void timerTick(void);
1057
1058virtual bool isPendingData(microtimeout_t timeout);
1059#else
1060
1061virtual void timerTick(void)
1062{return;}
1063
1064virtual bool isPendingData(microtimeout_t timeout)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001065{return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);}
Emeric Vigier2f625822012-08-06 11:09:52 -04001066
1067/**
1068 * Single runnable method for this RTP stacks, schedules
1069 * outgoing and incoming RTP data and RTCP packets.
1070 **/
1071virtual void run(void)
1072{
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001073 microtimeout_t timeout = 0;
1074 while ( ServiceQueue::isActive() ) {
1075 if ( timeout < 1000 ){ // !(timeout/1000)
1076 timeout = getSchedulingTimeout();
1077 }
1078 controlReceptionService();
1079 controlTransmissionService();
1080 microtimeout_t maxWait =
1081 timeval2microtimeout(getRTCPCheckInterval());
1082 // make sure the scheduling timeout is
1083 // <= the check interval for RTCP
1084 // packets
1085 timeout = (timeout > maxWait)? maxWait : timeout;
1086 if ( timeout < 1000 ) { // !(timeout/1000)
1087 dispatchDataPacket();
1088 timerTick();
1089 } else {
1090 if ( isPendingData(timeout/1000) ) {
1091 takeInDataPacket();
1092 }
1093 timeout = 0;
1094 }
1095 }
1096 dispatchBYE("GNU ccRTP stack finishing.");
Emeric Vigier2f625822012-08-06 11:09:52 -04001097 Thread::exit();
1098}
1099
1100#endif
1101
1102inline size_t takeInDataPacket(void)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001103{return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();}
Emeric Vigier2f625822012-08-06 11:09:52 -04001104
1105inline size_t dispatchBYE(const std::string &str)
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001106{return TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);}
Emeric Vigier2f625822012-08-06 11:09:52 -04001107};
1108
1109/**
1110 * @typedef RTPSession
1111 *
1112 * Uses two pairs of sockets for RTP data and RTCP
1113 * transmission/reception.
1114 *
1115 * @short UDP/IPv6 RTP Session scheduled by one thread of execution.
1116 **/
1117typedef SingleThreadRTPSessionIPV6<> RTPSessionIPV6;
1118
1119/**
1120 * @typedef RTPSocket
1121 *
1122 * Alias for RTPSession.
1123 **/
1124typedef RTPSessionIPV6 RTPSocketIPV6;
1125
1126/**
1127 * @typedef SymmetricRTPSession
1128 *
1129 * Uses one pair of sockets, (1) for RTP data and (2) for RTCP
1130 * transmission/reception.
1131 *
1132 * @short Symmetric UDP/IPv6 RTP session scheduled by one thread of execution.
1133 **/
1134 typedef SingleThreadRTPSessionIPV6<SymmetricRTPChannelIPV6,
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001135 SymmetricRTPChannelIPV6> SymmetricRTPSessionIPV6;
Emeric Vigier2f625822012-08-06 11:09:52 -04001136
1137
1138#endif
1139
1140/** @}*/ // sessions
1141
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001142END_NAMESPACE
Emeric Vigier2f625822012-08-06 11:09:52 -04001143
1144#endif //CCXX_RTP_RTP_H_
1145
1146/** EMACS **
1147 * Local variables:
1148 * mode: c++
1149 * c-basic-offset: 8
1150 * End:
1151 */