mirror of
https://github.com/espressif/openthread.git
synced 2026-09-13 12:40:05 +00:00
[ot-ctl] fix reset in non-interactive mode (#5011)
* set close on exec * explicitly close socket on reset * enhance ot-ctl to exit on peer close * added test for the change
This commit is contained in:
+14
-14
@@ -89,25 +89,25 @@ check()
|
||||
sudo "$(pwd)/$(ls output/posix/*linux*/bin/ot-daemon)" "${options[@]}" -I "${VALID_NETIF_NAME}" "${CORE_PTY}" &
|
||||
sleep 1
|
||||
OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-ctl)"
|
||||
OT_CLI_ARG=
|
||||
sudo "${OT_CLI_CMD}" panid 0xface | grep 'Done' || die 'failed to set panid with ot-ctl'
|
||||
|
||||
# verify this reset and factoryreset end immediately
|
||||
sudo "${OT_CLI_CMD}" reset
|
||||
sudo "${OT_CLI_CMD}" factoryreset
|
||||
else
|
||||
OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli)"
|
||||
OT_CLI_ARG="${CORE_PTY}"
|
||||
fi
|
||||
OT_CLI="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli)"
|
||||
sudo "${OT_CLI}" -I "${VALID_NETIF_NAME}" -n "${CORE_PTY}"
|
||||
|
||||
sudo "${OT_CLI_CMD}" "${OT_CLI_ARG}" -I "${VALID_NETIF_NAME}" -n
|
||||
# Cover setting a too long(max is 15 characters) network interface name.
|
||||
# Expect exit code to be 2(OT_EXIT_INVALID_ARGUMENTS).
|
||||
readonly INVALID_NETIF_NAME="wan0123456789123"
|
||||
sudo "${OT_CLI}" -I "${INVALID_NETIF_NAME}" -n "${CORE_PTY}" || test $? = 2
|
||||
|
||||
# Cover setting a too long(max is 15 characters) network interface name.
|
||||
# Expect exit code to be 2(OT_EXIT_INVALID_ARGUMENTS).
|
||||
readonly INVALID_NETIF_NAME="wan0123456789123"
|
||||
sudo "${OT_CLI_CMD}" "${OT_CLI_ARG}" -I "${INVALID_NETIF_NAME}" -n || test $? = 2
|
||||
|
||||
if [[ ${DAEMON} == 1 ]]; then
|
||||
sudo "${OT_CLI_CMD}" "${OT_CLI_ARG}" panid 0xface | grep 'Done' || die 'failed to set panid with ot-ctl'
|
||||
OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli) ${CORE_PTY}"
|
||||
fi
|
||||
|
||||
sudo expect <<EOF | tee "${OT_OUTPUT}" &
|
||||
spawn ${OT_CLI_CMD} ${OT_CLI_ARG}
|
||||
spawn ${OT_CLI_CMD}
|
||||
send "panid 0xface\r\n"
|
||||
expect "Done"
|
||||
send "ifconfig up\r\n"
|
||||
@@ -160,7 +160,7 @@ EOF
|
||||
if [[ ${coap_response} == *${extaddr}* ]]; then
|
||||
echo 'Success'
|
||||
else
|
||||
die 'failed to get extended address'
|
||||
die 'Failed to get extended address'
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
+67
-68
@@ -76,74 +76,74 @@ static void InputCallback(char *aLine)
|
||||
}
|
||||
#endif // OPENTHREAD_USE_READLINE
|
||||
|
||||
static bool FindDone(int *aDoneState, char aNowCharacter)
|
||||
static bool FindDone(int &aDoneState, char aNowCharacter)
|
||||
{
|
||||
switch (aNowCharacter)
|
||||
{
|
||||
case 'D':
|
||||
*aDoneState = *aDoneState == 0 ? 1 : -1;
|
||||
aDoneState = aDoneState == 0 ? 1 : -1;
|
||||
break;
|
||||
case 'o':
|
||||
*aDoneState = *aDoneState == 1 ? 2 : -1;
|
||||
aDoneState = aDoneState == 1 ? 2 : -1;
|
||||
break;
|
||||
case 'n':
|
||||
*aDoneState = *aDoneState == 2 ? 3 : -1;
|
||||
aDoneState = aDoneState == 2 ? 3 : -1;
|
||||
break;
|
||||
case 'e':
|
||||
*aDoneState = *aDoneState == 3 ? 4 : -1;
|
||||
aDoneState = aDoneState == 3 ? 4 : -1;
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
if (*aDoneState == 4)
|
||||
if (aDoneState == 4)
|
||||
{
|
||||
*aDoneState = 5;
|
||||
aDoneState = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
*aDoneState = 0;
|
||||
aDoneState = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*aDoneState = -1;
|
||||
aDoneState = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return *aDoneState == 5;
|
||||
return aDoneState == 5;
|
||||
}
|
||||
|
||||
static bool FindError(int *aErrorState, char aNowCharacter)
|
||||
static bool FindError(int &aErrorState, char aNowCharacter)
|
||||
{
|
||||
switch (aNowCharacter)
|
||||
{
|
||||
case 'E':
|
||||
*aErrorState = *aErrorState == 0 ? 1 : -1;
|
||||
aErrorState = aErrorState == 0 ? 1 : -1;
|
||||
break;
|
||||
case 'r':
|
||||
if (*aErrorState == 1 || *aErrorState == 2 || *aErrorState == 4)
|
||||
if (aErrorState == 1 || aErrorState == 2 || aErrorState == 4)
|
||||
{
|
||||
(*aErrorState)++;
|
||||
(aErrorState)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*aErrorState = -1;
|
||||
aErrorState = -1;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
*aErrorState = *aErrorState == 3 ? 4 : -1;
|
||||
aErrorState = aErrorState == 3 ? 4 : -1;
|
||||
break;
|
||||
case ' ':
|
||||
*aErrorState = *aErrorState == 5 ? 6 : -1;
|
||||
aErrorState = aErrorState == 5 ? 6 : -1;
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
*aErrorState = 0;
|
||||
aErrorState = 0;
|
||||
break;
|
||||
default:
|
||||
*aErrorState = -1;
|
||||
aErrorState = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return *aErrorState == 6;
|
||||
return aErrorState == 6;
|
||||
}
|
||||
|
||||
static bool DoWrite(int aFile, const void *aBuffer, size_t aSize)
|
||||
@@ -168,43 +168,12 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void SendBlockingCommand(int aArgc, char *aArgv[])
|
||||
{
|
||||
char buffer[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
|
||||
int doneState = 0;
|
||||
int errorState = 0;
|
||||
|
||||
for (int i = 0; i < aArgc; i++)
|
||||
{
|
||||
VerifyOrExit(DoWrite(sSessionFd, aArgv[i], strlen(aArgv[i])), OT_NOOP);
|
||||
VerifyOrExit(DoWrite(sSessionFd, " ", 1), OT_NOOP);
|
||||
}
|
||||
VerifyOrExit(DoWrite(sSessionFd, "\n", 1), OT_NOOP);
|
||||
|
||||
while (true)
|
||||
{
|
||||
ssize_t rval = read(sSessionFd, buffer, sizeof(buffer));
|
||||
|
||||
VerifyOrExit(rval >= 0, OT_NOOP);
|
||||
VerifyOrExit(DoWrite(STDOUT_FILENO, buffer, static_cast<size_t>(rval)), OT_NOOP);
|
||||
for (ssize_t i = 0; i < rval; i++)
|
||||
{
|
||||
if (FindDone(&doneState, buffer[i]) || FindError(&errorState, buffer[i]))
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(argc);
|
||||
OT_UNUSED_VARIABLE(argv);
|
||||
|
||||
int ret;
|
||||
int ret;
|
||||
bool isInteractive = true;
|
||||
int doneState = 0;
|
||||
int errorState = 0;
|
||||
|
||||
sSessionFd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
VerifyOrExit(sSessionFd != -1, perror("socket"); ret = OT_EXIT_FAILURE);
|
||||
@@ -216,40 +185,56 @@ int main(int argc, char *argv[])
|
||||
sockname.sun_family = AF_UNIX;
|
||||
strncpy(sockname.sun_path, OPENTHREAD_POSIX_DAEMON_SOCKET_NAME, sizeof(sockname.sun_path) - 1);
|
||||
|
||||
ret = connect(sSessionFd, (const struct sockaddr *)&sockname, sizeof(struct sockaddr_un));
|
||||
ret = connect(sSessionFd, reinterpret_cast<const struct sockaddr *>(&sockname), sizeof(struct sockaddr_un));
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf(stderr, "OpenThread daemon is not running.\n");
|
||||
ExitNow(ret = OT_EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
VerifyOrExit(DoWrite(sSessionFd, argv[i], strlen(argv[i])), ret = OT_EXIT_FAILURE);
|
||||
VerifyOrExit(DoWrite(sSessionFd, " ", 1), ret = OT_EXIT_FAILURE);
|
||||
}
|
||||
VerifyOrExit(DoWrite(sSessionFd, "\n", 1), ret = OT_EXIT_FAILURE);
|
||||
|
||||
isInteractive = false;
|
||||
}
|
||||
#if OPENTHREAD_USE_READLINE
|
||||
else
|
||||
{
|
||||
rl_instream = stdin;
|
||||
rl_outstream = stdout;
|
||||
rl_inhibit_completion = true;
|
||||
rl_callback_handler_install("> ", InputCallback);
|
||||
rl_already_prompted = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
SendBlockingCommand(argc - 1, &argv[1]);
|
||||
ExitNow(ret = 0);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
fd_set readFdSet;
|
||||
char buffer[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
|
||||
int maxFd = sSessionFd > STDIN_FILENO ? sSessionFd : STDIN_FILENO;
|
||||
int maxFd = sSessionFd;
|
||||
|
||||
FD_ZERO(&readFdSet);
|
||||
|
||||
FD_SET(STDIN_FILENO, &readFdSet);
|
||||
FD_SET(sSessionFd, &readFdSet);
|
||||
|
||||
if (isInteractive)
|
||||
{
|
||||
FD_SET(STDIN_FILENO, &readFdSet);
|
||||
if (STDIN_FILENO > maxFd)
|
||||
{
|
||||
maxFd = STDIN_FILENO;
|
||||
}
|
||||
}
|
||||
|
||||
ret = select(maxFd + 1, &readFdSet, NULL, NULL, NULL);
|
||||
|
||||
VerifyOrExit(ret != -1, perror("select"); ret = OT_EXIT_FAILURE);
|
||||
@@ -259,7 +244,7 @@ int main(int argc, char *argv[])
|
||||
ExitNow(ret = OT_EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (FD_ISSET(STDIN_FILENO, &readFdSet))
|
||||
if (isInteractive && FD_ISSET(STDIN_FILENO, &readFdSet))
|
||||
{
|
||||
#if OPENTHREAD_USE_READLINE
|
||||
rl_callback_read_char();
|
||||
@@ -278,12 +263,23 @@ int main(int argc, char *argv[])
|
||||
if (rval == 0)
|
||||
{
|
||||
// daemon closed sSessionFd
|
||||
ExitNow(ret = OT_EXIT_FAILURE);
|
||||
ExitNow(ret = isInteractive ? OT_EXIT_FAILURE : OT_EXIT_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(DoWrite(STDOUT_FILENO, buffer, static_cast<size_t>(rval)), ret = OT_EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!isInteractive)
|
||||
{
|
||||
for (ssize_t i = 0; i < rval; i++)
|
||||
{
|
||||
if (FindDone(doneState, buffer[i]) || FindError(errorState, buffer[i]))
|
||||
{
|
||||
ExitNow(ret = OT_EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +287,10 @@ exit:
|
||||
if (sSessionFd != -1)
|
||||
{
|
||||
#if OPENTHREAD_USE_READLINE
|
||||
rl_callback_handler_remove();
|
||||
if (isInteractive)
|
||||
{
|
||||
rl_callback_handler_remove();
|
||||
}
|
||||
#endif
|
||||
close(sSessionFd);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
#include <openthread/tasklet.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
#include <openthread/platform/uart.h>
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
|
||||
uint64_t gNodeId = 0;
|
||||
|
||||
@@ -76,6 +79,7 @@ void otSysDeinit(void)
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
|
||||
platformNetifDeinit();
|
||||
#endif
|
||||
IgnoreError(otPlatUartDisable());
|
||||
}
|
||||
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
|
||||
@@ -216,6 +216,39 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
|
||||
static void InitializeSessionSocket(void)
|
||||
{
|
||||
int rval;
|
||||
|
||||
VerifyOrExit((rval = accept(sUartSocket, NULL, NULL)) != -1, OT_NOOP);
|
||||
|
||||
if (sSessionSocket != -1)
|
||||
{
|
||||
close(sSessionSocket);
|
||||
}
|
||||
|
||||
sSessionSocket = rval;
|
||||
|
||||
VerifyOrExit((rval = fcntl(sSessionSocket, F_GETFD, 0)) != -1, OT_NOOP);
|
||||
|
||||
rval |= FD_CLOEXEC;
|
||||
|
||||
VerifyOrExit((rval = fcntl(sSessionSocket, F_SETFD, rval)) != -1, OT_NOOP);
|
||||
|
||||
exit:
|
||||
if (rval == -1)
|
||||
{
|
||||
otLogWarnPlat("Failed to initialize session socket: %s", strerror(errno));
|
||||
sSessionSocket = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
otLogInfoPlat("Session socket is ready", strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, const fd_set *aErrorFdSet)
|
||||
{
|
||||
ssize_t rval;
|
||||
@@ -229,7 +262,7 @@ void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, co
|
||||
}
|
||||
else if (FD_ISSET(sUartSocket, aReadFdSet))
|
||||
{
|
||||
sSessionSocket = accept(sUartSocket, NULL, NULL);
|
||||
InitializeSessionSocket();
|
||||
}
|
||||
|
||||
if (sSessionSocket == -1 && sWriteBuffer != NULL)
|
||||
|
||||
Reference in New Issue
Block a user