Replace select with poll.
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / tcp_adapter / catcpserver.c
index a98e8a1..40c076d 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <sys/select.h>
 #include <sys/ioctl.h>
 #ifdef __TIZENRT__
 #include <tinyara/config.h>
@@ -128,7 +127,7 @@ static CATCPConnectionHandleCallback g_connectionCallback = NULL;
 static CASocketFd_t CACreateAcceptSocket(int family, CASocket_t *sock);
 static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock);
 static void CAFindReadyMessage();
-static void CASelectReturned(fd_set *readFds);
+static void CAPollReturned(struct pollfd *readFds, size_t size);
 static void CAReceiveMessage(int fd);
 static void CAReceiveHandler(void *data);
 static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem);
@@ -155,9 +154,7 @@ const char *CAGetCloudAddressForProxy()
 }
 #endif
 
-#define CHECKFD(FD) \
-    if (FD > caglobals.tcp.maxfd) \
-        caglobals.tcp.maxfd = FD;
+#define MAX_TCP_SOCK_COUNT 4
 
 #define CLOSE_SOCKET(TYPE) \
     if (caglobals.tcp.TYPE.fd != OC_INVALID_SOCKET) \
@@ -166,11 +163,9 @@ const char *CAGetCloudAddressForProxy()
         caglobals.tcp.TYPE.fd = OC_INVALID_SOCKET; \
     }
 
-#define CA_FD_SET(TYPE, FDS) \
-    if (caglobals.tcp.TYPE.fd != OC_INVALID_SOCKET) \
-    { \
-        FD_SET(caglobals.tcp.TYPE.fd, FDS); \
-    }
+#define CA_FD_SET(TYPE, FDS, COUNT) \
+        FDS[COUNT].fd = caglobals.tcp.TYPE.fd; \
+        FDS[COUNT].events = POLLIN;
 
 void CATCPDestroyMutex()
 {
@@ -292,95 +287,110 @@ static void CAReceiveHandler(void *data)
 
 static void CAFindReadyMessage()
 {
-    fd_set readFds;
-    struct timeval timeout = { .tv_sec = caglobals.tcp.selectTimeout };
-
-    FD_ZERO(&readFds);
-    CA_FD_SET(ipv4, &readFds);
-    CA_FD_SET(ipv4s, &readFds);
-    CA_FD_SET(ipv6, &readFds);
-    CA_FD_SET(ipv6s, &readFds);
-#ifndef __TIZENRT__
-    if (OC_INVALID_SOCKET != caglobals.tcp.shutdownFds[0])
-    {
-        FD_SET(caglobals.tcp.shutdownFds[0], &readFds);
-    }
-#endif
-    if (OC_INVALID_SOCKET != caglobals.tcp.connectionFds[0])
+    int timeout = (caglobals.tcp.selectTimeout * 1000);
+    size_t counter = 0;
+
+    oc_mutex_lock(g_mutexObjectList);
+    uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);
+
+    // Consider 4 tcp sockets(ipv4, ipv4s, ipv6, ipv6s) + 1 connection fd + all sockets in svrlist
+    struct pollfd *readFds = (struct pollfd *)OICCalloc(MAX_TCP_SOCK_COUNT + 1 + length, sizeof(struct pollfd));
+    if (NULL == readFds)
     {
-        FD_SET(caglobals.tcp.connectionFds[0], &readFds);
+        OIC_LOG_V(ERROR, TAG, "Failed to allocate memory!");
+        oc_mutex_unlock(g_mutexObjectList);
+        return;
     }
 
-    uint32_t length = u_arraylist_length(caglobals.tcp.svrlist);
+    // 4 tcp sockets
+    CA_FD_SET(ipv4, readFds, counter);
+    counter++;
+    CA_FD_SET(ipv4s, readFds, counter);
+    counter++;
+    CA_FD_SET(ipv6, readFds, counter);
+    counter++;
+    CA_FD_SET(ipv6s, readFds, counter);
+    counter++;
+
+    // 1 connection fd
+    readFds[counter].fd = caglobals.tcp.connectionFds[0];
+    readFds[counter].events = POLLIN;
+    counter++;
+
+    // All sockets in svrlist
     for (size_t i = 0; i < length; i++)
     {
         CATCPSessionInfo_t *svritem =
                 (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i);
         if (svritem && 0 <= svritem->fd && CONNECTED == svritem->state)
         {
-            FD_SET(svritem->fd, &readFds);
+            readFds[counter].fd = svritem->fd;
+            readFds[counter].events = POLLIN;
+            counter++;
         }
     }
+    oc_mutex_unlock(g_mutexObjectList);
 
-    int ret = select(caglobals.tcp.maxfd + 1, &readFds, NULL, NULL, &timeout);
+    int ret = poll(readFds, counter, timeout);
 
     oc_mutex_lock(g_mutexObjectList);
     if (caglobals.tcp.terminate)
     {
-        oc_mutex_unlock(g_mutexObjectList);
         OIC_LOG_V(INFO, TAG, "Packet receiver Stop request received.");
+        oc_mutex_unlock(g_mutexObjectList);
+        OICFree(readFds);
         return;
     }
     oc_mutex_unlock(g_mutexObjectList);
-    if (0 >= ret)
+
+    if (ret > 0)
     {
-        if (0 > ret)
-        {
-            OIC_LOG_V(FATAL, TAG, "select error %s", strerror(errno));
-        }
-        return;
+        CAPollReturned(readFds, counter);
+    }
+    else if (ret < 0)
+    {
+        OIC_LOG_V(FATAL, TAG, "poll error %s", strerror(errno));
     }
 
-    CASelectReturned(&readFds);
+    OICFree(readFds);
 }
 
