Removed warnings from calls to OC_LOG_BUFFER from within stack.
[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
21 #include "ocstack.h"
22 #include "ocserverrequest.h"
23 #include "ocresourcehandler.h"
24
25
26 #include "cacommon.h"
27 #include "cainterface.h"
28
29 // Module Name
30 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
31
32 #define TAG  PCF("ocserverrequest")
33
34 static struct OCServerRequest * serverRequestList = NULL;
35 static struct OCServerResponse * serverResponseList = NULL;
36
37 OCServerRequest * GetServerRequestUsingToken (const CAToken_t token)
38 {
39     OCServerRequest * out = NULL;
40     LL_FOREACH (serverRequestList, out)
41     {
42         OC_LOG(INFO, TAG,PCF("comparing tokens"));
43         OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, CA_MAX_TOKEN_LEN);
44         OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->requestToken, CA_MAX_TOKEN_LEN);
45         if(memcmp(out->requestToken, token, CA_MAX_TOKEN_LEN) == 0)
46         {
47             return out;
48         }
49     }
50     OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
51     return NULL;
52 }
53
54 OCServerRequest * GetServerRequestUsingHandle (const OCServerRequest * handle)
55 {
56     OCServerRequest * out = NULL;
57     LL_FOREACH (serverRequestList, out)
58     {
59         if(out == handle)
60         {
61             return out;
62         }
63     }
64     OC_LOG(INFO, TAG, PCF("Server Request not found!!"));
65     return NULL;
66 }
67
68 OCServerResponse * GetServerResponseUsingHandle (const OCServerRequest * handle)
69 {
70     OCServerResponse * out = NULL;
71     LL_FOREACH (serverResponseList, out)
72     {
73         if(out->requestHandle == handle)
74         {
75             return out;
76         }
77     }
78     OC_LOG(INFO, TAG, PCF("Server Response not found!!"));
79     return NULL;
80 }
81
82 OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
83         uint8_t delayedResNeeded, uint8_t secured, uint8_t notificationFlag, OCMethod method,
84         uint8_t numRcvdVendorSpecificHeaderOptions, uint32_t observationOption,
85         OCQualityOfService qos, unsigned char * query,
86         OCHeaderOption * rcvdVendorSpecificHeaderOptions,
87         unsigned char * reqJSONPayload, CAToken_t * requestToken,
88         OCDevAddr * requesterAddr, unsigned char * resourceUrl, size_t reqTotalSize,
89         CAAddress_t *addressInfo, CAConnectivityType_t connectivityType)
90 {
91     OCServerRequest * serverRequest = NULL;
92
93     //Note: OCServerRequest includes 1 byte for the JSON Payload.  payloadSize is calculated
94     //as the required length of the string, so this will result in enough room for the
95     //null terminator as well.
96     serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) + reqTotalSize - 1);
97     VERIFY_NON_NULL(serverRequest);
98
99     serverRequest->coapID = coapID;
100     serverRequest->delayedResNeeded = delayedResNeeded;
101     serverRequest->secured = secured;
102     serverRequest->notificationFlag = notificationFlag;
103
104     serverRequest->method = method;
105     serverRequest->numRcvdVendorSpecificHeaderOptions = numRcvdVendorSpecificHeaderOptions;
106     serverRequest->observationOption = observationOption;
107     serverRequest->observeResult = OC_STACK_ERROR;
108     serverRequest->qos = qos;
109     serverRequest->ehResponseHandler = HandleSingleResponse;
110     serverRequest->numResponses = 1;
111     if(query)
112     {
113         memcpy(serverRequest->query, query, strlen((const char *)query) + 1);
114     }
115     if(rcvdVendorSpecificHeaderOptions)
116     {
117         memcpy(serverRequest->rcvdVendorSpecificHeaderOptions, rcvdVendorSpecificHeaderOptions,
118             MAX_HEADER_OPTIONS * sizeof(OCHeaderOption));
119     }
120     if(reqJSONPayload)
121     {
122         // destination is at least 1 greater than the source, so a NULL always exists in the
123         // last character
124         strncpy((char*)serverRequest->reqJSONPayload,
125                 (const char*)reqJSONPayload, reqTotalSize - 1);
126     }
127     serverRequest->requestComplete = 0;
128     if(requestToken)
129     {
130         serverRequest->requestToken = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
131         VERIFY_NON_NULL (serverRequest->requestToken);
132         memset(serverRequest->requestToken, 0, CA_MAX_TOKEN_LEN + 1);
133         memcpy(serverRequest->requestToken, *requestToken, CA_MAX_TOKEN_LEN);
134     }
135     if(requesterAddr)
136     {
137         memcpy(&serverRequest->requesterAddr, requesterAddr, sizeof(OCDevAddr));
138     }
139     if(resourceUrl)
140     {
141         memcpy(serverRequest->resourceUrl, resourceUrl, strlen((const char *)resourceUrl) + 1);
142     }
143     if (addressInfo)
144     {
145         serverRequest->addressInfo = *addressInfo;
146     }
147     serverRequest->connectivityType = connectivityType;
148
149     *request = serverRequest;
150     OC_LOG(INFO, TAG, PCF("Server Request Added!!"));
151     LL_APPEND (serverRequestList, serverRequest);
152     return OC_STACK_OK;
153
154 exit:
155     if (serverRequest)
156     {
157         OCFree(serverRequest);
158         serverRequest = NULL;
159     }
160     *request = NULL;
161     return OC_STACK_NO_MEMORY;
162 }
163
164 OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle requestHandle)
165 {
166     OCServerResponse * serverResponse = NULL;
167
168     serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse));
169     VERIFY_NON_NULL(serverResponse);
170
171     serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
172     VERIFY_NON_NULL(serverResponse->payload);
173     memset(serverResponse->payload, 0, MAX_RESPONSE_LENGTH);
174
175     serverResponse->remainingPayloadSize = MAX_RESPONSE_LENGTH;
176     serverResponse->requestHandle = requestHandle;
177
178     *response = serverResponse;
179     OC_LOG(INFO, TAG, PCF("Server Response Added!!"));
180     LL_APPEND (serverResponseList, serverResponse);
181     return OC_STACK_OK;
182
183 exit:
184     if (serverResponse)
185     {
186         OCFree(serverResponse);
187         serverResponse = NULL;
188     }
189     *response = NULL;
190     return OC_STACK_NO_MEMORY;
191 }
192
193 // Form the OCEntityHandlerRequest struct
194 OCStackResult FormOCEntityHandlerRequest(OCEntityHandlerRequest * entityHandlerRequest, OCRequestHandle request,
195         OCMethod method, OCResourceHandle resource, unsigned char * queryBuf, unsigned char * bufReqPayload,
196         uint8_t numVendorOptions, OCHeaderOption * vendorOptions, OCObserveAction observeAction,
197         OCObservationId observeID)
198 {
199     if (entityHandlerRequest)
200     {
201         memset(entityHandlerRequest, 0, sizeof(OCEntityHandlerRequest));
202         entityHandlerRequest->requestHandle = request;
203         entityHandlerRequest->method = method;
204         entityHandlerRequest->resource = (OCResourceHandle) resource;
205         entityHandlerRequest->query = queryBuf;
206         entityHandlerRequest->reqJSONPayload = bufReqPayload;
207         entityHandlerRequest->numRcvdVendorSpecificHeaderOptions = numVendorOptions;
208         entityHandlerRequest->rcvdVendorSpecificHeaderOptions = vendorOptions;
209
210         entityHandlerRequest->obsInfo.action = observeAction;
211         entityHandlerRequest->obsInfo.obsId = observeID;
212         return OC_STACK_OK;
213     }
214
215     return OC_STACK_INVALID_PARAM;
216 }
217
218 void FindAndDeleteServerResponse(OCServerResponse * serverResponse)
219 {
220     OCServerResponse* tmp;
221     if(serverResponse)
222     {
223         LL_FOREACH(serverResponseList, tmp)
224         {
225             if (serverResponse == tmp)
226             {
227                 DeleteServerResponse(tmp);
228                 return;
229             }
230         }
231     }
232 }
233
234 void DeleteServerResponse(OCServerResponse * serverResponse)
235 {
236     if(serverResponse) {
237         LL_DELETE(serverResponseList, serverResponse);
238         OCFree(serverResponse->payload);
239         OCFree(serverResponse);
240         OC_LOG(INFO, TAG, PCF("Server Response Removed!!"));
241     }
242 }
243
244 void FindAndDeleteServerRequest(OCServerRequest * serverRequest)
245 {
246     OCServerRequest* tmp;
247     if(serverRequest)
248     {
249         LL_FOREACH(serverRequestList, tmp)
250         {
251             if (serverRequest == tmp)
252             {
253                 DeleteServerRequest(tmp);
254                 return;
255             }
256         }
257     }
258 }
259
260 void DeleteServerRequest(OCServerRequest * serverRequest)
261 {
262     if(serverRequest) {
263         LL_DELETE(serverRequestList, serverRequest);
264         OCFree(serverRequest);
265         serverRequest = NULL;
266         OC_LOG(INFO, TAG, PCF("Server Request Removed!!"));
267     }
268 }
269
270 OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
271 {
272     OCStackResult result = OC_STACK_ERROR;
273     CARemoteEndpoint_t responseEndpoint = {0};
274     CAResponseInfo_t responseInfo = {0};
275     CAHeaderOption_t* optionsPointer;
276
277     OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
278
279     OCServerRequest *serverRequest = (OCServerRequest *)ehResponse->requestHandle;
280
281     // Copy the address
282     responseEndpoint.resourceUri      = (CAURI_t) serverRequest->resourceUrl;
283     responseEndpoint.addressInfo      = serverRequest->addressInfo;
284     responseEndpoint.connectivityType = serverRequest->connectivityType;
285     responseEndpoint.isSecured        = (CABool_t) serverRequest->secured;
286
287     // Copy the info
288     switch (ehResponse->ehResult)
289     {
290         case OC_EH_OK:
291             responseInfo.result = CA_SUCCESS;
292             break;
293         case OC_EH_ERROR:
294             responseInfo.result = CA_BAD_REQ;
295             break;
296         case OC_EH_RESOURCE_CREATED:
297             responseInfo.result = CA_CREATED;
298             break;
299         case OC_EH_RESOURCE_DELETED:
300             responseInfo.result = CA_DELETED;
301             break;
302         case OC_EH_SLOW:
303             responseInfo.result = CA_SUCCESS;
304             break;
305         case OC_EH_FORBIDDEN:
306             responseInfo.result = CA_BAD_REQ;
307             break;
308         default:
309             responseInfo.result = CA_BAD_REQ;
310             break;
311     }
312
313     // TODO-CA: Need to do something with a slow response if a confirmed request was sent
314     // from client
315
316     // TODO-CA:  Need to handle CA_MSG_RESET and CA_MSG_ACKNOWLEDGE
317     switch (serverRequest->qos)
318     {
319         case OC_LOW_QOS:
320             responseInfo.info.type = CA_MSG_NONCONFIRM;
321             break;
322         case OC_MEDIUM_QOS:
323             responseInfo.info.type = CA_MSG_NONCONFIRM;
324             break;
325         case OC_HIGH_QOS:
326             responseInfo.info.type = CA_MSG_CONFIRM;
327             break;
328         case OC_NA_QOS:
329             responseInfo.info.type = CA_MSG_NONCONFIRM;
330             break;
331         default:
332             responseInfo.info.type = CA_MSG_NONCONFIRM;
333             break;
334     }
335
336     responseInfo.info.token = (CAToken_t)OCMalloc(CA_MAX_TOKEN_LEN+1);
337     if (!responseInfo.info.token)
338     {
339         OC_LOG(FATAL, TAG, "Response Info Token is NULL");
340         return result;
341     }
342     memset(responseInfo.info.token, 0, CA_MAX_TOKEN_LEN + 1);
343     memcpy(responseInfo.info.token, serverRequest->requestToken, CA_MAX_TOKEN_LEN);
344
345     if(serverRequest->observeResult == OC_STACK_OK)
346     {
347         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions + 1;
348     }
349     else
350     {
351         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions;
352     }
353
354     responseInfo.info.options = (CAHeaderOption_t *)
355                                     malloc(sizeof(CAHeaderOption_t) * responseInfo.info.numOptions);
356
357     optionsPointer = responseInfo.info.options;
358
359     if(serverRequest->observeResult == OC_STACK_OK)
360     {
361         responseInfo.info.numOptions = ehResponse->numSendVendorSpecificHeaderOptions + 1;
362     }
363
364     // TODO-CA Revisit this logic
365     if(serverRequest->observeResult == OC_STACK_OK)
366     {
367         responseInfo.info.options[0].protocolID = CA_COAP_ID;
368         responseInfo.info.options[0].optionID = COAP_OPTION_OBSERVE;
369         responseInfo.info.options[0].optionLength = sizeof(uint32_t);
370         memcpy(responseInfo.info.options[0].optionData,
371                 &(serverRequest->observationOption), sizeof(uint32_t));
372
373         // Point to the next header option before copying vender specific header options
374         optionsPointer += 1;
375     }
376
377     if (ehResponse->numSendVendorSpecificHeaderOptions)
378     {
379         memcpy(optionsPointer, ehResponse->sendVendorSpecificHeaderOptions,
380                         sizeof(OCHeaderOption) * ehResponse->numSendVendorSpecificHeaderOptions);
381     }
382
383     // Allocate memory for the payload.
384     char *payload = (char *)OCMalloc(MAX_RESPONSE_LENGTH);
385     if(!payload)
386     {
387         return OC_STACK_NO_MEMORY;
388     }
389     memset(payload, 0, MAX_RESPONSE_LENGTH);
390     // Put the JSON prefix and suffix around the payload
391     strcpy(payload, (const char *)OC_JSON_PREFIX);
392     strcat(payload, (const char *)ehResponse->payload);
393     strcat(payload, (const char *)OC_JSON_SUFFIX);
394     responseInfo.info.payload = (CAPayload_t)payload;
395
396     CAResult_t caResult = CASendResponse(&responseEndpoint, &responseInfo);
397     if(caResult != CA_STATUS_OK)
398     {
399         OC_LOG(ERROR, TAG, PCF("CASendResponse error"));
400     }
401     else
402     {
403         result = OC_STACK_OK;
404     }
405
406     OCFree(payload);
407     //Delete the request
408     FindAndDeleteServerRequest(serverRequest);
409     return result;
410 }
411
412 OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
413 {
414     OCStackResult stackRet = OC_STACK_ERROR;
415     OCServerRequest * serverRequest = NULL;
416     OCServerResponse * serverResponse = NULL;
417
418     OC_LOG_V(INFO, TAG, "Inside HandleAggregateResponse: %s", ehResponse->payload);
419
420     serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
421     serverResponse = GetServerResponseUsingHandle((OCServerRequest *)ehResponse->requestHandle);
422
423     if(serverRequest)
424     {
425         if(!serverResponse)
426         {
427             OC_LOG(INFO, TAG, PCF("This is the first response fragment"));
428             stackRet = AddServerResponse(&serverResponse, ehResponse->requestHandle);
429             if (OC_STACK_OK != stackRet)
430             {
431                 OC_LOG(ERROR, TAG, PCF("Error adding server response"));
432                 return stackRet;
433             }
434             VERIFY_NON_NULL(serverResponse);
435             VERIFY_NON_NULL(serverResponse->payload);
436         }
437
438         if((serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 1 &&
439                 serverRequest->numResponses == 1) ||
440                 (serverResponse->remainingPayloadSize >= ehResponse->payloadSize + 2 &&
441                         serverRequest->numResponses > 1))
442         {
443             OC_LOG(INFO, TAG, PCF("There is room in response buffer"));
444             // append
445             snprintf((char *)serverResponse->payload, serverResponse->remainingPayloadSize, "%s%s", (char *)serverResponse->payload, (char *)ehResponse->payload);
446             OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
447             serverResponse->remainingPayloadSize -= ehResponse->payloadSize;
448             (serverRequest->numResponses)--;
449             if(serverRequest->numResponses == 0)
450             {
451                 OC_LOG(INFO, TAG, PCF("This is the last response fragment"));
452                 ehResponse->payload = serverResponse->payload;
453                 ehResponse->payloadSize = strlen((char *) serverResponse->payload) + 1;
454                 stackRet = HandleSingleResponse(ehResponse);
455                 //Delete the request and response
456                 FindAndDeleteServerRequest(serverRequest);
457                 FindAndDeleteServerResponse(serverResponse);
458             }
459             else
460             {
461                 OC_LOG(INFO, TAG, PCF("More response fragment to come"));
462                 // TODO: we should consider using strcat rather than setting a char by char here!
463                 snprintf((char *)serverResponse->payload, serverResponse->remainingPayloadSize, "%s%c", (char *)serverResponse->payload,OC_JSON_SEPARATOR);
464                 OC_LOG_V(INFO, TAG, "Current aggregated response  ...%s", serverResponse->payload);
465                 (serverResponse->remainingPayloadSize)--;
466                 stackRet = OC_STACK_OK;
467             }
468         }
469         else
470         {
471             OC_LOG(INFO, TAG, PCF("No room in response buffer"));
472             //Delete the request and response
473             FindAndDeleteServerRequest(serverRequest);
474             FindAndDeleteServerResponse(serverResponse);
475             stackRet = OC_STACK_NO_MEMORY;
476         }
477     }
478 exit:
479     return stackRet;
480 }