Replace select with poll.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / ip_adapter / caipserver.c
index aba261c..085f060 100644 (file)
 #define _GNU_SOURCE // for in6_pktinfo
 #endif
 
+#ifdef __TIZENRT__
+#include <tinyara/config.h>
+#include <uio.h>
+#include <poll.h>
+#endif
+
 #include "iotivity_config.h"
 #include <sys/types.h>
 #if !defined(_WIN32)
 #endif
 
 #include <stdio.h>
+#include <string.h>
 #if !defined(_MSC_VER)
 #include <unistd.h>
 #endif //!defined(_MSC_VER)
 #include <sys/types.h>
 #include <fcntl.h>
 #if !defined(_WIN32)
-#include <sys/select.h>
+#include <sys/poll.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <net/if.h>
 #include <linux/rtnetlink.h>
 #endif
 
+#ifdef __TIZENRT__
+#include <uio.h>
+#include <mqueue.h>
+#endif
+
 #include <coap/pdu.h>
 #include "caipinterface.h"
 #include "caipnwmonitor.h"
@@ -64,7 +76,7 @@
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 #include "ca_adapter_net_ssl.h"
 #endif
-#include "camutex.h"
+#include "octhread.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 
 #undef USE_IP_MREQN
 #endif
 
+#ifdef __TIZEN__
+#include <pthread.h>
+#endif
+
 /*
  * Logging tag for module name
  */
-#define TAG "OIC_CA_IP_SERVER"
+//#define TAG "OIC_CA_IP_SERVER"
+#define TAG IP_SERVER_TAG
 
+#ifdef __TIZENRT__
+mqd_t g_nwevent_mqfd;
+#ifdef CONFIG_NET_LWIP
+#define SOCK_CLOEXEC 0
+#else
+#define SOCK_CLOEXEC 1
+#endif
+#endif
 #define SELECT_TIMEOUT 1     // select() seconds (and termination latency)
 
 #define IPv4_MULTICAST     "224.0.1.187"
 static struct in_addr IPv4MulticastAddress = { 0 };
 
 #define IPv6_DOMAINS       16
+#define MOBILE_INTERFACES  2
 #define IPv6_MULTICAST_INT "ff01::158"
 static struct in6_addr IPv6MulticastAddressInt;
 #define IPv6_MULTICAST_LNK "ff02::158"
@@ -99,6 +125,11 @@ static struct in6_addr IPv6MulticastAddressOrg;
 #define IPv6_MULTICAST_GLB "ff0e::158"
 static struct in6_addr IPv6MulticastAddressGlb;
 
+/*
+ * Buffer size for the receive message buffer
+ */
+#define RECV_MSG_BUF_LEN 16384
+
 static char *ipv6mcnames[IPv6_DOMAINS] = {
     NULL,
     IPv6_MULTICAST_INT,
@@ -118,6 +149,41 @@ static char *ipv6mcnames[IPv6_DOMAINS] = {
     NULL
 };
 
+// Samsung Mobile
+static char *mobileinferfaces[MOBILE_INTERFACES] = {
+    "rmnet", "pdp"
+};
+
+#ifdef __TIZENRT__
+struct in6_pktinfo {
+        struct in6_addr ipi6_addr;
+        int             ipi6_ifindex;
+};
+
+struct in_pktinfo
+{
+  unsigned int   ipi_ifindex;  /* Interface index */
+  struct in_addr ipi_spec_dst; /* Local address */
+  struct in_addr ipi_addr;     /* Header Destination
+                                    address */
+};
+
+
+#define RTMGRP_LINK 1
+#define IP_PKTINFO         8
+#define IPV6_PKTINFO            50
+#define IPV6_MULTICAST_IF 9
+#define IPV6_V6ONLY 27
+#define IPV6_RECVPKTINFO       50
+#define IPV6_JOIN_GROUP 12
+#endif
+
+/**
+ * By default, IP multicast datagrams are sent with a time-to-live (TTL) of 1.
+ * An application can choose an initial TTL.
+ */
+static size_t multicastTTL = 1;
+
 #if defined (_WIN32)
 #define IFF_UP_RUNNING_FLAGS  (IFF_UP)
 
@@ -140,22 +206,65 @@ static CAIPPacketReceivedCallback g_packetReceivedCallback = NULL;
 
 static void CAFindReadyMessage();
 #if !defined(WSA_WAIT_EVENT_0)
-static void CASelectReturned(fd_set *readFds, int ret);
+static void CAPollReturned(struct pollfd *readFds, int ret);
 #else
 static void CAEventReturned(CASocketFd_t socket);
 #endif
 
 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags);
 
