haneefmubarak / Aixen

A partially distributed online multiplayer service
MIT License
13 stars 0 forks source link

GUI interface #9

Open haneefmubarak opened 10 years ago

haneefmubarak commented 10 years ago

In addition to #7, we should also have a more advanced interface for master servers, one that is a GUI. @MayeulC has volunteered for this and been given push permissions.

MayeulC commented 10 years ago

Should we impement this as a remote interface (then, we should add this functionality to the server), or as a local interface (a --gui parameter, or whatever)?

haneefmubarak commented 10 years ago

I think that as a remote interface would be best.

substanc3-dev commented 10 years ago

And btw what are you telling to my interface?

MayeulC commented 10 years ago

I like it, it is quite scalable (but we have to keep an eye on that, though, as we add more elements to the interface).

Then, there are some issues : the background of the typing zone is still white, I don't really like it. About the scalability, if your window is not tall enough, you end up with "Command not found" or whatever on the same line as aixen> , which can be an issue. If you enter a blank line, the console starts to scroll. I don't know if this is a good thing or not, but the behaviour should be the same, regardless of the window size, or the string entered.

For the main zone, at the center : will you put there the logs? I would also like the possibility of a client list, like the one you can have with netwatch. More feedback would be good, too, like a list of commands by typing "help" (hould be rather easy to implement). On the code side, I don't really like these escape sequences \033[ everywhere. In my opinion, this should be handled by defines such as :

#define clrscr() printf("\033[H\033[2J")

#define color2(param) printf("\033[%sm",#param)
#define color(param) color2(param)

then, just call color(BLUE;YELLOWBACK;BLINK); in your code (with the appropriate define). In my opinion, this is clearer. But you are free to do whatever you think is the best :smile:

MayeulC commented 10 years ago

Here is some code I used to include in such projects :


#ifndef COLOURS
#define COLOURS

#include <stdio.h>

#define clrscr() printf("\033[H\033[2J")
#define color2(param) printf("\033[%sm",#param)
#define color(param) color2(param)

//text :
#define BLACK 30
#define RED 31
#define GREEN 32
#define YELLOW 33
#define BLUE 34
#define MAGENTA 35
#define CYAN 36
#define WHITE 37

//background :
#define BLACKBACK 40
#define REDBACK 41
#define GREENBACK 42
#define YELLOWBACK 43
#define BLUEBACK 44
#define MAGENTABACK 45
#define CYANBACK 46
#define WHITEBACK 47

//specials :
#define BLINK 5             //blink text
#define REVERSE 7           //reverse colors
#define MAX 1               //high intensity
#define DEFAULT 0           //default

#endif

together with this function :

void gotoxy(int x, int y)
{
    printf("\033[%d;%df", y, x);
    fflush(stdout);
}

I had some problems without fflush. You can also define this as a macro, which should be better, since more portable to other platforms.

substanc3-dev commented 10 years ago

Ok, thanks for feedback BTW: As you can see i Made it to be compatible with my 80x38 terminal

MayeulC commented 10 years ago

If this is implemented as a remote control panel, I think we should add an interface for remote administration. This will also enable a web based control panel. But it means again an other port to bind... There is already a lot of parameters. How about some default values?

haneefmubarak commented 10 years ago

I think that we can hardcode the GUI config port, along with having people change the user and password for that given master server before they compile. Seeing as there should only be a few masters, this does not strike me as an issue.

MayeulC commented 10 years ago

I was thinking more about a certificate authentication, but we can go with just a password for now.

haneefmubarak commented 10 years ago

Well, seeing as that only the owner of an authorized master server ought to be able to view and control stats for the entire network, passwords shouldn't be that much of an issue.

MayeulC commented 10 years ago

Yes, but a certificate authentication should perform better (especially when associated to a classic User/Password combo) against bruteforces, no? Moreover, this would allow a better encryption system. Again, I am completely fine with a password authentication : after all, we are just on the early design phase, implementing whatever we choose later should not be a problem :smile:

haneefmubarak commented 10 years ago

Hey, I'm working on a KDF that I'm entering into the international competition - so once I finish that, I'll stick that in, and using a KDF, it'll be impossible to brute force in realistic time. Besides, encryption will be a given, I'm thinking we'll probably end up going with Ephemeral Diffie-Hellman (EDH) along with RC6 for encryption - that should pretty much take care of security.

