From: Leandro Lucarella Date: Fri, 23 Jun 2006 05:46:49 +0000 (+0000) Subject: Se agrega opción para recibir paquetes de un host específico y se mejora el X-Git-Tag: svn_import~27 X-Git-Url: https://git.llucax.com/z.facultad/75.74/practicos.git/commitdiff_plain/9ee7a97ec97d3dc41e1367f1f457d5ed5d5270ea Se agrega opción para recibir paquetes de un host específico y se mejora el manejo de buffers para que almacene paquetes completos. --- diff --git a/practicas/pipi/src/ipin.cpp b/practicas/pipi/src/ipin.cpp index c8ea64e..73913ab 100644 --- a/practicas/pipi/src/ipin.cpp +++ b/practicas/pipi/src/ipin.cpp @@ -27,10 +27,34 @@ void IPIn::drop(const std::string& msg, const IPHeader& iph) } /// Recibe un paquete IP -std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runtime_error) +std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst, bool filter) + throw (std::runtime_error) { while (true) { + // Reviso buffers completos a ver si puedo sacar algo + buffer_complete_type::iterator f = buffer_complete.find(proto); + if (f != buffer_complete.end()) // Hay algo + { + srcmap_type& srcmap = f->second; + srcmap_type::iterator b; + if (filter) + b = srcmap.find(src); // Si filtro, busco el que me interesa + else + b = srcmap.begin(); // Si no filtro, agarro el primero + if (b != srcmap.end()) + { + src = b->first; + dst = (b->second).dst; + std::string data = b->second.data; + // Limpio buffers + srcmap.erase(src); + if (srcmap.empty()) + buffer_complete.erase(proto); + return data; + } + } + // Si no pude sacar nada, recibo std::string buf = dev.receive(); // No es siquiera IP if (buf.size() < IPHeader::header_len()) @@ -87,8 +111,8 @@ std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runt // Es para nosotros y somos un host // Guarda en buffer buffer[iph][iph.offset] = buf.substr(iph.header_len()); - // Si tiene más fragmentos o es un protocolo distinto, sigo - if (iph.mf || (iph.proto != proto)) + // Si tiene más fragmentos, sigo + if (iph.mf) continue; // No hay más fragmentos, reensamblamos (de ser necesario) std::string data; @@ -103,6 +127,13 @@ std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runt << data << "'\n"; #endif buffer.erase(iph); + // Si es un protocolo distinto o no es de quien quiero, rearmo paquete + // (ya sé que no hay más fragmentos) y guardo en buffer nomás + if ((iph.proto != proto) || (filter == true && src != iph.src)) + { + buffer_complete[proto][iph.src] = BufferPkt(iph.dst, data); + continue; + } //TODO faltaría limpiar fragmentos viejos cada tanto (timer?) src = iph.src; dst = iph.dst; diff --git a/practicas/pipi/src/ipin.h b/practicas/pipi/src/ipin.h index 8620278..ecdc93e 100644 --- a/practicas/pipi/src/ipin.h +++ b/practicas/pipi/src/ipin.h @@ -47,6 +47,19 @@ struct IPIn typedef std::map< BufferKey, offsetmap_type > buffer_type; buffer_type buffer; + /// Buffers de paquetes completos + struct BufferPkt + { + uint32_t dst; + std::string data; + BufferPkt() {} + BufferPkt(const IPAddr& dst, const std::string& data): + dst(dst), data(data) {} + }; + typedef std::map< IPAddr, BufferPkt > srcmap_type; + typedef std::map< uint8_t, srcmap_type > buffer_complete_type; + buffer_complete_type buffer_complete; + /// Constructor IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router = false, bool forward = false, std::ostream& log = std::cout); @@ -56,7 +69,8 @@ struct IPIn void drop(const std::string& msg, const IPHeader& iph); /// Recibe un paquete IP - std::string recv(uint8_t proto, IPAddr& src, IPAddr& dst) + std::string recv(uint8_t proto, IPAddr& src, IPAddr& dst, + bool filter = false) throw (std::runtime_error); // Nada de andar copiando placas...