Move server-related code to server.c
The file server.c already existed, but exposed a low-level API. Make it higher-level, so that scrcpy.c does not handle server details directly.
This commit is contained in:
105
app/src/server.c
105
app/src/server.c
@@ -1,28 +1,34 @@
|
||||
#include "command.h"
|
||||
#include "server.h"
|
||||
|
||||
#include <SDL2/SDL_log.h>
|
||||
#include <SDL2/SDL_net.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include "netutil.h"
|
||||
|
||||
#define SOCKET_NAME "scrcpy"
|
||||
|
||||
process_t push_server(const char *serial) {
|
||||
static SDL_bool push_server(const char *serial) {
|
||||
const char *server_path = getenv("SCRCPY_SERVER_JAR");
|
||||
if (!server_path) {
|
||||
server_path = "scrcpy-server.jar";
|
||||
}
|
||||
return adb_push(serial, server_path, "/data/local/tmp/scrcpy-server.jar");
|
||||
process_t process = adb_push(serial, server_path, "/data/local/tmp/scrcpy-server.jar");
|
||||
return process_check_success(process, "adb push");
|
||||
}
|
||||
|
||||
process_t enable_tunnel(const char *serial, Uint16 local_port) {
|
||||
return adb_reverse(serial, SOCKET_NAME, local_port);
|
||||
static SDL_bool enable_tunnel(const char *serial, Uint16 local_port) {
|
||||
process_t process = adb_reverse(serial, SOCKET_NAME, local_port);
|
||||
return process_check_success(process, "adb reverse");
|
||||
}
|
||||
|
||||
process_t disable_tunnel(const char *serial) {
|
||||
return adb_reverse_remove(serial, SOCKET_NAME);
|
||||
static SDL_bool disable_tunnel(const char *serial) {
|
||||
process_t process = adb_reverse_remove(serial, SOCKET_NAME);
|
||||
return process_check_success(process, "adb reverse --remove");
|
||||
}
|
||||
|
||||
process_t start_server(const char *serial, Uint16 max_size, Uint32 bit_rate) {
|
||||
static process_t execute_server(const char *serial, Uint16 max_size, Uint32 bit_rate) {
|
||||
char max_size_string[6];
|
||||
char bit_rate_string[11];
|
||||
sprintf(max_size_string, "%"PRIu16, max_size);
|
||||
@@ -39,8 +45,89 @@ process_t start_server(const char *serial, Uint16 max_size, Uint32 bit_rate) {
|
||||
return adb_execute(serial, cmd, sizeof(cmd) / sizeof(cmd[0]));
|
||||
}
|
||||
|
||||
void stop_server(process_t server) {
|
||||
static void terminate_server(process_t server) {
|
||||
if (!cmd_terminate(server)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Could not terminate server: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static TCPsocket listen_on_port(Uint16 port) {
|
||||
IPaddress addr = {
|
||||
.host = INADDR_ANY,
|
||||
.port = SDL_SwapBE16(port),
|
||||
};
|
||||
return SDLNet_TCP_Open(&addr);
|
||||
}
|
||||
|
||||
void server_init(struct server *server) {
|
||||
*server = (struct server) SERVER_INITIALIZER;
|
||||
}
|
||||
|
||||
SDL_bool server_start(struct server *server, const char *serial, Uint16 local_port,
|
||||
Uint16 max_size, Uint32 bit_rate) {
|
||||
if (!push_server(serial)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!enable_tunnel(serial, local_port)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
// At the application level, the device part is "the server" because it
|
||||
// serves video stream and control. However, at network level, the client
|
||||
// listens and the server connects to the client. That way, the client can
|
||||
// listen before starting the server app, so there is no need to try to
|
||||
// connect until the server socket is listening on the device.
|
||||
|
||||
server->server_socket = listen_on_port(local_port);
|
||||
if (!server->server_socket) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not listen on port %" PRIu16, local_port);
|
||||
disable_tunnel(serial);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
// server will connect to our server socket
|
||||
server->process = execute_server(serial, max_size, bit_rate);
|
||||
if (server->process == PROCESS_NONE) {
|
||||
SDLNet_TCP_Close(server->server_socket);
|
||||
disable_tunnel(serial);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
server->adb_reverse_enabled = SDL_TRUE;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
TCPsocket server_connect_to(struct server *server) {
|
||||
SDL_assert(server->server_socket);
|
||||
server->device_socket = server_socket_accept(server->server_socket);
|
||||
// we don't need the server socket anymore
|
||||
SDLNet_TCP_Close(server->server_socket);
|
||||
server->server_socket = NULL;
|
||||
return server->device_socket;
|
||||
}
|
||||
|
||||
void server_stop(struct server *server, const char *serial) {
|
||||
SDL_assert(server->process != PROCESS_NONE);
|
||||
if (server->server_socket) {
|
||||
SDLNet_TCP_Close(server->server_socket);
|
||||
}
|
||||
if (server->device_socket) {
|
||||
SDLNet_TCP_Close(server->device_socket);
|
||||
}
|
||||
|
||||
// let the server some time to print any exception trace before killing it
|
||||
struct timespec timespec = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = 100000000, // 100ms
|
||||
};
|
||||
nanosleep(×pec, NULL); // ignore error
|
||||
|
||||
terminate_server(server->process);
|
||||
|
||||
if (server->adb_reverse_enabled) {
|
||||
// ignore failure
|
||||
disable_tunnel(serial);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user