Я пишу сервер веб-сокетов на C ++ и не могу заставить работать рукопожатие.Chrome сообщает, что ошибка вызвана неправильным заголовком подтверждения, но я считаю, что это значение верное.
В качестве примера обмена клиент отправляет следующий ключ:
Sec-WebSocket-Key: ypX0m2zum/pt80mxlVo8PA==
и мойсервер отправляет обратно:
Sec-WebSocket-Accept: Kl4mnqm5QA6bBmGf3EAN0nyGXws=
Я проверил свой сервер в соответствии с примером в RFC, и он проверил.Я не знаю, почему его не приняли.Моя теория состоит в том, что я должен делать что-то еще, что генерирует ту же ошибку, что и неверное принимаемое значение.
Вот другой запрос от захвата Wireshark:
Hypertext Transfer Protocol
GET /websocket HTTP/1.1\r\n
Host: 127.0.0.1:8443\r\n
Connection: Upgrade\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36\r\n
Upgrade: websocket\r\n
Origin: chrome-extension://eajaahbjpnhghjcdaclbkeamlkepinbl\r\n
Sec-WebSocket-Version: 13\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: en-US,en;q=0.9\r\n
Sec-WebSocket-Key: +zJ3/KI/Zrumgh+AjxopRQ==\r\n
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n
\r\n
[Full request URI: http://127.0.0.1:8443/websocket]
[HTTP request 1/1]
[Response in frame: 6]
А вот ответ:
Hypertext Transfer Protocol
HTTP/1.1 101 Switching Protocols\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Accept: anTEIFyI/gTepr8Q3okBj81M2/4=\r\n
\r\n
[HTTP response 1/1]
[Time since request: 0.000245010 seconds]
[Request in frame: 4]
Может кто-нибудь сказать мне, что не так с ответом?Является ли мое допустимое значение неверным?
РЕДАКТИРОВАТЬ 1:
Код, который я использую для создания значения ответа.Ключ websocket_key извлекается из запроса до этого.
const char *magic_string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
int pre_hash_size = 36 + websocket_key.size();
char pre_hash[pre_hash_size];
memcpy(pre_hash, websocket_key.c_str(), websocket_key.size());
memcpy(pre_hash + websocket_key.size(), magic_string, 36);
unique_ptr<Botan::HashFunction> hash1(Botan::HashFunction::create("SHA-1"));
Botan::secure_vector<uint8_t> post_hash = hash1->process(reinterpret_cast<const uint8_t *>(pre_hash), pre_hash_size);
string accept_response = base64_encode(post_hash.data(), post_hash.size());
Вот функция base 64:
/*
base64.cpp and base64.h
base64 encoding and decoding with C++.
Version: 1.01.00
Copyright (C) 2004-2017 René Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
std::string base64_encode(unsigned char const *bytes_to_encode, unsigned int in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--)
{
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3)
{
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}