started pipe rewrite

This commit is contained in:
itsmattkc 2024-08-04 16:58:26 -07:00
parent 64de9e9b08
commit ce98f9d923
11 changed files with 176 additions and 713 deletions

View file

@ -13,8 +13,6 @@
#include <unistd.h>
#include <vanilla.h>
#include "../pipe/pipe.h"
void vanillaEventHandler(void *context, int type, const char *data, size_t dataLength)
{
Backend *backend = static_cast<Backend*>(context);
@ -46,76 +44,16 @@ BackendViaLocalRoot::BackendViaLocalRoot(const QString &wirelessInterface, QObje
m_wirelessInterface = wirelessInterface;
}
BackendViaPipe::BackendViaPipe(QObject *parent) : Backend(parent)
{
}
BackendViaSocket::BackendViaSocket(const QHostAddress &backendAddr, quint16 backendPort, QObject *parent) : BackendViaPipe(parent)
{
m_backendAddress = backendAddr;
m_backendPort = backendPort;
m_socket = new QUdpSocket(this);
connect(m_socket, &QUdpSocket::readyRead, this, &BackendViaSocket::readPendingDatagrams);
connect(m_socket, &QUdpSocket::disconnected, this, &BackendViaSocket::closed);
}
void BackendViaSocket::init()
{
bool connected = false;
for (m_frontendPort = 10100; m_frontendPort < 10200; m_frontendPort++) {
printf("Trying to bind to port %u\n", m_frontendPort);
if (m_socket->bind(QHostAddress::Any, m_frontendPort)) {
printf("Bound to port %u\n", m_frontendPort);
connected = true;
break;
}
}
if (connected) {
// Send bind command to backend
pipe_control_code cmd;
cmd.code = VANILLA_PIPE_IN_BIND;
writeToPipe(&cmd, sizeof(cmd));
} else {
printf("Failed to bind to port\n");
emit error(tr("Failed to bind to UDP port"));
emit closed();
}
}
void BackendViaPipe::quitPipe()
{
pipe_control_code cmd;
cmd.code = VANILLA_PIPE_IN_QUIT;
writeToPipe(&cmd, sizeof(cmd));
}
void BackendViaLocalRoot::interrupt()
{
vanilla_stop();
}
void BackendViaPipe::interrupt()
{
pipe_control_code cmd;
cmd.code = VANILLA_PIPE_IN_INTERRUPT;
writeToPipe(&cmd, sizeof(cmd));
}
void BackendViaLocalRoot::requestIDR()
{
vanilla_request_idr();
}
void BackendViaPipe::requestIDR()
{
pipe_control_code cmd;
cmd.code = VANILLA_PIPE_IN_REQ_IDR;
writeToPipe(&cmd, sizeof(cmd));
}
void BackendViaLocalRoot::connectToConsole()
{
QtConcurrent::run(connectInternal, this, m_wirelessInterface);
@ -127,98 +65,26 @@ int BackendViaLocalRoot::connectInternal(BackendViaLocalRoot *instance, const QS
return vanilla_connect_to_console(wirelessInterfaceC.constData(), vanillaEventHandler, instance);
}
void BackendViaPipe::processPacket(const QByteArray &arr)
{
const pipe_control_code *cc = (const pipe_control_code *) arr.data();
switch (cc->code) {
case VANILLA_PIPE_OUT_EOF:
// Do nothing?
break;
case VANILLA_PIPE_OUT_DATA:
{
pipe_data_command *event = (pipe_data_command *) cc;
event->data_size = ntohs(event->data_size);
vanillaEventHandler(this, event->event_type, (const char *) event->data, event->data_size);
break;
}
case VANILLA_PIPE_OUT_BOUND_SUCCESSFUL:
emit ready();
break;
case VANILLA_PIPE_ERR_SUCCESS:
printf("ERR_SUCCESS code\n");
break;
case VANILLA_PIPE_OUT_SYNC_STATE:
{
const pipe_sync_state_command *ss = (const pipe_sync_state_command *) cc;
emit syncCompleted(ss->state == VANILLA_SUCCESS);
break;
}
}
}
void BackendViaPipe::connectToConsole()
{
// Request pipe to connect
pipe_control_code conn_cmd;
conn_cmd.code = VANILLA_PIPE_IN_CONNECT;
writeToPipe(&conn_cmd, sizeof(conn_cmd));
}
void BackendViaLocalRoot::updateTouch(int x, int y)
{
vanilla_set_touch(x, y);
}
void BackendViaPipe::updateTouch(int x, int y)
{
pipe_touch_command cmd;
cmd.base.code = VANILLA_PIPE_IN_TOUCH;
cmd.x = htonl(x);
cmd.y = htonl(y);
writeToPipe(&cmd, sizeof(cmd));
}
void BackendViaLocalRoot::setButton(int button, int32_t value)
{
vanilla_set_button(button, value);
}
void BackendViaPipe::setButton(int button, int32_t value)
{
pipe_button_command cmd;
cmd.base.code = VANILLA_PIPE_IN_BUTTON;
cmd.id = htonl(button);
cmd.value = htonl(value);
writeToPipe(&cmd, sizeof(cmd));
}
void BackendViaLocalRoot::setRegion(int region)
{
vanilla_set_region(region);
}
void BackendViaPipe::setRegion(int region)
{
pipe_region_command cmd;
cmd.base.code = VANILLA_PIPE_IN_REGION;
cmd.region = region;
writeToPipe(&cmd, sizeof(cmd));
}
void BackendViaLocalRoot::setBatteryStatus(int status)
{
vanilla_set_battery_status(status);
}
void BackendViaPipe::setBatteryStatus(int status)
{
pipe_battery_command cmd;
cmd.base.code = VANILLA_PIPE_IN_BATTERY;
cmd.battery = status;
writeToPipe(&cmd, sizeof(cmd));
}
void BackendViaLocalRoot::sync(uint16_t code)
{
QFutureWatcher<int> *watcher = new QFutureWatcher<int>(this);
@ -240,15 +106,6 @@ void BackendViaLocalRoot::syncFutureCompleted()
watcher->deleteLater();
}
void BackendViaPipe::sync(uint16_t code)
{
// Request pipe to sync
pipe_sync_command cmd;
cmd.base.code = VANILLA_PIPE_IN_SYNC;
cmd.code = htons(code);
writeToPipe(&cmd, sizeof(cmd));
}
BackendPipe::BackendPipe(const QString &wirelessInterface, QObject *parent) : QObject(parent)
{
m_process = nullptr;
@ -295,16 +152,3 @@ void BackendPipe::receivedData()
}
}
}
void BackendViaSocket::readPendingDatagrams()
{
while (m_socket->hasPendingDatagrams()) {
QNetworkDatagram datagram = m_socket->receiveDatagram();
processPacket(datagram.data());
}
}
ssize_t BackendViaSocket::writeToPipe(const void *data, size_t length)
{
return m_socket->writeDatagram((const char *) data, length, m_backendAddress, m_backendPort);
}

