mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-04-20 19:45:00 +00:00
Added complicated reverse tunnelling.
This commit is contained in:
parent
3bdd6acb53
commit
fc2961e21e
7 changed files with 96 additions and 44 deletions
|
@ -103,15 +103,22 @@ show_adb_err_msg(enum process_result err, const char *const argv[]) {
|
|||
}
|
||||
|
||||
process_t
|
||||
ssh_execute(const char *endpoint, const char *const adb_cmd[], size_t len) {
|
||||
const char *cmd[len + 3];
|
||||
int i = 2;
|
||||
ssh_execute(const char *endpoint, const char *const ssh_cmd[], size_t len,
|
||||
const char *const prefix_cmd[], size_t prefix_cmd_len,
|
||||
const char *const ssh_options[], size_t ssh_options_len) {
|
||||
const char *cmd[len + prefix_cmd_len + ssh_options_len + 3];
|
||||
unsigned i = 0;
|
||||
process_t process;
|
||||
cmd[0] = "ssh";
|
||||
cmd[1] = endpoint;
|
||||
|
||||
memcpy(&cmd[i], adb_cmd, len * sizeof(const char *));
|
||||
cmd[len + i] = NULL;
|
||||
cmd[i++] = "ssh";
|
||||
memcpy(&cmd[i], ssh_options, ssh_options_len * sizeof(const char *));
|
||||
i += ssh_options_len;
|
||||
cmd[i++] = endpoint;
|
||||
memcpy(&cmd[i], prefix_cmd, prefix_cmd_len * sizeof(const char *));
|
||||
i += prefix_cmd_len;
|
||||
memcpy(&cmd[i], ssh_cmd, len * sizeof(const char *));
|
||||
i += len;
|
||||
cmd[i] = NULL;
|
||||
enum process_result r = cmd_execute(cmd, &process);
|
||||
if (r != PROCESS_SUCCESS) {
|
||||
show_adb_err_msg(r, cmd);
|
||||
|
|
|
@ -58,7 +58,9 @@ bool
|
|||
cmd_simple_wait(process_t pid, exit_code_t *exit_code);
|
||||
|
||||
process_t
|
||||
ssh_execute(const char *serial, const char *const adb_cmd[], size_t len);
|
||||
ssh_execute(const char *serial, const char *const ssh_cmd[], size_t len,
|
||||
const char *const prefix_cmd[], size_t prefix_cmd_len,
|
||||
const char *const ssh_options[], size_t ssh_options_len);
|
||||
|
||||
process_t
|
||||
adb_execute(const char *serial, const char *const adb_cmd[], size_t len);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "util/str_util.h"
|
||||
|
||||
#define SOCKET_NAME "scrcpy"
|
||||
#define SSH_SOCKET_NAME "/data/local/tmp/scrcpy"
|
||||
#define SSH_SOCKET_NAME "/dev/socket/scrcpy"
|
||||
#define SERVER_FILENAME "scrcpy-server"
|
||||
|
||||
#define DEFAULT_SERVER_PATH PREFIX "/share/scrcpy/" SERVER_FILENAME
|
||||
|
@ -104,6 +104,17 @@ push_server(const char *serial) {
|
|||
return process_check_success(process, "adb push");
|
||||
}
|
||||
|
||||
static bool prepare_ssh_socket_path(const struct server_params *params) {
|
||||
const char *const cmd[] = {
|
||||
"rm",
|
||||
"-f",
|
||||
SSH_SOCKET_NAME,
|
||||
};
|
||||
process_t process = ssh_execute(params->ssh_endpoint, cmd, sizeof(cmd) / sizeof(cmd[0]),
|
||||
NULL, 0, NULL, 0);
|
||||
return process_check_success(process, "ssh rm -f " SSH_SOCKET_NAME);
|
||||
}
|
||||
|
||||
static bool
|
||||
enable_tunnel_reverse(const char *serial, uint16_t local_port) {
|
||||
process_t process = adb_reverse(serial, SOCKET_NAME, local_port);
|
||||
|
@ -295,7 +306,6 @@ execute_server(struct server *server, const struct server_params *params) {
|
|||
params->show_touches ? "true" : "false",
|
||||
params->stay_awake ? "true" : "false",
|
||||
params->codec_options ? params->codec_options : "-",
|
||||
params->use_ssh ? "true" : "false",
|
||||
};
|
||||
#ifdef SERVER_DEBUGGER
|
||||
LOGI("Server debugger waiting for a client on device port "
|
||||
|
@ -309,7 +319,46 @@ execute_server(struct server *server, const struct server_params *params) {
|
|||
// Then click on "Debug"
|
||||
#endif
|
||||
if (params->use_ssh)
|
||||
return ssh_execute(params->ssh_endpoint, cmd, sizeof(cmd) / sizeof(cmd[0]));
|
||||
{
|
||||
char *tunnel_desc = SDL_strdup(SSH_SOCKET_NAME ":localhost:12345");
|
||||
const char *const ssh_options[] = {
|
||||
"-o", "ExitOnForwardFailure=yes",
|
||||
"-R", tunnel_desc,
|
||||
};
|
||||
|
||||
const char *const prefix_cmd[] = {
|
||||
"/data/ssh/root/socat",
|
||||
"abstract-listen:" SOCKET_NAME ",fork",
|
||||
"unix-connect:" SSH_SOCKET_NAME,
|
||||
"&",
|
||||
};
|
||||
|
||||
for (uint16_t port = server->port_range.first;;) {
|
||||
server->server_socket = listen_on_port(port);
|
||||
if (server->server_socket == INVALID_SOCKET) {
|
||||
if (port < server->port_range.last) {
|
||||
LOGW("Could not listen on port %" PRIu16", retrying on %" PRIu16,
|
||||
port, (uint16_t) (port + 1));
|
||||
port++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (server->port_range.first == server->port_range.last) {
|
||||
LOGE("Could not listen on port %" PRIu16, server->port_range.first);
|
||||
} else {
|
||||
LOGE("Could not listen on any port in range %" PRIu16 ":%" PRIu16,
|
||||
server->port_range.first, server->port_range.last);
|
||||
}
|
||||
return PROCESS_NONE;
|
||||
}
|
||||
server->local_port = port;
|
||||
snprintf(tunnel_desc + strlen(tunnel_desc) - 5, 6, "%d", port);
|
||||
|
||||
return ssh_execute(params->ssh_endpoint, cmd, sizeof(cmd) / sizeof(cmd[0]),
|
||||
prefix_cmd, sizeof(prefix_cmd) / sizeof(prefix_cmd[0]),
|
||||
ssh_options, sizeof(ssh_options) / sizeof(ssh_options[0]));
|
||||
}
|
||||
}
|
||||
else
|
||||
return adb_execute(server->serial, cmd, sizeof(cmd) / sizeof(cmd[0]));
|
||||
}
|
||||
|
@ -390,10 +439,15 @@ server_start(struct server *server, const char *serial,
|
|||
}
|
||||
}
|
||||
|
||||
server->use_ssh = params->use_ssh;
|
||||
|
||||
if (!push_server(serial)) {
|
||||
goto error1;
|
||||
}
|
||||
|
||||
if (params->use_ssh && !prepare_ssh_socket_path(params))
|
||||
goto error1;
|
||||
|
||||
if (!params->use_ssh && !enable_tunnel_any_port(server, params->port_range,
|
||||
params->force_adb_forward)) {
|
||||
goto error1;
|
||||
|
@ -419,21 +473,21 @@ server_start(struct server *server, const char *serial,
|
|||
goto error2;
|
||||
}
|
||||
|
||||
if (!params->use_ssh)
|
||||
server->tunnel_enabled = true;
|
||||
server->tunnel_enabled = true;
|
||||
|
||||
return true;
|
||||
|
||||
error2:
|
||||
if (!params->use_ssh) {
|
||||
if (!server->tunnel_forward) {
|
||||
bool was_closed =
|
||||
atomic_flag_test_and_set(&server->server_socket_closed);
|
||||
// the thread is not started, the flag could not be already set
|
||||
assert(!was_closed);
|
||||
(void) was_closed;
|
||||
close_socket(server->server_socket);
|
||||
}
|
||||
if (!server->tunnel_forward) {
|
||||
bool was_closed =
|
||||
atomic_flag_test_and_set(&server->server_socket_closed);
|
||||
// the thread is not started, the flag could not be already set
|
||||
assert(!was_closed);
|
||||
(void) was_closed;
|
||||
close_socket(server->server_socket);
|
||||
}
|
||||
|
||||
if (!server->use_ssh) {
|
||||
disable_tunnel(server);
|
||||
}
|
||||
error1:
|
||||
|
@ -480,7 +534,8 @@ server_connect_to(struct server *server) {
|
|||
|
||||
if (server->tunnel_enabled) {
|
||||
// we don't need the adb tunnel anymore
|
||||
disable_tunnel(server); // ignore failure
|
||||
if (!server->use_ssh)
|
||||
disable_tunnel(server); // ignore failure
|
||||
server->tunnel_enabled = false;
|
||||
}
|
||||
|
||||
|
@ -504,7 +559,7 @@ server_stop(struct server *server) {
|
|||
|
||||
cmd_terminate(server->process);
|
||||
|
||||
if (server->tunnel_enabled) {
|
||||
if (server->tunnel_enabled && !server->use_ssh) {
|
||||
// ignore failure
|
||||
disable_tunnel(server);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ struct server {
|
|||
uint16_t local_port; // selected from port_range
|
||||
bool tunnel_enabled;
|
||||
bool tunnel_forward; // use "adb forward" instead of "adb reverse"
|
||||
bool use_ssh;
|
||||
};
|
||||
|
||||
#define SERVER_INITIALIZER { \
|
||||
|
@ -42,6 +43,7 @@ struct server {
|
|||
.local_port = 0, \
|
||||
.tunnel_enabled = false, \
|
||||
.tunnel_forward = false, \
|
||||
.use_ssh = false, \
|
||||
}
|
||||
|
||||
struct server_params {
|
||||
|
|
|
@ -16,7 +16,6 @@ public final class DesktopConnection implements Closeable {
|
|||
private static final int DEVICE_NAME_FIELD_LENGTH = 64;
|
||||
|
||||
private static final String SOCKET_NAME = "scrcpy";
|
||||
private static final String SSH_SOCKET_NAME = "/data/local/tmp/scrcpy";
|
||||
|
||||
private final LocalSocket videoSocket;
|
||||
private final FileDescriptor videoFd;
|
||||
|
@ -42,11 +41,11 @@ public final class DesktopConnection implements Closeable {
|
|||
return localSocket;
|
||||
}
|
||||
|
||||
public static DesktopConnection open(Device device, boolean tunnelForward, boolean sshMode) throws IOException {
|
||||
public static DesktopConnection open(Device device, boolean tunnelForward) throws IOException {
|
||||
LocalSocket videoSocket;
|
||||
LocalSocket controlSocket;
|
||||
if (tunnelForward) {
|
||||
LocalServerSocket localServerSocket = new LocalServerSocket(sshMode ? SSH_SOCKET_NAME : SOCKET_NAME);
|
||||
LocalServerSocket localServerSocket = new LocalServerSocket(SOCKET_NAME);
|
||||
try {
|
||||
videoSocket = localServerSocket.accept();
|
||||
// send one byte so the client may read() to detect a connection error
|
||||
|
@ -61,9 +60,9 @@ public final class DesktopConnection implements Closeable {
|
|||
localServerSocket.close();
|
||||
}
|
||||
} else {
|
||||
videoSocket = connect(sshMode ? SSH_SOCKET_NAME : SOCKET_NAME);
|
||||
videoSocket = connect(SOCKET_NAME);
|
||||
try {
|
||||
controlSocket = connect(sshMode ? SSH_SOCKET_NAME : SOCKET_NAME);
|
||||
controlSocket = connect(SOCKET_NAME);
|
||||
} catch (IOException | RuntimeException e) {
|
||||
videoSocket.close();
|
||||
throw e;
|
||||
|
|
|
@ -16,7 +16,6 @@ public class Options {
|
|||
private boolean showTouches;
|
||||
private boolean stayAwake;
|
||||
private String codecOptions;
|
||||
private boolean sshMode;
|
||||
|
||||
public Ln.Level getLogLevel() {
|
||||
return logLevel;
|
||||
|
@ -121,12 +120,4 @@ public class Options {
|
|||
public void setCodecOptions(String codecOptions) {
|
||||
this.codecOptions = codecOptions;
|
||||
}
|
||||
|
||||
public boolean isSshMode() {
|
||||
return sshMode;
|
||||
}
|
||||
|
||||
public void setSshMode(boolean sshMode) {
|
||||
this.sshMode = sshMode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,9 +52,8 @@ public final class Server {
|
|||
CleanUp.configure(mustDisableShowTouchesOnCleanUp, restoreStayOn, true);
|
||||
|
||||
boolean tunnelForward = options.isTunnelForward();
|
||||
boolean sshMode = options.isSshMode();
|
||||
|
||||
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward, sshMode)) {
|
||||
try (DesktopConnection connection = DesktopConnection.open(device, tunnelForward)) {
|
||||
ScreenEncoder screenEncoder = new ScreenEncoder(options.getSendFrameMeta(), options.getBitRate(), options.getMaxFps(), codecOptions);
|
||||
|
||||
if (options.getControl()) {
|
||||
|
@ -121,7 +120,7 @@ public final class Server {
|
|||
"The server version (" + BuildConfig.VERSION_NAME + ") does not match the client " + "(" + clientVersion + ")");
|
||||
}
|
||||
|
||||
final int expectedParameters = 15;
|
||||
final int expectedParameters = 14;
|
||||
if (args.length != expectedParameters) {
|
||||
throw new IllegalArgumentException("Expecting " + expectedParameters + " parameters");
|
||||
}
|
||||
|
@ -168,9 +167,6 @@ public final class Server {
|
|||
String codecOptions = args[13];
|
||||
options.setCodecOptions(codecOptions);
|
||||
|
||||
boolean sshMode = Boolean.parseBoolean(args[14]);
|
||||
options.setSshMode(sshMode);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue