<commit_before>
#include "socket.h"
#include "response.h"
#include <base/sha160.h>
#include <base/base64.h>
#include <base/endian.h>
#include <bitset>

namespace web
{

////////////////////////////////////////

socket::socket( request &req, net::tcp_socket &&client )
	: _socket( std::move( client ) )
{
	if ( req["Connection"] != "Upgrade" )
		throw_runtime( "Request is not an upgrade connection (got {0})", req["Connection"] );
	if ( req["Upgrade"] != "websocket" )
		throw_runtime( "Request is not for a WebSocket upgrade (got {0})", req["Upgrade"] );

	std::string key = req["Sec-WebSocket-Key"];
	key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
	base::sha160 hash;
	hash( key );
	auto h = hash.get_hash();

	response resp;
	resp.set_status_code( status_code::PROTOCOL_SWITCH );
	resp.set_header( "Upgrade", "websocket" );
	resp.set_header( "Connection", "upgrade" );
	resp.set_header( "Sec-WebSocket-Accept", base::base64_encode( h.data(), h.size() ) );
	resp.send( _socket );
	_masked = true;
}

////////////////////////////////////////

socket::socket( base::uri &server, const std::string &agent, double timeout )
{
	precondition( server.scheme() == "ws", "not WebSocket scheme: {0}", server.pretty() );
	_socket.connect( server, 80, timeout );


	std::string nonce;
	nonce.resize( 16 );
	for( size_t i = 0; i < 16; ++i )
		nonce[i] = static_cast<char>( random_byte() );

	request req( "GET", server.full_path() );
	req.set_header( "User-Agent", agent );
	req.set_header( "Host", server.host() + ":" + base::to_string( server.port( 80 ) ) );
	req.set_header( "Origin", server.pretty() );
	req.set_header( "Connection", "Upgrade" );
	req.set_header( "Upgrade", "websocket" );
	req.set_header( "Sec-WebSocket-Version", "13" );
	req.set_header( "Sec-WebSocket-Key", base::base64_encode( nonce ) );

	_socket.connect( server, 80, timeout );<commit_msg>make constructor explicit<commit_after>
#include "socket.h"
#include "response.h"
#include <base/sha160.h>
#include <base/base64.h>
#include <base/endian.h>
#include <bitset>

namespace web
{

////////////////////////////////////////

socket::socket( request &req, net::tcp_socket &&client )
	: _socket( std::move( client ) )
{
	if ( req["Connection"] != "Upgrade" )
		throw_runtime( "Request is not an upgrade connection (got {0})", req["Connection"] );
	if ( req["Upgrade"] != "websocket" )
		throw_runtime( "Request is not for a WebSocket upgrade (got {0})", req["Upgrade"] );

	std::string key = req["Sec-WebSocket-Key"];
	key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
	base::sha160 hash;
	hash( key );
	auto h = hash.get_hash();

	response resp;
	resp.set_status_code( status_code::PROTOCOL_SWITCH );
	resp.set_header( "Upgrade", "websocket" );
	resp.set_header( "Connection", "upgrade" );
	resp.set_header( "Sec-WebSocket-Accept", base::base64_encode( h.data(), h.size() ) );
	resp.send( _socket );
	_masked = true;
}

////////////////////////////////////////

socket::socket( base::uri &server, const std::string &agent, double timeout )
{
	precondition( server.scheme() == "ws", "not WebSocket scheme: {0}", server.pretty() );
	_socket.connect( server, 80, timeout );


	std::string nonce;
	nonce.resize( 16 );
	for( size_t i = 0; i < 16; ++i )
		nonce[i] = static_cast<char>( random_byte() );

	request req( "GET", base::uri( server.full_path() ) );
	req.set_header( "User-Agent", agent );
	req.set_header( "Host", server.host() + ":" + base::to_string( server.port( 80 ) ) );
	req.set_header( "Origin", server.pretty() );
	req.set_header( "Connection", "Upgrade" );
	req.set_header( "Upgrade", "websocket" );
	req.set_header( "Sec-WebSocket-Version", "13" );
	req.set_header( "Sec-WebSocket-Key", base::base64_encode( nonce ) );

	_socket.connect( server, 80, timeout );
{'fraction_non_alphanumeric': 0.22531442333422533, 'fraction_numerical': 0.024083489430024082, 'mean_word_length': 3.9906542056074765, 'pattern_counts': {'":': 2, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3350549', 'n_tokens_mistral': 1408, 'n_tokens_neox': 1325, 'n_words': 299}