View file

@ -99,62 +99,4 @@ private slots:
};
class BackendViaPipe : public Backend
{
Q_OBJECT
public:
enum ListenState {
IDLE,
WAITING_FOR_SYNC_RESULT,
WAITING_FOR_BIND_RESULT,
RECEIVING_DATA
};
BackendViaPipe(QObject *parent = nullptr);
virtual void interrupt() override;
virtual void updateTouch(int x, int y) override;
virtual void setButton(int button, int32_t value) override;
virtual void requestIDR() override;
virtual void setRegion(int region) override;
virtual void setBatteryStatus(int status) override;
public slots:
virtual void sync(uint16_t code) override;
virtual void connectToConsole() override;
void quitPipe();
protected:
void processPacket(const QByteArray &arr);
virtual ssize_t writeToPipe(const void *data, size_t length) = 0;
private:
ListenState m_listenState;
};
class BackendViaSocket : public BackendViaPipe
{
Q_OBJECT
public:
BackendViaSocket(const QHostAddress &backendAddr, quint16 backendPort, QObject *parent = nullptr);
public slots:
virtual void init() override;
protected:
virtual ssize_t writeToPipe(const void *data, size_t length) override;
private:
QUdpSocket *m_socket;
QHostAddress m_backendAddress;
quint16 m_frontendPort;
quint16 m_backendPort;
private slots:
void readPendingDatagrams();
};
#endif // BACKEND_H

