Replace/examine usages of mem* and strcat/strcpy
[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->ipAddress, info->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                 if (info->isSecured)
266                 {
267 #ifdef __WITH_DTLS__
268                     CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress, srcPort,
269                                                              (uint8_t *)recvBuffer, recvLen,
270                                                              CA_IPV4);
271                     OIC_LOG_V(DEBUG, IP_SERVER_TAG,
272                               "CAAdapterNetDtlsDecrypt returns [%d]", ret);
273 #endif
274                 }
275                 else //both multicast and unicast
276                 {
277                     ca_mutex_lock(g_mutexAdapterServerContext);
278
279                     if (g_adapterEthServerContext->packetReceivedCallback)
280                     {
281                         g_adapterEthServerContext->packetReceivedCallback(srcIPAddress, srcPort,
282                                                                           recvBuffer, recvLen,
283                                                                           false, NULL);
284                     }
285
286                     ca_mutex_unlock(g_mutexAdapterServerContext);
287                 }
288             }
289         }
290         CAClearServerInfoList(tempServerInfoList);
291     }
292     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
293 }
294
295 static CAResult_t CACreateSocket(int *socketFD, const char *localIp, uint16_t *port,
296                                  bool forceBindStart)
297 {
298     VERIFY_NON_NULL(socketFD, IP_SERVER_TAG, "socketFD is NULL");
299     VERIFY_NON_NULL(localIp, IP_SERVER_TAG, "localIp is NULL");
300     VERIFY_NON_NULL(port, IP_SERVER_TAG, "port is NULL");
301     // Create a UDP socket
302     int sock = -1;
303
304 #ifdef SOCK_CLOEXEC
305     sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
306 #endif
307
308     if (-1 == sock)
309     {
310         sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
311     }
312
313     if (-1 == sock)
314     {
315         OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to create Socket, Error code: %s",
316                   strerror(errno));
317         return CA_STATUS_FAILED;
318     }
319
320     // Make the socket non-blocking
321     if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
322     {
323         OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
324                   strerror(errno));
325
326         close(sock);
327         return CA_STATUS_FAILED;
328     }
329
330     if (true == forceBindStart)
331     {
332         int setOptionOn = SOCKETOPTION;
333         if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &setOptionOn,
334                              sizeof(setOptionOn)))
335         {
336             OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
337                       strerror(errno));
338             close(sock);
339             return CA_STATUS_FAILED;
340         }
341     }
342
343     struct sockaddr_in sockAddr = { 0 };
344     uint16_t serverPort = *port;
345     sockAddr.sin_family = AF_INET;
346     sockAddr.sin_port = htons(serverPort);
347     if (localIp)
348     {
349         sockAddr.sin_addr.s_addr = inet_addr(localIp);
350     }
351
352     int16_t i = 0;
353     bool isBound = false;
354     for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
355     {
356         if (-1 == bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)))
357         {
358             if (false == forceBindStart)
359             {
360                 OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
361                           strerror(errno));
362
363                 //Set the port to next one
364                 serverPort += 1;
365                 sockAddr.sin_port = htons(serverPort);
366                 continue;
367             }
368             else
369             {
370                 OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to bind socket[%s]!",
371                           strerror(errno));
372                 break;
373             }
374         }
375
376         isBound = true;
377         break;
378     }
379
380     if (false == isBound)
381     {
382         close(sock);
383         return CA_STATUS_FAILED;
384     }
385
386     *port = serverPort;
387     *socketFD = sock;
388     return CA_STATUS_OK;
389 }
390
391 static void CACloseSocket(int socketFD)
392 {
393     if (-1 == socketFD)
394     {
395         OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid Socket Fd");
396         return;
397     }
398
399     // close the socket
400     if (-1 == close(socketFD))
401     {
402         OIC_LOG_V(ERROR, IP_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
403                   strerror(errno));
404     }
405 }
406
407 static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port,
408                                        bool forceBindStart, bool isSecured, int *serverFD)
409 {
410     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
411
412     VERIFY_NON_NULL(serverFD, IP_SERVER_TAG, "serverFD");
413     VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
414     VERIFY_NON_NULL(port, IP_SERVER_TAG, "port");
415
416     CAResult_t ret = CACreateSocket(serverFD, localAddress, port, forceBindStart);
417     if (CA_STATUS_OK != ret)
418     {
419         OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create unicast socket");
420     }
421
422     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
423     return ret;
424 }
425
426 static CAResult_t CAIPStartPacketReceiverHandler()
427 {
428     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
429
430     ca_mutex_lock(g_mutexServerInfoList);
431
432     uint32_t listLength = u_arraylist_length(g_serverInfoList);
433
434     ca_mutex_unlock(g_mutexServerInfoList);
435
436     ca_mutex_lock(g_mutexAdapterServerContext);
437
438     if (!g_adapterEthServerContext)
439     {
440         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
441         ca_mutex_unlock(g_mutexAdapterServerContext);
442         return CA_STATUS_FAILED;
443     }
444
445     if (1 == listLength) //Its first time.
446     {
447         g_packetHandlerStopFlag = false;
448         if (CA_STATUS_OK != ca_thread_pool_add_task(g_adapterEthServerContext->threadPool,
449                                                    CAReceiveHandler, NULL ))
450         {
451             OIC_LOG(ERROR, IP_SERVER_TAG, "thread_pool_add_task failed!");
452             ca_mutex_unlock(g_mutexAdapterServerContext);
453             return CA_STATUS_FAILED;
454         }
455         OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread started successfully.");
456     }
457     else
458     {
459         OIC_LOG(DEBUG, IP_SERVER_TAG, "CAReceiveHandler thread already is running");
460     }
461     ca_mutex_unlock(g_mutexAdapterServerContext);
462
463     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
464
465     return CA_STATUS_OK;
466 }
467
468 static void CAIPServerDestroyMutex(void)
469 {
470     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
471
472     if (g_mutexServerInfoList)
473     {
474         ca_mutex_free(g_mutexServerInfoList);
475         g_mutexServerInfoList = NULL;
476     }
477
478     if (g_mutexAdapterServerContext)
479     {
480         ca_mutex_free(g_mutexAdapterServerContext);
481         g_mutexAdapterServerContext = NULL;
482     }
483
484     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
485 }
486
487 static CAResult_t CAIPServerCreateMutex(void)
488 {
489     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
490
491     g_mutexServerInfoList = ca_mutex_new();
492     if (!g_mutexServerInfoList)
493     {
494         OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
495         return CA_MEMORY_ALLOC_FAILED;
496     }
497
498     g_mutexAdapterServerContext = ca_mutex_new();
499     if (!g_mutexAdapterServerContext)
500     {
501         OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to created mutex!");
502         ca_mutex_free(g_mutexServerInfoList);
503         g_mutexServerInfoList = NULL;
504         return CA_MEMORY_ALLOC_FAILED;
505     }
506
507     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
508     return CA_STATUS_OK;
509 }
510
511 CAResult_t CAIPInitializeServer(const ca_thread_pool_t threadPool)
512 {
513     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
514
515     // Input validation
516     VERIFY_NON_NULL(threadPool, IP_SERVER_TAG, "Thread pool handle is NULL");
517
518     // Initialize mutex
519     if (CA_STATUS_OK != CAIPServerCreateMutex())
520     {
521         OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create mutex!");
522         return CA_STATUS_FAILED;
523     }
524
525     ca_mutex_lock(g_mutexAdapterServerContext);
526     g_adapterEthServerContext = (CAAdapterIPServerContext_t *) OICCalloc(1,
527                                  sizeof(CAAdapterIPServerContext_t));
528
529     if (!g_adapterEthServerContext)
530     {
531         OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
532         ca_mutex_unlock(g_mutexAdapterServerContext);
533         return CA_MEMORY_ALLOC_FAILED;
534     }
535
536     g_adapterEthServerContext->threadPool = threadPool;
537
538     ca_mutex_unlock(g_mutexAdapterServerContext);
539
540     ca_mutex_lock(g_mutexServerInfoList);
541
542     g_serverInfoList = u_arraylist_create();
543     if (!g_serverInfoList)
544     {
545         OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_create failed");
546         ca_mutex_unlock(g_mutexServerInfoList);
547         return CA_MEMORY_ALLOC_FAILED;
548     }
549     ca_mutex_unlock(g_mutexServerInfoList);
550     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
551     return CA_STATUS_OK;
552 }
553
554 void CAIPTerminateServer()
555 {
556     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
557     ca_mutex_lock(g_mutexAdapterServerContext);
558     if (!g_adapterEthServerContext)
559     {
560         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
561         ca_mutex_unlock(g_mutexAdapterServerContext);
562         return;
563     }
564
565     OICFree(g_adapterEthServerContext);
566     g_adapterEthServerContext = NULL;
567
568     ca_mutex_unlock(g_mutexAdapterServerContext);
569
570     ca_mutex_lock(g_mutexServerInfoList);
571
572     CAClearServerInfoList(g_serverInfoList);
573     g_serverInfoList = NULL;
574
575     ca_mutex_unlock(g_mutexServerInfoList);
576     // Destroy mutex
577     CAIPServerDestroyMutex();
578
579     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
580
581 }
582
583 CAResult_t CAIPStartUnicastServer(const char *localAddress, uint16_t *port,
584                                         bool forceBindStart, bool isSecured)
585 {
586     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
587
588     // Input validation
589     VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
590     VERIFY_NON_NULL(port, IP_SERVER_TAG, "port");
591
592     if (0 >= *port)
593     {
594         OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid input: port is invalid!");
595         return CA_STATUS_INVALID_PARAM;
596     }
597
598     ca_mutex_lock(g_mutexServerInfoList);
599     bool isUnicastServerStarted = CAIsUnicastServerStarted(g_serverInfoList, localAddress, *port);
600     if (!isUnicastServerStarted)
601     {
602         int unicastServerFd = -1;
603         if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceBindStart, isSecured,
604                                                  &unicastServerFd))
605         {
606             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to start unicast server!");
607             ca_mutex_unlock(g_mutexServerInfoList);
608             return CA_STATUS_FAILED;
609         }
610
611         CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t));
612         if (!info)
613         {
614             OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
615             close(unicastServerFd);
616             ca_mutex_unlock(g_mutexServerInfoList);
617             return CA_MEMORY_ALLOC_FAILED;
618         }
619
620         char *netMask = NULL;
621         if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask))
622         {
623             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
624         }
625         if (netMask)
626         {
627             OICStrcpy(info->subNetMask, sizeof(info->subNetMask), netMask);
628             OICFree(netMask);
629         }
630         OICStrcpy(info->ipAddress, sizeof(info->ipAddress), localAddress);
631         info->port = *port;
632         info->socketFd = unicastServerFd;
633         info->isSecured = isSecured;
634         info->isServerStarted = true;
635         info->isMulticastServer = false;
636         OICStrcpy(info->ifAddr, sizeof(info->ifAddr), localAddress);
637
638         CAResult_t res = CAAddServerInfo(g_serverInfoList, info);
639         if (CA_STATUS_OK != res)
640         {
641             OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!");
642             close(unicastServerFd);
643             ca_mutex_unlock(g_mutexServerInfoList);
644             return res;
645         }
646         ca_mutex_unlock(g_mutexServerInfoList);
647
648         res = CAIPStartPacketReceiverHandler();
649         if (CA_STATUS_OK != res)
650         {
651             OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!");
652             close(unicastServerFd);
653             return res;
654         }
655     }
656     else
657     {
658         OIC_LOG_V(DEBUG, IP_SERVER_TAG, "Already Unicast Server Started ip [%s] port [%d]",
659                   localAddress, *port);
660         ca_mutex_unlock(g_mutexServerInfoList);
661     }
662
663     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
664     return CA_STATUS_OK;
665 }
666
667 CAResult_t CAIPStartMulticastServer(const char *localAddress, const char *multicastAddress,
668                                           uint16_t multicastPort)
669 {
670     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
671
672     // Input validation
673     VERIFY_NON_NULL(localAddress, IP_SERVER_TAG, "localAddress");
674     VERIFY_NON_NULL(multicastAddress, IP_SERVER_TAG, "port");
675
676     uint16_t port = multicastPort;
677     if (0 >= port)
678     {
679         OIC_LOG(ERROR, IP_SERVER_TAG, "Invalid input: Multicast port is invalid!");
680         return CA_STATUS_INVALID_PARAM;
681     }
682
683     ca_mutex_lock(g_mutexServerInfoList);
684     bool isMulticastServerStarted = CAIsMulticastServerStarted(g_serverInfoList, localAddress,
685                                                                multicastAddress, port);
686     if (!isMulticastServerStarted)
687     {
688         int mulicastServerFd = -1;
689         CAResult_t ret = CACreateSocket(&mulicastServerFd, multicastAddress, &port, true);
690         if (ret != CA_STATUS_OK)
691         {
692             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to create multicast socket");
693             ca_mutex_unlock(g_mutexServerInfoList);
694             return ret;
695         }
696
697         struct ip_mreq multicastMemberReq = {.imr_interface.s_addr = inet_addr(localAddress)};
698         inet_aton(multicastAddress, &multicastMemberReq.imr_multiaddr);
699
700         if (-1 == setsockopt(mulicastServerFd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
701                              (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
702         {
703             OIC_LOG_V(ERROR, IP_SERVER_TAG,
704                       "Failed to add to multicast group, Error code: %s\n", strerror(errno));
705             close(mulicastServerFd);
706             ca_mutex_unlock(g_mutexServerInfoList);
707             return CA_STATUS_FAILED;
708         }
709
710         CAServerInfo_t *info = (CAServerInfo_t *) OICCalloc(1, sizeof(CAServerInfo_t));
711         if (!info)
712         {
713             OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed");
714             close(mulicastServerFd);
715             ca_mutex_unlock(g_mutexServerInfoList);
716             return CA_MEMORY_ALLOC_FAILED;
717         }
718
719         char *netMask = NULL;
720         if (CA_STATUS_OK != CAIPGetInterfaceSubnetMask(localAddress, &netMask))
721         {
722             OIC_LOG(ERROR, IP_SERVER_TAG, "Failed to get IP subnet");
723         }
724         if (netMask)
725         {
726             OICStrcpy(info->subNetMask, sizeof(info->subNetMask), netMask);
727             OICFree(netMask);
728         }
729
730         OICStrcpy(info->ipAddress, sizeof(info->ipAddress), multicastAddress);
731         info->port = multicastPort;
732         info->socketFd = mulicastServerFd;
733         info->isSecured = false;
734         info->isServerStarted = true;
735         info->isMulticastServer = true;
736         OICStrcpy(info->ifAddr, sizeof(info->ifAddr), localAddress);
737
738         ret = CAAddServerInfo(g_serverInfoList, info);
739
740         if (CA_STATUS_OK != ret)
741         {
742             OIC_LOG(ERROR, IP_SERVER_TAG, "CAAddServerInfo failed!");
743             close(mulicastServerFd);
744             ca_mutex_unlock(g_mutexServerInfoList);
745             return ret;
746         }
747         ca_mutex_unlock(g_mutexServerInfoList);
748
749         ret = CAIPStartPacketReceiverHandler();
750         if (CA_STATUS_OK != ret)
751         {
752             OIC_LOG(ERROR, IP_SERVER_TAG, "CAIPStartPacketReceiverHandler failed!");
753             close(mulicastServerFd);
754             return ret;
755         }
756     }
757     else
758     {
759         OIC_LOG_V(DEBUG, IP_SERVER_TAG,
760                   "Multicast Server is already started on interface addr[%s]", localAddress);
761         ca_mutex_unlock(g_mutexServerInfoList);
762     }
763
764     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
765     return CA_STATUS_OK;
766 }
767
768 CAResult_t CAIPStopServer(const char *interfaceAddress)
769 {
770     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
771
772     VERIFY_NON_NULL(interfaceAddress, IP_SERVER_TAG, "interfaceAddress is NULL");
773
774     ca_mutex_lock(g_mutexServerInfoList);
775     uint32_t listIndex = 0;
776     uint32_t listLength = u_arraylist_length(g_serverInfoList);
777
778     for (listIndex = 0; listIndex < listLength;)
779     {
780         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
781         if (!info)
782         {
783             listIndex++;
784             continue;
785         }
786
787         if (info->isMulticastServer && strncmp(interfaceAddress, info->ifAddr, strlen(info->ifAddr))
788                 == 0)
789         {
790             if (u_arraylist_remove(g_serverInfoList, listIndex))
791             {
792                 struct ip_mreq multicastMemberReq = { { 0 }, { 0 } };
793
794                 multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr);
795                 inet_aton(info->ipAddress, &multicastMemberReq.imr_multiaddr);
796                 if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
797                                      (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
798                 {
799                     OIC_LOG_V(ERROR, IP_SERVER_TAG,
800                               "Failed to leave multicast group, Error code: %s", strerror(errno));
801                 }
802                 CACloseSocket(info->socketFd);
803                 OICFree(info);
804                 OIC_LOG(DEBUG, IP_SERVER_TAG, "Multicast server is stopped successfully.");
805                 // Reduce list length by 1 as we removed one element.
806                 listLength--;
807             }
808             else
809             {
810                 OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
811                 ca_mutex_unlock(g_mutexServerInfoList);
812                 return CA_STATUS_FAILED;
813             }
814         }
815         else if (strncmp(interfaceAddress, info->ipAddress, strlen(info->ipAddress)) == 0)
816         {
817             if (u_arraylist_remove(g_serverInfoList, listIndex))
818             {
819                 CACloseSocket(info->socketFd);
820                 OICFree(info);
821                 OIC_LOG(DEBUG, IP_SERVER_TAG, "Unicast server is stopped successfully.");
822                 // Reduce list length by 1 as we removed one element.
823                 listLength--;
824             }
825             else
826             {
827                 OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
828                 ca_mutex_unlock(g_mutexServerInfoList);
829                 return CA_STATUS_FAILED;
830             }
831         }
832         else
833         {
834             listIndex++;
835         }
836     }
837
838     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
839     ca_mutex_unlock(g_mutexServerInfoList);
840     return CA_STATUS_OK;
841 }
842
843 CAResult_t CAIPStopAllServers()
844 {
845     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
846
847     g_packetHandlerStopFlag = true;
848
849     ca_mutex_lock(g_mutexServerInfoList);
850
851     uint32_t listIndex = 0;
852     uint32_t listLength = u_arraylist_length(g_serverInfoList);
853     for (listIndex = 0; listIndex < listLength;)
854     {
855         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, listIndex);
856         if (!info)
857         {
858             listIndex++;
859             continue;
860         }
861         if (u_arraylist_remove(g_serverInfoList, listIndex))
862         {
863             if (info->isMulticastServer)
864             {
865                 struct ip_mreq multicastMemberReq = { { 0 }, { 0 } };
866
867                 multicastMemberReq.imr_interface.s_addr = inet_addr(info->ifAddr);
868                 inet_aton(info->ipAddress, &multicastMemberReq.imr_multiaddr);
869                 if (-1 == setsockopt(info->socketFd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
870                                      (char *) &multicastMemberReq, sizeof(struct ip_mreq)))
871                 {
872                     OIC_LOG_V(ERROR, IP_SERVER_TAG,
873                               "Failed to leave multicast group, Error code: %s", strerror(errno));
874                 }
875             }
876             CACloseSocket(info->socketFd);
877             //Freeing server info.
878             OICFree(info);
879             // Reduce list length by 1 as we removed one element.
880             listLength--;
881         }
882         else
883         {
884             OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_remove failed.");
885             ca_mutex_unlock(g_mutexServerInfoList);
886             return CA_STATUS_FAILED;
887         }
888     }
889
890     ca_mutex_unlock(g_mutexServerInfoList);
891
892     OIC_LOG(DEBUG, IP_SERVER_TAG, "All Server stopped successfully. OUT");
893     return CA_STATUS_OK;
894 }
895
896 uint16_t CAGetServerPortNum(const char *ipAddress, bool isSecured)
897 {
898     ca_mutex_lock(g_mutexServerInfoList);
899
900     uint16_t port = CAGetServerPort(g_serverInfoList, ipAddress, isSecured);
901
902     ca_mutex_unlock(g_mutexServerInfoList);
903
904     return port;
905 }
906
907 CAResult_t CAGetIPServerInfoList(u_arraylist_t **serverInfoList)
908 {
909     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
910     ca_mutex_lock(g_mutexServerInfoList);
911
912     uint32_t list_index = 0;
913     uint32_t list_length = u_arraylist_length(g_serverInfoList);
914     for (list_index = 0; list_index < list_length; list_index++)
915     {
916         CAServerInfo_t *info = (CAServerInfo_t *) u_arraylist_get(g_serverInfoList, list_index);
917         if (!info)
918         {
919             continue;
920         }
921
922         CAServerInfo_t *newNetinfo = (CAServerInfo_t *) OICMalloc(sizeof(CAServerInfo_t));
923         if (!newNetinfo)
924         {
925             OIC_LOG(ERROR, IP_SERVER_TAG, "Malloc failed!");
926             ca_mutex_unlock(g_mutexServerInfoList);
927             return CA_MEMORY_ALLOC_FAILED;
928         }
929
930         *newNetinfo = *info;
931
932         CAResult_t result = u_arraylist_add(*serverInfoList, (void *) newNetinfo);
933         if (CA_STATUS_OK != result)
934         {
935             OIC_LOG(ERROR, IP_SERVER_TAG, "u_arraylist_add failed!");
936             ca_mutex_unlock(g_mutexServerInfoList);
937             return CA_STATUS_FAILED;
938         }
939     }
940     ca_mutex_unlock(g_mutexServerInfoList);
941     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
942     return CA_STATUS_OK;
943 }
944
945 void CAIPSetPacketReceiveCallback(CAIPPacketReceivedCallback callback)
946 {
947     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
948
949     ca_mutex_lock(g_mutexAdapterServerContext);
950
951     if (!g_adapterEthServerContext)
952     {
953         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
954         ca_mutex_unlock(g_mutexAdapterServerContext);
955         return;
956     }
957     g_adapterEthServerContext->packetReceivedCallback = callback;
958
959     ca_mutex_unlock(g_mutexAdapterServerContext);
960
961     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
962 }
963
964 void CAIPSetExceptionCallback(CAIPExceptionCallback callback)
965 {
966     OIC_LOG(DEBUG, IP_SERVER_TAG, "IN");
967     ca_mutex_lock(g_mutexAdapterServerContext);
968
969     if (!g_adapterEthServerContext)
970     {
971         OIC_LOG(ERROR, IP_SERVER_TAG, "g_adapterEthServerContext NULL");
972         ca_mutex_unlock(g_mutexAdapterServerContext);
973         return;
974     }
975     g_adapterEthServerContext->exceptionCallback = callback;
976
977     ca_mutex_unlock(g_mutexAdapterServerContext);
978
979     OIC_LOG(DEBUG, IP_SERVER_TAG, "OUT");
980 }
981