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