--- /dev/null
+#include <algorithm>
+#include <stdexcept>
+#include <arpa/inet.h>
+#include <netinet/ether.h>
+#include "address.h"
+
+using namespace std;
+
+Address::Address():
+ type(0),
+ length(0),
+ mask_bits(0)
+{ }
+
+Address::Address(uint32_t a):
+ type(ETH_P_IP),
+ length(4),
+ mask_bits(32)
+{
+ for(unsigned i=0; i<4; ++i)
+ data[i] = a>>(24-i*8);
+}
+
+Address::Address(unsigned short t, const unsigned char *d, unsigned char l):
+ type(t),
+ length(l)
+{
+ copy(d, d+l, data);
+}
+
+void Address::set_mask(const Address &mask)
+{
+ if(mask.length!=length)
+ throw invalid_argument("Address::set_mask");
+
+ mask_bits = 0;
+ for(unsigned i=0; (i<length && mask.data[i]); ++i)
+ {
+ mask_bits += 8;
+ if(mask.data[i]!=0xFF)
+ {
+ for(unsigned d=mask.data[i]; !(d&1); d>>=1)
+ --mask_bits;
+ break;
+ }
+ }
+}
+
+string Address::str() const
+{
+ if(type==ETH_P_IP)
+ {
+ char buf[INET_ADDRSTRLEN];
+ return inet_ntop(AF_INET, data, buf, INET_ADDRSTRLEN);
+ }
+ else
+ return "<unknown>";
+}
+
+unsigned Address::common_prefix_length(const Address &other) const
+{
+ if(length!=other.length)
+ return 0;
+
+ unsigned prefix = 0;
+ for(unsigned i=0; i<length; ++i)
+ {
+ prefix += 8;
+ if(data[i]!=other.data[i])
+ {
+ unsigned mismatch = data[i]^other.data[i];
+ for(; mismatch; mismatch>>=1)
+ --prefix;
+ break;
+ }
+ }
+
+ return prefix;
+}
+
+bool Address::masked_match(const Address &other) const
+{
+ unsigned prefix = common_prefix_length(other);
+ unsigned mask = min(mask_bits, other.mask_bits);
+ return prefix>=mask;
+}
+
+void Address::to_sockaddr(sockaddr_storage &sa) const
+{
+ if(type==ETH_P_IP)
+ {
+ sockaddr_in &sa_in = reinterpret_cast<sockaddr_in &>(sa);
+ sa_in.sin_family = AF_INET;
+ sa_in.sin_port = 0;
+ sa_in.sin_addr.s_addr = *(uint32_t *)data;
+ }
+ else
+ throw runtime_error("Unknown type");
+}
+
+bool Address::operator<(const Address &other) const
+{
+ if(length!=other.length)
+ return length<other.length;
+ for(unsigned i=0; i<length; ++i)
+ if(data[i]!=other.data[i])
+ return data[i]<other.data[i];
+ return false;
+}
--- /dev/null
+#ifndef ADDRESS_H_
+#define ADDRESS_H_
+
+#include <netinet/ip.h>
+#include <string>
+
+struct Address
+{
+ unsigned short type;
+ unsigned char length;
+ unsigned char mask_bits;
+ unsigned char data[16];
+
+ Address();
+ Address(uint32_t);
+ Address(unsigned short, const unsigned char *, unsigned char);
+
+ void set_mask(const Address &);
+ std::string str() const;
+ unsigned common_prefix_length(const Address &) const;
+ bool masked_match(const Address &) const;
+ void to_sockaddr(sockaddr_storage &) const;
+
+ bool operator<(const Address &) const;
+};
+
+#endif
using namespace std;
using namespace Msp;
-Host::Host(NetVis &nv, unsigned a):
+Host::Host(NetVis &nv, const Address &a):
netvis(nv),
addr(a),
+ name(addr.str()),
+ short_name(name),
local(false),
active(true),
throttle(0)
{
- in_addr ina;
- ina.s_addr = htonl(addr);
- name = inet_ntoa(ina);
- short_name = name;
}
void Host::set_name(const string &n)
if(!active)
return;
- const map<unsigned, Host *> &hosts = netvis.get_hosts();
+ const map<Address, Host *> &hosts = netvis.get_hosts();
float center_force = (local ? 0.5 : 0.1);
float fx = -pos.x*center_force;
float fy = -pos.y*center_force;
- for(map<unsigned, Host *>::const_iterator i=hosts.begin(); i!=hosts.end(); ++i)
+ for(map<Address, Host *>::const_iterator i=hosts.begin(); i!=hosts.end(); ++i)
{
if(i->second!=this)
{
float d2 = dx*dx+dy*dy;
float d = sqrt(d2);
- unsigned other_addr = i->second->get_address();
- unsigned matching_bits = 0;
- for(unsigned j=32; (j-- && !((addr^other_addr)>>j));)
- ++matching_bits;
+ unsigned matching_bits = addr.common_prefix_length(i->second->get_address());
float optimal_dist = 100+(24-min(matching_bits, 24U))*12;
float f = 5000.0*(1.0/optimal_dist-1.0/d);
#include <string>
#include <msp/time/timedelta.h>
#include "activity.h"
+#include "address.h"
#include "vector2.h"
class NetVis;
{
private:
NetVis &netvis;
- unsigned addr;
+ Address addr;
std::string name;
std::string short_name;
bool local;
float throttle;
public:
- Host(NetVis &, unsigned);
- unsigned get_address() const { return addr; }
+ Host(NetVis &, const Address &);
+
+ const Address &get_address() const { return addr; }
void set_name(const std::string &);
const std::string &get_name() const { return name; }
void set_local(bool);
if(pcap_setnonblock(pcap, true, err)==-1)
throw runtime_error(err);
- pcap_lookupnet(iface.c_str(), &localnet, &localnet_mask, err);
- localnet = ntohl(localnet);
- localnet_mask = ntohl(localnet_mask);
+ unsigned local_addr, local_mask;
+ pcap_lookupnet(iface.c_str(), &local_addr, &local_mask, err);
+ localnet = Address(ntohl(local_addr));
+ localnet.set_mask(Address(ntohl(local_mask)));
resolver = new Resolver;
delete wnd;
pcap_close(pcap);
- for(map<unsigned, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
+ for(map<Address, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
delete i->second;
- for(map<unsigned, Host *>::iterator i=disabled_hosts.begin(); i!=disabled_hosts.end(); ++i)
+ for(map<Address, Host *>::iterator i=disabled_hosts.begin(); i!=disabled_hosts.end(); ++i)
delete i->second;
for(map<unsigned, Port *>::iterator i=ports.begin(); i!=ports.end(); ++i)
delete i->second;
float min_activity = numeric_limits<float>::max();
- for(map<unsigned, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
+ for(map<Address, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
{
i->second->tick(dt);
min_activity = min(min_activity, i->second->get_activity());
}
float del_limit = pow(10, 6-0.1*static_cast<int>(max_hosts-hosts.size()-disabled_hosts.size()));
- for(map<unsigned, Host *>::iterator i=disabled_hosts.begin(); i!=disabled_hosts.end();)
+ for(map<Address, Host *>::iterator i=disabled_hosts.begin(); i!=disabled_hosts.end();)
{
i->second->tick(dt);
if(hosts.size()>max_visible_hosts)
{
list<float> activity;
- for(map<unsigned, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
+ for(map<Address, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
activity.push_back(i->second->get_activity());
activity.sort();
advance(j, activity.size()-max_visible_hosts);
float limit = *j;
- for(map<unsigned, Host *>::iterator i=hosts.begin(); i!=hosts.end();)
+ for(map<Address, Host *>::iterator i=hosts.begin(); i!=hosts.end();)
{
if(i->second->get_activity()<limit)
{
GL::MatrixStack::projection() = GL::Matrix::ortho_centered(1024, 768);
GL::MatrixStack::modelview() = GL::Matrix();
- for(map<unsigned, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
+ for(map<Address, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
i->second->render();
{
GL::Immediate imm((GL::COLOR4_UBYTE, GL::VERTEX2));
history->render();
}
-Host &NetVis::get_host(unsigned a)
+Host &NetVis::get_host(const Address &a)
{
- map<unsigned, Host *>::iterator i = hosts.find(a);
+ map<Address, Host *>::iterator i = hosts.find(a);
if(i!=hosts.end())
return *i->second;
return *i->second;
Host *host = new Host(*this, a);
- if((a&localnet_mask)==localnet)
+ if(localnet.masked_match(a))
host->set_local(true);
resolver->push(host);
host->set_position(Vector2(rand()*400.0/RAND_MAX-200.0, rand()*400.0/RAND_MAX-200.0));
#include <msp/gl/color.h>
#include <msp/gl/font.h>
#include <msp/time/timestamp.h>
+#include "address.h"
class History;
class Host;
std::string iface;
pcap_t *pcap;
Resolver *resolver;
- unsigned localnet;
- unsigned localnet_mask;
+ Address localnet;
Msp::Graphics::SimpleGLWindow *wnd;
Msp::GL::Font *font;
unsigned max_hosts;
unsigned max_visible_hosts;
- std::map<unsigned, Host *> hosts;
- std::map<unsigned, Host *> disabled_hosts;
+ std::map<Address, Host *> hosts;
+ std::map<Address, Host *> disabled_hosts;
std::list<Packet *> packets;
std::map<unsigned, Port *> ports;
History *history;
~NetVis();
const Msp::GL::Font &get_font() const { return *font; }
- const std::map<unsigned, Host *> &get_hosts() const { return hosts; }
+ const std::map<Address, Host *> &get_hosts() const { return hosts; }
const std::map<unsigned, Port *> &get_ports() const { return ports; }
private:
virtual void tick();
void render();
- Host &get_host(unsigned);
+ Host &get_host(const Address &);
Msp::GL::Color generate_color(bool) const;
Port &get_port(unsigned);
void create_history_texture();
{
while(!done)
{
- sockaddr_in addr;
- addr.sin_family = AF_INET;
+ sockaddr_storage addr;
{
MutexLock l_(mutex);
if(in_queue.empty())
break;
current = in_queue.front();
in_queue.erase(in_queue.begin());
- addr.sin_addr.s_addr = htonl(current->get_address());
+ current->get_address().to_sockaddr(addr);
}
char buf[128];