This file is indexed.

/usr/include/ptclib/psockbun.h is in libpt-dev 2.10.11~dfsg-2.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
/*
 * psockbun.h
 *
 * Socket and interface bundle code
 *
 * Portable Windows Library
 *
 * Copyright (C) 2007 Post Increment
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Post Increment
 *
 * Contributor(s): ______________________________________.
 *
 * $Revision: 28152 $
 * $Author: rjongbloed $
 * $Date: 2012-08-06 22:03:48 -0500 (Mon, 06 Aug 2012) $
 */

#ifndef PTLIB_PSOCKBUN_H
#define PTLIB_PSOCKBUN_H

#ifdef P_USE_PRAGMA
#pragma interface
#endif


#include <ptlib.h>
#include <ptlib/ipsock.h>
#include <ptlib/sockets.h>
#include <ptlib/safecoll.h>
#include <list>


class PNatMethod;
class PInterfaceMonitorClient;
class PInterfaceFilter;


#define PINTERFACE_MONITOR_FACTORY_NAME "InterfaceMonitor"


//////////////////////////////////////////////////

/** This class is a singleton that will monitor the network interfaces on a
    machine and update a list aof clients on any changes to the number or
    addresses of the interfaces.

    A user may override this singleton by creating a derived class and making
    a static instance of it before any monitor client classes are created.
    This would typically be done in the users main program.
  */
class PInterfaceMonitor : public PProcessStartup
{
  PCLASSINFO(PInterfaceMonitor, PProcessStartup);
  public: 
    enum {
      DefaultRefreshInterval = 60000
    };

    PInterfaceMonitor(
      unsigned refreshInterval = DefaultRefreshInterval,
      bool runMonitorThread = true
    );
    virtual ~PInterfaceMonitor();

    /// Return the singleton interface for the network monitor
    PFACTORY_GET_SINGLETON(PProcessStartupFactory, PInterfaceMonitor);
    
    /// Change the refresh interval
    void SetRefreshInterval (unsigned refresh);
    
    /// Change whether the monitor thread should run
    void SetRunMonitorThread (bool runMonitorThread);

    /** Start monitoring network interfaces.
        If the monitoring thread is already running, then this will cause an
        refresh of the interface list as soon as possible. Note that this will
        happen asynchronously.
      */
    void Start();

    /// Stop monitoring network interfaces.
    void Stop();

    typedef PIPSocket::InterfaceEntry InterfaceEntry;

    /** Get an array of all current interface descriptors, possibly including
        the loopback (127.0.0.1) interface. Note the names are of the form
        ip%name, eg "10.0.1.11%3Com 3C90x Ethernet Adapter" or "192.168.0.10%eth0"
      */
    PStringArray GetInterfaces(
      bool includeLoopBack = false,  ///< Flag for if loopback is to included in list
      const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
                          ///< Optional destination for selecting specific interface
    );

    /** Returns whether destination is reachable through binding or not.
        The default behaviour returns true unless there is an interface
        filter installed an the filter does not return <code>binding</code> among
        it's interfaces.
      */
    bool IsValidBindingForDestination(
      const PIPSocket::Address & binding,     ///< Interface binding to test
      const PIPSocket::Address & destination  ///< Destination to test against the <code>binding</code>
    );

    /** Return information about an active interface given the descriptor
       string. Note that when searchin the descriptor may be a partial match
       e.g. "10.0.1.11" or "%eth0" may be used.
      */
    bool GetInterfaceInfo(
      const PString & iface,  ///< Interface desciptor name
      InterfaceEntry & info   ///< Information on the interface
    ) const;
    
    /** Returns whether the descriptor string equals the interface entry.
        Note that when searching the descriptor may be a partial match
        e.g. "10.0.1.11" or "%eth0" may be used.
      */
    static bool IsMatchingInterface(
      const PString & iface,        ///< Interface descriptor
      const InterfaceEntry & entry  ///< Interface entry
    );
    
    /** Sets the monitor's interface filter. Note that the monitor instance
        handles deletion of the filter.
      */
    void SetInterfaceFilter(PInterfaceFilter * filter);
    bool HasInterfaceFilter() const { return m_interfaceFilter != NULL; }
    
    virtual void RefreshInterfaceList();
    
    void OnRemoveNatMethod(const PNatMethod * natMethod);

  protected:
    virtual void OnShutdown();

    void UpdateThreadMain();

    void AddClient(PInterfaceMonitorClient *);
    void RemoveClient(PInterfaceMonitorClient *);
    
