- Main Page
- Modules
- Classes
- Files
- Examples

- File List
- File Members

# 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
    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