mirror of
https://github.com/espressif/openthread.git
synced 2026-07-30 07:37:46 +00:00
[posix] make daemon as mainloop source (#6662)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user