OPAL Version 3.10.2
transports.h
Go to the documentation of this file.
00001 /*
00002  * transport.h
00003  *
00004  * Transport declarations
00005  *
00006  * Open Phone Abstraction Library (OPAL)
00007  * Formally known as the Open H323 project.
00008  *
00009  * Copyright (c) 2001 Equivalence Pty. Ltd.
00010  * Portions Copyright (C) 2006 by Post Increment
00011  *
00012  * The contents of this file are subject to the Mozilla Public License
00013  * Version 1.0 (the "License"); you may not use this file except in
00014  * compliance with the License. You may obtain a copy of the License at
00015  * http://www.mozilla.org/MPL/
00016  *
00017  * Software distributed under the License is distributed on an "AS IS"
00018  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00019  * the License for the specific language governing rights and limitations
00020  * under the License.
00021  *
00022  * The Original Code is Open Phone Abstraction Library.
00023  *
00024  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00025  *
00026  * Contributor(s): Post Increment
00027  *     Portions of this code were written with the assistance of funding from
00028  *     US Joint Forces Command Joint Concept Development & Experimentation (J9)
00029  *     http://www.jfcom.mil/about/abt_j9.htm
00030  *
00031  * $Revision: 26231 $
00032  * $Author: rjongbloed $
00033  * $Date: 2011-07-19 21:23:34 -0500 (Tue, 19 Jul 2011) $
00034  */
00035 
00036 #ifndef OPAL_OPAL_TRANSPORT_H
00037 #define OPAL_OPAL_TRANSPORT_H
00038 
00039 #ifdef P_USE_PRAGMA
00040 #pragma interface
00041 #endif
00042 
00043 #include <opal/buildopts.h>
00044 
00045 #include <ptlib/sockets.h>
00046 #include <ptclib/psockbun.h>
00047 
00048 
00049 class OpalManager;
00050 class OpalEndPoint;
00051 class OpalListener;
00052 class OpalTransport;
00053 class OpalInternalTransport;
00054 
00055 
00057 
00149 class OpalTransportAddress : public PCaselessString
00150 {
00151   PCLASSINFO(OpalTransportAddress, PCaselessString);
00152   public:
00155     OpalTransportAddress();
00156     OpalTransportAddress(
00157       const char * address,      
00158       WORD port = 0,             
00159       const char * proto = NULL  
00160     );
00161     OpalTransportAddress(
00162       const PString & address,   
00163       WORD port = 0,             
00164       const char * proto = NULL  
00165     );
00166     OpalTransportAddress(
00167       const PIPSocket::Address & ip,  
00168       WORD port,                      
00169       const char * proto = NULL       
00170     );
00172 
00180     PBoolean IsEquivalent(
00181       const OpalTransportAddress & address,   
00182       bool wildcards = false   
00183     ) const;
00184 
00187     PBoolean IsCompatible(
00188       const OpalTransportAddress & address
00189     ) const;
00190 
00193     PCaselessString GetProto(bool withDollar = false) const { return Left(Find('$')+(withDollar?1:0)); }
00194 
00198     PBoolean GetIpAddress(PIPSocket::Address & ip) const;
00199 
00203     PBoolean GetIpAndPort(PIPSocket::Address & ip, WORD & port) const;
00204     PBoolean GetIpAndPort(PIPSocketAddressAndPort & ipPort) const;
00205 
00209     virtual PString GetHostName() const;
00210 
00211     enum BindOptions {
00212       NoBinding,
00213       HostOnly,
00214       FullTSAP,
00215       Streamed,
00216       Datagram,
00217       RouteInterface,
00218       NumBindOptions
00219     };
00220 
00252     OpalListener * CreateListener(
00253       OpalEndPoint & endpoint,   
00254       BindOptions option         
00255     ) const;
00256 
00284     virtual OpalTransport * CreateTransport(
00285       OpalEndPoint & endpoint,   
00286       BindOptions option = HostOnly 
00287     ) const;
00289 
00290 
00291   protected:
00292     void SetInternalTransport(
00293       WORD port,             
00294       const char * proto     
00295     );
00296 
00297     OpalInternalTransport * transport;
00298 };
00299 
00300 
00301 PDECLARE_ARRAY(OpalTransportAddressArray, OpalTransportAddress)
00302   public:
00303     OpalTransportAddressArray(
00304       const OpalTransportAddress & address
00305     ) { AppendAddress(address); }
00306     OpalTransportAddressArray(
00307       const PStringArray & array
00308     ) { AppendStringCollection(array); }
00309     OpalTransportAddressArray(
00310       const PStringList & list
00311     ) { AppendStringCollection(list); }
00312     OpalTransportAddressArray(
00313       const PSortedStringList & list
00314     ) { AppendStringCollection(list); }
00315 
00316     void AppendString(
00317       const char * address
00318     );
00319     void AppendString(
00320       const PString & address
00321     );
00322     void AppendAddress(
00323       const OpalTransportAddress & address
00324     );
00325 
00326   protected:
00327     void AppendStringCollection(
00328       const PCollection & coll
00329     );
00330 };
00331 
00332 
00333 
00334 
00336 
00349 class OpalListener : public PObject
00350 {
00351     PCLASSINFO(OpalListener, PObject);
00352   public:
00357     OpalListener(
00358       OpalEndPoint & endpoint   
00359     );
00361 
00366     void PrintOn(
00367       ostream & strm
00368     ) const;
00370 
00373     enum ThreadMode {
00374       SpawnNewThreadMode,
00375       HandOffThreadMode,
00376       SingleThreadMode
00377     };
00378 
00393     virtual PBoolean Open(
00394       const PNotifier & acceptHandler,  
00395       ThreadMode mode = SpawnNewThreadMode 
00396     ) = 0;
00397 
00400     virtual PBoolean IsOpen() = 0;
00401 
00404     virtual void Close() = 0;
00405 
00408     virtual OpalTransport * Accept(
00409       const PTimeInterval & timeout  
00410     ) = 0;
00411 
00414     virtual OpalTransport * CreateTransport(
00415       const OpalTransportAddress & localAddress,
00416       const OpalTransportAddress & remoteAddress
00417     ) const = 0;
00418 
00424     virtual OpalTransportAddress GetLocalAddress(
00425       const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00426     ) const = 0;
00427 
00430     void CloseWait();
00431 
00435     void CleanUpOnTermination() { CloseWait(); }
00437 
00438 
00439   protected:
00448     PDECLARE_NOTIFIER(PThread, OpalListener, ListenForConnections);
00449     PBoolean StartThread(
00450       const PNotifier & acceptHandler,  
00451       ThreadMode mode                   
00452     );
00453 
00454     OpalEndPoint & endpoint;
00455     PThread      * thread;
00456     PNotifier      acceptHandler;
00457     ThreadMode     threadMode;
00458 };
00459 
00460 
00461 PLIST(OpalListenerList, OpalListener);
00462 
00463 
00464 class OpalListenerIP : public OpalListener
00465 {
00466   PCLASSINFO(OpalListenerIP, OpalListener);
00467   public:
00472     OpalListenerIP(
00473       OpalEndPoint & endpoint,                 
00474       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00475       WORD port = 0,                           
00476       PBoolean exclusive = true               
00477     );
00478     OpalListenerIP(
00479       OpalEndPoint & endpoint,                  
00480       const OpalTransportAddress & binding,     
00481       OpalTransportAddress::BindOptions option  
00482     );
00484 
00492     virtual OpalTransportAddress GetLocalAddress(
00493       const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00494     ) const;
00496 
00499     WORD GetListenerPort() const { return listenerPort; }
00500 
00501     virtual const char * GetProtoPrefix() const = 0;
00503 
00504 
00505   protected:
00506     PIPSocket::Address localAddress;
00507     WORD               listenerPort;
00508     PBoolean               exclusiveListener;
00509 };
00510 
00511 
00512 class OpalListenerTCP : public OpalListenerIP
00513 {
00514   PCLASSINFO(OpalListenerTCP, OpalListenerIP);
00515   public:
00520     OpalListenerTCP(
00521       OpalEndPoint & endpoint,                 
00522       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00523       WORD port = 0,                           
00524       PBoolean exclusive = true               
00525     );
00526     OpalListenerTCP(
00527       OpalEndPoint & endpoint,                  
00528       const OpalTransportAddress & binding,     
00529       OpalTransportAddress::BindOptions option  
00530     );
00531 
00534     ~OpalListenerTCP();
00536 
00559     virtual PBoolean Open(
00560       const PNotifier & acceptHandler,  
00561       ThreadMode mode = SpawnNewThreadMode 
00562     );
00563 
00566     virtual PBoolean IsOpen();
00567 
00570     virtual void Close();
00571 
00574     virtual OpalTransport * Accept(
00575       const PTimeInterval & timeout  
00576     );
00577 
00580     virtual OpalTransport * CreateTransport(
00581       const OpalTransportAddress & localAddress,
00582       const OpalTransportAddress & remoteAddress
00583     ) const;
00585 
00586 
00587   protected:
00588     virtual const char * GetProtoPrefix() const;
00589 
00590     PTCPSocket listener;
00591 };
00592 
00593 
00594 class OpalListenerUDP : public OpalListenerIP
00595 {
00596   PCLASSINFO(OpalListenerUDP, OpalListenerIP);
00597   public:
00602     OpalListenerUDP(
00603       OpalEndPoint & endpoint,  
00604       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00605       WORD port = 0,            
00606       PBoolean exclusive = true  
00607     );
00608     OpalListenerUDP(
00609       OpalEndPoint & endpoint,                  
00610       const OpalTransportAddress & binding,     
00611       OpalTransportAddress::BindOptions option  
00612     );
00613 
00616     ~OpalListenerUDP();
00618 
00641     virtual PBoolean Open(
00642       const PNotifier & acceptHandler,  
00643       ThreadMode mode = SpawnNewThreadMode 
00644     );
00645 
00648     virtual PBoolean IsOpen();
00649 
00652     virtual void Close();
00653 
00656     virtual OpalTransport * Accept(
00657       const PTimeInterval & timeout  
00658     );
00659 
00662     virtual OpalTransport * CreateTransport(
00663       const OpalTransportAddress & localAddress,
00664       const OpalTransportAddress & remoteAddress
00665     ) const;
00666 
00672     virtual OpalTransportAddress GetLocalAddress(
00673       const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00674     ) const;
00676 
00681     void SetBufferSize(
00682       PINDEX size
00683     ) { m_bufferSize = size; }
00685 
00686 
00687   protected:
00688     virtual const char * GetProtoPrefix() const;
00689 
00690     PMonitoredSocketsPtr listenerBundle;
00691     PINDEX               m_bufferSize;
00692 };
00693 
00694 
00696 
00701 class OpalTransport : public PIndirectChannel
00702 {
00703     PCLASSINFO(OpalTransport, PIndirectChannel);
00704   public:
00709     OpalTransport(OpalEndPoint & endpoint);
00710 
00713     ~OpalTransport();
00715 
00720     void PrintOn(
00721       ostream & strm
00722     ) const;
00724 
00729     virtual PBoolean IsReliable() const = 0;
00730 
00737     virtual PString GetInterface() const;
00738 
00745     virtual bool SetInterface(
00746       const PString & iface  
00747     );
00748 
00751     virtual OpalTransportAddress GetLocalAddress(
00752       bool allowNAT = true   
00753     ) const = 0;
00754 
00759     virtual PBoolean SetLocalAddress(
00760       const OpalTransportAddress & address
00761     ) = 0;
00762 
00765     virtual OpalTransportAddress GetRemoteAddress() const = 0;
00766 
00772     virtual PBoolean SetRemoteAddress(
00773       const OpalTransportAddress & address
00774     ) = 0;
00775 
00778     virtual PBoolean Connect() = 0;
00779 
00782     PBoolean ConnectTo(
00783       const OpalTransportAddress & address
00784     ) { return SetRemoteAddress(address) && Connect(); }
00785 
00788     virtual PBoolean Close();
00789 
00792     void CloseWait();
00793 
00797     void CleanUpOnTermination() { CloseWait(); }
00798 
00801     virtual PBoolean IsCompatibleTransport(
00802       const OpalTransportAddress & address
00803     ) const = 0;
00804 
00806     enum PromisciousModes {
00807       AcceptFromRemoteOnly,
00808       AcceptFromAnyAutoSet,
00809       AcceptFromAny,
00810       NumPromisciousModes
00811     };
00812 
00823     virtual void SetPromiscuous(
00824       PromisciousModes promiscuous
00825     );
00826 
00831     virtual OpalTransportAddress GetLastReceivedAddress() const;
00832 
00837     virtual PString GetLastReceivedInterface() const;
00838 
00848     virtual PBoolean ReadPDU(
00849       PBYTEArray & packet   
00850     ) = 0;
00851 
00857     virtual PBoolean WritePDU(
00858       const PBYTEArray & pdu     
00859     ) = 0;
00860 
00861     typedef PBoolean (*WriteConnectCallback)(OpalTransport & transport, void * userData);
00862 
00875     virtual PBoolean WriteConnect(
00876       WriteConnectCallback function,  
00877       void * userData                 
00878     );
00879 
00882     virtual void AttachThread(
00883       PThread * thread
00884     );
00885 
00888     virtual PBoolean IsRunning() const;
00890 
00891     OpalEndPoint & GetEndPoint() const { return endpoint; }
00892 
00895     virtual const char * GetProtoPrefix() const = 0;
00896 
00897     PMutex & GetWriteMutex() { return m_writeMutex; }
00898 
00899   protected:
00900     OpalEndPoint & endpoint;
00901     PThread      * thread;      
00902     PMutex         m_writeMutex;
00903 };
00904 
00905 
00906 class OpalTransportIP : public OpalTransport
00907 {
00908   PCLASSINFO(OpalTransportIP, OpalTransport);
00909   public:
00914     OpalTransportIP(
00915       OpalEndPoint & endpoint,    
00916       PIPSocket::Address binding, 
00917       WORD port                   
00918     );
00920 
00925     virtual OpalTransportAddress GetLocalAddress(
00926       bool allowNAT = true   
00927     ) const;
00928 
00933     virtual PBoolean SetLocalAddress(
00934       const OpalTransportAddress & address
00935     );
00936 
00939     virtual OpalTransportAddress GetRemoteAddress() const;
00940 
00946     virtual PBoolean SetRemoteAddress(
00947       const OpalTransportAddress & address
00948     );
00949 
00951 
00952   protected:
00955     virtual const char * GetProtoPrefix() const = 0;
00956 
00957     PIPSocket::Address localAddress;  // Address of the local interface
00958     WORD               localPort;
00959     PIPSocket::Address remoteAddress; // Address of the remote host
00960     WORD               remotePort;
00961 };
00962 
00963 
00964 class OpalTransportTCP : public OpalTransportIP
00965 {
00966     PCLASSINFO(OpalTransportTCP, OpalTransportIP);
00967   public:
00972     OpalTransportTCP(
00973       OpalEndPoint & endpoint,    
00974       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00975       WORD port = 0,              
00976       PBoolean reuseAddr = false      
00977     );
00978     OpalTransportTCP(
00979       OpalEndPoint & endpoint,    
00980       PTCPSocket * socket         
00981     );
00982 
00984     ~OpalTransportTCP();
00986 
00991     virtual PBoolean IsReliable() const;
00992 
00995     virtual PBoolean IsCompatibleTransport(
00996       const OpalTransportAddress & address
00997     ) const;
00998 
01001     virtual PBoolean Connect();
01002 
01012     virtual PBoolean ReadPDU(
01013       PBYTEArray & pdu  
01014     );
01015 
01021     virtual PBoolean WritePDU(
01022       const PBYTEArray & pdu     
01023     );
01025 
01026 
01027   protected:
01030     virtual const char * GetProtoPrefix() const;
01031 
01041     virtual PBoolean OnOpen();
01042 
01043 
01044     PBoolean reuseAddressFlag;
01045 };
01046 
01047 
01048 class OpalTransportUDP : public OpalTransportIP
01049 {
01050   PCLASSINFO(OpalTransportUDP, OpalTransportIP);
01051   public:
01056     OpalTransportUDP(
01057       OpalEndPoint & endpoint,    
01058       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
01059       WORD port = 0,              
01060       bool reuseAddr = false,     
01061       bool preOpen = false        
01062     );
01063 
01066     OpalTransportUDP(
01067       OpalEndPoint & endpoint,              
01068       const PMonitoredSocketsPtr & sockets, 
01069       const PString & iface                 
01070     );
01071 
01073     ~OpalTransportUDP();
01075 
01078     virtual PBoolean Read(
01079       void * buffer,
01080       PINDEX length
01081     );
01083 
01088     virtual PBoolean IsReliable() const;
01089 
01092     virtual PBoolean IsCompatibleTransport(
01093       const OpalTransportAddress & address
01094     ) const;
01095 
01103     virtual PBoolean Connect();
01104 
01107     virtual PString GetInterface() const;
01108 
01115     virtual bool SetInterface(
01116       const PString & iface  
01117     );
01118 
01121     virtual OpalTransportAddress GetLocalAddress(
01122       bool allowNAT = true   
01123     ) const;
01124 
01129     virtual PBoolean SetLocalAddress(
01130       const OpalTransportAddress & address
01131     );
01132 
01138     virtual PBoolean SetRemoteAddress(
01139       const OpalTransportAddress & address
01140     );
01141 
01153     virtual void SetPromiscuous(
01154       PromisciousModes promiscuous
01155     );
01156 
01161     virtual OpalTransportAddress GetLastReceivedAddress() const;
01162 
01167     virtual PString GetLastReceivedInterface() const;
01168 
01178     virtual PBoolean ReadPDU(
01179       PBYTEArray & packet   
01180     );
01181 
01187     virtual PBoolean WritePDU(
01188       const PBYTEArray & pdu     
01189     );
01190 
01201     virtual PBoolean WriteConnect(
01202       WriteConnectCallback function,  
01203       void * userData                 
01204     );
01205 
01208     void SetBufferSize(
01209       PINDEX size
01210     ) { m_bufferSize = size; }
01212 
01213   protected:
01216     virtual const char * GetProtoPrefix() const;
01217 
01218     OpalManager & manager;
01219     PINDEX        m_bufferSize;
01220     PBYTEArray    m_preReadPacket;
01221     bool          m_preReadOK;
01222 
01223   friend class OpalListenerUDP;
01224 };
01225 
01226 
01228 
01229 class OpalInternalTransport : public PObject
01230 {
01231     PCLASSINFO(OpalInternalTransport, PObject);
01232   public:
01233     virtual PString GetHostName(
01234       const OpalTransportAddress & address
01235     ) const;
01236 
01237     virtual PBoolean GetIpAndPort(
01238       const OpalTransportAddress & address,
01239       PIPSocket::Address & ip,
01240       WORD & port
01241     ) const;
01242 
01243     virtual OpalListener * CreateListener(
01244       const OpalTransportAddress & address,
01245       OpalEndPoint & endpoint,
01246       OpalTransportAddress::BindOptions options
01247     ) const  = 0;
01248 
01249     virtual OpalTransport * CreateTransport(
01250       const OpalTransportAddress & address,
01251       OpalEndPoint & endpoint,
01252       OpalTransportAddress::BindOptions options
01253     ) const = 0;
01254 };
01255 
01256 
01258 
01259 class OpalInternalIPTransport : public OpalInternalTransport
01260 {
01261     PCLASSINFO(OpalInternalIPTransport, OpalInternalTransport);
01262   public:
01263     virtual PString GetHostName(
01264       const OpalTransportAddress & address
01265     ) const;
01266     virtual PBoolean GetIpAndPort(
01267       const OpalTransportAddress & address,
01268       PIPSocket::Address & ip,
01269       WORD & port
01270     ) const;
01271 
01272     static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
01273                                      OpalEndPoint & endpoint,
01274                                      OpalTransportAddress::BindOptions option,
01275                                      PIPSocket::Address & ip,
01276                                      WORD & port,
01277                                      PBoolean & reuseAddr);
01278 };
01279 
01280 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
01281 class OpalInternalIPTransportTemplate : public OpalInternalIPTransport
01282 {
01283   public:
01284     OpalListener * CreateListener(
01285       const OpalTransportAddress & address,
01286       OpalEndPoint & endpoint,
01287       OpalTransportAddress::BindOptions options
01288     ) const
01289     {
01290       return new ListenerType(endpoint, address, options);
01291     }
01292 
01293     OpalTransport * CreateTransport(
01294       const OpalTransportAddress & address,
01295       OpalEndPoint & endpoint,
01296       OpalTransportAddress::BindOptions options
01297     ) const
01298     {
01299       PIPSocket::Address ip;
01300       WORD port;
01301       PBoolean reuseAddr;
01302       if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
01303         if (options == AltTypeOption)
01304           return new AltTypeClass(endpoint, ip, 0, reuseAddr);
01305         else
01306           return new TransportType(endpoint, ip, 0, reuseAddr);
01307       }
01308       return NULL;
01309     }
01310 };
01311 
01312 typedef OpalInternalIPTransportTemplate<OpalListenerTCP, OpalTransportTCP, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPTransport;
01313 typedef OpalInternalIPTransportTemplate<OpalListenerUDP, OpalTransportUDP, OpalTransportAddress::Streamed, OpalTransportTCP> OpalInternalUDPTransport;
01314 
01315 #if OPAL_PTLIB_SSL
01316 
01317 class PSSLContext;
01318 
01319 class OpalListenerTCPS : public OpalListenerTCP
01320 {
01321   PCLASSINFO(OpalListenerTCPS, OpalListenerTCP);
01322   public:
01323     OpalListenerTCPS(
01324       OpalEndPoint & endpoint,                 
01325       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
01326       WORD port = 0,                           
01327       PBoolean exclusive = true               
01328     );
01329     OpalListenerTCPS(
01330       OpalEndPoint & endpoint,                  
01331       const OpalTransportAddress & binding,     
01332       OpalTransportAddress::BindOptions option  
01333     );
01334 
01337     ~OpalListenerTCPS();
01338 
01339     OpalTransport * Accept(const PTimeInterval & timeout);
01340     const char * GetProtoPrefix() const;
01341 
01342   protected:
01343     void Construct();
01344 
01345     PSSLContext * sslContext;
01346 };
01347 
01348 class OpalTransportTCPS : public OpalTransportTCP
01349 {
01350   PCLASSINFO(OpalTransportTCPS, OpalTransportTCP);
01351     public:
01352       OpalTransportTCPS(
01353         OpalEndPoint & endpoint,    
01354         PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
01355         WORD port = 0,              
01356         PBoolean reuseAddr = false      
01357       );
01358       OpalTransportTCPS(
01359         OpalEndPoint & endpoint,    
01360         PTCPSocket * socket         
01361       );
01362 
01364       ~OpalTransportTCPS();
01365 
01366       PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
01367       PBoolean Connect();
01368       PBoolean OnOpen();
01369       const char * GetProtoPrefix() const;
01370 
01371     protected:
01372       PSSLContext * sslContext;
01373 };
01374 
01375 typedef OpalInternalIPTransportTemplate<OpalListenerTCPS, OpalTransportTCPS, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPSTransport;
01376 
01377 
01378 #endif // OPAL_PTLIB_SSL
01379 
01380 
01381 #endif  // OPAL_OPAL_TRANSPORT_H
01382 
01383 
01384 // End of File ///////////////////////////////////////////////////////////////