Skip to content

Commit d00f548

Browse files
committed
implement dump playback functionality
1 parent 3cb9622 commit d00f548

File tree

4 files changed

+125
-45
lines changed

4 files changed

+125
-45
lines changed

lib/gamepad/gamepad.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -536,16 +536,14 @@ void free_event_buffer_arena()
536536
}
537537
}
538538

539-
static void record_filename_for_port(char *buffer, size_t size, uint16_t port)
540-
{
541-
snprintf(buffer, size, "/tmp/vanilla_record_%u.bin", port);
542-
buffer[size-1] = 0; // Ensure null terminator
543-
}
539+
static const char *dump_filename = "/tmp/vanilla_dump.bin";
544540

545541
void record_start()
546542
{
547543
pthread_mutex_lock(&record_mutex);
548544

545+
unlink(dump_filename);
546+
549547
record_active = 1;
550548
gettimeofday(&record_start_time, 0);
551549

@@ -559,16 +557,15 @@ void record_packet(uint16_t port, const void *data, size_t size)
559557
pthread_mutex_lock(&record_mutex);
560558

561559
if (record_active) {
562-
char buf[512];
563-
record_filename_for_port(buf, sizeof(buf), port);
564-
565-
FILE *f = fopen(buf, "ab");
560+
FILE *f = fopen(dump_filename, "ab");
566561
struct timeval now;
567562
gettimeofday(&now, 0);
568563

569564
int64_t us = (now.tv_sec - record_start_time.tv_sec) * 1000000 + (now.tv_usec - record_start_time.tv_usec);
570565
fwrite(&us, sizeof(us), 1, f);
571566

567+
fwrite(&port, sizeof(port), 1, f);
568+
572569
uint64_t aligned_size = size;
573570
fwrite(&aligned_size, sizeof(aligned_size), 1, f);
574571

pipe/linux/main.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ int main(int argc, const char **argv)
3939
nlprint("");
4040
nlprint("External logging can be enabled with '-log <log-file>'.");
4141
nlprint("");
42+
nlprint("Playback of dumped data can be enabled with '-playback <dump-file>'.");
43+
nlprint("");
4244

4345
return 1;
4446
}
@@ -47,12 +49,22 @@ int main(int argc, const char **argv)
4749
int local_mode = 0;
4850
const char *wireless_interface = 0;
4951
const char *log_file = 0;
52+
const char *playback_file = 0;
5053

5154
for (int i = 1; i < argc; i++) {
5255
if (!strcmp(argv[i], "-udp")) {
5356
udp_mode = 1;
5457
} else if (!strcmp(argv[i], "-local")) {
5558
local_mode = 1;
59+
} else if (!strcmp(argv[i], "-playback")) {
60+
// Increment index
61+
i++;
62+
if (i < argc) {
63+
playback_file = argv[i];
64+
} else {
65+
nlprint("-playback requires an argument");
66+
return 1;
67+
}
5668
} else if (!strcmp(argv[i], "-log")) {
5769
// Increment index
5870
i++;
@@ -77,7 +89,7 @@ int main(int argc, const char **argv)
7789
return 1;
7890
}
7991

80-
pipe_listen(local_mode, wireless_interface, log_file);
92+
pipe_listen(local_mode, wireless_interface, log_file, playback_file);
8193

8294
return 0;
83-
}
95+
}

pipe/linux/wpa.c

Lines changed: 104 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct sync_args {
6767
int skt;
6868
sockaddr_u client;
6969
size_t client_size;
70+
const char *playback_file;
7071
};
7172

