Files
tools_previewer/util/WebSocketServer.cpp
T
2023-03-01 10:49:35 +08:00

145 lines
4.6 KiB
C++

/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <thread>
#include "CommandLineInterface.h"
#include "PreviewerEngineLog.h"
#include "WebSocketServer.h"
using namespace std;
lws* WebSocketServer::webSocket = nullptr;
bool WebSocketServer::interrupted = false;
WebSocketServer::WebSocketState WebSocketServer::webSocketWritable = WebSocketState::INIT;
uint8_t* WebSocketServer::firstImageBuffer = nullptr;
uint64_t WebSocketServer::firstImagebufferSize = 0;
int8_t* WebSocketServer::receivedMessage = nullptr;
WebSocketServer::WebSocketServer() : serverThread(nullptr), serverPort(0) {}
WebSocketServer::~WebSocketServer() {}
WebSocketServer& WebSocketServer::GetInstance()
{
static WebSocketServer server;
return server;
}
void WebSocketServer::SetServerPort(int port)
{
serverPort = port;
}
struct lws_protocols protocols[] = {
{
"ws", WebSocketServer::ProtocolCallback, 0, MAX_PAYLOAD_SIZE
},
{
NULL, NULL, 0, 0
}
};
int WebSocketServer::ProtocolCallback(struct lws* wsi,
enum lws_callback_reasons reason,
void* user,
void* in,
size_t len)
{
switch (reason) {
case LWS_CALLBACK_PROTOCOL_INIT:
ILOG("Engine Websocket protocol init");
break;
case LWS_CALLBACK_ESTABLISHED:
ILOG("Websocket client connect");
webSocket = wsi;
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_RECEIVE:
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
ILOG("Engine websocket server writeable");
if (firstImagebufferSize > 0 && webSocketWritable == WebSocketState::UNWRITEABLE) {
ILOG("Send last image after websocket reconnected");
std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
lws_write(wsi,
firstImageBuffer + LWS_PRE,
firstImagebufferSize,
LWS_WRITE_BINARY);
}
webSocketWritable = WebSocketState::WRITEABLE;
break;
case LWS_CALLBACK_CLOSED:
ILOG("Websocket client connection closed");
webSocketWritable = WebSocketState::UNWRITEABLE;
break;
default:
break;
}
return 0;
}
void WebSocketServer::sigint_handler(int sig)
{
interrupted = true;
}
void WebSocketServer::StartWebsocketListening()
{
if (signal(SIGINT, sigint_handler) == SIG_ERR) {
return;
}
ILOG("Begin to start websocket listening!");
struct lws_context_creation_info contextInfo = {0};
contextInfo.port = serverPort;
contextInfo.iface = serverHostname;
contextInfo.protocols = protocols;
contextInfo.ip_limit_wsi = websocketMaxConn;
contextInfo.options = LWS_SERVER_OPTION_VALIDATE_UTF8;
struct lws_context* context = lws_create_context(&contextInfo);
if (context == nullptr) {
ELOG("WebSocketServer::StartWebsocketListening context memory allocation failed");
return;
}
while (!interrupted) {
if (lws_service(context, WEBSOCKET_SERVER_TIMEOUT)) {
interrupted = true;
}
}
lws_context_destroy(context);
}
void WebSocketServer::Run()
{
if (serverThread != nullptr) {
delete serverThread;
serverThread = nullptr;
}
serverThread = new std::thread(&WebSocketServer::StartWebsocketListening, &WebSocketServer::GetInstance());
if (serverThread == nullptr) {
ELOG("WebSocketServer::Start serverThread memory allocation failed");
}
serverThread->detach();
}
size_t WebSocketServer::WriteData(unsigned char* data, size_t length)
{
while (webSocketWritable != WebSocketState::WRITEABLE) {
this_thread::sleep_for(chrono::milliseconds(1));
}
if (webSocket != nullptr && webSocketWritable == WebSocketState::WRITEABLE) {
return lws_write(webSocket, data, length, LWS_WRITE_BINARY);
}
return 0;
}