PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
psockbun.h
Go to the documentation of this file.
1 /*
2 * psockbun.h
3 *
4 * Socket and interface bundle code
5 *
6 * Portable Windows Library
7 *
8 * Copyright (C) 2007 Post Increment
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Post Increment
23 *
24 * Contributor(s): ______________________________________.
25 *
26 * $Revision: 30178 $
27 * $Author: rjongbloed $
28 * $Date: 2013-07-29 10:46:41 +1000 (Mon, 29 Jul 2013) $
29 */
30
31 #ifndef PTLIB_PSOCKBUN_H
32 #define PTLIB_PSOCKBUN_H
33
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37
38
39 #include <ptlib.h>
40 #include <ptlib/ipsock.h>
41 #include <ptlib/sockets.h>
42 #include <ptlib/safecoll.h>
43 #include <ptclib/pnat.h>
44 #include <map>
45
46
47 #define PINTERFACE_MONITOR_FACTORY_NAME "InterfaceMonitor"
48
49
51
52 class PInterfaceFilter : public PObject {
53 PCLASSINFO(PInterfaceFilter, PObject);
54
55 public:
56 virtual PIPSocket::InterfaceTable FilterInterfaces(const PIPSocket::Address & destination,
57 PIPSocket::InterfaceTable & interfaces) const = 0;
58 };
59
60
62
71 class PInterfaceMonitor : public PProcessStartup
72 {
73 PCLASSINFO(PInterfaceMonitor, PProcessStartup);
74 public:
75 enum {
76 DefaultRefreshInterval = 60000
77 };
78
79 PInterfaceMonitor(
80 unsigned refreshInterval = DefaultRefreshInterval,
81 bool runMonitorThread = true
82 );
83 virtual ~PInterfaceMonitor();
84
86 PFACTORY_GET_SINGLETON(PProcessStartupFactory, PInterfaceMonitor);
87
89 void SetRefreshInterval (unsigned refresh);
90
92 void SetRunMonitorThread (bool runMonitorThread);
93
99 void Start();
100
102 void Stop();
103
104 typedef PIPSocket::InterfaceEntry InterfaceEntry;
105
110 PStringArray GetInterfaces(
111 bool includeLoopBack = false,
112 const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
114 );
115
121 bool IsValidBindingForDestination(
122 const PIPSocket::Address & binding,
123 const PIPSocket::Address & destination
124 );
125
130 bool GetInterfaceInfo(
131 const PString & iface,
132 InterfaceEntry & info
133 ) const;
134
139 static bool IsMatchingInterface(
140 const PString & iface,
141 const InterfaceEntry & entry
142 );
143
146 struct InterfaceChange : public InterfaceEntry
147 {
148 InterfaceChange(const InterfaceEntry & entry, bool added)
149 : InterfaceEntry(entry)
150 , m_added(added)
151 #if P_NAT
152 , m_natMethod(NULL)
153 #endif
154 { }
155
156 const bool m_added;
157
158 #if P_NAT
159 InterfaceChange(const PNatMethod * natMethod, bool added)
160 : m_added(added), m_natMethod(natMethod) { }
161
162 const PNatMethod * const m_natMethod;
163 #endif
164 };
165
167 typedef PNotifierTemplate<InterfaceChange> Notifier;
168
170 #define PDECLARE_InterfaceNotifier(cls, fn) PDECLARE_NOTIFIER2(PInterfaceMonitor, cls, fn, PInterfaceMonitor::InterfaceChange)
171
173 #define PCREATE_InterfaceNotifier(fn) PCREATE_NOTIFIER2(fn, PInterfaceMonitor::InterfaceChange)
174
175 enum {
176 DefaultPriority = 50,
177 };
178
181 void AddNotifier(
182 const Notifier & notifier,
183 unsigned priority = DefaultPriority
184 );
185 void RemoveNotifier(
186 const Notifier & notifier
187 );
188
192 void SetInterfaceFilter(PInterfaceFilter * filter);
193 bool HasInterfaceFilter() const { return m_interfaceFilter != NULL; }
194
195 #if P_NAT
196 void OnRemoveNatMethod(const PNatMethod * natMethod);
197 #endif
198
199 protected:
200 virtual void OnShutdown();
201
202 void UpdateThreadMain();
203
204 virtual void RefreshInterfaceList();
205 virtual void OnInterfacesChanged(const PIPSocket::InterfaceTable & addedInterfaces, const PIPSocket::InterfaceTable & removedInterfaces);
206
207 typedef std::multimap<unsigned, Notifier> Notifiers;
208 Notifiers m_notifiers;
209 PMutex m_notifiersMutex;
210
211 PIPSocket::InterfaceTable m_interfaces;
212 PMutex m_interfacesMutex;
213
214 bool m_runMonitorThread;
215 PTimeInterval m_refreshInterval;
216 PMutex m_threadMutex;
217 PThread * m_updateThread;
218
219 PInterfaceFilter * m_interfaceFilter;
220 PIPSocket::RouteTableDetector * m_changedDetector;
221
222 friend class PInterfaceMonitorClient;
223 };
224
225
227
233 class PMonitoredSockets : public PSafeObject
234 {
235 PCLASSINFO(PMonitoredSockets, PSafeObject);
236 protected:
237 PMonitoredSockets(
238 bool reuseAddr
239 P_NAT_PARAM(PNatMethod * natMethod)
240 );
241
242 public:
243 typedef PIPSocket::InterfaceEntry InterfaceEntry;
244
251 virtual PBoolean Open(
252 WORD port
253 ) = 0;
254
256 PBoolean IsOpen() const { return opened; }
257
259 virtual PBoolean Close() = 0;
260
262 WORD GetPort() const { return localPort; }
263
265 virtual PBoolean GetAddress(
266 const PString & iface,
267 PIPSocket::Address & address,
268 WORD & port,
269 PBoolean usingNAT
270 ) const = 0;
271
272 struct BundleParams {
273 BundleParams()
274 : m_buffer(NULL)
275 , m_length(0)
276 , m_addr(0)
277 , m_port(0)
278 , m_lastCount(0)
279 , m_errorCode(PChannel::NoError)
280 , m_errorNumber(0)
281 { }
282
283 void * m_buffer;
284 PINDEX m_length;
285 PIPSocket::Address m_addr;
286 WORD m_port;
287 PString m_iface;
288 PINDEX m_lastCount;
289 PTimeInterval m_timeout;
290 PChannel::Errors m_errorCode;
291 int m_errorNumber;
292 };
293
299 virtual void WriteToBundle(
300 BundleParams & param
301 ) = 0;
302
309 virtual void ReadFromBundle(
310 BundleParams & param
311 ) = 0;
312
319 virtual PStringArray GetInterfaces(
320 bool includeLoopBack = false,
321 const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
323 );
324
329 virtual bool GetInterfaceInfo(
330 const PString & iface,
331 InterfaceEntry & info
332 ) const;
333
334 #if P_NAT
335
336 void SetNatMethod(
337 PNatMethod * method
338 ) { natMethod = method; }
339
340 // Get the current NAT method, eg STUN client pointer
341 PNatMethod * GetNatMethod() const { return natMethod; }
342
343 #endif
344
361 static PMonitoredSockets * Create(
362 const PString & iface,
363 bool reuseAddr = false
364 P_NAT_PARAM(PNatMethod * natMethod = NULL)
365 );
366
367 protected:
368 #if P_NAT
369 virtual void OnRemoveNatMethod(
370 const PNatMethod * natMethod
371 );
372 #endif
373
374 struct SocketInfo {
375 SocketInfo()
376 : socket(NULL)
377 , inUse(false)
378 { }
379 void Read(PMonitoredSockets & bundle, BundleParams & param);
380 void Write(BundleParams & param);
381
382 PUDPSocket * socket;
383 bool inUse;
384 };
385 friend struct SocketInfo;
386
387 bool CreateSocket(
388 SocketInfo & info,
389 const PIPSocket::Address & binding
390 );
391 bool DestroySocket(SocketInfo & info);
392 bool GetSocketAddress(
393 const SocketInfo & info,
394 PIPSocket::Address & address,
395 WORD & port,
396 bool usingNAT
397 ) const;
398
399 void ReadFromSocketList(
400 PSocket::SelectList & readers,
401 PUDPSocket * & socket,
402 BundleParams & param
403 );
404
405 WORD localPort;
406 bool reuseAddress;
407 #if P_NAT
408 PNatMethod * natMethod;
409 #endif
410
411 bool opened;
412 PUDPSocket interfaceAddedSignal;
413 };
414
415 typedef PSafePtr<PMonitoredSockets> PMonitoredSocketsPtr;
416
417
419
423 class PMonitoredSocketChannel : public PChannel
424 {
425 PCLASSINFO(PMonitoredSocketChannel, PChannel);
426 public:
429
430 PMonitoredSocketChannel(
431 const PMonitoredSocketsPtr & sockets,
432 bool shared
433 );
435
438 virtual PBoolean IsOpen() const;
439 virtual PBoolean Close();
440
443 virtual PBoolean Read(
444 void * buffer,
445 PINDEX length
446 );
447
450 virtual PBoolean Write(
451 const void * buffer,
452 PINDEX length
453 );
455
461 void SetInterface(
462 const PString & iface
463 );
464
466 PString GetInterface();
467
470 bool GetLocal(
471 PIPSocket::Address & address,
472 WORD & port,
473 bool usingNAT
474 );
475
477 void SetRemote(
478 const PIPSocket::Address & address,
479 WORD port
480 );
481
483 void SetRemote(
484 const PString & hostAndPort
485 );
486
488 void GetRemote(
489 PIPSocket::Address & addr,
490 WORD & port
491 ) const { addr = remoteAddress; port = remotePort; }
492
497 void SetPromiscuous(
498 bool flag
499 ) { promiscuousReads = flag; }
500
502 bool GetPromiscuous() { return promiscuousReads; }
503
505 void GetLastReceived(
506 PIPSocket::Address & addr,
507 WORD & port
508 ) const { addr = lastReceivedAddress; port = lastReceivedPort; }
509
511 PString GetLastReceivedInterface() const { return lastReceivedInterface; }
512
514 const PMonitoredSocketsPtr & GetMonitoredSockets() const { return socketBundle; }
516
517 protected:
518 PMonitoredSocketsPtr socketBundle;
519 bool sharedBundle;
520 PString currentInterface;
521 bool promiscuousReads;
522 PIPSocket::Address remoteAddress;
523 bool closing;
524 WORD remotePort;
525 PIPSocket::Address lastReceivedAddress;
526 WORD lastReceivedPort;
527 PString lastReceivedInterface;
528 PMutex mutex;
529 };
530
531
533
537 class PMonitoredSocketBundle : public PMonitoredSockets
538 {
539 PCLASSINFO(PMonitoredSocketBundle, PMonitoredSockets);
540 public:
541 PMonitoredSocketBundle(
542 const PString & fixedInterface,
543 unsigned ipVersion,
544 bool reuseAddr
545 P_NAT_PARAM(PNatMethod * natMethod = NULL)
546 );
547 ~PMonitoredSocketBundle();
548
555 virtual PStringArray GetInterfaces(
556 bool includeLoopBack = false,
557 const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
559 );
560
567 virtual PBoolean Open(
568 WORD port
569 );
570
572 virtual PBoolean Close();
573
575 virtual PBoolean GetAddress(
576 const PString & iface,
577 PIPSocket::Address & address,
578 WORD & port,
579 PBoolean usingNAT
580 ) const;
581
587 virtual void WriteToBundle(
588 BundleParams & param
589 );
590
597 virtual void ReadFromBundle(
598 BundleParams & param
599 );
600
601 protected:
602 PDECLARE_InterfaceNotifier(PMonitoredSocketBundle, OnInterfaceChange);
603 PInterfaceMonitor::Notifier m_onInterfaceChange;
604
605 typedef std::map<std::string, SocketInfo> SocketInfoMap_T;
606
607 void OpenSocket(const PString & iface);
608 void CloseSocket(SocketInfoMap_T::iterator iterSocket);
609
610 SocketInfoMap_T m_socketInfoMap;
611 PCaselessString m_fixedInterface;
612 unsigned m_ipVersion;
613 };
614
615
617
622 class PSingleMonitoredSocket : public PMonitoredSockets
623 {
624 PCLASSINFO(PSingleMonitoredSocket, PMonitoredSockets);
625 public:
626 PSingleMonitoredSocket(
627 const PString & theInterface,
628 bool reuseAddr
629 P_NAT_PARAM(PNatMethod * natMethod = NULL)
630 );
631 ~PSingleMonitoredSocket();
632
637 virtual PStringArray GetInterfaces(
638 bool includeLoopBack = false,
639 const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
641 );
642
649 virtual PBoolean Open(
650 WORD port
651 );
652
654 virtual PBoolean Close();
655
657 virtual PBoolean GetAddress(
658 const PString & iface,
659 PIPSocket::Address & address,
660 WORD & port,
661 PBoolean usingNAT
662 ) const;
663
669 virtual void WriteToBundle(
670 BundleParams & param
671 );
672
679 virtual void ReadFromBundle(
680 BundleParams & param
681 );
682
683
684 protected:
685 PDECLARE_InterfaceNotifier(PSingleMonitoredSocket, OnInterfaceChange);
686 PInterfaceMonitor::Notifier m_onInterfaceChange;
687
688 bool IsInterface(const PString & iface) const;
689
690 PString m_interface;
691 InterfaceEntry m_entry;
692 SocketInfo m_info;
693 };
694
695
696 #endif // PTLIB_PSOCKBUN_H
697
698
699 // End Of File ///////////////////////////////////////////////////////////////