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 = true
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 = true
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 = true
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
00590 void SetBufferSize(
00591 PINDEX size
00592 ) { m_bufferSize = size; }
00594
00595
00596 protected:
00597 virtual const char * GetProtoPrefix() const;
00598
00599 PMonitoredSocketsPtr listenerBundle;
00600 PINDEX m_bufferSize;
00601 };
00602
00603
00605
00610 class OpalTransport : public PIndirectChannel
00611 {
00612 PCLASSINFO(OpalTransport, PIndirectChannel);
00613 public:
00618 OpalTransport(OpalEndPoint & endpoint);
00619
00622 ~OpalTransport();
00624
00629 void PrintOn(
00630 ostream & strm
00631 ) const;
00633
00638 virtual PBoolean IsReliable() const = 0;
00639
00646 virtual PString GetInterface() const;
00647
00654 virtual bool SetInterface(
00655 const PString & iface
00656 );
00657
00660 virtual OpalTransportAddress GetLocalAddress(
00661 bool allowNAT = true
00662 ) const = 0;
00663
00668 virtual PBoolean SetLocalAddress(
00669 const OpalTransportAddress & address
00670 ) = 0;
00671
00674 virtual OpalTransportAddress GetRemoteAddress() const = 0;
00675
00681 virtual PBoolean SetRemoteAddress(
00682 const OpalTransportAddress & address
00683 ) = 0;
00684
00687 virtual PBoolean Connect() = 0;
00688
00691 PBoolean ConnectTo(
00692 const OpalTransportAddress & address
00693 ) { return SetRemoteAddress(address) && Connect(); }
00694
00697 virtual PBoolean Close();
00698
00701 void CloseWait();
00702
00706 void CleanUpOnTermination() { CloseWait(); }
00707
00710 virtual PBoolean IsCompatibleTransport(
00711 const OpalTransportAddress & address
00712 ) const = 0;
00713
00715 enum PromisciousModes {
00716 AcceptFromRemoteOnly,
00717 AcceptFromAnyAutoSet,
00718 AcceptFromAny,
00719 NumPromisciousModes
00720 };
00721
00732 virtual void SetPromiscuous(
00733 PromisciousModes promiscuous
00734 );
00735
00740 virtual OpalTransportAddress GetLastReceivedAddress() const;
00741
00746 virtual PString GetLastReceivedInterface() const;
00747
00757 virtual PBoolean ReadPDU(
00758 PBYTEArray & packet
00759 ) = 0;
00760
00766 virtual PBoolean WritePDU(
00767 const PBYTEArray & pdu
00768 ) = 0;
00769
00770 typedef PBoolean (*WriteConnectCallback)(OpalTransport & transport, void * userData);
00771
00784 virtual PBoolean WriteConnect(
00785 WriteConnectCallback function,
00786 void * userData
00787 );
00788
00791 virtual void AttachThread(
00792 PThread * thread
00793 );
00794
00797 virtual PBoolean IsRunning() const;
00799
00800 OpalEndPoint & GetEndPoint() const { return endpoint; }
00801
00804 virtual const char * GetProtoPrefix() const = 0;
00805
00806 PMutex & GetWriteMutex() { return m_writeMutex; }
00807
00808 protected:
00809 OpalEndPoint & endpoint;
00810 PThread * thread;
00811 PMutex m_writeMutex;
00812 };
00813
00814
00815 class OpalTransportIP : public OpalTransport
00816 {
00817 PCLASSINFO(OpalTransportIP, OpalTransport);
00818 public:
00823 OpalTransportIP(
00824 OpalEndPoint & endpoint,
00825 PIPSocket::Address binding,
00826 WORD port
00827 );
00829
00834 virtual OpalTransportAddress GetLocalAddress(
00835 bool allowNAT = true
00836 ) const;
00837
00842 virtual PBoolean SetLocalAddress(
00843 const OpalTransportAddress & address
00844 );
00845
00848 virtual OpalTransportAddress GetRemoteAddress() const;
00849
00855 virtual PBoolean SetRemoteAddress(
00856 const OpalTransportAddress & address
00857 );
00858
00860
00861 protected:
00864 virtual const char * GetProtoPrefix() const = 0;
00865
00866 PIPSocket::Address localAddress;
00867 WORD localPort;
00868 PIPSocket::Address remoteAddress;
00869 WORD remotePort;
00870 };
00871
00872
00873 class OpalTransportTCP : public OpalTransportIP
00874 {
00875 PCLASSINFO(OpalTransportTCP, OpalTransportIP);
00876 public:
00881 OpalTransportTCP(
00882 OpalEndPoint & endpoint,
00883 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00884 WORD port = 0,
00885 PBoolean reuseAddr = false
00886 );
00887 OpalTransportTCP(
00888 OpalEndPoint & endpoint,
00889 PTCPSocket * socket
00890 );
00891
00893 ~OpalTransportTCP();
00895
00900 virtual PBoolean IsReliable() const;
00901
00904 virtual PBoolean IsCompatibleTransport(
00905 const OpalTransportAddress & address
00906 ) const;
00907
00910 virtual PBoolean Connect();
00911
00921 virtual PBoolean ReadPDU(
00922 PBYTEArray & pdu
00923 );
00924
00930 virtual PBoolean WritePDU(
00931 const PBYTEArray & pdu
00932 );
00934
00935
00936 protected:
00939 virtual const char * GetProtoPrefix() const;
00940
00950 virtual PBoolean OnOpen();
00951
00952
00953 PBoolean reuseAddressFlag;
00954 };
00955
00956
00957 class OpalTransportUDP : public OpalTransportIP
00958 {
00959 PCLASSINFO(OpalTransportUDP, OpalTransportIP);
00960 public:
00965 OpalTransportUDP(
00966 OpalEndPoint & endpoint,
00967 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00968 WORD port = 0,
00969 bool reuseAddr = false,
00970 bool preOpen = false
00971 );
00972
00975 OpalTransportUDP(
00976 OpalEndPoint & endpoint,
00977 const PMonitoredSocketsPtr & sockets,
00978 const PString & iface
00979 );
00980
00982 ~OpalTransportUDP();
00984
00987 virtual PBoolean Read(
00988 void * buffer,
00989 PINDEX length
00990 );
00992
00997 virtual PBoolean IsReliable() const;
00998
01001 virtual PBoolean IsCompatibleTransport(
01002 const OpalTransportAddress & address
01003 ) const;
01004
01012 virtual PBoolean Connect();
01013
01016 virtual PString GetInterface() const;
01017
01024 virtual bool SetInterface(
01025 const PString & iface
01026 );
01027
01030 virtual OpalTransportAddress GetLocalAddress(
01031 bool allowNAT = true
01032 ) const;
01033
01038 virtual PBoolean SetLocalAddress(
01039 const OpalTransportAddress & address
01040 );
01041
01047 virtual PBoolean SetRemoteAddress(
01048 const OpalTransportAddress & address
01049 );
01050
01062 virtual void SetPromiscuous(
01063 PromisciousModes promiscuous
01064 );
01065
01070 virtual OpalTransportAddress GetLastReceivedAddress() const;
01071
01076 virtual PString GetLastReceivedInterface() const;
01077
01087 virtual PBoolean ReadPDU(
01088 PBYTEArray & packet
01089 );
01090
01096 virtual PBoolean WritePDU(
01097 const PBYTEArray & pdu
01098 );
01099
01110 virtual PBoolean WriteConnect(
01111 WriteConnectCallback function,
01112 void * userData
01113 );
01114
01117 void SetBufferSize(
01118 PINDEX size
01119 ) { m_bufferSize = size; }
01121
01122 protected:
01125 virtual const char * GetProtoPrefix() const;
01126
01127 OpalManager & manager;
01128 PINDEX m_bufferSize;
01129 PBYTEArray m_preReadPacket;
01130 bool m_preReadOK;
01131
01132 friend class OpalListenerUDP;
01133 };
01134
01135
01137
01138 class OpalInternalTransport : public PObject
01139 {
01140 PCLASSINFO(OpalInternalTransport, PObject);
01141 public:
01142 virtual PString GetHostName(
01143 const OpalTransportAddress & address
01144 ) const;
01145
01146 virtual PBoolean GetIpAndPort(
01147 const OpalTransportAddress & address,
01148 PIPSocket::Address & ip,
01149 WORD & port
01150 ) const;
01151
01152 virtual OpalListener * CreateListener(
01153 const OpalTransportAddress & address,
01154 OpalEndPoint & endpoint,
01155 OpalTransportAddress::BindOptions options
01156 ) const = 0;
01157
01158 virtual OpalTransport * CreateTransport(
01159 const OpalTransportAddress & address,
01160 OpalEndPoint & endpoint,
01161 OpalTransportAddress::BindOptions options
01162 ) const = 0;
01163 };
01164
01165
01167
01168 class OpalInternalIPTransport : public OpalInternalTransport
01169 {
01170 PCLASSINFO(OpalInternalIPTransport, OpalInternalTransport);
01171 public:
01172 virtual PString GetHostName(
01173 const OpalTransportAddress & address
01174 ) const;
01175 virtual PBoolean GetIpAndPort(
01176 const OpalTransportAddress & address,
01177 PIPSocket::Address & ip,
01178 WORD & port
01179 ) const;
01180
01181 static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
01182 OpalEndPoint & endpoint,
01183 OpalTransportAddress::BindOptions option,
01184 PIPSocket::Address & ip,
01185 WORD & port,
01186 PBoolean & reuseAddr);
01187 };
01188
01189 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
01190 class OpalInternalIPTransportTemplate : public OpalInternalIPTransport
01191 {
01192 public:
01193 OpalListener * CreateListener(
01194 const OpalTransportAddress & address,
01195 OpalEndPoint & endpoint,
01196 OpalTransportAddress::BindOptions options
01197 ) const
01198 {
01199 return new ListenerType(endpoint, address, options);
01200 }
01201
01202 OpalTransport * CreateTransport(
01203 const OpalTransportAddress & address,
01204 OpalEndPoint & endpoint,
01205 OpalTransportAddress::BindOptions options
01206 ) const
01207 {
01208 PIPSocket::Address ip;
01209 WORD port;
01210 PBoolean reuseAddr;
01211 if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
01212 if (options == AltTypeOption)
01213 return new AltTypeClass(endpoint, ip, 0, reuseAddr);
01214 else
01215 return new TransportType(endpoint, ip, 0, reuseAddr);
01216 }
01217 return NULL;
01218 }
01219 };
01220
01221 typedef OpalInternalIPTransportTemplate<OpalListenerTCP, OpalTransportTCP, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPTransport;
01222 typedef OpalInternalIPTransportTemplate<OpalListenerUDP, OpalTransportUDP, OpalTransportAddress::Streamed, OpalTransportTCP> OpalInternalUDPTransport;
01223
01224 #if OPAL_PTLIB_SSL
01225
01226 class PSSLContext;
01227
01228 class OpalListenerTCPS : public OpalListenerTCP
01229 {
01230 PCLASSINFO(OpalListenerTCPS, OpalListenerTCP);
01231 public:
01232 OpalListenerTCPS(
01233 OpalEndPoint & endpoint,
01234 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01235 WORD port = 0,
01236 PBoolean exclusive = true
01237 );
01238 OpalListenerTCPS(
01239 OpalEndPoint & endpoint,
01240 const OpalTransportAddress & binding,
01241 OpalTransportAddress::BindOptions option
01242 );
01243
01246 ~OpalListenerTCPS();
01247
01248 OpalTransport * Accept(const PTimeInterval & timeout);
01249 const char * GetProtoPrefix() const;
01250
01251 protected:
01252 void Construct();
01253
01254 PSSLContext * sslContext;
01255 };
01256
01257 class OpalTransportTCPS : public OpalTransportTCP
01258 {
01259 PCLASSINFO(OpalTransportTCPS, OpalTransportTCP);
01260 public:
01261 OpalTransportTCPS(
01262 OpalEndPoint & endpoint,
01263 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01264 WORD port = 0,
01265 PBoolean reuseAddr = false
01266 );
01267 OpalTransportTCPS(
01268 OpalEndPoint & endpoint,
01269 PTCPSocket * socket
01270 );
01271
01273 ~OpalTransportTCPS();
01274
01275 PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
01276 PBoolean Connect();
01277 PBoolean OnOpen();
01278 const char * GetProtoPrefix() const;
01279
01280 protected:
01281 PSSLContext * sslContext;
01282 };
01283
01284 typedef OpalInternalIPTransportTemplate<OpalListenerTCPS, OpalTransportTCPS, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPSTransport;
01285
01286
01287 #endif // OPAL_PTLIB_SSL
01288
01289
01290 #endif // OPAL_OPAL_TRANSPORT_H
01291
01292
01293