Skip to content
Snippets Groups Projects
Commit c40140b8 authored by Sébastien Blin's avatar Sébastien Blin Committed by Adrien Béraud
Browse files

upnp: rewrite pupnp by replacing select() with poll()

GitLab: #870
Change-Id: Ib8340359e7b3212714cf67407826cdda3b1b08cc
parent bd2789d5
No related branches found
No related tags found
No related merge requests found
upnp/src/genlib/net/http/httpreadwrite.c | 89 +++++++++++++++-------------------------
upnp/src/genlib/net/sock.c | 103 ++++++++++++++++++----------------------------
upnp/src/ssdp/ssdp_ctrlpt.c | 155 +++++++++++++++++++++++++--------------------------------------------
3 files changed, 129 insertions(+), 218 deletions(-)
diff --git a/upnp/src/genlib/net/http/httpreadwrite.c b/upnp/src/genlib/net/http/httpreadwrite.c
index 27e9c3a5..69eb0a1f 100644
--- a/upnp/src/genlib/net/http/httpreadwrite.c
+++ b/upnp/src/genlib/net/http/httpreadwrite.c
@@ -58,6 +58,7 @@
#include <assert.h>
#include <stdarg.h>
#include <string.h>
+#include <poll.h>
#include "posix_overwrites.h"
@@ -97,61 +98,39 @@ const int CHUNK_TAIL_SIZE = 10;
*
* \return 0 if successful, else -1.
*/
-static int Check_Connect_And_Wait_Connection(
- /*! [in] socket. */
- SOCKET sock,
- /*! [in] result of connect. */
- int connect_res)
-{
- struct timeval tmvTimeout = {DEFAULT_TCP_CONNECT_TIMEOUT, 0};
- int result;
- #ifdef _WIN32
- struct fd_set fdSet;
- #else
- fd_set fdSet;
- #endif
- FD_ZERO(&fdSet);
- FD_SET(sock, &fdSet);
-
- if (connect_res < 0) {
- #ifdef _WIN32
- if (WSAEWOULDBLOCK == WSAGetLastError()) {
- #else
- if (EINPROGRESS == errno) {
- #endif
- result = select(
- (int)sock + 1, NULL, &fdSet, NULL, &tmvTimeout);
- if (result < 0) {
- #ifdef _WIN32
- /* WSAGetLastError(); */
- #else
- /* errno */
- #endif
- return -1;
- } else if (result == 0) {
- /* timeout */
- return -1;
- #ifndef _WIN32
- } else {
- int valopt = 0;
- socklen_t len = sizeof(valopt);
- if (getsockopt(sock,
- SOL_SOCKET,
- SO_ERROR,
- (void *)&valopt,
- &len) < 0) {
- /* failed to read delayed error */
- return -1;
- } else if (valopt) {
- /* delayed error = valopt */
- return -1;
- }
- #endif
- }
- }
- }
-
- return 0;
+static int Check_Connect_And_Wait_Connection(SOCKET sock, int connect_res) {
+ struct timeval tmvTimeout = {DEFAULT_TCP_CONNECT_TIMEOUT, 0};
+ int result;
+ struct pollfd fds[1];
+
+ fds[0].fd = sock;
+ fds[0].events = POLLOUT;
+
+ if (connect_res < 0) {
+ result = poll(fds, 1, tmvTimeout.tv_sec * 1000 + tmvTimeout.tv_usec / 1000);
+
+ if (result < 0) {
+ /* Error in poll */
+ return -1;
+ } else if (result == 0) {
+ /* Timeout */
+ return -1;
+ } else {
+ int valopt = 0;
+ socklen_t len = sizeof(valopt);
+
+ /* Check if the socket is now writable (connected) */
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&valopt, &len) < 0) {
+ /* Failed to read delayed error */
+ return -1;
+ } else if (valopt) {
+ /* Delayed error = valopt */
+ return -1;
+ }
+ }
+ }
+
+ return 0;
}
#endif /* UPNP_ENABLE_BLOCKING_TCP_CONNECTIONS */
diff --git a/upnp/src/genlib/net/sock.c b/upnp/src/genlib/net/sock.c
index 396c692a..b8a980f0 100644
--- a/upnp/src/genlib/net/sock.c
+++ b/upnp/src/genlib/net/sock.c
@@ -56,6 +56,7 @@
#include <fcntl.h> /* for F_GETFL, F_SETFL, O_NONBLOCK */
#include <string.h>
#include <time.h>
+#include <poll.h>
#ifdef UPNP_ENABLE_OPEN_SSL
#include <openssl/ssl.h>
@@ -156,85 +157,59 @@ int sock_destroy(SOCKINFO *info, int ShutdownMethod)
* \li \c UPNP_E_TIMEDOUT - Timeout
* \li \c UPNP_E_SOCKET_ERROR - Error on socket calls
*/
-static int sock_read_write(
- /*! [in] Socket Information Object. */
- SOCKINFO *info,
- /*! [out] Buffer to get data to or send data from. */
- char *buffer,
- /*! [in] Size of the buffer. */
- size_t bufsize,
- /*! [in] timeout value. */
- int *timeoutSecs,
- /*! [in] Boolean value specifying read or write option. */
- int bRead)
-{
- int retCode;
- fd_set readSet;
- fd_set writeSet;
- struct timeval timeout;
- long numBytes;
- time_t start_time = time(NULL);
- SOCKET sockfd = info->socket;
- long bytes_sent = 0;
- size_t byte_left = 0;
- ssize_t num_written;
-
- FD_ZERO(&readSet);
- FD_ZERO(&writeSet);
- if (bRead)
- FD_SET(sockfd, &readSet);
- else
- FD_SET(sockfd, &writeSet);
- timeout.tv_sec = *timeoutSecs;
- timeout.tv_usec = 0;
- while (1) {
- if (*timeoutSecs < 0)
- retCode = select((int)sockfd + 1,
- &readSet,
- &writeSet,
- NULL,
- NULL);
- else
- retCode = select((int)sockfd + 1,
- &readSet,
- &writeSet,
- NULL,
- &timeout);
- if (retCode == 0)
- return UPNP_E_TIMEDOUT;
- if (retCode == -1) {
- if (errno == EINTR)
- continue;
- return UPNP_E_SOCKET_ERROR;
- } else
- /* read or write. */
- break;
- }
+static int sock_read_write(SOCKINFO *info, char *buffer, size_t bufsize, int *timeoutSecs, int bRead) {
+ int retCode;
+ struct pollfd fds[1];
+ time_t start_time = time(NULL);
+ SOCKET sockfd = info->socket;
+ long bytes_sent = 0;
+ size_t byte_left = 0;
+ ssize_t num_written;
+ long numBytes;
+
+ fds[0].fd = sockfd;
+ fds[0].events = (bRead ? POLLIN : POLLOUT);
+
+ while (1) {
+ int timeoutMillis = (*timeoutSecs < 0) ? -1 : (*timeoutSecs * 1000);
+
+ retCode = poll(fds, 1, timeoutMillis);
+
+ if (retCode == 0)
+ return UPNP_E_TIMEDOUT;
+ else if (retCode == -1) {
+ if (errno == EINTR)
+ continue;
+ return UPNP_E_SOCKET_ERROR;
+ } else
+ /* read or write. */
+ break;
+ }
+
#ifdef SO_NOSIGPIPE
- {
- int old;
- int set = 1;
- socklen_t olen = sizeof(old);
- getsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &old, &olen);
- setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set));
+ {
+ int old;
+ int set = 1;
+ socklen_t olen = sizeof(old);
+ getsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &old, &olen);
+ setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set));
#endif
if (bRead) {
#ifdef UPNP_ENABLE_OPEN_SSL
if (info->ssl) {
numBytes = (long)SSL_read(
- info->ssl, buffer, (size_t)bufsize);
+ info->ssl, buffer, bufsize);
} else {
#endif
/* read data. */
- numBytes = (long)recv(
- sockfd, buffer, bufsize, MSG_NOSIGNAL);
+ numBytes = (long)recv(sockfd, buffer, (int)bufsize, MSG_NOSIGNAL);
#ifdef UPNP_ENABLE_OPEN_SSL
}
#endif
} else {
byte_left = bufsize;
bytes_sent = 0;
- while (byte_left != (size_t)0) {
+ while (byte_left != 0) {
#ifdef UPNP_ENABLE_OPEN_SSL
if (info->ssl) {
num_written = SSL_write(info->ssl,
diff --git a/upnp/src/ssdp/ssdp_ctrlpt.c b/upnp/src/ssdp/ssdp_ctrlpt.c
index 8644c746..050b4916 100644
--- a/upnp/src/ssdp/ssdp_ctrlpt.c
+++ b/upnp/src/ssdp/ssdp_ctrlpt.c
@@ -40,6 +40,7 @@
#include "config.h"
#include "upnputil.h"
+#include <poll.h>
#ifdef INCLUDE_CLIENT_APIS
#if EXCLUDE_SSDP == 0
@@ -597,6 +598,7 @@ int SearchByTarget(int Hnd, int Mx, char *St, void *Cookie)
struct in_addr addrv4;
SOCKET max_fd = 0;
int retVal;
+ int numCopies = 0;
/*ThreadData *ThData; */
ThreadPoolJob job;
@@ -674,105 +676,60 @@ int SearchByTarget(int Hnd, int Mx, char *St, void *Cookie)
HandleUnlock();
/* End of lock */
- FD_ZERO(&wrSet);
- if (gSsdpReqSocket4 != INVALID_SOCKET) {
- setsockopt(gSsdpReqSocket4,
- IPPROTO_IP,
- IP_MULTICAST_IF,
- (char *)&addrv4,
- sizeof(addrv4));
- FD_SET(gSsdpReqSocket4, &wrSet);
- max_fd = max(max_fd, gSsdpReqSocket4);
- }
- #ifdef UPNP_ENABLE_IPV6
- if (gSsdpReqSocket6 != INVALID_SOCKET) {
- setsockopt(gSsdpReqSocket6,
- IPPROTO_IPV6,
- IPV6_MULTICAST_IF,
- (char *)&gIF_INDEX,
- sizeof(gIF_INDEX));
- FD_SET(gSsdpReqSocket6, &wrSet);
- max_fd = max(max_fd, gSsdpReqSocket6);
- }
- #endif
- ret = select((int)max_fd + 1, NULL, &wrSet, NULL, NULL);
- if (ret == -1) {
- strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
- UpnpPrintf(UPNP_INFO,
- SSDP,
- __FILE__,
- __LINE__,
- "SSDP_LIB: Error in select(): %s\n",
- errorBuffer);
- UpnpCloseSocket(gSsdpReqSocket4);
- #ifdef UPNP_ENABLE_IPV6
- UpnpCloseSocket(gSsdpReqSocket6);
- #endif
- return UPNP_E_INTERNAL_ERROR;
- }
- #ifdef UPNP_ENABLE_IPV6
- if (gSsdpReqSocket6 != INVALID_SOCKET &&
- FD_ISSET(gSsdpReqSocket6, &wrSet)) {
- int NumCopy = 0;
-
- while (NumCopy < NUM_SSDP_COPY) {
- UpnpPrintf(UPNP_INFO,
- SSDP,
- __FILE__,
- __LINE__,
- ">>> SSDP SEND M-SEARCH >>>\n%s\n",
- ReqBufv6UlaGua);
- sendto(gSsdpReqSocket6,
- ReqBufv6UlaGua,
- strlen(ReqBufv6UlaGua),
- 0,
- (struct sockaddr *)&__ss_v6,
- sizeof(struct sockaddr_in6));
- NumCopy++;
- imillisleep(SSDP_PAUSE);
- }
- NumCopy = 0;
- inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr);
- while (NumCopy < NUM_SSDP_COPY) {
- UpnpPrintf(UPNP_INFO,
- SSDP,
- __FILE__,
- __LINE__,
- ">>> SSDP SEND M-SEARCH >>>\n%s\n",
- ReqBufv6);
- sendto(gSsdpReqSocket6,
- ReqBufv6,
- strlen(ReqBufv6),
- 0,
- (struct sockaddr *)&__ss_v6,
- sizeof(struct sockaddr_in6));
- NumCopy++;
- imillisleep(SSDP_PAUSE);
- }
- }
- #endif /* IPv6 */
- if (gSsdpReqSocket4 != INVALID_SOCKET &&
- FD_ISSET(gSsdpReqSocket4, &wrSet)) {
- int NumCopy = 0;
- while (NumCopy < NUM_SSDP_COPY) {
- UpnpPrintf(UPNP_INFO,
- SSDP,
- __FILE__,
- __LINE__,
- ">>> SSDP SEND M-SEARCH >>>\n%s\n",
- ReqBufv4);
- sendto(gSsdpReqSocket4,
- ReqBufv4,
- strlen(ReqBufv4),
- 0,
- (struct sockaddr *)&__ss_v4,
- sizeof(struct sockaddr_in));
- NumCopy++;
- imillisleep(SSDP_PAUSE);
- }
- }
-
- return 1;
+ struct pollfd fds[2];
+ int nfds = 0;
+
+ if (gSsdpReqSocket4 != INVALID_SOCKET) {
+ setsockopt(gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addrv4, sizeof(addrv4));
+ fds[nfds].fd = gSsdpReqSocket4;
+ fds[nfds].events = POLLOUT;
+ nfds++;
+ }
+#ifdef UPNP_ENABLE_IPV6
+ if (gSsdpReqSocket6 != INVALID_SOCKET) {
+ setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&gIF_INDEX, sizeof(gIF_INDEX));
+ fds[nfds].fd = gSsdpReqSocket6;
+ fds[nfds].events = POLLOUT;
+ nfds++;
+ }
+#endif
+ ret = poll(fds, nfds, -1); // Wait indefinitely for the sockets to become writable
+ if (ret == -1) {
+ strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
+ UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "SSDP_LIB: Error in poll(): %s\n", errorBuffer);
+ UpnpCloseSocket(gSsdpReqSocket4);
+#ifdef UPNP_ENABLE_IPV6
+ UpnpCloseSocket(gSsdpReqSocket6);
+#endif
+ return UPNP_E_INTERNAL_ERROR;
+ }
+#ifdef UPNP_ENABLE_IPV6
+ if (gSsdpReqSocket6 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket6, &wrSet)) {
+ while (numCopies < NUM_SSDP_COPY) {
+ UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND M-SEARCH >>>\n%s\n", ReqBufv6UlaGua);
+ sendto(gSsdpReqSocket6, ReqBufv6UlaGua, (int)strlen(ReqBufv6UlaGua), 0, (struct sockaddr *)&__ss_v6, sizeof(struct sockaddr_in6));
+ numCopies++;
+ imillisleep(SSDP_PAUSE);
+ }
+ numCopies = 0;
+ inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr);
+ while (numCopies < NUM_SSDP_COPY) {
+ UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND M-SEARCH >>>\n%s\n", ReqBufv6);
+ sendto(gSsdpReqSocket6, ReqBufv6, (int)strlen(ReqBufv6), 0, (struct sockaddr *)&__ss_v6, sizeof(struct sockaddr_in6));
+ numCopies++;
+ imillisleep(SSDP_PAUSE);
+ }
+ }
+#endif /* IPv6 */
+ if (gSsdpReqSocket4 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket4, &wrSet)) {
+ while (numCopies < NUM_SSDP_COPY) {
+ UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND M-SEARCH >>>\n%s\n", ReqBufv4);
+ sendto(gSsdpReqSocket4, ReqBufv4, (int)strlen(ReqBufv4), 0, (struct sockaddr *)&__ss_v4, sizeof(struct sockaddr_in));
+ numCopies++;
+ imillisleep(SSDP_PAUSE);
+ }
+ }
+ return 1;
}
#endif /* EXCLUDE_SSDP */
#endif /* INCLUDE_CLIENT_APIS */
......@@ -17,6 +17,7 @@ upnp: pupnp-release-$(UPNP_VERSION).tar.gz .sum-upnp
ifeq ($(OS),Windows_NT)
$(APPLY) $(SRC)/upnp/libupnp-windows.patch
endif
$(APPLY) $(SRC)/upnp/poll.patch
$(UPDATE_AUTOCONFIG) && cd $(UNPACK_DIR) && mv config.guess config.sub
$(MOVE)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment