Implementation of following functionality
[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 "umutex.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   5683
48
49 /**
50  * @def CA_PORT
51  * @brief Port to listen for incoming data
52  */
53 #define CA_SECURE_PORT   5684
54
55 /**
56  * @def CA_MCAST_PORT
57  * @brief Multicast Port Number
58  */
59 #define CA_MCAST_PORT   5298
60
61 /**
62  * @def CA_MULTICAST_IP
63  * @brief Multicast IP Address
64  */
65 #define CA_MULTICAST_IP "224.0.1.187"
66
67
68 typedef struct
69 {
70     CARemoteEndpoint_t *remoteEndpoint;
71     void *data;
72     uint32_t dataLen;
73 } CAEthernetData;
74
75 /**
76  * @var gNetworkPacketCallback
77  * @brief Network Packet Received Callback to CA
78  */
79 static CANetworkPacketReceivedCallback gNetworkPacketCallback = NULL;
80
81 /**
82  * @var gEthernetNetworkChangeCallback
83  * @brief Network Changed Callback to CA
84  */
85 static CANetworkChangeCallback gNetworkChangeCallback = NULL;
86
87 /**
88  * @var gIsMulticastServerStarted
89  * @brief Flag to check if multicast server is started
90  */
91 static bool gIsMulticastServerStarted = false;
92
93 /**
94  * @var gIsStartServerCalled
95  * @brief Flag to check if server start requested by CA.
96  */
97 static bool gStartUnicastServerRequested = false;
98
99 /**
100  * @var gUnicastServerport
101  * @brief port number on which unicast server is running.
102  */
103 static int16_t gUnicastServerport = 0;
104
105 #ifdef __WITH_DTLS__
106 /**
107  * @var gSecureUnicastServerport
108  * @brief port number on which secure unicast server is running.
109  */
110 static int16_t gSecureUnicastServerport = 0;
111 #endif
112
113 /**
114  * @var gIsStartServerCalled
115  * @brief Flag to check if server start requested by CA.
116  */
117 static bool gStartMulticastServerRequested = false;
118
119 /**
120  * @var gSendQueueHandle
121  * @brief Queue handle for Send Data
122  */
123 static CAQueueingThread_t *gSendQueueHandle = NULL;
124
125 /**
126  * @var gThreadPool
127  * @brief ThreadPool for storing u_thread_pool_t handle passed from CA
128  */
129 static u_thread_pool_t gThreadPool = NULL;
130
131 static CAResult_t CAEthernetInitializeQueueHandles();
132 static void CAEthernetDeinitializeQueueHandles();
133 static void CAEthernetNotifyNetworkChange(const char *address, const int16_t port,
134                                           const CANetworkStatus_t status);
135 static void CAEthernetConnectionStateCB(const char *ipAddress,
136                                         const CANetworkStatus_t status);
137 static void CAEthernetPacketReceivedCB(const char *ipAddress, const uint32_t port,
138         const void *data, const uint32_t dataLength, const CABool_t isSecured);
139 #ifdef __WITH_DTLS__
140 static uint32_t CAEthernetPacketSendCB(const char *ipAddress, const uint32_t port,
141                                  const void *data, const uint32_t dataLength);
142 #endif
143 static CAResult_t CAEthernetStopServers();
144 static void CAEthernetSendDataThread(void *threadData);
145 static CAEthernetData *CACreateEthernetData(const CARemoteEndpoint_t *remoteEndpoint, void *data,
146                                             uint32_t dataLength);
147 void CAFreeEthernetData(CAEthernetData *ethernetData);
148
149
150 CAResult_t CAEthernetInitializeQueueHandles()
151 {
152     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
153
154     // Check if the message queue is already initialized
155     if (gSendQueueHandle)
156     {
157         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "Already queue is initialized!");
158         return CA_STATUS_OK;
159     }
160
161     // Create send message queue
162     gSendQueueHandle = OICMalloc(sizeof(CAQueueingThread_t));
163     if (!gSendQueueHandle)
164     {
165         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Memory allocation failed!");
166         return CA_MEMORY_ALLOC_FAILED;
167     }
168
169     if (CA_STATUS_OK != CAQueueingThreadInitialize(gSendQueueHandle, gThreadPool,
170             CAEthernetSendDataThread))
171     {
172         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Initialize send queue thread");
173         OICFree(gSendQueueHandle);
174         gSendQueueHandle = NULL;
175         return CA_STATUS_FAILED;
176     }
177
178     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
179     return CA_STATUS_OK;
180 }
181
182 void CAEthernetDeinitializeQueueHandles()
183 {
184     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
185
186     CAQueueingThreadDestroy(gSendQueueHandle);
187     OICFree(gSendQueueHandle);
188     gSendQueueHandle = NULL;
189
190     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
191 }
192
193 void CAEthernetNotifyNetworkChange(const char *address, const int16_t port,
194                                    const CANetworkStatus_t status)
195 {
196     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
197
198     CALocalConnectivity_t *localEndpoint = CAAdapterCreateLocalEndpoint(CA_ETHERNET, address);
199     if (!localEndpoint)
200     {
201         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Out of memory");
202         return;
203     }
204     localEndpoint->addressInfo.IP.port = port;
205
206     if (NULL != gNetworkChangeCallback)
207     {
208         gNetworkChangeCallback(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         int16_t port = CA_PORT;
228         int32_t serverFd = -1;
229
230         // Start Unicast server if requested earlier
231         if (gStartUnicastServerRequested)
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                 gUnicastServerport = 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                 gSecureUnicastServerport = 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 (gStartMulticastServerRequested)
264         {
265             int16_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                 gIsMulticastServerStarted = 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 uint32_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, CA_FALSE, CA_TRUE);
315
316     OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Successfully sent %d of encripted data!", sentLength);
317
318     return sentLength;
319 }
320 #endif
321
322 void CAEthernetPacketReceivedCB(const char *ipAddress, const uint32_t port,
323         const void *data, const uint32_t dataLength, const CABool_t 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 (gNetworkPacketCallback)
348     {
349         gNetworkPacketCallback(endPoint, buf, dataLength);
350     }
351
352     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
353 }
354
355 CAResult_t CAInitializeEthernet(CARegisterConnectivityCallback registerCallback,
356                                 CANetworkPacketReceivedCallback networkPacketCallback,
357                                 CANetworkChangeCallback netCallback, u_thread_pool_t handle)
358 {
359     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
360     VERIFY_NON_NULL(registerCallback, ETHERNET_ADAPTER_TAG, "registerCallback");
361     VERIFY_NON_NULL(networkPacketCallback, ETHERNET_ADAPTER_TAG, "networkPacketCallback");
362     VERIFY_NON_NULL(netCallback, ETHERNET_ADAPTER_TAG, "netCallback");
363     VERIFY_NON_NULL(handle, ETHERNET_ADAPTER_TAG, "thread pool handle");
364
365     gThreadPool  = handle;
366     gNetworkChangeCallback = netCallback;
367     gNetworkPacketCallback = networkPacketCallback;
368
369     CAResult_t ret = CAEthernetInitializeNetworkMonitor(gThreadPool);
370     if (CA_STATUS_OK != ret)
371     {
372         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to initialize n/w monitor![%d]", ret);
373         return ret;
374     }
375     CAEthernetSetConnectionStateChangeCallback(CAEthernetConnectionStateCB);
376
377     ret = CAEthernetInitializeServer(gThreadPool);
378     if (CA_STATUS_OK != ret)
379     {
380         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to initialize server![%d]", ret);
381         CATerminateEthernet();
382         return ret;
383     }
384
385     CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCB);
386 #ifdef __WITH_DTLS__
387     CAAdapterNetDtlsInit();
388     CADTLSSetAdapterCallbacks(CAEthernetPacketReceivedCB, CAEthernetPacketSendCB, DTLS_ETHERNET);
389 #endif
390
391     CAConnectivityHandler_t ethernetHandler;
392     ethernetHandler.startAdapter = CAStartEthernet;
393     ethernetHandler.startListenServer = CAStartEthernetListeningServer;
394     ethernetHandler.startDiscoverServer = CAStartEthernetDiscoveryServer;
395     ethernetHandler.sendData = CASendEthernetUnicastData;
396     ethernetHandler.sendDataToAll = CASendEthernetMulticastData;
397     ethernetHandler.GetnetInfo = CAGetEthernetInterfaceInformation;
398     ethernetHandler.readData = CAReadEthernetData;
399     ethernetHandler.stopAdapter = CAStopEthernet;
400     ethernetHandler.terminate = CATerminateEthernet;
401     registerCallback(ethernetHandler, CA_ETHERNET);
402
403     if (CA_STATUS_OK != CAEthernetInitializeQueueHandles())
404     {
405         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Initialize Queue Handle");
406         CATerminateEthernet();
407         return CA_STATUS_FAILED;
408     }
409
410     OIC_LOG(INFO, ETHERNET_ADAPTER_TAG, "IntializeEthernet is Success");
411     return CA_STATUS_OK;
412 }
413
414 CAResult_t CAStartEthernet()
415 {
416     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
417
418     // Start monitoring Ethernet network
419     CAResult_t ret = CAEthernetStartNetworkMonitor();
420     if (CA_STATUS_OK != ret)
421     {
422         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Start n/w monitor");
423         return ret;
424     }
425
426     // Start send queue thread
427     if (CA_STATUS_OK != CAQueueingThreadStart(gSendQueueHandle))
428     {
429         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Failed to Start Send Data Thread");
430         CAStopEthernet();
431         return CA_STATUS_FAILED;
432     }
433
434     gStartUnicastServerRequested = true;
435     bool retVal = CAEthernetIsConnected();
436     if (false == retVal)
437     {
438         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Ethernet is not Connected");
439         return CA_STATUS_OK;
440     }
441
442     char *ifcName;
443     char *ifcAdrs;
444     ret = CAEthernetGetInterfaceInfo(&ifcName, &ifcAdrs);
445     if(CA_STATUS_OK != ret)
446     {
447         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Failed to get ethernet interface info [%d]", ret);
448         return ret;
449     }
450     int16_t unicastPort = CA_PORT;
451     int32_t serverFd = 0;
452     // Address is hardcoded as we are using Single Interface
453     ret = CAEthernetStartUnicastServer(ifcAdrs, &unicastPort, false, false, &serverFd);
454     if (CA_STATUS_OK == ret)
455     {
456         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Unicast server started on %d port", unicastPort);
457         CAEthernetSetUnicastSocket(serverFd);
458         gUnicastServerport = unicastPort;
459     }
460
461 #ifdef __WITH_DTLS__
462     // Address is hardcoded as we are using Single Interface
463     unicastPort = CA_SECURE_PORT;
464     ret = CAEthernetStartUnicastServer(ifcAdrs, &unicastPort, false, true, &serverFd);
465     if (CA_STATUS_OK == ret)
466     {
467         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Secure Unicast server started on %d port", unicastPort);
468         CAEthernetSetSecureUnicastSocket(serverFd);
469         gSecureUnicastServerport = unicastPort;
470     }
471 #endif
472     OICFree(ifcName);
473     OICFree(ifcAdrs);
474     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
475     return ret;
476 }
477
478 CAResult_t CAStartEthernetListeningServer()
479 {
480     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
481
482     CAResult_t ret = CA_STATUS_OK;
483     int16_t multicastPort = CA_MCAST_PORT;
484
485     if (gIsMulticastServerStarted == true)
486     {
487         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG,
488                   "Failed to Start Multicast Server, Already Started!");
489         return CA_SERVER_STARTED_ALREADY;
490     }
491
492     gStartMulticastServerRequested = true;
493     bool retVal = CAEthernetIsConnected();
494     if (false == retVal)
495     {
496         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG,
497                   "Failed to Start Multicast Server, Ethernet not Connected");
498         return CA_STATUS_OK;
499     }
500
501     char *ifcName;
502     char *ifcAdrs;
503     ret = CAEthernetGetInterfaceInfo(&ifcName, &ifcAdrs);
504     if(CA_STATUS_OK != ret)
505     {
506         OIC_LOG_V(DEBUG, ETHERNET_ADAPTER_TAG, "Failed to get ethernet interface info [%d]", ret);
507         return ret;
508     }
509     int32_t multicastFd = 0;
510     ret = CAEthernetStartMulticastServer(ifcAdrs, CA_MULTICAST_IP, multicastPort, &multicastFd);
511     if (CA_STATUS_OK == ret)
512     {
513         OIC_LOG(INFO, ETHERNET_ADAPTER_TAG, "Multicast Server is Started Successfully");
514         gIsMulticastServerStarted = true;
515     }
516
517     OICFree(ifcName);
518     OICFree(ifcAdrs);
519     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
520     return ret;
521 }
522
523 CAResult_t CAStartEthernetDiscoveryServer()
524 {
525     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
526     return CAStartEthernetListeningServer();
527 }
528
529 uint32_t CASendEthernetUnicastData(const CARemoteEndpoint_t *remoteEndpoint, void *data,
530                                    uint32_t dataLength)
531 {
532     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
533
534     uint32_t dataSize = 0;
535     VERIFY_NON_NULL_RET(remoteEndpoint, ETHERNET_ADAPTER_TAG, "remoteEndpoint", dataSize);
536     VERIFY_NON_NULL_RET(data, ETHERNET_ADAPTER_TAG, "data", dataSize);
537     VERIFY_NON_NULL_RET(gSendQueueHandle, ETHERNET_ADAPTER_TAG, "sendQueueHandle", dataSize);
538
539     if (0 == dataLength)
540     {
541         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Invalid Data Length");
542         return dataSize;
543     }
544
545     // Create EthernetData to add to queue
546     CAEthernetData *ethernetData = CACreateEthernetData(remoteEndpoint, data, dataLength);
547     if (!ethernetData)
548     {
549         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to create ethernetData!");
550         return CA_MEMORY_ALLOC_FAILED;
551     }
552
553     // Add message to send queue
554     CAQueueingThreadAddData(gSendQueueHandle, ethernetData, sizeof(CAEthernetData));
555
556     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
557     return dataLength;
558 }
559
560 uint32_t CASendEthernetMulticastData(void *data, uint32_t dataLength)
561 {
562     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
563
564     uint32_t dataSize = 0;
565     VERIFY_NON_NULL_RET(data, ETHERNET_ADAPTER_TAG, "data", dataSize);
566     VERIFY_NON_NULL_RET(gSendQueueHandle, ETHERNET_ADAPTER_TAG, "sendQueueHandle", dataSize);
567
568     if (0 == dataLength)
569     {
570         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Invalid Data Length");
571         return dataSize;
572     }
573
574     // Create ethernetData to add to queue
575     CAEthernetData *ethernetData = CACreateEthernetData(NULL, data, dataLength);
576     if (!ethernetData)
577     {
578         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to create ethernetData!");
579         return CA_MEMORY_ALLOC_FAILED;
580     }
581
582     // Add message to send queue
583     CAQueueingThreadAddData(gSendQueueHandle, ethernetData, sizeof(CAEthernetData));
584
585     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
586     return dataLength;
587 }
588
589 CAResult_t CAGetEthernetInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
590 {
591     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
592     VERIFY_NON_NULL(info, ETHERNET_ADAPTER_TAG, "info");
593     VERIFY_NON_NULL(size, ETHERNET_ADAPTER_TAG, "size");
594
595     CALocalConnectivity_t *netInfo = NULL;
596     bool retVal = CAEthernetIsConnected();
597     if (false == retVal)
598     {
599         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG,
600                   "Failed to get interface address, Ethernet not Connected", CA_ADAPTER_NOT_ENABLED);
601         return CA_ADAPTER_NOT_ENABLED;
602     }
603
604     int32_t netInfoSize = 1;
605 #ifdef __WITH_DTLS__
606     if (gSecureUnicastServerport)
607     {
608         netInfoSize = 2;
609     }
610 #endif
611     netInfo = (CALocalConnectivity_t *) OICMalloc(sizeof(CALocalConnectivity_t) * netInfoSize);
612     VERIFY_NON_NULL_RET(netInfo, ETHERNET_ADAPTER_TAG, "malloc failed", CA_MEMORY_ALLOC_FAILED);
613     memset(netInfo, 0, sizeof(CALocalConnectivity_t) * netInfoSize);
614
615     char *ipAddress = NULL;
616     char *ifcName = NULL;
617     CAResult_t ret = CAEthernetGetInterfaceInfo(&ifcName, &ipAddress);
618     if (CA_STATUS_OK != ret || NULL == ipAddress)
619     {
620         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to get interface info [%d]", ret);
621
622         OICFree(netInfo);
623         OICFree(ipAddress);
624         OICFree(ifcName);
625         return ret;
626     }
627
628     // Create local endpoint using util function
629     CALocalConnectivity_t *endpoint = CAAdapterCreateLocalEndpoint(CA_ETHERNET, ipAddress);
630     if (NULL == endpoint)
631     {
632         OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "Failed to create Local Endpoint!",
633                   CA_MEMORY_ALLOC_FAILED);
634         OICFree(netInfo);
635         OICFree(ipAddress);
636         OICFree(ifcName);
637         return CA_MEMORY_ALLOC_FAILED;
638     }
639
640     // copy unciast server information
641     endpoint->isSecured = CA_FALSE;
642     endpoint->addressInfo.IP.port = gUnicastServerport;
643     memcpy(&netInfo[0], endpoint, sizeof(CALocalConnectivity_t));
644     *size = 1;
645 #ifdef __WITH_DTLS__
646     // copy sevure unicast server information
647     if (gSecureUnicastServerport)
648     {
649         endpoint->isSecured = CA_TRUE;
650         endpoint->addressInfo.IP.port = gSecureUnicastServerport;
651         memcpy(&netInfo[1], endpoint, sizeof(CALocalConnectivity_t));
652         *size = 2;
653     }
654 #endif
655     *info = netInfo;
656
657     OICFree(ipAddress);
658     OICFree(ifcName);
659     CAAdapterFreeLocalEndpoint(endpoint);
660
661     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
662     return CA_STATUS_OK;
663 }
664
665 CAResult_t CAReadEthernetData()
666 {
667     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
668     return CA_STATUS_OK;
669 }
670
671 CAResult_t CAEthernetStopServers()
672 {
673     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
674
675     // Stop unicast server and set client socket accordingly
676     if (CA_STATUS_OK == CAEthernetStopUnicastServer())
677     {
678         CAEthernetSetUnicastSocket(-1);
679         gUnicastServerport = -1;
680     }
681
682 #ifdef __WITH_DTLS__
683     // Stop secure unicast server and set client socket accordingly
684     if (CA_STATUS_OK == CAEthernetStopSecureUnicastServer())
685     {
686         CAEthernetSetSecureUnicastSocket(-1);
687         gSecureUnicastServerport = -1;
688     }
689 #endif
690
691     //Stop multicast server and set the state accordingly
692     if (CA_STATUS_OK == CAEthernetStopMulticastServer())
693     {
694         gIsMulticastServerStarted = false;
695     }
696
697     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
698     return CA_STATUS_OK;
699 }
700
701 CAResult_t CAStopEthernet()
702 {
703     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
704
705     gStartUnicastServerRequested = false;
706     gStartMulticastServerRequested = false;
707
708     // Stop ethernet network monitor
709     CAEthernetStopNetworkMonitor();
710
711     // Stop send queue thread
712     if (gSendQueueHandle && CA_FALSE == gSendQueueHandle->isStop)
713     {
714         CAQueueingThreadStop(gSendQueueHandle);
715     }
716
717     // Stop Unicast, Secured unicast and Multicast servers running
718     CAEthernetStopServers();
719
720     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
721     return CA_STATUS_OK;
722 }
723
724 void CATerminateEthernet()
725 {
726     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
727
728 #ifdef __WITH_DTLS__
729     CADTLSSetAdapterCallbacks(NULL, NULL, DTLS_ETHERNET);
730     CAAdapterNetDtlsDeInit();
731 #endif
732
733     // Stop ethernet adapter
734     CAStopEthernet();
735
736     // Terminate network monitor
737     CAEthernetSetConnectionStateChangeCallback(NULL);
738     CAEthernetTerminateNetworkMonitor();
739
740     // Terminate message queue handler
741     CAEthernetDeinitializeQueueHandles();
742     CAEthernetSetPacketReceiveCallback(NULL);
743
744     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
745     return;
746 }
747
748 void CAEthernetSendDataThread(void *threadData)
749 {
750     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "IN");
751
752     CAEthernetData *ethernetData = (CAEthernetData *) threadData;
753     if (!ethernetData)
754     {
755         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "Invalid ethernet data!");
756         return;
757     }
758
759     if (NULL != ethernetData->remoteEndpoint)
760     {
761         char *address = ethernetData->remoteEndpoint->addressInfo.IP.ipAddress;
762         uint32_t port = ethernetData->remoteEndpoint->addressInfo.IP.port;
763
764 #ifdef __WITH_DTLS__
765         if (!ethernetData->remoteEndpoint->isSecured)
766         {
767             CAEthernetSendData(address, port, ethernetData->data, ethernetData->dataLen, false,
768                            ethernetData->remoteEndpoint->isSecured);
769         }
770         else
771         {
772             OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt called!");
773             uint8_t cacheFalg = 0;
774             CAResult_t  result = CAAdapterNetDtlsEncrypt(address, port, ethernetData->data,
775                                  ethernetData->dataLen, &cacheFalg, DTLS_ETHERNET);
776
777             if (CA_STATUS_OK != result)
778             {
779                 OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt failed!");
780             }
781             OIC_LOG_V(ERROR, ETHERNET_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt returned with cache[%d]",
782                       cacheFalg);
783         }
784 #else
785         CAEthernetSendData(address, port, ethernetData->data, ethernetData->dataLen, false,
786                        ethernetData->remoteEndpoint->isSecured);
787 #endif
788     }
789     else
790     {
791         OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "Send Multicast Data is called");
792         CAEthernetSendData(CA_MULTICAST_IP, CA_MCAST_PORT, ethernetData->data,
793                        ethernetData->dataLen, true, false);
794     }
795
796     //Free ethernet data
797     CAFreeEthernetData(ethernetData);
798
799     OIC_LOG(DEBUG, ETHERNET_ADAPTER_TAG, "OUT");
800 }
801
802 CAEthernetData *CACreateEthernetData(const CARemoteEndpoint_t *remoteEndpoint, void *data,
803                                      uint32_t dataLength)
804 {
805     CAEthernetData *ethernetData = (CAEthernetData *) OICMalloc(sizeof(CAEthernetData));
806     if (!ethernetData)
807     {
808         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Memory allocation failed!");
809         return NULL;
810     }
811
812     ethernetData->remoteEndpoint = CAAdapterCopyRemoteEndpoint(remoteEndpoint);
813     ethernetData->data = (void *)OICMalloc(dataLength);
814     if (NULL == ethernetData->data)
815     {
816         OIC_LOG(ERROR, ETHERNET_ADAPTER_TAG, "Memory allocation failed!");
817         CAFreeEthernetData(ethernetData);
818         return NULL;
819     }
820
821     memcpy(ethernetData->data, data, dataLength);
822     ethernetData->dataLen = dataLength;
823
824     return ethernetData;
825 }
826
827 void CAFreeEthernetData(CAEthernetData *ethernetData)
828 {
829     if (!ethernetData)
830     {
831         return;
832     }
833
834     CAAdapterFreeRemoteEndpoint(ethernetData->remoteEndpoint);
835     OICFree(ethernetData->data);
836     OICFree(ethernetData);
837 }