]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/pipi/src/resolver.cpp
3eee09c601abb07a8b9eeb3b5965996da0b9b6a7
[z.facultad/75.74/practicos.git] / practicas / pipi / src / resolver.cpp
1 #include "resolver.h"
2 #include <sstream>
3 #include <algorithm>
4 #include <iterator>
5 #include <sstream>
6 #include <functional>
7 #ifdef DEBUG
8 #include <iostream>
9 #endif
10
11 /// Parsea un archivo de nameservers
12 static std::istream& parseservers(std::istream& is, Resolver::ipvec_t& nss)
13     throw (std::runtime_error)
14 {
15     std::string ns;
16     // [nameserver ip]
17     while (std::getline(is, ns))
18     {
19         if (ns == "") continue; // Salteo líneas en blanco
20         nss.push_back(IPAddr(ns));
21 #ifdef DEBUG_PARSER
22         std::cout << "parseservers: IP = " << IPAddr(ns) << "\n";
23 #endif
24     }
25     return is;
26 }
27
28 /// Constructor
29 Resolver::Resolver(std::istream& is, IPIn& ipin, IPOut& ipout, DevQue& res_que)
30     throw (std::runtime_error):
31     ipin(ipin), ipout(ipout), res_que(res_que)
32 {
33     parseservers(is, nameservers);
34 }
35
36 /// Obtiene la(s) IP de un host a través de su nombre de dominio
37 Resolver::result_t Resolver::gethostbyname(const std::string& name,
38         ipvec_t& ips)
39 {
40     result_t result = NO_RECOVERY;
41     for (ipvec_t::const_iterator ip = nameservers.begin();
42             ip != nameservers.end(); ++ip)
43     {
44         ResolvProtoResponse r = query(name, *ip);
45         switch (r.ret)
46         {
47             case RP_RES_A:
48                 ips = r.ips;
49                 return OK;
50             case RP_RES_NOTFOUND:
51                 result = HOST_NOT_FOUND;
52                 continue;
53             default:
54 #ifdef DEBUG_RESOLV
55                 std::cout << "Resolver::gethostbyname ERROR!!! respuesta "
56                     "inesperada: " << r << "\n";
57 #endif
58                 return TRY_AGAIN;
59         }
60     }
61     return result;
62 }
63
64 /// Consulta a otro name server sobre un nombre
65 ResolvProtoResponse Resolver::query(const std::string& name, const IPAddr& ip)
66 {
67     ResolvProtoRequest r(name, RP_REQ_RECURSIVE);
68 #ifdef DEBUG_RESOLV
69     std::cout << "query -> pidiendo " << r << " a " << ip << "\n";
70 #endif
71     ipout.send(std::string(r), RESOLV_PROTO, ip);
72     Dev::mac_type mac = ip;
73     std::string buf = res_que.receive(mac);
74     ResolvProtoResponse resp(buf);
75 #ifdef DEBUG_RESOLV
76     std::cerr << "query -> recibido " << resp << " de " << ip << "\n";
77 #endif
78     return resp;
79 }
80
81 void Resolver::recv_loop()
82 {
83     while (true)
84     {
85         IPAddr src, dst;
86         uint8_t proto;
87         std::string s = ipin.recv(proto, src, dst);
88 #ifdef DEBUG_RESOLV
89             std::cout << "NameServer::recv_loop() -> recibido len=" << s.size()
90                 << " de " << src << " para " << dst << " (proto = "
91                 << unsigned(proto) << ")\n";
92 #endif
93         if (proto == RESOLV_PROTO) // Si es para nosotros
94         {
95             rp_pkt_type_t type;
96             memcpy(&type, s.data(), sizeof(uint8_t));
97             switch (type)
98             {
99                 // Request
100                 case RP_REQ_DIRECT:
101                 case RP_REQ_RECURSIVE:
102 #ifdef DEBUG_RESOLV
103                     std::cout << "---> Recibido un REQUEST!!! Algo esta roto! "
104                         << ResolvProtoRequest(s) << "\n";
105 #endif
106                     break;
107                 // Response
108                 default:
109 #ifdef DEBUG_RESOLV
110                     std::cout << "---> " << ResolvProtoResponse(s) << "\n";
111 #endif
112                     res_que.transmit(s, src); // Encolo
113             }
114         }
115 #ifdef DEBUG_RESOLV
116         else
117         {
118             std::cout << "---> Recibido paquete IP desconocido (proto="
119                 << unsigned(proto) << "): " << s << "\n";
120         }
121 #endif
122     }
123 }
124
125 std::ostream& operator<< (std::ostream& os, const Resolver& res)
126 {
127     return os << "Resolver(nameservers=" << res.nameservers << ")";
128 }
129
130 std::ostream& operator<< (std::ostream& os, const Resolver::ipvec_t& v)
131 {
132     os << "[";
133     if (v.empty())
134         return os << "]";
135     std::copy(v.begin(), v.end() - 1,
136             std::ostream_iterator< IPAddr >(os, ", "));
137     return os << v.back() << "]";
138 }
139
140 // vim: set et sw=4 sts=4 :