MayeulC commented 10 years ago

Well, this sounds a bit overkill given our needs (at least for a control panel) : I don't think we need Perfect Forwards Secrecy, for instance. But if we can implement those easily, at a low processing cost, this could be really interesting to setup.

haneefmubarak commented 10 years ago

Well, I was going to setup the KDF + PFS for any communication to the server anyways. The DH will probably be super cheap (and the RC6 even cheaper), but the KDF will probably be set to a cost of 1-5 ms.

haneefmubarak commented 10 years ago

@MayeulC how's the GUI coming along?

MayeulC commented 10 years ago

I had a lot of work this week, and this week-end too. I did some research on SDL GUIs, bud I didn't find anything on SDL2. It is too recent, I think. We need to implement the control interface under aixen before the GUI could be of any use. I was wondering... wouldn't it be better to work on the GUI in a separate repo?

haneefmubarak commented 10 years ago

I think we should be fine with having the GUI in this repo too. If you could make a skeleton we can fill it in later. I've used SDL2 recently, so I can send you a few wiki articles plus a few code examples.

We can always use make gui or something to build only the GUI.

On Saturday, March 22, 2014, Mayeul Cantan notifications@github.com wrote:

I had a lot of work this week, and this week-end too. I did some research on SDL GUIs, bud I didn't find anything on SDL2. It is too recent, I think. We need to implement the control interface under aixen before the GUI could be of any use. I was wondering... wouldn't it be better to work on the GUI in a separate repo?

Reply to this email directly or view it on GitHubhttps://github.com/haneefmubarak/Aixen/issues/9#issuecomment-38363985 .

MayeulC commented 10 years ago

Well, why not? Please send me some code examples by e-mail :smile: I have started to design a GUI in Qt designer, since it's faster. What is your system like, so I can show you some designs?

haneefmubarak commented 10 years ago

The main issue with qt is that qt isn't in C; also, SDL is more portable. Also, SDL is much, much smaller and has few dependencies.

My systems are Ubuntu, Fedora, LFS, Ubuntu GNOME and OSX.

haneefmubarak commented 10 years ago

@MayeulC Sorry for the lateness, I couldn't access the computer these were stored on for the past few days; but anyways, here are three examples of programming with SDL2:


A fast primer on event driven programming that Xeek (over at freenode) was kind enough to write up for me when I was learning SDL2:

Xeek-example-eventloop.c

#include <SDL.h>
#include <stdio.h>

void on_render(SDL_Window* window, SDL_Renderer* renderer);