    virtual void OnInterfacesChanged(const PIPSocket::InterfaceTable & addedInterfaces, const PIPSocket::InterfaceTable & removedInterfaces);

    typedef PSmartPtr<PInterfaceMonitorClient> ClientPtr;

    typedef std::list<PInterfaceMonitorClient *> ClientList_T;
    ClientList_T m_clients;
    PMutex       m_clientsMutex;

    PIPSocket::InterfaceTable m_interfaces;
    PMutex                    m_interfacesMutex;

    bool           m_runMonitorThread;
    PTimeInterval  m_refreshInterval;
    PMutex         m_threadMutex;
    PThread      * m_updateThread;

    PInterfaceFilter * m_interfaceFilter;
    PIPSocket::RouteTableDetector * m_changedDetector;

  friend class PInterfaceMonitorClient;
};


//////////////////////////////////////////////////

/** This is a base class for clients of the PInterfaceMonitor singleton object.
    The OnAddInterface() and OnRemoveInterface() functions are called in the
    context of a thread that is monitoring interfaces. The client object is
    locked for Read/Write before these functions are called.
  */
class PInterfaceMonitorClient : public PSafeObject
{
  PCLASSINFO(PInterfaceMonitorClient, PSafeObject);
  public:
    enum {
      DefaultPriority = 50,
    };
    PInterfaceMonitorClient(PINDEX priority = DefaultPriority);
    ~PInterfaceMonitorClient();

    typedef PIPSocket::InterfaceEntry InterfaceEntry;

    /** Get an array of all current interface descriptors, possibly including
        the loopback (127.0.0.1) interface. Note the names are of the form
        ip%name, eg "10.0.1.11%3Com 3C90x Ethernet Adapter" or "192.168.0.10%eth0".
        If destination is not 'any' and a filter is set, filters the interface list
        before returning it.
      */
    virtual PStringArray GetInterfaces(
      bool includeLoopBack = false,  ///< Flag for if loopback is to included in list
      const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
                          ///< Optional destination for selecting specific interface
    );

    /** Return information about an active interface given the descriptor
       string. Note that when searchin the descriptor may be a partial match
       e.g. "10.0.1.11" or "%eth0" may be used.
      */
    virtual PBoolean GetInterfaceInfo(
      const PString & iface,  ///< Interface desciptor name
      InterfaceEntry & info   ///< Information on the interface
    ) const;
    
    /**Returns the priority of this client. A higher value means higher priority.
       Higher priority clients get their callback functions called first. Clients
       with the same priority get called in the order of their insertion.
      */
    PINDEX GetPriority() const { return priority; }

  protected:
    /// Call back function for when an interface has been added to the system
    virtual void OnAddInterface(const InterfaceEntry & entry) = 0;

    /// Call back function for when an interface has been removed from the system
    virtual void OnRemoveInterface(const InterfaceEntry & entry) = 0;
    
    /// Called when a NAT method is about to be destroyed
    virtual void OnRemoveNatMethod(const PNatMethod * /*natMethod*/) { }
    
    PINDEX priority;

  friend class PInterfaceMonitor;
};


//////////////////////////////////////////////////

class PInterfaceFilter : public PObject {
  PCLASSINFO(PInterfaceFilter, PObject);
  
  public:
    virtual PIPSocket::InterfaceTable FilterInterfaces(const PIPSocket::Address & destination,
                                                       PIPSocket::InterfaceTable & interfaces) const = 0;
};


//////////////////////////////////////////////////

/** This is a base class for UDP socket(s) that are monitored for interface
    changes. Two derived classes are available, one that is permanently
    bound to an IP address and/or interface name. The second will dynamically
    open/close ports as interfaces are added and removed from the system.
  */
class PMonitoredSockets : public PInterfaceMonitorClient
{
  PCLASSINFO(PMonitoredSockets, PInterfaceMonitorClient);
  protected:
    PMonitoredSockets(
      bool reuseAddr,
      PNatMethod * natMethod
    );

  public:
    /** Open the socket(s) using the specified port. If port is zero then a
        system allocated port is used. In this case and when multiple
        interfaces are supported, all sockets use the same dynamic port value.

        Returns true if all sockets are opened.
     */
    virtual PBoolean Open(
      WORD port
    ) = 0;

    /// Indicate if the socket(s) are open and ready for reads/writes.
    PBoolean IsOpen() const { return opened; }

    /// Close all socket(s)
    virtual PBoolean Close() = 0;

    /// Return the local port number being used by the socket(s)
    WORD GetPort() const { return localPort; }

