From ace6ce28fbd880483a68c88c9bb63f915cd6e5d4 Mon Sep 17 00:00:00 2001 From: Jonas Gunz Date: Sat, 3 Oct 2020 00:41:38 +0200 Subject: nice rcon interface via rcon_login/rcon_command --- src/rcon.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 115 insertions(+), 8 deletions(-) (limited to 'src/rcon.c') diff --git a/src/rcon.c b/src/rcon.c index 7d5492e..2a79e64 100644 --- a/src/rcon.c +++ b/src/rcon.c @@ -22,12 +22,14 @@ #include "rcon.h" -static char* rcon_errors[] = { - "No Error.", - "Undefined Error.", - "Login Denied.", - "Buffer size incorrect.", - "Malformed packet recieved." +static const unsigned int rcon_errors_len = 6; +static const char* rcon_errors[] = { + "OK", + "Undefined error", + "Authentification failed", + "Inadequate buffer", + "Packet format error", + "Connection timed out" }; static int rcon_write_int ( char* _buffer, int _len, int32_t _data ) { @@ -92,6 +94,111 @@ int rcon_construct_packet ( char* _buffer, uint32_t _len, rcon_packet_t* _packet return bytecount; } -char* rcon_strerror ( int _errno ) { - return _errno > 4 ? rcon_errors[1] : rcon_errors[_errno]; +const char* rcon_strerror ( int _errno ) { + return _errno >= rcon_errors_len ? rcon_errors[1] : rcon_errors[_errno]; +} + +// For packets created by rcon_parse_packet() +void rcon_free_packet ( rcon_packet_t* _packet ) { + if ( ! _packet || ! _packet->payload ) + return; + + free ( _packet->payload ); + _packet->payload = NULL; + _packet->payload_len = 0; +} + +//returns 0 on success +int rcon_send_packet ( int _socket, rcon_packet_t* _packet ) { + char buff [ RCON_SEND_PKGSIZE ]; + int ret; + if ( _socket < 0 || !_packet ) + return RCON_ERR_GENERIC; + + if( ! ((ret = rcon_construct_packet ( buff, RCON_SEND_PKGSIZE, _packet )) > 0) ) + return RCON_ERR_PACKET; + if ( send ( _socket, buff, ret, 0 ) > 0 ) + return 0; + + return RCON_ERR_GENERIC; +} + +//returns 0 on success +int rcon_recv_packet ( int _socket, rcon_packet_t* _packet, int _timeout_msecs ) { + char buff [ RCON_SEND_PKGSIZE ]; + int ret; + struct pollfd fds; + + if ( _socket < 0 || !_packet ) + return RCON_ERR_GENERIC; + + fds.fd = _socket; + fds.events = POLLIN; + + ret = poll ( &fds, 1, _timeout_msecs ); + if ( ret > 0 && fds.revents & POLLIN) { + ret = recv ( _socket, buff, RCON_RECV_PKGSIZE, 0 ); + if ( ! (rcon_parse_packet ( _packet, buff, ret ) > 0) ) + return RCON_ERR_PACKET; + + return 0; + } + + return RCON_ERR_TIMEOUT; //timeout +} + +int rcon_login ( int _socket, const char* _password ) { + int ret; + rcon_packet_t result, request = { + 0, + 1337, // TODO remove hardcoded ID + RCON_LOGIN, + (char*) _password, + strlen(_password) + }; + + if ( _socket < 0 || !_password ) + return RCON_ERR_GENERIC; + + if ( (ret = rcon_send_packet ( _socket, &request )) ) + return ret; + + if ( (ret = rcon_recv_packet ( _socket, &result, 1000 )) ) + return ret; + + if ( result.type != RCON_COMMAND || result.id != 1337 ) + return RCON_ERR_AUTH; + + return 0; +} + +int rcon_command ( char** _output, int _socket, const char* _command ) { + int ret; + if ( _socket < 0 || !_command ) + return RCON_ERR_GENERIC; + + rcon_packet_t result, request = { + 0, + 1337, // TODO remove hardcoded ID + RCON_COMMAND, + (char*) _command, //NONONONONONONONONONONO + strlen(_command) + }; + + if ( (ret = rcon_send_packet ( _socket, &request )) ) + return ret; + + if ( (ret = rcon_recv_packet ( _socket, &result, 1000 )) ) + return ret; + + // TODO truncated response + *_output = malloc ( result.payload_len + 1 ); + *_output[result.payload_len] = 0; + memcpy ( *_output, result.payload, result.payload_len ); + rcon_free_packet ( &result ); + + if ( result.type != RCON_RESPONSE || result.id != 1337 ) + return RCON_ERR_PACKET; + + return 0; } -- cgit v1.2.3