• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <thread>
17 #include "CommandLineInterface.h"
18 #include "PreviewerEngineLog.h"
19 #include "WebSocketServer.h"
20 using namespace std;
21 
22 lws* WebSocketServer::webSocket = nullptr;
23 bool WebSocketServer::interrupted = false;
24 WebSocketServer::WebSocketState WebSocketServer::webSocketWritable = WebSocketState::INIT;
25 uint8_t* WebSocketServer::firstImageBuffer = nullptr;
26 uint64_t WebSocketServer::firstImagebufferSize = 0;
27 int8_t* WebSocketServer::receivedMessage = nullptr;
28 
WebSocketServer()29 WebSocketServer::WebSocketServer() : serverThread(nullptr), serverPort(0)
30 {
31     protocols[0] = {"ws", WebSocketServer::ProtocolCallback, 0, MAX_PAYLOAD_SIZE};
32     protocols[1] = {NULL, NULL, 0, 0};
33 }
34 
~WebSocketServer()35 WebSocketServer::~WebSocketServer() {}
36 
GetInstance()37 WebSocketServer& WebSocketServer::GetInstance()
38 {
39     static WebSocketServer server;
40     return server;
41 }
42 
SetServerPort(int port)43 void WebSocketServer::SetServerPort(int port)
44 {
45     serverPort = port;
46 }
47 
ProtocolCallback(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)48 int WebSocketServer::ProtocolCallback(struct lws* wsi,
49                                       enum lws_callback_reasons reason,
50                                       void* user,
51                                       void* in,
52                                       size_t len)
53 {
54     switch (reason) {
55         case LWS_CALLBACK_PROTOCOL_INIT:
56             ILOG("Engine Websocket protocol init");
57             break;
58         case LWS_CALLBACK_ESTABLISHED:
59             ILOG("Websocket client connect");
60             webSocket = wsi;
61             lws_callback_on_writable(wsi);
62             break;
63         case LWS_CALLBACK_RECEIVE:
64             break;
65         case LWS_CALLBACK_SERVER_WRITEABLE:
66             ILOG("Engine websocket server writeable");
67             if (firstImagebufferSize > 0 && webSocketWritable == WebSocketState::UNWRITEABLE) {
68                 ILOG("Send last image after websocket reconnected");
69                 std::lock_guard<std::mutex> guard(WebSocketServer::GetInstance().mutex);
70                 lws_write(wsi,
71                           firstImageBuffer + LWS_PRE,
72                           firstImagebufferSize,
73                           LWS_WRITE_BINARY);
74             }
75             webSocketWritable = WebSocketState::WRITEABLE;
76             break;
77         case LWS_CALLBACK_CLOSED:
78             ILOG("Websocket client connection closed");
79             webSocketWritable = WebSocketState::UNWRITEABLE;
80             break;
81         default:
82             break;
83     }
84     return 0;
85 }
86 
sigint_handler(int sig)87 void WebSocketServer::sigint_handler(int sig)
88 {
89     interrupted = true;
90 }
91 
StartWebsocketListening()92 void WebSocketServer::StartWebsocketListening()
93 {
94     const auto sig = signal(SIGINT, sigint_handler);
95     if (sig == SIG_ERR) {
96         ELOG("StartWebsocketListening failed");
97         return;
98     }
99     ILOG("Begin to start websocket listening!");
100     struct lws_context_creation_info contextInfo = {0};
101     contextInfo.port = serverPort;
102     contextInfo.iface = serverHostname;
103     contextInfo.protocols = protocols;
104     contextInfo.ip_limit_wsi = websocketMaxConn;
105     contextInfo.options  = LWS_SERVER_OPTION_VALIDATE_UTF8;
106     struct lws_context* context = lws_create_context(&contextInfo);
107     if (context == nullptr) {
108         ELOG("WebSocketServer::StartWebsocketListening context memory allocation failed");
109         return;
110     }
111     while (!interrupted) {
112         if (lws_service(context, WEBSOCKET_SERVER_TIMEOUT)) {
113             interrupted = true;
114         }
115     }
116     lws_context_destroy(context);
117 }
118 
Run()119 void WebSocketServer::Run()
120 {
121     serverThread = std::make_unique<std::thread>(&WebSocketServer::StartWebsocketListening,
122                                                 &WebSocketServer::GetInstance());
123     if (serverThread == nullptr) {
124         ELOG("WebSocketServer::Start serverThread memory allocation failed");
125     }
126     serverThread->detach();
127 }
128 
WriteData(unsigned char * data,size_t length)129 size_t WebSocketServer::WriteData(unsigned char* data, size_t length)
130 {
131     while (webSocketWritable != WebSocketState::WRITEABLE) {
132         this_thread::sleep_for(chrono::milliseconds(1));
133     }
134     if (webSocket != nullptr && webSocketWritable == WebSocketState::WRITEABLE) {
135         return lws_write(webSocket, data, length, LWS_WRITE_BINARY);
136     }
137     return 0;
138 }
139