    /// Get the local address for the given interface.
    virtual PBoolean GetAddress(
      const PString & iface,        ///< Interface to get address for
      PIPSocket::Address & address, ///< Address of interface
      WORD & port,                  ///< Port listening on
      PBoolean usingNAT             ///< Require NAT address/port
    ) const = 0;

    /** Write to the remote address/port using the socket(s) available. If the
        iface parameter is empty, then the data is written to all socket(s).
        Otherwise the iface parameter indicates the specific interface socket
        to write the data to.
      */
    virtual PChannel::Errors WriteToBundle(
      const void * buffer,              ///< Data to write
      PINDEX length,                    ///< Length of data
      const PIPSocket::Address & addr,  ///< Remote IP address to write to
      WORD port,                        ///< Remote port to write to
      const PString & iface,            ///< Interface to use for writing
      PINDEX & lastWriteCount           ///< Number of bytes written
    ) = 0;

    /** Read fram a remote address/port using the socket(s) available. If the
        iface parameter is empty, then the first data received on any socket(s)
        is used, and the iface parameter is set to the name of that interface.
        Otherwise the iface parameter indicates the specific interface socket
        to read the data from.
      */
    virtual PChannel::Errors ReadFromBundle(
      void * buffer,                ///< Data to read
      PINDEX length,                ///< Maximum length of data
      PIPSocket::Address & addr,    ///< Remote IP address data came from
      WORD & port,                  ///< Remote port data came from
      PString & iface,              ///< Interface to use for read, also one data was read on
      PINDEX & lastReadCount,       ///< Actual length of data read
      const PTimeInterval & timeout ///< Time to wait for data
    ) = 0;

    /// Set the NAT method, eg STUN client pointer
    void SetNatMethod(
      PNatMethod * method
    ) { natMethod = method; }


    // Get the current NAT method, eg STUN client pointer
    PNatMethod * GetNatMethod() const { return natMethod; }

    /** Create a new monitored socket instance based on the interface
        descriptor. This will create a multiple or single socket derived class
        of PMonitoredSockets depending on teh iface parameter.
      */
    static PMonitoredSockets * Create(
      const PString & iface,            ///< Interface name to create socket for
      bool reuseAddr = false,           ///< Re-use or exclusive port number
      PNatMethod * natMethod = NULL     ///< NAT method
    );

  protected:
    virtual void OnRemoveNatMethod(
      const PNatMethod * natMethod
    );

    struct SocketInfo {
      SocketInfo()
        : socket(NULL)
        , inUse(false)
      { }
      PUDPSocket * socket;
      bool         inUse;
    };

    bool CreateSocket(
      SocketInfo & info,
      const PIPSocket::Address & binding
    );
    bool DestroySocket(SocketInfo & info);
    bool GetSocketAddress(
      const SocketInfo & info,
      PIPSocket::Address & address,
      WORD & port,
      bool usingNAT
    ) const;

    PChannel::Errors WriteToSocket(
      const void * buf,
      PINDEX len,
      const PIPSocket::Address & addr,
      WORD port,
      const SocketInfo & info,
      PINDEX & lastWriteCount
    );
    PChannel::Errors ReadFromSocket(
      SocketInfo & info,
      void * buf,
      PINDEX len,
      PIPSocket::Address & addr,
      WORD & port,
      PINDEX & lastReadCount,
      const PTimeInterval & timeout
    );
    PChannel::Errors ReadFromSocket(
      PSocket::SelectList & readers,
      PUDPSocket * & socket,
      void * buf,
      PINDEX len,
      PIPSocket::Address & addr,
      WORD & port,
      PINDEX & lastReadCount,
      const PTimeInterval & timeout
    );

    WORD          localPort;
    bool          reuseAddress;
    PNatMethod  * natMethod;

    bool          opened;
    PUDPSocket    interfaceAddedSignal;
};

typedef PSafePtr<PMonitoredSockets> PMonitoredSocketsPtr;


//////////////////////////////////////////////////

/** This class can be used to access the bundled/monitored UDP sockets using
    the PChannel API.
  */
class PMonitoredSocketChannel : public PChannel
{
  PCLASSINFO(PMonitoredSocketChannel, PChannel);
  public:
  /**@name Construction */
  //@{
    /// Construct a monitored socket bundle channel
    PMonitoredSocketChannel(
      const PMonitoredSocketsPtr & sockets,  ///< Monitored socket bundle to use in channel
      bool shared                            ///< Monitored socket is shared by other channels
    );
  //@}

  /**@name Overrides from class PSocket */
  //@{
    virtual PBoolean IsOpen() const;
    virtual PBoolean Close();

