28 #ifndef WEBSOCKETPP_PROCESSOR_HYBI00_HPP
29 #define WEBSOCKETPP_PROCESSOR_HYBI00_HPP
31 #include <websocketpp/frame.hpp>
32 #include <websocketpp/http/constants.hpp>
34 #include <websocketpp/utf8_validator.hpp>
35 #include <websocketpp/common/network.hpp>
36 #include <websocketpp/common/md5.hpp>
37 #include <websocketpp/common/platforms.hpp>
39 #include <websocketpp/processors/processor.hpp>
53 template <
typename config>
56 typedef processor<config> base;
58 typedef typename config::request_type request_type;
59 typedef typename config::response_type response_type;
61 typedef typename config::message_type message_type;
62 typedef typename message_type::ptr message_ptr;
64 typedef typename config::con_msg_manager_type::ptr msg_manager_ptr;
66 explicit hybi00(
bool secure,
bool p_is_server, msg_manager_ptr manager)
67 : processor<config>(secure, p_is_server)
71 , m_msg_manager(manager) {}
78 if (r.get_method() !=
"GET") {
79 return make_error_code(error::invalid_http_method);
82 if (r.get_version() !=
"HTTP/1.1") {
83 return make_error_code(error::invalid_http_version);
90 if (r.get_header(
"Sec-WebSocket-Key1").empty() ||
91 r.get_header(
"Sec-WebSocket-Key2").empty() ||
92 r.get_header(
"Sec-WebSocket-Key3").empty())
94 return make_error_code(error::missing_required_header);
97 return lib::error_code();
106 decode_client_key(req.get_header(
"Sec-WebSocket-Key1"), &key_final[0]);
109 decode_client_key(req.get_header(
"Sec-WebSocket-Key2"), &key_final[4]);
116 std::string
const & key3 = req.get_header(
"Sec-WebSocket-Key3");
117 std::copy(key3.c_str(),
118 key3.c_str()+(std::min)(
static_cast<size_t>(8), key3.size()),
122 "Sec-WebSocket-Key3",
123 md5::md5_hash_string(std::string(key_final,16))
126 res.append_header(
"Upgrade",
"WebSocket");
127 res.append_header(
"Connection",
"Upgrade");
131 if (res.get_header(
"Sec-WebSocket-Origin").empty()) {
132 res.append_header(
"Sec-WebSocket-Origin",req.get_header(
"Origin"));
137 if (res.get_header(
"Sec-WebSocket-Location").empty()) {
138 uri_ptr uri = get_uri(req);
139 res.append_header(
"Sec-WebSocket-Location",uri->str());
142 if (!subprotocol.empty()) {
143 res.replace_header(
"Sec-WebSocket-Protocol",subprotocol);
146 return lib::error_code();
161 return error::make_error_code(error::no_protocol_support);
176 return error::make_error_code(error::no_protocol_support);
180 response_type temp = res;
181 temp.remove_header(
"Sec-WebSocket-Key3");
182 return temp.raw() + res.get_header(
"Sec-WebSocket-Key3");
186 return r.get_header(
"Origin");
201 if (!req.get_header(
"Sec-WebSocket-Protocol").empty()) {
202 http::parameter_list p;
204 if (!req.get_header_as_plist(
"Sec-WebSocket-Protocol",p)) {
205 http::parameter_list::const_iterator it;
207 for (it = p.begin(); it != p.end(); ++it) {
208 subprotocol_list.push_back(it->first);
211 return error::make_error_code(error::subprotocol_parse_error);
214 return lib::error_code();
218 std::string h = request.get_header(
"Host");
220 size_t last_colon = h.rfind(
":");
221 size_t last_sbrace = h.rfind(
"]");
228 if (last_colon == std::string::npos ||
229 (last_sbrace != std::string::npos && last_sbrace > last_colon))
231 return lib::make_shared<uri>(base::m_secure, h, request.get_uri());
233 return lib::make_shared<uri>(base::m_secure,
234 h.substr(0,last_colon),
235 h.substr(last_colon+1),
258 ec = lib::error_code();
261 if (m_state == HEADER) {
262 if (buf[p] == msg_hdr) {
264 m_msg_ptr = m_msg_manager->get_message(frame::opcode::text,1);
267 ec = make_error_code(websocketpp::error::no_incoming_buffers);
268 m_state = FATAL_ERROR;
273 ec = make_error_code(error::protocol_violation);
274 m_state = FATAL_ERROR;
276 }
else if (m_state == PAYLOAD) {
277 uint8_t *it = std::find(buf+p,buf+len,msg_ftr);
283 l =
static_cast<size_t>(it-(buf+p));
284 m_msg_ptr->append_payload(buf+p,l);
310 return (m_state == READY);
318 message_ptr ret = m_msg_ptr;
319 m_msg_ptr = message_ptr();
332 return make_error_code(error::invalid_arguments);
338 if (in->get_opcode() != frame::opcode::text) {
339 return make_error_code(error::invalid_opcode);
342 std::string& i = in->get_raw_payload();
346 if (!utf8_validator::validate(i)) {
347 return make_error_code(error::invalid_payload);
351 out->set_header(std::string(
reinterpret_cast<
char const *>(&msg_hdr),1));
355 out->append_payload(std::string(
reinterpret_cast<
char const *>(&msg_ftr),1));
360 out->set_prepared(
true);
362 return lib::error_code();
375 return lib::error_code(error::no_protocol_support);
388 return lib::error_code(error::no_protocol_support);
405 return lib::error_code(error::invalid_arguments);
409 val.append(1,
'\xff');
410 val.append(1,
'\x00');
411 out->set_payload(val);
412 out->set_prepared(
true);
414 return lib::error_code();
417 void decode_client_key(std::string
const & key,
char * result)
const {
418 unsigned int spaces = 0;
423 for (size_t i = 0; i < key.size(); i++) {
426 }
else if (key[i] >=
'0' && key[i] <=
'9') {
431 num =
static_cast<uint32_t>(strtoul(digits.c_str(), NULL, 10));
432 if (spaces > 0 && num > 0) {
433 num = htonl(num/spaces);
434 std::copy(
reinterpret_cast<
char*>(&num),
435 reinterpret_cast<
char*>(&num)+4,
438 std::fill(result,result+4,0);
449 uint8_t
const msg_hdr;
450 uint8_t
const msg_ftr;
454 msg_manager_ptr m_msg_manager;
455 message_ptr m_msg_ptr;
456 utf8_validator::validator m_validator;