idevicedebugserverproxy: Allow binding to any available port

To eliminate crosstalk between multiple proxies and their clients,
add support for binding to any free port provided by the OS to
idevicedebugserverproxy. To bind to any port, leave out the port
argument to idevicedebugserverproxy. In that case, the proxy will
print out a line with the port so clients can connect to it.

This is useful for a CI macOS host with multiple iDevices
connected, and where many independent tests each want their own
proxy instance connected to a particular device.
diff --git a/docs/idevicedebugserverproxy.1 b/docs/idevicedebugserverproxy.1
index 37502eb..248c694 100644
--- a/docs/idevicedebugserverproxy.1
+++ b/docs/idevicedebugserverproxy.1
@@ -3,7 +3,7 @@
 idevicedebugserverproxy \- Remote debugging proxy.
 .SH SYNOPSIS
 .B idevicedebugserverproxy
-[OPTIONS] PORT
+[OPTIONS] [PORT]
 
 .SH DESCRIPTION
 
@@ -35,6 +35,7 @@
 .TP
 .B PORT
 The port under which the proxy should listen for connections from clients.
+If omitted, the next available port will be used and printed to stdout.
 
 .SH AUTHORS
 Martin Szulecki
diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c
index b190f63..79c2d38 100644
--- a/tools/idevicedebugserverproxy.c
+++ b/tools/idevicedebugserverproxy.c
@@ -44,6 +44,10 @@
 #include <libimobiledevice-glue/socket.h>
 #include <libimobiledevice-glue/thread.h>
 
+#ifndef ETIMEDOUT
+#define ETIMEDOUT 138
+#endif
+
 #define info(...) fprintf(stdout, __VA_ARGS__); fflush(stdout)
 #define debug(...) if(debug_mode) fprintf(stdout, __VA_ARGS__)
 
@@ -76,9 +80,11 @@
 	char *name = NULL;
 
 	name = strrchr(argv[0], '/');
-	printf("Usage: %s [OPTIONS] <PORT>\n", (name ? name + 1: argv[0]));
+	printf("Usage: %s [OPTIONS] [PORT]\n", (name ? name + 1: argv[0]));
 	printf("\n");
 	printf("Proxy debugserver connection from device to a local socket at PORT.\n");
+	printf("If PORT is omitted, the next available port will be used and printed\n");
+	printf("to stdout.\n");
 	printf("\n");
 	printf("OPTIONS:\n");
 	printf("  -u, --udid UDID\ttarget specific device by UDID\n");
@@ -239,13 +245,6 @@
 		}
 	}
 
-	/* a PORT is mandatory */
-	if (!local_port) {
-		fprintf(stderr, "Please specify a PORT.\n");
-		print_usage(argc, argv);
-		goto leave_cleanup;
-	}
-
 	/* start services and connect to device */
 	ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX);
 	if (ret != IDEVICE_E_SUCCESS) {
@@ -266,6 +265,17 @@
 		goto leave_cleanup;
 	}
 
+	if (local_port == 0) {
+		/* The user asked for any available port. Report the actual port. */
+		uint16_t port;
+		if (0 > socket_get_socket_port(server_fd, &port)) {
+			fprintf(stderr, "Could not determine socket port\n");
+			result = EXIT_FAILURE;
+			goto leave_cleanup;
+		}
+		printf("Listening on port %d\n", port);
+	}
+
 	while (!quit_flag) {
 		debug("%s: Waiting for connection on local port %d\n", __func__, local_port);