1 #include <boost/bind.hpp>
4 #include <theodwalha/client.hpp>
5 #include <theodwalha/configuration.hpp>
6 #include <theodwalha/temporary.hpp>
7 #include <theodwalha/reply.hpp>
9 http_server_client::http_server_client(boost::asio::io_service
& io_service
, temporary_file_manager
& file_manager
, module_manager
& modules
):
11 file_manager(file_manager
),
13 keep_alive_counter(keep_alive_max
)
15 read_buffer
= new char[read_buffer_size
];
18 http_server_client::~http_server_client()
23 void http_server_client::start()
29 void http_server_client::initialise()
35 void http_server_client::read()
38 std::cout
<< "Reading" << std::endl
;
40 socket
.async_read_some(boost::asio::buffer(read_buffer
, read_buffer_size
), boost::bind(&http_server_client::read_event
, this, boost::asio::placeholders::error
, boost::asio::placeholders::bytes_transferred
));
43 void http_server_client::write(std::string
const & data
)
46 std::cout
<< "Writing:" << std::endl
<< data
<< std::endl
;
48 char * write_buffer
= new char[data
.size()];
49 std::memcpy(write_buffer
, data
.c_str(), data
.size());
50 boost::asio::async_write(socket
, boost::asio::buffer(write_buffer
, data
.size()), boost::bind(&http_server_client::write_event
, this, boost::asio::placeholders::error
, write_buffer
));
53 void http_server_client::terminate()
56 std::cout
<< "Terminating" << std::endl
;
57 if(!temporary_file_name
.empty())
59 temporary_file
.close();
60 file_manager
.release(temporary_file_name
);
65 void http_server_client::read_event(boost::system::error_code
const & error
, std::size_t bytes_in_buffer
)
68 std::cout
<< "Read event" << std::endl
;
73 std::cout
<< "Read " << bytes_in_buffer
<< " bytes" << std::endl
;
74 bytes_read
+= bytes_in_buffer
;
76 if(bytes_read
> maximal_request_size
)
78 std::cout
<< "Request too large" << std::endl
;
83 std::string
new_data(read_buffer
, bytes_in_buffer
);
85 if(temporary_file_name
.empty())
87 extended_buffer
+= new_data
;
90 std::cout
<< extended_buffer
<< std::endl
;
94 std::string error_message
;
95 current_request
= http_request();
96 process_header_result::type result
= process_header(extended_buffer
, current_request
, error_message
);
99 case process_header_result::no_delimiter
:
100 std::cout
<< "No delimiter yet" << std::endl
;
103 case process_header_result::error
:
104 std::cout
<< error_message
<< std::endl
;
108 case process_header_result::success
:
111 std::cout
<< "Retrieved the full HTTP header" << std::endl
;
116 if(extended_buffer
.size() > maximal_extended_buffer_size
)
120 std::cout
<< "A client exceeded the maximal extended buffer size without delivering the HTTP header" << std::endl
;
125 temporary_file_name
= file_manager
.generate_name();
126 if(!temporary_file
.open_create(temporary_file_name
))
128 std::cout
<< "Failed to open temporary file " << temporary_file_name
<< std::endl
;
132 temporary_file
.write(extended_buffer
);
133 extended_buffer
.clear();
135 std::cout
<< "Using temporary file name " << temporary_file_name
<< std::endl
;
139 temporary_file
.write(new_data
);
143 std::size_t expected_byte_count
= current_request
.header_size
+ current_request
.content_length
;
145 std::cout
<< "Expected byte count: " << current_request
.header_size
<< " + " << current_request
.content_length
<< " = " << expected_byte_count
<< std::endl
;
146 if(bytes_read
> expected_byte_count
)
148 std::cout
<< "Received too many bytes from a client: " << bytes_read
<< " > " << expected_byte_count
<< std::endl
;
152 else if(bytes_read
== expected_byte_count
)
155 std::cout
<< "Ready to serve data for " << current_request
.path
<< std::endl
;
156 module_result result
;
157 if(modules
.process_request(current_request
, result
))
160 std::cout
<< "The module manager successfully processed the request" << std::endl
;
162 if(generate_content(current_request
, result
, data
))
165 std::cout
<< "Successfully generated the HTTP content, serving it to the client" << std::endl
;
171 std::cout
<< "Failed to generate HTTP content" << std::endl
;
178 std::cout
<< "The module manager failed to process this request" << std::endl
;
190 std::cout
<< "Read error" << std::endl
;
195 void http_server_client::write_event(boost::system::error_code
const & error
, char * write_buffer
)
200 std::cout
<< "Got a write event" << std::endl
;
204 if(current_request
.keep_alive
)
206 keep_alive_counter
--;
207 if(keep_alive_counter
<= 0)
210 std::cout
<< "Client keep alive counter is zero" << std::endl
;
216 std::cout
<< "Reinitialising the state" << std::endl
;
224 std::cout
<< "No keep-alive" << std::endl
;
230 std::cout
<< "Write error" << std::endl
;
235 bool http_server_client::generate_content(http_request
& request
, module_result
& result
, std::string
& content
)
238 reply
.protocol
= request
.protocol_version
;
239 switch(result
.return_code
)
241 case request_handler_return_code::ok
:
245 case request_handler_return_code::forbidden
:
249 case request_handler_return_code::not_found
:
254 std::cout
<< "Unknown request handler return code specified" << std::endl
;
258 reply
.gzip
= request
.gzip
;
259 reply
.keep_alive
= request
.keep_alive
;
260 reply
.content_type
= result
.content_type
;
261 reply
.keep_alive_timeout
= keep_alive_timeout
;
262 reply
.keep_alive_max
= keep_alive_counter
;
263 reply
.content
= result
.content
;
265 if(!reply
.get_packet(content
))
267 std::cout
<< "Failed to build reply packet" << std::endl
;