ccRTP
|
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation. 00002 // 00003 // This program is free software; you can redistribute it and/or modify 00004 // it under the terms of the GNU General Public License as published by 00005 // the Free Software Foundation; either version 2 of the License, or 00006 // (at your option) any later version. 00007 // 00008 // This program is distributed in the hope that it will be useful, 00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 // GNU General Public License for more details. 00012 // 00013 // You should have received a copy of the GNU General Public License 00014 // along with this program; if not, write to the Free Software 00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00016 // 00017 // As a special exception, you may use this file as part of a free software 00018 // library without restriction. Specifically, if other files instantiate 00019 // templates or use macros or inline functions from this file, or you compile 00020 // this file and link it with other files to produce an executable, this 00021 // file does not by itself cause the resulting executable to be covered by 00022 // the GNU General Public License. This exception does not however 00023 // invalidate any other reasons why the executable file might be covered by 00024 // the GNU General Public License. 00025 // 00026 // This exception applies only to the code released under the name GNU 00027 // ccRTP. If you copy code from other releases into a copy of GNU 00028 // ccRTP, as the General Public License permits, the exception does 00029 // not apply to the code that you add in this way. To avoid misleading 00030 // anyone as to the status of such modified files, you must delete 00031 // this exception notice from them. 00032 // 00033 // If you write modifications of your own for GNU ccRTP, it is your choice 00034 // whether to permit this exception to apply to your modifications. 00035 // If you do not wish that, delete this exception notice. 00036 // 00037 00049 #ifndef CCXX_RTP_RTP_H_ 00050 #define CCXX_RTP_RTP_H_ 00051 00052 #include <ccrtp/cqueue.h> 00053 #include <ccrtp/channel.h> 00054 00055 #ifdef CCXX_NAMESPACES 00056 namespace ost { 00057 #endif 00058 00085 template <class RTPDataChannel = DualRTPUDPIPv4Channel, 00086 class RTCPChannel = DualRTPUDPIPv4Channel, 00087 class ServiceQueue = AVPQueue> 00088 class __EXPORT TRTPSessionBase : public ServiceQueue 00089 { 00090 public: 00100 TRTPSessionBase(const InetHostAddress& ia, tpport_t dataPort, 00101 tpport_t controlPort, uint32 membersSize, 00102 RTPApplication& app) : 00103 ServiceQueue(membersSize,app) 00104 { build(ia,dataPort,controlPort); } 00105 00117 TRTPSessionBase(uint32 ssrc, 00118 const InetHostAddress& ia, 00119 tpport_t dataPort, tpport_t controlPort, 00120 uint32 membersSize, RTPApplication& app): 00121 ServiceQueue(ssrc,membersSize,app) 00122 { build(ia,dataPort,controlPort); } 00123 00136 TRTPSessionBase(const InetMcastAddress& ia, tpport_t dataPort, 00137 tpport_t controlPort, uint32 membersSize, 00138 RTPApplication& app, uint32 iface) : 00139 ServiceQueue(membersSize,app) 00140 { build(ia,dataPort,controlPort,iface); } 00141 00156 TRTPSessionBase(uint32 ssrc, 00157 const InetMcastAddress& ia, tpport_t dataPort, 00158 tpport_t controlPort, uint32 membersSize, 00159 RTPApplication& app, uint32 iface) : 00160 ServiceQueue(ssrc,membersSize,app) 00161 { build(ia,dataPort,controlPort,iface); } 00162 00163 virtual size_t dispatchBYE(const std::string &str) 00164 { 00165 return QueueRTCPManager::dispatchBYE(str); 00166 } 00167 00174 inline Socket::Error 00175 setMcastTTL(uint8 ttl) 00176 { 00177 Socket::Error error = dso->setMulticast(true); 00178 if ( error ) return error; 00179 error = dso->setTimeToLive(ttl); 00180 if ( error ) return error; 00181 error = cso->setMulticast(true); 00182 if ( error ) return error; 00183 return cso->setTimeToLive(ttl); 00184 } 00185 00186 inline virtual 00187 ~TRTPSessionBase() 00188 { 00189 endSocket(); 00190 } 00191 00192 inline RTPDataChannel *getDSO(void) 00193 {return dso;} 00194 00195 protected: 00199 inline bool 00200 isPendingData(microtimeout_t timeout) 00201 { return dso->isPendingRecv(timeout); } 00202 00203 InetHostAddress 00204 getDataSender(tpport_t *port = NULL) const 00205 { return dso->getSender(port); } 00206 00207 inline size_t 00208 getNextDataPacketSize() const 00209 { return dso->getNextPacketSize(); } 00210 00220 inline size_t 00221 recvData(unsigned char* buffer, size_t len, 00222 InetHostAddress& na, tpport_t& tp) 00223 { na = dso->getSender(tp); return dso->recv(buffer, len); } 00224 00225 inline void 00226 setDataPeer(const InetAddress &host, tpport_t port) 00227 { dso->setPeer(host,port); } 00228 00229 00234 inline size_t 00235 sendData(const unsigned char* const buffer, size_t len) 00236 { return dso->send(buffer, len); } 00237 00238 inline SOCKET getDataRecvSocket() const 00239 { return dso->getRecvSocket(); } 00240 00245 inline bool 00246 isPendingControl(microtimeout_t timeout) 00247 { return cso->isPendingRecv(timeout); } 00248 00249 InetHostAddress 00250 getControlSender(tpport_t *port = NULL) const 00251 { return cso->getSender(port); } 00252 00262 inline size_t 00263 recvControl(unsigned char *buffer, size_t len, 00264 InetHostAddress& na, tpport_t& tp) 00265 { na = cso->getSender(tp); return cso->recv(buffer,len); } 00266 00267 inline void 00268 setControlPeer(const InetAddress &host, tpport_t port) 00269 { cso->setPeer(host,port); } 00270 00276 inline size_t 00277 sendControl(const unsigned char* const buffer, size_t len) 00278 { return cso->send(buffer,len); } 00279 00280 inline SOCKET getControlRecvSocket() const 00281 { return cso->getRecvSocket(); } 00282 00289 inline Socket::Error 00290 joinGroup(const InetMcastAddress& ia, uint32 iface) 00291 { 00292 Socket::Error error = dso->setMulticast(true); 00293 if ( error ) return error; 00294 error = dso->join(ia,iface); 00295 if ( error ) return error; 00296 error = cso->setMulticast(true); 00297 if ( error ) { 00298 dso->drop(ia); 00299 return error; 00300 } 00301 error = cso->join(ia,iface); 00302 if ( error ) { 00303 dso->drop(ia); 00304 return error; 00305 } 00306 return Socket::errSuccess; 00307 } 00308 00315 inline Socket::Error 00316 leaveGroup(const InetMcastAddress& ia) 00317 { 00318 Socket::Error error = dso->setMulticast(false); 00319 if ( error ) return error; 00320 error = dso->leaveGroup(ia); 00321 if ( error ) return error; 00322 error = cso->setMulticast(false); 00323 if ( error ) return error; 00324 return cso->leaveGroup(ia); 00325 } 00326 00327 inline void 00328 endSocket() 00329 { 00330 if (dso) { 00331 dso->endSocket(); 00332 delete dso; 00333 } 00334 dso = NULL; 00335 if (cso) { 00336 cso->endSocket(); 00337 delete cso; 00338 } 00339 cso = NULL; 00340 } 00341 00342 private: 00343 void 00344 build(const InetHostAddress& ia, tpport_t dataPort, 00345 tpport_t controlPort) 00346 { 00347 if ( 0 == controlPort ) { 00348 dataBasePort = even_port(dataPort); 00349 controlBasePort = dataBasePort + 1; 00350 } else { 00351 dataBasePort = dataPort; 00352 controlBasePort = controlPort; 00353 } 00354 dso = new RTPDataChannel(ia,dataBasePort); 00355 cso = new RTCPChannel(ia,controlBasePort); 00356 } 00357 00358 void 00359 build(const InetMcastAddress& ia, tpport_t dataPort, 00360 tpport_t controlPort, uint32 iface) 00361 { 00362 if ( 0 == controlPort ) { 00363 dataBasePort = even_port(dataPort); 00364 controlBasePort = dataBasePort + 1; 00365 } else { 00366 dataBasePort = dataPort; 00367 controlBasePort = controlPort; 00368 } 00369 dso = new RTPDataChannel(InetHostAddress("0.0.0.0"),dataBasePort); 00370 cso = new RTCPChannel(InetHostAddress("0.0.0.0"),controlBasePort); 00371 joinGroup(ia,iface); 00372 } 00373 00381 inline tpport_t 00382 odd_port(tpport_t port) 00383 { return (port & 0x01)? (port) : (port - 1); } 00384 00392 inline tpport_t 00393 even_port(tpport_t port) 00394 { return (port & 0x01)? (port - 1) : (port); } 00395 00396 tpport_t dataBasePort; 00397 tpport_t controlBasePort; 00398 00399 protected: 00400 RTPDataChannel* dso; 00401 RTCPChannel* cso; 00402 friend class RTPSessionBaseHandler; 00403 }; 00404 00415 template 00416 <class RTPDataChannel = DualRTPUDPIPv4Channel, 00417 class RTCPChannel = DualRTPUDPIPv4Channel, 00418 class ServiceQueue = AVPQueue> 00419 class __EXPORT SingleThreadRTPSession : 00420 protected Thread, 00421 public TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue> 00422 { 00423 public: 00424 SingleThreadRTPSession(const InetHostAddress& ia, 00425 tpport_t dataPort = DefaultRTPDataPort, 00426 tpport_t controlPort = 0, 00427 int pri = 0, 00428 uint32 memberssize = 00429 MembershipBookkeeping::defaultMembersHashSize, 00430 RTPApplication& app = defaultApplication() 00431 #if defined(_MSC_VER) && _MSC_VER >= 1300 00432 ); 00433 #else 00434 ): 00435 Thread(pri), 00436 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue> 00437 (ia,dataPort,controlPort,memberssize,app) 00438 { } 00439 #endif 00440 00441 SingleThreadRTPSession(uint32 ssrc, const InetHostAddress& ia, 00442 tpport_t dataPort = DefaultRTPDataPort, 00443 tpport_t controlPort = 0, 00444 int pri = 0, 00445 uint32 memberssize = 00446 MembershipBookkeeping::defaultMembersHashSize, 00447 RTPApplication& app = defaultApplication() 00448 #if defined(_MSC_VER) && _MSC_VER >= 1300 00449 ); 00450 #else 00451 ): 00452 Thread(pri), 00453 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue> 00454 (ssrc, ia,dataPort,controlPort,memberssize,app) 00455 { } 00456 #endif 00457 00458 SingleThreadRTPSession(const InetMcastAddress& ia, 00459 tpport_t dataPort = DefaultRTPDataPort, 00460 tpport_t controlPort = 0, 00461 int pri = 0, 00462 uint32 memberssize = 00463 MembershipBookkeeping::defaultMembersHashSize, 00464 RTPApplication& app = defaultApplication(), 00465 uint32 iface = 0 00466 #if defined(_MSC_VER) && _MSC_VER >= 1300 00467 ); 00468 #else 00469 ): 00470 Thread(pri), 00471 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue> 00472 (ia,dataPort,controlPort,memberssize,app,iface) 00473 { } 00474 #endif 00475 00476 SingleThreadRTPSession(uint32 ssrc, const InetMcastAddress& ia, 00477 tpport_t dataPort = DefaultRTPDataPort, 00478 tpport_t controlPort = 0, 00479 int pri = 0, 00480 uint32 memberssize = 00481 MembershipBookkeeping::defaultMembersHashSize, 00482 RTPApplication& app = defaultApplication(), 00483 uint32 iface = 0 00484 #if defined(_MSC_VER) && _MSC_VER >= 1300 00485 ); 00486 #else 00487 ): 00488 Thread(pri), 00489 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue> 00490 (ssrc,ia,dataPort,controlPort,memberssize,app,iface) 00491 { } 00492 #endif 00493 00494 00495 ~SingleThreadRTPSession() 00496 { 00497 if (isRunning()) { 00498 disableStack(); Thread::join(); 00499 } 00500 } 00501 00502 #if defined(_MSC_VER) && _MSC_VER >= 1300 00503 virtual void startRunning(); 00504 #else 00505 00508 void 00509 startRunning() 00510 { enableStack(); Thread::start(); } 00511 #endif 00512 00513 00514 protected: 00515 inline void disableStack(void) 00516 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();} 00517 00518 inline void enableStack(void) 00519 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();} 00520 00521 inline microtimeout_t getSchedulingTimeout(void) 00522 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();} 00523 00524 inline void controlReceptionService(void) 00525 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();} 00526 00527 inline void controlTransmissionService(void) 00528 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();} 00529 00530 inline timeval getRTCPCheckInterval(void) 00531 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();} 00532 00533 inline size_t dispatchDataPacket(void) 00534 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();} 00535 00536 #if defined(_MSC_VER) && _MSC_VER >= 1300 00537 virtual void run(void); 00538 00539 virtual void timerTick(void); 00540 00541 virtual bool isPendingData(microtimeout_t timeout); 00542 #else 00543 00544 virtual void timerTick(void) 00545 {return;} 00546 00547 virtual bool isPendingData(microtimeout_t timeout) 00548 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);} 00549 00554 virtual void run(void) 00555 { 00556 microtimeout_t timeout = 0; 00557 while ( ServiceQueue::isActive() ) { 00558 if ( timeout < 1000 ){ // !(timeout/1000) 00559 timeout = getSchedulingTimeout(); 00560 } 00561 setCancel(cancelDeferred); 00562 controlReceptionService(); 00563 controlTransmissionService(); 00564 setCancel(cancelImmediate); 00565 microtimeout_t maxWait = 00566 timeval2microtimeout(getRTCPCheckInterval()); 00567 // make sure the scheduling timeout is 00568 // <= the check interval for RTCP 00569 // packets 00570 timeout = (timeout > maxWait)? maxWait : timeout; 00571 if ( timeout < 1000 ) { // !(timeout/1000) 00572 setCancel(cancelDeferred); 00573 dispatchDataPacket(); 00574 setCancel(cancelImmediate); 00575 timerTick(); 00576 } else { 00577 if ( isPendingData(timeout/1000) ) { 00578 setCancel(cancelDeferred); 00579 if (ServiceQueue::isActive()) { // take in only if active 00580 takeInDataPacket(); 00581 } 00582 setCancel(cancelImmediate); 00583 } 00584 timeout = 0; 00585 } 00586 } 00587 dispatchBYE("GNU ccRTP stack finishing."); 00588 // Thread::exit(); 00589 } 00590 00591 #endif 00592 00593 inline size_t takeInDataPacket(void) 00594 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();} 00595 00596 inline size_t dispatchBYE(const std::string &str) 00597 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);} 00598 }; 00599 00608 typedef SingleThreadRTPSession<> RTPSession; 00609 00615 typedef RTPSession RTPSocket; 00616 00625 typedef SingleThreadRTPSession<SymmetricRTPChannel, 00626 SymmetricRTPChannel> SymmetricRTPSession; 00627 00628 #ifdef CCXX_IPV6 00629 00651 template <class RTPDataChannel = DualRTPUDPIPv6Channel, 00652 class RTCPChannel = DualRTPUDPIPv6Channel, 00653 class ServiceQueue = AVPQueue> 00654 class __EXPORT TRTPSessionBaseIPV6 : public ServiceQueue 00655 { 00656 public: 00666 TRTPSessionBaseIPV6(const IPV6Host& ia, tpport_t dataPort, 00667 tpport_t controlPort, uint32 membersSize, 00668 RTPApplication& app) : 00669 ServiceQueue(membersSize,app) 00670 { build(ia,dataPort,controlPort); } 00671 00683 TRTPSessionBaseIPV6(uint32 ssrc, 00684 const IPV6Host& ia, 00685 tpport_t dataPort, tpport_t controlPort, 00686 uint32 membersSize, RTPApplication& app): 00687 ServiceQueue(ssrc,membersSize,app) 00688 { build(ia,dataPort,controlPort); } 00689 00702 TRTPSessionBaseIPV6(const IPV6Multicast& ia, tpport_t dataPort, 00703 tpport_t controlPort, uint32 membersSize, 00704 RTPApplication& app, uint32 iface) : 00705 ServiceQueue(membersSize,app) 00706 { build(ia,dataPort,controlPort,iface); } 00707 00722 TRTPSessionBaseIPV6(uint32 ssrc, 00723 const IPV6Multicast& ia, tpport_t dataPort, 00724 tpport_t controlPort, uint32 membersSize, 00725 RTPApplication& app, uint32 iface) : 00726 ServiceQueue(ssrc,membersSize,app) 00727 { build(ia,dataPort,controlPort,iface); } 00728 00729 virtual size_t dispatchBYE(const std::string &str) 00730 { 00731 return QueueRTCPManager::dispatchBYE(str); 00732 } 00733 00734 inline virtual 00735 ~TRTPSessionBaseIPV6() 00736 { 00737 endSocket(); 00738 } 00739 00740 inline RTPDataChannel *getDSO(void) 00741 {return dso;} 00742 00743 protected: 00747 inline bool 00748 isPendingData(microtimeout_t timeout) 00749 { return dso->isPendingRecv(timeout); } 00750 00751 inline IPV6Host 00752 getDataSender(tpport_t *port = NULL) const 00753 { return dso->getSender(port); } 00754 00755 inline size_t 00756 getNextDataPacketSize() const 00757 { return dso->getNextPacketSize(); } 00758 00768 inline size_t 00769 recvData(unsigned char* buffer, size_t len, 00770 IPV6Host& na, tpport_t& tp) 00771 { na = dso->getSender(tp); return dso->recv(buffer, len); } 00772 00773 inline void 00774 setDataPeerIPV6(const IPV6Host &host, tpport_t port) 00775 { dso->setPeer(host,port); } 00776 00781 inline size_t 00782 sendDataIPV6(const unsigned char* const buffer, size_t len) 00783 { return dso->send(buffer, len); } 00784 00785 inline SOCKET getDataRecvSocket() const 00786 { return dso->getRecvSocket(); } 00787 00792 inline bool 00793 isPendingControl(microtimeout_t timeout) 00794 { return cso->isPendingRecv(timeout); } 00795 00796 inline IPV6Host 00797 getControlSender(tpport_t *port = NULL) const 00798 { return cso->getSender(port); } 00799 00809 inline size_t 00810 recvControl(unsigned char *buffer, size_t len, 00811 IPV6Host& na, tpport_t& tp) 00812 { na = cso->getSender(tp); return cso->recv(buffer,len); } 00813 00814 inline void 00815 setControlPeerIPV6(const IPV6Host &host, tpport_t port) 00816 { cso->setPeer(host,port); } 00817 00823 inline size_t 00824 sendControl(const unsigned char* const buffer, size_t len) 00825 { return cso->send(buffer,len); } 00826 00827 inline SOCKET getControlRecvSocket() const 00828 { return cso->getRecvSocket(); } 00829 00830 inline void 00831 endSocket() 00832 { 00833 dso->endSocket(); 00834 cso->endSocket(); 00835 if (dso) delete dso; 00836 dso = NULL; 00837 if (cso) delete cso; 00838 cso = NULL; 00839 } 00840 00841 private: 00842 void 00843 build(const IPV6Host& ia, tpport_t dataPort, 00844 tpport_t controlPort) 00845 { 00846 if ( 0 == controlPort ) { 00847 dataBasePort = even_port(dataPort); 00848 controlBasePort = dataBasePort + 1; 00849 } else { 00850 dataBasePort = dataPort; 00851 controlBasePort = controlPort; 00852 } 00853 dso = new RTPDataChannel(ia,dataBasePort); 00854 cso = new RTCPChannel(ia,controlBasePort); 00855 } 00856 00857 void 00858 build(const IPV6Multicast& ia, tpport_t dataPort, 00859 tpport_t controlPort, uint32 iface) 00860 { 00861 if ( 0 == controlPort ) { 00862 dataBasePort = even_port(dataPort); 00863 controlBasePort = dataBasePort + 1; 00864 } else { 00865 dataBasePort = dataPort; 00866 controlBasePort = controlPort; 00867 } 00868 dso = new RTPDataChannel(IPV6Host("0.0.0.0"),dataBasePort); 00869 cso = new RTCPChannel(IPV6Host("0.0.0.0"),controlBasePort); 00870 joinGroup(ia,iface); 00871 } 00872 00879 inline Socket::Error 00880 joinGroup(const IPV6Multicast& ia, uint32 iface) 00881 { 00882 Socket::Error error = dso->setMulticast(true); 00883 if ( error ) return error; 00884 error = dso->join(ia,iface); 00885 if ( error ) return error; 00886 error = cso->setMulticast(true); 00887 if ( error ) { 00888 dso->drop(ia); 00889 return error; 00890 } 00891 error = cso->join(ia,iface); 00892 if ( error ) { 00893 dso->drop(ia); 00894 return error; 00895 } 00896 return Socket::errSuccess; 00897 } 00898 00905 inline Socket::Error 00906 leaveGroup(const IPV6Multicast& ia) 00907 { 00908 Socket::Error error = dso->setMulticast(false); 00909 if ( error ) return error; 00910 error = dso->leaveGroup(ia); 00911 if ( error ) return error; 00912 error = cso->setMulticast(false); 00913 if ( error ) return error; 00914 return cso->leaveGroup(ia); 00915 } 00916 00923 inline Socket::Error 00924 setMcastTTL(uint8 ttl) 00925 { 00926 Socket::Error error = dso->setMulticast(true); 00927 if ( error ) return error; 00928 error = dso->setTimeToLive(ttl); 00929 if ( error ) return error; 00930 error = cso->setMulticast(true); 00931 if ( error ) return error; 00932 return cso->setTimeToLive(ttl); 00933 } 00934 00942 inline tpport_t 00943 odd_port(tpport_t port) 00944 { return (port & 0x01)? (port) : (port - 1); } 00945 00953 inline tpport_t 00954 even_port(tpport_t port) 00955 { return (port & 0x01)? (port - 1) : (port); } 00956 00957 tpport_t dataBasePort; 00958 tpport_t controlBasePort; 00959 00960 protected: 00961 RTPDataChannel* dso; 00962 RTCPChannel* cso; 00963 friend class RTPSessionBaseHandler; 00964 }; 00965 00976 template 00977 <class RTPDataChannel = DualRTPUDPIPv6Channel, 00978 class RTCPChannel = DualRTPUDPIPv6Channel, 00979 class ServiceQueue = AVPQueue> 00980 class __EXPORT SingleThreadRTPSessionIPV6 : 00981 protected Thread, 00982 public TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue> 00983 { 00984 public: 00985 SingleThreadRTPSessionIPV6(const IPV6Host& ia, 00986 tpport_t dataPort = DefaultRTPDataPort, 00987 tpport_t controlPort = 0, 00988 int pri = 0, 00989 uint32 memberssize = 00990 MembershipBookkeeping::defaultMembersHashSize, 00991 RTPApplication& app = defaultApplication() 00992 #if defined(_MSC_VER) && _MSC_VER >= 1300 00993 ); 00994 #else 00995 ): 00996 Thread(pri), 00997 TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue> 00998 (ia,dataPort,controlPort,memberssize,app) 00999 { } 01000 #endif 01001 01002 SingleThreadRTPSessionIPV6(const IPV6Multicast& ia, 01003 tpport_t dataPort = DefaultRTPDataPort, 01004 tpport_t controlPort = 0, 01005 int pri = 0, 01006 uint32 memberssize = 01007 MembershipBookkeeping::defaultMembersHashSize, 01008 RTPApplication& app = defaultApplication(), 01009 uint32 iface = 0 01010 #if defined(_MSC_VER) && _MSC_VER >= 1300 01011 ); 01012 #else 01013 ): 01014 Thread(pri), 01015 TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue> 01016 (ia,dataPort,controlPort,memberssize,app,iface) 01017 { } 01018 #endif 01019 01020 ~SingleThreadRTPSessionIPV6() 01021 { 01022 if (isRunning()) { 01023 disableStack(); Thread::join(); 01024 } 01025 } 01026 01027 #if defined(_MSC_VER) && _MSC_VER >= 1300 01028 virtual void startRunning(); 01029 #else 01030 01033 void 01034 startRunning() 01035 { enableStack(); Thread::start(); } 01036 #endif 01037 01038 01039 protected: 01040 inline void enableStack(void) 01041 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();} 01042 01043 inline void disableStack(void) 01044 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();} 01045 01046 inline microtimeout_t getSchedulingTimeout(void) 01047 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();} 01048 01049 inline void controlReceptionService(void) 01050 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();} 01051 01052 inline void controlTransmissionService(void) 01053 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();} 01054 01055 inline timeval getRTCPCheckInterval(void) 01056 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();} 01057 01058 inline size_t dispatchDataPacket(void) 01059 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();} 01060 01061 #if defined(_MSC_VER) && _MSC_VER >= 1300 01062 virtual void run(void); 01063 01064 virtual void timerTick(void); 01065 01066 virtual bool isPendingData(microtimeout_t timeout); 01067 #else 01068 01069 virtual void timerTick(void) 01070 {return;} 01071 01072 virtual bool isPendingData(microtimeout_t timeout) 01073 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);} 01074 01079 virtual void run(void) 01080 { 01081 microtimeout_t timeout = 0; 01082 while ( ServiceQueue::isActive() ) { 01083 if ( timeout < 1000 ){ // !(timeout/1000) 01084 timeout = getSchedulingTimeout(); 01085 } 01086 setCancel(cancelDeferred); 01087 controlReceptionService(); 01088 controlTransmissionService(); 01089 setCancel(cancelImmediate); 01090 microtimeout_t maxWait = 01091 timeval2microtimeout(getRTCPCheckInterval()); 01092 // make sure the scheduling timeout is 01093 // <= the check interval for RTCP 01094 // packets 01095 timeout = (timeout > maxWait)? maxWait : timeout; 01096 if ( timeout < 1000 ) { // !(timeout/1000) 01097 setCancel(cancelDeferred); 01098 dispatchDataPacket(); 01099 setCancel(cancelImmediate); 01100 timerTick(); 01101 } else { 01102 if ( isPendingData(timeout/1000) ) { 01103 setCancel(cancelDeferred); 01104 takeInDataPacket(); 01105 setCancel(cancelImmediate); 01106 } 01107 timeout = 0; 01108 } 01109 } 01110 dispatchBYE("GNU ccRTP stack finishing."); 01111 Thread::exit(); 01112 } 01113 01114 #endif 01115 01116 inline size_t takeInDataPacket(void) 01117 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();} 01118 01119 inline size_t dispatchBYE(const std::string &str) 01120 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);} 01121 }; 01122 01131 typedef SingleThreadRTPSessionIPV6<> RTPSessionIPV6; 01132 01138 typedef RTPSessionIPV6 RTPSocketIPV6; 01139 01148 typedef SingleThreadRTPSessionIPV6<SymmetricRTPChannelIPV6, 01149 SymmetricRTPChannelIPV6> SymmetricRTPSessionIPV6; 01150 01151 01152 #endif 01153 // sessions 01155 01156 #ifdef CCXX_NAMESPACES 01157 } 01158 #endif 01159 01160 #endif //CCXX_RTP_RTP_H_ 01161