[DEV] correct key of websocket

This commit is contained in:
Edouard DUPIN 2016-06-20 22:08:34 +02:00
parent 4f82e11375
commit 19d49bb462
7 changed files with 94 additions and 31 deletions

View File

@ -368,25 +368,21 @@ void enet::Http::getHeader() {
continue;
}
header += type;
if ( header.size() > 6
if ( header.size() > 4
&& header[header.size()-1] == '\n'
&& header[header.size()-2] == '\r'
&& header[header.size()-3] == '\n'
&& header[header.size()-4] == '\r'
&& header[header.size()-5] == '\n'
&& header[header.size()-6] == '\r') {
&& header[header.size()-4] == '\r') {
// Normal end case ...
break;
} else if ( header.size() > 3
} else if ( header.size() > 2
&& header[header.size()-1] == '\n'
&& header[header.size()-2] == '\n'
&& header[header.size()-3] == '\n') {
&& header[header.size()-2] == '\n') {
// linux end case
break;
} else if ( header.size() > 3
} else if ( header.size() > 2
&& header[header.size()-1] == '\r'
&& header[header.size()-2] == '\r'
&& header[header.size()-3] == '\r') {
&& header[header.size()-2] == '\r') {
// Mac end case
break;
}
@ -600,13 +596,6 @@ void enet::HttpHeader::rmKey(const std::string& _key) {
}
std::string enet::HttpHeader::getKey(const std::string& _key) const {
ENET_WARNING("search key: " << _key << " in:");
for (auto &it : m_map) {
ENET_WARNING(" '" << it.first << "' : '" << it.second << "'");
if (it.first == _key) {
ENET_WARNING(" ==> Find");
}
}
auto it = m_map.find(_key);
if (it != m_map.end()) {
return it->second;
@ -672,7 +661,7 @@ std::string enet::HttpAnswer::generate() const {
}
out += "\r\n";
out += generateKeys();
out += "\r\n\r\n";
out += "\r\n";
return out;
}
enet::HttpServer::HttpServer(enet::Tcp _connection) :
@ -715,7 +704,7 @@ std::string enet::HttpRequest::generate() const {
out += etk::to_string(m_protocol);
out += "\r\n";
out += generateKeys();
out += "\r\n\r\n";
out += "\r\n";
return out;
}

View File

@ -10,6 +10,8 @@
#include <etk/stdTools.h>
#include <string.h>
#include <random>
#include <algue/base64.h>
#include <algue/sha1.h>
namespace enet {
@ -47,6 +49,23 @@ enet::WebSocket::~WebSocket() {
stop(true);
}
static std::string generateKey() {
// create dynamic key:
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_real_distribution<> dist(0, 0xFF);
uint8_t dataKey[16];
for (size_t iii=0; iii<16; ++iii) {
dataKey[iii] = uint8_t(dist(e2));
}
return algue::base64::encode(dataKey, 16);
}
static std::string generateCheckKey(const std::string& _key) {
std::string out = _key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
std::vector<uint8_t> keyData = algue::sha1::encode(out);
return algue::base64::encode(keyData);
}
void enet::WebSocket::start(const std::string& _uri) {
if (m_interface == nullptr) {
@ -59,8 +78,12 @@ void enet::WebSocket::start(const std::string& _uri) {
req.setUri(_uri);
req.setKey("Upgrade", "websocket");
req.setKey("Connection", "Upgrade");
req.setKey("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ=="); // this is an example key ...
m_checkKey = generateKey();
req.setKey("Sec-WebSocket-Key", m_checkKey); // this is an example key ...
m_checkKey = generateCheckKey(m_checkKey);
req.setKey("Sec-WebSocket-Version", "13");
req.setKey("Pragma", "no-cache");
req.setKey("Cache-Control", "no-cache");
ememory::SharedPtr<enet::HttpClient> interface = std::dynamic_pointer_cast<enet::HttpClient>(m_interface);
if (interface!=nullptr) {
interface->setHeader(req);
@ -83,7 +106,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
int32_t len = _connection.read(&opcode, sizeof(uint8_t));
if (len <= 0) {
if (len < 0) {
ENET_ERROR("Protocol error occured ...");
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
ENET_ERROR("Protocol error occured ...");
}
ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true);
return;
@ -103,7 +128,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
ENET_VERBOSE("Read payload : " << uint32_t(size1));
if (len <= 0) {
if (len < 0) {
ENET_ERROR("Protocol error occured ...");
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
ENET_ERROR("Protocol error occured ...");
}
ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true);
return;
@ -118,7 +145,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
len = _connection.read(&tmpSize, sizeof(uint16_t));
if (len <= 1) {
if (len < 0) {
ENET_ERROR("Protocol error occured ...");
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
ENET_ERROR("Protocol error occured ...");
}
ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true);
return;
@ -132,7 +161,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
len = _connection.read(&totalSize, sizeof(uint64_t));
if (len <= 7) {
if (len < 0) {
ENET_ERROR("Protocol error occured ...");
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
ENET_ERROR("Protocol error occured ...");
}
ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true);
return;
@ -148,7 +179,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
len = _connection.read(&dataMask, sizeof(uint32_t));
if (len <= 3) {
if (len < 0) {
ENET_ERROR("Protocol error occured ...");
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
ENET_ERROR("Protocol error occured ...");
}
ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true);
return;
@ -265,8 +298,8 @@ void enet::WebSocket::onReceiveRequest(const enet::HttpRequest& _data) {
enet::HttpAnswer answer(enet::HTTPAnswerCode::c101_switchingProtocols);
answer.setKey("Upgrade", "websocket");
answer.setKey("Connection", "Upgrade");
// TODO: Do it better:
answer.setKey("Sec-WebSocket-Accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="); //base64::encode());
std::string answerKey = generateCheckKey(_data.getKey("Sec-WebSocket-Key"));
answer.setKey("Sec-WebSocket-Accept", answerKey);
interface->setHeader(answer);
}
@ -292,7 +325,7 @@ void enet::WebSocket::onReceiveAnswer(const enet::HttpAnswer& _data) {
return;
}
// NOTE : This is a temporary magic check ...
if (_data.getKey("Sec-WebSocket-Accept") != "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=") {
if (_data.getKey("Sec-WebSocket-Accept") != m_checkKey) {
ENET_ERROR("Wrong key : 'Sec-WebSocket-Accept : xxx' get '" << _data.getKey("Sec-WebSocket-Accept") << "'");
m_interface->stop(true);
return;

View File

@ -15,6 +15,7 @@ namespace enet {
protected:
ememory::SharedPtr<enet::Http> m_interface;
std::vector<uint8_t> m_buffer;
std::string m_checkKey;
public:
WebSocket(enet::Tcp _connection, bool _isServer=false);
virtual ~WebSocket();

View File

@ -26,7 +26,7 @@ def get_version():
def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_module_depend(['etk', 'ememory'])
my_module.add_module_depend(['etk', 'ememory', 'algue'])
my_module.add_src_file([
'enet/debug.cpp'
])

View File

@ -53,7 +53,7 @@ int main(int _argc, const char *_argv[]) {
connection.connect(appl::onReceiveData);
// start http connection (the actual state is just TCP start ...)
connection.start("plop.txt");
connection.start("/plop.txt");
// send some data to play ...
connection.write("coucou comment ca vas ???");

View File

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function WebSocketTest() {
if ("WebSocket" in window) {
} else {
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
return;
}
alert("WebSocket is supported by your Browser!");
// Let us open a web socket
//var ws = new WebSocket("ws://localhost:1983");
var ws = new WebSocket("ws://localhost:12345/plop.txt");
ws.onopen = function() {
// Web Socket is connected, send data using send()
ws.send("Message to send");
alert("Message is sent...");
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("Message is received...");
};
ws.onclose = function() {
// websocket is closed.
alert("Connection is closed...");
};
}
</script>
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketTest()">Run WebSocket</a>
</div>
</body>
</html>

View File

@ -27,7 +27,7 @@ namespace appl {
}
bool onReceiveUri(enet::WebSocket* _interface, const std::string& _uri) {
TEST_INFO("Receive Header uri: " << _uri);
if (_uri == "plop.txt") {
if (_uri == "/plop.txt") {
return true;
}
return false;