1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
21 // Defining _POSIX_C_SOURCE macro with 200809L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2008 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2008 base specification,
26 // Refer http://pubs.opengroup.org/stage7tc1/
28 // For this specific file, see use of strndup,
29 // Refer http://man7.org/linux/man-pages/man3/strdup.3.html
30 #ifndef _POSIX_C_SOURCE
31 #define _POSIX_C_SOURCE 200809L
34 // Defining _BSD_SOURCE or _DEFAULT_SOURCE causes header files to expose
35 // definitions that may otherwise be skipped. Skipping can cause implicit
36 // declaration warnings and/or bugs and subtle problems in code execution.
37 // For glibc information on feature test macros,
38 // Refer http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
40 // This file requires #define use due to struct ip_mreq
41 #define _DEFAULT_SOURCE
43 #include <netinet/in.h>
45 #include "cawifiinterface.h"
47 #include <sys/types.h>
48 #include <sys/socket.h>
51 #include <sys/select.h>
52 #include <arpa/inet.h>
53 #include <netinet/in.h>
57 #include "caadapterutils.h"
59 #include "caadapternetdtls.h"
62 #include "oic_malloc.h"
64 // TODO g_stopSecureUnicast is set but never used. The three groups of
65 // globals should be combined into three instances of a common struct.
67 #define PIPE_READ_FD 0
69 #define PIPE_WRITE_FD 1
72 * @def WIFI_SERVER_TAG
73 * @brief Logging tag for module name
75 #define WIFI_SERVER_TAG "WIFI_SERVER"
78 * @def CA_UDP_BIND_RETRY_COUNT
79 * @brief Retry count in case of socket bind failure.
81 #define CA_UDP_BIND_RETRY_COUNT 10
85 * @brief max length for ip
90 * @var g_unicastServerSocketFD
91 * @brief Unicast server socket descriptor
93 static int32_t g_unicastServerSocketFD = -1;
96 * @var g_mutexUnicastServer
97 * @brief Mutex to synchronize unicast server
99 static u_mutex g_mutexUnicastServer = NULL;
103 * @brief Flag to control the Receive Unicast Data Thread
105 static bool g_stopUnicast = false;
108 * Handle to interrupt unicast server for stopping, etc.
110 static int g_unicastTriggerFD = -1;
113 * @var g_multicastServerSocketFD
114 * @brief socket descriptor for multicast server
116 static int32_t g_multicastServerSocketFD = -1;
119 * @var g_mutexMulticastServer
120 * @brief Mutex to synchronize secure multicast server
122 static u_mutex g_mutexMulticastServer = NULL;
125 * @var g_stopMulticast
126 * @brief Flag to control the Receive Multicast Data Thread
128 static bool g_stopMulticast = false;
131 * Handle to interrupt multicast server for stopping, etc.
133 static int g_multicastTriggerFD = -1;
137 * @var g_secureUnicastServerSocketFD
138 * @brief Secure unicast server socket descriptor
140 static int32_t g_secureUnicastServerSocketFD = -1;
143 * @var g_mutexSecureUnicastServer
144 * @brief Mutex to synchronize secure unicast server
146 static u_mutex g_mutexSecureUnicastServer = NULL;
149 * @var g_stopSecureUnicast
150 * @brief Flag to control the unicast secure data receive thread
152 static bool g_stopSecureUnicast = false;
157 * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
159 static u_thread_pool_t g_threadPool = NULL;
162 * @var g_multicastServerInterface
163 * @brief Local interface on which multicast server is running
165 static char g_multicastServerInterface[IPNAMESIZE];
168 * @var g_multicastMemberReq
169 * @brief ip_mreq structure passed to join a multicast group
171 static struct ip_mreq g_multicastMemberReq;
174 * @var g_packetReceivedCallback
175 * @brief Callback for notifying the upper layer on receival data from remote OIC device
177 static CAWiFiPacketReceivedCallback g_packetReceivedCallback = NULL;
180 * @var g_exceptionCallback
181 * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
183 static CAWiFiExceptionCallback g_exceptionCallback = NULL;
186 @brief Thread context information for unicast, multicast and secured unicast server
193 CAAdapterServerType_t type;
194 } CAAdapterReceiveThreadContext_t;
197 * Creates a non-blocking pipe.
199 * Creates a pipe with two file descriptors then sets both to be
200 * non-blocking. If an error occurs setting flags, any created handles
201 * will be closed and set to -1.
203 * @param pipefd array of two ints to store the pipe handles in.
205 * @return 0 on success, -1 otherwise.
207 static int createNonblockingPipe(int pipefd[2]);
210 * Sets the given file descriptor to be non-blocking.
212 * @param fd the file descriptor to make non-blocking.
214 * @return 0 on success, -1 otherwise.
216 static int setNonblocking(int fd);
218 static void CAReceiveHandler(void *data)
220 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
222 VERIFY_NON_NULL_VOID(data, WIFI_SERVER_TAG, "Invalid thread context");
224 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) data;
226 struct timeval timeout;
227 char recvBuffer[COAP_MAX_PDU_SIZE] =
230 while (true != *(ctx->stopFlag))
232 // safe to set longer value as select can be interrupted.
237 FD_SET(ctx->socket_fd, &reads);
238 int highest = (ctx->stopFd > ctx->socket_fd) ? ctx->stopFd : ctx->socket_fd;
239 if (ctx->stopFd != -1)
241 FD_SET(ctx->stopFd, &reads);
244 int32_t ret = select(highest + 1, &reads, NULL, NULL, &timeout);
245 if (*(ctx->stopFlag) == true)
247 OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Stop request received for [%d] server", ctx->type);
252 OIC_LOG_V(FATAL, WIFI_SERVER_TAG, "select returned error %s", strerror(errno));
256 if ((ctx->stopFd != -1) && FD_ISSET(ctx->stopFd, &reads))
258 // Doesn't matter at this point what happens (errors can be
259 // ignored). Just drain some data if this code ever gets hit.
260 recv(ctx->stopFd, recvBuffer, sizeof(recvBuffer), MSG_DONTWAIT);
263 if (!FD_ISSET(ctx->socket_fd, &reads))
268 memset(recvBuffer, 0, sizeof(recvBuffer));
270 // Read data from socket
271 struct sockaddr_in srcSockAddress;
273 socklen_t srcAddressLen = sizeof(srcSockAddress);
275 == (recvLen = recvfrom(ctx->socket_fd, recvBuffer, sizeof(recvBuffer), 0,
276 (struct sockaddr *) &srcSockAddress, &srcAddressLen)))
278 OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "%s", strerror(errno));
281 else if (0 == recvLen)
283 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Server socket shutdown [%d]!", ctx->type);
285 // Notify upper layer this exception
286 if (g_exceptionCallback)
288 g_exceptionCallback(ctx->type);
290 if (ctx->stopFd != -1)
298 const char *srcIPAddress = NULL;
299 uint16_t srcPort = 0;
301 srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
302 srcPort = ntohs(srcSockAddress.sin_port);
304 OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Received packet from %s:%d\n", srcIPAddress, srcPort);
305 OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Data: %s\t, DataLength: %d\n", recvBuffer, recvLen);
307 char *netMask = NULL;
308 if (CA_STATUS_OK != CAWiFiGetInterfaceSubnetMask(&netMask))
310 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to get ethernet subnet");
314 if (!CAAdapterIsSameSubnet(g_multicastServerInterface, srcIPAddress, netMask))
316 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "Packet received from different subnet, Ignore!");
328 case CA_UNICAST_SERVER:
329 case CA_MULTICAST_SERVER:
330 // Notify data to upper layer
331 if (g_packetReceivedCallback)
333 g_packetReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);
337 case CA_SECURED_UNICAST_SERVER:
339 CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,
341 (uint8_t *)recvBuffer,
343 OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
346 #endif //__WITH_DTLS__
348 // Should never occur
349 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "Invalid server type");
350 if (ctx->stopFd != -1)
360 if (ctx->stopFd != -1)
366 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
369 static CAResult_t CAWiFiCreateSocket(int32_t *socketFD, const char *localIp, uint16_t *port,
370 const bool forceStart)
373 // Create a UDP socket
374 if (-1 == (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
376 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to create Socket, Error code: %s",
378 return CA_STATUS_FAILED;
381 // Make the socket non-blocking
382 if (-1 == setNonblocking(sock))
385 return CA_STATUS_FAILED;
388 if (true == forceStart)
390 int32_t setOptionOn = 1;
392 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &setOptionOn,
393 sizeof(setOptionOn)))
395 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
399 return CA_STATUS_FAILED;
403 struct sockaddr_in sockAddr;
404 bool isBound = false;
405 uint16_t serverPort = 0;
413 return CA_STATUS_INVALID_PARAM;
416 memset((char *) &sockAddr, 0, sizeof(sockAddr));
417 sockAddr.sin_family = AF_INET;
418 sockAddr.sin_port = htons(serverPort);
421 sockAddr.sin_addr.s_addr = inet_addr(localIp);
425 sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
429 for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
431 if (-1 == bind(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)))
433 if (false == forceStart)
435 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
438 //Set the port to next one
440 sockAddr.sin_port = htons(serverPort);
445 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]!", strerror(errno));
454 if (false == isBound)
457 return CA_STATUS_FAILED;
465 static CAResult_t CAWiFiCloseSocket(int32_t *socketFD)
467 if (socketFD == NULL)
469 return CA_STATUS_INVALID_PARAM;
474 OIC_LOG(INFO, WIFI_SERVER_TAG, "Server not running");
475 return CA_SERVER_NOT_STARTED;
479 if (-1 == close(*socketFD))
481 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
483 return CA_STATUS_FAILED;
490 static CAResult_t CAStartUnicastServer(const char *localAddress, uint16_t *port,
491 const bool forceStart, bool isSecured, int32_t *serverFD)
493 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
495 if (serverFD == NULL)
497 return CA_STATUS_INVALID_PARAM;
500 CAResult_t ret = CAWiFiCreateSocket(serverFD, localAddress, port, forceStart);
501 if (CA_STATUS_OK != ret)
503 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create unicast socket");
508 * The task to listen for data from unicast socket is added to the thread pool.
509 * This is a blocking call is made where we try to receive some data..
510 * We will keep waiting until some data is received.
511 * This task will be terminated when thread pool is freed on stopping the adapters.
512 * Thread context will be freed by thread on exit.
514 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
515 sizeof(CAAdapterReceiveThreadContext_t));
518 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Out of memory!");
520 return CA_MEMORY_ALLOC_FAILED;
523 int pipefd[2] = {-1, -1};
524 if (createNonblockingPipe(pipefd) != 0)
526 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create pipe");
530 return CA_STATUS_FAILED;
533 g_unicastTriggerFD = pipefd[PIPE_WRITE_FD]; // The write end of the pipe
535 ctx->stopFlag = &g_stopUnicast;
536 ctx->stopFd = pipefd[PIPE_READ_FD]; // The read end of the pipe
537 ctx->socket_fd = *serverFD;
538 ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
539 if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *) ctx))
541 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create read thread!");
543 close(g_unicastTriggerFD);
544 g_unicastTriggerFD = -1;
548 OICFree((void *) ctx);
550 return CA_STATUS_FAILED;
553 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
557 static void CAWiFiServerDestroyMutex(void)
559 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
561 if (g_mutexUnicastServer)
563 u_mutex_free(g_mutexUnicastServer);
564 g_mutexUnicastServer = NULL;
568 if (g_mutexSecureUnicastServer)
570 u_mutex_free(g_mutexSecureUnicastServer);
571 g_mutexSecureUnicastServer = NULL;
575 if (g_mutexMulticastServer)
577 u_mutex_free(g_mutexMulticastServer);
578 g_mutexMulticastServer = NULL;
581 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
584 static CAResult_t CAWiFiServerCreateMutex(void)
586 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
588 g_mutexUnicastServer = u_mutex_new();
589 if (!g_mutexUnicastServer)
591 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");
592 return CA_STATUS_FAILED;
596 g_mutexSecureUnicastServer = u_mutex_new();
597 if (!g_mutexSecureUnicastServer)
599 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");
601 CAWiFiServerDestroyMutex();
602 return CA_STATUS_FAILED;
606 g_mutexMulticastServer = u_mutex_new();
607 if (!g_mutexMulticastServer)
609 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");
611 CAWiFiServerDestroyMutex();
612 return CA_STATUS_FAILED;
615 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
619 CAResult_t CAWiFiInitializeServer(const u_thread_pool_t threadPool)
621 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
624 VERIFY_NON_NULL(threadPool, WIFI_SERVER_TAG, "Thread pool handle is NULL");
627 if (CA_STATUS_OK != CAWiFiServerCreateMutex())
629 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create mutex!");
630 return CA_STATUS_FAILED;
633 g_threadPool = threadPool;
635 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
639 void CAWiFiTerminateServer(void)
641 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
646 CAWiFiServerDestroyMutex();
648 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
651 CAResult_t CAWiFiStartUnicastServer(const char *localAddress, uint16_t *port, const bool forceStart,
652 const bool isSecured, int32_t *serverFD)
654 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
657 VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "localAddress");
658 VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "port");
659 VERIFY_NON_NULL(serverFD, WIFI_SERVER_TAG, "server socket FD");
663 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Invalid input: port is invalid!");
664 return CA_STATUS_INVALID_PARAM;
668 if (false == isSecured)
670 u_mutex_lock(g_mutexUnicastServer);
671 if (-1 != g_unicastServerSocketFD)
673 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server is Started Already!",
674 CA_SERVER_STARTED_ALREADY);
676 *serverFD = g_unicastServerSocketFD;
677 u_mutex_unlock(g_mutexUnicastServer);
678 return CA_SERVER_STARTED_ALREADY;
681 g_stopUnicast = false;
683 != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
684 &g_unicastServerSocketFD))
686 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to start unicast server!");
687 g_unicastServerSocketFD = -1;
688 u_mutex_unlock(g_mutexUnicastServer);
689 return CA_STATUS_FAILED;
692 *serverFD = g_unicastServerSocketFD;
693 u_mutex_unlock(g_mutexUnicastServer);
696 else // Start unicast server for secured communication
698 u_mutex_lock(g_mutexSecureUnicastServer);
699 if (-1 != g_secureUnicastServerSocketFD)
701 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server is Started Already!",
702 CA_SERVER_STARTED_ALREADY);
704 *serverFD = g_secureUnicastServerSocketFD;
705 u_mutex_unlock(g_mutexSecureUnicastServer);
706 return CA_SERVER_STARTED_ALREADY;
709 g_stopSecureUnicast = false;
710 if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
711 &g_secureUnicastServerSocketFD))
713 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to start unicast server!");
714 g_secureUnicastServerSocketFD = -1;
715 u_mutex_unlock(g_mutexSecureUnicastServer);
716 return CA_STATUS_FAILED;
719 *serverFD = g_secureUnicastServerSocketFD;
720 u_mutex_unlock(g_mutexSecureUnicastServer);
723 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
727 CAResult_t CAWiFiStartMulticastServer(const char *localAddress, const char *multicastAddress,
728 const uint16_t multicastPort, int32_t *serverFD)
730 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
733 VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "localAddress");
734 VERIFY_NON_NULL(multicastAddress, WIFI_SERVER_TAG, "port");
735 VERIFY_NON_NULL(serverFD, WIFI_SERVER_TAG, "server socket FD");
737 uint16_t port = multicastPort;
740 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Invalid input: Multicast port is invalid!");
741 return CA_STATUS_INVALID_PARAM;
744 u_mutex_lock(g_mutexMulticastServer);
746 if (g_multicastServerSocketFD != -1)
748 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Multicast Server is already running!");
749 u_mutex_unlock(g_mutexMulticastServer);
750 return CA_SERVER_STARTED_ALREADY;
753 CAResult_t ret = CAWiFiCreateSocket(&g_multicastServerSocketFD, multicastAddress, &port, true);
754 if (ret != CA_STATUS_OK)
756 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create multicast socket");
757 u_mutex_unlock(g_mutexMulticastServer);
761 // Add membership to receiving socket (join group)
762 memset(&g_multicastMemberReq, 0, sizeof(struct ip_mreq));
763 g_multicastMemberReq.imr_interface.s_addr = inet_addr(localAddress);
764 inet_aton(multicastAddress, &g_multicastMemberReq.imr_multiaddr);
767 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
768 (char *) &g_multicastMemberReq, sizeof(struct ip_mreq)))
770 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
772 close(g_multicastServerSocketFD);
773 g_multicastServerSocketFD = -1;
774 u_mutex_unlock(g_mutexMulticastServer);
775 return CA_STATUS_FAILED;
779 * The task to listen to data from multicastcast socket is added to the thread pool.
780 * This is a blocking call is made where we try to receive some data.
781 * We will keep waiting until some data is received.
782 * This task will be terminated when thread pool is freed on stopping the adapters.
783 * Thread context will be freed by thread on exit.
785 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
786 sizeof(CAAdapterReceiveThreadContext_t));
789 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Out of memory!");
790 close(g_multicastServerSocketFD);
791 g_multicastServerSocketFD = -1;
792 return CA_MEMORY_ALLOC_FAILED;
795 int pipefd[2] = {-1, -1};
796 if (createNonblockingPipe(pipefd) != 0)
798 OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create pipe");
800 close(g_multicastServerSocketFD);
801 g_multicastServerSocketFD = -1;
802 return CA_STATUS_FAILED;
805 g_multicastTriggerFD = pipefd[PIPE_WRITE_FD]; // The write end of the pipe
807 ctx->stopFlag = &g_stopMulticast;
808 ctx->stopFd = pipefd[PIPE_READ_FD]; // The read end of the pipe
809 ctx->socket_fd = g_multicastServerSocketFD;
810 ctx->type = CA_MULTICAST_SERVER;
812 g_stopMulticast = false;
813 if (CA_STATUS_OK != u_thread_pool_add_task(g_threadPool, CAReceiveHandler, (void *) ctx))
815 OIC_LOG(ERROR, WIFI_SERVER_TAG, "thread_pool_add_task failed!");
817 close(g_multicastTriggerFD);
818 g_multicastTriggerFD = -1;
822 close(g_multicastServerSocketFD);
823 g_multicastServerSocketFD = -1;
824 g_stopMulticast = true;
825 u_mutex_unlock(g_mutexMulticastServer);
826 return CA_STATUS_FAILED;
829 *serverFD = g_multicastServerSocketFD;
830 strncpy(g_multicastServerInterface, localAddress, IPNAMESIZE);
831 u_mutex_unlock(g_mutexMulticastServer);
833 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
837 CAResult_t CAWiFiStopUnicastServer()
839 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
841 u_mutex_lock(g_mutexUnicastServer);
842 g_stopUnicast = true;
843 if (g_unicastTriggerFD != -1)
845 if (write(g_unicastTriggerFD, "X", 1) == -1)
847 OIC_LOG_V(ERROR, WIFI_SERVER_TAG,
848 "Failed to write to trigger, Error code: %s",
851 close(g_unicastTriggerFD);
852 g_unicastTriggerFD = -1;
854 CAResult_t ret = CAWiFiCloseSocket(&g_unicastServerSocketFD);
855 u_mutex_unlock(g_mutexUnicastServer);
857 OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Unicast server stopped [%d]", ret);
862 CAResult_t CAWiFiStopSecureUnicastServer()
864 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
866 u_mutex_lock(g_mutexSecureUnicastServer);
867 g_stopSecureUnicast = true;
868 if (g_unicastTriggerFD != -1)
870 if (write(g_unicastTriggerFD, "X", 1) == -1)
872 OIC_LOG_V(ERROR, WIFI_SERVER_TAG,
873 "Failed to write to trigger, Error code: %s",
876 close(g_unicastTriggerFD);
877 g_unicastTriggerFD = -1;
879 CAResult_t ret = CAWiFiCloseSocket(&g_secureUnicastServerSocketFD);
880 u_mutex_unlock(g_mutexSecureUnicastServer);
882 OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Secured unicast server stopped [%d]", ret);
887 CAResult_t CAWiFiStopMulticastServer(void)
889 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
891 u_mutex_lock(g_mutexMulticastServer);
893 if (g_multicastServerSocketFD == -1)
895 OIC_LOG(INFO, WIFI_SERVER_TAG, "Multicast server is not yet started");
896 u_mutex_unlock(g_mutexMulticastServer);
897 return CA_SERVER_NOT_STARTED;
900 g_stopMulticast = true;
901 if (g_multicastTriggerFD != -1)
903 if (write(g_multicastTriggerFD, "X", 1) == -1)
905 OIC_LOG_V(ERROR, WIFI_SERVER_TAG,
906 "Failed to write to trigger, Error code: %s",
909 close(g_multicastTriggerFD);
910 g_multicastTriggerFD = -1;
913 // leave the group after you are done
915 == setsockopt(g_multicastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
916 (char *) &g_multicastMemberReq, sizeof(struct ip_mreq)))
918 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",
922 CAResult_t ret = CAWiFiCloseSocket(&g_multicastServerSocketFD);
923 u_mutex_unlock(g_mutexMulticastServer);
925 OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Multicast server stopped [%d]", ret);
929 CAResult_t CAWiFiGetUnicastServerInfo(const bool isSecured, char **ipAddress, uint16_t *port,
932 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
935 VERIFY_NON_NULL(ipAddress, WIFI_SERVER_TAG, "IP address");
936 VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "Port");
937 VERIFY_NON_NULL(serverFD, WIFI_SERVER_TAG, "Server ID");
939 struct sockaddr_in sockAddr;
940 socklen_t len = sizeof(struct sockaddr_in);
941 if (-1 == getsockname(g_unicastServerSocketFD, (struct sockaddr *) &sockAddr, &len))
943 OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));
944 return CA_STATUS_FAILED;
947 char serverAddress[CA_IPADDR_SIZE];
948 inet_ntop(AF_INET, &sockAddr.sin_addr.s_addr, serverAddress, sizeof(serverAddress));
950 *ipAddress = strndup(serverAddress, strlen(serverAddress));
951 *port = ntohs(sockAddr.sin_port);
953 *serverFD = (true == isSecured) ? g_secureUnicastServerSocketFD : g_unicastServerSocketFD;
955 *serverFD = g_unicastServerSocketFD;
957 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
961 void CAWiFiSetPacketReceiveCallback(CAWiFiPacketReceivedCallback callback)
963 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
965 g_packetReceivedCallback = callback;
968 void CAWiFiSetExceptionCallback(CAWiFiExceptionCallback callback)
970 OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
972 g_exceptionCallback = callback;
975 int setNonblocking(int fd)
977 int rc = fcntl(fd, F_GETFL);
980 OIC_LOG_V(ERROR, WIFI_SERVER_TAG,
981 "Failed to get existing flags, Error code: %s",
986 rc = fcntl(fd, F_SETFL, rc | O_NONBLOCK);
989 OIC_LOG_V(ERROR, WIFI_SERVER_TAG,
990 "Failed to set non-blocking mode, Error code: %s",
998 int createNonblockingPipe(int pipefd[2])
1003 pipefd[PIPE_READ_FD] = -1;
1004 pipefd[PIPE_WRITE_FD] = -1;
1009 rc = setNonblocking(pipefd[PIPE_READ_FD]);
1014 rc = setNonblocking(pipefd[PIPE_WRITE_FD]);
1019 if (pipefd[PIPE_READ_FD] != -1)
1021 close(pipefd[PIPE_READ_FD]);
1022 pipefd[PIPE_READ_FD] = -1;
1024 if (pipefd[PIPE_WRITE_FD] != -1)
1026 close(pipefd[PIPE_WRITE_FD]);
1027 pipefd[PIPE_WRITE_FD]= -1;