diff --git a/src/posix/platform/daemon.cpp b/src/posix/platform/daemon.cpp index e64efd370..0e554b8ed 100644 --- a/src/posix/platform/daemon.cpp +++ b/src/posix/platform/daemon.cpp @@ -26,8 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "openthread-posix-config.h" -#include "platform-posix.h" +#include "posix/platform/daemon.hpp" #include #include @@ -42,6 +41,7 @@ #include "cli/cli_config.h" #include "common/code_utils.hpp" +#include "posix/platform/platform-posix.h" #if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE @@ -49,11 +49,10 @@ static_assert(sizeof(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME) < sizeof(sockaddr_un::sun_path), "OpenThread daemon socket name too long!"); -namespace { +namespace ot { +namespace Posix { -int sListenSocket = -1; -int sDaemonLock = -1; -int sSessionSocket = -1; +namespace { typedef char(Filename)[sizeof(sockaddr_un::sun_path)]; @@ -68,10 +67,10 @@ void GetFilename(Filename &aFilename, const char *aPattern) } } -int OutputFormatV(void *aContext, const char *aFormat, va_list aArguments) -{ - OT_UNUSED_VARIABLE(aContext); +} // namespace +int Daemon::OutputFormatV(const char *aFormat, va_list aArguments) +{ char buf[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH + 1]; int rval; @@ -82,32 +81,32 @@ int OutputFormatV(void *aContext, const char *aFormat, va_list aArguments) VerifyOrExit(rval >= 0, otLogWarnPlat("Failed to format CLI output: %s", strerror(errno))); otLogInfoPlat("%s", buf); - VerifyOrExit(sSessionSocket != -1); + VerifyOrExit(mSessionSocket != -1); #if defined(__linux__) // Don't die on SIGPIPE - rval = send(sSessionSocket, buf, static_cast(rval), MSG_NOSIGNAL); + rval = send(mSessionSocket, buf, static_cast(rval), MSG_NOSIGNAL); #else - rval = static_cast(write(sSessionSocket, buf, static_cast(rval))); + rval = static_cast(write(mSessionSocket, buf, static_cast(rval))); #endif if (rval < 0) { otLogWarnPlat("Failed to write CLI output: %s", strerror(errno)); - close(sSessionSocket); - sSessionSocket = -1; + close(mSessionSocket); + mSessionSocket = -1; } exit: return rval; } -void InitializeSessionSocket(void) +void Daemon::InitializeSessionSocket(void) { int newSessionSocket; int rval; - VerifyOrExit((newSessionSocket = accept(sListenSocket, nullptr, nullptr)) != -1, rval = -1); + VerifyOrExit((newSessionSocket = accept(mListenSocket, nullptr, nullptr)) != -1, rval = -1); VerifyOrExit((rval = fcntl(newSessionSocket, F_GETFD, 0)) != -1); @@ -128,11 +127,11 @@ void InitializeSessionSocket(void) #endif #endif // __linux__ - if (sSessionSocket != -1) + if (mSessionSocket != -1) { - close(sSessionSocket); + close(mSessionSocket); } - sSessionSocket = newSessionSocket; + mSessionSocket = newSessionSocket; exit: if (rval == -1) @@ -149,19 +148,17 @@ exit: } } -} // namespace - -void platformDaemonEnable(otInstance *aInstance) +void Daemon::Enable(otInstance *aInstance) { struct sockaddr_un sockname; int ret; // This allows implementing pseudo reset. - VerifyOrExit(sListenSocket == -1); + VerifyOrExit(mListenSocket == -1); - sListenSocket = SocketWithCloseExec(AF_UNIX, SOCK_STREAM, 0, kSocketNonBlock); + mListenSocket = SocketWithCloseExec(AF_UNIX, SOCK_STREAM, 0, kSocketNonBlock); - if (sListenSocket == -1) + if (mListenSocket == -1) { DieNow(OT_EXIT_FAILURE); } @@ -173,15 +170,15 @@ void platformDaemonEnable(otInstance *aInstance) GetFilename(lockfile, OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK); - sDaemonLock = open(lockfile, O_CREAT | O_RDONLY | O_CLOEXEC, 0600); + mDaemonLock = open(lockfile, O_CREAT | O_RDONLY | O_CLOEXEC, 0600); } - if (sDaemonLock == -1) + if (mDaemonLock == -1) { DieNowWithMessage("open", OT_EXIT_ERROR_ERRNO); } - if (flock(sDaemonLock, LOCK_EX | LOCK_NB) == -1) + if (flock(mDaemonLock, LOCK_EX | LOCK_NB) == -1) { DieNowWithMessage("flock", OT_EXIT_ERROR_ERRNO); } @@ -192,7 +189,7 @@ void platformDaemonEnable(otInstance *aInstance) GetFilename(sockname.sun_path, OPENTHREAD_POSIX_DAEMON_SOCKET_NAME); (void)unlink(sockname.sun_path); - ret = bind(sListenSocket, (const struct sockaddr *)&sockname, sizeof(struct sockaddr_un)); + ret = bind(mListenSocket, (const struct sockaddr *)&sockname, sizeof(struct sockaddr_un)); if (ret == -1) { @@ -202,30 +199,39 @@ void platformDaemonEnable(otInstance *aInstance) // // only accept 1 connection. // - ret = listen(sListenSocket, 1); + ret = listen(mListenSocket, 1); if (ret == -1) { DieNowWithMessage("listen", OT_EXIT_ERROR_ERRNO); } - otCliInit(aInstance, OutputFormatV, aInstance); + otCliInit( + aInstance, + [](void *aContext, const char *aFormat, va_list aArguments) -> int { + return static_cast(aContext)->OutputFormatV(aFormat, aArguments); + }, + this); + + Mainloop::Manager::Get().Add(*this); exit: return; } -void platformDaemonDisable(void) +void Daemon::Disable(void) { - if (sSessionSocket != -1) + Mainloop::Manager::Get().Remove(*this); + + if (mSessionSocket != -1) { - close(sSessionSocket); - sSessionSocket = -1; + close(mSessionSocket); + mSessionSocket = -1; } - if (sListenSocket != -1) + if (mListenSocket != -1) { - close(sListenSocket); - sListenSocket = -1; + close(mListenSocket); + mListenSocket = -1; } if (gPlatResetReason != OT_PLAT_RESET_REASON_SOFTWARE) @@ -237,69 +243,69 @@ void platformDaemonDisable(void) (void)unlink(sockfile); } - if (sDaemonLock != -1) + if (mDaemonLock != -1) { - (void)flock(sDaemonLock, LOCK_UN); - close(sDaemonLock); - sDaemonLock = -1; + (void)flock(mDaemonLock, LOCK_UN); + close(mDaemonLock); + mDaemonLock = -1; } } -void platformDaemonUpdate(otSysMainloopContext *aContext) +void Daemon::Update(otSysMainloopContext &aContext) { - if (sListenSocket != -1) + if (mListenSocket != -1) { - FD_SET(sListenSocket, &aContext->mReadFdSet); - FD_SET(sListenSocket, &aContext->mErrorFdSet); + FD_SET(mListenSocket, &aContext.mReadFdSet); + FD_SET(mListenSocket, &aContext.mErrorFdSet); - if (aContext->mMaxFd < sListenSocket) + if (aContext.mMaxFd < mListenSocket) { - aContext->mMaxFd = sListenSocket; + aContext.mMaxFd = mListenSocket; } } - if (sSessionSocket != -1) + if (mSessionSocket != -1) { - FD_SET(sSessionSocket, &aContext->mReadFdSet); - FD_SET(sSessionSocket, &aContext->mErrorFdSet); + FD_SET(mSessionSocket, &aContext.mReadFdSet); + FD_SET(mSessionSocket, &aContext.mErrorFdSet); - if (aContext->mMaxFd < sSessionSocket) + if (aContext.mMaxFd < mSessionSocket) { - aContext->mMaxFd = sSessionSocket; + aContext.mMaxFd = mSessionSocket; } } return; } -void platformDaemonProcess(const otSysMainloopContext *aContext) +void Daemon::Process(const otSysMainloopContext &aContext) { ssize_t rval; - VerifyOrExit(sListenSocket != -1); + VerifyOrExit(mListenSocket != -1); - if (FD_ISSET(sListenSocket, &aContext->mErrorFdSet)) + if (FD_ISSET(mListenSocket, &aContext.mErrorFdSet)) { DieNowWithMessage("daemon socket error", OT_EXIT_FAILURE); } - else if (FD_ISSET(sListenSocket, &aContext->mReadFdSet)) + else if (FD_ISSET(mListenSocket, &aContext.mReadFdSet)) { InitializeSessionSocket(); } - VerifyOrExit(sSessionSocket != -1); + VerifyOrExit(mSessionSocket != -1); - if (FD_ISSET(sSessionSocket, &aContext->mErrorFdSet)) + if (FD_ISSET(mSessionSocket, &aContext.mErrorFdSet)) { - close(sSessionSocket); - sSessionSocket = -1; + close(mSessionSocket); + mSessionSocket = -1; } - else if (FD_ISSET(sSessionSocket, &aContext->mReadFdSet)) + else if (FD_ISSET(mSessionSocket, &aContext.mReadFdSet)) { uint8_t buffer[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH]; // leave 1 byte for the null terminator - rval = read(sSessionSocket, buffer, sizeof(buffer) - 1); + rval = read(mSessionSocket, buffer, sizeof(buffer) - 1); if (rval > 0) { @@ -314,8 +320,8 @@ void platformDaemonProcess(const otSysMainloopContext *aContext) { otLogWarnPlat("Daemon read: %s", strerror(errno)); } - close(sSessionSocket); - sSessionSocket = -1; + close(mSessionSocket); + mSessionSocket = -1; } } @@ -323,4 +329,13 @@ exit: return; } +Daemon &Daemon::Get(void) +{ + static Daemon sInstance; + + return sInstance; +} + +} // namespace Posix +} // namespace ot #endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE diff --git a/src/posix/platform/daemon.hpp b/src/posix/platform/daemon.hpp new file mode 100644 index 000000000..3b1a372b1 --- /dev/null +++ b/src/posix/platform/daemon.hpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef OT_POSIX_PLATFORM_DAEMON_HPP_ +#define OT_POSIX_PLATFORM_DAEMON_HPP_ + +#include "openthread-posix-config.h" + +#include "core/common/non_copyable.hpp" +#include "posix/platform/mainloop.hpp" + +namespace ot { +namespace Posix { + +class Daemon : public Mainloop::Source, private NonCopyable +{ +public: + static Daemon &Get(void); + + void Enable(otInstance *aInstance); + void Disable(void); + void Update(otSysMainloopContext &aContext) override; + void Process(const otSysMainloopContext &aContext) override; + +private: + int OutputFormatV(const char *aFormat, va_list aArguments); + void InitializeSessionSocket(void); + + int mListenSocket = -1; + int mDaemonLock = -1; + int mSessionSocket = -1; +}; + +} // namespace Posix +} // namespace ot + +#endif // OT_POSIX_PLATFORM_DAEMON_HPP_ diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h index 69b944ebb..236f15648 100644 --- a/src/posix/platform/platform-posix.h +++ b/src/posix/platform/platform-posix.h @@ -491,36 +491,6 @@ extern unsigned int gBackboneNetifIndex; */ bool platformInfraIfIsRunning(void); -/** - * This function enables daemon. - * - * @param[in] aInstance The OpenThread instance structure. - * - */ -void platformDaemonEnable(otInstance *aInstance); - -/** - * This function disables daemon. - * - */ -void platformDaemonDisable(void); - -/** - * This function updates the file descriptor sets with file descriptors used by daemon. - * - * @param[inout] aMainloop A pointer to the mainloop context. - * - */ -void platformDaemonUpdate(otSysMainloopContext *aContext); - -/** - * This function performs daemon processing. - * - * @param[in] aMainloop A pointer to the mainloop context. - * - */ -void platformDaemonProcess(const otSysMainloopContext *aContext); - #ifdef __cplusplus } #endif diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp index 58f34b6a4..eb65347fb 100644 --- a/src/posix/platform/system.cpp +++ b/src/posix/platform/system.cpp @@ -47,6 +47,7 @@ #include #include "common/code_utils.hpp" +#include "posix/platform/daemon.hpp" #include "posix/platform/infra_if.hpp" #include "posix/platform/mainloop.hpp" #include "posix/platform/radio_url.hpp" @@ -148,7 +149,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig) #endif #if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE - platformDaemonEnable(instance); + ot::Posix::Daemon::Get().Enable(instance); #endif return instance; } @@ -156,7 +157,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig) void otSysDeinit(void) { #if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE - platformDaemonDisable(); + ot::Posix::Daemon::Get().Disable(); #endif #if OPENTHREAD_POSIX_VIRTUAL_TIME virtualTimeDeinit(); @@ -229,10 +230,6 @@ void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop) platformTrelUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mMaxFd, &aMainloop->mTimeout); #endif -#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE - platformDaemonUpdate(aMainloop); -#endif - if (otTaskletsArePending(aInstance)) { aMainloop->mTimeout.tv_sec = 0; @@ -302,9 +299,6 @@ void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMa #if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE platformUdpProcess(aInstance, &aMainloop->mReadFdSet); #endif -#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE - platformDaemonProcess(aMainloop); -#endif } #if OPENTHREAD_CONFIG_OTNS_ENABLE