From d51a48acca7341f6886cfaee332debdc4b8ccc67 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 14 Mar 2013 13:27:51 +0000 Subject: [PATCH] work in progress: get_interfaces() --- panda/src/net/connectionManager.cxx | 116 ++++++++++++++++++++++++++++ panda/src/net/connectionManager.h | 54 +++++++++++++ 2 files changed, 170 insertions(+) diff --git a/panda/src/net/connectionManager.cxx b/panda/src/net/connectionManager.cxx index f5d9e91558..c45a618d43 100644 --- a/panda/src/net/connectionManager.cxx +++ b/panda/src/net/connectionManager.cxx @@ -23,6 +23,9 @@ #if defined(WIN32_VC) || defined(WIN64_VC) #include // For gethostname() +#else +#include +#include #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 << " ]"; +} diff --git a/panda/src/net/connectionManager.h b/panda/src/net/connectionManager.h index e7da81e56e..2d43b22c95 100644 --- a/panda/src/net/connectionManager.h +++ b/panda/src/net/connectionManager.h @@ -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 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