From ea0fd3c136fe9e8ecdd81c4122677dd2f4c2d031 Mon Sep 17 00:00:00 2001 From: hwfqb Date: Sat, 6 Sep 2025 21:38:42 +0800 Subject: [PATCH] fix bug: TcpSocketServer close interface support object-isolation Signed-off-by: hwfqb --- .../socket/socket_exec/include/socket_exec.h | 143 +++++++++--------- .../socket/socket_exec/src/socket_exec.cpp | 80 ++++++++-- .../socket_module/src/socket_module.cpp | 8 +- utils/napi_utils/include/event_manager.h | 9 ++ utils/napi_utils/src/event_manager.cpp | 10 ++ 5 files changed, 159 insertions(+), 91 deletions(-) diff --git a/frameworks/js/napi/socket/socket_exec/include/socket_exec.h b/frameworks/js/napi/socket/socket_exec/include/socket_exec.h index d545af8b7..bd502adf9 100644 --- a/frameworks/js/napi/socket/socket_exec/include/socket_exec.h +++ b/frameworks/js/napi/socket/socket_exec/include/socket_exec.h @@ -38,8 +38,77 @@ #include namespace OHOS::NetStack::Socket::SocketExec { + +class SocketConfig { +public: + SocketConfig() {} + ~SocketConfig() {} + void SetTcpExtraOptions(int listenFd, const TCPExtraOptions& option) + { + tcpExtraOptions_.EnsureInsert(listenFd, option); + } + + bool GetTcpExtraOptions(int listenFd, TCPExtraOptions& option) + { + return tcpExtraOptions_.Find(listenFd, option); + } + + void AddNewListenSocket(int listenFd) + { + tcpClients_.Insert(listenFd, {}); + } + + void AddNewAcceptSocket(int listenFd, int acceptFd) + { + std::set fdSet; + auto fn = [&](std::set &value) -> void { + value.emplace(acceptFd); + }; + if (tcpClients_.Find(listenFd, fdSet)) { + tcpClients_.ChangeValueByLambda(listenFd, fn); + } + } + + void RemoveAcceptSocket(int acceptFd) + { + tcpClients_.Iterate([acceptFd](int listenFd, std::set fdSet) { + if (auto ite = fdSet.find(acceptFd); ite != fdSet.end()) { + fdSet.erase(ite); + } + }); + } + + std::set GetClients(int listenFd) + { + std::set fdSet; + tcpClients_.Find(listenFd, fdSet); + return fdSet; + } + + void RemoveServerSocket(int listenFd) + { + tcpExtraOptions_.Erase(listenFd); + tcpClients_.Erase(listenFd); + } + + void ShutdownAllSockets() + { + tcpClients_.Iterate([](const int key, std::set&) { shutdown(key, SHUT_RDWR); }); + tcpExtraOptions_.Clear(); + tcpClients_.Clear(); + } +private: + SocketConfig(const SocketConfig& singleton) = delete; + SocketConfig& operator=(const SocketConfig& singleton) = delete; + + SafeMap tcpExtraOptions_; + SafeMap> tcpClients_; +}; + void NotifyRegisterEvent(); +std::shared_ptr GetSharedConfig(const std::shared_ptr &manager); + /* async work execute */ bool ExecUdpBind(BindContext *context); @@ -175,80 +244,6 @@ struct TcpConnection { int32_t clientId; }; -class SingletonSocketConfig { -public: - static SingletonSocketConfig& GetInstance() - { - static SingletonSocketConfig instance; - return instance; - } - - void SetTcpExtraOptions(int listenFd, const TCPExtraOptions& option) - { - tcpExtraOptions_.EnsureInsert(listenFd, option); - } - - bool GetTcpExtraOptions(int listenFd, TCPExtraOptions& option) - { - return tcpExtraOptions_.Find(listenFd, option); - } - - void AddNewListenSocket(int listenFd) - { - tcpClients_.Insert(listenFd, {}); - } - - void AddNewAcceptSocket(int listenFd, int acceptFd) - { - std::set fdSet; - auto fn = [&](std::set &value) -> void { - value.emplace(acceptFd); - }; - if (tcpClients_.Find(listenFd, fdSet)) { - tcpClients_.ChangeValueByLambda(listenFd, fn); - } - } - - void RemoveAcceptSocket(int acceptFd) - { - tcpClients_.Iterate([acceptFd](int listenFd, std::set fdSet) { - if (auto ite = fdSet.find(acceptFd); ite != fdSet.end()) { - fdSet.erase(ite); - } - }); - } - - std::set GetClients(int listenFd) - { - std::set fdSet; - tcpClients_.Find(listenFd, fdSet); - return fdSet; - } - - void RemoveServerSocket(int listenFd) - { - tcpExtraOptions_.Erase(listenFd); - tcpClients_.Erase(listenFd); - } - - void ShutdownAllSockets() - { - tcpClients_.Iterate([](const int key, std::set&) { shutdown(key, SHUT_RDWR); }); - tcpExtraOptions_.Clear(); - tcpClients_.Clear(); - } - -private: - SingletonSocketConfig() {} - ~SingletonSocketConfig() {} - - SingletonSocketConfig(const SingletonSocketConfig& singleton) = delete; - SingletonSocketConfig& operator=(const SingletonSocketConfig& singleton) = delete; - - SafeMap tcpExtraOptions_; - SafeMap> tcpClients_; -}; - class MessageCallback { public: MessageCallback() = delete; diff --git a/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp b/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp index 482d3d994..fc543317f 100644 --- a/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp +++ b/frameworks/js/napi/socket/socket_exec/src/socket_exec.cpp @@ -125,6 +125,7 @@ static void SetIsConnected(sa_family_t family, GetStateContext *context, const s static napi_value MakeError(napi_env env, void *errCode) { auto code = reinterpret_cast(errCode); + NETSTACK_LOGI("go to MakeError, err: %{public}d", *code); auto deleter = [](const int32_t *p) { delete p; }; std::unique_ptr handler(code, deleter); @@ -2099,8 +2100,14 @@ static std::shared_ptr WaitForManagerReady(int32_t clientId, int & static inline void RecvInErrorCondition(int reason, int clientId, int connectFD, const TcpMessageCallback &callback) { + NETSTACK_LOGE("Recv Error, reason: %{public}d, clientId: %{public}d," + "connectFD: %{public}d", reason, clientId, connectFD); RemoveClientConnection(clientId); - SingletonSocketConfig::GetInstance().RemoveAcceptSocket(connectFD); + auto config = GetSharedConfig(callback.GetEventManager()); + if (config == nullptr) { + return; + } + config->RemoveAcceptSocket(connectFD); callback.OnError(reason); } @@ -2109,7 +2116,11 @@ static inline void CloseClientHandler(int clientId, int connectFD, const std::sh { callback.OnCloseMessage(manager); RemoveClientConnection(clientId); - SingletonSocketConfig::GetInstance().RemoveAcceptSocket(connectFD); + auto config = GetSharedConfig(callback.GetEventManager()); + if (config == nullptr) { + return; + } + config->RemoveAcceptSocket(connectFD); } static int PollSocket(int clientId, int connectFD, const std::shared_ptr &manager, @@ -2185,15 +2196,16 @@ static void ClientPollRecv(int clientId, int connectFD, uint32_t recvBufferSize, CloseClientHandler(clientId, connectFD, manager, callback); break; } - int flags = fcntl(connectFD, F_GETFL, 0); - if (flags == -1) { + if (fcntl(connectFD, F_GETFL, 0) == -1) { + NETSTACK_LOGE("Client socket %{public}d fcntl F_GETFL error, errno is %{public}d", connectFD, errno); CloseClientHandler(clientId, connectFD, manager, callback); break; } if (recvSize <= 0) { - NETSTACK_LOGI("ClientRecv: fd:%{public}d, size:%{public}d, errno:%{public}d, is non blocking:%{public}s", - connectFD, recvSize, errno, static_cast(flags) & O_NONBLOCK ? "true" : "false"); + NETSTACK_LOGI("Recv: fd:%{public}d, size:%{public}d, err:%{public}d", connectFD, recvSize, errno); if ((recvSize == 0) || (recvSize < 0 && errno != EAGAIN && errno != EINTR)) { + recvSize == 0 ? NETSTACK_LOGE("connection closed by peer, socket is %{public}d", connectFD) : + NETSTACK_LOGE("connection recv failed, socket: %{public}d, errno: %{public}d", connectFD, errno); CloseClientHandler(clientId, connectFD, manager, callback); break; } @@ -2219,7 +2231,12 @@ static void ClientHandler(int32_t sock, int32_t clientId, const TcpMessageCallba uint32_t recvBufferSize = DEFAULT_BUFFER_SIZE; TCPExtraOptions option; - if (SingletonSocketConfig::GetInstance().GetTcpExtraOptions(sock, option)) { + auto config = GetSharedConfig(callback.GetEventManager()); + if (config == nullptr) { + return; + } + config->RemoveAcceptSocket(connectFD); + if (config->GetTcpExtraOptions(sock, option)) { if (option.GetReceiveBufferSize() != 0) { recvBufferSize = option.GetReceiveBufferSize(); } @@ -2252,15 +2269,18 @@ static void AcceptRecvData(int sock, sockaddr *addr, socklen_t addrLen, const Tc close(connectFD); continue; } - NETSTACK_LOGI("Server accept new client SUCCESS, fd = %{public}d", connectFD); + NETSTACK_LOGI("Server accept new client, fd= %{public}d clientfd= %{public}d", sock, connectFD); g_userCounter++; g_clientFDs[g_userCounter] = connectFD; } callback.OnTcpConnectionMessage(g_userCounter); int clientId = g_userCounter; - - SingletonSocketConfig::GetInstance().AddNewAcceptSocket(sock, connectFD); - if (TCPExtraOptions option; SingletonSocketConfig::GetInstance().GetTcpExtraOptions(sock, option)) { + auto config = GetSharedConfig(callback.GetEventManager()); + if (config == nullptr) { + return; + } + config->AddNewAcceptSocket(sock, connectFD); + if (TCPExtraOptions option; config->GetTcpExtraOptions(sock, option)) { SocketSetTcpExtraOptions(connectFD, option); } auto handlerThread = std::make_shared(ClientHandler, sock, clientId, callback); @@ -2288,7 +2308,16 @@ bool ExecTcpServerListen(TcpServerListenContext *context) NETSTACK_LOGE("tcp server listen error"); return false; } - SingletonSocketConfig::GetInstance().AddNewListenSocket(context->GetSocketFd()); + auto manager = context->GetSharedManager(); + if (manager == nullptr) { + NETSTACK_LOGE("manager is null"); + return false; + } + if (!manager->GetSocketConfig()) { + auto config = std::make_shared(); + manager->SetSocketConfig(config); + } + manager->GetSocketConfig()->AddNewListenSocket(context->GetSocketFd()); NETSTACK_LOGI("listen success"); std::thread serviceThread(AcceptRecvData, context->GetSocketFd(), nullptr, 0, TcpMessageCallback(context->GetSharedManager())); @@ -2301,6 +2330,19 @@ bool ExecTcpServerListen(TcpServerListenContext *context) return true; } +std::shared_ptr GetSharedConfig(const std::shared_ptr &manager) +{ + if (manager == nullptr) { + NETSTACK_LOGE("GetSocketConfig manager is nullptr"); + return nullptr; + } + if (manager->GetSocketConfig() == nullptr) { + NETSTACK_LOGE("GetSocketConfig socketConfig is nullptr"); + return nullptr; + } + return manager->GetSocketConfig(); +} + bool ExecTcpServerClose(TcpServerCloseContext *context) { if (!CommonUtils::HasInternetPermission()) { @@ -2312,7 +2354,11 @@ bool ExecTcpServerClose(TcpServerCloseContext *context) NETSTACK_LOGI("TCPServer socket was closed before"); return true; } - SocketExec::SingletonSocketConfig::GetInstance().ShutdownAllSockets(); + auto config = GetSharedConfig(context->GetSharedManager()); + if (config == nullptr) { + return false; + } + config->ShutdownAllSockets(); NETSTACK_LOGI("close all listenfd"); context->SetSocketFd(-1); return true; @@ -2328,7 +2374,11 @@ bool ExecTcpServerSetExtraOptions(TcpServerSetExtraOptionsContext *context) context->SetError(ERRNO_BAD_FD, strerror(ERRNO_BAD_FD)); return false; } - auto clients = SingletonSocketConfig::GetInstance().GetClients(context->GetSocketFd()); + auto config = GetSharedConfig(context->GetSharedManager()); + if (config == nullptr) { + return false; + } + auto clients = config->GetClients(context->GetSocketFd()); if (std::any_of(clients.begin(), clients.end(), [&context](int32_t fd) { return !SocketSetTcpExtraOptions(fd, context->options_); })) { @@ -2336,7 +2386,7 @@ bool ExecTcpServerSetExtraOptions(TcpServerSetExtraOptionsContext *context) return false; } - SingletonSocketConfig::GetInstance().SetTcpExtraOptions(context->GetSocketFd(), context->options_); + config->SetTcpExtraOptions(context->GetSocketFd(), context->options_); return true; } diff --git a/frameworks/js/napi/socket/socket_module/src/socket_module.cpp b/frameworks/js/napi/socket/socket_module/src/socket_module.cpp index d7b645853..88aefc0ef 100644 --- a/frameworks/js/napi/socket/socket_module/src/socket_module.cpp +++ b/frameworks/js/napi/socket/socket_module/src/socket_module.cpp @@ -175,7 +175,6 @@ void Finalize(napi_env env, void *data, void *) if (sock == 0) { NETSTACK_LOGE("manager->GetData() got nullptr, Finalize() called before creating socket?"); } else if (sock != -1) { - SocketExec::SingletonSocketConfig::GetInstance().RemoveServerSocket(sock); auto context = new BaseContext(env, manager); context->CreateAsyncWork(FINALIZE_CLOSE_NAME, ExecFinalizeClose, ExecFinalizeCloseCallback); } @@ -191,9 +190,13 @@ void FinalizeTcpSocketServer(napi_env, void *data, void *) auto manager = *sharedManager; int sock = static_cast(reinterpret_cast(manager->GetData())); if (sock != -1) { - SocketExec::SingletonSocketConfig::GetInstance().ShutdownAllSockets(); NETSTACK_LOGI("finalize close all listenfd"); manager->SetData(reinterpret_cast(-1)); + auto config = SocketExec::GetSharedConfig(manager); + if (config == nullptr) { + return; + } + config->ShutdownAllSockets(); } delete sharedManager; } @@ -639,6 +642,7 @@ void SocketModuleExports::DefineLocalSocketServerClass(napi_env env, napi_value napi_value SocketModuleExports::ConstructTCPSocketServerInstance(napi_env env, napi_callback_info info) { + NETSTACK_LOGI("create new instance for TCPSocketServer"); return ModuleTemplate::NewInstanceWithSharedManager(env, info, INTERFACE_TCP_SOCKET_SERVER, FinalizeTcpSocketServer); } diff --git a/utils/napi_utils/include/event_manager.h b/utils/napi_utils/include/event_manager.h index 0c4825404..fdf9e2f79 100644 --- a/utils/napi_utils/include/event_manager.h +++ b/utils/napi_utils/include/event_manager.h @@ -49,6 +49,10 @@ class UserData; namespace Socks5 { class Socks5Instance; } + +namespace Socket::SocketExec { +class SocketConfig; +} using Finalizer = void (*)(napi_env, void *data, void *); class EventManager : public std::enable_shared_from_this { public: @@ -121,6 +125,10 @@ public: std::shared_ptr GetWebSocketUserData(); + void SetSocketConfig(const std::shared_ptr &config); + + std::shared_ptr GetSocketConfig(); + bool GetReuseAddr(); std::shared_ptr GetProxyData(); @@ -168,6 +176,7 @@ private: bool sockRcvExit_ = false; std::atomic_bool isReuseAddr_ = false; std::shared_ptr webSocketUserData_; + std::shared_ptr socketConfig_ = nullptr; std::shared_ptr proxyData_; std::shared_mutex dataServerQueueMutex_; std::mutex mapMutex_; diff --git a/utils/napi_utils/src/event_manager.cpp b/utils/napi_utils/src/event_manager.cpp index e3d77df4a..429cc48df 100644 --- a/utils/napi_utils/src/event_manager.cpp +++ b/utils/napi_utils/src/event_manager.cpp @@ -391,6 +391,16 @@ std::shared_ptr EventManager::GetWebSocketUserData() return webSocketUserData_; } +void EventManager::SetSocketConfig(const std::shared_ptr &config) +{ + socketConfig_ = config; +} + +std::shared_ptr EventManager::GetSocketConfig() +{ + return socketConfig_; +} + UvWorkWrapperShared::UvWorkWrapperShared(void *theData, napi_env theEnv, std::string eventType, const std::shared_ptr &eventManager) : data(theData), env(theEnv), type(std::move(eventType)), manager(eventManager) -- Gitee