do things for refractor
This commit is contained in:
parent
ba38bf705a
commit
9aecac6010
18
Makefile
18
Makefile
|
@ -1,7 +1,11 @@
|
||||||
Q=@
|
Q=@
|
||||||
CC=gcc
|
CC=clang
|
||||||
CFLAGS=-std=c11 -pedantic -g -Wall -Wno-format-truncation -pthread -lm -D_GNU_SOURCE
|
|
||||||
LDFLAGS=-lm
|
GCCCFLAGS=-Wno-format-truncation
|
||||||
|
CLANGCFLAGS=-fsanitize=memory
|
||||||
|
CFLAGS=-std=c11 -pedantic -g -Wall -pthread -D_GNU_SOURCE
|
||||||
|
LDFLAGS=-lm -fsanitize=memory
|
||||||
|
|
||||||
BUILD_DIR=./objects
|
BUILD_DIR=./objects
|
||||||
BIN=jsfw
|
BIN=jsfw
|
||||||
|
|
||||||
|
@ -11,6 +15,14 @@ SOURCES=$(wildcard *.c)
|
||||||
|
|
||||||
OBJECTS:=$(patsubst %.c,$(BUILD_DIR)/%.o,$(SOURCES))
|
OBJECTS:=$(patsubst %.c,$(BUILD_DIR)/%.o,$(SOURCES))
|
||||||
|
|
||||||
|
ifeq ($(CC),gcc)
|
||||||
|
CFLAGS:=$(CFLAGS) $(GCCCFLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CC),clang)
|
||||||
|
CFLAGS:=$(CFLAGS) $(CLANGCFLAGS)
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: $(BIN)
|
run: $(BIN)
|
||||||
@echo "RUN $(BIN) $(RUNARGS)"
|
@echo "RUN $(BIN) $(RUNARGS)"
|
||||||
|
|
28
client.c
28
client.c
|
@ -94,7 +94,7 @@ static const JSONAdapter ConfigAdapter = {
|
||||||
.size = sizeof(ClientConfig),
|
.size = sizeof(ClientConfig),
|
||||||
};
|
};
|
||||||
|
|
||||||
void destroy_devices() {
|
void destroy_devices(void) {
|
||||||
for (int i = 0; i < config.controller_count; i++) {
|
for (int i = 0; i < config.controller_count; i++) {
|
||||||
int fd = *(int *)vec_get(&devices_fd, i);
|
int fd = *(int *)vec_get(&devices_fd, i);
|
||||||
MessageDeviceInfo *info = vec_get(&devices_info, i);
|
MessageDeviceInfo *info = vec_get(&devices_info, i);
|
||||||
|
@ -245,7 +245,7 @@ void device_handle_report(MessageDeviceReport *report) {
|
||||||
device_emit(report->index, EV_SYN, 0, 0);
|
device_emit(report->index, EV_SYN, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_devices() {
|
void setup_devices(void) {
|
||||||
devices_fd = vec_of(int);
|
devices_fd = vec_of(int);
|
||||||
devices_info = vec_of(MessageDeviceInfo);
|
devices_info = vec_of(MessageDeviceInfo);
|
||||||
|
|
||||||
|
@ -264,10 +264,10 @@ void setup_devices() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_fifo();
|
void setup_fifo(void);
|
||||||
|
|
||||||
// (Re)Open the fifo
|
// (Re)Open the fifo
|
||||||
void open_fifo() {
|
void open_fifo(void) {
|
||||||
close(fifo);
|
close(fifo);
|
||||||
fifo = open(config.fifo_path, O_RDONLY | O_NONBLOCK);
|
fifo = open(config.fifo_path, O_RDONLY | O_NONBLOCK);
|
||||||
if (fifo < 0 && fifo_attempt == 0) {
|
if (fifo < 0 && fifo_attempt == 0) {
|
||||||
|
@ -281,7 +281,7 @@ void open_fifo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the fifo exists and opens it (also setup poll_fd)
|
// Ensure the fifo exists and opens it (also setup poll_fd)
|
||||||
void setup_fifo() {
|
void setup_fifo(void) {
|
||||||
mode_t prev = umask(0);
|
mode_t prev = umask(0);
|
||||||
mkfifo(config.fifo_path, 0666);
|
mkfifo(config.fifo_path, 0666);
|
||||||
umask(prev);
|
umask(prev);
|
||||||
|
@ -293,7 +293,7 @@ void setup_fifo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// (Re)Connect to the server
|
// (Re)Connect to the server
|
||||||
void connect_server() {
|
void connect_server(void) {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (sock > 0) {
|
if (sock > 0) {
|
||||||
// Close previous connection
|
// Close previous connection
|
||||||
|
@ -319,7 +319,7 @@ void connect_server() {
|
||||||
socket_poll->fd = sock;
|
socket_poll->fd = sock;
|
||||||
printf("CLIENT: Connected !\n");
|
printf("CLIENT: Connected !\n");
|
||||||
|
|
||||||
uint8_t buf[2048] __attribute__((aligned(4)));
|
uint8_t buf[2048] __attribute__((aligned(4))) = {0};
|
||||||
|
|
||||||
int len = msg_serialize(buf, 2048, (Message *)&device_request);
|
int len = msg_serialize(buf, 2048, (Message *)&device_request);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
|
@ -350,7 +350,7 @@ void setup_server(char *address, uint16_t port) {
|
||||||
connect_server();
|
connect_server();
|
||||||
}
|
}
|
||||||
|
|
||||||
void build_device_request() {
|
void build_device_request(void) {
|
||||||
char **tags = malloc(config.controller_count * sizeof(char *));
|
char **tags = malloc(config.controller_count * sizeof(char *));
|
||||||
for (int i = 0; i < config.controller_count; i++) {
|
for (int i = 0; i < config.controller_count; i++) {
|
||||||
tags[i] = config.controllers[i].tag;
|
tags[i] = config.controllers[i].tag;
|
||||||
|
@ -387,8 +387,8 @@ void client_run(char *address, uint16_t port, char *config_path) {
|
||||||
|
|
||||||
setup_fifo();
|
setup_fifo();
|
||||||
build_device_request();
|
build_device_request();
|
||||||
setup_server(address, port);
|
|
||||||
setup_devices();
|
setup_devices();
|
||||||
|
setup_server(address, port);
|
||||||
|
|
||||||
uint8_t buf[2048] __attribute__((aligned(4)));
|
uint8_t buf[2048] __attribute__((aligned(4)));
|
||||||
uint8_t json_buf[2048] __attribute__((aligned(8)));
|
uint8_t json_buf[2048] __attribute__((aligned(8)));
|
||||||
|
@ -429,7 +429,7 @@ void client_run(char *address, uint16_t port, char *config_path) {
|
||||||
|
|
||||||
// A broken or closed socket produces a POLLIN event, so we check for error on the recv
|
// A broken or closed socket produces a POLLIN event, so we check for error on the recv
|
||||||
if (socket_poll->revents & POLLIN) {
|
if (socket_poll->revents & POLLIN) {
|
||||||
int len = recv(sock, buf, 2048, 0);
|
int len = recv(sock, buf, 2048, MSG_PEEK);
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
printf("CLIENT: Lost connection to server, reconnecting\n");
|
printf("CLIENT: Lost connection to server, reconnecting\n");
|
||||||
connect_server();
|
connect_server();
|
||||||
|
@ -438,9 +438,11 @@ void client_run(char *address, uint16_t port, char *config_path) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msg_len = msg_deserialize(buf, len, &message);
|
||||||
// We've got data from the server
|
// We've got data from the server
|
||||||
if (msg_deserialize(buf, len, &message) != 0) {
|
if (msg_len < 0) {
|
||||||
printf("CLIENT: Couldn't parse message (code: %d, len: %d)\n", buf[0], len);
|
recv(sock, buf, 2048, 0);
|
||||||
|
printf("CLIENT: Couldn't parse message (code: %d, len: %d)\n", buf[4], len);
|
||||||
|
|
||||||
int l = len > 100 ? 100 : len;
|
int l = len > 100 ? 100 : len;
|
||||||
for (int i = 0; i < l; i++) {
|
for (int i = 0; i < l; i++) {
|
||||||
|
@ -455,6 +457,8 @@ void client_run(char *address, uint16_t port, char *config_path) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recv(sock, buf, msg_len, 0);
|
||||||
|
|
||||||
if (message.code == DeviceInfo) {
|
if (message.code == DeviceInfo) {
|
||||||
if (device_exists(message.device_info.index)) {
|
if (device_exists(message.device_info.index)) {
|
||||||
printf("CLIENT: Got more than one device info for same device\n");
|
printf("CLIENT: Got more than one device info for same device\n");
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
{
|
{
|
||||||
"controllers": [
|
"controllers": [
|
||||||
{
|
{
|
||||||
"tag": "Admin",
|
"tag": "Mouse",
|
||||||
"vendor": "054c",
|
"vendor": "6969",
|
||||||
"product": "09cc",
|
"product": "0001",
|
||||||
"name": "JSFW PS4 Controller (Admin)"
|
"name": "JSFW Mouse"
|
||||||
},
|
|
||||||
{
|
|
||||||
"tag": "User",
|
|
||||||
"vendor": "6942",
|
|
||||||
"product": "1337",
|
|
||||||
"name": "JSFW PS4 Controller (User)"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fifo_path": "/tmp/jsfw_fifo_2",
|
"fifo_path": "/tmp/jsfw_fifo_2",
|
||||||
"retry_delay": 2.5
|
"retry_delay": 1
|
||||||
}
|
}
|
||||||
|
|
70
hid.c
70
hid.c
|
@ -18,7 +18,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
// List of uniq of the currently known devices
|
// List of ids of the currently known devices
|
||||||
static Vec known_devices;
|
static Vec known_devices;
|
||||||
// Queue of available devices, devices that can only be given to one client
|
// Queue of available devices, devices that can only be given to one client
|
||||||
static Vec available_devices;
|
static Vec available_devices;
|
||||||
|
@ -119,7 +119,7 @@ void setup_device(PhysicalDevice *dev) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filter_event(int fd, char *event, ControllerFilter *filter) {
|
bool filter_event(int fd, char *event, ControllerFilter *filter, uniq_t uniq) {
|
||||||
if (filter->js) {
|
if (filter->js) {
|
||||||
char device_path[64];
|
char device_path[64];
|
||||||
snprintf(device_path, 64, "/sys/class/input/%s/device", event);
|
snprintf(device_path, 64, "/sys/class/input/%s/device", event);
|
||||||
|
@ -142,6 +142,18 @@ bool filter_event(int fd, char *event, ControllerFilter *filter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter->name != NULL) {
|
||||||
|
char name[256] = {0};
|
||||||
|
ioctl(fd, EVIOCGNAME(256), name);
|
||||||
|
if (strcmp(name, filter->name) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter->uniq > 0 && uniq != filter->uniq) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct input_id ids;
|
struct input_id ids;
|
||||||
ioctl(fd, EVIOCGID, &ids);
|
ioctl(fd, EVIOCGID, &ids);
|
||||||
|
|
||||||
|
@ -154,18 +166,25 @@ bool filter_event(int fd, char *event, ControllerFilter *filter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize vectors for polling
|
// Initialize vectors for polling
|
||||||
void poll_devices_init() {
|
void poll_devices_init(void) {
|
||||||
known_devices = vec_of(Controller);
|
known_devices = vec_of(Controller);
|
||||||
cloneable_devices = vec_of(Controller *);
|
cloneable_devices = vec_of(Controller *);
|
||||||
available_devices = vec_of(Controller *);
|
available_devices = vec_of(Controller *);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block to get a device, this is thread safe
|
// Block to get a device, this is thread safe
|
||||||
Controller *get_device(char *tag) {
|
// stop: additional condition to check before doing anything,
|
||||||
|
// if the condition is ever found to be true the function will return immediately with a NULL pointer.
|
||||||
|
Controller *get_device(char *tag, bool *stop) {
|
||||||
// Check if we can get one right away
|
// Check if we can get one right away
|
||||||
pthread_mutex_lock(&devices_mutex);
|
pthread_mutex_lock(&devices_mutex);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (*stop) {
|
||||||
|
pthread_mutex_unlock(&devices_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < available_devices.len; i++) {
|
for (int i = 0; i < available_devices.len; i++) {
|
||||||
Controller *c = *(Controller **)vec_get(&available_devices, i);
|
Controller *c = *(Controller **)vec_get(&available_devices, i);
|
||||||
if (strcmp(c->ctr.tag, tag) == 0) {
|
if (strcmp(c->ctr.tag, tag) == 0) {
|
||||||
|
@ -210,7 +229,7 @@ void forget_device(Controller *c) {
|
||||||
pthread_mutex_lock(&devices_mutex);
|
pthread_mutex_lock(&devices_mutex);
|
||||||
for (int i = 0; i < cloneable_devices.len; i++) {
|
for (int i = 0; i < cloneable_devices.len; i++) {
|
||||||
Controller *d = *(Controller **)vec_get(&cloneable_devices, i);
|
Controller *d = *(Controller **)vec_get(&cloneable_devices, i);
|
||||||
if (d->dev.uniq == c->dev.uniq) {
|
if (d->dev.id == c->dev.id) {
|
||||||
vec_remove(&cloneable_devices, i, NULL);
|
vec_remove(&cloneable_devices, i, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -220,10 +239,10 @@ void forget_device(Controller *c) {
|
||||||
|
|
||||||
// Free the name if it was allocated
|
// Free the name if it was allocated
|
||||||
if (c->dev.name != NULL && c->dev.name != DEVICE_DEFAULT_NAME) {
|
if (c->dev.name != NULL && c->dev.name != DEVICE_DEFAULT_NAME) {
|
||||||
printf("HID: Forgetting device '%s' (%012lx)\n", c->dev.name, c->dev.uniq);
|
printf("HID: Forgetting device '%s' (%016lx)\n", c->dev.name, c->dev.id);
|
||||||
free(c->dev.name);
|
free(c->dev.name);
|
||||||
} else {
|
} else {
|
||||||
printf("HID: Forgetting device %012lx\n", c->dev.uniq);
|
printf("HID: Forgetting device %016lx\n", c->dev.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to close the file descriptor, they may be already closed if the device was unpugged.
|
// try to close the file descriptor, they may be already closed if the device was unpugged.
|
||||||
|
@ -234,7 +253,7 @@ void forget_device(Controller *c) {
|
||||||
pthread_mutex_lock(&known_devices_mutex);
|
pthread_mutex_lock(&known_devices_mutex);
|
||||||
for (int i = 0; i < known_devices.len; i++) {
|
for (int i = 0; i < known_devices.len; i++) {
|
||||||
Controller *d = vec_get(&known_devices, i);
|
Controller *d = vec_get(&known_devices, i);
|
||||||
if (d->dev.uniq == c->dev.uniq) {
|
if (d->dev.id == c->dev.id) {
|
||||||
vec_remove(&known_devices, i, NULL);
|
vec_remove(&known_devices, i, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -243,7 +262,7 @@ void forget_device(Controller *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all available devices and pick up on new ones
|
// Find all available devices and pick up on new ones
|
||||||
void poll_devices() {
|
void poll_devices(void) {
|
||||||
// loop over all entries of /sys/class/input
|
// loop over all entries of /sys/class/input
|
||||||
DIR *input_dir = opendir("/sys/class/input");
|
DIR *input_dir = opendir("/sys/class/input");
|
||||||
struct dirent *input;
|
struct dirent *input;
|
||||||
|
@ -256,6 +275,7 @@ void poll_devices() {
|
||||||
|
|
||||||
PhysicalDevice dev;
|
PhysicalDevice dev;
|
||||||
dev.hidraw = -1;
|
dev.hidraw = -1;
|
||||||
|
dev.uniq = 0;
|
||||||
|
|
||||||
// Open /dev/input/eventXX
|
// Open /dev/input/eventXX
|
||||||
{
|
{
|
||||||
|
@ -280,6 +300,14 @@ void poll_devices() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to get uniq, drop device if we can't
|
||||||
|
{
|
||||||
|
char uniq_str[17] = {0};
|
||||||
|
|
||||||
|
ioctl(dev.event, EVIOCGUNIQ(17), uniq_str);
|
||||||
|
dev.uniq = parse_uniq(uniq_str);
|
||||||
|
}
|
||||||
|
|
||||||
// Used for linear searches
|
// Used for linear searches
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
|
@ -290,7 +318,7 @@ void poll_devices() {
|
||||||
for (int i = 0; i < config->controller_count; i++) {
|
for (int i = 0; i < config->controller_count; i++) {
|
||||||
ctr = &config->controllers[i];
|
ctr = &config->controllers[i];
|
||||||
|
|
||||||
if (filter_event(dev.event, input->d_name, &ctr->filter)) {
|
if (filter_event(dev.event, input->d_name, &ctr->filter, dev.uniq)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -301,17 +329,11 @@ void poll_devices() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to get uniq, drop device if we can't
|
// Get the id
|
||||||
{
|
{
|
||||||
char uniq_str[17] = {0};
|
struct input_id id;
|
||||||
|
ioctl(dev.event, EVIOCGID, &id);
|
||||||
ioctl(dev.event, EVIOCGUNIQ(17), uniq_str);
|
dev.id = *(uint64_t *)&id;
|
||||||
dev.uniq = parse_uniq(uniq_str);
|
|
||||||
|
|
||||||
// If we couldn't parse the uniq (this assumes uniq can't be zero, which is probably alright)
|
|
||||||
if (dev.uniq == 0) {
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we already know of this device
|
// Check if we already know of this device
|
||||||
|
@ -321,7 +343,7 @@ void poll_devices() {
|
||||||
pthread_mutex_lock(&known_devices_mutex);
|
pthread_mutex_lock(&known_devices_mutex);
|
||||||
for (int i = 0; i < known_devices.len; i++) {
|
for (int i = 0; i < known_devices.len; i++) {
|
||||||
Controller *c = vec_get(&known_devices, i);
|
Controller *c = vec_get(&known_devices, i);
|
||||||
if (c->dev.uniq == dev.uniq) {
|
if (c->dev.id == dev.id) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +412,7 @@ void poll_devices() {
|
||||||
// Pointer to the device in known_devices
|
// Pointer to the device in known_devices
|
||||||
Controller *p = vec_get(&known_devices, index);
|
Controller *p = vec_get(&known_devices, index);
|
||||||
|
|
||||||
printf("HID: New device, %s [%s] (%s: %012lx)\n", name, ctr->tag, input->d_name, dev.uniq);
|
printf("HID: New device, %s [%s] (%s: %016lx)\n", name, ctr->tag, input->d_name, dev.id);
|
||||||
|
|
||||||
if (ctr->duplicate) {
|
if (ctr->duplicate) {
|
||||||
pthread_mutex_lock(&devices_mutex);
|
pthread_mutex_lock(&devices_mutex);
|
||||||
|
@ -419,11 +441,11 @@ void poll_devices() {
|
||||||
// "Execute" a MessageControllerState: set the led color, rumble and flash using the hidraw interface (Dualshock 4 only)
|
// "Execute" a MessageControllerState: set the led color, rumble and flash using the hidraw interface (Dualshock 4 only)
|
||||||
void apply_controller_state(Controller *c, MessageControllerState *state) {
|
void apply_controller_state(Controller *c, MessageControllerState *state) {
|
||||||
if (c->ctr.ps4_hidraw && c->dev.hidraw < 0) {
|
if (c->ctr.ps4_hidraw && c->dev.hidraw < 0) {
|
||||||
printf("HID: Trying to apply controller state on incompatible device (%012lx)\n", c->dev.uniq);
|
printf("HID: Trying to apply controller state on incompatible device (%016lx)\n", c->dev.id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("HID: (%012lx) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.uniq, state->led[0],
|
printf("HID: (%016lx) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.id, state->led[0],
|
||||||
state->led[1], state->led[2], state->flash_on, state->flash_off, state->small_rumble, state->big_rumble);
|
state->led[1], state->led[2], state->flash_on, state->flash_off, state->small_rumble, state->big_rumble);
|
||||||
|
|
||||||
uint8_t buf[32] = {0x05, 0xff, 0x00, 0x00};
|
uint8_t buf[32] = {0x05, 0xff, 0x00, 0x00};
|
||||||
|
|
3
hid.h
3
hid.h
|
@ -25,6 +25,7 @@ typedef struct {
|
||||||
int event;
|
int event;
|
||||||
int hidraw;
|
int hidraw;
|
||||||
uniq_t uniq;
|
uniq_t uniq;
|
||||||
|
uint64_t id;
|
||||||
char *name;
|
char *name;
|
||||||
DeviceMap mapping;
|
DeviceMap mapping;
|
||||||
MessageDeviceInfo device_info;
|
MessageDeviceInfo device_info;
|
||||||
|
@ -38,7 +39,7 @@ typedef struct {
|
||||||
void *hid_thread(void *arg);
|
void *hid_thread(void *arg);
|
||||||
void return_device(Controller *c);
|
void return_device(Controller *c);
|
||||||
void forget_device(Controller *c);
|
void forget_device(Controller *c);
|
||||||
Controller *get_device(char *tag);
|
Controller *get_device(char *tag, bool *stop);
|
||||||
void apply_controller_state(Controller *c, MessageControllerState *state);
|
void apply_controller_state(Controller *c, MessageControllerState *state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
6
json.c
6
json.c
|
@ -16,11 +16,11 @@ static JSONError jerrno = NoError;
|
||||||
static size_t jerr_index = 0;
|
static size_t jerr_index = 0;
|
||||||
|
|
||||||
// Get a string explaining the last json parsing error
|
// Get a string explaining the last json parsing error
|
||||||
const char *json_strerr() { return JSONErrorMessage[jerrno]; }
|
const char *json_strerr(void) { return JSONErrorMessage[jerrno]; }
|
||||||
// Get the code of the last json parsing error
|
// Get the code of the last json parsing error
|
||||||
JSONError json_errno() { return jerrno; }
|
JSONError json_errno(void) { return jerrno; }
|
||||||
// Get the location of the last json parsing error
|
// Get the location of the last json parsing error
|
||||||
size_t json_errloc() { return jerr_index; }
|
size_t json_errloc(void) { return jerr_index; }
|
||||||
|
|
||||||
static inline bool is_primitive(const JSONAdapter *adapter) { return adapter->props == NULL; }
|
static inline bool is_primitive(const JSONAdapter *adapter) { return adapter->props == NULL; }
|
||||||
|
|
||||||
|
|
6
json.h
6
json.h
|
@ -60,9 +60,9 @@ typedef struct JSONAdapter JSONAdapter;
|
||||||
void json_adapt(uint8_t *buf, const JSONAdapter *adapter, void *ptr);
|
void json_adapt(uint8_t *buf, const JSONAdapter *adapter, void *ptr);
|
||||||
int json_parse(const char *src, size_t src_len, uint8_t *dst, size_t dst_len);
|
int json_parse(const char *src, size_t src_len, uint8_t *dst, size_t dst_len);
|
||||||
void json_print_value(uint8_t *buf);
|
void json_print_value(uint8_t *buf);
|
||||||
const char *json_strerr();
|
const char *json_strerr(void);
|
||||||
size_t json_errloc();
|
size_t json_errloc(void);
|
||||||
JSONError json_errno();
|
JSONError json_errno(void);
|
||||||
|
|
||||||
extern const JSONAdapter NumberAdapter;
|
extern const JSONAdapter NumberAdapter;
|
||||||
extern const JSONAdapter StringAdapter;
|
extern const JSONAdapter StringAdapter;
|
||||||
|
|
118
net.c
118
net.c
|
@ -5,15 +5,30 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
// Deserialize the message in buf, buf must be at least 4 aligned. Returns -1 on error, otherwise returns 0
|
// Deserialize the message in buf, buf must be at least 4 aligned. Returns -1 on error, otherwise returns 0
|
||||||
// and writes result to dst
|
// and writes result to dst
|
||||||
int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
||||||
|
{
|
||||||
|
if(len <= MAGIC_SIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*(MAGIC_TYPE*)buf != MAGIC_BEG) {
|
||||||
|
printf("NET: No magic in message\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf += MAGIC_SIZE;
|
||||||
|
len -= MAGIC_SIZE;
|
||||||
|
}
|
||||||
// Decrement len so that it becomes the len of the data without the code.
|
// Decrement len so that it becomes the len of the data without the code.
|
||||||
if (len-- < 1)
|
if (len-- < 1)
|
||||||
return -1;
|
return -1;
|
||||||
// This ensures that only a byte is read instead of a full enum value
|
// This ensures that only a byte is read instead of a full enum value
|
||||||
uint8_t code_byte = buf[0];
|
uint8_t code_byte = buf[0];
|
||||||
MessageCode code = (MessageCode)code_byte;
|
MessageCode code = (MessageCode)code_byte;
|
||||||
|
uint32_t size = 0;
|
||||||
|
|
||||||
uint16_t abs, rel, key, index, *buf16;
|
uint16_t abs, rel, key, index, *buf16;
|
||||||
|
|
||||||
|
@ -62,7 +77,8 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
||||||
buf += 2;
|
buf += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
size = MSS_DEVICE_INFO(abs, rel, key) + 1;
|
||||||
|
break;
|
||||||
case DeviceReport:
|
case DeviceReport:
|
||||||
if (len < 7)
|
if (len < 7)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -96,7 +112,10 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
||||||
for (int i = 0; i < key; i++)
|
for (int i = 0; i < key; i++)
|
||||||
dst->device_report.key[i] = *(buf++);
|
dst->device_report.key[i] = *(buf++);
|
||||||
|
|
||||||
return 0;
|
buf += align_4(key) - key;
|
||||||
|
|
||||||
|
size = MSS_DEVICE_REPORT(abs, rel, key) + 1;
|
||||||
|
break;
|
||||||
case ControllerState:
|
case ControllerState:
|
||||||
if (len < MSS_CONTROLLER_STATE)
|
if (len < MSS_CONTROLLER_STATE)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -110,7 +129,9 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
||||||
dst->controller_state.big_rumble = buf[8];
|
dst->controller_state.big_rumble = buf[8];
|
||||||
dst->controller_state.flash_on = buf[9];
|
dst->controller_state.flash_on = buf[9];
|
||||||
dst->controller_state.flash_off = buf[10];
|
dst->controller_state.flash_off = buf[10];
|
||||||
return 0;
|
size = MSS_CONTROLLER_STATE + 1;
|
||||||
|
buf += size;
|
||||||
|
break;
|
||||||
case Request: {
|
case Request: {
|
||||||
if (len < 3)
|
if (len < 3)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -138,16 +159,19 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str = malloc(str_len + 1);
|
char *str = malloc(str_len + 1);
|
||||||
str[len] = '\0';
|
str[str_len] = '\0';
|
||||||
|
|
||||||
strncpy(str, (char *)buf, str_len);
|
strncpy(str, (char *)buf, str_len);
|
||||||
|
|
||||||
|
tags[i] = str;
|
||||||
|
|
||||||
buf += align_2(str_len);
|
buf += align_2(str_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
dst->request.requests = tags;
|
dst->request.requests = tags;
|
||||||
return 0;
|
size = expected_len + 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case DeviceDestroy:
|
case DeviceDestroy:
|
||||||
if (len < MSS_DESTROY)
|
if (len < MSS_DESTROY)
|
||||||
|
@ -155,19 +179,37 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) {
|
||||||
|
|
||||||
dst->code = code;
|
dst->code = code;
|
||||||
dst->destroy.index = *(uint16_t *)(buf + 2);
|
dst->destroy.index = *(uint16_t *)(buf + 2);
|
||||||
return 0;
|
size = MSS_DESTROY + 1;
|
||||||
|
buf += size;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(size + MAGIC_SIZE > len + 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*(MAGIC_TYPE*)buf != MAGIC_END) {
|
||||||
|
printf("NET: Magic not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size + 2 * MAGIC_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the message msg in buf, buf must be at least 4 aligned. Returns -1 on error (buf not big enough);
|
// Serialize the message msg in buf, buf must be at least 4 aligned. Returns -1 on error (buf not big enough);
|
||||||
int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
||||||
// If len is 0 we can't serialize any message
|
// If len is less than the two magic and the code we can't serialize any message
|
||||||
if (len-- == 0)
|
if (len < MAGIC_SIZE * 2 + 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
*(MAGIC_TYPE*)buf = MAGIC_BEG;
|
||||||
|
buf += MAGIC_SIZE;
|
||||||
|
len -= MAGIC_SIZE + 1;
|
||||||
|
|
||||||
uint16_t abs, rel, key, *buf16;
|
uint16_t abs, rel, key, *buf16;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
switch (msg->code) {
|
switch (msg->code) {
|
||||||
case DeviceInfo:
|
case DeviceInfo:
|
||||||
|
@ -214,7 +256,8 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
||||||
buf += 2;
|
buf += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MSS_DEVICE_INFO(abs, rel, key) + 1;
|
size = MSS_DEVICE_INFO(abs, rel, key) + 1;
|
||||||
|
break;
|
||||||
case DeviceReport:
|
case DeviceReport:
|
||||||
abs = msg->device_report.abs_count;
|
abs = msg->device_report.abs_count;
|
||||||
rel = msg->device_report.rel_count;
|
rel = msg->device_report.rel_count;
|
||||||
|
@ -244,7 +287,9 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
||||||
for (int i = 0; i < key; i++)
|
for (int i = 0; i < key; i++)
|
||||||
*(buf++) = msg->device_report.key[i];
|
*(buf++) = msg->device_report.key[i];
|
||||||
|
|
||||||
return MSS_DEVICE_REPORT(abs, rel, key) + 1;
|
size = MSS_DEVICE_REPORT(abs, rel, key) + 1;
|
||||||
|
buf += align_4(key) - key;
|
||||||
|
break;
|
||||||
case ControllerState:
|
case ControllerState:
|
||||||
if (len < MSS_CONTROLLER_STATE)
|
if (len < MSS_CONTROLLER_STATE)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -260,7 +305,9 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
||||||
buf[8] = msg->controller_state.big_rumble;
|
buf[8] = msg->controller_state.big_rumble;
|
||||||
buf[9] = msg->controller_state.flash_on;
|
buf[9] = msg->controller_state.flash_on;
|
||||||
buf[10] = msg->controller_state.flash_off;
|
buf[10] = msg->controller_state.flash_off;
|
||||||
return MSS_CONTROLLER_STATE + 1;
|
size = MSS_CONTROLLER_STATE + 1;
|
||||||
|
buf += size;
|
||||||
|
break;
|
||||||
case Request: {
|
case Request: {
|
||||||
int expected_len = MSS_REQUEST(msg->request.request_count);
|
int expected_len = MSS_REQUEST(msg->request.request_count);
|
||||||
if (len < expected_len)
|
if (len < expected_len)
|
||||||
|
@ -279,7 +326,7 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
||||||
*buf16++ = str_len;
|
*buf16++ = str_len;
|
||||||
buf = (uint8_t *)buf16;
|
buf = (uint8_t *)buf16;
|
||||||
|
|
||||||
expected_len += byte_len;
|
expected_len += byte_len + 2;
|
||||||
if (len < expected_len) {
|
if (len < expected_len) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -290,7 +337,8 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
||||||
buf16 = (uint16_t *)buf;
|
buf16 = (uint16_t *)buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
return expected_len;
|
size = expected_len;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case DeviceDestroy:
|
case DeviceDestroy:
|
||||||
if (len < MSS_DESTROY)
|
if (len < MSS_DESTROY)
|
||||||
|
@ -299,11 +347,21 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) {
|
||||||
buf[0] = (uint8_t)msg->code;
|
buf[0] = (uint8_t)msg->code;
|
||||||
|
|
||||||
*(uint16_t *)(buf + 2) = msg->controller_state.index;
|
*(uint16_t *)(buf + 2) = msg->controller_state.index;
|
||||||
return MSS_DESTROY + 1;
|
size = MSS_DESTROY + 1;
|
||||||
|
buf += size;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("ERR(msg_serialize): Trying to serialize unknown message of code %d\n", msg->code);
|
printf("ERR(msg_serialize): Trying to serialize unknown message of code %d\n", msg->code);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(size + MAGIC_SIZE > len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(MAGIC_TYPE*)buf = MAGIC_END;
|
||||||
|
|
||||||
|
return size + MAGIC_SIZE * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void msg_free(Message *msg) {
|
void msg_free(Message *msg) {
|
||||||
|
@ -314,3 +372,29 @@ void msg_free(Message *msg) {
|
||||||
free(msg->request.requests);
|
free(msg->request.requests);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_message_buffer(const uint8_t * buf, int len) {
|
||||||
|
bool last_beg = false;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (i + MAGIC_SIZE <= len) {
|
||||||
|
MAGIC_TYPE magic = *(MAGIC_TYPE *)(&buf[i]);
|
||||||
|
if (magic == MAGIC_BEG) {
|
||||||
|
printf(" \033[32m%08X\033[0m", magic);
|
||||||
|
i += MAGIC_SIZE - 1;
|
||||||
|
last_beg = true;
|
||||||
|
continue;
|
||||||
|
} else if (magic == MAGIC_END) {
|
||||||
|
printf(" \033[32m%08X\033[0m", magic);
|
||||||
|
i += MAGIC_SIZE - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_beg) {
|
||||||
|
last_beg = false;
|
||||||
|
printf(" \033[034m%02X\033[0m", buf[i]);
|
||||||
|
} else {
|
||||||
|
printf(" %02X", buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
8
net.h
8
net.h
|
@ -5,6 +5,11 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define MAGIC_TYPE uint32_t
|
||||||
|
#define MAGIC_SIZE sizeof(MAGIC_TYPE)
|
||||||
|
static const MAGIC_TYPE MAGIC_BEG = 0xDEADCAFE;
|
||||||
|
static const MAGIC_TYPE MAGIC_END = 0xCAFEDEAD;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NoMessage = 0,
|
NoMessage = 0,
|
||||||
DeviceInfo = 1,
|
DeviceInfo = 1,
|
||||||
|
@ -55,7 +60,7 @@ typedef struct {
|
||||||
uint32_t rel[REL_CNT];
|
uint32_t rel[REL_CNT];
|
||||||
uint8_t key[KEY_CNT];
|
uint8_t key[KEY_CNT];
|
||||||
} MessageDeviceReport;
|
} MessageDeviceReport;
|
||||||
#define MSS_DEVICE_REPORT(abs, rel, key) (8 + abs * 4 + rel * 4 + key * 1 + 1)
|
#define MSS_DEVICE_REPORT(abs, rel, key) (11 + abs * 4 + rel * 4 + align_4(key))
|
||||||
|
|
||||||
// 1 aligned
|
// 1 aligned
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -99,5 +104,6 @@ typedef union {
|
||||||
int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst);
|
int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst);
|
||||||
int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg);
|
int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg);
|
||||||
void msg_free(Message *msg);
|
void msg_free(Message *msg);
|
||||||
|
void print_message_buffer(const uint8_t * buf, int len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
57
server.c
57
server.c
|
@ -26,6 +26,7 @@
|
||||||
struct Connection {
|
struct Connection {
|
||||||
int socket;
|
int socket;
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
bool closed;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeviceThreadArgs {
|
struct DeviceThreadArgs {
|
||||||
|
@ -39,10 +40,11 @@ static void default_timespec(void *ptr) { *(struct timespec *)ptr = POLL_DEVICE_
|
||||||
static void default_request_timeout(void *ptr) { *(uint32_t *)ptr = REQUEST_TIMEOUT; }
|
static void default_request_timeout(void *ptr) { *(uint32_t *)ptr = REQUEST_TIMEOUT; }
|
||||||
|
|
||||||
const JSONPropertyAdapter FilterAdapterProps[] = {
|
const JSONPropertyAdapter FilterAdapterProps[] = {
|
||||||
{".mac_address", &StringAdapter, offsetof(ControllerFilter, mac_address), default_to_zero_u64, tsf_strmac_to_u64},
|
{".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 },
|
{".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 },
|
{".product", &StringAdapter, offsetof(ControllerFilter, product), default_to_negative_one_i32, tsf_hex_to_i32 },
|
||||||
{".js", &BooleanAdapter, offsetof(ControllerFilter, js), default_to_false, NULL },
|
{".js", &BooleanAdapter, offsetof(ControllerFilter, js), default_to_false, NULL },
|
||||||
|
{".name", &StringAdapter, offsetof(ControllerFilter, name), default_to_null, NULL },
|
||||||
};
|
};
|
||||||
const JSONAdapter FilterAdapter = {
|
const JSONAdapter FilterAdapter = {
|
||||||
.props = FilterAdapterProps,
|
.props = FilterAdapterProps,
|
||||||
|
@ -80,12 +82,16 @@ static sigset_t empty_sigset;
|
||||||
#define TRAP(sig, handler) \
|
#define TRAP(sig, handler) \
|
||||||
if (sigaction(sig, &(struct sigaction){.sa_handler = handler, .sa_mask = empty_sigset, .sa_flags = 0}, NULL) != 0) \
|
if (sigaction(sig, &(struct sigaction){.sa_handler = handler, .sa_mask = empty_sigset, .sa_flags = 0}, NULL) != 0) \
|
||||||
printf("SERVER: can't trap " #sig ".\n")
|
printf("SERVER: can't trap " #sig ".\n")
|
||||||
|
#define TRAP_IGN(sig) \
|
||||||
|
if (sigaction(sig, &(struct sigaction){{SIG_IGN}}, NULL) != 0) \
|
||||||
|
printf("SERVER: can't ignore " #sig ".\n")
|
||||||
|
|
||||||
void device_thread_exit() {
|
void device_thread_exit(int _sig) {
|
||||||
struct DeviceThreadArgs *args = pthread_getspecific(device_args_key);
|
struct DeviceThreadArgs *args = pthread_getspecific(device_args_key);
|
||||||
|
printf("CONN(%d): [%d] exiting\n", args->conn->id, args->index);
|
||||||
|
|
||||||
Controller * ctr = *args->controller;
|
Controller *ctr = *args->controller;
|
||||||
if(ctr != NULL) {
|
if (ctr != NULL) {
|
||||||
return_device(ctr);
|
return_device(ctr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +105,7 @@ void *device_thread(void *args_) {
|
||||||
|
|
||||||
pthread_setspecific(device_args_key, args);
|
pthread_setspecific(device_args_key, args);
|
||||||
|
|
||||||
|
TRAP_IGN(SIGPIPE);
|
||||||
TRAP(SIGTERM, device_thread_exit);
|
TRAP(SIGTERM, device_thread_exit);
|
||||||
|
|
||||||
uint8_t buf[2048] __attribute__((aligned(4))) = {0};
|
uint8_t buf[2048] __attribute__((aligned(4))) = {0};
|
||||||
|
@ -106,13 +113,16 @@ void *device_thread(void *args_) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
*args->controller = NULL;
|
*args->controller = NULL;
|
||||||
Controller *ctr = get_device(args->tag);
|
Controller *ctr = get_device(args->tag, &args->conn->closed);
|
||||||
|
if(ctr == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
*args->controller = ctr;
|
*args->controller = ctr;
|
||||||
dev_info = ctr->dev.device_info;
|
dev_info = ctr->dev.device_info;
|
||||||
dev_info.index = args->index;
|
dev_info.index = args->index;
|
||||||
|
|
||||||
printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%012lx)\n", args->conn->id, args->index, args->tag,
|
printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%016lx)\n", args->conn->id, args->index, args->tag,
|
||||||
ctr->dev.name, ctr->dev.uniq);
|
ctr->dev.name, ctr->dev.id);
|
||||||
|
|
||||||
// Send over device info
|
// Send over device info
|
||||||
{
|
{
|
||||||
|
@ -129,6 +139,7 @@ void *device_thread(void *args_) {
|
||||||
report.abs_count = ctr->dev.device_info.abs_count;
|
report.abs_count = ctr->dev.device_info.abs_count;
|
||||||
report.rel_count = ctr->dev.device_info.rel_count;
|
report.rel_count = ctr->dev.device_info.rel_count;
|
||||||
report.key_count = ctr->dev.device_info.key_count;
|
report.key_count = ctr->dev.device_info.key_count;
|
||||||
|
report.index = args->index;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
struct input_event event;
|
struct input_event event;
|
||||||
|
@ -188,7 +199,7 @@ void *device_thread(void *args_) {
|
||||||
// Send device destroy message
|
// Send device destroy message
|
||||||
{
|
{
|
||||||
MessageDestroy dstr;
|
MessageDestroy dstr;
|
||||||
dstr.code = DeviceDestroy;
|
dstr.code = DeviceDestroy;
|
||||||
dstr.index = args->index;
|
dstr.index = args->index;
|
||||||
|
|
||||||
int len = msg_serialize(buf, 2048, (Message *)&dstr);
|
int len = msg_serialize(buf, 2048, (Message *)&dstr);
|
||||||
|
@ -199,7 +210,7 @@ void *device_thread(void *args_) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
device_thread_exit();
|
device_thread_exit(SIGTERM);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,12 +266,24 @@ void *server_handle_conn(void *args_) {
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
closing_message = "Lost peer (from recv)";
|
closing_message = "Lost peer (from recv)";
|
||||||
goto conn_end;
|
goto conn_end;
|
||||||
|
} 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse message
|
// Parse message
|
||||||
Message msg;
|
Message msg;
|
||||||
if (msg_deserialize(buf, len, &msg) != 0) {
|
int msg_len = msg_deserialize(buf, len, &msg);
|
||||||
printf("CONN(%d): Couldn't parse message.\n", args->id);
|
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);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,18 +338,19 @@ void *server_handle_conn(void *args_) {
|
||||||
conn_end:
|
conn_end:
|
||||||
shutdown(args->socket, SHUT_RDWR);
|
shutdown(args->socket, SHUT_RDWR);
|
||||||
printf("CONN(%u): connection closed (%s)\n", args->id, closing_message);
|
printf("CONN(%u): connection closed (%s)\n", args->id, closing_message);
|
||||||
free(args);
|
args->closed = true;
|
||||||
for (int i = 0; i < device_threads.len; i++) {
|
for (int i = 0; i < device_threads.len; i++) {
|
||||||
pthread_t thread = *(pthread_t *)vec_get(&device_threads, i);
|
pthread_t thread = *(pthread_t *)vec_get(&device_threads, i);
|
||||||
pthread_kill(thread, SIGTERM);
|
pthread_kill(thread, SIGTERM);
|
||||||
pthread_join(thread, NULL);
|
pthread_join(thread, NULL);
|
||||||
}
|
}
|
||||||
|
free(args);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sockfd;
|
static int sockfd;
|
||||||
|
|
||||||
void clean_exit() {
|
void clean_exit(int _sig) {
|
||||||
printf("\rSERVER: exiting\n");
|
printf("\rSERVER: exiting\n");
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -405,6 +429,7 @@ void server_run(uint16_t port, char *config_path) {
|
||||||
struct Connection conn;
|
struct Connection conn;
|
||||||
|
|
||||||
conn.socket = accept(sock, &con_addr, &con_len);
|
conn.socket = accept(sock, &con_addr, &con_len);
|
||||||
|
conn.closed = false;
|
||||||
|
|
||||||
if (conn.socket >= 0) {
|
if (conn.socket >= 0) {
|
||||||
printf("SERVER: got connection\n");
|
printf("SERVER: got connection\n");
|
||||||
|
|
6
server.h
6
server.h
|
@ -6,13 +6,15 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// the 0 mac_address represents no filter
|
// the 0 uniq represents no filter
|
||||||
uint64_t mac_address;
|
uint64_t uniq;
|
||||||
// negative values means no filter
|
// negative values means no filter
|
||||||
int32_t vendor;
|
int32_t vendor;
|
||||||
// negative values means no filter
|
// negative values means no filter
|
||||||
int32_t product;
|
int32_t product;
|
||||||
bool js;
|
bool js;
|
||||||
|
// NULL means no filter
|
||||||
|
char * name;
|
||||||
} ControllerFilter;
|
} ControllerFilter;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -1,16 +1,7 @@
|
||||||
{
|
{
|
||||||
"controllers": [
|
"controllers": [
|
||||||
{
|
{
|
||||||
"filter": { "mac_address": "00:b0:d0:63:c2:26" },
|
"filter": { "name": "SteelSeries SteelSeries Rival 310 eSports Mouse" },
|
||||||
"tag": "Admin",
|
|
||||||
"properties": { "duplicate": true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filter": { "vendor": "054c", "product": "05c4", "js": true },
|
|
||||||
"tag": "User"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filter": { "vendor": "046d", "product": "c332"},
|
|
||||||
"tag": "Mouse"
|
"tag": "Mouse"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
6
util.c
6
util.c
|
@ -64,10 +64,10 @@ void tsf_numsec_to_intms(void *arg, void *ptr) {
|
||||||
*(uint32_t *)ptr = seconds * 1000;
|
*(uint32_t *)ptr = seconds * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tsf_strmac_to_u64(void *arg, void *ptr) {
|
void tsf_uniq_to_u64(void *arg, void *ptr) {
|
||||||
char *s = *(char **)arg;
|
char *s = *(char **)arg;
|
||||||
if (strnlen(s, 18) != 17) {
|
if (strnlen(s, 18) != 17) {
|
||||||
printf("JSON: wrong length for mac address, expected 'xx:xx:xx:xx:xx:xx'\n");
|
printf("JSON: wrong length for uniq, expected 'xx:xx:xx:xx:xx:xx'\n");
|
||||||
free(s);
|
free(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ void tsf_strmac_to_u64(void *arg, void *ptr) {
|
||||||
else if (c == ':')
|
else if (c == ':')
|
||||||
continue;
|
continue;
|
||||||
else {
|
else {
|
||||||
printf("JSON: unexpected character '%c' in mac address at position %i (%s)\n", c, i, s);
|
printf("JSON: unexpected character '%c' in uniq at position %i (%s)\n", c, i, s);
|
||||||
free(s);
|
free(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
6
util.h
6
util.h
|
@ -13,7 +13,9 @@ uint16_t parse_port(const char *str);
|
||||||
static inline bool bit_set(uint8_t *bits, int i) { return bits[i / 8] & (1 << (i % 8)); }
|
static inline bool bit_set(uint8_t *bits, int i) { return bits[i / 8] & (1 << (i % 8)); }
|
||||||
// Align n to the next 8 boundary
|
// Align n to the next 8 boundary
|
||||||
static inline size_t align_8(size_t n) { return (((n - 1) >> 3) + 1) << 3; }
|
static inline size_t align_8(size_t n) { return (((n - 1) >> 3) + 1) << 3; }
|
||||||
// Align n to the next 8 boundary
|
// Align n to the next 4 boundary
|
||||||
|
static inline size_t align_4(size_t n) { return (((n - 1) >> 2) + 1) << 2; }
|
||||||
|
// Align n to the next 2 boundary
|
||||||
static inline size_t align_2(size_t n) { return (((n - 1) >> 1) + 1) << 1; }
|
static inline size_t align_2(size_t n) { return (((n - 1) >> 1) + 1) << 1; }
|
||||||
uint8_t parse_hex_digit(char h);
|
uint8_t parse_hex_digit(char h);
|
||||||
|
|
||||||
|
@ -29,7 +31,7 @@ void default_to_negative_one_i32(void *ptr);
|
||||||
|
|
||||||
void tsf_numsec_to_timespec(void *arg, void *ptr);
|
void tsf_numsec_to_timespec(void *arg, void *ptr);
|
||||||
void tsf_numsec_to_intms(void *arg, void *ptr);
|
void tsf_numsec_to_intms(void *arg, void *ptr);
|
||||||
void tsf_strmac_to_u64(void *arg, void *ptr);
|
void tsf_uniq_to_u64(void *arg, void *ptr);
|
||||||
void tsf_hex_to_i32(void *arg, void *ptr);
|
void tsf_hex_to_i32(void *arg, void *ptr);
|
||||||
void tsf_double_to_size(void * arg, void * ptr);
|
void tsf_double_to_size(void * arg, void * ptr);
|
||||||
void tsf_hex_to_color(void *arg, void *ptr);
|
void tsf_hex_to_color(void *arg, void *ptr);
|
||||||
|
|
Loading…
Reference in New Issue