From 2f529e06f9bbe49f6db8ed9837d4023c435e6850 Mon Sep 17 00:00:00 2001 From: sweetlilmre Date: Sat, 7 May 2011 14:00:11 +0200 Subject: [PATCH] Added support for compiling mux and rfs_server under Visual Studio 2010. Patch includes move of rfs functions out of main.c in rfs_server and into rfs_transports.c/h Signed-off-by: sweetlilmre --- mux.lua | 2 +- mux.py | 2 +- mux_src/main.c | 5 + mux_src/mux.vcxproj | 107 ++++++ mux_src/mux.vcxproj.filters | 69 ++++ rfs_server.lua | 2 +- rfs_server.py | 2 +- rfs_server_src/main.c | 408 +-------------------- rfs_server_src/rfs_server.vcxproj | 105 ++++++ rfs_server_src/rfs_server.vcxproj.filters | 69 ++++ rfs_server_src/rfs_transports.c | 413 ++++++++++++++++++++++ rfs_server_src/rfs_transports.h | 22 ++ rfs_server_src/serial_win32.c | 4 +- 13 files changed, 797 insertions(+), 413 deletions(-) create mode 100644 mux_src/mux.vcxproj create mode 100644 mux_src/mux.vcxproj.filters create mode 100644 rfs_server_src/rfs_server.vcxproj create mode 100644 rfs_server_src/rfs_server.vcxproj.filters create mode 100644 rfs_server_src/rfs_transports.c create mode 100644 rfs_server_src/rfs_transports.h diff --git a/mux.lua b/mux.lua index 8085bca9..d8fca7bc 100644 --- a/mux.lua +++ b/mux.lua @@ -6,7 +6,7 @@ builder:init( args ) builder:set_build_mode( builder.BUILD_DIR_LINEARIZED ) local flist = "main.c" -local rfs_flist = "main.c server.c log.c deskutils.c" +local rfs_flist = "main.c server.c log.c deskutils.c rfs_transports.c" local cdefs = "RFS_UDP_TRANSPORT RFS_INSIDE_MUX_MODE" local socklib if utils.is_windows() then diff --git a/mux.py b/mux.py index 2dc638a9..6fa51a08 100644 --- a/mux.py +++ b/mux.py @@ -1,7 +1,7 @@ import os, sys, platform flist = "main.c" -rfs_flist = "main.c server.c log.c deskutils.c" +rfs_flist = "main.c server.c log.c deskutils.c rfs_transports.c" cdefs = "-DRFS_UDP_TRANSPORT -DRFS_INSIDE_MUX_MODE" socklib = '' ptlib = '' diff --git a/mux_src/main.c b/mux_src/main.c index 6892b6ce..9daec74f 100644 --- a/mux_src/main.c +++ b/mux_src/main.c @@ -145,7 +145,12 @@ static int parse_transport( const char* s ) #define FIRST_SERVICE_IDX 3 #define MIN_ARGC_COUNT 4 +#ifdef _MSC_VER +#define strcasecmp _stricmp +int main( int argc, char *argv[] ) +#else int main( int argc, char **argv ) +#endif { unsigned i; SERVICE_DATA *tservice; diff --git a/mux_src/mux.vcxproj b/mux_src/mux.vcxproj new file mode 100644 index 00000000..c83bba85 --- /dev/null +++ b/mux_src/mux.vcxproj @@ -0,0 +1,107 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + + + {68EE7183-C1E2-41A9-AADA-3456B4773685} + Win32Proj + mux + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + true + ..\rfs_server_src;..\inc;..\inc\remotefs;$(IncludePath) + + + false + ..\rfs_server_src;..\inc;..\inc\remotefs;$(IncludePath) + + + + + + Level3 + Disabled + WIN32_BUILD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + Ws2_32.lib;%(AdditionalDependencies) + + + + + + + Level3 + + + MaxSpeed + true + true + WIN32_BUILD;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + Ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/mux_src/mux.vcxproj.filters b/mux_src/mux.vcxproj.filters new file mode 100644 index 00000000..b04d17fc --- /dev/null +++ b/mux_src/mux.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + + + {edd07642-0c4f-4725-9e8f-641858b5e631} + + + {7234826d-2dcc-404c-9472-998da14f1314} + + + \ No newline at end of file diff --git a/rfs_server.lua b/rfs_server.lua index b482b6fd..a69f7da6 100644 --- a/rfs_server.lua +++ b/rfs_server.lua @@ -20,7 +20,7 @@ if utils.is_windows() then print "SIM target not supported under Windows" os.exit( 1 ) end - flist = "main.c server.c os_io_win32.c log.c net_win32.c serial_win32.c deskutils.c" + flist = "main.c server.c os_io_win32.c log.c net_win32.c serial_win32.c deskutils.c rfs_transports.c" cdefs = cdefs .. " WIN32_BUILD" exeprefix = "exe" socklib = 'ws2_32' diff --git a/rfs_server.py b/rfs_server.py index da8d50e2..04de1c3d 100644 --- a/rfs_server.py +++ b/rfs_server.py @@ -13,7 +13,7 @@ if platform.system() == "Windows": if sim == '1': print "SIM target not supported under Windows" os.exit( 1 ) - flist = "main.c server.c os_io_win32.c log.c net_win32.c serial_win32.c deskutils.c" + flist = "main.c server.c os_io_win32.c log.c net_win32.c serial_win32.c deskutils.c rfs_transports.c" cdefs = cdefs + " -DWIN32_BUILD" exeprefix = ".exe" socklib = '-lws2_32' diff --git a/rfs_server_src/main.c b/rfs_server_src/main.c index ce3a58d0..c692f488 100644 --- a/rfs_server_src/main.c +++ b/rfs_server_src/main.c @@ -15,413 +15,7 @@ #include #include "rfs.h" #include "deskutils.h" - -// **************************************************************************** -// Local definitions - -typedef void ( *p_read_request )( void ); -typedef void ( *p_send_response )( void ); -typedef void ( *p_cleanup )( void ); -typedef struct -{ - p_read_request f_read_request; - p_send_response f_send_response; - p_cleanup f_cleanup; -} RFS_TRANSPORT_DATA; - -// **************************************************************************** -// Local variables - -#define MAX_PACKET_SIZE 4096 -static u8 rfs_buffer[ MAX_PACKET_SIZE + ELUARPC_WRITE_REQUEST_EXTRA ]; -static const RFS_TRANSPORT_DATA *p_transport_data; - -// **************************************************************************** -// Serial transport implementation - -static ser_handler ser; - -static void flush_serial() -{ - // Flush all data in serial port - while( ser_read_byte( ser, SER_NO_TIMEOUT ) != -1 ); -} - -// Read a packet from the serial port -static void ser_read_request_packet() -{ - u16 temp16; - u32 readbytes; - - while( 1 ) - { - // First read the length - if( ( readbytes = ser_read( ser, rfs_buffer, ELUARPC_START_OFFSET, SER_INF_TIMEOUT ) ) != ELUARPC_START_OFFSET ) - { - log_msg( "read_request_packet: ERROR reading packet length. Requested %d bytes, got %d bytes\n", ELUARPC_START_OFFSET, readbytes ); - flush_serial(); - continue; - } - - if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) == ELUARPC_ERR ) - { - log_msg( "read_request_packet: ERROR getting packet size.\n" ); - flush_serial(); - continue; - } - - // Then the rest of the data - if( ( readbytes = ser_read( ser, rfs_buffer + ELUARPC_START_OFFSET, temp16 - ELUARPC_START_OFFSET, SER_INF_TIMEOUT ) ) != temp16 - ELUARPC_START_OFFSET ) - { - log_msg( "read_request_packet: ERROR reading full packet, got %u bytes, expected %u bytes\n", ( unsigned )readbytes, ( unsigned )temp16 - ELUARPC_START_OFFSET ); - flush_serial(); - continue; - } - else - break; - } -} - -// Send a packet to the serial port -static void ser_send_response_packet() -{ - u16 temp16; - - // Send request - if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) != ELUARPC_ERR ) - { - log_msg( "send_response_packet: sending response packet of %u bytes\n", ( unsigned )temp16 ); - ser_write( ser, rfs_buffer, temp16 ); - } -} - -static int ser_server_init( const char *portname, int serspeed, int flow ) -{ - // Setup serial port - if( ( ser = ser_open( portname ) ) == SER_HANDLER_INVALID ) - { - log_err( "Cannot open port %s\n", portname ); - return 0; - } - if( ser_setup( ser, ( u32 )serspeed, SER_DATABITS_8, SER_PARITY_NONE, SER_STOPBITS_1, flow ) != SER_OK ) - { - log_err( "Unable to initialize serial port\n" ); - return 0; - } - flush_serial(); - - // User report - log_msg( "Running RFS server on serial port %s (%u baud).\n", portname, ( unsigned )serspeed ); - return 1; -} - -static void ser_cleanup() -{ - ser_close( ser ); -} - -static const RFS_TRANSPORT_DATA ser_transport_data = { ser_read_request_packet, ser_send_response_packet, ser_cleanup }; - -// **************************************************************************** -// UDP transport implementation - -static NET_SOCKET trans_socket = INVALID_SOCKET_VALUE; -static struct sockaddr_in trans_from; - -// Helper: read (blocking) the specified number of bytes - -static void udp_read_helper( u8 *dest, u32 size ) -{ - socklen_t fromlen; - int readbytes; - - while( size ) - { - fromlen = sizeof( trans_from ); - readbytes = net_recvfrom( trans_socket, ( char* )dest, size, 0, ( struct sockaddr* )&trans_from, &fromlen, NET_INF_TIMEOUT ); - size -= readbytes; - if( size == 0 ) - break; - dest += readbytes; - } -} - -static void udp_read_request_packet() -{ - u16 temp16; - - while( 1 ) - { - // First read the length - udp_read_helper( rfs_buffer, ELUARPC_START_OFFSET ); - - if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) == ELUARPC_ERR ) - { - log_msg( "read_request_packet: ERROR getting packet size.\n" ); - continue; - } - - // Then the rest of the data - udp_read_helper( rfs_buffer + ELUARPC_START_OFFSET, temp16 - ELUARPC_START_OFFSET ); - break; - } -} - -static void udp_send_response_packet() -{ - u16 temp16; - - // Send request - if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) != ELUARPC_ERR ) - { - log_msg( "send_response_packet: sending response packet of %u bytes\n", ( unsigned )temp16 ); - net_sendto( trans_socket, ( char* )rfs_buffer, temp16, 0, ( struct sockaddr* )&trans_from, sizeof( trans_from ) ); - } -} - -static int udp_server_init( unsigned server_port ) -{ - int length; - struct sockaddr_in server; - - if( ( trans_socket = net_create_socket( AF_INET, SOCK_DGRAM, 0 ) ) == INVALID_SOCKET_VALUE ) - { - log_err( "Unable to create socket\n" ); - return 1; - } - length = sizeof( server ); - memset( &server, 0, sizeof( server ) ); - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; - server.sin_port = htons( server_port ); - if( bind( net_socket( trans_socket ), ( struct sockaddr * )&server, length ) < 0 ) - { - log_err( "Unable to bind socket\n" ); - return 0; - } - log_msg( "Running RFS server on UDP port %u.\n", ( unsigned )server_port ); - return 1; -} - -static void udp_cleanup() -{ - net_close( trans_socket ); -} - -static const RFS_TRANSPORT_DATA udp_transport_data = { udp_read_request_packet, udp_send_response_packet, udp_cleanup }; - -// **************************************************************************** -// Memory transport implementation - -// Read state machine -enum -{ - MEM_STATE_READ_LENGTH, - MEM_STATE_READ_REQUEST, - MEM_STATE_REQUEST_DONE -}; - -static int mem_read_len; -static int mem_expected_len; -static int mem_read_state; -static int mem_response_flag; - -void rfs_mem_start_request() -{ - mem_read_state = MEM_STATE_READ_LENGTH; - mem_read_len = mem_expected_len = 0; - mem_response_flag = 0; -} - -int rfs_mem_read_request_packet( int c ) -{ - u16 temp16; - int res = 1; - - if( c == -1 ) - { - rfs_mem_start_request(); - return 0; - } - - switch( mem_read_state ) - { - case MEM_STATE_READ_LENGTH: - rfs_buffer[ mem_read_len ++ ] = c; - if( mem_read_len == ELUARPC_START_OFFSET ) - { - mem_read_len = 0; - if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) == ELUARPC_ERR ) - { - log_msg( "RFS read_request_packet: ERROR getting packet size.\n" ); - mem_read_state = MEM_STATE_REQUEST_DONE; - res = 0; - } - else - { - mem_read_state = MEM_STATE_READ_REQUEST; - mem_expected_len = temp16 - ELUARPC_START_OFFSET; - } - } - break; - - case MEM_STATE_READ_REQUEST: - rfs_buffer[ ELUARPC_START_OFFSET + mem_read_len ] = c; - mem_read_len ++; - if( mem_read_len == mem_expected_len ) - { - mem_read_state = MEM_STATE_REQUEST_DONE; - mem_response_flag = 1; - } - break; - } - - return res; -} - -int rfs_mem_has_response() -{ - return mem_response_flag; -} - -void rfs_mem_write_response( u16 *plen, u8 **pdata ) -{ - // Execute request - server_execute_request( rfs_buffer ); - - // Send response - if( eluarpc_get_packet_size( rfs_buffer, plen ) != ELUARPC_ERR ) - { - log_msg( "send_response_packet: sending response packet of %u bytes\n", ( unsigned )*plen ); - *pdata = rfs_buffer; - } - else - { - log_msg( "ERROR in send_response_packet!\n" ); - *plen = 0; - } -} - -static int mem_server_init() -{ - rfs_mem_start_request(); - log_msg( "RFS: using memory transport.\n" ); - return 1; -} - -static const RFS_TRANSPORT_DATA mem_transport_data = { NULL, NULL, NULL }; - -// **************************************************************************** -// Helper functions - -// Transport parser -static int parse_transport_and_init( const char* s ) -{ - const char *c, *c2; - char *temps, *tempb; - long tempi; - int flow; - - if( strstr( s, "ser:" ) == s ) - { - p_transport_data = &ser_transport_data; - s += strlen( "ser:" ); - if( ( c = strchr( s, ',' ) ) == NULL ) - { - log_err( "Invalid serial transport syntax\n" ); - return 0; - } - temps = l_strndup( s, c - s ); - if( ( c2 = strchr( c + 1, ',' ) ) == NULL ) - { - log_err( "Invalid serial transport syntax.\n" ); - return 0; - } - tempb = l_strndup( c + 1, c2 - c - 1 ); - if( secure_atoi( tempb, &tempi ) == 0 ) - { - log_err( "Invalid port speed\n" ); - return 0; - } - free( tempb ); - if( !strcmp( c2 + 1, "none" ) ) - flow = SER_FLOW_NONE; - else if( !strcmp( c2 + 1, "rtscts" ) ) - flow = SER_FLOW_RTSCTS; - else - { - log_err( "Invalid flow control type.\n" ); - return 0; - } - tempi = ser_server_init( temps, tempi, flow ); - free( temps ); - return tempi; - } - else if( strstr( s, "udp:" ) == s ) - { - p_transport_data = &udp_transport_data; - s += strlen( "udp:" ); - if( secure_atoi( s, &tempi ) == 0 ) - { - log_err( "Invalid port number\n" ); - return 0; - } - if( net_init() == 0 ) - { - log_err( "Unable to initialize network\n" ); - return 0; - } - return udp_server_init( tempi ); - } - else if( !strcmp( s, "mem" ) ) - { - // Direct memory transport, only used with mux in rfsmux mode - p_transport_data = &mem_transport_data; - return mem_server_init( tempi ); - } - log_err( "Error: unsupported transport\n" ); - return 0; -} - -// ***************************************************************************** -// Entry point - -#define TRANSPORT_ARG_IDX 1 -#define DIRNAME_ARG_IDX 2 -#define VERBOSE_ARG_IDX 3 -#define MIN_ARGC_COUNT 3 -#define VERBOSE_ARGC_COUNT 4 - -int rfs_init( int argc, const char **argv ) -{ - setvbuf( stdout, NULL, _IONBF, 0 ); - if( argc < MIN_ARGC_COUNT ) - { - log_err( "Usage: %s [-v]\n", argv[ 0 ] ); - log_err( " Serial transport: 'ser:,, ('flow' defines the flow control and can be either 'none' or 'rtscts')\n" ); - log_err( " UDP transport: 'udp:'\n" ); - log_err( "Use -v for verbose output.\n" ); - return 1; - } - - if( ( argc >= VERBOSE_ARGC_COUNT ) && !strcmp( argv[ VERBOSE_ARG_IDX ], "-v" ) ) - log_init( LOG_ALL ); - else - log_init( LOG_NONE ); - - if( !os_isdir( argv[ DIRNAME_ARG_IDX ] ) ) - { - log_err( "Invalid directory %s\n", argv[ DIRNAME_ARG_IDX ] ); - return 1; - } - if( parse_transport_and_init( argv[ TRANSPORT_ARG_IDX ] ) == 0 ) - return 1; - - // Setup RFS server - server_setup( argv[ DIRNAME_ARG_IDX ] ); - log_msg( "Sharing directory %s\n", argv[ DIRNAME_ARG_IDX ] ); - return 0; -} +#include "rfs_transports.h" #ifdef RFS_STANDALONE_MODE int main( int argc, const char **argv ) diff --git a/rfs_server_src/rfs_server.vcxproj b/rfs_server_src/rfs_server.vcxproj new file mode 100644 index 00000000..1b4ee199 --- /dev/null +++ b/rfs_server_src/rfs_server.vcxproj @@ -0,0 +1,105 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + + + {4A3A33C6-6A0C-4C82-8C07-A6896BAFB4FA} + Win32Proj + rfs_server + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + true + .\;..\inc;..\inc\remotefs;$(IncludePath) + + + false + .\;..\inc;..\inc\remotefs;$(IncludePath) + + + + + + Level3 + Disabled + RFS_STANDALONE_MODE;WIN32_BUILD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + Ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + RFS_STANDALONE_MODE;WIN32_BUILD;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + Ws2_32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/rfs_server_src/rfs_server.vcxproj.filters b/rfs_server_src/rfs_server.vcxproj.filters new file mode 100644 index 00000000..dc7d0df9 --- /dev/null +++ b/rfs_server_src/rfs_server.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + source + + + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + headers + + + + + {337cdfd6-7a94-45a7-9773-202c632d5000} + + + {ed41819a-7341-42c2-b1ee-525a54aeeee1} + + + \ No newline at end of file diff --git a/rfs_server_src/rfs_transports.c b/rfs_server_src/rfs_transports.c new file mode 100644 index 00000000..03904f14 --- /dev/null +++ b/rfs_server_src/rfs_transports.c @@ -0,0 +1,413 @@ +// Remote FS server + +#include "net.h" +#include "remotefs.h" +#include "eluarpc.h" +#include "serial.h" +#include "server.h" +#include "type.h" +#include "log.h" +#include "os_io.h" +#include +#include +#include +#include +#include +#include "rfs.h" +#include "deskutils.h" +#include "rfs_transports.h" + +// **************************************************************************** +// Local variables + + +u8 rfs_buffer[ MAX_PACKET_SIZE + ELUARPC_WRITE_REQUEST_EXTRA ]; +const RFS_TRANSPORT_DATA *p_transport_data; + +// **************************************************************************** +// Serial transport implementation + +static ser_handler ser; + +static void flush_serial() +{ + // Flush all data in serial port + while( ser_read_byte( ser, SER_NO_TIMEOUT ) != -1 ); +} + +// Read a packet from the serial port +static void ser_read_request_packet() +{ + u16 temp16; + u32 readbytes; + + while( 1 ) + { + // First read the length + if( ( readbytes = ser_read( ser, rfs_buffer, ELUARPC_START_OFFSET, SER_INF_TIMEOUT ) ) != ELUARPC_START_OFFSET ) + { + log_msg( "read_request_packet: ERROR reading packet length. Requested %d bytes, got %d bytes\n", ELUARPC_START_OFFSET, readbytes ); + flush_serial(); + continue; + } + + if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) == ELUARPC_ERR ) + { + log_msg( "read_request_packet: ERROR getting packet size.\n" ); + flush_serial(); + continue; + } + + // Then the rest of the data + if( ( readbytes = ser_read( ser, rfs_buffer + ELUARPC_START_OFFSET, temp16 - ELUARPC_START_OFFSET, SER_INF_TIMEOUT ) ) != temp16 - ELUARPC_START_OFFSET ) + { + log_msg( "read_request_packet: ERROR reading full packet, got %u bytes, expected %u bytes\n", ( unsigned )readbytes, ( unsigned )temp16 - ELUARPC_START_OFFSET ); + flush_serial(); + continue; + } + else + break; + } +} + +// Send a packet to the serial port +static void ser_send_response_packet() +{ + u16 temp16; + + // Send request + if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) != ELUARPC_ERR ) + { + log_msg( "send_response_packet: sending response packet of %u bytes\n", ( unsigned )temp16 ); + ser_write( ser, rfs_buffer, temp16 ); + } +} + +static int ser_server_init( const char *portname, int serspeed, int flow ) +{ + // Setup serial port + if( ( ser = ser_open( portname ) ) == SER_HANDLER_INVALID ) + { + log_err( "Cannot open port %s\n", portname ); + return 0; + } + if( ser_setup( ser, ( u32 )serspeed, SER_DATABITS_8, SER_PARITY_NONE, SER_STOPBITS_1, flow ) != SER_OK ) + { + log_err( "Unable to initialize serial port\n" ); + return 0; + } + flush_serial(); + + // User report + log_msg( "Running RFS server on serial port %s (%u baud).\n", portname, ( unsigned )serspeed ); + return 1; +} + +static void ser_cleanup() +{ + ser_close( ser ); +} + +const RFS_TRANSPORT_DATA ser_transport_data = { ser_read_request_packet, ser_send_response_packet, ser_cleanup }; + +// **************************************************************************** +// UDP transport implementation + +static NET_SOCKET trans_socket = INVALID_SOCKET_VALUE; +static struct sockaddr_in trans_from; + +// Helper: read (blocking) the specified number of bytes + +static void udp_read_helper( u8 *dest, u32 size ) +{ + socklen_t fromlen; + int readbytes; + + while( size ) + { + fromlen = sizeof( trans_from ); + readbytes = net_recvfrom( trans_socket, ( char* )dest, size, 0, ( struct sockaddr* )&trans_from, &fromlen, NET_INF_TIMEOUT ); + size -= readbytes; + if( size == 0 ) + break; + dest += readbytes; + } +} + +static void udp_read_request_packet() +{ + u16 temp16; + + while( 1 ) + { + // First read the length + udp_read_helper( rfs_buffer, ELUARPC_START_OFFSET ); + + if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) == ELUARPC_ERR ) + { + log_msg( "read_request_packet: ERROR getting packet size.\n" ); + continue; + } + + // Then the rest of the data + udp_read_helper( rfs_buffer + ELUARPC_START_OFFSET, temp16 - ELUARPC_START_OFFSET ); + break; + } +} + +static void udp_send_response_packet() +{ + u16 temp16; + + // Send request + if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) != ELUARPC_ERR ) + { + log_msg( "send_response_packet: sending response packet of %u bytes\n", ( unsigned )temp16 ); + net_sendto( trans_socket, ( char* )rfs_buffer, temp16, 0, ( struct sockaddr* )&trans_from, sizeof( trans_from ) ); + } +} + +static int udp_server_init( unsigned server_port ) +{ + int length; + struct sockaddr_in server; + + if( ( trans_socket = net_create_socket( AF_INET, SOCK_DGRAM, 0 ) ) == INVALID_SOCKET_VALUE ) + { + log_err( "Unable to create socket\n" ); + return 1; + } + length = sizeof( server ); + memset( &server, 0, sizeof( server ) ); + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons( server_port ); + if( bind( net_socket( trans_socket ), ( struct sockaddr * )&server, length ) < 0 ) + { + log_err( "Unable to bind socket\n" ); + return 0; + } + log_msg( "Running RFS server on UDP port %u.\n", ( unsigned )server_port ); + return 1; +} + +static void udp_cleanup() +{ + net_close( trans_socket ); +} + +const RFS_TRANSPORT_DATA udp_transport_data = { udp_read_request_packet, udp_send_response_packet, udp_cleanup }; + +// **************************************************************************** +// Memory transport implementation + +// Read state machine +enum +{ + MEM_STATE_READ_LENGTH, + MEM_STATE_READ_REQUEST, + MEM_STATE_REQUEST_DONE +}; + +static int mem_read_len; +static int mem_expected_len; +static int mem_read_state; +static int mem_response_flag; + +void rfs_mem_start_request() +{ + mem_read_state = MEM_STATE_READ_LENGTH; + mem_read_len = mem_expected_len = 0; + mem_response_flag = 0; +} + +int rfs_mem_read_request_packet( int c ) +{ + u16 temp16; + int res = 1; + + if( c == -1 ) + { + rfs_mem_start_request(); + return 0; + } + + switch( mem_read_state ) + { + case MEM_STATE_READ_LENGTH: + rfs_buffer[ mem_read_len ++ ] = c; + if( mem_read_len == ELUARPC_START_OFFSET ) + { + mem_read_len = 0; + if( eluarpc_get_packet_size( rfs_buffer, &temp16 ) == ELUARPC_ERR ) + { + log_msg( "RFS read_request_packet: ERROR getting packet size.\n" ); + mem_read_state = MEM_STATE_REQUEST_DONE; + res = 0; + } + else + { + mem_read_state = MEM_STATE_READ_REQUEST; + mem_expected_len = temp16 - ELUARPC_START_OFFSET; + } + } + break; + + case MEM_STATE_READ_REQUEST: + rfs_buffer[ ELUARPC_START_OFFSET + mem_read_len ] = c; + mem_read_len ++; + if( mem_read_len == mem_expected_len ) + { + mem_read_state = MEM_STATE_REQUEST_DONE; + mem_response_flag = 1; + } + break; + } + + return res; +} + +int rfs_mem_has_response() +{ + return mem_response_flag; +} + +void rfs_mem_write_response( u16 *plen, u8 **pdata ) +{ + // Execute request + server_execute_request( rfs_buffer ); + + // Send response + if( eluarpc_get_packet_size( rfs_buffer, plen ) != ELUARPC_ERR ) + { + log_msg( "send_response_packet: sending response packet of %u bytes\n", ( unsigned )*plen ); + *pdata = rfs_buffer; + } + else + { + log_msg( "ERROR in send_response_packet!\n" ); + *plen = 0; + } +} + +static int mem_server_init() +{ + rfs_mem_start_request(); + log_msg( "RFS: using memory transport.\n" ); + return 1; +} + +const RFS_TRANSPORT_DATA mem_transport_data = { NULL, NULL, NULL }; + +// **************************************************************************** +// Helper functions + +// Transport parser +static int parse_transport_and_init( const char* s ) +{ + const char *c, *c2; + char *temps, *tempb; + long tempi = 0; + int flow; + + if( strstr( s, "ser:" ) == s ) + { + p_transport_data = &ser_transport_data; + s += strlen( "ser:" ); + if( ( c = strchr( s, ',' ) ) == NULL ) + { + log_err( "Invalid serial transport syntax\n" ); + return 0; + } + temps = l_strndup( s, c - s ); + if( ( c2 = strchr( c + 1, ',' ) ) == NULL ) + { + log_err( "Invalid serial transport syntax.\n" ); + return 0; + } + tempb = l_strndup( c + 1, c2 - c - 1 ); + if( secure_atoi( tempb, &tempi ) == 0 ) + { + log_err( "Invalid port speed\n" ); + return 0; + } + free( tempb ); + if( !strcmp( c2 + 1, "none" ) ) + flow = SER_FLOW_NONE; + else if( !strcmp( c2 + 1, "rtscts" ) ) + flow = SER_FLOW_RTSCTS; + else + { + log_err( "Invalid flow control type.\n" ); + return 0; + } + tempi = ser_server_init( temps, tempi, flow ); + free( temps ); + return tempi; + } + else if( strstr( s, "udp:" ) == s ) + { + p_transport_data = &udp_transport_data; + s += strlen( "udp:" ); + if( secure_atoi( s, &tempi ) == 0 ) + { + log_err( "Invalid port number\n" ); + return 0; + } + if( net_init() == 0 ) + { + log_err( "Unable to initialize network\n" ); + return 0; + } + return udp_server_init( tempi ); + } + else if( !strcmp( s, "mem" ) ) + { + // Direct memory transport, only used with mux in rfsmux mode + p_transport_data = &mem_transport_data; + return mem_server_init( tempi ); + } + log_err( "Error: unsupported transport\n" ); + return 0; +} + +// ***************************************************************************** +// Entry point + +#define TRANSPORT_ARG_IDX 1 +#define DIRNAME_ARG_IDX 2 +#define VERBOSE_ARG_IDX 3 +#define MIN_ARGC_COUNT 3 +#define VERBOSE_ARGC_COUNT 4 + +int rfs_init( int argc, const char **argv ) +{ + setvbuf( stdout, NULL, _IONBF, 0 ); + if( argc < MIN_ARGC_COUNT ) + { + log_err( "Usage: %s [-v]\n", argv[ 0 ] ); + log_err( " Serial transport: 'ser:,, ('flow' defines the flow control and can be either 'none' or 'rtscts')\n" ); + log_err( " UDP transport: 'udp:'\n" ); + log_err( "Use -v for verbose output.\n" ); + return 1; + } + + if( ( argc >= VERBOSE_ARGC_COUNT ) && !strcmp( argv[ VERBOSE_ARG_IDX ], "-v" ) ) + log_init( LOG_ALL ); + else + log_init( LOG_NONE ); + + if( !os_isdir( argv[ DIRNAME_ARG_IDX ] ) ) + { + log_err( "Invalid directory %s\n", argv[ DIRNAME_ARG_IDX ] ); + return 1; + } + if( parse_transport_and_init( argv[ TRANSPORT_ARG_IDX ] ) == 0 ) + return 1; + + // Setup RFS server + server_setup( argv[ DIRNAME_ARG_IDX ] ); + log_msg( "Sharing directory %s\n", argv[ DIRNAME_ARG_IDX ] ); + return 0; +} + diff --git a/rfs_server_src/rfs_transports.h b/rfs_server_src/rfs_transports.h new file mode 100644 index 00000000..ad99370c --- /dev/null +++ b/rfs_server_src/rfs_transports.h @@ -0,0 +1,22 @@ +#ifndef _RFS_TRANSPORTS_H +#define _RFS_TRANSPORTS_H + +typedef void ( *p_read_request )( void ); +typedef void ( *p_send_response )( void ); +typedef void ( *p_cleanup )( void ); +typedef struct +{ + p_read_request f_read_request; + p_send_response f_send_response; + p_cleanup f_cleanup; +} RFS_TRANSPORT_DATA; + +#define MAX_PACKET_SIZE 4096 + +extern const RFS_TRANSPORT_DATA *p_transport_data; +extern const RFS_TRANSPORT_DATA mem_transport_data; +extern const RFS_TRANSPORT_DATA udp_transport_data; +extern const RFS_TRANSPORT_DATA ser_transport_data; +extern u8 rfs_buffer[ MAX_PACKET_SIZE + ELUARPC_WRITE_REQUEST_EXTRA ]; + +#endif \ No newline at end of file diff --git a/rfs_server_src/serial_win32.c b/rfs_server_src/serial_win32.c index ae7bb873..d538c562 100644 --- a/rfs_server_src/serial_win32.c +++ b/rfs_server_src/serial_win32.c @@ -229,7 +229,7 @@ u32 ser_write_byte( ser_handler id, u8 data ) int ser_select_byte( ser_handler *pobjects, unsigned nobjects, int timeout ) { int i, idx; - DWORD readbytes; + DWORD readbytes, dwRes; int res = -1; unsigned num_wait = 0; ser_handler hnd; @@ -272,7 +272,7 @@ int ser_select_byte( ser_handler *pobjects, unsigned nobjects, int timeout ) if( num_wait > 0 ) { idx = -1; - DWORD dwRes = WaitForMultipleObjects( num_wait, sel_handlers, FALSE, timeout == SER_INF_TIMEOUT ? INFINITE : timeout ); + dwRes = WaitForMultipleObjects( num_wait, sel_handlers, FALSE, timeout == SER_INF_TIMEOUT ? INFINITE : timeout ); if( dwRes >= WAIT_OBJECT_0 && dwRes < WAIT_OBJECT_0 + num_wait ) { i = idx = dwRes - WAIT_OBJECT_0;