From ba84e8a0d583671cd05937925fecce9bcaf7089c Mon Sep 17 00:00:00 2001 From: Jiacheng Guo Date: Fri, 11 Jun 2021 14:59:39 +0800 Subject: [PATCH] [shell] make shell ping command asynchronous --- examples/shell/shell_common/cmd_ping.cpp | 114 ++++++++++++----------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/examples/shell/shell_common/cmd_ping.cpp b/examples/shell/shell_common/cmd_ping.cpp index 1979b846693319..ba5c749b5028d5 100644 --- a/examples/shell/shell_common/cmd_ping.cpp +++ b/examples/shell/shell_common/cmd_ping.cpp @@ -129,12 +129,60 @@ class PingArguments } gPingArguments; Protocols::Echo::EchoClient gEchoClient; +Transport::AdminPairingTable gAdmins; -bool EchoIntervalExpired(void) +CHIP_ERROR SendEchoRequest(streamer_t * stream); + +Transport::PeerAddress GetEchoPeerAddress() { - uint64_t now = System::Timer::GetCurrentEpoch(); +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + if (gPingArguments.IsUsingTCP()) + { + return Transport::PeerAddress::TCP(gDestAddr, gPingArguments.GetEchoPort()); + } + else +#endif + { - return (now >= gPingArguments.GetLastEchoTime() + gPingArguments.GetEchoInterval()); + return Transport::PeerAddress::UDP(gDestAddr, gPingArguments.GetEchoPort(), INET_NULL_INTERFACEID); + } +} + +void Shutdown() +{ +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + if (gPingArguments.IsUsingTCP()) + { + gTCPManager.Disconnect(GetEchoPeerAddress()); + } + gTCPManager.Close(); +#endif + gUDPManager.Close(); + + gEchoClient.Shutdown(); + gExchangeManager.Shutdown(); + gSessionManager.Shutdown(); +} + +void EchoTimerHandler(chip::System::Layer * systemLayer, void * appState, chip::System::Error error) +{ + if (gPingArguments.GetEchoRespCount() != gPingArguments.GetEchoCount()) + { + streamer_printf(streamer_get(), "No response received\n"); + gPingArguments.SetEchoRespCount(gPingArguments.GetEchoCount()); + } + if (gPingArguments.GetEchoCount() < gPingArguments.GetMaxEchoCount()) + { + CHIP_ERROR err = SendEchoRequest(streamer_get()); + if (err != CHIP_NO_ERROR) + { + streamer_printf(streamer_get(), "Send request failed: %s\n", ErrorStr(err)); + } + } + else + { + Shutdown(); + } } CHIP_ERROR SendEchoRequest(streamer_t * stream) @@ -166,6 +214,7 @@ CHIP_ERROR SendEchoRequest(streamer_t * stream) } gPingArguments.SetLastEchoTime(System::Timer::GetCurrentEpoch()); + chip::DeviceLayer::SystemLayer.StartTimer(gPingArguments.GetEchoInterval(), EchoTimerHandler, NULL); streamer_printf(stream, "\nSend echo request message with payload size: %d bytes to Node: %" PRIu64 "\n", size, kTestDeviceNodeId); @@ -192,7 +241,7 @@ CHIP_ERROR SendEchoRequest(streamer_t * stream) return err; } -CHIP_ERROR EstablishSecureSession(streamer_t * stream, Transport::PeerAddress & peerAddress) +CHIP_ERROR EstablishSecureSession(streamer_t * stream, const Transport::PeerAddress & peerAddress) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -239,10 +288,7 @@ void StartPinging(streamer_t * stream, char * destination) { CHIP_ERROR err = CHIP_NO_ERROR; - Transport::AdminPairingTable admins; - Transport::PeerAddress peerAddress; Transport::AdminPairingInfo * adminInfo = nullptr; - uint32_t maxEchoCount = 0; if (!IPAddress::FromString(destination, gDestAddr)) { @@ -250,7 +296,7 @@ void StartPinging(streamer_t * stream, char * destination) ExitNow(err = CHIP_ERROR_INVALID_ARGUMENT); } - adminInfo = admins.AssignAdminId(gAdminId, kTestControllerNodeId); + adminInfo = gAdmins.AssignAdminId(gAdminId, kTestControllerNodeId); VerifyOrExit(adminInfo != nullptr, err = CHIP_ERROR_NO_MEMORY); #if INET_CONFIG_ENABLE_TCP_ENDPOINT @@ -268,10 +314,8 @@ void StartPinging(streamer_t * stream, char * destination) #if INET_CONFIG_ENABLE_TCP_ENDPOINT if (gPingArguments.IsUsingTCP()) { - peerAddress = Transport::PeerAddress::TCP(gDestAddr, gPingArguments.GetEchoPort()); - err = - gSessionManager.Init(kTestControllerNodeId, &DeviceLayer::SystemLayer, &gTCPManager, &admins, &gMessageCounterManager); + gSessionManager.Init(kTestControllerNodeId, &DeviceLayer::SystemLayer, &gTCPManager, &gAdmins, &gMessageCounterManager); SuccessOrExit(err); err = gExchangeManager.Init(&gSessionManager); @@ -280,10 +324,8 @@ void StartPinging(streamer_t * stream, char * destination) else #endif { - peerAddress = Transport::PeerAddress::UDP(gDestAddr, gPingArguments.GetEchoPort(), INET_NULL_INTERFACEID); - err = - gSessionManager.Init(kTestControllerNodeId, &DeviceLayer::SystemLayer, &gUDPManager, &admins, &gMessageCounterManager); + gSessionManager.Init(kTestControllerNodeId, &DeviceLayer::SystemLayer, &gUDPManager, &gAdmins, &gMessageCounterManager); SuccessOrExit(err); err = gExchangeManager.Init(&gSessionManager); @@ -294,7 +336,7 @@ void StartPinging(streamer_t * stream, char * destination) SuccessOrExit(err); // Start the CHIP connection to the CHIP echo responder. - err = EstablishSecureSession(stream, peerAddress); + err = EstablishSecureSession(stream, GetEchoPeerAddress()); SuccessOrExit(err); // TODO: temprary create a SecureSessionHandle from node id to unblock end-to-end test. Complete solution is tracked in PR:4451 @@ -304,48 +346,16 @@ void StartPinging(streamer_t * stream, char * destination) // Arrange to get a callback whenever an Echo Response is received. gEchoClient.SetEchoResponseReceived(HandleEchoResponseReceived); - maxEchoCount = gPingArguments.GetMaxEchoCount(); - - // Connection has been established. Now send the EchoRequests. - for (unsigned int i = 0; i < maxEchoCount; i++) + err = SendEchoRequest(stream); + if (err != CHIP_NO_ERROR) { - err = SendEchoRequest(stream); - - if (err != CHIP_NO_ERROR) - { - streamer_printf(stream, "Send request failed: %s\n", ErrorStr(err)); - break; - } - - // Wait for response until the Echo interval. - while (!EchoIntervalExpired()) - { - // TODO:#5496: Use condition_varible to suspend the current thread and wake it up when response arrive. - sleep(1); - } - - // Check if expected response was received. - if (gPingArguments.IsWaitingForEchoResp()) - { - streamer_printf(stream, "No response received\n"); - gPingArguments.SetWaitingForEchoResp(false); - } + streamer_printf(stream, "Send request failed: %s\n", ErrorStr(err)); } - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - gTCPManager.Disconnect(peerAddress); - gTCPManager.Close(); -#endif - gUDPManager.Close(); - - gEchoClient.Shutdown(); - gExchangeManager.Shutdown(); - gSessionManager.Shutdown(); - exit: - if ((err != CHIP_NO_ERROR)) + if (err != CHIP_NO_ERROR) { streamer_printf(stream, "Ping failed with error: %s\n", ErrorStr(err)); + Shutdown(); } }