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 //
9 #include <anna/core/tracing/Logger.hpp>
10 #include <anna/core/tracing/TraceMethod.hpp>
11 #include <anna/config/defines.hpp>
12 #include <anna/core/functions.hpp>
14 #include <anna/xml/Node.hpp>
15 #include <anna/xml/Attribute.hpp>
17 #include <anna/comm/ServerSocket.hpp>
18 #include <anna/comm/internal/BinderSocket.hpp>
19 #include <anna/comm/ClientSocket.hpp>
25 const Millisecond comm::ServerSocket::DefaultBindDelay(200);
27 comm::ServerSocket::~ServerSocket() {
28 delete a_binderSocket;
31 void comm::ServerSocket::prepare()
32 throw(RuntimeException) {
33 if (::listen(Socket::a_fd, a_backlog) == -1) {
34 const int xerrno(errno);
35 std::string msg(asString());
37 throw RuntimeException(msg, xerrno, ANNA_FILE_LOCATION);
41 int comm::ServerSocket::do_bind(const struct sockaddr* s, const int len)
42 throw(RuntimeException) {
43 if (a_sharedBind == false)
44 return Socket::do_bind(s, len);
46 if (a_binderSocket == NULL)
47 a_binderSocket = new BinderSocket(this);
49 a_binderSocket->requestBind(s, len);
53 * (1) Se invoca desde [Tx], pero hay que evitar que el .create se invoque a la misma vez que algún [Tz] este invocando
54 * al ServerSocket::release porque ha cerrado la conexión.
56 comm::LocalConnection* comm::ServerSocket::accept()
57 throw(RuntimeException) {
58 LOGMETHOD(TraceMethod traceMethod(Logger::Local7, "comm::ServerSocket", "accept", ANNA_FILE_LOCATION));
59 LocalConnection* result(NULL);
60 sockaddr_in sourceAddress;
61 socklen_t len(sizeof(sockaddr_in));
62 anna_memset(&sourceAddress, 0, sizeof(sockaddr_in));
63 int newSocket = ::accept(Socket::a_fd, (sockaddr*) & sourceAddress, &len);
66 const int xerrno = errno;
68 if (xerrno != EWOULDBLOCK && xerrno != EINTR)
69 throw RuntimeException(asString(), xerrno, ANNA_FILE_LOCATION);
71 result = a_localConnections.create(); // (1)
74 result->setServerSocket(this);
75 ClientSocket* clientSocket;
77 if ((clientSocket = result->getClientSocket()) == NULL) {
78 clientSocket = allocateClientSocket();
79 result->setClientSocket(clientSocket);
81 string msg("comm::ServerSocket::accept | New ClientSocket: ");
82 msg += functions::asHexString(anna_ptrnumber_cast(clientSocket));
83 msg += functions::asText(" | fd: ", newSocket);
84 Logger::debug(msg, ANNA_FILE_LOCATION);
88 string msg("comm::ServerSocket::accept | Reuse ClientSocket: ");
89 msg += functions::asHexString(anna_ptrnumber_cast(clientSocket));
90 msg += functions::asText(" | fd: ", newSocket);
91 Logger::debug(msg, ANNA_FILE_LOCATION);
95 clientSocket->setfd(newSocket);
96 clientSocket->setCategory(getCategory());
97 clientSocket->setReceiverFactory(*getReceiverFactory());
99 string msg("comm::ServerSocket::accept | ");
102 msg += result->asString();
103 Logger::debug(msg, ANNA_FILE_LOCATION);
105 } catch (RuntimeException&) {
115 comm::ClientSocket* comm::ServerSocket::allocateClientSocket() const
117 return new ClientSocket(getTransportFactory(), Socket::Domain::Inet, Socket::Type::Stream);
121 * Se invoca desde el [Tz] = LocalConnection:[Tx] -> Communicator
122 * De forma que hay que bloquear esta instancia para que SU [Tx] no vaya a crear en este momento una nueva conexión.
125 * Se invoca desde comm::handler::ServerSocket::apply::[Tx] -> <null>
127 void comm::ServerSocket::release(LocalConnection* localConnection)
128 throw(RuntimeException) {
129 if (localConnection == NULL)
132 if (localConnection != NULL)
133 localConnection->setServerSocket(NULL);
135 a_localConnections.release(localConnection);
138 std::string comm::ServerSocket::asString() const
140 std::string msg("comm::ServerSocket { ");
141 msg += comm::Socket::asString();
144 if (a_sharedBind == true) {
146 msg += functions::asString(a_binderSocket);
153 xml::Node* comm::ServerSocket::asXML(xml::Node* parent) const
154 throw(RuntimeException) {
155 xml::Node* result = parent->createChild("comm.ServerSocket");
156 comm::Socket::asXML(result);
157 result->createAttribute("Bind", (a_sharedBind) ? "Shared" : "Exclusive");
159 if (a_sharedBind == true && a_binderSocket != NULL)
160 a_binderSocket->asXML(result);