    /** Override of PChannel functions to allow connectionless reads
     */
    virtual PBoolean Read(
      void * buffer,
      PINDEX length
    );

    /** Override of PChannel functions to allow connectionless writes
     */
    virtual PBoolean Write(
      const void * buffer,
      PINDEX length
    );
  //@}

  /**@name New functions for class */
  //@{
    /** Set the interface descriptor to be used for all reads/writes to this channel.
        The iface parameter can be a partial descriptor eg "%eth0".
      */
    void SetInterface(
      const PString & iface   ///< Interface descriptor
    );

    /// Get the current interface descriptor being used/
    PString GetInterface();

    /** Get the local IP address and port for the currently selected interface.
      */
    bool GetLocal(
      PIPSocket::Address & address, ///< IP address of local interface
      WORD & port,                  ///< Port listening on
      bool usingNAT                 ///< Require NAT address/port
    );

    /// Set the remote address/port for all Write() functions
    void SetRemote(
      const PIPSocket::Address & address, ///< Remote IP address
      WORD port                           ///< Remote port number
    );

    /// Set the remote address/port for all Write() functions
    void SetRemote(
      const PString & hostAndPort ///< String of the form host[:port]
    );

    /// Get the current remote address/port for all Write() functions
    void GetRemote(
      PIPSocket::Address & addr,  ///< Remote IP address
      WORD & port                 ///< Remote port number
    ) const { addr = remoteAddress; port = remotePort; }

    /** Set flag for receiving UDP data from any remote address. If the flag
        is false then data received from anything other than the configured
        remote address and port is ignored.
      */
    void SetPromiscuous(
      bool flag   ///< New flag
    ) { promiscuousReads = flag; }

    /// Get flag for receiving UDP data from any remote address
    bool GetPromiscuous() { return promiscuousReads; }

    /// Get the IP address and port of the last received UDP data.
    void GetLastReceived(
      PIPSocket::Address & addr,  ///< Remote IP address
      WORD & port                 ///< Remote port number
    ) const { addr = lastReceivedAddress; port = lastReceivedPort; }

    /// Get the interface the last received UDP data was recieved on.
    PString GetLastReceivedInterface() const { return lastReceivedInterface; }

    /// Get the monitored socket bundle being used by this channel.
    const PMonitoredSocketsPtr & GetMonitoredSockets() const { return socketBundle; }
  //@}

  protected:
    PMonitoredSocketsPtr socketBundle;
    bool                 sharedBundle;
    PString              currentInterface;
    bool                 promiscuousReads;
    PIPSocket::Address   remoteAddress;
    bool                 closing;
    WORD                 remotePort;
    PIPSocket::Address   lastReceivedAddress;
    WORD                 lastReceivedPort;
    PString              lastReceivedInterface;
    PMutex               mutex;
};


//////////////////////////////////////////////////

/** This concrete class bundles a set of UDP sockets which are dynamically
    adjusted as interfaces are added and removed from the system.
  */
class PMonitoredSocketBundle : public PMonitoredSockets
{
  PCLASSINFO(PMonitoredSocketBundle, PMonitoredSockets);
  public:
    PMonitoredSocketBundle(
      bool reuseAddr = false,
      PNatMethod  * natMethod = NULL
    );
    ~PMonitoredSocketBundle();

    /** Get an array of all current interface descriptors, possibly including
        the loopback (127.0.0.1) interface. Note the names are of the form
        ip%name, eg "10.0.1.11%3Com 3C90x Ethernet Adapter" or "192.168.0.10%eth0".
        If destination is not 'any' and a filter is set, filters the interface list
        before returning it.
      */
    virtual PStringArray GetInterfaces(
      bool includeLoopBack = false,  ///< Flag for if loopback is to included in list
      const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
                          ///< Optional destination for selecting specific interface
    );

    /** Open the socket(s) using the specified port. If port is zero then a
        system allocated port is used. In this case and when multiple
        interfaces are supported, all sockets use the same dynamic port value.

        Returns true if all sockets are opened.
     */
    virtual PBoolean Open(
      WORD port
    );

    /// Close all socket(s)
    virtual PBoolean Close();

    /// Get the local address for the given interface.
    virtual PBoolean GetAddress(
      const PString & iface,        ///< Interface to get address for
      PIPSocket::Address & address, ///< Address of interface
      WORD & port,                  ///< Port listening on
      PBoolean usingNAT             ///< Require NAT address/port
    ) const;

