3 * Copyright (c) 2020 Project CHIP Authors
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file implements an object for a CHIP Echo unsolicitied
32 CHIP_ERROR EchoClient::Init(Messaging::ExchangeManager * exchangeMgr, SecureSessionHandle session)
34 // Error if already initialized.
35 if (mExchangeMgr != nullptr)
36 return CHIP_ERROR_INCORRECT_STATE;
38 mExchangeMgr = exchangeMgr;
39 mSecureSession = session;
40 OnEchoResponseReceived = nullptr;
41 mExchangeCtx = nullptr;
46 void EchoClient::Shutdown()
48 if (mExchangeCtx != nullptr)
50 mExchangeCtx->Abort();
51 mExchangeCtx = nullptr;
54 OnEchoResponseReceived = nullptr;
55 mExchangeMgr = nullptr;
58 CHIP_ERROR EchoClient::SendEchoRequest(System::PacketBufferHandle && payload, const Messaging::SendFlags & sendFlags)
60 CHIP_ERROR err = CHIP_NO_ERROR;
62 // Discard any existing exchange context. Effectively we can only have one Echo exchange with
63 // a single node at any one time.
64 if (mExchangeCtx != nullptr)
66 mExchangeCtx->Abort();
67 mExchangeCtx = nullptr;
70 // Create a new exchange context.
71 mExchangeCtx = mExchangeMgr->NewContext(mSecureSession, this);
72 if (mExchangeCtx == nullptr)
74 return CHIP_ERROR_NO_MEMORY;
77 // Send an Echo Request message. Discard the exchange context if the send fails.
78 err = mExchangeCtx->SendMessage(MsgType::EchoRequest, std::move(payload), sendFlags);
80 if (err != CHIP_NO_ERROR)
82 mExchangeCtx->Abort();
83 mExchangeCtx = nullptr;
89 void EchoClient::OnMessageReceived(Messaging::ExchangeContext * ec, const PacketHeader & packetHeader,
90 const PayloadHeader & payloadHeader, System::PacketBufferHandle payload)
92 // Assert that the exchange context matches the client's current context.
93 // This should never fail because even if SendEchoRequest is called
94 // back-to-back, the second call will call Close() on the first exchange,
95 // which clears the OnMessageReceived callback.
96 VerifyOrDie(ec == mExchangeCtx);
98 // Verify that the message is an Echo Response.
99 // If not, close the exchange and free the payload.
100 if (!payloadHeader.HasMessageType(MsgType::EchoResponse))
103 mExchangeCtx = nullptr;
107 // Remove the EC from the app state now. OnEchoResponseReceived can call
108 // SendEchoRequest and install a new one. We abort rather than close
109 // because we no longer care whether the echo request message has been
110 // acknowledged at the transport layer.
111 mExchangeCtx->Abort();
112 mExchangeCtx = nullptr;
114 // Call the registered OnEchoResponseReceived handler, if any.
115 if (OnEchoResponseReceived != nullptr)
117 OnEchoResponseReceived(ec, std::move(payload));
121 void EchoClient::OnResponseTimeout(Messaging::ExchangeContext * ec)
123 ChipLogProgress(Echo, "Time out! failed to receive echo response from Exchange: %p", ec);
127 } // namespace Protocols