След като Beast прочете заглавката на отговора CONNECT от прокси, проверете както статуса на отговора, така и динамичния буфер. Операцията за четене може да вземе байтове отвъд края на заглавката и да ги задържи в подадения буфер. Ако стартирате TLS с вариант, който чете само сокета, тези задържани байтове остават извън входния път на TLS.

За WebSocket поток, чийто следващ слой е SSL потокът, използвайте буферирания вариант на ръкостискането. В съществуваща сесия yield_context, като държите buffer жив през всички операции:

http::response_parser<http::empty_body> response;
http::async_read_header(
    beast::get_lowest_layer(ws), buffer, response, yield[ec]);
if (ec) return;

auto status = response.get().result_int();
if (status < 200 || status >= 300) return;

std::size_t used = ws.next_layer().async_handshake(
    ssl::stream_base::client, buffer.data(), yield[ec]);
if (ec) return;
buffer.consume(used);

Ранните връщания са изходите при отказ на сесията; прикачете там обичайното отчитане на грешки и почистване. Само успешен отговор CONNECT установява тунела. Страница за отказ не бива да става вход за TLS.

Буферираният вариант завършва с код за грешка и брой байтове. Този брой показва колко байта е консумирал от подадените буфери. След завършване премахнете точно този префикс с consume(used). Не изчиствайте буфера преди началото на операцията, не променяйте хранилището му, докато ръкостискането е в ход, и не предполагайте, че операцията е консумирала всеки подаден байт.

При обичайния TLS, започнат от клиента веднага след CONNECT, буферът може да е празен. Вариантът обработва и този случай. Целта му е да запази границите на потока; той не прави произволни следващи прокси данни валиден TLS. Пазете проверката на името на хоста и настройката за SNI на SSL слоя преди ръкостискането и стартирайте надграждането до WebSocket само след успешен TLS.

Подобни статии