]> git.tdb.fi Git - netvis.git/commitdiff
Handle addresses in a more generic way
authorMikko Rasa <tdb@tdb.fi>
Mon, 16 Jun 2014 17:05:36 +0000 (20:05 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 16 Jun 2014 17:06:33 +0000 (20:06 +0300)
source/address.cpp [new file with mode: 0644]
source/address.h [new file with mode: 0644]
source/host.cpp
source/host.h
source/netvis.cpp
source/netvis.h
source/resolver.cpp

diff --git a/source/address.cpp b/source/address.cpp
new file mode 100644 (file)
index 0000000..3a49971
--- /dev/null
@@ -0,0 +1,109 @@
+#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;
+}
diff --git a/source/address.h b/source/address.h
new file mode 100644 (file)
index 0000000..42e671f
--- /dev/null
@@ -0,0 +1,27 @@
+#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
index afa61b71e775a4eaa5ab49c8c87fc799ce5f71b0..93c537ea104fae71d27977f7486feca149821ebd 100644 (file)
@@ -19,17 +19,15 @@ Distributed unter the GPL
 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)
@@ -99,11 +97,11 @@ void Host::tick(const Msp::Time::TimeDelta &td)
        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)
                {
@@ -113,10 +111,7 @@ void Host::tick(const Msp::Time::TimeDelta &td)
                        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);
index c41610fd25d4b786420b8ee030d98340020fe851..928d7aaf79566ebebf5bdccae794fd5d1fff106a 100644 (file)
@@ -12,6 +12,7 @@ Distributed unter the GPL
 #include <string>
 #include <msp/time/timedelta.h>
 #include "activity.h"
+#include "address.h"
 #include "vector2.h"
 
 class NetVis;
@@ -20,7 +21,7 @@ class Host
 {
 private:
        NetVis &netvis;
-       unsigned addr;
+       Address addr;
        std::string name;
        std::string short_name;
        bool local;
@@ -30,8 +31,9 @@ private:
        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);
index 22231b150a4b62356c312d403534fed34ff6f2ff..a8f6209142b2e12505e8017613bf5385c2d88d49 100644 (file)
@@ -54,9 +54,10 @@ NetVis::NetVis(int argc, char **argv):
        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;
 
@@ -84,9 +85,9 @@ NetVis::~NetVis()
        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;
@@ -118,13 +119,13 @@ void NetVis::tick()
 
 
        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);
 
@@ -149,7 +150,7 @@ void NetVis::tick()
        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();
 
@@ -157,7 +158,7 @@ void NetVis::tick()
                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)
                        {
@@ -208,7 +209,7 @@ void NetVis::render()
        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));
@@ -244,9 +245,9 @@ void NetVis::render()
        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;
 
@@ -255,7 +256,7 @@ Host &NetVis::get_host(unsigned a)
                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));
index 68eed052f3649255d4d9ee74655e624a89327968..a59b65061f37141f30bacb88cf0145cf61b21d19 100644 (file)
@@ -23,6 +23,7 @@ Distributed unter the GPL
 #include <msp/gl/color.h>
 #include <msp/gl/font.h>
 #include <msp/time/timestamp.h>
+#include "address.h"
 
 class History;
 class Host;
@@ -48,16 +49,15 @@ private:
        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;
@@ -72,12 +72,12 @@ public:
        ~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();
index b34fc65096a785b724950530d82f290ed602b583..196a8b2beae1b8bfcaae8cf8fb68260617639ecc 100644 (file)
@@ -74,15 +74,14 @@ void Resolver::main()
        {
                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];