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
00149 class OpalTransportAddress : public PCaselessString
00150 {
00151 PCLASSINFO(OpalTransportAddress, PCaselessString);
00152 public:
00155 OpalTransportAddress();
00156 OpalTransportAddress(
00157 const char * address,
00158 WORD port = 0,
00159 const char * proto = NULL
00160 );
00161 OpalTransportAddress(
00162 const PString & address,
00163 WORD port = 0,
00164 const char * proto = NULL
00165 );
00166 OpalTransportAddress(
00167 const PIPSocket::Address & ip,
00168 WORD port,
00169 const char * proto = NULL
00170 );
00172
00180 PBoolean IsEquivalent(
00181 const OpalTransportAddress & address,
00182 bool wildcards = false
00183 ) const;
00184
00187 PBoolean IsCompatible(
00188 const OpalTransportAddress & address
00189 ) const;
00190
00193 PCaselessString GetProto(bool withDollar = false) const { return Left(Find('$')+(withDollar?1:0)); }
00194
00198 PBoolean GetIpAddress(PIPSocket::Address & ip) const;
00199
00203 PBoolean GetIpAndPort(PIPSocket::Address & ip, WORD & port) const;
00204 PBoolean GetIpAndPort(PIPSocketAddressAndPort & ipPort) const;
00205
00209 virtual PString GetHostName() const;
00210
00211 enum BindOptions {
00212 NoBinding,
00213 HostOnly,
00214 FullTSAP,
00215 Streamed,
00216 Datagram,
00217 RouteInterface,
00218 NumBindOptions
00219 };
00220
00252 OpalListener * CreateListener(
00253 OpalEndPoint & endpoint,
00254 BindOptions option
00255 ) const;
00256
00284 virtual OpalTransport * CreateTransport(
00285 OpalEndPoint & endpoint,
00286 BindOptions option = HostOnly
00287 ) const;
00289
00290
00291 protected:
00292 void SetInternalTransport(
00293 WORD port,
00294 const char * proto
00295 );
00296
00297 OpalInternalTransport * transport;
00298 };
00299
00300
00301 PDECLARE_ARRAY(OpalTransportAddressArray, OpalTransportAddress)
00302 public:
00303 OpalTransportAddressArray(
00304 const OpalTransportAddress & address
00305 ) { AppendAddress(address); }
00306 OpalTransportAddressArray(
00307 const PStringArray & array
00308 ) { AppendStringCollection(array); }
00309 OpalTransportAddressArray(
00310 const PStringList & list
00311 ) { AppendStringCollection(list); }
00312 OpalTransportAddressArray(
00313 const PSortedStringList & list
00314 ) { AppendStringCollection(list); }
00315
00316 void AppendString(
00317 const char * address
00318 );
00319 void AppendString(
00320 const PString & address
00321 );
00322 void AppendAddress(
00323 const OpalTransportAddress & address
00324 );
00325
00326 protected:
00327 void AppendStringCollection(
00328 const PCollection & coll
00329 );
00330 };
00331
00332
00333
00334
00336
00349 class OpalListener : public PObject
00350 {
00351 PCLASSINFO(OpalListener, PObject);
00352 public:
00357 OpalListener(
00358 OpalEndPoint & endpoint
00359 );
00361
00366 void PrintOn(
00367 ostream & strm
00368 ) const;
00370
00373 enum ThreadMode {
00374 SpawnNewThreadMode,
00375 HandOffThreadMode,
00376 SingleThreadMode
00377 };
00378
00393 virtual PBoolean Open(
00394 const PNotifier & acceptHandler,
00395 ThreadMode mode = SpawnNewThreadMode
00396 ) = 0;
00397
00400 virtual PBoolean IsOpen() = 0;
00401
00404 virtual void Close() = 0;
00405
00408 virtual OpalTransport * Accept(
00409 const PTimeInterval & timeout
00410 ) = 0;
00411
00414 virtual OpalTransport * CreateTransport(
00415 const OpalTransportAddress & localAddress,
00416 const OpalTransportAddress & remoteAddress
00417 ) const = 0;
00418
00424 virtual OpalTransportAddress GetLocalAddress(
00425 const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00426 ) const = 0;
00427
00430 void CloseWait();
00431
00435 void CleanUpOnTermination() { CloseWait(); }
00437
00438
00439 protected:
00448 PDECLARE_NOTIFIER(PThread, OpalListener, ListenForConnections);
00449 PBoolean StartThread(
00450 const PNotifier & acceptHandler,
00451 ThreadMode mode
00452 );
00453
00454 OpalEndPoint & endpoint;
00455 PThread * thread;
00456 PNotifier acceptHandler;
00457 ThreadMode threadMode;
00458 };
00459
00460
00461 PLIST(OpalListenerList, OpalListener);
00462
00463
00464 class OpalListenerIP : public OpalListener
00465 {
00466 PCLASSINFO(OpalListenerIP, OpalListener);
00467 public:
00472 OpalListenerIP(
00473 OpalEndPoint & endpoint,
00474 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00475 WORD port = 0,
00476 PBoolean exclusive = true
00477 );
00478 OpalListenerIP(
00479 OpalEndPoint & endpoint,
00480 const OpalTransportAddress & binding,
00481 OpalTransportAddress::BindOptions option
00482 );
00484
00492 virtual OpalTransportAddress GetLocalAddress(
00493 const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00494 ) const;
00496
00499 WORD GetListenerPort() const { return listenerPort; }
00500
00501 virtual const char * GetProtoPrefix() const = 0;
00503
00504
00505 protected:
00506 PIPSocket::Address localAddress;
00507 WORD listenerPort;
00508 PBoolean exclusiveListener;
00509 };
00510
00511
00512 class OpalListenerTCP : public OpalListenerIP
00513 {
00514 PCLASSINFO(OpalListenerTCP, OpalListenerIP);
00515 public:
00520 OpalListenerTCP(
00521 OpalEndPoint & endpoint,
00522 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00523 WORD port = 0,
00524 PBoolean exclusive = true
00525 );
00526 OpalListenerTCP(
00527 OpalEndPoint & endpoint,
00528 const OpalTransportAddress & binding,
00529 OpalTransportAddress::BindOptions option
00530 );
00531
00534 ~OpalListenerTCP();
00536
00559 virtual PBoolean Open(
00560 const PNotifier & acceptHandler,
00561 ThreadMode mode = SpawnNewThreadMode
00562 );
00563
00566 virtual PBoolean IsOpen();
00567
00570 virtual void Close();
00571
00574 virtual OpalTransport * Accept(
00575 const PTimeInterval & timeout
00576 );
00577
00580 virtual OpalTransport * CreateTransport(
00581 const OpalTransportAddress & localAddress,
00582 const OpalTransportAddress & remoteAddress
00583 ) const;
00585
00586
00587 protected:
00588 virtual const char * GetProtoPrefix() const;
00589
00590 PTCPSocket listener;
00591 };
00592
00593
00594 class OpalListenerUDP : public OpalListenerIP
00595 {
00596 PCLASSINFO(OpalListenerUDP, OpalListenerIP);
00597 public:
00602 OpalListenerUDP(
00603 OpalEndPoint & endpoint,
00604 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00605 WORD port = 0,
00606 PBoolean exclusive = true
00607 );
00608 OpalListenerUDP(
00609 OpalEndPoint & endpoint,
00610 const OpalTransportAddress & binding,
00611 OpalTransportAddress::BindOptions option
00612 );
00613
00616 ~OpalListenerUDP();
00618
00641 virtual PBoolean Open(
00642 const PNotifier & acceptHandler,
00643 ThreadMode mode = SpawnNewThreadMode
00644 );
00645
00648 virtual PBoolean IsOpen();
00649
00652 virtual void Close();
00653
00656 virtual OpalTransport * Accept(
00657 const PTimeInterval & timeout
00658 );
00659
00662 virtual OpalTransport * CreateTransport(
00663 const OpalTransportAddress & localAddress,
00664 const OpalTransportAddress & remoteAddress
00665 ) const;
00666
00672 virtual OpalTransportAddress GetLocalAddress(
00673 const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00674 ) const;
00676
00681 void SetBufferSize(
00682 PINDEX size
00683 ) { m_bufferSize = size; }
00685
00686
00687 protected:
00688 virtual const char * GetProtoPrefix() const;
00689
00690 PMonitoredSocketsPtr listenerBundle;
00691 PINDEX m_bufferSize;
00692 };
00693
00694
00696
00701 class OpalTransport : public PIndirectChannel
00702 {
00703 PCLASSINFO(OpalTransport, PIndirectChannel);
00704 public:
00709 OpalTransport(OpalEndPoint & endpoint);
00710
00713 ~OpalTransport();
00715
00720 void PrintOn(
00721 ostream & strm
00722 ) const;
00724
00729 virtual PBoolean IsReliable() const = 0;
00730
00737 virtual PString GetInterface() const;
00738
00745 virtual bool SetInterface(
00746 const PString & iface
00747 );
00748
00751 virtual OpalTransportAddress GetLocalAddress(
00752 bool allowNAT = true
00753 ) const = 0;
00754
00759 virtual PBoolean SetLocalAddress(
00760 const OpalTransportAddress & address
00761 ) = 0;
00762
00765 virtual OpalTransportAddress GetRemoteAddress() const = 0;
00766
00772 virtual PBoolean SetRemoteAddress(
00773 const OpalTransportAddress & address
00774 ) = 0;
00775
00778 virtual PBoolean Connect() = 0;
00779
00782 PBoolean ConnectTo(
00783 const OpalTransportAddress & address
00784 ) { return SetRemoteAddress(address) && Connect(); }
00785
00788 virtual PBoolean Close();
00789
00792 void CloseWait();
00793
00797 void CleanUpOnTermination() { CloseWait(); }
00798
00801 virtual PBoolean IsCompatibleTransport(
00802 const OpalTransportAddress & address
00803 ) const = 0;
00804
00806 enum PromisciousModes {
00807 AcceptFromRemoteOnly,
00808 AcceptFromAnyAutoSet,
00809 AcceptFromAny,
00810 NumPromisciousModes
00811 };
00812
00823 virtual void SetPromiscuous(
00824 PromisciousModes promiscuous
00825 );
00826
00831 virtual OpalTransportAddress GetLastReceivedAddress() const;
00832
00837 virtual PString GetLastReceivedInterface() const;
00838
00848 virtual PBoolean ReadPDU(
00849 PBYTEArray & packet
00850 ) = 0;
00851
00857 virtual PBoolean WritePDU(
00858 const PBYTEArray & pdu
00859 ) = 0;
00860
00861 typedef PBoolean (*WriteConnectCallback)(OpalTransport & transport, void * userData);
00862
00875 virtual PBoolean WriteConnect(
00876 WriteConnectCallback function,
00877 void * userData
00878 );
00879
00882 virtual void AttachThread(
00883 PThread * thread
00884 );
00885
00888 virtual PBoolean IsRunning() const;
00890
00891 OpalEndPoint & GetEndPoint() const { return endpoint; }
00892
00895 virtual const char * GetProtoPrefix() const = 0;
00896
00897 PMutex & GetWriteMutex() { return m_writeMutex; }
00898
00899 protected:
00900 OpalEndPoint & endpoint;
00901 PThread * thread;
00902 PMutex m_writeMutex;
00903 };
00904
00905
00906 class OpalTransportIP : public OpalTransport
00907 {
00908 PCLASSINFO(OpalTransportIP, OpalTransport);
00909 public:
00914 OpalTransportIP(
00915 OpalEndPoint & endpoint,
00916 PIPSocket::Address binding,
00917 WORD port
00918 );
00920
00925 virtual OpalTransportAddress GetLocalAddress(
00926 bool allowNAT = true
00927 ) const;
00928
00933 virtual PBoolean SetLocalAddress(
00934 const OpalTransportAddress & address
00935 );
00936
00939 virtual OpalTransportAddress GetRemoteAddress() const;
00940
00946 virtual PBoolean SetRemoteAddress(
00947 const OpalTransportAddress & address
00948 );
00949
00951
00952 protected:
00955 virtual const char * GetProtoPrefix() const = 0;
00956
00957 PIPSocket::Address localAddress;
00958 WORD localPort;
00959 PIPSocket::Address remoteAddress;
00960 WORD remotePort;
00961 };
00962
00963
00964 class OpalTransportTCP : public OpalTransportIP
00965 {
00966 PCLASSINFO(OpalTransportTCP, OpalTransportIP);
00967 public:
00972 OpalTransportTCP(
00973 OpalEndPoint & endpoint,
00974 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00975 WORD port = 0,
00976 PBoolean reuseAddr = false
00977 );
00978 OpalTransportTCP(
00979 OpalEndPoint & endpoint,
00980 PTCPSocket * socket
00981 );
00982
00984 ~OpalTransportTCP();
00986
00991 virtual PBoolean IsReliable() const;
00992
00995 virtual PBoolean IsCompatibleTransport(
00996 const OpalTransportAddress & address
00997 ) const;
00998
01001 virtual PBoolean Connect();
01002
01012 virtual PBoolean ReadPDU(
01013 PBYTEArray & pdu
01014 );
01015
01021 virtual PBoolean WritePDU(
01022 const PBYTEArray & pdu
01023 );
01025
01026
01027 protected:
01030 virtual const char * GetProtoPrefix() const;
01031
01041 virtual PBoolean OnOpen();
01042
01043
01044 PBoolean reuseAddressFlag;
01045 };
01046
01047
01048 class OpalTransportUDP : public OpalTransportIP
01049 {
01050 PCLASSINFO(OpalTransportUDP, OpalTransportIP);
01051 public:
01056 OpalTransportUDP(
01057 OpalEndPoint & endpoint,
01058 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01059 WORD port = 0,
01060 bool reuseAddr = false,
01061 bool preOpen = false
01062 );
01063
01066 OpalTransportUDP(
01067 OpalEndPoint & endpoint,
01068 const PMonitoredSocketsPtr & sockets,
01069 const PString & iface
01070 );
01071
01073 ~OpalTransportUDP();
01075
01078 virtual PBoolean Read(
01079 void * buffer,
01080 PINDEX length
01081 );
01083
01088 virtual PBoolean IsReliable() const;
01089
01092 virtual PBoolean IsCompatibleTransport(
01093 const OpalTransportAddress & address
01094 ) const;
01095
01103 virtual PBoolean Connect();
01104
01107 virtual PString GetInterface() const;
01108
01115 virtual bool SetInterface(
01116 const PString & iface
01117 );
01118
01121 virtual OpalTransportAddress GetLocalAddress(
01122 bool allowNAT = true
01123 ) const;
01124
01129 virtual PBoolean SetLocalAddress(
01130 const OpalTransportAddress & address
01131 );
01132
01138 virtual PBoolean SetRemoteAddress(
01139 const OpalTransportAddress & address
01140 );
01141
01153 virtual void SetPromiscuous(
01154 PromisciousModes promiscuous
01155 );
01156
01161 virtual OpalTransportAddress GetLastReceivedAddress() const;
01162
01167 virtual PString GetLastReceivedInterface() const;
01168
01178 virtual PBoolean ReadPDU(
01179 PBYTEArray & packet
01180 );
01181
01187 virtual PBoolean WritePDU(
01188 const PBYTEArray & pdu
01189 );
01190
01201 virtual PBoolean WriteConnect(
01202 WriteConnectCallback function,
01203 void * userData
01204 );
01205
01208 void SetBufferSize(
01209 PINDEX size
01210 ) { m_bufferSize = size; }
01212
01213 protected:
01216 virtual const char * GetProtoPrefix() const;
01217
01218 OpalManager & manager;
01219 PINDEX m_bufferSize;
01220 PBYTEArray m_preReadPacket;
01221 bool m_preReadOK;
01222
01223 friend class OpalListenerUDP;
01224 };
01225
01226
01228
01229 class OpalInternalTransport : public PObject
01230 {
01231 PCLASSINFO(OpalInternalTransport, PObject);
01232 public:
01233 virtual PString GetHostName(
01234 const OpalTransportAddress & address
01235 ) const;
01236
01237 virtual PBoolean GetIpAndPort(
01238 const OpalTransportAddress & address,
01239 PIPSocket::Address & ip,
01240 WORD & port
01241 ) const;
01242
01243 virtual OpalListener * CreateListener(
01244 const OpalTransportAddress & address,
01245 OpalEndPoint & endpoint,
01246 OpalTransportAddress::BindOptions options
01247 ) const = 0;
01248
01249 virtual OpalTransport * CreateTransport(
01250 const OpalTransportAddress & address,
01251 OpalEndPoint & endpoint,
01252 OpalTransportAddress::BindOptions options
01253 ) const = 0;
01254 };
01255
01256
01258
01259 class OpalInternalIPTransport : public OpalInternalTransport
01260 {
01261 PCLASSINFO(OpalInternalIPTransport, OpalInternalTransport);
01262 public:
01263 virtual PString GetHostName(
01264 const OpalTransportAddress & address
01265 ) const;
01266 virtual PBoolean GetIpAndPort(
01267 const OpalTransportAddress & address,
01268 PIPSocket::Address & ip,
01269 WORD & port
01270 ) const;
01271
01272 static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
01273 OpalEndPoint & endpoint,
01274 OpalTransportAddress::BindOptions option,
01275 PIPSocket::Address & ip,
01276 WORD & port,
01277 PBoolean & reuseAddr);
01278 };
01279
01280 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
01281 class OpalInternalIPTransportTemplate : public OpalInternalIPTransport
01282 {
01283 public:
01284 OpalListener * CreateListener(
01285 const OpalTransportAddress & address,
01286 OpalEndPoint & endpoint,
01287 OpalTransportAddress::BindOptions options
01288 ) const
01289 {
01290 return new ListenerType(endpoint, address, options);
01291 }
01292
01293 OpalTransport * CreateTransport(
01294 const OpalTransportAddress & address,
01295 OpalEndPoint & endpoint,
01296 OpalTransportAddress::BindOptions options
01297 ) const
01298 {
01299 PIPSocket::Address ip;
01300 WORD port;
01301 PBoolean reuseAddr;
01302 if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
01303 if (options == AltTypeOption)
01304 return new AltTypeClass(endpoint, ip, 0, reuseAddr);
01305 else
01306 return new TransportType(endpoint, ip, 0, reuseAddr);
01307 }
01308 return NULL;
01309 }
01310 };
01311
01312 typedef OpalInternalIPTransportTemplate<OpalListenerTCP, OpalTransportTCP, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPTransport;
01313 typedef OpalInternalIPTransportTemplate<OpalListenerUDP, OpalTransportUDP, OpalTransportAddress::Streamed, OpalTransportTCP> OpalInternalUDPTransport;
01314
01315 #if OPAL_PTLIB_SSL
01316
01317 class PSSLContext;
01318
01319 class OpalListenerTCPS : public OpalListenerTCP
01320 {
01321 PCLASSINFO(OpalListenerTCPS, OpalListenerTCP);
01322 public:
01323 OpalListenerTCPS(
01324 OpalEndPoint & endpoint,
01325 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01326 WORD port = 0,
01327 PBoolean exclusive = true
01328 );
01329 OpalListenerTCPS(
01330 OpalEndPoint & endpoint,
01331 const OpalTransportAddress & binding,
01332 OpalTransportAddress::BindOptions option
01333 );
01334
01337 ~OpalListenerTCPS();
01338
01339 OpalTransport * Accept(const PTimeInterval & timeout);
01340 const char * GetProtoPrefix() const;
01341
01342 protected:
01343 void Construct();
01344
01345 PSSLContext * sslContext;
01346 };
01347
01348 class OpalTransportTCPS : public OpalTransportTCP
01349 {
01350 PCLASSINFO(OpalTransportTCPS, OpalTransportTCP);
01351 public:
01352 OpalTransportTCPS(
01353 OpalEndPoint & endpoint,
01354 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01355 WORD port = 0,
01356 PBoolean reuseAddr = false
01357 );
01358 OpalTransportTCPS(
01359 OpalEndPoint & endpoint,
01360 PTCPSocket * socket
01361 );
01362
01364 ~OpalTransportTCPS();
01365
01366 PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
01367 PBoolean Connect();
01368 PBoolean OnOpen();
01369 const char * GetProtoPrefix() const;
01370
01371 protected:
01372 PSSLContext * sslContext;
01373 };
01374
01375 typedef OpalInternalIPTransportTemplate<OpalListenerTCPS, OpalTransportTCPS, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPSTransport;
01376
01377
01378 #endif // OPAL_PTLIB_SSL
01379
01380
01381 #endif // OPAL_OPAL_TRANSPORT_H
01382
01383
01384