|
Packit |
9795e1 |
/* usbredirserver.c simple usb network redirection tcp/ip server (host).
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
Copyright 2010-2011 Red Hat, Inc.
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
Red Hat Authors:
|
|
Packit |
9795e1 |
Hans de Goede <hdegoede@redhat.com>
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
This program is free software; you can redistribute it and/or
|
|
Packit |
9795e1 |
modify it under the terms of the GNU General Public
|
|
Packit |
9795e1 |
License as published by the Free Software Foundation; either
|
|
Packit |
9795e1 |
version 2 of the License, or (at your option) any later version.
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
9795e1 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
9795e1 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
9795e1 |
General Public License for more details.
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
You should have received a copy of the GNU General Public License
|
|
Packit |
9795e1 |
along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
9795e1 |
*/
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
#include "config.h"
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
#include <stdio.h>
|
|
Packit |
9795e1 |
#include <stdlib.h>
|
|
Packit |
9795e1 |
#include <stdarg.h>
|
|
Packit |
9795e1 |
#include <string.h>
|
|
Packit |
9795e1 |
#include <getopt.h>
|
|
Packit |
9795e1 |
#include <unistd.h>
|
|
Packit |
9795e1 |
#include <errno.h>
|
|
Packit |
9795e1 |
#include <poll.h>
|
|
Packit |
9795e1 |
#include <fcntl.h>
|
|
Packit |
9795e1 |
#include <signal.h>
|
|
Packit |
9795e1 |
#include <sys/socket.h>
|
|
Packit |
9795e1 |
#include <sys/types.h>
|
|
Packit |
9795e1 |
#include <sys/time.h>
|
|
Packit |
9795e1 |
#include <netdb.h>
|
|
Packit |
9795e1 |
#include <netinet/in.h>
|
|
Packit |
9795e1 |
#include <arpa/inet.h>
|
|
Packit |
9795e1 |
#include <netinet/tcp.h>
|
|
Packit |
9795e1 |
#include "usbredirhost.h"
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
#define SERVER_VERSION "usbredirserver " PACKAGE_VERSION
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static int verbose = usbredirparser_info;
|
|
Packit |
9795e1 |
static int client_fd, running = 1;
|
|
Packit |
9795e1 |
static libusb_context *ctx;
|
|
Packit |
9795e1 |
static struct usbredirhost *host;
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static const struct option longopts[] = {
|
|
Packit |
9795e1 |
{ "port", required_argument, NULL, 'p' },
|
|
Packit |
9795e1 |
{ "verbose", required_argument, NULL, 'v' },
|
|
Packit |
9795e1 |
{ "ipv4", required_argument, NULL, '4' },
|
|
Packit |
9795e1 |
{ "ipv6", required_argument, NULL, '6' },
|
|
Packit |
9795e1 |
{ "keepalive", required_argument, NULL, 'k' },
|
|
Packit |
9795e1 |
{ "help", no_argument, NULL, 'h' },
|
|
Packit |
9795e1 |
{ NULL, 0, NULL, 0 }
|
|
Packit |
9795e1 |
};
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static void usbredirserver_log(void *priv, int level, const char *msg)
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
if (level <= verbose)
|
|
Packit |
9795e1 |
fprintf(stderr, "%s\n", msg);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static int usbredirserver_read(void *priv, uint8_t *data, int count)
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
int r = read(client_fd, data, count);
|
|
Packit |
9795e1 |
if (r < 0) {
|
|
Packit |
9795e1 |
if (errno == EAGAIN)
|
|
Packit |
9795e1 |
return 0;
|
|
Packit |
9795e1 |
return -1;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (r == 0) { /* Client disconnected */
|
|
Packit |
9795e1 |
close(client_fd);
|
|
Packit |
9795e1 |
client_fd = -1;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
return r;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static int usbredirserver_write(void *priv, uint8_t *data, int count)
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
int r = write(client_fd, data, count);
|
|
Packit |
9795e1 |
if (r < 0) {
|
|
Packit |
9795e1 |
if (errno == EAGAIN)
|
|
Packit |
9795e1 |
return 0;
|
|
Packit |
9795e1 |
if (errno == EPIPE) { /* Client disconnected */
|
|
Packit |
9795e1 |
close(client_fd);
|
|
Packit |
9795e1 |
client_fd = -1;
|
|
Packit |
9795e1 |
return 0;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
return -1;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
return r;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static void usage(int exit_code, char *argv0)
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
fprintf(exit_code? stderr:stdout,
|
|
Packit |
9795e1 |
"Usage: %s [-p|--port <port>] [-v|--verbose <0-5>] "
|
|
Packit |
9795e1 |
"[[-4|--ipv4 ipaddr]|[-6|--ipv6 ipaddr]] "
|
|
Packit |
9795e1 |
"[-k|--keepalive seconds] "
|
|
Packit |
9795e1 |
"<busnum-devnum|vendorid:prodid>\n",
|
|
Packit |
9795e1 |
argv0);
|
|
Packit |
9795e1 |
exit(exit_code);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static void invalid_usb_device_id(char *usb_device_id, char *argv0)
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
fprintf(stderr, "Invalid usb device identifier: %s\n", usb_device_id);
|
|
Packit |
9795e1 |
usage(1, argv0);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static void run_main_loop(void)
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
const struct libusb_pollfd **pollfds = NULL;
|
|
Packit |
9795e1 |
fd_set readfds, writefds;
|
|
Packit |
9795e1 |
int i, n, nfds;
|
|
Packit |
9795e1 |
struct timeval timeout, *timeout_p;
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
while (running && client_fd != -1) {
|
|
Packit |
9795e1 |
FD_ZERO(&readfds);
|
|
Packit |
9795e1 |
FD_ZERO(&writefds);
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
FD_SET(client_fd, &readfds);
|
|
Packit |
9795e1 |
if (usbredirhost_has_data_to_write(host)) {
|
|
Packit |
9795e1 |
FD_SET(client_fd, &writefds);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
nfds = client_fd + 1;
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
free(pollfds);
|
|
Packit |
9795e1 |
pollfds = libusb_get_pollfds(ctx);
|
|
Packit |
9795e1 |
for (i = 0; pollfds && pollfds[i]; i++) {
|
|
Packit |
9795e1 |
if (pollfds[i]->events & POLLIN) {
|
|
Packit |
9795e1 |
FD_SET(pollfds[i]->fd, &readfds);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (pollfds[i]->events & POLLOUT) {
|
|
Packit |
9795e1 |
FD_SET(pollfds[i]->fd, &writefds);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (pollfds[i]->fd >= nfds)
|
|
Packit |
9795e1 |
nfds = pollfds[i]->fd + 1;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (libusb_get_next_timeout(ctx, &timeout) == 1) {
|
|
Packit |
9795e1 |
timeout_p = &timeout;
|
|
Packit |
9795e1 |
} else {
|
|
Packit |
9795e1 |
timeout_p = NULL;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
n = select(nfds, &readfds, &writefds, NULL, timeout_p);
|
|
Packit |
9795e1 |
if (n == -1) {
|
|
Packit |
9795e1 |
if (errno == EINTR) {
|
|
Packit |
9795e1 |
continue;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
perror("select");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
memset(&timeout, 0, sizeof(timeout));
|
|
Packit |
9795e1 |
if (n == 0) {
|
|
Packit |
9795e1 |
libusb_handle_events_timeout(ctx, &timeout);
|
|
Packit |
9795e1 |
continue;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (FD_ISSET(client_fd, &readfds)) {
|
|
Packit |
9795e1 |
if (usbredirhost_read_guest_data(host)) {
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
/* usbredirhost_read_guest_data may have detected client disconnect */
|
|
Packit |
9795e1 |
if (client_fd == -1)
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (FD_ISSET(client_fd, &writefds)) {
|
|
Packit |
9795e1 |
if (usbredirhost_write_guest_data(host)) {
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
for (i = 0; pollfds && pollfds[i]; i++) {
|
|
Packit |
9795e1 |
if (FD_ISSET(pollfds[i]->fd, &readfds) ||
|
|
Packit |
9795e1 |
FD_ISSET(pollfds[i]->fd, &writefds)) {
|
|
Packit |
9795e1 |
libusb_handle_events_timeout(ctx, &timeout);
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (client_fd != -1) { /* Broken out of the loop because of an error ? */
|
|
Packit |
9795e1 |
close(client_fd);
|
|
Packit |
9795e1 |
client_fd = -1;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
free(pollfds);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
static void quit_handler(int sig)
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
running = 0;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
int main(int argc, char *argv[])
|
|
Packit |
9795e1 |
{
|
|
Packit |
9795e1 |
int o, flags, server_fd = -1;
|
|
Packit |
9795e1 |
char *endptr, *delim;
|
|
Packit |
9795e1 |
int port = 4000;
|
|
Packit |
9795e1 |
int usbbus = -1;
|
|
Packit |
9795e1 |
int usbaddr = -1;
|
|
Packit |
9795e1 |
int usbvendor = -1;
|
|
Packit |
9795e1 |
int usbproduct = -1;
|
|
Packit |
9795e1 |
int on = 1;
|
|
Packit |
9795e1 |
int keepalive = -1;
|
|
Packit |
9795e1 |
char *ipv4_addr = NULL, *ipv6_addr = NULL;
|
|
Packit |
9795e1 |
union {
|
|
Packit |
9795e1 |
struct sockaddr_in v4;
|
|
Packit |
9795e1 |
struct sockaddr_in6 v6;
|
|
Packit |
9795e1 |
} serveraddr;
|
|
Packit |
9795e1 |
struct sigaction act;
|
|
Packit |
9795e1 |
libusb_device_handle *handle = NULL;
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
while ((o = getopt_long(argc, argv, "hp:v:4:6:k:", longopts, NULL)) != -1) {
|
|
Packit |
9795e1 |
switch (o) {
|
|
Packit |
9795e1 |
case 'p':
|
|
Packit |
9795e1 |
port = strtol(optarg, &endptr, 10);
|
|
Packit |
9795e1 |
if (*endptr != '\0') {
|
|
Packit |
9795e1 |
fprintf(stderr, "Invalid value for --port: '%s'\n", optarg);
|
|
Packit |
9795e1 |
usage(1, argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
case 'v':
|
|
Packit |
9795e1 |
verbose = strtol(optarg, &endptr, 10);
|
|
Packit |
9795e1 |
if (*endptr != '\0') {
|
|
Packit |
9795e1 |
fprintf(stderr, "Invalid value for --verbose: '%s'\n", optarg);
|
|
Packit |
9795e1 |
usage(1, argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
case '4':
|
|
Packit |
9795e1 |
ipv4_addr = optarg;
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
case '6':
|
|
Packit |
9795e1 |
ipv6_addr = optarg;
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
case 'k':
|
|
Packit |
9795e1 |
keepalive = strtol(optarg, &endptr, 10);
|
|
Packit |
9795e1 |
if (*endptr != '\0') {
|
|
Packit |
9795e1 |
fprintf(stderr, "Invalid value for -k: '%s'\n", optarg);
|
|
Packit |
9795e1 |
usage(1, argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
case '?':
|
|
Packit |
9795e1 |
case 'h':
|
|
Packit |
9795e1 |
usage(o == '?', argv[0]);
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (optind == argc) {
|
|
Packit |
9795e1 |
fprintf(stderr, "Missing usb device identifier argument\n");
|
|
Packit |
9795e1 |
usage(1, argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
delim = strchr(argv[optind], '-');
|
|
Packit |
9795e1 |
if (delim && delim[1]) {
|
|
Packit |
9795e1 |
usbbus = strtol(argv[optind], &endptr, 10);
|
|
Packit |
9795e1 |
if (*endptr != '-') {
|
|
Packit |
9795e1 |
invalid_usb_device_id(argv[optind], argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
usbaddr = strtol(delim + 1, &endptr, 10);
|
|
Packit |
9795e1 |
if (*endptr != '\0') {
|
|
Packit |
9795e1 |
invalid_usb_device_id(argv[optind], argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
} else {
|
|
Packit |
9795e1 |
delim = strchr(argv[optind], ':');
|
|
Packit |
9795e1 |
if (!delim || !delim[1]) {
|
|
Packit |
9795e1 |
invalid_usb_device_id(argv[optind], argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
usbvendor = strtol(argv[optind], &endptr, 16);
|
|
Packit |
9795e1 |
if (*endptr != ':' || usbvendor <= 0 || usbvendor > 0xffff) {
|
|
Packit |
9795e1 |
invalid_usb_device_id(argv[optind], argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
usbproduct = strtol(delim + 1, &endptr, 16);
|
|
Packit |
9795e1 |
/* Product ID 0000 is valid */
|
|
Packit |
9795e1 |
if (*endptr != '\0' || usbproduct < 0 || usbproduct > 0xffff) {
|
|
Packit |
9795e1 |
invalid_usb_device_id(argv[optind], argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
optind++;
|
|
Packit |
9795e1 |
if (optind != argc) {
|
|
Packit |
9795e1 |
fprintf(stderr, "Excess non option arguments\n");
|
|
Packit |
9795e1 |
usage(1, argv[0]);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
memset(&act, 0, sizeof(act));
|
|
Packit |
9795e1 |
act.sa_handler = quit_handler;
|
|
Packit |
9795e1 |
sigaction(SIGINT, &act, NULL);
|
|
Packit |
9795e1 |
sigaction(SIGHUP, &act, NULL);
|
|
Packit |
9795e1 |
sigaction(SIGTERM, &act, NULL);
|
|
Packit |
9795e1 |
sigaction(SIGQUIT, &act, NULL);
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (libusb_init(&ctx)) {
|
|
Packit |
9795e1 |
fprintf(stderr, "Could not init libusb\n");
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
#if LIBUSB_API_VERSION >= 0x01000106
|
|
Packit |
9795e1 |
libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, verbose);
|
|
Packit |
9795e1 |
#else
|
|
Packit |
9795e1 |
libusb_set_debug(ctx, verbose);
|
|
Packit |
9795e1 |
#endif
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (ipv4_addr) {
|
|
Packit |
9795e1 |
server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
Packit |
9795e1 |
} else {
|
|
Packit |
9795e1 |
server_fd = socket(AF_INET6, SOCK_STREAM, 0);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (server_fd == -1) {
|
|
Packit |
9795e1 |
perror("Error creating ip socket");
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
|
|
Packit |
9795e1 |
perror("Error setsockopt(SO_REUSEADDR) failed");
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
memset(&serveraddr, 0, sizeof(serveraddr));
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (ipv4_addr) {
|
|
Packit |
9795e1 |
serveraddr.v4.sin_family = AF_INET;
|
|
Packit |
9795e1 |
serveraddr.v4.sin_port = htons(port);
|
|
Packit |
9795e1 |
if ((inet_pton(AF_INET, ipv4_addr,
|
|
Packit |
9795e1 |
&serveraddr.v4.sin_addr)) != 1) {
|
|
Packit |
9795e1 |
perror("Error convert ipv4 address");
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
} else {
|
|
Packit |
9795e1 |
serveraddr.v6.sin6_family = AF_INET6;
|
|
Packit |
9795e1 |
serveraddr.v6.sin6_port = htons(port);
|
|
Packit |
9795e1 |
if (ipv6_addr) {
|
|
Packit |
9795e1 |
if ((inet_pton(AF_INET6, ipv6_addr,
|
|
Packit |
9795e1 |
&serveraddr.v6.sin6_addr)) != 1) {
|
|
Packit |
9795e1 |
perror("Error convert ipv6 address");
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
} else {
|
|
Packit |
9795e1 |
serveraddr.v6.sin6_addr = in6addr_any;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (bind(server_fd, (struct sockaddr *)&serveraddr,
|
|
Packit |
9795e1 |
sizeof(serveraddr))) {
|
|
Packit |
9795e1 |
perror("Error bind");
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (listen(server_fd, 1)) {
|
|
Packit |
9795e1 |
perror("Error listening");
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
while (running) {
|
|
Packit |
9795e1 |
client_fd = accept(server_fd, NULL, 0);
|
|
Packit |
9795e1 |
if (client_fd == -1) {
|
|
Packit |
9795e1 |
if (errno == EINTR) {
|
|
Packit |
9795e1 |
continue;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
perror("accept");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
if (keepalive > 0) {
|
|
Packit |
9795e1 |
int optval = 1;
|
|
Packit |
9795e1 |
socklen_t optlen = sizeof(optval);
|
|
Packit |
9795e1 |
if (setsockopt(client_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) == -1) {
|
|
Packit |
9795e1 |
if (errno != ENOTSUP) {
|
|
Packit |
9795e1 |
perror("setsockopt SO_KEEPALIVE error.");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
optval = keepalive; /* set default TCP_KEEPIDLE time from cmdline */
|
|
Packit |
9795e1 |
if (setsockopt(client_fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) == -1) {
|
|
Packit |
9795e1 |
if (errno != ENOTSUP) {
|
|
Packit |
9795e1 |
perror("setsockopt TCP_KEEPIDLE error.");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
optval = 10; /* set default TCP_KEEPINTVL time as 10s */
|
|
Packit |
9795e1 |
if (setsockopt(client_fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) == -1) {
|
|
Packit |
9795e1 |
if (errno != ENOTSUP) {
|
|
Packit |
9795e1 |
perror("setsockopt TCP_KEEPINTVL error.");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
optval = 3; /* set default TCP_KEEPCNT as 3 */
|
|
Packit |
9795e1 |
if (setsockopt(client_fd, SOL_TCP, TCP_KEEPCNT, &optval, optlen) == -1) {
|
|
Packit |
9795e1 |
if (errno != ENOTSUP) {
|
|
Packit |
9795e1 |
perror("setsockopt TCP_KEEPCNT error.");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
flags = fcntl(client_fd, F_GETFL);
|
|
Packit |
9795e1 |
if (flags == -1) {
|
|
Packit |
9795e1 |
perror("fcntl F_GETFL");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
flags = fcntl(client_fd, F_SETFL, flags | O_NONBLOCK);
|
|
Packit |
9795e1 |
if (flags == -1) {
|
|
Packit |
9795e1 |
perror("fcntl F_SETFL O_NONBLOCK");
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
/* Try to find the specified usb device */
|
|
Packit |
9795e1 |
if (usbvendor != -1) {
|
|
Packit |
9795e1 |
handle = libusb_open_device_with_vid_pid(ctx, usbvendor,
|
|
Packit |
9795e1 |
usbproduct);
|
|
Packit |
9795e1 |
if (!handle) {
|
|
Packit |
9795e1 |
fprintf(stderr,
|
|
Packit |
9795e1 |
"Could not open an usb-device with vid:pid %04x:%04x\n",
|
|
Packit |
9795e1 |
usbvendor, usbproduct);
|
|
Packit |
9795e1 |
} else if (verbose >= usbredirparser_info) {
|
|
Packit |
9795e1 |
libusb_device *dev;
|
|
Packit |
9795e1 |
dev = libusb_get_device(handle);
|
|
Packit |
9795e1 |
fprintf(stderr, "Open a usb-device with vid:pid %04x:%04x on "
|
|
Packit |
9795e1 |
"bus %03x device %03x\n",
|
|
Packit |
9795e1 |
usbvendor, usbproduct,
|
|
Packit |
9795e1 |
libusb_get_bus_number(dev),
|
|
Packit |
9795e1 |
libusb_get_device_address(dev));
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
} else {
|
|
Packit |
9795e1 |
libusb_device **list = NULL;
|
|
Packit |
9795e1 |
ssize_t i, n;
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
n = libusb_get_device_list(ctx, &list);
|
|
Packit |
9795e1 |
for (i = 0; i < n; i++) {
|
|
Packit |
9795e1 |
if (libusb_get_bus_number(list[i]) == usbbus &&
|
|
Packit |
9795e1 |
libusb_get_device_address(list[i]) == usbaddr)
|
|
Packit |
9795e1 |
break;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (i < n) {
|
|
Packit |
9795e1 |
if (libusb_open(list[i], &handle) != 0) {
|
|
Packit |
9795e1 |
fprintf(stderr,
|
|
Packit |
9795e1 |
"Could not open usb-device at busnum-devnum %d-%d\n",
|
|
Packit |
9795e1 |
usbbus, usbaddr);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
} else {
|
|
Packit |
9795e1 |
fprintf(stderr,
|
|
Packit |
9795e1 |
"Could not find an usb-device at busnum-devnum %d-%d\n",
|
|
Packit |
9795e1 |
usbbus, usbaddr);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
libusb_free_device_list(list, 1);
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
if (!handle) {
|
|
Packit |
9795e1 |
close(client_fd);
|
|
Packit |
9795e1 |
continue;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
host = usbredirhost_open(ctx, handle, usbredirserver_log,
|
|
Packit |
9795e1 |
usbredirserver_read, usbredirserver_write,
|
|
Packit |
9795e1 |
NULL, SERVER_VERSION, verbose, 0);
|
|
Packit |
9795e1 |
if (!host)
|
|
Packit |
9795e1 |
exit(1);
|
|
Packit |
9795e1 |
run_main_loop();
|
|
Packit |
9795e1 |
usbredirhost_close(host);
|
|
Packit |
9795e1 |
handle = NULL;
|
|
Packit |
9795e1 |
}
|
|
Packit |
9795e1 |
|
|
Packit |
9795e1 |
close(server_fd);
|
|
Packit |
9795e1 |
libusb_exit(ctx);
|
|
Packit |
9795e1 |
exit(0);
|
|
Packit |
9795e1 |
}
|