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.
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
msmtp-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/msmtp-users