[posix] make daemon as mainloop source (#6662)

This commit is contained in:
Yakun Xu
2021-05-25 22:06:03 -07:00
committed by GitHub
parent da906def50
commit 71e6543d9b
4 changed files with 144 additions and 104 deletions
+80 -65
View File
@@ -26,8 +26,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "openthread-posix-config.h"
#include "platform-posix.h"
#include "posix/platform/daemon.hpp"
#include <fcntl.h>
#include <signal.h>
@@ -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<size_t>(rval), MSG_NOSIGNAL);
rval = send(mSessionSocket, buf, static_cast<size_t>(rval), MSG_NOSIGNAL);
#else
rval = static_cast<int>(write(sSessionSocket, buf, static_cast<size_t>(rval)));
rval = static_cast<int>(write(mSessionSocket, buf, static_cast<size_t>(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<Daemon *>(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
+61
View File
@@ -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_
-30
View File
@@ -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
+3 -9
View File
@@ -47,6 +47,7 @@
#include <openthread/platform/radio.h>
#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