Remove dynamic exceptions
[anna.git] / source / http / parser / WaitMessage.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 #include <anna/http/parser/WaitMessage.hpp>
10
11 #include <anna/http/internal/Token.hpp>
12 #include <anna/http/Transport.hpp>
13 #include <anna/http/Method.hpp>
14 #include <anna/http/Request.hpp>
15 #include <anna/http/Response.hpp>
16
17 using namespace std;
18 using namespace anna;
19
20 //----------------------------------------------------------------------------------------------------
21 // Todavia no se ha identificado el comienzo del mensaje HTTP. Comprueba el primer token de la
22 // linea para comprobar si se puede identificar una mensaje HTTP de tipo 'Response' o 'Request'.
23 //
24 // La expresion del mensaje HTTP sera:
25 //
26 // Mensahe HTTP := Request | Response
27 //
28 // Resquest := Method <sp> URI <sp> version <crlf> *(Header)<crlf><crlf> [Body]
29 // Response := version <sp> status_code <sp> phrase <crlf> *(Header)
30 //
31 // (1) Si recibimos una linea vacia o con solo CRLF's
32 // (2) Separa el contenido de la linea en los tokens. El separador seran espacios en blanco, tabs, etc.
33 // (3) Si estamos recibiendo un Request.
34 // (4) Si estamos recibiendo un Response
35 //----------------------------------------------------------------------------------------------------
36 int http::parser::WaitMessage::processLine(http::Transport& transport, const DataBlock&, const http::Token& line) const
37 noexcept(false) {
38   if(line.getSize() == 0)                                                         // (1)
39     return -1;
40
41   const Tokenizer& tokenizer = transport.split(line);                             // (2)
42   const Token* token = tokenizer [tokenizer.begin()];
43
44   if(token == NULL)
45     return -1;
46
47   if(Method::asType(token) != Method::Type::None)                                  // (3)
48     if(setupRequest(transport, tokenizer) == true)
49       return -1;
50
51   if(token != NULL) {
52     if(token->match("http/1.1") || token->match("http/1.0"))                      // (4)
53       setupResponse(transport, tokenizer);
54   }
55
56   return -1;
57 }
58
59 //----------------------------------------------------------------------------------------------------
60 // (1) Verifica que en la linea solo esten los tres elementos esperados
61 //----------------------------------------------------------------------------------------------------
62 /*static*/
63 bool http::parser::WaitMessage::setupRequest(http::Transport& transport, const http::Tokenizer& tokenizer)
64 {
65   bool result = true;
66   const Token* token;
67   Tokenizer::const_iterator ii = tokenizer.begin();
68
69   try {
70     if((token = tokenizer [ii ++]) == NULL)
71       return false;
72
73     const Method::Type::_v method = Method::asType(token);
74
75     if((token = tokenizer [ii ++]) == NULL)
76       return false;
77
78     const string& uri(token->getStringValue());
79
80     if((token = tokenizer [ii ++]) == NULL)
81       return false;
82
83     if(tokenizer [ii] != NULL)                                           // (1)
84       return false;
85
86     const string& version(token->getStringValue());
87     http::Request* request = static_cast <http::Request*>(transport.allocateInputMessage(Message::Type::Request));
88     request->setMethod(method);
89     request->setURI(uri);
90     request->setVersion(version);
91     setState(transport, ClassType::ReadHeader);
92   } catch(RuntimeException&) {
93     result = false;
94   }
95
96   return result;
97 }
98
99 //----------------------------------------------------------------------------------------------------
100 // (1) IN_NEMRD_01.00.00_http_001
101 //----------------------------------------------------------------------------------------------------
102 /*static*/
103 void http::parser::WaitMessage::setupResponse(http::Transport& transport, const http::Tokenizer& tokenizer)
104 {
105   const Token* token;
106   Tokenizer::const_iterator ii = tokenizer.begin();
107
108   try {
109     if((token = tokenizer [ii ++]) == NULL)
110       return;
111
112     const string& version(token->getStringValue());
113
114     if((token = tokenizer [ii ++]) == NULL)
115       return;
116
117     const int statusCode(token->getIntegerValue());
118     string reasonPhrase;
119
120     if((token = tokenizer [ii ++]) != NULL) {                               // (1)
121       reasonPhrase = token->getStringValue();
122
123       while((token = tokenizer [ii ++]) != NULL) {
124         reasonPhrase += ' ';
125         reasonPhrase += token->getStringValue();
126       }
127     }
128
129     http::Response* response = static_cast <http::Response*>(transport.allocateInputMessage(Message::Type::Response));
130     response->setVersion(version);
131     response->setStatusCode(statusCode);
132     response->setReasonPhrase(reasonPhrase);
133     setState(transport, ClassType::ReadHeader);
134   } catch(RuntimeException&) {
135   }
136 }