Remove warnings
[anna.git] / example / comm / datagramRServer / main.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
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 //
7
8
9 /*
10   Ejemplo de programa servidor. Atiende peticiones aritmeticas, el protocolo de transporte
11   sera el comm::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.
13   
14   Ejemplo de uso del sistema de receiveres, que son capaces de tratar N peticiones de forma
15   totalmetne simultanea en caso de estar en un entorno MT.
16
17   Para poder probar el sistema de congestion se puede indicar un numero de milisegundos de 
18   retardo aplicados a cada contestacion.
19
20   Los clientes pueden ser: client.p o kclient.p
21 */
22 #include <iostream>
23
24 #include <anna/core/core.hpp>
25 #include <anna/comm/comm.hpp>
26
27 #include <anna/xml/Node.hpp>
28 #include <anna/xml/Attribute.hpp>
29
30 #include <anna/app/functions.hpp>
31
32 #include <anna/test/Request.hpp>
33 #include <anna/test/Response.hpp>
34 #include <anna/test/Communicator.hpp>
35
36 using namespace std;
37 using namespace test;
38
39 class MyCommunicator : public test::Communicator {
40 public:
41    MyCommunicator () :  test::Communicator () {;}
42 };
43
44 class MyReceiver : public Receiver {
45 public:
46    virtual ~MyReceiver() {;}
47    static const char* className () throw () { return "MyReceiver"; }
48
49 private:
50    Request a_request;
51    Response a_response;
52    MyCommunicator* a_communicator;
53    
54    MyReceiver () : Receiver ("MyReceiver") { ; }
55    void initialize () throw (RuntimeException);
56    void apply (comm::ClientSocket &, const Message&) throw (RuntimeException);
57    
58    friend class Allocator <MyReceiver>;      
59 };
60
61 class ArithmeticServer : public comm::Application {
62 public:
63    ArithmeticServer ();
64
65    comm::DatagramSocket* getOutput () throw () { return a_output; }
66       
67 private:
68    MyCommunicator* a_communicator;
69    ReceiverFactoryImpl <MyReceiver> a_receiverFactory;
70    comm::DatagramSocket* a_input;
71    comm::DatagramSocket* a_output;
72
73    void initialize () throw (RuntimeException);
74    void run () throw (RuntimeException);
75    xml::Node* asXML (xml::Node* app) const throw ();
76 };
77
78 using namespace std;
79 using namespace anna::comm;
80
81 int main (int argc, const char** argv)
82 {
83    CommandLine& commandLine (CommandLine::instantiate ());
84    ArithmeticServer app;
85
86    srand (time (NULL));
87    
88    try {
89       commandLine.initialize (argv, argc);
90       commandLine.verify ();
91
92       Logger::setLevel (Logger::Debug); 
93       Logger::initialize ("arithmeticServer", new TraceWriter ("file.trace",4096000));
94  
95       app.start ();
96    }
97    catch (Exception& ex) {
98       cout << ex.asString () << endl;
99    }
100    
101    return 0;
102 }
103
104 ArithmeticServer::ArithmeticServer () : 
105    Application ("arithmeticServer", "Servidor de operaciones (iRS)", "1.0"),
106    a_communicator (NULL)
107 {
108    CommandLine& commandLine (CommandLine::instantiate ());
109    
110    commandLine.add ("as", CommandLine::Argument::Optional, "Direccion broadcast en el que servidor atiende peticiones.");
111    commandLine.add ("ps", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende las peticiones.");
112    commandLine.add ("ac", CommandLine::Argument::Optional, "Direccion broadcast en el que cliente atiende respuestas.");
113    commandLine.add ("pc", CommandLine::Argument::Mandatory, "Puerto al que enviar las respuestas");
114    commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
115 }
116
117 //-----------------------------------------------------------------------------------------
118 // Inicializa el servidor de sockets.
119 //-----------------------------------------------------------------------------------------
120 void ArithmeticServer::initialize () 
121    throw (RuntimeException)
122 {
123    CommandLine& cl (CommandLine::instantiate ());
124
125    const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("as")));
126    int port = cl.getIntegerValue ("ps");
127
128    a_communicator = new MyCommunicator ();
129
130    INetAddress localAddress (device, port);
131    a_input = new DatagramSocket (DatagramSocket::ReadOnly, localAddress);
132    a_input->setReceiverFactory (a_receiverFactory);
133    a_communicator->attach (a_input);
134
135    device = Network::instantiate ().find (Device::asAddress (cl.getValue ("ac")));
136    port = cl.getIntegerValue ("pc");
137
138    INetAddress remoteAddress (device, port);
139    a_output = new DatagramSocket (DatagramSocket::WriteOnly, remoteAddress);
140    a_output->connect ();
141 }
142
143 //-----------------------------------------------------------------------------------------
144 // Atiende las peticiones.
145 // Cuando hay un nuevo mensaje invocar�a Communicator::eventReceiveMessage
146 //-----------------------------------------------------------------------------------------
147 void ArithmeticServer::run ()
148    throw (RuntimeException)
149 {
150    CommandLine& cl (CommandLine::instantiate ());
151
152    if (cl.exists ("trace"))
153       Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
154
155    a_communicator->accept ();
156 }
157
158 xml::Node* ArithmeticServer::asXML (xml::Node* app) const 
159    throw ()
160 {
161    xml::Node* node = app::Application::asXML (app);
162    
163    node->createAttribute ("MaxMessage", a_communicator->getMaxMessage ());
164    node->createAttribute ("Message", a_communicator->getMessage ());
165    
166    return node;
167 }
168
169 void MyReceiver::initialize ()
170    throw (RuntimeException)
171 {
172    a_communicator = app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION);
173 }
174
175 void MyReceiver::apply (ClientSocket&, const Message& message) 
176    throw (RuntimeException)
177 {
178    LOGMETHOD (TraceMethod tm ("MyReceiver", "apply", ANNA_FILE_LOCATION));
179
180    a_request.decode (message.getBody ());
181
182    a_communicator->delay ();
183
184    a_response.x = a_request.x;
185    a_response.y = a_request.y;
186    a_response.initTime = a_request.initTime;
187
188    switch (a_response.op = a_request.op) {
189       case '+':
190          a_response.result = a_request.x + a_request.y;
191          break;
192       case '-':
193          a_response.result = a_request.x - a_request.y;
194          break;
195       case '*':
196          a_response.result = a_request.x * a_request.y;
197          break;
198       case '/':
199          a_response.result = (a_request.y != 0) ? (a_request.x / a_request.y): 0;
200          break;
201    }
202
203    LOGINFORMATION (
204       string msg = anna::functions::asString ("%d %c %d = %d", a_request.x, a_request.op, a_request.y, a_response.result);
205       msg += anna::functions::asText (" | InitTime: ",  a_response.initTime);
206       Logger::information (msg, ANNA_FILE_LOCATION);
207    )
208
209    try {
210       static_cast <ArithmeticServer&> (app::functions::getApp ()).getOutput ()->send (a_response);
211    }
212    catch (Exception& ex) {
213       ex.trace ();
214    }
215 }