Code portability cleanup.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ethernet_adapter / linux / caethernetserver.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
21 // Defining _POSIX_C_SOURCE macro with 200809L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2008 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2008 base specification,
26 // Refer http://pubs.opengroup.org/stage7tc1/
27 //
28 // For this specific file, see use of strndup,
29 // Refer http://man7.org/linux/man-pages/man3/strdup.3.html
30 #ifndef _POSIX_C_SOURCE
31 #define _POSIX_C_SOURCE 200809L
32 #endif
33
34 // Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
35 // definitions that may otherwise be skipped. Skipping can cause implicit
36 // declaration warnings and/or bugs and subtle problems in code execution.
37 // For glibc information on feature test macros,
38 // Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
39 //
40 // This file requires #define use due to struct ip_mreq
41 #define _DEFAULT_SOURCE
42 #define _BSD_SOURCE
43 #include <netinet/in.h>
44
45 #include "caethernetinterface.h"
46
47 #include <sys/types.h>
48 #include <sys/socket.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51 #include <sys/select.h>
52 #include <arpa/inet.h>
53 #include <string.h>
54
55 #include <errno.h>
56
57 #include "pdu.h"
58 #include "caadapterutils.h"
59 #ifdef __WITH_DTLS__
60 #include "caadapternetdtls.h"
61 #endif
62 #include "umutex.h"
63 #include "oic_malloc.h"
64
65 /**
66  * @def ETHERNET_SERVER_TAG
67  * @brief Logging tag for module name
68  */
69 #define ETHERNET_SERVER_TAG "ETHERNET_SERVER"
70
71 /**
72  * @def CA_UDP_BIND_RETRY_COUNT
73  * @brief Retry count in case of socket bind failure.
74  */
75 #define CA_UDP_BIND_RETRY_COUNT 10
76
77 /**
78  * @def IPNAMESIZE
79  * @brief max length for ip
80  */
81 #define IPNAMESIZE 16
82
83 /**
84  * @var g_unicastServerSocketFD
85  * @brief Unicast server socket descriptor
86  */
87 static int32_t g_unicastServerSocketFD = -1;
88
89 /**
90  * @var g_mutexUnicastServer
91  * @brief Mutex to synchronize unicast server
92  */
93 static u_mutex g_mutexUnicastServer = NULL;
94
95 /**
96  * @var g_stopUnicast
97  * @brief Flag to control the Receive Unicast Data Thread
98  */
99 static bool g_stopUnicast = false;
100
101 /**
102  * @var g_multicastServerSocketFD
103  * @brief socket descriptor for multicast server
104  */
105 static int32_t g_multicastServerSocketFD = -1;
106
107 /**
108  * @var g_mutexMulticastServer
109  * @brief Mutex to synchronize secure multicast server
110  */
111 static u_mutex g_mutexMulticastServer = NULL;
112
113 /**
114  * @var g_stopMulticast
115  * @brief Flag to control the Receive Multicast Data Thread
116  */
117 static bool g_stopMulticast = false;
118
119 #ifdef __WITH_DTLS__
120 /**
121  * @var g_secureUnicastServerSocketFD
122  * @brief Secure unicast server socket descriptor
123  */
124 static int32_t g_secureUnicastServerSocketFD = -1;
125
126 /**
127  * @var g_mutexSecureUnicastServer
128  * @brief Mutex to synchronize secure unicast server
129  */
130 static u_mutex g_mutexSecureUnicastServer = NULL;
131
132 /**
133  * @var g_stopSecureUnicast
134  * @brief Flag to control the unicast secure data receive thread
135  */
136 static bool g_stopSecureUnicast = false;
137 #endif
138
139 /**
140  * @var g_threadPool
141  * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
142  */
143 static u_thread_pool_t g_threadPool = NULL;
144
145 /**
146  * @var g_multicastServerInterface
147  * @brief Local interface on which multicast server is running
148  */
149 static char g_multicastServerInterface[IPNAMESIZE];
150
151 /**
152  * @var g_multicastMemberReq
153  * @brief ip_mreq structure passed to join a multicast group
154  */
155 static struct ip_mreq g_multicastMemberReq;
156
157 /**
158  * @var g_packetReceivedCallback
159  * @brief Callback for notifying the upper layer on receival data from remote OIC device
160  */
161 static CAEthernetPacketReceivedCallback g_packetReceivedCallback = NULL;
162
163 /**
164  * @var g_exceptionCallback
165  * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
166  */
167 static CAEthernetExceptionCallback g_exceptionCallback = NULL;
168
169 /**
170  @brief Thread context information for unicast, multicast and secured unicast server
171  */
172 typedef struct
173 {
174     bool *stopFlag;
175     int32_t socket_fd;
176     CAAdapterServerType_t type;
177 } CAAdapterReceiveThreadContext_t;
178
179 static void CAReceiveHandler(void *data)
180 {
181     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
182
183     // Input validation
184     VERIFY_NON_NULL_VOID(data, ETHERNET_SERVER_TAG, "Invalid thread context");
185
186     CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data;
187     fd_set reads;
188     struct timeval timeout;
189     char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
190
191     while (true != *(ctx->stopFlag))
192     {
193         timeout.tv_sec = 1;
194         timeout.tv_usec = 0;
195
196         FD_ZERO(&reads);
197         FD_SET(ctx->socket_fd, &reads);
198
199         int32_t ret = select(ctx->socket_fd + 1, &reads, NULL, NULL, &timeout);
200         if (*(ctx->stopFlag) == true)
201         {
202             OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG,
203                 "Stop request received for [%d] server", ctx->type);
204             break;
205         }
206
207         if (ret < 0)
208         {
209             OIC_LOG_V(FATAL, ETHERNET_SERVER_TAG, "select returned error %s", strerror(errno));
210             continue;
211         }
212
213         if (!FD_ISSET(ctx->socket_fd, &reads))
214         {
215             continue;
216         }
217
218         memset(recvBuffer, 0, sizeof(recvBuffer));
219
220         // Read data from socket
221         struct sockaddr_in srcSockAddress;
222         int32_t recvLen;
223         socklen_t srcAddressLen = sizeof(srcSockAddress);
224
225         recvLen = recvfrom(ctx->socket_fd, recvBuffer,
226                                       sizeof(recvBuffer), 0, (struct sockaddr *) &srcSockAddress,
227                                       &srcAddressLen);
228
229         if (-1 == recvLen)
230         {
231             OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "%s", strerror(errno));
232             continue;
233         }
234         else if (0 == recvLen)
235         {
236             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Server socket shutdown [%d]!", ctx->type);
237
238             // Notify upper layer this exception
239             if (g_exceptionCallback)
240             {
241                 g_exceptionCallback(ctx->type);
242             }
243             OICFree(ctx);
244             ctx = NULL;
245             return;
246         }
247
248         char srcIPAddress[CA_IPADDR_SIZE] = {0};
249         inet_ntop(AF_INET, &srcSockAddress.sin_addr.s_addr, srcIPAddress, sizeof(srcIPAddress));
250         uint16_t srcPort = 0;
251         srcPort = ntohs(srcSockAddress.sin_port);
252
253         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Received packet from %s:%d\n",
254                   srcIPAddress, srcPort);
255         OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
256                   recvBuffer, recvLen);
257
258         char *netMask = NULL;
259         if (CA_STATUS_OK != CAEthernetGetInterfaceSubnetMask(&netMask))
260         {
261             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to get ethernet subnet");
262             continue;
263         }
264
265         if (!CAAdapterIsSameSubnet(g_multicastServerInterface, srcIPAddress, netMask))
266         {
267             OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "Packet received from different subnet, Ignore!");
268             if (NULL != netMask)
269             {
270                 OICFree(netMask);
271             }
272             netMask = NULL;
273             continue;
274         }
275
276         OICFree(netMask);
277         switch (ctx->type)
278         {
279             case CA_UNICAST_SERVER:
280             case CA_MULTICAST_SERVER:
281                 // Notify data to upper layer
282                 if (g_packetReceivedCallback)
283                 {
284                     g_packetReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);
285                 }
286                 break;
287 #ifdef __WITH_DTLS__
288             case CA_SECURED_UNICAST_SERVER:
289                 {
290                     CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,
291                                      srcPort,
292                                      (uint8_t *)recvBuffer,
293                                      recvLen, DTLS_ETHERNET);
294                     OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG,
295                         "CAAdapterNetDtlsDecrypt returns [%d]", ret);
296                 }
297                 break;
298 #endif //__WITH_DTLS__
299             default:
300                 // Should never occur
301                 OIC_LOG_V(DEBUG, ETHERNET_SERVER_TAG, "Invalid server type");
302                 OICFree(ctx);
303                 ctx = NULL;
304                 return;
305         }
306     }
307     OICFree(ctx);
308     ctx = NULL;
309
310
311     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
312 }
313
314 static CAResult_t CACreateSocket(int32_t *socketFD, const char *localIp, uint16_t *port,
315                                  bool forceStart)
316 {
317     int32_t sock = -1;
318     // Create a UDP socket
319     sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
320     if (-1 == sock)
321     {
322         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to create Socket, Error code: %s",
323                   strerror(errno));
324         return CA_STATUS_FAILED;
325     }
326
327     // Make the socket non-blocking
328     if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
329     {
330         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
331                   strerror(errno));
332
333         close(sock);
334         return CA_STATUS_FAILED;
335     }
336
337     if (true == forceStart)
338     {
339         int32_t setOptionOn = 1;
340         if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
341                              (char *) &setOptionOn,
342                              sizeof(setOptionOn)))
343         {
344             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
345                       strerror(errno));
346
347             close(sock);
348             return CA_STATUS_FAILED;
349         }
350     }
351
352     struct sockaddr_in sockAddr;
353     bool isBound = false;
354     uint16_t serverPort = *port;
355
356     memset(&sockAddr, 0, sizeof(sockAddr));
357     sockAddr.sin_family = AF_INET;
358     sockAddr.sin_port = htons(serverPort);
359     if (localIp)
360     {
361         sockAddr.sin_addr.s_addr = inet_addr(localIp);
362     }
363     else
364     {
365         sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
366     }
367
368     int16_t i;
369     for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
370     {
371         if (-1 == bind(sock, (struct sockaddr *) &sockAddr,
372                        sizeof(sockAddr)))
373         {
374             if (false == forceStart)
375             {
376                 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
377                           strerror(errno));
378
379                 //Set the port to next one
380                 serverPort += 1;
381                 sockAddr.sin_port = htons(serverPort);
382                 continue;
383             }
384             else
385             {
386                 OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to bind socket[%s]!",
387                           strerror(errno));
388                 break;
389             }
390         }
391
392         isBound = true;
393         break;
394     }
395
396     if (false == isBound)
397     {
398         close(sock);
399         return CA_STATUS_FAILED;
400     }
401
402     *port = serverPort;
403     *socketFD = sock;
404     return CA_STATUS_OK;
405 }
406
407 static CAResult_t CACloseSocket(int32_t *socketFD)
408 {
409     if (socketFD == NULL)
410     {
411         return CA_STATUS_INVALID_PARAM;
412     }
413
414     if (-1 == *socketFD)
415     {
416         OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Server not running");
417         return CA_SERVER_NOT_STARTED;
418     }
419
420     // close the socket
421     if (-1 == close(*socketFD))
422     {
423         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
424                   strerror(errno));
425         return CA_STATUS_FAILED;
426     }
427
428     *socketFD = -1;
429     return CA_STATUS_OK;
430 }
431
432 static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port,
433                                        const bool forceStart, bool isSecured, int32_t *serverFD)
434 {
435     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
436
437     if (serverFD == NULL)
438     {
439         return CA_STATUS_INVALID_PARAM;
440     }
441
442     CAResult_t ret = CACreateSocket(serverFD, localAddress, port, forceStart);
443     if (CA_STATUS_OK != ret)
444     {
445         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create unicast socket");
446         return ret;
447     }
448
449     /**
450       * The task to listen for data from unicast socket is added to the thread pool.
451       * This is a blocking call is made where we try to receive some data..
452       * We will keep waiting until some data is received.
453       * This task will be terminated when thread pool is freed on stopping the adapters.
454       * Thread context will be freed by thread on exit.
455       */
456     CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
457                                            OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
458     if (!ctx)
459     {
460         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
461         close(*serverFD);
462         return CA_MEMORY_ALLOC_FAILED;
463     }
464
465     ctx->stopFlag = &g_stopUnicast;
466     ctx->socket_fd = *serverFD;
467     ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
468     if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *)ctx))
469     {
470         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create read thread!");
471         OICFree(ctx);
472         close(*serverFD);
473         *serverFD = -1;
474         return CA_STATUS_FAILED;
475     }
476
477     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
478     return CA_STATUS_OK;
479 }
480
481 static void CAEthernetServerDestroyMutex(void)
482 {
483     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
484
485     if (g_mutexUnicastServer)
486     {
487         u_mutex_free(g_mutexUnicastServer);
488         g_mutexUnicastServer = NULL;
489     }
490
491 #ifdef __WITH_DTLS__
492     if (g_mutexSecureUnicastServer)
493     {
494         u_mutex_free(g_mutexSecureUnicastServer);
495         g_mutexSecureUnicastServer = NULL;
496     }
497 #endif
498
499     if (g_mutexMulticastServer)
500     {
501         u_mutex_free(g_mutexMulticastServer);
502         g_mutexMulticastServer = NULL;
503     }
504
505     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
506 }
507
508 static CAResult_t CAEthernetServerCreateMutex(void)
509 {
510     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
511
512     if(g_mutexUnicastServer) {
513         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "mutex is already created!");
514
515         OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
516         return CA_STATUS_FAILED;
517     }
518
519     g_mutexUnicastServer = u_mutex_new();
520     if (!g_mutexUnicastServer)
521     {
522         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
523         return CA_STATUS_FAILED;
524     }
525
526 #ifdef __WITH_DTLS__
527     g_mutexSecureUnicastServer = u_mutex_new();
528     if (!g_mutexSecureUnicastServer)
529     {
530         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
531
532         CAEthernetServerDestroyMutex();
533         return CA_STATUS_FAILED;
534     }
535 #endif
536
537     g_mutexMulticastServer = u_mutex_new();
538     if (!g_mutexMulticastServer)
539     {
540         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to created mutex!");
541
542         CAEthernetServerDestroyMutex();
543         return CA_STATUS_FAILED;
544     }
545
546     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
547     return CA_STATUS_OK;
548 }
549
550 CAResult_t CAEthernetInitializeServer(const u_thread_pool_t threadPool)
551 {
552     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
553
554     // Input validation
555     VERIFY_NON_NULL(threadPool, ETHERNET_SERVER_TAG, "Thread pool handle is NULL");
556
557     // Initialize mutex
558     if (CA_STATUS_OK != CAEthernetServerCreateMutex())
559     {
560         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create mutex!");
561         return CA_STATUS_FAILED;
562     }
563
564     g_threadPool = threadPool;
565
566     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
567     return CA_STATUS_OK;
568 }
569
570 void CAEthernetTerminateServer(void)
571 {
572     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
573
574     g_threadPool = NULL;
575
576     // Destroy mutex
577     CAEthernetServerDestroyMutex();
578
579     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
580 }
581
582 CAResult_t CAEthernetStartUnicastServer(const char *localAddress, uint16_t *port,
583                                         bool forceStart, bool isSecured, int32_t *serverFD)
584 {
585     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
586
587     // Input validation
588     VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
589     VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "port");
590     VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
591
592     if (0 >= *port)
593     {
594         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: port is invalid!");
595         return CA_STATUS_INVALID_PARAM;
596     }
597
598     *serverFD = -1;
599     if (false == isSecured)
600     {
601         u_mutex_lock(g_mutexUnicastServer);
602         if (-1 != g_unicastServerSocketFD)
603         {
604             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
605                       CA_SERVER_STARTED_ALREADY);
606
607             *serverFD = g_unicastServerSocketFD;
608             u_mutex_unlock(g_mutexUnicastServer);
609             return CA_SERVER_STARTED_ALREADY;
610         }
611
612         g_stopUnicast = false;
613         if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
614                 &g_unicastServerSocketFD))
615         {
616             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
617             g_unicastServerSocketFD = -1;
618             u_mutex_unlock(g_mutexUnicastServer);
619             return CA_STATUS_FAILED;
620         }
621
622         *serverFD = g_unicastServerSocketFD;
623         u_mutex_unlock(g_mutexUnicastServer);
624     }
625 #ifdef __WITH_DTLS__
626     else // Start unicast server for secured communication
627     {
628         u_mutex_lock(g_mutexSecureUnicastServer);
629         if (-1 != g_secureUnicastServerSocketFD)
630         {
631             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Unicast Server is Started Already!",
632                       CA_SERVER_STARTED_ALREADY);
633
634             *serverFD = g_secureUnicastServerSocketFD;
635             u_mutex_unlock(g_mutexSecureUnicastServer);
636             return CA_SERVER_STARTED_ALREADY;
637         }
638
639         g_stopSecureUnicast = false;
640         if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
641                 &g_secureUnicastServerSocketFD))
642         {
643             OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to start unicast server!");
644             g_secureUnicastServerSocketFD = -1;
645             u_mutex_unlock(g_mutexSecureUnicastServer);
646             return CA_STATUS_FAILED;
647         }
648
649         *serverFD = g_secureUnicastServerSocketFD;
650         u_mutex_unlock(g_mutexSecureUnicastServer);
651     }
652 #endif
653     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
654     return CA_STATUS_OK;
655 }
656
657 CAResult_t CAEthernetStartMulticastServer(const char *localAddress,
658     const char *multicastAddress, const uint16_t multicastPort, int32_t *serverFD)
659 {
660     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
661
662     // Input validation
663     VERIFY_NON_NULL(localAddress, ETHERNET_SERVER_TAG, "localAddress");
664     VERIFY_NON_NULL(multicastAddress, ETHERNET_SERVER_TAG, "port");
665     VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "server socket FD");
666
667     uint16_t port = multicastPort;
668     if (0 >= port)
669     {
670         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Invalid input: Multicast port is invalid!");
671         return CA_STATUS_INVALID_PARAM;
672     }
673
674     u_mutex_lock(g_mutexMulticastServer);
675
676     if (g_multicastServerSocketFD != -1)
677     {
678         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Multicast Server is already running!");
679         u_mutex_unlock(g_mutexMulticastServer);
680         return CA_SERVER_STARTED_ALREADY;
681     }
682
683     CAResult_t ret = CACreateSocket(&g_multicastServerSocketFD, multicastAddress, &port, true);
684     if (ret != CA_STATUS_OK)
685     {
686         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Failed to create multicast socket");
687         u_mutex_unlock(g_mutexMulticastServer);
688         return ret;
689     }
690
691     // Add membership to receiving socket (join group)
692     memset(&g_multicastMemberReq, 0, sizeof(struct ip_mreq));
693     g_multicastMemberReq.imr_interface.s_addr = inet_addr(localAddress);
694     inet_aton(multicastAddress, &g_multicastMemberReq.imr_multiaddr);
695
696     if (-1 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
697                          (char *) &g_multicastMemberReq,
698                          sizeof(struct ip_mreq)))
699     {
700         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
701                   strerror(errno));
702         close(g_multicastServerSocketFD);
703         g_multicastServerSocketFD = -1;
704         u_mutex_unlock(g_mutexMulticastServer);
705         return CA_STATUS_FAILED;
706     }
707
708     /**
709       * The task to listen to data from multicastcast socket is added to the thread pool.
710       * This is a blocking call is made where we try to receive some data.
711       * We will keep waiting until some data is received.
712       * This task will be terminated when thread pool is freed on stopping the adapters.
713       * Thread context will be freed by thread on exit.
714       */
715     CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
716                                            OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
717     if (!ctx)
718     {
719         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "Out of memory!");
720         close(g_multicastServerSocketFD);
721         g_multicastServerSocketFD = -1;
722         return CA_MEMORY_ALLOC_FAILED;
723     }
724
725     ctx->stopFlag = &g_stopMulticast;
726     ctx->socket_fd = g_multicastServerSocketFD;
727     ctx->type = CA_MULTICAST_SERVER;
728
729     g_stopMulticast = false;
730     if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *)ctx))
731     {
732         OIC_LOG(ERROR, ETHERNET_SERVER_TAG, "thread_pool_add_task failed!");
733
734         close(g_multicastServerSocketFD);
735         g_multicastServerSocketFD = -1;
736         g_stopMulticast = true;
737         u_mutex_unlock(g_mutexMulticastServer);
738         return CA_STATUS_FAILED;
739     }
740
741     *serverFD = g_multicastServerSocketFD;
742     strncpy(g_multicastServerInterface, localAddress, IPNAMESIZE);
743     u_mutex_unlock(g_mutexMulticastServer);
744
745     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
746     return CA_STATUS_OK;
747 }
748
749 CAResult_t CAEthernetStopUnicastServer()
750 {
751     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
752
753     u_mutex_lock(g_mutexUnicastServer);
754     g_stopUnicast = true;
755     CAResult_t ret = CACloseSocket(&g_unicastServerSocketFD);
756     u_mutex_unlock(g_mutexUnicastServer);
757
758     OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Unicast server stopped [%d]", ret);
759     return ret;
760 }
761
762 #ifdef __WITH_DTLS__
763 CAResult_t CAEthernetStopSecureUnicastServer()
764 {
765     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
766
767     u_mutex_lock(g_mutexSecureUnicastServer);
768     g_stopSecureUnicast = true;
769     CAResult_t ret = CACloseSocket(&g_secureUnicastServerSocketFD);
770     u_mutex_unlock(g_mutexSecureUnicastServer);
771
772     OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Secured unicast server stopped [%d]", ret);
773     return ret;
774 }
775 #endif
776
777 CAResult_t CAEthernetStopMulticastServer(void)
778 {
779     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
780
781     u_mutex_lock(g_mutexMulticastServer);
782
783     if (g_multicastServerSocketFD == -1)
784     {
785         OIC_LOG(INFO, ETHERNET_SERVER_TAG, "Multicast server is not yet started");
786         u_mutex_unlock(g_mutexMulticastServer);
787         return CA_SERVER_NOT_STARTED;
788     }
789
790     g_stopMulticast = true;
791
792     // leave the group after you are done
793     if (-1 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
794                          (char *)&g_multicastMemberReq,
795                          sizeof(struct ip_mreq)))
796     {
797         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",
798                   strerror(errno));
799     }
800
801     CAResult_t ret = CACloseSocket(&g_multicastServerSocketFD);
802     u_mutex_unlock(g_mutexMulticastServer);
803
804     OIC_LOG_V(INFO, ETHERNET_SERVER_TAG, "Multicast server stopped [%d]", ret);
805     return ret;
806 }
807
808 CAResult_t CAEthernetGetUnicastServerInfo(bool isSecured,
809     char **ipAddress, uint16_t *port, int32_t *serverFD)
810 {
811     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
812
813     // Input validation
814     VERIFY_NON_NULL(ipAddress, ETHERNET_SERVER_TAG, "IP address");
815     VERIFY_NON_NULL(port, ETHERNET_SERVER_TAG, "Port");
816     VERIFY_NON_NULL(serverFD, ETHERNET_SERVER_TAG, "Server ID");
817
818     struct sockaddr_in sockAddr;
819     socklen_t len = sizeof(struct sockaddr_in);
820     if (-1 == getsockname(g_unicastServerSocketFD, (struct sockaddr *)&sockAddr, &len))
821     {
822         OIC_LOG_V(ERROR, ETHERNET_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));
823         return CA_STATUS_FAILED;
824     }
825
826
827     const char *serverAddress = inet_ntoa(sockAddr.sin_addr);
828     *ipAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) : NULL;
829     *port = ntohs(sockAddr.sin_port);
830 #ifdef __WITH_DTLS__
831     *serverFD = (true == isSecured) ? g_secureUnicastServerSocketFD : g_unicastServerSocketFD;
832 #else
833     *serverFD = g_unicastServerSocketFD;
834 #endif
835
836     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
837     return CA_STATUS_OK;
838 }
839
840 void CAEthernetSetPacketReceiveCallback(CAEthernetPacketReceivedCallback callback)
841 {
842     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
843     g_packetReceivedCallback = callback;
844     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
845 }
846
847 void CAEthernetSetExceptionCallback(CAEthernetExceptionCallback callback)
848 {
849     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "IN");
850     g_exceptionCallback = callback;
851     OIC_LOG(DEBUG, ETHERNET_SERVER_TAG, "OUT");
852 }
853