<commit_before>// system includes
#include <stdexcept>
#include <cassert>

// stl includes
#include <iostream>
#include <sstream>
#include <iterator>

// Qt includes
#include <QResource>
#include <QDateTime>
#include <QCryptographicHash>
#include <QHostInfo>

// hyperion util includes
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
#include <hyperion/ColorTransform.h>
#include <utils/ColorRgb.h>

// project includes
#include "JsonClientConnection.h"

JsonClientConnection::JsonClientConnection(QTcpSocket *socket, Hyperion * hyperion) :
	QObject(),
	_socket(socket),
	_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
	_hyperion(hyperion),
	_receiveBuffer()
{
	_webSocketHandshakeDone = false;
	// connect internal signals and slots
	connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
	connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
}


JsonClientConnection::~JsonClientConnection()
{
	delete _socket;
}

void JsonClientConnection::readData()
{
	_receiveBuffer += _socket->readAll();
	
	if (_webSocketHandshakeDone) { // websocket mode, data frame
		quint8 opCode = 0;
		quint64 payloadLength = 0;
		bool isMasked = false;
		quint32 index = 0;
		quint8 maskKey[4];
				
		if ((_receiveBuffer.at(0) & 0x80) == 0x80) { // final bit
			opCode = _receiveBuffer.at(0) & 0x0F;
			isMasked = (_receiveBuffer.at(1) & 0x80) == 0x80;
			payloadLength = _receiveBuffer.at(1) & 0x7F;
			index = 2;
			
			switch (payloadLength) {
				case 126:
					payloadLength = ((_receiveBuffer.at(2) << 8) & 0xFF00) | (_receiveBuffer.at(3) & 0xFF);
					index += 2;
					break;
				case 127: {
						payloadLength = 0;
						for (int i=0; i < 8; i++) {
							payloadLength |= ((quint64)(_receiveBuffer.at(index+i) & 0xFF)) << (8*(7-i));
						}
						index += 8;
					}
					break;
				default:
					break;
			}
			
			if (isMasked) { // if the data is masked we need to get the key for unmasking
				for (int i=0; i < 4; i++) {
					maskKey[i] = _receiveBuffer.at(index + i);	
				}
				index += 4;
			}
			
			// check the type of data frame
			switch (opCode) {
				case 0x01: { // text
					QByteArray result = _receiveBuffer.mid(index, payloadLength);
					_receiveBuffer.clear();
					
					// unmask data if necessary
					if (isMasked) {
						for (uint i=0 ; i < payloadLength; i++) {
							result[i] = (result[i] ^ maskKey[i % 4]);
						}
					}
										
					handleMessage(QString(result).toStdString());
				}
				break;
				case 0x08: { // close
					quint8 close[]={0x88, 0};				
					_socket->write((const char*)close, 2);
					_socket->flush();
					_socket->close();
				}
				break;
				case 0x09: { // ping, send pong
					quint8 close[]={0x0A, 0};				
					_socket->write((const char*)close, 2);
					_socket->flush();
				}
				break;
			}
		} else {
			std::cout << "Someone is sending very big messages over several frames... it's not supported yet" << std::endl;
			quint8 close[]={0x88, 0};				
			_socket->write((const char*)close, 2);
			_socket->flush();
			_socket->close();
		}
	} else { // might be a handshake request or raw socket data
		if(_receiveBuffer.contains("Upgrade: websocket")){ // http header, might not be a very reliable check...
			std::cout << "Websocket handshake" << std::endl;
		
			// get the key to tprepare an answer
			int start = _receiveBuffer.indexOf("Sec-WebSocket-Key") + 19;
			std::string value(_receiveBuffer.mid(start, _receiveBuffer.indexOf("\r\n", start) - start).data());
			_receiveBuffer.clear();

			// must be always appended
			value += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
		
			// generate sha1 hash
			QByteArray hash = QCryptographicHash::hash(value.c_str(), QCryptographicHash::Sha1);
		
			// prepare an answer
			std::ostringstream h;
			h << "HTTP/1.1 101 Switching Protocols\r\n" <<
			"Upgrade: websocket\r\n" <<
			"Connection: Upgrade\r\n" << 
			"Sec-WebSocket-Accept: " << QString(hash.toBase64()).toStdString() << "\r\n\r\n";

			_socket->write(h.str().c_str());
			_socket->flush();
			_webSocketHandshakeDone = true; // we are in WebSocket mode, data frames should follow next
		} else { // raw socket data, handling as usual
			int bytes = _receiveBuffer.indexOf('\n') + 1;
			while(bytes > 0)
			{
				// create message string
				std::string message(_receiveBuffer.data(), bytes);

				// remove message data from buffer
				_receiveBuffer = _receiveBuffer.mid(bytes);

				// handle message
				handleMessage(message);

				// try too look up '\n' again
				bytes = _receiveBuffer.indexOf('\n') + 1;
			}		
		}
	}
	
	/*
	int bytes = _receiveBuffer.indexOf('\n') + 1;
	while(bytes > 0)
	{
		// create message string
		std::string message(_receiveBuffer.data(), bytes);

		// remove message data from buffer
		_receiveBuffer = _receiveBuffer.mid(bytes);

		// handle message
		handleMessage(message);

		// try too look up '\n' again
		bytes = _receiveBuffer.indexOf('\n') + 1;
	}
	*/
}

