Updated license
[anna.git] / example / comm / brkClient / main.cpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
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
16 // distribution.
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.
20 //
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.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 /*
38    Establece un manejador externo para controlar el teclado, recoge los parametros de la operacion
39    por este y envia la peticion al servidor que devolvera el resultado de aplicar la operacion 
40    sobre los parametros recogidos.
41
42    Realiza las peticiones mediante un servicio de reparto por rangos [42, 43]=[+,*], 
43    [45, 45]=[-,-] y la division no tiene ningun rango asociado asi que deberia usar el 
44    ultimo rango que haya sido establecido.
45
46    El cliente de esta aplicacion es: server.p rserver.p => Transporte: comm::Transport.
47 */
48 #include <iostream>
49
50 #include <string.h>
51
52 #include <anna/core/core.hpp>
53 #include <anna/comm/comm.hpp>
54
55 #include <anna/test/Menu.hpp>
56 #include <anna/test/Request.hpp>
57 #include <anna/test/Response.hpp>
58
59 class MyCommunicator : public Communicator {
60 public:   
61    MyCommunicator () : Communicator () {;}
62    
63 private:
64    test::Response a_response;   
65    test::Request a_request;
66    
67    void eventReceiveMessage (ClientSocket&, const Message&) throw (RuntimeException);
68    void eventUser (const char* id, const void* context) throw ();   
69 };
70
71 typedef comm::ByRangeDelivery<int> MyService;
72
73 class BRKClient : public anna::comm::Application {
74 public:
75
76    BRKClient ();
77       
78    MyService* getService () const throw () { return a_service; }
79    const test::Menu& getMenu () const throw () { return a_menu; }
80    
81 private:
82    MyCommunicator a_communicator;
83    test::Menu a_menu;
84    MyService* a_service;
85
86    void initialize () throw (RuntimeException);
87    void run () throw (RuntimeException);    
88 };
89
90 using namespace std;
91 using namespace test;
92
93 int main (int argc, const char** argv)
94 {
95    CommandLine& commandLine (CommandLine::instantiate ());
96    BRKClient app;
97    
98    try {
99       commandLine.initialize (argv, argc);
100       commandLine.verify ();
101
102       Logger::setLevel (Logger::Debug); 
103       Logger::initialize ("kclient", new TraceWriter ("file.trace", 4096000));
104  
105       app.start ();
106    }
107    catch (Exception& ex) {
108       cout << ex.asString () << endl;
109    }
110    
111    return 0;
112 }
113
114 BRKClient::BRKClient () : 
115    Application ("kclient", "BRKClient", "1.0.0"),
116    a_menu (&a_communicator)
117 {
118    CommandLine& commandLine (CommandLine::instantiate ());
119       
120    commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccion en el que el servidor atiende respuestas.");
121    commandLine.add ("px", CommandLine::Argument::Mandatory, "Puertos en los que hay servidores de + y *");
122    commandLine.add ("pm", CommandLine::Argument::Mandatory, "Puertos en los que hay servidores de -");
123 }
124
125 void BRKClient::initialize () 
126    throw (RuntimeException)
127 {
128    CommandLine& cl (CommandLine::instantiate ());    
129
130    Network& network = Network::instantiate ();
131
132    Tokenizer ports;
133    int port;
134    MyService::range_iterator rr;
135    
136    const char* ip = cl.getValue ("a");
137
138    a_service = new MyService ("Service_Arithmetic", true);
139
140    rr = a_service->createRange ('*', '+');
141    ports.apply (cl.getValue ("px"), ",");
142    for (Tokenizer::const_iterator ii = ports.begin (), maxii = ports.end (); ii != maxii; ii ++) {
143       port = atoi (Tokenizer::data (ii));
144       a_service->attach (rr, network.createServer (ip, port, true));
145    }
146
147    rr  = a_service->createRange ('-', '-');
148    ports.apply (cl.getValue ("pm"), ",");
149    for (Tokenizer::const_iterator ii = ports.begin (), maxii = ports.end (); ii != maxii; ii ++) {
150       port = atoi (Tokenizer::data (ii));
151       a_service->attach (rr, network.createServer (ip, port, true));
152    }
153
154    a_communicator.attach (a_service);
155    a_communicator.attach (&a_menu);
156 }
157
158 void BRKClient::run ()
159    throw (RuntimeException)
160 {   
161    a_menu.paint ();
162    a_communicator.accept ();
163 }
164
165 void MyCommunicator::eventReceiveMessage (ClientSocket&, const Message& message)
166    throw (RuntimeException)
167 {
168    a_response.decode (message.getBody ());
169
170    const Millisecond responseTime = anna::functions::millisecond () - a_response.initTime;
171    
172    cout << endl << "ResponseTime: " << responseTime << " ms" << endl;
173    cout << "Resultado de la peticion: " << a_response.x << (char) a_response.op << a_response.y  << " = " << a_response.result << endl << endl;
174    
175    static_cast <BRKClient&> (anna::comm::functions::getApp ()).getMenu ().paint ();
176 }
177
178 //-----------------------------------------------------------------------------------------
179 // Cuando el Menu tiene disponibles todos los datos necesarios para la peticiĆ³n se lo
180 // notifica al comunicador mediante un evento de usuario.
181 //-----------------------------------------------------------------------------------------
182 void MyCommunicator::eventUser (const char* id, const void* context) 
183    throw ()
184 {
185    LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventUser", ANNA_FILE_LOCATION));
186
187    if (anna_strcmp (id, Menu::EventData) == 0) {
188       const Menu::Data* data (reinterpret_cast <const Menu::Data*>  (context));
189       
190       a_request.op = data->a_operation;
191       a_request.x = data->a_op1;
192       a_request.y = data->a_op2;
193       a_request.initTime = anna::functions::millisecond ();
194       
195       MyService* service = static_cast <BRKClient&> (anna::comm::functions::getApp ()).getService ();
196       
197       try {
198          service->prepare (data->a_operation);
199          service->send (a_request);
200       }
201       catch (RuntimeException& ex) {
202          ex.trace ();
203       }
204    } 
205 }