Update snapshot(2018-01-10)
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipadapter.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 #include "caipadapter.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdint.h>
26
27 #include "caipnwmonitor.h"
28 #include "caipinterface.h"
29 #include "caqueueingthread.h"
30 #include "caadapterutils.h"
31 #ifdef __WITH_DTLS__
32 #include "ca_adapter_net_ssl.h"
33 #ifdef WITH_TCP
34 #include "catcpinterface.h"
35 #endif
36 #endif
37
38 #include "octhread.h"
39 #include "uarraylist.h"
40 #include "caremotehandler.h"
41 #include "logger.h"
42 #include "oic_malloc.h"
43 #include "oic_string.h"
44
45 /**
46  * Logging tag for module name.
47  */
48 #define TAG "OIC_CA_IP_ADAP"
49
50 #ifndef SINGLE_THREAD
51 /**
52  * Holds inter thread ip data information.
53  */
54 typedef struct
55 {
56     CAEndpoint_t *remoteEndpoint;
57     void *data;
58     uint32_t dataLen;
59     bool isMulticast;
60 } CAIPData_t;
61
62 /**
63  * Queue handle for Send Data.
64  */
65 static CAQueueingThread_t *g_sendQueueHandle = NULL;
66 #endif
67
68 /**
69  * Network Packet Received Callback to CA.
70  */
71 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
72
73 /**
74  * Network Changed Callback to CA.
75  */
76 static CAAdapterChangeCallback g_networkChangeCallback = NULL;
77
78 /**
79  * error Callback to CA adapter.
80  */
81 static CAErrorHandleCallback g_errorCallback = NULL;
82
83 static CAResult_t CAIPPacketReceivedCB(const CASecureEndpoint_t *endpoint,
84                                        const void *data, size_t dataLength);
85 #ifdef __WITH_DTLS__
86 static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint,
87                                 const void *data, size_t dataLength);
88 #endif
89
90 #ifndef SINGLE_THREAD
91
92 static CAResult_t CAIPInitializeQueueHandles();
93
94 static void CAIPDeinitializeQueueHandles();
95
96 static void CAIPSendDataThread(void *threadData);
97
98 static CAIPData_t *CACreateIPData(const CAEndpoint_t *remoteEndpoint,
99                                   const void *data, uint32_t dataLength,
100                                   bool isMulticast);
101
102 void CAFreeIPData(CAIPData_t *ipData);
103
104 static void CADataDestroyer(void *data, uint32_t size);
105
106 CAResult_t CAIPInitializeQueueHandles()
107 {
108     // Check if the message queue is already initialized
109     if (g_sendQueueHandle)
110     {
111         OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
112         return CA_STATUS_OK;
113     }
114
115     // Create send message queue
116     g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
117     if (!g_sendQueueHandle)
118     {
119         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
120         return CA_MEMORY_ALLOC_FAILED;
121     }
122
123     if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
124                                 (const ca_thread_pool_t)caglobals.ip.threadpool,
125                                 CAIPSendDataThread, CADataDestroyer))
126     {
127         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
128         OICFree(g_sendQueueHandle);
129         g_sendQueueHandle = NULL;
130         return CA_STATUS_FAILED;
131     }
132
133     return CA_STATUS_OK;
134 }
135
136 void CAIPDeinitializeQueueHandles()
137 {
138     CAQueueingThreadDestroy(g_sendQueueHandle);
139     OICFree(g_sendQueueHandle);
140     g_sendQueueHandle = NULL;
141 }
142
143 #endif // SINGLE_THREAD
144
145 void CAIPAdapterHandler(CATransportAdapter_t adapter, CANetworkStatus_t status)
146 {
147     if (g_networkChangeCallback)
148     {
149         g_networkChangeCallback(adapter, status);
150     }
151     else
152     {
153         OIC_LOG(ERROR, TAG, "g_networkChangeCallback is NULL");
154     }
155
156     if (CA_INTERFACE_DOWN == status)
157     {
158         OIC_LOG(DEBUG, TAG, "Network status for IP is down");
159
160         CAResult_t res = CAQueueingThreadClearData(g_sendQueueHandle);
161         if (res != CA_STATUS_OK)
162         {
163             OIC_LOG_V(ERROR, TAG, "CAQueueingThreadClearData failed[%d]", res);
164         }
165
166 #ifdef __WITH_DTLS__
167 #ifdef TCP_ADAPTER
168         CATCPCloseInProgressConnections();
169 #endif
170         OIC_LOG(DEBUG, TAG, "close all ssl session");
171         CAcloseSslConnectionAll(CA_ADAPTER_IP);
172 #endif
173     }
174 }
175
176 #ifdef __WITH_DTLS__
177 static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_t dataLength)
178 {
179     VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint is NULL", -1);
180     VERIFY_NON_NULL_RET(data, TAG, "data is NULL", -1);
181
182     CAIPSendData(endpoint, data, dataLength, false);
183     return dataLength;
184 }
185 #endif
186
187
188 CAResult_t CAIPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
189                                 size_t dataLength)
190 {
191     VERIFY_NON_NULL(sep, TAG, "sep is NULL");
192     VERIFY_NON_NULL(data, TAG, "data is NULL");
193
194     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
195
196     CAResult_t res = CA_STATUS_OK;
197     if (g_networkPacketCallback)
198     {
199         res = g_networkPacketCallback(sep, data, dataLength);
200         if (CA_STATUS_OK != res)
201         {
202             OIC_LOG(ERROR, TAG, "Error parsing CoAP data");
203         }
204     }
205     return res;
206 }
207
208 void CAIPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
209                       uint32_t dataLength, CAResult_t result)
210 {
211     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
212     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
213
214     if (g_errorCallback)
215     {
216         g_errorCallback(endpoint, data, dataLength, result);
217     }
218 }
219
220 static void CAInitializeIPGlobals()
221 {
222     caglobals.ip.u6.fd  = -1;
223     caglobals.ip.u6s.fd = -1;
224     caglobals.ip.u4.fd  = -1;
225     caglobals.ip.u4s.fd = -1;
226     caglobals.ip.m6.fd  = -1;
227     caglobals.ip.m6s.fd = -1;
228     caglobals.ip.m4.fd  = -1;
229     caglobals.ip.m4s.fd = -1;
230     caglobals.ip.u6.port  = 0;
231     caglobals.ip.u6s.port = 0;
232     caglobals.ip.u4.port  = 0;
233     caglobals.ip.u4s.port = 0;
234     caglobals.ip.m6.port  = CA_COAP;
235     caglobals.ip.m6s.port = CA_SECURE_COAP;
236     caglobals.ip.m4.port  = CA_COAP;
237     caglobals.ip.m4s.port = CA_SECURE_COAP;
238
239     CATransportFlags_t flags = 0;
240     if (caglobals.client)
241     {
242         flags |= caglobals.clientFlags;
243     }
244     if (caglobals.server)
245     {
246         flags |= caglobals.serverFlags;
247     }
248 //TODO Enable once TizenRT supports IPv6
249 #ifndef __TIZENRT__
250     caglobals.ip.ipv6enabled = flags & CA_IPV6;
251 #endif
252     caglobals.ip.ipv4enabled = flags & CA_IPV4;
253     caglobals.ip.dualstack = caglobals.ip.ipv6enabled && caglobals.ip.ipv4enabled;
254 }
255
256 CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
257                           CANetworkPacketReceivedCallback networkPacketCallback,
258                           CAAdapterChangeCallback netCallback,
259                           CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
260 {
261     OIC_LOG(DEBUG, TAG, "IN");
262     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
263     VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
264     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
265 #ifndef SINGLE_THREAD
266     VERIFY_NON_NULL(handle, TAG, "thread pool handle");
267 #endif
268
269     g_networkChangeCallback = netCallback;
270     g_networkPacketCallback = networkPacketCallback;
271     g_errorCallback = errorCallback;
272
273     CAInitializeIPGlobals();
274     caglobals.ip.threadpool = handle;
275
276     CAIPSetErrorHandler(CAIPErrorHandler);
277     CAIPSetPacketReceiveCallback((CAIPPacketReceivedCallback)CAIPPacketReceivedCB);
278
279 #ifdef __WITH_DTLS__
280     CAsetSslAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, CA_ADAPTER_IP);
281 #endif
282
283     static const CAConnectivityHandler_t ipHandler =
284         {
285             .startAdapter = CAStartIP,
286             .stopAdapter = CAStopIP,
287             .startListenServer = CAStartIPListeningServer,
288             .stopListenServer = CAStopIPListeningServer,
289             .startDiscoveryServer = CAStartIPDiscoveryServer,
290             .sendData = CASendIPUnicastData,
291             .sendDataToAll = CASendIPMulticastData,
292             .GetnetInfo = CAGetIPInterfaceInformation,
293             .readData = CAReadIPData,
294             .terminate = CATerminateIP,
295             .cType = CA_ADAPTER_IP
296         };
297     registerCallback(ipHandler);
298
299     OIC_LOG(INFO, TAG, "OUT IntializeIP is Success");
300     return CA_STATUS_OK;
301 }
302
303 CAResult_t CAStartIP()
304 {
305     // Specific the port number received from application.
306     caglobals.ip.u6.port  = caglobals.ports.udp.u6;
307     caglobals.ip.u6s.port = caglobals.ports.udp.u6s;
308     caglobals.ip.u4.port  = caglobals.ports.udp.u4;
309     caglobals.ip.u4s.port = caglobals.ports.udp.u4s;
310
311     CAIPStartNetworkMonitor(CAIPAdapterHandler, CA_ADAPTER_IP);
312 #ifdef SINGLE_THREAD
313     uint16_t unicastPort = 55555;
314     // Address is hardcoded as we are using Single Interface
315     CAResult_t ret = CAIPStartServer();
316     if (CA_STATUS_OK != ret)
317     {
318         OIC_LOG_V(DEBUG, TAG, "CAIPStartServer failed[%d]", ret);
319         return ret;
320     }
321 #else
322     if (CA_STATUS_OK != CAIPInitializeQueueHandles())
323     {
324         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
325         CATerminateIP();
326         return CA_STATUS_FAILED;
327     }
328
329     // Start send queue thread
330 #ifndef __TIZENRT__
331     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
332 #else
333     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle, "IoT_IPSendQueue"))
334 #endif
335     {
336         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
337         return CA_STATUS_FAILED;
338     }
339
340     CAResult_t ret = CAIPStartServer((const ca_thread_pool_t)caglobals.ip.threadpool);
341     if (CA_STATUS_OK != ret)
342     {
343         OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
344         return ret;
345     }
346
347 #endif
348
349     return CA_STATUS_OK;
350 }
351
352 CAResult_t CAStartIPListeningServer()
353 {
354     CAResult_t ret = CAIPStartListenServer();
355     if (CA_STATUS_OK != ret)
356     {
357         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", ret);
358         return ret;
359     }
360
361     return CA_STATUS_OK;
362 }
363
364 CAResult_t CAStopIPListeningServer()
365 {
366     CAResult_t ret = CAIPStopListenServer();
367     if (CA_STATUS_OK != ret)
368     {
369         OIC_LOG_V(ERROR, TAG, "Failed to stop listening server![%d]", ret);
370     }
371
372     return ret;
373 }
374
375 CAResult_t CAStartIPDiscoveryServer()
376 {
377     return CAStartIPListeningServer();
378 }
379
380 static int32_t CAQueueIPData(bool isMulticast, const CAEndpoint_t *endpoint,
381                              const void *data, uint32_t dataLength)
382 {
383     VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
384     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
385
386     if (0 == dataLength)
387     {
388         OIC_LOG(ERROR, TAG, "Invalid Data Length");
389         return -1;
390     }
391
392 #ifdef SINGLE_THREAD
393
394     CAIPSendData(endpoint, data, dataLength, isMulticast);
395     return dataLength;
396
397 #else
398
399     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
400     // Create IPData to add to queue
401     CAIPData_t *ipData = CACreateIPData(endpoint, data, dataLength, isMulticast);
402     if (!ipData)
403     {
404         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
405         return -1;
406     }
407     // Add message to send queue
408     CAQueueingThreadAddData(g_sendQueueHandle, ipData, sizeof(CAIPData_t));
409
410 #endif // SINGLE_THREAD
411
412     return dataLength;
413 }
414
415 int32_t CASendIPUnicastData(const CAEndpoint_t *endpoint,
416                             const void *data, uint32_t dataLength,
417                             CADataType_t dataType)
418 {
419     (void)dataType;
420     return CAQueueIPData(false, endpoint, data, dataLength);
421 }
422
423 int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength,
424                               CADataType_t dataType)
425 {
426     (void)dataType;
427     return CAQueueIPData(true, endpoint, data, dataLength);
428 }
429
430 CAResult_t CAReadIPData()
431 {
432     CAIPPullData();
433     return CA_STATUS_OK;
434 }
435
436 CAResult_t CAStopIP()
437 {
438 #ifndef SINGLE_THREAD
439     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
440     {
441         CAQueueingThreadStop(g_sendQueueHandle);
442     }
443 #endif
444
445     CAIPStopNetworkMonitor(CA_ADAPTER_IP);
446     CAIPStopServer();
447     //Re-initializing the Globals to start them again
448     CAInitializeIPGlobals();
449
450     return CA_STATUS_OK;
451 }
452
453 void CATerminateIP()
454 {
455 #ifdef __WITH_DTLS__
456     CAsetSslAdapterCallbacks(NULL, NULL, CA_ADAPTER_IP);
457 #endif
458
459     CAIPSetPacketReceiveCallback(NULL);
460
461 #ifndef SINGLE_THREAD
462     CAIPDeinitializeQueueHandles();
463 #endif
464 }
465
466 #ifndef SINGLE_THREAD
467
468 void CAIPSendDataThread(void *threadData)
469 {
470     CAIPData_t *ipData = (CAIPData_t *) threadData;
471     if (!ipData)
472     {
473         OIC_LOG(DEBUG, TAG, "Invalid ip data!");
474         return;
475     }
476
477     if (ipData->isMulticast)
478     {
479         //Processing for sending multicast
480         OIC_LOG(DEBUG, TAG, "Send Multicast Data is called");
481         CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, true);
482     }
483     else
484     {
485         //Processing for sending unicast
486 #ifdef __WITH_DTLS__
487         if (ipData->remoteEndpoint && ipData->remoteEndpoint->flags & CA_SECURE)
488         {
489             OIC_LOG(INFO, TAG, "DTLS encrypt called");
490             CAResult_t result = CAencryptSsl(ipData->remoteEndpoint, ipData->data, ipData->dataLen);
491             if (CA_STATUS_OK != result)
492             {
493                 OIC_LOG(ERROR, TAG, "CAencryptSsl failed!");
494             }
495             OIC_LOG_V(INFO, TAG, "CAencryptSsl returned with result[%d]", result);
496         }
497         else
498         {
499             OIC_LOG(DEBUG, TAG, "Send Unicast Data is called");
500             CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
501         }
502 #else
503         CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
504 #endif
505     }
506 }
507
508 #endif
509
510 #ifndef SINGLE_THREAD
511 CAIPData_t *CACreateIPData(const CAEndpoint_t *remoteEndpoint, const void *data,
512                            uint32_t dataLength, bool isMulticast)
513 {
514     VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
515     VERIFY_NON_NULL_RET(data, TAG, "IPData is NULL", NULL);
516
517     CAIPData_t *ipData = (CAIPData_t *) OICMalloc(sizeof(*ipData));
518     if (!ipData)
519     {
520         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
521         return NULL;
522     }
523
524     ipData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
525     ipData->data = (void *) OICMalloc(dataLength);
526     if (!ipData->data)
527     {
528         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
529         CAFreeIPData(ipData);
530         return NULL;
531     }
532
533     memcpy(ipData->data, data, dataLength);
534     ipData->dataLen = dataLength;
535
536     ipData->isMulticast = isMulticast;
537
538     return ipData;
539 }
540
541 void CAFreeIPData(CAIPData_t *ipData)
542 {
543     VERIFY_NON_NULL_VOID(ipData, TAG, "ipData is NULL");
544
545     CAFreeEndpoint(ipData->remoteEndpoint);
546     OICFree(ipData->data);
547     OICFree(ipData);
548 }
549
550 void CADataDestroyer(void *data, uint32_t size)
551 {
552     if (size < sizeof(CAIPData_t))
553     {
554         OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
555     }
556     CAIPData_t *etdata = (CAIPData_t *) data;
557
558     CAFreeIPData(etdata);
559 }
560
561 #endif // SINGLE_THREAD