[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[msmtp-users] Patches for timeout on Windows
Hi!
I've come up with some patches regarding the timeout setting on Windows
(which doesn't work right now).
The first patch correctly handles timeout on send()/recv() operations.
--- msmtp-1.6.6/src/net.c 2016-11-11 15:12:04.000000000 +0700
+++ msmtp/src/net.c 2018-06-09 18:03:35.407374256 +0700
@@ -179,7 +179,7 @@
{
#ifdef W32_NATIVE
int e = WSAGetLastError();
- if (e == WSAEWOULDBLOCK)
+ if (e == WSAETIMEDOUT)
{
*errstr = xasprintf(_("network read error: %s"),
_("the operation timed out"));
@@ -226,7 +226,7 @@
{
#ifdef W32_NATIVE
int e = WSAGetLastError();
- if (e == WSAEWOULDBLOCK)
+ if (e == WSAETIMEDOUT)
{
*errstr = xasprintf(_("network write error: %s"),
_("the operation timed out"))
The second patch implements timeout on connect() for Windows. I also removed
the unnecessary rset variable (it doesn't matter for select() on connect()).
--- msmtp-1.6.6/src/net.c 2016-11-11 15:12:04.000000000 +0700
+++ msmtp/src/net.c 2018-06-09 18:23:11.721796148 +0700
@@ -319,16 +319,17 @@
int timeout)
{
#ifdef W32_NATIVE
- /* TODO: I don't know how to do this on Win32. Please send a patch. */
- return connect(fd, serv_addr, addrlen);
-#else /* UNIX or DJGPP */
-
+ u_long flags;
+ DWORD err;
+ int optlen;
+ fd_set eset;
+#else
int flags;
- struct timeval tv;
- fd_set rset;
- fd_set wset;
int err;
socklen_t optlen;
+#endif
+ struct timeval tv;
+ fd_set wset;
if (timeout <= 0)
{
@@ -337,8 +338,13 @@
else
{
/* make socket non-blocking */
+#ifdef W32_NATIVE
+ flags = 1;
+ if (ioctlsocket(fd, FIONBIO, &flags) == SOCKET_ERROR)
+#else
flags = fcntl(fd, F_GETFL, 0);
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
+#endif
{
return -1;
}
@@ -346,51 +352,75 @@
/* start connect */
if (connect(fd, serv_addr, addrlen) < 0)
{
+#ifdef W32_NATIVE
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+#else
if (errno != EINPROGRESS)
+#endif
{
return -1;
}
tv.tv_sec = timeout;
tv.tv_usec = 0;
- FD_ZERO(&rset);
FD_ZERO(&wset);
- FD_SET(fd, &rset);
FD_SET(fd, &wset);
+#ifdef W32_NATIVE
+ FD_ZERO(&eset);
+ FD_SET(fd, &eset);
+#endif
/* wait for connect() to finish */
- if ((err = select(fd + 1, &rset, &wset, NULL, &tv)) <= 0)
+#ifdef W32_NATIVE
+ /* In case of an error on connect(), eset will be affected instead
+ * of wset (on Windows only). */
+ if ((err = select(fd + 1, NULL, &wset, &eset, &tv)) <= 0)
+#else
+ if ((err = select(fd + 1, NULL, &wset, NULL, &tv)) <= 0)
+#endif
{
/* errno is already set if err < 0 */
if (err == 0)
{
+#ifdef W32_NATIVE
+ WSASetLastError(WSAETIMEDOUT);
+#else
errno = ETIMEDOUT;
+#endif
}
return -1;
}
/* test for success, set errno */
- optlen = sizeof(int);
+ optlen = sizeof(err);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen) < 0)
{
return -1;
}
if (err != 0)
{
+#ifdef W32_NATIVE
+ WSASetLastError(err);
+#else
errno = err;
+#endif
return -1;
}
}
/* restore blocking mode */
+#ifdef W32_NATIVE
+ flags = 0;
+ if (ioctlsocket(fd, FIONBIO, &flags) == SOCKET_ERROR)
+#else
if (fcntl(fd, F_SETFL, flags) == -1)
+#endif
{
return -1;
}
return 0;
}
-#endif /* UNIX */
}
And the third patch just closes Windows sockets properly.
--- msmtp-1.6.6/src/net.c 2016-11-11 15:12:04.000000000 +0700
+++ msmtp/src/net.c 2018-06-09 18:38:52.920735844 +0700
@@ -682,7 +712,7 @@
failure_errno = errno;
}
#endif
- close(fd);
+ net_close_socket(fd);
fd = -1;
continue;
}
I've tested the patches mildly on both Windows 7 and Wine.