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: wims20_kclient.p wims20_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/http/wims20/ServerSide.hpp>
38 class MyCommunicator : public comm::Communicator {
43 class MyHandler : public http::Handler {
45 MyHandler () : http::Handler ("wims20_rserver::MyHandler"), a_request (NULL) {;}
47 static const char* className () throw () { return "wims20_rserver::ReceiverFactory"; }
50 MyCommunicator* a_communicator;
51 http::wims20::ServerSide* a_request;
53 void initialize () throw (RuntimeException);
54 void evRequest (ClientSocket&, const http::Request& request) throw (RuntimeException);
55 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException) {;}
58 class HTTPArithmeticServer : public comm::Application {
60 HTTPArithmeticServer ();
63 MyCommunicator a_communicator;
64 ReceiverFactoryImpl <MyHandler> a_receiverFactory;
65 comm::ServerSocket* a_serverSocket;
67 void initialize () throw (RuntimeException);
68 void run () throw (RuntimeException);
72 using namespace anna::comm;
74 int main (int argc, const char** argv)
76 CommandLine& commandLine (CommandLine::instantiate ());
77 HTTPArithmeticServer app;
79 http::functions::initialize ();
84 commandLine.initialize (argv, argc);
85 commandLine.verify ();
87 Logger::setLevel (Logger::Debug);
88 Logger::initialize ("wims20_server", new anna::TraceWriter ("file.trace", 4048000));
92 catch (Exception& ex) {
93 cout << ex.asString () << endl;
99 HTTPArithmeticServer::HTTPArithmeticServer () :
100 Application ("wims20_rserver", "Servidor HTTP/WIMS 2.0 de operaciones aritmeticas (iRS)", "1.0")
102 CommandLine& commandLine (CommandLine::instantiate ());
104 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
105 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccion IP en la que atender");
106 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
107 commandLine.add ("domain", CommandLine::Argument::Mandatory, "Domain indicado en la peticion WIMS 2.0");
108 commandLine.add ("path", CommandLine::Argument::Optional, "Path indicado en la peticion WIMS 2.0");
111 void HTTPArithmeticServer::initialize ()
112 throw (RuntimeException)
114 CommandLine& cl (CommandLine::instantiate ());
116 int port = cl.getIntegerValue ("p");
117 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
119 comm::TransportFactory* ttff = &http::Transport::getFactory ();
121 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"), ttff);
122 a_serverSocket->setReceiverFactory (a_receiverFactory);
125 void HTTPArithmeticServer::run ()
126 throw (RuntimeException)
128 CommandLine& cl (CommandLine::instantiate ());
130 a_communicator.attach (a_serverSocket);
132 if (cl.exists ("trace"))
133 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
135 a_communicator.accept ();
138 void MyHandler::initialize ()
139 throw (RuntimeException)
141 CommandLine& cl (CommandLine::instantiate ());
143 string domain = cl.getValue ("domain");
145 if (cl.exists ("path")) {
146 string path = cl.getValue ("path");
147 a_request = new http::wims20::ServerSide (domain, path);
150 a_request = new http::wims20::ServerSide (domain);
152 a_communicator = app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION);
153 allocateResponse ()->createHeader (http::Header::Type::Date);
156 // Recibe una petición de operación aritmética y visualiza el resultado por pantalla.
157 // Para mantener la simplicidad del ejemplo sólo notifica al cliente si ha ido bien
158 // o no, pero no deuuelve ningún resultado
160 // Definimos que nuestro servicio deberá recibir una petición REST de la forma:
161 // http://<domain>/<path>/math/guest@tid.es/<op>?X=nnn&Y=nnn
162 // Observar que la <op> correspondería con las parte other_possible_levels
163 // de la especificación WIMS 2.0
164 void MyHandler::evRequest (ClientSocket& clientSocket, const http::Request& request)
165 throw (RuntimeException)
167 LOGMETHOD (TraceMethod tm ("MyReceiver", "apply", ANNA_FILE_LOCATION));
169 a_request->decode (request);
171 cout << a_request->asString () << endl << endl;
173 http::Response* response = allocateResponse ();
175 if (a_request->getServiceID () != "math" || a_request->getGUID () != "user@tid.es") {
176 response->setStatusCode (401);
177 clientSocket.send (*response);
181 if (a_request->hasOtherLevels () == false) {
182 response->setStatusCode (416);
183 clientSocket.send (*response);
187 // El primer nivel indica la operación a realizar
188 const std::string& op = *http::wims20::ServerSide::otherLevel (a_request->other_level_begin ());
193 x = a_request->getIntegerValue ("X");
194 y = a_request->getIntegerValue ("Y");
195 response->setStatusCode (200);
198 cout << x << " + " << y << " = " << x + y << endl << endl;
199 else if (op == "sub")
200 cout << x << " - " << y << " = " << x - y << endl << endl;
201 else if (op == "mul")
202 cout << x << " * " << y << " = " << x * y << endl << endl;
203 else if (op == "div") {
205 cout << x << " / " << y << " = " << x / y << endl << endl;
207 response->setStatusCode (400);
208 response->setReasonPhrase ("Division por cero");
212 response->setStatusCode (501);
214 catch (RuntimeException& ex) {
216 response->setStatusCode (500);
217 response->setReasonPhrase (ex.getText ());
221 clientSocket.send (*response);
223 catch (Exception& ex) {