]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/pipi/src/ipin.cpp
Se agrega README/Informe.
[z.facultad/75.74/practicos.git] / practicas / pipi / src / ipin.cpp
1
2 #include "ipin.h"
3 #include "ipheader.h"
4 #ifdef DEBUG
5 #include <iostream>
6 #endif
7
8 /// Constructor
9 IPIn::IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router,
10         bool forward, std::ostream& log):
11     ip(ip), dev(dev), forward_que(forward_que), router(router),
12     forward(forward), log(log)
13 {
14     if (router) forward = true;
15 }
16
17 void IPIn::drop(const std::string& msg, const std::string& buf)
18 {
19     log << "IPIn::drop: " << msg << "\n\tBuffer: " << buf << "\n";
20 }
21
22 void IPIn::drop(const std::string& msg, const IPHeader& iph)
23 {
24     log << "IPIn::drop: " << msg << "\n\tIPHeader: " << iph << "\n";
25 }
26
27 /// Recibe un paquete IP
28 std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runtime_error)
29 {
30     while (true)
31     {
32         std::string buf = dev.receive();
33         // No es siquiera IP
34         if (buf.size() < IPHeader::header_len())
35         {
36             drop("Cabecera incompleta o no es IP", buf);
37             continue;
38         }
39         IPHeader iph(buf);
40 #ifdef DEBUG
41         std::cout << "IPIn::recv: IPHeader: " << iph << "\n";
42         std::string tmp = buf.substr(iph.header_len());
43         std::cout << "\tdata (" << tmp.size() << ") = " << tmp << "\n";
44 #endif
45         if (iph.version != 4)
46         {
47             drop("Versión IP incorrecta", iph);
48             continue;
49         }
50         if (!iph.check_checksum())
51         {
52             drop("Mal checksum", iph);
53             continue;
54         }
55         // No es para nosotros y no forwardeamos
56         if (iph.dst != ip && !forward)
57         {
58             drop("No es para nosotros y no hacemos forward", iph);
59             continue;
60         }
61         // No es para nosotros pero forwardeamos
62         else if (iph.dst != ip)
63         {
64             forward_que.transmit(buf, ip);
65             continue;
66         }
67         // Es para nosotros pero somos router
68         else if (router)
69         {
70             drop("Es para nosotros pero somos un router", iph);
71             continue;
72         }
73         // Es para nosotros y somos un host
74         // Guarda en buffer
75         buffer[iph][iph.offset] = buf.substr(iph.header_len());
76         // Si tiene más fragmentos o es un protocolo distinto, sigo
77         if (iph.mf || (iph.proto != proto))
78             continue;
79         // No hay más fragmentos, reensamblamos (de ser necesario)
80         std::string data;
81         for (offsetmap_type::iterator i = buffer[iph].begin();
82                 i != buffer[iph].end(); ++i)
83         {
84             //TODO chequear que los fragmentos estén todos
85             data += i->second;
86         }
87 #ifdef DEBUG
88         std::cout << "IPIn::recv: Paquete completo: data = '" << data << "'\n";
89 #endif
90         buffer.erase(iph);
91         //TODO faltaría limpiar fragmentos viejos cada tanto (timer?)
92         src = iph.src;
93         dst = iph.dst;
94         return data;
95     }
96 }
97
98 // vim: set et sw=4 sts=4 :