Skip to content

Commit

Permalink
Feature: Enable Fragmentation for Text Frames in WebSocket Gateway AS…
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Huebl committed Nov 7, 2022
1 parent 3253215 commit f1ae6aa
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/OpcUaWebServer/WebSocket/WebSocketChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace OpcUaWebServer

bool timeout_;
uint32_t id_;
uint8_t opcode_;
uint8_t opcode_ { 0x01 }; // OP_TEXT_FRAME
boost::asio::streambuf recvBuffer_;
boost::asio::streambuf sendBuffer_;
WebSocketRequest webSocketRequest_;
Expand Down
123 changes: 123 additions & 0 deletions src/OpcUaWebServer/WebSocket/WebSocketMessageContext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
Copyright 2015-2022 ASNeG ([email protected])
Lizenziert gemäß Apache Licence Version 2.0 (die „Lizenz“); Nutzung dieser
Datei nur in Übereinstimmung mit der Lizenz erlaubt.
Eine Kopie der Lizenz erhalten Sie auf http://www.apache.org/licenses/LICENSE-2.0.
Sofern nicht gemäß geltendem Recht vorgeschrieben oder schriftlich vereinbart,
erfolgt die Bereitstellung der im Rahmen der Lizenz verbreiteten Software OHNE
GEWÄHR ODER VORBEHALTE – ganz gleich, ob ausdrücklich oder stillschweigend.
Informationen über die jeweiligen Bedingungen für Genehmigungen und Einschränkungen
im Rahmen der Lizenz finden Sie in der Lizenz.
Autor: Samuel Huebl
*/

#include <boost/make_shared.hpp>

#include "OpcUaStackCore/Base/Log.h"
#include "OpcUaWebServer/WebSocket/WebSocketMessageContext.h"

using namespace OpcUaStackCore;

namespace OpcUaWebServer
{

void
WebSocketMessageContext::setHeader(bool fin, uint8_t opcode, bool mask, uint32_t length)
{
fin_ = fin;
opcode_ = opcode;
mask_ = mask;
length_ = length;

Log(Info, "WebSocketServer set new message header")
.parameter("fin", fin_)
.parameter("opcode", opcode_)
.parameter("mask", mask_)
.parameter("length", length_);
}

bool
WebSocketMessageContext::fin(void)
{
return fin_;
}

uint8_t
WebSocketMessageContext::opcode(void)
{
return opcode_;
}

bool
WebSocketMessageContext::mask(void)
{
return mask_;
}

uint32_t
WebSocketMessageContext::length(void)
{
return length_;
}

void
WebSocketMessageContext::setMessageFragment(WebSocketMessage::SPtr message)
{
Log(Info, "WebSocketServer add container for message fragmentation.");

if (webSocketMessageFragmentation_ != nullptr) {
webSocketMessageFragmentation_.reset();
webSocketMessageFragmentation_ = nullptr;
}

webSocketMessageFragmentation_ = message;
}

WebSocketMessage::SPtr
WebSocketMessageContext::getMessageFragments(void)
{
return webSocketMessageFragmentation_;
}

void
WebSocketMessageContext::clear(void)
{
Log(Info, "WebSocketServer clears message context.");

fin_ = true;
opcode_ = 1;
mask_ = true;
length_ = 0;

if (webSocketMessageFragmentation_ != nullptr) {
webSocketMessageFragmentation_.reset();
webSocketMessageFragmentation_ = nullptr;
}
}


WebSocketMessageContext::EnumFrameType
WebSocketMessageContext::getFrameType(void)
{
// https://www.rfc-editor.org/rfc/rfc6455#section-5.4
// opcode == 0 && fin == true => LastFrame
// opcode == 0 && fin == false => Frame
// opcode != 0 && fin == false => FirstFrame
// opcode != 0 && fin == true => SingleFrame

if (opcode_ == 0x00 /*OP_CONTINUATION_FRAME*/) {
if (fin_) return EnumFrameType::FrameType_LastFrame;
else return EnumFrameType::FrameType_Frame;
}

if (!fin_) return EnumFrameType::FrameType_FirstFrame;

return EnumFrameType::FrameType_SingleFrame;
}

}
62 changes: 62 additions & 0 deletions src/OpcUaWebServer/WebSocket/WebSocketMessageContext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Copyright 2015-2022 ASNeG ([email protected])
Lizenziert gemäß Apache Licence Version 2.0 (die „Lizenz“); Nutzung dieser
Datei nur in Übereinstimmung mit der Lizenz erlaubt.
Eine Kopie der Lizenz erhalten Sie auf http://www.apache.org/licenses/LICENSE-2.0.
Sofern nicht gemäß geltendem Recht vorgeschrieben oder schriftlich vereinbart,
erfolgt die Bereitstellung der im Rahmen der Lizenz verbreiteten Software OHNE
GEWÄHR ODER VORBEHALTE – ganz gleich, ob ausdrücklich oder stillschweigend.
Informationen über die jeweiligen Bedingungen für Genehmigungen und Einschränkungen
im Rahmen der Lizenz finden Sie in der Lizenz.
Autor: Samuel Huebl
*/

#include "OpcUaStackCore/Base/os.h"
#include "OpcUaWebServer/WebSocket/WebSocketMessage.h"

namespace OpcUaWebServer
{

class DLLEXPORT WebSocketMessageContext
{
public:
typedef enum {
FrameType_Unknown = 0,
FrameType_SingleFrame = 1,
FrameType_Frame = 2,
FrameType_FirstFrame = 3,
FrameType_LastFrame = 4
} EnumFrameType;

typedef boost::shared_ptr<WebSocketMessageContext> SPtr;

WebSocketMessageContext(void) = default;
virtual ~WebSocketMessageContext(void) = default;

void setHeader(bool fin, uint8_t opcode, bool mask, uint32_t length);
bool fin(void);
uint8_t opcode(void);
bool mask(void);
uint32_t length(void);

void setMessageFragment(WebSocketMessage::SPtr message);
WebSocketMessage::SPtr getMessageFragments(void);

void clear(void);

EnumFrameType getFrameType(void);

private:
bool fin_ { true };
uint8_t opcode_ { 0x1 };
bool mask_ { true };
uint32_t length_ { 0x0 };

WebSocketMessage::SPtr webSocketMessageFragmentation_ { nullptr };
};

}
Loading

0 comments on commit f1ae6aa

Please sign in to comment.