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 //
10 Ejemplo de programa servidor. Atiende peticiones aritmeticas, el protocolo de transporte sera HTTP
11 ver http::Transport y el contenido del mensaje sera el resutaldo de un comm::Codec con los
12 (x, y, op) -> El resultado sera estos tres componente mas result.
14 Para poder probar el sistema de congestion se puede indicar un numero de milisegundos de
15 retardo aplicados a cada contestacion.
17 Los clientes pueden ser: http_kclient.p http_client.p
21 #include <anna/core/core.hpp>
23 #include <anna/xml/Node.hpp>
24 #include <anna/xml/Attribute.hpp>
26 #include <anna/comm/comm.hpp>
28 #include <anna/http/Request.hpp>
29 #include <anna/http/Response.hpp>
30 #include <anna/http/Handler.hpp>
31 #include <anna/http/Transport.hpp>
32 #include <anna/http/functions.hpp>
34 #include <anna/test/Request.hpp>
35 #include <anna/test/Response.hpp>
36 #include <anna/test/Communicator.hpp>
42 class MyCommunicator : public test::Communicator {
47 class MyHandler : public http::Handler {
49 MyHandler () : http::Handler ("http_rserver::MyHandler") {;}
51 static const char* className () throw () { return "http_rserver::ReceiverFactory"; }
54 MyCommunicator* a_communicator;
55 test::Request a_testRequest;
56 test::Response a_testResponse;
58 void initialize () throw (RuntimeException);
59 void evRequest (ClientSocket&, const http::Request& request) throw (RuntimeException);
60 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException) {;}
63 class HTTPArithmeticServer : public comm::Application {
65 HTTPArithmeticServer ();
68 MyCommunicator a_communicator;
69 ReceiverFactoryImpl <MyHandler> a_receiverFactory;
70 comm::ServerSocket* a_serverSocket;
72 void initialize () throw (RuntimeException);
73 void run () throw (RuntimeException);
74 xml::Node* asXML (xml::Node* app) const throw ();
78 using namespace anna::comm;
80 int main (int argc, const char** argv)
82 CommandLine& commandLine (CommandLine::instantiate ());
83 HTTPArithmeticServer app;
85 http::functions::initialize ();
90 commandLine.initialize (argv, argc);
91 commandLine.verify ();
93 Logger::setLevel (Logger::Debug);
94 Logger::initialize ("http_server", new anna::TraceWriter ("file.trace", 4048000));
98 catch (Exception& ex) {
99 cout << ex.asString () << endl;
105 HTTPArithmeticServer::HTTPArithmeticServer () :
106 Application ("http_rserver", "Servidor HTTP de operaciones aritmeticas (iRS)", "1.0")
108 CommandLine& commandLine (CommandLine::instantiate ());
110 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
111 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP en la que atender");
112 commandLine.add ("d", CommandLine::Argument::Mandatory, "Retardo aplicado a la contestacion");
113 commandLine.add ("r", CommandLine::Argument::Optional, "Indicador de reuso de direccin", false);
114 commandLine.add ("limit", CommandLine::Argument::Mandatory, "% de ocupacion que permitimos");
115 commandLine.add ("n", CommandLine::Argument::Optional, "Numero de mensajes a servir", true);
116 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
117 commandLine.add ("timeout", CommandLine::Argument::Optional, "Timeout (ms) del cliente sin enviar peticiones");
118 commandLine.add ("quota", CommandLine::Argument::Optional, "Numero de bytes aceptados antes de cerrar el socket");
121 void HTTPArithmeticServer::initialize ()
122 throw (RuntimeException)
124 CommandLine& cl (CommandLine::instantiate ());
126 int port = cl.getIntegerValue ("p");
127 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
129 comm::TransportFactory* ttff = &http::Transport::getFactory ();
131 if (cl.exists ("quota") == true)
132 ttff->setOverQuotaSize (cl.getIntegerValue ("quota"));
134 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"), ttff);
135 a_serverSocket->setReceiverFactory (a_receiverFactory);
138 void HTTPArithmeticServer::run ()
139 throw (RuntimeException)
141 CommandLine& cl (CommandLine::instantiate ());
143 a_communicator.attach (a_serverSocket);
144 a_communicator.setDelay ((Millisecond)cl.getIntegerValue ("d"));
146 if (cl.exists ("n") == true)
147 a_communicator.setMaxMessage (cl.getIntegerValue ("n"));
149 if (cl.exists ("trace"))
150 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
152 CongestionController::instantiate ().setLimit (cl.getIntegerValue ("limit"));
154 if (cl.exists ("timeout") == true)
155 a_communicator.setTimeout ((Millisecond)cl.getIntegerValue ("timeout"));
157 a_communicator.accept ();
160 xml::Node* HTTPArithmeticServer::asXML (xml::Node* app) const
163 xml::Node* node = app::Application::asXML (app);
165 node->createAttribute ("MaxMessage", a_communicator.getMaxMessage ());
166 node->createAttribute ("Message", a_communicator.getMessage ());
171 void MyHandler::initialize ()
172 throw (RuntimeException)
174 a_communicator = app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION);
175 allocateResponse ()->createHeader (http::Header::Type::Date);
178 void MyHandler::evRequest (ClientSocket& clientSocket, const http::Request& request)
179 throw (RuntimeException)
181 LOGMETHOD (TraceMethod tm ("MyReceiver", "apply", ANNA_FILE_LOCATION));
183 if (a_communicator->canContinue (clientSocket) == false)
186 const DataBlock& body = request.getBody ();
188 if (body.getSize () == 0)
189 throw RuntimeException ("La peticion no incorpora los parametros de operacion", ANNA_FILE_LOCATION);
192 string msg ("Body recibido: ");
193 msg += anna::functions::asString (body);
194 Logger::information (msg, ANNA_FILE_LOCATION);
197 if (Codec::getType (body) != test::Request::Id)
198 throw RuntimeException ("El mensaje recibido no es una peticion aritmetica", ANNA_FILE_LOCATION);
200 a_testRequest.decode (body);
202 a_communicator->delay ();
204 a_testResponse.x = a_testRequest.x;
205 a_testResponse.y = a_testRequest.y;
206 a_testResponse.initTime = a_testRequest.initTime;
208 http::Response* response = allocateResponse ();
210 response->setStatusCode (200);
212 switch (a_testResponse.op = a_testRequest.op) {
214 a_testResponse.result = a_testRequest.x + a_testRequest.y;
217 a_testResponse.result = a_testRequest.x - a_testRequest.y;
220 a_testResponse.result = a_testRequest.x * a_testRequest.y;
223 if (a_testRequest.y == 0) {
224 response->setStatusCode (400);
225 response->setReasonPhrase ("Division por cero");
226 a_testResponse.result = 0;
229 a_testResponse.result = a_testRequest.x / a_testRequest.y;
233 response->setBody (a_testResponse.code ());
235 response->find (http::Header::Type::Date)->setValue ("Mon, 30 Jan 2006 14:36:18 GMT");
237 http::Header* keepAlive = response->find ("Keep-Alive");
239 if (keepAlive == NULL)
240 keepAlive = response->createHeader ("Keep-Alive");
242 keepAlive->setValue ("Verificacion del cambio 1.0.7");
245 string msg = anna::functions::asString ("%d %c %d = %d", a_testRequest.x, a_testRequest.op, a_testRequest.y, a_testResponse.result);
246 Logger::information (msg, ANNA_FILE_LOCATION);
250 clientSocket.send (*response);
252 catch (Exception& ex) {