@@ -67,6 +67,7 @@ struct sync_args {
67
67
int skt ;
68
68
sockaddr_u client ;
69
69
size_t client_size ;
70
+ const char * playback_file ;
70
71
};
71
72
72
73
struct relay_info {
@@ -223,7 +224,7 @@ void *wpa_setup_environment(void *data)
223
224
interface .driver = "nl80211" ;
224
225
interface .ifname = args -> wireless_interface ;
225
226
interface .confname = args -> wireless_config ;
226
-
227
+
227
228
struct wpa_global * wpa = wpa_supplicant_init (& params );
228
229
if (!wpa ) {
229
230
nlprint ("FAILED TO INIT WPA SUPPLICANT" );
@@ -329,7 +330,7 @@ void dhcp_callback(const char *type, char **env, void *data)
329
330
330
331
// Send request
331
332
nl_send_auto_complete (nl , msg );
332
-
333
+
333
334
// Cleanup
334
335
nlmsg_free (msg );
335
336
rtnl_addr_put (ra );
@@ -359,7 +360,7 @@ int call_dhcp(const char *network_interface)
359
360
nlprint ("FAILED TO ALLOC NL_SOCK" );
360
361
goto exit ;
361
362
}
362
-
363
+
363
364
int nlr = nl_connect (nl , NETLINK_ROUTE );
364
365
if (nlr < 0 ) {
365
366
nlprint ("FAILED TO CONNECT NL: %i" , nlr );
@@ -448,7 +449,7 @@ int open_socket(int local, in_port_t port)
448
449
struct timeval tv = {0 };
449
450
tv .tv_usec = 250000 ;
450
451
setsockopt (skt , SOL_SOCKET , SO_RCVTIMEO , & tv , sizeof (tv ));
451
-
452
+
452
453
if (bind (skt , (const struct sockaddr * ) & sa , sa_size ) == -1 ) {
453
454
nlprint ("FAILED TO BIND PORT %u: %i" , port , errno );
454
455
close (skt );
@@ -460,6 +461,24 @@ int open_socket(int local, in_port_t port)
460
461
return skt ;
461
462
}
462
463
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
+
463
482
void * open_relay (void * data )
464
483
{
465
484
struct relay_info * info = (struct relay_info * ) data ;
@@ -485,20 +504,8 @@ void *open_relay(void *data)
485
504
console_addr .sin_addr .s_addr = inet_addr ("192.168.1.10" );
486
505
console_addr .sin_port = htons (port - 100 );
487
506
488
- sockaddr_u frontend_addr ;
489
507
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 );
502
509
503
510
// nlprint("ENTERING MAIN LOOP");
504
511
while (are_relays_running ()) {
@@ -540,7 +547,7 @@ void create_all_relays(struct sync_args *args)
540
547
vid_info .local = aud_info .local = msg_info .local = cmd_info .local = hid_info .local = args -> local ;
541
548
vid_info .client = aud_info .client = msg_info .client = cmd_info .client = hid_info .client = args -> client ;
542
549
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
+
544
551
vid_info .port = PORT_VID ;
545
552
aud_info .port = PORT_AUD ;
546
553
msg_info .port = PORT_MSG ;
@@ -596,14 +603,14 @@ void *thread_handler(void *data)
596
603
pthread_mutex_unlock (& running_mutex );
597
604
598
605
void * ret = args -> start_routine (data );
599
-
606
+
600
607
free (args );
601
608
602
609
interrupt ();
603
610
604
611
// Locked by calling thread
605
612
pthread_mutex_unlock (& action_mutex );
606
-
613
+
607
614
return ret ;
608
615
}
609
616
@@ -679,7 +686,7 @@ void bytes_to_str(unsigned char *data, size_t data_size, const char *separator,
679
686
}
680
687
681
688
int create_connect_config (const char * filename , unsigned char * bssid , unsigned char * psk )
682
- {
689
+ {
683
690
FILE * out_file = fopen (filename , "w" );
684
691
if (!out_file ) {
685
692
nlprint ("FAILED TO OPEN OUTPUT CONFIG FILE" );
@@ -703,7 +710,7 @@ int create_connect_config(const char *filename, unsigned char *bssid, unsigned c
703
710
" pbss=2\n"
704
711
"}\n"
705
712
"\n" ;
706
-
713
+
707
714
char bssid_str [18 ];
708
715
char ssid_str [17 ];
709
716
char psk_str [65 ];
@@ -883,27 +890,27 @@ void *do_connect(void *data)
883
890
while (!wpa_ctrl_pending (args -> ctrl )) {
884
891
sleep (2 );
885
892
nlprint ("WAITING FOR CONNECTION" );
886
-
893
+
887
894
if (is_interrupted ()) return THREADRESULT (VANILLA_ERR_GENERIC );
888
895
}
889
-
896
+
890
897
char buf [1024 ];
891
898
size_t actual_buf_len = sizeof (buf );
892
899
wpa_ctrl_recv (args -> ctrl , buf , & actual_buf_len );
893
900
if (!strstr (buf , "CTRL-EVENT-BSS-ADDED" )
894
901
&& !strstr (buf , "CTRL-EVENT-BSS-REMOVED" )) {
895
902
nlprint ("CONN RECV: %.*s" , actual_buf_len , buf );
896
903
}
897
-
904
+
898
905
if (memcmp (buf , "<3>CTRL-EVENT-CONNECTED" , 23 ) == 0 ) {
899
906
break ;
900
907
}
901
-
908
+
902
909
if (is_interrupted ()) return THREADRESULT (VANILLA_ERR_GENERIC );
903
910
}
904
-
911
+
905
912
nlprint ("CONNECTED TO CONSOLE" );
906
-
913
+
907
914
// Use DHCP on interface
908
915
int r = call_dhcp (args -> wireless_interface );
909
916
if (r != VANILLA_SUCCESS ) {
@@ -912,8 +919,8 @@ void *do_connect(void *data)
912
919
} else {
913
920
nlprint ("DHCP ESTABLISHED" );
914
921
}
915
-
916
- create_all_relays (args );
922
+
923
+ create_all_relays (args );
917
924
}
918
925
919
926
return THREADRESULT (VANILLA_SUCCESS );
@@ -954,7 +961,68 @@ void *vanilla_connect_to_console(void *data)
954
961
return wpa_setup_environment (args );
955
962
}
956
963
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 )
958
1026
{
959
1027
// Store reference to log file
960
1028
ext_logfile = log_file ;
@@ -1006,16 +1074,19 @@ void pipe_listen(int local, const char *wireless_interface, const char *log_file
1006
1074
args -> skt = skt ;
1007
1075
args -> client = addr ;
1008
1076
args -> client_size = addr_size ;
1077
+ args -> playback_file = playback_file ;
1009
1078
1010
1079
if (cmd .control_code == VANILLA_PIPE_CC_SYNC ) {
1011
1080
args -> code = ntohs (cmd .sync .code );
1012
1081
args -> start_routine = vanilla_sync_with_console ;
1082
+ } else if (args -> playback_file ) {
1083
+ args -> start_routine = do_playback ;
1013
1084
} else {
1014
1085
memcpy (args -> bssid , cmd .connection .bssid .bssid , sizeof (cmd .connection .bssid .bssid ));
1015
1086
memcpy (args -> psk , cmd .connection .psk .psk , sizeof (cmd .connection .psk .psk ));
1016
1087
args -> start_routine = vanilla_connect_to_console ;
1017
1088
}
1018
-
1089
+
1019
1090
// Acknowledge
1020
1091
cmd .control_code = VANILLA_PIPE_CC_BIND_ACK ;
1021
1092
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
1065
1136
int vanilla_has_config ()
1066
1137
{
1067
1138
return (access (get_wireless_connect_config_filename (), F_OK ) == 0 );
1068
- }
1139
+ }
0 commit comments