View file

@ -348,20 +348,15 @@ void MainWindow::initBackend(T func)
d->open();
QString localWirelessIntf = m_wirelessInterfaceComboBox->currentData().toString();
if (localWirelessIntf.isEmpty()) {
if (0 && localWirelessIntf.isEmpty()) {
UdpAddressDialog udpDiag(this);
if (udpDiag.exec() == QDialog::Accepted) {
m_backend = new BackendViaSocket(udpDiag.acceptedAddress(), udpDiag.acceptedPort());
// m_backend = new BackendViaSocket(udpDiag.acceptedAddress(), udpDiag.acceptedPort());
} else {
d->deleteLater();
closeBackend();
return;
}
} else if ((geteuid() != 0)) {
// If not root, use named pipe
QMessageBox::critical(this, QString(), tr("Unimplemented..."));
d->deleteLater();
return;
//m_backend = new BackendViaNamedPipe(localWirelessIntf);
} else {
// If root, use lib locally
m_backend = new BackendViaLocalRoot(localWirelessIntf);

View file

@ -1,16 +1,11 @@
#ifndef VANILLA_GAMEPAD_H
#define VANILLA_GAMEPAD_H
#include "ports.h"
#include "vanilla.h"
struct wpa_ctrl;
static const uint16_t PORT_MSG = 50110;
static const uint16_t PORT_VID = 50120;
static const uint16_t PORT_AUD = 50121;
static const uint16_t PORT_HID = 50122;
static const uint16_t PORT_CMD = 50123;
struct gamepad_thread_context
{
vanilla_event_handler_t event_handler;

12
lib/gamepad/ports.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef GAMEPAD_PORTS_H
#define GAMEPAD_PORTS_H
#include <stdint.h>
static const uint16_t PORT_MSG = 50110;
static const uint16_t PORT_VID = 50120;
static const uint16_t PORT_AUD = 50121;
static const uint16_t PORT_HID = 50122;
static const uint16_t PORT_CMD = 50123;
#endif // GAMEPAD_PORTS_H

View file

@ -9,12 +9,12 @@ extern "C" {
#include <stddef.h>
#include <stdint.h>
#define VANILLA_SUCCESS 0
#define VANILLA_ERROR -1
#define VANILLA_READY -2
#define VANILLA_INFO -3
#define VANILLA_UNKNOWN_COMMAND -4
#define VANILLA_INVALID_ARGUMENT -5
static const int VANILLA_SUCCESS = 0;
static const int VANILLA_ERROR = -1;
static const int VANILLA_READY = -2;
static const int VANILLA_INFO = -3;
static const int VANILLA_UNKNOWN_COMMAND = -4;
static const int VANILLA_INVALID_ARGUMENT = -5;
enum VanillaGamepadButtons
{

View file

@ -1,14 +1 @@
add_executable(vanilla-pipe
main.c
)
target_link_libraries(vanilla-pipe PRIVATE
vanilla
pthread
)
target_include_directories(vanilla-pipe PRIVATE
${CMAKE_SOURCE_DIR}/lib
)
install(TARGETS vanilla-pipe)
add_subdirectory(linux)

View file

@ -0,0 +1,5 @@
add_executable(vanilla-pipe
main.c
)
install(TARGETS vanilla-pipe)

148
pipe/linux/main.c Normal file
View file

@ -0,0 +1,148 @@
#include <arpa/inet.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../../lib/gamepad/ports.h"
typedef struct {
int from;
int to;
} relay_ports;
struct in_addr client_address = {0};
void* do_relay(void *data)
{
relay_ports *ports = (relay_ports *) data;
char buf[2048];
ssize_t read_size;
while ((read_size = recv(ports->from, buf, sizeof(buf), 0)) != -1) {
struct sockaddr_in forward = {0};
forward.sin_family = AF_INET;
forward.sin_addr = client_address;
forward.sin_port = ports->to;
sendto(ports->to, buf, read_size, 0, (const struct sockaddr *) &forward, sizeof(forward));
}
return NULL;
}
int open_socket(in_port_t port)
{
struct sockaddr_in in = {0};
in.sin_family = AF_INET;
in.sin_addr.s_addr = INADDR_ANY;
in.sin_port = htons(port);
int skt = socket(AF_INET, SOCK_DGRAM, 0);
if (skt == -1) {
return -1;
}
if (bind(skt, (const struct sockaddr *) &in, sizeof(in)) == -1) {
printf("FAILED TO BIND PORT %u: %i\n", port, errno);
close(skt);
return -1;
}
return skt;
}
void *open_relay(void *data)
{
in_port_t port = (in_port_t) data;
int ret = -1;
// Open an incoming port from the console
int from_console = open_socket(port);
if (from_console == -1) {
goto close;
}
// Open an incoming port from the frontend
int from_frontend = open_socket(port + 100);
if (from_frontend == -1) {
goto close_console_connection;
}
relay_ports a_ports, b_ports;
a_ports.from = from_console;
a_ports.to = from_frontend;
b_ports.from = from_frontend;
b_ports.to = from_console;
pthread_t a_thread, b_thread;
pthread_create(&a_thread, NULL, do_relay, &a_ports);
pthread_create(&b_thread, NULL, do_relay, &b_ports);
pthread_join(a_thread, NULL);
pthread_join(b_thread, NULL);
ret = 0;
close_frontend_connection:
close(from_frontend);
close_console_connection:
close(from_console);
close:
return (void *) ret;
}
int main(int argc, const char **argv)
{
if (argc != 3) {
goto show_help;
}
if (!strcmp("-sync", argv[1])) {
int code = atoi(argv[2]);
if (code == 0) {
printf("ERROR: Invalid sync code\n\n");
goto show_help;
}
} else if (!strcmp("-connect", argv[1])) {
inet_pton(AF_INET, argv[2], &client_address);
pthread_t vid_thread, aud_thread, msg_thread, cmd_thread, hid_thread;
pthread_create(&vid_thread, NULL, open_relay, (void *) PORT_VID);
pthread_create(&aud_thread, NULL, open_relay, (void *) PORT_AUD);
pthread_create(&msg_thread, NULL, open_relay, (void *) PORT_MSG);
pthread_create(&cmd_thread, NULL, open_relay, (void *) PORT_CMD);
pthread_create(&hid_thread, NULL, open_relay, (void *) PORT_HID);
printf("READY\n");
pthread_join(vid_thread, NULL);
pthread_join(aud_thread, NULL);
pthread_join(msg_thread, NULL);
pthread_join(cmd_thread, NULL);
pthread_join(hid_thread, NULL);
} else {
printf("ERROR: Invalid mode\n\n");
goto show_help;
}
return 0;
show_help:
printf("vanilla-pipe - brokers a connection between Vanilla and the Wii U\n");
printf("\n");
printf("Usage: %s <mode> <args>\n", argv[0]);
printf("\n");
printf("Modes: \n");
printf(" -sync <code> Sync/authenticate with the Wii U\n");
printf(" -connect <client-address> Connect to the Wii U (requires syncing prior)\n");
printf("\n");
return 1;
}

View file

@ -1,379 +0,0 @@
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <vanilla.h>
#include "pipe.h"
int create_fifo(const char *name)
{
int f = mkfifo(name, 0777);
if (f == -1) {
printf("Failed to create FIFO: %s (%i)\n", name, errno);
}
return f;
}
int open_fifo(const char *name, int mode)
{
int f = open(name, mode);
if (f == -1) {
printf("Failed to open FIFO: %s (%i)\n", name, errno);
}
return f;
}
int fd_in = 0, fd_out = 0;
uint8_t client_addr[128] = {0};
ssize_t write_pipe(const void *buf, size_t size)
{
sendto(fd_in, buf, size, 0, (const struct sockaddr *) client_addr, sizeof(client_addr));
}
pthread_mutex_t action_mutex;
int action_ended = 0;
int write_control_code(uint8_t code)
{
struct pipe_control_code cmd;
cmd.code = code;
write_pipe(&cmd, sizeof(cmd));
}
void event_handler(void *context, int event_type, const char *data, size_t data_size)
{
struct pipe_data_command cmd;
cmd.base.code = VANILLA_PIPE_OUT_DATA;
cmd.event_type = event_type;
cmd.data_size = htons(data_size);
memcpy(cmd.data, data, data_size);
write_pipe(&cmd, sizeof(cmd)-sizeof(cmd.data)+data_size);
}
void write_sync_state(uint8_t success)
{
struct pipe_sync_state_command cmd;
cmd.base.code = VANILLA_PIPE_OUT_SYNC_STATE;
cmd.state = success;
write_pipe(&cmd, sizeof(cmd));
}
struct sync_args
{
const char *wireless_interface;
uint16_t code;
};
void *sync_command(void *a)
{
struct sync_args *args = (struct sync_args *)a;
int r = vanilla_sync_with_console(args->wireless_interface, args->code);
free(args);
write_sync_state(r);
pthread_mutex_lock(&action_mutex);
action_ended = 1;
pthread_mutex_unlock(&action_mutex);
return (void *) (size_t) r;
}
struct connect_args
{
const char *wireless_interface;
};
void *connect_command(void *a)
{
struct connect_args *args = (struct connect_args *) a;
int r = vanilla_connect_to_console(args->wireless_interface, event_handler, NULL);
free(args);
write_control_code(VANILLA_PIPE_OUT_EOF);
pthread_mutex_lock(&action_mutex);
action_ended = 1;
pthread_mutex_unlock(&action_mutex);
return (void *) (size_t) r;
}
void lib_logger(const char *fmt, va_list args)
{
vfprintf(stderr, fmt, args);
// FILE *fff = fopen("/home/matt/Desktop/temp.log", "a");
// vfprintf(fff, fmt, args);
// fclose(fff);
}
void vapipelog(const char *str, ...)
{
va_list va;
va_start(va, str);
vfprintf(stderr, str, va);
fprintf(stderr, "\n");
// FILE *fff = fopen("/home/matt/Desktop/temp.log", "a");
// vfprintf(fff, str, va);
// fprintf(fff, "\n");
// fclose(fff);
va_end(va);
}
const char *get_positional_arg(int argc, const char **argv, int index)
{
int cur_index = 0;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
i++;
} else if (cur_index == index) {
return argv[i];
} else {
cur_index++;
}
}
return NULL;
}
const char *get_optional_arg(int argc, const char **argv, const char *opt_arg_name, int *exists)
{
*exists = 0;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], opt_arg_name)) {
*exists = 1;
if (i + 1 < argc) {
return argv[i + 1];
}
break;
}
}
return NULL;
}
int main(int argc, const char **argv)
{
if (argc < 3) {
goto show_help;
}
const char *wireless_interface = get_positional_arg(argc, argv, 0);
if (!wireless_interface) {
printf("No wireless interface specified\n");
goto show_help;
}
int pipe_exists, udp_exists;
const char *pipe_mode = get_optional_arg(argc, argv, "-pipe", &pipe_exists);
const char *udp_mode = get_optional_arg(argc, argv, "-udp", &udp_exists);
uint8_t address[128] = {0};
socklen_t address_len;
if (pipe_exists && udp_exists) {
printf("-pipe and -udp cannot both be specified\n");
return 1;
} else if (pipe_mode) {
address_len = sizeof(struct sockaddr_un);
} else if (udp_mode) {
address_len = sizeof(struct sockaddr_in);
} else if (pipe_exists) {
printf("-pipe requires <fifo-path>\n");
return 1;
} else if (udp_exists) {
printf("-udp requires <server-port>\n");
return 1;
} else {
printf("No mode or mode option specified\n");
goto show_help;
}
if (pipe_mode) {
struct sockaddr_un *sa = (struct sockaddr_un *) address;
int len = strlen(pipe_mode);
if (len+1 > sizeof(sa->sun_path)) {
printf("<fifo-path> is too long, must be less than 108 chars including null-term\n");
return 1;
}
sa->sun_family = AF_UNIX;
strncpy(sa->sun_path, pipe_mode, sizeof(sa->sun_path)-1);
fd_in = socket(AF_UNIX, SOCK_DGRAM, 0);
} else {
uint16_t server_port = atoi(udp_mode);
if (server_port == 0) {
printf("UDP port provided was invalid\n");
return 1;
}
struct sockaddr_in *in = (struct sockaddr_in *) address;
in->sin_family = AF_INET;
in->sin_addr.s_addr = INADDR_ANY;
in->sin_port = htons(server_port);
fd_in = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}
if (bind(fd_in, (const struct sockaddr *) address, address_len) == -1) {
printf("Failed to bind to socket\n");
return 1;
}
fprintf(stderr, "READY\n");
char read_buffer[2048];
ssize_t read_size;
pthread_t current_action = 0;
int m_quit = 0;
vanilla_install_logger(lib_logger);
pthread_mutex_init(&action_mutex, NULL);
while (!m_quit) {
uint8_t sender_addr[sizeof(client_addr)];
socklen_t sender_addr_len = sizeof(sender_addr);
read_size = recvfrom(fd_in, read_buffer, sizeof(read_buffer), 0, (struct sockaddr *) sender_addr, &sender_addr_len);
if (read_size == 0) {
continue;
}
pthread_mutex_lock(&action_mutex);
if (action_ended) {
void *ret;
pthread_join(current_action, &ret);
action_ended = 0;
current_action = 0;
}
pthread_mutex_unlock(&action_mutex);
struct pipe_control_code *control_code = (struct pipe_control_code *) read_buffer;
switch (control_code->code) {
case VANILLA_PIPE_IN_SYNC:
{
if (current_action != 0) {
write_control_code(VANILLA_PIPE_ERR_BUSY);
} else {
struct pipe_sync_command *sync_cmd = (struct pipe_sync_command *) read_buffer;
sync_cmd->code = ntohs(sync_cmd->code);
struct sync_args *args = (struct sync_args *) malloc(sizeof(struct sync_args));
args->code = sync_cmd->code;
args->wireless_interface = wireless_interface;
write_control_code(VANILLA_PIPE_ERR_SUCCESS);
pthread_create(&current_action, NULL, sync_command, args);
}
break;
}
case VANILLA_PIPE_IN_CONNECT:
{
if (current_action != 0) {
write_control_code(VANILLA_PIPE_ERR_BUSY);
} else {
struct connect_args *args = (struct connect_args *) malloc(sizeof(struct connect_args));
args->wireless_interface = wireless_interface;
write_control_code(VANILLA_PIPE_ERR_SUCCESS);
pthread_create(&current_action, NULL, connect_command, args);
}
break;
}
case VANILLA_PIPE_IN_BUTTON:
{
struct pipe_button_command *btn_cmd = (struct pipe_button_command *) read_buffer;
btn_cmd->id = ntohl(btn_cmd->id);
btn_cmd->value = ntohl(btn_cmd->value);
vanilla_set_button(btn_cmd->id, btn_cmd->value);
break;
}
case VANILLA_PIPE_IN_TOUCH:
{
struct pipe_touch_command *touch_cmd = (struct pipe_touch_command *) read_buffer;
touch_cmd->x = ntohl(touch_cmd->x);
touch_cmd->y = ntohl(touch_cmd->y);
vanilla_set_touch(touch_cmd->x, touch_cmd->y);
break;
}
case VANILLA_PIPE_IN_INTERRUPT:
{
if (current_action != 0) {
void *ret;
vanilla_stop();
}
break;
}
case VANILLA_PIPE_IN_REQ_IDR:
{
vanilla_request_idr();
break;
}
case VANILLA_PIPE_IN_REGION:
{
struct pipe_region_command *region_cmd = (struct pipe_region_command *) read_buffer;
vanilla_set_region(region_cmd->region);
break;
}
case VANILLA_PIPE_IN_BATTERY:
{
struct pipe_battery_command *battery_cmd = (struct pipe_battery_command *) read_buffer;
vanilla_set_battery_status(battery_cmd->battery);
break;
}
case VANILLA_PIPE_IN_QUIT:
m_quit = 1;
break;
case VANILLA_PIPE_IN_BIND:
{
struct pipe_command_code *bind_cmd = (struct pipe_command_code *) read_buffer;
// Send success message back to client
uint8_t cc = VANILLA_PIPE_OUT_BOUND_SUCCESSFUL;
sendto(fd_in, &cc, sizeof(cc), 0, (const struct sockaddr *) &sender_addr, sizeof(sender_addr));
// Add client to list
memcpy(client_addr, sender_addr, sizeof(client_addr));
struct sockaddr_in *udp_client = (struct sockaddr_in *) client_addr;
char addr_buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &udp_client->sin_addr.s_addr, addr_buf, INET_ADDRSTRLEN);
printf("BIND %s:%u\n", addr_buf, ntohs(udp_client->sin_port));
break;
}
}
}
pthread_mutex_destroy(&action_mutex);
close(fd_in);
close(fd_out);
return 0;
show_help:
printf("Usage: %s <wireless-interface> <mode> [args]\n\n", argv[0]);
printf("vanilla-pipe provides a way to connect a frontend to Vanilla's backend when they\n");
printf("aren't able to run on the same device or in the same environment (e.g. when the \n");
printf("backend must run as root but the frontend must run as user).\n\n");
printf("Modes:\n\n");
printf(" -pipe <fifo>\n");
printf(" Set up communication through Unix FIFO pipes. This is the most reliable\n");
printf(" solution if you're running the frontend and backend on the same device.\n\n");
printf(" -udp <port>\n\n");
printf(" Set up communication through networked UDP port. This is the best option\n");
printf(" if the frontend and backend are on separate devices.\n\n");
return 1;
}

