Add option for remote scrcpy connection

This commit is contained in:
RipleyTom 2021-11-18 01:02:53 +01:00
commit 7e5a1d5b7a
7 changed files with 89 additions and 7 deletions

View file

@ -137,6 +137,12 @@ foreach f : check_functions
endif endif
endforeach 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 # the version, updated on release
conf.set_quoted('SCRCPY_VERSION', meson.project_version()) conf.set_quoted('SCRCPY_VERSION', meson.project_version())

View file

@ -13,6 +13,14 @@
#include "util/strbuf.h" #include "util/strbuf.h"
#include "util/term.h" #include "util/term.h"
#ifdef __WINDOWS__
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#define STR_IMPL_(x) #x #define STR_IMPL_(x) #x
#define STR(x) STR_IMPL_(x) #define STR(x) STR_IMPL_(x)
@ -46,6 +54,8 @@
#define OPT_V4L2_SINK 1027 #define OPT_V4L2_SINK 1027
#define OPT_DISPLAY_BUFFER 1028 #define OPT_DISPLAY_BUFFER 1028
#define OPT_V4L2_BUFFER 1029 #define OPT_V4L2_BUFFER 1029
#define OPT_TUNNEL_HOST 1030
#define OPT_TUNNEL_PORT 1031
struct sc_option { struct sc_option {
char shortopt; char shortopt;
@ -239,6 +249,20 @@ static const struct sc_option options[] = {
"Default is " STR(DEFAULT_LOCAL_PORT_RANGE_FIRST) ":" "Default is " STR(DEFAULT_LOCAL_PORT_RANGE_FIRST) ":"
STR(DEFAULT_LOCAL_PORT_RANGE_LAST) ".", 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_id = OPT_POWER_OFF_ON_CLOSE,
.longopt = "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; 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 static enum sc_record_format
guess_record_format(const char *filename) { guess_record_format(const char *filename) {
size_t len = strlen(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; return false;
} }
break; 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': case 'n':
opts->control = false; opts->control = false;
break; break;

View file

@ -19,6 +19,8 @@ const struct scrcpy_options scrcpy_options_default = {
.first = DEFAULT_LOCAL_PORT_RANGE_FIRST, .first = DEFAULT_LOCAL_PORT_RANGE_FIRST,
.last = DEFAULT_LOCAL_PORT_RANGE_LAST, .last = DEFAULT_LOCAL_PORT_RANGE_LAST,
}, },
.scrcpy_ip = 0,
.scrcpy_port = 0,
.shortcut_mods = { .shortcut_mods = {
.data = {SC_MOD_LALT, SC_MOD_LSUPER}, .data = {SC_MOD_LALT, SC_MOD_LSUPER},
.count = 2, .count = 2,

View file

@ -77,6 +77,8 @@ struct scrcpy_options {
enum sc_record_format record_format; enum sc_record_format record_format;
enum sc_keyboard_input_mode keyboard_input_mode; enum sc_keyboard_input_mode keyboard_input_mode;
struct sc_port_range port_range; struct sc_port_range port_range;
uint32_t scrcpy_ip;
uint16_t scrcpy_port;
struct sc_shortcut_mods shortcut_mods; struct sc_shortcut_mods shortcut_mods;
uint16_t max_size; uint16_t max_size;
uint32_t bit_rate; uint32_t bit_rate;

View file

@ -345,6 +345,8 @@ scrcpy(struct scrcpy_options *options) {
.log_level = options->log_level, .log_level = options->log_level,
.crop = options->crop, .crop = options->crop,
.port_range = options->port_range, .port_range = options->port_range,
.scrcpy_ip = options->scrcpy_ip,
.scrcpy_port = options->scrcpy_port,
.max_size = options->max_size, .max_size = options->max_size,
.bit_rate = options->bit_rate, .bit_rate = options->bit_rate,
.max_fps = options->max_fps, .max_fps = options->max_fps,

View file

@ -202,8 +202,8 @@ execute_server(struct sc_server *server,
} }
static bool static bool
connect_and_read_byte(struct sc_intr *intr, sc_socket socket, uint16_t 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, IPV4_LOCALHOST, port); bool ok = net_connect_intr(intr, socket, ip, port);
if (!ok) { if (!ok) {
return false; return false;
} }
@ -220,13 +220,12 @@ connect_and_read_byte(struct sc_intr *intr, sc_socket socket, uint16_t port) {
} }
static sc_socket static sc_socket
connect_to_server(struct sc_server *server, uint32_t attempts, sc_tick delay) { connect_to_server(struct sc_server *server, uint32_t attempts, sc_tick delay, uint32_t ip, uint16_t port) {
uint16_t port = server->tunnel.local_port;
do { do {
LOGD("Remaining connection attempts: %d", (int) attempts); LOGD("Remaining connection attempts: %d", (int) attempts);
sc_socket socket = net_socket(); sc_socket socket = net_socket();
if (socket != SC_SOCKET_NONE) { 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) { if (ok) {
// it worked! // it worked!
return socket; return socket;
@ -352,9 +351,23 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
goto fail; goto fail;
} }
} else { } 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; uint32_t attempts = 100;
sc_tick delay = SC_TICK_FROM_MS(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) { if (video_socket == SC_SOCKET_NONE) {
goto fail; goto fail;
} }
@ -365,7 +378,7 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
goto fail; goto fail;
} }
bool ok = net_connect_intr(&server->intr, control_socket, bool ok = net_connect_intr(&server->intr, control_socket,
IPV4_LOCALHOST, tunnel->local_port); ip, port);
if (!ok) { if (!ok) {
goto fail; goto fail;
} }

View file

@ -29,6 +29,8 @@ struct sc_server_params {
const char *codec_options; const char *codec_options;
const char *encoder_name; const char *encoder_name;
struct sc_port_range port_range; struct sc_port_range port_range;
uint32_t scrcpy_ip;
uint16_t scrcpy_port;
uint16_t max_size; uint16_t max_size;
uint32_t bit_rate; uint32_t bit_rate;
uint16_t max_fps; uint16_t max_fps;