xref: /aosp_15_r20/external/openthread/src/cli/cli_coap.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2017, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker /**
30*cfb92d14SAndroid Build Coastguard Worker  * @file
31*cfb92d14SAndroid Build Coastguard Worker  *   This file implements a simple CLI for the CoAP service.
32*cfb92d14SAndroid Build Coastguard Worker  */
33*cfb92d14SAndroid Build Coastguard Worker 
34*cfb92d14SAndroid Build Coastguard Worker #include "cli_coap.hpp"
35*cfb92d14SAndroid Build Coastguard Worker 
36*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_API_ENABLE
37*cfb92d14SAndroid Build Coastguard Worker 
38*cfb92d14SAndroid Build Coastguard Worker #include <openthread/random_noncrypto.h>
39*cfb92d14SAndroid Build Coastguard Worker 
40*cfb92d14SAndroid Build Coastguard Worker #include <ctype.h>
41*cfb92d14SAndroid Build Coastguard Worker 
42*cfb92d14SAndroid Build Coastguard Worker #include "cli/cli.hpp"
43*cfb92d14SAndroid Build Coastguard Worker 
44*cfb92d14SAndroid Build Coastguard Worker namespace ot {
45*cfb92d14SAndroid Build Coastguard Worker namespace Cli {
46*cfb92d14SAndroid Build Coastguard Worker 
Coap(otInstance * aInstance,OutputImplementer & aOutputImplementer)47*cfb92d14SAndroid Build Coastguard Worker Coap::Coap(otInstance *aInstance, OutputImplementer &aOutputImplementer)
48*cfb92d14SAndroid Build Coastguard Worker     : Utils(aInstance, aOutputImplementer)
49*cfb92d14SAndroid Build Coastguard Worker     , mUseDefaultRequestTxParameters(true)
50*cfb92d14SAndroid Build Coastguard Worker     , mUseDefaultResponseTxParameters(true)
51*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
52*cfb92d14SAndroid Build Coastguard Worker     , mObserveSerial(0)
53*cfb92d14SAndroid Build Coastguard Worker     , mRequestTokenLength(0)
54*cfb92d14SAndroid Build Coastguard Worker     , mSubscriberTokenLength(0)
55*cfb92d14SAndroid Build Coastguard Worker     , mSubscriberConfirmableNotifications(false)
56*cfb92d14SAndroid Build Coastguard Worker #endif
57*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
58*cfb92d14SAndroid Build Coastguard Worker     , mBlockCount(1)
59*cfb92d14SAndroid Build Coastguard Worker #endif
60*cfb92d14SAndroid Build Coastguard Worker {
61*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mResource);
62*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
63*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mRequestAddr);
64*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mSubscriberSock);
65*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mRequestToken);
66*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mSubscriberToken);
67*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mRequestUri);
68*cfb92d14SAndroid Build Coastguard Worker #endif
69*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mUriPath);
70*cfb92d14SAndroid Build Coastguard Worker     strncpy(mResourceContent, "0", sizeof(mResourceContent));
71*cfb92d14SAndroid Build Coastguard Worker     mResourceContent[sizeof(mResourceContent) - 1] = '\0';
72*cfb92d14SAndroid Build Coastguard Worker }
73*cfb92d14SAndroid Build Coastguard Worker 
74*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
CancelResourceSubscription(void)75*cfb92d14SAndroid Build Coastguard Worker otError Coap::CancelResourceSubscription(void)
76*cfb92d14SAndroid Build Coastguard Worker {
77*cfb92d14SAndroid Build Coastguard Worker     otError       error   = OT_ERROR_NONE;
78*cfb92d14SAndroid Build Coastguard Worker     otMessage    *message = nullptr;
79*cfb92d14SAndroid Build Coastguard Worker     otMessageInfo messageInfo;
80*cfb92d14SAndroid Build Coastguard Worker 
81*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(messageInfo);
82*cfb92d14SAndroid Build Coastguard Worker     messageInfo.mPeerAddr = mRequestAddr;
83*cfb92d14SAndroid Build Coastguard Worker     messageInfo.mPeerPort = OT_DEFAULT_COAP_PORT;
84*cfb92d14SAndroid Build Coastguard Worker 
85*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(mRequestTokenLength != 0, error = OT_ERROR_INVALID_STATE);
86*cfb92d14SAndroid Build Coastguard Worker 
87*cfb92d14SAndroid Build Coastguard Worker     message = otCoapNewMessage(GetInstancePtr(), nullptr);
88*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
89*cfb92d14SAndroid Build Coastguard Worker 
90*cfb92d14SAndroid Build Coastguard Worker     otCoapMessageInit(message, OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_GET);
91*cfb92d14SAndroid Build Coastguard Worker 
92*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otCoapMessageSetToken(message, mRequestToken, mRequestTokenLength));
93*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otCoapMessageAppendObserveOption(message, 1));
94*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, mRequestUri));
95*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = otCoapSendRequest(GetInstancePtr(), message, &messageInfo, &Coap::HandleResponse, this));
96*cfb92d14SAndroid Build Coastguard Worker 
97*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mRequestAddr);
98*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mRequestUri);
99*cfb92d14SAndroid Build Coastguard Worker     mRequestTokenLength = 0;
100*cfb92d14SAndroid Build Coastguard Worker 
101*cfb92d14SAndroid Build Coastguard Worker exit:
102*cfb92d14SAndroid Build Coastguard Worker 
103*cfb92d14SAndroid Build Coastguard Worker     if ((error != OT_ERROR_NONE) && (message != nullptr))
104*cfb92d14SAndroid Build Coastguard Worker     {
105*cfb92d14SAndroid Build Coastguard Worker         otMessageFree(message);
106*cfb92d14SAndroid Build Coastguard Worker     }
107*cfb92d14SAndroid Build Coastguard Worker 
108*cfb92d14SAndroid Build Coastguard Worker     return error;
109*cfb92d14SAndroid Build Coastguard Worker }
110*cfb92d14SAndroid Build Coastguard Worker 
CancelSubscriber(void)111*cfb92d14SAndroid Build Coastguard Worker void Coap::CancelSubscriber(void)
112*cfb92d14SAndroid Build Coastguard Worker {
113*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(mSubscriberSock);
114*cfb92d14SAndroid Build Coastguard Worker     mSubscriberTokenLength = 0;
115*cfb92d14SAndroid Build Coastguard Worker }
116*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
117*cfb92d14SAndroid Build Coastguard Worker 
PrintPayload(otMessage * aMessage)118*cfb92d14SAndroid Build Coastguard Worker void Coap::PrintPayload(otMessage *aMessage)
119*cfb92d14SAndroid Build Coastguard Worker {
120*cfb92d14SAndroid Build Coastguard Worker     uint8_t  buf[kMaxBufferSize];
121*cfb92d14SAndroid Build Coastguard Worker     uint16_t bytesToPrint;
122*cfb92d14SAndroid Build Coastguard Worker     uint16_t bytesPrinted = 0;
123*cfb92d14SAndroid Build Coastguard Worker     uint16_t length       = otMessageGetLength(aMessage) - otMessageGetOffset(aMessage);
124*cfb92d14SAndroid Build Coastguard Worker 
125*cfb92d14SAndroid Build Coastguard Worker     if (length > 0)
126*cfb92d14SAndroid Build Coastguard Worker     {
127*cfb92d14SAndroid Build Coastguard Worker         OutputFormat(" with payload: ");
128*cfb92d14SAndroid Build Coastguard Worker 
129*cfb92d14SAndroid Build Coastguard Worker         while (length > 0)
130*cfb92d14SAndroid Build Coastguard Worker         {
131*cfb92d14SAndroid Build Coastguard Worker             bytesToPrint = Min(length, static_cast<uint16_t>(sizeof(buf)));
132*cfb92d14SAndroid Build Coastguard Worker             otMessageRead(aMessage, otMessageGetOffset(aMessage) + bytesPrinted, buf, bytesToPrint);
133*cfb92d14SAndroid Build Coastguard Worker 
134*cfb92d14SAndroid Build Coastguard Worker             OutputBytes(buf, static_cast<uint8_t>(bytesToPrint));
135*cfb92d14SAndroid Build Coastguard Worker 
136*cfb92d14SAndroid Build Coastguard Worker             length -= bytesToPrint;
137*cfb92d14SAndroid Build Coastguard Worker             bytesPrinted += bytesToPrint;
138*cfb92d14SAndroid Build Coastguard Worker         }
139*cfb92d14SAndroid Build Coastguard Worker     }
140*cfb92d14SAndroid Build Coastguard Worker 
141*cfb92d14SAndroid Build Coastguard Worker     OutputNewLine();
142*cfb92d14SAndroid Build Coastguard Worker }
143*cfb92d14SAndroid Build Coastguard Worker 
144*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
145*cfb92d14SAndroid Build Coastguard Worker /**
146*cfb92d14SAndroid Build Coastguard Worker  * @cli coap cancel
147*cfb92d14SAndroid Build Coastguard Worker  * @code
148*cfb92d14SAndroid Build Coastguard Worker  * coap cancel
149*cfb92d14SAndroid Build Coastguard Worker  * Done
150*cfb92d14SAndroid Build Coastguard Worker  * @endcode
151*cfb92d14SAndroid Build Coastguard Worker  * @par
152*cfb92d14SAndroid Build Coastguard Worker  * Cancels an existing observation subscription to a remote resource on the CoAP server.
153*cfb92d14SAndroid Build Coastguard Worker  * @note This command is available only when `OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE` is set.
154*cfb92d14SAndroid Build Coastguard Worker  * @csa{coap observe}
155*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])156*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("cancel")>(Arg aArgs[])
157*cfb92d14SAndroid Build Coastguard Worker {
158*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aArgs);
159*cfb92d14SAndroid Build Coastguard Worker 
160*cfb92d14SAndroid Build Coastguard Worker     return CancelResourceSubscription();
161*cfb92d14SAndroid Build Coastguard Worker }
162*cfb92d14SAndroid Build Coastguard Worker #endif
163*cfb92d14SAndroid Build Coastguard Worker 
164*cfb92d14SAndroid Build Coastguard Worker /**
165*cfb92d14SAndroid Build Coastguard Worker  * @cli coap resource (get,set)
166*cfb92d14SAndroid Build Coastguard Worker  * @code
167*cfb92d14SAndroid Build Coastguard Worker  * coap resource test-resource
168*cfb92d14SAndroid Build Coastguard Worker  * Done
169*cfb92d14SAndroid Build Coastguard Worker  * @endcode
170*cfb92d14SAndroid Build Coastguard Worker  * @code
171*cfb92d14SAndroid Build Coastguard Worker  * coap resource
172*cfb92d14SAndroid Build Coastguard Worker  * test-resource
173*cfb92d14SAndroid Build Coastguard Worker  * Done
174*cfb92d14SAndroid Build Coastguard Worker  * @endcode
175*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap resource [@ca{uri-path}]
176*cfb92d14SAndroid Build Coastguard Worker  * @par
177*cfb92d14SAndroid Build Coastguard Worker  * Gets or sets the URI path of the CoAP server resource.
178*cfb92d14SAndroid Build Coastguard Worker  * @sa otCoapAddResource
179*cfb92d14SAndroid Build Coastguard Worker  * @sa otCoapAddBlockWiseResource
180*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])181*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("resource")>(Arg aArgs[])
182*cfb92d14SAndroid Build Coastguard Worker {
183*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
184*cfb92d14SAndroid Build Coastguard Worker 
185*cfb92d14SAndroid Build Coastguard Worker     if (!aArgs[0].IsEmpty())
186*cfb92d14SAndroid Build Coastguard Worker     {
187*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(aArgs[0].GetLength() < kMaxUriLength, error = OT_ERROR_INVALID_ARGS);
188*cfb92d14SAndroid Build Coastguard Worker 
189*cfb92d14SAndroid Build Coastguard Worker         mResource.mUriPath = mUriPath;
190*cfb92d14SAndroid Build Coastguard Worker         mResource.mContext = this;
191*cfb92d14SAndroid Build Coastguard Worker         mResource.mHandler = &Coap::HandleRequest;
192*cfb92d14SAndroid Build Coastguard Worker 
193*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
194*cfb92d14SAndroid Build Coastguard Worker         mResource.mReceiveHook  = &Coap::BlockwiseReceiveHook;
195*cfb92d14SAndroid Build Coastguard Worker         mResource.mTransmitHook = &Coap::BlockwiseTransmitHook;
196*cfb92d14SAndroid Build Coastguard Worker 
197*cfb92d14SAndroid Build Coastguard Worker         if (!aArgs[1].IsEmpty())
198*cfb92d14SAndroid Build Coastguard Worker         {
199*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[1].ParseAsUint32(mBlockCount));
200*cfb92d14SAndroid Build Coastguard Worker         }
201*cfb92d14SAndroid Build Coastguard Worker #endif
202*cfb92d14SAndroid Build Coastguard Worker 
203*cfb92d14SAndroid Build Coastguard Worker         strncpy(mUriPath, aArgs[0].GetCString(), sizeof(mUriPath) - 1);
204*cfb92d14SAndroid Build Coastguard Worker 
205*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
206*cfb92d14SAndroid Build Coastguard Worker         otCoapAddBlockWiseResource(GetInstancePtr(), &mResource);
207*cfb92d14SAndroid Build Coastguard Worker #else
208*cfb92d14SAndroid Build Coastguard Worker         otCoapAddResource(GetInstancePtr(), &mResource);
209*cfb92d14SAndroid Build Coastguard Worker #endif
210*cfb92d14SAndroid Build Coastguard Worker     }
211*cfb92d14SAndroid Build Coastguard Worker     else
212*cfb92d14SAndroid Build Coastguard Worker     {
213*cfb92d14SAndroid Build Coastguard Worker         OutputLine("%s", mResource.mUriPath != nullptr ? mResource.mUriPath : "");
214*cfb92d14SAndroid Build Coastguard Worker     }
215*cfb92d14SAndroid Build Coastguard Worker 
216*cfb92d14SAndroid Build Coastguard Worker exit:
217*cfb92d14SAndroid Build Coastguard Worker     return error;
218*cfb92d14SAndroid Build Coastguard Worker }
219*cfb92d14SAndroid Build Coastguard Worker 
220*cfb92d14SAndroid Build Coastguard Worker /**
221*cfb92d14SAndroid Build Coastguard Worker  * @cli coap set
222*cfb92d14SAndroid Build Coastguard Worker  * @code
223*cfb92d14SAndroid Build Coastguard Worker  * coap set Testing123
224*cfb92d14SAndroid Build Coastguard Worker  * Done
225*cfb92d14SAndroid Build Coastguard Worker  * @endcode
226*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap set @ca{new-content}
227*cfb92d14SAndroid Build Coastguard Worker  * @par
228*cfb92d14SAndroid Build Coastguard Worker  * Sets the content sent by the resource on the CoAP server.
229*cfb92d14SAndroid Build Coastguard Worker  * If a CoAP client is observing the resource, a notification is sent to that client.
230*cfb92d14SAndroid Build Coastguard Worker  * @csa{coap observe}
231*cfb92d14SAndroid Build Coastguard Worker  * @sa otCoapMessageInit
232*cfb92d14SAndroid Build Coastguard Worker  * @sa otCoapNewMessage
233*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])234*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("set")>(Arg aArgs[])
235*cfb92d14SAndroid Build Coastguard Worker {
236*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
237*cfb92d14SAndroid Build Coastguard Worker     otMessage    *notificationMessage = nullptr;
238*cfb92d14SAndroid Build Coastguard Worker     otMessageInfo messageInfo;
239*cfb92d14SAndroid Build Coastguard Worker #endif
240*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
241*cfb92d14SAndroid Build Coastguard Worker 
242*cfb92d14SAndroid Build Coastguard Worker     if (!aArgs[0].IsEmpty())
243*cfb92d14SAndroid Build Coastguard Worker     {
244*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(aArgs[0].GetLength() < sizeof(mResourceContent), error = OT_ERROR_INVALID_ARGS);
245*cfb92d14SAndroid Build Coastguard Worker         strncpy(mResourceContent, aArgs[0].GetCString(), sizeof(mResourceContent));
246*cfb92d14SAndroid Build Coastguard Worker         mResourceContent[sizeof(mResourceContent) - 1] = '\0';
247*cfb92d14SAndroid Build Coastguard Worker 
248*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
249*cfb92d14SAndroid Build Coastguard Worker         if (mSubscriberTokenLength > 0)
250*cfb92d14SAndroid Build Coastguard Worker         {
251*cfb92d14SAndroid Build Coastguard Worker             // Notify the subscriber
252*cfb92d14SAndroid Build Coastguard Worker             ClearAllBytes(messageInfo);
253*cfb92d14SAndroid Build Coastguard Worker             messageInfo.mPeerAddr = mSubscriberSock.mAddress;
254*cfb92d14SAndroid Build Coastguard Worker             messageInfo.mPeerPort = mSubscriberSock.mPort;
255*cfb92d14SAndroid Build Coastguard Worker 
256*cfb92d14SAndroid Build Coastguard Worker             OutputFormat("sending coap notification to ");
257*cfb92d14SAndroid Build Coastguard Worker             OutputIp6AddressLine(mSubscriberSock.mAddress);
258*cfb92d14SAndroid Build Coastguard Worker 
259*cfb92d14SAndroid Build Coastguard Worker             notificationMessage = otCoapNewMessage(GetInstancePtr(), nullptr);
260*cfb92d14SAndroid Build Coastguard Worker             VerifyOrExit(notificationMessage != nullptr, error = OT_ERROR_NO_BUFS);
261*cfb92d14SAndroid Build Coastguard Worker 
262*cfb92d14SAndroid Build Coastguard Worker             otCoapMessageInit(
263*cfb92d14SAndroid Build Coastguard Worker                 notificationMessage,
264*cfb92d14SAndroid Build Coastguard Worker                 ((mSubscriberConfirmableNotifications) ? OT_COAP_TYPE_CONFIRMABLE : OT_COAP_TYPE_NON_CONFIRMABLE),
265*cfb92d14SAndroid Build Coastguard Worker                 OT_COAP_CODE_CONTENT);
266*cfb92d14SAndroid Build Coastguard Worker 
267*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapMessageSetToken(notificationMessage, mSubscriberToken, mSubscriberTokenLength));
268*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapMessageAppendObserveOption(notificationMessage, mObserveSerial++));
269*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapMessageSetPayloadMarker(notificationMessage));
270*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otMessageAppend(notificationMessage, mResourceContent,
271*cfb92d14SAndroid Build Coastguard Worker                                                   static_cast<uint16_t>(strlen(mResourceContent))));
272*cfb92d14SAndroid Build Coastguard Worker 
273*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapSendRequest(GetInstancePtr(), notificationMessage, &messageInfo,
274*cfb92d14SAndroid Build Coastguard Worker                                                     &Coap::HandleNotificationResponse, this));
275*cfb92d14SAndroid Build Coastguard Worker         }
276*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
277*cfb92d14SAndroid Build Coastguard Worker     }
278*cfb92d14SAndroid Build Coastguard Worker     else
279*cfb92d14SAndroid Build Coastguard Worker     {
280*cfb92d14SAndroid Build Coastguard Worker         OutputLine("%s", mResourceContent);
281*cfb92d14SAndroid Build Coastguard Worker     }
282*cfb92d14SAndroid Build Coastguard Worker 
283*cfb92d14SAndroid Build Coastguard Worker exit:
284*cfb92d14SAndroid Build Coastguard Worker 
285*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
286*cfb92d14SAndroid Build Coastguard Worker     if ((error != OT_ERROR_NONE) && (notificationMessage != nullptr))
287*cfb92d14SAndroid Build Coastguard Worker     {
288*cfb92d14SAndroid Build Coastguard Worker         otMessageFree(notificationMessage);
289*cfb92d14SAndroid Build Coastguard Worker     }
290*cfb92d14SAndroid Build Coastguard Worker #endif
291*cfb92d14SAndroid Build Coastguard Worker 
292*cfb92d14SAndroid Build Coastguard Worker     return error;
293*cfb92d14SAndroid Build Coastguard Worker }
294*cfb92d14SAndroid Build Coastguard Worker 
295*cfb92d14SAndroid Build Coastguard Worker /**
296*cfb92d14SAndroid Build Coastguard Worker  * @cli coap start
297*cfb92d14SAndroid Build Coastguard Worker  * @code
298*cfb92d14SAndroid Build Coastguard Worker  * coap start
299*cfb92d14SAndroid Build Coastguard Worker  * Done
300*cfb92d14SAndroid Build Coastguard Worker  * @endcode
301*cfb92d14SAndroid Build Coastguard Worker  * @par
302*cfb92d14SAndroid Build Coastguard Worker  * Starts the CoAP server. @moreinfo{@coap}.
303*cfb92d14SAndroid Build Coastguard Worker  * @sa otCoapStart
304*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])305*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("start")>(Arg aArgs[])
306*cfb92d14SAndroid Build Coastguard Worker {
307*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aArgs);
308*cfb92d14SAndroid Build Coastguard Worker 
309*cfb92d14SAndroid Build Coastguard Worker     return otCoapStart(GetInstancePtr(), OT_DEFAULT_COAP_PORT);
310*cfb92d14SAndroid Build Coastguard Worker }
311*cfb92d14SAndroid Build Coastguard Worker 
312*cfb92d14SAndroid Build Coastguard Worker /**
313*cfb92d14SAndroid Build Coastguard Worker  * @cli coap stop
314*cfb92d14SAndroid Build Coastguard Worker  * @code
315*cfb92d14SAndroid Build Coastguard Worker  * coap stop
316*cfb92d14SAndroid Build Coastguard Worker  * Done
317*cfb92d14SAndroid Build Coastguard Worker  * @endcode
318*cfb92d14SAndroid Build Coastguard Worker  * @par api_copy
319*cfb92d14SAndroid Build Coastguard Worker  * #otCoapStop
320*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])321*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("stop")>(Arg aArgs[])
322*cfb92d14SAndroid Build Coastguard Worker {
323*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aArgs);
324*cfb92d14SAndroid Build Coastguard Worker 
325*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
326*cfb92d14SAndroid Build Coastguard Worker     otCoapRemoveBlockWiseResource(GetInstancePtr(), &mResource);
327*cfb92d14SAndroid Build Coastguard Worker #else
328*cfb92d14SAndroid Build Coastguard Worker     otCoapRemoveResource(GetInstancePtr(), &mResource);
329*cfb92d14SAndroid Build Coastguard Worker #endif
330*cfb92d14SAndroid Build Coastguard Worker 
331*cfb92d14SAndroid Build Coastguard Worker     return otCoapStop(GetInstancePtr());
332*cfb92d14SAndroid Build Coastguard Worker }
333*cfb92d14SAndroid Build Coastguard Worker 
334*cfb92d14SAndroid Build Coastguard Worker /**
335*cfb92d14SAndroid Build Coastguard Worker  * @cli coap parameters(get,set)
336*cfb92d14SAndroid Build Coastguard Worker  * @code
337*cfb92d14SAndroid Build Coastguard Worker  * coap parameters request
338*cfb92d14SAndroid Build Coastguard Worker  * Transmission parameters for request:
339*cfb92d14SAndroid Build Coastguard Worker  * ACK_TIMEOUT=1000 ms, ACK_RANDOM_FACTOR=255/254, MAX_RETRANSMIT=2
340*cfb92d14SAndroid Build Coastguard Worker  * Done
341*cfb92d14SAndroid Build Coastguard Worker  * @endcode
342*cfb92d14SAndroid Build Coastguard Worker  * @code
343*cfb92d14SAndroid Build Coastguard Worker  * coap parameters request default
344*cfb92d14SAndroid Build Coastguard Worker  * Transmission parameters for request:
345*cfb92d14SAndroid Build Coastguard Worker  * default
346*cfb92d14SAndroid Build Coastguard Worker  * Done
347*cfb92d14SAndroid Build Coastguard Worker  * @endcode
348*cfb92d14SAndroid Build Coastguard Worker  * @code
349*cfb92d14SAndroid Build Coastguard Worker  * coap parameters request 1000 255 254 2
350*cfb92d14SAndroid Build Coastguard Worker  * Transmission parameters for request:
351*cfb92d14SAndroid Build Coastguard Worker  * ACK_TIMEOUT=1000 ms, ACK_RANDOM_FACTOR=255/254, MAX_RETRANSMIT=2
352*cfb92d14SAndroid Build Coastguard Worker  * Done
353*cfb92d14SAndroid Build Coastguard Worker  * @endcode
354*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap parameters @ca{type} [@ca{default} | <!--
355*cfb92d14SAndroid Build Coastguard Worker  * -->@ca{ack_timeout ack_random_factor_numerator <!--
356*cfb92d14SAndroid Build Coastguard Worker  * -->ack_random_factor_denominator max_retransmit}]
357*cfb92d14SAndroid Build Coastguard Worker  *   * `type`: `request` for CoAP requests, or `response` for CoAP responses.
358*cfb92d14SAndroid Build Coastguard Worker         If no more parameters are given, the command prints the current configuration.
359*cfb92d14SAndroid Build Coastguard Worker  *   * `default`: Sets the transmission parameters to
360*cfb92d14SAndroid Build Coastguard Worker         the following default values:
361*cfb92d14SAndroid Build Coastguard Worker  *       * `ack_timeout`: 2000 milliseconds
362*cfb92d14SAndroid Build Coastguard Worker  *       * `ack_random_factor_numerator`: 3
363*cfb92d14SAndroid Build Coastguard Worker  *       * `ack_random_factor_denominator`: 2
364*cfb92d14SAndroid Build Coastguard Worker  *       * `max_retransmit`: 4
365*cfb92d14SAndroid Build Coastguard Worker  *   * `ack_timeout`: The `ACK_TIMEOUT` (0-UINT32_MAX) in milliseconds.
366*cfb92d14SAndroid Build Coastguard Worker        Refer to RFC7252.
367*cfb92d14SAndroid Build Coastguard Worker  *   * `ack_random_factor_numerator`:
368*cfb92d14SAndroid Build Coastguard Worker        The `ACK_RANDOM_FACTOR` numerator, with possible values
369*cfb92d14SAndroid Build Coastguard Worker        of 0-255. Refer to RFC7252.
370*cfb92d14SAndroid Build Coastguard Worker  *   * `ack_random_factor_denominator`:
371*cfb92d14SAndroid Build Coastguard Worker  *     The `ACK_RANDOM_FACTOR` denominator, with possible values
372*cfb92d14SAndroid Build Coastguard Worker  *     of 0-255. Refer to RFC7252.
373*cfb92d14SAndroid Build Coastguard Worker  *   * `max_retransmit`: The `MAX_RETRANSMIT` (0-255). Refer to RFC7252.
374*cfb92d14SAndroid Build Coastguard Worker  * @par
375*cfb92d14SAndroid Build Coastguard Worker  * Gets current CoAP parameter values if the command is run with no optional
376*cfb92d14SAndroid Build Coastguard Worker  * parameters.
377*cfb92d14SAndroid Build Coastguard Worker  * @par
378*cfb92d14SAndroid Build Coastguard Worker  * Sets the CoAP parameters either to their default values or to the values
379*cfb92d14SAndroid Build Coastguard Worker  * you specify, depending on the syntax chosen.
380*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])381*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("parameters")>(Arg aArgs[])
382*cfb92d14SAndroid Build Coastguard Worker {
383*cfb92d14SAndroid Build Coastguard Worker     otError             error = OT_ERROR_NONE;
384*cfb92d14SAndroid Build Coastguard Worker     bool               *defaultTxParameters;
385*cfb92d14SAndroid Build Coastguard Worker     otCoapTxParameters *txParameters;
386*cfb92d14SAndroid Build Coastguard Worker 
387*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0] == "request")
388*cfb92d14SAndroid Build Coastguard Worker     {
389*cfb92d14SAndroid Build Coastguard Worker         txParameters        = &mRequestTxParameters;
390*cfb92d14SAndroid Build Coastguard Worker         defaultTxParameters = &mUseDefaultRequestTxParameters;
391*cfb92d14SAndroid Build Coastguard Worker     }
392*cfb92d14SAndroid Build Coastguard Worker     else if (aArgs[0] == "response")
393*cfb92d14SAndroid Build Coastguard Worker     {
394*cfb92d14SAndroid Build Coastguard Worker         txParameters        = &mResponseTxParameters;
395*cfb92d14SAndroid Build Coastguard Worker         defaultTxParameters = &mUseDefaultResponseTxParameters;
396*cfb92d14SAndroid Build Coastguard Worker     }
397*cfb92d14SAndroid Build Coastguard Worker     else
398*cfb92d14SAndroid Build Coastguard Worker     {
399*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = OT_ERROR_INVALID_ARGS);
400*cfb92d14SAndroid Build Coastguard Worker     }
401*cfb92d14SAndroid Build Coastguard Worker 
402*cfb92d14SAndroid Build Coastguard Worker     if (!aArgs[1].IsEmpty())
403*cfb92d14SAndroid Build Coastguard Worker     {
404*cfb92d14SAndroid Build Coastguard Worker         if (aArgs[1] == "default")
405*cfb92d14SAndroid Build Coastguard Worker         {
406*cfb92d14SAndroid Build Coastguard Worker             *defaultTxParameters = true;
407*cfb92d14SAndroid Build Coastguard Worker         }
408*cfb92d14SAndroid Build Coastguard Worker         else
409*cfb92d14SAndroid Build Coastguard Worker         {
410*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[1].ParseAsUint32(txParameters->mAckTimeout));
411*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[2].ParseAsUint8(txParameters->mAckRandomFactorNumerator));
412*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[3].ParseAsUint8(txParameters->mAckRandomFactorDenominator));
413*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[4].ParseAsUint8(txParameters->mMaxRetransmit));
414*cfb92d14SAndroid Build Coastguard Worker 
415*cfb92d14SAndroid Build Coastguard Worker             VerifyOrExit(txParameters->mAckRandomFactorNumerator > txParameters->mAckRandomFactorDenominator,
416*cfb92d14SAndroid Build Coastguard Worker                          error = OT_ERROR_INVALID_ARGS);
417*cfb92d14SAndroid Build Coastguard Worker 
418*cfb92d14SAndroid Build Coastguard Worker             *defaultTxParameters = false;
419*cfb92d14SAndroid Build Coastguard Worker         }
420*cfb92d14SAndroid Build Coastguard Worker     }
421*cfb92d14SAndroid Build Coastguard Worker 
422*cfb92d14SAndroid Build Coastguard Worker     OutputLine("Transmission parameters for %s:", aArgs[0].GetCString());
423*cfb92d14SAndroid Build Coastguard Worker 
424*cfb92d14SAndroid Build Coastguard Worker     if (*defaultTxParameters)
425*cfb92d14SAndroid Build Coastguard Worker     {
426*cfb92d14SAndroid Build Coastguard Worker         OutputLine("default");
427*cfb92d14SAndroid Build Coastguard Worker     }
428*cfb92d14SAndroid Build Coastguard Worker     else
429*cfb92d14SAndroid Build Coastguard Worker     {
430*cfb92d14SAndroid Build Coastguard Worker         OutputLine("ACK_TIMEOUT=%lu ms, ACK_RANDOM_FACTOR=%u/%u, MAX_RETRANSMIT=%u", ToUlong(txParameters->mAckTimeout),
431*cfb92d14SAndroid Build Coastguard Worker                    txParameters->mAckRandomFactorNumerator, txParameters->mAckRandomFactorDenominator,
432*cfb92d14SAndroid Build Coastguard Worker                    txParameters->mMaxRetransmit);
433*cfb92d14SAndroid Build Coastguard Worker     }
434*cfb92d14SAndroid Build Coastguard Worker 
435*cfb92d14SAndroid Build Coastguard Worker exit:
436*cfb92d14SAndroid Build Coastguard Worker     return error;
437*cfb92d14SAndroid Build Coastguard Worker }
438*cfb92d14SAndroid Build Coastguard Worker 
439*cfb92d14SAndroid Build Coastguard Worker /**
440*cfb92d14SAndroid Build Coastguard Worker  * @cli coap get
441*cfb92d14SAndroid Build Coastguard Worker  * @code
442*cfb92d14SAndroid Build Coastguard Worker  * coap get fdde:ad00:beef:0:2780:9423:166c:1aac test-resource
443*cfb92d14SAndroid Build Coastguard Worker  * Done
444*cfb92d14SAndroid Build Coastguard Worker  * @endcode
445*cfb92d14SAndroid Build Coastguard Worker  * @code
446*cfb92d14SAndroid Build Coastguard Worker  * coap get fdde:ad00:beef:0:2780:9423:166c:1aac test-resource block-1024
447*cfb92d14SAndroid Build Coastguard Worker  * Done
448*cfb92d14SAndroid Build Coastguard Worker  * @endcode
449*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap get @ca{address} @ca{uri-path} [@ca{type}]
450*cfb92d14SAndroid Build Coastguard Worker  *   * `address`: IPv6 address of the CoAP server.
451*cfb92d14SAndroid Build Coastguard Worker  *   * `uri-path`: URI path of the resource.
452*cfb92d14SAndroid Build Coastguard Worker  *   * `type`:
453*cfb92d14SAndroid Build Coastguard Worker  *       * `con`: Confirmable
454*cfb92d14SAndroid Build Coastguard Worker  *       * `non-con`: Non-confirmable (default)
455*cfb92d14SAndroid Build Coastguard Worker  *       * `block-`: Use this option, followed by the block-wise value,
456*cfb92d14SAndroid Build Coastguard Worker  *          if the response should be transferred block-wise. Valid
457*cfb92d14SAndroid Build Coastguard Worker  *          values are: `block-16`, `block-32`, `block-64`, `block-128`,
458*cfb92d14SAndroid Build Coastguard Worker  *          `block-256`, `block-512`, or `block-1024`.
459*cfb92d14SAndroid Build Coastguard Worker  * @par
460*cfb92d14SAndroid Build Coastguard Worker  * Gets information about the specified CoAP resource on the CoAP server.
461*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])462*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("get")>(Arg aArgs[]) { return ProcessRequest(aArgs, OT_COAP_CODE_GET); }
463*cfb92d14SAndroid Build Coastguard Worker 
464*cfb92d14SAndroid Build Coastguard Worker /**
465*cfb92d14SAndroid Build Coastguard Worker  * @cli coap post
466*cfb92d14SAndroid Build Coastguard Worker  * @code
467*cfb92d14SAndroid Build Coastguard Worker  * coap post fdde:ad00:beef:0:2780:9423:166c:1aac test-resource con hellothere
468*cfb92d14SAndroid Build Coastguard Worker  * Done
469*cfb92d14SAndroid Build Coastguard Worker  * @endcode
470*cfb92d14SAndroid Build Coastguard Worker  * @code
471*cfb92d14SAndroid Build Coastguard Worker  * coap post fdde:ad00:beef:0:2780:9423:166c:1aac test-resource block-1024 10
472*cfb92d14SAndroid Build Coastguard Worker  * Done
473*cfb92d14SAndroid Build Coastguard Worker  * @endcode
474*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap post @ca{address} @ca{uri-path} [@ca{type}] [@ca{payload}]
475*cfb92d14SAndroid Build Coastguard Worker  *   * `address`: IPv6 address of the CoAP server.
476*cfb92d14SAndroid Build Coastguard Worker  *   * `uri-path`: URI path of the resource.
477*cfb92d14SAndroid Build Coastguard Worker  *   * `type`:
478*cfb92d14SAndroid Build Coastguard Worker  *         * `con`: Confirmable
479*cfb92d14SAndroid Build Coastguard Worker  *         * `non-con`: Non-confirmable (default)
480*cfb92d14SAndroid Build Coastguard Worker  *         * `block-`: Use this option, followed by the block-wise value,
481*cfb92d14SAndroid Build Coastguard Worker  *            to send blocks with a randomly generated number of bytes
482*cfb92d14SAndroid Build Coastguard Worker  *            for the payload. Valid values are:
483*cfb92d14SAndroid Build Coastguard Worker  *            `block-16`, `block-32`, `block-64`, `block-128`,
484*cfb92d14SAndroid Build Coastguard Worker  *            `block-256`, `block-512`, or `block-1024`.
485*cfb92d14SAndroid Build Coastguard Worker  *   * `payload`: CoAP payload request, which if used is either a string or an
486*cfb92d14SAndroid Build Coastguard Worker  *     integer, depending on the `type`. If the `type` is `con` or `non-con`,
487*cfb92d14SAndroid Build Coastguard Worker  *     the `payload` parameter is optional. If you leave out the
488*cfb92d14SAndroid Build Coastguard Worker  *     `payload` parameter, an empty payload is sent. However, If you use the
489*cfb92d14SAndroid Build Coastguard Worker  *     `payload` parameter, its value must be a string, such as
490*cfb92d14SAndroid Build Coastguard Worker  *     `hellothere`.  If the `type` is `block-`,
491*cfb92d14SAndroid Build Coastguard Worker  *     the value of the`payload` parameter must be an integer that specifies
492*cfb92d14SAndroid Build Coastguard Worker  *     the number of blocks to send. The `block-` type requires
493*cfb92d14SAndroid Build Coastguard Worker  *     `OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE` to be set.
494*cfb92d14SAndroid Build Coastguard Worker  * @par
495*cfb92d14SAndroid Build Coastguard Worker  * Creates the specified CoAP resource. @moreinfo{@coap}.
496*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])497*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("post")>(Arg aArgs[]) { return ProcessRequest(aArgs, OT_COAP_CODE_POST); }
498*cfb92d14SAndroid Build Coastguard Worker 
499*cfb92d14SAndroid Build Coastguard Worker /**
500*cfb92d14SAndroid Build Coastguard Worker  * @cli coap put
501*cfb92d14SAndroid Build Coastguard Worker  * @code
502*cfb92d14SAndroid Build Coastguard Worker  * coap put fdde:ad00:beef:0:2780:9423:166c:1aac test-resource con hellothere
503*cfb92d14SAndroid Build Coastguard Worker  * Done
504*cfb92d14SAndroid Build Coastguard Worker  * @endcode
505*cfb92d14SAndroid Build Coastguard Worker  * @code
506*cfb92d14SAndroid Build Coastguard Worker  * coap put fdde:ad00:beef:0:2780:9423:166c:1aac test-resource block-1024 10
507*cfb92d14SAndroid Build Coastguard Worker  * Done
508*cfb92d14SAndroid Build Coastguard Worker  * @endcode
509*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap put @ca{address} @ca{uri-path} [@ca{type}] [@ca{payload}]
510*cfb92d14SAndroid Build Coastguard Worker  *   * `address`: IPv6 address of the CoAP server.
511*cfb92d14SAndroid Build Coastguard Worker  *   * `uri-path`: URI path of the resource.
512*cfb92d14SAndroid Build Coastguard Worker  *   * `type`:
513*cfb92d14SAndroid Build Coastguard Worker  *         * `con`: Confirmable
514*cfb92d14SAndroid Build Coastguard Worker  *         * `non-con`: Non-confirmable (default)
515*cfb92d14SAndroid Build Coastguard Worker  *         * `block-`: Use this option, followed by the block-wise value,
516*cfb92d14SAndroid Build Coastguard Worker  *            to send blocks with a randomly generated number of bytes
517*cfb92d14SAndroid Build Coastguard Worker  *            for the payload. Valid values are:
518*cfb92d14SAndroid Build Coastguard Worker  *            `block-16`, `block-32`, `block-64`, `block-128`,
519*cfb92d14SAndroid Build Coastguard Worker  *            `block-256`, `block-512`, or `block-1024`.
520*cfb92d14SAndroid Build Coastguard Worker  *   * `payload`: CoAP payload request, which if used is either a string or an
521*cfb92d14SAndroid Build Coastguard Worker  *     integer, depending on the `type`. If the `type` is `con` or `non-con`,
522*cfb92d14SAndroid Build Coastguard Worker  *     the `payload` parameter is optional. If you leave out the
523*cfb92d14SAndroid Build Coastguard Worker  *     `payload` parameter, an empty payload is sent. However, If you use the
524*cfb92d14SAndroid Build Coastguard Worker  *     `payload` parameter, its value must be a string, such as
525*cfb92d14SAndroid Build Coastguard Worker  *     `hellothere`. If the `type` is `block-`,
526*cfb92d14SAndroid Build Coastguard Worker  *     the value of the`payload` parameter must be an integer that specifies
527*cfb92d14SAndroid Build Coastguard Worker  *     the number of blocks to send. The `block-` type requires
528*cfb92d14SAndroid Build Coastguard Worker  *     `OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE` to be set.
529*cfb92d14SAndroid Build Coastguard Worker  * @par
530*cfb92d14SAndroid Build Coastguard Worker  * Modifies the specified CoAP resource. @moreinfo{@coap}.
531*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])532*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("put")>(Arg aArgs[]) { return ProcessRequest(aArgs, OT_COAP_CODE_PUT); }
533*cfb92d14SAndroid Build Coastguard Worker 
534*cfb92d14SAndroid Build Coastguard Worker /**
535*cfb92d14SAndroid Build Coastguard Worker  * @cli coap delete
536*cfb92d14SAndroid Build Coastguard Worker  * @code
537*cfb92d14SAndroid Build Coastguard Worker  * coap delete fdde:ad00:beef:0:2780:9423:166c:1aac test-resource con hellothere
538*cfb92d14SAndroid Build Coastguard Worker  * Done
539*cfb92d14SAndroid Build Coastguard Worker  * @endcode
540*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap delete @ca{address} @ca{uri-path} [@ca{type}] [@ca{payload}]
541*cfb92d14SAndroid Build Coastguard Worker  *   * `address`: IPv6 address of the CoAP server.
542*cfb92d14SAndroid Build Coastguard Worker  *   * `uri-path`: URI path of the resource.
543*cfb92d14SAndroid Build Coastguard Worker  *   * `type`:
544*cfb92d14SAndroid Build Coastguard Worker  *       * `con`: Confirmable
545*cfb92d14SAndroid Build Coastguard Worker  *       * `non-con`: Non-confirmable (default)
546*cfb92d14SAndroid Build Coastguard Worker  *   * `payload`: The CoAP payload string. For example, `hellothere`.
547*cfb92d14SAndroid Build Coastguard Worker  *  @par
548*cfb92d14SAndroid Build Coastguard Worker  *  Deletes the specified CoAP resource.
549*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])550*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("delete")>(Arg aArgs[]) { return ProcessRequest(aArgs, OT_COAP_CODE_DELETE); }
551*cfb92d14SAndroid Build Coastguard Worker 
552*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
553*cfb92d14SAndroid Build Coastguard Worker /**
554*cfb92d14SAndroid Build Coastguard Worker  * @cli coap observe
555*cfb92d14SAndroid Build Coastguard Worker  * @code
556*cfb92d14SAndroid Build Coastguard Worker  * coap observe fdde:ad00:beef:0:2780:9423:166c:1aac test-resource
557*cfb92d14SAndroid Build Coastguard Worker  * Done
558*cfb92d14SAndroid Build Coastguard Worker  * @endcode
559*cfb92d14SAndroid Build Coastguard Worker  * @cparam coap observe @ca{address} @ca{uri-path} [@ca{type}]
560*cfb92d14SAndroid Build Coastguard Worker  *   * `address`: IPv6 address of the CoAP server.
561*cfb92d14SAndroid Build Coastguard Worker  *   * `uri-path`: URI path of the resource.
562*cfb92d14SAndroid Build Coastguard Worker  *   * `type`:
563*cfb92d14SAndroid Build Coastguard Worker  *       * `con`: Confirmable
564*cfb92d14SAndroid Build Coastguard Worker  *       * `non-con`: Non-confirmable (default).
565*cfb92d14SAndroid Build Coastguard Worker  * @par
566*cfb92d14SAndroid Build Coastguard Worker  * Triggers a subscription request which allows the CoAP client to
567*cfb92d14SAndroid Build Coastguard Worker  * observe the specified resource on the CoAP server for possible changes
568*cfb92d14SAndroid Build Coastguard Worker  * in its state.
569*cfb92d14SAndroid Build Coastguard Worker  * @note This command is available only when `OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE` is set.
570*cfb92d14SAndroid Build Coastguard Worker  */
Process(Arg aArgs[])571*cfb92d14SAndroid Build Coastguard Worker template <> otError Coap::Process<Cmd("observe")>(Arg aArgs[])
572*cfb92d14SAndroid Build Coastguard Worker {
573*cfb92d14SAndroid Build Coastguard Worker     return ProcessRequest(aArgs, OT_COAP_CODE_GET, /* aCoapObserve */ true);
574*cfb92d14SAndroid Build Coastguard Worker }
575*cfb92d14SAndroid Build Coastguard Worker #endif
576*cfb92d14SAndroid Build Coastguard Worker 
577*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
ProcessRequest(Arg aArgs[],otCoapCode aCoapCode,bool aCoapObserve)578*cfb92d14SAndroid Build Coastguard Worker otError Coap::ProcessRequest(Arg aArgs[], otCoapCode aCoapCode, bool aCoapObserve)
579*cfb92d14SAndroid Build Coastguard Worker #else
580*cfb92d14SAndroid Build Coastguard Worker otError Coap::ProcessRequest(Arg aArgs[], otCoapCode aCoapCode)
581*cfb92d14SAndroid Build Coastguard Worker #endif
582*cfb92d14SAndroid Build Coastguard Worker {
583*cfb92d14SAndroid Build Coastguard Worker     otError       error   = OT_ERROR_NONE;
584*cfb92d14SAndroid Build Coastguard Worker     otMessage    *message = nullptr;
585*cfb92d14SAndroid Build Coastguard Worker     otMessageInfo messageInfo;
586*cfb92d14SAndroid Build Coastguard Worker     uint16_t      payloadLength    = 0;
587*cfb92d14SAndroid Build Coastguard Worker     char         *uriQueryStartPtr = nullptr;
588*cfb92d14SAndroid Build Coastguard Worker 
589*cfb92d14SAndroid Build Coastguard Worker     // Default parameters
590*cfb92d14SAndroid Build Coastguard Worker     char         coapUri[kMaxUriLength] = "test";
591*cfb92d14SAndroid Build Coastguard Worker     otCoapType   coapType               = OT_COAP_TYPE_NON_CONFIRMABLE;
592*cfb92d14SAndroid Build Coastguard Worker     otIp6Address coapDestinationIp;
593*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
594*cfb92d14SAndroid Build Coastguard Worker     bool           coapBlock     = false;
595*cfb92d14SAndroid Build Coastguard Worker     otCoapBlockSzx coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_16;
596*cfb92d14SAndroid Build Coastguard Worker     BlockType      coapBlockType = (aCoapCode == OT_COAP_CODE_GET) ? kBlockType2 : kBlockType1;
597*cfb92d14SAndroid Build Coastguard Worker #endif
598*cfb92d14SAndroid Build Coastguard Worker 
599*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE && OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
600*cfb92d14SAndroid Build Coastguard Worker     if (aCoapObserve)
601*cfb92d14SAndroid Build Coastguard Worker     {
602*cfb92d14SAndroid Build Coastguard Worker         coapBlockType = kBlockType1;
603*cfb92d14SAndroid Build Coastguard Worker     }
604*cfb92d14SAndroid Build Coastguard Worker #endif
605*cfb92d14SAndroid Build Coastguard Worker 
606*cfb92d14SAndroid Build Coastguard Worker     SuccessOrExit(error = aArgs[0].ParseAsIp6Address(coapDestinationIp));
607*cfb92d14SAndroid Build Coastguard Worker 
608*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(!aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
609*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(aArgs[1].GetLength() < sizeof(coapUri), error = OT_ERROR_INVALID_ARGS);
610*cfb92d14SAndroid Build Coastguard Worker     strcpy(coapUri, aArgs[1].GetCString());
611*cfb92d14SAndroid Build Coastguard Worker 
612*cfb92d14SAndroid Build Coastguard Worker     // CoAP-Type
613*cfb92d14SAndroid Build Coastguard Worker     if (!aArgs[2].IsEmpty())
614*cfb92d14SAndroid Build Coastguard Worker     {
615*cfb92d14SAndroid Build Coastguard Worker         if (aArgs[2] == "con")
616*cfb92d14SAndroid Build Coastguard Worker         {
617*cfb92d14SAndroid Build Coastguard Worker             coapType = OT_COAP_TYPE_CONFIRMABLE;
618*cfb92d14SAndroid Build Coastguard Worker         }
619*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
620*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "block-16")
621*cfb92d14SAndroid Build Coastguard Worker         {
622*cfb92d14SAndroid Build Coastguard Worker             coapType      = OT_COAP_TYPE_CONFIRMABLE;
623*cfb92d14SAndroid Build Coastguard Worker             coapBlock     = true;
624*cfb92d14SAndroid Build Coastguard Worker             coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_16;
625*cfb92d14SAndroid Build Coastguard Worker         }
626*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "block-32")
627*cfb92d14SAndroid Build Coastguard Worker         {
628*cfb92d14SAndroid Build Coastguard Worker             coapType      = OT_COAP_TYPE_CONFIRMABLE;
629*cfb92d14SAndroid Build Coastguard Worker             coapBlock     = true;
630*cfb92d14SAndroid Build Coastguard Worker             coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_32;
631*cfb92d14SAndroid Build Coastguard Worker         }
632*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "block-64")
633*cfb92d14SAndroid Build Coastguard Worker         {
634*cfb92d14SAndroid Build Coastguard Worker             coapType      = OT_COAP_TYPE_CONFIRMABLE;
635*cfb92d14SAndroid Build Coastguard Worker             coapBlock     = true;
636*cfb92d14SAndroid Build Coastguard Worker             coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_64;
637*cfb92d14SAndroid Build Coastguard Worker         }
638*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "block-128")
639*cfb92d14SAndroid Build Coastguard Worker         {
640*cfb92d14SAndroid Build Coastguard Worker             coapType      = OT_COAP_TYPE_CONFIRMABLE;
641*cfb92d14SAndroid Build Coastguard Worker             coapBlock     = true;
642*cfb92d14SAndroid Build Coastguard Worker             coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_128;
643*cfb92d14SAndroid Build Coastguard Worker         }
644*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "block-256")
645*cfb92d14SAndroid Build Coastguard Worker         {
646*cfb92d14SAndroid Build Coastguard Worker             coapType      = OT_COAP_TYPE_CONFIRMABLE;
647*cfb92d14SAndroid Build Coastguard Worker             coapBlock     = true;
648*cfb92d14SAndroid Build Coastguard Worker             coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_256;
649*cfb92d14SAndroid Build Coastguard Worker         }
650*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "block-512")
651*cfb92d14SAndroid Build Coastguard Worker         {
652*cfb92d14SAndroid Build Coastguard Worker             coapType      = OT_COAP_TYPE_CONFIRMABLE;
653*cfb92d14SAndroid Build Coastguard Worker             coapBlock     = true;
654*cfb92d14SAndroid Build Coastguard Worker             coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_512;
655*cfb92d14SAndroid Build Coastguard Worker         }
656*cfb92d14SAndroid Build Coastguard Worker         else if (aArgs[2] == "block-1024")
657*cfb92d14SAndroid Build Coastguard Worker         {
658*cfb92d14SAndroid Build Coastguard Worker             coapType      = OT_COAP_TYPE_CONFIRMABLE;
659*cfb92d14SAndroid Build Coastguard Worker             coapBlock     = true;
660*cfb92d14SAndroid Build Coastguard Worker             coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_1024;
661*cfb92d14SAndroid Build Coastguard Worker         }
662*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
663*cfb92d14SAndroid Build Coastguard Worker     }
664*cfb92d14SAndroid Build Coastguard Worker 
665*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
666*cfb92d14SAndroid Build Coastguard Worker     if (aCoapObserve && mRequestTokenLength)
667*cfb92d14SAndroid Build Coastguard Worker     {
668*cfb92d14SAndroid Build Coastguard Worker         // New observe request, cancel any existing observation
669*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = CancelResourceSubscription());
670*cfb92d14SAndroid Build Coastguard Worker     }
671*cfb92d14SAndroid Build Coastguard Worker #endif
672*cfb92d14SAndroid Build Coastguard Worker 
673*cfb92d14SAndroid Build Coastguard Worker     message = otCoapNewMessage(GetInstancePtr(), nullptr);
674*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
675*cfb92d14SAndroid Build Coastguard Worker 
676*cfb92d14SAndroid Build Coastguard Worker     otCoapMessageInit(message, coapType, aCoapCode);
677*cfb92d14SAndroid Build Coastguard Worker     otCoapMessageGenerateToken(message, OT_COAP_DEFAULT_TOKEN_LENGTH);
678*cfb92d14SAndroid Build Coastguard Worker 
679*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
680*cfb92d14SAndroid Build Coastguard Worker     if (aCoapObserve)
681*cfb92d14SAndroid Build Coastguard Worker     {
682*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otCoapMessageAppendObserveOption(message, 0));
683*cfb92d14SAndroid Build Coastguard Worker     }
684*cfb92d14SAndroid Build Coastguard Worker #endif
685*cfb92d14SAndroid Build Coastguard Worker 
686*cfb92d14SAndroid Build Coastguard Worker     uriQueryStartPtr = const_cast<char *>(StringFind(coapUri, '?'));
687*cfb92d14SAndroid Build Coastguard Worker 
688*cfb92d14SAndroid Build Coastguard Worker     if (uriQueryStartPtr == nullptr)
689*cfb92d14SAndroid Build Coastguard Worker     {
690*cfb92d14SAndroid Build Coastguard Worker         // "?" doesn't present in URI --> contains only URI path parts
691*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, coapUri));
692*cfb92d14SAndroid Build Coastguard Worker     }
693*cfb92d14SAndroid Build Coastguard Worker     else
694*cfb92d14SAndroid Build Coastguard Worker     {
695*cfb92d14SAndroid Build Coastguard Worker         // "?" presents in URI --> contains URI path AND URI query parts
696*cfb92d14SAndroid Build Coastguard Worker         *uriQueryStartPtr++ = '\0';
697*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, coapUri));
698*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otCoapMessageAppendUriQueryOptions(message, uriQueryStartPtr));
699*cfb92d14SAndroid Build Coastguard Worker     }
700*cfb92d14SAndroid Build Coastguard Worker 
701*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
702*cfb92d14SAndroid Build Coastguard Worker     if (coapBlock)
703*cfb92d14SAndroid Build Coastguard Worker     {
704*cfb92d14SAndroid Build Coastguard Worker         if (coapBlockType == kBlockType1)
705*cfb92d14SAndroid Build Coastguard Worker         {
706*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapMessageAppendBlock1Option(message, 0, true, coapBlockSize));
707*cfb92d14SAndroid Build Coastguard Worker         }
708*cfb92d14SAndroid Build Coastguard Worker         else
709*cfb92d14SAndroid Build Coastguard Worker         {
710*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapMessageAppendBlock2Option(message, 0, false, coapBlockSize));
711*cfb92d14SAndroid Build Coastguard Worker         }
712*cfb92d14SAndroid Build Coastguard Worker     }
713*cfb92d14SAndroid Build Coastguard Worker #endif
714*cfb92d14SAndroid Build Coastguard Worker 
715*cfb92d14SAndroid Build Coastguard Worker     if (!aArgs[3].IsEmpty())
716*cfb92d14SAndroid Build Coastguard Worker     {
717*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
718*cfb92d14SAndroid Build Coastguard Worker         if (coapBlock)
719*cfb92d14SAndroid Build Coastguard Worker         {
720*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = aArgs[3].ParseAsUint32(mBlockCount));
721*cfb92d14SAndroid Build Coastguard Worker         }
722*cfb92d14SAndroid Build Coastguard Worker         else
723*cfb92d14SAndroid Build Coastguard Worker         {
724*cfb92d14SAndroid Build Coastguard Worker #endif
725*cfb92d14SAndroid Build Coastguard Worker             payloadLength = aArgs[3].GetLength();
726*cfb92d14SAndroid Build Coastguard Worker 
727*cfb92d14SAndroid Build Coastguard Worker             if (payloadLength > 0)
728*cfb92d14SAndroid Build Coastguard Worker             {
729*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = otCoapMessageSetPayloadMarker(message));
730*cfb92d14SAndroid Build Coastguard Worker             }
731*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
732*cfb92d14SAndroid Build Coastguard Worker         }
733*cfb92d14SAndroid Build Coastguard Worker #endif
734*cfb92d14SAndroid Build Coastguard Worker     }
735*cfb92d14SAndroid Build Coastguard Worker 
736*cfb92d14SAndroid Build Coastguard Worker     // Embed content into message if given
737*cfb92d14SAndroid Build Coastguard Worker     if (payloadLength > 0)
738*cfb92d14SAndroid Build Coastguard Worker     {
739*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otMessageAppend(message, aArgs[3].GetCString(), payloadLength));
740*cfb92d14SAndroid Build Coastguard Worker     }
741*cfb92d14SAndroid Build Coastguard Worker 
742*cfb92d14SAndroid Build Coastguard Worker     ClearAllBytes(messageInfo);
743*cfb92d14SAndroid Build Coastguard Worker     messageInfo.mPeerAddr = coapDestinationIp;
744*cfb92d14SAndroid Build Coastguard Worker     messageInfo.mPeerPort = OT_DEFAULT_COAP_PORT;
745*cfb92d14SAndroid Build Coastguard Worker 
746*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
747*cfb92d14SAndroid Build Coastguard Worker     if (aCoapObserve)
748*cfb92d14SAndroid Build Coastguard Worker     {
749*cfb92d14SAndroid Build Coastguard Worker         // Make a note of the message details for later so we can cancel it later.
750*cfb92d14SAndroid Build Coastguard Worker         memcpy(&mRequestAddr, &coapDestinationIp, sizeof(mRequestAddr));
751*cfb92d14SAndroid Build Coastguard Worker         mRequestTokenLength = otCoapMessageGetTokenLength(message);
752*cfb92d14SAndroid Build Coastguard Worker         memcpy(mRequestToken, otCoapMessageGetToken(message), mRequestTokenLength);
753*cfb92d14SAndroid Build Coastguard Worker         // Use `memcpy` instead of `strncpy` here because GCC will give warnings for `strncpy` when the dest's length is
754*cfb92d14SAndroid Build Coastguard Worker         // not bigger than the src's length.
755*cfb92d14SAndroid Build Coastguard Worker         memcpy(mRequestUri, coapUri, sizeof(mRequestUri) - 1);
756*cfb92d14SAndroid Build Coastguard Worker     }
757*cfb92d14SAndroid Build Coastguard Worker #endif
758*cfb92d14SAndroid Build Coastguard Worker 
759*cfb92d14SAndroid Build Coastguard Worker     if ((coapType == OT_COAP_TYPE_CONFIRMABLE) || (aCoapCode == OT_COAP_CODE_GET))
760*cfb92d14SAndroid Build Coastguard Worker     {
761*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
762*cfb92d14SAndroid Build Coastguard Worker         if (coapBlock)
763*cfb92d14SAndroid Build Coastguard Worker         {
764*cfb92d14SAndroid Build Coastguard Worker             if (aCoapCode == OT_COAP_CODE_PUT || aCoapCode == OT_COAP_CODE_POST)
765*cfb92d14SAndroid Build Coastguard Worker             {
766*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = otCoapMessageSetPayloadMarker(message));
767*cfb92d14SAndroid Build Coastguard Worker             }
768*cfb92d14SAndroid Build Coastguard Worker             error = otCoapSendRequestBlockWiseWithParameters(GetInstancePtr(), message, &messageInfo,
769*cfb92d14SAndroid Build Coastguard Worker                                                              &Coap::HandleResponse, this, GetRequestTxParameters(),
770*cfb92d14SAndroid Build Coastguard Worker                                                              Coap::BlockwiseTransmitHook, Coap::BlockwiseReceiveHook);
771*cfb92d14SAndroid Build Coastguard Worker         }
772*cfb92d14SAndroid Build Coastguard Worker         else
773*cfb92d14SAndroid Build Coastguard Worker         {
774*cfb92d14SAndroid Build Coastguard Worker #endif
775*cfb92d14SAndroid Build Coastguard Worker             error = otCoapSendRequestWithParameters(GetInstancePtr(), message, &messageInfo, &Coap::HandleResponse,
776*cfb92d14SAndroid Build Coastguard Worker                                                     this, GetRequestTxParameters());
777*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
778*cfb92d14SAndroid Build Coastguard Worker         }
779*cfb92d14SAndroid Build Coastguard Worker #endif
780*cfb92d14SAndroid Build Coastguard Worker     }
781*cfb92d14SAndroid Build Coastguard Worker     else
782*cfb92d14SAndroid Build Coastguard Worker     {
783*cfb92d14SAndroid Build Coastguard Worker         error = otCoapSendRequestWithParameters(GetInstancePtr(), message, &messageInfo, nullptr, nullptr,
784*cfb92d14SAndroid Build Coastguard Worker                                                 GetResponseTxParameters());
785*cfb92d14SAndroid Build Coastguard Worker     }
786*cfb92d14SAndroid Build Coastguard Worker 
787*cfb92d14SAndroid Build Coastguard Worker exit:
788*cfb92d14SAndroid Build Coastguard Worker 
789*cfb92d14SAndroid Build Coastguard Worker     if ((error != OT_ERROR_NONE) && (message != nullptr))
790*cfb92d14SAndroid Build Coastguard Worker     {
791*cfb92d14SAndroid Build Coastguard Worker         otMessageFree(message);
792*cfb92d14SAndroid Build Coastguard Worker     }
793*cfb92d14SAndroid Build Coastguard Worker 
794*cfb92d14SAndroid Build Coastguard Worker     return error;
795*cfb92d14SAndroid Build Coastguard Worker }
796*cfb92d14SAndroid Build Coastguard Worker 
Process(Arg aArgs[])797*cfb92d14SAndroid Build Coastguard Worker otError Coap::Process(Arg aArgs[])
798*cfb92d14SAndroid Build Coastguard Worker {
799*cfb92d14SAndroid Build Coastguard Worker #define CmdEntry(aCommandString)                            \
800*cfb92d14SAndroid Build Coastguard Worker     {                                                       \
801*cfb92d14SAndroid Build Coastguard Worker         aCommandString, &Coap::Process<Cmd(aCommandString)> \
802*cfb92d14SAndroid Build Coastguard Worker     }
803*cfb92d14SAndroid Build Coastguard Worker 
804*cfb92d14SAndroid Build Coastguard Worker     static constexpr Command kCommands[] = {
805*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
806*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("cancel"),
807*cfb92d14SAndroid Build Coastguard Worker #endif
808*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("delete"),
809*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("get"),
810*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
811*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("observe"),
812*cfb92d14SAndroid Build Coastguard Worker #endif
813*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("parameters"),
814*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("post"),
815*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("put"),
816*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("resource"),
817*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("set"),
818*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("start"),
819*cfb92d14SAndroid Build Coastguard Worker         CmdEntry("stop"),
820*cfb92d14SAndroid Build Coastguard Worker     };
821*cfb92d14SAndroid Build Coastguard Worker 
822*cfb92d14SAndroid Build Coastguard Worker #undef CmdEntry
823*cfb92d14SAndroid Build Coastguard Worker 
824*cfb92d14SAndroid Build Coastguard Worker     static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
825*cfb92d14SAndroid Build Coastguard Worker 
826*cfb92d14SAndroid Build Coastguard Worker     otError        error = OT_ERROR_INVALID_COMMAND;
827*cfb92d14SAndroid Build Coastguard Worker     const Command *command;
828*cfb92d14SAndroid Build Coastguard Worker 
829*cfb92d14SAndroid Build Coastguard Worker     if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
830*cfb92d14SAndroid Build Coastguard Worker     {
831*cfb92d14SAndroid Build Coastguard Worker         OutputCommandTable(kCommands);
832*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = aArgs[0].IsEmpty() ? OT_ERROR_INVALID_ARGS : OT_ERROR_NONE);
833*cfb92d14SAndroid Build Coastguard Worker     }
834*cfb92d14SAndroid Build Coastguard Worker 
835*cfb92d14SAndroid Build Coastguard Worker     command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
836*cfb92d14SAndroid Build Coastguard Worker     VerifyOrExit(command != nullptr);
837*cfb92d14SAndroid Build Coastguard Worker 
838*cfb92d14SAndroid Build Coastguard Worker     error = (this->*command->mHandler)(aArgs + 1);
839*cfb92d14SAndroid Build Coastguard Worker 
840*cfb92d14SAndroid Build Coastguard Worker exit:
841*cfb92d14SAndroid Build Coastguard Worker     return error;
842*cfb92d14SAndroid Build Coastguard Worker }
843*cfb92d14SAndroid Build Coastguard Worker 
HandleRequest(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo)844*cfb92d14SAndroid Build Coastguard Worker void Coap::HandleRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
845*cfb92d14SAndroid Build Coastguard Worker {
846*cfb92d14SAndroid Build Coastguard Worker     static_cast<Coap *>(aContext)->HandleRequest(aMessage, aMessageInfo);
847*cfb92d14SAndroid Build Coastguard Worker }
848*cfb92d14SAndroid Build Coastguard Worker 
HandleRequest(otMessage * aMessage,const otMessageInfo * aMessageInfo)849*cfb92d14SAndroid Build Coastguard Worker void Coap::HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo)
850*cfb92d14SAndroid Build Coastguard Worker {
851*cfb92d14SAndroid Build Coastguard Worker     otError    error           = OT_ERROR_NONE;
852*cfb92d14SAndroid Build Coastguard Worker     otMessage *responseMessage = nullptr;
853*cfb92d14SAndroid Build Coastguard Worker     otCoapCode responseCode    = OT_COAP_CODE_EMPTY;
854*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
855*cfb92d14SAndroid Build Coastguard Worker     uint64_t observe        = 0;
856*cfb92d14SAndroid Build Coastguard Worker     bool     observePresent = false;
857*cfb92d14SAndroid Build Coastguard Worker #endif
858*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
859*cfb92d14SAndroid Build Coastguard Worker     uint64_t blockValue   = 0;
860*cfb92d14SAndroid Build Coastguard Worker     bool     blockPresent = false;
861*cfb92d14SAndroid Build Coastguard Worker #endif
862*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE || OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
863*cfb92d14SAndroid Build Coastguard Worker     otCoapOptionIterator iterator;
864*cfb92d14SAndroid Build Coastguard Worker #endif
865*cfb92d14SAndroid Build Coastguard Worker 
866*cfb92d14SAndroid Build Coastguard Worker     OutputFormat("coap request from ");
867*cfb92d14SAndroid Build Coastguard Worker     OutputIp6Address(aMessageInfo->mPeerAddr);
868*cfb92d14SAndroid Build Coastguard Worker     OutputFormat(" ");
869*cfb92d14SAndroid Build Coastguard Worker 
870*cfb92d14SAndroid Build Coastguard Worker     switch (otCoapMessageGetCode(aMessage))
871*cfb92d14SAndroid Build Coastguard Worker     {
872*cfb92d14SAndroid Build Coastguard Worker     case OT_COAP_CODE_GET:
873*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("GET");
874*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE || OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
875*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(error = otCoapOptionIteratorInit(&iterator, aMessage));
876*cfb92d14SAndroid Build Coastguard Worker #endif
877*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
878*cfb92d14SAndroid Build Coastguard Worker         if (otCoapOptionIteratorGetFirstOptionMatching(&iterator, OT_COAP_OPTION_OBSERVE) != nullptr)
879*cfb92d14SAndroid Build Coastguard Worker         {
880*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapOptionIteratorGetOptionUintValue(&iterator, &observe));
881*cfb92d14SAndroid Build Coastguard Worker             observePresent = true;
882*cfb92d14SAndroid Build Coastguard Worker 
883*cfb92d14SAndroid Build Coastguard Worker             OutputFormat(" OBS=");
884*cfb92d14SAndroid Build Coastguard Worker             OutputUint64(observe);
885*cfb92d14SAndroid Build Coastguard Worker         }
886*cfb92d14SAndroid Build Coastguard Worker #endif
887*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
888*cfb92d14SAndroid Build Coastguard Worker         if (otCoapOptionIteratorGetFirstOptionMatching(&iterator, OT_COAP_OPTION_BLOCK2) != nullptr)
889*cfb92d14SAndroid Build Coastguard Worker         {
890*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapOptionIteratorGetOptionUintValue(&iterator, &blockValue));
891*cfb92d14SAndroid Build Coastguard Worker             blockPresent = true;
892*cfb92d14SAndroid Build Coastguard Worker         }
893*cfb92d14SAndroid Build Coastguard Worker #endif
894*cfb92d14SAndroid Build Coastguard Worker         break;
895*cfb92d14SAndroid Build Coastguard Worker 
896*cfb92d14SAndroid Build Coastguard Worker     case OT_COAP_CODE_DELETE:
897*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("DELETE");
898*cfb92d14SAndroid Build Coastguard Worker         break;
899*cfb92d14SAndroid Build Coastguard Worker 
900*cfb92d14SAndroid Build Coastguard Worker     case OT_COAP_CODE_PUT:
901*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("PUT");
902*cfb92d14SAndroid Build Coastguard Worker         break;
903*cfb92d14SAndroid Build Coastguard Worker 
904*cfb92d14SAndroid Build Coastguard Worker     case OT_COAP_CODE_POST:
905*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("POST");
906*cfb92d14SAndroid Build Coastguard Worker         break;
907*cfb92d14SAndroid Build Coastguard Worker 
908*cfb92d14SAndroid Build Coastguard Worker     default:
909*cfb92d14SAndroid Build Coastguard Worker         OutputLine("Undefined");
910*cfb92d14SAndroid Build Coastguard Worker         ExitNow(error = OT_ERROR_PARSE);
911*cfb92d14SAndroid Build Coastguard Worker     }
912*cfb92d14SAndroid Build Coastguard Worker 
913*cfb92d14SAndroid Build Coastguard Worker     PrintPayload(aMessage);
914*cfb92d14SAndroid Build Coastguard Worker 
915*cfb92d14SAndroid Build Coastguard Worker     if (otCoapMessageGetType(aMessage) == OT_COAP_TYPE_CONFIRMABLE ||
916*cfb92d14SAndroid Build Coastguard Worker         otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
917*cfb92d14SAndroid Build Coastguard Worker     {
918*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
919*cfb92d14SAndroid Build Coastguard Worker         if (observePresent && (mSubscriberTokenLength > 0) && (observe == 0))
920*cfb92d14SAndroid Build Coastguard Worker         {
921*cfb92d14SAndroid Build Coastguard Worker             // There is already a subscriber
922*cfb92d14SAndroid Build Coastguard Worker             responseCode = OT_COAP_CODE_SERVICE_UNAVAILABLE;
923*cfb92d14SAndroid Build Coastguard Worker         }
924*cfb92d14SAndroid Build Coastguard Worker         else
925*cfb92d14SAndroid Build Coastguard Worker #endif
926*cfb92d14SAndroid Build Coastguard Worker             if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
927*cfb92d14SAndroid Build Coastguard Worker         {
928*cfb92d14SAndroid Build Coastguard Worker             responseCode = OT_COAP_CODE_CONTENT;
929*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
930*cfb92d14SAndroid Build Coastguard Worker             if (observePresent)
931*cfb92d14SAndroid Build Coastguard Worker             {
932*cfb92d14SAndroid Build Coastguard Worker                 if (observe == 0)
933*cfb92d14SAndroid Build Coastguard Worker                 {
934*cfb92d14SAndroid Build Coastguard Worker                     // New subscriber
935*cfb92d14SAndroid Build Coastguard Worker                     OutputLine("Subscribing client");
936*cfb92d14SAndroid Build Coastguard Worker                     mSubscriberSock.mAddress = aMessageInfo->mPeerAddr;
937*cfb92d14SAndroid Build Coastguard Worker                     mSubscriberSock.mPort    = aMessageInfo->mPeerPort;
938*cfb92d14SAndroid Build Coastguard Worker                     mSubscriberTokenLength   = otCoapMessageGetTokenLength(aMessage);
939*cfb92d14SAndroid Build Coastguard Worker                     memcpy(mSubscriberToken, otCoapMessageGetToken(aMessage), mSubscriberTokenLength);
940*cfb92d14SAndroid Build Coastguard Worker 
941*cfb92d14SAndroid Build Coastguard Worker                     /*
942*cfb92d14SAndroid Build Coastguard Worker                      * Implementer note.
943*cfb92d14SAndroid Build Coastguard Worker                      *
944*cfb92d14SAndroid Build Coastguard Worker                      * Here, we try to match a confirmable GET request with confirmable
945*cfb92d14SAndroid Build Coastguard Worker                      * notifications, however this is not a requirement of RFC7641:
946*cfb92d14SAndroid Build Coastguard Worker                      * the server can send notifications of either type regardless of
947*cfb92d14SAndroid Build Coastguard Worker                      * what the client used to subscribe initially.
948*cfb92d14SAndroid Build Coastguard Worker                      */
949*cfb92d14SAndroid Build Coastguard Worker                     mSubscriberConfirmableNotifications = (otCoapMessageGetType(aMessage) == OT_COAP_TYPE_CONFIRMABLE);
950*cfb92d14SAndroid Build Coastguard Worker                 }
951*cfb92d14SAndroid Build Coastguard Worker                 else if (observe == 1)
952*cfb92d14SAndroid Build Coastguard Worker                 {
953*cfb92d14SAndroid Build Coastguard Worker                     // See if it matches our subscriber token
954*cfb92d14SAndroid Build Coastguard Worker                     if ((otCoapMessageGetTokenLength(aMessage) == mSubscriberTokenLength) &&
955*cfb92d14SAndroid Build Coastguard Worker                         (memcmp(otCoapMessageGetToken(aMessage), mSubscriberToken, mSubscriberTokenLength) == 0))
956*cfb92d14SAndroid Build Coastguard Worker                     {
957*cfb92d14SAndroid Build Coastguard Worker                         // Unsubscribe request
958*cfb92d14SAndroid Build Coastguard Worker                         CancelSubscriber();
959*cfb92d14SAndroid Build Coastguard Worker                     }
960*cfb92d14SAndroid Build Coastguard Worker                 }
961*cfb92d14SAndroid Build Coastguard Worker             }
962*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
963*cfb92d14SAndroid Build Coastguard Worker         }
964*cfb92d14SAndroid Build Coastguard Worker         else
965*cfb92d14SAndroid Build Coastguard Worker         {
966*cfb92d14SAndroid Build Coastguard Worker             responseCode = OT_COAP_CODE_CHANGED;
967*cfb92d14SAndroid Build Coastguard Worker         }
968*cfb92d14SAndroid Build Coastguard Worker 
969*cfb92d14SAndroid Build Coastguard Worker         responseMessage = otCoapNewMessage(GetInstancePtr(), nullptr);
970*cfb92d14SAndroid Build Coastguard Worker         VerifyOrExit(responseMessage != nullptr, error = OT_ERROR_NO_BUFS);
971*cfb92d14SAndroid Build Coastguard Worker 
972*cfb92d14SAndroid Build Coastguard Worker         SuccessOrExit(
973*cfb92d14SAndroid Build Coastguard Worker             error = otCoapMessageInitResponse(responseMessage, aMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode));
974*cfb92d14SAndroid Build Coastguard Worker 
975*cfb92d14SAndroid Build Coastguard Worker         if (responseCode == OT_COAP_CODE_CONTENT)
976*cfb92d14SAndroid Build Coastguard Worker         {
977*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
978*cfb92d14SAndroid Build Coastguard Worker             if (observePresent && (observe == 0))
979*cfb92d14SAndroid Build Coastguard Worker             {
980*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = otCoapMessageAppendObserveOption(responseMessage, mObserveSerial++));
981*cfb92d14SAndroid Build Coastguard Worker             }
982*cfb92d14SAndroid Build Coastguard Worker #endif
983*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
984*cfb92d14SAndroid Build Coastguard Worker             if (blockPresent)
985*cfb92d14SAndroid Build Coastguard Worker             {
986*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = otCoapMessageAppendBlock2Option(responseMessage,
987*cfb92d14SAndroid Build Coastguard Worker                                                                       static_cast<uint32_t>(blockValue >> 4), true,
988*cfb92d14SAndroid Build Coastguard Worker                                                                       static_cast<otCoapBlockSzx>(blockValue & 0x7)));
989*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = otCoapMessageSetPayloadMarker(responseMessage));
990*cfb92d14SAndroid Build Coastguard Worker             }
991*cfb92d14SAndroid Build Coastguard Worker             else
992*cfb92d14SAndroid Build Coastguard Worker             {
993*cfb92d14SAndroid Build Coastguard Worker #endif
994*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = otCoapMessageSetPayloadMarker(responseMessage));
995*cfb92d14SAndroid Build Coastguard Worker                 SuccessOrExit(error = otMessageAppend(responseMessage, mResourceContent,
996*cfb92d14SAndroid Build Coastguard Worker                                                       static_cast<uint16_t>(strlen(mResourceContent))));
997*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
998*cfb92d14SAndroid Build Coastguard Worker             }
999*cfb92d14SAndroid Build Coastguard Worker #endif
1000*cfb92d14SAndroid Build Coastguard Worker         }
1001*cfb92d14SAndroid Build Coastguard Worker 
1002*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
1003*cfb92d14SAndroid Build Coastguard Worker         if (blockPresent)
1004*cfb92d14SAndroid Build Coastguard Worker         {
1005*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapSendResponseBlockWiseWithParameters(GetInstancePtr(), responseMessage,
1006*cfb92d14SAndroid Build Coastguard Worker                                                                             aMessageInfo, GetResponseTxParameters(),
1007*cfb92d14SAndroid Build Coastguard Worker                                                                             this, mResource.mTransmitHook));
1008*cfb92d14SAndroid Build Coastguard Worker         }
1009*cfb92d14SAndroid Build Coastguard Worker         else
1010*cfb92d14SAndroid Build Coastguard Worker         {
1011*cfb92d14SAndroid Build Coastguard Worker #endif
1012*cfb92d14SAndroid Build Coastguard Worker             SuccessOrExit(error = otCoapSendResponseWithParameters(GetInstancePtr(), responseMessage, aMessageInfo,
1013*cfb92d14SAndroid Build Coastguard Worker                                                                    GetResponseTxParameters()));
1014*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
1015*cfb92d14SAndroid Build Coastguard Worker         }
1016*cfb92d14SAndroid Build Coastguard Worker #endif
1017*cfb92d14SAndroid Build Coastguard Worker     }
1018*cfb92d14SAndroid Build Coastguard Worker 
1019*cfb92d14SAndroid Build Coastguard Worker exit:
1020*cfb92d14SAndroid Build Coastguard Worker 
1021*cfb92d14SAndroid Build Coastguard Worker     if (error != OT_ERROR_NONE)
1022*cfb92d14SAndroid Build Coastguard Worker     {
1023*cfb92d14SAndroid Build Coastguard Worker         if (responseMessage != nullptr)
1024*cfb92d14SAndroid Build Coastguard Worker         {
1025*cfb92d14SAndroid Build Coastguard Worker             OutputLine("coap send response error %d: %s", error, otThreadErrorToString(error));
1026*cfb92d14SAndroid Build Coastguard Worker             otMessageFree(responseMessage);
1027*cfb92d14SAndroid Build Coastguard Worker         }
1028*cfb92d14SAndroid Build Coastguard Worker     }
1029*cfb92d14SAndroid Build Coastguard Worker     else if (responseCode >= OT_COAP_CODE_RESPONSE_MIN)
1030*cfb92d14SAndroid Build Coastguard Worker     {
1031*cfb92d14SAndroid Build Coastguard Worker         OutputLine("coap response sent");
1032*cfb92d14SAndroid Build Coastguard Worker     }
1033*cfb92d14SAndroid Build Coastguard Worker }
1034*cfb92d14SAndroid Build Coastguard Worker 
1035*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
HandleNotificationResponse(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo,otError aError)1036*cfb92d14SAndroid Build Coastguard Worker void Coap::HandleNotificationResponse(void                *aContext,
1037*cfb92d14SAndroid Build Coastguard Worker                                       otMessage           *aMessage,
1038*cfb92d14SAndroid Build Coastguard Worker                                       const otMessageInfo *aMessageInfo,
1039*cfb92d14SAndroid Build Coastguard Worker                                       otError              aError)
1040*cfb92d14SAndroid Build Coastguard Worker {
1041*cfb92d14SAndroid Build Coastguard Worker     static_cast<Coap *>(aContext)->HandleNotificationResponse(aMessage, aMessageInfo, aError);
1042*cfb92d14SAndroid Build Coastguard Worker }
1043*cfb92d14SAndroid Build Coastguard Worker 
HandleNotificationResponse(otMessage * aMessage,const otMessageInfo * aMessageInfo,otError aError)1044*cfb92d14SAndroid Build Coastguard Worker void Coap::HandleNotificationResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
1045*cfb92d14SAndroid Build Coastguard Worker {
1046*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aMessage);
1047*cfb92d14SAndroid Build Coastguard Worker 
1048*cfb92d14SAndroid Build Coastguard Worker     switch (aError)
1049*cfb92d14SAndroid Build Coastguard Worker     {
1050*cfb92d14SAndroid Build Coastguard Worker     case OT_ERROR_NONE:
1051*cfb92d14SAndroid Build Coastguard Worker         if (aMessageInfo != nullptr)
1052*cfb92d14SAndroid Build Coastguard Worker         {
1053*cfb92d14SAndroid Build Coastguard Worker             OutputFormat("Received ACK in reply to notification from ");
1054*cfb92d14SAndroid Build Coastguard Worker             OutputIp6AddressLine(aMessageInfo->mPeerAddr);
1055*cfb92d14SAndroid Build Coastguard Worker         }
1056*cfb92d14SAndroid Build Coastguard Worker         break;
1057*cfb92d14SAndroid Build Coastguard Worker 
1058*cfb92d14SAndroid Build Coastguard Worker     default:
1059*cfb92d14SAndroid Build Coastguard Worker         OutputLine("coap receive notification response error %d: %s", aError, otThreadErrorToString(aError));
1060*cfb92d14SAndroid Build Coastguard Worker         CancelSubscriber();
1061*cfb92d14SAndroid Build Coastguard Worker         break;
1062*cfb92d14SAndroid Build Coastguard Worker     }
1063*cfb92d14SAndroid Build Coastguard Worker }
1064*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
1065*cfb92d14SAndroid Build Coastguard Worker 
HandleResponse(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo,otError aError)1066*cfb92d14SAndroid Build Coastguard Worker void Coap::HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
1067*cfb92d14SAndroid Build Coastguard Worker {
1068*cfb92d14SAndroid Build Coastguard Worker     static_cast<Coap *>(aContext)->HandleResponse(aMessage, aMessageInfo, aError);
1069*cfb92d14SAndroid Build Coastguard Worker }
1070*cfb92d14SAndroid Build Coastguard Worker 
HandleResponse(otMessage * aMessage,const otMessageInfo * aMessageInfo,otError aError)1071*cfb92d14SAndroid Build Coastguard Worker void Coap::HandleResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
1072*cfb92d14SAndroid Build Coastguard Worker {
1073*cfb92d14SAndroid Build Coastguard Worker     if (aError != OT_ERROR_NONE)
1074*cfb92d14SAndroid Build Coastguard Worker     {
1075*cfb92d14SAndroid Build Coastguard Worker         OutputLine("coap receive response error %d: %s", aError, otThreadErrorToString(aError));
1076*cfb92d14SAndroid Build Coastguard Worker     }
1077*cfb92d14SAndroid Build Coastguard Worker     else if ((aMessageInfo != nullptr) && (aMessage != nullptr))
1078*cfb92d14SAndroid Build Coastguard Worker     {
1079*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
1080*cfb92d14SAndroid Build Coastguard Worker         otCoapOptionIterator iterator;
1081*cfb92d14SAndroid Build Coastguard Worker #endif
1082*cfb92d14SAndroid Build Coastguard Worker 
1083*cfb92d14SAndroid Build Coastguard Worker         OutputFormat("coap response from ");
1084*cfb92d14SAndroid Build Coastguard Worker         OutputIp6Address(aMessageInfo->mPeerAddr);
1085*cfb92d14SAndroid Build Coastguard Worker 
1086*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
1087*cfb92d14SAndroid Build Coastguard Worker         if (otCoapOptionIteratorInit(&iterator, aMessage) == OT_ERROR_NONE)
1088*cfb92d14SAndroid Build Coastguard Worker         {
1089*cfb92d14SAndroid Build Coastguard Worker             const otCoapOption *observeOpt =
1090*cfb92d14SAndroid Build Coastguard Worker                 otCoapOptionIteratorGetFirstOptionMatching(&iterator, OT_COAP_OPTION_OBSERVE);
1091*cfb92d14SAndroid Build Coastguard Worker 
1092*cfb92d14SAndroid Build Coastguard Worker             if (observeOpt != nullptr)
1093*cfb92d14SAndroid Build Coastguard Worker             {
1094*cfb92d14SAndroid Build Coastguard Worker                 uint64_t observeVal = 0;
1095*cfb92d14SAndroid Build Coastguard Worker                 otError  error      = otCoapOptionIteratorGetOptionUintValue(&iterator, &observeVal);
1096*cfb92d14SAndroid Build Coastguard Worker 
1097*cfb92d14SAndroid Build Coastguard Worker                 if (error == OT_ERROR_NONE)
1098*cfb92d14SAndroid Build Coastguard Worker                 {
1099*cfb92d14SAndroid Build Coastguard Worker                     OutputFormat(" OBS=");
1100*cfb92d14SAndroid Build Coastguard Worker                     OutputUint64(observeVal);
1101*cfb92d14SAndroid Build Coastguard Worker                 }
1102*cfb92d14SAndroid Build Coastguard Worker             }
1103*cfb92d14SAndroid Build Coastguard Worker         }
1104*cfb92d14SAndroid Build Coastguard Worker #endif
1105*cfb92d14SAndroid Build Coastguard Worker         PrintPayload(aMessage);
1106*cfb92d14SAndroid Build Coastguard Worker     }
1107*cfb92d14SAndroid Build Coastguard Worker }
1108*cfb92d14SAndroid Build Coastguard Worker 
1109*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
BlockwiseReceiveHook(void * aContext,const uint8_t * aBlock,uint32_t aPosition,uint16_t aBlockLength,bool aMore,uint32_t aTotalLength)1110*cfb92d14SAndroid Build Coastguard Worker otError Coap::BlockwiseReceiveHook(void          *aContext,
1111*cfb92d14SAndroid Build Coastguard Worker                                    const uint8_t *aBlock,
1112*cfb92d14SAndroid Build Coastguard Worker                                    uint32_t       aPosition,
1113*cfb92d14SAndroid Build Coastguard Worker                                    uint16_t       aBlockLength,
1114*cfb92d14SAndroid Build Coastguard Worker                                    bool           aMore,
1115*cfb92d14SAndroid Build Coastguard Worker                                    uint32_t       aTotalLength)
1116*cfb92d14SAndroid Build Coastguard Worker {
1117*cfb92d14SAndroid Build Coastguard Worker     return static_cast<Coap *>(aContext)->BlockwiseReceiveHook(aBlock, aPosition, aBlockLength, aMore, aTotalLength);
1118*cfb92d14SAndroid Build Coastguard Worker }
1119*cfb92d14SAndroid Build Coastguard Worker 
BlockwiseReceiveHook(const uint8_t * aBlock,uint32_t aPosition,uint16_t aBlockLength,bool aMore,uint32_t aTotalLength)1120*cfb92d14SAndroid Build Coastguard Worker otError Coap::BlockwiseReceiveHook(const uint8_t *aBlock,
1121*cfb92d14SAndroid Build Coastguard Worker                                    uint32_t       aPosition,
1122*cfb92d14SAndroid Build Coastguard Worker                                    uint16_t       aBlockLength,
1123*cfb92d14SAndroid Build Coastguard Worker                                    bool           aMore,
1124*cfb92d14SAndroid Build Coastguard Worker                                    uint32_t       aTotalLength)
1125*cfb92d14SAndroid Build Coastguard Worker {
1126*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aMore);
1127*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aTotalLength);
1128*cfb92d14SAndroid Build Coastguard Worker 
1129*cfb92d14SAndroid Build Coastguard Worker     OutputLine("received block: Num %i Len %i", aPosition / aBlockLength, aBlockLength);
1130*cfb92d14SAndroid Build Coastguard Worker 
1131*cfb92d14SAndroid Build Coastguard Worker     for (uint16_t i = 0; i < aBlockLength / 16; i++)
1132*cfb92d14SAndroid Build Coastguard Worker     {
1133*cfb92d14SAndroid Build Coastguard Worker         OutputBytesLine(&aBlock[i * 16], 16);
1134*cfb92d14SAndroid Build Coastguard Worker     }
1135*cfb92d14SAndroid Build Coastguard Worker 
1136*cfb92d14SAndroid Build Coastguard Worker     return OT_ERROR_NONE;
1137*cfb92d14SAndroid Build Coastguard Worker }
1138*cfb92d14SAndroid Build Coastguard Worker 
BlockwiseTransmitHook(void * aContext,uint8_t * aBlock,uint32_t aPosition,uint16_t * aBlockLength,bool * aMore)1139*cfb92d14SAndroid Build Coastguard Worker otError Coap::BlockwiseTransmitHook(void     *aContext,
1140*cfb92d14SAndroid Build Coastguard Worker                                     uint8_t  *aBlock,
1141*cfb92d14SAndroid Build Coastguard Worker                                     uint32_t  aPosition,
1142*cfb92d14SAndroid Build Coastguard Worker                                     uint16_t *aBlockLength,
1143*cfb92d14SAndroid Build Coastguard Worker                                     bool     *aMore)
1144*cfb92d14SAndroid Build Coastguard Worker {
1145*cfb92d14SAndroid Build Coastguard Worker     return static_cast<Coap *>(aContext)->BlockwiseTransmitHook(aBlock, aPosition, aBlockLength, aMore);
1146*cfb92d14SAndroid Build Coastguard Worker }
1147*cfb92d14SAndroid Build Coastguard Worker 
BlockwiseTransmitHook(uint8_t * aBlock,uint32_t aPosition,uint16_t * aBlockLength,bool * aMore)1148*cfb92d14SAndroid Build Coastguard Worker otError Coap::BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore)
1149*cfb92d14SAndroid Build Coastguard Worker {
1150*cfb92d14SAndroid Build Coastguard Worker     static uint32_t blockCount = 0;
1151*cfb92d14SAndroid Build Coastguard Worker     OT_UNUSED_VARIABLE(aPosition);
1152*cfb92d14SAndroid Build Coastguard Worker 
1153*cfb92d14SAndroid Build Coastguard Worker     // Send a random payload
1154*cfb92d14SAndroid Build Coastguard Worker     otRandomNonCryptoFillBuffer(aBlock, *aBlockLength);
1155*cfb92d14SAndroid Build Coastguard Worker 
1156*cfb92d14SAndroid Build Coastguard Worker     OutputLine("send block: Num %i Len %i", blockCount, *aBlockLength);
1157*cfb92d14SAndroid Build Coastguard Worker 
1158*cfb92d14SAndroid Build Coastguard Worker     for (uint16_t i = 0; i < *aBlockLength / 16; i++)
1159*cfb92d14SAndroid Build Coastguard Worker     {
1160*cfb92d14SAndroid Build Coastguard Worker         OutputBytesLine(&aBlock[i * 16], 16);
1161*cfb92d14SAndroid Build Coastguard Worker     }
1162*cfb92d14SAndroid Build Coastguard Worker 
1163*cfb92d14SAndroid Build Coastguard Worker     if (blockCount == mBlockCount - 1)
1164*cfb92d14SAndroid Build Coastguard Worker     {
1165*cfb92d14SAndroid Build Coastguard Worker         blockCount = 0;
1166*cfb92d14SAndroid Build Coastguard Worker         *aMore     = false;
1167*cfb92d14SAndroid Build Coastguard Worker     }
1168*cfb92d14SAndroid Build Coastguard Worker     else
1169*cfb92d14SAndroid Build Coastguard Worker     {
1170*cfb92d14SAndroid Build Coastguard Worker         *aMore = true;
1171*cfb92d14SAndroid Build Coastguard Worker         blockCount++;
1172*cfb92d14SAndroid Build Coastguard Worker     }
1173*cfb92d14SAndroid Build Coastguard Worker 
1174*cfb92d14SAndroid Build Coastguard Worker     return OT_ERROR_NONE;
1175*cfb92d14SAndroid Build Coastguard Worker }
1176*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
1177*cfb92d14SAndroid Build Coastguard Worker 
1178*cfb92d14SAndroid Build Coastguard Worker } // namespace Cli
1179*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
1180*cfb92d14SAndroid Build Coastguard Worker 
1181*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
1182