[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:
Yakun Xu
2020-05-28 10:31:16 -07:00
committed by GitHub
parent 204308f4a7
commit 5e65833d72
4 changed files with 119 additions and 83 deletions
+14 -14
View File
@@ -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
View File
@@ -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);
}
+4
View File
@@ -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
+34 -1
View File
@@ -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)