From 005f602d2323741f287d6f6b02c9333f964593bd Mon Sep 17 00:00:00 2001 From: shihchienc Date: Wed, 31 Jan 2024 07:37:55 +0000 Subject: [PATCH] [Thread] Wait until socket created to create interface Bug: 313425570 Test: build pass & manual test Change-Id: I4704178519ed032ad352a3ab252e80478c179574 --- .../aidl/default/socket_interface.cpp | 66 +++++++++++++++++++ .../aidl/default/socket_interface.hpp | 24 +++++++ 2 files changed, 90 insertions(+) diff --git a/threadnetwork/aidl/default/socket_interface.cpp b/threadnetwork/aidl/default/socket_interface.cpp index e42f03db7f..a8b434af07 100644 --- a/threadnetwork/aidl/default/socket_interface.cpp +++ b/threadnetwork/aidl/default/socket_interface.cpp @@ -24,14 +24,18 @@ #include #include +#include #include #include #include #include #include +#include + #include "common/code_utils.hpp" #include "openthread/openthread-system.h" +#include "platform-posix.h" namespace aidl { namespace android { @@ -54,6 +58,8 @@ otError SocketInterface::Init(ReceiveFrameCallback aCallback, void* aCallbackCon VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY); + WaitForSocketFileCreated(mRadioUrl.GetPath()); + mSockFd = OpenFile(mRadioUrl); VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED); @@ -125,6 +131,66 @@ exit: return; } +void SocketInterface::WaitForSocketFileCreated(const char* aPath) { + int inotifyFd; + int wd; + int lastSlashIdx; + std::string folderPath; + std::string socketPath(aPath); + + VerifyOrExit(!IsSocketFileExisted(aPath)); + + inotifyFd = inotify_init(); + VerifyOrDie(inotifyFd != -1, OT_EXIT_ERROR_ERRNO); + + lastSlashIdx = socketPath.find_last_of('/'); + VerifyOrDie(lastSlashIdx != std::string::npos, OT_EXIT_ERROR_ERRNO); + + folderPath = socketPath.substr(0, lastSlashIdx); + wd = inotify_add_watch(inotifyFd, folderPath.c_str(), IN_CREATE); + VerifyOrDie(wd != -1, OT_EXIT_ERROR_ERRNO); + + otLogInfoPlat("Waiting for socket file %s be created...", aPath); + + while (true) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(inotifyFd, &fds); + struct timeval timeout = {kMaxSelectTimeMs / MS_PER_S, + (kMaxSelectTimeMs % MS_PER_S) * MS_PER_S}; + + int rval = select(inotifyFd + 1, &fds, nullptr, nullptr, &timeout); + VerifyOrDie(rval >= 0, OT_EXIT_ERROR_ERRNO); + + if (rval == 0 && IsSocketFileExisted(aPath)) { + break; + } + + if (FD_ISSET(inotifyFd, &fds)) { + char buffer[sizeof(struct inotify_event)]; + ssize_t bytesRead = read(inotifyFd, buffer, sizeof(buffer)); + + VerifyOrDie(bytesRead >= 0, OT_EXIT_ERROR_ERRNO); + + struct inotify_event* event = reinterpret_cast(buffer); + if ((event->mask & IN_CREATE) && IsSocketFileExisted(aPath)) { + break; + } + } + } + + close(inotifyFd); + +exit: + otLogInfoPlat("Socket file: %s is created", aPath); + return; +} + +bool SocketInterface::IsSocketFileExisted(const char* aPath) { + struct stat st; + return stat(aPath, &st) == 0 && S_ISSOCK(st.st_mode); +} + } // namespace threadnetwork } // namespace hardware } // namespace android diff --git a/threadnetwork/aidl/default/socket_interface.hpp b/threadnetwork/aidl/default/socket_interface.hpp index 5c679cd899..23940f5fda 100644 --- a/threadnetwork/aidl/default/socket_interface.hpp +++ b/threadnetwork/aidl/default/socket_interface.hpp @@ -140,6 +140,30 @@ class SocketInterface : public ot::Spinel::SpinelInterface { */ void CloseFile(void); + /** + * Check if socket file is created. + * + * @param[in] aPath Socket file path name. + * + * @retval TRUE The required socket file is created. + * @retval FALSE The required socket file is not created. + * + */ + bool IsSocketFileExisted(const char* aPath); + + /** + * Wait until the socket file is created. + * + * @param[in] aPath Socket file path name. + * + */ + void WaitForSocketFileCreated(const char* aPath); + + enum { + kMaxSelectTimeMs = 2000, ///< Maximum wait time in Milliseconds for file + ///< descriptor to become available. + }; + ReceiveFrameCallback mReceiveFrameCallback; void* mReceiveFrameContext; RxFrameBuffer* mReceiveFrameBuffer;