+#ifdef __TIZEN__
+static int cleanup_pop_arg = 1;
+
+static void CAIPCleanupHandler(void *arg)
+{
+    (void)arg;
+
+    OIC_LOG(DEBUG, TAG, "Called clean-up handler");
+
+    if (caglobals.ip.shutdownFds[0] != OC_INVALID_SOCKET)
+    {
+        close(caglobals.ip.shutdownFds[0]);
+        caglobals.ip.shutdownFds[0] = OC_INVALID_SOCKET;
+    }
+}
+
 static void CAReceiveHandler(void *data)
 {
     (void)data;
+    OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler");
+
+    pthread_cleanup_push(CAIPCleanupHandler, NULL);
 
     while (!caglobals.ip.terminate)
     {
         CAFindReadyMessage();
     }
+
+    pthread_cleanup_pop(cleanup_pop_arg);
+
+    OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
 }
+#else
+static void CAReceiveHandler(void *data)
+{
+    (void)data;
+    OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler");
+
+    while (!caglobals.ip.terminate)
+    {
+        CAFindReadyMessage();
+    }
+#ifndef __TIZENRT__
+    if (caglobals.ip.shutdownFds[0] != OC_INVALID_SOCKET)
+    {
+        close(caglobals.ip.shutdownFds[0]);
+        caglobals.ip.shutdownFds[0] = OC_INVALID_SOCKET;
+    }
+#endif
+    OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
+}
+#endif
 
 #if !defined(WSA_WAIT_EVENT_0)
 
@@ -166,119 +275,152 @@ static void CAReceiveHandler(void *data)
         caglobals.ip.TYPE.fd = OC_INVALID_SOCKET; \
     }
 
