API change , Retransmission Callback on expiry , remove glib source for dynamic linking
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / wifi_adapter / linux / cawifiserver.c
index 9538e03..9dd2d84 100644 (file)
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
-#include "cawifiinterface.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/select.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <errno.h>
-
-#include "pdu.h"
-#include "caadapterutils.h"
-#ifdef __WITH_DTLS__
-#include "caadapternetdtls.h"
-#endif
-#include "umutex.h"
-
-/**
- * @def WIFI_SERVER_TAG
- * @brief Logging tag for module name
- */
-#define WIFI_SERVER_TAG "WIFI_SERVER"
-
-/**
- * @def CA_UDP_BIND_RETRY_COUNT
- * @brief Retry count in case of socket bind failure.
- */
-#define CA_UDP_BIND_RETRY_COUNT 10
-
-/**
- * @def IPNAMESIZE
- * @brief max length for ip
- */
-#define IPNAMESIZE 16
-
-/**
- * @var gUnicastServerSocketFD
- * @brief Unicast server socket descriptor
- */
-static int32_t gUnicastServerSocketFD = -1;
-
-/**
- * @var gMutexUnicastServer
- * @brief Mutex to synchronize unicast server
- */
-static u_mutex gMutexUnicastServer = NULL;
-
-/**
- * @var gStopUnicast
- * @brief Flag to control the Receive Unicast Data Thread
- */
-static bool gStopUnicast = false;
-
-/**
- * @var gMulticastServerSocketFD
- * @brief socket descriptor for multicast server
- */
-static int32_t gMulticastServerSocketFD = -1;
-
-/**
- * @var gMutexMulticastServer
- * @brief Mutex to synchronize secure multicast server
- */
-static u_mutex gMutexMulticastServer = NULL;
-
-/**
- * @var gStopMulticast
- * @brief Flag to control the Receive Multicast Data Thread
- */
-static bool gStopMulticast = false;
-
-#ifdef __WITH_DTLS__
-/**
- * @var gSecureUnicastServerSocketFD
- * @brief Secure unicast server socket descriptor
- */
-static int32_t gSecureUnicastServerSocketFD = -1;
-
-/**
- * @var gMutexSecureUnicastServer
- * @brief Mutex to synchronize secure unicast server
- */
-static u_mutex gMutexSecureUnicastServer = NULL;
-
-/**
- * @var gStopSecureUnicast
- * @brief Flag to control the unicast secure data receive thread
- */
-static bool gStopSecureUnicast = false;
-#endif
-
-/**
- * @var gThreadPool
- * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter
- */
-static u_thread_pool_t gThreadPool = NULL;
-
-/**
- * @var gMulticastServerInterface
- * @brief Local interface on which multicast server is running
- */
-static char gMulticastServerInterface[IPNAMESIZE];
-
-/**
- * @var gMulticastMemberReq
- * @brief ip_mreq structure passed to join a multicast group
- */
-static struct ip_mreq gMulticastMemberReq;
-
-/**
- * @var gPacketReceivedCallback
- * @brief Callback for notifying the upper layer on receival data from remote OIC device
- */
-static CAWiFiPacketReceivedCallback gPacketReceivedCallback = NULL;
-
-/**
- * @var gExceptionCallback
- * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception
- */
-static CAWiFiExceptionCallback gExceptionCallback = NULL;
-
-/**
- @brief Thread context information for unicast, multicast and secured unicast server
- */
-typedef struct
-{
-    bool *stopFlag;
-    int32_t socket_fd;
-    CAAdapterServerType_t type;
-}CAAdapterReceiveThreadContext_t;
-
-static void CAReceiveHandler(void *data)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-    // Input validation
-    VERIFY_NON_NULL_VOID(data, WIFI_SERVER_TAG, "Invalid thread context");
-
-    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data;
-    fd_set reads;
-    struct timeval timeout;
-    char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
-
-    while (true != *(ctx->stopFlag))
-    {
-        timeout.tv_sec = 1;
-        timeout.tv_usec = 0;
-
-        FD_ZERO(&reads);
-        FD_SET(ctx->socket_fd, &reads);
-
-        int32_t ret = select(ctx->socket_fd + 1, &reads, NULL, NULL, &timeout);
-        if (*(ctx->stopFlag) == true)
-        {
-            OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Stop request received for [%d] server", ctx->type);
-            break;
-        }
-        if (ret < 0)
-        {
-            OIC_LOG_V(FATAL, WIFI_SERVER_TAG, "select returned error %s", strerror(errno));
-            continue;
-        }
-        if (!FD_ISSET(ctx->socket_fd, &reads))
-        {
-            continue;
-        }
-
-        memset(recvBuffer, 0, sizeof(recvBuffer));
-
-        // Read data from socket
-        struct sockaddr_in srcSockAddress;
-        int32_t recvLen;
-        socklen_t srcAddressLen = sizeof(srcSockAddress);
-        if (-1 == (recvLen = recvfrom(ctx->socket_fd, recvBuffer,
-                                      sizeof(recvBuffer), 0, (struct sockaddr *) &srcSockAddress,
-                                      &srcAddressLen)))
-        {
-            OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "%s", strerror(errno));
-            continue;
-        }
-        else if (0 == recvLen)
-        {
-            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Server socket shutdown [%d]!", ctx->type);
-
-            // Notify upper layer this exception
-            if (gExceptionCallback)
-            {
-                gExceptionCallback(ctx->type);
-            }
-            OICFree(ctx);
-            return;
-        }
-
-        const char *srcIPAddress = NULL;
-        int32_t srcPort = -1;
-
-        srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);
-        srcPort = ntohs(srcSockAddress.sin_port);
-
-        OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Received packet from %s:%d\n",
-                  srcIPAddress, srcPort);
-        OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Data: %s\t, DataLength: %d\n",
-                  recvBuffer, recvLen);
-
-        char *netMask = NULL;
-        if (CA_STATUS_OK != CAWiFiGetInterfaceSubnetMask(&netMask))
-        {
-            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to get ethernet subnet");
-            continue;
-        }
-
-        if(!CAAdapterIsSameSubnet(gMulticastServerInterface, srcIPAddress, netMask))
-        {
-            OIC_LOG(DEBUG, WIFI_SERVER_TAG, "Packet received from different subnet, Ignore!");
-            continue;
-        }
-
-        OICFree(netMask);
-        switch(ctx->type)
-        {
-            case CA_UNICAST_SERVER:
-            case CA_MULTICAST_SERVER:
-                // Notify data to upper layer
-                if (gPacketReceivedCallback)
-                {
-                    gPacketReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);
-                }
-                break;
-#ifdef __WITH_DTLS__
-            case CA_SECURED_UNICAST_SERVER:
-                {
-                    CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,
-                                        srcPort,
-                                        (uint8_t *)recvBuffer,
-                                        recvLen, DTLS_WIFI);
-                    OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);
-                }
-                break;
-#endif //__WITH_DTLS__
-            default:
-                // Should never occur
-                OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Invalid server type");
-                OICFree(ctx);
-                return;
-        }
-    }
-
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-}
-
-static CAResult_t CAWiFiCreateSocket(int32_t* socketFD, const char *localIp, int16_t *port,
-                                     const bool forceStart)
-{
-    int32_t sock = -1;
-    // Create a UDP socket
-    if (-1 == (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to create Socket, Error code: %s",
-                  strerror(errno));
-        return CA_STATUS_FAILED;
-    }
-
-    // Make the socket non-blocking
-    if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to set non-block mode, Error code: %s",
-                  strerror(errno));
-
-        close(sock);
-        return CA_STATUS_FAILED;
-    }
-
-    if (true == forceStart)
-    {
-        int32_t setOptionOn = 1;
-        if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-                             (char *) &setOptionOn,
-                             sizeof(setOptionOn)))
-        {
-            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",
-                      strerror(errno));
-
-            close(sock);
-            return CA_STATUS_FAILED;
-        }
-    }
-
-    struct sockaddr_in sockAddr;
-    bool isBound = false;
-    int16_t serverPort = *port;
-
-    memset((char *) &sockAddr, 0, sizeof(sockAddr));
-    sockAddr.sin_family = AF_INET;
-    sockAddr.sin_port = htons(serverPort);
-    if(localIp)
-    {
-        sockAddr.sin_addr.s_addr = inet_addr(localIp);
-    }
-    else
-    {
-        sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
-    }
-
-    int16_t i;
-    for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)
-    {
-        if (-1 == bind(sock, (struct sockaddr *) &sockAddr,
-                       sizeof(sockAddr)))
-        {
-            if (false == forceStart)
-            {
-                OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",
-                          strerror(errno));
-
-                //Set the port to next one
-                serverPort += 1;
-                sockAddr.sin_port = htons(serverPort);
-                continue;
-            }
-            else
-            {
-                OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]!",
-                          strerror(errno));
-                break;
-            }
-        }
-
-        isBound = true;
-        break;
-    }
-
-    if (false == isBound)
-    {
-        close(sock);
-        return CA_STATUS_FAILED;
-    }
-
-    *port = serverPort;
-    *socketFD = sock;
-    return CA_STATUS_OK;
-}
-
-static CAResult_t CAWiFiCloseSocket(int32_t *socketFD)
-{
-    if (-1 == *socketFD)
-    {
-        OIC_LOG(INFO, WIFI_SERVER_TAG, "Server not running");
-        return CA_SERVER_NOT_STARTED;
-    }
-
-    // close the socket
-    if (-1 == close(*socketFD))
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to close the socket, Error code: %s\n",
-                  strerror(errno));
-        return CA_STATUS_FAILED;
-    }
-
-    *socketFD = -1;
-    return CA_STATUS_OK;
-}
-
-static CAResult_t CAStartUnicastServer(const char *localAddress, int16_t *port,
-                                       const bool forceStart, bool isSecured, int32_t *serverFD)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    CAResult_t ret = CAWiFiCreateSocket(serverFD, localAddress, port, forceStart);
-    if(CA_STATUS_OK != ret)
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create unicast socket");
-        return ret;
-    }
-
-    /**
-      * The task to listen for data from unicast socket is added to the thread pool.
-      * This is a blocking call is made where we try to receive some data..
-      * We will keep waiting until some data is received.
-      * This task will be terminated when thread pool is freed on stopping the adapters.
-      * Thread context will be freed by thread on exit.
-      */
-    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
-                                            OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
-    if(!ctx)
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Out of memory!");
-        close(*serverFD);
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-
-    ctx->stopFlag = &gStopUnicast;
-    ctx->socket_fd = *serverFD;
-    ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER:CA_UNICAST_SERVER;
-    if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create read thread!");
-        OICFree((void *)ctx);
-        close(*serverFD);
-        return CA_STATUS_FAILED;
-    }
-
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-static void CAWiFiServerDestroyMutex(void)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    if (gMutexUnicastServer)
-    {
-        u_mutex_free(gMutexUnicastServer);
-        gMutexUnicastServer = NULL;
-    }
-
-#ifdef __WITH_DTLS__
-    if (gMutexSecureUnicastServer)
-    {
-        u_mutex_free(gMutexSecureUnicastServer);
-        gMutexSecureUnicastServer = NULL;
-    }
-#endif
-
-    if (gMutexMulticastServer)
-    {
-        u_mutex_free(gMutexMulticastServer);
-        gMutexMulticastServer = NULL;
-    }
-
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-}
-
-static CAResult_t CAWiFiServerCreateMutex(void)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    gMutexUnicastServer = u_mutex_new();
-    if (!gMutexUnicastServer)
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");
-        return CA_STATUS_FAILED;
-    }
-
-#ifdef __WITH_DTLS__
-    gMutexSecureUnicastServer = u_mutex_new();
-    if (!gMutexSecureUnicastServer)
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");
-
-        CAWiFiServerDestroyMutex();
-        return CA_STATUS_FAILED;
-    }
-#endif
-
-    gMutexMulticastServer = u_mutex_new();
-    if (!gMutexMulticastServer)
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");
-
-        CAWiFiServerDestroyMutex();
-        return CA_STATUS_FAILED;
-    }
-
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAWiFiInitializeServer(const u_thread_pool_t threadPool)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    // Input validation
-    VERIFY_NON_NULL(threadPool, WIFI_SERVER_TAG, "Thread pool handle is NULL");
-
-    // Initialize mutex
-    if (CA_STATUS_OK != CAWiFiServerCreateMutex())
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create mutex!");
-        return CA_STATUS_FAILED;
-    }
-
-    gThreadPool = threadPool;
-
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-void CAWiFiTerminateServer(void)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    gThreadPool = NULL;
-
-    // Destroy mutex
-    CAWiFiServerDestroyMutex();
-
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-}
-
-CAResult_t CAWiFiStartUnicastServer(const char *localAddress, int16_t *port,
-                                    const bool forceStart, const CABool_t isSecured,
-                                    int32_t *serverFD)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    // Input validation
-    VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "localAddress");
-    VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "port");
-    VERIFY_NON_NULL(serverFD, WIFI_SERVER_TAG, "server socket FD");
-
-    if (0 >= *port)
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Invalid input: port is invalid!");
-        return CA_STATUS_INVALID_PARAM;
-    }
-
-    *serverFD = -1;
-    if (CA_FALSE == isSecured)
-    {
-        u_mutex_lock(gMutexUnicastServer);
-        if (-1 != gUnicastServerSocketFD)
-        {
-            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server is Started Already!",
-                      CA_SERVER_STARTED_ALREADY);
-
-            *serverFD = gUnicastServerSocketFD;
-            u_mutex_unlock(gMutexUnicastServer);
-            return CA_SERVER_STARTED_ALREADY;
-        }
-
-        gStopUnicast = false;
-        if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
-                                                 &gUnicastServerSocketFD))
-        {
-            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to start unicast server!");
-            gUnicastServerSocketFD = -1;
-            u_mutex_unlock(gMutexUnicastServer);
-            return CA_STATUS_FAILED;
-        }
-
-        *serverFD = gUnicastServerSocketFD;
-        u_mutex_unlock(gMutexUnicastServer);
-    }
-#ifdef __WITH_DTLS__
-    else // Start unicast server for secured communication
-    {
-        u_mutex_lock(gMutexSecureUnicastServer);
-        if (-1 != gSecureUnicastServerSocketFD)
-        {
-            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server is Started Already!",
-                      CA_SERVER_STARTED_ALREADY);
-
-            *serverFD = gSecureUnicastServerSocketFD;
-            u_mutex_unlock(gMutexSecureUnicastServer);
-            return CA_SERVER_STARTED_ALREADY;
-        }
-
-        gStopSecureUnicast = false;
-        if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,
-                                                 &gSecureUnicastServerSocketFD))
-        {
-            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to start unicast server!");
-            gSecureUnicastServerSocketFD = -1;
-            u_mutex_unlock(gMutexSecureUnicastServer);
-            return CA_STATUS_FAILED;
-        }
-
-        *serverFD = gSecureUnicastServerSocketFD;
-        u_mutex_unlock(gMutexSecureUnicastServer);
-    }
-#endif
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAWiFiStartMulticastServer(const char *localAddress, const char *multicastAddress,
-                                      const int16_t multicastPort, int32_t *serverFD)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    // Input validation
-    VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "Local address is NULL");
-    VERIFY_NON_NULL(multicastAddress, WIFI_SERVER_TAG, "Multicast address is NULL");
-
-    int16_t port = multicastPort;
-    if (0 >= port)
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Invalid input: Multicast port is invalid!");
-        return CA_STATUS_INVALID_PARAM;
-    }
-
-    u_mutex_lock(gMutexMulticastServer);
-
-    if (gMulticastServerSocketFD != -1)
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Multicast Server is already running!");
-        u_mutex_unlock(gMutexMulticastServer);
-        return CA_SERVER_STARTED_ALREADY;
-    }
-
-    CAResult_t ret = CAWiFiCreateSocket(&gMulticastServerSocketFD, multicastAddress, &port, true);
-    if(ret != CA_STATUS_OK)
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create multicast socket");
-        u_mutex_unlock(gMutexMulticastServer);
-        return ret;
-    }
-
-    // Add membership to receiving socket (join group)
-    memset(&gMulticastMemberReq, 0, sizeof(struct ip_mreq));
-    gMulticastMemberReq.imr_interface.s_addr = inet_addr(localAddress);
-    inet_aton(multicastAddress, &gMulticastMemberReq.imr_multiaddr);
-
-    if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,
-                         (char *) &gMulticastMemberReq,
-                         sizeof(struct ip_mreq)))
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",
-                  strerror(errno));
-        close(gMulticastServerSocketFD);
-        gMulticastServerSocketFD = -1;
-        u_mutex_unlock(gMutexMulticastServer);
-        return CA_STATUS_FAILED;
-    }
-
-    /**
-      * The task to listen to data from multicastcast socket is added to the thread pool.
-      * This is a blocking call is made where we try to receive some data.
-      * We will keep waiting until some data is received.
-      * This task will be terminated when thread pool is freed on stopping the adapters.
-      * Thread context will be freed by thread on exit.
-      */
-    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)
-                                            OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));
-    if(!ctx)
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Out of memory!");
-        close(gMulticastServerSocketFD);
-        gMulticastServerSocketFD = -1;
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-
-    ctx->stopFlag = &gStopMulticast;
-    ctx->socket_fd = gMulticastServerSocketFD;
-    ctx->type = CA_MULTICAST_SERVER;
-
-    gStopMulticast = false;
-    if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))
-    {
-        OIC_LOG(ERROR, WIFI_SERVER_TAG, "thread_pool_add_task failed!");
-
-        close(gMulticastServerSocketFD);
-        gMulticastServerSocketFD = -1;
-        gStopMulticast = true;
-        u_mutex_unlock(gMutexMulticastServer);
-        return CA_STATUS_FAILED;
-    }
-
-    *serverFD = gMulticastServerSocketFD;
-    strncpy(gMulticastServerInterface, localAddress, sizeof(gMulticastServerInterface));
-    u_mutex_unlock(gMutexMulticastServer);
-
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-CAResult_t CAWiFiStopUnicastServer()
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    u_mutex_lock(gMutexUnicastServer);
-    gStopUnicast = true;
-    CAResult_t ret = CAWiFiCloseSocket(&gUnicastServerSocketFD);
-    u_mutex_unlock(gMutexUnicastServer);
-
-    OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Unicast server stopped [%d]", ret);
-    return ret;
-}
-
-#ifdef __WITH_DTLS__
-CAResult_t CAWiFiStopSecureUnicastServer()
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    u_mutex_lock(gMutexSecureUnicastServer);
-    gStopSecureUnicast = true;
-    CAResult_t ret = CAWiFiCloseSocket(&gSecureUnicastServerSocketFD);
-    u_mutex_unlock(gMutexSecureUnicastServer);
-
-    OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Secured unicast server stopped [%d]", ret);
-    return ret;
-}
-#endif
-
-CAResult_t CAWiFiStopMulticastServer(void)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    u_mutex_lock(gMutexMulticastServer);
-
-    if (gMulticastServerSocketFD == -1)
-    {
-        OIC_LOG(INFO, WIFI_SERVER_TAG, "Multicast server is not yet started");
-        u_mutex_unlock(gMutexMulticastServer);
-        return CA_SERVER_NOT_STARTED;
-    }
-
-    gStopMulticast = true;
-
-    // leave the group after you are done
-    if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,
-                         (char *)&gMulticastMemberReq,
-                         sizeof(struct ip_mreq)))
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",
-                  strerror(errno));
-    }
-
-    CAResult_t ret = CAWiFiCloseSocket(&gMulticastServerSocketFD);
-    u_mutex_unlock(gMutexMulticastServer);
-
-    OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Multicast server stopped [%d]", ret);
-    return ret;
-}
-
-CAResult_t CAWiFiGetUnicastServerInfo(const CABool_t isSecured, char **ipAddress,
-                                      int16_t *port, int32_t *serverFD)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    // Input validation
-    VERIFY_NON_NULL(ipAddress, WIFI_SERVER_TAG, "IP address");
-    VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "Port");
-    VERIFY_NON_NULL(serverFD, WIFI_SERVER_TAG, "Server ID");
-
-    struct sockaddr_in sockAddr;
-    socklen_t len = sizeof(struct sockaddr_in);
-    if (-1 == getsockname(gUnicastServerSocketFD, (struct sockaddr *)&sockAddr, &len))
-    {
-        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));
-        return CA_STATUS_FAILED;
-    }
-
-
-    const char *serverAddress = inet_ntoa(sockAddr.sin_addr);
-    *ipAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) : NULL;
-    *port = ntohs(sockAddr.sin_port);
-#ifdef __WITH_DTLS__
-    *serverFD = (CA_TRUE == isSecured) ? gSecureUnicastServerSocketFD : gUnicastServerSocketFD;
-#else
-    *serverFD = gUnicastServerSocketFD;
-#endif
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");
-    return CA_STATUS_OK;
-}
-
-void CAWiFiSetPacketReceiveCallback(CAWiFiPacketReceivedCallback callback)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    gPacketReceivedCallback = callback;
-}
-
-void CAWiFiSetExceptionCallback(CAWiFiExceptionCallback callback)
-{
-    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");
-
-    gExceptionCallback = callback;
-}
-
-
+/******************************************************************\r
+*\r
+* Copyright 2014 Samsung Electronics All Rights Reserved.\r
+*\r
+*\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*      http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*\r
+******************************************************************/\r
+#include "cawifiinterface.h"\r
+\r
+#include <sys/types.h>\r
+#include <sys/socket.h>\r
+#include <unistd.h>\r
+#include <fcntl.h>\r
+#include <sys/select.h>\r
+#include <arpa/inet.h>\r
+#include <netinet/in.h>\r
+#include <errno.h>\r
+\r
+#include "pdu.h"\r
+#include "caadapterutils.h"\r
+#ifdef __WITH_DTLS__\r
+#include "caadapternetdtls.h"\r
+#endif\r
+#include "umutex.h"\r
+\r
+/**\r
+ * @def WIFI_SERVER_TAG\r
+ * @brief Logging tag for module name\r
+ */\r
+#define WIFI_SERVER_TAG "WIFI_SERVER"\r
+\r
+/**\r
+ * @def CA_UDP_BIND_RETRY_COUNT\r
+ * @brief Retry count in case of socket bind failure.\r
+ */\r
+#define CA_UDP_BIND_RETRY_COUNT 10\r
+\r
+/**\r
+ * @def IPNAMESIZE\r
+ * @brief max length for ip\r
+ */\r
+#define IPNAMESIZE 16\r
+\r
+/**\r
+ * @var gUnicastServerSocketFD\r
+ * @brief Unicast server socket descriptor\r
+ */\r
+static int32_t gUnicastServerSocketFD = -1;\r
+\r
+/**\r
+ * @var gMutexUnicastServer\r
+ * @brief Mutex to synchronize unicast server\r
+ */\r
+static u_mutex gMutexUnicastServer = NULL;\r
+\r
+/**\r
+ * @var gStopUnicast\r
+ * @brief Flag to control the Receive Unicast Data Thread\r
+ */\r
+static bool gStopUnicast = false;\r
+\r
+/**\r
+ * @var gMulticastServerSocketFD\r
+ * @brief socket descriptor for multicast server\r
+ */\r
+static int32_t gMulticastServerSocketFD = -1;\r
+\r
+/**\r
+ * @var gMutexMulticastServer\r
+ * @brief Mutex to synchronize secure multicast server\r
+ */\r
+static u_mutex gMutexMulticastServer = NULL;\r
+\r
+/**\r
+ * @var gStopMulticast\r
+ * @brief Flag to control the Receive Multicast Data Thread\r
+ */\r
+static bool gStopMulticast = false;\r
+\r
+#ifdef __WITH_DTLS__\r
+/**\r
+ * @var gSecureUnicastServerSocketFD\r
+ * @brief Secure unicast server socket descriptor\r
+ */\r
+static int32_t gSecureUnicastServerSocketFD = -1;\r
+\r
+/**\r
+ * @var gMutexSecureUnicastServer\r
+ * @brief Mutex to synchronize secure unicast server\r
+ */\r
+static u_mutex gMutexSecureUnicastServer = NULL;\r
+\r
+/**\r
+ * @var gStopSecureUnicast\r
+ * @brief Flag to control the unicast secure data receive thread\r
+ */\r
+static bool gStopSecureUnicast = false;\r
+#endif\r
+\r
+/**\r
+ * @var gThreadPool\r
+ * @brief ThreadPool for storing u_thread_pool_t handle passed from adapter\r
+ */\r
+static u_thread_pool_t gThreadPool = NULL;\r
+\r
+/**\r
+ * @var gMulticastServerInterface\r
+ * @brief Local interface on which multicast server is running\r
+ */\r
+static char gMulticastServerInterface[IPNAMESIZE];\r
+\r
+/**\r
+ * @var gMulticastMemberReq\r
+ * @brief ip_mreq structure passed to join a multicast group\r
+ */\r
+static struct ip_mreq gMulticastMemberReq;\r
+\r
+/**\r
+ * @var gPacketReceivedCallback\r
+ * @brief Callback for notifying the upper layer on receival data from remote OIC device\r
+ */\r
+static CAWiFiPacketReceivedCallback gPacketReceivedCallback = NULL;\r
+\r
+/**\r
+ * @var gExceptionCallback\r
+ * @brief Callback for notifying the upper layer when unicast/multicast server encounters exception\r
+ */\r
+static CAWiFiExceptionCallback gExceptionCallback = NULL;\r
+\r
+/**\r
+ @brief Thread context information for unicast, multicast and secured unicast server\r
+ */\r
+typedef struct\r
+{\r
+    bool *stopFlag;\r
+    int32_t socket_fd;\r
+    CAAdapterServerType_t type;\r
+} CAAdapterReceiveThreadContext_t;\r
+\r
+static void CAReceiveHandler(void *data)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+    // Input validation\r
+    VERIFY_NON_NULL_VOID(data, WIFI_SERVER_TAG, "Invalid thread context");\r
+\r
+    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)data;\r
+    fd_set reads;\r
+    struct timeval timeout;\r
+    char recvBuffer[COAP_MAX_PDU_SIZE] = {0};\r
+\r
+    while (true != *(ctx->stopFlag))\r
+    {\r
+        timeout.tv_sec = 1;\r
+        timeout.tv_usec = 0;\r
+\r
+        FD_ZERO(&reads);\r
+        FD_SET(ctx->socket_fd, &reads);\r
+\r
+        int32_t ret = select(ctx->socket_fd + 1, &reads, NULL, NULL, &timeout);\r
+        if (*(ctx->stopFlag) == true)\r
+        {\r
+            OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Stop request received for [%d] server", ctx->type);\r
+            break;\r
+        }\r
+        if (ret < 0)\r
+        {\r
+            OIC_LOG_V(FATAL, WIFI_SERVER_TAG, "select returned error %s", strerror(errno));\r
+            continue;\r
+        }\r
+        if (!FD_ISSET(ctx->socket_fd, &reads))\r
+        {\r
+            continue;\r
+        }\r
+\r
+        memset(recvBuffer, 0, sizeof(recvBuffer));\r
+\r
+        // Read data from socket\r
+        struct sockaddr_in srcSockAddress;\r
+        int32_t recvLen;\r
+        socklen_t srcAddressLen = sizeof(srcSockAddress);\r
+        if (-1 == (recvLen = recvfrom(ctx->socket_fd, recvBuffer,\r
+                                      sizeof(recvBuffer), 0, (struct sockaddr *) &srcSockAddress,\r
+                                      &srcAddressLen)))\r
+        {\r
+            OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "%s", strerror(errno));\r
+            continue;\r
+        }\r
+        else if (0 == recvLen)\r
+        {\r
+            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Server socket shutdown [%d]!", ctx->type);\r
+\r
+            // Notify upper layer this exception\r
+            if (gExceptionCallback)\r
+            {\r
+                gExceptionCallback(ctx->type);\r
+            }\r
+            OICFree(ctx);\r
+            return;\r
+        }\r
+\r
+        const char *srcIPAddress = NULL;\r
+        int32_t srcPort = -1;\r
+\r
+        srcIPAddress = inet_ntoa(srcSockAddress.sin_addr);\r
+        srcPort = ntohs(srcSockAddress.sin_port);\r
+\r
+        OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Received packet from %s:%d\n",\r
+                  srcIPAddress, srcPort);\r
+        OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Data: %s\t, DataLength: %d\n",\r
+                  recvBuffer, recvLen);\r
+\r
+        char *netMask = NULL;\r
+        if (CA_STATUS_OK != CAWiFiGetInterfaceSubnetMask(&netMask))\r
+        {\r
+            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to get ethernet subnet");\r
+            continue;\r
+        }\r
+\r
+        if (!CAAdapterIsSameSubnet(gMulticastServerInterface, srcIPAddress, netMask))\r
+        {\r
+            OIC_LOG(DEBUG, WIFI_SERVER_TAG, "Packet received from different subnet, Ignore!");\r
+            continue;\r
+        }\r
+\r
+        OICFree(netMask);\r
+        switch (ctx->type)\r
+        {\r
+            case CA_UNICAST_SERVER:\r
+            case CA_MULTICAST_SERVER:\r
+                // Notify data to upper layer\r
+                if (gPacketReceivedCallback)\r
+                {\r
+                    gPacketReceivedCallback(srcIPAddress, srcPort, recvBuffer, recvLen, false);\r
+                }\r
+                break;\r
+#ifdef __WITH_DTLS__\r
+            case CA_SECURED_UNICAST_SERVER:\r
+                {\r
+                    CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress,\r
+                                     srcPort,\r
+                                     (uint8_t *)recvBuffer,\r
+                                     recvLen, DTLS_WIFI);\r
+                    OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "CAAdapterNetDtlsDecrypt returns [%d]", ret);\r
+                }\r
+                break;\r
+#endif //__WITH_DTLS__\r            default:\r                // Should never occur\r
+                OIC_LOG_V(DEBUG, WIFI_SERVER_TAG, "Invalid server type");\r
+                OICFree(ctx);\r
+                return;\r
+        }\r
+    }\r
+\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+}\r
+\r
+static CAResult_t CAWiFiCreateSocket(int32_t *socketFD, const char *localIp, int16_t *port,\r
+                                     const bool forceStart)\r
+{\r
+    int32_t sock = -1;\r
+    // Create a UDP socket\r
+    if (-1 == (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to create Socket, Error code: %s",\r
+                  strerror(errno));\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    // Make the socket non-blocking\r
+    if (-1 == fcntl(sock, F_SETFL, O_NONBLOCK))\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to set non-block mode, Error code: %s",\r
+                  strerror(errno));\r
+\r
+        close(sock);\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    if (true == forceStart)\r
+    {\r
+        int32_t setOptionOn = 1;\r
+        if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,\r
+                             (char *) &setOptionOn,\r
+                             sizeof(setOptionOn)))\r
+        {\r
+            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to set SO_REUSEADDR! Error code: %s",\r
+                      strerror(errno));\r
+\r
+            close(sock);\r
+            return CA_STATUS_FAILED;\r
+        }\r
+    }\r
+\r
+    struct sockaddr_in sockAddr;\r
+    bool isBound = false;\r
+    int16_t serverPort = *port;\r
+\r
+    memset((char *) &sockAddr, 0, sizeof(sockAddr));\r
+    sockAddr.sin_family = AF_INET;\r
+    sockAddr.sin_port = htons(serverPort);\r
+    if (localIp)\r
+    {\r
+        sockAddr.sin_addr.s_addr = inet_addr(localIp);\r
+    }\r
+    else\r
+    {\r
+        sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);\r
+    }\r
+\r
+    int16_t i;\r
+    for (i = 0; i < CA_UDP_BIND_RETRY_COUNT; i++)\r
+    {\r
+        if (-1 == bind(sock, (struct sockaddr *) &sockAddr,\r
+                       sizeof(sockAddr)))\r
+        {\r
+            if (false == forceStart)\r
+            {\r
+                OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]. Trying again..",\r
+                          strerror(errno));\r
+\r
+                //Set the port to next one\r
+                serverPort += 1;\r
+                sockAddr.sin_port = htons(serverPort);\r
+                continue;\r
+            }\r
+            else\r
+            {\r
+                OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to bind socket[%s]!",\r
+                          strerror(errno));\r
+                break;\r
+            }\r
+        }\r
+\r
+        isBound = true;\r
+        break;\r
+    }\r
+\r
+    if (false == isBound)\r
+    {\r
+        close(sock);\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    *port = serverPort;\r
+    *socketFD = sock;\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+static CAResult_t CAWiFiCloseSocket(int32_t *socketFD)\r
+{\r
+    if (-1 == *socketFD)\r
+    {\r
+        OIC_LOG(INFO, WIFI_SERVER_TAG, "Server not running");\r
+        return CA_SERVER_NOT_STARTED;\r
+    }\r
+\r
+    // close the socket\r
+    if (-1 == close(*socketFD))\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to close the socket, Error code: %s\n",\r
+                  strerror(errno));\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    *socketFD = -1;\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+static CAResult_t CAStartUnicastServer(const char *localAddress, int16_t *port,\r
+                                       const bool forceStart, bool isSecured, int32_t *serverFD)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    CAResult_t ret = CAWiFiCreateSocket(serverFD, localAddress, port, forceStart);\r
+    if (CA_STATUS_OK != ret)\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create unicast socket");\r
+        return ret;\r
+    }\r
+\r
+    /**\r
+      * The task to listen for data from unicast socket is added to the thread pool.\r
+      * This is a blocking call is made where we try to receive some data..\r
+      * We will keep waiting until some data is received.\r
+      * This task will be terminated when thread pool is freed on stopping the adapters.\r
+      * Thread context will be freed by thread on exit.\r
+      */\r
+    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)\r
+                                           OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));\r
+    if (!ctx)\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Out of memory!");\r
+        close(*serverFD);\r
+        return CA_MEMORY_ALLOC_FAILED;\r
+    }\r
+\r
+    ctx->stopFlag = &gStopUnicast;\r
+    ctx->socket_fd = *serverFD;\r
+    ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;\r
+    if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create read thread!");\r
+        OICFree((void *)ctx);\r
+        close(*serverFD);\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+static void CAWiFiServerDestroyMutex(void)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    if (gMutexUnicastServer)\r
+    {\r
+        u_mutex_free(gMutexUnicastServer);\r
+        gMutexUnicastServer = NULL;\r
+    }\r
+\r
+#ifdef __WITH_DTLS__\r
+    if (gMutexSecureUnicastServer)\r
+    {\r
+        u_mutex_free(gMutexSecureUnicastServer);\r
+        gMutexSecureUnicastServer = NULL;\r
+    }\r
+#endif\r
+\r
+    if (gMutexMulticastServer)\r
+    {\r
+        u_mutex_free(gMutexMulticastServer);\r
+        gMutexMulticastServer = NULL;\r
+    }\r
+\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+}\r
+\r
+static CAResult_t CAWiFiServerCreateMutex(void)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    gMutexUnicastServer = u_mutex_new();\r
+    if (!gMutexUnicastServer)\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+#ifdef __WITH_DTLS__\r
+    gMutexSecureUnicastServer = u_mutex_new();\r
+    if (!gMutexSecureUnicastServer)\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");\r
+\r
+        CAWiFiServerDestroyMutex();\r
+        return CA_STATUS_FAILED;\r
+    }\r
+#endif\r
+\r
+    gMutexMulticastServer = u_mutex_new();\r
+    if (!gMutexMulticastServer)\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to created mutex!");\r
+\r
+        CAWiFiServerDestroyMutex();\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+CAResult_t CAWiFiInitializeServer(const u_thread_pool_t threadPool)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    // Input validation\r
+    VERIFY_NON_NULL(threadPool, WIFI_SERVER_TAG, "Thread pool handle is NULL");\r
+\r
+    // Initialize mutex\r
+    if (CA_STATUS_OK != CAWiFiServerCreateMutex())\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create mutex!");\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    gThreadPool = threadPool;\r
+\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+void CAWiFiTerminateServer(void)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    gThreadPool = NULL;\r
+\r
+    // Destroy mutex\r
+    CAWiFiServerDestroyMutex();\r
+\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+}\r
+\r
+CAResult_t CAWiFiStartUnicastServer(const char *localAddress, int16_t *port,\r
+                                    const bool forceStart, const CABool_t isSecured,\r
+                                    int32_t *serverFD)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    // Input validation\r
+    VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "localAddress");\r
+    VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "port");\r
+    VERIFY_NON_NULL(serverFD, WIFI_SERVER_TAG, "server socket FD");\r
+\r
+    if (0 >= *port)\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Invalid input: port is invalid!");\r
+        return CA_STATUS_INVALID_PARAM;\r
+    }\r
+\r
+    *serverFD = -1;\r
+    if (CA_FALSE == isSecured)\r
+    {\r
+        u_mutex_lock(gMutexUnicastServer);\r
+        if (-1 != gUnicastServerSocketFD)\r
+        {\r
+            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server is Started Already!",\r
+                      CA_SERVER_STARTED_ALREADY);\r
+\r
+            *serverFD = gUnicastServerSocketFD;\r
+            u_mutex_unlock(gMutexUnicastServer);\r
+            return CA_SERVER_STARTED_ALREADY;\r
+        }\r
+\r
+        gStopUnicast = false;\r
+        if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,\r
+                &gUnicastServerSocketFD))\r
+        {\r
+            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to start unicast server!");\r
+            gUnicastServerSocketFD = -1;\r
+            u_mutex_unlock(gMutexUnicastServer);\r
+            return CA_STATUS_FAILED;\r
+        }\r
+\r
+        *serverFD = gUnicastServerSocketFD;\r
+        u_mutex_unlock(gMutexUnicastServer);\r
+    }\r
+#ifdef __WITH_DTLS__\r
+    else // Start unicast server for secured communication\r
+    {\r
+        u_mutex_lock(gMutexSecureUnicastServer);\r
+        if (-1 != gSecureUnicastServerSocketFD)\r
+        {\r
+            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Unicast Server is Started Already!",\r
+                      CA_SERVER_STARTED_ALREADY);\r
+\r
+            *serverFD = gSecureUnicastServerSocketFD;\r
+            u_mutex_unlock(gMutexSecureUnicastServer);\r
+            return CA_SERVER_STARTED_ALREADY;\r
+        }\r
+\r
+        gStopSecureUnicast = false;\r
+        if (CA_STATUS_OK != CAStartUnicastServer(localAddress, port, forceStart, isSecured,\r
+                &gSecureUnicastServerSocketFD))\r
+        {\r
+            OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to start unicast server!");\r
+            gSecureUnicastServerSocketFD = -1;\r
+            u_mutex_unlock(gMutexSecureUnicastServer);\r
+            return CA_STATUS_FAILED;\r
+        }\r
+\r
+        *serverFD = gSecureUnicastServerSocketFD;\r
+        u_mutex_unlock(gMutexSecureUnicastServer);\r
+    }\r
+#endif\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+CAResult_t CAWiFiStartMulticastServer(const char *localAddress, const char *multicastAddress,\r
+                                      const int16_t multicastPort, int32_t *serverFD)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    // Input validation\r
+    VERIFY_NON_NULL(localAddress, WIFI_SERVER_TAG, "Local address is NULL");\r
+    VERIFY_NON_NULL(multicastAddress, WIFI_SERVER_TAG, "Multicast address is NULL");\r
+\r
+    int16_t port = multicastPort;\r
+    if (0 >= port)\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Invalid input: Multicast port is invalid!");\r
+        return CA_STATUS_INVALID_PARAM;\r
+    }\r
+\r
+    u_mutex_lock(gMutexMulticastServer);\r
+\r
+    if (gMulticastServerSocketFD != -1)\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Multicast Server is already running!");\r
+        u_mutex_unlock(gMutexMulticastServer);\r
+        return CA_SERVER_STARTED_ALREADY;\r
+    }\r
+\r
+    CAResult_t ret = CAWiFiCreateSocket(&gMulticastServerSocketFD, multicastAddress, &port, true);\r
+    if (ret != CA_STATUS_OK)\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Failed to create multicast socket");\r
+        u_mutex_unlock(gMutexMulticastServer);\r
+        return ret;\r
+    }\r
+\r
+    // Add membership to receiving socket (join group)\r
+    memset(&gMulticastMemberReq, 0, sizeof(struct ip_mreq));\r
+    gMulticastMemberReq.imr_interface.s_addr = inet_addr(localAddress);\r
+    inet_aton(multicastAddress, &gMulticastMemberReq.imr_multiaddr);\r
+\r
+    if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_ADD_MEMBERSHIP,\r
+                         (char *) &gMulticastMemberReq,\r
+                         sizeof(struct ip_mreq)))\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to add to multicast group, Error code: %s\n",\r
+                  strerror(errno));\r
+        close(gMulticastServerSocketFD);\r
+        gMulticastServerSocketFD = -1;\r
+        u_mutex_unlock(gMutexMulticastServer);\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    /**\r
+      * The task to listen to data from multicastcast socket is added to the thread pool.\r
+      * This is a blocking call is made where we try to receive some data.\r
+      * We will keep waiting until some data is received.\r
+      * This task will be terminated when thread pool is freed on stopping the adapters.\r
+      * Thread context will be freed by thread on exit.\r
+      */\r
+    CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *)\r
+                                           OICMalloc(sizeof(CAAdapterReceiveThreadContext_t));\r
+    if (!ctx)\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "Out of memory!");\r
+        close(gMulticastServerSocketFD);\r
+        gMulticastServerSocketFD = -1;\r
+        return CA_MEMORY_ALLOC_FAILED;\r
+    }\r
+\r
+    ctx->stopFlag = &gStopMulticast;\r
+    ctx->socket_fd = gMulticastServerSocketFD;\r
+    ctx->type = CA_MULTICAST_SERVER;\r
+\r
+    gStopMulticast = false;\r
+    if (CA_STATUS_OK != u_thread_pool_add_task(gThreadPool, CAReceiveHandler, (void *)ctx))\r
+    {\r
+        OIC_LOG(ERROR, WIFI_SERVER_TAG, "thread_pool_add_task failed!");\r
+\r
+        close(gMulticastServerSocketFD);\r
+        gMulticastServerSocketFD = -1;\r
+        gStopMulticast = true;\r
+        u_mutex_unlock(gMutexMulticastServer);\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+    *serverFD = gMulticastServerSocketFD;\r
+    strncpy(gMulticastServerInterface, localAddress, sizeof(IPNAMESIZE));\r
+    u_mutex_unlock(gMutexMulticastServer);\r
+\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+CAResult_t CAWiFiStopUnicastServer()\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    u_mutex_lock(gMutexUnicastServer);\r
+    gStopUnicast = true;\r
+    CAResult_t ret = CAWiFiCloseSocket(&gUnicastServerSocketFD);\r
+    u_mutex_unlock(gMutexUnicastServer);\r
+\r
+    OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Unicast server stopped [%d]", ret);\r
+    return ret;\r
+}\r
+\r
+#ifdef __WITH_DTLS__\r
+CAResult_t CAWiFiStopSecureUnicastServer()\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    u_mutex_lock(gMutexSecureUnicastServer);\r
+    gStopSecureUnicast = true;\r
+    CAResult_t ret = CAWiFiCloseSocket(&gSecureUnicastServerSocketFD);\r
+    u_mutex_unlock(gMutexSecureUnicastServer);\r
+\r
+    OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Secured unicast server stopped [%d]", ret);\r
+    return ret;\r
+}\r
+#endif\r
+\r
+CAResult_t CAWiFiStopMulticastServer(void)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    u_mutex_lock(gMutexMulticastServer);\r
+\r
+    if (gMulticastServerSocketFD == -1)\r
+    {\r
+        OIC_LOG(INFO, WIFI_SERVER_TAG, "Multicast server is not yet started");\r
+        u_mutex_unlock(gMutexMulticastServer);\r
+        return CA_SERVER_NOT_STARTED;\r
+    }\r
+\r
+    gStopMulticast = true;\r
+\r
+    // leave the group after you are done\r
+    if (-1 == setsockopt(gMulticastServerSocketFD, IPPROTO_IP, IP_DROP_MEMBERSHIP,\r
+                         (char *)&gMulticastMemberReq,\r
+                         sizeof(struct ip_mreq)))\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed to leave multicast group, Error code: %s\n",\r
+                  strerror(errno));\r
+    }\r
+\r
+    CAResult_t ret = CAWiFiCloseSocket(&gMulticastServerSocketFD);\r
+    u_mutex_unlock(gMutexMulticastServer);\r
+\r
+    OIC_LOG_V(INFO, WIFI_SERVER_TAG, "Multicast server stopped [%d]", ret);\r
+    return ret;\r
+}\r
+\r
+CAResult_t CAWiFiGetUnicastServerInfo(const CABool_t isSecured, char **ipAddress,\r
+                                      int16_t *port, int32_t *serverFD)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    // Input validation\r
+    VERIFY_NON_NULL(ipAddress, WIFI_SERVER_TAG, "IP address");\r
+    VERIFY_NON_NULL(port, WIFI_SERVER_TAG, "Port");\r
+    VERIFY_NON_NULL(serverFD, WIFI_SERVER_TAG, "Server ID");\r
+\r
+    struct sockaddr_in sockAddr;\r
+    socklen_t len = sizeof(struct sockaddr_in);\r
+    if (-1 == getsockname(gUnicastServerSocketFD, (struct sockaddr *)&sockAddr, &len))\r
+    {\r
+        OIC_LOG_V(ERROR, WIFI_SERVER_TAG, "Failed in getsockname [%s]!", strerror(errno));\r
+        return CA_STATUS_FAILED;\r
+    }\r
+\r
+\r
+    const char *serverAddress = inet_ntoa(sockAddr.sin_addr);\r
+    *ipAddress = (serverAddress) ? strndup(serverAddress, strlen(serverAddress)) : NULL;\r
+    *port = ntohs(sockAddr.sin_port);\r
+#ifdef __WITH_DTLS__\r
+    *serverFD = (CA_TRUE == isSecured) ? gSecureUnicastServerSocketFD : gUnicastServerSocketFD;\r
+#else\r
+    *serverFD = gUnicastServerSocketFD;\r
+#endif\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "OUT");\r
+    return CA_STATUS_OK;\r
+}\r
+\r
+void CAWiFiSetPacketReceiveCallback(CAWiFiPacketReceivedCallback callback)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    gPacketReceivedCallback = callback;\r
+}\r
+\r
+void CAWiFiSetExceptionCallback(CAWiFiExceptionCallback callback)\r
+{\r
+    OIC_LOG(DEBUG, WIFI_SERVER_TAG, "IN");\r
+\r
+    gExceptionCallback = callback;\r
+}\r
+\r
+\r