int main(int argc, char** argv)
{
    SDL_Window      *mainwindow = NULL;
    SDL_Renderer    *renderer = NULL;
    SDL_Event       event = { 0 };
    int             exit = 0;   // If 1, the event loop will break.

    // INITIALIZE SDL (VIDEO ONLY):
    if(SDL_Init(SDL_INIT_VIDEO) == -1) {
        printf("SDL_Init() failed with \"%s.\"", SDL_GetError());
        return 1;
    }

    // CREATE WINDOW:
    mainwindow = SDL_CreateWindow("SDL2 Application", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
    if(!mainwindow) {
        printf("SDL_CreateWindow() failed with \"%s.\"", SDL_GetError());
        return -1;
    }

    // CREATE RENDERER:
    renderer = SDL_CreateRenderer(mainwindow, -1, SDL_RENDERER_ACCELERATED);
    if(!renderer) {
        printf("SDL_CreateRenderer() failed with \"%s.\"", SDL_GetError());
        return -1;
    }

    // MAIN LOOP:
    while(!exit) {

        // EVENT LOOP:
        if(SDL_WaitEvent(&event)) {
            switch(event.type) {
            case SDL_QUIT:
                exit = 1;
                break;
            case SDL_KEYDOWN:
                if(event.key.keysym.sym == SDLK_ESCAPE) exit = 1;
                break;
            case SDL_WINDOWEVENT:
                switch(event.window.event) {
                case SDL_WINDOWEVENT_CLOSE:
                    exit = 1;
                    break;
                }
                break;
            default: break;
            }
        }

        // RENDER SCREEN:
        on_render(mainwindow, renderer);

        // SWAP BUFFERS TO DISPLAY:
        SDL_RenderPresent(renderer);
    }

    // CLEAN-UP:
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(mainwindow);
    SDL_Quit();

    return 0;
}

void on_render(SDL_Window* window, SDL_Renderer* renderer)
{
    int rect_width = 300, rect_height = 300;
    SDL_Rect window_rect = { 0 };

    // CLEAR THE SCREEN WITH A BLUE COLOR:
    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
    SDL_RenderClear(renderer);

    // DRAW A RECTANGLE:
    SDL_GetWindowSize(window, &window_rect.w, &window_rect.h);

    SDL_Rect draw_rect = {
        (window_rect.x + (window_rect.w / 2) - (rect_width / 2)) - 1,
        (window_rect.y + (window_rect.h / 2) - (rect_height / 2)) - 1,
        rect_width + 2,
        rect_height + 2
    };

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(renderer, &draw_rect);
}

Creates a window, renders something, and quits when you hit Esc.


A quickie that I wrote when learning how to do text in SDL2:

1.c


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <assert.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

void cleanup (void) {
    TTF_Quit ();
    SDL_Quit ();
}

static const char *error_msg[] = { "error: could not initialize ", ":\t" };

int init (void) {
    int status = 0;

    if ((status |= SDL_Init (SDL_INIT_EVERYTHING))) {
        fputs (error_msg[0], stderr);
        fputs ("SDL", stderr);
        fputs (error_msg[1], stderr);
        fputs (SDL_GetError(), stderr);
        fputc ('\n', stderr);
    }

    if ((status |= TTF_Init())) {
        fputs (error_msg[0], stderr);
        fputs ("TTF", stderr);
        fputs (error_msg[1], stderr);
        fputs (TTF_GetError(), stderr);
        fputc ('\n', stderr);
    }

    return status;
}

int main (int argc, char **argv) {
    assert (!init ());
    SDL_assert_release (!atexit(cleanup));

    int x;

    TTF_Font **font_audiowide = malloc (sizeof (TTF_Font *) * 12);  // Font sizes are font[size/2]
    SDL_assert_release (font_audiowide);
    for (x = 1; x < 13; x++) {
        font_audiowide[x] = TTF_OpenFont ("./Audiowide-Regular.ttf", x * 200);
        if (!font_audiowide[x]) {
            fputs (error_msg[0], stderr);
            fputs ("font", stderr);
            fputs (error_msg[1], stderr);
            fputs (TTF_GetError(), stderr);
            fputc ('\n', stderr);
            exit (1);
        }
    }

    SDL_Window *window_main = SDL_CreateWindow (
                    "Main Window",
                    SDL_WINDOWPOS_CENTERED,
                    SDL_WINDOWPOS_CENTERED,
                    640,
                    480,
                    SDL_WINDOW_OPENGL|SDL_WINDOW_ALLOW_HIGHDPI
                    );
    SDL_assert_release (window_main);
    SDL_Renderer *renderer_main = SDL_CreateRenderer (window_main, -1, 0);
    SDL_assert_release (renderer_main);
    if (!renderer_main) {
        fprintf (stderr, "renderer_main init failed:\t%s\n", SDL_GetError());
    }

    SDL_Color color_text = {255,255,255,0};
    SDL_Surface *surface_text = TTF_RenderText_Blended (font_audiowide[11], "Hello World!", color_text);

    SDL_Texture *texture_main = SDL_CreateTextureFromSurface (renderer_main, surface_text);

    SDL_RenderClear (renderer_main);

    float ratio = 15.0f / (float) surface_text->h;
    SDL_Rect dstrect;
    dstrect.x = 20;
    dstrect.y = 20;
    dstrect.w = 1.5f * ratio * (float) surface_text->w;
    dstrect.h = 15;

    SDL_FreeSurface (surface_text);

    SDL_RenderCopy (renderer_main, texture_main, NULL, &dstrect);
    SDL_RenderPresent (renderer_main);

    SDL_Delay (15000);

    SDL_DestroyTexture (texture_main);
    SDL_DestroyRenderer (renderer_main);
    SDL_DestroyWindow (window_main);

    return 0;
}

Creates a window, renders "Hello World!" onto it, and requires you to quit using Ctrl + C.


A more involved SDL2 program I wrote for keyevent detection:

2.h


#pragma once

// ========================================
// Includes

// libc
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// asserts
#include <assert.h>

// SDL2
#include "SDL.h"
#include "SDL_ttf.h"

// ========================================
// Declarations

// Main
void    cleanup     (void);
int init        (void);

// Miscellaneous
void    errorMsg    (unsigned int type, const char *module, const char *message);

// Render
void    on_render   (SDL_Window* window, SDL_Renderer* renderer);

2.c


#include "2.h"

int main (int argc, char **argv) {
    // Initialize SDL and SDL_ttf
    assert (!init ());
    SDL_assert_release (!atexit (cleanup));

    SDL_Window  *window_main = NULL;
    SDL_Renderer    *renderer_main = NULL;
    SDL_Event   event = { 0 };
    int     exit = 0;

    // Create window
    window_main = SDL_CreateWindow (
                    "SDL2 Application",     // Window Title
                    SDL_WINDOWPOS_CENTERED, // pos x
                    SDL_WINDOWPOS_CENTERED, // pos y
                    640,                // dim x
                    480,                // dim y
                    SDL_WINDOW_OPENGL|SDL_WINDOW_ALLOW_HIGHDPI
                    );
    SDL_assert_release (window_main);

    // Create renderer
    renderer_main = SDL_CreateRenderer (
                    window_main,
                    -1, // let SDL find the best driver
                    0   // no special features needed
                    );

    // Main loop
    while (!exit) {

        // Event loop
        if (SDL_PollEvent (&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    exit = 1;
                    break;
                case SDL_KEYDOWN:
                    fprintf (stdout, "Key Pressed:\t%s\n",
                        SDL_GetKeyName (event.key.keysym.sym));
                    break;
                case SDL_WINDOWEVENT:
                    switch (event.window.event) {
                        case SDL_WINDOWEVENT_CLOSE:
                            exit = 1;
                            break;
                    }
                    break;
                default:
                    break;
            }
        }

        // Render screen
        on_render (window_main, renderer_main);

        // Update screen
        SDL_RenderPresent (renderer_main);

        // Sleep till next update
        SDL_Delay (1);  // 1 ms
    }

    // Cleanup
    SDL_DestroyRenderer (renderer_main);
    SDL_DestroyWindow (window_main);

    return 0;
}

void cleanup (void) {
    TTF_Quit ();
    SDL_Quit ();
}

int init (void) {
    int status = 0;

    if ((status |= SDL_Init (SDL_INIT_EVERYTHING))) {
        errorMsg (1, "SDL", SDL_GetError());
    }

    if ((status |= TTF_Init())) {
        errorMsg (1, "TTF", SDL_GetError());
    }

    return status;
}

static const char *error_msg[] = { "\b", "could not initialize" };

void errorMsg (unsigned int type, const char *module, const char *message) {
    if (type > 1) type = 0;

    fprintf (stderr, "error: %s %s:\t%s\n", error_msg[type], module, message);

    return;
}

void on_render (SDL_Window *window, SDL_Renderer *renderer) {
    int rect_width = 300, rect_height = 300;
    SDL_Rect window_rect = { 0 };

    // Clear the screen magenta
    SDL_SetRenderDrawColor (
                renderer,
                255,    // R
                0,  // G
                255,    // B
                255 // A
                );
    SDL_RenderClear (renderer);

    // Draw a rectangle
    SDL_GetWindowSize (window, &window_rect.w, &window_rect.h);

    SDL_Rect draw_rect = {
        (window_rect.x + (window_rect.w / 2) - (rect_width / 2)) - 1,   // pos x
        (window_rect.y + (window_rect.h / 2) - (rect_height / 2)) - 1,  // pos y
        rect_width + 2,                         // dim x
        rect_height +2                          // dim y
    };

    // Paint the bg white
    SDL_SetRenderDrawColor (renderer, 255, 255, 255, 255);
    // Draw the rectangle in the fg
    SDL_RenderFillRect (renderer, &draw_rect);
}

Creates a window, renders something, then detects keyevents and echoes them back to the terminal, and exits cleanly when the X button on the window is clicked to close the window.

haneefmubarak commented 10 years ago

@MayeulC - how are the designs coming along?

MayeulC commented 10 years ago

@haneefmubarak I am really sorry, but I am very busy for now with my studies, and I am afraid I won't be able to code until next week. But I will try my best to do so.

haneefmubarak commented 10 years ago

That's fine - thanks for letting us know :smile:!