summaryrefslogtreecommitdiff
path: root/usbredirserver
diff options
context:
space:
mode:
authorzhenwei.pi <zhenwei.pi@youruncloud.com>2018-03-09 16:16:43 +0800
committerVictor Toso <me@victortoso.com>2018-03-12 11:25:57 +0100
commitaca0e87db16da1837e07cb52f160f61999745e84 (patch)
treecc4b961182761a7dfb9db7142ba53f4264dd22f9 /usbredirserver
parent6d510437542c6712c7005fe61cf9c919b9c90038 (diff)
usbredirserver : enable TCP keepalive
In some bad cases, for example, host OS crashes without sending any FIN to usbredirserver, and usbredirserver will keep idle connection for a long time. We can also set the kernel arguments, it means that other processes may be affected. Setting a sensible timeout(like 10 minutes) seems good. But QEMU is restarted after host OS crashes, it usually needs to reconnect usbredirserver within 2 minutes. So, add cmdline argument '-k' and "--keepalive" for usbredirserver to set tcp keepalive idle time, interval time(10s), and maximum number of keepalive probes count(3). Detecting disconnection costs time is : idle time + 10s * 3 If setting TCP keepalive fails with errno ENOTSUP, ignore the specific error. Signed-off-by: zhenwei.pi <zhenwei.pi@youruncloud.com> Tested-by: Uri Lublin <uril@redhat.com> Acked-by: Frediano Ziglio <fziglio@redhat.com>
Diffstat (limited to 'usbredirserver')
-rw-r--r--usbredirserver/usbredirserver.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/usbredirserver/usbredirserver.c b/usbredirserver/usbredirserver.c
index 5575181..849aa05 100644
--- a/usbredirserver/usbredirserver.c
+++ b/usbredirserver/usbredirserver.c
@@ -37,6 +37,7 @@
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <netinet/tcp.h>
#include "usbredirhost.h"
@@ -52,6 +53,7 @@ static const struct option longopts[] = {
{ "verbose", required_argument, NULL, 'v' },
{ "ipv4", required_argument, NULL, '4' },
{ "ipv6", required_argument, NULL, '6' },
+ { "keepalive", required_argument, NULL, 'k' },
{ "help", no_argument, NULL, 'h' },
{ NULL, 0, NULL, 0 }
};
@@ -98,6 +100,7 @@ static void usage(int exit_code, char *argv0)
fprintf(exit_code? stderr:stdout,
"Usage: %s [-p|--port <port>] [-v|--verbose <0-5>] "
"[[-4|--ipv4 ipaddr]|[-6|--ipv6 ipaddr]] "
+ "[-k|--keepalive seconds] "
"<busnum-devnum|vendorid:prodid>\n",
argv0);
exit(exit_code);
@@ -203,6 +206,7 @@ int main(int argc, char *argv[])
int usbvendor = -1;
int usbproduct = -1;
int on = 1;
+ int keepalive = -1;
char *ipv4_addr = NULL, *ipv6_addr = NULL;
union {
struct sockaddr_in v4;
@@ -211,7 +215,7 @@ int main(int argc, char *argv[])
struct sigaction act;
libusb_device_handle *handle = NULL;
- while ((o = getopt_long(argc, argv, "hp:v:4:6:", longopts, NULL)) != -1) {
+ while ((o = getopt_long(argc, argv, "hp:v:4:6:k:", longopts, NULL)) != -1) {
switch (o) {
case 'p':
port = strtol(optarg, &endptr, 10);
@@ -233,6 +237,13 @@ int main(int argc, char *argv[])
case '6':
ipv6_addr = optarg;
break;
+ case 'k':
+ keepalive = strtol(optarg, &endptr, 10);
+ if (*endptr != '\0') {
+ fprintf(stderr, "Invalid value for -k: '%s'\n", optarg);
+ usage(1, argv[0]);
+ }
+ break;
case '?':
case 'h':
usage(o == '?', argv[0]);
@@ -348,6 +359,38 @@ int main(int argc, char *argv[])
break;
}
+ if (keepalive > 0) {
+ int optval = 1;
+ socklen_t optlen = sizeof(optval);
+ if (setsockopt(client_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt SO_KEEPALIVE error.");
+ break;
+ }
+ }
+ optval = keepalive; /* set default TCP_KEEPIDLE time from cmdline */
+ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt TCP_KEEPIDLE error.");
+ break;
+ }
+ }
+ optval = 10; /* set default TCP_KEEPINTVL time as 10s */
+ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt TCP_KEEPINTVL error.");
+ break;
+ }
+ }
+ optval = 3; /* set default TCP_KEEPCNT as 3 */
+ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPCNT, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt TCP_KEEPCNT error.");
+ break;
+ }
+ }
+ }
+
flags = fcntl(client_fd, F_GETFL);
if (flags == -1) {
perror("fcntl F_GETFL");