void websocket_info::parse_sec_keys(request_impl const &req) { std::string const &key1 = req.header(WS_STR_SEC_WEBSOCKET_KEY1); if (key1.empty()) { return; } std::string const &key2 = req.header(WS_STR_SEC_WEBSOCKET_KEY2); if (key2.empty()) { return; } if (req.body().size() < 8) { throw std::runtime_error("can not find data in websocket request"); } boost::int32_t v1 = get_websocket_key_value(key1.c_str(), WS_STR_SEC_WEBSOCKET_KEY1); boost::int32_t v2 = get_websocket_key_value(key2.c_str(), WS_STR_SEC_WEBSOCKET_KEY2); MD5_CTX md5handler; MD5_Init(&md5handler); MD5_Update(&md5handler, &v1, sizeof(v1)); MD5_Update(&md5handler, &v2, sizeof(v2)); MD5_Update(&md5handler, req.body().data(), 8); std::string str; str.resize(16); MD5_Final((unsigned char*)&str[0], &md5handler); str.swap(sec_data_); }
bool websocket_info::parse(request_impl const &req, bool secure) { if (req.header(WS_STR_CONNECTION) != WS_STR_UPGRADE || req.header(WS_STR_UPGRADE) != WS_STR_WEBSOCKET) { return false; } empty_ = false; std::string const &host = req.header(WS_STR_HOST); if (host.empty()) { throw std::runtime_error("can not find Host in websocket request"); } std::string const &key1 = req.header(WS_STR_SEC_WEBSOCKET_KEY1); std::string const &key2 = req.header(WS_STR_SEC_WEBSOCKET_KEY2); if (!key1.empty() && !key2.empty()) { if (req.body().size() < 8) { throw std::runtime_error("can not find data in websocket request"); } boost::int32_t v1 = get_websocket_key_value(key1.c_str(), WS_STR_SEC_WEBSOCKET_KEY1); boost::int32_t v2 = get_websocket_key_value(key2.c_str(), WS_STR_SEC_WEBSOCKET_KEY2); MD5_CTX md5handler; MD5_Init(&md5handler); MD5_Update(&md5handler, &v1, sizeof(v1)); MD5_Update(&md5handler, &v2, sizeof(v2)); MD5_Update(&md5handler, req.body().data(), 8); std::string str; str.resize(16); MD5_Final((unsigned char*)&str[0], &md5handler); str.swap(sec_data_); } std::string const &uri = req.uri(); if (secure) { location_.reserve(WS_STR_SECURE_SCHEME_DELIMITER.size() + host.size() + uri.size() + 1); location_.assign(WS_STR_SECURE_SCHEME_DELIMITER).append(host).append(uri); } else { location_.reserve(WS_STR_SCHEME_DELIMITER.size() + host.size() + uri.size() + 1); location_.assign(WS_STR_SCHEME_DELIMITER).append(host).append(uri); } origin_ = req.header(WS_STR_ORIGIN); protocol_ = req.header(WS_STR_WEBSOCKET_PROTOCOL); return true; }
void websocket_info::parse_sec_key(request_impl const &req) { std::string const &key = req.header(WS_STR_SEC_WEBSOCKET_KEY); if (key.empty()) { throw std::runtime_error("can not find key in websocket request"); } enum { SHA_OUTPUT_SIZE = 20 }; unsigned char obuf[SHA_OUTPUT_SIZE]; std::string const key_data = key + WS_STR_SECRET_WORD; SHA1((const unsigned char*)key_data.c_str(), key_data.size(), obuf); BIO *b64 = BIO_new(BIO_f_base64()); if (NULL == b64) { throw std::bad_alloc(); } cleanup_bio cleaner(b64); BIO *bmem = BIO_new(BIO_s_mem()); if (NULL == bmem) { throw std::bad_alloc(); } cleaner.bio_ = b64 = BIO_push(b64, bmem); BIO_write(b64, obuf, sizeof(obuf)); BIO_flush(b64); BUF_MEM *bptr = NULL; BIO_get_mem_ptr(b64, &bptr); if (NULL == bptr || NULL == bptr->data || bptr->length != (BASE64_LENGTH(SHA_OUTPUT_SIZE) + 1)) { throw std::runtime_error("can not create accept data in websocket request"); } sec_data_.assign((const char*)bptr->data, bptr->length - 1); }
void websocket_info::parse(request_impl const &req) { if (req.header(WS_STR_CONNECTION) != WS_STR_UPGRADE || req.header(WS_STR_UPGRADE) != WS_STR_WEBSOCKET) { return; } empty_ = false; std::string const &host = req.header(WS_STR_HOST); if (host.empty()) { throw std::runtime_error("can not find Host in websocket request"); } std::string const &uri = req.uri(); location_.reserve(WS_STR_SCHEME_DELIMITER.size() + host.size() + uri.size() + 1); location_.assign(WS_STR_SCHEME_DELIMITER).append(host).append(uri); origin_ = req.header(WS_STR_ORIGIN); protocol_ = req.header(WS_STR_PROTOCOL); }
void connection_base::init(request_impl &req, bool secure) { if (ws_info_.parse(req, secure)) { req.set_websocket(); } }
bool websocket_info::parse(request_impl const &req, bool secure) { if (req.header(WS_STR_CONNECTION) != WS_STR_UPGRADE) { return false; } std::string const &upgrade_hdr = req.header(WS_STR_UPGRADE); if (upgrade_hdr == WS_STR_WEBSOCKET_LOWERCASE) { std::string const &version_hdr = req.header(WS_STR_SEC_WEBSOCKET_VERSION); if (version_hdr == "13") { proto_13_ = true; } else if (version_hdr != "7" && version_hdr != "8") { throw std::runtime_error("not supported websocket protocol version: " + version_hdr); } proto_newsec_ = true; } else if (upgrade_hdr != WS_STR_WEBSOCKET) { return false; } empty_ = false; std::string const &host = req.header(WS_STR_HOST); if (host.empty()) { throw std::runtime_error("can not find Host in websocket request"); } if (proto_newsec_) { parse_sec_key(req); } else { parse_sec_keys(req); } std::string const &uri = req.uri(); if (secure) { location_.reserve(WS_STR_SECURE_SCHEME_DELIMITER.size() + host.size() + uri.size() + 1); location_.assign(WS_STR_SECURE_SCHEME_DELIMITER).append(host).append(uri); } else { location_.reserve(WS_STR_SCHEME_DELIMITER.size() + host.size() + uri.size() + 1); location_.assign(WS_STR_SCHEME_DELIMITER).append(host).append(uri); } if (proto_newsec_ && !proto_13_) { // 7 or 8 origin_ = req.header(WS_STR_SEC_WEBSOCKET_ORIGIN); if (origin_.empty()) { // draft 11,12 ? origin_ = req.header(WS_STR_ORIGIN); } } else { origin_ = req.header(WS_STR_ORIGIN); } protocol_ = req.header(WS_STR_WEBSOCKET_PROTOCOL); if (proto_newsec_) { size_t pos = protocol_.find(','); if (std::string::npos != pos) { protocol_.erase(pos); } } return true; }