/* TELNET_CONSOLE.C symbols in this file: 001201D0 00e0: _telnet_console_initialize (0000) 001202B0 0050: _telnet_console_dispose (0000) 00120300 00c0: _telnet_console_print (0000) 001203C0 01f0: _code_001203c0 (0000) 001205B0 0160: _telnet_console_process (0000) 00288D04 003e: ??_C@_0DO@PCBIDEOI@create_transport_endpoint?$CI?$CJ?5fail@ (0000) 00288D44 0032: ??_C@_0DC@CJAJBFKG@bind_endpoint?$CI?$CJ?5failed?5on?5telnet@ (0000) 00288D78 0034: ??_C@_0DE@MBCCFOEL@listen_endpoint?$CI?$CJ?5failed?5on?5teln@ (0000) 00288DAC 0021: ??_C@_0CB@NCDEMBCM@connection?5lost?5to?5telnet?5client@ (0000) 00288DD0 002f: ??_C@_0CP@LBGDAMPB@?$AN?6overflowed?5client?5buffer?$DL?5rese@ (0000) 00288E00 0028: ??_C@_0CI@BALEJICP@failed?5to?5write?5to?5telnet?5client@ (0000) 00288E28 000d: ??_C@_0N@FIIHEHGK@?$AN?6goodbye?$CB?$AN?6?$AA@ (0000) 00288E38 0028: ??_C@_0CI@BMDHLBAG@connection?5lost?5to?5telnet?5client@ (0000) 00288E60 001f: ??_C@_0BP@BBNCCABM@error?5processing?5telnet?5client?$AA@ (0000) 00288E80 0048: ??_C@_0EI@HONFGAEA@sorry?5?9?5the?5maximum?5number?5of?5cl@ (0000) 00288EC8 0021: ??_C@_0CB@MOGHMNHN@Would?5you?5like?5to?5play?5a?5game?$DP?$AN?6@ (0000) 00456D00 008c: _bss_00456d00 (0000) */ /* ---------- headers */ #include "cseries.h" #include "bungie_net/network/transport.h" #include "networking/telnet_console.h" /* ---------- constants */ enum { MAXIMUM_TELNET_CLIENTS = 1, TELNET_CLIENT_BUFFER_SIZE = 128, TELNET_CONSOLE_PORT = 23, _transport_endpoint_type_telnet = 0x12 }; /* ---------- macros */ /* ---------- structures */ struct transport_endpoint; struct telnet_client { struct transport_endpoint *endpoint; char buffer[TELNET_CLIENT_BUFFER_SIZE]; }; struct telnet_console_globals { struct transport_endpoint *listening_endpoint; struct telnet_client clients[MAXIMUM_TELNET_CLIENTS]; boolean initialized; }; /* ---------- prototypes */ struct transport_endpoint *create_transport_endpoint( long type); void delete_transport_endpoint( struct transport_endpoint *endpoint); short bind_endpoint( struct transport_endpoint *endpoint, struct transport_address *address); short listen_endpoint( struct transport_endpoint *endpoint); struct transport_endpoint *accept_endpoint( struct transport_endpoint *endpoint); boolean endpoint_readable( struct transport_endpoint *endpoint, long timeout); long read_endpoint( struct transport_endpoint *endpoint, void *buffer, long size); long write_endpoint( struct transport_endpoint *endpoint, const void *buffer, long size); boolean hs_compile_and_evaluate( char *expression); void telnet_console_initialize( void); void telnet_console_dispose( void); static boolean code_001203c0( char *buffer, long size, struct telnet_client *client); /* ---------- globals */ struct telnet_console_globals bss_00456d00 = {0}; /* ---------- public code */ void telnet_console_initialize( void) { csmemset(&bss_00456d00, 0, sizeof(bss_00456d00)); bss_00456d00.listening_endpoint = create_transport_endpoint(_transport_endpoint_type_telnet); if (bss_00456d00.listening_endpoint) { struct transport_address address = {{0}}; address.address_length = IPV4_ADDRESS_LENGTH; address.port = TELNET_CONSOLE_PORT; if (bind_endpoint(bss_00456d00.listening_endpoint, &address)==_transport_error_none) { if (listen_endpoint(bss_00456d00.listening_endpoint)==_transport_error_none) { bss_00456d00.initialized = TRUE; } else { error(2, "listen_endpoint() failed on telnet console endpoint"); delete_transport_endpoint(bss_00456d00.listening_endpoint); bss_00456d00.listening_endpoint = NULL; } } else { error(2, "bind_endpoint() failed on telnet console endpoint"); delete_transport_endpoint(bss_00456d00.listening_endpoint); bss_00456d00.listening_endpoint = NULL; } } else { error(2, "create_transport_endpoint() failed on telnet console endpoint"); } return; } void telnet_console_dispose( void) { if (bss_00456d00.initialized) { if (bss_00456d00.listening_endpoint) delete_transport_endpoint(bss_00456d00.listening_endpoint); if (bss_00456d00.clients[0].endpoint) delete_transport_endpoint(bss_00456d00.clients[0].endpoint); } csmemset(&bss_00456d00, 0, sizeof(bss_00456d00)); return; } void telnet_console_print( char *string) { if (bss_00456d00.initialized && string && string[0]) { long length = csstrlen(string); if (bss_00456d00.clients[0].endpoint) { long result = write_endpoint(bss_00456d00.clients[0].endpoint, "\r\n", 2); if (result>0) { result = write_endpoint(bss_00456d00.clients[0].endpoint, string, length); if (result>0) { if (bss_00456d00.clients[0].buffer[0]) { result = write_endpoint( bss_00456d00.clients[0].endpoint, bss_00456d00.clients[0].buffer, csstrlen(bss_00456d00.clients[0].buffer)); } if (result>0) return; } } error(2, "connection lost to telnet client"); delete_transport_endpoint(bss_00456d00.clients[0].endpoint); bss_00456d00.clients[0].endpoint = NULL; } } return; } void telnet_console_process( void) { if (bss_00456d00.initialized) { char buffer[32]; long count; if (endpoint_readable(bss_00456d00.listening_endpoint, 0)) { struct transport_endpoint *endpoint = accept_endpoint(bss_00456d00.listening_endpoint); if (endpoint) { long client_index; for (client_index = 0; client_index0) { if (code_001203c0(buffer, count, bss_00456d00.clients)) return; error(2, "error processing telnet client"); } else { error(2, "connection lost to telnet client ('%s')", transport_error_to_string((short)count)); } if (bss_00456d00.clients[0].endpoint) { delete_transport_endpoint(bss_00456d00.clients[0].endpoint); bss_00456d00.clients[0].endpoint = NULL; } } } return; } /* ---------- private code */ static boolean code_001203c0( char *buffer, long size, struct telnet_client *client) { boolean result = TRUE; long index; for (index = 0; result && index0x7f) continue; if (isalnum(*character) || ispunct(*character) || *character==' ') { length = csstrlen(client->buffer)+1; if (length>=TELNET_CLIENT_BUFFER_SIZE) { client->buffer[0] = 0; length = write_endpoint( client->endpoint, "\r\noverflowed client buffer; resetting buffer\r\n", csstrlen("\r\noverflowed client buffer; resetting buffer\r\n")); if (length<=0) { error(2, "failed to write to telnet client ('%s')", transport_error_to_string((short)length)); return FALSE; } return result; } client->buffer[length-1] = *character; client->buffer[length] = 0; } else { switch (*character) { case 10: case 13: if (client->buffer[0]) { char expression[TELNET_CLIENT_BUFFER_SIZE]; csstrncpy(expression, client->buffer, TELNET_CLIENT_BUFFER_SIZE-1); expression[TELNET_CLIENT_BUFFER_SIZE-1] = 0; client->buffer[0] = 0; if (hs_compile_and_evaluate(expression)) { if (write_endpoint(client->endpoint, "\r\n", 2)<=0) result = FALSE; } } continue; case 8: if (client->buffer[0]) { length = csstrlen(client->buffer); if (length>0) client->buffer[length-1] = 0; } break; case 4: write_endpoint( client->endpoint, "\r\ngoodbye!\r\n", csstrlen("\r\ngoodbye!\r\n")); delete_transport_endpoint(client->endpoint); client->endpoint = NULL; index = size; continue; default: continue; } } length = write_endpoint(client->endpoint, character, 1); if (length<=0) { error(2, "failed to write to telnet client ('%s')", transport_error_to_string((short)length)); result = FALSE; } } return result; }