[IOT-IOT-2739] Simulator plugin crash
[iotivity.git] / resource / csdk / stack / src / ocserverrequest.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include <string.h>
21
22 #include "ocstack.h"
23 #include "ocserverrequest.h"
24 #include "ocresourcehandler.h"
25 #include "ocobserve.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "ocpayload.h"
29 #include "ocpayloadcbor.h"
30 #include "logger.h"
31
32 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
33 #include "routingutility.h"
34 #endif
35
36 #include "cacommon.h"
37 #include "cainterface.h"
38
39 #include <coap/pdu.h>
40
41 // Module Name
42 #define VERIFY_NON_NULL(arg) { if (!arg) {OIC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
43
44 #define TAG  "OIC_RI_SERVERREQUEST"
45
46 // for RB tree
47 static int RBRequestTokenCmp(OCServerRequest *target, OCServerRequest *treeNode)
48 {
49     return memcmp(target->requestToken, treeNode->requestToken, target->tokenLength);
50 }
51
52 static int RBResponseTokenCmp(OCServerResponse *target, OCServerResponse *treeNode)
53 {
54     return memcmp(((OCServerRequest*)target->requestHandle)->requestToken,
55                   ((OCServerRequest*)treeNode->requestHandle)->requestToken,
56                   ((OCServerRequest*)target->requestHandle)->tokenLength);
57 }
58
59 RB_HEAD(ServerRequestTree, OCServerRequest) serverRequestTree = RB_INITIALIZER(&serverRequestTree);
60 RB_GENERATE(ServerRequestTree, OCServerRequest, entry, RBRequestTokenCmp)
61 RB_HEAD(ServerResponseTree, OCServerResponse) serverResponseTree =
62                                                             RB_INITIALIZER(&serverResponseTree);
63 RB_GENERATE(ServerResponseTree, OCServerResponse, entry, RBResponseTokenCmp)
64
65 //-------------------------------------------------------------------------------------------------
66 // Local functions
67 //-------------------------------------------------------------------------------------------------
68
69 /**
70  * Add a server response to the server response list
71  *
72  * @param response initialized server response that is created by this function
73  * @param requestHandle - handle of the response
74  *
75  * @return
76  *     OCStackResult
77  */
78 static OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
79 {
80     if (!response)
81     {
82         return OC_STACK_INVALID_PARAM;
83     }
84
85     OCServerResponse * serverResponse = NULL;
86
87     serverResponse = (OCServerResponse *) OICCalloc(1, sizeof(OCServerResponse));
88     VERIFY_NON_NULL(serverResponse);
89
90     serverResponse->payload = NULL;
91     serverResponse->requestHandle = requestHandle;
92
93     *response = serverResponse;
94
95     RB_INSERT(ServerResponseTree, &serverResponseTree, serverResponse);
96     OIC_LOG(INFO, TAG, "Server Response Added!!");
97     return OC_STACK_OK;
98
99 exit:
100     *response = NULL;
101     return OC_STACK_NO_MEMORY;
102 }
103
104 /**
105  * Delete a server request from the server request list
106  *
107  * @param serverRequest - server request to delete
108  */
109 static void DeleteServerRequest(OCServerRequest * serverRequest)
110 {
111     if(serverRequest)
112     {
113         RB_REMOVE(ServerRequestTree, &serverRequestTree, serverRequest);
114         OICFree(serverRequest->requestToken);
115         OICFree(serverRequest);
116         serverRequest = NULL;
117         OIC_LOG(INFO, TAG, "Server Request Removed!!");
118     }
119 }
120
121 /**
122  * Delete a server response from the server response list
123  *
124  * @param serverResponse - server response to delete
125  */
126 static void DeleteServerResponse(OCServerResponse * serverResponse)
127 {
128     if(serverResponse)
129     {
130         RB_REMOVE(ServerResponseTree, &serverResponseTree, serverResponse);
131         OICFree(serverResponse);
132         serverResponse = NULL;
133         OIC_LOG(INFO, TAG, "Server Response Removed!!");
134     }
135 }
136
137 /**
138  * Ensure no accept header option is included when sending responses and add routing info to
139  * outgoing response.
140  *
141  * @param object CA remote endpoint.
142  * @param responseInfo CA response info.
143  *
144  * @return ::OC_STACK_OK on success, some other value upon failure.
145  */
146 static OCStackResult OCSendResponse(const CAEndpoint_t *object, CAResponseInfo_t *responseInfo)
147 {
148 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
149     // Add route info in RM option.
150     OCStackResult rmResult = RMAddInfo(object->routeData, responseInfo, false, NULL);
151     if(OC_STACK_OK != rmResult)
152     {
153         OIC_LOG(ERROR, TAG, "Add option failed");
154         return rmResult;
155     }
156 #endif
157
158     // Do not include the accept header option
159     responseInfo->info.acceptFormat = CA_FORMAT_UNDEFINED;
160     CAResult_t result = CASendResponse(object, responseInfo);
161     if(CA_STATUS_OK != result)
162     {
163         OIC_LOG_V(ERROR, TAG, "CASendResponse failed with CA error %u", result);
164         return CAResultToOCResult(result);
165     }
166     return OC_STACK_OK;
167 }
168
169 static CAPayloadFormat_t OCToCAPayloadFormat(OCPayloadFormat ocFormat)
170 {
171     switch (ocFormat)
172     {
173     case OC_FORMAT_UNDEFINED:
174         return CA_FORMAT_UNDEFINED;
175     case OC_FORMAT_CBOR:
176         return CA_FORMAT_APPLICATION_CBOR;
177     case OC_FORMAT_VND_OCF_CBOR:
178         return CA_FORMAT_APPLICATION_VND_OCF_CBOR;
179     default:
180         return CA_FORMAT_UNSUPPORTED;
181     }
182 }
183 //-------------------------------------------------------------------------------------------------
184 // Internal APIs
185 //-------------------------------------------------------------------------------------------------
186
187 /**
188  * Get a server request from the server request list using the specified token.
189  *
190  * @param token - token of server request
191  * @param tokenLength - length of token
192  *
193  * @return
194  *     OCServerRequest*
195  */
196 OCServerRequest * GetServerRequestUsingToken (const CAToken_t token, uint8_t tokenLength)
197 {
198     if(!token)
199     {
200         OIC_LOG(ERROR, TAG, "Invalid Parameter Token");
201         return NULL;
202     }
203
204     OIC_LOG(INFO, TAG,"Get server request with token");
205     OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
206
207     OCServerRequest tmpFind, *out = NULL;
208
209     tmpFind.requestToken = token;
210     tmpFind.tokenLength = tokenLength;
211     out = RB_FIND(ServerRequestTree, &serverRequestTree, &tmpFind);
212
213     if (!out)
214     {
215         OIC_LOG(INFO, TAG, "Server Request not found!!");
216         return NULL;
217     }
218
219     OIC_LOG(INFO, TAG, "Found in server request list");
220     return out;
221 }
222
223 /**
224  * Get a server request from the server request list using the specified handle
225  *
226  * @param handle - handle of server request
227  * @return
228  *     OCServerRequest*
229  */
230 OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle)
231 {
232     if (!handle)
233     {
234         OIC_LOG(ERROR, TAG, "Invalid Parameter handle");
235         return NULL;
236     }
237
238     return GetServerRequestUsingToken(handle->requestToken, handle->tokenLength);
239 }
240
241 /**
242  * Get a server response from the server response list using the specified handle
243  *
244  * @param handle - handle of server response
245  *
246  * @return
247  *     OCServerResponse*
248  */
249 OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle)
250 {
251     if (!handle)
252     {
253         OIC_LOG(ERROR, TAG, "Invalid Parameter handle");
254         return NULL;
255     }
256
257     OCServerResponse tmpFind, *out = NULL;
258
259     tmpFind.requestHandle = (OCRequestHandle)handle;
260     out = RB_FIND(ServerResponseTree, &serverResponseTree, &tmpFind);
261
262     if (!out)
263     {
264         OIC_LOG(INFO, TAG, "Server Response not found!!");
265         return NULL;
266     }
267
268     OIC_LOG(INFO, TAG, "Found in server response list");
269     return out;
270 }
271
272 OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
273         uint8_t delayedResNeeded, uint8_t notificationFlag, OCMethod method,
274         uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
275         OCQualityOfService qos, char * query,
276         OCHeaderOption * rcvdVendorSpecificHeaderOptions,
277         OCPayloadFormat payloadFormat, uint8_t * payload, CAToken_t requestToken,
278         uint8_t tokenLength, char * resourceUrl, size_t reqTotalSize, OCPayloadFormat acceptFormat,
279         uint16_t acceptVersion, const OCDevAddr *devAddr)
280 {
281     if (!request)
282     {
283         return OC_STACK_INVALID_PARAM;
284     }
285
286     OCServerRequest * serverRequest = NULL;
287
288     OIC_LOG_V(INFO, TAG, "addserverrequest entry!! [%s:%u]", devAddr->addr, devAddr->port);
289
290     serverRequest = (OCServerRequest *) OICCalloc(1, sizeof(OCServerRequest) +
291         (reqTotalSize ? reqTotalSize : 1) - 1);
292     VERIFY_NON_NULL(devAddr);
293     VERIFY_NON_NULL(serverRequest);
294
295     serverRequest->coapID = coapID;
296     serverRequest->delayedResNeeded = delayedResNeeded;
297     serverRequest->notificationFlag = notificationFlag;
298
299     serverRequest->method = method;
300     serverRequest->numRcvdVendorSpecificHeaderOptions = numRcvdVendorSpecificHeaderOptions;
301     serverRequest->observationOption = observationOption;
302     serverRequest->observeResult = OC_STACK_ERROR;
303     serverRequest->qos = qos;
304     serverRequest->acceptFormat = acceptFormat;
305     serverRequest->acceptVersion = acceptVersion;
306     serverRequest->ehResponseHandler = HandleSingleResponse;
307     serverRequest->numResponses = 1;
308
309     if(query)
310     {
311         OICStrcpy(serverRequest->query, sizeof(serverRequest->query), query);
312     }
313
314     if(rcvdVendorSpecificHeaderOptions)
315     {
316         memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
317             MAX_HEADER_OPTIONS * sizeof(OCHeaderOption));
318     }
319     if(payload && reqTotalSize)
320     {
321        // destination is at least 1 greater than the source, so a NULL always exists in the
322         // last character
323         memcpy(serverRequest->payload, payload, reqTotalSize);
324         serverRequest->payloadSize = reqTotalSize;
325         serverRequest->payloadFormat = payloadFormat;
326     }
327
328     serverRequest->requestComplete = 0;
329     if(requestToken)
330     {
331         // If tokenLength is zero, the return value depends on the
332         // particular library implementation (it may or may not be a null pointer).
333         if (tokenLength)
334         {
335             serverRequest->requestToken = (CAToken_t) OICMalloc(tokenLength);
336             VERIFY_NON_NULL(serverRequest->requestToken);
337             memcpy(serverRequest->requestToken, requestToken, tokenLength);
338         }
339     }
340     serverRequest->tokenLength = tokenLength;
341
342     if(resourceUrl)
343     {
344         OICStrcpy(serverRequest->resourceUrl, sizeof(serverRequest->resourceUrl),
345             resourceUrl);
346     }
347
348     serverRequest->devAddr = *devAddr;
349
350     *request = serverRequest;
351
352     RB_INSERT(ServerRequestTree, &serverRequestTree, serverRequest);
353     OIC_LOG(INFO, TAG, "Server Request Added!!");
354     return OC_STACK_OK;
355
356 exit:
357     if (serverRequest)
358     {
359         OICFree(serverRequest);
360         serverRequest = NULL;
361     }
362     *request = NULL;
363     return OC_STACK_NO_MEMORY;
364 }
365
366 OCStackResult FormOCEntityHandlerRequest(
367         OCEntityHandlerRequest * entityHandlerRequest,
368         OCRequestHandle request,
369         OCMethod method,
370         OCDevAddr *endpoint,
371         OCResourceHandle resource,
372         char * queryBuf,
373         OCPayloadType payloadType,
374         OCPayloadFormat payloadFormat,
375         uint8_t * payload,
376         size_t payloadSize,
377         uint8_t numVendorOptions,
378         OCHeaderOption * vendorOptions,
379         OCObserveAction observeAction,
380         OCObservationId observeID,
381         uint16_t messageID)
382 {
383     if (entityHandlerRequest)
384     {
385         entityHandlerRequest->resource = (OCResourceHandle) resource;
386         entityHandlerRequest->requestHandle = request;
387         entityHandlerRequest->method = method;
388         entityHandlerRequest->devAddr = *endpoint;
389         entityHandlerRequest->query = queryBuf;
390         entityHandlerRequest->obsInfo.action = observeAction;
391         entityHandlerRequest->obsInfo.obsId = observeID;
392         entityHandlerRequest->messageID = messageID;
393
394         if(payload && payloadSize)
395         {
396             if(OCParsePayload(&entityHandlerRequest->payload, payloadFormat, payloadType,
397                         payload, payloadSize) != OC_STACK_OK)
398             {
399                 return OC_STACK_ERROR;
400             }
401         }
402         else
403         {
404             entityHandlerRequest->payload = NULL;
405         }
406
407         entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions;
408         entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions;
409
410         return OC_STACK_OK;
411     }
412
413     return OC_STACK_INVALID_PARAM;
414 }
415
416 /**
417  * Find a server request in the server request list and delete
418  *
419  * @param serverRequest - server request to find and delete
420  */
421 void FindAndDeleteServerRequest(OCServerRequest * serverRequest)
422 {
423     if(serverRequest)
424     {
425         OCServerRequest* out = NULL;
426         out = RB_FIND(ServerRequestTree, &serverRequestTree, serverRequest);
427
428         if (out)
429         {
430             DeleteServerRequest(out);
431         }
432     }
433 }
434
435 CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result, OCMethod method)
436 {
437     CAResponseResult_t caResult = CA_BAD_REQ;
438
439     switch (result)
440     {
441         // Successful Client Request
442         case OC_EH_RESOURCE_CREATED: // 2.01
443             if (method == OC_REST_POST || method == OC_REST_PUT)
444             {
445                 caResult = CA_CREATED;
446             }
447             break;
448         case OC_EH_RESOURCE_DELETED: // 2.02
449             if (method == OC_REST_POST || method == OC_REST_DELETE)
450             {
451                 caResult = CA_DELETED;
452             }
453             break;
454         case OC_EH_SLOW: // 2.05
455             caResult = CA_CONTENT;
456             break;
457         case OC_EH_OK:
458         case OC_EH_CHANGED: // 2.04
459         case OC_EH_CONTENT: // 2.05
460             if (method == OC_REST_POST || method == OC_REST_PUT)
461             {
462                 caResult = CA_CHANGED;
463             }
464             else if (method == OC_REST_DELETE)
465             {
466                 caResult = CA_DELETED;
467             }
468             else if (method == OC_REST_GET)
469             {
470                 caResult = CA_CONTENT;
471             }
472             break;
473         case OC_EH_VALID: // 2.03
474             caResult = CA_VALID;
475             break;
476         // Unsuccessful Client Request
477         case OC_EH_UNAUTHORIZED_REQ: // 4.01
478             caResult = CA_UNAUTHORIZED_REQ;
479             break;
480         case OC_EH_BAD_OPT: // 4.02
481             caResult = CA_BAD_OPT;
482             break;
483         case OC_EH_FORBIDDEN: // 4.03
484             caResult = CA_FORBIDDEN_REQ;
485             break;
486         case OC_EH_RESOURCE_NOT_FOUND: // 4.04
487             caResult = CA_NOT_FOUND;
488             break;
489         case OC_EH_METHOD_NOT_ALLOWED: // 4.05
490             caResult = CA_METHOD_NOT_ALLOWED;
491             break;
492         case OC_EH_NOT_ACCEPTABLE: // 4.06
493             caResult = CA_NOT_ACCEPTABLE;
494             break;
495         case OC_EH_INTERNAL_SERVER_ERROR: // 5.00
496             caResult = CA_INTERNAL_SERVER_ERROR;
497             break;
498         case OC_EH_SERVICE_UNAVAILABLE: // 5.03
499             caResult = CA_SERVICE_UNAVAILABLE;
500             break;
501         case OC_EH_RETRANSMIT_TIMEOUT: // 5.04
502             caResult = CA_RETRANSMIT_TIMEOUT;
503             break;
504         default:
505             caResult = CA_BAD_REQ;
506             break;
507     }
508     return caResult;
509 }
510
511
512 /**
513  * Handler function for sending a response from a single resource
514  *
515  * @param ehResponse - pointer to the response from the resource
516  *
517  * @return
518  *     OCStackResult
519  */
520 OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
521 {
522     OCStackResult result = OC_STACK_ERROR;
523     CAEndpoint_t responseEndpoint = {.adapter = CA_DEFAULT_ADAPTER};
524     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
525     CAHeaderOption_t* optionsPointer = NULL;
526
527     if(!ehResponse || !ehResponse->requestHandle)
528     {
529         OIC_LOG(ERROR, TAG, "ehResponse/requestHandle is NULL");
530         return OC_STACK_ERROR;
531     }
532
533     OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
534
535     CopyDevAddrToEndpoint(&serverRequest->devAddr, &responseEndpoint);
536
537     responseInfo.info.messageId = serverRequest->coapID;
538     responseInfo.info.resourceUri = serverRequest->resourceUrl;
539     responseInfo.result = ConvertEHResultToCAResult(ehResponse->ehResult, serverRequest->method);
540     responseInfo.info.dataType = CA_RESPONSE_DATA;
541
542     if(serverRequest->notificationFlag && serverRequest->qos == OC_HIGH_QOS)
543     {
544         responseInfo.info.type = CA_MSG_CONFIRM;
545     }
546     else if(serverRequest->notificationFlag && serverRequest->qos != OC_HIGH_QOS)
547     {
548         responseInfo.info.type = CA_MSG_NONCONFIRM;
549     }
550     else if(!serverRequest->notificationFlag && !serverRequest->slowFlag &&
551             serverRequest->qos == OC_HIGH_QOS)
552     {
553         responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
554     }
555     else if(!serverRequest->notificationFlag && serverRequest->slowFlag &&
556             serverRequest->qos == OC_HIGH_QOS)
557     {
558         // To assign new messageId in CA.
559         responseInfo.info.messageId = 0;
560         responseInfo.info.type = CA_MSG_CONFIRM;
561     }
562     else if(!serverRequest->notificationFlag)
563     {
564         responseInfo.info.type = CA_MSG_NONCONFIRM;
565     }
566     else
567     {
568         OIC_LOG(ERROR, TAG, "default responseInfo type is NON");
569         responseInfo.info.type = CA_MSG_NONCONFIRM;
570     }
571
572     char rspToken[CA_MAX_TOKEN_LEN + 1] = {0};
573     responseInfo.info.messageId = serverRequest->coapID;
574     responseInfo.info.token = (CAToken_t)rspToken;
575
576     memcpy(responseInfo.info.token, serverRequest->requestToken, serverRequest->tokenLength);
577     responseInfo.info.tokenLength = serverRequest->tokenLength;
578
579     if((serverRequest->observeResult == OC_STACK_OK)&&
580        (serverRequest->observationOption != MAX_SEQUENCE_NUMBER + 1))
581     {
582         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions + 1;
583     }
584     else
585     {
586         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions;
587     }
588
589     // Path of new resource is returned in options as location-path.
590     if (ehResponse->resourceUri[0] != '\0')
591     {
592         responseInfo.info.numOptions++;
593     }
594
595     // Check if version and format option exist.
596     uint16_t payloadVersion = OC_SPEC_VERSION_VALUE;
597     uint16_t payloadFormat = COAP_MEDIATYPE_APPLICATION_VND_OCF_CBOR;
598     bool IsPayloadVersionSet = false;
599     bool IsPayloadFormatSet = false;
600     if (ehResponse->payload)
601     {
602         for (uint8_t i = 0; i < responseInfo.info.numOptions; i++)
603         {
604             if (COAP_OPTION_CONTENT_VERSION == ehResponse->sendVendorSpecificHeaderOptions[i].optionID)
605             {
606                 payloadVersion =
607                         (ehResponse->sendVendorSpecificHeaderOptions[i].optionData[1] << 8)
608                         + ehResponse->sendVendorSpecificHeaderOptions[i].optionData[0];
609                 IsPayloadVersionSet = true;
610             }
611             else if (COAP_OPTION_CONTENT_TYPE == ehResponse->sendVendorSpecificHeaderOptions[i].optionID)
612             {
613                 if (1 == ehResponse->sendVendorSpecificHeaderOptions[i].optionLength)
614                 {
615                     payloadFormat = ehResponse->sendVendorSpecificHeaderOptions[i].optionData[0];
616                     IsPayloadFormatSet = true;
617                 }
618                 else if (2 == ehResponse->sendVendorSpecificHeaderOptions[i].optionLength)
619                 {
620                     payloadFormat =
621                             (ehResponse->sendVendorSpecificHeaderOptions[i].optionData[1] << 8)
622                             + ehResponse->sendVendorSpecificHeaderOptions[i].optionData[0];
623
624                     IsPayloadFormatSet = true;
625                 }
626                 else
627                 {
628                     payloadFormat = CA_FORMAT_UNSUPPORTED;
629                     IsPayloadFormatSet = false;
630                     OIC_LOG_V(DEBUG, TAG, "option has an unsupported format");
631                 }
632             }
633         }
634         if (!IsPayloadVersionSet && !IsPayloadFormatSet)
635         {
636             responseInfo.info.numOptions = responseInfo.info.numOptions + 2;
637         }
638         else if ((IsPayloadFormatSet && CA_FORMAT_APPLICATION_VND_OCF_CBOR == payloadFormat
639                 && !IsPayloadVersionSet) || (IsPayloadVersionSet && !IsPayloadFormatSet))
640         {
641             responseInfo.info.numOptions++;
642         }
643     }
644
645     if (responseInfo.info.numOptions > 0)
646     {
647         responseInfo.info.options = (CAHeaderOption_t *)
648                                       OICCalloc(responseInfo.info.numOptions,
649                                               sizeof(CAHeaderOption_t));
650
651         if(!responseInfo.info.options)
652         {
653             OIC_LOG(FATAL, TAG, "Memory alloc for options failed");
654             return OC_STACK_NO_MEMORY;
655         }
656
657         optionsPointer = responseInfo.info.options;
658
659         // TODO: This exposes CoAP specific details.  At some point, this should be
660         // re-factored and handled in the CA layer.
661         // Stack sets MAX_SEQUENCE_NUMBER+1 to sequence number on observe cancel request.
662         // And observe option should not be part of CoAP response for observe cancel request.
663         if(serverRequest->observeResult == OC_STACK_OK
664            && serverRequest->observationOption != MAX_SEQUENCE_NUMBER + 1)
665         {
666             responseInfo.info.options[0].protocolID = CA_COAP_ID;
667             responseInfo.info.options[0].optionID = COAP_OPTION_OBSERVE;
668             responseInfo.info.options[0].optionLength = sizeof(uint32_t);
669             uint8_t* observationData = (uint8_t*)responseInfo.info.options[0].optionData;
670             uint32_t observationOption= serverRequest->observationOption;
671
672             for (size_t i=sizeof(uint32_t); i; --i)
673             {
674                 observationData[i-1] = observationOption & 0xFF;
675                 observationOption >>=8;
676             }
677
678             // Point to the next header option before copying vender specific header options
679             optionsPointer += 1;
680         }
681
682         if (ehResponse->numSendVendorSpecificHeaderOptions)
683         {
684             memcpy(optionsPointer, ehResponse->sendVendorSpecificHeaderOptions,
685                             sizeof(OCHeaderOption) *
686                             ehResponse->numSendVendorSpecificHeaderOptions);
687
688             // Advance the optionPointer by the number of vendor options.
689             optionsPointer += ehResponse->numSendVendorSpecificHeaderOptions;
690         }
691
692         // Return new resource as location-path option.
693         // https://tools.ietf.org/html/rfc7252#section-5.8.2.
694         if (ehResponse->resourceUri[0] != '\0')
695         {
696             if ((strlen(ehResponse->resourceUri) + 1) > CA_MAX_HEADER_OPTION_DATA_LENGTH)
697             {
698                 OIC_LOG(ERROR, TAG,
699                     "New resource path must be less than CA_MAX_HEADER_OPTION_DATA_LENGTH");
700                 OICFree(responseInfo.info.options);
701                 return OC_STACK_INVALID_URI;
702             }
703
704             optionsPointer->protocolID = CA_COAP_ID;
705             optionsPointer->optionID = CA_HEADER_OPTION_ID_LOCATION_PATH;
706             OICStrcpy(
707                 optionsPointer->optionData,
708                 sizeof(optionsPointer->optionData),
709                 ehResponse->resourceUri);
710             optionsPointer->optionLength = (uint16_t)strlen(optionsPointer->optionData) + 1;
711             optionsPointer += 1;
712         }
713
714         if (ehResponse->payload)
715         {
716             if (!IsPayloadVersionSet && !IsPayloadFormatSet)
717             {
718                 optionsPointer->protocolID = CA_COAP_ID;
719                 optionsPointer->optionID = CA_OPTION_CONTENT_VERSION;
720                 memcpy(optionsPointer->optionData, &payloadVersion,
721                         sizeof(uint16_t));
722                 optionsPointer->optionLength = sizeof(uint16_t);
723                 optionsPointer += 1;
724
725                 optionsPointer->protocolID = CA_COAP_ID;
726                 optionsPointer->optionID = COAP_OPTION_CONTENT_FORMAT;
727                 memcpy(optionsPointer->optionData, &payloadFormat,
728                         sizeof(uint16_t));
729                 optionsPointer->optionLength = sizeof(uint16_t);
730             }
731             else if (IsPayloadFormatSet && CA_FORMAT_APPLICATION_VND_OCF_CBOR == payloadFormat
732                             && !IsPayloadVersionSet)
733             {
734                 optionsPointer->protocolID = CA_COAP_ID;
735                 optionsPointer->optionID = CA_OPTION_CONTENT_VERSION;
736                 memcpy(optionsPointer->optionData, &payloadVersion,
737                         sizeof(uint16_t));
738                 optionsPointer->optionLength = sizeof(uint16_t);
739             }
740             else if (IsPayloadVersionSet && OC_SPEC_VERSION_VALUE <= payloadVersion && !IsPayloadFormatSet)
741             {
742                 optionsPointer->protocolID = CA_COAP_ID;
743                 optionsPointer->optionID = COAP_OPTION_CONTENT_TYPE;
744                 memcpy(optionsPointer->optionData, &payloadFormat,
745                         sizeof(uint16_t));
746                 optionsPointer->optionLength = sizeof(uint16_t);
747             }
748         }
749     }
750     else
751     {
752         responseInfo.info.options = NULL;
753     }
754
755     responseInfo.isMulticast = false;
756     responseInfo.info.payload = NULL;
757     responseInfo.info.payloadSize = 0;
758     responseInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
759
760     // Put the JSON prefix and suffix around the payload
761     if(ehResponse->payload)
762     {
763         if (ehResponse->payload->type == PAYLOAD_TYPE_PRESENCE)
764         {
765             responseInfo.isMulticast = true;
766         }
767         else
768         {
769             responseInfo.isMulticast = false;
770         }
771
772         switch(serverRequest->acceptFormat)
773         {
774             case OC_FORMAT_UNDEFINED:
775                 // No preference set by the client, so default to CBOR then
776             case OC_FORMAT_CBOR:
777             case OC_FORMAT_VND_OCF_CBOR:
778                 if((result = OCConvertPayload(ehResponse->payload, serverRequest->acceptFormat,
779                                 &responseInfo.info.payload, &responseInfo.info.payloadSize))
780                         != OC_STACK_OK)
781                 {
782                     OIC_LOG(ERROR, TAG, "Error converting payload");
783                     OICFree(responseInfo.info.options);
784                     return result;
785                 }
786                 // Add CONTENT_FORMAT OPT if payload exist
787                 if (ehResponse->payload->type != PAYLOAD_TYPE_DIAGNOSTIC &&
788                         responseInfo.info.payloadSize > 0)
789                 {
790                     responseInfo.info.payloadFormat = OCToCAPayloadFormat(
791                             serverRequest->acceptFormat);
792                     if (CA_FORMAT_UNDEFINED == responseInfo.info.payloadFormat)
793                     {
794                         responseInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
795                     }
796                     if ((OC_FORMAT_VND_OCF_CBOR == serverRequest->acceptFormat))
797                     {
798                         // Add versioning information for this format
799                         responseInfo.info.payloadVersion = serverRequest->acceptVersion;
800                         if (!responseInfo.info.payloadVersion)
801                         {
802                             responseInfo.info.payloadVersion = DEFAULT_VERSION_VALUE;
803                         }
804
805                     }
806                 }
807                 break;
808             default:
809                 responseInfo.result = CA_NOT_ACCEPTABLE;
810         }
811     }
812
813 #ifdef WITH_PRESENCE
814     CATransportAdapter_t CAConnTypes[] = {
815                             CA_ADAPTER_IP,
816                             CA_ADAPTER_GATT_BTLE,
817                             CA_ADAPTER_RFCOMM_BTEDR,
818                             CA_ADAPTER_NFC
819 #ifdef RA_ADAPTER
820                             , CA_ADAPTER_REMOTE_ACCESS
821 #endif
822                             , CA_ADAPTER_TCP
823                         };
824
825     size_t size = sizeof(CAConnTypes)/ sizeof(CATransportAdapter_t);
826
827     CATransportAdapter_t adapter = responseEndpoint.adapter;
828     // Default adapter, try to send response out on all adapters.
829     if (adapter == CA_DEFAULT_ADAPTER)
830     {
831         adapter =
832             (CATransportAdapter_t)(
833                 CA_ADAPTER_IP           |
834                 CA_ADAPTER_GATT_BTLE    |
835                 CA_ADAPTER_RFCOMM_BTEDR |
836                 CA_ADAPTER_NFC
837 #ifdef RA_ADAP
838                 | CA_ADAPTER_REMOTE_ACCESS
839 #endif
840                 | CA_ADAPTER_TCP
841             );
842     }
843
844     result = OC_STACK_OK;
845     OCStackResult tempResult = OC_STACK_OK;
846
847     for(size_t i = 0; i < size; i++ )
848     {
849         responseEndpoint.adapter = (CATransportAdapter_t)(adapter & CAConnTypes[i]);
850         if(responseEndpoint.adapter)
851         {
852             //The result is set to OC_STACK_OK only if OCSendResponse succeeds in sending the
853             //response on all the n/w interfaces else it is set to OC_STACK_ERROR
854             tempResult = OCSendResponse(&responseEndpoint, &responseInfo);
855         }
856         if(OC_STACK_OK != tempResult)
857         {
858             result = tempResult;
859         }
860     }
861 #else
862
863     OIC_LOG(INFO, TAG, "Calling OCSendResponse with:");
864     OIC_LOG_V(INFO, TAG, "\tEndpoint address: %s", responseEndpoint.addr);
865     OIC_LOG_V(INFO, TAG, "\tEndpoint adapter: %s", responseEndpoint.adapter);
866     OIC_LOG_V(INFO, TAG, "\tResponse result : %s", responseInfo.result);
867     OIC_LOG_V(INFO, TAG, "\tResponse for uri: %s", responseInfo.info.resourceUri);
868
869     result = OCSendResponse(&responseEndpoint, &responseInfo);
870 #endif
871
872     OICFree(responseInfo.info.payload);
873     OICFree(responseInfo.info.options);
874     //Delete the request
875     FindAndDeleteServerRequest(serverRequest);
876     return result;
877 }
878
879 /**
880  * Handler function for sending a response from multiple resources, such as a collection.
881  * Aggregates responses from multiple resource until all responses are received then sends the
882  * concatenated response
883  *
884  * TODO: Need to add a timeout in case a (remote?) resource does not respond
885  *
886  * @param ehResponse - pointer to the response from the resource
887  *
888  * @return
889  *     OCStackResult
890  */
891 OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
892 {
893     if(!ehResponse || !ehResponse->payload)
894     {
895         OIC_LOG(ERROR, TAG, "HandleAggregateResponse invalid parameters");
896         return OC_STACK_INVALID_PARAM;
897     }
898
899     OIC_LOG(INFO, TAG, "Inside HandleAggregateResponse");
900
901     OCServerRequest *serverRequest = GetServerRequestUsingHandle((OCServerRequest *)
902                                                                  ehResponse->requestHandle);
903     OCServerResponse *serverResponse = GetServerResponseUsingHandle((OCServerRequest *)
904                                                                     ehResponse->requestHandle);
905
906     OCStackResult stackRet = OC_STACK_ERROR;
907     if(serverRequest)
908     {
909         if(!serverResponse)
910         {
911             OIC_LOG(INFO, TAG, "This is the first response fragment");
912             stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
913             if (OC_STACK_OK != stackRet)
914             {
915                 OIC_LOG(ERROR, TAG, "Error adding server response");
916                 return stackRet;
917             }
918             VERIFY_NON_NULL(serverResponse);
919         }
920
921         if(ehResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
922         {
923             stackRet = OC_STACK_ERROR;
924             OIC_LOG(ERROR, TAG, "Error adding payload, as it was the incorrect type");
925             goto exit;
926         }
927
928         OCRepPayload *newPayload = OCRepPayloadBatchClone((OCRepPayload *)ehResponse->payload);
929
930         if(!serverResponse->payload)
931         {
932             serverResponse->payload = (OCPayload *)newPayload;
933         }
934         else
935         {
936             OCRepPayloadAppend((OCRepPayload*)serverResponse->payload,
937                     (OCRepPayload*)newPayload);
938         }
939
940         (serverRequest->numResponses)--;
941
942         if(serverRequest->numResponses == 0)
943         {
944             OIC_LOG(INFO, TAG, "This is the last response fragment");
945             ehResponse->payload = serverResponse->payload;
946             ehResponse->ehResult = OC_EH_OK;
947             stackRet = HandleSingleResponse(ehResponse);
948             //Delete the request and response
949             FindAndDeleteServerRequest(serverRequest);
950             DeleteServerResponse(serverResponse);
951         }
952         else
953         {
954             OIC_LOG(INFO, TAG, "More response fragments to come");
955             stackRet = OC_STACK_OK;
956         }
957     }
958 exit:
959
960     return stackRet;
961 }