jsfw/server.c

505 lines
18 KiB
C
Raw Normal View History

2022-10-07 18:36:53 -05:00
#include "server.h"
#include "const.h"
2022-08-30 17:54:56 -05:00
#include "hid.h"
2022-10-07 18:36:53 -05:00
#include "json.h"
2022-08-30 17:54:56 -05:00
#include "net.h"
#include "util.h"
2022-10-07 18:36:53 -05:00
#include "vec.h"
2022-08-30 17:54:56 -05:00
2023-03-18 10:31:33 -05:00
#include <arpa/inet.h>
2022-08-31 11:59:06 -05:00
#include <linux/input-event-codes.h>
2022-08-30 08:37:34 -05:00
#include <linux/input.h>
2022-08-30 12:08:36 -05:00
#include <netinet/in.h>
2022-08-29 18:06:25 -05:00
#include <netinet/tcp.h>
2022-08-30 12:08:36 -05:00
#include <poll.h>
2022-08-29 18:06:25 -05:00
#include <pthread.h>
2022-10-07 18:36:53 -05:00
#include <signal.h>
2022-10-12 15:28:50 -05:00
#include <stddef.h>
2022-08-29 18:06:25 -05:00
#include <stdint.h>
#include <stdio.h>
2022-08-30 12:08:36 -05:00
#include <stdlib.h>
2022-08-29 18:06:25 -05:00
#include <string.h>
#include <sys/socket.h>
2022-08-30 12:08:36 -05:00
#include <unistd.h>
2022-08-29 17:27:03 -05:00
2022-09-11 04:23:31 -05:00
// Arguments for a connection thread
2022-08-29 17:27:03 -05:00
struct Connection {
2022-08-29 18:06:25 -05:00
int socket;
2022-08-29 17:27:03 -05:00
uint32_t id;
2022-10-12 12:33:18 -05:00
bool closed;
2022-08-29 17:27:03 -05:00
};
2022-10-07 18:36:53 -05:00
struct DeviceThreadArgs {
int index;
2023-03-18 10:31:33 -05:00
char **tags;
size_t tag_count;
2022-10-07 18:36:53 -05:00
Controller **controller;
struct Connection *conn;
};
2022-08-29 17:27:03 -05:00
2022-10-07 18:36:53 -05:00
static void default_timespec(void *ptr) { *(struct timespec *)ptr = POLL_DEVICE_INTERVAL; }
static void default_request_timeout(void *ptr) { *(uint32_t *)ptr = REQUEST_TIMEOUT; }
2022-08-29 18:06:25 -05:00
2022-10-07 18:36:53 -05:00
const JSONPropertyAdapter FilterAdapterProps[] = {
2022-10-12 12:33:18 -05:00
{".uniq", &StringAdapter, offsetof(ControllerFilter, uniq), default_to_zero_u64, tsf_uniq_to_u64},
{".vendor", &StringAdapter, offsetof(ControllerFilter, vendor), default_to_negative_one_i32, tsf_hex_to_i32 },
{".product", &StringAdapter, offsetof(ControllerFilter, product), default_to_negative_one_i32, tsf_hex_to_i32 },
{".js", &BooleanAdapter, offsetof(ControllerFilter, js), default_to_false, NULL },
{".name", &StringAdapter, offsetof(ControllerFilter, name), default_to_null, NULL },
2022-10-07 18:36:53 -05:00
};
const JSONAdapter FilterAdapter = {
.props = FilterAdapterProps,
.prop_count = sizeof(FilterAdapterProps) / sizeof(JSONPropertyAdapter),
.size = sizeof(ControllerFilter),
};
2022-08-29 18:06:25 -05:00
2022-10-07 18:36:53 -05:00
const JSONPropertyAdapter ControllerAdapterProps[] = {
{".filter", &FilterAdapter, offsetof(ServerConfigController, filter), NULL, NULL},
{".tag", &StringAdapter, offsetof(ServerConfigController, tag), default_to_null, NULL},
{".properties.duplicate", &BooleanAdapter, offsetof(ServerConfigController, duplicate), default_to_false, NULL},
{".properties.ps4_hidraw", &BooleanAdapter, offsetof(ServerConfigController, ps4_hidraw), default_to_false, NULL},
};
const JSONAdapter ControllerAdapter = {
.props = ControllerAdapterProps,
.prop_count = sizeof(ControllerAdapterProps) / sizeof(JSONPropertyAdapter),
.size = sizeof(ServerConfigController),
};
2022-10-07 18:36:53 -05:00
const JSONPropertyAdapter ConfigAdapterProps[] = {
{".controllers[]", &ControllerAdapter, offsetof(ServerConfig, controllers), default_to_null, NULL },
{".poll_interval", &NumberAdapter, offsetof(ServerConfig, poll_interval), default_timespec, tsf_numsec_to_timespec},
{".request_timeout", &NumberAdapter, offsetof(ServerConfig, request_timeout), default_request_timeout, tsf_numsec_to_intms }
};
const JSONAdapter ConfigAdapter = {
.props = ConfigAdapterProps,
.prop_count = sizeof(ConfigAdapterProps) / sizeof(JSONPropertyAdapter),
.size = sizeof(ServerConfig),
};
2022-08-29 18:06:25 -05:00
2022-10-07 18:36:53 -05:00
static ServerConfig config;
static pthread_key_t device_args_key;
static sigset_t empty_sigset;
2022-10-07 18:36:53 -05:00
#define TRAP(sig, handler) \
if (sigaction(sig, &(struct sigaction){.sa_handler = handler, .sa_mask = empty_sigset, .sa_flags = 0}, NULL) != 0) \
printf("SERVER: can't trap " #sig ".\n")
2022-10-12 12:33:18 -05:00
#define TRAP_IGN(sig) \
if (sigaction(sig, &(struct sigaction){{SIG_IGN}}, NULL) != 0) \
printf("SERVER: can't ignore " #sig ".\n")
2022-08-29 18:06:25 -05:00
2023-04-15 11:24:25 -05:00
static void print_config() __attribute__((unused));
2023-03-18 10:31:33 -05:00
static void print_config() {
printf("SERVER: Config\n");
printf(" retry_delay: %fs\n", (double)(config.request_timeout) / 1000.0);
printf(" poll_interval: %fs\n", timespec_to_double(&config.poll_interval));
printf(" controllers:\n");
for (size_t i = 0; i < config.controller_count; i++) {
ServerConfigController *ctr = &config.controllers[i];
printf(" - tag: '%s'\n", ctr->tag);
printf(" duplicate: %s\n", ctr->duplicate ? "true" : "false");
printf(" ps4_hidraw: %s\n", ctr->ps4_hidraw ? "true" : "false");
if (ctr->filter.name != NULL || ctr->filter.js != false || ctr->filter.uniq != 0 || ctr->filter.vendor >= 0 ||
ctr->filter.product >= 0) {
printf(" filter:\n");
if (ctr->filter.name != NULL)
printf(" name: '%s'\n", ctr->filter.name);
if (ctr->filter.js)
printf(" has_js\n");
if (ctr->filter.uniq != 0)
printf(" uniq: %016lx\n", ctr->filter.uniq);
if (ctr->filter.vendor >= 0)
printf(" vendor: %04x\n", ctr->filter.vendor);
if (ctr->filter.product >= 0)
printf(" product: %04x\n", ctr->filter.product);
}
}
printf("\n");
}
2022-10-12 12:33:18 -05:00
void device_thread_exit(int _sig) {
2022-10-07 18:36:53 -05:00
struct DeviceThreadArgs *args = pthread_getspecific(device_args_key);
2022-10-12 12:33:18 -05:00
printf("CONN(%d): [%d] exiting\n", args->conn->id, args->index);
2022-08-30 11:28:29 -05:00
2022-10-12 12:33:18 -05:00
Controller *ctr = *args->controller;
if (ctr != NULL) {
2022-10-07 18:36:53 -05:00
return_device(ctr);
2023-03-18 12:41:17 -05:00
free(ctr);
2022-10-07 18:36:53 -05:00
}
2022-08-30 11:28:29 -05:00
2023-03-18 10:31:33 -05:00
for (int i = 0; i < args->tag_count; i++) {
free(args->tags[i]);
}
free(args->tags);
2022-10-07 18:36:53 -05:00
free(args);
pthread_exit(NULL);
}
2022-08-30 12:08:36 -05:00
2022-10-07 18:36:53 -05:00
void *device_thread(void *args_) {
struct DeviceThreadArgs *args = args_;
2022-08-30 08:37:34 -05:00
2022-10-07 18:36:53 -05:00
pthread_setspecific(device_args_key, args);
2022-08-30 17:54:56 -05:00
2022-10-12 12:33:18 -05:00
TRAP_IGN(SIGPIPE);
2022-10-07 18:36:53 -05:00
TRAP(SIGTERM, device_thread_exit);
2022-08-29 18:06:25 -05:00
2022-10-07 18:36:53 -05:00
uint8_t buf[2048] __attribute__((aligned(4))) = {0};
MessageDeviceInfo dev_info;
2022-08-30 08:37:34 -05:00
2022-10-07 18:36:53 -05:00
while (true) {
2023-03-18 12:41:17 -05:00
if (*args->controller != NULL) {
free(*args->controller);
}
2022-10-07 18:36:53 -05:00
*args->controller = NULL;
2023-03-18 12:41:17 -05:00
uint8_t controller_index;
Controller *ctr = malloc(sizeof(Controller));
if (!get_device(args->tags, args->tag_count, &args->conn->closed, ctr, &controller_index)) {
2022-10-12 12:33:18 -05:00
break;
}
2022-10-07 18:36:53 -05:00
*args->controller = ctr;
dev_info = ctr->dev.device_info;
2023-03-18 12:41:17 -05:00
dev_info.slot = args->index;
dev_info.index = controller_index;
2022-08-30 08:37:34 -05:00
2023-03-18 12:41:17 -05:00
printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%lu)\n", args->conn->id, args->index, ctr->ctr.tag,
2022-10-12 12:33:18 -05:00
ctr->dev.name, ctr->dev.id);
2022-08-30 08:37:34 -05:00
2022-10-07 18:36:53 -05:00
// Send over device info
{
int len = msg_serialize(buf, 2048, (Message *)&dev_info);
if (write(args->conn->socket, buf, len) == -1) {
printf("CONN(%d): [%d] Couldn't send device info\n", args->conn->id, args->index);
break;
2022-08-30 08:37:34 -05:00
}
}
2022-08-30 17:54:56 -05:00
2022-10-07 18:36:53 -05:00
MessageDeviceReport report = {0};
2022-08-30 17:54:56 -05:00
2022-10-07 18:36:53 -05:00
report.code = DeviceReport;
report.abs_count = ctr->dev.device_info.abs_count;
report.rel_count = ctr->dev.device_info.rel_count;
report.key_count = ctr->dev.device_info.key_count;
2023-03-18 12:41:17 -05:00
report.slot = args->index;
report.index = controller_index;
2022-10-07 18:36:53 -05:00
while (true) {
2022-08-30 11:28:29 -05:00
struct input_event event;
2022-08-30 17:54:56 -05:00
2022-10-07 18:36:53 -05:00
int len = read(ctr->dev.event, &event, sizeof(struct input_event));
2022-08-30 17:54:56 -05:00
if (len <= 0) {
2022-10-07 18:36:53 -05:00
// We lost the device, so we mark it as broken (we forget it) and try to get a new one (in the next iteration of
// the outer while)
forget_device(ctr);
break;
2022-08-30 17:54:56 -05:00
}
2022-08-30 11:28:29 -05:00
if (len < sizeof(struct input_event)) {
2022-10-07 18:36:53 -05:00
printf("CONN(%d): [%d] error reading event\n", args->conn->id, args->index);
2022-08-30 11:28:29 -05:00
continue;
}
if (event.type == EV_SYN) {
int len = msg_serialize(buf, 2048, (Message *)&report);
if (len < 0) {
2022-10-07 18:36:53 -05:00
printf("CONN(%d): [%d] Couldn't serialize report %d\n", args->conn->id, args->index, len);
2022-08-30 11:28:29 -05:00
continue;
};
2022-10-07 18:36:53 -05:00
send(args->conn->socket, buf, len, 0);
2022-08-30 11:28:29 -05:00
} else if (event.type == EV_ABS) {
2022-10-07 18:36:53 -05:00
int index = ctr->dev.mapping.abs_indices[event.code];
2022-08-29 18:06:25 -05:00
2022-08-30 11:28:29 -05:00
if (index < 0) {
2022-10-07 18:36:53 -05:00
printf("CONN(%d): [%d] Invalid abs\n", args->conn->id, args->index);
2022-08-30 11:28:29 -05:00
continue;
};
report.abs[index] = event.value;
} else if (event.type == EV_REL) {
2022-10-07 18:36:53 -05:00
int index = ctr->dev.mapping.rel_indices[event.code];
2022-08-30 11:28:29 -05:00
if (index < 0) {
2022-10-07 18:36:53 -05:00
printf("CONN(%d): [%d] Invalid rel\n", args->conn->id, args->index);
2022-08-30 11:28:29 -05:00
continue;
};
report.rel[index] = event.value;
} else if (event.type == EV_KEY) {
2022-10-07 18:36:53 -05:00
int index = ctr->dev.mapping.key_indices[event.code];
2022-08-30 11:28:29 -05:00
if (index < 0) {
2022-10-07 18:36:53 -05:00
printf("CONN(%d): [%d] Invalid key\n", args->conn->id, args->index);
2022-08-30 11:28:29 -05:00
continue;
};
report.key[index] = !!event.value;
}
2022-08-29 17:27:03 -05:00
}
2022-10-07 18:36:53 -05:00
// Send device destroy message
{
MessageDestroy dstr;
2022-10-12 12:33:18 -05:00
dstr.code = DeviceDestroy;
2022-10-07 18:36:53 -05:00
dstr.index = args->index;
int len = msg_serialize(buf, 2048, (Message *)&dstr);
if (write(args->conn->socket, buf, len) == -1) {
printf("CONN(%d): [%d] Couldn't send device destroy message\n", args->conn->id, args->index);
break;
}
}
}
2022-10-12 12:33:18 -05:00
device_thread_exit(SIGTERM);
2022-10-07 18:36:53 -05:00
return NULL;
}
void *server_handle_conn(void *args_) {
struct Connection *args = args_;
printf("CONN(%u): start\n", args->id);
if (setsockopt(args->socket, SOL_SOCKET, SO_KEEPALIVE, &TCP_KEEPALIVE_ENABLE, sizeof(int)) != 0)
printf("ERR(server_handle_conn): Enabling socket keepalives on client\n");
if (setsockopt(args->socket, SOL_TCP, TCP_KEEPIDLE, &TCP_KEEPALIVE_IDLE_TIME, sizeof(int)) != 0)
printf("ERR(server_handle_conn): Setting initial idle-time value\n");
if (setsockopt(args->socket, SOL_TCP, TCP_KEEPCNT, &TCP_KEEPALIVE_RETRY_COUNT, sizeof(int)) != 0)
printf("ERR(server_handle_conn): Setting idle retry count\n");
if (setsockopt(args->socket, SOL_TCP, TCP_KEEPINTVL, &TCP_KEEPALIVE_RETRY_INTERVAL, sizeof(int)) != 0)
printf("ERR(server_handle_conn): Setting idle retry interval\n");
uint8_t buf[2048] __attribute__((aligned(4))) = {0};
char *closing_message = "";
bool got_request = false;
Vec device_threads = vec_of(pthread_t);
Vec device_controllers = vec_of(Controller *);
struct pollfd pfd = {.fd = args->socket, .events = POLLIN};
while (1) {
int rc = poll(&pfd, 1, config.request_timeout);
// If poll timed out
if (rc == 0) {
if (!got_request) {
printf("CONN(%d): Didn't get a device request within %i.%03ds\n", args->id, config.request_timeout / 1000,
config.request_timeout % 1000);
closing_message = "Timed out";
goto conn_end;
}
continue;
} else if (rc < 0) { // If poll failed (basically never)
closing_message = "Poll error";
goto conn_end;
}
// Test for error on socket
if (pfd.revents & POLLHUP || pfd.revents & POLLERR) {
closing_message = "Lost peer";
goto conn_end;
}
// Receive data
int len = recv(args->socket, buf, 2048, 0);
if (len <= 0) {
closing_message = "Lost peer (from recv)";
goto conn_end;
2022-10-12 12:33:18 -05:00
} else if (len > 1 + MAGIC_SIZE * 2) {
printf("CONN(%d): Got message: ", args->id);
printf("\n");
} else {
printf("CONN(%d): Malformed message\n", args->id);
2022-10-07 18:36:53 -05:00
}
// Parse message
Message msg;
2022-10-12 12:33:18 -05:00
int msg_len = msg_deserialize(buf, len, &msg);
if (msg_len < 0) {
if (len > 1 + MAGIC_SIZE * 2) {
printf("CONN(%d): Couldn't parse message: ", args->id);
print_message_buffer(buf, len);
printf("\n");
} else {
printf("CONN(%d): Couldn't parse message", args->id);
}
2022-10-07 18:36:53 -05:00
continue;
}
// Handle message
if (msg.code == ControllerState) {
int i = msg.controller_state.index;
if (i >= device_controllers.len) {
printf("CONN(%d): Invalid controller index in controller state message\n", args->id);
continue;
}
Controller *ctr = *(Controller **)vec_get(&device_controllers, i);
if (ctr == NULL) {
printf("CONN(%d): Received controller state message but the device hasn't yet been received\n", args->id);
continue;
}
apply_controller_state(ctr, &msg.controller_state);
} else if (msg.code == Request) {
if (got_request) {
printf("CONN(%d): Illegal Request message after initial request\n", args->id);
msg_free(&msg);
continue;
}
got_request = true;
printf("CONN(%d): Got client request\n", args->id);
for (int i = 0; i < msg.request.request_count; i++) {
int index = device_controllers.len;
Controller *ctr = NULL;
vec_push(&device_controllers, &ctr);
struct DeviceThreadArgs *dev_args = malloc(sizeof(struct DeviceThreadArgs));
2023-03-18 10:31:33 -05:00
dev_args->controller = vec_get(&device_controllers, index);
dev_args->tag_count = msg.request.requests[i].count;
dev_args->tags = malloc(dev_args->tag_count * sizeof(char *));
dev_args->conn = args;
dev_args->index = index;
for (int j = 0; j < dev_args->tag_count; j++) {
dev_args->tags[j] = strdup(msg.request.requests[i].tags[j]);
}
2022-10-07 18:36:53 -05:00
pthread_t thread;
pthread_create(&thread, NULL, device_thread, dev_args);
vec_push(&device_threads, &thread);
}
msg_free(&msg);
} else {
printf("CONN(%d): Illegal message\n", args->id);
}
2022-08-29 17:27:03 -05:00
}
2022-08-29 18:06:25 -05:00
conn_end:
2022-08-30 08:37:34 -05:00
shutdown(args->socket, SHUT_RDWR);
2022-08-30 17:54:56 -05:00
printf("CONN(%u): connection closed (%s)\n", args->id, closing_message);
2022-10-12 12:33:18 -05:00
args->closed = true;
2022-10-07 18:36:53 -05:00
for (int i = 0; i < device_threads.len; i++) {
pthread_t thread = *(pthread_t *)vec_get(&device_threads, i);
pthread_kill(thread, SIGTERM);
pthread_join(thread, NULL);
}
2022-10-12 12:33:18 -05:00
free(args);
2022-10-12 12:40:53 -05:00
vec_free(device_threads);
vec_free(device_controllers);
2022-08-29 17:27:03 -05:00
return NULL;
}
2022-10-07 18:36:53 -05:00
static int sockfd;
2022-10-12 12:33:18 -05:00
void clean_exit(int _sig) {
2022-10-07 18:36:53 -05:00
printf("\rSERVER: exiting\n");
close(sockfd);
exit(0);
}
void server_run(uint16_t port, char *config_path) {
sigemptyset(&empty_sigset);
pthread_key_create(&device_args_key, NULL);
2022-08-30 17:54:56 -05:00
printf("SERVER: start\n");
2022-08-29 18:06:25 -05:00
2022-10-07 18:36:53 -05:00
// Parse the config
{
FILE *configfd = fopen(config_path, "r");
if (configfd == NULL) {
perror("SERVER: Couldn't open config file");
exit(1);
}
char *cbuf = malloc(8192);
uint8_t *jbuf = (uint8_t *)cbuf + 4096;
int len = fread(cbuf, 1, 4096, configfd);
if (json_parse(cbuf, len, jbuf, 4096) != 0) {
printf("SERVER: Couldn't parse config, %s (at index %lu)\n", json_strerr(), json_errloc());
exit(1);
}
json_adapt(jbuf, &ConfigAdapter, &config);
2023-03-18 10:31:33 -05:00
#ifdef VERBOSE
print_config();
#endif
2022-10-07 18:36:53 -05:00
free(cbuf);
fclose(configfd);
}
// Start the hid thread
{
pthread_t _thread;
pthread_create(&_thread, NULL, hid_thread, &config);
}
// Start the TCP server
2022-08-29 17:27:03 -05:00
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
2022-08-29 18:06:25 -05:00
panicf("Couldn't open socket\n");
}
2022-08-29 18:06:25 -05:00
2022-10-07 18:36:53 -05:00
sockfd = sock;
TRAP(SIGINT, clean_exit);
TRAP(SIGHUP, clean_exit);
TRAP(SIGQUIT, clean_exit);
TRAP(SIGTERM, clean_exit);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
printf("SERVER: error when trying to enable SO_REUSEADDR\n");
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)) < 0)
printf("SERVER: error when trying to enable SO_REUSEPORT\n");
struct sockaddr_in addr = {0};
2022-08-29 18:06:25 -05:00
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
2022-08-29 17:27:03 -05:00
panicf("Couldn't bind to the socket\n");
}
2022-08-29 18:06:25 -05:00
if (listen(sock, 16) != 0) {
2022-08-29 17:27:03 -05:00
panicf("Couldn't listen on socket\n");
}
2022-08-29 17:27:03 -05:00
uint32_t ids = 0;
2022-08-29 18:06:25 -05:00
while (1) {
struct sockaddr con_addr;
socklen_t con_len = sizeof(con_addr);
2022-08-29 17:27:03 -05:00
struct Connection conn;
conn.socket = accept(sock, &con_addr, &con_len);
2022-10-12 12:33:18 -05:00
conn.closed = false;
2022-08-29 17:27:03 -05:00
2022-08-29 18:06:25 -05:00
if (conn.socket >= 0) {
2022-08-30 17:54:56 -05:00
printf("SERVER: got connection\n");
2022-08-29 17:27:03 -05:00
conn.id = ids++;
2022-08-29 18:06:25 -05:00
struct Connection *conn_ptr = malloc(sizeof(struct Connection));
2022-08-29 17:27:03 -05:00
memcpy(conn_ptr, &conn, sizeof(struct Connection));
pthread_t thread;
pthread_create(&thread, NULL, server_handle_conn, conn_ptr);
} else {
printf("Couldn't accept connection (%d)\n", conn.socket);
}
}
}