]> git.llucax.com Git - z.facultad/75.74/practicos.git/commitdiff
Se agrega una primera aproximación al NameServer. Se implementa el parser y
authorLeandro Lucarella <llucax@gmail.com>
Thu, 22 Jun 2006 12:09:57 +0000 (12:09 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Thu, 22 Jun 2006 12:09:57 +0000 (12:09 +0000)
almacenamiento en memoria de zonas (test incluído).

practicas/pipi/src/Makefile
practicas/pipi/src/nameserver.cpp [new file with mode: 0644]
practicas/pipi/src/nameserver.h [new file with mode: 0644]
practicas/pipi/src/test_nameserver_file.cpp [new file with mode: 0644]
practicas/pipi/src/test_nameserver_zones.txt [new file with mode: 0644]

index b3e071ce1b493bcb8b1f89bb4844fceb39a7774f..bbd1d679cee89c8c27ffb8e646a9155e2d5c2589 100644 (file)
@@ -32,7 +32,7 @@ CC=g++
 # Programas
 targets=ip
 tests=test_send test_recv test_ipaddr test_ipin test_ipout test_devtcp \
-      test_poll test_resolvprotos test_resolvprotoc
+      test_poll test_resolvprotos test_resolvprotoc test_nameserver_file
 
 # Fuentes
 fuentes ?= $(wildcard *.cpp) $(wildcard *.c)
@@ -65,6 +65,8 @@ test_resolvprotos: test_resolvprotos.o libtcp.o ipaddr.o resolvproto.o
 
 test_resolvprotoc: test_resolvprotoc.o libtcp.o ipaddr.o resolvproto.o
 
+test_nameserver_file: test_nameserver_file.o ipaddr.o nameserver.o
+
 ip: ip.o ipout.o ipin.o ipaddr.o ipheader.o devque.o devtcp.o routetable.o libtcp.o
 
 depend:
@@ -175,6 +177,10 @@ ipout.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
 ipout.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h
 ipout.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h
 ipout.o: /usr/include/bits/msq.h
+nameserver.o: nameserver.h ipaddr.h /usr/include/stdint.h
+nameserver.o: /usr/include/features.h /usr/include/sys/cdefs.h
+nameserver.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
+nameserver.o: /usr/include/bits/wordsize.h
 resolvproto.o: resolvproto.h ipaddr.h /usr/include/stdint.h
 resolvproto.o: /usr/include/features.h /usr/include/sys/cdefs.h
 resolvproto.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
@@ -276,6 +282,10 @@ test_ipout.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h
 test_ipout.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h
 test_ipout.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h
 test_ipout.o: /usr/include/bits/msq.h
+test_nameserver_file.o: nameserver.h ipaddr.h /usr/include/stdint.h
+test_nameserver_file.o: /usr/include/features.h /usr/include/sys/cdefs.h
+test_nameserver_file.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h
+test_nameserver_file.o: /usr/include/bits/wordsize.h
 test_recv.o: devque.h dev.h /usr/include/unistd.h /usr/include/features.h
 test_recv.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h
 test_recv.o: /usr/include/bits/posix_opt.h /usr/include/bits/types.h
diff --git a/practicas/pipi/src/nameserver.cpp b/practicas/pipi/src/nameserver.cpp
new file mode 100644 (file)
index 0000000..2814427
--- /dev/null
@@ -0,0 +1,136 @@
+#include "nameserver.h"
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+#ifdef DEBUG2
+#include <iostream>
+#endif
+
+static void parsename(const std::string& s, NameServer::name_t& name)
+{
+    std::istringstream iss(s);
+    std::string tok;
+    while (std::getline(iss, tok, '.'))
+    {
+        name.push_back(tok);
+    }
+}
+
+static std::ostream& operator<< (std::ostream& os, const NameServer::name_t& name)
+{
+    if (name.empty())
+        return os;
+    std::copy(name.begin(), name.end() - 1,
+            std::ostream_iterator< std::string >(os, "."));
+    return os << name.back();
+}
+
+/// Parsea una zona
+static std::istream& parsezone(std::istream& is, NameServer::Zone& z)
+    throw (std::runtime_error)
+{
+    std::string line, sname, ip;
+    // [dominio] [ttl] [parent ip]
+    while (std::getline(is, line) && (line == "")); // Salteo líneas en blanco
+    if (!is)
+        return is;
+    std::istringstream iss(line);
+    if (!(iss >> sname >> z.ttl >> ip))
+        throw std::runtime_error("Error al parsear");
+    parsename(sname, z.name);
+#ifdef DEBUG2
+    std::cerr << "parsezone: IP = " << ip << "\n\n";
+#endif
+    z.parent = IPAddr(ip);
+    // un record por linea, sin líneas vacías
+    // [name] [type] [ip]
+    while (std::getline(is, line) && (line != ""))
+    {
+        iss.clear();
+        iss.str(line);
+        std::string key, type;
+        if (!(iss >> key >> type >> ip))
+            throw std::runtime_error("Error al parsear");
+        typedef NameServer::Record Rec;
+#ifdef DEBUG2
+        std::cerr << "parsezone: IP = " << ip << "\n\n";
+#endif
+        Rec r((type == "NS") ? Rec::NS : Rec::A, IPAddr(ip));
+        z.records.insert(NameServer::Zone::records_t::value_type(key, r));
+    }
+#ifdef DEBUG2
+    std::cerr << "parsezone: " << z << "\n\n";
+#endif
+    return is;
+}
+
+/// Constructor
+NameServer::Zone::Zone(std::string sname, size_t ttl, const IPAddr& parent):
+    ttl(ttl), parent(parent)
+{
+    parsename(sname, name);
+}
+
+/// Constructor
+NameServer::Zone::Zone(std::istream& is)
+    throw (std::runtime_error)
+{
+    // Parsea la zona
+    if (!parsezone(is, *this))
+        throw std::runtime_error("Error de parser, no hay zona");
+}
+
+/// Limpia una zona
+void NameServer::Zone::clear()
+{
+    name.clear();
+    records.clear();
+}
+
+/// Constructor
+NameServer::NameServer(std::istream& is)
+    throw (std::runtime_error)
+{
+    Zone z;
+    while (parsezone(is, z))
+    {
+        zones.push_back(z);
+        z.clear();
+#ifdef DEBUG2
+        std::cerr << "NameServer: " << z << "\n\n";
+#endif
+    }
+}
+
+std::ostream& operator<< (std::ostream& os, const NameServer::Record& r)
+{
+    if (r.type == NameServer::Record::NS)
+        os << "NS ";
+    else
+        os << "A ";
+    return os << r.ip;
+}
+
+std::ostream& operator<< (std::ostream& os,
+        const NameServer::Zone::records_t::value_type& p)
+{
+    return os << p.first << ": " << p.second;
+}
+
+std::ostream& operator<< (std::ostream& os, const NameServer::Zone& z)
+{
+    os << "Zone " << z.name << " " << z.ttl << " " << z.parent << "\n";
+    std::copy(z.records.begin(), z.records.end(), std::ostream_iterator<
+            NameServer::Zone::records_t::value_type >(os, "\n"));
+    return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const NameServer& ns)
+{
+    os << "NameServer: zones[" << ns.zones.size() << "] (\n\n";
+    std::copy(ns.zones.begin(), ns.zones.end(),
+            std::ostream_iterator< NameServer::Zone >(os, "\n"));
+    return os << ")";
+}
+
+// vim: set et sw=4 sts=4 :
diff --git a/practicas/pipi/src/nameserver.h b/practicas/pipi/src/nameserver.h
new file mode 100644 (file)
index 0000000..686fb52
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _NAMESERVER_H_
+#define _NAMESERVER_H_
+
+#include "ipaddr.h"
+//XXX#include "resolvproto.h"
+#include <string>
+#include <vector>
+#include <map>
+#include <istream>
+#include <ostream>
+#include <stdexcept>
+
+/// Petición del resolver a un nameserver
+struct NameServer
+{
+
+    /// Nombre de un dominio dividido en tokens
+    typedef std::vector< std::string > name_t;
+
+    /// Registro de una zona
+    struct Record
+    {
+        /// Tipo de registro
+        enum type_t { A, NS };
+        type_t type;
+        /// Dirección IP del registro
+        IPAddr ip;
+        /// Constructor
+        Record(type_t t, const IPAddr& i): type(t), ip(i) {}
+    };
+
+    /// Zona
+    struct Zone
+    {
+        /// Nombre
+        name_t name;
+        /// Time to live
+        size_t ttl;
+        /// Nodo padre
+        IPAddr parent;
+        /// Registros
+        typedef std::multimap< std::string, Record > records_t;
+        records_t records;
+        /// Constructores
+        Zone() {}
+        Zone(std::string sname, size_t ttl, const IPAddr& parent);
+        Zone(std::istream& is) throw (std::runtime_error);
+        /// Limpia una zona
+        void clear();
+    };
+
+    //TODO cache de _records_ (no zonas)
+
+    /// Zonas para las que este servidor de nombres es autoridad
+    typedef std::vector< Zone > zones_t;
+    zones_t zones;
+
+    /// Constructor
+    NameServer(std::istream& is) throw (std::runtime_error);
+
+};
+
+/// Impresión (para debug)
+std::ostream& operator<< (std::ostream& os, const NameServer& ns);
+std::ostream& operator<< (std::ostream& os, const NameServer::Record& r);
+std::ostream& operator<< (std::ostream& os, const NameServer::Zone& z);
+
+#endif // _NAMESERVER_H_
+
+// vim: set et sw=4 sts=4 :
diff --git a/practicas/pipi/src/test_nameserver_file.cpp b/practicas/pipi/src/test_nameserver_file.cpp
new file mode 100644 (file)
index 0000000..43a4215
--- /dev/null
@@ -0,0 +1,16 @@
+
+#include "nameserver.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+int main(int argc, char* argv[])
+{
+    std::ifstream ifs("test_nameserver_zones.txt");
+    NameServer ns(ifs);
+    std::cout << ns << "\n";
+    return 0;
+}
+
+// vim: set et sw=4 sts=4 :
diff --git a/practicas/pipi/src/test_nameserver_zones.txt b/practicas/pipi/src/test_nameserver_zones.txt
new file mode 100644 (file)
index 0000000..4752260
--- /dev/null
@@ -0,0 +1,24 @@
+mi.super.nombre        600     10.10.10.1
+tito   A       10.10.100.1
+juan   A       10.10.100.2
+juan   A       10.10.100.3
+pepe   A       10.10.100.4
+juan   A       10.10.100.5
+pepe   A       10.10.100.6
+otro   NS      10.10.100.100
+otro   NS      10.10.100.101
+mas    NS      10.10.200.1
+otro   NS      10.10.200.2
+
+mas.super.nombres      9500    10.10.1.100
+tito   A       10.1.100.1
+juan   A       10.1.100.2
+juan   A       10.1.100.3
+pepe   A       10.1.100.4
+juan   A       10.1.100.5
+pepe   A       10.1.100.6
+otro   NS      10.1.100.100
+otro   NS      10.1.100.101
+mas    NS      10.1.200.1
+otro   NS      10.1.200.2
+