00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
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 
00058 class OpalTransportAddress : public PCaselessString
00059 {
00060   PCLASSINFO(OpalTransportAddress, PCaselessString);
00061   public:
00064     OpalTransportAddress();
00065     OpalTransportAddress(
00066       const char * address,      
00067       WORD port = 0,             
00068       const char * proto = NULL  
00069     );
00070     OpalTransportAddress(
00071       const PString & address,   
00072       WORD port = 0,             
00073       const char * proto = NULL  
00074     );
00075     OpalTransportAddress(
00076       const PIPSocket::Address & ip,
00077       WORD port,
00078       const char * proto = NULL 
00079     );
00081 
00089     PBoolean IsEquivalent(
00090       const OpalTransportAddress & address,
00091       bool wildcards = false   
00092     ) const;
00093 
00096     PBoolean IsCompatible(
00097       const OpalTransportAddress & address
00098     ) const;
00099 
00102     PCaselessString GetProto() const { return Left(Find('$')); }
00103 
00107     PBoolean GetIpAddress(PIPSocket::Address & ip) const;
00108 
00112     PBoolean GetIpAndPort(PIPSocket::Address & ip, WORD & port) const;
00113     PBoolean GetIpAndPort(PIPSocketAddressAndPort & ipPort) const;
00114 
00118     virtual PString GetHostName() const;
00119 
00120     enum BindOptions {
00121       NoBinding,
00122       HostOnly,
00123       FullTSAP,
00124       Streamed,
00125       Datagram,
00126       RouteInterface,
00127       NumBindOptions
00128     };
00129 
00161     OpalListener * CreateListener(
00162       OpalEndPoint & endpoint,   
00163       BindOptions option         
00164     ) const;
00165 
00193     virtual OpalTransport * CreateTransport(
00194       OpalEndPoint & endpoint,   
00195       BindOptions option = HostOnly 
00196     ) const;
00198 
00199 
00200   protected:
00201     void SetInternalTransport(
00202       WORD port,             
00203       const char * proto     
00204     );
00205 
00206     OpalInternalTransport * transport;
00207 };
00208 
00209 
00210 PDECLARE_ARRAY(OpalTransportAddressArray, OpalTransportAddress)
00211   public:
00212     OpalTransportAddressArray(
00213       const OpalTransportAddress & address
00214     ) { AppendAddress(address); }
00215     OpalTransportAddressArray(
00216       const PStringArray & array
00217     ) { AppendStringCollection(array); }
00218     OpalTransportAddressArray(
00219       const PStringList & list
00220     ) { AppendStringCollection(list); }
00221     OpalTransportAddressArray(
00222       const PSortedStringList & list
00223     ) { AppendStringCollection(list); }
00224 
00225     void AppendString(
00226       const char * address
00227     );
00228     void AppendString(
00229       const PString & address
00230     );
00231     void AppendAddress(
00232       const OpalTransportAddress & address
00233     );
00234 
00235   protected:
00236     void AppendStringCollection(
00237       const PCollection & coll
00238     );
00239 };
00240 
00241 
00242 
00243 
00245 
00258 class OpalListener : public PObject
00259 {
00260     PCLASSINFO(OpalListener, PObject);
00261   public:
00266     OpalListener(
00267       OpalEndPoint & endpoint   
00268     );
00270 
00275     void PrintOn(
00276       ostream & strm
00277     ) const;
00279 
00282     enum ThreadMode {
00283       SpawnNewThreadMode,
00284       HandOffThreadMode,
00285       SingleThreadMode
00286     };
00287 
00302     virtual PBoolean Open(
00303       const PNotifier & acceptHandler,  
00304       ThreadMode mode = SpawnNewThreadMode 
00305     ) = 0;
00306 
00309     virtual PBoolean IsOpen() = 0;
00310 
00313     virtual void Close() = 0;
00314 
00317     virtual OpalTransport * Accept(
00318       const PTimeInterval & timeout  
00319     ) = 0;
00320 
00323     virtual OpalTransport * CreateTransport(
00324       const OpalTransportAddress & localAddress,
00325       const OpalTransportAddress & remoteAddress
00326     ) const = 0;
00327 
00333     virtual OpalTransportAddress GetLocalAddress(
00334       const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00335     ) const = 0;
00336 
00339     void CloseWait();
00340 
00344     void CleanUpOnTermination() { CloseWait(); }
00346 
00347 
00348   protected:
00357     PDECLARE_NOTIFIER(PThread, OpalListener, ListenForConnections);
00358     PBoolean StartThread(
00359       const PNotifier & acceptHandler,  
00360       ThreadMode mode                   
00361     );
00362 
00363     OpalEndPoint & endpoint;
00364     PThread      * thread;
00365     PNotifier      acceptHandler;
00366     ThreadMode     threadMode;
00367 };
00368 
00369 
00370 PLIST(OpalListenerList, OpalListener);
00371 
00372 
00373 class OpalListenerIP : public OpalListener
00374 {
00375   PCLASSINFO(OpalListenerIP, OpalListener);
00376   public:
00381     OpalListenerIP(
00382       OpalEndPoint & endpoint,                 
00383       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00384       WORD port = 0,                           
00385       PBoolean exclusive = PTrue
00386     );
00387     OpalListenerIP(
00388       OpalEndPoint & endpoint,                  
00389       const OpalTransportAddress & binding,     
00390       OpalTransportAddress::BindOptions option  
00391     );
00393 
00401     virtual OpalTransportAddress GetLocalAddress(
00402       const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00403     ) const;
00405 
00408     WORD GetListenerPort() const { return listenerPort; }
00409 
00410     virtual const char * GetProtoPrefix() const = 0;
00412 
00413 
00414   protected:
00415     PIPSocket::Address localAddress;
00416     WORD               listenerPort;
00417     PBoolean               exclusiveListener;
00418 };
00419 
00420 
00421 class OpalListenerTCP : public OpalListenerIP
00422 {
00423   PCLASSINFO(OpalListenerTCP, OpalListenerIP);
00424   public:
00429     OpalListenerTCP(
00430       OpalEndPoint & endpoint,                 
00431       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00432       WORD port = 0,                           
00433       PBoolean exclusive = PTrue
00434     );
00435     OpalListenerTCP(
00436       OpalEndPoint & endpoint,                  
00437       const OpalTransportAddress & binding,     
00438       OpalTransportAddress::BindOptions option  
00439     );
00440 
00443     ~OpalListenerTCP();
00445 
00468     virtual PBoolean Open(
00469       const PNotifier & acceptHandler,  
00470       ThreadMode mode = SpawnNewThreadMode 
00471     );
00472 
00475     virtual PBoolean IsOpen();
00476 
00479     virtual void Close();
00480 
00483     virtual OpalTransport * Accept(
00484       const PTimeInterval & timeout  
00485     );
00486 
00489     virtual OpalTransport * CreateTransport(
00490       const OpalTransportAddress & localAddress,
00491       const OpalTransportAddress & remoteAddress
00492     ) const;
00494 
00495 
00496   protected:
00497     virtual const char * GetProtoPrefix() const;
00498 
00499     PTCPSocket listener;
00500 };
00501 
00502 
00503 class OpalListenerUDP : public OpalListenerIP
00504 {
00505   PCLASSINFO(OpalListenerUDP, OpalListenerIP);
00506   public:
00511     OpalListenerUDP(
00512       OpalEndPoint & endpoint,  
00513       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00514       WORD port = 0,            
00515       PBoolean exclusive = PTrue
00516     );
00517     OpalListenerUDP(
00518       OpalEndPoint & endpoint,                  
00519       const OpalTransportAddress & binding,     
00520       OpalTransportAddress::BindOptions option  
00521     );
00522 
00525     ~OpalListenerUDP();
00527 
00550     virtual PBoolean Open(
00551       const PNotifier & acceptHandler,  
00552       ThreadMode mode = SpawnNewThreadMode 
00553     );
00554 
00557     virtual PBoolean IsOpen();
00558 
00561     virtual void Close();
00562 
00565     virtual OpalTransport * Accept(
00566       const PTimeInterval & timeout  
00567     );
00568 
00571     virtual OpalTransport * CreateTransport(
00572       const OpalTransportAddress & localAddress,
00573       const OpalTransportAddress & remoteAddress
00574     ) const;
00575 
00581     virtual OpalTransportAddress GetLocalAddress(
00582       const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00583     ) const;
00585 
00586 
00587   protected:
00588     virtual const char * GetProtoPrefix() const;
00589 
00590     PMonitoredSocketsPtr listenerBundle;
00591 };
00592 
00593 
00595 
00600 class OpalTransport : public PIndirectChannel
00601 {
00602     PCLASSINFO(OpalTransport, PIndirectChannel);
00603   public:
00608     OpalTransport(OpalEndPoint & endpoint);
00609 
00612     ~OpalTransport();
00614 
00619     void PrintOn(
00620       ostream & strm
00621     ) const;
00623 
00628     virtual PBoolean IsReliable() const = 0;
00629 
00636     virtual PString GetInterface() const;
00637 
00644     virtual bool SetInterface(
00645       const PString & iface  
00646     );
00647 
00650     virtual OpalTransportAddress GetLocalAddress(
00651       bool allowNAT = true   
00652     ) const = 0;
00653 
00658     virtual PBoolean SetLocalAddress(
00659       const OpalTransportAddress & address
00660     ) = 0;
00661 
00664     virtual OpalTransportAddress GetRemoteAddress() const = 0;
00665 
00671     virtual PBoolean SetRemoteAddress(
00672       const OpalTransportAddress & address
00673     ) = 0;
00674 
00677     virtual PBoolean Connect() = 0;
00678 
00681     PBoolean ConnectTo(
00682       const OpalTransportAddress & address
00683     ) { return SetRemoteAddress(address) && Connect(); }
00684 
00687     virtual PBoolean Close();
00688 
00691     void CloseWait();
00692 
00696     void CleanUpOnTermination() { CloseWait(); }
00697 
00700     virtual PBoolean IsCompatibleTransport(
00701       const OpalTransportAddress & address
00702     ) const = 0;
00703 
00705     enum PromisciousModes {
00706       AcceptFromRemoteOnly,
00707       AcceptFromAnyAutoSet,
00708       AcceptFromAny,
00709       NumPromisciousModes
00710     };
00711 
00722     virtual void SetPromiscuous(
00723       PromisciousModes promiscuous
00724     );
00725 
00730     virtual OpalTransportAddress GetLastReceivedAddress() const;
00731 
00736     virtual PString GetLastReceivedInterface() const;
00737 
00743     virtual PBoolean ReadPDU(
00744       PBYTEArray & packet   
00745     ) = 0;
00746 
00752     virtual PBoolean WritePDU(
00753       const PBYTEArray & pdu     
00754     ) = 0;
00755 
00756     typedef PBoolean (*WriteConnectCallback)(OpalTransport & transport, void * userData);
00757 
00770     virtual PBoolean WriteConnect(
00771       WriteConnectCallback function,  
00772       void * userData                 
00773     );
00774 
00777     virtual void AttachThread(
00778       PThread * thread
00779     );
00780 
00783     virtual PBoolean IsRunning() const;
00785 
00786     OpalEndPoint & GetEndPoint() const { return endpoint; }
00787 
00790     virtual const char * GetProtoPrefix() const = 0;
00791 
00792     PMutex & GetWriteMutex() { return m_writeMutex; }
00793 
00794   protected:
00795     OpalEndPoint & endpoint;
00796     PThread      * thread;      
00797     PMutex         m_writeMutex;
00798 };
00799 
00800 
00801 class OpalTransportIP : public OpalTransport
00802 {
00803   PCLASSINFO(OpalTransportIP, OpalTransport);
00804   public:
00809     OpalTransportIP(
00810       OpalEndPoint & endpoint,    
00811       PIPSocket::Address binding, 
00812       WORD port                   
00813     );
00815 
00820     virtual OpalTransportAddress GetLocalAddress(
00821       bool allowNAT = true   
00822     ) const;
00823 
00828     virtual PBoolean SetLocalAddress(
00829       const OpalTransportAddress & address
00830     );
00831 
00834     virtual OpalTransportAddress GetRemoteAddress() const;
00835 
00841     virtual PBoolean SetRemoteAddress(
00842       const OpalTransportAddress & address
00843     );
00844 
00846 
00847   protected:
00850     virtual const char * GetProtoPrefix() const = 0;
00851 
00852     PIPSocket::Address localAddress;  
00853     WORD               localPort;
00854     PIPSocket::Address remoteAddress; 
00855     WORD               remotePort;
00856 };
00857 
00858 
00859 class OpalTransportTCP : public OpalTransportIP
00860 {
00861     PCLASSINFO(OpalTransportTCP, OpalTransportIP);
00862   public:
00867     OpalTransportTCP(
00868       OpalEndPoint & endpoint,    
00869       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00870       WORD port = 0,              
00871       PBoolean reuseAddr = PFalse      
00872     );
00873     OpalTransportTCP(
00874       OpalEndPoint & endpoint,    
00875       PTCPSocket * socket         
00876     );
00877 
00879     ~OpalTransportTCP();
00881 
00886     virtual PBoolean IsReliable() const;
00887 
00890     virtual PBoolean IsCompatibleTransport(
00891       const OpalTransportAddress & address
00892     ) const;
00893 
00896     virtual PBoolean Connect();
00897 
00903     virtual PBoolean ReadPDU(
00904       PBYTEArray & pdu  
00905     );
00906 
00912     virtual PBoolean WritePDU(
00913       const PBYTEArray & pdu     
00914     );
00916 
00917 
00918   protected:
00921     virtual const char * GetProtoPrefix() const;
00922 
00932     virtual PBoolean OnOpen();
00933 
00934 
00935     PBoolean reuseAddressFlag;
00936 };
00937 
00938 
00939 class OpalTransportUDP : public OpalTransportIP
00940 {
00941   PCLASSINFO(OpalTransportUDP, OpalTransportIP);
00942   public:
00947     OpalTransportUDP(
00948       OpalEndPoint & endpoint,    
00949       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00950       WORD port = 0,              
00951       bool reuseAddr = false,     
00952       bool preOpen = false        
00953     );
00954 
00957     OpalTransportUDP(
00958       OpalEndPoint & endpoint,              
00959       const PBYTEArray & preReadPacket,     
00960       const PMonitoredSocketsPtr & sockets, 
00961       const PString & iface,                
00962       PIPSocket::Address remoteAddress,     
00963       WORD remotePort                       
00964     );
00965 
00967     ~OpalTransportUDP();
00969 
00972     virtual PBoolean Read(
00973       void * buffer,
00974       PINDEX length
00975     );
00977 
00982     virtual PBoolean IsReliable() const;
00983 
00986     virtual PBoolean IsCompatibleTransport(
00987       const OpalTransportAddress & address
00988     ) const;
00989 
00997     virtual PBoolean Connect();
00998 
01001     virtual PString GetInterface() const;
01002 
01009     virtual bool SetInterface(
01010       const PString & iface  
01011     );
01012 
01015     virtual OpalTransportAddress GetLocalAddress(
01016       bool allowNAT = true   
01017     ) const;
01018 
01023     virtual PBoolean SetLocalAddress(
01024       const OpalTransportAddress & address
01025     );
01026 
01032     virtual PBoolean SetRemoteAddress(
01033       const OpalTransportAddress & address
01034     );
01035 
01047     virtual void SetPromiscuous(
01048       PromisciousModes promiscuous
01049     );
01050 
01055     virtual OpalTransportAddress GetLastReceivedAddress() const;
01056 
01061     virtual PString GetLastReceivedInterface() const;
01062 
01068     virtual PBoolean ReadPDU(
01069       PBYTEArray & packet   
01070     );
01071 
01077     virtual PBoolean WritePDU(
01078       const PBYTEArray & pdu     
01079     );
01080 
01091     virtual PBoolean WriteConnect(
01092       WriteConnectCallback function,  
01093       void * userData                 
01094     );
01096 
01097   protected:
01100     virtual const char * GetProtoPrefix() const;
01101 
01102     OpalManager & manager;
01103     PBYTEArray    preReadPacket;
01104 };
01105 
01106 
01108 
01109 class OpalInternalTransport : public PObject
01110 {
01111     PCLASSINFO(OpalInternalTransport, PObject);
01112   public:
01113     virtual PString GetHostName(
01114       const OpalTransportAddress & address
01115     ) const;
01116 
01117     virtual PBoolean GetIpAndPort(
01118       const OpalTransportAddress & address,
01119       PIPSocket::Address & ip,
01120       WORD & port
01121     ) const;
01122 
01123     virtual OpalListener * CreateListener(
01124       const OpalTransportAddress & address,
01125       OpalEndPoint & endpoint,
01126       OpalTransportAddress::BindOptions options
01127     ) const  = 0;
01128 
01129     virtual OpalTransport * CreateTransport(
01130       const OpalTransportAddress & address,
01131       OpalEndPoint & endpoint,
01132       OpalTransportAddress::BindOptions options
01133     ) const = 0;
01134 };
01135 
01136 
01138 
01139 class OpalInternalIPTransport : public OpalInternalTransport
01140 {
01141     PCLASSINFO(OpalInternalIPTransport, OpalInternalTransport);
01142   public:
01143     virtual PString GetHostName(
01144       const OpalTransportAddress & address
01145     ) const;
01146     virtual PBoolean GetIpAndPort(
01147       const OpalTransportAddress & address,
01148       PIPSocket::Address & ip,
01149       WORD & port
01150     ) const;
01151 
01152     static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
01153                                      OpalEndPoint & endpoint,
01154                                      OpalTransportAddress::BindOptions option,
01155                                      PIPSocket::Address & ip,
01156                                      WORD & port,
01157                                      PBoolean & reuseAddr);
01158 };
01159 
01160 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
01161 class OpalInternalIPTransportTemplate : public OpalInternalIPTransport
01162 {
01163   public:
01164     OpalListener * CreateListener(
01165       const OpalTransportAddress & address,
01166       OpalEndPoint & endpoint,
01167       OpalTransportAddress::BindOptions options
01168     ) const
01169     {
01170       return new ListenerType(endpoint, address, options);
01171     }
01172 
01173     OpalTransport * CreateTransport(
01174       const OpalTransportAddress & address,
01175       OpalEndPoint & endpoint,
01176       OpalTransportAddress::BindOptions options
01177     ) const
01178     {
01179       PIPSocket::Address ip;
01180       WORD port;
01181       PBoolean reuseAddr;
01182       if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
01183         if (options == AltTypeOption)
01184           return new AltTypeClass(endpoint, ip, 0, reuseAddr);
01185         else
01186           return new TransportType(endpoint, ip, 0, reuseAddr);
01187       }
01188       return NULL;
01189     }
01190 };
01191 
01192 typedef OpalInternalIPTransportTemplate<OpalListenerTCP, OpalTransportTCP, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPTransport;
01193 typedef OpalInternalIPTransportTemplate<OpalListenerUDP, OpalTransportUDP, OpalTransportAddress::Streamed, OpalTransportTCP> OpalInternalUDPTransport;
01194 
01195 #if OPAL_PTLIB_SSL
01196 
01197 class PSSLContext;
01198 
01199 class OpalListenerTCPS : public OpalListenerTCP
01200 {
01201   PCLASSINFO(OpalListenerTCPS, OpalListenerTCP);
01202   public:
01203     OpalListenerTCPS(
01204       OpalEndPoint & endpoint,                 
01205       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
01206       WORD port = 0,                           
01207       PBoolean exclusive = PTrue
01208     );
01209     OpalListenerTCPS(
01210       OpalEndPoint & endpoint,                  
01211       const OpalTransportAddress & binding,     
01212       OpalTransportAddress::BindOptions option  
01213     );
01214 
01217     ~OpalListenerTCPS();
01218 
01219     OpalTransport * Accept(const PTimeInterval & timeout);
01220     const char * GetProtoPrefix() const;
01221 
01222   protected:
01223     void Construct();
01224 
01225     PSSLContext * sslContext;
01226 };
01227 
01228 class OpalTransportTCPS : public OpalTransportTCP
01229 {
01230   PCLASSINFO(OpalTransportTCPS, OpalTransportTCP);
01231     public:
01232       OpalTransportTCPS(
01233         OpalEndPoint & endpoint,    
01234         PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
01235         WORD port = 0,              
01236         PBoolean reuseAddr = PFalse      
01237       );
01238       OpalTransportTCPS(
01239         OpalEndPoint & endpoint,    
01240         PTCPSocket * socket         
01241       );
01242 
01244       ~OpalTransportTCPS();
01245 
01246       PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
01247       PBoolean Connect();
01248       PBoolean OnOpen();
01249       const char * GetProtoPrefix() const;
01250 
01251     protected:
01252       PSSLContext * sslContext;
01253 };
01254 
01255 typedef OpalInternalIPTransportTemplate<OpalListenerTCPS, OpalTransportTCPS, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPSTransport;
01256 
01257 
01258 #endif // OPAL_PTLIB_SSL
01259 
01260 
01261 #endif  // OPAL_OPAL_TRANSPORT_H
01262 
01263 
01264