[ADMIN][RCON] mcrcon, remote connection client for minecraft servers

Discussion in 'Bukkit Tools' started by Tiiffi, Apr 16, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Tiiffi

    Hello all.

    This is my first post here. :)

    I noticed that there is no proper and working console based rcon client for minecraft servers available so I wrote one.
    I thought it would be nice to share it for the joy of the poor server admins without proper administration tools.


    News:
    • IPv6 support added!
    • Mac OS X binaries available. Tested and working on Mac OS X (Lion 10.7.3)
    • "Launch script" and "Create shortcut script" added to Windows binary package.
    Bug reports goes here!


    Downloads:
    Latest version: 0.0.5

    Main:
    Windows:
    Linux:
    Mac:
    GIT-repository: git clone git://git.code.sf.net/p/mcrcon/code mcrcon-code

    Please report any compiling problems to my mail.


    Stay tuned for new features and bug fixes!

    Naturally I would appreciate any feedback including bug reports and feature requests.
    Contact email: tiiffi _at_ gmail _dot_ com or Tiiffi @ #quakenet
    You can also submit bug report tickets in sourceforge.

    ------------------------------------------------------------------------------------------------------------------

    [​IMG]
    Name: mcrcon (minecraft rcon)
    Version: 0.0.5
    Date: 30.08.2012

    License: zlib/libpng License

    Description:

    Mcrcon is powerful minecraft rcon client / terminal with bukkit coloring support. It is well suited for remote administration and to be used as part of automated server maintenance scripts. It does not trigger "IO: Broken pipe" or "IO: Connection reset" spam bug on server side.


    Features:
    • IPv6 support.
    • Send multiple commands in one command line.
    • Terminal mode. Keeps the connection alive so need for authing all the time.
    • Silent mode. Does not print rcon output.
    • Support for bukkit coloring on Windows and Linux (sh compatible shells).
    • Multiplatform code. Compiles on many platforms with minor changes.
    Version history:

    0.0.5
    • IPv6 support! (Thanks to 'Tanja84dk' for addressing the real need of IPv6.)
    • Fixed bug causing crash / segmentation fault (invalid write) when receiving malformed rcon packet.
    • Program makes use of C99 feature (variable-length arrays) so "-std=gnu99" flag on GCC-compiler must be used to avoid unecessary warnings.
    • Rcon receive buffer is now bigger (2048 bytes -> 10240 bytes). Thanks to 'gman_ftw' @ Bukkit forums.
    • Fixed invalid error message when receiving empty rcon packet (10 bytes). Thanks to 'pkmnfrk' @ bukkit forums.
    • Terminal mode now closes automatically when rcon socket is closed by server or if packet size cannot be retrieved correctly.
    • Client now tries to clean the incoming socket data if last package was out of spec.
    0.0.4
    • Reverted back to default getopts options error handler (opterr = 1). Custom error handler requires rewriting.
    • Some comestic fixes in program output strings.
    • Program usage(); function now waits for enter before exiting on Windows.
    0.0.3
    • Colors are now supported on Windows too!
    • Terminal mode is now triggered with "-t" flag. "-i" flag still works for backwards compatibility.
    • Bug fixes (Packet size check always evaluating false and color validity check always evaluating true).
    0.0.2
    • License changed from 'ISC License' to 'zlib/libpng License'.
    • Bug fixes & code cleanups
    • Interactive mode (-i flag). Client acts as interactive terminal.
    • Program return value is now the number of rcon commmands sent successfully. If connecting or authentication fails, the return value is -1.
    • Colors are now enabled by default. Now '-c' flag disables the color support.
    0.0.1
    • Added experimental support for bukkit colors. Should work with any sh compatible shell.
    • Packet string data limited to max 2048 (DATA_BUFFSIZE) bytes. No idea how Minecraft handles multiple rcon packets so if someone knows, please mail me so I can implement it
    Usage:
    Code:
    Usage: mcrcon [OPTIONS]... [COMMANDS]...
    Sends rcon commands to minecraft server.
     
    Option:
      -h      Prints usage.
      -s      Silent mode. Do not print data received from rcon.
      -t      Terminal mode. Acts as interactive terminal.
      -p      Rcon password. Default: none.
      -H      Host address. Default: none.
      -P      Port. Default: 25575.
      -c      Do not print colors. Disables bukkit color printing.
     
    Invidual commands must be separated with spaces.
     
    Example:
    mcrcon -c -H 192.168.1.42 -P 9999 -p password cmd1 "cmd2 with spaces"
     
    minecraft rcon (mcrcon) 0.0.5.
    Report bugs to tiiffi_at_gmail_dot_com.
     
    
    mcrcon in action @ youtube (thanks for ReNextGaming)

    Screenshot (ver. 0.0.4):

    [​IMG]

    [​IMG]
     
    lastern, MrVasyanich and Thasan like this.
  2. Offline

    PeterBrinck

    Nice! I will download it!
     
    Tiiffi likes this.
  3. Offline

    crock

    currently not working for me
    it launches and after a min or so it closes again
    i couldn't even typ anything in that min just didn't let me
     
  4. Offline

    Tiiffi

    It is console based client with textual user interface. It is intended to be used from OS console. Launch it from windows commandline or create .bat file with correct launch options.

    Create text file with following command line and place it into same directory as mcrcon client:
    Code:
    mcrcon -t -H your_server_address -p your_password
    
    The file extension must be .bat so that windows knows its batch script ("launch.bat" for example).
    This .bat file acts as "shortcut" to connect to your server rcon.

    UPDATE: New launch script available for Windows users.
     
  5. Offline

    Tiiffi

    *UPDATE*

    0.0.3 -> 0.0.4
    • Reverted back to default getopts options error handler (opterr = 1). Custom error handler requires rewriting.
    • Some comestic fixes in program output strings.
    • Program usage(); function now waits for enter before exiting on Windows.
    Launch script and Create shortcut script added to windows binary bundle. Check Windows binary package README.txt for more information.
     
  6. DERP! MAC SUPPORT PLEASE!
     
  7. Offline

    Tiiffi

    Have you tried to compile it on Mac? Its posix compliant code so it should compile on Mac without any problems.
    Color support may not be working but you can use "-c" flag to disable colors.

    "Official" Mac support in progress.. (I dont have Mac machine available at the moment).
     
  8. Offline

    Tiiffi

  9. Yay tyvm
     
  10. Offline

    pkmnfrk

    Hey, this is great timing since I was just looking to implement rcon!

    However, I have a problem. Whenever I issue a command, like "say test" or "op someone", I get an error saying "Unknown command "say test". Type "help" or "?" for help.". However, in the log, it appears that the command succeded ("[RCON] test"). This happens in both command line and interactive mode.

    It's not really hurting things, since I can just ignore the error, but it would be nice to see just in case there is a real error :)
     
  11. Offline

    Tiiffi

    Hi!

    What version of Minecraft server you are using?

    There might be something I have missed in the way of things on Vanilla minecraft server. For example, Vanilla server does not format its rcon output so there is no newlines at all.

    Edit: I just noticed that Vanilla server sends emtpy packet (length 10) with correct packet id when command is executed succesfully. No textual output at all. I will fix this "cosmetic" problem in next release (0.0.5). Thank you pkmnfrk for the bug report.
     
  12. Offline

    pkmnfrk

    Whoops, I suppose that on a bukkit forum I really should specify that I am not using bukkit! I'm running a server with a few other mods (IC2, BuildCraft, etc), but it is the latest vanilla 1.2.5 server.

    If you want me to do some debugging and figure out what's causing that, I'm more than happy to do so, but you will have to wait until I get home :)
     
  13. Offline

    Tiiffi

    If its possible, I could use some network traffic dump captured in pcap format.
    But I think I already know the problem so traffic analyzing is propably not needed at the moment.
     
  14. Offline

    pkmnfrk

    Hmm, compiling on Debian x86_64 with gcc is easy:

    Code:
    gcc -o mcrcon mcrcon.c
    But with gcc on mingw on Windows, it actually makes me add the linker flag for winsock:

    Code:
    gcc -o mcrcon.exe -lws2_32 mcrcon.c
    Stupid C compilers.

    Anyway, here's the capture of me sending a single command, "say ignore this message". The dump is zipped because the forum doesn't like .pcap for some reason :)

    (In the off chance that my password is recoverable from from the dump, don't worry would-be hackers: the rcon port is not reachable through the firewall.)
     

    Attached Files:

    • rcon.zip
      File size:
      593 bytes
      Views:
      5
  15. Offline

    Tiiffi

    Yeah Windows is a bit more pedantic with linking (and winsockets has some retarded differences compared to more standard berkeley sockets). I am usually using following flags when compiling release builds:

    But hmm .. Am I blind or something? :eek: Cant see any zipped packages in your post? You could send me a private message so there would be no risk of exposing possibly private data to public.
     
  16. Offline

    pkmnfrk

    I totally attached it to the post... whatever, that's a better idea. PM incoming.
     
  17. Offline

    gman_ftw

    Before I say anything, great utility, really the rcon utility on minecraft forums is nothing compared to this!

    However I am encountering a specific problem for the past hour, whenever I try to send a command that sends back a lot of text (eg. pex group Admin, dynmap, etc.) it gives me the following: "Warning: invalid packet size <4106>. Must be over 10 and less than 2048." Now after that any command which I send it repeats the warning no matter what command is like ?, list, etc. In order to "reset" it I need to restart the application and then it works fine (providing that I don't enter the pex group Admin command and such similar commands like dynmap again).
     
  18. Offline

    Tiiffi

    Thank you for the problem report!

    What are the biggest packages you are getting from the server and what exact commands triggers them?

    Apparently the command sends quite a big packet to the rcon client. This problem will be fixed in the next release which will be ready in few days.
     
  19. Offline

    curlyfries1999

    Does the windows version work on a 64-bit?
     
  20. Offline

    MrVasyanich

    I has just finished Android port of it.
    But it requires:
    1. Root access (it requies because compiler requies it)
    2. Terminal Emulator (it's free program which you can get from Play Market)
    3. A little modificated souces of 0.0.5 McRCon:
    Code:
    /*
    * Copyright (c) 2012, Tiiffi <tiiffi_at_gmail_dot_com>
    *
    * This software is provided 'as-is', without any express or implied
    * warranty. In no event will the authors be held liable for any damages
    * arising from the use of this software.
    *
    * Permission is granted to anyone to use this software for any purpose,
    * including commercial applications, and to alter it and redistribute it
    * freely, subject to the following restrictions:
    *
    *  1. The origin of this software must not be misrepresented; you must not
    *  claim that you wrote the original software. If you use this software
    *  in a product, an acknowledgment in the product documentation would be
    *  appreciated but is not required.
    *
    *  2. Altered source versions must be plainly marked as such, and must not be
    *  misrepresented as being the original software.
    *
    *  3. This notice may not be removed or altered from any source
    *  distribution.
    */
     
    /*
    * Name: mcrcon (minecraft rcon)
    *
    * License: zlib/libpng License
    *
    *
    * Contact:
    *  WWW:  http://sourceforge.net/projects/mcrcon/
    *  MAIL: tiiffi_at_gmail_dot_com
    *  IRC:  tiiffi @ quakenet
    *
    *
    * Description:
    *  Mcrcon is powerful minecraft rcon client / terminal with bukkit coloring support.
    *  It is well suited for remote administration and to be used as part of automated server maintenance scripts.
    *  Does not cause "IO: Broken pipe" or "IO: Connection reset" spam in server console.
    *
    *
    * Features:
    *  - Interacive terminal mode. Keeps the connection alive.
    *  - Send multiple commands in one command line.
    *  - Silent mode. Does not print rcon output.
    *  - Support for bukkit coloring on Windows and Linux (sh compatible shells).
    *  - Multiplatform code. Compiles on many platforms with minor changes.
    *
    *
    * Version history:
    *
    * 0.0.5
    *  - Program makes use of C99 feature (variable-length arrays) so "-std=gnu99" flag on
    *    GCC-compiler must be used to avoid unecessary warnings.
    *
    *  - Rcon receive buffer is now bigger (2024 bytes -> 10240 bytes).
    *    * Thanks to 'gman_ftw' @ Bukkit forums.
    *
    *  - Fixed invalid error message when receiving empty rcon packet (10 bytes).
    *    * Thanks to 'pkmnfrk' @ bukkit forums.
    *
    *  - Terminal mode now closes automatically when rcon socket is closed by server
    *    or if packet size cannot be retrieved correctly.
    *
    *  - Client now tries to clean the incoming socket data if last package was out of spec.
    *
    *
    * 0.0.4
    *  - Reverted back to default getopts options error handler (opterr = 1).
    *    Custom error handler requires rewriting.
    *  - Some comestic fixes in program output strings.
    *  - Program usage(); function now waits for enter before exiting on Windows.
    *
    *
    * 0.0.3
    *  - Colors are now supported on Windows too!
    *  - Terminal mode is now triggered with "-t" flag. "-i" flag still works for
    *    backwards compatibility.
    *  - Bug fixes (Packet size check always evaluating false and color validity
    *    check always evaluating true).
    *
    *
    * 0.0.2
    *  - License changed from 'ISC License' to 'zlib/libpng License'.
    *  - Bug fixes & code cleanups
    *  - Interactive mode (-i flag). Client acts as interactive terminal.
    *  - Program return value is now the number of rcon commmands sent successfully.
    *    If connecting or authentication fails, the return value is -1.
    *  - Colors are now enabled by default. Now '-c' flag disables the color support.
    *
    *
    * 0.0.1
    *  - Added experimental support for bukkit colors.
    *    Should work with any sh compatible shell.
    *  - Packet string data limited to max 2048 (DATA_BUFFSIZE) bytes.
    *    No idea how Minecraft handles multiple rcon packets.
    *    If someone knows, please mail me so I can implement it.
    *
    *
    * TODO:
    *  - Make the receive buffer dynamic
    *  - Change some of the packet size issues to fatal errors
    *  - Code cleanups
    *  - Check global variables (remove if possible)
    *  - Add some protocol checks (proper packet id check etc..)
    *  - Preprocessor (#ifdef / #ifndef) cleanups
    *  - Follow valve rcon protocol standard strictly?
    *  - Multiple packet support if minecraft supports it?!
    *  - Investigate if player chat messages gets sent through rcon.
    *    If they are, the messaging system requires rewriting.
    *
    *
    * Bug reports and feature requests to tiiffi_at_gmail_dot_com.
    *
    */
     
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <signal.h>
     
    #ifdef _WIN32
        /* for name resolving on windows */
        #define _WIN32_WINNT 0x0501
     
        #include <ws2tcpip.h>
        #include <winsock2.h>
        #include <windows.h>
    #else
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <netdb.h>
    #endif
     
    /* absolute value macro
    #define absolute(x) (x < 0) ? (0 - x) : x
    */
     
    #define RCON_EXEC_COMMAND      2
    #define RCON_AUTHENTICATE      3
    #define RCON_RESPONSEVALUE      0
    #define RCON_AUTH_RESPONSE      2
    #define RCON_PID                42
     
    /* Safe value I think. This should me made dynamic for more stable performance! */
    #define DATA_BUFFSIZE 10240
     
    #define VERSION "0.0.5"
    #define IN_NAME "mcrcon"
    #define VER_STR IN_NAME" "VERSION
     
    /* rcon packet structure */
    typedef struct _rc_packet {
        int size;
        int id;
        int cmd;
        char data[DATA_BUFFSIZE];
        /* ignoring string2 atm.. */
    } rc_packet;
     
    /* functions */
     
    void            error(char *errstring);
    #ifndef _WIN32
    void            print_color(int color);
    #endif
     
    struct in_addr  net_resolve(char *host);
    void            net_close_socket(int sd);
    int            net_open_socket(char *host, int port);
    int            net_send_packet(int sd, rc_packet *packet);
    rc_packet*      net_recv_packet(int sd);
    #ifdef _WIN32
    void            net_init_WSA(void);
    #endif
    int            net_clean_incoming(int sd, int size);
     
    rc_packet*      packet_build(int id, int cmd, char *s1);
    void            packet_print(rc_packet *packet);
     
    int            rcon_auth(int rsock, char *passwd);
    int            rcon_command(int rsock, char *command);
     
    int            get_line(char *buffer, int len);
    int            run_terminal_mode(int rsock);
    int            run_commands(int argc, char *argv[]);
     
     
    /* some globals */
    int silent_mode = 0;
    int print_colors = 1;
    int connection_alive = 1;
    int rsock; /* rcon socket */
     
    #ifdef _WIN32
      /* console coloring on windows */
      HANDLE console_handle;
    #endif
     
    /* safety stuff (windows is still misbehaving) */
    void exit_proc(void) {
        if(rsock != -1) net_close_socket(rsock);
    }
     
    /* Check windows & linux behaviour !!! */
    void sighandler(int sig) {
        connection_alive = 0;
        #ifndef _WIN32
          exit(-1);
        #endif
    }
     
    int main(int argc, char *argv[])
    {
        int opt, ret = 0;
        int terminal_mode = 1;
     
        char *host = "192.168.1.3";
        char *pass = "123456";
        int port = 25575;
     
     
     
        opterr = 1; /* default error handler enabled */
        while((opt = getopt(argc, argv, "tcshH:p:P:i")) != -1)
        {
            switch(opt)
            {
                case 'H': host = optarg;        break;
                case 'P': port = atoi(optarg);  break;
                case 'p': pass = optarg;        break;
                case 'C':
                case 'c': print_colors = 0;    break;
                case 'S':
                case 's': silent_mode = 1;      break;
                case 'T':
                case 't':
                case 'I':
                case 'i': terminal_mode = 1;    break;
                case 'h':
                case '?':
                    /*
                    if(optopt == 'P' || optopt == 'H' || optopt == 'p')
                        fprintf (stderr, "Option -%c requires an argument.\n\n", optopt);
                    */
     
                    /* else fprintf (stderr, "Unknown option -%c\n\n", optopt); */
     
     
                break;
     
                default: abort();
            }
        }
     
        if(host == NULL) {
            fputs("Host not defined. Check -H flag.\n\n", stdout);
     
        }
     
        if(port <= 0) {
            fputs("Invalid port. Check -P flag.\n\n", stdout);
     
        }
     
        if(optind == argc && terminal_mode == 0) {
            fputs("No commands specified.\n\n", stdout);
       
        }
     
        /* safety features to prevent "IO: Connection reset" bug on the server side */
        atexit(&exit_proc);
        signal(SIGABRT, &sighandler);
        signal(SIGTERM, &sighandler);
        signal(SIGINT, &sighandler);
     
        #ifdef _WIN32
          net_init_WSA();
          console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
          if(console_handle == INVALID_HANDLE_VALUE) console_handle = NULL;
        #endif
     
        /* open socket */
        rsock = net_open_socket(host, port);
     
        /* auth & commands */
        if(rcon_auth(rsock, pass))
        {
            if(terminal_mode)
                ret = run_terminal_mode(rsock);
            else
                ret = run_commands(argc, argv);
        }
        else /* auth failed */
        {
            ret = -1;
            fprintf(stdout, "Authentication failed!\n");
        }
     
        /* cleanup */
        net_close_socket(rsock);
        rsock = -1;
     
        return ret;
    }
     
    void usage(void)
    {
        fputs(
            "Usage: "IN_NAME" [OPTIONS]... [COMMANDS]...\n"
            "Sends rcon commands to minecraft server.\n\n"
            "Option:\n"
            "  -h\t\tPrints usage.\n"
            "  -s\t\tSilent mode. Do not print data received from rcon.\n"
            "  -t\t\tTerminal mode. Acts as interactive terminal.\n"
            "  -p\t\tRcon password. Default: \"\".\n"
            "  -H\t\tHost address or ip.\n"
            "  -P\t\tPort. Default: 25575.\n"
            "  -c\t\tDo not print colors. Disables bukkit color printing.\n"
        ,stdout);
     
        puts("\nInvidual commands must be separated with spaces.\n");
        puts("Example:\n  "IN_NAME" -c -H 192.168.1.42 -P 9999 -p password cmd1 \"cmd2 with spaces\"\n");
        puts("minecraft rcon ("IN_NAME") "VERSION".\nReport bugs to tiiffi_at_gmail_dot_com.\n");
     
        #ifdef _WIN32
          puts("Press enter to exit.");
          getchar();
        #endif
        exit(0);
    }
     
    void error(char *errstring)
    {
        fputs(errstring, stderr);
        exit(-1);
    }
     
    #ifdef _WIN32
    void net_init_WSA(void)
    {
        WSADATA wsadata;
        int err;
     
        err = WSAStartup(MAKEWORD(1, 1), &wsadata);
        if(err != 0)
        {
            fprintf(stderr, "WSAStartup failed. Errno: %d.\n", err);
            exit(-1);
        }
    }
    #endif
     
    struct in_addr net_resolve(char *host)
    {
        struct in_addr address;
     
        struct sockaddr_in *sockaddr_ipv4;
        struct addrinfo hints, *result;
        int ret;
     
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
     
        ret = getaddrinfo(host, NULL, &hints, &result);
        if(ret != 0)
        {
            fprintf(stderr, "Error: Unable to resolve hostname (%s).\n", host);
            exit(-1);
        }
     
        sockaddr_ipv4 = (struct sockaddr_in *) result->ai_addr;
     
        address = sockaddr_ipv4->sin_addr;
     
        freeaddrinfo(result);
     
        return address;
    }
     
    /* socket close and cleanup */
    void net_close_socket(int sd)
    {
        #ifdef _WIN32
            closesocket(sd);
            WSACleanup();
        #else
            close(sd);
        #endif
    }
     
    /* Opens and connects socket */
    int net_open_socket(char *host, int port)
    {
        int sd;
        struct sockaddr_in sa;
     
        memset(&sa, 0, sizeof(sa));            /* Set structure full of zeros. */
        sa.sin_family = AF_INET;                /* Address Family Inet = Protocol Family Inet. */
        sa.sin_port = htons(port);              /* Port number. */
        sa.sin_addr = net_resolve(host);        /* resolve host. */
     
        if((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        {
            #ifdef _WIN32
                WSACleanup();
            #endif
            error("Error: cannot create socket.\n");
        }
     
        if(connect(sd, (struct sockaddr *)&sa, sizeof(sa)) != 0)
        {
            net_close_socket(sd);
            fprintf(stderr, "Error: connection failed (%s).\n", host);
            exit(-1);
        }
     
        return sd;
    }
     
    int net_send_packet(int sd, rc_packet *packet)
    {
        int len;
        int total = 0;        /* how many bytes we've sent */
        int bytesleft;        /* how many we have left to send */
        int ret = -1;
     
        bytesleft = len = packet->size + sizeof(int);
     
        while(total < len)
        {
            ret = send(sd, (char *) packet + total, bytesleft, 0);
            if(ret == -1) { break; }
            total += ret;
            bytesleft -= ret;
        }
     
        /* return -1 on failure, 0 on success */
        return ret == -1 ? -1 : 1;
    }
     
    rc_packet *net_recv_packet(int sd)
    {
        int psize;
        static rc_packet packet = {0, 0, 0, { 0x00 }};
     
        /* packet.size = packet.id = packet.cmd = 0; */
     
        int ret = recv(sd, (char *) &psize, sizeof(int), 0);
     
        if(ret == 0) {
            fprintf(stderr, "Connection lost.\n");
            connection_alive = 0;
            return NULL;
        }
     
        if(ret != sizeof(int)) {
            fprintf(stderr, "Error: recv() failed. Invalid packet size (%d).\n", ret);
            connection_alive = 0;
            return NULL;
        }
     
        if(psize < 10 || psize > DATA_BUFFSIZE) {
            fprintf(stderr, "Warning: invalid packet size (%d). Must over 10 and less than %d.\n", psize, DATA_BUFFSIZE);
            net_clean_incoming(sd, psize);
            return NULL;
        }
     
        packet.size = psize;
     
        ret = recv(sd, (char *) &packet + sizeof(int), psize, 0);
        if(ret == 0) {
            fprintf(stderr, "Connection lost.\n");
            connection_alive = 0;
            return NULL;
        }
        if(ret != psize) {
            fprintf(stderr, "Warning: recv() return value (%d) does not match expected packet size (%d).\n", ret, psize);
            net_clean_incoming(sd, DATA_BUFFSIZE); /* Should be enough. Needs some checking */
            return NULL;
        }
     
        return &packet;
    }
     
    int net_clean_incoming(int sd, int size)
    {
        char tmp[size];
     
        int ret = recv(sd, tmp, size, 0);
     
        if(ret == 0) {
            fprintf(stderr, "Connection lost.\n");
            connection_alive = 0;
        }
     
        return ret;
    }
     
    void print_color(int color)
    {
        /* sh compatible color array */
        #ifndef _WIN32
        char *colors[] = {
            "\033[0;30m", /* 00 BLACK    0x30 */
            "\033[0;34m", /* 01 BLUE    0x31 */
            "\033[0;32m", /* 02 GREEN    0x32 */
            "\033[0;36m", /* 03 CYAN    0x33 */
            "\033[0;31m", /* 04 RED      0x34 */
            "\033[0;35m", /* 05 PURPLE  0x35 */
            "\033[0;33m", /* 06 GOLD    0x36 */
            "\033[0;37m", /* 07 GREY    0x37 */
            "\033[1;30m", /* 08 DGREY    0x38 */
            "\033[1;34m", /* 09 LBLUE    0x39 */
            "\033[1;32m", /* 10 LGREEN  0x61 */
            "\033[1;36m", /* 11 LCYAN    0x62 */
            "\033[1;31m", /* 12 LRED    0x63 */
            "\033[1;35m", /* 13 LPURPLE  0x64 */
            "\033[1;33m", /* 14 YELLOW  0x65 */
            "\033[1;37m", /* 15 WHITE    0x66 */
        };
     
        if(color == 0) {
            fputs("\033[0m", stdout); /* CANCEL COLOR */
        }
        else
        #endif
        {
            if(color >= 0x61 && color <= 0x66) color -= 0x57;
            else if(color >= 0x30 && color <= 0x39) color -= 0x30;
            else return;
     
            #ifndef _WIN32
              fputs(colors[color], stdout);
            #else
              SetConsoleTextAttribute(console_handle, color);
            #endif
        }
    }
     
    /* this hacky mess might use some optmizing */
    void packet_print(rc_packet *packet)
    {
        int i;
        int def_color = 0;
     
        #ifdef _WIN32
          CONSOLE_SCREEN_BUFFER_INFO console_info;
          if(GetConsoleScreenBufferInfo(console_handle, &console_info) != 0)
              def_color = console_info.wAttributes + 0x30;
          else def_color = 0x37;
        #endif
     
        /* colors enabled so try to handle the bukkit colors for terminal */
        if(print_colors == 1) {
     
            for(i = 0; (unsigned char) packet->data[i] != 0; ++i) {
                if((unsigned char) packet->data[i] == 0xa7) {
                    ++i;
                    print_color(packet->data[i]);
                    continue;
                }
                if(packet->data[i] == 0x0A) print_color(def_color);
     
                putchar(packet->data[i]);
            }
            print_color(def_color); /* cancel coloring */
     
        }
        /* strip colors */
        else
        {
            for(i = 0; (unsigned char) packet->data[i] != 0; ++i) {
                if((unsigned char) packet->data[i] == 0xa7) {
                    ++i;
                    continue;
                }
                putchar(packet->data[i]);
            }
        }
     
        /* print newline if string has no newline */
        if(packet->data[i-1] != 10 && packet->data[i-1] != 13)
            putchar('\n');
    }
     
    rc_packet *packet_build(int id, int cmd, char *s1)
    {  /* hacky function */
        static rc_packet packet = {0, 0, 0, { 0x00 }};
     
        /* size + id + cmd + s1 + s2 NULL terminator */
        int s1_len = strlen(s1);
        if(s1_len > DATA_BUFFSIZE) {
            fprintf(stderr, "Warning: Command string too long (%d). Maximum allowed: %d.\n", s1_len, DATA_BUFFSIZE);
            return NULL;
        }
     
        packet.size = sizeof(int) * 2 + s1_len + 2;
        packet.id = id;
        packet.cmd = cmd;
        strncpy(packet.data, s1, DATA_BUFFSIZE);
     
        return &packet;
    }
     
    int rcon_auth(int rsock, char *passwd)
    {
        int ret;
     
        rc_packet *packet = packet_build(RCON_PID, RCON_AUTHENTICATE, passwd);
        if(packet == NULL) return 0;
     
        ret = net_send_packet(rsock, packet);
        if(!ret) return 0; /* send failed */
     
        packet = net_recv_packet(rsock);
        if(packet == NULL) return 0;
     
        /* return 1 if authentication OK */
        return packet->id == -1 ? 0 : 1;
    }
     
    int rcon_command(int rsock, char *command)
    {
        int ret;
     
        rc_packet *packet = packet_build(RCON_PID, RCON_EXEC_COMMAND, command);
        if(packet == NULL) {
            connection_alive = 0;
            return 0;
        }
     
        ret = net_send_packet(rsock, packet);
        if(!ret) return 0; /* send failed */
     
        packet = net_recv_packet(rsock);
        if(packet == NULL) return 0;
     
        if(packet->id != RCON_PID) return 0; /* wrong packet id */
     
        if(!silent_mode) {
            /*
            if(packet->size == 10) {
                printf("Unknown command \"%s\". Type \"help\" or \"?\" for help.\n", command);
            }
            else
            */
            if(packet->size > 10)
                packet_print(packet);
        }
     
        /* return 1 if world was saved */
        return 1;
    }
     
    int run_commands(int argc, char *argv[])
    {
        int i, ok = 1, ret = 0;
     
        for(i = optind; i < argc && ok; i++) {
            ok = rcon_command(rsock, argv[i]);
            ret += ok;
        }
     
        return ret;
    }
     
    /* interactive terminal mode */
    int run_terminal_mode(int rsock)
    {
        int ret = 0;
        char command[DATA_BUFFSIZE] = {0x00};
     
        puts("Logged in. Type \"Q\" to quit!");
     
        while(connection_alive) {
     
            int len = get_line(command, DATA_BUFFSIZE);
            if(command[0] == 'Q' && command[1] == 0) break;
     
            if(len > 0 && connection_alive) ret += rcon_command(rsock, command);
     
            command[0] = len = 0;
        }
     
        return ret;
    }
     
    /* gets line from stdin and deals with rubbish left in input buffer */
    int get_line(char *buffer, int bsize)
    {
        int ch, len;
     
        fputs("> ", stdout);
        fgets(buffer, bsize, stdin);
     
        if(buffer[0] == 0) connection_alive = 0;
     
        /* remove unwanted characters from the buffer */
        buffer[strcspn(buffer, "\r\n")] = '\0';
     
        len = strlen(buffer);
     
        /* clean input buffer if needed */
        if(len == bsize - 1)
            while ((ch = getchar()) != '\n' && ch != EOF);
     
        return len;
    }
    
    It has just 1 differens from original code: you set your particular IP address and port and it will automaticaly log in to your server in terminal mode, but also you can change IP and port as a "tag" (like it was at original version).

    4. C4Droid + GCC plugin (in the c4droid settings you need select compiler: "GCC + Bionic").

    So you just compile that code, go to the folder: /data/data/com.n0n3m4.droidc/files/temp and copy file "temp" to your sdcard or other folder. After that you go to the terminal input: "/mnt/sdcard/temp" or full path to that file.

    You also can try myself-build binary (just copy it to SD card and input "/mnt/sdcard/temp" in the terminal (if your sd-card is mounted to the "sdcard" folder).

    https://docs.google.com/open?id=0B_Q3AsiGjDdxeXhiMjg3RUxNZGs
     
  21. Offline

    bocaj812

    Two things, one, I can't execute many server or bukkit commands Because 'You don't have permission' How do I get, or give myself permission. and the second thing, is it possible to send the entire console output, in a way replicating the console via rcon? Thanks, Jacob
     
  22. Offline

    gman_ftw

    when do you think the new version will be out?! fyi love the tool :p
     
  23. Offline

    nopresnik

    Is it possible to have info shown? Like player left and join?
     
  24. Offline

    Tiiffi

    Hello all!

    Sorry for the delay with new release. I have been busy with other projects but now I am getting back with this.

    Yes it works on 32bit and 64bit Windows NT systems. The app is so small so basically 64bit version is "worthless" anyway.

    Nice. Cool project. I was thinking of making Android port of the app but I think I need some Android "specialists" to help me. Is there any other way to compile C on Android systems or do I have to rewrite the app in Java to get it more accesible for people.

    I think Minecraft server has some inbuilt restrictions for some of the commands. Not sure if its possible to enable them by modifying the server config files.
    Here is some configuration help: http://www.minecraftwiki.net/wiki/Server.properties
    But doesnt look too helpful for your particular problem.

    Minecraft implentation of rcon doesnt send all the console input to rcon unfortunately.:( You probaly need some third party plugin implementation of admin console to get the desired features. I really think they should improve the rcon useability and features.

    As soon as I get them compiled. In fact the 0.0.5 version sourcecode has been available online for a few months now. I think I will upload the precompiled binaries in a week or so.

    I am researching that possibility but looks like Minecraft rcon implementation doesnt send that information to the rcon client. But this needs some work and checking. It will be implemented if possible!
     
  25. Offline

    Fogel

    I'm not sure if I'm doing something wrong or there are some settings I am missing.
    When I try to connect to my server it succeeds and says "Logged in. Type "Q" to quit!".
    As soon as I try writing/executing a command, it just goes "Connection lost." and throws me out.

    Running Bukkit 1.2.5-R4.0, get back to me if you need more information! :)
    mcrcon 0.0.5 from the git-thingy on Debian 6.0.5
     
    Tiiffi likes this.
  26. Offline

    Tiiffi

    What commands you are trying to execute?
    Also does it happen when you send the command without -t flag (terminal mode)?
    And did you try the 0.0.4 version?

    I "fixed" the connection logic in 0.0.5 version so there might be weird bug somewhere hiding. :D
     
  27. Offline

    Fogel

    I tried the 0.0.4 version first, and got the same problem but didn't get disconnected instantly (did happen on the second command, first command just says "connection lost" but doesn't break the connection)!
    I just tried executing a "?" to see what I would be able to do. Also tried /help and /? but to no avail.

    Seems like I'm able to execute commands without the -t flag.
    Though I would like to stay connected if I need to execute more than one command at a time :)

    EDIT: Just saw that doing the connection without -t flag (just running the command) kind of gets rcon on the server stuck in a loop or something. Java.exe takes 100% cpu after 3-4 commands (did "?" as a command all the times) via mcrcon, is this something with bukkit/minecraft or with mcrcon 0.0.5?
     
    Tiiffi likes this.
  28. Offline

    Tiiffi

    Okay. Thanks for the report.
    I think this need some research to be done. I havent got any other reports on this kinds of problems but I know bukkit team has done some changes to rcon stuff so it might be the cause of these problems.

    This was well known problem in older Bukkit versions. I thought they already fixed it as the bugtracker page says: "Fix Version/s: CraftBukkit 1.2.5-R4.0".

    Not sure if there is a new bug now or is this old bug still appearing.
    Does the server say something when it gets into the loop?

    This issue also needs some research.

    So thanks again for the updates and stay tuned!
     
    Fogel likes this.
  29. Offline

    Fogel

    The only thing I saw from the server.log was:
    Code:
    2012-07-16 23:39:47 [INFO] Rcon connection from: /192.168.11.22
    2012-07-16 23:39:47 [INFO] [Rcon] Fogel testing :3
    2012-07-16 23:39:47 [INFO] [Server] Fogel testing :3
    When I executed:
    Code:
    ./mcrcon -p <password> -H 192.168.11.20 -P 25572 "say Fogel testing :3"
    I realized that the java.exe process was spiking up at like 25% CPU usage per command I sent via mcrcon and when I saw that the usage didn't lower from 100% at all I tried rebooting bukkit and sent the commands again to confirm that it was rcon.
    The server did however not lag in any way while the CPU was at 100%, everything ran smoothly :p
     
  30. Offline

    Tiiffi

    Can you capture a packet log of your rcon sessions? I could use that information.
    Wireshark does the job on windows and tcpdump on Linux. The packet log should be in .pcap format.
    It would be good if you could catch the log when something unexpected happens.

    If you are going to capture the traffic, remember to use different dummy password in you traffic or remove the real password from the capture log afterwards before posting it online.
     
    Fogel likes this.
Thread Status:
Not open for further replies.

Share This Page