Fix local server for multiple applications
[anna.git] / example / comm / brkClient / 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    Establece un manejador externo para controlar el teclado, recoge los parametros de la operacion
11    por este y envia la peticion al servidor que devolvera el resultado de aplicar la operacion 
12    sobre los parametros recogidos.
13
14    Realiza las peticiones mediante un servicio de reparto por rangos [42, 43]=[+,*], 
15    [45, 45]=[-,-] y la division no tiene ningun rango asociado asi que deberia usar el 
16    ultimo rango que haya sido establecido.
17
18    El cliente de esta aplicacion es: server.p rserver.p => Transporte: comm::Transport.
19 */
20 #include <iostream>
21
22 #include <string.h>
23
24 #include <anna/core/core.hpp>
25 #include <anna/comm/comm.hpp>
26
27 #include <anna/test/Menu.hpp>
28 #include <anna/test/Request.hpp>
29 #include <anna/test/Response.hpp>
30
31 class MyCommunicator : public Communicator {
32 public:   
33    MyCommunicator () : Communicator () {;}
34    
35 private:
36    test::Response a_response;   
37    test::Request a_request;
38    
39    void eventReceiveMessage (ClientSocket&, const Message&) noexcept(false);
40    void eventUser (const char* id, const void* context) ;   
41 };
42
43 typedef comm::ByRangeDelivery<int> MyService;
44
45 class BRKClient : public anna::comm::Application {
46 public:
47
48    BRKClient ();
49       
50    MyService* getService () const { return a_service; }
51    const test::Menu& getMenu () const { return a_menu; }
52    
53 private:
54    MyCommunicator a_communicator;
55    test::Menu a_menu;
56    MyService* a_service;
57
58    void initialize () noexcept(false);
59    void run () noexcept(false);    
60 };
61
62 using namespace std;
63 using namespace test;
64
65 int main (int argc, const char** argv)
66 {
67    CommandLine& commandLine (CommandLine::instantiate ());
68    BRKClient app;
69    
70    try {
71       commandLine.initialize (argv, argc);
72       commandLine.verify ();
73
74       Logger::setLevel (Logger::Debug); 
75       Logger::initialize ("kclient", new TraceWriter ("file.trace", 4096000));
76  
77       app.start ();
78    }
79    catch (Exception& ex) {
80       cout << ex.asString () << endl;
81    }
82    
83    return 0;
84 }
85
86 BRKClient::BRKClient () : 
87    Application ("kclient", "BRKClient", "1.0.0"),
88    a_menu (&a_communicator)
89 {
90    CommandLine& commandLine (CommandLine::instantiate ());
91       
92    commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccion en el que el servidor atiende respuestas.");
93    commandLine.add ("px", CommandLine::Argument::Mandatory, "Puertos en los que hay servidores de + y *");
94    commandLine.add ("pm", CommandLine::Argument::Mandatory, "Puertos en los que hay servidores de -");
95 }
96
97 void BRKClient::initialize () 
98    noexcept(false)
99 {
100    CommandLine& cl (CommandLine::instantiate ());    
101
102    Network& network = Network::instantiate ();
103
104    Tokenizer ports;
105    int port;
106    MyService::range_iterator rr;
107    
108    const char* ip = cl.getValue ("a");
109
110    a_service = new MyService ("Service_Arithmetic", true);
111
112    rr = a_service->createRange ('*', '+');
113    ports.apply (cl.getValue ("px"), ",");
114    for (Tokenizer::const_iterator ii = ports.begin (), maxii = ports.end (); ii != maxii; ii ++) {
115       port = atoi (Tokenizer::data (ii));
116       a_service->attach (rr, network.createServer (ip, port, true));
117    }
118
119    rr  = a_service->createRange ('-', '-');
120    ports.apply (cl.getValue ("pm"), ",");
121    for (Tokenizer::const_iterator ii = ports.begin (), maxii = ports.end (); ii != maxii; ii ++) {
122       port = atoi (Tokenizer::data (ii));
123       a_service->attach (rr, network.createServer (ip, port, true));
124    }
125
126    a_communicator.attach (a_service);
127    a_communicator.attach (&a_menu);
128 }
129
130 void BRKClient::run ()
131    noexcept(false)
132 {   
133    a_menu.paint ();
134    a_communicator.accept ();
135 }
136
137 void MyCommunicator::eventReceiveMessage (ClientSocket&, const Message& message)
138    noexcept(false)
139 {
140    a_response.decode (message.getBody ());
141
142    const Millisecond responseTime = anna::functions::millisecond () - a_response.initTime;
143    
144    cout << endl << "ResponseTime: " << responseTime << " ms" << endl;
145    cout << "Resultado de la peticion: " << a_response.x << (char) a_response.op << a_response.y  << " = " << a_response.result << endl << endl;
146    
147    static_cast <BRKClient&> (anna::comm::functions::getApp ()).getMenu ().paint ();
148 }
149
150 //-----------------------------------------------------------------------------------------
151 // Cuando el Menu tiene disponibles todos los datos necesarios para la peticiĆ³n se lo
152 // notifica al comunicador mediante un evento de usuario.
153 //-----------------------------------------------------------------------------------------
154 void MyCommunicator::eventUser (const char* id, const void* context) 
155    
156 {
157    LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventUser", ANNA_FILE_LOCATION));
158
159    if (anna_strcmp (id, Menu::EventData) == 0) {
160       const Menu::Data* data (reinterpret_cast <const Menu::Data*>  (context));
161       
162       a_request.op = data->a_operation;
163       a_request.x = data->a_op1;
164       a_request.y = data->a_op2;
165       a_request.initTime = anna::functions::millisecond ();
166       
167       MyService* service = static_cast <BRKClient&> (anna::comm::functions::getApp ()).getService ();
168       
169       try {
170          service->prepare (data->a_operation);
171          service->send (a_request);
172       }
173       catch (RuntimeException& ex) {
174          ex.trace ();
175       }
176    } 
177 }