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