Updated license
[anna.git] / example / http / xmlSender / 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    Envia una peticion de interseccion sobre HTTP/XML para ihttp_server
39
40    El cliente de esta aplicacion es: ihttp_server.p => Transporte: http::Transport.
41 */
42 #include <iostream>
43
44 #include <string.h>
45
46 #include <anna/core/core.hpp>
47 #include <anna/comm/comm.hpp>
48
49 #include <anna/app/functions.hpp>
50
51 #include <anna/xml/DocumentFile.hpp>
52 #include <anna/xml/DocumentMemory.hpp>
53
54 #include <anna/io/TextReader.hpp>
55
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>
61
62 class MyHandler : public http::Handler {
63 public:
64    MyHandler () : http::Handler ("ihttp_client::MyHandler") {;}
65
66 private:
67    http::Response a_httpResponse;
68
69    void evRequest (ClientSocket&, const http::Request&) throw (RuntimeException) {;}
70    void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException);
71 };
72
73 class MyCommunicator : public Communicator {
74 public:
75    MyCommunicator () : Communicator (), a_httpRequest ()
76    {
77       a_httpRequest.setMethod (http::Method::Type::Get);
78       a_httpRequest.setURI ("ihttp_client");
79    }
80
81 private:
82    MyHandler a_httpHandler;
83    http::Request a_httpRequest;
84
85    void eventReceiveMessage (ClientSocket &, const Message&) throw (RuntimeException);
86    void eventBreakConnection (Server* server) throw ();
87    void eventStartup () throw (RuntimeException);
88 };
89
90 class IHTTPClient : public anna::comm::Application {
91 public:
92    IHTTPClient ();
93
94    Server* getServer () const throw () { return a_server; }
95
96 private:
97    MyCommunicator a_communicator;
98    Server* a_server;
99
100    void initialize () throw (RuntimeException);
101    void run () throw (RuntimeException);
102 };
103
104 using namespace std;
105
106 bool st_xmlResponse (false);
107
108 int main (int argc, const char** argv)
109 {
110    CommandLine& commandLine (CommandLine::instantiate ());
111    IHTTPClient app;
112
113    http::functions::initialize ();
114
115    try {
116       commandLine.initialize (argv, argc);
117       commandLine.verify ();
118
119       Logger::setLevel (Logger::Debug);
120       Logger::initialize ("ihttp_client", new TraceWriter ("file.trace", 4096000));
121
122       app.start ();
123    }
124    catch (Exception& ex) {
125       cout << ex.asString () << endl;
126    }
127
128    return 0;
129 }
130
131 IHTTPClient::IHTTPClient () :
132    Application ("ihttp_client", "IHTTPClient", "2.0.0")
133 {
134    CommandLine& commandLine (CommandLine::instantiate ());
135
136    commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
137    commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
138    commandLine.add ("xml", CommandLine::Argument::Optional, "Documento XML que contiene la peticion");
139    commandLine.add ("nocheck", CommandLine::Argument::Optional, "Indicador para que no comprueba la validaded del HTML", false);
140    commandLine.add ("version", CommandLine::Argument::Optional, "Indica la version HTTP usada para enviar");
141    commandLine.add ("uri", CommandLine::Argument::Optional, "URI a usar");
142    commandLine.add ("m", CommandLine::Argument::Optional, "Método HTTP a usar");
143    commandLine.add ("xmlresponse", CommandLine::Argument::Optional, "Visualiza la respuesta como un documento XML", false);
144    commandLine.add ("overquota", CommandLine::Argument::Optional, "Nº de bytes a recibir sin identificar el protocolo");
145    commandLine.add ("c", CommandLine::Argument::Optional, "Valor de la cookie");
146 }
147
148 void IHTTPClient::initialize () 
149    throw (RuntimeException)
150 {
151    CommandLine& cl (CommandLine::instantiate ());
152
153    Network& network = Network::instantiate ();
154
155    Host* host = network.find_host ("host000");
156    host->assign (network.find (Device::asAddress (cl.getValue ("a"))));
157
158    comm::TransportFactory& ttff = http::Transport::getFactory ();
159    if (cl.exists ("overquota") == true) 
160       ttff.setOverQuotaSize (cl.getIntegerValue ("overquota"));
161
162    a_server = host->createServer ("http_server", cl.getIntegerValue ("p"), false, &ttff);
163 }
164
165 void IHTTPClient::run ()
166    throw (RuntimeException)
167 {
168    a_communicator.accept ();
169 }
170
171 void MyCommunicator::eventStartup ()
172    throw (RuntimeException)
173 {
174    CommandLine& cl (CommandLine::instantiate ());
175
176    const char* filename = (cl.exists ("xml")) ? cl.getValue ("xml"): NULL;
177
178    if (filename == NULL) {
179       a_httpRequest.clearBody ();
180    }
181    else {
182       if (cl.exists ("nocheck") == false) {
183          xml::DocumentFile xmlDocument;
184          xmlDocument.initialize (filename);
185          a_httpRequest.setBody (xmlDocument.getContent ());
186       }
187       else {
188          io::TextReader reader;
189          reader.open (filename);
190          DataBlock body (true);
191          const char* line;
192    
193          while ((line = reader.fetch ()) != NULL)
194             body.append (line, anna_strlen (line));
195    
196          http::Header* header = a_httpRequest.createHeader (http::Header::Type::Connection);
197          header->setValue ("   Keep-Alive    ");
198    
199          a_httpRequest.setBody (body);
200       }
201    }
202
203    if (cl.exists ("version"))
204       a_httpRequest.setVersion (cl.getValue ("version"));
205
206    if (cl.exists ("uri"))
207       a_httpRequest.setURI (cl.getValue ("uri"));
208
209    if (cl.exists ("xmlresponse"))
210       st_xmlResponse = true;
211
212    if (cl.exists ("m")) {
213       http::Method::Type::_v type = http::Method::Type::asEnum (cl.getValue ("m"));
214
215       if (type == http::Method::Type::None) {
216          string msg ("Método HTTP no reconocido. ");
217          msg += http::Method::Type::asList ();
218          throw RuntimeException (msg, ANNA_FILE_LOCATION);
219       }
220
221       a_httpRequest.setMethod (type);
222    }
223
224    if (cl.exists ("c") == true) {
225       http::Header* header = a_httpRequest.createHeader ("Cookie");
226       header->setValue (cl.getValue ("c"));
227       cout << "Con cookie: " << cl.getValue ("c") << " | " << header->asString () << endl << endl;
228    }
229
230    // Header requeridos por la plataforma MovilForum para enviar mensajes WapPush
231    a_httpRequest.createHeader (http::Header::Type::ContentType)->setValue ("text/xml; charset=\"iso-8859-1\"");
232    a_httpRequest.createHeader (http::Header::Type::UserAgent)->setValue ("ANNA.http 1.x");
233
234    string host = anna::functions::asString ("%s:%d", cl.getValue ("a"), cl.getIntegerValue ("p"));
235    a_httpRequest.createHeader (http::Header::Type::Host)->setValue (host);
236    a_httpRequest.createHeader (http::Header::Type::Authorization)->setValue (" Basic VGlkTGNtOlQxZExjbQ==");
237    
238    static_cast <IHTTPClient&> (anna::comm::functions::getApp ()).getServer ()->send (a_httpRequest);
239 }
240
241 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
242    throw (RuntimeException)
243 {
244    LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
245
246    if (clientSocket.support (http::Transport::className ()) == false)
247       return;
248
249    a_httpHandler.apply (clientSocket, message);
250 }
251
252 void MyCommunicator::eventBreakConnection (Server* server) 
253    throw ()
254 {
255    cout << "Perdida conexión con " << server->asString () << endl;
256    requestStop ();
257 }
258
259 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
260    throw (RuntimeException)
261 {
262    const DataBlock& body = response.getBody ();
263    
264    cout << "HTTP StatusCode: " << response.getStatusCode () << endl;
265    cout << "HTTP Text: " << response.getReasonPhrase () << endl;
266
267    if (st_xmlResponse == false)
268       cout << "Resultado: \n" << anna::functions::asString (body, 24) << endl << endl;
269    else {
270       try {
271          xml::DocumentMemory xmlDoc;
272          xmlDoc.initialize (response.getBody ());
273          cout << xmlDoc.getContentAsCString () << endl << endl;
274       }
275       catch (RuntimeException& ex) {
276          ex.trace ();
277       }
278    }
279
280    app::functions::component <Communicator> (ANNA_FILE_LOCATION)->requestStop ();
281 }
282