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

View File

@ -10,6 +10,8 @@
#include <etk/stdTools.h> #include <etk/stdTools.h>
#include <string.h> #include <string.h>
#include <random> #include <random>
#include <algue/base64.h>
#include <algue/sha1.h>
namespace enet { namespace enet {
@ -47,6 +49,23 @@ enet::WebSocket::~WebSocket() {
stop(true); 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) { void enet::WebSocket::start(const std::string& _uri) {
if (m_interface == nullptr) { if (m_interface == nullptr) {
@ -59,8 +78,12 @@ void enet::WebSocket::start(const std::string& _uri) {
req.setUri(_uri); req.setUri(_uri);
req.setKey("Upgrade", "websocket"); req.setKey("Upgrade", "websocket");
req.setKey("Connection", "Upgrade"); 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("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); ememory::SharedPtr<enet::HttpClient> interface = std::dynamic_pointer_cast<enet::HttpClient>(m_interface);
if (interface!=nullptr) { if (interface!=nullptr) {
interface->setHeader(req); interface->setHeader(req);
@ -83,7 +106,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
int32_t len = _connection.read(&opcode, sizeof(uint8_t)); int32_t len = _connection.read(&opcode, sizeof(uint8_t));
if (len <= 0) { if (len <= 0) {
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]"); ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true); m_interface->stop(true);
return; return;
@ -103,7 +128,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
ENET_VERBOSE("Read payload : " << uint32_t(size1)); ENET_VERBOSE("Read payload : " << uint32_t(size1));
if (len <= 0) { if (len <= 0) {
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]"); ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true); m_interface->stop(true);
return; return;
@ -118,7 +145,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
len = _connection.read(&tmpSize, sizeof(uint16_t)); len = _connection.read(&tmpSize, sizeof(uint16_t));
if (len <= 1) { if (len <= 1) {
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]"); ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true); m_interface->stop(true);
return; return;
@ -132,7 +161,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
len = _connection.read(&totalSize, sizeof(uint64_t)); len = _connection.read(&totalSize, sizeof(uint64_t));
if (len <= 7) { if (len <= 7) {
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]"); ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true); m_interface->stop(true);
return; return;
@ -148,7 +179,9 @@ void enet::WebSocket::onReceiveData(enet::Tcp& _connection) {
len = _connection.read(&dataMask, sizeof(uint32_t)); len = _connection.read(&dataMask, sizeof(uint32_t));
if (len <= 3) { if (len <= 3) {
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]"); ENET_VERBOSE("ReadRaw 1 [STOP]");
m_interface->stop(true); m_interface->stop(true);
return; return;
@ -265,8 +298,8 @@ void enet::WebSocket::onReceiveRequest(const enet::HttpRequest& _data) {
enet::HttpAnswer answer(enet::HTTPAnswerCode::c101_switchingProtocols); enet::HttpAnswer answer(enet::HTTPAnswerCode::c101_switchingProtocols);
answer.setKey("Upgrade", "websocket"); answer.setKey("Upgrade", "websocket");
answer.setKey("Connection", "Upgrade"); answer.setKey("Connection", "Upgrade");
// TODO: Do it better: std::string answerKey = generateCheckKey(_data.getKey("Sec-WebSocket-Key"));
answer.setKey("Sec-WebSocket-Accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="); //base64::encode()); answer.setKey("Sec-WebSocket-Accept", answerKey);
interface->setHeader(answer); interface->setHeader(answer);
} }
@ -292,7 +325,7 @@ void enet::WebSocket::onReceiveAnswer(const enet::HttpAnswer& _data) {
return; return;
} }
// NOTE : This is a temporary magic check ... // 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") << "'"); ENET_ERROR("Wrong key : 'Sec-WebSocket-Accept : xxx' get '" << _data.getKey("Sec-WebSocket-Accept") << "'");
m_interface->stop(true); m_interface->stop(true);
return; return;

View File

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

View File

@ -26,7 +26,7 @@ def get_version():
def create(target, module_name): def create(target, module_name):
my_module = module.Module(__file__, module_name, get_type()) 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([ my_module.add_src_file([
'enet/debug.cpp' 'enet/debug.cpp'
]) ])

View File

@ -53,7 +53,7 @@ int main(int _argc, const char *_argv[]) {
connection.connect(appl::onReceiveData); connection.connect(appl::onReceiveData);
// start http connection (the actual state is just TCP start ...) // start http connection (the actual state is just TCP start ...)
connection.start("plop.txt"); connection.start("/plop.txt");
// send some data to play ... // send some data to play ...
connection.write("coucou comment ca vas ???"); 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) { bool onReceiveUri(enet::WebSocket* _interface, const std::string& _uri) {
TEST_INFO("Receive Header uri: " << _uri); TEST_INFO("Receive Header uri: " << _uri);
if (_uri == "plop.txt") { if (_uri == "/plop.txt") {
return true; return true;
} }
return false; return false;