7273
struct relay_info {
@@ -223,7 +224,7 @@ void *wpa_setup_environment(void *data)
223224
interface.driver = "nl80211";
224225
interface.ifname = args->wireless_interface;
225226
interface.confname = args->wireless_config;
226-
227+
227228
struct wpa_global *wpa = wpa_supplicant_init(&params);
228229
if (!wpa) {
229230
nlprint("FAILED TO INIT WPA SUPPLICANT");
@@ -329,7 +330,7 @@ void dhcp_callback(const char *type, char **env, void *data)
329330

330331
// Send request
331332
nl_send_auto_complete(nl, msg);
332-
333+
333334
// Cleanup
334335
nlmsg_free(msg);
335336
rtnl_addr_put(ra);
@@ -359,7 +360,7 @@ int call_dhcp(const char *network_interface)
359360
nlprint("FAILED TO ALLOC NL_SOCK");
360361
goto exit;
361362
}
362-
363+
363364
int nlr = nl_connect(nl, NETLINK_ROUTE);
364365
if (nlr < 0) {
365366
nlprint("FAILED TO CONNECT NL: %i", nlr);
@@ -448,7 +449,7 @@ int open_socket(int local, in_port_t port)
448449
struct timeval tv = {0};
449450
tv.tv_usec = 250000;
450451
setsockopt(skt, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
451-
452+
452453
if (bind(skt, (const struct sockaddr *) &sa, sa_size) == -1) {
453454
nlprint("FAILED TO BIND PORT %u: %i", port, errno);
454455
close(skt);
@@ -460,6 +461,24 @@ int open_socket(int local, in_port_t port)
460461
return skt;
461462
}
462463

464+
sockaddr_u get_frontend_sockaddr(int local, sockaddr_u client, uint16_t port, size_t *size)
465+
{
466+
sockaddr_u frontend_addr;
467+
if (local) {
468+
memset(&frontend_addr.un, 0, sizeof(frontend_addr.un));
469+
frontend_addr.un.sun_family = AF_UNIX;
470+
snprintf(frontend_addr.un.sun_path, sizeof(frontend_addr.un.sun_path), VANILLA_PIPE_LOCAL_SOCKET, port);
471+
*size = sizeof(frontend_addr.un);
472+
} else {
473+
memset(&frontend_addr.in, 0, sizeof(frontend_addr.in));
474+
frontend_addr.in.sin_family = AF_INET;
475+
frontend_addr.in.sin_addr = client.in.sin_addr;
476+
frontend_addr.in.sin_port = htons(port);
477+
*size = sizeof(frontend_addr.in);
478+
}
479+
return frontend_addr;
480+
}
481+
463482
void *open_relay(void *data)
464483
{
465484
struct relay_info *info = (struct relay_info *) data;
@@ -485,20 +504,8 @@ void *open_relay(void *data)
485504
console_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
486505
console_addr.sin_port = htons(port - 100);
487506

488-
sockaddr_u frontend_addr;
489507
size_t frontend_addr_size;
490-
if (info->local) {
491-
memset(&frontend_addr.un, 0, sizeof(frontend_addr.un));
492-
frontend_addr.un.sun_family = AF_UNIX;
493-
snprintf(frontend_addr.un.sun_path, sizeof(frontend_addr.un.sun_path), VANILLA_PIPE_LOCAL_SOCKET, port);
494-
frontend_addr_size = sizeof(frontend_addr.un);
495-
} else {
496-
memset(&frontend_addr.in, 0, sizeof(frontend_addr.in));
497-
frontend_addr.in.sin_family = AF_INET;
498-
frontend_addr.in.sin_addr = info->client.in.sin_addr;
499-
frontend_addr.in.sin_port = htons(port);
500-
frontend_addr_size = sizeof(frontend_addr.in);
501-
}
508+
sockaddr_u frontend_addr = get_frontend_sockaddr(info->local, info->client, port, &frontend_addr_size);
502509

503510
// nlprint("ENTERING MAIN LOOP");
504511
while (are_relays_running()) {
@@ -540,7 +547,7 @@ void create_all_relays(struct sync_args *args)
540547
vid_info.local = aud_info.local = msg_info.local = cmd_info.local = hid_info.local = args->local;
541548
vid_info.client = aud_info.client = msg_info.client = cmd_info.client = hid_info.client = args->client;
542549
vid_info.client_size = aud_info.client_size = msg_info.client_size = cmd_info.client_size = hid_info.client_size = args->client_size;
543-
550+
544551
vid_info.port = PORT_VID;
545552
aud_info.port = PORT_AUD;
546553
msg_info.port = PORT_MSG;
@@ -596,14 +603,14 @@ void *thread_handler(void *data)
596603
pthread_mutex_unlock(&running_mutex);
597604

598605
void *ret = args->start_routine(data);
599-
606+
600607
free(args);
601608

602609
interrupt();
603610

604611
// Locked by calling thread
605612
pthread_mutex_unlock(&action_mutex);
606-
613+
607614
return ret;
608615
}
609616

@@ -679,7 +686,7 @@ void bytes_to_str(unsigned char *data, size_t data_size, const char *separator,
679686
}
680687

681688
int create_connect_config(const char *filename, unsigned char *bssid, unsigned char *psk)
682-
{
689+
{
683690
FILE *out_file = fopen(filename, "w");
684691
if (!out_file) {
685692
nlprint("FAILED TO OPEN OUTPUT CONFIG FILE");
@@ -703,7 +710,7 @@ int create_connect_config(const char *filename, unsigned char *bssid, unsigned c
703710
" pbss=2\n"
704711
"}\n"
705712
"\n";
706-
713+
707714
char bssid_str[18];
708715
char ssid_str[17];
709716
char psk_str[65];
@@ -883,27 +890,27 @@ void *do_connect(void *data)
883890
while (!wpa_ctrl_pending(args->ctrl)) {
884891
sleep(2);
885892
nlprint("WAITING FOR CONNECTION");
886-
893+
887894
if (is_interrupted()) return THREADRESULT(VANILLA_ERR_GENERIC);
888895
}
889-
896+
890897
char buf[1024];
891898
size_t actual_buf_len = sizeof(buf);
892899
wpa_ctrl_recv(args->ctrl, buf, &actual_buf_len);
893900
if (!strstr(buf, "CTRL-EVENT-BSS-ADDED")
894901
&& !strstr(buf, "CTRL-EVENT-BSS-REMOVED")) {
895902
nlprint("CONN RECV: %.*s", actual_buf_len, buf);
896903
}
897-
904+
898905
if (memcmp(buf, "<3>CTRL-EVENT-CONNECTED", 23) == 0) {
899906
break;
900907
}
901-
908+
902909
if (is_interrupted()) return THREADRESULT(VANILLA_ERR_GENERIC);
903910
}
904-
911+
905912
nlprint("CONNECTED TO CONSOLE");
906-
913+
907914
// Use DHCP on interface
908915
int r = call_dhcp(args->wireless_interface);
909916
if (r != VANILLA_SUCCESS) {
@@ -912,8 +919,8 @@ void *do_connect(void *data)
912919
} else {
913920
nlprint("DHCP ESTABLISHED");
914921
}
915-
916-
create_all_relays(args);
922+
923+
create_all_relays(args);
917924
}
918925

919926
return THREADRESULT(VANILLA_SUCCESS);
@@ -954,7 +961,68 @@ void *vanilla_connect_to_console(void *data)
954961
return wpa_setup_environment(args);
955962
}
956963

957-
void pipe_listen(int local, const char *wireless_interface, const char *log_file)
964+
void *do_playback(void *data)
965+
{
966+
struct sync_args *args = (struct sync_args *) data;
967+
968+
FILE *f = fopen(args->playback_file, "rb");
969+
if (!f) {
970+
nlprint("Failed to open playback file \"%s\"", args->playback_file);
971+
return THREADRESULT(VANILLA_ERR_GENERIC);
972+
}
973+
974+
// Tell user we're connected
975+
vanilla_pipe_command_t cmd;
976+
cmd.control_code = VANILLA_PIPE_CC_CONNECTED;
977+
sendto(args->skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &args->client, args->client_size);
978+
979+
struct timeval start;
980+
gettimeofday(&start, 0);
981+
982+
int waiting = 0;
983+
int64_t timestamp;
984+
char buffer[4096];
985+
986+
while (!is_interrupted()) {
987+
if (!waiting) {
988+
// Read next timestamp
989+
fread(&timestamp, sizeof(timestamp), 1, f);
990+
}
991+
992+
struct timeval now;
993+
gettimeofday(&now, 0);
994+
995+
int64_t us = (now.tv_sec - start.tv_sec) * 1000000 + (now.tv_usec - start.tv_usec);
996+
997+
if (us >= timestamp) {
998+
waiting = 0;
999+
1000+
// Read port
1001+
uint16_t port;
1002+
fread(&port, sizeof(port), 1, f);
1003+
1004+
// Read size of packet
1005+
uint64_t size;
1006+
fread(&size, sizeof(size), 1, f);
1007+
1008+
// Read data into buffer
1009+
fread(buffer, size, 1, f);
1010+
1011+
// Send data to gamepad
1012+
size_t frontend_addr_size;
1013+
sockaddr_u frontend_addr = get_frontend_sockaddr(args->local, args->client, port, &frontend_addr_size);
1014+
if (sendto(args->skt, buffer, size, 0, (const struct sockaddr *) &frontend_addr, frontend_addr_size) == -1) {
1015+
nlprint("Failed to send playback packet to port %u", port);
1016+
}
1017+
} else {
1018+
waiting = 1;
1019+
}
1020+
}
1021+
1022+
return THREADRESULT(VANILLA_SUCCESS);
1023+
}
1024+
1025+
void pipe_listen(int local, const char *wireless_interface, const char *log_file, const char *playback_file)
9581026
{
9591027
// Store reference to log file
9601028
ext_logfile = log_file;
@@ -1006,16 +1074,19 @@ void pipe_listen(int local, const char *wireless_interface, const char *log_file
10061074
args->skt = skt;
10071075
args->client = addr;
10081076
args->client_size = addr_size;
1077+
args->playback_file = playback_file;
10091078

10101079
if (cmd.control_code == VANILLA_PIPE_CC_SYNC) {
10111080
args->code = ntohs(cmd.sync.code);
10121081
args->start_routine = vanilla_sync_with_console;
1082+
} else if (args->playback_file) {
1083+
args->start_routine = do_playback;
10131084
} else {
10141085
memcpy(args->bssid, cmd.connection.bssid.bssid, sizeof(cmd.connection.bssid.bssid));
10151086
memcpy(args->psk, cmd.connection.psk.psk, sizeof(cmd.connection.psk.psk));
10161087
args->start_routine = vanilla_connect_to_console;
10171088
}
1018-
1089+
10191090
// Acknowledge
10201091
cmd.control_code = VANILLA_PIPE_CC_BIND_ACK;
10211092
if (sendto(skt, &cmd, sizeof(cmd.control_code), 0, (const struct sockaddr *) &addr, addr_size) == -1) {
@@ -1065,4 +1136,4 @@ void pipe_listen(int local, const char *wireless_interface, const char *log_file
10651136
int vanilla_has_config()
10661137
{
10671138
return (access(get_wireless_connect_config_filename(), F_OK) == 0);
1068-
}
1139+
}

pipe/linux/wpa.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ int enable_networkmanager_on_device(const char *wireless_interface);
1717

1818
void nlprint(const char *fmt, ...);
1919

20-
void pipe_listen(int local, const char *wireless_interface, const char *log_file);
20+
void pipe_listen(int local, const char *wireless_interface, const char *log_file, const char *playback_file);
2121

2222
#endif // VANILLA_WPA_H

0 commit comments

Comments
 (0)