-#define SET(TYPE, FDS) \
-    if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET) \
-    { \
-        FD_SET(caglobals.ip.TYPE.fd, FDS); \
-    }
-
-#define ISSET(TYPE, FDS, FLAGS) \
-    if (caglobals.ip.TYPE.fd != OC_INVALID_SOCKET && FD_ISSET(caglobals.ip.TYPE.fd, FDS)) \
-    { \
-        fd = caglobals.ip.TYPE.fd; \
-        flags = FLAGS; \
-    }
-
+#define SET(TYPE, FDS, COUNT) \
+        FDS[COUNT].fd = caglobals.ip.TYPE.fd; \
+        FDS[COUNT].events = POLLIN;
+
+#define MAX_UDP_SOCK_COUNT 8
+
+static const CASocketFd_t *sockFdPtr[MAX_UDP_SOCK_COUNT] = {
+        &caglobals.ip.u6.fd,
+        &caglobals.ip.u6s.fd,
+        &caglobals.ip.u4.fd,
+        &caglobals.ip.u4s.fd,
+        &caglobals.ip.m6.fd,
+        &caglobals.ip.m6s.fd,
+        &caglobals.ip.m4.fd,
+        &caglobals.ip.m4s.fd
+    };
+
+static const CATransportFlags_t inputflags[MAX_UDP_SOCK_COUNT] = {
+        CA_IPV6,
+        CA_IPV6 | CA_SECURE,
+        CA_IPV4,
+        CA_IPV4 | CA_SECURE,
+        CA_MULTICAST | CA_IPV6,
+        CA_MULTICAST | CA_IPV6 | CA_SECURE,
+        CA_MULTICAST | CA_IPV4,
+        CA_MULTICAST | CA_IPV4 | CA_SECURE
+    };
 
 static void CAFindReadyMessage()
 {
-    fd_set readFds;
-    struct timeval timeout;
-
-    timeout.tv_sec = caglobals.ip.selectTimeout;
-    timeout.tv_usec = 0;
-    struct timeval *tv = caglobals.ip.selectTimeout == -1 ? NULL : &timeout;
-
-    FD_ZERO(&readFds);
-    SET(u6,  &readFds)
-    SET(u6s, &readFds)
-    SET(u4,  &readFds)
-    SET(u4s, &readFds)
-    SET(m6,  &readFds)
-    SET(m6s, &readFds)
-    SET(m4,  &readFds)
-    SET(m4s, &readFds)
+    struct pollfd readFds[MAX_UDP_SOCK_COUNT + 2]; // 8 UDP sockets, 1 netlink and 1 read pipe socket fd
+    int timeout = (caglobals.ip.selectTimeout * 1000);
+    int counter = 0;
+
+    SET(u6, readFds, counter);
+    counter++;
+    SET(u6s, readFds, counter);
+    counter++;
+    SET(u4, readFds, counter);
+    counter++;
+    SET(u4s, readFds, counter);
+    counter++;
+    SET(m6, readFds, counter);
+    counter++;
+    SET(m6s, readFds, counter);
+    counter++;
+    SET(m4, readFds, counter);
+    counter++;
+    SET(m4s, readFds, counter);
+    counter++;
+
+#ifndef __TIZENRT__
+    readFds[counter].fd = caglobals.ip.shutdownFds[0];
+    readFds[counter].events = POLLIN;
+    counter++;
+
+    readFds[counter].fd = caglobals.ip.netlinkFd;
+    readFds[counter].events = POLLIN;
+    counter++;
+#endif
 
-    if (caglobals.ip.shutdownFds[0] != -1)
+    int ret = poll(readFds, counter, timeout);
+    if (caglobals.ip.terminate)
     {
-        FD_SET(caglobals.ip.shutdownFds[0], &readFds);
+        OIC_LOG_V(INFO, TAG, "Packet receiver Stop request received.");
+        return;
     }
-    if (caglobals.ip.netlinkFd != OC_INVALID_SOCKET)
+#ifdef __TIZENRT__
+    u_arraylist_t *iflist = CAFindInterfaceChange();
+    if (iflist)
+    {
+        uint32_t listLength = u_arraylist_length(iflist);
+        for (uint32_t i = 0; i < listLength; i++)
+        {
+            CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+            if (ifitem)
+            {
+                CAProcessNewInterface(ifitem);
+            }
+        }
+        u_arraylist_destroy(iflist);
+    }
+#endif
+    if (ret > 0)
+    {
+        CAPollReturned(readFds, ret);
+    }
+    else if (ret < 0)
     {
-        FD_SET(caglobals.ip.netlinkFd, &readFds);
+        OIC_LOG_V(FATAL, TAG, "poll error %s", CAIPS_GET_ERROR);
     }
+}
+
+static void CAPollReturned(struct pollfd *readFds, int ret)
+{
+    (void)ret;
 
-    int ret = select(caglobals.ip.maxfd + 1, &readFds, NULL, NULL, tv);
+    int counter = 0;
+
+    for (int i = 0; i < MAX_UDP_SOCK_COUNT && !caglobals.ip.terminate; i++)
+    {
+        if (*sockFdPtr[i] != OC_INVALID_SOCKET && readFds[i].revents == POLLIN)
+        {
+            (void)CAReceiveMessage(readFds[i].fd, inputflags[i]);
+        }
+        counter++;
+    }
 
+#ifndef __TIZENRT__
     if (caglobals.ip.terminate)
     {
-        OIC_LOG_V(DEBUG, TAG, "Packet receiver Stop request received.");
         return;
     }
 
-    if (ret <= 0)
+    if (caglobals.ip.shutdownFds[0] != -1 && readFds[counter].revents != 0)
     {
-        if (ret < 0)
+        char buf[10] = {0};
+        ssize_t len = read(caglobals.ip.shutdownFds[0], buf, sizeof (buf));
+        if (-1 != len)
         {
-            OIC_LOG_V(FATAL, TAG, "select error %s", CAIPS_GET_ERROR);
+            // Write end of the pipe is closed. Indicates the termination of UDP server.
+            return;
         }
-        return;
-    }
-
-    CASelectReturned(&readFds, ret);
-}
 
-static void CASelectReturned(fd_set *readFds, int ret)
-{
-    (void)ret;
-    CASocketFd_t fd = OC_INVALID_SOCKET;
-    CATransportFlags_t flags = CA_DEFAULT_FLAGS;
+        counter++;
+    }
 
-    while (!caglobals.ip.terminate)
+    if (!caglobals.ip.terminate &&
+           (caglobals.ip.netlinkFd != OC_INVALID_SOCKET) && readFds[counter].revents != 0)
     {
-        ISSET(u6,  readFds, CA_IPV6)
-        else ISSET(u6s, readFds, CA_IPV6 | CA_SECURE)
-        else ISSET(u4,  readFds, CA_IPV4)
-        else ISSET(u4s, readFds, CA_IPV4 | CA_SECURE)
-        else ISSET(m6,  readFds, CA_MULTICAST | CA_IPV6)
-        else ISSET(m6s, readFds, CA_MULTICAST | CA_IPV6 | CA_SECURE)
-        else ISSET(m4,  readFds, CA_MULTICAST | CA_IPV4)
-        else ISSET(m4s, readFds, CA_MULTICAST | CA_IPV4 | CA_SECURE)
-        else if ((caglobals.ip.netlinkFd != OC_INVALID_SOCKET) && FD_ISSET(caglobals.ip.netlinkFd, readFds))
+        u_arraylist_t *iflist = CAFindInterfaceChange();
+        if (iflist)
         {
-            u_arraylist_t *iflist = CAFindInterfaceChange();
-            if (iflist)
+            uint32_t listLength = u_arraylist_length(iflist);
+            for (uint32_t i = 0; i < listLength; i++)
             {
-                uint32_t listLength = u_arraylist_length(iflist);
-                for (uint32_t i = 0; i < listLength; i++)
+                CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
+                if (ifitem)
                 {
-                    CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
-                    if (ifitem)
-                    {
-                        CAProcessNewInterface(ifitem);
-                    }
+                    CAProcessNewInterface(ifitem);
                 }
-                u_arraylist_destroy(iflist);
             }
-            break;
+            u_arraylist_destroy(iflist);
         }
-        else if (FD_ISSET(caglobals.ip.shutdownFds[0], readFds))
-        {
-            char buf[10] = {0};
-            ssize_t len = read(caglobals.ip.shutdownFds[0], buf, sizeof (buf));
-            if (-1 == len)
-            {
-                continue;
-            }
-            break;
-        }
-        else
-        {
-            break;
-        }
-        (void)CAReceiveMessage(fd, flags);
-        FD_CLR(fd, readFds);
     }
