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