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