+#endif
 }
 
 #else // if defined(WSA_WAIT_EVENT_0)
@@ -470,14 +612,7 @@ static void CAEventReturned(CASocketFd_t socket)
 
 void CADeInitializeIPGlobals()
 {
-    CLOSE_SOCKET(u6);
-    CLOSE_SOCKET(u6s);
-    CLOSE_SOCKET(u4);
-    CLOSE_SOCKET(u4s);
-    CLOSE_SOCKET(m6);
-    CLOSE_SOCKET(m6s);
-    CLOSE_SOCKET(m4);
-    CLOSE_SOCKET(m4s);
+    CloseMulticastSocket();
 
     if (caglobals.ip.netlinkFd != OC_INVALID_SOCKET)
     {
@@ -492,7 +627,8 @@ void CADeInitializeIPGlobals()
 
 static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
 {
-    char recvBuffer[COAP_MAX_PDU_SIZE] = {0};
+    OIC_LOG(DEBUG, TAG, "IN - CAReceiveMessage");
+    char recvBuffer[RECV_MSG_BUF_LEN] = {0};
 
     size_t len = 0;
     int level = 0;
@@ -537,6 +673,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
         OIC_LOG_V(ERROR, TAG, "Recvfrom failed %s", strerror(errno));
         return CA_STATUS_FAILED;
     }
+    OIC_LOG_V(DEBUG, TAG, "recvd %zd bytes from recvmsg", recvLen);
 
     if (flags & CA_MULTICAST)
     {
@@ -599,6 +736,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
 #endif // !defined(WSA_CMSG_DATA)
     CASecureEndpoint_t sep = {.endpoint = {.adapter = CA_ADAPTER_IP, .flags = flags}};
 
+#ifndef __TIZENRT__
     if (flags & CA_IPV6)
     {
         /** @todo figure out correct usage for ifindex, and sin6_scope_id.*/
@@ -613,6 +751,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
         }
     }
     else
+#endif
     {
         if ((flags & CA_MULTICAST) && pktinfo)
         {
@@ -632,7 +771,7 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
     {
 #ifdef __WITH_DTLS__
         int ret = CAdecryptSsl(&sep, (uint8_t *)recvBuffer, recvLen);
-        OIC_LOG_V(DEBUG, TAG, "CAdecryptSsl returns [%d]", ret);
+        OIC_LOG_V(INFO, TAG, "CAdecryptSsl returns [%d]", ret);
 #else
         OIC_LOG(ERROR, TAG, "Encrypted message but no DTLS");
 #endif
@@ -641,10 +780,12 @@ static CAResult_t CAReceiveMessage(CASocketFd_t fd, CATransportFlags_t flags)
     {
         if (g_packetReceivedCallback)
         {
+            OIC_LOG(DEBUG, TAG, "call receivedCB");
             g_packetReceivedCallback(&sep, recvBuffer, recvLen);
         }
     }
 
+    OIC_LOG(DEBUG, TAG, "OUT - CAReceiveMessage");
     return CA_STATUS_OK;
 
 }
@@ -765,24 +906,64 @@ static CASocketFd_t CACreateSocket(int family, uint16_t *port, bool isMulticast)
     return fd;
 }
 
-#define CHECKFD(FD) \
-    if (FD > caglobals.ip.maxfd) \
-        caglobals.ip.maxfd = FD;
 #define NEWSOCKET(FAMILY, NAME, MULTICAST) \
-    caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
     if (caglobals.ip.NAME.fd == OC_INVALID_SOCKET) \
     {   \
-        caglobals.ip.NAME.port = 0; \
         caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
+        if (caglobals.ip.NAME.fd == OC_INVALID_SOCKET) \
+        {   \
+            caglobals.ip.NAME.port = 0; \
+            caglobals.ip.NAME.fd = CACreateSocket(FAMILY, &caglobals.ip.NAME.port, MULTICAST); \
+        }   \
     }   \
-    CHECKFD(caglobals.ip.NAME.fd)
+
+void CreateMulticastSocket()
+{
+    OIC_LOG_V(INFO, TAG, "In %s", __func__);
+
+    if (caglobals.ip.ipv6enabled)
+    {
+        NEWSOCKET(AF_INET6, u6, false)
+        NEWSOCKET(AF_INET6, u6s, false)
+        NEWSOCKET(AF_INET6, m6, true)
+        NEWSOCKET(AF_INET6, m6s, true)
+        OIC_LOG_V(INFO, TAG, "IPv6 unicast port: %u", caglobals.ip.u6.port);
+    }
+    if (caglobals.ip.ipv4enabled)
+    {
+        NEWSOCKET(AF_INET, u4, false)
+        NEWSOCKET(AF_INET, u4s, false)
+        NEWSOCKET(AF_INET, m4, true)
+        NEWSOCKET(AF_INET, m4s, true)
+        OIC_LOG_V(INFO, TAG, "IPv4 unicast port: %u", caglobals.ip.u4.port);
+    }
+
+    OIC_LOG_V(INFO, TAG, "Out %s", __func__);
+}
+
+void CloseMulticastSocket()
+{
+    OIC_LOG_V(INFO, TAG, "In %s", __func__);
+
+    CLOSE_SOCKET(u6);
+    CLOSE_SOCKET(u6s);
+    CLOSE_SOCKET(u4);
+    CLOSE_SOCKET(u4s);
+    CLOSE_SOCKET(m6);
+    CLOSE_SOCKET(m6s);
+    CLOSE_SOCKET(m4);
+    CLOSE_SOCKET(m4s);
+
+    OIC_LOG_V(INFO, TAG, "Out %s", __func__);
+}
 
 static void CAInitializeNetlink()
 {
     caglobals.ip.netlinkFd = OC_INVALID_SOCKET;
 #ifdef __linux__
     // create NETLINK fd for interface change notifications
-    struct sockaddr_nl sa = { AF_NETLINK, 0, 0, RTMGRP_LINK };
+    struct sockaddr_nl sa = { AF_NETLINK, 0, 0,
+                              RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR };
 
     caglobals.ip.netlinkFd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
     if (caglobals.ip.netlinkFd == OC_INVALID_SOCKET)
@@ -798,11 +979,18 @@ static void CAInitializeNetlink()
             close(caglobals.ip.netlinkFd);
             caglobals.ip.netlinkFd = OC_INVALID_SOCKET;
         }
-        else
-        {
-            CHECKFD(caglobals.ip.netlinkFd);
-        }
     }
+#elif defined (__TIZENRT__) // pkmsgq
+       struct mq_attr lq_attr;
+       lq_attr.mq_maxmsg = 10;
+       lq_attr.mq_msgsize = 4;
+       lq_attr.mq_flags = 0;
+       g_nwevent_mqfd = mq_open("netlink_evtq", O_RDWR | O_NONBLOCK | O_CREAT, 0666, &lq_attr);
+       if (g_nwevent_mqfd == (mqd_t) - 1)
+       {
+               OIC_LOG_V(ERROR, TAG,"RECV mq_open failed\n");
+               return ;
+       }
 #endif
 }
 
@@ -817,10 +1005,11 @@ static void CAInitializeFastShutdownMechanism()
         ret = 0;
     }
 #elif defined(HAVE_PIPE2)
