1 /*
2  *  Copyright (c) 2016, 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 implements the OpenThread CoAP API.
32  */
33 
34 #include "openthread-core-config.h"
35 
36 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
37 
38 #include <openthread/coap.h>
39 
40 #include "coap/coap_message.hpp"
41 #include "common/instance.hpp"
42 #include "common/locator_getters.hpp"
43 
44 using namespace ot;
45 
otCoapNewMessage(otInstance * aInstance,const otMessageSettings * aSettings)46 otMessage *otCoapNewMessage(otInstance *aInstance, const otMessageSettings *aSettings)
47 {
48     Instance &instance = *static_cast<Instance *>(aInstance);
49 
50     return instance.GetApplicationCoap().NewMessage(Message::Settings(aSettings));
51 }
52 
otCoapMessageInit(otMessage * aMessage,otCoapType aType,otCoapCode aCode)53 void otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode)
54 {
55     static_cast<Coap::Message *>(aMessage)->Init(static_cast<Coap::Type>(aType), static_cast<Coap::Code>(aCode));
56 }
57 
otCoapMessageInitResponse(otMessage * aResponse,const otMessage * aRequest,otCoapType aType,otCoapCode aCode)58 otError otCoapMessageInitResponse(otMessage *aResponse, const otMessage *aRequest, otCoapType aType, otCoapCode aCode)
59 {
60     Coap::Message &      response = *static_cast<Coap::Message *>(aResponse);
61     const Coap::Message &request  = *static_cast<const Coap::Message *>(aRequest);
62 
63     response.Init(static_cast<Coap::Type>(aType), static_cast<Coap::Code>(aCode));
64     response.SetMessageId(request.GetMessageId());
65 
66     return response.SetTokenFromMessage(request);
67 }
68 
otCoapMessageSetToken(otMessage * aMessage,const uint8_t * aToken,uint8_t aTokenLength)69 otError otCoapMessageSetToken(otMessage *aMessage, const uint8_t *aToken, uint8_t aTokenLength)
70 {
71     return static_cast<Coap::Message *>(aMessage)->SetToken(aToken, aTokenLength);
72 }
73 
otCoapMessageGenerateToken(otMessage * aMessage,uint8_t aTokenLength)74 void otCoapMessageGenerateToken(otMessage *aMessage, uint8_t aTokenLength)
75 {
76     IgnoreError(static_cast<Coap::Message *>(aMessage)->GenerateRandomToken(aTokenLength));
77 }
78 
otCoapMessageAppendContentFormatOption(otMessage * aMessage,otCoapOptionContentFormat aContentFormat)79 otError otCoapMessageAppendContentFormatOption(otMessage *aMessage, otCoapOptionContentFormat aContentFormat)
80 {
81     return static_cast<Coap::Message *>(aMessage)->AppendContentFormatOption(aContentFormat);
82 }
83 
otCoapMessageAppendOption(otMessage * aMessage,uint16_t aNumber,uint16_t aLength,const void * aValue)84 otError otCoapMessageAppendOption(otMessage *aMessage, uint16_t aNumber, uint16_t aLength, const void *aValue)
85 {
86     return static_cast<Coap::Message *>(aMessage)->AppendOption(aNumber, aLength, aValue);
87 }
88 
otCoapMessageAppendUintOption(otMessage * aMessage,uint16_t aNumber,uint32_t aValue)89 otError otCoapMessageAppendUintOption(otMessage *aMessage, uint16_t aNumber, uint32_t aValue)
90 {
91     return static_cast<Coap::Message *>(aMessage)->AppendUintOption(aNumber, aValue);
92 }
93 
otCoapMessageAppendObserveOption(otMessage * aMessage,uint32_t aObserve)94 otError otCoapMessageAppendObserveOption(otMessage *aMessage, uint32_t aObserve)
95 {
96     return static_cast<Coap::Message *>(aMessage)->AppendObserveOption(aObserve);
97 }
98 
otCoapMessageAppendUriPathOptions(otMessage * aMessage,const char * aUriPath)99 otError otCoapMessageAppendUriPathOptions(otMessage *aMessage, const char *aUriPath)
100 {
101     return static_cast<Coap::Message *>(aMessage)->AppendUriPathOptions(aUriPath);
102 }
103 
otCoapBlockSizeFromExponent(otCoapBlockSzx aSize)104 uint16_t otCoapBlockSizeFromExponent(otCoapBlockSzx aSize)
105 {
106     return static_cast<uint16_t>(1 << (static_cast<uint8_t>(aSize) + Coap::Message::kBlockSzxBase));
107 }
108 
otCoapMessageAppendBlock2Option(otMessage * aMessage,uint32_t aNum,bool aMore,otCoapBlockSzx aSize)109 otError otCoapMessageAppendBlock2Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize)
110 {
111     return static_cast<Coap::Message *>(aMessage)->AppendBlockOption(Coap::Message::kBlockType2, aNum, aMore, aSize);
112 }
113 
otCoapMessageAppendBlock1Option(otMessage * aMessage,uint32_t aNum,bool aMore,otCoapBlockSzx aSize)114 otError otCoapMessageAppendBlock1Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize)
115 {
116     return static_cast<Coap::Message *>(aMessage)->AppendBlockOption(Coap::Message::kBlockType1, aNum, aMore, aSize);
117 }
118 
otCoapMessageAppendProxyUriOption(otMessage * aMessage,const char * aUriPath)119 otError otCoapMessageAppendProxyUriOption(otMessage *aMessage, const char *aUriPath)
120 {
121     return static_cast<Coap::Message *>(aMessage)->AppendProxyUriOption(aUriPath);
122 }
123 
otCoapMessageAppendMaxAgeOption(otMessage * aMessage,uint32_t aMaxAge)124 otError otCoapMessageAppendMaxAgeOption(otMessage *aMessage, uint32_t aMaxAge)
125 {
126     return static_cast<Coap::Message *>(aMessage)->AppendMaxAgeOption(aMaxAge);
127 }
128 
otCoapMessageAppendUriQueryOption(otMessage * aMessage,const char * aUriQuery)129 otError otCoapMessageAppendUriQueryOption(otMessage *aMessage, const char *aUriQuery)
130 {
131     return static_cast<Coap::Message *>(aMessage)->AppendUriQueryOption(aUriQuery);
132 }
133 
otCoapMessageSetPayloadMarker(otMessage * aMessage)134 otError otCoapMessageSetPayloadMarker(otMessage *aMessage)
135 {
136     return static_cast<Coap::Message *>(aMessage)->SetPayloadMarker();
137 }
138 
otCoapMessageGetType(const otMessage * aMessage)139 otCoapType otCoapMessageGetType(const otMessage *aMessage)
140 {
141     return static_cast<otCoapType>(static_cast<const Coap::Message *>(aMessage)->GetType());
142 }
143 
otCoapMessageGetCode(const otMessage * aMessage)144 otCoapCode otCoapMessageGetCode(const otMessage *aMessage)
145 {
146     return static_cast<otCoapCode>(static_cast<const Coap::Message *>(aMessage)->GetCode());
147 }
148 
otCoapMessageCodeToString(const otMessage * aMessage)149 const char *otCoapMessageCodeToString(const otMessage *aMessage)
150 {
151     return static_cast<const Coap::Message *>(aMessage)->CodeToString();
152 }
153 
otCoapMessageGetMessageId(const otMessage * aMessage)154 uint16_t otCoapMessageGetMessageId(const otMessage *aMessage)
155 {
156     return static_cast<const Coap::Message *>(aMessage)->GetMessageId();
157 }
158 
otCoapMessageGetTokenLength(const otMessage * aMessage)159 uint8_t otCoapMessageGetTokenLength(const otMessage *aMessage)
160 {
161     return static_cast<const Coap::Message *>(aMessage)->GetTokenLength();
162 }
163 
otCoapMessageGetToken(const otMessage * aMessage)164 const uint8_t *otCoapMessageGetToken(const otMessage *aMessage)
165 {
166     return static_cast<const Coap::Message *>(aMessage)->GetToken();
167 }
168 
otCoapOptionIteratorInit(otCoapOptionIterator * aIterator,const otMessage * aMessage)169 otError otCoapOptionIteratorInit(otCoapOptionIterator *aIterator, const otMessage *aMessage)
170 {
171     return static_cast<Coap::Option::Iterator *>(aIterator)->Init(*static_cast<const Coap::Message *>(aMessage));
172 }
173 
otCoapOptionIteratorGetFirstOptionMatching(otCoapOptionIterator * aIterator,uint16_t aOption)174 const otCoapOption *otCoapOptionIteratorGetFirstOptionMatching(otCoapOptionIterator *aIterator, uint16_t aOption)
175 {
176     Coap::Option::Iterator &iterator = *static_cast<Coap::Option::Iterator *>(aIterator);
177 
178     IgnoreError(iterator.Init(iterator.GetMessage(), aOption));
179     return iterator.GetOption();
180 }
181 
otCoapOptionIteratorGetFirstOption(otCoapOptionIterator * aIterator)182 const otCoapOption *otCoapOptionIteratorGetFirstOption(otCoapOptionIterator *aIterator)
183 {
184     Coap::Option::Iterator &iterator = *static_cast<Coap::Option::Iterator *>(aIterator);
185 
186     IgnoreError(iterator.Init(iterator.GetMessage()));
187     return iterator.GetOption();
188 }
189 
otCoapOptionIteratorGetNextOptionMatching(otCoapOptionIterator * aIterator,uint16_t aOption)190 const otCoapOption *otCoapOptionIteratorGetNextOptionMatching(otCoapOptionIterator *aIterator, uint16_t aOption)
191 {
192     Coap::Option::Iterator &iterator = *static_cast<Coap::Option::Iterator *>(aIterator);
193 
194     IgnoreError(iterator.Advance(aOption));
195     return iterator.GetOption();
196 }
197 
otCoapOptionIteratorGetNextOption(otCoapOptionIterator * aIterator)198 const otCoapOption *otCoapOptionIteratorGetNextOption(otCoapOptionIterator *aIterator)
199 {
200     Coap::Option::Iterator &iterator = *static_cast<Coap::Option::Iterator *>(aIterator);
201 
202     IgnoreError(iterator.Advance());
203     return iterator.GetOption();
204 }
205 
otCoapOptionIteratorGetOptionUintValue(otCoapOptionIterator * aIterator,uint64_t * aValue)206 otError otCoapOptionIteratorGetOptionUintValue(otCoapOptionIterator *aIterator, uint64_t *aValue)
207 {
208     return static_cast<Coap::Option::Iterator *>(aIterator)->ReadOptionValue(*aValue);
209 }
210 
otCoapOptionIteratorGetOptionValue(otCoapOptionIterator * aIterator,void * aValue)211 otError otCoapOptionIteratorGetOptionValue(otCoapOptionIterator *aIterator, void *aValue)
212 {
213     return static_cast<Coap::Option::Iterator *>(aIterator)->ReadOptionValue(aValue);
214 }
215 
216 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
otCoapSendRequestBlockWiseWithParameters(otInstance * aInstance,otMessage * aMessage,const otMessageInfo * aMessageInfo,otCoapResponseHandler aHandler,void * aContext,const otCoapTxParameters * aTxParameters,otCoapBlockwiseTransmitHook aTransmitHook,otCoapBlockwiseReceiveHook aReceiveHook)217 otError otCoapSendRequestBlockWiseWithParameters(otInstance *                aInstance,
218                                                  otMessage *                 aMessage,
219                                                  const otMessageInfo *       aMessageInfo,
220                                                  otCoapResponseHandler       aHandler,
221                                                  void *                      aContext,
222                                                  const otCoapTxParameters *  aTxParameters,
223                                                  otCoapBlockwiseTransmitHook aTransmitHook,
224                                                  otCoapBlockwiseReceiveHook  aReceiveHook)
225 {
226     Error                     error;
227     Instance &                instance     = *static_cast<Instance *>(aInstance);
228     const Coap::TxParameters &txParameters = Coap::TxParameters::From(aTxParameters);
229 
230     if (aTxParameters != nullptr)
231     {
232         VerifyOrExit(txParameters.IsValid(), error = kErrorInvalidArgs);
233     }
234 
235     error = instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
236                                                       *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
237                                                       txParameters, aHandler, aContext, aTransmitHook, aReceiveHook);
238 
239 exit:
240     return error;
241 }
242 #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
243 
otCoapSendRequestWithParameters(otInstance * aInstance,otMessage * aMessage,const otMessageInfo * aMessageInfo,otCoapResponseHandler aHandler,void * aContext,const otCoapTxParameters * aTxParameters)244 otError otCoapSendRequestWithParameters(otInstance *              aInstance,
245                                         otMessage *               aMessage,
246                                         const otMessageInfo *     aMessageInfo,
247                                         otCoapResponseHandler     aHandler,
248                                         void *                    aContext,
249                                         const otCoapTxParameters *aTxParameters)
250 {
251     Error                     error;
252     Instance &                instance     = *static_cast<Instance *>(aInstance);
253     const Coap::TxParameters &txParameters = Coap::TxParameters::From(aTxParameters);
254 
255     if (aTxParameters != nullptr)
256     {
257         VerifyOrExit(txParameters.IsValid(), error = kErrorInvalidArgs);
258     }
259 
260     error = instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
261                                                       *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
262                                                       txParameters, aHandler, aContext);
263 
264 exit:
265     return error;
266 }
267 
otCoapStart(otInstance * aInstance,uint16_t aPort)268 otError otCoapStart(otInstance *aInstance, uint16_t aPort)
269 {
270     Instance &instance = *static_cast<Instance *>(aInstance);
271 
272     return instance.GetApplicationCoap().Start(aPort);
273 }
274 
otCoapStop(otInstance * aInstance)275 otError otCoapStop(otInstance *aInstance)
276 {
277     Instance &instance = *static_cast<Instance *>(aInstance);
278 
279     return instance.GetApplicationCoap().Stop();
280 }
281 
282 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
otCoapAddBlockWiseResource(otInstance * aInstance,otCoapBlockwiseResource * aResource)283 void otCoapAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource)
284 {
285     Instance &instance = *static_cast<Instance *>(aInstance);
286 
287     instance.GetApplicationCoap().AddBlockWiseResource(*static_cast<Coap::ResourceBlockWise *>(aResource));
288 }
289 
otCoapRemoveBlockWiseResource(otInstance * aInstance,otCoapBlockwiseResource * aResource)290 void otCoapRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource)
291 {
292     Instance &instance = *static_cast<Instance *>(aInstance);
293 
294     instance.GetApplicationCoap().RemoveBlockWiseResource(*static_cast<Coap::ResourceBlockWise *>(aResource));
295 }
296 #endif
297 
otCoapAddResource(otInstance * aInstance,otCoapResource * aResource)298 void otCoapAddResource(otInstance *aInstance, otCoapResource *aResource)
299 {
300     Instance &instance = *static_cast<Instance *>(aInstance);
301 
302     instance.GetApplicationCoap().AddResource(*static_cast<Coap::Resource *>(aResource));
303 }
304 
otCoapRemoveResource(otInstance * aInstance,otCoapResource * aResource)305 void otCoapRemoveResource(otInstance *aInstance, otCoapResource *aResource)
306 {
307     Instance &instance = *static_cast<Instance *>(aInstance);
308 
309     instance.GetApplicationCoap().RemoveResource(*static_cast<Coap::Resource *>(aResource));
310 }
311 
otCoapSetDefaultHandler(otInstance * aInstance,otCoapRequestHandler aHandler,void * aContext)312 void otCoapSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandler, void *aContext)
313 {
314     Instance &instance = *static_cast<Instance *>(aInstance);
315 
316     instance.GetApplicationCoap().SetDefaultHandler(aHandler, aContext);
317 }
318 
319 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
otCoapSendResponseBlockWiseWithParameters(otInstance * aInstance,otMessage * aMessage,const otMessageInfo * aMessageInfo,const otCoapTxParameters * aTxParameters,void * aContext,otCoapBlockwiseTransmitHook aTransmitHook)320 otError otCoapSendResponseBlockWiseWithParameters(otInstance *                aInstance,
321                                                   otMessage *                 aMessage,
322                                                   const otMessageInfo *       aMessageInfo,
323                                                   const otCoapTxParameters *  aTxParameters,
324                                                   void *                      aContext,
325                                                   otCoapBlockwiseTransmitHook aTransmitHook)
326 {
327     Instance &instance = *static_cast<Instance *>(aInstance);
328 
329     return instance.GetApplicationCoap().SendMessage(
330         *static_cast<Coap::Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
331         Coap::TxParameters::From(aTxParameters), nullptr, aContext, aTransmitHook, nullptr);
332 }
333 #endif
334 
otCoapSendResponseWithParameters(otInstance * aInstance,otMessage * aMessage,const otMessageInfo * aMessageInfo,const otCoapTxParameters * aTxParameters)335 otError otCoapSendResponseWithParameters(otInstance *              aInstance,
336                                          otMessage *               aMessage,
337                                          const otMessageInfo *     aMessageInfo,
338                                          const otCoapTxParameters *aTxParameters)
339 {
340     Instance &instance = *static_cast<Instance *>(aInstance);
341 
342     return instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
343                                                      *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
344                                                      Coap::TxParameters::From(aTxParameters), nullptr, nullptr);
345 }
346 
347 #endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
348