psockbun.h

Go to the documentation of this file.
00001 /*
00002  * psockbun.h
00003  *
00004  * Socket and interface bundle code
00005  *
00006  * Portable Windows Library
00007  *
00008  * Copyright (C) 2007 Post Increment
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Portable Windows Library.
00021  *
00022  * The Initial Developer of the Original Code is Post Increment
00023  *
00024  * Contributor(s): ______________________________________.
00025  *
00026  * $Log: psockbun.h,v $
00027  * Revision 1.14  2007/10/12 03:52:15  rjongbloed
00028  * Fixed broken virtual by someone changing base class function signature,
00029  *   and the override is silently not called. pet hate #1 about C++!
00030  *
00031  * Revision 1.13  2007/10/07 07:35:30  rjongbloed
00032  * Changed bundled sockets so does not return error if interface goes away it just
00033  *   blocks reads till the interface comes back, or is explicitly closed.
00034  * Also return error codes, rather than just a BOOL.
00035  *
00036  * Revision 1.12  2007/09/28 09:59:16  hfriederich
00037  * Allow to use PInterfaceMonitor without running monitor thread
00038  *
00039  * Revision 1.11  2007/09/25 14:27:51  hfriederich
00040  * Don't use STUN if interface filter is in use and STUN server is not
00041  * reachable through local binding. This avoids unnecessary timeouts.
00042  *
00043  * Revision 1.10  2007/09/22 04:32:03  rjongbloed
00044  * Fixed lock up on exit whena  gatekeeper is used.
00045  * Also fixed fatal "read error" (ECONNRESET) when send packet to a machine which
00046  *   is not listening on the specified port. No error is lgged but does not stop listener.
00047  *
00048  * Revision 1.9  2007/08/26 20:01:58  hfriederich
00049  * Allow to filter interfaces based on remote address
00050  *
00051  * Revision 1.8  2007/07/22 04:03:32  rjongbloed
00052  * Fixed issues with STUN usage in socket bundling, now OpalTransport indicates
00053  *   if it wants local or NAT address/port for inclusion to outgoing PDUs.
00054  *
00055  * Revision 1.7  2007/07/03 08:55:17  rjongbloed
00056  * Fixed various issues with handling interfaces going up, eg not being added
00057  *   to currently active ReadFrom().
00058  * Added more logging.
00059  *
00060  * Revision 1.6  2007/06/25 05:44:01  rjongbloed
00061  * Fixed numerous issues with "bound" managed socket, ie associating
00062  *   listeners to a specific named interface.
00063  *
00064  * Revision 1.5  2007/06/14 00:43:04  csoutheren
00065  * Removed warnings on Linux
00066  * Fixed Makefiles for new socket bundle code
00067  *
00068  * Revision 1.4  2007/06/10 06:26:50  rjongbloed
00069  * Major enhancements to the "socket bundling" feature:
00070  *   singleton thread for monitoring network interfaces
00071  *   a generic API for anything to be informed of interface changes
00072  *   PChannel derived class for reading/writing to bundled sockets
00073  *   many new API functions
00074  *
00075  * Revision 1.3  2007/05/22 11:50:47  csoutheren
00076  * Further implementation of socket bundle
00077  *
00078  * Revision 1.2  2007/05/21 06:35:37  csoutheren
00079  * Changed to be descended off PSafeObject
00080  *
00081  * Revision 1.1  2007/05/21 06:06:56  csoutheren
00082  * Add new socket bundle code to be used to OpalUDPListener
00083  *
00084  */
00085 
00086 #ifndef _PSOCKBUN_H
00087 #define _PSOCKBUN_H
00088 
00089 #ifdef P_USE_PRAGMA
00090 #pragma interface
00091 #endif
00092 
00093 
00094 #include <ptlib.h>
00095 #include <ptlib/ipsock.h>
00096 #include <ptlib/sockets.h>
00097 #include <ptlib/safecoll.h>
00098 #include <list>
00099 
00100 
00101 class PSTUNClient;
00102 class PInterfaceMonitorClient;
00103 class PInterfaceFilter;
00104 
00105 
00107 
00116 class PInterfaceMonitor : public PObject
00117 {
00118   PCLASSINFO(PInterfaceMonitor, PObject);
00119   public: 
00120     enum {
00121       DefaultRefreshInterval = 5000
00122     };
00123 
00124     PInterfaceMonitor(
00125       unsigned refreshInterval = DefaultRefreshInterval,
00126       BOOL runMonitorThread = TRUE
00127     );
00128     virtual ~PInterfaceMonitor();
00129 
00131     static PInterfaceMonitor & GetInstance();
00132 
00134     BOOL Start();
00135 
00137     void Stop();
00138 
00139     typedef PIPSocket::InterfaceEntry InterfaceEntry;
00140 
00145     PStringArray GetInterfaces(
00146       BOOL includeLoopBack = FALSE,  
00147       const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
00148     );
00149 
00155     BOOL IsValidBindingForDestination(
00156       const PIPSocket::Address & binding,
00157       const PIPSocket::Address & destination
00158     );
00159 
00164     BOOL GetInterfaceInfo(
00165       const PString & iface,  
00166       InterfaceEntry & info   
00167     );
00168     
00172     void SetInterfaceFilter(PInterfaceFilter * filter);
00173     
00174     virtual void RefreshInterfaceList();
00175 
00176   protected:
00177     void UpdateThreadMain();
00178 
00179     void AddClient(PInterfaceMonitorClient *);
00180     void RemoveClient(PInterfaceMonitorClient *);
00181 
00182     virtual void OnAddInterface(const InterfaceEntry & entry);
00183     virtual void OnRemoveInterface(const InterfaceEntry & entry);
00184 
00185 
00186     typedef PSmartPtr<PInterfaceMonitorClient> ClientPtr;
00187 
00188     typedef std::list<PInterfaceMonitorClient *> ClientList_T;
00189     ClientList_T              currentClients;
00190     PIPSocket::InterfaceTable currentInterfaces;
00191 
00192     BOOL runMonitorThread;
00193     PTimeInterval  refreshInterval;
00194     PMutex         mutex;
00195     PThread      * updateThread;
00196     PSyncPoint     threadRunning;
00197     
00198     PInterfaceFilter * interfaceFilter;
00199 
00200   friend class PInterfaceMonitorClient;
00201 };
00202 
00203 
00205 
00211 class PInterfaceMonitorClient : public PSafeObject
00212 {
00213   PCLASSINFO(PInterfaceMonitorClient, PSafeObject);
00214   public:
00215     PInterfaceMonitorClient();
00216     ~PInterfaceMonitorClient();
00217 
00218     typedef PIPSocket::InterfaceEntry InterfaceEntry;
00219 
00226     virtual PStringArray GetInterfaces(
00227       BOOL includeLoopBack = FALSE,  
00228       const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny() 
00229     );
00230 
00235     virtual BOOL GetInterfaceInfo(
00236       const PString & iface,  
00237       InterfaceEntry & info   
00238     );
00239 
00240   protected:
00242     virtual void OnAddInterface(const InterfaceEntry & entry) = 0;
00243 
00245     virtual void OnRemoveInterface(const InterfaceEntry & entry) = 0;
00246 
00247   friend class PInterfaceMonitor;
00248 };
00249 
00250 
00252 
00253 class PInterfaceFilter : public PObject {
00254   PCLASSINFO(PInterfaceFilter, PObject);
00255   
00256   public:
00257     virtual PIPSocket::InterfaceTable FilterInterfaces(const PIPSocket::Address & destination,
00258                                                        PIPSocket::InterfaceTable & interfaces) const = 0;
00259 };
00260 
00261 
00263 
00269 class PMonitoredSockets : public PInterfaceMonitorClient
00270 {
00271   PCLASSINFO(PMonitoredSockets, PInterfaceMonitorClient);
00272   protected:
00273     PMonitoredSockets(
00274       BOOL reuseAddr,
00275       PSTUNClient * stunClient
00276     );
00277 
00278   public:
00285     virtual BOOL Open(
00286       WORD port
00287     ) = 0;
00288 
00290     BOOL IsOpen() const { return opened; }
00291 
00293     virtual BOOL Close() = 0;
00294 
00296     WORD GetPort() const { return localPort; }
00297 
00299     virtual BOOL GetAddress(
00300       const PString & iface,        
00301       PIPSocket::Address & address, 
00302       WORD & port,                  
00303       BOOL usingNAT                 
00304     ) const = 0;
00305 
00311     virtual PChannel::Errors WriteToBundle(
00312       const void * buffer,              
00313       PINDEX length,                    
00314       const PIPSocket::Address & addr,  
00315       WORD port,                        
00316       const PString & iface,            
00317       PINDEX & lastWriteCount
00318     ) = 0;
00319 
00326     virtual PChannel::Errors ReadFromBundle(
00327       void * buffer,                
00328       PINDEX length,                
00329       PIPSocket::Address & addr,    
00330       WORD & port,                  
00331       PString & iface,              
00332       PINDEX & lastReadCount,       
00333       const PTimeInterval & timeout 
00334     ) = 0;
00335 
00337     void SetSTUN(
00338       PSTUNClient * stunClient
00339     ) { stun = stunClient; }
00340 
00341     // Get the current STUN server
00342     PSTUNClient * GetSTUN() const { return stun; }
00343 
00348     static PMonitoredSockets * Create(
00349       const PString & iface,            
00350       BOOL reuseAddr = FALSE,           
00351       PSTUNClient * stunClient = NULL   
00352     );
00353 
00354   protected:
00355     struct SocketInfo {
00356       SocketInfo()
00357         : socket(NULL)
00358         , inUse(false)
00359       { }
00360       PUDPSocket * socket;
00361       bool         inUse;
00362     };
00363 
00364     BOOL CreateSocket(
00365       SocketInfo & info,
00366       const PIPSocket::Address & binding
00367     );
00368     BOOL DestroySocket(SocketInfo & info);
00369     BOOL GetSocketAddress(
00370       const SocketInfo & info,
00371       PIPSocket::Address & address,
00372       WORD & port,
00373       BOOL usingNAT
00374     ) const;
00375 
00376     PChannel::Errors WriteToSocket(
00377       const void * buf,
00378       PINDEX len,
00379       const PIPSocket::Address & addr,
00380       WORD port,
00381       const SocketInfo & info,
00382       PINDEX & lastWriteCount
00383     );
00384     PChannel::Errors ReadFromSocket(
00385       SocketInfo & info,
00386       void * buf,
00387       PINDEX len,
00388       PIPSocket::Address & addr,
00389       WORD & port,
00390       PINDEX & lastReadCount,
00391       const PTimeInterval & timeout
00392     );
00393 
00394     WORD          localPort;
00395     BOOL          reuseAddress;
00396     PSTUNClient * stun;
00397 
00398     bool          opened;
00399     PUDPSocket    interfaceAddedSignal;
00400 };
00401 
00402 typedef PSafePtr<PMonitoredSockets> PMonitoredSocketsPtr;
00403 
00404 
00406 
00410 class PMonitoredSocketChannel : public PChannel
00411 {
00412   PCLASSINFO(PMonitoredSocketChannel, PChannel);
00413   public:
00416 
00417     PMonitoredSocketChannel(
00418       const PMonitoredSocketsPtr & sockets,  
00419       BOOL shared                            
00420     );
00422 
00425     virtual BOOL IsOpen() const;
00426     virtual BOOL Close();
00427 
00430     virtual BOOL Read(
00431       void * buffer,
00432       PINDEX length
00433     );
00434 
00435     virtual BOOL Write(
00438       const void * buffer,
00439       PINDEX length
00440     );
00442 
00448     void SetInterface(
00449       const PString & iface   
00450     );
00451 
00453     const PString & GetInterface();
00454 
00457     BOOL GetLocal(
00458       PIPSocket::Address & address, 
00459       WORD & port,                  
00460       BOOL usingNAT                 
00461     );
00462 
00464     void SetRemote(
00465       const PIPSocket::Address & address, 
00466       WORD port                           
00467     );
00468 
00470     void SetRemote(
00471       const PString & hostAndPort 
00472     );
00473 
00475     void GetRemote(
00476       PIPSocket::Address & addr,  
00477       WORD & port                 
00478     ) const { addr = remoteAddress; port = remotePort; }
00479 
00484     void SetPromiscuous(
00485       BOOL flag   
00486     ) { promiscuousReads = flag; }
00487 
00489     bool GetPromiscuous() { return promiscuousReads; }
00490 
00491     // Get the IP address and port of the last received UDP data.
00492     void GetLastReceived(
00493       PIPSocket::Address & addr,  
00494       WORD & port                 
00495     ) const { addr = lastReceivedAddress; port = lastReceivedPort; }
00496 
00498     const PMonitoredSocketsPtr & GetMonitoredSockets() const { return socketBundle; }
00500 
00501   protected:
00502     PMonitoredSocketsPtr socketBundle;
00503     BOOL                 sharedBundle;
00504     PString              currentInterface;
00505     BOOL                 promiscuousReads;
00506     PIPSocket::Address   remoteAddress;
00507     BOOL                 closing;
00508     WORD                 remotePort;
00509     PIPSocket::Address   lastReceivedAddress;
00510     WORD                 lastReceivedPort;
00511 };
00512 
00513 
00515 
00519 class PMonitoredSocketBundle : public PMonitoredSockets
00520 {
00521   PCLASSINFO(PMonitoredSocketBundle, PMonitoredSockets);
00522   public:
00523     PMonitoredSocketBundle(
00524       BOOL reuseAddr = FALSE,
00525       PSTUNClient * stunClient = NULL
00526     );
00527     ~PMonitoredSocketBundle();
00528 
00535     virtual BOOL Open(
00536       WORD port
00537     );
00538 
00540     virtual BOOL Close();
00541 
00543     virtual BOOL GetAddress(
00544       const PString & iface,        
00545       PIPSocket::Address & address, 
00546       WORD & port,                  
00547       BOOL usingNAT                 
00548     ) const;
00549 
00555     virtual PChannel::Errors WriteToBundle(
00556       const void * buf,
00557       PINDEX len,
00558       const PIPSocket::Address & addr,
00559       WORD port,
00560       const PString & iface,
00561       PINDEX & lastWriteCount
00562     );
00563 
00570     virtual PChannel::Errors ReadFromBundle(
00571       void * buf,
00572       PINDEX len,
00573       PIPSocket::Address & addr,
00574       WORD & port,
00575       PString & iface,
00576       PINDEX & lastReadCount,
00577       const PTimeInterval & timeout
00578     );
00579 
00580   protected:
00582     virtual void OnAddInterface(const InterfaceEntry & entry);
00583 
00585     virtual void OnRemoveInterface(const InterfaceEntry & entry);
00586 
00587     typedef std::map<std::string, SocketInfo> SocketInfoMap_T;
00588 
00589     void OpenSocket(const PString & iface);
00590     void CloseSocket(const SocketInfoMap_T::iterator & iterSocket);
00591 
00592     SocketInfoMap_T socketInfoMap;
00593 };
00594 
00595 
00597 
00602 class PSingleMonitoredSocket : public PMonitoredSocketBundle
00603 {
00604   PCLASSINFO(PSingleMonitoredSocket, PMonitoredSocketBundle);
00605   public:
00606     PSingleMonitoredSocket(
00607       const PString & theInterface,
00608       BOOL reuseAddr = FALSE,
00609       PSTUNClient * stunClient = NULL
00610     );
00611     ~PSingleMonitoredSocket();
00612 
00617     virtual PStringArray GetInterfaces(
00618       BOOL includeLoopBack = FALSE,  
00619       const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
00620     );
00621 
00628     virtual BOOL Open(
00629       WORD port
00630     );
00631 
00633     virtual BOOL Close();
00634 
00636     virtual BOOL GetAddress(
00637       const PString & iface,        
00638       PIPSocket::Address & address, 
00639       WORD & port,                  
00640       BOOL usingNAT                 
00641     ) const;
00642 
00648     virtual PChannel::Errors WriteToBundle(
00649       const void * buf,
00650       PINDEX len,
00651       const PIPSocket::Address & addr,
00652       WORD port,
00653       const PString & iface,
00654       PINDEX & lastWriteCount
00655     );
00656 
00663     virtual PChannel::Errors ReadFromBundle(
00664       void * buf,
00665       PINDEX len,
00666       PIPSocket::Address & addr,
00667       WORD & port,
00668       PString & iface,
00669       PINDEX & lastReadCount,
00670       const PTimeInterval & timeout
00671     );
00672 
00673 
00674   protected:
00676     virtual void OnAddInterface(const InterfaceEntry & entry);
00677 
00679     virtual void OnRemoveInterface(const InterfaceEntry & entry);
00680 
00681     BOOL IsInterface(const PString & iface) const;
00682 
00683     PString        theInterface;
00684     InterfaceEntry theEntry;
00685     SocketInfo     theInfo;
00686 };
00687 
00688 #endif

Generated on Fri Mar 7 06:25:02 2008 for PTLib by  doxygen 1.5.1