RESET/ACK code review update.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / camessagehandler_singlethread.c
1 /******************************************************************
2  *
3  * Copyright 2014 Samsung Electronics 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 <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdint.h>
25
26 #include "cainterface.h"
27 #include "camessagehandler_singlethread.h"
28 #include "caremotehandler.h"
29 #include "cainterfacecontroller_singlethread.h"
30 #include "caprotocolmessage.h"
31 #include "caretransmission_singlethread.h"
32 #include "logger.h"
33 #include "config.h" /* for coap protocol */
34 #include "oic_malloc.h"
35
36 #define TAG "CAMH_ST"
37
38 #define CA_MAX_RT_ARRAY_SIZE    3
39
40 typedef enum
41 {
42     SEND_TYPE_MULTICAST = 0, SEND_TYPE_UNICAST
43 } CASendDataType_t;
44
45 typedef struct
46 {
47     CASendDataType_t type;
48     CARemoteEndpoint_t *remoteEndpoint;
49     CARequestInfo_t *requestInfo;
50     CAResponseInfo_t *responseInfo;
51     CAHeaderOption_t *options;
52     uint8_t numOptions;
53 } CAData_t;
54
55
56 static CARetransmission_t g_retransmissionContext;
57
58 // handler field
59 static CARequestCallback g_requestHandler = NULL;
60 static CAResponseCallback g_responseHandler = NULL;
61
62 static void CATimeoutCallback(const CARemoteEndpoint_t *endpoint, const void *pdu, uint32_t size)
63 {
64     OIC_LOG(DEBUG, TAG, "IN");
65     CARemoteEndpoint_t* ep = CACloneRemoteEndpoint(endpoint);
66     if (NULL == ep)
67     {
68         OIC_LOG(ERROR, TAG, "clone failed");
69         return;
70     }
71
72     CAResponseInfo_t* resInfo = (CAResponseInfo_t*) OICCalloc(1, sizeof(CAResponseInfo_t));
73
74     if (NULL == resInfo)
75     {
76         OIC_LOG(ERROR, TAG, "calloc failed");
77         CADestroyRemoteEndpointInternal(ep);
78         return;
79     }
80
81     resInfo->result = CA_RETRANSMIT_TIMEOUT;
82     resInfo->info.type = CAGetMessageTypeFromPduBinaryData(pdu, size);
83     resInfo->info.messageId = CAGetMessageIdFromPduBinaryData(pdu, size);
84
85     if (g_responseHandler)
86     {
87         g_responseHandler(ep, resInfo);
88     }
89
90     CADestroyRemoteEndpointInternal(ep);
91     OICFree(resInfo);
92
93     OIC_LOG(DEBUG, TAG, "OUT");
94 }
95 static void CAProcessData(const CAData_t *data)
96 {
97     OIC_LOG(DEBUG, TAG, "IN");
98     VERIFY_NON_NULL_VOID(data, TAG, "data");
99     VERIFY_NON_NULL_VOID(data->remoteEndpoint, TAG, "remoteEndpoint");
100
101     CAResult_t res = CA_STATUS_FAILED;
102
103     CASendDataType_t type = data->type;
104
105     if (SEND_TYPE_UNICAST == type)
106     {
107         coap_pdu_t *pdu = NULL;
108
109         if (NULL != data->requestInfo)
110         {
111             OIC_LOG(DEBUG, TAG, "reqInfo avlbl");
112
113             pdu = (coap_pdu_t *) CAGeneratePDU(data->remoteEndpoint->resourceUri,
114                                                data->requestInfo->method,
115                                                data->requestInfo->info);
116         }
117         else if (NULL != data->responseInfo)
118         {
119             OIC_LOG(DEBUG, TAG, "resInfo avlbl");
120
121             pdu = (coap_pdu_t *) CAGeneratePDU(data->remoteEndpoint->resourceUri,
122                                                data->responseInfo->result,
123                                                data->responseInfo->info);
124         }
125         else
126         {
127             OIC_LOG(DEBUG, TAG, "request info, response info is empty");
128         }
129
130         // interface controller function call.
131         if (NULL != pdu)
132         {
133             CALogPDUInfo(pdu);
134
135             res = CASendUnicastData(data->remoteEndpoint, pdu->hdr, pdu->length);
136             if (CA_STATUS_OK != res)
137             {
138                 OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
139                 coap_delete_pdu(pdu);
140                 return;
141             }
142             // for retransmission
143             res = CARetransmissionSentData(&g_retransmissionContext, data->remoteEndpoint, pdu->hdr,
144                                            pdu->length);
145             if (CA_STATUS_OK != res)
146             {
147                 OIC_LOG_V(INFO, TAG, "retransmissions will not be working: %d", res);
148                 coap_delete_pdu(pdu);
149                 return;
150             }
151
152             coap_delete_pdu(pdu);
153         }
154     }
155     else if (SEND_TYPE_MULTICAST == type)
156     {
157         OIC_LOG(DEBUG, TAG, "both requestInfo & responseInfo is not available");
158
159         CAInfo_t info = { 0 };
160
161         info.options = data->options;
162         info.numOptions = data->numOptions;
163         info.token = data->requestInfo->info.token;
164         info.tokenLength = data->requestInfo->info.tokenLength;
165         info.type = data->requestInfo->info.type;
166         info.messageId = data->requestInfo->info.messageId;
167         info.payload = data->requestInfo->info.payload;
168
169         coap_pdu_t *pdu = (coap_pdu_t *) CAGeneratePDU(data->remoteEndpoint->resourceUri, CA_GET,
170                                                        info);
171
172         if (NULL != pdu)
173         {
174             CALogPDUInfo(pdu);
175             res = CASendMulticastData(pdu->hdr, pdu->length);
176             if(CA_STATUS_OK != res)
177             {
178                 OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
179                 coap_delete_pdu(pdu);
180                 return;
181             }
182
183             coap_delete_pdu(pdu);
184         }
185     }
186
187     OIC_LOG(DEBUG, TAG, "OUT");
188 }
189
190 static void CAReceivedPacketCallback(CARemoteEndpoint_t *endpoint, void *data, uint32_t dataLen)
191 {
192     OIC_LOG(DEBUG, TAG, "IN");
193     VERIFY_NON_NULL_VOID(data, TAG, "data");
194
195     uint32_t code = CA_NOT_FOUND;
196     coap_pdu_t *pdu = (coap_pdu_t *) CAParsePDU((const char *) data, dataLen, &code);
197
198     if (NULL == pdu)
199     {
200         OIC_LOG(ERROR, TAG, "Parse PDU failed");
201         return;
202     }
203
204     char uri[CA_MAX_URI_LENGTH] = { 0, };
205     uint32_t bufLen = sizeof(uri);
206
207     if (CA_GET == code || CA_POST == code || CA_PUT == code || CA_DELETE == code)
208     {
209         CARequestInfo_t *ReqInfo = (CARequestInfo_t *) OICCalloc(1, sizeof(CARequestInfo_t));
210         if (NULL == ReqInfo)
211         {
212             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, Memory allocation failed!");
213             coap_delete_pdu(pdu);
214             return;
215         }
216
217         CAResult_t res = CAGetRequestInfoFromPDU(pdu, ReqInfo, uri, bufLen);
218         if (CA_STATUS_OK != res)
219         {
220             OIC_LOG_V(ERROR, TAG, "CAGetRequestInfoFromPDU failed : %d", res);
221             OICFree(ReqInfo);
222             coap_delete_pdu(pdu);
223             return;
224         }
225
226         if (NULL != ReqInfo->info.options)
227         {
228             for (uint32_t i = 0; i < ReqInfo->info.numOptions; i++)
229             {
230                 OIC_LOG_V(DEBUG, TAG, "optionID: %d", ReqInfo->info.options[i].optionID);
231
232                 OIC_LOG_V(DEBUG, TAG, "list: %s", ReqInfo->info.options[i].optionData);
233             }
234         }
235
236         if (NULL != ReqInfo->info.payload)
237         {
238             OIC_LOG_V(DEBUG, TAG, "Request- payload: %s", ReqInfo->info.payload);
239         }
240
241         OIC_LOG_V(DEBUG, TAG, "code: %d", ReqInfo->method);
242         OIC_LOG(DEBUG, TAG, "token:");
243         OIC_LOG_BUFFER(DEBUG, TAG, (const uint8_t *) ReqInfo->info.token, CA_MAX_TOKEN_LEN);
244         if (NULL != endpoint)
245         {
246             endpoint->resourceUri = (char *) OICMalloc(bufLen + 1);
247             if (NULL == endpoint->resourceUri)
248             {
249                 OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, Memory allocation failed!");
250                 OICFree(ReqInfo);
251                 coap_delete_pdu(pdu);
252                 return;
253             }
254             memcpy(endpoint->resourceUri, uri, bufLen);
255             endpoint->resourceUri[bufLen] = '\0';
256             OIC_LOG_V(DEBUG, TAG, "URI : %s", endpoint->resourceUri);
257         }
258
259         if (ReqInfo)
260         {
261             if (g_requestHandler)
262             {
263                 g_requestHandler(endpoint, ReqInfo);
264             }
265
266             CADestroyRequestInfoInternal(ReqInfo);
267         }
268     }
269     else
270     {
271         CAResponseInfo_t *ResInfo = (CAResponseInfo_t *) OICCalloc(1, sizeof(CAResponseInfo_t));
272         if (NULL == ResInfo)
273         {
274             OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, Memory allocation failed!");
275             coap_delete_pdu(pdu);
276             return;
277         }
278
279         CAResult_t res = CAGetResponseInfoFromPDU(pdu, ResInfo, uri, bufLen);
280         if (CA_STATUS_OK != res)
281         {
282             OIC_LOG_V(ERROR, TAG, "CAGetResponseInfoFromPDU failed : %d", res);
283             OICFree(ResInfo);
284             coap_delete_pdu(pdu);
285             return;
286         }
287
288         if (NULL != ResInfo->info.options)
289         {
290             for (uint32_t i = 0; i < ResInfo->info.numOptions; i++)
291             {
292                 OIC_LOG_V(DEBUG, TAG, "optionID: %d", ResInfo->info.options[i].optionID);
293
294                 OIC_LOG_V(DEBUG, TAG, "list: %s", ResInfo->info.options[i].optionData);
295             }
296         }
297
298         if (NULL != ResInfo->info.payload)
299         {
300             OIC_LOG_V(DEBUG, TAG, "payload: %s", ResInfo->info.payload);
301         }
302         OIC_LOG_V(DEBUG, TAG, "code: %d", ResInfo->result);
303
304         if (NULL != endpoint)
305         {
306             endpoint->resourceUri = (char *) OICMalloc(bufLen + 1);
307             if (NULL == endpoint->resourceUri)
308             {
309                 OIC_LOG(ERROR, TAG, "CAReceivedPacketCallback, Memory allocation failed !");
310                 OICFree(ResInfo);
311                 coap_delete_pdu(pdu);
312                 return;
313             }
314             memcpy(endpoint->resourceUri, uri, bufLen);
315             endpoint->resourceUri[bufLen] = '\0';
316             OIC_LOG_V(DEBUG, TAG, "URI : %s", endpoint->resourceUri);
317         }
318
319         // for retransmission
320         void *retransmissionPdu = NULL;
321         CARetransmissionReceivedData(&g_retransmissionContext, endpoint, pdu->hdr, pdu->length,
322                                      &retransmissionPdu);
323
324         // get token from saved data in retransmission list
325         if (retransmissionPdu && CA_EMPTY == code)
326         {
327             CAResult_t res = CAGetTokenFromPDU((const coap_hdr_t *)retransmissionPdu,
328                                                &(ResInfo->info));
329             if(res != CA_STATUS_OK)
330             {
331                 OIC_LOG(ERROR, TAG, "fail to get Token from retransmission list");
332                 OICFree(ResInfo->info.token);
333             }
334         }
335         OICFree(retransmissionPdu);
336
337         if (NULL != ResInfo)
338         {
339             if (g_responseHandler)
340             {
341                 g_responseHandler(endpoint, ResInfo);
342             }
343             CADestroyResponseInfoInternal(ResInfo);
344         }
345     }
346
347     if (endpoint && endpoint->resourceUri)
348     {
349         OICFree(endpoint->resourceUri);
350         endpoint->resourceUri = NULL;
351     }
352     if (pdu)
353     {
354         coap_delete_pdu(pdu);
355     }
356     OIC_LOG(DEBUG, TAG, "OUT");
357 }
358
359 static void CANetworkChangedCallback(CALocalConnectivity_t *info, CANetworkStatus_t status)
360 {
361     OIC_LOG(DEBUG, TAG, "IN");
362
363     OIC_LOG(DEBUG, TAG, "OUT");
364 }
365
366 void CAHandleRequestResponseCallbacks()
367 {
368     CAReadData();
369     CARetransmissionBaseRoutine((void *)&g_retransmissionContext);
370 }
371
372 CAResult_t CADetachRequestMessage(const CARemoteEndpoint_t *object, const CARequestInfo_t *request)
373 {
374     OIC_LOG(DEBUG, TAG, "IN");
375
376     VERIFY_NON_NULL(object, TAG, "object");
377     VERIFY_NON_NULL(request, TAG, "request");
378
379     // If max retransmission queue is reached, then don't handle new request
380     if (CA_MAX_RT_ARRAY_SIZE == u_arraylist_length(g_retransmissionContext.dataList))
381     {
382         OIC_LOG(ERROR, TAG, "max RT queue size reached!");
383         return CA_SEND_FAILED;
384     }
385
386     // allocate & initialize
387     CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
388     CA_MEMORY_ALLOC_CHECK(data);
389
390     // save data
391     data->type = SEND_TYPE_UNICAST;
392     data->remoteEndpoint = object;
393     data->requestInfo = request;
394     data->responseInfo = NULL;
395
396     CAProcessData(data);
397     OICFree(data);
398     OIC_LOG(DEBUG, TAG, "OUT");
399     return CA_STATUS_OK;
400
401 // memory error label.
402 memory_error_exit:
403     OICFree(data);
404     OIC_LOG(DEBUG, TAG, "OUT");
405     return CA_MEMORY_ALLOC_FAILED;
406 }
407
408 CAResult_t CADetachRequestToAllMessage(const CAGroupEndpoint_t *object,
409                                        const CARequestInfo_t *request)
410 {
411     OIC_LOG(DEBUG, TAG, "IN");
412
413     if (NULL == object || NULL == request || NULL == object->resourceUri)
414     {
415         return CA_STATUS_INVALID_PARAM;
416     }
417
418     if ((request->method < CA_GET) || (request->method > CA_DELETE))
419     {
420         OIC_LOG(ERROR, TAG, "Invalid method type!");
421
422         return CA_STATUS_INVALID_PARAM;
423     }
424
425     // allocate & initialize
426     CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
427     CA_MEMORY_ALLOC_CHECK(data);
428
429     CAAddress_t addr = {0};
430     CARemoteEndpoint_t *remoteEndpoint = CACreateRemoteEndpointInternal(object->resourceUri, addr,
431                                                                         object->connectivityType);
432
433     // save data
434     data->type = SEND_TYPE_MULTICAST;
435     data->remoteEndpoint = remoteEndpoint;
436     data->requestInfo = request;
437     data->responseInfo = NULL;
438
439     CAProcessData(data);
440     CADestroyRemoteEndpointInternal(remoteEndpoint);
441
442     OICFree(data);
443     OIC_LOG(DEBUG, TAG, "OUT");
444     return CA_STATUS_OK;
445
446 // memory error label.
447 memory_error_exit:
448
449     OICFree(data);
450     OIC_LOG(DEBUG, TAG, "OUT");
451     return CA_MEMORY_ALLOC_FAILED;
452 }
453
454 CAResult_t CADetachResponseMessage(const CARemoteEndpoint_t *object,
455                                    const CAResponseInfo_t *response)
456 {
457     OIC_LOG(DEBUG, TAG, "IN");
458     VERIFY_NON_NULL(object, TAG, "object");
459     VERIFY_NON_NULL(response, TAG, "response");
460
461     // allocate & initialize
462     CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
463     CA_MEMORY_ALLOC_CHECK(data);
464
465     // save data
466     data->type = SEND_TYPE_UNICAST;
467     data->remoteEndpoint = object;
468     data->requestInfo = NULL;
469     data->responseInfo = response;
470
471     CAProcessData(data);
472
473     OICFree(data);
474     OIC_LOG(DEBUG, TAG, "OUT");
475     return CA_STATUS_OK;
476
477 // memory error label.
478 memory_error_exit:
479     OICFree(data);
480     OIC_LOG(DEBUG, TAG, "OUT");
481
482     return CA_MEMORY_ALLOC_FAILED;
483 }
484
485 CAResult_t CADetachMessageResourceUri(const CAURI_t resourceUri, const CAToken_t token,
486                                       uint8_t tokenLength, const CAHeaderOption_t *options,
487                                       uint8_t numOptions)
488 {
489     OIC_LOG(DEBUG, TAG, "IN");
490     VERIFY_NON_NULL(resourceUri, TAG, "resourceUri is NULL");
491     VERIFY_NON_NULL(token, TAG, "Token is NULL");
492
493     // allocate & initialize
494     CAData_t *data = (CAData_t *) OICCalloc(1, sizeof(CAData_t));
495     CA_MEMORY_ALLOC_CHECK(data);
496
497     CAAddress_t addr = {0};
498     CARemoteEndpoint_t *remoteEndpoint =
499             CACreateRemoteEndpointInternal(resourceUri, addr,
500                                            CA_ETHERNET | CA_WIFI | CA_EDR | CA_LE);
501
502     // create request info
503     CARequestInfo_t *reqInfo = (CARequestInfo_t *) OICCalloc(1, sizeof(CARequestInfo_t));
504     CA_MEMORY_ALLOC_CHECK(reqInfo);
505
506     // save request info data
507     reqInfo->method = CA_GET;
508     reqInfo->info.type = CA_MSG_NONCONFIRM;
509
510     reqInfo->info.token = token;
511     reqInfo->info.tokenLength = tokenLength;
512
513     // save data
514     data->type = SEND_TYPE_MULTICAST;
515     data->remoteEndpoint = remoteEndpoint;
516     data->requestInfo = reqInfo;
517
518     data->responseInfo = NULL;
519     data->options = NULL;
520     data->numOptions = 0;
521     CAHeaderOption_t *headerOption = NULL;
522     if (NULL != options && numOptions > 0)
523     {
524         // copy data
525         headerOption = (CAHeaderOption_t *) OICMalloc(sizeof(CAHeaderOption_t) * numOptions);
526         CA_MEMORY_ALLOC_CHECK(headerOption);
527         memcpy(headerOption, options, sizeof(CAHeaderOption_t) * numOptions);
528
529         data->options = headerOption;
530         data->numOptions = numOptions;
531     }
532
533     CAProcessData(data);
534
535     CADestroyRemoteEndpoint(remoteEndpoint);
536     OICFree(headerOption);
537     OICFree(data);
538     OICFree(reqInfo);
539     OIC_LOG(DEBUG, TAG, "OUT");
540     return CA_STATUS_OK;
541
542 // memory error label.
543 memory_error_exit:
544
545     CADestroyRemoteEndpointInternal(remoteEndpoint);
546
547     OICFree(reqInfo);
548     OICFree(data);
549     OIC_LOG(DEBUG, TAG, "OUT");
550     return CA_MEMORY_ALLOC_FAILED;
551 }
552
553 void CASetRequestResponseCallbacks(CARequestCallback ReqHandler, CAResponseCallback RespHandler)
554 {
555     OIC_LOG(DEBUG, TAG, "IN");
556     g_requestHandler = ReqHandler;
557     g_responseHandler = RespHandler;
558     OIC_LOG(DEBUG, TAG, "OUT");
559 }
560
561 CAResult_t CAInitializeMessageHandler()
562 {
563     OIC_LOG(DEBUG, TAG, "IN");
564     CASetPacketReceivedCallback(CAReceivedPacketCallback);
565
566     CASetNetworkChangeCallback(CANetworkChangedCallback);
567
568     // retransmission initialize
569     CARetransmissionInitialize(&g_retransmissionContext, CASendUnicastData,
570                                CATimeoutCallback, NULL);
571
572     CAInitializeAdapters();
573     OIC_LOG(DEBUG, TAG, "OUT");
574     return CA_STATUS_OK;
575 }
576
577 void CATerminateMessageHandler()
578 {
579     OIC_LOG(DEBUG, TAG, "IN");
580     // terminate interface adapters by controller
581     CATerminateAdapters();
582
583     // stop retransmission
584     CARetransmissionStop(&g_retransmissionContext);
585     CARetransmissionDestroy(&g_retransmissionContext);
586
587     OIC_LOG(DEBUG, TAG, "OUT");
588 }
589
590 void CALogPDUInfo(coap_pdu_t *pdu)
591 {
592     VERIFY_NON_NULL_VOID(pdu, TAG, "pdu");
593
594     OIC_LOG_V(DEBUG, TAG, "PDU Maker - payload : %s", pdu->data);
595
596     OIC_LOG_V(DEBUG, TAG, "PDU Maker - type : %d", pdu->hdr->type);
597
598     OIC_LOG_V(DEBUG, TAG, "PDU Maker - code : %d", pdu->hdr->code);
599
600     OIC_LOG_V(DEBUG, TAG, "PDU Maker - id : %d", ntohs(pdu->hdr->id));
601
602     OIC_LOG(DEBUG, TAG, "PDU Maker - token :");
603
604     OIC_LOG_BUFFER(DEBUG, TAG, pdu->hdr->token, pdu->hdr->token_length);
605 }
606