Compare commits
4 Commits
threadwait
...
threadwait
Author | SHA1 | Date | |
---|---|---|---|
73d098872c | |||
943d264b35 | |||
32dc192883 | |||
7732f1097b |
@ -5,6 +5,8 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <SDL2/SDL_thread.h>
|
||||||
#include <SDL2/SDL_timer.h>
|
#include <SDL2/SDL_timer.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
#include <SDL2/SDL_platform.h>
|
||||||
|
|
||||||
@ -332,6 +334,18 @@ server_init(struct server *server) {
|
|||||||
*server = (struct server) SERVER_INITIALIZER;
|
*server = (struct server) SERVER_INITIALIZER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
run_wait_server(void *data) {
|
||||||
|
struct server *server = data;
|
||||||
|
cmd_simple_wait(server->process, NULL); // ignore exit code
|
||||||
|
|
||||||
|
// wake up any net_select_interruptible()
|
||||||
|
close(server->pipe_intr[1]);
|
||||||
|
|
||||||
|
LOGD("Server terminated");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
server_start(struct server *server, const char *serial,
|
server_start(struct server *server, const char *serial,
|
||||||
const struct server_params *params) {
|
const struct server_params *params) {
|
||||||
@ -345,46 +359,79 @@ server_start(struct server *server, const char *serial,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!push_server(serial)) {
|
if (!push_server(serial)) {
|
||||||
SDL_free(server->serial);
|
goto error1;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enable_tunnel_any_port(server, params->port_range)) {
|
if (!enable_tunnel_any_port(server, params->port_range)) {
|
||||||
SDL_free(server->serial);
|
goto error1;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
bool ok = net_pipe(server->pipe_intr);
|
||||||
|
if (!ok) {
|
||||||
|
perror("pipe");
|
||||||
|
goto error2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// server will connect to our server socket
|
// server will connect to our server socket
|
||||||
server->process = execute_server(server, params);
|
server->process = execute_server(server, params);
|
||||||
|
|
||||||
if (server->process == PROCESS_NONE) {
|
if (server->process == PROCESS_NONE) {
|
||||||
if (!server->tunnel_forward) {
|
goto error3;
|
||||||
close_socket(&server->server_socket);
|
}
|
||||||
}
|
|
||||||
disable_tunnel(server);
|
server->wait_server_thread =
|
||||||
SDL_free(server->serial);
|
SDL_CreateThread(run_wait_server, "wait-server", server);
|
||||||
return false;
|
if (!server->wait_server_thread) {
|
||||||
|
cmd_terminate(server->process);
|
||||||
|
cmd_simple_wait(server->process, NULL); // ignore exit code
|
||||||
|
goto error3;
|
||||||
}
|
}
|
||||||
|
|
||||||
server->tunnel_enabled = true;
|
server->tunnel_enabled = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error3:
|
||||||
|
close(server->pipe_intr[0]);
|
||||||
|
close(server->pipe_intr[1]);
|
||||||
|
error2:
|
||||||
|
if (!server->tunnel_forward) {
|
||||||
|
close_socket(&server->server_socket);
|
||||||
|
}
|
||||||
|
disable_tunnel(server);
|
||||||
|
error1:
|
||||||
|
SDL_free(server->serial);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
server_connect_to(struct server *server) {
|
server_connect_to(struct server *server) {
|
||||||
if (!server->tunnel_forward) {
|
if (!server->tunnel_forward) {
|
||||||
|
bool acceptable = net_select_interruptible(server->server_socket,
|
||||||
|
server->pipe_intr[0]);
|
||||||
|
if (!acceptable) {
|
||||||
|
// the process died, accept() would never succeed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
server->video_socket = net_accept(server->server_socket);
|
server->video_socket = net_accept(server->server_socket);
|
||||||
if (server->video_socket == INVALID_SOCKET) {
|
if (server->video_socket == INVALID_SOCKET) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acceptable = net_select_interruptible(server->server_socket,
|
||||||
|
server->pipe_intr[0]);
|
||||||
|
if (!acceptable) {
|
||||||
|
// the process died, accept() would never succeed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
server->control_socket = net_accept(server->server_socket);
|
server->control_socket = net_accept(server->server_socket);
|
||||||
if (server->control_socket == INVALID_SOCKET) {
|
if (server->control_socket == INVALID_SOCKET) {
|
||||||
// the video_socket will be cleaned up on destroy
|
// the video_socket will be cleaned up on destroy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(server->pipe_intr[0]);
|
||||||
|
|
||||||
// we don't need the server socket anymore
|
// we don't need the server socket anymore
|
||||||
close_socket(&server->server_socket);
|
close_socket(&server->server_socket);
|
||||||
} else {
|
} else {
|
||||||
@ -425,17 +472,14 @@ server_stop(struct server *server) {
|
|||||||
|
|
||||||
assert(server->process != PROCESS_NONE);
|
assert(server->process != PROCESS_NONE);
|
||||||
|
|
||||||
if (!cmd_terminate(server->process)) {
|
cmd_terminate(server->process);
|
||||||
LOGW("Could not terminate server");
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_simple_wait(server->process, NULL); // ignore exit code
|
|
||||||
LOGD("Server terminated");
|
|
||||||
|
|
||||||
if (server->tunnel_enabled) {
|
if (server->tunnel_enabled) {
|
||||||
// ignore failure
|
// ignore failure
|
||||||
disable_tunnel(server);
|
disable_tunnel(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_WaitThread(server->wait_server_thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <SDL2/SDL_thread.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
@ -12,6 +13,8 @@
|
|||||||
struct server {
|
struct server {
|
||||||
char *serial;
|
char *serial;
|
||||||
process_t process;
|
process_t process;
|
||||||
|
SDL_Thread *wait_server_thread;
|
||||||
|
int pipe_intr[2]; // to wake up blocking accept() on process exit
|
||||||
socket_t server_socket; // only used if !tunnel_forward
|
socket_t server_socket; // only used if !tunnel_forward
|
||||||
socket_t video_socket;
|
socket_t video_socket;
|
||||||
socket_t control_socket;
|
socket_t control_socket;
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL_platform.h>
|
#include <SDL2/SDL_platform.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "common.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
# include <io.h>
|
||||||
|
# include <winsock2.h>
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
#else
|
#else
|
||||||
# include <sys/types.h>
|
# include <sys/select.h>
|
||||||
# include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
|
# include <sys/types.h>
|
||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
@ -145,3 +151,38 @@ net_close(socket_t socket) {
|
|||||||
return !close(socket);
|
return !close(socket);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_select_interruptible(int fd, int fd_intr) {
|
||||||
|
fd_set rfds;
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(fd, &rfds);
|
||||||
|
FD_SET(fd_intr, &rfds);
|
||||||
|
|
||||||
|
int nfds = MAX(fd, fd_intr) + 1;
|
||||||
|
|
||||||
|
// use select() because it's available on supported platforms
|
||||||
|
int r = select(nfds, &rfds, NULL, NULL, NULL);
|
||||||
|
if (r == -1) {
|
||||||
|
// failure
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
assert(r > 0);
|
||||||
|
if (FD_ISSET(fd_intr, &rfds)) {
|
||||||
|
// interrupted is set
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(FD_ISSET(fd, &rfds));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_pipe(int fds[static 2]) {
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
return !_pipe(fds, 4096, 0);
|
||||||
|
#else
|
||||||
|
return !pipe(fds);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@ -54,4 +54,12 @@ net_shutdown(socket_t socket, int how);
|
|||||||
bool
|
bool
|
||||||
net_close(socket_t socket);
|
net_close(socket_t socket);
|
||||||
|
|
||||||
|
// wait for fd or fd_intr to be readable
|
||||||
|
// return true if fd is readable and fd_intr is not
|
||||||
|
bool
|
||||||
|
net_select_interruptible(int fd, int fd_intr);
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_pipe(int fd[static 2]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user