rtp.h

Go to the documentation of this file.
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 
00233                 inline size_t
00234                 sendData(const unsigned char* const buffer, size_t len)
00235                         { return dso->send(buffer, len); }
00236 
00237                 inline SOCKET getDataRecvSocket() const
00238                         { return dso->getRecvSocket(); }
00239 
00244                 inline bool
00245                 isPendingControl(microtimeout_t timeout)
00246                         { return cso->isPendingRecv(timeout); }
00247 
00248                 InetHostAddress
00249                 getControlSender(tpport_t *port = NULL) const
00250                         { return cso->getSender(port); }
00251 
00261                 inline size_t
00262                 recvControl(unsigned char *buffer, size_t len,
00263                             InetHostAddress& na, tpport_t& tp)
00264                         { na = cso->getSender(tp); return cso->recv(buffer,len); }
00265 
00266                 inline void
00267                 setControlPeer(const InetAddress &host, tpport_t port)
00268                         { cso->setPeer(host,port); }
00269 
00275                 inline size_t
00276                 sendControl(const unsigned char* const buffer, size_t len)
00277                         { return cso->send(buffer,len); }
00278 
00279                 inline SOCKET getControlRecvSocket() const
00280                         { return cso->getRecvSocket(); }
00281 
00288                 inline Socket::Error
00289                 joinGroup(const InetMcastAddress& ia, uint32 iface)
00290                         {
00291                                 Socket::Error error  = dso->setMulticast(true);
00292                                 if ( error ) return error;
00293                                 error = dso->join(ia,iface);
00294                                 if ( error ) return error;
00295                                 error = cso->setMulticast(true);
00296                                 if ( error ) {
00297                                         dso->drop(ia);
00298                                         return error;
00299                                 }
00300                                 error = cso->join(ia,iface);
00301                                 if ( error ) {
00302                                         dso->drop(ia);
00303                                         return error;
00304                                 }
00305                                 return Socket::errSuccess;
00306                         }
00307 
00314                 inline Socket::Error
00315                 leaveGroup(const InetMcastAddress& ia)
00316                         {
00317                                 Socket::Error error = dso->setMulticast(false);
00318                                 if ( error ) return error;
00319                                 error = dso->leaveGroup(ia);
00320                                 if ( error ) return error;
00321                                 error = cso->setMulticast(false);
00322                                 if ( error ) return error;
00323                                 return cso->leaveGroup(ia);
00324                         }
00325 
00326                 inline void
00327                 endSocket()
00328                         {
00329                                 if (dso) {
00330                                         dso->endSocket();
00331                                         delete dso;
00332                                 }
00333                                 dso = NULL;
00334                                 if (cso) {
00335                                         cso->endSocket();
00336                                         delete cso;
00337                                 }
00338                                 cso = NULL;
00339                         }
00340 
00341         private:
00342                 void
00343                 build(const InetHostAddress& ia, tpport_t dataPort,
00344                       tpport_t controlPort)
00345                         {
00346                                 if ( 0 == controlPort ) {
00347                                         dataBasePort = even_port(dataPort);
00348                                         controlBasePort = dataBasePort + 1;
00349                                 } else {
00350                                         dataBasePort = dataPort;
00351                                         controlBasePort = controlPort;
00352                                 }
00353                                 dso = new RTPDataChannel(ia,dataBasePort);
00354                                 cso = new RTCPChannel(ia,controlBasePort);
00355                         }
00356 
00357                 void
00358                 build(const InetMcastAddress& ia, tpport_t dataPort,
00359                       tpport_t controlPort, uint32 iface)
00360                         {
00361                                 if ( 0 == controlPort ) {
00362                                         dataBasePort = even_port(dataPort);
00363                                         controlBasePort = dataBasePort + 1;
00364                                 } else {
00365                                         dataBasePort = dataPort;
00366                                         controlBasePort = controlPort;
00367                                 }
00368                                 dso = new RTPDataChannel(InetHostAddress("0.0.0.0"),dataBasePort);
00369                                 cso = new RTCPChannel(InetHostAddress("0.0.0.0"),controlBasePort);
00370                                 joinGroup(ia,iface);
00371                         }
00372 
00380                 inline tpport_t
00381                 odd_port(tpport_t port)
00382                         { return (port & 0x01)? (port) : (port - 1); }
00383 
00391                 inline tpport_t
00392                 even_port(tpport_t port)
00393                         { return (port & 0x01)? (port - 1) : (port); }
00394 
00395                 tpport_t dataBasePort;
00396                 tpport_t controlBasePort;
00397 
00398         protected:
00399                 RTPDataChannel* dso;
00400                 RTCPChannel* cso;
00401                 friend class RTPSessionBaseHandler;
00402         };
00403 
00414         template
00415         <class RTPDataChannel = DualRTPUDPIPv4Channel,
00416          class RTCPChannel = DualRTPUDPIPv4Channel,
00417          class ServiceQueue = AVPQueue>
00418         class __EXPORT SingleThreadRTPSession :
00419                 protected Thread,
00420                 public TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00421         {
00422         public:
00423                 SingleThreadRTPSession(const InetHostAddress& ia,
00424                                        tpport_t dataPort = DefaultRTPDataPort,
00425                                        tpport_t controlPort = 0,
00426                                        int pri = 0,
00427                                        uint32 memberssize =
00428                                        MembershipBookkeeping::defaultMembersHashSize,
00429                                        RTPApplication& app = defaultApplication()
00430 #if defined(_MSC_VER) && _MSC_VER >= 1300
00431                         );
00432 #else
00433                 ):
00434                 Thread(pri),
00435                 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00436                 (ia,dataPort,controlPort,memberssize,app)
00437                 { }
00438 #endif
00439 
00440         SingleThreadRTPSession(uint32 ssrc, const InetHostAddress& ia,
00441                                tpport_t dataPort = DefaultRTPDataPort,
00442                                tpport_t controlPort = 0,
00443                                int pri = 0,
00444                                uint32 memberssize =
00445                                MembershipBookkeeping::defaultMembersHashSize,
00446                                RTPApplication& app = defaultApplication()
00447 #if defined(_MSC_VER) && _MSC_VER >= 1300
00448                 );
00449 #else
00450         ):
00451         Thread(pri),
00452         TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00453         (ssrc, ia,dataPort,controlPort,memberssize,app)
00454 { }
00455 #endif
00456 
00457 SingleThreadRTPSession(const InetMcastAddress& ia,
00458                        tpport_t dataPort = DefaultRTPDataPort,
00459                        tpport_t controlPort = 0,
00460                        int pri = 0,
00461                        uint32 memberssize =
00462                        MembershipBookkeeping::defaultMembersHashSize,
00463                        RTPApplication& app = defaultApplication(),
00464                        uint32 iface = 0
00465 #if defined(_MSC_VER) && _MSC_VER >= 1300
00466                );
00467 #else
00468         ):
00469         Thread(pri),
00470         TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00471         (ia,dataPort,controlPort,memberssize,app,iface)
00472         { }
00473 #endif
00474 
00475 SingleThreadRTPSession(uint32 ssrc, const InetMcastAddress& ia,
00476                        tpport_t dataPort = DefaultRTPDataPort,
00477                        tpport_t controlPort = 0,
00478                        int pri = 0,
00479                        uint32 memberssize =
00480                        MembershipBookkeeping::defaultMembersHashSize,
00481                        RTPApplication& app = defaultApplication(),
00482                        uint32 iface = 0
00483 #if defined(_MSC_VER) && _MSC_VER >= 1300
00484                       );
00485 #else
00486                 ):
00487                 Thread(pri),
00488                 TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>
00489                 (ssrc,ia,dataPort,controlPort,memberssize,app,iface)
00490 { }
00491 #endif
00492 
00493 
00494 ~SingleThreadRTPSession()
00495 {
00496     if (isRunning()) {
00497         disableStack(); Thread::join();
00498     }
00499 }
00500 
00501 #if defined(_MSC_VER) && _MSC_VER >= 1300
00502 virtual void startRunning();
00503 #else
00504 
00507 void
00508 startRunning()
00509 { enableStack(); Thread::start(); }
00510 #endif
00511 
00512 
00513 protected:
00514 inline void disableStack(void)
00515 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();}
00516 
00517 inline void enableStack(void)
00518 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();}
00519 
00520 inline microtimeout_t getSchedulingTimeout(void)
00521 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();}
00522 
00523 inline void controlReceptionService(void)
00524 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();}
00525 
00526 inline void controlTransmissionService(void)
00527 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();}
00528 
00529 inline timeval getRTCPCheckInterval(void)
00530 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();};
00531 
00532 inline size_t dispatchDataPacket(void)
00533 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();};
00534 
00535 #if defined(_MSC_VER) && _MSC_VER >= 1300
00536 virtual void run(void);
00537 
00538 virtual void timerTick(void);
00539 
00540 virtual bool isPendingData(microtimeout_t timeout);
00541 #else
00542 
00543 virtual void timerTick(void)
00544 {return;}
00545 
00546 virtual bool isPendingData(microtimeout_t timeout)
00547 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);}
00548 
00553 virtual void run(void)
00554 {
00555         microtimeout_t timeout = 0;
00556         while ( ServiceQueue::isActive() ) {
00557                 if ( timeout < 1000 ){ // !(timeout/1000)
00558                         timeout = getSchedulingTimeout();
00559                 }
00560                 setCancel(cancelDeferred);
00561                 controlReceptionService();
00562                 controlTransmissionService();
00563                 setCancel(cancelImmediate);
00564                 microtimeout_t maxWait =
00565                         timeval2microtimeout(getRTCPCheckInterval());
00566                 // make sure the scheduling timeout is
00567                 // <= the check interval for RTCP
00568                 // packets
00569                 timeout = (timeout > maxWait)? maxWait : timeout;
00570                 if ( timeout < 1000 ) { // !(timeout/1000)
00571                         setCancel(cancelDeferred);
00572                         dispatchDataPacket();
00573                         setCancel(cancelImmediate);
00574                         timerTick();
00575                 } else {
00576                         if ( isPendingData(timeout/1000) ) {
00577                                 setCancel(cancelDeferred);
00578                                 if (ServiceQueue::isActive()) { // take in only if active
00579                                     takeInDataPacket();
00580                                 }
00581                                 setCancel(cancelImmediate);
00582                         }
00583                         timeout = 0;
00584                 }
00585         }
00586         dispatchBYE("GNU ccRTP stack finishing.");
00587         Thread::exit();
00588 }
00589 
00590 #endif
00591 
00592 inline size_t takeInDataPacket(void)
00593 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();}
00594 
00595 inline size_t dispatchBYE(const std::string &str)
00596 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);}
00597 };
00598 
00607 typedef SingleThreadRTPSession<> RTPSession;
00608 
00614 typedef RTPSession RTPSocket;
00615 
00624 typedef SingleThreadRTPSession<SymmetricRTPChannel,
00625                                SymmetricRTPChannel> SymmetricRTPSession;
00626 
00627 #ifdef  CCXX_IPV6
00628 
00650 template <class RTPDataChannel = DualRTPUDPIPv6Channel,
00651           class RTCPChannel = DualRTPUDPIPv6Channel,
00652           class ServiceQueue = AVPQueue>
00653 class __EXPORT TRTPSessionBaseIPV6 : public ServiceQueue
00654 {
00655 public:
00665 TRTPSessionBaseIPV6(const IPV6Host& ia, tpport_t dataPort,
00666         tpport_t controlPort, uint32 membersSize,
00667         RTPApplication& app) :
00668         ServiceQueue(membersSize,app)
00669 { build(ia,dataPort,controlPort); }
00670 
00682         TRTPSessionBaseIPV6(uint32 ssrc,
00683                             const IPV6Host& ia,
00684                             tpport_t dataPort, tpport_t controlPort,
00685                             uint32 membersSize, RTPApplication& app):
00686                 ServiceQueue(ssrc,membersSize,app)
00687                 { build(ia,dataPort,controlPort); }
00688 
00701         TRTPSessionBaseIPV6(const IPV6Multicast& ia, tpport_t dataPort,
00702                             tpport_t controlPort, uint32 membersSize,
00703                             RTPApplication& app, uint32 iface) :
00704                 ServiceQueue(membersSize,app)
00705                 { build(ia,dataPort,controlPort,iface); }
00706 
00721         TRTPSessionBaseIPV6(uint32 ssrc,
00722                             const IPV6Multicast& ia, tpport_t dataPort,
00723                             tpport_t controlPort, uint32 membersSize,
00724                             RTPApplication& app, uint32 iface) :
00725                 ServiceQueue(ssrc,membersSize,app)
00726                 { build(ia,dataPort,controlPort,iface); }
00727 
00728         virtual size_t dispatchBYE(const std::string &str)
00729                 {
00730                         return QueueRTCPManager::dispatchBYE(str);
00731                 }
00732 
00733         inline virtual
00734         ~TRTPSessionBaseIPV6()
00735                 {
00736                         endSocket();
00737                 }
00738 
00739         inline RTPDataChannel *getDSO(void)
00740                 {return dso;};
00741 
00742 protected:
00746         inline bool
00747         isPendingData(microtimeout_t timeout)
00748                 { return dso->isPendingRecv(timeout); }
00749 
00750         inline IPV6Host
00751         getDataSender(tpport_t *port = NULL) const
00752                 { return dso->getSender(port); }
00753 
00754         inline size_t
00755         getNextDataPacketSize() const
00756                 { return dso->getNextPacketSize(); }
00757 
00767         inline size_t
00768         recvData(unsigned char* buffer, size_t len,
00769                  IPV6Host& na, tpport_t& tp)
00770                 { na = dso->getSender(tp); return dso->recv(buffer, len); }
00771 
00772         inline void
00773         setDataPeer(const IPV6Host &host, tpport_t port)
00774                 { dso->setPeer(host,port); }
00775 
00780         inline size_t
00781         sendData(const unsigned char* const buffer, size_t len)
00782                 { return dso->send(buffer, len); }
00783 
00784         inline SOCKET getDataRecvSocket() const
00785                 { return dso->getRecvSocket(); }
00786 
00791         inline bool
00792         isPendingControl(microtimeout_t timeout)
00793                 { return cso->isPendingRecv(timeout); }
00794 
00795         inline IPV6Host
00796         getControlSender(tpport_t *port = NULL) const
00797                 { return cso->getSender(port); }
00798 
00808         inline size_t
00809         recvControl(unsigned char *buffer, size_t len,
00810                     IPV6Host& na, tpport_t& tp)
00811                 { na = cso->getSender(tp); return cso->recv(buffer,len); }
00812 
00813         inline void
00814         setControlPeer(const IPV6Host &host, tpport_t port)
00815                 { cso->setPeer(host,port); }
00816 
00822         inline size_t
00823         sendControl(const unsigned char* const buffer, size_t len)
00824                 { return cso->send(buffer,len); }
00825 
00826         inline SOCKET getControlRecvSocket() const
00827                 { return cso->getRecvSocket(); }
00828 
00829         inline void
00830         endSocket()
00831                 {
00832                         dso->endSocket();
00833                         cso->endSocket();
00834                         if (dso) delete dso;
00835                         dso = NULL;
00836                         if (cso) delete cso;
00837                         cso = NULL;
00838                 }
00839 
00840 private:
00841         void
00842         build(const IPV6Host& ia, tpport_t dataPort,
00843               tpport_t controlPort)
00844                 {
00845                         if ( 0 == controlPort ) {
00846                                 dataBasePort = even_port(dataPort);
00847                                 controlBasePort = dataBasePort + 1;
00848                         } else {
00849                                 dataBasePort = dataPort;
00850                                 controlBasePort = controlPort;
00851                         }
00852                         dso = new RTPDataChannel(ia,dataBasePort);
00853                         cso = new RTCPChannel(ia,controlBasePort);
00854                 }
00855 
00856         void
00857         build(const IPV6Multicast& ia, tpport_t dataPort,
00858               tpport_t controlPort, uint32 iface)
00859                 {
00860                         if ( 0 == controlPort ) {
00861                                 dataBasePort = even_port(dataPort);
00862                                 controlBasePort = dataBasePort + 1;
00863                         } else {
00864                                 dataBasePort = dataPort;
00865                                 controlBasePort = controlPort;
00866                         }
00867                         dso = new RTPDataChannel(IPV6Host("0.0.0.0"),dataBasePort);
00868                         cso = new RTCPChannel(IPV6Host("0.0.0.0"),controlBasePort);
00869                         joinGroup(ia,iface);
00870                 }
00871 
00878         inline Socket::Error
00879         joinGroup(const IPV6Multicast& ia, uint32 iface)
00880                 {
00881                         Socket::Error error  = dso->setMulticast(true);
00882                         if ( error ) return error;
00883                         error = dso->join(ia,iface);
00884                         if ( error ) return error;
00885                         error = cso->setMulticast(true);
00886                         if ( error ) {
00887                                 dso->drop(ia);
00888                                 return error;
00889                         }
00890                         error = cso->join(ia,iface);
00891                         if ( error ) {
00892                                 dso->drop(ia);
00893                                 return error;
00894                         }
00895                         return Socket::errSuccess;
00896                 }
00897 
00904         inline Socket::Error
00905         leaveGroup(const IPV6Multicast& ia)
00906                 {
00907                         Socket::Error error = dso->setMulticast(false);
00908                         if ( error ) return error;
00909                         error = dso->leaveGroup(ia);
00910                         if ( error ) return error;
00911                         error = cso->setMulticast(false);
00912                         if ( error ) return error;
00913                         return cso->leaveGroup(ia);
00914                 }
00915 
00922         inline Socket::Error
00923         setMcastTTL(uint8 ttl)
00924                 {
00925                         Socket::Error error = dso->setMulticast(true);
00926                         if ( error ) return error;
00927                         error = dso->setTimeToLive(ttl);
00928                         if ( error ) return error;
00929                         error = cso->setMulticast(true);
00930                         if ( error ) return error;
00931                         return cso->setTimeToLive(ttl);
00932                 }
00933 
00941         inline tpport_t
00942         odd_port(tpport_t port)
00943                 { return (port & 0x01)? (port) : (port - 1); }
00944 
00952         inline tpport_t
00953         even_port(tpport_t port)
00954                 { return (port & 0x01)? (port - 1) : (port); }
00955 
00956         tpport_t dataBasePort;
00957         tpport_t controlBasePort;
00958 
00959 protected:
00960         RTPDataChannel* dso;
00961         RTCPChannel* cso;
00962         friend class RTPSessionBaseHandler;
00963 };
00964 
00975 template
00976 <class RTPDataChannel = DualRTPUDPIPv6Channel,
00977  class RTCPChannel = DualRTPUDPIPv6Channel,
00978  class ServiceQueue = AVPQueue>
00979 class __EXPORT SingleThreadRTPSessionIPV6 :
00980         protected Thread,
00981         public TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
00982 {
00983 public:
00984         SingleThreadRTPSessionIPV6(const IPV6Host& ia,
00985                                    tpport_t dataPort = DefaultRTPDataPort,
00986                                    tpport_t controlPort = 0,
00987                                    int pri = 0,
00988                                    uint32 memberssize =
00989                                    MembershipBookkeeping::defaultMembersHashSize,
00990                                    RTPApplication& app = defaultApplication()
00991 #if defined(_MSC_VER) && _MSC_VER >= 1300
00992                 );
00993 #else
00994         ):
00995         Thread(pri),
00996         TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
00997         (ia,dataPort,controlPort,memberssize,app)
00998 { }
00999 #endif
01000 
01001 SingleThreadRTPSessionIPV6(const IPV6Multicast& ia,
01002                            tpport_t dataPort = DefaultRTPDataPort,
01003                            tpport_t controlPort = 0,
01004                            int pri = 0,
01005                            uint32 memberssize =
01006                            MembershipBookkeeping::defaultMembersHashSize,
01007                            RTPApplication& app = defaultApplication(),
01008                            uint32 iface = 0
01009 #if defined(_MSC_VER) && _MSC_VER >= 1300
01010         );
01011 #else
01012         ):
01013         Thread(pri),
01014         TRTPSessionBaseIPV6<RTPDataChannel,RTCPChannel,ServiceQueue>
01015         (ia,dataPort,controlPort,memberssize,app,iface)
01016 { }
01017 #endif
01018 
01019 ~SingleThreadRTPSessionIPV6()
01020 {
01021     if (isRunning()) {
01022         disableStack(); Thread::join();
01023     }
01024 }
01025 
01026 #if defined(_MSC_VER) && _MSC_VER >= 1300
01027 virtual void startRunning();
01028 #else
01029 
01032 void
01033 startRunning()
01034 { enableStack(); Thread::start(); }
01035 #endif
01036 
01037 
01038 protected:
01039 inline void enableStack(void)
01040 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::enableStack();}
01041 
01042 inline void disableStack(void)
01043 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::disableStack();}
01044 
01045 inline microtimeout_t getSchedulingTimeout(void)
01046 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getSchedulingTimeout();}
01047 
01048 inline void controlReceptionService(void)
01049 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlReceptionService();}
01050 
01051 inline void controlTransmissionService(void)
01052 {TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::controlTransmissionService();}
01053 
01054 inline timeval getRTCPCheckInterval(void)
01055 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::getRTCPCheckInterval();};
01056 
01057 inline size_t dispatchDataPacket(void)
01058 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchDataPacket();};
01059 
01060 #if defined(_MSC_VER) && _MSC_VER >= 1300
01061 virtual void run(void);
01062 
01063 virtual void timerTick(void);
01064 
01065 virtual bool isPendingData(microtimeout_t timeout);
01066 #else
01067 
01068 virtual void timerTick(void)
01069 {return;}
01070 
01071 virtual bool isPendingData(microtimeout_t timeout)
01072 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::isPendingData(timeout);}
01073 
01078 virtual void run(void)
01079 {
01080         microtimeout_t timeout = 0;
01081         while ( ServiceQueue::isActive() ) {
01082                 if ( timeout < 1000 ){ // !(timeout/1000)
01083                         timeout = getSchedulingTimeout();
01084                 }
01085                 setCancel(cancelDeferred);
01086                 controlReceptionService();
01087                 controlTransmissionService();
01088                 setCancel(cancelImmediate);
01089                 microtimeout_t maxWait =
01090                         timeval2microtimeout(getRTCPCheckInterval());
01091                 // make sure the scheduling timeout is
01092                 // <= the check interval for RTCP
01093                 // packets
01094                 timeout = (timeout > maxWait)? maxWait : timeout;
01095                 if ( timeout < 1000 ) { // !(timeout/1000)
01096                         setCancel(cancelDeferred);
01097                         dispatchDataPacket();
01098                         setCancel(cancelImmediate);
01099                         timerTick();
01100                 } else {
01101                         if ( isPendingData(timeout/1000) ) {
01102                                 setCancel(cancelDeferred);
01103                                 takeInDataPacket();
01104                                 setCancel(cancelImmediate);
01105                         }
01106                         timeout = 0;
01107                 }
01108         }
01109         dispatchBYE("GNU ccRTP stack finishing.");
01110         Thread::exit();
01111 }
01112 
01113 #endif
01114 
01115 inline size_t takeInDataPacket(void)
01116 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::takeInDataPacket();}
01117 
01118 inline size_t dispatchBYE(const std::string &str)
01119 {return TRTPSessionBase<RTPDataChannel,RTCPChannel,ServiceQueue>::dispatchBYE(str);}
01120 };
01121 
01130 typedef SingleThreadRTPSessionIPV6<> RTPSessionIPV6;
01131 
01137 typedef RTPSessionIPV6 RTPSocketIPV6;
01138 
01147  typedef SingleThreadRTPSessionIPV6<SymmetricRTPChannelIPV6,
01148                                     SymmetricRTPChannelIPV6> SymmetricRTPSessionIPV6;
01149 
01150 
01151 #endif
01152  // sessions
01154 
01155 #ifdef  CCXX_NAMESPACES
01156 }
01157 #endif
01158 
01159 #endif  //CCXX_RTP_RTP_H_
01160 

Generated on Fri Jan 12 15:49:11 2007 for ccRTP by  doxygen 1.5.1