Replace glib threadpool usage with a 'dumb' thread implementation.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ethernet_adapter / caethernetadapter.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 "caethernetadapter.h"
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdint.h>
26
27 #include "caethernetinterface.h"
28 #include "caqueueingthread.h"
29 #include "caadapterutils.h"
30 #ifdef __WITH_DTLS__
31 #include "caadapternetdtls.h"
32 #endif
33 #include "camutex.h"
34 #include "logger.h"
35 #include "oic_malloc.h"
36
37 /**
38  * @def ETHERNET_ADAPTER_TAG
39  * @brief Logging tag for module name
40  */
41 #define ETHERNET_ADAPTER_TAG "ETHERNET_ADAP"
42
43 /**
44  * @def CA_PORT
45  * @brief Port to listen for incoming data
46  */
47 #define CA_PORT   6298
48
49 /**
50  * @def CA_SECURE_PORT
51  * @brief Secured (unicast) port number as defined in COAP Specification, RFC-7252.
52  */
53 #define CA_SECURE_PORT   5684
54
55 /**
56  * @def CA_MCAST_PORT
57  * @brief Multicast port number as defined in COAP Specification, RFC-7252.
58  */
59 #define CA_MCAST_PORT   5683
60
61 /**
62  * @def CA_MULTICAST_IP
63  * @brief Multicast IP Address as defined in COAP Specification, RFC-7252.
64  */
65 #define CA_MULTICAST_IP "224.0.1.187"
66
67 typedef struct
68 {
69     CARemoteEndpoint_t *remoteEndpoint;
70     void *data;
71     uint32_t dataLen;
72 } CAEthernetData;
73
74 /**
75  * @var g_networkPacketCallback
76  * @brief Network Packet Received Callback to CA
77  */
78 static CANetworkPacketReceivedCallback g_networkPacketCallback = NULL;
79
80 /**
81  * @var g_networkChangeCallback
82  * @brief Network Changed Callback to CA
83  */
84 static CANetworkChangeCallback g_networkChangeCallback = NULL;
85
86 /**
87  * @var g_isMulticastServerStarted
88  * @brief Flag to check if multicast server is started
89  */
90 static bool g_isMulticastServerStarted = false;
91
92 /**
93  * @var gIsStartServerCalled
94  * @brief Flag to check if server start requested by CA.
95  */
96 static bool g_startUnicastServerRequested = false;
97
98 /**
99  * @var g_unicastServerport
100  * @brief port number on which unicast server is running.
101  */
102 static uint16_t g_unicastServerport = 0;
103
104 #ifdef __WITH_DTLS__
105 /**
106  * @var g_secureUnicastServerport
107  * @brief port number on which secure unicast server is running.
108  */
109 static uint16_t g_secureUnicastServerport = 0;
110 #endif
111
112 /**
113  * @var g_startMulticastServerRequested
114  * @brief Flag to check if server start requested by CA.
115  */
116 static bool g_startMulticastServerRequested = false;
117
118 /**
119  * @var g_sendQueueHandle
120  * @brief Queue handle for Send Data
121  */
122 static CAQueueingThread_t *g_sendQueueHandle = NULL;
123
124 /**
125  * @var g_threadPool
126  * @brief ThreadPool for storing ca_thread_pool_t handle passed from CA
127  */
128 static ca_thread_pool_t g_threadPool = NULL;
129
130 static CAResult_t CAEthernetInitializeQueueHandles();
131 static void CAEthernetDeinitializeQueueHandles();
132 static void CAEthernetNotifyNetworkChange(const char *address, const uint16_t port,
133         const CANetworkStatus_t status);
134 static void CAEthernetConnectionStateCB(const char *ipAddress,
135                                     const CANetworkStatus_t status);
136 static void CAEthernetPacketReceivedCB(const char *ipAddress, const uint16_t port,
137                                        const void *data, const uint32_t dataLength, const bool isSecured);
138 #ifdef __WITH_DTLS__
139 static uint32_t CAEthernetPacketSendCB(const char *ipAddress, const uint16_t port,
140                                        const void *data, const uint32_t dataLength);
141 #endif
142
143 static CAResult_t CAEthernetStopServers();
144 static void CAEthernetSendDataThread(void *threadData);
145 static CAEthernetData *CACreateEthernetData(const CARemoteEndpoint_t *remoteEndpoint, const void *data,
146         uint32_t dataLength);
147 void CAFreeEthernetData(CAEthernetData *EthernetData);
148
149 static void CADataDestroyer(void *data, uint32_t size);
150
151 CAResult_t CAEthernetInitializeQueueHandles()
152 {
153     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
154
155     // Check if the message queue is already initialized
156     if (g_sendQueueHandle)
157     {
158         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "send queue handle is already initialized!");
159         return CA_STATUS_OK;
160     }
161
162     // Create send message queue
163     g_sendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
164     if (!g_sendQueueHandle)
165     {
166         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Memory allocation failed!");
167         return CA_MEMORY_ALLOC_FAILED;
168     }
169
170     if (CA_STATUS_OK != CAQueueingThreadInitialize(g_sendQueueHandle, g_threadPool,
171             CAEthernetSendDataThread, CADataDestroyer))
172     {
173         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Initialize send queue thread");
174         OICFree(g_sendQueueHandle);
175         g_sendQueueHandle = NULL;
176         return CA_STATUS_FAILED;
177     }
178
179     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
180     return CA_STATUS_OK;
181 }
182
183 void CAEthernetDeinitializeQueueHandles()
184 {
185     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
186
187     CAQueueingThreadDestroy(g_sendQueueHandle);
188     OICFree(g_sendQueueHandle);
189     g_sendQueueHandle = NULL;
190
191     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
192 }
193
194 void CAEthernetNotifyNetworkChange(const char *address, const uint16_t port,
195                                const CANetworkStatus_t status)
196 {
197     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
198
199     CALocalConnectivity_t *localEndpoint = CAAdapterCreateLocalEndpoint(CA_ETHERNET, address);
200     if (!localEndpoint)
201     {
202         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Out of memory");
203         return;
204     }
205
206     if (NULL != g_networkChangeCallback)
207     {
208         g_networkChangeCallback(localEndpoint, status);
209     }
210
211     CAAdapterFreeLocalEndpoint(localEndpoint);
212 }
213
214 void CAEthernetConnectionStateCB(const char *ipAddress,
215                              const CANetworkStatus_t status)
216 {
217     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
218
219     CAResult_t ret = CA_STATUS_FAILED;
220
221     /**
222      * If Ethernet is connected, then get the latest IP from the Ethernet Interface
223      * and start unicast and multicast servers if requested earlier
224      */
225     if (CA_INTERFACE_UP == status)
226     {
227         uint16_t port = CA_PORT;
228         int32_t serverFd = -1;
229
230         // Start Unicast server if requested earlier
231         if (g_startUnicastServerRequested)
232         {
233             ret = CAEthernetStartUnicastServer("0.0.0.0", &port, false, false, &serverFd);
234             if (CA_STATUS_OK == ret)
235             {
236                 OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Unicast server started on %d port", port);
237                 CAEthernetSetUnicastSocket(serverFd);
238                 g_unicastServerport = port;
239             }
240             else
241             {
242                 OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to start Unicast server [%d]", ret);
243             }
244
245 #ifdef __WITH_DTLS__
246             port = CA_SECURE_PORT;
247             ret = CAEthernetStartUnicastServer("0.0.0.0", &port, false, true, &serverFd);
248             if (CA_STATUS_OK == ret)
249             {
250                 OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Secure Unicast server started on %d", port);
251                 CAEthernetSetSecureUnicastSocket(serverFd);
252                 g_secureUnicastServerport = port;
253             }
254             else
255             {
256                 OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to start secure Unicast server [%d]",
257                           ret);
258             }
259 #endif
260         }
261
262         // Start Multicast server if requested earlier
263         if (g_startMulticastServerRequested)
264         {
265             uint16_t multicastPort = CA_MCAST_PORT;
266             int32_t multicastFd = 0;
267             ret = CAEthernetStartMulticastServer("0.0.0.0", CA_MULTICAST_IP, multicastPort,
268                                              &multicastFd);
269             if (CA_STATUS_OK == ret)
270             {
271                 OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Multicast server started on %d port",
272                           multicastPort);
273                 g_isMulticastServerStarted = true;
274             }
275             else
276             {
277                 OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to start Multicast server [%d]", ret);
278             }
279         }
280
281         char *address = NULL;
282         char *ifcName = NULL;
283         ret = CAEthernetGetInterfaceInfo(&ifcName, &address);
284         if (CA_STATUS_OK != ret || NULL == address)
285         {
286             OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to get interface info [%d]", ret);
287             OICFree(address);
288             OICFree(ifcName);
289             return;
290         }
291
292         // Notify network change to CA
293         CAEthernetNotifyNetworkChange(address, port, status);
294         OICFree(address);
295         OICFree(ifcName);
296     }
297     else
298     {
299         CAEthernetNotifyNetworkChange("", 0, status);
300
301         // Stop Unicast, Secured unicast and Multicast servers
302         CAEthernetStopServers();
303     }
304
305     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
306 }
307
308 #ifdef __WITH_DTLS__
309 uint32_t CAEthernetPacketSendCB(const char *ipAddress, const uint16_t port,
310                                 const void *data, const uint32_t dataLength)
311 {
312     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
313
314     uint32_t sentLength = CAEthernetSendData(ipAddress, port, data, dataLength, false, true);
315
316     OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Successfully sent %d of encrypted data!", sentLength);
317
318     return sentLength;
319 }
320 #endif
321
322 void CAEthernetPacketReceivedCB(const char *ipAddress, const uint16_t port,
323                                 const void *data, const uint32_t dataLength, const bool isSecured)
324 {
325     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
326     OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Address: %s, port:%d, data:%s", ipAddress, port, data);
327
328     // CA is freeing this memory
329     CARemoteEndpoint_t *endPoint = CAAdapterCreateRemoteEndpoint(CA_ETHERNET, ipAddress, NULL);
330     if (NULL == endPoint)
331     {
332         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Out of memory");
333         return;
334     }
335     endPoint->addressInfo.IP.port = port;
336     endPoint->isSecured = isSecured;
337
338     void *buf = OICMalloc(dataLength + 1);
339     if (NULL == buf)
340     {
341         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Out of memory");
342         CAAdapterFreeRemoteEndpoint(endPoint);
343         return;
344     }
345     memcpy(buf, data, dataLength);
346     memset(buf + dataLength, 0, 1);
347     if (g_networkPacketCallback)
348     {
349         g_networkPacketCallback(endPoint, buf, dataLength);
350     }
351     else
352     {
353         OICFree(buf);
354         CAAdapterFreeRemoteEndpoint(endPoint);
355     }
356
357     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
358 }
359
360 CAResult_t CAInitializeEthernet(CARegisterConnectivityCallback registerCallback,
361                             CANetworkPacketReceivedCallback networkPacketCallback,
362                             CANetworkChangeCallback netCallback, ca_thread_pool_t handle)
363 {
364     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
365     VERIFY_NON_NULL(registerCallback, ETHERNET_ADAPTER_TAG, "registerCallback");
366     VERIFY_NON_NULL(networkPacketCallback, ETHERNET_ADAPTER_TAG, "networkPacketCallback");
367     VERIFY_NON_NULL(netCallback, ETHERNET_ADAPTER_TAG, "netCallback");
368     VERIFY_NON_NULL(handle, ETHERNET_ADAPTER_TAG, "thread pool handle");
369
370     g_threadPool  = handle;
371     g_networkChangeCallback = netCallback;
372     g_networkPacketCallback = networkPacketCallback;
373
374     CAResult_t ret = CAEthernetInitializeNetworkMonitor(g_threadPool);
375     if (CA_STATUS_OK != ret)
376     {
377         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to initialize n/w monitor![%d]", ret);
378         return ret;
379     }
380     CAEthernetSetConnectionStateChangeCallback(CAEthernetConnectionStateCB);
381
382     ret = CAEthernetInitializeServer(g_threadPool);
383     if (CA_STATUS_OK != ret)
384     {
385         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to initialize server![%d]", ret);
386         CATerminateEthernet();
387         return ret;
388     }
389
390     CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCB);
391 #ifdef __WITH_DTLS__
392     CAAdapterNetDtlsInit();
393
394     CADTLSSetAdapterCallbacks(CAEthernetPacketReceivedCB, CAEthernetPacketSendCB, DTLS_ETHERNET);
395 #endif
396
397     CAConnectivityHandler_t ethernetHandler;
398     ethernetHandler.startAdapter = CAStartEthernet;
399     ethernetHandler.startListenServer = CAStartEthernetListeningServer;
400     ethernetHandler.startDiscoveryServer = CAStartEthernetDiscoveryServer;
401     ethernetHandler.sendData = CASendEthernetUnicastData;
402     ethernetHandler.sendDataToAll = CASendEthernetMulticastData;
403     ethernetHandler.GetnetInfo = CAGetEthernetInterfaceInformation;
404     ethernetHandler.readData = CAReadEthernetData;
405     ethernetHandler.stopAdapter = CAStopEthernet;
406     ethernetHandler.terminate = CATerminateEthernet;
407     registerCallback(ethernetHandler, CA_ETHERNET);
408
409     if (CA_STATUS_OK != CAEthernetInitializeQueueHandles())
410     {
411         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Initialize Queue Handle");
412         CATerminateEthernet();
413         return CA_STATUS_FAILED;
414     }
415
416     OIC_LOG(INFO, ETHERNET_ADAPTER_TAG, "IntializeEthernet is Success");
417     return CA_STATUS_OK;
418 }
419
420 CAResult_t CAStartEthernet()
421 {
422     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
423
424     // Start monitoring Ethernet network
425     CAResult_t ret = CAEthernetStartNetworkMonitor();
426     if (CA_STATUS_OK != ret)
427     {
428         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Start n/w monitor");
429         return ret;
430     }
431
432     // Start send queue thread
433     if (CA_STATUS_OK != CAQueueingThreadStart(g_sendQueueHandle))
434     {
435         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Start Send Data Thread");
436         CAStopEthernet();
437         return CA_STATUS_FAILED;
438     }
439
440     g_startUnicastServerRequested = true;
441     bool retVal = CAEthernetIsConnected();
442     if (false == retVal)
443     {
444         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Ethernet is not Connected");
445         return CA_STATUS_OK;
446     }
447
448     char *ifcName = NULL;
449     char *ifcAdrs = NULL;
450     ret = CAEthernetGetInterfaceInfo(&ifcName, &ifcAdrs);
451     if (CA_STATUS_OK != ret)
452     {
453         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Failed to get ethernet interface info [%d]", ret);
454         return ret;
455     }
456     uint16_t unicastPort = CA_PORT;
457     int32_t serverFd = 0;
458     // Address is hardcoded as we are using Single Interface
459     ret = CAEthernetStartUnicastServer(ifcAdrs, &unicastPort, false, false, &serverFd);
460     if (CA_STATUS_OK == ret)
461     {
462         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Unicast server started on %d port", unicastPort);
463         CAEthernetSetUnicastSocket(serverFd);
464         g_unicastServerport = unicastPort;
465     }
466
467 #ifdef __WITH_DTLS__
468     // Address is hardcoded as we are using Single Interface
469     unicastPort = CA_SECURE_PORT;
470     ret = CAEthernetStartUnicastServer(ifcAdrs, &unicastPort, false, true, &serverFd);
471
472     if (CA_STATUS_OK == ret)
473     {
474         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Secure Unicast server started on %d port", unicastPort);
475         CAEthernetSetSecureUnicastSocket(serverFd);
476         g_secureUnicastServerport = unicastPort;
477     }
478 #endif
479
480     OICFree(ifcName);
481     OICFree(ifcAdrs);
482
483     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
484     return ret;
485 }
486
487 CAResult_t CAStartEthernetListeningServer()
488 {
489     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
490
491     CAResult_t ret = CA_STATUS_OK;
492     uint16_t multicastPort = CA_MCAST_PORT;
493
494     if (g_isMulticastServerStarted == true)
495     {
496         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG,
497                   "Failed to Start Multicast Server, Already Started!");
498         return CA_SERVER_STARTED_ALREADY;
499     }
500
501     g_startMulticastServerRequested = true;
502     bool retVal = CAEthernetIsConnected();
503     if (false == retVal)
504     {
505         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG,
506                   "Failed to Start Multicast Server, Ethernet not Connected");
507         return CA_STATUS_OK;
508     }
509
510     char *ifcName = NULL;
511     char *ifcAdrs = NULL;
512     ret = CAEthernetGetInterfaceInfo(&ifcName, &ifcAdrs);
513     if (CA_STATUS_OK != ret)
514     {
515         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Failed to get ethernet interface info [%d]", ret);
516         return ret;
517     }
518     int32_t multicastFd = 0;
519     ret = CAEthernetStartMulticastServer(ifcAdrs, CA_MULTICAST_IP, multicastPort, &multicastFd);
520     if (CA_STATUS_OK == ret)
521     {
522         OIC_LOG(INFO, ETHERNET_ADAPTER_TAG, "Multicast Server is Started Successfully");
523         g_isMulticastServerStarted = true;
524     }
525
526     OICFree(ifcName);
527     OICFree(ifcAdrs);
528
529     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
530     return ret;
531 }
532
533 CAResult_t CAStartEthernetDiscoveryServer()
534 {
535     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
536     return CAStartEthernetListeningServer();
537 }
538
539 int32_t CASendEthernetUnicastData(const CARemoteEndpoint_t *remoteEndpoint, const void *data,
540                                uint32_t dataLength)
541 {
542     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
543
544     VERIFY_NON_NULL_RET(remoteEndpoint, ETHERNET_ADAPTER_TAG, "remoteEndpoint", -1);
545     VERIFY_NON_NULL_RET(data, ETHERNET_ADAPTER_TAG, "data", -1);
546     VERIFY_NON_NULL_RET(g_sendQueueHandle, ETHERNET_ADAPTER_TAG, "sendQueueHandle", -1);
547
548     if (0 == dataLength)
549     {
550         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Invalid Data Length");
551         return -1;
552     }
553
554     // Create EthernetData to add to queue
555     CAEthernetData *ethernetData = CACreateEthernetData(remoteEndpoint, data, dataLength);
556     if (!ethernetData)
557     {
558         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to create ethernetData!");
559         return -1;
560     }
561     else
562     {
563         // Add message to send queue
564         CAQueueingThreadAddData(g_sendQueueHandle, ethernetData, sizeof(CAEthernetData));
565
566         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
567         return dataLength;
568     }
569 }
570
571 int32_t CASendEthernetMulticastData(const void *data, uint32_t dataLength)
572 {
573     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
574
575     VERIFY_NON_NULL_RET(data, ETHERNET_ADAPTER_TAG, "data", -1);
576     VERIFY_NON_NULL_RET(g_sendQueueHandle, ETHERNET_ADAPTER_TAG, "sendQueueHandle", -1);
577
578     if (0 == dataLength)
579     {
580         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Invalid Data Length");
581         return -1;
582     }
583
584     // Create EthernetData to add to queue
585     CAEthernetData *EthernetData = CACreateEthernetData(NULL, data, dataLength);
586     if (!EthernetData)
587     {
588         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to create ethernetData!");
589         return -1;
590     }
591     else
592     {
593         // Add message to send queue
594         CAQueueingThreadAddData(g_sendQueueHandle, EthernetData, sizeof(CAEthernetData));
595
596         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
597         return dataLength;
598     }
599 }
600
601 CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
602 {
603     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
604
605     VERIFY_NON_NULL(info, ETHERNET_ADAPTER_TAG, "info");
606     VERIFY_NON_NULL(size, ETHERNET_ADAPTER_TAG, "size");
607
608     if (info == NULL || size == NULL)
609     {
610         return CA_STATUS_INVALID_PARAM;
611     }
612
613     CALocalConnectivity_t *netInfo = NULL;
614     bool retVal = CAEthernetIsConnected();
615     if (false == retVal)
616     {
617         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG,
618                   "Failed to get interface address, Ethernet not Connected",
619                   CA_ADAPTER_NOT_ENABLED);
620         return CA_ADAPTER_NOT_ENABLED;
621     }
622
623     int32_t netInfoSize = 1;
624 #ifdef __WITH_DTLS__
625     if (g_secureUnicastServerport)
626     {
627         netInfoSize++;
628     }
629 #endif
630     netInfo = (CALocalConnectivity_t *) OICCalloc(netInfoSize, sizeof(CALocalConnectivity_t));
631     VERIFY_NON_NULL_RET(netInfo, ETHERNET_ADAPTER_TAG, "malloc failed", CA_MEMORY_ALLOC_FAILED);
632
633     char *ipAddress = NULL;
634     char *ifcName = NULL;
635     CAResult_t ret = CAEthernetGetInterfaceInfo(&ifcName, &ipAddress);
636     if (CA_STATUS_OK != ret || NULL == ipAddress)
637     {
638         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to get interface info [%d]", ret);
639
640         OICFree(netInfo);
641         OICFree(ipAddress);
642         OICFree(ifcName);
643         return ret;
644     }
645
646     // Create local endpoint using util function
647     CALocalConnectivity_t *endpoint = CAAdapterCreateLocalEndpoint(CA_ETHERNET, ipAddress);
648     if (NULL == endpoint)
649     {
650         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to create Local Endpoint!",
651                   CA_MEMORY_ALLOC_FAILED);
652         OICFree(netInfo);
653         OICFree(ipAddress);
654         OICFree(ifcName);
655         return CA_MEMORY_ALLOC_FAILED;
656     }
657
658     // copy unicast server information
659     endpoint->isSecured = false;
660     endpoint->addressInfo.IP.port = g_unicastServerport;
661     memcpy(&netInfo[0], endpoint, sizeof(CALocalConnectivity_t));
662     *size = 1;
663 #ifdef __WITH_DTLS__
664     // copy secure unicast server information
665     if (g_secureUnicastServerport)
666     {
667         endpoint->isSecured = true;
668         endpoint->addressInfo.IP.port = g_secureUnicastServerport;
669         memcpy(&netInfo[1], endpoint, sizeof(CALocalConnectivity_t));
670         (*size)++;
671     }
672 #endif
673     *info = netInfo;
674
675     OICFree(ipAddress);
676     OICFree(ifcName);
677     CAAdapterFreeLocalEndpoint(endpoint);
678
679     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
680     return CA_STATUS_OK;
681 }
682
683 CAResult_t CAReadEthernetData()
684 {
685     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
686     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
687     return CA_STATUS_OK;
688 }
689
690 CAResult_t CAEthernetStopServers()
691 {
692     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
693
694     // Stop unicast server and set client socket accordingly
695     if (CA_STATUS_OK == CAEthernetStopUnicastServer())
696     {
697         CAEthernetSetUnicastSocket(-1);
698         g_unicastServerport = -1;
699     }
700
701 #ifdef __WITH_DTLS__
702     // Stop secure unicast server and set client socket accordingly
703     if (CA_STATUS_OK == CAEthernetStopSecureUnicastServer())
704     {
705         CAEthernetSetSecureUnicastSocket(-1);
706         g_secureUnicastServerport = -1;
707     }
708 #endif
709
710     //Stop multicast server and set the state accordingly
711     if (CA_STATUS_OK == CAEthernetStopMulticastServer())
712     {
713         g_isMulticastServerStarted = false;
714     }
715
716     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
717     return CA_STATUS_OK;
718 }
719
720 CAResult_t CAStopEthernet()
721 {
722     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
723
724     g_startUnicastServerRequested = false;
725     g_startMulticastServerRequested = false;
726
727     // Stop ethernet network monitor
728     CAEthernetStopNetworkMonitor();
729
730     // Stop send queue thread
731     if (g_sendQueueHandle && false == g_sendQueueHandle->isStop)
732     {
733         CAQueueingThreadStop(g_sendQueueHandle);
734     }
735
736     // Stop Unicast, Secured unicast and Multicast servers running
737     CAEthernetStopServers();
738
739     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
740     return CA_STATUS_OK;
741 }
742
743 void CATerminateEthernet()
744 {
745     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
746
747 #ifdef __WITH_DTLS__
748     CADTLSSetAdapterCallbacks(NULL, NULL, DTLS_ETHERNET);
749     CAAdapterNetDtlsDeInit();
750 #endif
751
752     // Stop ethernet adapter
753     CAStopEthernet();
754
755     // Terminate Ethernet server
756     CAEthernetTerminateServer();
757
758     // Terminate network monitor
759     CAEthernetSetConnectionStateChangeCallback(NULL);
760     CAEthernetTerminateNetworkMonitor();
761
762     // Terminate message queue handler
763     CAEthernetDeinitializeQueueHandles();
764     CAEthernetSetPacketReceiveCallback(NULL);
765
766     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
767     return;
768 }
769
770 void CAEthernetSendDataThread(void *threadData)
771 {
772     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
773
774     CAEthernetData *ethernetData = (CAEthernetData *) threadData;
775     if (!ethernetData)
776     {
777         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "Invalid ethernet data!");
778         return;
779     }
780
781     if (NULL != ethernetData->remoteEndpoint)
782     {
783         char *address = ethernetData->remoteEndpoint->addressInfo.IP.ipAddress;
784         uint16_t port = ethernetData->remoteEndpoint->addressInfo.IP.port;
785
786 #ifdef __WITH_DTLS__
787         if (!ethernetData->remoteEndpoint->isSecured)
788         {
789             CAEthernetSendData(address, port, ethernetData->data, ethernetData->dataLen, false,
790                                ethernetData->remoteEndpoint->isSecured);
791         }
792         else
793         {
794             OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt called!");
795             uint8_t cacheFlag = 0;
796             CAResult_t  result = CAAdapterNetDtlsEncrypt(address, port, ethernetData->data,
797                                  ethernetData->dataLen, &cacheFlag, DTLS_ETHERNET);
798
799             if (CA_STATUS_OK != result)
800             {
801                 OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt failed!");
802             }
803             OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG,
804                 "CAAdapterNetDtlsEncrypt returned with cache[%d]",cacheFlag);
805         }
806 #else
807         CAEthernetSendData(address, port, ethernetData->data, ethernetData->dataLen, false,
808                            ethernetData->remoteEndpoint->isSecured);
809 #endif
810     }
811     else
812     {
813         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "Send Multicast Data is called");
814         CAEthernetSendData(CA_MULTICAST_IP, CA_MCAST_PORT, ethernetData->data,
815                            ethernetData->dataLen, true, false);
816     }
817
818     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
819 }
820
821 CAEthernetData *CACreateEthernetData(const CARemoteEndpoint_t *remoteEndpoint, const void *data,
822                              uint32_t dataLength)
823 {
824     CAEthernetData *ethernetData = (CAEthernetData *) OICMalloc(sizeof(CAEthernetData));
825     if (!ethernetData)
826     {
827         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Memory allocation failed!");
828         return NULL;
829     }
830
831     ethernetData->remoteEndpoint = CAAdapterCopyRemoteEndpoint(remoteEndpoint);
832     ethernetData->data = (void *)OICMalloc(dataLength);
833     if (NULL == ethernetData->data)
834     {
835         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Memory allocation failed!");
836         CAFreeEthernetData(ethernetData);
837         return NULL;
838     }
839
840     memcpy(ethernetData->data, data, dataLength);
841     ethernetData->dataLen = dataLength;
842
843     return ethernetData;
844 }
845
846 void CAFreeEthernetData(CAEthernetData *ethernetData)
847 {
848     if (!ethernetData)
849     {
850         return;
851     }
852
853     CAAdapterFreeRemoteEndpoint(ethernetData->remoteEndpoint);
854     OICFree(ethernetData->data);
855     OICFree(ethernetData);
856 }
857
858 void CADataDestroyer(void *data, uint32_t size)
859 {
860     CAEthernetData *etdata = (CAEthernetData *) data;
861
862     CAFreeEthernetData(etdata);
863 }
864
865