Compare commits

..

4 Commits

Author SHA1 Message Date
Romain Vimont
e48bbb3c2c Log server pushed
Now that "adb push" stdout is disabled, add a log to notify server
pushed.
2021-11-19 22:27:01 +01:00
Romain Vimont
36c0d6864c explicit_inherit 2021-11-19 22:27:01 +01:00
Romain Vimont
88e9c2b4af process_inherit 2021-11-19 22:27:01 +01:00
Romain Vimont
c96dc6d2c4 Simplify Windows process inheritance configuration
Merge if-blocks together.
2021-11-19 22:27:01 +01:00
19 changed files with 175 additions and 267 deletions

View File

@@ -412,47 +412,12 @@ autoadb scrcpy -s '{}'
[AutoAdb]: https://github.com/rom1v/autoadb [AutoAdb]: https://github.com/rom1v/autoadb
#### Tunnels #### SSH tunnel
To connect to a remote device, it is possible to connect a local `adb` client to To connect to a remote device, it is possible to connect a local `adb` client to
a remote `adb` server (provided they use the same version of the _adb_ a remote `adb` server (provided they use the same version of the _adb_
protocol). protocol).
##### Remote ADB server
To connect to a remote ADB server, make the server listen on all interfaces:
```bash
adb kill-server
adb -a nodaemon server start
# keep this open
```
**Warning: all communications between clients and ADB server are unencrypted.**
Suppose that this server is accessible at 192.168.1.2. Then, from another
terminal, run scrcpy:
```bash
export ADB_SERVER_SOCKET=tcp:192.168.1.2:5037
scrcpy --tunnel-host=192.168.1.2
```
By default, scrcpy uses the local port used for `adb forward` tunnel
establishment (typically `27183`, see `--port`). It is also possible to force a
different tunnel port (it may be useful in more complex situations, when more
redirections are involved):
```
scrcpy --tunnel-port=1234
```
##### SSH tunnel
To communicate with a remote ADB server securely, it is preferable to use a SSH
tunnel.
First, make sure the ADB server is running on the remote computer: First, make sure the ADB server is running on the remote computer:
```bash ```bash

View File

@@ -199,7 +199,6 @@ if get_option('buildtype') == 'debug'
'tests/test_cli.c', 'tests/test_cli.c',
'src/cli.c', 'src/cli.c',
'src/options.c', 'src/options.c',
'src/util/net.c',
'src/util/str.c', 'src/util/str.c',
'src/util/strbuf.c', 'src/util/strbuf.c',
'src/util/term.c', 'src/util/term.c',

View File

@@ -203,18 +203,6 @@ Enable "show touches" on start, restore the initial value on exit.
It only shows physical touches (not clicks from scrcpy). It only shows physical touches (not clicks from scrcpy).
.TP
.BI "\-\-tunnel\-host " ip
Set the IP address of the adb tunnel to reach the scrcpy server. This option automatically enables --force-adb-forward.
Default is localhost.
.TP
.BI "\-\-tunnel\-port " port
Set the TCP port of the adb tunnel to reach the scrcpy server. This option automatically enables --force-adb-forward.
Default is 0 (not forced): the local port used for establishing the tunnel will be used.
.TP .TP
.BI "\-\-v4l2-sink " /dev/videoN .BI "\-\-v4l2-sink " /dev/videoN
Output to v4l2loopback device. Output to v4l2loopback device.

View File