-static void CASelectReturned(fd_set *readFds)
+static void CAPollReturned(struct pollfd *readFds, size_t size)
 {
     VERIFY_NON_NULL_VOID(readFds, TAG, "readFds is NULL");
 
-    if (caglobals.tcp.ipv4.fd != -1 && FD_ISSET(caglobals.tcp.ipv4.fd, readFds))
+    if (caglobals.tcp.ipv4.fd != -1 && readFds[0].revents == POLLIN)
     {
         CAAcceptConnection(CA_IPV4, &caglobals.tcp.ipv4);
         return;
     }
-    else if (caglobals.tcp.ipv4s.fd != -1 && FD_ISSET(caglobals.tcp.ipv4s.fd, readFds))
+    else if (caglobals.tcp.ipv4s.fd != -1 && readFds[1].revents == POLLIN)
     {
         CAAcceptConnection(CA_IPV4 | CA_SECURE, &caglobals.tcp.ipv4s);
         return;
     }
-    else if (caglobals.tcp.ipv6.fd != -1 && FD_ISSET(caglobals.tcp.ipv6.fd, readFds))
+    else if (caglobals.tcp.ipv6.fd != -1 && readFds[2].revents == POLLIN)
     {
         CAAcceptConnection(CA_IPV6, &caglobals.tcp.ipv6);
         return;
     }
-    else if (caglobals.tcp.ipv6s.fd != -1 && FD_ISSET(caglobals.tcp.ipv6s.fd, readFds))
+    else if (caglobals.tcp.ipv6s.fd != -1 && readFds[3].revents == POLLIN)
     {
         CAAcceptConnection(CA_IPV6 | CA_SECURE, &caglobals.tcp.ipv6s);
         return;
     }
-    else if (-1 != caglobals.tcp.connectionFds[0] &&
-            FD_ISSET(caglobals.tcp.connectionFds[0], readFds))
+    else if (-1 != caglobals.tcp.connectionFds[0] && readFds[4].revents != 0)
     {
-        // new connection was created from remote device.
-        // exit the function to update read file descriptor.
-        char buf[MAX_ADDR_STR_SIZE_CA] = {0};
-        ssize_t len = read(caglobals.tcp.connectionFds[0], buf, sizeof (buf));
-        if (-1 == len)
-        {
+            // new connection was created from remote device.
+            // exit the function to update read file descriptor.
+            char buf[MAX_ADDR_STR_SIZE_CA] = {0};
+            ssize_t len = read(caglobals.tcp.connectionFds[0], buf, sizeof (buf));
+            if (-1 == len)
+            {
+                return;
+            }
+            OIC_LOG_V(DEBUG, TAG, "Received new connection event with [%s]", buf);
             return;
-        }
-        OIC_LOG_V(DEBUG, TAG, "Received new connection event with [%s]", buf);
-        return;
     }
     else
     {
@@ -404,7 +414,17 @@ static void CASelectReturned(fd_set *readFds)
                     (CATCPSessionInfo_t *) u_arraylist_get(caglobals.tcp.svrlist, i);
             if (svritem && svritem->fd >= 0)
             {
-                if (FD_ISSET(svritem->fd, readFds))
+                size_t j = 0;
+                while (j < size)
+                {
+                    if (svritem->fd == readFds[j].fd)
+                    {
+                        break;
+                    }
+                    j++;
+                }
+
+                if (j < size  && readFds[j].revents != 0)
                 {
                     readFDList[readFDListSize++] = svritem->fd;
                 }
@@ -485,8 +505,6 @@ static void CAAcceptConnection(CATransportFlags_t flag, CASocket_t *sock)
         }
         oc_mutex_unlock(g_mutexObjectList);
 
-        CHECKFD(sockfd);
-
         // pass the connection information to CA Common Layer.
         if (g_connectionCallback)
         {
@@ -922,7 +940,6 @@ static CAResult_t CATCPCreateSocket(int family, CATCPSessionInfo_t *svritem)
 
     OIC_LOG(INFO, TAG, "connect socket success");
     svritem->state = CONNECTED;
-    CHECKFD(svritem->fd);
     ssize_t len = CAWakeUpForReadFdsUpdate(svritem->sep.endpoint.addr);
     if (-1 == len)
     {
@@ -1126,7 +1143,6 @@ static void CAInitializePipe(int *fds)
         caglobals.tcp.NAME.port = 0; \
         caglobals.tcp.NAME.fd = CACreateAcceptSocket(FAMILY, &caglobals.tcp.NAME); \
     } \
-    CHECKFD(caglobals.tcp.NAME.fd);
 
 void CATCPInitializeSocket()
 {
@@ -1195,13 +1211,9 @@ CAResult_t CATCPStartServer(const ca_thread_pool_t threadPool)
 #ifndef __TIZENRT__
     // create pipe for fast shutdown
     CAInitializePipe(caglobals.tcp.shutdownFds);
-    CHECKFD(caglobals.tcp.shutdownFds[0]);
-    CHECKFD(caglobals.tcp.shutdownFds[1]);
 #endif
     // create pipe for connection event
     CAInitializePipe(caglobals.tcp.connectionFds);
-    CHECKFD(caglobals.tcp.connectionFds[0]);
-    CHECKFD(caglobals.tcp.connectionFds[1]);
 
     CAResult_t res = CA_STATUS_OK;
 #ifndef __TIZENRT__