1 /* ****************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
20 #include "caipadapter.h"
27 #include "caipnwmonitor.h"
28 #include "caipinterface.h"
29 #include "caqueueingthread.h"
30 #include "caadapterutils.h"
32 #include "ca_adapter_net_ssl.h"
35 #include "uarraylist.h"
36 #include "caremotehandler.h"
37 #include "experimental/logger.h"
38 #include "oic_malloc.h"
39 #include "oic_string.h"
40 #include "iotivity_debug.h"
43 * Logging tag for module name.
45 #define TAG "OIC_CA_IP_ADAP"
48 * Holds inter thread ip data information.
52 CAEndpoint_t *remoteEndpoint;
59 * Queue handle for Send Data.
61 static CAQueueingThread_t *g_sendQueueHandle = NULL;
64 * List of the endpoint that has a stack-owned IP address.
66 static u_arraylist_t *g_ownIpEndpointList = NULL;
69 * Network Packet Received Callback to CA.
71 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
74 * Network Changed Callback to CA.
76 static CAAdapterChangeCallback g_networkChangeCallback = NULL;
79 * error Callback to CA adapter.
81 static CAErrorHandleCallback g_errorCallback = NULL;
83 static void CAIPPacketReceivedCB(const CASecureEndpoint_t *endpoint,
84 const void *data, size_t dataLength);
86 static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint,
87 const void *data, size_t dataLength);
90 static void CAUpdateStoredIPAddressInfo(CANetworkStatus_t status);
93 static CAResult_t CAIPInitializeQueueHandles();
95 static void CAIPDeinitializeQueueHandles();
97 static void CAIPSendDataThread(void *threadData);
99 static CAIPData_t *CACreateIPData(const CAEndpoint_t *remoteEndpoint,
100 const void *data, uint32_t dataLength,
103 void CAFreeIPData(CAIPData_t *ipData);
105 static void CADataDestroyer(void *data, uint32_t size);
107 CAResult_t CAIPInitializeQueueHandles()
109 // Check if the message queue is already initialized
110 if (g_sendQueueHandle)
112 OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
116 g_ownIpEndpointList = u_arraylist_create();
117 if (!g_ownIpEndpointList)
119 OIC_LOG(ERROR, TAG, "Memory allocation failed! (g_ownIpEndpointList)");
120 return CA_MEMORY_ALLOC_FAILED;
123 // Create send message queue
124 g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
125 if (!g_sendQueueHandle)
127 OIC_LOG(ERROR, TAG, "Memory allocation failed! (g_sendQueueHandle)");
128 u_arraylist_free(&g_ownIpEndpointList);
129 g_ownIpEndpointList = NULL;
130 return CA_MEMORY_ALLOC_FAILED;
133 if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle,
134 (const ca_thread_pool_t)caglobals.ip.threadpool,
135 CAIPSendDataThread, CADataDestroyer))
137 OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
138 OICFree(g_sendQueueHandle);
139 g_sendQueueHandle = NULL;
140 u_arraylist_free(&g_ownIpEndpointList);
141 g_ownIpEndpointList = NULL;
142 return CA_STATUS_FAILED;
148 void CAIPDeinitializeQueueHandles()
150 CAQueueingThreadDestroy(g_sendQueueHandle);
151 OICFree(g_sendQueueHandle);
152 g_sendQueueHandle = NULL;
154 // Since the items in g_ownIpEndpointList are allocated once in a big chunk, we only need to
155 // free the first item. Another location this is done is in the CA_INTERFACE_DOWN handler
156 // in CAUpdateStoredIPAddressInfo().
157 OICFree(u_arraylist_get(g_ownIpEndpointList, 0));
158 u_arraylist_free(&g_ownIpEndpointList);
159 g_ownIpEndpointList = NULL;
163 void CAIPAdapterHandler(CATransportAdapter_t adapter, CANetworkStatus_t status)
165 CAUpdateStoredIPAddressInfo(status);
167 if (g_networkChangeCallback)
169 g_networkChangeCallback(adapter, status);
173 OIC_LOG(ERROR, TAG, "g_networkChangeCallback is NULL");
176 if (CA_INTERFACE_DOWN == status)
178 OIC_LOG(DEBUG, TAG, "Network status for IP is down");
180 OIC_LOG(DEBUG, TAG, "close all ssl session");
181 CAcloseSslConnectionAll(CA_ADAPTER_IP);
186 static void CAUpdateStoredIPAddressInfo(CANetworkStatus_t status)
188 if (CA_INTERFACE_UP == status)
190 OIC_LOG(DEBUG, TAG, "IP adapter status is on. Store the own IP address info");
192 CAEndpoint_t *eps = NULL;
195 CAResult_t res = CAGetIPInterfaceInformation(&eps, &numOfEps);
196 if (CA_STATUS_OK != res)
198 OIC_LOG(ERROR, TAG, "CAGetIPInterfaceInformation failed");
202 for (size_t i = 0; i < numOfEps; i++)
204 u_arraylist_add(g_ownIpEndpointList, (void *)&eps[i]);
207 else // CA_INTERFACE_DOWN
209 OIC_LOG(DEBUG, TAG, "IP adapter status is off. Remove the own IP address info");
211 CAEndpoint_t *headEp = u_arraylist_get(g_ownIpEndpointList, 0);
215 size_t len = u_arraylist_length(g_ownIpEndpointList);
216 for (size_t i = len; i > 0; i--)
218 u_arraylist_remove(g_ownIpEndpointList, i - 1);
224 static ssize_t CAIPPacketSendCB(CAEndpoint_t *endpoint, const void *data, size_t dataLength)
226 VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint is NULL", -1);
227 VERIFY_NON_NULL_RET(data, TAG, "data is NULL", -1);
229 CAIPSendData(endpoint, data, dataLength, false);
234 void CAIPPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data,
237 VERIFY_NON_NULL_VOID(sep, TAG, "sep is NULL");
238 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
240 OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
242 if (g_networkPacketCallback)
244 g_networkPacketCallback(sep, data, dataLength);
248 bool CAIPIsLocalEndpoint(const CAEndpoint_t *ep)
250 char addr[MAX_ADDR_STR_SIZE_CA];
251 OICStrcpy(addr, MAX_ADDR_STR_SIZE_CA, ep->addr);
253 // drop the zone ID if the address of endpoint is IPv6. ifindex will be checked instead.
254 if ((ep->flags & CA_IPV6) && strchr(addr, '%'))
259 size_t len = u_arraylist_length(g_ownIpEndpointList);
260 for (size_t i = 0; i < len; i++)
262 CAEndpoint_t *ownIpEp = u_arraylist_get(g_ownIpEndpointList, i);
263 if (!strcmp(addr, ownIpEp->addr) && ep->port == ownIpEp->port
264 && ep->ifindex == ownIpEp->ifindex)
273 void CAIPErrorHandler(const CAEndpoint_t *endpoint, const void *data,
274 size_t dataLength, CAResult_t result)
276 VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
277 VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
281 g_errorCallback(endpoint, data, dataLength, result);
285 static void CAInitializeIPGlobals()
287 caglobals.ip.u6.fd = OC_INVALID_SOCKET;
288 caglobals.ip.u6s.fd = OC_INVALID_SOCKET;
289 caglobals.ip.u4.fd = OC_INVALID_SOCKET;
290 caglobals.ip.u4s.fd = OC_INVALID_SOCKET;
291 caglobals.ip.m6.fd = OC_INVALID_SOCKET;
292 caglobals.ip.m6s.fd = OC_INVALID_SOCKET;
293 caglobals.ip.m4.fd = OC_INVALID_SOCKET;
294 caglobals.ip.m4s.fd = OC_INVALID_SOCKET;
295 caglobals.ip.u6.port = 0;
296 caglobals.ip.u6s.port = 0;
297 caglobals.ip.u4.port = 0;
298 caglobals.ip.u4s.port = 0;
299 caglobals.ip.m6.port = CA_COAP;
300 caglobals.ip.m6s.port = CA_SECURE_COAP;
301 caglobals.ip.m4.port = CA_COAP;
302 caglobals.ip.m4s.port = CA_SECURE_COAP;
304 CATransportFlags_t flags = 0;
305 if (caglobals.client)
307 flags |= caglobals.clientFlags;
309 if (caglobals.server)
311 flags |= caglobals.serverFlags;
313 caglobals.ip.ipv6enabled = flags & CA_IPV6;
314 caglobals.ip.ipv4enabled = flags & CA_IPV4;
315 caglobals.ip.dualstack = caglobals.ip.ipv6enabled && caglobals.ip.ipv4enabled;
318 CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
319 CANetworkPacketReceivedCallback networkPacketCallback,
320 CAAdapterChangeCallback netCallback,
321 CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
323 OIC_LOG(DEBUG, TAG, "IN");
324 VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
325 VERIFY_NON_NULL(networkPacketCallback, TAG, "networkPacketCallback");
326 VERIFY_NON_NULL(netCallback, TAG, "netCallback");
327 VERIFY_NON_NULL(handle, TAG, "thread pool handle");
329 #ifdef WSA_WAIT_EVENT_0
330 // Windows-specific initialization.
331 WORD wVersionRequested = MAKEWORD(2, 2);
332 WSADATA wsaData = {.wVersion = 0};
333 int err = WSAStartup(wVersionRequested, &wsaData);
336 OIC_LOG_V(ERROR, TAG, "%s: WSAStartup failed: %i", __func__, err);
337 return CA_STATUS_FAILED;
339 OIC_LOG(DEBUG, TAG, "WSAStartup Succeeded");
342 g_networkChangeCallback = netCallback;
343 g_networkPacketCallback = networkPacketCallback;
344 g_errorCallback = errorCallback;
346 CAInitializeIPGlobals();
347 caglobals.ip.threadpool = handle;
349 CAIPSetErrorHandler(CAIPErrorHandler);
350 CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
353 if (CA_STATUS_OK != CAinitSslAdapter())
355 OIC_LOG(ERROR, TAG, "Failed to init SSL adapter");
359 CAsetSslAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, CAIPErrorHandler, CA_ADAPTER_IP);
363 static const CAConnectivityHandler_t ipHandler =
365 .startAdapter = CAStartIP,
366 .stopAdapter = CAStopIP,
367 .startListenServer = CAStartIPListeningServer,
368 .stopListenServer = CAStopIPListeningServer,
369 .startDiscoveryServer = CAStartIPDiscoveryServer,
370 .sendData = CASendIPUnicastData,
371 .sendDataToAll = CASendIPMulticastData,
372 .GetnetInfo = CAGetIPInterfaceInformation,
373 .readData = CAReadIPData,
374 .terminate = CATerminateIP,
375 .cType = CA_ADAPTER_IP
377 registerCallback(ipHandler);
379 OIC_LOG(INFO, TAG, "OUT IntializeIP is Success");
383 CAResult_t CAStartIP()
385 //Initializing the Globals
386 CAInitializeIPGlobals();
388 // Specific the port number received from application.
389 caglobals.ip.u6.port = caglobals.ports.udp.u6;
390 caglobals.ip.u6s.port = caglobals.ports.udp.u6s;
391 caglobals.ip.u4.port = caglobals.ports.udp.u4;
392 caglobals.ip.u4s.port = caglobals.ports.udp.u4s;
394 CAIPStartNetworkMonitor(CAIPAdapterHandler, CA_ADAPTER_IP);
395 if (CA_STATUS_OK != CAIPInitializeQueueHandles())
397 OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
399 return CA_STATUS_FAILED;
402 // Start send queue thread
403 if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
405 OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
406 return CA_STATUS_FAILED;
409 CAResult_t ret = CAIPStartServer((const ca_thread_pool_t)caglobals.ip.threadpool);
410 if (CA_STATUS_OK != ret)
412 OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
420 CAResult_t CAStartIPListeningServer()
422 CAResult_t ret = CAIPStartListenServer();
423 if (CA_STATUS_OK != ret)
425 OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", ret);
432 CAResult_t CAStopIPListeningServer()
434 CAResult_t ret = CAIPStopListenServer();
435 if (CA_STATUS_OK != ret)
437 OIC_LOG_V(ERROR, TAG, "Failed to stop listening server![%d]", ret);
443 CAResult_t CAStartIPDiscoveryServer()
445 return CAStartIPListeningServer();
448 static int32_t CAQueueIPData(bool isMulticast, const CAEndpoint_t *endpoint,
449 const void *data, uint32_t dataLength)
451 VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
452 VERIFY_NON_NULL_RET(data, TAG, "data", -1);
456 OIC_LOG(ERROR, TAG, "Invalid Data Length");
461 VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
462 // Create IPData to add to queue
463 CAIPData_t *ipData = CACreateIPData(endpoint, data, dataLength, isMulticast);
466 OIC_LOG(ERROR, TAG, "Failed to create ipData!");
469 // Add message to send queue
470 CAQueueingThreadAddData(g_sendQueueHandle, ipData, sizeof(CAIPData_t));
476 int32_t CASendIPUnicastData(const CAEndpoint_t *endpoint,
477 const void *data, uint32_t dataLength,
478 CADataType_t dataType)
481 return CAQueueIPData(false, endpoint, data, dataLength);
484 int32_t CASendIPMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength,
485 CADataType_t dataType)
488 return CAQueueIPData(true, endpoint, data, dataLength);
491 CAResult_t CAReadIPData()
497 CAResult_t CAStopIP()
500 CAdeinitSslAdapter();
503 if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
505 CAQueueingThreadStop(g_sendQueueHandle);
508 CAIPStopNetworkMonitor(CA_ADAPTER_IP);
517 CAsetSslAdapterCallbacks(NULL, NULL, NULL, CA_ADAPTER_IP);
520 CAIPSetPacketReceiveCallback(NULL);
522 CAIPDeinitializeQueueHandles();
524 #ifdef WSA_WAIT_EVENT_0
525 // Windows-specific clean-up.
526 OC_VERIFY(0 == WSACleanup());
531 void CAIPSendDataThread(void *threadData)
533 CAIPData_t *ipData = (CAIPData_t *) threadData;
536 OIC_LOG(DEBUG, TAG, "Invalid ip data!");
540 if (ipData->isMulticast)
542 //Processing for sending multicast
543 OIC_LOG(DEBUG, TAG, "Send Multicast Data is called");
544 CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, true);
548 //Processing for sending unicast
550 if (ipData->remoteEndpoint && ipData->remoteEndpoint->flags & CA_SECURE)
552 OIC_LOG(DEBUG, TAG, "DTLS encrypt called");
553 CAResult_t result = CAencryptSsl(ipData->remoteEndpoint, ipData->data, ipData->dataLen);
554 if (CA_STATUS_OK != result)
556 OIC_LOG(ERROR, TAG, "CAencryptSsl failed!");
558 OIC_LOG_V(DEBUG, TAG, "CAencryptSsl returned with result[%d]", result);
562 OIC_LOG(DEBUG, TAG, "Send Unicast Data is called");
563 CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
566 CAIPSendData(ipData->remoteEndpoint, ipData->data, ipData->dataLen, false);
572 CAIPData_t *CACreateIPData(const CAEndpoint_t *remoteEndpoint, const void *data,
573 uint32_t dataLength, bool isMulticast)
575 VERIFY_NON_NULL_RET(remoteEndpoint, TAG, "remoteEndpoint is NULL", NULL);
576 VERIFY_NON_NULL_RET(data, TAG, "IPData is NULL", NULL);
578 CAIPData_t *ipData = (CAIPData_t *) OICMalloc(sizeof(*ipData));
581 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
585 ipData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
586 ipData->data = (void *) OICMalloc(dataLength);
589 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
590 CAFreeIPData(ipData);
594 memcpy(ipData->data, data, dataLength);
595 ipData->dataLen = dataLength;
597 ipData->isMulticast = isMulticast;
602 void CAFreeIPData(CAIPData_t *ipData)
604 VERIFY_NON_NULL_VOID(ipData, TAG, "ipData is NULL");
606 CAFreeEndpoint(ipData->remoteEndpoint);
607 OICFree(ipData->data);
611 void CADataDestroyer(void *data, uint32_t size)
613 if (size < sizeof(CAIPData_t))
615 OIC_LOG_V(ERROR, TAG, "Destroy data too small %p %d", data, size);
617 CAIPData_t *etdata = (CAIPData_t *) data;
619 CAFreeIPData(etdata);