1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
39 #include <anna/core/tracing/Logger.hpp>
41 #include <anna/comm/Network.hpp>
43 #include <anna/comm/Device.hpp>
44 #include <anna/comm/Host.hpp>
45 #include <anna/comm/Server.hpp>
47 #include <anna/xml/Node.hpp>
48 #include <anna/xml/Attribute.hpp>
53 comm::Device* comm::Network::find(const in_addr_t& address)
55 Device* result = NULL;
57 if(a_cacheDevice != NULL && *a_cacheDevice == address)
60 for(device_iterator ii = device_begin(), maxii = device_end(); ii != maxii; ii ++) {
63 if(*result == address)
64 return a_cacheDevice = result;
67 a_devices.push_back(result = new Device(address));
68 return a_cacheDevice = result;
71 comm::Host* comm::Network::find_host(const char* name)
75 if(a_cacheHost != NULL && anna_strcmp(a_cacheHost->getName().c_str(), name) == 0)
78 for(host_iterator ii = host_begin(), maxii = host_end(); ii != maxii; ii ++) {
81 if(anna_strcmp(result->getName().c_str(), name) == 0)
82 return a_cacheHost = result;
85 a_hosts.push_back(result = new Host(name));
86 return a_cacheHost = result;
89 comm::Host* comm::Network::resolve(const char* hostname)
90 throw(RuntimeException) {
91 comm::Host* result = find_host(hostname);
94 if((host = gethostbyname(hostname)) == NULL) {
95 string msg("comm::Network::resolve | Host: ");
98 msg += hstrerror(h_errno);
99 throw RuntimeException(msg, ANNA_FILE_LOCATION);
102 if(host->h_addrtype != AF_INET) {
103 string msg("comm::Network::resolve | Host: ");
105 msg += " | Address type unsupported";
106 throw RuntimeException(msg, ANNA_FILE_LOCATION);
109 for(int i = 0; host->h_addr_list[i] != NULL; i ++) {
110 const in_addr_t& address = *reinterpret_cast <in_addr_t*>(host->h_addr_list[i]);
112 string msg("comm::Network::resolve | Host: ");
115 msg += inet_ntoa(*reinterpret_cast <in_addr*>(host->h_addr_list[i]));
116 Logger::debug(msg, ANNA_FILE_LOCATION);
118 result->assign(find(address));
125 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)
126 throw(RuntimeException) {
127 comm::Server* result(NULL);
128 comm::Host* host = find_host(ip);
129 Guard guard(host, "comm::Host from comm::Network::createServer");
131 if(mode == Port::Unique) {
133 * Si ya existe una conexión previa con esa (ip, port) la devuelve
135 if((result = host->find_server(remotePort)) != NULL)
139 comm::Device* device = find(comm::Device::asAddress(ip));
140 host->assign(device);
141 string serverName = ip;
142 serverName += functions::asText(":", remotePort);
143 return host->createServer(serverName, remotePort, autoRecovery, transportFactory, false /* ignore incoming messages */, (doConnect == DoConnect::Yes));
146 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)
147 throw(RuntimeException) {
148 Server* result = createServer(ip, remotePort, autoRecovery, transportFactory, mode, doConnect);
149 result->setReceiverFactory(rrff);
153 //comm::Server* comm::Network::findServer (const char* ip, const int remotePort)
154 // throw (RuntimeException)
156 // comm::Host* _host (NULL);
158 // for (host_iterator ii = host_begin (), maxii = host_end (); ii != maxii; ii ++) {
159 // if (host (ii)->getName () == ip) {
160 // _host = host (ii);
165 // return (_host == NULL) ? NULL: _host->find_server (remotePort);
169 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)
170 throw(RuntimeException) {
171 comm::Server* result(NULL);
172 comm::Host* host = resolve(hostname);
173 Guard guard(host, "comm::Host from comm::Network::resolveServer");
175 if(mode == Port::Unique) {
177 * Si ya existe una conexión previa con esa (ip, port) la devuelve
179 if((result = host->find_server(remotePort)) != NULL)
183 string serverName = hostname;
184 serverName += functions::asText(":", remotePort);
185 return host->createServer(serverName, remotePort, autoRecovery, transportFactory, false /* ignore incoming messages */, (doConnect == DoConnect::Yes));
188 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)
189 throw(RuntimeException) {
190 Server* result = resolveServer(hostname, remotePort, autoRecovery, transportFactory, mode, doConnect);
191 result->setReceiverFactory(rrff);
195 comm::INetAddress comm::Network::getINetAddress(const char* ip, const int port)
196 throw(RuntimeException) {
197 const Device* device = find(Device::asAddress(ip));
198 return INetAddress(device, port);
201 comm::INetAddress comm::Network::getINetAddress(const std::string& ip, const int port)
202 throw(RuntimeException) {
203 const Device* device = find(Device::asAddress(ip));
204 return INetAddress(device, port);
207 xml::Node* comm::Network::asXML(xml::Node* parent) const
209 xml::Node* result = parent->createChild("comm.Network");
210 xml::Node* node = result->createChild("comm.Devices");
212 for(const_device_iterator ii = device_begin(), maxii = device_end(); ii != maxii; ii ++)
213 device(ii)->asXML(node);
215 node = result->createChild("comm.Hosts");
217 for(const_host_iterator ii = host_begin(), maxii = host_end(); ii != maxii; ii ++)
218 host(ii)->asXML(node);