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