]> git.tdb.fi Git - netvis.git/blob - source/netvis.cpp
711788b86062c6e2d388cd1025cc1d7c350f343e
[netvis.git] / source / netvis.cpp
1 #include <iostream>
2 #include <netinet/ip.h>
3 #include <netinet/tcp.h>
4 #include <netinet/udp.h>
5 #include <linux/if_ether.h>
6 #include <msp/core/except.h>
7 #include <msp/gl/immediate.h>
8 #include <msp/gl/matrix.h>
9 #include <msp/gl/misc.h>
10 #include <msp/gl/projection.h>
11 #include <msp/gl/texture2d.h>
12 #include <msp/gl/transform.h>
13 #include <msp/strings/formatter.h>
14 #include <msp/time/utils.h>
15 #include "host.h"
16 #include "netvis.h"
17 #include "packet.h"
18
19 using namespace std;
20 using namespace Msp;
21
22 NetVis::NetVis(int /*argc*/, char **argv)
23 {
24         iface=argv[1];
25 }
26
27 int NetVis::main()
28 {
29         char err[1024];
30         pcap=pcap_open_live(iface.c_str(), 128, true, 0, err);
31         if(!pcap)
32                 throw Exception(err);
33
34         if(pcap_setnonblock(pcap, true, err)==-1)
35                 throw Exception(err);
36
37         dpy=new Graphics::Display;
38         wnd=new Graphics::Window(*dpy, 1024, 768);
39         glc=new Graphics::GLContext(*wnd);
40         wnd->set_title("NetVis");
41         wnd->show();
42
43         GL::enable(GL_BLEND);
44         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
45
46         font=new GL::Font;
47         DataFile::load(*font, "dejavu-10.font");
48         font_tex=new GL::Texture2D;
49         DataFile::load(*font_tex, "dejavu-10.tex");
50         font->set_texture(*font_tex);
51
52         Application::main();
53
54         delete glc;
55         delete wnd;
56         delete dpy;
57
58         return exit_code;
59 }
60
61 void NetVis::tick()
62 {
63         Msp::Time::TimeStamp t=Msp::Time::now();
64         if(!last_tick)
65                 last_tick=t;
66         Msp::Time::TimeDelta dt=t-last_tick;
67         last_tick=t;
68
69         dpy->tick();
70
71         pcap_dispatch(pcap, -1, &capture_handler, reinterpret_cast<unsigned char *>(this));
72
73         glClear(GL_COLOR_BUFFER_BIT);
74
75         GL::matrix_mode(GL::PROJECTION);
76         GL::load_identity();
77         GL::ortho_centered(1024, 768);
78         GL::matrix_mode(GL::MODELVIEW);
79         GL::load_identity();
80
81         for(map<unsigned, Host *>::iterator i=hosts.begin(); i!=hosts.end(); ++i)
82         {
83                 i->second->tick(dt);
84                 i->second->render();
85         }
86         for(list<Packet *>::iterator i=packets.begin(); i!=packets.end();)
87         {
88                 (*i)->tick(dt);
89                 (*i)->render();
90                 if((*i)->get_stale())
91                 {
92                         delete *i;
93                         i=packets.erase(i);
94                 }
95                 else
96                         ++i;
97         }
98
99         GL::translate(-500, 360, 0);
100         for(map<unsigned, GL::Color>::iterator i=port_colors.begin(); i!=port_colors.end(); ++i)
101         {
102                 GL::Color &color=i->second;
103
104                 GL::push_matrix();
105
106                 GL::Immediate imm((GL::COLOR4_UBYTE,GL::VERTEX2));
107                 imm.begin(GL::QUADS);
108                 imm.color(color.r, color.g, color.b, color.a);
109                 for(float x=0; x<0.5; x+=0.2)
110                 {
111                         imm.vertex(x+0, 0);
112                         imm.vertex(x+10, 0);
113                         imm.vertex(x+10, 10);
114                         imm.vertex(x+0, 10);
115                 }
116                 imm.end();
117
118                 GL::translate(15, 1, 0);
119                 GL::scale_uniform(10);
120                 glColor4f(1.0, 1.0, 1.0, 1.0);
121                 font->draw_string(format("%d", i->first));
122                 GL::Texture::unbind();
123
124                 GL::pop_matrix();
125                 GL::translate(0, -12, 0);
126         }
127
128         glc->swap_buffers();
129 }
130
131 Host &NetVis::get_host(unsigned a)
132 {
133         map<unsigned, Host *>::iterator i=hosts.find(a);
134         if(i!=hosts.end())
135                 return *i->second;
136
137         Host *host=new Host(*this, a);
138         host->set_position(Vector2(rand()*30.0/RAND_MAX-15.0, rand()*20.0/RAND_MAX-10.0));
139         hosts[a]=host;
140         return *host;
141 }
142
143 GL::Color &NetVis::get_port_color(unsigned port)
144 {
145         map<unsigned, GL::Color>::iterator i=port_colors.find(port);
146         if(i!=port_colors.end())
147                 return i->second;
148
149         GL::Color color;
150         while(1)
151         {
152                 color.r=rand()*1.0/RAND_MAX;
153                 color.g=rand()*1.0/RAND_MAX;
154                 color.b=rand()*1.0/RAND_MAX;
155                 if(color.r>0.5 || color.g>0.5 || color.b>0.7)
156                         break;
157         }
158         color.a=0.4f;
159         return port_colors[port]=color;
160 }
161
162 void NetVis::capture_handler(unsigned char *user, const pcap_pkthdr *, const unsigned char *data)
163 {
164         NetVis *self=reinterpret_cast<NetVis *>(user);
165
166         const ethhdr *eth=reinterpret_cast<const ethhdr *>(data);
167         if(ntohs(eth->h_proto)==ETH_P_IP)
168         {
169                 const iphdr *ip=reinterpret_cast<const iphdr *>(eth+1);
170
171                 //cout<<"IP packet of "<<hdr->len<<'/'<<ntohs(ip->tot_len)<<" bytes\n";
172
173                 unsigned port=0;
174                 if(ip->protocol==IPPROTO_TCP)
175                 {
176                         const tcphdr *tcp=reinterpret_cast<const tcphdr *>(ip+1);
177                         port=min(ntohs(tcp->source), ntohs(tcp->dest));
178                 }
179                 else if(ip->protocol==IPPROTO_UDP)
180                 {
181                         const udphdr *udp=reinterpret_cast<const udphdr *>(ip+1);
182                         port=min(ntohs(udp->source), ntohs(udp->dest));
183                 }
184                 Host &shost=self->get_host(ntohl(ip->saddr));
185                 Host *dhost=0;
186                 if((ntohl(ip->daddr)&0xFF)!=0xFF)
187                         dhost=&self->get_host(ntohl(ip->daddr));
188                 self->packets.push_back(new Packet(shost, dhost, self->get_port_color(port), ntohs(ip->tot_len)));
189         }
190 }
191
192 Application::RegApp<NetVis> NetVis::reg;