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/functions.hpp>
11 #include <anna/core/mt/Guard.hpp>
12 #include <anna/core/tracing/TraceMethod.hpp>
14 #include <anna/xml/Node.hpp>
15 #include <anna/xml/Attribute.hpp>
17 #include <anna/comm/internal/LocalConnection.hpp>
18 #include <anna/comm/Communicator.hpp>
19 #include <anna/comm/Device.hpp>
20 #include <anna/comm/ServerSocket.hpp>
21 #include <anna/comm/ClientSocket.hpp>
22 #include <anna/comm/Receiver.hpp>
23 #include <anna/comm/CongestionController.hpp>
25 #include <anna/comm/handler/LocalConnection.hpp>
30 void comm::handler::LocalConnection::initialize()
32 LOGMETHOD(TraceMethod traceMethod("comm::handler::LocationConnection", "initialize", ANNA_FILE_LOCATION));
34 if(a_localConnection == NULL) {
35 string msg(asString());
36 msg += " | comm::LocalConnection was not established";
37 throw RuntimeException(msg, ANNA_FILE_LOCATION);
40 if(a_localConnection->getClientSocket() == NULL) {
41 string msg(asString());
42 msg += " | comm::ClientSocket was not established";
43 throw RuntimeException(msg, ANNA_FILE_LOCATION);
46 setfd(a_localConnection->getClientSocket()->getfd());
47 CongestionController::instantiate().incrementIncomingSocket();
50 comm::ClientSocket* comm::handler::LocalConnection::getClientSocket()
52 return (a_localConnection != NULL) ? a_localConnection->getClientSocket() : NULL;
56 * Se invoca desde Communicator::detach.
58 <Method Id="comm::handler::MetaClientSocket::apply" File="handler.db/comm.handler.MetaClientSocket.cc" Line="45" LineNo="281">
59 <Guard Id="0x68ccd0" Name="comm::ClientSocket from comm::handler::MetaClientSocket::apply" LineNo="283"/>
60 <Guard Id="0x68c6a0" Name="comm::Communicator::detach" LineNo="289">
61 <Method Id="comm::handler::LocationConnection::finalize" File="handler.db/comm.handler.LocalConnection.cc" Line="78" LineNo="293">
62 <Guard Id="0x68ccd0" Name="comm::Socket::close" LineNo="295">
63 <Guard Id="0x6818e0" Name="PN7anna4comm16TransportFactoryE" LineNo="297"/>
65 <Guard Id="0x68c678" Name="N7anna12SafeRecyclerINS_4comm15LocalConnectionENS_9AllocatorIS2_EEEE::release (T*)" LineNo="305"/>
71 void comm::handler::LocalConnection::finalize()
73 LOGMETHOD(TraceMethod traceMethod("comm::handler::LocationConnection", "finalize", ANNA_FILE_LOCATION));
75 if(a_localConnection == NULL)
78 comm::ClientSocket* clientSocket = a_localConnection->getClientSocket();
80 if(clientSocket != NULL) {
81 // Notificacion al Receiver (EDU Julio 2012)
84 if((receiver = clientSocket->getReceiver()) != NULL)
85 receiver->eventBreakLocalConnection(*clientSocket);
87 a_communicator->eventBreakLocalConnection(*clientSocket);
88 clientSocket->close();
91 comm::ServerSocket* serverSocket = a_localConnection->getServerSocket();
93 if(serverSocket != NULL) {
94 // serverSocket->eventBreakLocalConnection (a_localConnection); // @Eduardo (independence from communicator)
96 // Este lo quito porque ya tenemos el Receiver del clientSocket y eso cubre los dos tipos de politica de gestion de conexiones:
98 // (1) Un proceso servidor que admite N conexiones puede controlar las gestionadas mediante cierre/apertura del servidor de escucha (ServerSocket)
99 // Cuando llega al máximo configurado, hace un detach del comunicador (desaparece el LISTEN): communicator::detach(anna::comm::ServerSocket*)
100 // Cuando se rompe una conexion, se hace el attach del comunicador (aparece de nuevo el LISTEN): communicator::attach(anna::comm::ServerSocket*)
102 // (2) Un proceso servidor que admite N conexiones puede controlar las gestionadas mediante control de aceptacion devolviendo true o false al metodo
103 // virtual (eventAcceptConnection), void comm::handler::ServerSocket::apply ():
105 // bool accept = a_communicator->eventAcceptConnection (*localConnection->getClientSocket ());
107 // // @Eduardo (independence from communicator)
108 // if (accept) accept = a_serverSocket->eventAcceptConnection(*localConnection->getClientSocket ());
111 // (1) En este caso, si hemos ocupado todas las conexiones y no tenemos escucha, el ServerSocket ha desaparecido (es NULL) entonces NO INVOCARIA AL
112 // 'serverSocket->eventBreakLocalConnection (a_localConnection);' porque no pasa por este bloque (serverSocket es NULL) y la aplicación no puede ser notificada.
113 // Pero si la aplicacion establece un receiver al clientSocket recibido en el eventAcceptConnection, si sería notificada. Quito por lo tanto la notificacion
114 // 'serverSocket->eventBreakLocalConnection (a_localConnection)', porque si la politica es la (2), la aplicación sería notificada dos veces, lo cual no es deseable.
116 // (2) El problema de este metodo es el consumo de recursos, y sobre todo, que el cliente va a conectar y enviar paquetes que luego se sabe que no
117 // van a ninguna parte porque el accept devolverá un false y se cerrara dicha conexion. Es preferible que el cliente vea un connection refused
118 // por no existir un LISTEN
120 serverSocket->release(a_localConnection);
123 a_localConnection = NULL;
124 CongestionController::instantiate().decrementIncomingSocket();
127 string comm::handler::LocalConnection::asString() const
129 string result("comm::handler::LocalConnection { ");
130 result += comm::Handler::asString();
132 result += functions::asString(a_localConnection);
133 return result += " }";
136 xml::Node* comm::handler::LocalConnection::asXML(xml::Node* parent) const
138 xml::Node* result = parent->createChild("comm.handler.LocalConnection");
139 comm::Handler::asAttribute(result);
141 if(a_localConnection)
142 a_localConnection->asXML(result);