work in progress: get_interfaces()

This commit is contained in:
David Rose 2013-03-14 13:27:51 +00:00
parent b7be283ce9
commit d51a48acca
2 changed files with 170 additions and 0 deletions

View File

@ -23,6 +23,9 @@
#if defined(WIN32_VC) || defined(WIN64_VC)
#include <winsock2.h> // For gethostname()
#else
#include <net/if.h>
#include <ifaddrs.h>
#endif
////////////////////////////////////////////////////////////////////
@ -33,6 +36,7 @@
ConnectionManager::
ConnectionManager() : _set_mutex("ConnectionManager::_set_mutex")
{
_interfaces_scanned = false;
}
////////////////////////////////////////////////////////////////////
@ -504,6 +508,95 @@ get_host_name() {
return string();
}
////////////////////////////////////////////////////////////////////
// Function: ConnectionManager::scan_interfaces
// Access: Published
// Description: Repopulates the list reported by
// get_num_interface()/get_interface(). It is not
// necessary to call this explicitly, unless you want to
// re-determine the connected interfaces (for instance,
// if you suspect the hardware has recently changed).
////////////////////////////////////////////////////////////////////
void ConnectionManager::
scan_interfaces() {
LightMutexHolder holder(_set_mutex);
_interfaces.clear();
_interfaces_scanned = true;
#ifdef WIN32_VC
// TODO.
#else // WIN32_VC
struct ifaddrs *ifa;
if (getifaddrs(&ifa) != 0) {
// Failure.
net_cat.error()
<< "Failed to call getifaddrs\n";
return;
}
struct ifaddrs *p = ifa;
while (p != NULL) {
if (p->ifa_addr->sa_family == AF_INET) {
Interface interface;
interface.set_name(p->ifa_name);
if (p->ifa_addr != NULL) {
interface.set_ip(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_addr)));
}
if (p->ifa_netmask != NULL) {
interface.set_netmask(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_netmask)));
}
if ((p->ifa_flags & IFF_BROADCAST) && p->ifa_broadaddr != NULL) {
interface.set_broadcast(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_broadaddr)));
} else if ((p->ifa_flags & IFF_POINTOPOINT) && p->ifa_dstaddr != NULL) {
interface.set_p2p(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_dstaddr)));
}
_interfaces.push_back(interface);
}
p = p->ifa_next;
}
freeifaddrs(ifa);
#endif // WIN32_VC
}
////////////////////////////////////////////////////////////////////
// Function: ConnectionManager::get_num_interfaces
// Access: Published
// Description: This returns the number of usable network interfaces
// detected on this machine. (Currently, only IPv4
// interfaces are reported.) See scan_interfaces() to
// repopulate this list.
////////////////////////////////////////////////////////////////////
int ConnectionManager::
get_num_interfaces() {
if (!_interfaces_scanned) {
scan_interfaces();
}
LightMutexHolder holder(_set_mutex);
return _interfaces.size();
}
////////////////////////////////////////////////////////////////////
// Function: ConnectionManager::get_interface
// Access: Published
// Description: Returns the nth usable network interface detected on
// this machine. (Currently, only IPv4 interfaces are
// reported.) See scan_interfaces() to repopulate this
// list.
////////////////////////////////////////////////////////////////////
const ConnectionManager::Interface &ConnectionManager::
get_interface(int n) {
if (!_interfaces_scanned) {
scan_interfaces();
}
LightMutexHolder holder(_set_mutex);
nassertr(n >= 0 && n < (int)_interfaces.size(), _interfaces[0]);
return _interfaces[n];
}
////////////////////////////////////////////////////////////////////
// Function: ConnectionManager::new_connection
// Access: Protected
@ -629,3 +722,26 @@ remove_writer(ConnectionWriter *writer) {
LightMutexHolder holder(_set_mutex);
_writers.erase(writer);
}
////////////////////////////////////////////////////////////////////
// Function: ConnectionManager::Interface::Output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void ConnectionManager::Interface::
output(ostream &out) const {
out << get_name() << " [";
if (has_ip()) {
out << " " << get_ip();
}
if (has_netmask()) {
out << " netmask " << get_netmask();
}
if (has_broadcast()) {
out << " broadcast " << get_broadcast();
}
if (has_p2p()) {
out << " p2p " << get_p2p();
}
out << " ]";
}

View File

@ -21,6 +21,7 @@
#include "connection.h"
#include "pointerTo.h"
#include "pset.h"
#include "pvector.h"
#include "lightMutex.h"
class NetAddress;
@ -66,6 +67,50 @@ PUBLISHED:
static string get_host_name();
class Interface {
PUBLISHED:
const string &get_name() const { return _name; }
bool has_ip() const { return (_flags & F_has_ip) != 0; }
const NetAddress &get_ip() const { return _ip; }
bool has_netmask() const { return (_flags & F_has_netmask) != 0; }
const NetAddress &get_netmask() const { return _netmask; }
bool has_broadcast() const { return (_flags & F_has_broadcast) != 0; }
const NetAddress &get_broadcast() const { return _broadcast; }
bool has_p2p() const { return (_flags & F_has_p2p) != 0; }
const NetAddress &get_p2p() const { return _p2p; }
void output(ostream &out) const;
public:
Interface() { _flags = 0; }
void set_name(const string &name) { _name = name; }
void set_ip(const NetAddress &ip) { _ip = ip; _flags |= F_has_ip; }
void set_netmask(const NetAddress &ip) { _netmask = ip; _flags |= F_has_netmask; }
void set_broadcast(const NetAddress &ip) { _broadcast = ip; _flags |= F_has_broadcast; }
void set_p2p(const NetAddress &ip) { _p2p = ip; _flags |= F_has_p2p; }
private:
string _name;
NetAddress _ip;
NetAddress _netmask;
NetAddress _broadcast;
NetAddress _p2p;
int _flags;
enum Flags {
F_has_ip = 0x001,
F_has_netmask = 0x002,
F_has_broadcast = 0x004,
F_has_p2p = 0x008,
};
};
void scan_interfaces();
int get_num_interfaces();
const Interface &get_interface(int n);
MAKE_SEQ(get_interfaces, get_num_interfaces, get_interface);
protected:
void new_connection(const PT(Connection) &connection);
virtual void flush_read_connection(Connection *connection);
@ -85,6 +130,10 @@ protected:
Writers _writers;
LightMutex _set_mutex;
typedef pvector<Interface> Interfaces;
Interfaces _interfaces;
bool _interfaces_scanned;
private:
friend class ConnectionReader;
friend class ConnectionWriter;
@ -92,4 +141,9 @@ private:
friend class Connection;
};
INLINE ostream &operator << (ostream &out, const ConnectionManager::Interface &interface) {
interface.output(out);
return out;
}
#endif