iSulad/0040-bugfix-for-websocket-receive-data-too-long.patch

155 lines
5.4 KiB
Diff
Raw Normal View History

From 3942fb5667077200017a1a7c72672e482e798df6 Mon Sep 17 00:00:00 2001
From: zhangxiaoyu <zhangxiaoyu58@huawei.com>
Date: Tue, 1 Nov 2022 14:36:02 +0800
Subject: [PATCH 40/43] bugfix for websocket receive data too long
Signed-off-by: zhangxiaoyu <zhangxiaoyu58@huawei.com>
---
.../entry/cri/websocket/service/ws_server.cc | 65 ++++++++++++++++---
.../entry/cri/websocket/service/ws_server.h | 5 +-
2 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/src/daemon/entry/cri/websocket/service/ws_server.cc b/src/daemon/entry/cri/websocket/service/ws_server.cc
index 41bb3fe8..ea320ff4 100644
--- a/src/daemon/entry/cri/websocket/service/ws_server.cc
+++ b/src/daemon/entry/cri/websocket/service/ws_server.cc
@@ -126,6 +126,32 @@ void SessionData::CloseSession()
sessionMutex->unlock();
}
+bool SessionData::IsStdinComplete()
+{
+ bool c = true;
+
+ if (sessionMutex == nullptr) {
+ return true;
+ }
+
+ sessionMutex->lock();
+ c = completeStdin;
+ sessionMutex->unlock();
+
+ return c;
+}
+
+void SessionData::SetStdinComplete(bool complete)
+{
+ if (sessionMutex == nullptr) {
+ return;
+ }
+
+ sessionMutex->lock();
+ completeStdin = complete;
+ sessionMutex->unlock();
+}
+
void SessionData::EraseAllMessage()
{
if (sessionMutex == nullptr) {
@@ -330,6 +356,7 @@ int WebsocketServer::GenerateSessionData(SessionData *session, const std::string
session->sessionMutex = bufMutex;
session->syncCloseSem = syncCloseSem;
session->close = false;
+ session->completeStdin = true;
session->containerID = containerID;
session->suffix = std::string(suffix);
@@ -524,28 +551,44 @@ int WebsocketServer::ResizeTerminal(int socketID, const char *jsonData, size_t l
return ret;
}
-void WebsocketServer::Receive(int socketID, void *in, size_t len)
+void WebsocketServer::Receive(int socketID, void *in, size_t len, bool complete)
{
auto it = m_wsis.find(socketID);
if (it == m_wsis.end()) {
- ERROR("invailed websocket session!");
+ ERROR("Invailed websocket session!");
return;
}
+ if (!it->second->IsStdinComplete()) {
+ DEBUG("Receive remaning stdin data with length %zu", len);
+ // Too much data may cause error 'resource temporarily unavaliable' by using 'write'
+ if (util_write_nointr_in_total(m_wsis[socketID]->pipes.at(1), (char *)in, len) < 0) {
+ ERROR("Sub write over! err msg: %s", strerror(errno));
+ }
+ goto out;
+ }
+
if (*static_cast<char *>(in) == WebsocketChannel::RESIZECHANNEL) {
if (ResizeTerminal(socketID, (char *)in + 1, len, it->second->containerID, it->second->suffix) != 0) {
ERROR("Failed to resize terminal tty");
- return;
}
- } else if (*static_cast<char *>(in) == WebsocketChannel::STDINCHANNEL) {
- if (write(m_wsis[socketID]->pipes.at(1), (void *)((char *)in + 1), len - 1) < 0) {
- ERROR("sub write over!");
- return;
+ if (!complete) {
+ ERROR("Resize data too long");
}
- } else {
- ERROR("invalid data: %s", (char *)in);
return;
}
+
+ if (*static_cast<char *>(in) == WebsocketChannel::STDINCHANNEL) {
+ if (util_write_nointr_in_total(m_wsis[socketID]->pipes.at(1), (char *)in + 1, len - 1) < 0) {
+ ERROR("Sub write over! err msg: %s", strerror(errno));
+ }
+ goto out;
+ }
+
+ ERROR("Invalid data: %s", (char *)in);
+
+out:
+ it->second->SetStdinComplete(complete);
}
int WebsocketServer::Callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
@@ -605,7 +648,9 @@ int WebsocketServer::Callback(struct lws *wsi, enum lws_callback_reasons reason,
break;
case LWS_CALLBACK_RECEIVE: {
ReadGuard<RWMutex> lock(m_mutex);
- WebsocketServer::GetInstance()->Receive(lws_get_socket_fd(wsi), static_cast<char *>(in), len);
+ size_t bytesLen = lws_remaining_packet_payload(wsi);
+ WebsocketServer::GetInstance()->Receive(lws_get_socket_fd(wsi), static_cast<char *>(in),
+ len, bytesLen == 0);
}
break;
case LWS_CALLBACK_CLOSED: {
diff --git a/src/daemon/entry/cri/websocket/service/ws_server.h b/src/daemon/entry/cri/websocket/service/ws_server.h
index a2a180ec..7da56818 100644
--- a/src/daemon/entry/cri/websocket/service/ws_server.h
+++ b/src/daemon/entry/cri/websocket/service/ws_server.h
@@ -44,6 +44,7 @@ struct SessionData {
std::list<unsigned char *> buffer;
std::string containerID;
std::string suffix;
+ volatile bool completeStdin;
unsigned char *FrontMessage();
void PopMessage();
@@ -51,6 +52,8 @@ struct SessionData {
bool IsClosed();
void CloseSession();
void EraseAllMessage();
+ bool IsStdinComplete();
+ void SetStdinComplete(bool complete);
};
class WebsocketServer {
@@ -72,7 +75,7 @@ private:
std::vector<std::string> split(std::string str, char r);
int CreateContext();
- inline void Receive(int socketID, void *in, size_t len);
+ inline void Receive(int socketID, void *in, size_t len, bool complete);
int Wswrite(struct lws *wsi, const unsigned char *message);
inline void DumpHandshakeInfo(struct lws *wsi) noexcept;
int RegisterStreamTask(struct lws *wsi) noexcept;
--
2.25.1