Go to the documentation of this file.00001 #include <boost/regex.hpp>
00002 #include <openssl/sha.h>
00003 #include <openssl/hmac.h>
00004 #include <openssl/evp.h>
00005 #include <openssl/bio.h>
00006 #include <openssl/buffer.h>
00007 #include "async_web_server_cpp/websocket_request_handler.hpp"
00008 #include "async_web_server_cpp/websocket_connection.hpp"
00009 #include "async_web_server_cpp/http_reply.hpp"
00010
00011 namespace async_web_server_cpp
00012 {
00013
00014 const std::string WebsocketHttpRequestHandler::KEY_MAGIC_STRING = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
00015
00016 WebsocketHttpRequestHandler::WebsocketHttpRequestHandler(WebsocketRequestHandler handler)
00017 : handler_(handler) {}
00018
00019
00020 bool WebsocketHttpRequestHandler::operator()(const HttpRequest &request, boost::shared_ptr<HttpConnection> connection, const char* begin, const char* end)
00021 {
00022 std::string connection_header = request.get_header_value_or_default("Connection", "");
00023 std::string upgrade_header = request.get_header_value_or_default("Upgrade", "");
00024 std::string websocket_key = request.get_header_value_or_default("Sec-WebSocket-Key", "");
00025
00026 if (connection_header.find("Upgrade") != std::string::npos && upgrade_header.compare("websocket") == 0
00027 && websocket_key.size() > 0)
00028 {
00029 std::string concat_key = websocket_key + KEY_MAGIC_STRING;
00030
00031
00032 unsigned char sha1_buf[20];
00033 SHA1((const unsigned char*)concat_key.data(), concat_key.size(), sha1_buf);
00034
00035
00036 BIO* b64 = BIO_new(BIO_f_base64());
00037 BIO* bmem = BIO_new(BIO_s_mem());
00038 b64 = BIO_push(b64, bmem);
00039 BIO_write(b64, sha1_buf, 20);
00040 BIO_flush(b64);
00041 BUF_MEM *bptr;
00042 BIO_get_mem_ptr(b64, &bptr);
00043 std::string base64_key(bptr->data, bptr->length - 1);
00044 BIO_free_all(b64);
00045
00046
00047 async_web_server_cpp::HttpReply::builder(async_web_server_cpp::HttpReply::switching_protocols)
00048 .header("Upgrade", "websocket")
00049 .header("Connection", "Upgrade")
00050 .header("Sec-WebSocket-Version", "13")
00051 .header("Sec-WebSocket-Accept", base64_key)
00052 .write(connection);
00053
00054 WebsocketConnectionPtr websocket_connection(new WebsocketConnection(connection));
00055 WebsocketConnection::MessageHandler message_handler = handler_(request, websocket_connection);
00056 websocket_connection->set_message_handler(message_handler);
00057 websocket_connection->handle_read(begin, end);
00058 }
00059 else
00060 {
00061 async_web_server_cpp::HttpReply::stock_reply(async_web_server_cpp::HttpReply::bad_request)(request, connection, begin, end);
00062 }
00063 return true;
00064 }
00065
00066 }