@@ -112,7 +112,7 @@ show_adb_err_msg(enum sc_process_result err, const char *const argv[]) {
static sc_pid static sc_pid
adb_execute_p(const char *serial, const char *const adb_cmd[], adb_execute_p(const char *serial, const char *const adb_cmd[],
size_t len, sc_pipe *pout) { size_t len, unsigned inherit, sc_pipe *pout) {
int i; int i;
sc_pid pid; sc_pid pid;
@@ -133,7 +133,7 @@ adb_execute_p(const char *serial, const char *const adb_cmd[],
memcpy(&argv[i], adb_cmd, len * sizeof(const char *)); memcpy(&argv[i], adb_cmd, len * sizeof(const char *));
argv[len + i] = NULL; argv[len + i] = NULL;
enum sc_process_result r = enum sc_process_result r =
sc_process_execute_p(argv, &pid, NULL, pout, NULL); sc_process_execute_p(argv, &pid, inherit, NULL, pout, NULL);
if (r != SC_PROCESS_SUCCESS) { if (r != SC_PROCESS_SUCCESS) {
show_adb_err_msg(r, argv); show_adb_err_msg(r, argv);
pid = SC_PROCESS_NONE; pid = SC_PROCESS_NONE;
@@ -144,50 +144,54 @@ adb_execute_p(const char *serial, const char *const adb_cmd[],
} }
sc_pid sc_pid
adb_execute(const char *serial, const char *const adb_cmd[], size_t len) { adb_execute(const char *serial, const char *const adb_cmd[], size_t len,
return adb_execute_p(serial, adb_cmd, len, NULL); unsigned inherit) {
return adb_execute_p(serial, adb_cmd, len, inherit, NULL);
} }
static sc_pid static sc_pid
adb_exec_forward(const char *serial, uint16_t local_port, adb_exec_forward(const char *serial, uint16_t local_port,
const char *device_socket_name) { const char *device_socket_name, unsigned inherit) {
char local[4 + 5 + 1]; // tcp:PORT char local[4 + 5 + 1]; // tcp:PORT
char remote[108 + 14 + 1]; // localabstract:NAME char remote[108 + 14 + 1]; // localabstract:NAME
sprintf(local, "tcp:%" PRIu16, local_port); sprintf(local, "tcp:%" PRIu16, local_port);
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name); snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
const char *const adb_cmd[] = {"forward", local, remote}; const char *const adb_cmd[] = {"forward", local, remote};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
} }
static sc_pid static sc_pid
adb_exec_forward_remove(const char *serial, uint16_t local_port) { adb_exec_forward_remove(const char *serial, uint16_t local_port,
unsigned inherit) {
char local[4 + 5 + 1]; // tcp:PORT char local[4 + 5 + 1]; // tcp:PORT
sprintf(local, "tcp:%" PRIu16, local_port); sprintf(local, "tcp:%" PRIu16, local_port);
const char *const adb_cmd[] = {"forward", "--remove", local}; const char *const adb_cmd[] = {"forward", "--remove", local};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
} }
static sc_pid static sc_pid
adb_exec_reverse(const char *serial, const char *device_socket_name, adb_exec_reverse(const char *serial, const char *device_socket_name,
uint16_t local_port) { uint16_t local_port, unsigned inherit) {
char local[4 + 5 + 1]; // tcp:PORT char local[4 + 5 + 1]; // tcp:PORT
char remote[108 + 14 + 1]; // localabstract:NAME char remote[108 + 14 + 1]; // localabstract:NAME
sprintf(local, "tcp:%" PRIu16, local_port); sprintf(local, "tcp:%" PRIu16, local_port);
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name); snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
const char *const adb_cmd[] = {"reverse", remote, local}; const char *const adb_cmd[] = {"reverse", remote, local};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
} }
static sc_pid static sc_pid
adb_exec_reverse_remove(const char *serial, const char *device_socket_name) { adb_exec_reverse_remove(const char *serial, const char *device_socket_name,
unsigned inherit) {
char remote[108 + 14 + 1]; // localabstract:NAME char remote[108 + 14 + 1]; // localabstract:NAME
snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name); snprintf(remote, sizeof(remote), "localabstract:%s", device_socket_name);
const char *const adb_cmd[] = {"reverse", "--remove", remote}; const char *const adb_cmd[] = {"reverse", "--remove", remote};
return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); return adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
} }
static sc_pid static sc_pid
adb_exec_push(const char *serial, const char *local, const char *remote) { adb_exec_push(const char *serial, const char *local, const char *remote,
unsigned inherit) {
#ifdef __WINDOWS__ #ifdef __WINDOWS__
// Windows will parse the string, so the paths must be quoted // Windows will parse the string, so the paths must be quoted
// (see sys/win/command.c) // (see sys/win/command.c)
@@ -203,7 +207,7 @@ adb_exec_push(const char *serial, const char *local, const char *remote) {
#endif #endif
const char *const adb_cmd[] = {"push", local, remote}; const char *const adb_cmd[] = {"push", local, remote};
sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
#ifdef __WINDOWS__ #ifdef __WINDOWS__
free((void *) remote); free((void *) remote);
@@ -214,7 +218,7 @@ adb_exec_push(const char *serial, const char *local, const char *remote) {
} }
static sc_pid static sc_pid
adb_exec_install(const char *serial, const char *local) { adb_exec_install(const char *serial, const char *local, unsigned inherit) {
#ifdef __WINDOWS__ #ifdef __WINDOWS__
// Windows will parse the string, so the local name must be quoted // Windows will parse the string, so the local name must be quoted
// (see sys/win/command.c) // (see sys/win/command.c)
@@ -225,7 +229,7 @@ adb_exec_install(const char *serial, const char *local) {
#endif #endif
const char *const adb_cmd[] = {"install", "-r", local}; const char *const adb_cmd[] = {"install", "-r", local};
sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd)); sc_pid pid = adb_execute(serial, adb_cmd, ARRAY_LEN(adb_cmd), inherit);
#ifdef __WINDOWS__ #ifdef __WINDOWS__
free((void *) local); free((void *) local);
@@ -235,58 +239,62 @@ adb_exec_install(const char *serial, const char *local) {
} }
static sc_pid static sc_pid
adb_exec_get_serialno(sc_pipe *pout) { adb_exec_get_serialno(unsigned inherit, sc_pipe *pout) {
const char *const adb_cmd[] = {"get-serialno"}; const char *const adb_cmd[] = {"get-serialno"};
return adb_execute_p(NULL, adb_cmd, ARRAY_LEN(adb_cmd), pout); return adb_execute_p(NULL, adb_cmd, ARRAY_LEN(adb_cmd), inherit, pout);
} }
bool bool
adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port, adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port,
const char *device_socket_name) { const char *device_socket_name, unsigned inherit) {
sc_pid pid = adb_exec_forward(serial, local_port, device_socket_name); sc_pid pid =
adb_exec_forward(serial, local_port, device_socket_name, inherit);
return sc_process_check_success_intr(intr, pid, "adb forward", true); return sc_process_check_success_intr(intr, pid, "adb forward", true);
} }
bool bool
adb_forward_remove(struct sc_intr *intr, const char *serial, adb_forward_remove(struct sc_intr *intr, const char *serial,
uint16_t local_port) { uint16_t local_port, unsigned inherit) {
sc_pid pid = adb_exec_forward_remove(serial, local_port); sc_pid pid = adb_exec_forward_remove(serial, local_port, inherit);
return sc_process_check_success_intr(intr, pid, "adb forward --remove", return sc_process_check_success_intr(intr, pid, "adb forward --remove",
true); true);
} }
bool bool
adb_reverse(struct sc_intr *intr, const char *serial, adb_reverse(struct sc_intr *intr, const char *serial,
const char *device_socket_name, uint16_t local_port) { const char *device_socket_name, uint16_t local_port,
sc_pid pid = adb_exec_reverse(serial, device_socket_name, local_port); unsigned inherit) {
sc_pid pid =
adb_exec_reverse(serial, device_socket_name, local_port, inherit);
return sc_process_check_success_intr(intr, pid, "adb reverse", true); return sc_process_check_success_intr(intr, pid, "adb reverse", true);
} }
bool bool
adb_reverse_remove(struct sc_intr *intr, const char *serial, adb_reverse_remove(struct sc_intr *intr, const char *serial,
const char *device_socket_name) { const char *device_socket_name, unsigned inherit) {
sc_pid pid = adb_exec_reverse_remove(serial, device_socket_name); sc_pid pid = adb_exec_reverse_remove(serial, device_socket_name, inherit);
return sc_process_check_success_intr(intr, pid, "adb reverse --remove", return sc_process_check_success_intr(intr, pid, "adb reverse --remove",
true); true);
} }
bool bool
adb_push(struct sc_intr *intr, const char *serial, const char *local, adb_push(struct sc_intr *intr, const char *serial, const char *local,
const char *remote) { const char *remote, unsigned inherit) {
sc_pid pid = adb_exec_push(serial, local, remote); sc_pid pid = adb_exec_push(serial, local, remote, inherit);
return sc_process_check_success_intr(intr, pid, "adb push", true); return sc_process_check_success_intr(intr, pid, "adb push", true);
} }
bool bool
adb_install(struct sc_intr *intr, const char *serial, const char *local) { adb_install(struct sc_intr *intr, const char *serial, const char *local,
sc_pid pid = adb_exec_install(serial, local); unsigned inherit) {
sc_pid pid = adb_exec_install(serial, local, inherit);
return sc_process_check_success_intr(intr, pid, "adb install", true); return sc_process_check_success_intr(intr, pid, "adb install", true);
} }
char * char *
adb_get_serialno(struct sc_intr *intr) { adb_get_serialno(struct sc_intr *intr, unsigned inherit) {
sc_pipe pout; sc_pipe pout;
sc_pid pid = adb_exec_get_serialno(&pout); sc_pid pid = adb_exec_get_serialno(inherit, &pout);
if (pid == SC_PROCESS_NONE) { if (pid == SC_PROCESS_NONE) {
LOGE("Could not execute \"adb get-serialno\""); LOGE("Could not execute \"adb get-serialno\"");
return NULL; return NULL;

View File

@@ -9,30 +9,33 @@
#include "util/intr.h" #include "util/intr.h"
sc_pid sc_pid
adb_execute(const char *serial, const char *const adb_cmd[], size_t len); adb_execute(const char *serial, const char *const adb_cmd[], size_t len,
unsigned inherit);
bool bool
adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port, adb_forward(struct sc_intr *intr, const char *serial, uint16_t local_port,
const char *device_socket_name); const char *device_socket_name, unsigned inherit);
bool bool
adb_forward_remove(struct sc_intr *intr, const char *serial, adb_forward_remove(struct sc_intr *intr, const char *serial,
uint16_t local_port); uint16_t local_port, unsigned inherit);
bool bool
adb_reverse(struct sc_intr *intr, const char *serial, adb_reverse(struct sc_intr *intr, const char *serial,
const char *device_socket_name, uint16_t local_port); const char *device_socket_name, uint16_t local_port,
unsigned inherit);
bool bool
adb_reverse_remove(struct sc_intr *intr, const char *serial, adb_reverse_remove(struct sc_intr *intr, const char *serial,
const char *device_socket_name); const char *device_socket_name, unsigned inherit);
bool bool
adb_push(struct sc_intr *intr, const char *serial, const char *local, adb_push(struct sc_intr *intr, const char *serial, const char *local,
const char *remote); const char *remote, unsigned inherit);
bool bool
adb_install(struct sc_intr *intr, const char *serial, const char *local); adb_install(struct sc_intr *intr, const char *serial, const char *local,
unsigned inherit);
/** /**
* Execute `adb get-serialno` * Execute `adb get-serialno`
@@ -40,6 +43,6 @@ adb_install(struct sc_intr *intr, const char *serial, const char *local);
* Return the result, to be freed by the caller, or NULL on error. * Return the result, to be freed by the caller, or NULL on error.
*/ */
char * char *
adb_get_serialno(struct sc_intr *intr); adb_get_serialno(struct sc_intr *intr, unsigned inherit);
#endif #endif

View File

@@ -20,7 +20,8 @@ enable_tunnel_reverse_any_port(struct sc_adb_tunnel *tunnel,
struct sc_port_range port_range) { struct sc_port_range port_range) {
uint16_t port = port_range.first; uint16_t port = port_range.first;
for (;;) { for (;;) {
if (!adb_reverse(intr, serial, SC_SOCKET_NAME, port)) { if (!adb_reverse(intr, serial, SC_SOCKET_NAME, port,
SC_INHERIT_STDERR)) {
// the command itself failed, it will fail on any port // the command itself failed, it will fail on any port
return false; return false;
} }
@@ -51,7 +52,8 @@ enable_tunnel_reverse_any_port(struct sc_adb_tunnel *tunnel,
} }
// failure, disable tunnel and try another port // failure, disable tunnel and try another port
if (!adb_reverse_remove(intr, serial, SC_SOCKET_NAME)) { if (!adb_reverse_remove(intr, serial, SC_SOCKET_NAME,
SC_INHERIT_STDERR)) {
LOGW("Could not remove reverse tunnel on port %" PRIu16, port); LOGW("Could not remove reverse tunnel on port %" PRIu16, port);
} }
@@ -81,7 +83,8 @@ enable_tunnel_forward_any_port(struct sc_adb_tunnel *tunnel,
uint16_t port = port_range.first; uint16_t port = port_range.first;
for (;;) { for (;;) {
if (adb_forward(intr, serial, port, SC_SOCKET_NAME)) { if (adb_forward(intr, serial, port, SC_SOCKET_NAME,
SC_INHERIT_STDERR)) {
// success // success
tunnel->local_port = port; tunnel->local_port = port;
tunnel->enabled = true; tunnel->enabled = true;
@@ -146,9 +149,11 @@ sc_adb_tunnel_close(struct sc_adb_tunnel *tunnel, struct sc_intr *intr,
bool ret; bool ret;
if (tunnel->forward) { if (tunnel->forward) {
ret = adb_forward_remove(intr, serial, tunnel->local_port); ret = adb_forward_remove(intr, serial, tunnel->local_port,
SC_INHERIT_STDERR);
} else { } else {
ret = adb_reverse_remove(intr, serial, SC_SOCKET_NAME); ret = adb_reverse_remove(intr, serial, SC_SOCKET_NAME,
SC_INHERIT_STDERR);
assert(tunnel->server_socket != SC_SOCKET_NONE); assert(tunnel->server_socket != SC_SOCKET_NONE);
if (!net_close(tunnel->server_socket)) { if (!net_close(tunnel->server_socket)) {

View File

@@ -9,7 +9,6 @@
#include "options.h" #include "options.h"
#include "util/log.h" #include "util/log.h"
#include "util/net.h"
#include "util/str.h" #include "util/str.h"
#include "util/strbuf.h" #include "util/strbuf.h"
#include "util/term.h" #include "util/term.h"
@@ -47,8 +46,6 @@
#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;
@@ -333,25 +330,6 @@ static const struct sc_option options[] = {
"on exit.\n" "on exit.\n"
"It only shows physical touches (not clicks from scrcpy).", "It only shows physical touches (not clicks from scrcpy).",
}, },
{
.longopt_id = OPT_TUNNEL_HOST,
.longopt = "tunnel-host",
.argdesc = "ip",
.text = "Set the IP address of the adb tunnel to reach the scrcpy "
"server. This option automatically enables "
"--force-adb-forward.\n"
"Default is localhost.",
},
{
.longopt_id = OPT_TUNNEL_PORT,
.longopt = "tunnel-port",
.argdesc = "port",
.text = "Set the TCP port of the adb tunnel to reach the scrcpy "
"server. This option automatically enables "
"--force-adb-forward.\n"
"Default is 0 (not forced): the local port used for "
"establishing the tunnel will be used.",
},
#ifdef HAVE_V4L2 #ifdef HAVE_V4L2
{ {
.longopt_id = OPT_V4L2_SINK, .longopt_id = OPT_V4L2_SINK,
@@ -1149,21 +1127,6 @@ 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) {
return net_parse_ipv4(optarg, ipv4);
}
static bool
parse_port(const char *optarg, uint16_t *port) {
long value;
if (!parse_integer_arg(optarg, &value, false, 0, 0xFFFF, "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);
@@ -1236,16 +1199,6 @@ 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->tunnel_host)) {
return false;
}
break;
case OPT_TUNNEL_PORT:
if (!parse_port(optarg, &opts->tunnel_port)) {
return false;
}
break;
case 'n': case 'n':
opts->control = false; opts->control = false;
break; break;
@@ -1405,12 +1358,6 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
} }
#endif #endif
if ((opts->tunnel_host || opts->tunnel_port) && !opts->force_adb_forward) {
LOGI("Tunnel host/port is set, "
"--force-adb-forward automatically enabled.");
opts->force_adb_forward = true;
}
int index = optind; int index = optind;
if (index < argc) { if (index < argc) {
LOGE("Unexpected additional argument: %s", argv[index]); LOGE("Unexpected additional argument: %s", argv[index]);

View File

@@ -128,7 +128,8 @@ run_file_handler(void *data) {
if (req.action == ACTION_INSTALL_APK) { if (req.action == ACTION_INSTALL_APK) {
LOGI("Installing %s...", req.file); LOGI("Installing %s...", req.file);
bool ok = adb_install(intr, serial, req.file); bool ok = adb_install(intr, serial, req.file,
SC_INHERIT_STDOUT | SC_INHERIT_STDERR);
if (ok) { if (ok) {
LOGI("%s successfully installed", req.file); LOGI("%s successfully installed", req.file);
} else { } else {
@@ -136,7 +137,8 @@ run_file_handler(void *data) {
} }
} else { } else {
LOGI("Pushing %s...", req.file); LOGI("Pushing %s...", req.file);
bool ok = adb_push(intr, serial, req.file, push_target); bool ok = adb_push(intr, serial, req.file, push_target,
SC_INHERIT_STDOUT | SC_INHERIT_STDERR);
if (ok) { if (ok) {
LOGI("%s successfully pushed to %s", req.file, push_target); LOGI("%s successfully pushed to %s", req.file, push_target);
} else { } else {

View File

@@ -19,8 +19,6 @@ 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,
}, },
.tunnel_host = 0,
.tunnel_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,8 +77,6 @@ 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 tunnel_host;
uint16_t tunnel_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,8 +345,6 @@ 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,
.tunnel_host = options->tunnel_host,
.tunnel_port = options->tunnel_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

@@ -112,7 +112,8 @@ push_server(struct sc_intr *intr, const char *serial) {
free(server_path); free(server_path);
return false; return false;
} }
bool ok = adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH); bool ok = adb_push(intr, serial, server_path, SC_DEVICE_SERVER_PATH,
SC_INHERIT_STDERR);
free(server_path); free(server_path);
return ok; return ok;
} }
@@ -198,13 +199,14 @@ execute_server(struct sc_server *server,
// Port: 5005 // Port: 5005
// Then click on "Debug" // Then click on "Debug"
#endif #endif
return adb_execute(serial, cmd, ARRAY_LEN(cmd)); // Inherit both stdout and stderr (all server logs are printed to stdout)
return adb_execute(serial, cmd, ARRAY_LEN(cmd),
SC_INHERIT_STDOUT | SC_INHERIT_STDERR);
} }
static bool static bool
connect_and_read_byte(struct sc_intr *intr, sc_socket socket, connect_and_read_byte(struct sc_intr *intr, sc_socket socket, uint16_t port) {
uint32_t tunnel_host, uint16_t tunnel_port) { bool ok = net_connect_intr(intr, socket, IPV4_LOCALHOST, port);
bool ok = net_connect_intr(intr, socket, tunnel_host, tunnel_port);
if (!ok) { if (!ok) {
return false; return false;
} }
@@ -221,13 +223,13 @@ connect_and_read_byte(struct sc_intr *intr, sc_socket socket,
} }
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 host, 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, host, port); bool ok = connect_and_read_byte(&server->intr, socket, port);
if (ok) { if (ok) {
// it worked! // it worked!
return socket; return socket;
@@ -353,20 +355,9 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
goto fail; goto fail;
} }
} else { } else {
uint32_t tunnel_host = server->params.tunnel_host;
if (!tunnel_host) {
tunnel_host = IPV4_LOCALHOST;
}
uint16_t tunnel_port = server->params.tunnel_port;
if (!tunnel_port) {
tunnel_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, tunnel_host, video_socket = connect_to_server(server, attempts, delay);
tunnel_port);
if (video_socket == SC_SOCKET_NONE) { if (video_socket == SC_SOCKET_NONE) {
goto fail; goto fail;
} }
@@ -376,8 +367,8 @@ sc_server_connect_to(struct sc_server *server, struct sc_server_info *info) {
if (control_socket == SC_SOCKET_NONE) { if (control_socket == SC_SOCKET_NONE) {
goto fail; goto fail;
} }
bool ok = net_connect_intr(&server->intr, control_socket, tunnel_host, bool ok = net_connect_intr(&server->intr, control_socket,
tunnel_port); IPV4_LOCALHOST, tunnel->local_port);
if (!ok) { if (!ok) {
goto fail; goto fail;
} }
@@ -442,7 +433,8 @@ sc_server_fill_serial(struct sc_server *server) {
// device/emulator" error) // device/emulator" error)
if (!server->params.serial) { if (!server->params.serial) {
// The serial is owned by sc_server_params, and will be freed on destroy // The serial is owned by sc_server_params, and will be freed on destroy
server->params.serial = adb_get_serialno(&server->intr); server->params.serial = adb_get_serialno(&server->intr,
SC_INHERIT_STDERR);
if (!server->params.serial) { if (!server->params.serial) {
LOGE("Could not get device serial"); LOGE("Could not get device serial");
return false; return false;
@@ -469,6 +461,8 @@ run_server(void *data) {
goto error_connection_failed; goto error_connection_failed;
} }
LOGI("Server pushed");
ok = sc_adb_tunnel_open(&server->tunnel, &server->intr, params->serial, ok = sc_adb_tunnel_open(&server->tunnel, &server->intr, params->serial,
params->port_range, params->force_adb_forward); params->port_range, params->force_adb_forward);
if (!ok) { if (!ok) {

View File

@@ -29,8 +29,6 @@ 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 tunnel_host;
uint16_t tunnel_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;

View File

@@ -11,8 +11,16 @@
#include "util/log.h" #include "util/log.h"
enum sc_process_result enum sc_process_result
sc_process_execute_p(const char *const argv[], sc_pid *pid, sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit,
int *pin, int *pout, int *perr) { int *pin, int *pout, int *perr) {
bool inherit_stdout = inherit & SC_INHERIT_STDOUT;
bool inherit_stderr = inherit & SC_INHERIT_STDERR;
// If pout is defined, then inherit MUST NOT contain SC_INHERIT_STDOUT.
assert(!pout || !inherit_stdout);
// If perr is defined, then inherit MUST NOT contain SC_INHERIT_STDERR.
assert(!perr || !inherit_stderr);
int in[2]; int in[2];
int out[2]; int out[2];
int err[2]; int err[2];
@@ -90,20 +98,31 @@ sc_process_execute_p(const char *const argv[], sc_pid *pid,
} }
close(in[1]); close(in[1]);
} }
// Do not close stdin in the child process, this makes adb fail on
// Linux
if (pout) { if (pout) {
if (out[1] != STDOUT_FILENO) { if (out[1] != STDOUT_FILENO) {
dup2(out[1], STDOUT_FILENO); dup2(out[1], STDOUT_FILENO);
close(out[1]); close(out[1]);
} }
close(out[0]); close(out[0]);
} else if (!inherit_stdout) {
// Close stdout in the child process
close(STDOUT_FILENO);
} }
if (perr) { if (perr) {
if (err[1] != STDERR_FILENO) { if (err[1] != STDERR_FILENO) {
dup2(err[1], STDERR_FILENO); dup2(err[1], STDERR_FILENO);
close(err[1]); close(err[1]);
} }
close(err[0]); close(err[0]);
} else if (!inherit_stderr) {
// Close stderr in the child process
close(STDERR_FILENO);
} }
close(internal[0]); close(internal[0]);
enum sc_process_result err; enum sc_process_result err;
if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) { if (fcntl(internal[1], F_SETFD, FD_CLOEXEC) == 0) {

View File

@@ -27,12 +27,17 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) {
} }
enum sc_process_result enum sc_process_result
sc_process_execute_p(const char *const argv[], HANDLE *handle, sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned inherit,
HANDLE *pin, HANDLE *pout, HANDLE *perr) { HANDLE *pin, HANDLE *pout, HANDLE *perr) {
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC; bool inherit_stdout = inherit & SC_INHERIT_STDOUT;
bool inherit_stderr = inherit & SC_INHERIT_STDERR;
// Add 1 per non-NULL pointer // If pout is defined, then inherit MUST NOT contain SC_INHERIT_STDOUT.
unsigned handle_count = !!pin + !!pout + !!perr; assert(!pout || !inherit_stdout);
// If perr is defined, then inherit MUST NOT contain SC_INHERIT_STDERR.
assert(!perr || !inherit_stderr);
enum sc_process_result ret = SC_PROCESS_ERROR_GENERIC;
SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.nLength = sizeof(SECURITY_ATTRIBUTES);
@@ -80,59 +85,52 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
HANDLE handles[3]; HANDLE handles[3];
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL; LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
if (handle_count) { si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
if (pin) {
si.StartupInfo.hStdInput = stdin_read_handle;
}
if (pout) {
si.StartupInfo.hStdOutput = stdout_write_handle;
}
if (perr) {
si.StartupInfo.hStdError = stderr_write_handle;
}
SIZE_T size; unsigned handle_count = 0;
// Call it once to know the required buffer size if (pin) {
BOOL ok = si.StartupInfo.hStdInput = stdin_read_handle;
InitializeProcThreadAttributeList(NULL, 1, 0, &size) handles[handle_count++] = si.StartupInfo.hStdInput;
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER;
if (!ok) {
goto error_close_stderr;
}
lpAttributeList = malloc(size);
if (!lpAttributeList) {
goto error_close_stderr;
}
ok = InitializeProcThreadAttributeList(lpAttributeList, 1, 0, &size);
if (!ok) {
free(lpAttributeList);
goto error_close_stderr;
}
// Explicitly pass the HANDLEs that must be inherited
unsigned i = 0;
if (pin) {
handles[i++] = stdin_read_handle;
}
if (pout) {
handles[i++] = stdout_write_handle;
}
if (perr) {
handles[i++] = stderr_write_handle;
}
ok = UpdateProcThreadAttribute(lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
handles, handle_count * sizeof(HANDLE),
NULL, NULL);
if (!ok) {
goto error_free_attribute_list;
}
si.lpAttributeList = lpAttributeList;
} }
if (pout || inherit_stdout) {
si.StartupInfo.hStdOutput = pout ? stdout_write_handle
: GetStdHandle(STD_OUTPUT_HANDLE);
handles[handle_count++] = si.StartupInfo.hStdOutput;
}
if (perr || inherit_stderr) {
si.StartupInfo.hStdError = perr ? stderr_write_handle
: GetStdHandle(STD_ERROR_HANDLE);
handles[handle_count++] = si.StartupInfo.hStdError;
}
SIZE_T size;
// Call it once to know the required buffer size
BOOL ok =
InitializeProcThreadAttributeList(NULL, 1, 0, &size)
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER;
if (!ok) {
goto error_close_stderr;
}
lpAttributeList = malloc(size);
if (!lpAttributeList) {
goto error_close_stderr;
}
ok = InitializeProcThreadAttributeList(lpAttributeList, 1, 0, &size);
if (!ok) {
free(lpAttributeList);
goto error_close_stderr;
}
ok = UpdateProcThreadAttribute(lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handles,
handle_count * sizeof(HANDLE), NULL, NULL);
if (!ok) {
goto error_free_attribute_list;
}
si.lpAttributeList = lpAttributeList;
char *cmd = malloc(CMD_MAX_LEN); char *cmd = malloc(CMD_MAX_LEN);
if (!cmd || !build_cmd(cmd, CMD_MAX_LEN, argv)) { if (!cmd || !build_cmd(cmd, CMD_MAX_LEN, argv)) {
@@ -146,10 +144,9 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
goto error_free_attribute_list; goto error_free_attribute_list;
} }
BOOL bInheritHandles = handle_count > 0; ok = CreateProcessW(NULL, wide, NULL, NULL, TRUE,
DWORD dwCreationFlags = handle_count > 0 ? EXTENDED_STARTUPINFO_PRESENT : 0; EXTENDED_STARTUPINFO_PRESENT, NULL, NULL,
BOOL ok = CreateProcessW(NULL, wide, NULL, NULL, bInheritHandles, &si.StartupInfo, &pi);
dwCreationFlags, NULL, NULL, &si.StartupInfo, &pi);
free(wide); free(wide);
if (!ok) { if (!ok) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) { if (GetLastError() == ERROR_FILE_NOT_FOUND) {

View File

@@ -1,7 +1,3 @@
// For inet_pton() on Windows
#define _WIN32_WINNT 0x0600
#define WINVER 0x0600
#include "net.h" #include "net.h"
#include <assert.h> #include <assert.h>
@@ -11,7 +7,6 @@
#include "log.h" #include "log.h"
#ifdef __WINDOWS__ #ifdef __WINDOWS__
# include <ws2tcpip.h>
typedef int socklen_t; typedef int socklen_t;
typedef SOCKET sc_raw_socket; typedef SOCKET sc_raw_socket;
#else #else
@@ -230,15 +225,3 @@ net_close(sc_socket socket) {
return !close(raw_sock); return !close(raw_sock);
#endif #endif
} }
bool
net_parse_ipv4(const char *s, uint32_t *ipv4) {
struct in_addr addr;
if (!inet_pton(AF_INET, s, &addr)) {
LOGE("Invalid IPv4 address: %s", s);
return false;
}
*ipv4 = ntohl(addr.s_addr);
return true;
}

View File

@@ -68,10 +68,4 @@ net_interrupt(sc_socket socket);
bool bool
net_close(sc_socket socket); net_close(sc_socket socket);
/**
* Parse `ip` "xxx.xxx.xxx.xxx" to an IPv4 host representation
*/
bool
net_parse_ipv4(const char *ip, uint32_t *ipv4);
#endif #endif

View File

@@ -5,8 +5,8 @@
#include "log.h" #include "log.h"
enum sc_process_result enum sc_process_result
sc_process_execute(const char *const argv[], sc_pid *pid) { sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit) {
return sc_process_execute_p(argv, pid, NULL, NULL, NULL); return sc_process_execute_p(argv, pid, inherit, NULL, NULL, NULL);
} }
bool bool

View File

@@ -67,20 +67,32 @@ enum sc_process_result {
SC_PROCESS_ERROR_MISSING_BINARY, SC_PROCESS_ERROR_MISSING_BINARY,
}; };
#define SC_INHERIT_NONE 0
#define SC_INHERIT_STDOUT (1 << 0)
#define SC_INHERIT_STDERR (1 << 1)
/** /**
* Execute the command and write the process id to `pid` * Execute the command and write the process id to `pid`
*
* The parameter `inherit` is a ORed value of SC_INHERIT_* flags. It indicates
* if stdout and stderr must be inherited from the scrcpy process (in other
* words, if the process must output to the scrcpy console).
*/ */
enum sc_process_result enum sc_process_result
sc_process_execute(const char *const argv[], sc_pid *pid); sc_process_execute(const char *const argv[], sc_pid *pid, unsigned inherit);
/** /**
* Execute the command and write the process id to `pid` * Execute the command and write the process id to `pid`
* *
* If not NULL, provide a pipe for stdin (`pin`), stdout (`pout`) and stderr * If not NULL, provide a pipe for stdin (`pin`), stdout (`pout`) and stderr
* (`perr`). * (`perr`).
*
* The parameter `inherit` has the same semantics as in `sc_process_execute()`.
* If `pout` is not NULL, then `inherit` MUST NOT contain SC_INHERIT_STDOUT.
* If `perr` is not NULL, then `inherit` MUST NOT contain SC_INHERIT_STDERR.
*/ */
enum sc_process_result enum sc_process_result
sc_process_execute_p(const char *const argv[], sc_pid *pid, sc_process_execute_p(const char *const argv[], sc_pid *pid, unsigned inherit,
sc_pipe *pin, sc_pipe *pout, sc_pipe *perr); sc_pipe *pin, sc_pipe *pout, sc_pipe *perr);
/** /**