diff options
| author | 2020-05-28 20:33:15 +0200 | |
|---|---|---|
| committer | 2020-05-28 20:33:15 +0200 | |
| commit | 3ae1cbbfb3b21af9ab1bc749b6a2681a3a3334ec (patch) | |
| tree | 9c949e4e1ed2786023ba3b881a82287f0fef133d /tools | |
| parent | 839d9cbcfe35d367638135c486fb119556098e19 (diff) | |
| download | libusbmuxd-3ae1cbbfb3b21af9ab1bc749b6a2681a3a3334ec.tar.gz libusbmuxd-3ae1cbbfb3b21af9ab1bc749b6a2681a3a3334ec.tar.bz2 | |
iproxy: Allow multiple port mappings (in local:device format)
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/iproxy.c | 173 | 
1 files changed, 119 insertions, 54 deletions
| diff --git a/tools/iproxy.c b/tools/iproxy.c index e9524a4..64a9989 100644 --- a/tools/iproxy.c +++ b/tools/iproxy.c @@ -232,11 +232,13 @@ static void print_usage(int argc, char **argv, int is_error)  int main(int argc, char **argv)  { -	int mysock = -1;  	char* device_udid = NULL;  	char* source_addr = NULL; -	uint16_t listen_port = 0; -	uint16_t device_port = 0; +	uint16_t listen_port[16]; +	uint16_t device_port[16]; +	int listen_sock[16] = { -1, }; +	int num_pairs = 0; +	int i = 0;  	enum usbmux_lookup_options lookup_opts = 0;  	const struct option longopts[] = { @@ -294,75 +296,138 @@ int main(int argc, char **argv)  	argc -= optind;  	argv += optind; -	if (argc < 2) { +	if (argc == 0) { +		fprintf(stderr, "ERROR: Not enough parameters. Need at least one pair of ports.\n");  		print_usage(argc + optind, argv - optind, 1);  		free(device_udid); +		free(source_addr);  		return 2;  	} -	listen_port = atoi(argv[0]); -	device_port = atoi(argv[1]); - -	if (!listen_port) { -		fprintf(stderr, "Invalid listen port specified!\n"); -		free(device_udid); -		return -EINVAL; -	} - -	if (!device_port) { -		fprintf(stderr, "Invalid device port specified!\n"); -		free(device_udid); -		return -EINVAL; +	if (argc == 2 && (strchr(argv[0], ':') == NULL) && (strchr(argv[1], ':') == NULL)) { +		/* support old-style port pair specification */ +		char* endp = NULL; +		listen_port[0] = (uint16_t)strtol(argv[0], &endp, 10); +		if (!listen_port[0] || *endp != '\0') { +			fprintf(stderr, "Invalid listen port specified in argument '%s'!\n", argv[0]); +			free(device_udid); +			free(source_addr); +			return -EINVAL; +		} +		endp = NULL; +		device_port[0] = (uint16_t)strtol(argv[1], &endp, 10); +		if (!device_port[0] || *endp != '\0') { +			fprintf(stderr, "Invalid device port specified in argument '%s'!\n", argv[1]); +			free(device_udid); +			free(source_addr); +			return -EINVAL; +		} +		num_pairs = 1; +	} else { +		/* new style, colon-separated local:device port pairs */ +		for (i = 0; i < argc; i++) { +			char* endp = NULL; +			listen_port[i] = (uint16_t)strtol(argv[i], &endp, 10); +			if (!listen_port[i] || (*endp != ':')) { +				fprintf(stderr, "Invalid listen port specified in argument '%s'!\n", argv[i]); +				free(device_udid); +				free(source_addr); +				return -EINVAL; +			} +			device_port[i] = (uint16_t)strtol(endp+1, &endp, 10); +			if (!device_port[i] || (*endp != '\0')) { +				fprintf(stderr, "Invalid device port specified in argument '%s'!\n", argv[i+1]); +				free(device_udid); +				free(source_addr); +				return -EINVAL; +			} +		} +		num_pairs = argc;  	}  #ifndef WIN32  	signal(SIGPIPE, SIG_IGN);  #endif -	// first create the listening socket endpoint waiting for connections. -	mysock = socket_create(source_addr, listen_port); -	if (mysock < 0) { -		fprintf(stderr, "Error creating socket: %s\n", strerror(errno)); -		free(device_udid); -		return -errno; -	} else { + +	// first create the listening sockets +	for (i = 0; i < num_pairs; i++) { +		printf("Creating listening port %d for device port %d\n", listen_port[i], device_port[i]); +		listen_sock[i] = socket_create(source_addr, listen_port[i]); +		if (listen_sock[i] < 0) { +			int j; +			fprintf(stderr, "Error creating socket for listen port %u: %s\n", listen_port[i], strerror(errno)); +			free(source_addr); +			free(device_udid); +			for (j = i; j >= 0; j--) { +				socket_close(listen_sock[j]); +			} +			return -errno; +		} +	} + +	// make them non-blocking and add them to fd set +	fd_set fds; +	FD_ZERO(&fds); +	for (i = 0; i < num_pairs; i++) {  #ifdef WIN32 -		HANDLE acceptor = NULL; +		u_long l_yes = 1; +		ioctlsocket(listen_sock[i], FIONBIO, &l_yes);  #else -		pthread_t acceptor; +		int flags = fcntl(listen_sock[i], F_GETFL, 0); +		fcntl(listen_sock[i], F_SETFL, flags | O_NONBLOCK);  #endif -		struct client_data *cdata; -		int c_sock; -		while (1) { -			printf("waiting for connection\n"); -			c_sock = socket_accept(mysock, listen_port); -			if (c_sock < 0) { -				fprintf(stderr, "accept: %s\n", strerror(errno)); -				break; -			} else { -				printf("accepted connection, fd = %d\n", c_sock); -				cdata = (struct client_data*)malloc(sizeof(struct client_data)); -				if (!cdata) { -					socket_close(c_sock); -					fprintf(stderr, "ERROR: Out of memory\n"); -					free(device_udid); -					return -1; -				} -				cdata->fd = c_sock; -				cdata->sfd = -1; -				cdata->udid = strdup(device_udid); -				cdata->lookup_opts = lookup_opts; -				cdata->device_port = device_port; +		FD_SET(listen_sock[i], &fds); +	} + +	// main loop +	while (1) { +		printf("waiting for connection\n"); +		fd_set read_fds = fds; +		int ret_sel = select(listen_sock[num_pairs-1]+1, &read_fds, NULL, NULL, NULL); +		if (ret_sel < 0) { +			perror("select"); +			break; +		} +		for (i = 0; i < num_pairs; i++) { +			if (FD_ISSET(listen_sock[i], &read_fds)) {  #ifdef WIN32 -				acceptor = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)acceptor_thread, cdata, 0, NULL); -				CloseHandle(acceptor); +				HANDLE acceptor = NULL;  #else -				pthread_create(&acceptor, NULL, acceptor_thread, cdata); -				pthread_detach(acceptor); +				pthread_t acceptor;  #endif +				struct client_data *cdata; +				int c_sock = socket_accept(listen_sock[i], listen_port[i]); +				if (c_sock < 0) { +					fprintf(stderr, "accept: %s\n", strerror(errno)); +					break; +				} else { +					printf("New connection for %d->%d, fd = %d\n", listen_port[i], device_port[i], c_sock); +					cdata = (struct client_data*)malloc(sizeof(struct client_data)); +					if (!cdata) { +						socket_close(c_sock); +						fprintf(stderr, "ERROR: Out of memory\n"); +						free(device_udid); +						return -1; +					} +					cdata->fd = c_sock; +					cdata->sfd = -1; +					cdata->udid = strdup(device_udid); +					cdata->lookup_opts = lookup_opts; +					cdata->device_port = device_port[i]; +#ifdef WIN32 +					acceptor = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)acceptor_thread, cdata, 0, NULL); +					CloseHandle(acceptor); +#else +					pthread_create(&acceptor, NULL, acceptor_thread, cdata); +					pthread_detach(acceptor); +#endif +				}  			}  		} -		socket_close(c_sock); -		socket_close(mysock); +	} + +	for (i = 0; i < num_pairs; i++) { +		socket_close(listen_sock[i]);  	}  	free(device_udid); | 
