1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
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 the copyright holder 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
39 #include <anna/core/core.hpp>
40 #include <anna/comm/comm.hpp>
42 #include <anna/http/Request.hpp>
43 #include <anna/http/Response.hpp>
44 #include <anna/http/Handler.hpp>
45 #include <anna/http/Transport.hpp>
46 #include <anna/http/functions.hpp>
47 #include <anna/http/internal/sccs.hpp>
48 #include <anna/core/internal/sccs.hpp>
50 anna_import_sccs_tag (http);
54 class MyHandler : public http::Handler {
56 MyHandler () : http::Handler ("http_echo::MyHandler") {
57 a_httpResponse.createHeader (http::Header::Type::Date);
58 a_httpResponse.createHeader (http::Header::Type::Server)->setValue (anna_use_sccs_tag (http));
61 void setNotSend (const bool notSend) throw () { a_notSend = notSend; }
64 http::Response a_httpResponse;
67 void evRequest (ClientSocket&, const http::Request& request) throw (RuntimeException);
68 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException) {;}
71 class MyCommunicator : public comm::Communicator {
75 void setNotSend (const bool notSend) throw () { a_httpHandler.setNotSend (notSend); }
78 MyHandler a_httpHandler;
80 void eventReceiveMessage (comm::ClientSocket &, const Message& message)
81 throw (RuntimeException);
84 class HTTPArithmeticServer : public comm::Application {
86 HTTPArithmeticServer ();
89 MyCommunicator a_communicator;
90 comm::ServerSocket* a_serverSocket;
92 void initialize () throw (RuntimeException);
93 void run () throw (RuntimeException);
97 using namespace anna::comm;
99 int main (int argc, const char** argv)
101 CommandLine& commandLine (CommandLine::instantiate ());
102 HTTPArithmeticServer app;
104 http::functions::initialize ();
109 commandLine.initialize (argv, argc);
110 commandLine.verify ();
112 Logger::setLevel (Logger::Debug);
113 Logger::initialize ("http_echo", new anna::TraceWriter ("file.trace", 4048000));
117 catch (Exception& ex) {
118 cout << ex.asString () << endl;
124 HTTPArithmeticServer::HTTPArithmeticServer () :
125 Application ("http_echo", "Servidor de echo", "1.0")
127 CommandLine& commandLine (CommandLine::instantiate ());
129 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
130 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP en la que atender");
131 commandLine.add ("r", CommandLine::Argument::Optional, "Indicador de reuso de direccin", false);
132 commandLine.add ("notsend", CommandLine::Argument::Optional, "Indicador de no responder al mensaje", false);
135 void HTTPArithmeticServer::initialize ()
136 throw (RuntimeException)
138 CommandLine& cl (CommandLine::instantiate ());
140 int port = cl.getIntegerValue ("p");
141 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
143 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"), &http::Transport::getFactory ());
145 a_communicator.setNotSend (cl.exists ("notsend"));
148 void HTTPArithmeticServer::run ()
149 throw (RuntimeException)
151 a_communicator.attach (a_serverSocket);
152 a_communicator.accept ();
155 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
156 throw (RuntimeException)
158 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
160 if (clientSocket.support (http::Transport::className ()) == false)
163 static int messageCounter = 0;
164 static int successCounter = 0;
168 CongestionController& congestionController = CongestionController::instantiate ();
172 if (congestionController.getAdvice (clientSocket) == CongestionController::Advice::Discard)
177 a_httpHandler.apply (clientSocket, message);
180 void MyHandler::evRequest (ClientSocket& clientSocket, const http::Request& request)
181 throw (RuntimeException)
183 const DataBlock& body = request.getBody ();
186 string msg ("Body recibido: ");
187 msg += anna::functions::asString (body);
188 Logger::information (msg, ANNA_FILE_LOCATION);
192 const http::Header* header;
195 for (http::Request::const_header_iterator ii = request.header_begin (), maxii = request.header_end (); ii != maxii; ii ++) {
196 header = http::Request::header (ii);
197 Logger::information (header->asString (), ANNA_FILE_LOCATION);
200 if ((header = request.find (http::Header::Type::Connection)) != NULL) {
201 if (header->match ("keep-alive", http::Header::Compare::FullMode))
202 Logger::information ("Keep Alive activado en la conexion", ANNA_FILE_LOCATION);
204 Logger::information ("Keep Alive NO activado en la conexion", ANNA_FILE_LOCATION);
208 if (a_notSend == true)
211 a_httpResponse.clearBody ();
212 a_httpResponse.find (http::Header::Type::Date)->setValue ("Mon, 30 Jan 2006 14:36:18 GMT");
214 http::Header* userData = a_httpResponse.find ("UserData");
216 if (userData == NULL)
217 userData = a_httpResponse.createHeader ("UserData");
219 userData->setValue ("Verificacio del cambio 1.0.7");
220 a_httpResponse.setBody (body);
223 clientSocket.send (a_httpResponse);
225 catch (Exception& ex) {