void JsonClientConnection::socketClosed()
{<commit_msg>Update JsonClientConnection.cpp<commit_after>// system includes
#include <stdexcept>
#include <cassert>

// stl includes
#include <iostream>
#include <sstream>
#include <iterator>

// Qt includes
#include <QResource>
#include <QDateTime>
#include <QCryptographicHash>
#include <QHostInfo>

// hyperion util includes
#include <hyperion/ImageProcessorFactory.h>
#include <hyperion/ImageProcessor.h>
#include <hyperion/ColorTransform.h>
#include <utils/ColorRgb.h>

// project includes
#include "JsonClientConnection.h"

JsonClientConnection::JsonClientConnection(QTcpSocket *socket, Hyperion * hyperion) :
	QObject(),
	_socket(socket),
	_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
	_hyperion(hyperion),
	_receiveBuffer()
{
	_webSocketHandshakeDone = false;
	// connect internal signals and slots
	connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
	connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
}


JsonClientConnection::~JsonClientConnection()
{
	delete _socket;
}

void JsonClientConnection::readData()
{
	_receiveBuffer += _socket->readAll();
	
	if (_webSocketHandshakeDone) { // websocket mode, data frame
		quint8 opCode = 0;
		quint64 payloadLength = 0;
		bool isMasked = false;
		quint32 index = 0;
		quint8 maskKey[4];
				
		if ((_receiveBuffer.at(0) & 0x80) == 0x80) { // final bit
			opCode = _receiveBuffer.at(0) & 0x0F;
			isMasked = (_receiveBuffer.at(1) & 0x80) == 0x80;
			payloadLength = _receiveBuffer.at(1) & 0x7F;
			index = 2;
			
			switch (payloadLength) {
				case 126:
					payloadLength = ((_receiveBuffer.at(2) << 8) & 0xFF00) | (_receiveBuffer.at(3) & 0xFF);
					index += 2;
					break;
				case 127: {
						payloadLength = 0;
						for (uint i=0; i < 8; i++) {
							payloadLength |= ((quint64)(_receiveBuffer.at(index+i) & 0xFF)) << (8*(7-i));
						}
						index += 8;
					}
					break;
				default:
					break;
			}
			
			if (isMasked) { // if the data is masked we need to get the key for unmasking
				for (uint i=0; i < 4; i++) {
					maskKey[i] = _receiveBuffer.at(index + i);	
				}
				index += 4;
			}
			
			// check the type of data frame
			switch (opCode) {
				case 0x01: { // text
					QByteArray result = _receiveBuffer.mid(index, payloadLength);
					_receiveBuffer.clear();
					
					// unmask data if necessary
					if (isMasked) {
						for (uint i=0 ; i < payloadLength; i++) {
							result[i] = (result[i] ^ maskKey[i % 4]);
						}
					}
										
					handleMessage(QString(result).toStdString());
				}
				break;
				case 0x08: { // close
					quint8 close[]={0x88, 0};				
					_socket->write((const char*)close, 2);
					_socket->flush();
					_socket->close();
				}
				break;
				case 0x09: { // ping, send pong
					quint8 close[]={0x0A, 0};				
					_socket->write((const char*)close, 2);
					_socket->flush();
				}
				break;
			}
		} else {
			std::cout << "Someone is sending very big messages over several frames... it's not supported yet" << std::endl;
			quint8 close[]={0x88, 0};				
			_socket->write((const char*)close, 2);
			_socket->flush();
			_socket->close();
		}
	} else { // might be a handshake request or raw socket data
		if(_receiveBuffer.contains("Upgrade: websocket")){ // http header, might not be a very reliable check...
			std::cout << "Websocket handshake" << std::endl;
		
			// get the key to tprepare an answer
			int start = _receiveBuffer.indexOf("Sec-WebSocket-Key") + 19;
			std::string value(_receiveBuffer.mid(start, _receiveBuffer.indexOf("\r\n", start) - start).data());
			_receiveBuffer.clear();

			// must be always appended
			value += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
		
			// generate sha1 hash
			QByteArray hash = QCryptographicHash::hash(value.c_str(), QCryptographicHash::Sha1);
		
			// prepare an answer
			std::ostringstream h;
			h << "HTTP/1.1 101 Switching Protocols\r\n" <<
			"Upgrade: websocket\r\n" <<
			"Connection: Upgrade\r\n" << 
			"Sec-WebSocket-Accept: " << QString(hash.toBase64()).toStdString() << "\r\n\r\n";

			_socket->write(h.str().c_str());
			_socket->flush();
			_webSocketHandshakeDone = true; // we are in WebSocket mode, data frames should follow next
		} else { // raw socket data, handling as usual
			int bytes = _receiveBuffer.indexOf('\n') + 1;
			while(bytes > 0)
			{
				// create message string
				std::string message(_receiveBuffer.data(), bytes);

				// remove message data from buffer
				_receiveBuffer = _receiveBuffer.mid(bytes);

				// handle message
				handleMessage(message);

				// try too look up '\n' again
				bytes = _receiveBuffer.indexOf('\n') + 1;
			}		
		}
	}
}

void JsonClientConnection::socketClosed()
{
{'fraction_non_alphanumeric': 0.14853837413490342, 'fraction_numerical': 0.024274351823158763, 'mean_word_length': 3.2095652173913045, 'pattern_counts': {'":': 0, '<': 83, '<?xml version=': 0, '>': 54, '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': '4030872', 'n_tokens_mistral': 4095, 'n_tokens_neox': 3223, 'n_words': 784}