diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2023-05-08 11:14:18 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2023-05-08 11:14:18 +0900 |
commit | 9110945ce625e4a668eeed6a00252b7851e6d4b6 (patch) | |
tree | 2a3ba2b94fff96470adcde04e67099dc0fea9c68 | |
parent | 3d8195ebc5e3f48c004b3a7ec473e66166c58fe7 (diff) | |
download | libassuan-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.texi | 17 | ||||
-rw-r--r-- | src/assuan-socket.c | 57 | ||||
-rw-r--r-- | src/assuan.h.in | 2 |
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); |