Fixes a large number of Klocwork identified issues.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipserver.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 #include "caipinterface.h"
22
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/select.h>
28 #include <arpa/inet.h>
29 #include <netinet/in.h>
30 #include <errno.h>
31
32 #include "pdu.h"
33 #include "caadapterutils.h"
34 #ifdef __WITH_DTLS__
35 #include "caadapternetdtls.h"
36 #endif
37 #include "camutex.h"
38 #include "oic_malloc.h"
39
40 /**
41  * @def IP_SERVER_TAG
42  * @brief Logging tag for module name
43  */
44 #define IP_SERVER_TAG "IP_SERVER"
45
46 /**
47  * @def CA_UDP_BIND_RETRY_COUNT
48  * @brief Retry count in case of socket bind failure.
49  */
50 #define CA_UDP_BIND_RETRY_COUNT 10
51
52 /**
53  * @def IPNAMESIZE
54  * @brief Max length for ip address.
55  */
56 #define IPNAMESIZE 16
57
58 /**
59  * @def SOCKETOPTION
60  * @brief Socket option.
61  */
62 #define SOCKETOPTION 1
63
64 /**
65  * @var g_packetHandlerStopFlag
66  * @brief Flag for stopping packet handler thread.
67  */
68 static bool g_packetHandlerStopFlag = false;
69
70 /**
71  * @var CAAdapterIPServerContext_t
72  * @brief Thread context information for callbacks and threadpool.
73  */
74 typedef struct
75 {
76     ca_thread_pool_t threadPool;
77     CAIPPacketReceivedCallback packetReceivedCallback;
78     CAIPExceptionCallback exceptionCallback;
79 } CAAdapterIPServerContext_t;
80
81 /**
82  * @var g_serverInfoList
83  * @brief Mutex to synchronize ethenet adapter context.
84  */
85 static u_arraylist_t *g_serverInfoList = NULL;
86
87 /**
88  * @var g_mutexServerInfoList
89  * @brief Mutex to synchronize Server Information.
90  */
91 static ca_mutex g_mutexServerInfoList = NULL;
92
93 /**
94  * @var g_adapterEthServerContext
95  * @brief Mutex to synchronize ethenet adapter context.
96  */
97 static CAAdapterIPServerContext_t *g_adapterEthServerContext = NULL;
98
99 /**
100  * @var g_mutexAdapterServerContext
101  * @brief Mutex to synchronize unicast server
102  */
103 static ca_mutex g_mutexAdapterServerContext = NULL;
104
105 static void CAReceiveHandler(void *data)
106 {
107     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
108
109     fd_set readFds;
110     int maxSd = 0;
111     struct timeval timeout;
112     char recvBuffer[COAP_MAX_PDU_SIZE] = { 0 };
113
114     while (true != g_packetHandlerStopFlag)
115     {
116         timeout.tv_sec = 1;
117         timeout.tv_usec = 0;
118         FD_ZERO(&readFds);
119
120         ca_mutex_lock(g_mutexServerInfoList);
121         uint32_t listIndex = 0;
122         uint32_t listLength = u_arraylist_length(g_serverInfoList);
123
124         u_arraylist_t *tempServerInfoList = u_arraylist_create();
125         if (!tempServerInfoList)
126         {
127             OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed");
128             ca_mutex_unlock(g_mutexServerInfoList);
129             return;
130         }
131
132         for (listIndex = 0; listIndex < listLength; listIndex++)
133         {
134             CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
135             if (!info)
136             {
137                 listIndex++;
138                 continue;
139             }
140
141             int sd = info->socketFd;
142             //if valid socket descriptor then add to read list
143             if (sd > 0)
144             {
145                 FD_SET(sd, &readFds);
146             }
147
148             //highest file descriptor number, need it for the select function
149             if (sd > maxSd)
150             {
151                 maxSd = sd;
152             }
153
154             CAServerInfo_t *newInfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t));
155             if (!newInfo)
156             {
157                 OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
158                 CAClearServerInfoList(tempServerInfoList);
159                 ca_mutex_unlock(g_mutexServerInfoList);
160                 return;
161             }
162
163             memcpy(newInfo, info, sizeof(CAServerInfo_t));
164
165             CAResult_t result = u_arraylist_add(tempServerInfoList, (void *) newInfo);
166             if (CA_STATUS_OK != result)
167             {
168                 OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!Thread exit");
169                 CAClearServerInfoList(tempServerInfoList);
170                 ca_mutex_unlock(g_mutexServerInfoList);
171                 return;
172             }
173         }
174
175         ca_mutex_unlock(g_mutexServerInfoList);
176
177         int ret = select(maxSd + 1, &readFds, NULL, NULL, &timeout);
178         if (g_packetHandlerStopFlag)
179         {
180             OIC_LOG_V(DEBUG, IP_SERVER_TAG,
181                       "Packet receiver handler Stop request received. Thread exited");
182             CAClearServerInfoList(tempServerInfoList);
183             break;
184         }
185         if (ret < 0)
186         {
187             OIC_LOG_V(FATAL, IP_SERVER_TAG, "select returned error %s", strerror(errno));
188             CAClearServerInfoList(tempServerInfoList);
189             continue;
190         }
191
192         listLength = u_arraylist_length(tempServerInfoList);
193         for (listIndex = 0; listIndex < listLength; listIndex++)
194         {
195             CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(tempServerInfoList,
196                                                                       listIndex);
197             if (!info)
198             {
199                 continue;
200             }
201
202             int sd = info->socketFd;
203             if (FD_ISSET(sd , &readFds))
204             {
205                 OIC_LOG_V(ERROR, IP_SERVER_TAG,
206                           "data Received server information ip %s, port %d socket %d",
207                           info->ipAddress, info->port, sd);
208                 memset(recvBuffer, 0, sizeof(recvBuffer));
209
210                 struct sockaddr_in srcSockAddress = { 0 };
211                 socklen_t srcAddressLen = sizeof(srcSockAddress);
212
213                 //Reading from socket
214                 ssize_t recvLen = recvfrom(sd, recvBuffer, sizeof(recvBuffer), 0,
215                                            (struct sockaddr *) &srcSockAddress, &srcAddressLen);
216                 if (-1 == recvLen)
217                 {
218                     OIC_LOG_V(ERROR, IP_SERVER_TAG, "Recvfrom failed %s", strerror(errno));
219                     continue;
220                 }
221                 else if (0 == recvLen)
222                 {
223                     OIC_LOG_V(ERROR, IP_SERVER_TAG, "Server socket shutdown sock fd[%d]", sd);
224                     ca_mutex_lock(g_mutexAdapterServerContext);
225                     // Notify upper layer this exception
226                     if (g_adapterEthServerContext->exceptionCallback)
227                     {
228                         // need to make proper exception callback.
229                         //g_adapterEthServerContext->exceptionCallback(ctx->type);
230                     }
231                     ca_mutex_unlock(g_mutexAdapterServerContext);
232                 }
233
234                 char srcIPAddress[CA_IPADDR_SIZE] = { 0 };
235                 if (!inet_ntop(AF_INET, &srcSockAddress.sin_addr.s_addr, srcIPAddress,
236                                sizeof(srcIPAddress)))
237                 {
238
239                     OIC_LOG(ERROR, IP_SERVER_TAG, "inet_ntop is failed!");
240                     continue;
241                 }
242
243                 uint16_t srcPort = ntohs(srcSockAddress.sin_port);
244
245                 OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Received packet from %s:%d len %d",
246                           srcIPAddress, srcPort, recvLen);
247
248                 char *netMask = NULL;
249                 if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(info->ifAddr, &netMask))
250                 {
251                     OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
252                     continue;
253                 }
254
255                 if (!CAAdapterIsSameSubnet(info->ifAddr, srcIPAddress, netMask))
256                 {
257                     OIC_LOG(DEBUG, IP_SERVER_TAG,
258                             "Packet received from different subnet, Ignore!");
259                     OICFree(netMask);
260                     continue;
261                 }
262                 OICFree(netMask);
263
264                 if (info->isSecured)
265                 {
266 #ifdef __WITH_DTLS__
267                     CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress, srcPort,
268                                                              (uint8_t *)recvBuffer, recvLen,
269                                                              DTLS_IP);
270                     OIC_LOG_V(DEBUG, IP_SERVER_TAG,
271                               "CAAdapterNetDtlsDecrypt returns [%d]", ret);
272 #endif
273                 }
274                 else //both multicast and unicast
275                 {
276                     ca_mutex_lock(g_mutexAdapterServerContext);
277
278                     if (g_adapterEthServerContext->packetReceivedCallback)
279                     {
280                         g_adapterEthServerContext->packetReceivedCallback(srcIPAddress, srcPort,
281                                                                           recvBuffer, recvLen,
282                                                                           false);
283                     }
284
285                     ca_mutex_unlock(g_mutexAdapterServerContext);
286                 }
287             }
288         }
289         CAClearServerInfoList(tempServerInfoList);
290     }
291     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
292 }
293
294 static CAResult_t CACreateSocket(int *socketFD, const char *localIp, uint16_t *port,
295                                  bool forceBindStart)
296 {
297     VERIFY_NON_NULL(socketFD, IP_SERVER_TAG, "socketFD is NULL");
298     VERIFY_NON_NULL(localIp, IP_SERVER_TAG, "localIp is NULL");
299     VERIFY_NON_NULL(port, IP_SERVER_TAG, "port is NULL");
300     // Create a UDP socket
301     int sock = -1;
302
303 #ifdef SOCK_CLOEXEC
304     sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
305 #endif
306
307     if (-1 == sock)
308     {
309         sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
310     }
311
312     if (-1 == sock)
313     {
314         OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to create Socket, Error code: %s",
315                   strerror(errno));
316         return CA_STATUS_FAILED;
317     }
318
319     // Make the socket non-blocking
320     if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
321     {
322         OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
323                   strerror(errno));
324
325         close(sock);
326         return CA_STATUS_FAILED;
327     }
328
329     if (true == forceBindStart)
330     {
331         int setOptionOn = SOCKETOPTION;
332         if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &setOptionOn,
333                              sizeof(setOptionOn)))
334         {
335             OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
336                       strerror(errno));
337             close(sock);
338             return CA_STATUS_FAILED;
339         }
340     }
341
342     struct sockaddr_in sockAddr = { 0 };
343     uint16_t serverPort = *port;
344     sockAddr.sin_family = AF_INET;
345     sockAddr.sin_port = htons(serverPort);
346     if (localIp)
347     {
348         sockAddr.sin_addr.s_addr = inet_addr(localIp);
349     }
350     else
351     {
352         sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
353     }
354
355     int16_t i = 0;
356     bool isBound = false;
357     for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
358     {
359         if (-1 == bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)))
360         {
361             if (false == forceBindStart)
362             {
363                 OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
364                           strerror(errno));
365
366                 //Set the port to next one
367                 serverPort += 1;
368                 sockAddr.sin_port = htons(serverPort);
369                 continue;
370             }
371             else
372             {
373                 OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to bind socket[%s]!",
374                           strerror(errno));
375                 break;
376             }
377         }
378
379         isBound = true;
380         break;
381     }
382
383     if (false == isBound)
384     {
385         close(sock);
386         return CA_STATUS_FAILED;
387     }
388
389     *port = serverPort;
390     *socketFD = sock;
391     return CA_STATUS_OK;
392 }
393
394 static void CACloseSocket(int socketFD)
395 {
396     if (-1 == socketFD)
397     {
398         OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid Socket Fd");
399         return;
400     }
401
402     // close the socket
403     if (-1 == close(socketFD))
404     {
405         OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
406                   strerror(errno));
407     }
408 }
409
410 static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port,
411                                        bool forceBindStart, bool isSecured, int *serverFD)
412 {
413     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
414
415     VERIFY_NON_NULL(serverFD, IP_SERVER_TAG, "serverFD");
416     VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
417     VERIFY_NON_NULL(port, IP_SERVER_TAG, "port");
418
419     CAResult_t ret = CACreateSocket(serverFD, localAddress, port, forceBindStart);
420     if (CA_STATUS_OK != ret)
421     {
422         OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create unicast socket");
423     }
424
425     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
426     return ret;
427 }
428
429 static CAResult_t CAIPStartPacketReceiverHandler()
430 {
431     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
432
433     ca_mutex_lock(g_mutexServerInfoList);
434
435     uint32_t listLength = u_arraylist_length(g_serverInfoList);
436
437     ca_mutex_unlock(g_mutexServerInfoList);
438
439     ca_mutex_lock(g_mutexAdapterServerContext);
440
441     if (!g_adapterEthServerContext)
442     {
443         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
444         ca_mutex_unlock(g_mutexAdapterServerContext);
445         return CA_STATUS_FAILED;
446     }
447
448     if (1 == listLength) //Its first time.
449     {
450         g_packetHandlerStopFlag = false;
451         if (CA_STATUS_OK != ca_thread_pool_add_task(g_adapterEthServerContext->threadPool,
452                                                    CAReceiveHandler, NULL ))
453         {
454             OIC_LOG(ERROR, IP_SERVER_TAG, "thread_pool_add_task failed!");
455             ca_mutex_unlock(g_mutexAdapterServerContext);
456             return CA_STATUS_FAILED;
457         }
458         OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread started successfully.");
459     }
460     else
461     {
462         OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread already is running");
463     }
464     ca_mutex_unlock(g_mutexAdapterServerContext);
465
466     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
467
468     return CA_STATUS_OK;
469 }
470
471 static void CAIPServerDestroyMutex(void)
472 {
473     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
474
475     if (g_mutexServerInfoList)
476     {
477         ca_mutex_free(g_mutexServerInfoList);
478         g_mutexServerInfoList = NULL;
479     }
480
481     if (g_mutexAdapterServerContext)
482     {
483         ca_mutex_free(g_mutexAdapterServerContext);
484         g_mutexAdapterServerContext = NULL;
485     }
486
487     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
488 }
489
490 static CAResult_t CAIPServerCreateMutex(void)
491 {
492     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
493
494     g_mutexServerInfoList = ca_mutex_new();
495     if (!g_mutexServerInfoList)
496     {
497         OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
498         return CA_MEMORY_ALLOC_FAILED;
499     }
500
501     g_mutexAdapterServerContext = ca_mutex_new();
502     if (!g_mutexAdapterServerContext)
503     {
504         OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to created mutex!");
505         ca_mutex_free(g_mutexServerInfoList);
506         g_mutexServerInfoList = NULL;
507         return CA_MEMORY_ALLOC_FAILED;
508     }
509
510     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
511     return CA_STATUS_OK;
512 }
513
514 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
515 {
516     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
517
518     // Input validation
519     VERIFY_NON_NULL(threadPool, IP_SERVER_TAG, "Thread pool handle is NULL");
520
521     // Initialize mutex
522     if (CA_STATUS_OK != CAIPServerCreateMutex())
523     {
524         OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create mutex!");
525         return CA_STATUS_FAILED;
526     }
527
528     ca_mutex_lock(g_mutexAdapterServerContext);
529     g_adapterEthServerContext = (CAAdapterIPServerContext_t *) OICCalloc(1,
530                                  sizeof(CAAdapterIPServerContext_t));
531
532     if (!g_adapterEthServerContext)
533     {
534         OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
535         ca_mutex_unlock(g_mutexAdapterServerContext);
536         return CA_MEMORY_ALLOC_FAILED;
537     }
538
539     g_adapterEthServerContext->threadPool = threadPool;
540
541     ca_mutex_unlock(g_mutexAdapterServerContext);
542
543     ca_mutex_lock(g_mutexServerInfoList);
544
545     g_serverInfoList = u_arraylist_create();
546     if (!g_serverInfoList)
547     {
548         OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed");
549         ca_mutex_unlock(g_mutexServerInfoList);
550         return CA_MEMORY_ALLOC_FAILED;
551     }
552     ca_mutex_unlock(g_mutexServerInfoList);
553     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
554     return CA_STATUS_OK;
555 }
556
557 void CAIPTerminateServer()
558 {
559     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
560     ca_mutex_lock(g_mutexAdapterServerContext);
561     if (!g_adapterEthServerContext)
562     {
563         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
564         ca_mutex_unlock(g_mutexAdapterServerContext);
565         return;
566     }
567
568     OICFree(g_adapterEthServerContext);
569     g_adapterEthServerContext = NULL;
570
571     ca_mutex_unlock(g_mutexAdapterServerContext);
572
573     ca_mutex_lock(g_mutexServerInfoList);
574
575     CAClearServerInfoList(g_serverInfoList);
576     g_serverInfoList = NULL;
577
578     ca_mutex_unlock(g_mutexServerInfoList);
579     // Destroy mutex
580     CAIPServerDestroyMutex();
581
582     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
583
584 }
585
586 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
587                                         bool forceBindStart, bool isSecured)
588 {
589     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
590
591     // Input validation
592     VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
593     VERIFY_NON_NULL(port, IP_SERVER_TAG, "port");
594
595     if (0 >= *port)
596     {
597         OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid input: port is invalid!");
598         return CA_STATUS_INVALID_PARAM;
599     }
600
601     ca_mutex_lock(g_mutexServerInfoList);
602     bool isUnicastServerStarted = CAIsUnicastServerStarted(g_serverInfoList, localAddress, *port);
603     if (!isUnicastServerStarted)
604     {
605         int unicastServerFd = -1;
606         if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceBindStart, isSecured,
607                                                  &unicastServerFd))
608         {
609             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to start unicast server!");
610             ca_mutex_unlock(g_mutexServerInfoList);
611             return CA_STATUS_FAILED;
612         }
613
614         CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t));
615         if (!info)
616         {
617             OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
618             close(unicastServerFd);
619             ca_mutex_unlock(g_mutexServerInfoList);
620             return CA_MEMORY_ALLOC_FAILED;
621         }
622
623         char *netMask = NULL;
624         if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask))
625         {
626             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
627         }
628         if (netMask)
629         {
630             strncpy(info->subNetMask, netMask, sizeof(info->subNetMask) - 1);
631             info->subNetMask[sizeof(info->subNetMask)-1] = '\0';
632             OICFree(netMask);
633         }
634         strncpy(info->ipAddress, localAddress, sizeof(info->ipAddress) - 1);
635         info->ipAddress[sizeof(info->ipAddress) - 1] = '\0';
636         info->port = *port;
637         info->socketFd = unicastServerFd;
638         info->isSecured = isSecured;
639         info->isServerStarted = true;
640         info->isMulticastServer = false;
641         strncpy(info->ifAddr, localAddress, sizeof(info->ifAddr) - 1);
642         info->ifAddr[sizeof(info->ifAddr) - 1] = '\0';
643
644         CAResult_t res = CAAddServerInfo(g_serverInfoList, info);
645         if (CA_STATUS_OK != res)
646         {
647             OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!");
648             close(unicastServerFd);
649             ca_mutex_unlock(g_mutexServerInfoList);
650             return res;
651         }
652         ca_mutex_unlock(g_mutexServerInfoList);
653
654         res = CAIPStartPacketReceiverHandler();
655         if (CA_STATUS_OK != res)
656         {
657             OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!");
658             close(unicastServerFd);
659             return res;
660         }
661     }
662     else
663     {
664         OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Already Unicast Server Started ip [%s] port [%d]",
665                   localAddress, *port);
666         ca_mutex_unlock(g_mutexServerInfoList);
667     }
668
669     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
670     return CA_STATUS_OK;
671 }
672
673 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
674                                           uint16_t multicastPort)
675 {
676     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
677
678     // Input validation
679     VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
680     VERIFY_NON_NULL(multicastAddress, IP_SERVER_TAG, "port");
681
682     uint16_t port = multicastPort;
683     if (0 >= port)
684     {
685         OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid input: Multicast port is invalid!");
686         return CA_STATUS_INVALID_PARAM;
687     }
688
689     ca_mutex_lock(g_mutexServerInfoList);
690     bool isMulticastServerStarted = CAIsMulticastServerStarted(g_serverInfoList, localAddress,
691                                                                multicastAddress, port);
692     if (!isMulticastServerStarted)
693     {
694         int mulicastServerFd = -1;
695         CAResult_t ret = CACreateSocket(&mulicastServerFd, multicastAddress, &port, true);
696         if (ret != CA_STATUS_OK)
697         {
698             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create multicast socket");
699             ca_mutex_unlock(g_mutexServerInfoList);
700             return ret;
701         }
702
703         struct ip_mreq multicastMemberReq = {.imr_interface.s_addr = inet_addr(localAddress)};
704         inet_aton(multicastAddress, &multicastMemberReq.imr_multiaddr);
705
706         if (-1 == setsockopt(mulicastServerFd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
707                              (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
708         {
709             OIC_LOG_V(ERROR, IP_SERVER_TAG,
710                       "Failed to add to multicast group, Error code: %s\n", strerror(errno));
711             close(mulicastServerFd);
712             ca_mutex_unlock(g_mutexServerInfoList);
713             return CA_STATUS_FAILED;
714         }
715
716         CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t));
717         if (!info)
718         {
719             OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
720             close(mulicastServerFd);
721             ca_mutex_unlock(g_mutexServerInfoList);
722             return CA_MEMORY_ALLOC_FAILED;
723         }
724
725         char *netMask = NULL;
726         if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask))
727         {
728             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
729         }
730         if (netMask)
731         {
732             strncpy(info->subNetMask, netMask, sizeof(info->subNetMask) - 1);
733             info->subNetMask[sizeof(info->subNetMask) -1] = '\0';
734             OICFree(netMask);
735         }
736
737         strncpy(info->ipAddress, multicastAddress, sizeof(info->ipAddress) - 1);
738         info->ipAddress[sizeof(info->ipAddress) -1] = '\0';
739         info->port = multicastPort;
740         info->socketFd = mulicastServerFd;
741         info->isSecured = false;
742         info->isServerStarted = true;
743         info->isMulticastServer = true;
744         strncpy(info->ifAddr, localAddress, sizeof(info->ifAddr)-1);
745         info->ifAddr[sizeof(info->ifAddr) -1] = '\0';
746
747         ret = CAAddServerInfo(g_serverInfoList, info);
748
749         if (CA_STATUS_OK != ret)
750         {
751             OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!");
752             close(mulicastServerFd);
753             ca_mutex_unlock(g_mutexServerInfoList);
754             return ret;
755         }
756         ca_mutex_unlock(g_mutexServerInfoList);
757
758         ret = CAIPStartPacketReceiverHandler();
759         if (CA_STATUS_OK != ret)
760         {
761             OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!");
762             close(mulicastServerFd);
763             return ret;
764         }
765     }
766     else
767     {
768         OIC_LOG_V(DEBUG, IP_SERVER_TAG,
769                   "Multicast Server is already started on interface addr[%s]", localAddress);
770         ca_mutex_unlock(g_mutexServerInfoList);
771     }
772
773     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
774     return CA_STATUS_OK;
775 }
776
777 CAResult_t CAIPStopServer(const char *interfaceAddress)
778 {
779     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
780
781     VERIFY_NON_NULL(interfaceAddress, IP_SERVER_TAG, "interfaceAddress is NULL");
782
783     ca_mutex_lock(g_mutexServerInfoList);
784     uint32_t listIndex = 0;
785     uint32_t listLength = u_arraylist_length(g_serverInfoList);
786
787     for (listIndex = 0; listIndex < listLength;)
788     {
789         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
790         if (!info)
791         {
792             listIndex++;
793             continue;
794         }
795
796         if (info->isMulticastServer && strncmp(interfaceAddress, info->ifAddr, strlen(info->ifAddr))
797                 == 0)
798         {
799             if (u_arraylist_remove(g_serverInfoList, listIndex))
800             {
801                 struct ip_mreq multicastMemberReq = { { 0 }, { 0 } };
802
803                 multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr);
804                 inet_aton(info->ipAddress, &multicastMemberReq.imr_multiaddr);
805                 if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
806                                      (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
807                 {
808                     OIC_LOG_V(ERROR, IP_SERVER_TAG,
809                               "Failed to leave multicast group, Error code: %s", strerror(errno));
810                 }
811                 CACloseSocket(info->socketFd);
812                 OICFree(info);
813                 OIC_LOG_V(DEBUG, IP_SERVER_TAG,
814                           "Multicast server is stopped successfully on IF [%s]", info->ifAddr);
815                 // Reduce list length by 1 as we removed one element.
816                 listLength--;
817             }
818             else
819             {
820                 OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
821                 ca_mutex_unlock(g_mutexServerInfoList);
822                 return CA_STATUS_FAILED;
823             }
824         }
825         else if (strncmp(interfaceAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
826         {
827             if (u_arraylist_remove(g_serverInfoList, listIndex))
828             {
829                 CACloseSocket(info->socketFd);
830                 OICFree(info);
831                 OIC_LOG_V(DEBUG, IP_SERVER_TAG,
832                           "Unicast server is stopped successfully on IF [%s]", info->ifAddr);
833                 // Reduce list length by 1 as we removed one element.
834                 listLength--;
835             }
836             else
837             {
838                 OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
839                 ca_mutex_unlock(g_mutexServerInfoList);
840                 return CA_STATUS_FAILED;
841             }
842         }
843         else
844         {
845             listIndex++;
846         }
847     }
848
849     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
850     ca_mutex_unlock(g_mutexServerInfoList);
851     return CA_STATUS_OK;
852 }
853
854 CAResult_t CAIPStopAllServers()
855 {
856     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
857
858     g_packetHandlerStopFlag = true;
859
860     ca_mutex_lock(g_mutexServerInfoList);
861
862     uint32_t listIndex = 0;
863     uint32_t listLength = u_arraylist_length(g_serverInfoList);
864     for (listIndex = 0; listIndex < listLength;)
865     {
866         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
867         if (!info)
868         {
869             listIndex++;
870             continue;
871         }
872         if (u_arraylist_remove(g_serverInfoList, listIndex))
873         {
874             if (info->isMulticastServer)
875             {
876                 struct ip_mreq multicastMemberReq = { { 0 }, { 0 } };
877
878                 multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr);
879                 inet_aton(info->ipAddress, &multicastMemberReq.imr_multiaddr);
880                 if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
881                                      (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
882                 {
883                     OIC_LOG_V(ERROR, IP_SERVER_TAG,
884                               "Failed to leave multicast group, Error code: %s", strerror(errno));
885                 }
886             }
887             CACloseSocket(info->socketFd);
888             //Freeing server info.
889             OICFree(info);
890             // Reduce list length by 1 as we removed one element.
891             listLength--;
892         }
893         else
894         {
895             OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
896             ca_mutex_unlock(g_mutexServerInfoList);
897             return CA_STATUS_FAILED;
898         }
899     }
900
901     ca_mutex_unlock(g_mutexServerInfoList);
902
903     OIC_LOG(DEBUG, IP_SERVER_TAG, "All Server stopped successfully. OUT");
904     return CA_STATUS_OK;
905 }
906
907 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
908 {
909     ca_mutex_lock(g_mutexServerInfoList);
910
911     uint16_t port = CAGetServerPort(g_serverInfoList, ipAddress, isSecured);
912
913     ca_mutex_unlock(g_mutexServerInfoList);
914
915     return port;
916 }
917
918 CAResult_t CAGetIPServerInfoList(u_arraylist_t **serverInfoList)
919 {
920     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
921     ca_mutex_lock(g_mutexServerInfoList);
922
923     uint32_t list_index = 0;
924     uint32_t list_length = u_arraylist_length(g_serverInfoList);
925     for (list_index = 0; list_index < list_length; list_index++)
926     {
927         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, list_index);
928         if (!info)
929         {
930             continue;
931         }
932
933         CAServerInfo_t *newNetinfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t));
934         if (!newNetinfo)
935         {
936             OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed!");
937             ca_mutex_unlock(g_mutexServerInfoList);
938             return CA_MEMORY_ALLOC_FAILED;
939         }
940
941         memcpy(newNetinfo, info, sizeof(*info));
942
943         CAResult_t result = u_arraylist_add(*serverInfoList, (void *) newNetinfo);
944         if (CA_STATUS_OK != result)
945         {
946             OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!");
947             ca_mutex_unlock(g_mutexServerInfoList);
948             return CA_STATUS_FAILED;
949         }
950     }
951     ca_mutex_unlock(g_mutexServerInfoList);
952     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
953     return CA_STATUS_OK;
954 }
955
956 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
957 {
958     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
959
960     ca_mutex_lock(g_mutexAdapterServerContext);
961
962     if (!g_adapterEthServerContext)
963     {
964         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
965         ca_mutex_unlock(g_mutexAdapterServerContext);
966         return;
967     }
968     g_adapterEthServerContext->packetReceivedCallback = callback;
969
970     ca_mutex_unlock(g_mutexAdapterServerContext);
971
972     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
973 }
974
975 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
976 {
977     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
978     ca_mutex_lock(g_mutexAdapterServerContext);
979
980     if (!g_adapterEthServerContext)
981     {
982         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
983         ca_mutex_unlock(g_mutexAdapterServerContext);
984         return;
985     }
986     g_adapterEthServerContext->exceptionCallback = callback;
987
988     ca_mutex_unlock(g_mutexAdapterServerContext);
989
990     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
991 }
992