+#ifndef __TIZENRT__
     ret = pipe2(caglobals.ip.shutdownFds, O_CLOEXEC);
-    CHECKFD(caglobals.ip.shutdownFds[0]);
-    CHECKFD(caglobals.ip.shutdownFds[1]);
+#endif
 #else
+#ifndef __TIZENRT__
     ret = pipe(caglobals.ip.shutdownFds);
     if (-1 != ret)
     {
@@ -845,8 +1034,7 @@ static void CAInitializeFastShutdownMechanism()
             caglobals.ip.shutdownFds[1] = -1;
         }
     }
-    CHECKFD(caglobals.ip.shutdownFds[0]);
-    CHECKFD(caglobals.ip.shutdownFds[1]);
+#endif
 #endif
     if (-1 == ret)
     {
@@ -891,34 +1079,32 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
         caglobals.ip.ipv4enabled = true;  // only needed to run CA tests
     }
 
-    if (caglobals.ip.ipv6enabled)
+#ifdef __ANDROID__
+    bool hasWifiConnection = isWifiConnectedDuringInit();
+    if (hasWifiConnection)
     {
-        NEWSOCKET(AF_INET6, u6, false)
-        NEWSOCKET(AF_INET6, u6s, false)
-        NEWSOCKET(AF_INET6, m6, true)
-        NEWSOCKET(AF_INET6, m6s, true)
-        OIC_LOG_V(INFO, TAG, "IPv6 unicast port: %u", caglobals.ip.u6.port);
+        CreateMulticastSocket();
     }