View file

@ -1,86 +0,0 @@
#ifndef VANILLA_PIPE_H
#define VANILLA_PIPE_H
// Control codes that our pipe will receive
enum pipe_opcodes
{
VANILLA_PIPE_IN_SYNC = 1,
VANILLA_PIPE_IN_CONNECT,
VANILLA_PIPE_IN_BUTTON,
VANILLA_PIPE_IN_TOUCH,
VANILLA_PIPE_IN_REQ_IDR,
VANILLA_PIPE_IN_REGION,
VANILLA_PIPE_IN_BATTERY,
VANILLA_PIPE_IN_BIND,
VANILLA_PIPE_IN_INTERRUPT = 0x1E,
VANILLA_PIPE_IN_QUIT = 0x1F,
VANILLA_PIPE_OUT_DATA = 0x20,
VANILLA_PIPE_OUT_SYNC_STATE,
VANILLA_PIPE_OUT_BOUND_SUCCESSFUL,
VANILLA_PIPE_OUT_EOF,
// Errors that our pipe will send
VANILLA_PIPE_ERR_SUCCESS = 0x30,
VANILLA_PIPE_ERR_UNK,
VANILLA_PIPE_ERR_INVALID,
VANILLA_PIPE_ERR_BUSY
};
#pragma pack(push, 1)
struct pipe_control_code
{
uint8_t code;
};
struct pipe_sync_command
{
struct pipe_control_code base;
uint16_t code;
};
struct pipe_button_command
{
struct pipe_control_code base;
int32_t id;
int32_t value;
};
struct pipe_touch_command
{
struct pipe_control_code base;
int32_t x;
int32_t y;
};
struct pipe_region_command
{
struct pipe_control_code base;
int8_t region;
};
struct pipe_battery_command
{
struct pipe_control_code base;
int8_t battery;
};
struct pipe_sync_state_command
{
struct pipe_control_code base;
uint8_t state;
};
struct pipe_data_command
{
struct pipe_control_code base;
uint8_t event_type;
uint16_t data_size;
uint8_t data[2048];
};
#pragma pack(pop)
#endif // VANILLA_PIPE_H