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_TRANSPORT_H
00037 #define __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 PString
00059 {
00060   PCLASSINFO(OpalTransportAddress, PString);
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 
00086     PBoolean IsEquivalent(
00087       const OpalTransportAddress & address
00088     ) const;
00089 
00092     PBoolean IsCompatible(
00093       const OpalTransportAddress & address
00094     ) const;
00095 
00099     PBoolean GetIpAddress(PIPSocket::Address & ip) const;
00100 
00104     PBoolean GetIpAndPort(PIPSocket::Address & ip, WORD & port) const;
00105 
00109     virtual PString GetHostName() const;
00110 
00111     enum BindOptions {
00112       NoBinding,
00113       HostOnly,
00114       FullTSAP,
00115       Streamed,
00116       Datagram,
00117       RouteInterface,
00118       NumBindOptions
00119     };
00120 
00152     OpalListener * CreateListener(
00153       OpalEndPoint & endpoint,   
00154       BindOptions option         
00155     ) const;
00156 
00184     virtual OpalTransport * CreateTransport(
00185       OpalEndPoint & endpoint,   
00186       BindOptions option = HostOnly 
00187     ) const;
00189 
00190 
00191   protected:
00192     void SetInternalTransport(
00193       WORD port,             
00194       const char * proto     
00195     );
00196 
00197     OpalInternalTransport * transport;
00198 };
00199 
00200 
00201 PDECLARE_ARRAY(OpalTransportAddressArray, OpalTransportAddress)
00202   public:
00203     OpalTransportAddressArray(
00204       const OpalTransportAddress & address
00205     ) { AppendAddress(address); }
00206     OpalTransportAddressArray(
00207       const PStringArray & array
00208     ) { AppendStringCollection(array); }
00209     OpalTransportAddressArray(
00210       const PStringList & list
00211     ) { AppendStringCollection(list); }
00212     OpalTransportAddressArray(
00213       const PSortedStringList & list
00214     ) { AppendStringCollection(list); }
00215 
00216     void AppendString(
00217       const char * address
00218     );
00219     void AppendString(
00220       const PString & address
00221     );
00222     void AppendAddress(
00223       const OpalTransportAddress & address
00224     );
00225 
00226   protected:
00227     void AppendStringCollection(
00228       const PCollection & coll
00229     );
00230 };
00231 
00232 
00233 
00234 
00236 
00249 class OpalListener : public PObject
00250 {
00251     PCLASSINFO(OpalListener, PObject);
00252   public:
00257     OpalListener(
00258       OpalEndPoint & endpoint   
00259     );
00261 
00266     void PrintOn(
00267       ostream & strm
00268     ) const;
00270 
00273     enum ThreadMode {
00274       SpawnNewThreadMode,
00275       HandOffThreadMode,
00276       SingleThreadMode
00277     };
00278 
00293     virtual PBoolean Open(
00294       const PNotifier & acceptHandler,  
00295       ThreadMode mode = SpawnNewThreadMode 
00296     ) = 0;
00297 
00300     virtual PBoolean IsOpen() = 0;
00301 
00304     virtual void Close() = 0;
00305 
00308     virtual OpalTransport * Accept(
00309       const PTimeInterval & timeout  
00310     ) = 0;
00311 
00314     virtual OpalTransport * CreateTransport(
00315       const OpalTransportAddress & localAddress,
00316       const OpalTransportAddress & remoteAddress
00317     ) const = 0;
00318 
00321     virtual OpalTransportAddress GetLocalAddress(
00322       const OpalTransportAddress & preferredAddress = OpalTransportAddress()
00323     ) const = 0;
00324 
00328     OpalTransportAddress GetTransportAddress() const { return GetLocalAddress(); }
00329 
00332     void CloseWait();
00333 
00337     void CleanUpOnTermination() { CloseWait(); }
00339 
00340 
00341   protected:
00350     PDECLARE_NOTIFIER(PThread, OpalListener, ListenForConnections);
00351     PBoolean StartThread(
00352       const PNotifier & acceptHandler,  
00353       ThreadMode mode                   
00354     );
00355 
00356     OpalEndPoint & endpoint;
00357     PThread      * thread;
00358     PNotifier      acceptHandler;
00359     ThreadMode     threadMode;
00360 };
00361 
00362 
00363 PLIST(OpalListenerList, OpalListener);
00364 
00365 
00368 OpalTransportAddressArray OpalGetInterfaceAddresses(
00369   const OpalListenerList & listeners, 
00370   PBoolean excludeLocalHost = PTrue,       
00371   OpalTransport * associatedTransport = NULL
00373 );
00374 
00375 OpalTransportAddressArray OpalGetInterfaceAddresses(
00376   const OpalTransportAddress & addr,  
00377   PBoolean excludeLocalHost = PTrue,       
00378   OpalTransport * associatedTransport = NULL
00380 );
00381 
00382 
00383 class OpalListenerIP : public OpalListener
00384 {
00385   PCLASSINFO(OpalListenerIP, OpalListener);
00386   public:
00391     OpalListenerIP(
00392       OpalEndPoint & endpoint,                 
00393       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00394       WORD port = 0,                           
00395       PBoolean exclusive = PTrue
00396     );
00397     OpalListenerIP(
00398       OpalEndPoint & endpoint,                  
00399       const OpalTransportAddress & binding,     
00400       OpalTransportAddress::BindOptions option  
00401     );
00403 
00408     virtual OpalTransportAddress GetLocalAddress(
00409       const OpalTransportAddress & preferredAddress = OpalTransportAddress()
00410     ) const;
00412 
00415     WORD GetListenerPort() const { return listenerPort; }
00416 
00417     virtual const char * GetProtoPrefix() const = 0;
00419 
00420 
00421   protected:
00422     PIPSocket::Address localAddress;
00423     WORD               listenerPort;
00424     PBoolean               exclusiveListener;
00425 };
00426 
00427 
00428 class OpalListenerTCP : public OpalListenerIP
00429 {
00430   PCLASSINFO(OpalListenerTCP, OpalListenerIP);
00431   public:
00436     OpalListenerTCP(
00437       OpalEndPoint & endpoint,                 
00438       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00439       WORD port = 0,                           
00440       PBoolean exclusive = PTrue
00441     );
00442     OpalListenerTCP(
00443       OpalEndPoint & endpoint,                  
00444       const OpalTransportAddress & binding,     
00445       OpalTransportAddress::BindOptions option  
00446     );
00447 
00450     ~OpalListenerTCP();
00452 
00475     virtual PBoolean Open(
00476       const PNotifier & acceptHandler,  
00477       ThreadMode mode = SpawnNewThreadMode 
00478     );
00479 
00482     virtual PBoolean IsOpen();
00483 
00486     virtual void Close();
00487 
00490     virtual OpalTransport * Accept(
00491       const PTimeInterval & timeout  
00492     );
00493 
00496     virtual OpalTransport * CreateTransport(
00497       const OpalTransportAddress & localAddress,
00498       const OpalTransportAddress & remoteAddress
00499     ) const;
00501 
00502 
00503   protected:
00504     virtual const char * GetProtoPrefix() const;
00505 
00506     PTCPSocket listener;
00507 };
00508 
00509 
00510 class OpalListenerUDP : public OpalListenerIP
00511 {
00512   PCLASSINFO(OpalListenerUDP, OpalListenerIP);
00513   public:
00518     OpalListenerUDP(
00519       OpalEndPoint & endpoint,  
00520       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00521       WORD port = 0,            
00522       PBoolean exclusive = PTrue
00523     );
00524     OpalListenerUDP(
00525       OpalEndPoint & endpoint,                  
00526       const OpalTransportAddress & binding,     
00527       OpalTransportAddress::BindOptions option  
00528     );
00529 
00532     ~OpalListenerUDP();
00534 
00557     virtual PBoolean Open(
00558       const PNotifier & acceptHandler,  
00559       ThreadMode mode = SpawnNewThreadMode 
00560     );
00561 
00564     virtual PBoolean IsOpen();
00565 
00568     virtual void Close();
00569 
00572     virtual OpalTransport * Accept(
00573       const PTimeInterval & timeout  
00574     );
00575 
00578     virtual OpalTransport * CreateTransport(
00579       const OpalTransportAddress & localAddress,
00580       const OpalTransportAddress & remoteAddress
00581     ) const;
00583 
00584 
00585   protected:
00586     virtual const char * GetProtoPrefix() const;
00587 
00588     PMonitoredSocketsPtr listenerBundle;
00589 };
00590 
00591 
00593 
00598 class OpalTransport : public PIndirectChannel
00599 {
00600     PCLASSINFO(OpalTransport, PIndirectChannel);
00601   public:
00606     OpalTransport(OpalEndPoint & endpoint);
00607 
00610     ~OpalTransport();
00612 
00617     void PrintOn(
00618       ostream & strm
00619     ) const;
00621 
00626     virtual PBoolean IsReliable() const = 0;
00627 
00634     virtual PString GetInterface() const;
00635 
00642     virtual bool SetInterface(
00643       const PString & iface  
00644     );
00645 
00648     virtual OpalTransportAddress GetLocalAddress() const = 0;
00649 
00654     virtual PBoolean SetLocalAddress(
00655       const OpalTransportAddress & address
00656     ) = 0;
00657 
00660     virtual OpalTransportAddress GetRemoteAddress() const = 0;
00661 
00667     virtual PBoolean SetRemoteAddress(
00668       const OpalTransportAddress & address
00669     ) = 0;
00670 
00673     virtual PBoolean Connect() = 0;
00674 
00677     PBoolean ConnectTo(
00678       const OpalTransportAddress & address
00679     ) { return SetRemoteAddress(address) && Connect(); }
00680 
00683     virtual PBoolean Close();
00684 
00687     void CloseWait();
00688 
00692     void CleanUpOnTermination() { CloseWait(); }
00693 
00696     virtual PBoolean IsCompatibleTransport(
00697       const OpalTransportAddress & address
00698     ) const = 0;
00699 
00701     enum PromisciousModes {
00702       AcceptFromRemoteOnly,
00703       AcceptFromAnyAutoSet,
00704       AcceptFromAny,
00705       NumPromisciousModes
00706     };
00707 
00718     virtual void SetPromiscuous(
00719       PromisciousModes promiscuous
00720     );
00721 
00726     virtual OpalTransportAddress GetLastReceivedAddress() const;
00727 
00732     virtual PString GetLastReceivedInterface() const;
00733 
00739     virtual PBoolean ReadPDU(
00740       PBYTEArray & packet   
00741     ) = 0;
00742 
00748     virtual PBoolean WritePDU(
00749       const PBYTEArray & pdu     
00750     ) = 0;
00751 
00752     typedef PBoolean (*WriteConnectCallback)(OpalTransport & transport, void * userData);
00753 
00766     virtual PBoolean WriteConnect(
00767       WriteConnectCallback function,  
00768       void * userData                 
00769     );
00770 
00773     virtual void AttachThread(
00774       PThread * thread
00775     );
00776 
00779     virtual PBoolean IsRunning() const;
00781 
00782     OpalEndPoint & GetEndPoint() const { return endpoint; }
00783 
00786     virtual const char * GetProtoPrefix() const = 0;
00787 
00788   protected:
00789     OpalEndPoint & endpoint;
00790     PThread      * thread;      
00791 };
00792 
00793 
00794 class OpalTransportIP : public OpalTransport
00795 {
00796   PCLASSINFO(OpalTransportIP, OpalTransport);
00797   public:
00802     OpalTransportIP(
00803       OpalEndPoint & endpoint,    
00804       PIPSocket::Address binding, 
00805       WORD port                   
00806     );
00808 
00813     virtual OpalTransportAddress GetLocalAddress() const;
00814 
00819     virtual PBoolean SetLocalAddress(
00820       const OpalTransportAddress & address
00821     );
00822 
00825     virtual OpalTransportAddress GetRemoteAddress() const;
00826 
00832     virtual PBoolean SetRemoteAddress(
00833       const OpalTransportAddress & address
00834     );
00835 
00837 
00838   protected:
00841     virtual const char * GetProtoPrefix() const = 0;
00842 
00843     PIPSocket::Address localAddress;  
00844     WORD               localPort;
00845     PIPSocket::Address remoteAddress; 
00846     WORD               remotePort;
00847 };
00848 
00849 
00850 class OpalTransportTCP : public OpalTransportIP
00851 {
00852     PCLASSINFO(OpalTransportTCP, OpalTransportIP);
00853   public:
00858     OpalTransportTCP(
00859       OpalEndPoint & endpoint,    
00860       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00861       WORD port = 0,              
00862       PBoolean reuseAddr = PFalse      
00863     );
00864     OpalTransportTCP(
00865       OpalEndPoint & endpoint,    
00866       PTCPSocket * socket         
00867     );
00868 
00870     ~OpalTransportTCP();
00872 
00877     virtual PBoolean IsReliable() const;
00878 
00881     virtual PBoolean IsCompatibleTransport(
00882       const OpalTransportAddress & address
00883     ) const;
00884 
00887     virtual PBoolean Connect();
00888 
00894     virtual PBoolean ReadPDU(
00895       PBYTEArray & pdu  
00896     );
00897 
00903     virtual PBoolean WritePDU(
00904       const PBYTEArray & pdu     
00905     );
00907 
00908 
00909   protected:
00912     virtual const char * GetProtoPrefix() const;
00913 
00923     virtual PBoolean OnOpen();
00924 
00925 
00926     PBoolean reuseAddressFlag;
00927 };
00928 
00929 
00930 class OpalTransportUDP : public OpalTransportIP
00931 {
00932   PCLASSINFO(OpalTransportUDP, OpalTransportIP);
00933   public:
00938     OpalTransportUDP(
00939       OpalEndPoint & endpoint,    
00940       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
00941       WORD port = 0,              
00942       PBoolean reuseAddr = PFalse      
00943     );
00944 
00947     OpalTransportUDP(
00948       OpalEndPoint & endpoint,              
00949       const PBYTEArray & preReadPacket,     
00950       const PMonitoredSocketsPtr & sockets, 
00951       const PString & iface,                
00952       PIPSocket::Address remoteAddress,     
00953       WORD remotePort                       
00954     );
00955 
00957     ~OpalTransportUDP();
00959 
00962     virtual PBoolean Read(
00963       void * buffer,
00964       PINDEX length
00965     );
00967 
00972     virtual PBoolean IsReliable() const;
00973 
00976     virtual PBoolean IsCompatibleTransport(
00977       const OpalTransportAddress & address
00978     ) const;
00979 
00987     virtual PBoolean Connect();
00988 
00991     virtual PString GetInterface() const;
00992 
00999     virtual bool SetInterface(
01000       const PString & iface  
01001     );
01002 
01005     virtual OpalTransportAddress GetLocalAddress() const;
01006 
01011     virtual PBoolean SetLocalAddress(
01012       const OpalTransportAddress & address
01013     );
01014 
01020     virtual PBoolean SetRemoteAddress(
01021       const OpalTransportAddress & address
01022     );
01023 
01035     virtual void SetPromiscuous(
01036       PromisciousModes promiscuous
01037     );
01038 
01043     virtual OpalTransportAddress GetLastReceivedAddress() const;
01044 
01049     virtual PString GetLastReceivedInterface() const;
01050 
01056     virtual PBoolean ReadPDU(
01057       PBYTEArray & packet   
01058     );
01059 
01065     virtual PBoolean WritePDU(
01066       const PBYTEArray & pdu     
01067     );
01068 
01079     virtual PBoolean WriteConnect(
01080       WriteConnectCallback function,  
01081       void * userData                 
01082     );
01084 
01085   protected:
01088     virtual const char * GetProtoPrefix() const;
01089 
01090     OpalManager & manager;
01091     PBYTEArray    preReadPacket;
01092 };
01093 
01094 
01096 
01097 class OpalInternalTransport : public PObject
01098 {
01099     PCLASSINFO(OpalInternalTransport, PObject);
01100   public:
01101     virtual PString GetHostName(
01102       const OpalTransportAddress & address
01103     ) const;
01104 
01105     virtual PBoolean GetIpAndPort(
01106       const OpalTransportAddress & address,
01107       PIPSocket::Address & ip,
01108       WORD & port
01109     ) const;
01110 
01111     virtual OpalListener * CreateListener(
01112       const OpalTransportAddress & address,
01113       OpalEndPoint & endpoint,
01114       OpalTransportAddress::BindOptions options
01115     ) const  = 0;
01116 
01117     virtual OpalTransport * CreateTransport(
01118       const OpalTransportAddress & address,
01119       OpalEndPoint & endpoint,
01120       OpalTransportAddress::BindOptions options
01121     ) const = 0;
01122 };
01123 
01124 
01126 
01127 class OpalInternalIPTransport : public OpalInternalTransport
01128 {
01129     PCLASSINFO(OpalInternalIPTransport, OpalInternalTransport);
01130   public:
01131     virtual PString GetHostName(
01132       const OpalTransportAddress & address
01133     ) const;
01134     virtual PBoolean GetIpAndPort(
01135       const OpalTransportAddress & address,
01136       PIPSocket::Address & ip,
01137       WORD & port
01138     ) const;
01139 
01140     static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
01141                                      OpalEndPoint & endpoint,
01142                                      OpalTransportAddress::BindOptions option,
01143                                      PIPSocket::Address & ip,
01144                                      WORD & port,
01145                                      PBoolean & reuseAddr);
01146 };
01147 
01148 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
01149 class OpalInternalIPTransportTemplate : public OpalInternalIPTransport
01150 {
01151   public:
01152     OpalListener * CreateListener(
01153       const OpalTransportAddress & address,
01154       OpalEndPoint & endpoint,
01155       OpalTransportAddress::BindOptions options
01156     ) const
01157     {
01158       return new ListenerType(endpoint, address, options);
01159     }
01160 
01161     OpalTransport * CreateTransport(
01162       const OpalTransportAddress & address,
01163       OpalEndPoint & endpoint,
01164       OpalTransportAddress::BindOptions options
01165     ) const
01166     {
01167       PIPSocket::Address ip;
01168       WORD port;
01169       PBoolean reuseAddr;
01170       if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
01171         if (options == AltTypeOption)
01172           return new AltTypeClass(endpoint, ip, 0, reuseAddr);
01173         else
01174           return new TransportType(endpoint, ip, 0, reuseAddr);
01175       }
01176       return NULL;
01177     }
01178 };
01179 
01180 typedef OpalInternalIPTransportTemplate<OpalListenerTCP, OpalTransportTCP, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPTransport;
01181 typedef OpalInternalIPTransportTemplate<OpalListenerUDP, OpalTransportUDP, OpalTransportAddress::Streamed, OpalTransportTCP> OpalInternalUDPTransport;
01182 
01183 #if P_SSL
01184 
01185 class PSSLContext;
01186 
01187 class OpalListenerTCPS : public OpalListenerTCP
01188 {
01189   PCLASSINFO(OpalListenerTCPS, OpalListenerTCP);
01190   public:
01191     OpalListenerTCPS(
01192       OpalEndPoint & endpoint,                 
01193       PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
01194       WORD port = 0,                           
01195       PBoolean exclusive = PTrue
01196     );
01197     OpalListenerTCPS(
01198       OpalEndPoint & endpoint,                  
01199       const OpalTransportAddress & binding,     
01200       OpalTransportAddress::BindOptions option  
01201     );
01202 
01205     ~OpalListenerTCPS();
01206 
01207     OpalTransport * Accept(const PTimeInterval & timeout);
01208     const char * GetProtoPrefix() const;
01209 
01210   protected:
01211     void Construct();
01212 
01213     PSSLContext * sslContext;
01214 };
01215 
01216 class OpalTransportTCPS : public OpalTransportTCP
01217 {
01218   PCLASSINFO(OpalTransportTCPS, OpalTransportTCP);
01219     public:
01220       OpalTransportTCPS(
01221         OpalEndPoint & endpoint,    
01222         PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(), 
01223         WORD port = 0,              
01224         PBoolean reuseAddr = PFalse      
01225       );
01226       OpalTransportTCPS(
01227         OpalEndPoint & endpoint,    
01228         PTCPSocket * socket         
01229       );
01230 
01232       ~OpalTransportTCPS();
01233 
01234       PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
01235       PBoolean Connect();
01236       PBoolean OnOpen();
01237       const char * GetProtoPrefix() const;
01238 
01239     protected:
01240       PSSLContext * sslContext;
01241 };
01242 
01243 typedef OpalInternalIPTransportTemplate<OpalListenerTCPS, OpalTransportTCPS, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPSTransport;
01244 
01245 
01246 #endif // P_SSL
01247 
01248 
01249 #endif  // __OPAL_TRANSPORT_H
01250 
01251 
01252