Implement client websocket masking.

Disable this for easy strace debugging and a bit of perf. to the forkit.

Change-Id: Ia330582817481410d26df50db5eb42b4692ad01c
This commit is contained in:
Michael Meeks 2018-06-15 14:18:31 +01:00
parent 5741d76a5d
commit 7e6e81eb46
3 changed files with 38 additions and 13 deletions

View file

@ -2009,7 +2009,7 @@ class KitWebSocketHandler final : public WebSocketHandler, public std::enable_sh
public:
KitWebSocketHandler(const std::string& socketName, const std::shared_ptr<lok::Office>& loKit, const std::string& jailId, SocketPoll& socketPoll) :
WebSocketHandler(/* isClient = */ true),
WebSocketHandler(/* isClient = */ true, /* isMasking */ false),
_queue(std::make_shared<TileQueue>()),
_socketName(socketName),
_loKit(loKit),

View file

@ -36,6 +36,7 @@ protected:
std::vector<char> _wsPayload;
std::atomic<bool> _shuttingDown;
bool _isClient;
bool _isMasking;
struct WSFrameMask
{
@ -48,11 +49,12 @@ protected:
public:
/// Perform upgrade ourselves, or select a client web socket.
WebSocketHandler(bool isClient = false) :
WebSocketHandler(bool isClient = false, bool isMasking = true) :
_lastPingSentTime(std::chrono::steady_clock::now()),
_pingTimeUs(0),
_shuttingDown(false),
_isClient(isClient)
_isClient(isClient),
_isMasking(isClient && isMasking)
{
}
@ -65,7 +67,8 @@ public:
std::chrono::milliseconds(InitialPingDelayMs)),
_pingTimeUs(0),
_shuttingDown(false),
_isClient(false)
_isClient(false),
_isMasking(false)
{
upgradeToWebSocket(request);
}
@ -381,14 +384,14 @@ public:
return sendFrame(socket, data, len, WSFrameMask::Fin | static_cast<unsigned char>(code), flush);
}
protected:
private:
/// Sends a WebSocket frame given the data, length, and flags.
/// Returns the number of bytes written (including frame overhead) on success,
/// 0 for closed/invalid socket, and -1 for other errors.
static int sendFrame(const std::shared_ptr<StreamSocket>& socket,
const char* data, const size_t len,
const unsigned char flags, const bool flush = true)
int sendFrame(const std::shared_ptr<StreamSocket>& socket,
const char* data, const size_t len,
unsigned char flags, const bool flush = true) const
{
if (!socket || data == nullptr || len == 0)
return -1;
@ -402,19 +405,20 @@ protected:
out.push_back(flags);
int maskFlag = _isMasking ? 0x80 : 0;
if (len < 126)
{
out.push_back((char)len);
out.push_back((char)(len | maskFlag));
}
else if (len <= 0xffff)
{
out.push_back((char)126);
out.push_back((char)(126 | maskFlag));
out.push_back(static_cast<char>((len >> 8) & 0xff));
out.push_back(static_cast<char>((len >> 0) & 0xff));
}
else
{
out.push_back((char)127);
out.push_back((char)(127 | maskFlag));
out.push_back(static_cast<char>((len >> 56) & 0xff));
out.push_back(static_cast<char>((len >> 48) & 0xff));
out.push_back(static_cast<char>((len >> 40) & 0xff));
@ -425,8 +429,27 @@ protected:
out.push_back(static_cast<char>((len >> 0) & 0xff));
}
// Copy the data.
out.insert(out.end(), data, data + len);
if (_isMasking)
{ // flip some top bits - perhaps it helps.
size_t mask = out.size();
out.push_back(static_cast<char>(0x81));
out.push_back(static_cast<char>(0x76));
out.push_back(static_cast<char>(0x81));
out.push_back(static_cast<char>(0x76));
// Copy the data.
out.insert(out.end(), data, data + len);
// Mask it.
for (size_t i = 4; i < out.size() - mask; ++i)
out[mask + i] = out[mask + i] ^ out[mask + (i%4)];
}
else
{
// Copy the data.
out.insert(out.end(), data, data + len);
}
const size_t size = out.size() - oldSize;
if (flush)
@ -435,6 +458,8 @@ protected:
return size;
}
protected:
/// To be overriden to handle the websocket messages the way you need.
virtual void handleMessage(bool /*fin*/, WSOpCode /*code*/, std::vector<char> &/*data*/)
{

Binary file not shown.