From 5b3ae2cb2f95a333b3b90253ac959a34d51dd4ea Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 4 Feb 2022 20:49:35 +0100 Subject: [PATCH] Store actual serial in sc_server Before starting the server, the actual device serial (possibly its ip:port if it's over TCP/IP) must be known. A serial might be requested via -s/--serial (stored in the sc_server_params), but the actual serial may change afterwards: - if none is provided, then it is retrieved with "adb get-serialno"; - if --tcpip is requested, then the final serial will be the target ip:port. The requested serial was overwritten by the actual serial in the sc_server_params struct, which was a bit hacky. Instead, store a separate serial field in sc_server (and rename the one from sc_server_params to "req_serial" to avoid confusion). --- app/src/scrcpy.c | 4 +- app/src/server.c | 116 +++++++++++++++++++++++------------------------ app/src/server.h | 3 +- 3 files changed, 60 insertions(+), 63 deletions(-) diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 5da6588c..c846ee18 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -296,7 +296,7 @@ scrcpy(struct scrcpy_options *options) { struct sc_acksync *acksync = NULL; struct sc_server_params params = { - .serial = options->serial, + .req_serial = options->serial, .log_level = options->log_level, .crop = options->crop, .port_range = options->port_range, @@ -355,7 +355,7 @@ scrcpy(struct scrcpy_options *options) { // It is necessarily initialized here, since the device is connected struct sc_server_info *info = &s->server.info; - const char *serial = s->server.params.serial; + const char *serial = s->server.serial; assert(serial); struct sc_file_pusher *fp = NULL; diff --git a/app/src/server.c b/app/src/server.c index 2d4f70b8..e8ae32af 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -65,7 +65,7 @@ get_server_path(void) { static void sc_server_params_destroy(struct sc_server_params *params) { // The server stores a copy of the params provided by the user - free((char *) params->serial); + free((char *) params->req_serial); free((char *) params->crop); free((char *) params->codec_options); free((char *) params->encoder_name); @@ -89,7 +89,7 @@ sc_server_params_copy(struct sc_server_params *dst, } \ } - COPY(serial); + COPY(req_serial); COPY(crop); COPY(codec_options); COPY(encoder_name); @@ -157,7 +157,7 @@ execute_server(struct sc_server *server, const struct sc_server_params *params) { sc_pid pid = SC_PROCESS_NONE; - const char *serial = params->serial; + const char *serial = server->serial; assert(serial); const char *cmd[128]; @@ -353,6 +353,7 @@ sc_server_init(struct sc_server *server, const struct sc_server_params *params, return false; } + server->serial = NULL; server->stopped = false; server->video_socket = SC_SOCKET_NONE; @@ -397,7 +398,9 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) { assert(tunnel->enabled); - const char *serial = server->params.serial; + const char *serial = server->serial; + assert(serial); + bool control = server->params.control; sc_socket video_socket = SC_SOCKET_NONE; @@ -500,30 +503,25 @@ sc_server_on_terminated(void *userdata) { LOGD("Server terminated"); } -static bool -sc_server_fill_serial(struct sc_server *server) { - // Retrieve the actual device immediately if not provided, so that all - // future adb commands are executed for this specific device, even if other - // devices are connected afterwards (without "more than one - // device/emulator" error) - if (!server->params.serial) { - // The serial is owned by sc_server_params, and will be freed on destroy - server->params.serial = sc_adb_get_serialno(&server->intr, 0); - if (!server->params.serial) { - LOGE("Could not get device serial"); - return false; +static char * +sc_server_read_serial(struct sc_server *server) { + char *serial; + if (server->params.req_serial) { + // The serial is already known + serial = strdup(server->params.req_serial); + if (!serial) { + LOG_OOM(); } - - LOGD("Device serial: %s", server->params.serial); + } else { + serial = sc_adb_get_serialno(&server->intr, 0); } - return true; + return serial; } static bool -is_tcpip_mode_enabled(struct sc_server *server) { +is_tcpip_mode_enabled(struct sc_server *server, const char *serial) { struct sc_intr *intr = &server->intr; - const char *serial = server->params.serial; char *current_port = sc_adb_getprop(intr, serial, "service.adb.tcp.port", SC_ADB_SILENT); @@ -538,9 +536,9 @@ is_tcpip_mode_enabled(struct sc_server *server) { } static bool -wait_tcpip_mode_enabled(struct sc_server *server, unsigned attempts, - sc_tick delay) { - if (is_tcpip_mode_enabled(server)) { +wait_tcpip_mode_enabled(struct sc_server *server, const char *serial, + unsigned attempts, sc_tick delay) { + if (is_tcpip_mode_enabled(server, serial)) { LOGI("TCP/IP mode enabled"); return true; } @@ -555,7 +553,7 @@ wait_tcpip_mode_enabled(struct sc_server *server, unsigned attempts, return false; } - if (is_tcpip_mode_enabled(server)) { + if (is_tcpip_mode_enabled(server, serial)) { LOGI("TCP/IP mode enabled"); return true; } @@ -581,12 +579,13 @@ append_port_5555(const char *ip) { } static char * -sc_server_switch_to_tcpip(struct sc_server *server) { - const char *serial = server->params.serial; +sc_server_switch_to_tcpip(struct sc_server *server, const char *serial) { assert(serial); struct sc_intr *intr = &server->intr; + LOGI("Switching device %s to TCP/IP...", serial); + char *ip = sc_adb_get_device_ip(intr, serial, 0); if (!ip) { LOGE("Device IP not found"); @@ -599,7 +598,7 @@ sc_server_switch_to_tcpip(struct sc_server *server) { return NULL; } - bool tcp_mode = is_tcpip_mode_enabled(server); + bool tcp_mode = is_tcpip_mode_enabled(server, serial); if (!tcp_mode) { bool ok = sc_adb_tcpip(intr, serial, 5555, SC_ADB_NO_STDOUT); @@ -610,7 +609,7 @@ sc_server_switch_to_tcpip(struct sc_server *server) { unsigned attempts = 40; sc_tick delay = SC_TICK_FROM_MS(250); - ok = wait_tcpip_mode_enabled(server, attempts, delay); + ok = wait_tcpip_mode_enabled(server, serial, attempts, delay); if (!ok) { goto error; } @@ -630,20 +629,14 @@ sc_server_connect_to_tcpip(struct sc_server *server, const char *ip_port) { // Error expected if not connected, do not report any error sc_adb_disconnect(intr, ip_port, SC_ADB_SILENT); + LOGI("Connecting to %s...", ip_port); + bool ok = sc_adb_connect(intr, ip_port, 0); if (!ok) { LOGE("Could not connect to %s", ip_port); return false; } - // Override the serial, owned by the sc_server_params - free((void *) server->params.serial); - server->params.serial = strdup(ip_port); - if (!server->params.serial) { - LOG_OOM(); - return false; - } - LOGI("Connected to %s", ip_port); return true; } @@ -657,7 +650,7 @@ sc_server_configure_tcpip(struct sc_server *server) { // If tcpip parameter is given, then it must connect to this address. // Therefore, the device is unknown, so serial is meaningless at this point. - assert(!params->serial || !params->tcpip_dst); + assert(!params->req_serial || !params->tcpip_dst); if (params->tcpip_dst) { // Append ":5555" if no port is present @@ -671,30 +664,32 @@ sc_server_configure_tcpip(struct sc_server *server) { } else { // The device IP address must be retrieved from the current // connected device - if (!sc_server_fill_serial(server)) { + char *serial = sc_server_read_serial(server); + if (!serial) { + LOGE("Could not get device serial"); return false; } // The serial is either the real serial when connected via USB, or // the IP:PORT when connected over TCP/IP. Only the latter contains // a colon. - bool is_already_tcpip = strchr(params->serial, ':'); + bool is_already_tcpip = strchr(serial, ':'); if (is_already_tcpip) { // Nothing to do - LOGI("Device already connected via TCP/IP: %s", params->serial); + LOGI("Device already connected via TCP/IP: %s", serial); + free(serial); return true; } - ip_port = sc_server_switch_to_tcpip(server); + ip_port = sc_server_switch_to_tcpip(server, serial); + free(serial); if (!ip_port) { return false; } } - // On success, this call changes params->serial - bool ok = sc_server_connect_to_tcpip(server, ip_port); - free(ip_port); - return ok; + server->serial = ip_port; + return sc_server_connect_to_tcpip(server, ip_port); } static int @@ -703,30 +698,30 @@ run_server(void *data) { const struct sc_server_params *params = &server->params; - if (params->serial) { - LOGD("Device serial: %s", params->serial); - } - if (params->tcpip) { - // params->serial may be changed after this call bool ok = sc_server_configure_tcpip(server); if (!ok) { goto error_connection_failed; } + assert(server->serial); + } else { + server->serial = sc_server_read_serial(server); + if (!server->serial) { + LOGD("Could not get device serial"); + goto error_connection_failed; + } } - // It is ok to call this function even if the device serial has been - // changed by switching over TCP/IP - if (!sc_server_fill_serial(server)) { - goto error_connection_failed; - } + const char *serial = server->serial; + assert(serial); + LOGD("Device serial: %s", serial); - bool ok = push_server(&server->intr, params->serial); + bool ok = push_server(&server->intr, serial); if (!ok) { goto error_connection_failed; } - ok = sc_adb_tunnel_open(&server->tunnel, &server->intr, params->serial, + ok = sc_adb_tunnel_open(&server->tunnel, &server->intr, serial, params->port_range, params->force_adb_forward); if (!ok) { goto error_connection_failed; @@ -735,7 +730,7 @@ run_server(void *data) { // server will connect to our server socket sc_pid pid = execute_server(server, params); if (pid == SC_PROCESS_NONE) { - sc_adb_tunnel_close(&server->tunnel, &server->intr, params->serial); + sc_adb_tunnel_close(&server->tunnel, &server->intr, serial); goto error_connection_failed; } @@ -747,7 +742,7 @@ run_server(void *data) { if (!ok) { sc_process_terminate(pid); sc_process_wait(pid, true); // ignore exit code - sc_adb_tunnel_close(&server->tunnel, &server->intr, params->serial); + sc_adb_tunnel_close(&server->tunnel, &server->intr, serial); goto error_connection_failed; } @@ -840,6 +835,7 @@ sc_server_destroy(struct sc_server *server) { net_close(server->control_socket); } + free(server->serial); sc_server_params_destroy(&server->params); sc_intr_destroy(&server->intr); sc_cond_destroy(&server->cond_stopped); diff --git a/app/src/server.h b/app/src/server.h index 1dff19a7..c2293118 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -22,7 +22,7 @@ struct sc_server_info { }; struct sc_server_params { - const char *serial; + const char *req_serial; enum sc_log_level log_level; const char *crop; const char *codec_options; @@ -49,6 +49,7 @@ struct sc_server_params { struct sc_server { // The internal allocated strings are copies owned by the server struct sc_server_params params; + char *serial; sc_thread thread; struct sc_server_info info; // initialized once connected