-    if (caglobals.ip.ipv4enabled)
+    else
     {
-        NEWSOCKET(AF_INET, u4, false)
-        NEWSOCKET(AF_INET, u4s, false)
-        NEWSOCKET(AF_INET, m4, true)
-        NEWSOCKET(AF_INET, m4s, true)
-        OIC_LOG_V(INFO, TAG, "IPv4 unicast port: %u", caglobals.ip.u4.port);
+        OIC_LOG(INFO, TAG, "No WiFi connection. So UDP sockets are not created.");
     }
+#else
+    CreateMulticastSocket();
+#endif
 
-    OIC_LOG_V(DEBUG, TAG,
+    OIC_LOG_V(INFO, TAG,
               "socket summary: u6=%d, u6s=%d, u4=%d, u4s=%d, m6=%d, m6s=%d, m4=%d, m4s=%d",
               caglobals.ip.u6.fd, caglobals.ip.u6s.fd, caglobals.ip.u4.fd, caglobals.ip.u4s.fd,
               caglobals.ip.m6.fd, caglobals.ip.m6s.fd, caglobals.ip.m4.fd, caglobals.ip.m4s.fd);
 
-    OIC_LOG_V(DEBUG, TAG,
+    OIC_LOG_V(INFO, TAG,
               "port summary: u6 port=%d, u6s port=%d, u4 port=%d, u4s port=%d, m6 port=%d,"
               "m6s port=%d, m4 port=%d, m4s port=%d",
               caglobals.ip.u6.port, caglobals.ip.u6s.port, caglobals.ip.u4.port,
               caglobals.ip.u4s.port, caglobals.ip.m6.port, caglobals.ip.m6s.port,
               caglobals.ip.m4.port, caglobals.ip.m4s.port);
+
 #if defined (SIO_GET_EXTENSION_FUNCTION_POINTER)
     caglobals.ip.wsaRecvMsg = NULL;
     GUID GuidWSARecvMsg = WSAID_WSARECVMSG;
@@ -938,7 +1124,19 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
 
     caglobals.ip.selectTimeout = CAGetPollingInterval(caglobals.ip.selectTimeout);
 
+#ifdef __ANDROID__
+    if (hasWifiConnection)
+    {
+        res = CAIPStartListenServer();
+    }
+    else
+    {
+        OIC_LOG(INFO, TAG, "No WiFi connection. So IP Listen/Multicast server is not started.");
+    }
+#else
     res = CAIPStartListenServer();
+#endif
+
     if (CA_STATUS_OK != res)
     {
         OIC_LOG_V(ERROR, TAG, "Failed to start listening server![%d]", res);
@@ -946,13 +1144,19 @@ CAResult_t CAIPStartServer(const ca_thread_pool_t threadPool)
     }
 
     caglobals.ip.terminate = false;
-    res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL);
+#ifndef __TIZENRT__
+    res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL, NULL);
+#else
+    res = ca_thread_pool_add_task(threadPool, CAReceiveHandler, NULL, NULL, "IoT_ReceiveHandler",
+                                  CONFIG_IOTIVITY_RECEIVEHANDLER_PTHREAD_STACKSIZE);
+#endif
     if (CA_STATUS_OK != res)
     {
         OIC_LOG(ERROR, TAG, "thread_pool_add_task failed");
+        CAIPStopServer();
         return res;
     }
-    OIC_LOG(DEBUG, TAG, "CAReceiveHandler thread started successfully.");
+    OIC_LOG(INFO, TAG, "CAReceiveHandler thread started successfully.");
 
     caglobals.ip.started = true;
     return CA_STATUS_OK;
@@ -963,7 +1167,10 @@ void CAIPStopServer()
     caglobals.ip.started = false;
     caglobals.ip.terminate = true;
 
+    CADeInitializeIPGlobals();
+
 #if !defined(WSA_WAIT_EVENT_0)
