6 #include <openssl/sha.h>
7 #include <openssl/bio.h>
8 #include <openssl/evp.h>
9 #include <openssl/buffer.h>
14 #include <gpcm/client.h>
18 #include <atomizes.hpp>
19 #include <service/file_system.h>
21 #include <websocket/client.h>
23 using namespace atomizes;
25 typedef void (
Websocket::Client::*RequestActionFunc)(
const atomizes::HTTPMessage&,
const std::string&,
const Util::Url::Variables&);
27 static std::map<std::string, RequestActionFunc> mRequestActions =
32 Websocket::Client::Client(
int socket,
struct sockaddr_in address)
34 this->_socket = socket;
35 this->_address = address;
36 this->UpdateLastRecievedTime();
39 Websocket::Client::~Client()
44 void Websocket::Client::Listen()
48 std::vector<char> buffer(4096, 0);
51 int recv_size = read(this->_socket, &(buffer[0]), 4096);
62 buffer.resize(recv_size);
64 this->UpdateLastRecievedTime();
67 this->onRequest(buffer);
73 void Websocket::Client::Disconnect()
79 void Websocket::Client::Send(
const atomizes::HTTPMessage &http_response)
const
86 void Websocket::Client::onRequest(
const std::vector<char>& buffer)
88 if(Util::Buffer::ToString(buffer).substr(0, 3) ==
"GET")
90 HTTPMessage http_response;
91 HTTPMessageParser http_parser;
92 HTTPMessage http_request;
94 http_parser.Parse(&http_request, &(buffer[0]));
96 std::string websocket_key = http_request.GetHeader(
"Sec-WebSocket-Key");
97 std::string websocket_accept_key = this->_GetSocketAcceptKey(websocket_key);
99 Logger::debug(
"websocket_key = " + websocket_key);
100 Logger::debug(
"websocket_accept_key = " + websocket_accept_key);
102 http_response.SetStatusCode(101);
103 http_response.SetHeader(
"Upgrade",
"websocket");
104 http_response.SetHeader(
"Connection",
"Upgrade");
105 http_response.SetHeader(
"Sec-WebSocket-Accept", websocket_accept_key);
108 http_response.SetHeader(
"Server",
"BF2MC-Matchmaker");
110 this->Send(http_response);
112 this->_LogTransaction(
"<--",
"HTTP/1.1 101 Switching Protocols");
116 std::vector<char> key(buffer.begin() + 4, buffer.begin() + 8);
117 std::vector<char> payload(buffer.begin() + 8, buffer.end());
119 std::vector<char> unmask_data = this->_UnmaskPayload(key, payload);
121 Logger::debug(
"unmask_data = " + Util::Buffer::ToString(unmask_data));
143 void Websocket::Client::_LogTransaction(
const std::string& direction,
const std::string& response)
const
145 std::shared_lock<std::shared_mutex> guard(g_settings_mutex);
147 if ((g_logger_mode & Logger::Mode::Development) == 0)
152 bool show_console = (g_settings[
"websocket"][
"show_requests"].asBool() && direction ==
"-->") ||
153 (g_settings[
"websocket"][
"show_responses"].asBool() && direction ==
"<--");
155 Logger::info(this->GetAddress() +
" " + direction +
" " + response,
156 Server::Type::Websocket, show_console);
159 std::string Websocket::Client::_GetSocketAcceptKey(
const std::string& websocket_key)
161 std::string GUID =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
162 std::string concatenated = websocket_key + GUID;
164 unsigned char hash[SHA_DIGEST_LENGTH];
165 SHA1(
reinterpret_cast<const unsigned char*
>(concatenated.c_str()), concatenated.length(), hash);
167 BIO* b64 = BIO_new(BIO_f_base64());
168 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
169 BIO* bio = BIO_new(BIO_s_mem());
171 BIO_write(b64, hash, SHA_DIGEST_LENGTH);
175 BIO_get_mem_ptr(b64, &bptr);
177 std::string websocket_accept_key(bptr->data, bptr->length - 1);
181 return websocket_accept_key +
"=";
184 std::vector<char> Websocket::Client::_UnmaskPayload(
const std::vector<char>& key,
const std::vector<char>& payload)
186 std::vector<char> unmask_data;
189 for (
size_t i = 0; i < payload.size(); ++i)
191 unmask_data.push_back(payload[i] ^ key[i % 4]);
void Send(const std::string &msg) const
Sends a message over the socket.
void onClientDisconnect(const Net::Socket &client)
Called when a client disconnects from the server.