summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2023-05-08 11:14:18 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2023-05-08 11:14:18 +0900
commit9110945ce625e4a668eeed6a00252b7851e6d4b6 (patch)
tree2a3ba2b94fff96470adcde04e67099dc0fea9c68
parent3d8195ebc5e3f48c004b3a7ec473e66166c58fe7 (diff)
downloadlibassuan-9110945ce625e4a668eeed6a00252b7851e6d4b6.tar.gz
Implement timeout in assuan_sock_connect_byname.
* src/assuan-socket.c (socks5_connect): Add new argument TIMEOUT in milliseconds. (_assuan_sock_connect): Follow the change. (_assuan_sock_connect_byname): Fourth argument is now TIMEOUT. (assuan_sock_connect_byname): Likewise. -- GnuPG-bug-id: 3302 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--doc/assuan.texi17
-rw-r--r--src/assuan-socket.c57
-rw-r--r--src/assuan.h.in2
3 files changed, 52 insertions, 24 deletions
diff --git a/doc/assuan.texi b/doc/assuan.texi
index 7ecf544..111e6e3 100644
--- a/doc/assuan.texi
+++ b/doc/assuan.texi
@@ -1997,7 +1997,7 @@ details on the redirection file format.
@deftypefun int assuan_sock_connect_byname (@w{const char * @var{host}}, @
@w{unsigned short @var{port}}, @
- @w{int @var{reserved}}, @
+ @w{int @var{timeout}}, @
@w{const char *@var{credentials}}, @
@w{unsigned int @var{flags}})
@@ -2007,12 +2007,15 @@ current implementation requires that @var{flags} has either
new TCP STREAM socket is returned; on error @code{ASSUAN_INVALID_FD}
and ERRNO set. If @var{credentials} is not @code{NULL}, it is a
string used for password based SOCKS authentication. Username and
-password are separated by a colon. @var{reserved} should be 0. To
-test whether the proxy is available @var{host} and @var{port} may be
-given as NULL/0: If the proxy is available the function returns a
-valid socket which is in the state after credentials sub-negotiation.
-The caller now knows that the SOCKS proxy is available and has been
-authenticated; normally the caller closes the socket then.
+password are separated by a colon. @var{timeout} specifies timeout
+value (in miliseconds) for the connection. @var{timeout} with zero
+means no timeout (for client side, the SOCKS server may timeout).
+@var{timeout} with -1 means no wait. To test whether the proxy is
+available @var{host} and @var{port} may be given as NULL/0: If the
+proxy is available the function returns a valid socket which is in the
+state after credentials sub-negotiation. The caller now knows that
+the SOCKS proxy is available and has been authenticated; normally the
+caller closes the socket then.
@end deftypefun
diff --git a/src/assuan-socket.c b/src/assuan-socket.c
index c53468b..71e1495 100644
--- a/src/assuan-socket.c
+++ b/src/assuan-socket.c
@@ -692,7 +692,8 @@ socks5_connect (assuan_context_t ctx, assuan_fd_t sock,
unsigned short socksport,
const char *credentials,
const char *hostname, unsigned short hostport,
- struct sockaddr *addr, socklen_t length)
+ struct sockaddr *addr, socklen_t length,
+ int timeout)
{
int ret;
/* struct sockaddr_in6 proxyaddr_in6; */
@@ -751,11 +752,6 @@ socks5_connect (assuan_context_t ctx, assuan_fd_t sock,
proxyaddr_in.sin_port = htons (TOR_PORT2);
ret = _assuan_connect (ctx, sock, proxyaddr, proxyaddrlen);
}
- /* If we get an EINPROGRESS here the caller is trying to do a
- * non-blocking connect (e.g. for custom time out handling) which
- * fails here. The easiest fix would be to allow the client to tell
- * us the timeout value and we do the timeout handling later on in the
- * Socks protocol. */
if (ret)
return ret;
buffer[0] = 5; /* RFC-1928 VER field. */
@@ -783,7 +779,9 @@ socks5_connect (assuan_context_t ctx, assuan_fd_t sock,
succeeding calls, this select should soon return successfully.
*/
ret = select (HANDLE2SOCKET (sock)+1, &fds, NULL, NULL, &tv);
- if (!ret)
+ if (ret < 0)
+ return ret;
+ else if (!ret)
{
gpg_err_set_errno (ETIMEDOUT);
return -1;
@@ -887,6 +885,30 @@ socks5_connect (assuan_context_t ctx, assuan_fd_t sock,
ret = do_writen (ctx, sock, buffer, buflen);
if (ret)
return ret;
+
+ if (timeout != 0)
+ {
+ if (timeout == -1)
+ {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ else
+ {
+ /* TIMEOUT is in milisecond */
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ }
+ ret = select (HANDLE2SOCKET (sock)+1, &fds, NULL, NULL, &tv);
+ if (ret < 0)
+ return ret;
+ if (!ret)
+ {
+ gpg_err_set_errno (ETIMEDOUT);
+ return -1;
+ }
+ }
+
ret = do_readn (ctx, sock, buffer, 10 /* Length for IPv4 */);
if (ret)
return ret;
@@ -1065,7 +1087,7 @@ _assuan_sock_connect (assuan_context_t ctx, assuan_fd_t sockfd,
else if (use_socks (addr))
{
return socks5_connect (ctx, sockfd, tor_mode,
- NULL, NULL, 0, addr, addrlen);
+ NULL, NULL, 0, addr, addrlen, 0);
}
else
{
@@ -1108,7 +1130,7 @@ _assuan_sock_connect (assuan_context_t ctx, assuan_fd_t sockfd,
if (use_socks (addr))
{
return socks5_connect (ctx, sockfd, tor_mode,
- NULL, NULL, 0, addr, addrlen);
+ NULL, NULL, 0, addr, addrlen, 0);
}
else
{
@@ -1124,12 +1146,14 @@ _assuan_sock_connect (assuan_context_t ctx, assuan_fd_t sockfd,
returned; on error ASSUAN_INVALID_FD is returned and ERRNO set. If
CREDENTIALS is not NULL, it is a string used for password based
authentication. Username and password are separated by a colon.
- RESERVED must be 0. By passing HOST and PORT as 0 the function can
- be used to check for proxy availability: If the proxy is available
- a socket will be returned which the caller should then close. */
+ TIMEOUT specifies connection timeout in miliseconds (0 means
+ default timeout, -1 means immediate timeout). By passing HOST and
+ PORT as 0 the function can be used to check for proxy availability:
+ If the proxy is available a socket will be returned which the
+ caller should then close. */
assuan_fd_t
_assuan_sock_connect_byname (assuan_context_t ctx, const char *host,
- unsigned short port, int reserved,
+ unsigned short port, int timeout,
const char *credentials, unsigned int flags)
{
assuan_fd_t fd;
@@ -1161,7 +1185,8 @@ _assuan_sock_connect_byname (assuan_context_t ctx, const char *host,
that we can't pass NULL directly as this indicates IP address
mode to the called function. */
if (socks5_connect (ctx, fd, socksport,
- credentials, host? host:"", port, NULL, 0))
+ credentials, host? host:"", port, NULL, 0,
+ timeout))
{
int save_errno = errno;
assuan_sock_close (fd);
@@ -1514,11 +1539,11 @@ assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
assuan_fd_t
assuan_sock_connect_byname (const char *host, unsigned short port,
- int reserved, const char *credentials,
+ int timeout, const char *credentials,
unsigned int flags)
{
return _assuan_sock_connect_byname (sock_ctx,
- host, port, reserved, credentials, flags);
+ host, port, timeout, credentials, flags);
}
int
diff --git a/src/assuan.h.in b/src/assuan.h.in
index cf79970..a101344 100644
--- a/src/assuan.h.in
+++ b/src/assuan.h.in
@@ -503,7 +503,7 @@ assuan_fd_t assuan_sock_accept (assuan_fd_t sockfd,
int assuan_sock_connect (assuan_fd_t sockfd,
struct sockaddr *addr, int addrlen);
assuan_fd_t assuan_sock_connect_byname (const char *host, unsigned short port,
- int reserved,
+ int timeout,
const char *credentials,
unsigned int flags);
int assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen);