<commit_before>
#include "libws_config.h"

#include "libws_types.h"
#include "libws_log.h"
#include "libws_handshake.h"
#include "libws_private.h"
#include "libws_base64.h"
#include "libws_sha1.h"
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <assert.h>
#include <string.h>

int _ws_generate_handshake_key(ws_t ws)
{
	char rand_key[16];
	int key_len;
	assert(ws);

	if (ws->handshake_key_base64)
	{
		_ws_free(ws->handshake_key_base64);
		ws->handshake_key_base64 = NULL;
	}

	// Randomize 16 bytes and base64 encode them for the
	// Sec-WebSocket-Key field.
	if (_ws_get_random_mask(ws, rand_key, sizeof(rand_key)) < 0)
	{
		LIBWS_LOG(LIBWS_ERR, "Failed to get random byte sequence "
							 "for Websocket upgrade handshake key");
		return -1;
	}

	ws->handshake_key_base64 = libws_base64((const void *)rand_key, 
											sizeof(rand_key), &key_len);

	if (!ws->handshake_key_base64)
	{
		LIBWS_LOG(LIBWS_ERR, "Failed to base64 encode websocket key");
		return -1;
	}

	return 0;
}

int _ws_send_handshake(ws_t ws, struct evbuffer *out)
{
    size_t i;
	assert(ws);
	assert(out);

	LIBWS_LOG(LIBWS_DEBUG, "Start sending websocket handshake");

	if (!ws->server)
	{
		return -1;
	}

	LIBWS_LOG(LIBWS_DEBUG, "Generate handshake key");

	if (_ws_generate_handshake_key(ws))
	{
		LIBWS_LOG(LIBWS_ERR, "Failed to generate handshake key");
		return -1;
	}

	evbuffer_add_printf(out,
		"GET /%s HTTP/1.1\r\n"
		"Host: %s:%d\r\n"
		"Connection: Upgrade\r\n"
		"Upgrade: websocket\r\n"
		"Sec-Websocket-Version: 13\r\n"
		"Sec-WebSocket-Key: %s\r\n",
		(ws->uri ? ws->uri : ""),
		ws->server,
		ws->port,
		ws->handshake_key_base64);

	if (ws->origin)
	{
		evbuffer_add_printf(out, "Origin: %s\r\n", ws->origin);
	}

	if (ws->num_subprotocols > 0)
	{
		evbuffer_add_printf(out, "Sec-WebSocket-Protocol: %s", 
			ws->subprotocols[0]);

		for (i = 1; i < ws->num_subprotocols; i++)
		{
			evbuffer_add_printf(out, ", %s", ws->subprotocols[i]);
		}
	}
	
	evbuffer_add_printf(out, "\r\n");

	ws->connect_state = WS_CONNECT_STATE_SENT_REQ;

	LIBWS_LOG(LIBWS_DEBUG, "%s", evbuffer_pullup(out, evbuffer_get_length(out)));
<commit_msg>Fixed broken HTTP request when subprotocols are used<commit_after>
#include "libws_config.h"

#include "libws_types.h"
#include "libws_log.h"
#include "libws_handshake.h"
#include "libws_private.h"
#include "libws_base64.h"
#include "libws_sha1.h"
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <assert.h>
#include <string.h>

int _ws_generate_handshake_key(ws_t ws)
{
	char rand_key[16];
	int key_len;
	assert(ws);

	if (ws->handshake_key_base64)
	{
		_ws_free(ws->handshake_key_base64);
		ws->handshake_key_base64 = NULL;
	}

	// Randomize 16 bytes and base64 encode them for the
	// Sec-WebSocket-Key field.
	if (_ws_get_random_mask(ws, rand_key, sizeof(rand_key)) < 0)
	{
		LIBWS_LOG(LIBWS_ERR, "Failed to get random byte sequence "
							 "for Websocket upgrade handshake key");
		return -1;
	}

	ws->handshake_key_base64 = libws_base64((const void *)rand_key, 
											sizeof(rand_key), &key_len);

	if (!ws->handshake_key_base64)
	{
		LIBWS_LOG(LIBWS_ERR, "Failed to base64 encode websocket key");
		return -1;
	}

	return 0;
}

int _ws_send_handshake(ws_t ws, struct evbuffer *out)
{
    size_t i;
	assert(ws);
	assert(out);

	LIBWS_LOG(LIBWS_DEBUG, "Start sending websocket handshake");

	if (!ws->server)
	{
		return -1;
	}

	LIBWS_LOG(LIBWS_DEBUG, "Generate handshake key");

	if (_ws_generate_handshake_key(ws))
	{
		LIBWS_LOG(LIBWS_ERR, "Failed to generate handshake key");
		return -1;
	}

	evbuffer_add_printf(out,
		"GET /%s HTTP/1.1\r\n"
		"Host: %s:%d\r\n"
		"Connection: Upgrade\r\n"
		"Upgrade: websocket\r\n"
		"Sec-Websocket-Version: 13\r\n"
		"Sec-WebSocket-Key: %s\r\n",
		(ws->uri ? ws->uri : ""),
		ws->server,
		ws->port,
		ws->handshake_key_base64);

	if (ws->origin)
	{
		evbuffer_add_printf(out, "Origin: %s\r\n", ws->origin);
	}

	if (ws->num_subprotocols > 0)
	{
		evbuffer_add_printf(out, "Sec-WebSocket-Protocol: %s", 
			ws->subprotocols[0]);

		for (i = 1; i < ws->num_subprotocols; i++)
		{
			evbuffer_add_printf(out, ", %s", ws->subprotocols[i]);
		}
        evbuffer_add_printf(out, "\r\n");
	}
	
	evbuffer_add_printf(out, "\r\n");

	ws->connect_state = WS_CONNECT_STATE_SENT_REQ;

	LIBWS_LOG(LIBWS_DEBUG, "%s", evbuffer_pullup(out, evbuffer_get_length(out)));

{'fraction_non_alphanumeric': 0.15600271309066244, 'fraction_numerical': 0.01853945286004974, 'mean_word_length': 4.3173076923076925, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 51, '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': '3999417', 'n_tokens_mistral': 2034, 'n_tokens_neox': 1863, 'n_words': 347}