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 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
));
40 void http_server_client::write(std::string
const & data
)
42 std::cout
<< "Writing:" << std::endl
<< data
<< std::endl
;
44 char * write_buffer
= new char[data
.size()];
45 std::memcpy(write_buffer
, data
.c_str(), data
.size());
46 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
));
49 void http_server_client::terminate()
51 std::cout
<< "Terminating" << std::endl
;
52 if(!temporary_file_name
.empty())
54 temporary_file
.close();
55 file_manager
.release(temporary_file_name
);
60 void http_server_client::read_event(boost::system::error_code
const & error
, std::size_t bytes_in_buffer
)
64 std::cout
<< "Read " << bytes_in_buffer
<< " bytes:" << std::endl
;
65 bytes_read
+= bytes_in_buffer
;
67 if(bytes_read
> maximal_request_size
)
69 std::cout
<< "Request too large" << std::endl
;
74 std::string
new_data(read_buffer
, bytes_in_buffer
);
76 if(temporary_file_name
.empty())
78 extended_buffer
+= new_data
;
80 std::cout
<< extended_buffer
<< std::endl
;
84 std::string error_message
;
85 current_request
= http_request();
86 process_header_result::type result
= process_header(extended_buffer
, current_request
, error_message
);
89 case process_header_result::no_delimiter
:
90 std::cout
<< "No delimiter yet" << std::endl
;
93 case process_header_result::error
:
94 std::cout
<< error_message
<< std::endl
;
98 case process_header_result::success
:
100 std::cout
<< "Retrieved the full HTTP header" << std::endl
;
105 if(extended_buffer
.size() > maximal_extended_buffer_size
)
109 std::cout
<< "A client exceeded the maximal extended buffer size without delivering the HTTP header" << std::endl
;
114 temporary_file_name
= file_manager
.generate_name();
115 if(!temporary_file
.open_create(temporary_file_name
))
117 std::cout
<< "Failed to open temporary file " << temporary_file_name
<< std::endl
;
121 temporary_file
.write(extended_buffer
);
122 extended_buffer
.clear();
124 std::cout
<< "Using temporary file name " << temporary_file_name
<< std::endl
;
128 temporary_file
.write(new_data
);
132 std::size_t expected_byte_count
= current_request
.header_size
+ current_request
.content_length
;
133 std::cout
<< "Expected byte count: " << current_request
.header_size
<< " + " << current_request
.content_length
<< " = " << expected_byte_count
<< std::endl
;
134 if(bytes_read
> expected_byte_count
)
136 std::cout
<< "Received too many bytes from a client" << std::endl
;
140 else if(bytes_read
== expected_byte_count
)
142 std::cout
<< "Ready to serve data for " << current_request
.path
<< std::endl
;
143 module_result result
;
144 if(modules
.process_request(current_request
, result
))
146 std::cout
<< "The module manager successfully processed the request" << std::endl
;
148 if(generate_content(current_request
, result
, data
))
150 std::cout
<< "Successfully generated the HTTP content, serving it to the client" << std::endl
;
155 std::cout
<< "Failed to generate HTTP content" << std::endl
;
162 std::cout
<< "The module manager failed to process this request" << std::endl
;
175 void http_server_client::write_event(boost::system::error_code
const & error
, char * write_buffer
)
179 std::cout
<< "Got a write event" << std::endl
;
183 if(current_request
.keep_alive
)
185 keep_alive_counter
--;
186 if(keep_alive_counter
<= 0)
188 std::cout
<< "Client keep alive counter is zero" << std::endl
;
199 bool http_server_client::generate_content(http_request
& request
, module_result
& result
, std::string
& content
)
202 reply
.protocol
= request
.protocol_version
;
203 switch(result
.return_code
)
205 case request_handler_return_code::ok
:
209 case request_handler_return_code::forbidden
:
213 case request_handler_return_code::not_found
:
218 std::cout
<< "Unknown request handler return code specified" << std::endl
;
222 reply
.gzip
= request
.gzip
;
223 reply
.keep_alive
= request
.keep_alive
;
224 reply
.content_type
= result
.content_type
;
225 reply
.keep_alive_timeout
= keep_alive_timeout
;
226 reply
.keep_alive_max
= keep_alive_counter
;
227 reply
.content
= result
.content
;
229 if(!reply
.get_packet(content
))
231 std::cout
<< "Failed to build reply packet" << std::endl
;