#endif
#endif
int selectTimeout; /**< in seconds */
- int maxfd; /**< highest fd (for select) */
bool started; /**< the IP adapter has started */
bool terminate; /**< the IP adapter needs to stop */
bool ipv6enabled; /**< IPv6 enabled by OCInit flags */
int shutdownFds[2]; /**< shutdown pipe */
#endif
int connectionFds[2]; /**< connection pipe */
- int maxfd; /**< highest fd (for select) */
bool started; /**< the TCP adapter has started */
bool terminate; /**< the TCP adapter needs to stop */
bool ipv4tcpenabled; /**< IPv4 TCP enabled by OCInit flags */
#ifdef __TIZENRT__
#include <tinyara/config.h>
#include <uio.h>
+#include <poll.h>
#endif
#include "iotivity_config.h"
#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>
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
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__
- if (caglobals.ip.shutdownFds[0] != -1)
- {
- FD_SET(caglobals.ip.shutdownFds[0], &readFds);
- }
-#endif
- if (caglobals.ip.netlinkFd != OC_INVALID_SOCKET)
- {
- FD_SET(caglobals.ip.netlinkFd, &readFds);
- }
+ readFds[counter].fd = caglobals.ip.shutdownFds[0];
+ readFds[counter].events = POLLIN;
+ counter++;
- int ret = select(caglobals.ip.maxfd + 1, &readFds, NULL, NULL, tv);
+ readFds[counter].fd = caglobals.ip.netlinkFd;
+ readFds[counter].events = POLLIN;
+ counter++;
+#endif
+ int ret = poll(readFds, counter, timeout);
if (caglobals.ip.terminate)
{
OIC_LOG_V(INFO, TAG, "Packet receiver Stop request received.");
u_arraylist_destroy(iflist);
}
#endif
- if (0 < ret)
+ if (ret > 0)
{
- CASelectReturned(&readFds, ret);
+ CAPollReturned(readFds, ret);
}
- else if (0 > ret)
+ else if (ret < 0)
{
- OIC_LOG_V(FATAL, TAG, "select error %s", CAIPS_GET_ERROR);
+ OIC_LOG_V(FATAL, TAG, "poll error %s", CAIPS_GET_ERROR);
}
}
-static void CASelectReturned(fd_set *readFds, int ret)
+static void CAPollReturned(struct pollfd *readFds, int ret)
{
(void)ret;
- CASocketFd_t fd = OC_INVALID_SOCKET;
- CATransportFlags_t flags = CA_DEFAULT_FLAGS;
- while (!caglobals.ip.terminate)
+ int counter = 0;
+
+ for (int i = 0; i < MAX_UDP_SOCK_COUNT && !caglobals.ip.terminate; i++)
{
- 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))
+ if (*sockFdPtr[i] != OC_INVALID_SOCKET && readFds[i].revents == POLLIN)
{
-#ifndef __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);
- }
- break;
-#endif
+ (void)CAReceiveMessage(readFds[i].fd, inputflags[i]);
}
+ counter++;
+ }
+
#ifndef __TIZENRT__
- else if (FD_ISSET(caglobals.ip.shutdownFds[0], readFds))
+ if (caglobals.ip.terminate)
+ {
+ return;
+ }
+
+ if (caglobals.ip.shutdownFds[0] != -1 && readFds[counter].revents != 0)
+ {
+ char buf[10] = {0};
+ ssize_t len = read(caglobals.ip.shutdownFds[0], buf, sizeof (buf));
+ if (-1 != len)
{
- char buf[10] = {0};
- ssize_t len = read(caglobals.ip.shutdownFds[0], buf, sizeof (buf));
- if (-1 == len)
- {
- continue;
- }
- break;
+ // Write end of the pipe is closed. Indicates the termination of UDP server.
+ return;
}
-#endif
- else
+
+ counter++;
+ }
+
+ if (!caglobals.ip.terminate &&
+ (caglobals.ip.netlinkFd != OC_INVALID_SOCKET) && readFds[counter].revents != 0)
+ {
+ u_arraylist_t *iflist = CAFindInterfaceChange();
+ if (iflist)
{
- break;
+ 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);
}
- (void)CAReceiveMessage(fd, flags);
- FD_CLR(fd, readFds);
}
+#endif
}
#else // if defined(WSA_WAIT_EVENT_0)
return fd;
}
-#define CHECKFD(FD) \
- if (FD > caglobals.ip.maxfd) \
- caglobals.ip.maxfd = FD;
#define NEWSOCKET(FAMILY, NAME, 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()
close(caglobals.ip.netlinkFd);
caglobals.ip.netlinkFd = OC_INVALID_SOCKET;
}
- else
- {
- CHECKFD(caglobals.ip.netlinkFd);
- }
}
#elif defined (__TIZENRT__) // pkmsgq
struct mq_attr lq_attr;
#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__
caglobals.ip.shutdownFds[1] = -1;
}
}
- CHECKFD(caglobals.ip.shutdownFds[0]);
- CHECKFD(caglobals.ip.shutdownFds[1]);
#endif
#endif
if (-1 == ret)
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/select.h>
#include <sys/ioctl.h>
#ifdef __TIZENRT__
#include <tinyara/config.h>
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);
}
#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) \
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()
{
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
{
(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;
}
}
oc_mutex_unlock(g_mutexObjectList);
- CHECKFD(sockfd);
-
// pass the connection information to CA Common Layer.
if (g_connectionCallback)
{
OIC_LOG(INFO, TAG, "connect socket success");
svritem->state = CONNECTED;
- CHECKFD(svritem->fd);
ssize_t len = CAWakeUpForReadFdsUpdate(svritem->sep.endpoint.addr);
if (-1 == len)
{
caglobals.tcp.NAME.port = 0; \
caglobals.tcp.NAME.fd = CACreateAcceptSocket(FAMILY, &caglobals.tcp.NAME); \
} \
- CHECKFD(caglobals.tcp.NAME.fd);
void CATCPInitializeSocket()
{
#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__