+#ifndef __TIZENRT__
     if (caglobals.ip.shutdownFds[1] != -1)
     {
         close(caglobals.ip.shutdownFds[1]);
@@ -973,6 +1180,7 @@ void CAIPStopServer()
     {
         // receive thread will stop in SELECT_TIMEOUT seconds.
     }
+#endif
 #else
     // receive thread will stop immediately.
     if (!WSASetEvent(caglobals.ip.shutdownEvent))
@@ -980,29 +1188,8 @@ void CAIPStopServer()
         OIC_LOG_V(DEBUG, TAG, "set shutdown event failed: %#08X", GetLastError());
     }
 #endif
-}
 
-void CAWakeUpForChange()
-{
-#if !defined(WSA_WAIT_EVENT_0)
-    if (caglobals.ip.shutdownFds[1] != -1)
-    {
-        ssize_t len = 0;
-        do
-        {
-            len = write(caglobals.ip.shutdownFds[1], "w", 1);
-        } while ((len == -1) && (errno == EINTR));
-        if ((len == -1) && (errno != EINTR) && (errno != EPIPE))
-        {
-            OIC_LOG_V(DEBUG, TAG, "write failed: %s", strerror(errno));
-        }
-    }
-#else
-    if (!WSASetEvent(caglobals.ip.shutdownEvent))
-    {
-        OIC_LOG_V(DEBUG, TAG, "set shutdown event failed: %#08X", GetLastError());
-    }
-#endif
+    OIC_LOG(INFO, TAG, "Adapter terminated successfully");
 }
 
 static void applyMulticastToInterface4(uint32_t ifindex)
@@ -1049,7 +1236,8 @@ static void applyMulticastToInterface4(uint32_t ifindex)
 
 static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t ifindex)
 {
-    struct ipv6_mreq mreq = {.ipv6mr_multiaddr = {0},
+#ifndef __TIZENRT__
+    struct ipv6_mreq mreq = {.ipv6mr_multiaddr = {{{0}}},
                              .ipv6mr_interface = ifindex };
 
     // VS2013 has problems with struct copies inside struct initializers, so copy separately.
@@ -1067,6 +1255,7 @@ static void applyMulticast6(int fd, struct in6_addr *addr, uint32_t ifindex)
             OIC_LOG_V(ERROR, TAG, "IPv6 IPV6_JOIN_GROUP failed: %s", CAIPS_GET_ERROR);
         }
     }
+#endif
 }
 
 static void applyMulticastToInterface6(uint32_t ifindex)
@@ -1077,17 +1266,17 @@ static void applyMulticastToInterface6(uint32_t ifindex)
     }
     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressInt, ifindex);
     applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressLnk, ifindex);
-    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, ifindex);
+    applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressRlm, ifindex);
     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressAdm, ifindex);
-    //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, ifindex);
+    applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressSit, ifindex);
     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressOrg, ifindex);
     //applyMulticast6(caglobals.ip.m6.fd, &IPv6MulticastAddressGlb, ifindex);
 
     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressInt, ifindex);
     applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressLnk, ifindex);
-    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, ifindex);
+    applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressRlm, ifindex);
     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressAdm, ifindex);
-    //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, ifindex);
+    applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressSit, ifindex);
     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressOrg, ifindex);
     //applyMulticast6(caglobals.ip.m6s.fd, &IPv6MulticastAddressGlb, ifindex);
 }
@@ -1118,12 +1307,12 @@ CAResult_t CAIPStartListenServer()
         }
         if (ifitem->family == AF_INET)
         {
-            OIC_LOG_V(DEBUG, TAG, "Adding IPv4 interface %i to multicast group", ifitem->index);
+            OIC_LOG_V(DEBUG, TAG, "Adding IPv4 interface(%d) to multicast group", ifitem->index);
             applyMulticastToInterface4(ifitem->index);
         }
         if (ifitem->family == AF_INET6)
         {
-            OIC_LOG_V(DEBUG, TAG, "Adding IPv6 interface %i to multicast group", ifitem->index);
+            OIC_LOG_V(DEBUG, TAG, "Adding IPv6 interface(%d) to multicast group", ifitem->index);
             applyMulticastToInterface6(ifitem->index);
         }
     }
@@ -1183,10 +1372,12 @@ void CAProcessNewInterface(CAInterface_t *ifitem)
 
     if (ifitem->family == AF_INET6)
     {
+        OIC_LOG_V(DEBUG, TAG, "Adding a new IPv6 interface(%d) to multicast group", ifitem->index);
         applyMulticastToInterface6(ifitem->index);
     }
     if (ifitem->family == AF_INET)
     {
+        OIC_LOG_V(DEBUG, TAG, "Adding a new IPv4 interface(%d) to multicast group", ifitem->index);
         applyMulticastToInterface4(ifitem->index);
     }
 }
