1 // ANNA - Anna is Not 'N' Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // https://bitbucket.org/testillano/anna
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
38 Ejemplo de programa servidor. Atiende peticiones aritmeticas, el protocolo de transporte sera HTTP
39 ver http::Transport y el contenido del mensaje sera el resutaldo de un comm::Codec con los
40 (x, y, op) -> El resultado sera estos tres componente mas result.
42 Para poder probar el sistema de congestion se puede indicar un numero de milisegundos de
43 retardo aplicados a cada contestacion.
45 Los clientes pueden ser: wims20_kclient.p wims20_client.p
49 #include <anna/core/core.hpp>
51 #include <anna/xml/Node.hpp>
52 #include <anna/xml/Attribute.hpp>
54 #include <anna/comm/comm.hpp>
56 #include <anna/http/Request.hpp>
57 #include <anna/http/Response.hpp>
58 #include <anna/http/Handler.hpp>
59 #include <anna/http/Transport.hpp>
60 #include <anna/http/functions.hpp>
62 #include <anna/http/wims20/ServerSide.hpp>
66 class MyCommunicator : public comm::Communicator {
71 class MyHandler : public http::Handler {
73 MyHandler () : http::Handler ("wims20_rserver::MyHandler"), a_request (NULL) {;}
75 static const char* className () throw () { return "wims20_rserver::ReceiverFactory"; }
78 MyCommunicator* a_communicator;
79 http::wims20::ServerSide* a_request;
81 void initialize () throw (RuntimeException);
82 void evRequest (ClientSocket&, const http::Request& request) throw (RuntimeException);
83 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException) {;}
86 class HTTPArithmeticServer : public comm::Application {
88 HTTPArithmeticServer ();
91 MyCommunicator a_communicator;
92 ReceiverFactoryImpl <MyHandler> a_receiverFactory;
93 comm::ServerSocket* a_serverSocket;
95 void initialize () throw (RuntimeException);
96 void run () throw (RuntimeException);
100 using namespace anna::comm;
102 int main (int argc, const char** argv)
104 CommandLine& commandLine (CommandLine::instantiate ());
105 HTTPArithmeticServer app;
107 http::functions::initialize ();
112 commandLine.initialize (argv, argc);
113 commandLine.verify ();
115 Logger::setLevel (Logger::Debug);
116 Logger::initialize ("wims20_server", new anna::TraceWriter ("file.trace", 4048000));
120 catch (Exception& ex) {
121 cout << ex.asString () << endl;
127 HTTPArithmeticServer::HTTPArithmeticServer () :
128 Application ("wims20_rserver", "Servidor HTTP/WIMS 2.0 de operaciones aritmeticas (iRS)", "1.0")
130 CommandLine& commandLine (CommandLine::instantiate ());
132 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
133 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP en la que atender");
134 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
135 commandLine.add ("domain", CommandLine::Argument::Mandatory, "Domain indicado en la petición WIMS 2.0");
136 commandLine.add ("path", CommandLine::Argument::Optional, "Path indicado en la petición WIMS 2.0");
139 void HTTPArithmeticServer::initialize ()
140 throw (RuntimeException)
142 CommandLine& cl (CommandLine::instantiate ());
144 int port = cl.getIntegerValue ("p");
145 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
147 comm::TransportFactory* ttff = &http::Transport::getFactory ();
149 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"), ttff);
150 a_serverSocket->setReceiverFactory (a_receiverFactory);
153 void HTTPArithmeticServer::run ()
154 throw (RuntimeException)
156 CommandLine& cl (CommandLine::instantiate ());
158 a_communicator.attach (a_serverSocket);
160 if (cl.exists ("trace"))
161 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
163 a_communicator.accept ();
166 void MyHandler::initialize ()
167 throw (RuntimeException)
169 CommandLine& cl (CommandLine::instantiate ());
171 string domain = cl.getValue ("domain");
173 if (cl.exists ("path")) {
174 string path = cl.getValue ("path");
175 a_request = new http::wims20::ServerSide (domain, path);
178 a_request = new http::wims20::ServerSide (domain);
180 a_communicator = app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION);
181 allocateResponse ()->createHeader (http::Header::Type::Date);
184 // Recibe una petición de operación aritmética y visualiza el resultado por pantalla.
185 // Para mantener la simplicidad del ejemplo sólo notifica al cliente si ha ido bien
186 // o no, pero no deuuelve ningún resultado
188 // Definimos que nuestro servicio deberá recibir una petición REST de la forma:
189 // http://<domain>/<path>/math/guest@tid.es/<op>?X=nnn&Y=nnn
190 // Observar que la <op> correspondería con las parte other_possible_levels
191 // de la especificación WIMS 2.0
192 void MyHandler::evRequest (ClientSocket& clientSocket, const http::Request& request)
193 throw (RuntimeException)
195 LOGMETHOD (TraceMethod tm ("MyReceiver", "apply", ANNA_FILE_LOCATION));
197 a_request->decode (request);
199 cout << a_request->asString () << endl << endl;
201 http::Response* response = allocateResponse ();
203 if (a_request->getServiceID () != "math" || a_request->getGUID () != "user@tid.es") {
204 response->setStatusCode (401);
205 clientSocket.send (*response);
209 if (a_request->hasOtherLevels () == false) {
210 response->setStatusCode (416);
211 clientSocket.send (*response);
215 // El primer nivel indica la operación a realizar
216 const std::string& op = *http::wims20::ServerSide::otherLevel (a_request->other_level_begin ());
221 x = a_request->getIntegerValue ("X");
222 y = a_request->getIntegerValue ("Y");
223 response->setStatusCode (200);
226 cout << x << " + " << y << " = " << x + y << endl << endl;
227 else if (op == "sub")
228 cout << x << " - " << y << " = " << x - y << endl << endl;
229 else if (op == "mul")
230 cout << x << " * " << y << " = " << x * y << endl << endl;
231 else if (op == "div") {
233 cout << x << " / " << y << " = " << x / y << endl << endl;
235 response->setStatusCode (400);
236 response->setReasonPhrase ("Division por cero");
240 response->setStatusCode (501);
242 catch (RuntimeException& ex) {
244 response->setStatusCode (500);
245 response->setReasonPhrase (ex.getText ());
249 clientSocket.send (*response);
251 catch (Exception& ex) {