diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..dacd17e0e5 --- /dev/null +++ b/.clang-format @@ -0,0 +1,4 @@ +UseTab: Never +TabWidth: 4 +IndentWidth: 4 +AlwaysBreakAfterReturnType: AllDefinitions diff --git a/app/meson.build b/app/meson.build index 4894babc9f..7545cc751a 100644 --- a/app/meson.build +++ b/app/meson.build @@ -137,6 +137,12 @@ foreach f : check_functions endif endforeach +if host_machine.system() == 'windows' or get_option('crossbuild_windows') + # Set the windows version higher than mingw default, needed for inet_pton on windows + add_global_arguments('-D_WIN32_WINNT=0x0600', language : 'c') + add_global_arguments('-DWINVER=0x0600', language : 'c') +endif + # the version, updated on release conf.set_quoted('SCRCPY_VERSION', meson.project_version()) diff --git a/app/src/cli.c b/app/src/cli.c index 1550c70638..03de3aae7e 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -13,6 +13,14 @@ #include "util/strbuf.h" #include "util/term.h" +#ifdef __WINDOWS__ +#include +#include +#else +#include +#include +#endif + #define STR_IMPL_(x) #x #define STR(x) STR_IMPL_(x) @@ -46,6 +54,8 @@ #define OPT_V4L2_SINK 1027 #define OPT_DISPLAY_BUFFER 1028 #define OPT_V4L2_BUFFER 1029 +#define OPT_TUNNEL_HOST 1030 +#define OPT_TUNNEL_PORT 1031 struct sc_option { char shortopt; @@ -239,6 +249,20 @@ static const struct sc_option options[] = { "Default is " STR(DEFAULT_LOCAL_PORT_RANGE_FIRST) ":" STR(DEFAULT_LOCAL_PORT_RANGE_LAST) ".", }, + { + .longopt_id = OPT_TUNNEL_HOST, + .longopt = "tunnel-host", + .argdesc = "host", + .text = "Set the remote IP address of the scrcpy server.\n" + "This option is only valid with --force-adb-forward.", + }, + { + .longopt_id = OPT_TUNNEL_PORT, + .longopt = "tunnel-port", + .argdesc = "port", + .text = "Set the remote TCP port of the scrcpy server.\n" + "This option is only valid with --force-adb-forward.", + }, { .longopt_id = OPT_POWER_OFF_ON_CLOSE, .longopt = "power-off-on-close", @@ -1123,6 +1147,27 @@ parse_record_format(const char *optarg, enum sc_record_format *format) { return false; } +static bool +parse_ip(const char *optarg, uint32_t *ipv4) { + struct in_addr conv; + if (!inet_pton(AF_INET, optarg, &conv)) { + LOGE("IP address is invalid: %s", optarg); + return false; + } + *ipv4 = ntohl(conv.s_addr); + return true; +} + +static bool +parse_port(const char *optarg, uint16_t *port) { + long value; + if (!parse_integer_arg(optarg, &value, false, 1, 0xFFFF, "tunnel port")) { + return false; + } + *port = (uint16_t)value; + return true; +} + static enum sc_record_format guess_record_format(const char *filename) { size_t len = strlen(filename); @@ -1195,6 +1240,16 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[], return false; } break; + case OPT_TUNNEL_HOST: + if (!parse_ip(optarg, &opts->scrcpy_ip)) { + return false; + } + break; + case OPT_TUNNEL_PORT: + if (!parse_port(optarg, &opts->scrcpy_port)) { + return false; + } + break; case 'n': opts->control = false; break; diff --git a/app/src/options.c b/app/src/options.c index 82f2534290..ae75899593 100644 --- a/app/src/options.c +++ b/app/src/options.c @@ -19,6 +19,8 @@ const struct scrcpy_options scrcpy_options_default = { .first = DEFAULT_LOCAL_PORT_RANGE_FIRST, .last = DEFAULT_LOCAL_PORT_RANGE_LAST, }, + .scrcpy_ip = 0, + .scrcpy_port = 0, .shortcut_mods = { .data = {SC_MOD_LALT, SC_MOD_LSUPER}, .count = 2, diff --git a/app/src/options.h b/app/src/options.h index 434225b94c..8408aca36f 100644 --- a/app/src/options.h +++ b/app/src/options.h @@ -77,6 +77,8 @@ struct scrcpy_options { enum sc_record_format record_format; enum sc_keyboard_input_mode keyboard_input_mode; struct sc_port_range port_range; + uint32_t scrcpy_ip; + uint16_t scrcpy_port; struct sc_shortcut_mods shortcut_mods; uint16_t max_size; uint32_t bit_rate; diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 9643b04e2e..ca757bb66f 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -345,6 +345,8 @@ scrcpy(struct scrcpy_options *options) { .log_level = options->log_level, .crop = options->crop, .port_range = options->port_range, + .scrcpy_ip = options->scrcpy_ip, + .scrcpy_port = options->scrcpy_port, .max_size = options->max_size, .bit_rate = options->bit_rate, .max_fps = options->max_fps, diff --git a/app/src/server.c b/app/src/server.c index d792364dc5..a2e848df99 100644 --- a/app/src/server.c +++ b/app/src/server.c @@ -202,8 +202,8 @@ execute_server(struct sc_server *server, } static bool -connect_and_read_byte(struct sc_intr *intr, sc_socket socket, uint16_t port) { - bool ok = net_connect_intr(intr, socket, IPV4_LOCALHOST, port); +connect_and_read_byte(struct sc_intr *intr, sc_socket socket, uint32_t ip, uint16_t port) { + bool ok = net_connect_intr(intr, socket, ip, port); if (!ok) { return false; } @@ -220,13 +220,12 @@ connect_and_read_byte(struct sc_intr *intr, sc_socket socket, uint16_t port) { } static sc_socket -connect_to_server(struct sc_server *server, uint32_t attempts, sc_tick delay) { - uint16_t port = server->tunnel.local_port; +connect_to_server(struct sc_server *server, uint32_t attempts, sc_tick delay, uint32_t ip, uint16_t port) { do { LOGD("Remaining connection attempts: %d", (int) attempts); sc_socket socket = net_socket(); if (socket != SC_SOCKET_NONE) { - bool ok = connect_and_read_byte(&server->intr, socket, port); + bool ok = connect_and_read_byte(&server->intr, socket, ip, port); if (ok) { // it worked! return socket; @@ -352,9 +351,23 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) { goto fail; } } else { + uint32_t ip; + if (server->params.scrcpy_ip) { + ip = server->params.scrcpy_ip; + } else { + ip = IPV4_LOCALHOST; + } + + uint16_t port; + if (server->params.scrcpy_port) { + port = server->params.scrcpy_port; + } else { + port = tunnel->local_port; + } + uint32_t attempts = 100; sc_tick delay = SC_TICK_FROM_MS(100); - video_socket = connect_to_server(server, attempts, delay); + video_socket = connect_to_server(server, attempts, delay, ip, port); if (video_socket == SC_SOCKET_NONE) { goto fail; } @@ -365,7 +378,7 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) { goto fail; } bool ok = net_connect_intr(&server->intr, control_socket, - IPV4_LOCALHOST, tunnel->local_port); + ip, port); if (!ok) { goto fail; } diff --git a/app/src/server.h b/app/src/server.h index 3859c328df..e6945ba358 100644 --- a/app/src/server.h +++ b/app/src/server.h @@ -29,6 +29,8 @@ struct sc_server_params { const char *codec_options; const char *encoder_name; struct sc_port_range port_range; + uint32_t scrcpy_ip; + uint16_t scrcpy_port; uint16_t max_size; uint32_t bit_rate; uint16_t max_fps;