X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fnetvis.cpp;h=7bb49bb458e507cb52d3f33cfcd17872f3537142;hb=049518d751b3e2bada5af0bd1af63273e782775f;hp=711788b86062c6e2d388cd1025cc1d7c350f343e;hpb=229e1d6ab66a9e987ffe3cd4a8de7c7f874f6de1;p=netvis.git diff --git a/source/netvis.cpp b/source/netvis.cpp index 711788b..7bb49bb 100644 --- a/source/netvis.cpp +++ b/source/netvis.cpp @@ -1,9 +1,22 @@ -#include +/* $Id$ + +This file is part of NetVis +Copyright @ 2008 Mikko Rasa, Mikkosoft Productions +Distributed unter the GPL +*/ + +#include +#include +#include +#include +#include #include #include #include -#include #include +#include +#include +#include #include #include #include @@ -11,182 +24,344 @@ #include #include #include +#include #include +#include "history.h" #include "host.h" #include "netvis.h" #include "packet.h" +#include "port.h" +#include "resolver.h" using namespace std; using namespace Msp; -NetVis::NetVis(int /*argc*/, char **argv) +NetVis::NetVis(int argc, char **argv): + pcap(0), + resolver(0), + wnd(0), + font(0), + max_hosts(1000), + max_visible_hosts(30), + frames(0) { - iface=argv[1]; -} + if(argc<2) + throw UsageError("No interface given"); + iface = argv[1]; -int NetVis::main() -{ char err[1024]; - pcap=pcap_open_live(iface.c_str(), 128, true, 0, err); + pcap = pcap_open_live(iface.c_str(), 128, true, 0, err); if(!pcap) throw Exception(err); if(pcap_setnonblock(pcap, true, err)==-1) throw Exception(err); - dpy=new Graphics::Display; - wnd=new Graphics::Window(*dpy, 1024, 768); - glc=new Graphics::GLContext(*wnd); + pcap_lookupnet(iface.c_str(), &localnet, &localnet_mask, err); + localnet = ntohl(localnet); + localnet_mask = ntohl(localnet_mask); + + resolver = new Resolver; + + wnd = new Graphics::SimpleGLWindow(1024, 768); wnd->set_title("NetVis"); + wnd->signal_close.connect(sigc::bind(sigc::mem_fun(this, &NetVis::exit), 0)); wnd->show(); - GL::enable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL::enable(GL::BLEND); + GL::blend_func(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA); - font=new GL::Font; + font = new GL::Font; DataFile::load(*font, "dejavu-10.font"); - font_tex=new GL::Texture2D; - DataFile::load(*font_tex, "dejavu-10.tex"); - font->set_texture(*font_tex); - Application::main(); + history = new History(*this, 301, 100); - delete glc; + catch_signal(SIGINT); +} + +NetVis::~NetVis() +{ + delete resolver; + + delete font; delete wnd; - delete dpy; - return exit_code; + pcap_close(pcap); + for(map::iterator i=hosts.begin(); i!=hosts.end(); ++i) + delete i->second; + for(map::iterator i=disabled_hosts.begin(); i!=disabled_hosts.end(); ++i) + delete i->second; + for(map::iterator i=ports.begin(); i!=ports.end(); ++i) + delete i->second; + for(list::iterator i=packets.begin(); i!=packets.end(); ++i) + delete *i; } void NetVis::tick() { - Msp::Time::TimeStamp t=Msp::Time::now(); - if(!last_tick) - last_tick=t; - Msp::Time::TimeDelta dt=t-last_tick; - last_tick=t; + Msp::Time::TimeStamp t = Msp::Time::now(); + Msp::Time::TimeDelta dt; + if(tick_t) + dt = t-tick_t; + tick_t = t; - dpy->tick(); + if(tick_t>fps_t+Msp::Time::sec) + { + fps = frames/((tick_t-fps_t)/Msp::Time::sec); + fps_t = tick_t; + frames = 0; + } - pcap_dispatch(pcap, -1, &capture_handler, reinterpret_cast(this)); + wnd->get_display().tick(); - glClear(GL_COLOR_BUFFER_BIT); + while(pcap_dispatch(pcap, -1, &capture_handler, reinterpret_cast(this))>0) ; - GL::matrix_mode(GL::PROJECTION); - GL::load_identity(); - GL::ortho_centered(1024, 768); - GL::matrix_mode(GL::MODELVIEW); - GL::load_identity(); + resolver->tick(); + history->tick(tick_t); + + float min_activity = numeric_limits::max(); for(map::iterator i=hosts.begin(); i!=hosts.end(); ++i) { i->second->tick(dt); - i->second->render(); + min_activity = min(min_activity, i->second->get_activity()); + } + float del_limit = pow(10, 6-0.1*static_cast(max_hosts-hosts.size()-disabled_hosts.size())); + for(map::iterator i=disabled_hosts.begin(); i!=disabled_hosts.end();) + { + i->second->tick(dt); + + if(i->second->get_activity()>min_activity) + { + i->second->set_active(true); + hosts.insert(*i); + for(unsigned j=0; j<100; ++j) + i->second->tick(100*Time::msec); + disabled_hosts.erase(i++); + } + else if(i->second->get_activity()cancel(i->second); + delete i->second; + disabled_hosts.erase(i++); + } + else + ++i; + } + + if(hosts.size()>max_visible_hosts) + { + list activity; + for(map::iterator i=hosts.begin(); i!=hosts.end(); ++i) + activity.push_back(i->second->get_activity()); + activity.sort(); + + list::iterator j = activity.begin(); + advance(j, activity.size()-max_visible_hosts); + float limit = *j; + + for(map::iterator i=hosts.begin(); i!=hosts.end();) + { + if(i->second->get_activity()second->set_active(false); + disabled_hosts.insert(*i); + hosts.erase(i++); + } + else + ++i; + } + } + + for(map::iterator i=ports.begin(); i!=ports.end();) + { + i->second->tick(dt); + + if(!i->second->is_registered() && i->second->get_activity()<0.1) + { + delete i->second; + ports.erase(i++); + } + else + ++i; } + for(list::iterator i=packets.begin(); i!=packets.end();) { (*i)->tick(dt); - (*i)->render(); if((*i)->get_stale()) { delete *i; - i=packets.erase(i); + i = packets.erase(i); } else ++i; } - GL::translate(-500, 360, 0); - for(map::iterator i=port_colors.begin(); i!=port_colors.end(); ++i) - { - GL::Color &color=i->second; + render(); + wnd->swap_buffers(); + + ++frames; +} - GL::push_matrix(); +void NetVis::render() +{ + GL::clear(GL::COLOR_BUFFER_BIT); - GL::Immediate imm((GL::COLOR4_UBYTE,GL::VERTEX2)); + GL::matrix_mode(GL::PROJECTION); + GL::load_identity(); + GL::ortho_centered(1024, 768); + GL::matrix_mode(GL::MODELVIEW); + GL::load_identity(); + + for(map::iterator i=hosts.begin(); i!=hosts.end(); ++i) + i->second->render(); + { + GL::Immediate imm((GL::COLOR4_UBYTE, GL::VERTEX2)); imm.begin(GL::QUADS); - imm.color(color.r, color.g, color.b, color.a); - for(float x=0; x<0.5; x+=0.2) - { - imm.vertex(x+0, 0); - imm.vertex(x+10, 0); - imm.vertex(x+10, 10); - imm.vertex(x+0, 10); - } + for(list::iterator i=packets.begin(); i!=packets.end(); ++i) + (*i)->render(imm); imm.end(); + } - GL::translate(15, 1, 0); - GL::scale_uniform(10); - glColor4f(1.0, 1.0, 1.0, 1.0); - font->draw_string(format("%d", i->first)); - GL::Texture::unbind(); - - GL::pop_matrix(); - GL::translate(0, -12, 0); + GL::push_matrix(); + GL::translate(-500, 360, 0); + unsigned n = 0; + for(map::iterator i=ports.begin(); (i!=ports.end() && n<50); ++i) + { + float act = i->second->get_activity(); + if((i->second->is_registered() && act>1) || act>200) + { + i->second->render(); + GL::translate(0, -12, 0); + ++n; + } } + GL::pop_matrix(); + + GL::push_matrix(); + GL::translate(-500, -348, 0); + GL::scale_uniform(10); + font->draw_string(format("%d hosts", hosts.size()+disabled_hosts.size())); + GL::translate(0, -1.2, 0); + font->draw_string(format("%d ports", ports.size())); + GL::translate(0, -1.2, 0); + font->draw_string(format("%.2f fps", fps)); + GL::Texture::unbind(); + GL::pop_matrix(); - glc->swap_buffers(); + GL::push_matrix(); + GL::translate(170, -370, 0); + history->render(); + GL::pop_matrix(); } Host &NetVis::get_host(unsigned a) { - map::iterator i=hosts.find(a); + map::iterator i = hosts.find(a); if(i!=hosts.end()) return *i->second; - Host *host=new Host(*this, a); - host->set_position(Vector2(rand()*30.0/RAND_MAX-15.0, rand()*20.0/RAND_MAX-10.0)); - hosts[a]=host; + i = disabled_hosts.find(a); + if(i!=disabled_hosts.end()) + return *i->second; + + Host *host = new Host(*this, a); + if((a&localnet_mask)==localnet) + 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)); + for(unsigned j=0; j<100; ++j) + host->tick(100*Time::msec); + hosts[a] = host; return *host; } -GL::Color &NetVis::get_port_color(unsigned port) +Port &NetVis::get_port(unsigned number) { - map::iterator i=port_colors.find(port); - if(i!=port_colors.end()) - return i->second; - - GL::Color color; - while(1) - { - color.r=rand()*1.0/RAND_MAX; - color.g=rand()*1.0/RAND_MAX; - color.b=rand()*1.0/RAND_MAX; - if(color.r>0.5 || color.g>0.5 || color.b>0.7) - break; - } - color.a=0.4f; - return port_colors[port]=color; + map::iterator i = ports.find(number); + if(i!=ports.end()) + return *i->second; + Port *port = new Port(*this, number); + ports[number] = port; + return *port; } void NetVis::capture_handler(unsigned char *user, const pcap_pkthdr *, const unsigned char *data) { - NetVis *self=reinterpret_cast(user); + NetVis *self = reinterpret_cast(user); - const ethhdr *eth=reinterpret_cast(data); + const ethhdr *eth = reinterpret_cast(data); if(ntohs(eth->h_proto)==ETH_P_IP) { - const iphdr *ip=reinterpret_cast(eth+1); + const iphdr *ip = reinterpret_cast(eth+1); - //cout<<"IP packet of "<len<<'/'<tot_len)<<" bytes\n"; + unsigned size = ntohs(ip->tot_len); - unsigned port=0; + Port *sport = 0; + Port *dport = 0; if(ip->protocol==IPPROTO_TCP) { - const tcphdr *tcp=reinterpret_cast(ip+1); - port=min(ntohs(tcp->source), ntohs(tcp->dest)); + const tcphdr *tcp = reinterpret_cast(ip+1); + sport = &self->get_port(ntohs(tcp->source)); + dport = &self->get_port(ntohs(tcp->dest)); } else if(ip->protocol==IPPROTO_UDP) { - const udphdr *udp=reinterpret_cast(ip+1); - port=min(ntohs(udp->source), ntohs(udp->dest)); + const udphdr *udp = reinterpret_cast(ip+1); + sport = &self->get_port(ntohs(udp->source)); + dport = &self->get_port(ntohs(udp->dest)); + } + + Port *port = 0; + if(sport && dport) + { + if(sport->is_registered()!=dport->is_registered()) + { + if(sport->is_registered()) + port = sport; + else + port = dport; + } + else if(sport->get_number()get_number()) + port = sport; + else + port = dport; } - Host &shost=self->get_host(ntohl(ip->saddr)); - Host *dhost=0; + else + port = &self->get_port(0); + + Host &shost = self->get_host(ntohl(ip->saddr)); + Host *dhost = 0; if((ntohl(ip->daddr)&0xFF)!=0xFF) - dhost=&self->get_host(ntohl(ip->daddr)); - self->packets.push_back(new Packet(shost, dhost, self->get_port_color(port), ntohs(ip->tot_len))); + dhost = &self->get_host(ntohl(ip->daddr)); + + float throttle = shost.send_packet(); + if(throttle<1) + { + self->packets.push_back(new Packet(shost, dhost, port->get_color(), size)); + self->packets.back()->tick(-throttle*Msp::Time::sec); + } + + shost.add_activity(size); + if(dhost) + dhost->add_activity(size); + + if(sport) + sport->add_activity(size); + if(dport) + dport->add_activity(size); + + if((ntohl(ip->saddr)&self->localnet_mask)==self->localnet) + self->history->activity(0, size); + else if((ntohl(ip->daddr)&self->localnet_mask)==self->localnet) + self->history->activity(size, 0); } } +void NetVis::sighandler(int) +{ + exit(0); +} + Application::RegApp NetVis::reg;