1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
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 //
12 #include <sys/types.h>
17 #include <anna/core/tracing/Logger.hpp>
18 #include <anna/core/tracing/TraceMethod.hpp>
19 #include <anna/core/DataBlock.hpp>
21 #include <anna/xml/Node.hpp>
23 #include <anna/comm/Socket.hpp>
24 #include <anna/comm/INetAddress.hpp>
25 #include <anna/comm/functions.hpp>
26 #include <anna/comm/Application.hpp>
27 #include <anna/comm/TransportFactory.hpp>
28 #include <anna/comm/ReceiverFactory.hpp>
32 using namespace anna::comm;
34 Socket::Socket(const Domain::_v domain, const Type::_v type, TransportFactory* transportFactory) :
41 a_receiverFactory(NULL) {
42 if((a_transportFactory = transportFactory) == NULL) {
44 comm::Application& app = comm::functions::getApp();
45 a_transportFactory = &app.comm::Application::getDefaultTransportFactory();
46 } catch(Exception& ex) {
52 Socket::Socket(const INetAddress& localAddress, const Type::_v type, TransportFactory* transportFactory) :
53 a_domain(Domain::Inet),
56 a_localAccessPoint(localAddress),
60 a_receiverFactory(NULL) {
61 if((a_transportFactory = transportFactory) == NULL) {
63 comm::Application& app = comm::functions::getApp();
64 a_transportFactory = &app.comm::Application::getDefaultTransportFactory();
65 } catch(Exception& ex) {
71 Socket::Socket(const std::string& path, const Type::_v type, TransportFactory* transportFactory) :
72 a_transportFactory(NULL),
73 a_domain(Domain::Unix),
76 a_localAccessPoint(path),
80 a_receiverFactory(NULL) {
81 if((a_transportFactory = transportFactory) == NULL) {
83 comm::Application& app = comm::functions::getApp();
84 a_transportFactory = &app.comm::Application::getDefaultTransportFactory();
85 } catch(Exception& ex) {
94 } catch(RuntimeException& ex) {
99 bool Socket::support(const char* transportClassName) const
101 if(a_transportFactory == NULL)
104 return anna_strcmp(a_transportFactory->getName().c_str(), transportClassName) == 0;
107 //---------------------------------------------------------------------------
108 // No hace falta que sea MT-safe porque siempre se invoca desde m�odo que
109 // ya tienen activa su propia zona de exclusin.
110 //---------------------------------------------------------------------------
112 throw(RuntimeException) {
116 if(a_transportFactory == NULL) {
117 std::string msg(asString());
118 msg += " | Transport factory was not especified";
119 throw RuntimeException(msg, ANNA_FILE_LOCATION);
122 anna_comm_socket_check(a_fd = socket((int) a_domain, (int) a_type, 0), "Cannot create the socket");
124 socklen_t len = sizeof(int);
125 anna_comm_socket_check(
126 getsockopt(a_fd, SOL_SOCKET, SO_REUSEADDR, &value, &len),
127 "Cannot obtain reuse mode"
129 a_reuseMode = (value == 1);
131 if(a_type == Type::Datagram) {
133 anna_comm_socket_check(
134 setsockopt(a_fd, SOL_SOCKET, SO_BROADCAST, &value, sizeof(int)),
135 "Cannot activate broadcast system"
140 string msg("comm::Socket::open | ");
142 Logger::debug(msg, ANNA_FILE_LOCATION);
151 Guard guard(*this, "comm::Socket::close");
160 string msg("comm::Socket::close | ");
162 Logger::debug(msg, ANNA_FILE_LOCATION);
166 bool Socket::setBlockingMode(const bool blockingMode)
167 throw(RuntimeException) {
170 anna_socket_assert(a_fd == -1, "Socket is not opened");
171 anna_comm_socket_check(opts = fcntl(a_fd, F_GETFL), "Cannot obtain state bits (F_GETFL)");
172 result = !(opts & O_NONBLOCK);
174 if(blockingMode == false)
179 anna_comm_socket_check(fcntl(a_fd, F_SETFL, opts), "Cannot set state bits (F_SETFL)");
181 string msg("comm::Socket::setBlockingMode | Current: ");
182 msg += functions::asString(blockingMode);
183 msg += functions::asText(" | Previous: ", result != 0);
184 Logger::debug(msg, ANNA_FILE_LOCATION);
186 return (result != 0);
189 bool Socket::setReuseMode(const bool reuseMode)
190 throw(RuntimeException) {
191 anna_socket_assert(a_fd == -1, "Socket is not opened");
193 if(a_reuseMode == reuseMode)
197 result = a_reuseMode;
198 int value = htons((a_reuseMode = reuseMode) == true);
199 anna_comm_socket_check(
200 setsockopt(a_fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)),
201 "Cannot set the reuse mode"
207 throw(RuntimeException) {
208 Guard guard(*this, "comm::Socket::bind");
213 anna_socket_assert(a_isBound == true, "Already attached");
217 a_localAccessPoint.translate(*this, s, len);
219 if(do_bind(s, len) < 0) {
220 RuntimeException ex(asString(), errno, ANNA_FILE_LOCATION);
227 string msg("comm::Socket::bind | ");
229 Logger::debug(msg, ANNA_FILE_LOCATION);
233 int Socket::do_bind(const struct sockaddr *addr, const int len)
234 throw(RuntimeException) {
235 return ::bind(a_fd, addr, len);
238 std::string Socket::asString() const
240 std::string msg("comm::Socket { Domain: ");
243 return msg += " <null> }";
246 case Domain::Unix: msg += "Unix"; break;
247 case Domain::Inet: msg += "Inet"; break;
248 default: msg += '<'; msg += functions::asString((int) a_domain); msg += '>'; break;
252 msg += (a_type == Type::Stream) ? "Stream" : "Datagram";
255 if(a_transportFactory != NULL) {
256 msg += a_transportFactory->asString();
261 msg += functions::asString(a_fd);
262 msg += " | LocalPoint: ";
263 a_localAccessPoint.asString(msg);
265 msg += functions::asString(a_isBound);
266 msg += " | Opened: ";
267 msg += functions::asString(isOpened());
270 msg += functions::asText(" | Category: ", a_category);
272 if(a_receiverFactory != NULL) {
274 msg += a_receiverFactory->asString();
280 xml::Node* Socket::asXML(xml::Node* parent) const
281 throw(RuntimeException) {
283 xml::Node* result = parent->createChild("comm.Socket");
286 case Domain::Unix: aux = "Unix"; break;
287 case Domain::Inet: aux = "Inet"; break;
288 default: aux = functions::asString((int) a_domain).c_str(); break;
291 result->createAttribute("Domain", aux);
292 result->createAttribute("Type", (a_type == Type::Stream) ? "Stream" : "Datagram");
294 if(a_transportFactory != NULL)
295 a_transportFactory->asXML(result);
297 result->createAttribute("fd", a_fd);
298 result->createAttribute("Bound", functions::asString(a_isBound));
299 result->createAttribute("Opened", functions::asString(isOpened()));
300 a_localAccessPoint.asXML("comm.LocalPoint", result);
305 if((opts = fcntl(a_fd, F_GETFL)) != -1)
306 result->createAttribute("Mode", (opts & O_NONBLOCK) ? "Non-Blocking" : "Blocking");
310 result->createAttribute("Category", a_category);
312 if(a_receiverFactory != NULL)
313 a_receiverFactory->asXML(result);
318 const char* Socket::asText(const Socket::Notify::_v v)
320 static const char* text [] = { "None", "ReceiveData", "Close", "Corrupt" };