]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/pipi/src/devtcp.cpp
Se emprolija un poco la info de debug.
[z.facultad/75.74/practicos.git] / practicas / pipi / src / devtcp.cpp
1 #include "devtcp.h"
2 #include "ipaddr.h"
3 #include "libtcp.h"
4 #include <cstring>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/types.h>
8 #include <sys/ipc.h>
9 #include <sys/msg.h>
10 #include <sys/poll.h>
11 #ifdef DEBUG
12 #include <iostream>
13 #endif
14
15 #define ISSET(var, flag) ((var & flag) == flag)
16
17 DevTCP::DevTCP(mac_type mac, uint16_t port, size_t mtu)
18     throw (std::runtime_error, std::logic_error):
19         Dev(mac, mtu), port(port), pfds_size(1)
20 {
21     if ((pfds[0].fd = libtcp_open_pasivo(port)) == -1)
22         throw std::runtime_error("No se pudo crear el socket que escucha");
23     pfds[0].events = POLLIN | POLLPRI;
24 }
25
26 void DevTCP::transmit(const std::string& data, const mac_type& mac)
27     throw (std::runtime_error, std::logic_error)
28 {
29 #ifdef DEBUG_TRACE
30     std::cout << "DevTCP[" << port << "]::transmit()\n";
31 #endif
32     if (data.size() > mtu)
33         throw std::logic_error("Tamaño de datos mayor al MTU");
34     if (tx_pool.find(mac) == tx_pool.end()) // No existe la conexión
35     {
36         std::string addr = IPAddr(mac);
37 #ifdef DEBUG_QUE
38         std::cout << "DevTCP::transmit: conectando a " << addr << ":" << port << "\n";
39 #endif
40         tx_pool[mac] = libtcp_open_activo(addr.c_str(), port);
41         if (tx_pool[mac] == -1)
42             throw std::runtime_error("Error al conectar el socket");
43     }
44     size_t size = data.size();
45     if (libtcp_send(tx_pool[mac], &size, sizeof(size_t)) != sizeof(size_t))
46         throw std::runtime_error("Error al enviar por el socket");
47     if ((unsigned)libtcp_send(tx_pool[mac], data.data(), data.size()) != data.size())
48         throw std::runtime_error("Error al enviar por el socket");
49 #ifdef DEBUG_QUE
50     std::cout << "DevTCP::transmit(mac = " << mac << ", size = "
51         << data.size() << ")\n";
52 #endif
53 }
54
55 std::string DevTCP::receive() throw (std::runtime_error)
56 {
57 #ifdef DEBUG_TRACE
58     std::cout << "DevTCP[" << port << "]::receive()\n";
59 #endif
60     // Nos fijamos en todos los file descriptors si hay algo para nosotros.
61     while (true)
62     {
63         int res = poll(pfds, pfds_size, -1);
64         if (res == -1)
65             throw std::runtime_error("Error al hacer poll");
66         if (!res)
67             continue;
68         // Si tengo conexiones esperando, las atiendo...
69         if (ISSET(pfds[0].revents, POLLIN)
70                 || ISSET(pfds[0].revents, POLLPRI))
71         {
72             if (pfds_size == DEVTCP_MAX_CONN)
73                 throw std::runtime_error("Demasiadas conexiones activas");
74             pfds[pfds_size].fd = accept(pfds[0].fd, NULL, NULL);
75             if (pfds[pfds_size].fd == -1)
76                 throw std::runtime_error("Error al hacer accept");
77             pfds[pfds_size].events = POLLIN | POLLPRI;
78             ++pfds_size;
79         }
80         // Luego me fijo si tengo algún otro socket con cosas para recibir
81         for (size_t i = 1; i < pfds_size; ++i)
82         {
83             if (ISSET(pfds[i].revents, POLLIN)
84                     || ISSET(pfds[i].revents, POLLPRI))
85             {
86                 size_t size;
87                 int r = libtcp_receive_bin(pfds[i].fd, &size, sizeof(size_t));
88                 if (r != sizeof(size_t))
89                     // TODO cerrar socket?
90                     continue;
91                 char* buf = (char*)malloc(size);
92                 r = libtcp_receive_bin(pfds[i].fd, buf, size);
93                 if ((unsigned)r != size)
94                     // TODO cerrar socket?
95                     continue;
96                 std::string ret(buf, size);
97                 free(buf);
98 #ifdef DEBUG_QUE
99                 std::cout << "DevTCP::receive(msgtype/mac = " << mac << ", size = "
100                     << ret.size() << ")\n";
101 #endif
102                 return ret;
103             }
104         }
105     }
106     return ""; // No deberíamos caer nunca acá.
107 }
108
109 // vim: set et sw=4 sts=4 :