@@ -1242,10 +1433,14 @@ static void sendData(int fd, const CAEndpoint_t *endpoint,
             g_ipErrorHandler(endpoint, data, dlen, CA_SEND_FAILED);
         }
         OIC_LOG_V(ERROR, TAG, "%s%s %s sendTo failed: %s", secure, cast, fam, strerror(errno));
+        CALogSendStateInfo(endpoint->adapter, endpoint->addr, endpoint->port,
+                           len, false, strerror(errno));
     }
     else
     {
         OIC_LOG_V(INFO, TAG, "%s%s %s sendTo is successful: %zd bytes", secure, cast, fam, len);
+        CALogSendStateInfo(endpoint->adapter, endpoint->addr, endpoint->port,
+                           len, true, NULL);
     }
 #else
     int err = 0;
@@ -1272,11 +1467,11 @@ static void sendData(int fd, const CAEndpoint_t *endpoint,
             sent += len;
             if (sent != len)
             {
-                OIC_LOG_V(DEBUG, TAG, "%s%s %s sendTo (Partial Send) is successful: "
-                                      "currently sent: %ld bytes, "
-                                      "total sent: %ld bytes, "
-                                      "remaining: %ld bytes",
-                                      secure, cast, fam, len, sent, dlen-sent);
+                OIC_LOG_V(INFO, TAG, "%s%s %s sendTo (Partial Send) is successful: "
+                          "currently sent: %ld bytes, "
+                          "total sent: %ld bytes, "
+                          "remaining: %ld bytes",
+                          secure, cast, fam, len, sent, dlen-sent);
             }
             else
             {
@@ -1325,12 +1520,34 @@ static void sendMulticastData6(const u_arraylist_t *iflist,
             continue;
         }
 
+        bool isMobile = false;
+        for (uint32_t j = 0; j < MOBILE_INTERFACES; j++)
+        {
+            if (strstr(ifitem->name, mobileinferfaces[j]))
+            {
+                isMobile = true;
+                break;
+            }
+        }
+        if (isMobile)
+        {
+            continue;
+        }
+
         int index = ifitem->index;
         if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, OPTVAL_T(&index), sizeof (index)))
         {
             OIC_LOG_V(ERROR, TAG, "setsockopt6 failed: %s", CAIPS_GET_ERROR);
             return;
         }
+
+#ifndef __TIZENRT__
+        // Set multicast packet TTL; default TTL is 1
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &multicastTTL, sizeof(multicastTTL)))
+        {
+            OIC_LOG_V(ERROR, TAG, "IPV6_MULTICAST_HOPS failed: %s", CAIPS_GET_ERROR);
+        }
+#endif
         sendData(fd, endpoint, data, datalen, "multicast", "ipv6");
     }
 }
@@ -1369,6 +1586,21 @@ static void sendMulticastData4(const u_arraylist_t *iflist,
         {
             continue;
         }
+
+        bool isMobile = false;
+        for (uint32_t j = 0; j < MOBILE_INTERFACES; j++)
+        {
+            if (strstr(ifitem->name, mobileinferfaces[j]))
+            {
+                isMobile = true;
+                break;
+            }
+        }
+        if (isMobile)
+        {
+            continue;
+        }
+
 #if defined(USE_IP_MREQN)
         mreq.imr_ifindex = ifitem->index;
 #else
@@ -1379,6 +1611,12 @@ static void sendMulticastData4(const u_arraylist_t *iflist,
             OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)",
                     CAIPS_GET_ERROR);
         }
+
+        // Set multicast packet TTL; default TTL is 1
+        if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &multicastTTL, sizeof(multicastTTL)))
+        {
+            OIC_LOG_V(ERROR, TAG, "IP_MULTICAST_TTL failed: %s", CAIPS_GET_ERROR);
+        }
         sendData(fd, endpoint, data, datalen, "multicast", "ipv4");
     }
 }
@@ -1524,3 +1762,17 @@ void CAIPSetErrorHandler(CAIPErrorHandleCallback errorHandleCallback)
 {
     g_ipErrorHandler = errorHandleCallback;
 }
+
+CAResult_t CAIPSetMulticastTTL(size_t ttl)
+{
+    multicastTTL = ttl;
+    return CA_STATUS_OK;
+}
+
+CAResult_t CAIPGetMulticastTTL(size_t *ttl)
+{
+    VERIFY_NON_NULL(ttl, TAG, "ttl is NULL");
+
+    *ttl = multicastTTL;
+    return CA_STATUS_OK;
+}