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()
37 std::cout
<< "Reading" << std::endl
;
38 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
));
41 void http_server_client::write(std::string
const & data
)
43 std::cout
<< "Writing:" << std::endl
<< data
<< std::endl
;
45 char * write_buffer
= new char[data
.size()];
46 std::memcpy(write_buffer
, data
.c_str(), data
.size());
47 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
));
50 void http_server_client::terminate()
52 std::cout
<< "Terminating" << std::endl
;
53 if(!temporary_file_name
.empty())
55 temporary_file
.close();
56 file_manager
.release(temporary_file_name
);
61 void http_server_client::read_event(boost::system::error_code
const & error
, std::size_t bytes_in_buffer
)
63 std::cout
<< "Read event" << std::endl
;
66 std::cout
<< "Read " << bytes_in_buffer
<< " bytes:" << std::endl
;
67 bytes_read
+= bytes_in_buffer
;
69 if(bytes_read
> maximal_request_size
)
71 std::cout
<< "Request too large" << std::endl
;
76 std::string
new_data(read_buffer
, bytes_in_buffer
);
78 if(temporary_file_name
.empty())
80 extended_buffer
+= new_data
;
82 std::cout
<< extended_buffer
<< std::endl
;
86 std::string error_message
;
87 current_request
= http_request();
88 process_header_result::type result
= process_header(extended_buffer
, current_request
, error_message
);
91 case process_header_result::no_delimiter
:
92 std::cout
<< "No delimiter yet" << std::endl
;
95 case process_header_result::error
:
96 std::cout
<< error_message
<< std::endl
;
100 case process_header_result::success
:
102 std::cout
<< "Retrieved the full HTTP header" << std::endl
;
107 if(extended_buffer
.size() > maximal_extended_buffer_size
)
111 std::cout
<< "A client exceeded the maximal extended buffer size without delivering the HTTP header" << std::endl
;
116 temporary_file_name
= file_manager
.generate_name();
117 if(!temporary_file
.open_create(temporary_file_name
))
119 std::cout
<< "Failed to open temporary file " << temporary_file_name
<< std::endl
;
123 temporary_file
.write(extended_buffer
);
124 extended_buffer
.clear();
126 std::cout
<< "Using temporary file name " << temporary_file_name
<< std::endl
;
130 temporary_file
.write(new_data
);
134 std::size_t expected_byte_count
= current_request
.header_size
+ current_request
.content_length
;
135 std::cout
<< "Expected byte count: " << current_request
.header_size
<< " + " << current_request
.content_length
<< " = " << expected_byte_count
<< std::endl
;
136 if(bytes_read
> expected_byte_count
)
138 std::cout
<< "Received too many bytes from a client: " << bytes_read
<< " > " << expected_byte_count
<< std::endl
;
142 else if(bytes_read
== expected_byte_count
)
144 std::cout
<< "Ready to serve data for " << current_request
.path
<< std::endl
;
145 module_result result
;
146 if(modules
.process_request(current_request
, result
))
148 std::cout
<< "The module manager successfully processed the request" << std::endl
;
150 if(generate_content(current_request
, result
, data
))
152 std::cout
<< "Successfully generated the HTTP content, serving it to the client" << std::endl
;
158 std::cout
<< "Failed to generate HTTP content" << std::endl
;
165 std::cout
<< "The module manager failed to process this request" << std::endl
;
178 void http_server_client::write_event(boost::system::error_code
const & error
, char * write_buffer
)
182 std::cout
<< "Got a write event" << std::endl
;
186 if(current_request
.keep_alive
)
188 keep_alive_counter
--;
189 if(keep_alive_counter
<= 0)
191 std::cout
<< "Client keep alive counter is zero" << std::endl
;
197 std::cout
<< "Reinitialising the state" << std::endl
;
207 bool http_server_client::generate_content(http_request
& request
, module_result
& result
, std::string
& content
)
210 reply
.protocol
= request
.protocol_version
;
211 switch(result
.return_code
)
213 case request_handler_return_code::ok
:
217 case request_handler_return_code::forbidden
:
221 case request_handler_return_code::not_found
:
226 std::cout
<< "Unknown request handler return code specified" << std::endl
;
230 reply
.gzip
= request
.gzip
;
231 reply
.keep_alive
= request
.keep_alive
;
232 reply
.content_type
= result
.content_type
;
233 reply
.keep_alive_timeout
= keep_alive_timeout
;
234 reply
.keep_alive_max
= keep_alive_counter
;
235 reply
.content
= result
.content
;
237 if(!reply
.get_packet(content
))
239 std::cout
<< "Failed to build reply packet" << std::endl
;