    /** Write to the remote address/port using the socket(s) available. If the
        iface parameter is empty, then the data is written to all socket(s).
        Otherwise the iface parameter indicates the specific interface socket
        to write the data to.
      */
    virtual PChannel::Errors WriteToBundle(
      const void * buf,
      PINDEX len,
      const PIPSocket::Address & addr,
      WORD port,
      const PString & iface,
      PINDEX & lastWriteCount
    );

    /** Read fram a remote address/port using the socket(s) available. If the
        iface parameter is empty, then the first data received on any socket(s)
        is used, and the iface parameter is set to the name of that interface.
        Otherwise the iface parameter indicates the specific interface socket
        to read the data from.
      */
    virtual PChannel::Errors ReadFromBundle(
      void * buf,
      PINDEX len,
      PIPSocket::Address & addr,
      WORD & port,
      PString & iface,
      PINDEX & lastReadCount,
      const PTimeInterval & timeout
    );

  protected:
    /// Call back function for when an interface has been added to the system
    virtual void OnAddInterface(const InterfaceEntry & entry);

    /// Call back function for when an interface has been removed from the system
    virtual void OnRemoveInterface(const InterfaceEntry & entry);

    typedef std::map<std::string, SocketInfo> SocketInfoMap_T;

    void OpenSocket(const PString & iface);
    void CloseSocket(SocketInfoMap_T::iterator iterSocket);

    SocketInfoMap_T socketInfoMap;
};


//////////////////////////////////////////////////

/** This concrete class monitors a single scoket bound to a specific interface
   or address. The interface name may be a partial descriptor such as
   "%eth0".
  */
class PSingleMonitoredSocket : public PMonitoredSockets
{
  PCLASSINFO(PSingleMonitoredSocket, PMonitoredSockets);
  public:
    PSingleMonitoredSocket(
      const PString & theInterface,
      bool reuseAddr = false,
      PNatMethod  * natMethod = NULL
    );
    ~PSingleMonitoredSocket();

    /** Get an array of all current interface descriptors, possibly including
        the loopback (127.0.0.1) interface. Note the names are of the form
        ip%name, eg "10.0.1.11%3Com 3C90x Ethernet Adapter" or "192.168.0.10%eth0"
      */
    virtual PStringArray GetInterfaces(
      bool includeLoopBack = false,  ///< Flag for if loopback is to included in list
      const PIPSocket::Address & destination = PIPSocket::GetDefaultIpAny()
                          ///< Optional destination for selecting specific interface
    );

    /** Open the socket(s) using the specified port. If port is zero then a
        system allocated port is used. In this case and when multiple
        interfaces are supported, all sockets use the same dynamic port value.

        Returns true if all sockets are opened.
     */
    virtual PBoolean Open(
      WORD port
    );

    /// Close all socket(s)
    virtual PBoolean Close();

    /// Get the local address for the given interface.
    virtual PBoolean GetAddress(
      const PString & iface,        ///< Interface to get address for
      PIPSocket::Address & address, ///< Address of interface
      WORD & port,                  ///< Port listening on
      PBoolean usingNAT             ///< Require NAT address/port
    ) const;

    /** Write to the remote address/port using the socket(s) available. If the
        iface parameter is empty, then the data is written to all socket(s).
        Otherwise the iface parameter indicates the specific interface socket
        to write the data to.
      */
    virtual PChannel::Errors WriteToBundle(
      const void * buf,
      PINDEX len,
      const PIPSocket::Address & addr,
      WORD port,
      const PString & iface,
      PINDEX & lastWriteCount
    );

    /** Read fram a remote address/port using the socket(s) available. If the
        iface parameter is empty, then the first data received on any socket(s)
        is used, and the iface parameter is set to the name of that interface.
        Otherwise the iface parameter indicates the specific interface socket
        to read the data from.
      */
    virtual PChannel::Errors ReadFromBundle(
      void * buf,
      PINDEX len,
      PIPSocket::Address & addr,
      WORD & port,
      PString & iface,
      PINDEX & lastReadCount,
      const PTimeInterval & timeout
    );


  protected:
    /// Call back function for when an interface has been added to the system
    virtual void OnAddInterface(const InterfaceEntry & entry);

    /// Call back function for when an interface has been removed from the system
    virtual void OnRemoveInterface(const InterfaceEntry & entry);

    bool IsInterface(const PString & iface) const;

    PString        theInterface;
    InterfaceEntry theEntry;
    SocketInfo     theInfo;
};


#endif // PTLIB_PSOCKBUN_H


// End Of File ///////////////////////////////////////////////////////////////