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