For non-blocking TCP/Unix connection, OpenVPN checks was it established in
loop and if not - sleeps or handles management for next one second. Since
the first check is made right after the connection attempt, it will likely
be always unsuccessful, causing redundant wait for one or more seconds:
00:00:00.667607 fcntl(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
00:00:00.667713 connect(5, {...}, 16) = -1 EINPROGRESS (Operation now
in progress)
00:00:00.667832 poll([{fd=5, events=POLLOUT}], 1, 0) = 0 (Timeout)
00:00:00.667954 nanosleep({tv_sec=1, tv_nsec=0}, 0x7fff52450270) = 0
00:00:01.668608 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5,
revents=POLLOUT}])
After this patch openvpn_connect() will perform blocking wait for
connection
establishment (if possible) and just check for management events once in
one
second (if management enabled) w/o sleep. This speedups TCP/Unix connection
establishment and provides almost real connection time that can be used for
detection of the fastest remote server in subsequent patches:
00:00:00.790510 fcntl(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
00:00:00.790616 connect(5, {...}, 16) = -1 EINPROGRESS (Operation now
in progress)
00:00:00.790877 poll([{fd=5, events=POLLOUT}], 1, 1000) = 0 (Timeout)
00:00:01.792880 poll([{fd=5, events=POLLOUT}], 1, 1000) = 1 ([{fd=5,
revents=POLLOUT}])
Or, with management interface enabled:
00:00:00.906421 fcntl(5, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
00:00:00.906527 connect(6, {...}, 16) = -1 EINPROGRESS (Operation now
in progress)
00:00:00.906779 poll([{fd=6, events=POLLOUT}], 1, 1000) = 0 (Timeout)
00:00:01.910418 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 0) = 0
(Timeout)
00:00:01.911365 poll([{fd=6, events=POLLOUT}], 1, 1000) = 0 ([{fd=6,
revents=POLLOUT}])
v2: cosmetics, decrease connection_timeout to avoid wait more than it
v3: teach management_sleep() to handle zero timeout and reject negative
use 1s timeout for connection and 0s timeout for management events
Signed-off-by: Vladislav Grishenko <themiron@yandex-team.ru>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <
20201001225319.25125-1-themiron@yandex-team.ru>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg21139.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
if (man_standalone_ok(man))
{
+ /* expire time can be already overdue, for this case init zero
+ * timeout to avoid waiting first time and exit loop early with
+ * either obtained event or timeout.
+ */
+ tv.tv_usec = 0;
+ tv.tv_sec = 0;
+
while (true)
{
event_reset(man->connection.es);
management_socket_set(man, man->connection.es, NULL, NULL);
- tv.tv_usec = 0;
- tv.tv_sec = 1;
if (man_check_for_signals(signal_received))
{
status = -1;
}
break;
}
+
+ /* wait one second more */
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
}
}
return status;
/* set expire time */
update_time();
- if (sec)
+ if (sec >= 0)
{
expire = now + sec;
}
/* revert state */
man->persist.standalone_disabled = standalone_disabled_save;
}
- else
+ else if (sec > 0)
{
sleep(sec);
}
void
management_sleep(const int n)
{
- if (management)
+ if (n < 0)
+ {
+ return;
+ }
+ else if (management)
{
management_event_loop_n_seconds(management, n);
}
- else
+ else if (n > 0)
{
sleep(n);
}
void
management_sleep(const int n)
{
- sleep(n);
+ if (n > 0)
+ {
+ sleep(n);
+ }
}
#endif /* ENABLE_MANAGEMENT */
struct pollfd fds[1];
fds[0].fd = sd;
fds[0].events = POLLOUT;
- status = poll(fds, 1, 0);
+ status = poll(fds, 1, (connect_timeout > 0) ? 1000 : 0);
#else
fd_set writes;
struct timeval tv;
FD_ZERO(&writes);
openvpn_fd_set(sd, &writes);
- tv.tv_sec = 0;
+ tv.tv_sec = (connect_timeout > 0) ? 1 : 0;
tv.tv_usec = 0;
status = select(sd + 1, NULL, &writes, NULL, &tv);
#endif
break;
}
- management_sleep(1);
+ management_sleep(0);
continue;
}