Remove dynamic exceptions
[anna.git] / source / comm / Network.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #include <netdb.h>
10
11 #include <anna/core/tracing/Logger.hpp>
12
13 #include <anna/comm/Network.hpp>
14
15 #include <anna/comm/Device.hpp>
16 #include <anna/comm/Host.hpp>
17 #include <anna/comm/Server.hpp>
18
19 #include <anna/xml/Node.hpp>
20 #include <anna/xml/Attribute.hpp>
21
22 using namespace std;
23 using namespace anna;
24
25 comm::Device* comm::Network::find(const in_addr_t& address)
26 {
27   Device* result = NULL;
28
29   if(a_cacheDevice != NULL && *a_cacheDevice == address)
30     return a_cacheDevice;
31
32   for(device_iterator ii = device_begin(), maxii = device_end(); ii != maxii; ii ++) {
33     result = device(ii);
34
35     if(*result == address)
36       return a_cacheDevice = result;
37   }
38
39   a_devices.push_back(result = new Device(address));
40   return a_cacheDevice = result;
41 }
42
43 comm::Host* comm::Network::find_host(const char* name)
44 {
45   Host* result = NULL;
46
47   if(a_cacheHost != NULL && anna_strcmp(a_cacheHost->getName().c_str(), name) == 0)
48     return a_cacheHost;
49
50   for(host_iterator ii = host_begin(), maxii = host_end(); ii != maxii; ii ++) {
51     result = host(ii);
52
53     if(anna_strcmp(result->getName().c_str(), name) == 0)
54       return a_cacheHost = result;
55   }
56
57   a_hosts.push_back(result = new Host(name));
58   return a_cacheHost = result;
59 }
60
61 comm::Host* comm::Network::resolve(const char* hostname)
62 noexcept(false) {
63   comm::Host* result = find_host(hostname);
64   struct hostent *host;
65
66   if((host = gethostbyname(hostname)) == NULL) {
67     string msg("comm::Network::resolve | Host: ");
68     msg += hostname;
69     msg += " | ";
70     msg += hstrerror(h_errno);
71     throw RuntimeException(msg, ANNA_FILE_LOCATION);
72   }
73
74   if(host->h_addrtype != AF_INET) {
75     string msg("comm::Network::resolve | Host: ");
76     msg += hostname;
77     msg += " | Address type unsupported";
78     throw RuntimeException(msg, ANNA_FILE_LOCATION);
79   }
80
81   for(int i = 0; host->h_addr_list[i] != NULL; i ++) {
82     const in_addr_t& address = *reinterpret_cast <in_addr_t*>(host->h_addr_list[i]);
83     LOGDEBUG(
84       string msg("comm::Network::resolve | Host: ");
85       msg += hostname;
86       msg += " | IP: ";
87       msg += inet_ntoa(*reinterpret_cast <in_addr*>(host->h_addr_list[i]));
88       Logger::debug(msg, ANNA_FILE_LOCATION);
89     );
90     result->assign(find(address));
91   }
92
93   return result;
94 }
95
96
97 comm::Server* comm::Network::createServer(const char* ip, const int remotePort, const bool autoRecovery, comm::TransportFactory* transportFactory, const Port::_v mode, const DoConnect::_v doConnect)
98 noexcept(false) {
99   comm::Server* result(NULL);
100   comm::Host* host = find_host(ip);
101   Guard guard(host, "comm::Host from comm::Network::createServer");
102
103   if(mode == Port::Unique) {
104     /**
105      * Si ya existe una conexión previa con esa (ip, port) la devuelve
106      */
107     if((result = host->find_server(remotePort)) != NULL)
108       return result;
109   }
110
111   comm::Device* device = find(comm::Device::asAddress(ip));
112   host->assign(device);
113   string serverName = ip;
114   serverName += functions::asText(":", remotePort);
115   return host->createServer(serverName, remotePort, autoRecovery, transportFactory, false /* ignore incoming messages */, (doConnect == DoConnect::Yes));
116 }
117
118 comm::Server* comm::Network::createServer(const char* ip, const int remotePort, const bool autoRecovery, comm::ReceiverFactory& rrff, comm::TransportFactory* transportFactory, const Port::_v mode, const DoConnect::_v doConnect)
119 noexcept(false) {
120   Server* result = createServer(ip, remotePort, autoRecovery, transportFactory, mode, doConnect);
121   result->setReceiverFactory(rrff);
122   return result;
123 }
124
125 //comm::Server* comm::Network::findServer (const char* ip, const int remotePort)
126 //   noexcept(false)
127 //{
128 //   comm::Host* _host (NULL);
129 //
130 //   for (host_iterator ii = host_begin (), maxii = host_end (); ii != maxii; ii ++) {
131 //      if (host (ii)->getName () == ip) {
132 //         _host = host (ii);
133 //         break;
134 //      }
135 //   }
136 //
137 //   return (_host == NULL) ? NULL: _host->find_server (remotePort);
138 //}
139
140
141 comm::Server* comm::Network::resolveServer(const char* hostname, const int remotePort, const bool autoRecovery, comm::TransportFactory* transportFactory, const Port::_v mode, const DoConnect::_v doConnect)
142 noexcept(false) {
143   comm::Server* result(NULL);
144   comm::Host* host = resolve(hostname);
145   Guard guard(host, "comm::Host from comm::Network::resolveServer");
146
147   if(mode == Port::Unique) {
148     /**
149      * Si ya existe una conexión previa con esa (ip, port) la devuelve
150      */
151     if((result = host->find_server(remotePort)) != NULL)
152       return result;
153   }
154
155   string serverName = hostname;
156   serverName += functions::asText(":", remotePort);
157   return host->createServer(serverName, remotePort, autoRecovery, transportFactory, false /* ignore incoming messages */, (doConnect == DoConnect::Yes));
158 }
159
160 comm::Server* comm::Network::resolveServer(const char* hostname, const int remotePort, const bool autoRecovery, comm::ReceiverFactory& rrff, comm::TransportFactory* transportFactory, const Port::_v mode, const DoConnect::_v doConnect)
161 noexcept(false) {
162   Server* result = resolveServer(hostname, remotePort, autoRecovery, transportFactory, mode, doConnect);
163   result->setReceiverFactory(rrff);
164   return result;
165 }
166
167 comm::INetAddress comm::Network::getINetAddress(const char* ip, const int port)
168 noexcept(false) {
169   const Device* device = find(Device::asAddress(ip));
170   return INetAddress(device, port);
171 }
172
173 comm::INetAddress comm::Network::getINetAddress(const std::string& ip, const int port)
174 noexcept(false) {
175   const Device* device = find(Device::asAddress(ip));
176   return INetAddress(device, port);
177 }
178
179 xml::Node* comm::Network::asXML(xml::Node* parent) const
180 {
181   xml::Node* result = parent->createChild("comm.Network");
182   xml::Node* node = result->createChild("comm.Devices");
183
184   for(const_device_iterator ii = device_begin(), maxii = device_end(); ii != maxii; ii ++)
185     device(ii)->asXML(node);
186
187   node = result->createChild("comm.Hosts");
188
189   for(const_host_iterator ii = host_begin(), maxii = host_end(); ii != maxii; ii ++)
190     host(ii)->asXML(node);
191
192   return result;
193 }
194