1 /*
2  *  Copyright (c) 2017, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file contains definitions for a simple CLI CoAP server and client.
32  */
33 
34 #ifndef CLI_COAP_HPP_
35 #define CLI_COAP_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
40 
41 #include <openthread/coap.h>
42 
43 #include "utils/lookup_table.hpp"
44 #include "utils/parse_cmdline.hpp"
45 
46 namespace ot {
47 namespace Cli {
48 
49 class Interpreter;
50 
51 /**
52  * This class implements the CLI CoAP server and client.
53  *
54  */
55 class Coap
56 {
57 public:
58     typedef Utils::CmdLineParser::Arg Arg;
59 
60     /**
61      * Constructor
62      *
63      * @param[in]  aInterpreter  The CLI interpreter.
64      *
65      */
66     explicit Coap(Interpreter &aInterpreter);
67 
68     /**
69      * This method interprets a list of CLI arguments.
70      *
71      * @param[in]  aArgs        An array of command line arguments.
72      *
73      */
74     otError Process(Arg aArgs[]);
75 
76 private:
77     enum
78     {
79         kMaxUriLength  = 32,
80         kMaxBufferSize = 16
81     };
82 
83     struct Command
84     {
85         const char *mName;
86         otError (Coap::*mHandler)(Arg aArgs[]);
87     };
88 
89 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
90     enum BlockType : uint8_t
91     {
92         kBlockType1,
93         kBlockType2,
94     };
95 #endif
96 
97 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
98     otError CancelResourceSubscription(void);
99     void    CancelSubscriber(void);
100 #endif
101 
102     void PrintPayload(otMessage *aMessage) const;
103 
104     otError ProcessHelp(Arg aArgs[]);
105 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
106     otError ProcessCancel(Arg aArgs[]);
107 #endif
108     otError ProcessDelete(Arg aArgs[]);
109     otError ProcessGet(Arg aArgs[]);
110 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
111     otError ProcessObserve(Arg aArgs[]);
112 #endif
113     otError ProcessParameters(Arg aArgs[]);
114     otError ProcessPost(Arg aArgs[]);
115     otError ProcessPut(Arg aArgs[]);
116     otError ProcessResource(Arg aArgs[]);
117     otError ProcessSet(Arg aArgs[]);
118     otError ProcessStart(Arg aArgs[]);
119     otError ProcessStop(Arg aArgs[]);
120 
121 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
122     otError ProcessRequest(Arg aArgs[], otCoapCode aCoapCode, bool aCoapObserve = false);
123 #else
124     otError        ProcessRequest(Arg aArgs[], otCoapCode aCoapCode);
125 #endif
126 
127     static void HandleRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
128     void        HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo);
129 
130 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
131     static void HandleNotificationResponse(void *               aContext,
132                                            otMessage *          aMessage,
133                                            const otMessageInfo *aMessageInfo,
134                                            otError              aError);
135     void        HandleNotificationResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
136 #endif
137 
138     static void HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
139     void        HandleResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
140 
141 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
142 
143     static otError BlockwiseReceiveHook(void *         aContext,
144                                         const uint8_t *aBlock,
145                                         uint32_t       aPosition,
146                                         uint16_t       aBlockLength,
147                                         bool           aMore,
148                                         uint32_t       aTotalLength);
149     otError        BlockwiseReceiveHook(const uint8_t *aBlock,
150                                         uint32_t       aPosition,
151                                         uint16_t       aBlockLength,
152                                         bool           aMore,
153                                         uint32_t       aTotalLength);
154     static otError BlockwiseTransmitHook(void *    aContext,
155                                          uint8_t * aBlock,
156                                          uint32_t  aPosition,
157                                          uint16_t *aBlockLength,
158                                          bool *    aMore);
159     otError        BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore);
160 #endif
161 
GetRequestTxParameters(void) const162     const otCoapTxParameters *GetRequestTxParameters(void) const
163     {
164         return mUseDefaultRequestTxParameters ? nullptr : &mRequestTxParameters;
165     }
166 
GetResponseTxParameters(void) const167     const otCoapTxParameters *GetResponseTxParameters(void) const
168     {
169         return mUseDefaultResponseTxParameters ? nullptr : &mResponseTxParameters;
170     }
171 
172     static constexpr Command sCommands[] = {
173 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
174         {"cancel", &Coap::ProcessCancel},
175 #endif
176         {"delete", &Coap::ProcessDelete},
177         {"get", &Coap::ProcessGet},
178         {"help", &Coap::ProcessHelp},
179 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
180         {"observe", &Coap::ProcessObserve},
181 #endif
182         {"parameters", &Coap::ProcessParameters},
183         {"post", &Coap::ProcessPost},
184         {"put", &Coap::ProcessPut},
185         {"resource", &Coap::ProcessResource},
186         {"set", &Coap::ProcessSet},
187         {"start", &Coap::ProcessStart},
188         {"stop", &Coap::ProcessStop},
189     };
190 
191     static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
192 
193     Interpreter &mInterpreter;
194 
195     bool mUseDefaultRequestTxParameters;
196     bool mUseDefaultResponseTxParameters;
197 
198     otCoapTxParameters mRequestTxParameters;
199     otCoapTxParameters mResponseTxParameters;
200 
201 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
202     otCoapBlockwiseResource mResource;
203 #else
204     otCoapResource mResource;
205 #endif
206 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
207     otIp6Address mRequestAddr;
208     otSockAddr   mSubscriberSock;
209     char         mRequestUri[kMaxUriLength];
210     uint8_t      mRequestToken[OT_COAP_MAX_TOKEN_LENGTH];
211     uint8_t      mSubscriberToken[OT_COAP_MAX_TOKEN_LENGTH];
212 #endif
213     char mUriPath[kMaxUriLength];
214     char mResourceContent[kMaxBufferSize];
215 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
216     uint32_t mObserveSerial;
217     uint8_t  mRequestTokenLength;
218     uint8_t  mSubscriberTokenLength;
219     bool     mSubscriberConfirmableNotifications;
220 #endif
221 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
222     uint32_t mBlockCount;
223 #endif
224 };
225 
226 } // namespace Cli
227 } // namespace ot
228 
229 #endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
230 
231 #endif // CLI_COAP_HPP_
232