[CONPRO-1398] Adjust server request handling
[platform/upstream/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/utlist.h>
40 #include <coap/pdu.h>
41
42 // Module Name
43 #define VERIFY_NON_NULL(arg) { if (!arg) {OIC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
44
45 #define TAG  "OIC_RI_SERVERREQUEST"
46
47 static struct OCServerRequest * serverRequestList = NULL;
48 static struct OCServerResponse * serverResponseList = NULL;
49
50 //-------------------------------------------------------------------------------------------------
51 // Local functions
52 //-------------------------------------------------------------------------------------------------
53
54 /**
55  * Add a server response to the server response list
56  *
57  * @param response initialized server response that is created by this function
58  * @param requestHandle - handle of the response
59  *
60  * @return
61  *     OCStackResult
62  */
63 static OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
64 {
65     if (!response)
66     {
67         return OC_STACK_INVALID_PARAM;
68     }
69
70     OCServerResponse * serverResponse = NULL;
71
72     serverResponse = (OCServerResponse *) OICCalloc(1, sizeof(OCServerResponse));
73     VERIFY_NON_NULL(serverResponse);
74
75     serverResponse->payload = NULL;
76
77     serverResponse->requestHandle = requestHandle;
78
79     *response = serverResponse;
80     OIC_LOG(INFO, TAG, "Server Response Added!!");
81     LL_APPEND (serverResponseList, serverResponse);
82     return OC_STACK_OK;
83
84 exit:
85     if (serverResponse)
86     {
87         OICFree(serverResponse);
88         serverResponse = NULL;
89     }
90     *response = NULL;
91     return OC_STACK_NO_MEMORY;
92 }
93
94 /**
95  * Delete a server request from the server request list
96  *
97  * @param serverRequest - server request to delete
98  */
99 static void DeleteServerRequest(OCServerRequest * serverRequest)
100 {
101     if(serverRequest)
102     {
103         OIC_LOG_V(WARNING, TAG, "Server request ID = [%u]", serverRequest->requestId);
104         LL_DELETE(serverRequestList, serverRequest);
105         OICFree(serverRequest->requestToken);
106         OICFree(serverRequest->rcvdVendorSpecificHeaderOptions);
107         OICFree(serverRequest);
108         serverRequest = NULL;
109         OIC_LOG(INFO, TAG, "Server Request Removed!!");
110     }
111 }
112
113 /**
114  * Delete a server response from the server response list
115  *
116  * @param serverResponse - server response to delete
117  */
118 static void DeleteServerResponse(OCServerResponse * serverResponse)
119 {
120     if(serverResponse)
121     {
122         LL_DELETE(serverResponseList, serverResponse);
123         OCPayloadDestroy(serverResponse->payload);
124         OICFree(serverResponse);
125         OIC_LOG(INFO, TAG, "Server Response Removed!!");
126     }
127 }
128
129 /**
130  * Find a server response and delete it from the server response list
131  *
132  * @param serverResponse - server response to find and delete
133  */
134 static void FindAndDeleteServerResponse(OCServerResponse * serverResponse)
135 {
136     OCServerResponse* tmp;
137     if(serverResponse)
138     {
139         LL_FOREACH(serverResponseList, tmp)
140         {
141             if (serverResponse == tmp)
142             {
143                 DeleteServerResponse(tmp);
144                 return;
145             }
146         }
147     }
148 }
149
150 /**
151  * Ensure no accept header option is included when sending responses and add routing info to
152  * outgoing response.
153  *
154  * @param object CA remote endpoint.
155  * @param requestInfo CA request info.
156  *
157  * @return ::OC_STACK_OK on success, some other value upon failure.
158  */
159 static OCStackResult OCSendResponse(const CAEndpoint_t *object, CAResponseInfo_t *responseInfo)
160 {
161 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
162     // Add route info in RM option.
163     OCStackResult rmResult = RMAddInfo(object->routeData, responseInfo, false, NULL);
164     if(OC_STACK_OK != rmResult)
165     {
166         OIC_LOG(ERROR, TAG, "Add option failed");
167         return rmResult;
168     }
169 #endif
170
171     // Do not include the accept header option
172     responseInfo->info.acceptFormat = CA_FORMAT_UNDEFINED;
173     CAResult_t result = CASendResponse(object, responseInfo);
174     if(CA_STATUS_OK != result)
175     {
176         OIC_LOG_V(ERROR, TAG, "CASendResponse failed with CA error %u", result);
177         return CAResultToOCResult(result);
178     }
179     return OC_STACK_OK;
180 }
181
182 //-------------------------------------------------------------------------------------------------
183 // Internal APIs
184 //-------------------------------------------------------------------------------------------------
185
186 /**
187  * Get a server request from the server request list using the specified token.
188  *
189  * @param token - token of server request
190  * @param tokenLength - length of token
191  *
192  * @return
193  *     OCServerRequest*
194  */
195 OCServerRequest * GetServerRequestUsingToken (const CAToken_t token, uint8_t tokenLength)
196 {
197     if(!token)
198     {
199         OIC_LOG(ERROR, TAG, "Invalid Parameter Token");
200         return NULL;
201     }
202
203     OCServerRequest * out = NULL;
204     OIC_LOG(INFO, TAG,"Get server request with token");
205     OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
206
207     OIC_LOG(INFO, TAG, "Found token");
208     LL_FOREACH (serverRequestList, out)
209     {
210         if(out)
211         {
212             OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->requestToken, out->tokenLength);
213             if((tokenLength == out->tokenLength) &&
214                 memcmp(out->requestToken, token, tokenLength) == 0)
215             {
216                 return out;
217             }
218         }
219     }
220     OIC_LOG(INFO, TAG, "Server Request not found!!");
221     return NULL;
222 }
223
224 /**
225  * Get a server request from the server request list using the specified handle
226  *
227  * @param handle - handle of server request
228  * @return
229  *     OCServerRequest*
230  */
231 OCServerRequest * GetServerRequestUsingHandle (const OCRequestHandle handle)
232 {
233     OCServerRequest * out = NULL;
234     LL_FOREACH (serverRequestList, out)
235     {
236         if(out->requestId == handle)
237         {
238             return out;
239         }
240     }
241     OIC_LOG(ERROR, TAG, "Server Request not found!!");
242     return NULL;
243 }
244
245 /**
246  * Get a server response from the server response list using the specified handle
247  *
248  * @param handle - handle of server response
249  *
250  * @return
251  *     OCServerResponse*
252  */
253 OCServerResponse * GetServerResponseUsingHandle (const OCRequestHandle handle)
254 {
255     OCServerResponse * out = NULL;
256     LL_FOREACH (serverResponseList, out)
257     {
258         if(out->requestHandle == handle)
259         {
260             return out;
261         }
262     }
263     OIC_LOG(INFO, TAG, "Server Response not found!!");
264     return NULL;
265 }
266
267 OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
268         uint8_t delayedResNeeded, uint8_t notificationFlag, OCMethod method,
269         uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
270         OCQualityOfService qos, char * query,
271         OCHeaderOption * rcvdVendorSpecificHeaderOptions,
272         uint8_t * payload, CAToken_t requestToken, uint8_t tokenLength,
273         char * resourceUrl, size_t reqTotalSize, OCPayloadFormat acceptFormat,
274         const OCDevAddr *devAddr)
275 {
276     if (!request)
277     {
278         return OC_STACK_INVALID_PARAM;
279     }
280
281     OCServerRequest * serverRequest = NULL;
282
283     OIC_LOG_V(INFO, TAG, "addserverrequest entry!! [%s:%u]", devAddr->addr, devAddr->port);
284
285     serverRequest = (OCServerRequest *) OICCalloc(1, sizeof(OCServerRequest) +
286         (reqTotalSize ? reqTotalSize : 1) - 1);
287     VERIFY_NON_NULL(devAddr);
288     VERIFY_NON_NULL(serverRequest);
289
290     serverRequest->coapID = coapID;
291     serverRequest->delayedResNeeded = delayedResNeeded;
292     serverRequest->notificationFlag = notificationFlag;
293
294     serverRequest->method = method;
295     serverRequest->numRcvdVendorSpecificHeaderOptions = numRcvdVendorSpecificHeaderOptions;
296     serverRequest->observationOption = observationOption;
297     serverRequest->observeResult = OC_STACK_ERROR;
298     serverRequest->qos = qos;
299     serverRequest->acceptFormat = acceptFormat;
300     serverRequest->ehResponseHandler = HandleSingleResponse;
301     serverRequest->numResponses = 1;
302     serverRequest->requestId = OCGetRandom();
303
304     // checking same id exist
305     while(serverRequest->requestId == 0 || GetServerRequestUsingHandle(serverRequest->requestId) != NULL)
306     {
307         serverRequest->requestId = OCGetRandom();
308     }
309
310     if(query)
311     {
312         OICStrcpy(serverRequest->query, sizeof(serverRequest->query), query);
313     }
314
315     if(rcvdVendorSpecificHeaderOptions)
316     {
317         serverRequest->rcvdVendorSpecificHeaderOptions =
318                     (OCHeaderOption *) OICCalloc(numRcvdVendorSpecificHeaderOptions, sizeof(OCHeaderOption));
319         VERIFY_NON_NULL(serverRequest->rcvdVendorSpecificHeaderOptions);
320
321         memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
322             numRcvdVendorSpecificHeaderOptions * sizeof(OCHeaderOption));
323     }
324     if(payload && reqTotalSize)
325     {
326         // destination is at least 1 greater than the source, so a NULL always exists in the
327         // last character
328         memcpy(serverRequest->payload, payload, reqTotalSize);
329         serverRequest->payloadSize = reqTotalSize;
330     }
331
332     serverRequest->requestComplete = 0;
333     if(requestToken)
334     {
335          // If tokenLength is zero, the return value depends on the
336          // particular library implementation (it may or may not be a null pointer).
337         if (tokenLength)
338         {
339             serverRequest->requestToken = (CAToken_t) OICMalloc(tokenLength);
340             VERIFY_NON_NULL(serverRequest->requestToken);
341             memcpy(serverRequest->requestToken, requestToken, tokenLength);
342         }
343     }
344     serverRequest->tokenLength = tokenLength;
345
346     if(resourceUrl)
347     {
348         OICStrcpy(serverRequest->resourceUrl, sizeof(serverRequest->resourceUrl),
349             resourceUrl);
350     }
351
352     serverRequest->devAddr = *devAddr;
353
354     *request = serverRequest;
355     OIC_LOG(INFO, TAG, "Server Request Added!!");
356     LL_APPEND (serverRequestList, serverRequest);
357     return OC_STACK_OK;
358
359 exit:
360     if (serverRequest)
361     {
362         OICFree(serverRequest->requestToken);
363         OICFree(serverRequest->rcvdVendorSpecificHeaderOptions);
364         OICFree(serverRequest);
365         serverRequest = NULL;
366     }
367     *request = NULL;
368     return OC_STACK_NO_MEMORY;
369 }
370
371 OCStackResult FormOCEntityHandlerRequest(
372         OCEntityHandlerRequest * entityHandlerRequest,
373         OCRequestHandle request,
374         OCMethod method,
375         OCDevAddr *endpoint,
376         OCResourceHandle resource,
377         char * queryBuf,
378         OCPayloadType payloadType,
379         uint8_t * payload,
380         size_t payloadSize,
381         uint8_t numVendorOptions,
382         OCHeaderOption * vendorOptions,
383         OCObserveAction observeAction,
384         OCObservationId observeID,
385         uint16_t messageID)
386 {
387     if (entityHandlerRequest)
388     {
389         entityHandlerRequest->resource = (OCResourceHandle) resource;
390         entityHandlerRequest->requestHandle = request;
391         entityHandlerRequest->method = method;
392         entityHandlerRequest->devAddr = *endpoint;
393         entityHandlerRequest->query = queryBuf;
394         entityHandlerRequest->obsInfo.action = observeAction;
395         entityHandlerRequest->obsInfo.obsId = observeID;
396         entityHandlerRequest->messageID = messageID;
397
398         if(payload && payloadSize)
399         {
400             if(OCParsePayload(&entityHandlerRequest->payload, payloadType,
401                         payload, payloadSize) != OC_STACK_OK)
402             {
403                 return OC_STACK_ERROR;
404             }
405         }
406         else
407         {
408             entityHandlerRequest->payload = NULL;
409         }
410
411         entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions;
412         entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions;
413
414         return OC_STACK_OK;
415     }
416
417     return OC_STACK_INVALID_PARAM;
418 }
419
420 /**
421  * Find a server request in the server request list and delete
422  *
423  * @param serverRequest - server request to find and delete
424  */
425 void FindAndDeleteServerRequest(OCServerRequest * serverRequest)
426 {
427     OCServerRequest* tmp;
428     if(serverRequest)
429     {
430         LL_FOREACH(serverRequestList, tmp)
431         {
432             if (serverRequest == tmp)
433             {
434                 DeleteServerRequest(tmp);
435                 return;
436             }
437         }
438     }
439 }
440
441 CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result, OCMethod method)
442 {
443     CAResponseResult_t caResult = CA_BAD_REQ;
444
445     switch (result)
446     {
447         // Successful Client Request
448         case OC_EH_RESOURCE_CREATED: // 2.01
449             if (method == OC_REST_POST || method == OC_REST_PUT)
450             {
451                 caResult = CA_CREATED;
452             }
453             break;
454         case OC_EH_RESOURCE_DELETED: // 2.02
455             if (method == OC_REST_POST || method == OC_REST_DELETE)
456             {
457                 caResult = CA_DELETED;
458             }
459             break;
460         case OC_EH_SLOW: // 2.05
461             caResult = CA_CONTENT;
462             break;
463         case OC_EH_OK:
464         case OC_EH_CHANGED: // 2.04
465         case OC_EH_CONTENT: // 2.05
466             if (method == OC_REST_POST || method == OC_REST_PUT)
467             {
468                 caResult = CA_CHANGED;
469             }
470             else if (method == OC_REST_GET)
471             {
472                 caResult = CA_CONTENT;
473             }
474             break;
475         case OC_EH_VALID: // 2.03
476             caResult = CA_VALID;
477             break;
478         // Unsuccessful Client Request
479         case OC_EH_UNAUTHORIZED_REQ: // 4.01
480             caResult = CA_UNAUTHORIZED_REQ;
481             break;
482         case OC_EH_BAD_OPT: // 4.02
483             caResult = CA_BAD_OPT;
484             break;
485         case OC_EH_FORBIDDEN: // 4.03
486             caResult = CA_FORBIDDEN_REQ;
487             break;
488         case OC_EH_RESOURCE_NOT_FOUND: // 4.04
489             caResult = CA_NOT_FOUND;
490             break;
491         case OC_EH_METHOD_NOT_ALLOWED: // 4.05
492             caResult = CA_METHOD_NOT_ALLOWED;
493             break;
494         case OC_EH_NOT_ACCEPTABLE: // 4.06
495             caResult = CA_NOT_ACCEPTABLE;
496             break;
497         case OC_EH_TOO_MANY_REQUESTS: // 4.29
498             caResult = CA_TOO_MANY_REQUESTS;
499             break;
500         case OC_EH_INTERNAL_SERVER_ERROR: // 5.00
501             caResult = CA_INTERNAL_SERVER_ERROR;
502             break;
503         case OC_EH_NOT_IMPLEMENTED: // 5.01
504             caResult = CA_NOT_IMPLEMENTED;
505             break;
506         case OC_EH_BAD_GATEWAY: // 5.02
507             caResult = CA_BAD_GATEWAY;
508             break;
509         case OC_EH_SERVICE_UNAVAILABLE: // 5.03
510             caResult = CA_SERVICE_UNAVAILABLE;
511             break;
512         case OC_EH_RETRANSMIT_TIMEOUT: // 5.04
513             caResult = CA_RETRANSMIT_TIMEOUT;
514             break;
515         case OC_EH_PROXY_NOT_SUPPORTED: // 5.05
516             caResult = CA_PROXY_NOT_SUPPORTED;
517             break;
518         default:
519             caResult = CA_BAD_REQ;
520             break;
521     }
522     return caResult;
523 }
524
525
526 /**
527  * Handler function for sending a response from a single resource
528  *
529  * @param ehResponse - pointer to the response from the resource
530  *
531  * @return
532  *     OCStackResult
533  */
534 OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
535 {
536     OCStackResult result = OC_STACK_ERROR;
537     CAEndpoint_t responseEndpoint = {.adapter = CA_DEFAULT_ADAPTER};
538     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
539     CAHeaderOption_t* optionsPointer = NULL;
540
541     if(!ehResponse || !ehResponse->requestHandle)
542     {
543         OIC_LOG(ERROR, TAG, "ehResponse/requestHandle is NULL");
544         return OC_STACK_ERROR;
545     }
546
547     OCServerRequest *serverRequest = GetServerRequestUsingHandle(ehResponse->requestHandle);
548     if (NULL == serverRequest)
549     {
550         OIC_LOG(ERROR, TAG, "No serverRequest matching with ehResponse");
551         return OC_STACK_ERROR;
552     }
553
554     CopyDevAddrToEndpoint(&serverRequest->devAddr, &responseEndpoint);
555
556     responseInfo.info.messageId = serverRequest->coapID;
557     responseInfo.info.resourceUri = serverRequest->resourceUrl;
558     responseInfo.result = ConvertEHResultToCAResult(ehResponse->ehResult, serverRequest->method);
559     responseInfo.info.dataType = CA_RESPONSE_DATA;
560
561     if(serverRequest->notificationFlag && serverRequest->qos == OC_HIGH_QOS)
562     {
563         responseInfo.info.type = CA_MSG_CONFIRM;
564     }
565     else if(serverRequest->notificationFlag && serverRequest->qos != OC_HIGH_QOS)
566     {
567         responseInfo.info.type = CA_MSG_NONCONFIRM;
568     }
569     else if(!serverRequest->notificationFlag && !serverRequest->slowFlag &&
570             serverRequest->qos == OC_HIGH_QOS)
571     {
572         responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
573     }
574     else if(!serverRequest->notificationFlag && serverRequest->slowFlag &&
575             serverRequest->qos == OC_HIGH_QOS)
576     {
577         // To assign new messageId in CA.
578         responseInfo.info.messageId = 0;
579         responseInfo.info.type = CA_MSG_CONFIRM;
580     }
581     else if(!serverRequest->notificationFlag)
582     {
583         responseInfo.info.type = CA_MSG_NONCONFIRM;
584     }
585     else
586     {
587         OIC_LOG(ERROR, TAG, "default responseInfo type is NON");
588         responseInfo.info.type = CA_MSG_NONCONFIRM;
589     }
590
591     char rspToken[CA_MAX_TOKEN_LEN + 1] = {0};
592     responseInfo.info.messageId = serverRequest->coapID;
593     responseInfo.info.token = (CAToken_t)rspToken;
594
595     memcpy(responseInfo.info.token, serverRequest->requestToken, serverRequest->tokenLength);
596     responseInfo.info.tokenLength = serverRequest->tokenLength;
597
598     if((serverRequest->observeResult == OC_STACK_OK)&&
599        (serverRequest->observationOption != MAX_SEQUENCE_NUMBER + 1))
600     {
601         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions + 1;
602     }
603     else
604     {
605         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions;
606     }
607
608     if(responseInfo.info.numOptions > 0)
609     {
610         responseInfo.info.options = (CAHeaderOption_t *)
611                                       OICCalloc(responseInfo.info.numOptions,
612                                               sizeof(CAHeaderOption_t));
613
614         if(!responseInfo.info.options)
615         {
616             OIC_LOG(FATAL, TAG, "Memory alloc for options failed");
617             return OC_STACK_NO_MEMORY;
618         }
619
620         optionsPointer = responseInfo.info.options;
621
622         // TODO: This exposes CoAP specific details.  At some point, this should be
623         // re-factored and handled in the CA layer.
624         if(serverRequest->observeResult == OC_STACK_OK)
625         {
626             responseInfo.info.options[0].protocolID = CA_COAP_ID;
627             responseInfo.info.options[0].optionID = COAP_OPTION_OBSERVE;
628             responseInfo.info.options[0].optionLength = sizeof(uint32_t);
629             uint8_t* observationData = (uint8_t*)responseInfo.info.options[0].optionData;
630             uint32_t observationOption= serverRequest->observationOption;
631
632             for (size_t i=sizeof(uint32_t); i; --i)
633             {
634                 observationData[i-1] = observationOption & 0xFF;
635                 observationOption >>=8;
636             }
637
638             // Point to the next header option before copying vender specific header options
639             optionsPointer += 1;
640         }
641
642         if (ehResponse->numSendVendorSpecificHeaderOptions)
643         {
644             memcpy(optionsPointer, ehResponse->sendVendorSpecificHeaderOptions,
645                             sizeof(OCHeaderOption) *
646                             ehResponse->numSendVendorSpecificHeaderOptions);
647         }
648     }
649     else
650     {
651         responseInfo.info.options = NULL;
652     }
653
654     responseInfo.isMulticast = false;
655     responseInfo.info.payload = NULL;
656     responseInfo.info.payloadSize = 0;
657     responseInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
658
659     // Put the JSON prefix and suffix around the payload
660     if(ehResponse->payload)
661     {
662 #ifdef WITH_PRESENCE
663         if (ehResponse->payload->type == PAYLOAD_TYPE_PRESENCE)
664         {
665             responseInfo.isMulticast = true;
666         }
667         else
668 #endif
669         {
670             responseInfo.isMulticast = false;
671         }
672
673         switch(serverRequest->acceptFormat)
674         {
675             case OC_FORMAT_UNDEFINED:
676                 // No preference set by the client, so default to CBOR then
677             case OC_FORMAT_CBOR:
678                 if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
679                                 &responseInfo.info.payloadSize))
680                         != OC_STACK_OK)
681                 {
682                     OIC_LOG(ERROR, TAG, "Error converting payload");
683                     OICFree(responseInfo.info.options);
684                     return result;
685                 }
686                 // Add CONTENT_FORMAT OPT if payload exist
687                 if (responseInfo.info.payloadSize > 0)
688                 {
689                     responseInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
690                 }
691                 break;
692             default:
693                 responseInfo.result = CA_NOT_ACCEPTABLE;
694         }
695     }
696
697 #ifdef WITH_PRESENCE
698     CATransportAdapter_t CAConnTypes[] = {
699                             CA_ADAPTER_IP,
700                             CA_ADAPTER_GATT_BTLE,
701                             CA_ADAPTER_RFCOMM_BTEDR,
702                             CA_ADAPTER_NFC
703 #ifdef RA_ADAPTER
704                             , CA_ADAPTER_REMOTE_ACCESS
705 #endif
706                             , CA_ADAPTER_TCP
707                         };
708
709     size_t size = sizeof(CAConnTypes)/ sizeof(CATransportAdapter_t);
710
711     CATransportAdapter_t adapter = responseEndpoint.adapter;
712     // Default adapter, try to send response out on all adapters.
713     if (adapter == CA_DEFAULT_ADAPTER)
714     {
715         adapter =
716             (CATransportAdapter_t)(
717                 CA_ADAPTER_IP           |
718                 CA_ADAPTER_GATT_BTLE    |
719                 CA_ADAPTER_RFCOMM_BTEDR |
720                 CA_ADAPTER_NFC
721 #ifdef RA_ADAP
722                 | CA_ADAPTER_REMOTE_ACCESS
723 #endif
724                 | CA_ADAPTER_TCP
725             );
726     }
727
728     result = OC_STACK_OK;
729     OCStackResult tempResult = OC_STACK_OK;
730
731     for(size_t i = 0; i < size; i++ )
732     {
733         responseEndpoint.adapter = (CATransportAdapter_t)(adapter & CAConnTypes[i]);
734         if(responseEndpoint.adapter)
735         {
736             //The result is set to OC_STACK_OK only if OCSendResponse succeeds in sending the
737             //response on all the n/w interfaces else it is set to OC_STACK_ERROR
738             tempResult = OCSendResponse(&responseEndpoint, &responseInfo);
739         }
740         if(OC_STACK_OK != tempResult)
741         {
742             result = tempResult;
743         }
744     }
745 #else
746
747     OIC_LOG(INFO, TAG, "Calling OCSendResponse with:");
748     OIC_LOG_V(INFO, TAG, "\tEndpoint address: %s", responseEndpoint.addr);
749     OIC_LOG_V(INFO, TAG, "\tEndpoint adapter: %d", responseEndpoint.adapter);
750     OIC_LOG_V(INFO, TAG, "\tResponse result : %d", responseInfo.result);
751     OIC_LOG_V(INFO, TAG, "\tResponse for uri: %s", responseInfo.info.resourceUri);
752
753     result = OCSendResponse(&responseEndpoint, &responseInfo);
754 #endif
755
756     OICFree(responseInfo.info.payload);
757     OICFree(responseInfo.info.options);
758     //Delete the request
759     FindAndDeleteServerRequest(serverRequest);
760     return result;
761 }
762
763 /**
764  * Handler function for sending a response from multiple resources, such as a collection.
765  * Aggregates responses from multiple resource until all responses are received then sends the
766  * concatenated response
767  *
768  * TODO: Need to add a timeout in case a (remote?) resource does not respond
769  *
770  * @param ehResponse - pointer to the response from the resource
771  *
772  * @return
773  *     OCStackResult
774  */
775 OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
776 {
777     if(!ehResponse || !ehResponse->payload)
778     {
779         OIC_LOG(ERROR, TAG, "HandleAggregateResponse invalid parameters");
780         return OC_STACK_INVALID_PARAM;
781     }
782
783     OIC_LOG(INFO, TAG, "Inside HandleAggregateResponse");
784
785     OCServerRequest *serverRequest = GetServerRequestUsingHandle(ehResponse->requestHandle);
786     OCServerResponse *serverResponse = GetServerResponseUsingHandle(ehResponse->requestHandle);
787
788     OCStackResult stackRet = OC_STACK_ERROR;
789     if(serverRequest)
790     {
791         if(!serverResponse)
792         {
793             OIC_LOG(INFO, TAG, "This is the first response fragment");
794             stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
795             if (OC_STACK_OK != stackRet)
796             {
797                 OIC_LOG(ERROR, TAG, "Error adding server response");
798                 return stackRet;
799             }
800             VERIFY_NON_NULL(serverResponse);
801         }
802
803         if(ehResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION)
804         {
805             stackRet = OC_STACK_ERROR;
806             OIC_LOG(ERROR, TAG, "Error adding payload, as it was the incorrect type");
807             goto exit;
808         }
809
810         OCRepPayload *newPayload = OCRepPayloadBatchClone((OCRepPayload *)ehResponse->payload);
811
812         if(!serverResponse->payload)
813         {
814             serverResponse->payload = (OCPayload *)newPayload;
815         }
816         else
817         {
818             OCRepPayloadAppend((OCRepPayload*)serverResponse->payload,
819                     (OCRepPayload*)newPayload);
820         }
821
822         (serverRequest->numResponses)--;
823
824         if(serverRequest->numResponses == 0)
825         {
826             OIC_LOG(INFO, TAG, "This is the last response fragment");
827             ehResponse->payload = serverResponse->payload;
828             ehResponse->ehResult = OC_EH_OK;
829             stackRet = HandleSingleResponse(ehResponse);
830             //Delete the request and response
831             FindAndDeleteServerRequest(serverRequest);
832             FindAndDeleteServerResponse(serverResponse);
833         }
834         else
835         {
836             OIC_LOG(INFO, TAG, "More response fragments to come");
837             stackRet = OC_STACK_OK;
838         }
839     }
840 exit:
841
842     return stackRet;
843 }