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(
00210 bool includeService = false
00211 ) const;
00212
00213 enum BindOptions {
00214 NoBinding,
00215 HostOnly,
00216 FullTSAP,
00217 Streamed,
00218 Datagram,
00219 RouteInterface,
00220 NumBindOptions
00221 };
00222
00254 OpalListener * CreateListener(
00255 OpalEndPoint & endpoint,
00256 BindOptions option
00257 ) const;
00258
00286 virtual OpalTransport * CreateTransport(
00287 OpalEndPoint & endpoint,
00288 BindOptions option = HostOnly
00289 ) const;
00291
00292
00293 protected:
00294 void SetInternalTransport(
00295 WORD port,
00296 const char * proto
00297 );
00298
00299 OpalInternalTransport * transport;
00300 };
00301
00302
00303 PDECLARE_ARRAY(OpalTransportAddressArray, OpalTransportAddress)
00304 public:
00305 OpalTransportAddressArray(
00306 const OpalTransportAddress & address
00307 ) { AppendAddress(address); }
00308 OpalTransportAddressArray(
00309 const PStringArray & array
00310 ) { AppendStringCollection(array); }
00311 OpalTransportAddressArray(
00312 const PStringList & list
00313 ) { AppendStringCollection(list); }
00314 OpalTransportAddressArray(
00315 const PSortedStringList & list
00316 ) { AppendStringCollection(list); }
00317
00318 void AppendString(
00319 const char * address
00320 );
00321 void AppendString(
00322 const PString & address
00323 );
00324 void AppendAddress(
00325 const OpalTransportAddress & address
00326 );
00327
00328 protected:
00329 void AppendStringCollection(
00330 const PCollection & coll
00331 );
00332 };
00333
00334
00335
00336
00338
00351 class OpalListener : public PObject
00352 {
00353 PCLASSINFO(OpalListener, PObject);
00354 public:
00359 OpalListener(
00360 OpalEndPoint & endpoint
00361 );
00363
00368 void PrintOn(
00369 ostream & strm
00370 ) const;
00372
00375 enum ThreadMode {
00376 SpawnNewThreadMode,
00377 HandOffThreadMode,
00378 SingleThreadMode
00379 };
00380
00395 virtual PBoolean Open(
00396 const PNotifier & acceptHandler,
00397 ThreadMode mode = SpawnNewThreadMode
00398 ) = 0;
00399
00402 virtual PBoolean IsOpen() = 0;
00403
00406 virtual void Close() = 0;
00407
00410 virtual OpalTransport * Accept(
00411 const PTimeInterval & timeout
00412 ) = 0;
00413
00416 virtual OpalTransport * CreateTransport(
00417 const OpalTransportAddress & localAddress,
00418 const OpalTransportAddress & remoteAddress
00419 ) const = 0;
00420
00426 virtual OpalTransportAddress GetLocalAddress(
00427 const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00428 ) const = 0;
00429
00432 void CloseWait();
00433
00437 void CleanUpOnTermination() { CloseWait(); }
00439
00440
00441 protected:
00450 PDECLARE_NOTIFIER(PThread, OpalListener, ListenForConnections);
00451 PBoolean StartThread(
00452 const PNotifier & acceptHandler,
00453 ThreadMode mode
00454 );
00455
00456 OpalEndPoint & endpoint;
00457 PThread * thread;
00458 PNotifier acceptHandler;
00459 ThreadMode threadMode;
00460 };
00461
00462
00463 PLIST(OpalListenerList, OpalListener);
00464
00465
00466 class OpalListenerIP : public OpalListener
00467 {
00468 PCLASSINFO(OpalListenerIP, OpalListener);
00469 public:
00474 OpalListenerIP(
00475 OpalEndPoint & endpoint,
00476 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00477 WORD port = 0,
00478 PBoolean exclusive = true
00479 );
00480 OpalListenerIP(
00481 OpalEndPoint & endpoint,
00482 const OpalTransportAddress & binding,
00483 OpalTransportAddress::BindOptions option
00484 );
00486
00494 virtual OpalTransportAddress GetLocalAddress(
00495 const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00496 ) const;
00498
00501 WORD GetListenerPort() const { return listenerPort; }
00502
00503 virtual const char * GetProtoPrefix() const = 0;
00505
00506
00507 protected:
00508 PIPSocket::Address localAddress;
00509 WORD listenerPort;
00510 PBoolean exclusiveListener;
00511 };
00512
00513
00514 class OpalListenerTCP : public OpalListenerIP
00515 {
00516 PCLASSINFO(OpalListenerTCP, OpalListenerIP);
00517 public:
00522 OpalListenerTCP(
00523 OpalEndPoint & endpoint,
00524 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00525 WORD port = 0,
00526 PBoolean exclusive = true
00527 );
00528 OpalListenerTCP(
00529 OpalEndPoint & endpoint,
00530 const OpalTransportAddress & binding,
00531 OpalTransportAddress::BindOptions option
00532 );
00533
00536 ~OpalListenerTCP();
00538
00561 virtual PBoolean Open(
00562 const PNotifier & acceptHandler,
00563 ThreadMode mode = SpawnNewThreadMode
00564 );
00565
00568 virtual PBoolean IsOpen();
00569
00572 virtual void Close();
00573
00576 virtual OpalTransport * Accept(
00577 const PTimeInterval & timeout
00578 );
00579
00582 virtual OpalTransport * CreateTransport(
00583 const OpalTransportAddress & localAddress,
00584 const OpalTransportAddress & remoteAddress
00585 ) const;
00587
00588
00589 protected:
00590 virtual const char * GetProtoPrefix() const;
00591
00592 PTCPSocket listener;
00593 };
00594
00595
00596 class OpalListenerUDP : public OpalListenerIP
00597 {
00598 PCLASSINFO(OpalListenerUDP, OpalListenerIP);
00599 public:
00604 OpalListenerUDP(
00605 OpalEndPoint & endpoint,
00606 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00607 WORD port = 0,
00608 PBoolean exclusive = true
00609 );
00610 OpalListenerUDP(
00611 OpalEndPoint & endpoint,
00612 const OpalTransportAddress & binding,
00613 OpalTransportAddress::BindOptions option
00614 );
00615
00618 ~OpalListenerUDP();
00620
00643 virtual PBoolean Open(
00644 const PNotifier & acceptHandler,
00645 ThreadMode mode = SpawnNewThreadMode
00646 );
00647
00650 virtual PBoolean IsOpen();
00651
00654 virtual void Close();
00655
00658 virtual OpalTransport * Accept(
00659 const PTimeInterval & timeout
00660 );
00661
00664 virtual OpalTransport * CreateTransport(
00665 const OpalTransportAddress & localAddress,
00666 const OpalTransportAddress & remoteAddress
00667 ) const;
00668
00674 virtual OpalTransportAddress GetLocalAddress(
00675 const OpalTransportAddress & remoteAddress = OpalTransportAddress()
00676 ) const;
00678
00683 void SetBufferSize(
00684 PINDEX size
00685 ) { m_bufferSize = size; }
00687
00688
00689 protected:
00690 virtual const char * GetProtoPrefix() const;
00691
00692 PMonitoredSocketsPtr listenerBundle;
00693 PINDEX m_bufferSize;
00694 };
00695
00696
00698
00703 class OpalTransport : public PIndirectChannel
00704 {
00705 PCLASSINFO(OpalTransport, PIndirectChannel);
00706 public:
00711 OpalTransport(OpalEndPoint & endpoint);
00712
00715 ~OpalTransport();
00717
00722 void PrintOn(
00723 ostream & strm
00724 ) const;
00726
00731 virtual PBoolean IsReliable() const = 0;
00732
00739 virtual PString GetInterface() const;
00740
00747 virtual bool SetInterface(
00748 const PString & iface
00749 );
00750
00753 virtual OpalTransportAddress GetLocalAddress(
00754 bool allowNAT = true
00755 ) const = 0;
00756
00761 virtual PBoolean SetLocalAddress(
00762 const OpalTransportAddress & address
00763 ) = 0;
00764
00767 virtual OpalTransportAddress GetRemoteAddress() const = 0;
00768
00774 virtual PBoolean SetRemoteAddress(
00775 const OpalTransportAddress & address
00776 ) = 0;
00777
00780 virtual PBoolean Connect() = 0;
00781
00784 PBoolean ConnectTo(
00785 const OpalTransportAddress & address
00786 ) { return SetRemoteAddress(address) && Connect(); }
00787
00790 virtual PBoolean Close();
00791
00794 void CloseWait();
00795
00799 void CleanUpOnTermination() { CloseWait(); }
00800
00803 virtual PBoolean IsCompatibleTransport(
00804 const OpalTransportAddress & address
00805 ) const = 0;
00806
00808 enum PromisciousModes {
00809 AcceptFromRemoteOnly,
00810 AcceptFromAnyAutoSet,
00811 AcceptFromAny,
00812 NumPromisciousModes
00813 };
00814
00825 virtual void SetPromiscuous(
00826 PromisciousModes promiscuous
00827 );
00828
00833 virtual OpalTransportAddress GetLastReceivedAddress() const;
00834
00839 virtual PString GetLastReceivedInterface() const;
00840
00850 virtual PBoolean ReadPDU(
00851 PBYTEArray & packet
00852 ) = 0;
00853
00859 virtual PBoolean WritePDU(
00860 const PBYTEArray & pdu
00861 ) = 0;
00862
00863 typedef PBoolean (*WriteConnectCallback)(OpalTransport & transport, void * userData);
00864
00877 virtual PBoolean WriteConnect(
00878 WriteConnectCallback function,
00879 void * userData
00880 );
00881
00884 virtual void AttachThread(
00885 PThread * thread
00886 );
00887
00890 virtual PBoolean IsRunning() const;
00892
00893 OpalEndPoint & GetEndPoint() const { return endpoint; }
00894
00897 virtual const char * GetProtoPrefix() const = 0;
00898
00899 PMutex & GetWriteMutex() { return m_writeMutex; }
00900
00901 protected:
00902 OpalEndPoint & endpoint;
00903 PThread * thread;
00904 PMutex m_writeMutex;
00905 };
00906
00907
00908 class OpalTransportIP : public OpalTransport
00909 {
00910 PCLASSINFO(OpalTransportIP, OpalTransport);
00911 public:
00916 OpalTransportIP(
00917 OpalEndPoint & endpoint,
00918 PIPSocket::Address binding,
00919 WORD port
00920 );
00922
00927 virtual OpalTransportAddress GetLocalAddress(
00928 bool allowNAT = true
00929 ) const;
00930
00935 virtual PBoolean SetLocalAddress(
00936 const OpalTransportAddress & address
00937 );
00938
00941 virtual OpalTransportAddress GetRemoteAddress() const;
00942
00948 virtual PBoolean SetRemoteAddress(
00949 const OpalTransportAddress & address
00950 );
00951
00953
00954 protected:
00957 virtual const char * GetProtoPrefix() const = 0;
00958
00959 PIPSocket::Address localAddress;
00960 WORD localPort;
00961 PIPSocket::Address remoteAddress;
00962 WORD remotePort;
00963 };
00964
00965
00966 class OpalTransportTCP : public OpalTransportIP
00967 {
00968 PCLASSINFO(OpalTransportTCP, OpalTransportIP);
00969 public:
00974 OpalTransportTCP(
00975 OpalEndPoint & endpoint,
00976 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
00977 WORD port = 0,
00978 PBoolean reuseAddr = false
00979 );
00980 OpalTransportTCP(
00981 OpalEndPoint & endpoint,
00982 PTCPSocket * socket
00983 );
00984
00986 ~OpalTransportTCP();
00988
00993 virtual PBoolean IsReliable() const;
00994
00997 virtual PBoolean IsCompatibleTransport(
00998 const OpalTransportAddress & address
00999 ) const;
01000
01003 virtual PBoolean Connect();
01004
01014 virtual PBoolean ReadPDU(
01015 PBYTEArray & pdu
01016 );
01017
01023 virtual PBoolean WritePDU(
01024 const PBYTEArray & pdu
01025 );
01027
01028
01029 protected:
01032 virtual const char * GetProtoPrefix() const;
01033
01043 virtual PBoolean OnOpen();
01044
01045
01046 PBoolean reuseAddressFlag;
01047 };
01048
01049
01050 class OpalTransportUDP : public OpalTransportIP
01051 {
01052 PCLASSINFO(OpalTransportUDP, OpalTransportIP);
01053 public:
01058 OpalTransportUDP(
01059 OpalEndPoint & endpoint,
01060 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01061 WORD port = 0,
01062 bool reuseAddr = false,
01063 bool preOpen = false
01064 );
01065
01068 OpalTransportUDP(
01069 OpalEndPoint & endpoint,
01070 const PMonitoredSocketsPtr & sockets,
01071 const PString & iface
01072 );
01073
01075 ~OpalTransportUDP();
01077
01080 virtual PBoolean Read(
01081 void * buffer,
01082 PINDEX length
01083 );
01085
01090 virtual PBoolean IsReliable() const;
01091
01094 virtual PBoolean IsCompatibleTransport(
01095 const OpalTransportAddress & address
01096 ) const;
01097
01105 virtual PBoolean Connect();
01106
01109 virtual PString GetInterface() const;
01110
01117 virtual bool SetInterface(
01118 const PString & iface
01119 );
01120
01123 virtual OpalTransportAddress GetLocalAddress(
01124 bool allowNAT = true
01125 ) const;
01126
01131 virtual PBoolean SetLocalAddress(
01132 const OpalTransportAddress & address
01133 );
01134
01140 virtual PBoolean SetRemoteAddress(
01141 const OpalTransportAddress & address
01142 );
01143
01155 virtual void SetPromiscuous(
01156 PromisciousModes promiscuous
01157 );
01158
01163 virtual OpalTransportAddress GetLastReceivedAddress() const;
01164
01169 virtual PString GetLastReceivedInterface() const;
01170
01180 virtual PBoolean ReadPDU(
01181 PBYTEArray & packet
01182 );
01183
01189 virtual PBoolean WritePDU(
01190 const PBYTEArray & pdu
01191 );
01192
01203 virtual PBoolean WriteConnect(
01204 WriteConnectCallback function,
01205 void * userData
01206 );
01207
01210 void SetBufferSize(
01211 PINDEX size
01212 ) { m_bufferSize = size; }
01214
01215 protected:
01218 virtual const char * GetProtoPrefix() const;
01219
01220 OpalManager & manager;
01221 PINDEX m_bufferSize;
01222 PBYTEArray m_preReadPacket;
01223 bool m_preReadOK;
01224
01225 friend class OpalListenerUDP;
01226 };
01227
01228
01230
01231 class OpalInternalTransport : public PObject
01232 {
01233 PCLASSINFO(OpalInternalTransport, PObject);
01234 public:
01235 virtual PString GetHostName(
01236 const OpalTransportAddress & address,
01237 bool includeService
01238 ) const;
01239
01240 virtual PBoolean GetIpAndPort(
01241 const OpalTransportAddress & address,
01242 PIPSocket::Address & ip,
01243 WORD & port
01244 ) const;
01245
01246 virtual OpalListener * CreateListener(
01247 const OpalTransportAddress & address,
01248 OpalEndPoint & endpoint,
01249 OpalTransportAddress::BindOptions options
01250 ) const = 0;
01251
01252 virtual OpalTransport * CreateTransport(
01253 const OpalTransportAddress & address,
01254 OpalEndPoint & endpoint,
01255 OpalTransportAddress::BindOptions options
01256 ) const = 0;
01257 };
01258
01259
01261
01262 class OpalInternalIPTransport : public OpalInternalTransport
01263 {
01264 PCLASSINFO(OpalInternalIPTransport, OpalInternalTransport);
01265 public:
01266 virtual PString GetHostName(
01267 const OpalTransportAddress & address,
01268 bool includeService
01269 ) const;
01270 virtual PBoolean GetIpAndPort(
01271 const OpalTransportAddress & address,
01272 PIPSocket::Address & ip,
01273 WORD & port
01274 ) const;
01275
01276 static PBoolean GetAdjustedIpAndPort(const OpalTransportAddress & address,
01277 OpalEndPoint & endpoint,
01278 OpalTransportAddress::BindOptions option,
01279 PIPSocket::Address & ip,
01280 WORD & port,
01281 PBoolean & reuseAddr);
01282 };
01283
01284 template <class ListenerType, class TransportType, unsigned AltTypeOption, class AltTypeClass>
01285 class OpalInternalIPTransportTemplate : public OpalInternalIPTransport
01286 {
01287 public:
01288 OpalListener * CreateListener(
01289 const OpalTransportAddress & address,
01290 OpalEndPoint & endpoint,
01291 OpalTransportAddress::BindOptions options
01292 ) const
01293 {
01294 return new ListenerType(endpoint, address, options);
01295 }
01296
01297 OpalTransport * CreateTransport(
01298 const OpalTransportAddress & address,
01299 OpalEndPoint & endpoint,
01300 OpalTransportAddress::BindOptions options
01301 ) const
01302 {
01303 PIPSocket::Address ip;
01304 WORD port;
01305 PBoolean reuseAddr;
01306 if (GetAdjustedIpAndPort(address, endpoint, options, ip, port, reuseAddr)) {
01307 if (options == AltTypeOption)
01308 return new AltTypeClass(endpoint, ip, 0, reuseAddr);
01309 else
01310 return new TransportType(endpoint, ip, 0, reuseAddr);
01311 }
01312 return NULL;
01313 }
01314 };
01315
01316 typedef OpalInternalIPTransportTemplate<OpalListenerTCP, OpalTransportTCP, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPTransport;
01317 typedef OpalInternalIPTransportTemplate<OpalListenerUDP, OpalTransportUDP, OpalTransportAddress::Streamed, OpalTransportTCP> OpalInternalUDPTransport;
01318
01319 #if OPAL_PTLIB_SSL
01320
01321 class PSSLContext;
01322
01323 class OpalListenerTCPS : public OpalListenerTCP
01324 {
01325 PCLASSINFO(OpalListenerTCPS, OpalListenerTCP);
01326 public:
01327 OpalListenerTCPS(
01328 OpalEndPoint & endpoint,
01329 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01330 WORD port = 0,
01331 PBoolean exclusive = true
01332 );
01333 OpalListenerTCPS(
01334 OpalEndPoint & endpoint,
01335 const OpalTransportAddress & binding,
01336 OpalTransportAddress::BindOptions option
01337 );
01338
01341 ~OpalListenerTCPS();
01342
01343 OpalTransport * Accept(const PTimeInterval & timeout);
01344 const char * GetProtoPrefix() const;
01345
01346 protected:
01347 void Construct();
01348
01349 PSSLContext * sslContext;
01350 };
01351
01352 class OpalTransportTCPS : public OpalTransportTCP
01353 {
01354 PCLASSINFO(OpalTransportTCPS, OpalTransportTCP);
01355 public:
01356 OpalTransportTCPS(
01357 OpalEndPoint & endpoint,
01358 PIPSocket::Address binding = PIPSocket::GetDefaultIpAny(),
01359 WORD port = 0,
01360 PBoolean reuseAddr = false
01361 );
01362 OpalTransportTCPS(
01363 OpalEndPoint & endpoint,
01364 PTCPSocket * socket
01365 );
01366
01368 ~OpalTransportTCPS();
01369
01370 PBoolean IsCompatibleTransport(const OpalTransportAddress & address) const;
01371 PBoolean Connect();
01372 PBoolean OnOpen();
01373 const char * GetProtoPrefix() const;
01374
01375 protected:
01376 PSSLContext * sslContext;
01377 };
01378
01379 typedef OpalInternalIPTransportTemplate<OpalListenerTCPS, OpalTransportTCPS, OpalTransportAddress::Datagram, OpalTransportUDP> OpalInternalTCPSTransport;
01380
01381
01382 #endif // OPAL_PTLIB_SSL
01383
01384
01385 #endif // OPAL_OPAL_TRANSPORT_H
01386
01387
01388