[DEV] correct key of websocket
This commit is contained in:
parent
4f82e11375
commit
19d49bb462
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
|
||||||
ENET_ERROR("Protocol error occured ...");
|
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) {
|
||||||
|
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
|
||||||
ENET_ERROR("Protocol error occured ...");
|
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) {
|
||||||
|
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
|
||||||
ENET_ERROR("Protocol error occured ...");
|
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) {
|
||||||
|
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
|
||||||
ENET_ERROR("Protocol error occured ...");
|
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) {
|
||||||
|
if (_connection.getConnectionStatus() == enet::Tcp::status::link) {
|
||||||
ENET_ERROR("Protocol error occured ...");
|
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;
|
||||||
|
@ -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();
|
||||||
|
@ -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'
|
||||||
])
|
])
|
||||||
|
@ -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 ???");
|
||||||
|
40
test/main-client-websocket.html
Normal file
40
test/main-client-websocket.html
Normal 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>
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user