From 1489be34bfd9a706ee8a1430074b1142e5e5f856 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Sat, 5 Jan 2013 03:43:31 +0100 Subject: [PATCH] Migrated struct wmudClient to the WmudClient GObject --- wmud/Makefile.am | 2 +- wmud/game-networking.c | 232 +++++++++++++++++----------------------- wmud/game-networking.h | 6 +- wmud/interpreter.c | 14 +-- wmud/interpreter.h | 6 +- wmud/menu.c | 12 +-- wmud/menu.h | 8 +- wmud/players.c | 4 +- wmud/players.h | 3 +- wmud/texts.c | 2 +- wmud/texts.h | 2 +- wmud/wmud-types.h | 33 ------ wmud/wmudclient.c | 237 +++++++++++++++++++++++++++++++++++++++++ wmud/wmudclient.h | 74 +++++++++++++ 14 files changed, 436 insertions(+), 199 deletions(-) create mode 100644 wmud/wmudclient.c create mode 100644 wmud/wmudclient.h diff --git a/wmud/Makefile.am b/wmud/Makefile.am index 1d50198..8a7367e 100644 --- a/wmud/Makefile.am +++ b/wmud/Makefile.am @@ -1,5 +1,5 @@ bin_PROGRAMS = wmud AM_CPPFLAGS = -DWMUD_STATEDIR=\""$(localstatedir)"\" -DWMUD_CONFDIR=\""$(sysconfdir)"\" $(MEMCACHED_CFLAGS) $(GLIB_CFLAGS) $(GIO_CFLAGS) $(GTHREAD_CFLAGS) $(SQLITE3_CFLAGS) $(CURL_CFLAGS) -wmud_SOURCES = main.c game-networking.c interpreter.c db.c players.c maintenance.c game.c configuration.c world.c menu.c texts.c +wmud_SOURCES = main.c game-networking.c interpreter.c db.c players.c maintenance.c game.c configuration.c world.c menu.c texts.c wmudclient.c wmud_LDADD = $(MEMCACHED_LIBS) $(GLIB_LIBS) $(GIO_LIBS) $(GTHREAD_LIBS) $(SQLITE3_LIBS) $(CURL_LIBS) diff --git a/wmud/game-networking.c b/wmud/game-networking.c index 5467b90..8961621 100644 --- a/wmud/game-networking.c +++ b/wmud/game-networking.c @@ -33,6 +33,7 @@ #include "configuration.h" #include "menu.h" #include "texts.h" +#include "wmudclient.h" /** * SECTION:game-networking @@ -49,55 +50,33 @@ struct AcceptData { /** * clients: - * The full #GSList of the currently connected #wmudClient structs. + * The full #GSList of the currently connected #WmudClient objects. */ GSList *clients = NULL; static GRegex *email_regex = NULL; -void wmud_client_interpret_newplayer_email(wmudClient *client); -void wmud_client_interpret_newplayer_mailconfirm(wmudClient *client); -static void state_fresh(wmudClient *client); -static void state_passwait(wmudClient *client); -static void state_menu(wmudClient *client); -static void state_yesno(wmudClient *client); -static void state_registering(wmudClient *client); -static void state_regemail_confirm(wmudClient *client); +void wmud_client_interpret_newplayer_email(WmudClient *client); +void wmud_client_interpret_newplayer_mailconfirm(WmudClient *client); +static void state_fresh(WmudClient *client); +static void state_passwait(WmudClient *client); +static void state_menu(WmudClient *client); +static void state_yesno(WmudClient *client); +static void state_registering(WmudClient *client); +static void state_regemail_confirm(WmudClient *client); -/** - * wmud_client_close: - * @client: the client whose connection should be dropped - * @send_goodbye: if set to %TRUE, we will send a nice good-bye message to the - * client before dropping the connection - * - * Closes a client connection. If send_goodbye is set to %TRUE, a good-bye - * message will be sent to the client. - */ -void -wmud_client_close(wmudClient *client, gboolean send_goodbye) +static void +remove_client(WmudClient *client, gboolean send_quitmessage) { - if (send_goodbye) - wmud_client_send(client, "\r\nHave a nice real-world day!\r\n\r\n"); - - g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Connection closed."); - g_socket_shutdown(client->socket, TRUE, TRUE, NULL); clients = g_slist_remove(clients, client); - - if (client->player && !client->player->registered) - wmud_player_free(&(client->player)); - - if (client->buffer) - g_string_free(client->buffer, TRUE); - - g_source_destroy(client->socket_source); - g_free(client); + wmud_client_close(client, send_quitmessage); } /** * wmud_client_callback: * @client: the socket of the client on which the data arrived * @condition: the condition available on the client socket - * @client: the wmudClient structure of the client + * @client: the WmudClient structure of the client * * Processes incoming client data, and client hangup * @@ -105,12 +84,12 @@ wmud_client_close(wmudClient *client, gboolean send_goodbye) * otherwise */ static gboolean -wmud_client_callback(GSocket *client_socket, GIOCondition condition, wmudClient *client) +wmud_client_callback(GSocket *client_socket, GIOCondition condition, WmudClient *client) { GError *err = NULL; if (condition & G_IO_HUP) { - wmud_client_close(client, FALSE); + remove_client(client, FALSE); return FALSE; } else if ((condition & G_IO_IN) || (condition & G_IO_PRI)) { @@ -120,7 +99,7 @@ wmud_client_callback(GSocket *client_socket, GIOCondition condition, wmudClient if ((len = g_socket_receive(client_socket, buf, MAX_RECV_LEN, NULL, &err)) == 0) { g_free(buf); - wmud_client_close(client, FALSE); + remove_client(client, FALSE); return FALSE; } @@ -135,38 +114,38 @@ wmud_client_callback(GSocket *client_socket, GIOCondition condition, wmudClient sloc = -1; if ((r < n) && r) { - if (client->buffer->len > 0) - g_string_append_len(client->buffer, buf2, (r - buf2)); + if (wmud_client_get_buffer_length(client) > 0) + g_string_append_len(wmud_client_get_buffer(client), buf2, (r - buf2)); else - g_string_overwrite_len(client->buffer, 0, buf2, (r - buf2)); + g_string_overwrite_len(wmud_client_get_buffer(client), 0, buf2, (r - buf2)); buf2 = r; } else if (n) { - if (client->buffer->len > 0) - g_string_append_len(client->buffer, buf2, (n - buf2)); + if (wmud_client_get_buffer_length(client) > 0) + g_string_append_len(wmud_client_get_buffer(client), buf2, (n - buf2)); else - g_string_overwrite_len(client->buffer, 0, buf2, (n - buf2)); + g_string_overwrite_len(wmud_client_get_buffer(client), 0, buf2, (n - buf2)); buf2 = n; } /* Remove telnet codes from the string */ - for (i = 0; i < client->buffer->len; i++) { - guchar c = (client->buffer->str)[i]; + for (i = 0; i < wmud_client_get_buffer_length(client); i++) { + guchar c = (wmud_client_get_buffer(client)->str)[i]; if ((c >= 240) || (c == 1)) { if (sloc == -1) sloc = i; } else { if (sloc != -1) { - g_string_erase(client->buffer, sloc, i - sloc); + g_string_erase(wmud_client_get_buffer(client), sloc, i - sloc); sloc = -1; } } } if (sloc != -1) - g_string_erase(client->buffer, sloc, -1); + g_string_erase(wmud_client_get_buffer(client), sloc, -1); - switch (client->state) + switch (wmud_client_get_state(client)) { case WMUD_CLIENT_STATE_FRESH: state_fresh(client); @@ -190,17 +169,17 @@ wmud_client_callback(GSocket *client_socket, GIOCondition condition, wmudClient state_regemail_confirm(client); break; } - g_string_erase(client->buffer, 0, -1); + g_string_erase(wmud_client_get_buffer(client), 0, -1); for (; ((*buf2 == '\r') || (*buf2 == '\n')) && *buf2; buf2++); if (!*buf2) break; } else { - if (client->buffer->len > 0) - g_string_append(client->buffer, buf2); + if (wmud_client_get_buffer_length(client) > 0) + g_string_append(wmud_client_get_buffer(client), buf2); else - g_string_overwrite(client->buffer, 0, buf2); + g_string_overwrite(wmud_client_get_buffer(client), 0, buf2); break; } @@ -229,21 +208,19 @@ game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData GSocket *client_socket; GSource *client_source; GError *err = NULL; - wmudClient *client; GSocketAddress *remote_addr; + WmudClient *client; /* This function should never return an error. If so, it is a huge bug, * and will trigger a higher level error. */ client_socket = g_socket_listener_accept_socket(accept_data->listener, NULL, NULL, &err); - client = g_new0(wmudClient, 1); - client->socket = client_socket; - client->buffer = g_string_new(""); - client->state = WMUD_CLIENT_STATE_FRESH; + client = wmud_client_new(); + wmud_client_set_socket(WMUD_CLIENT(client), client_socket); + client_source = wmud_client_get_socket_source(client); + clients = g_slist_prepend(clients, client); - client_source = g_socket_create_source(client_socket, G_IO_IN | G_IO_OUT | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, NULL); - client->socket_source = client_source; g_source_set_callback(client_source, (GSourceFunc)wmud_client_callback, client, NULL); g_source_attach(client_source, accept_data->context); @@ -267,7 +244,7 @@ game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData } g_clear_error(&err); - wmud_client_send(client, "By what name shall we call you? "); + wmud_client_send(WMUD_CLIENT(client), "By what name shall we call you? "); return TRUE; } @@ -394,99 +371,80 @@ wmud_networking_init(guint port_number, GMainContext *game_context, GSList *menu return TRUE; } -/** - * wmud_client_send: - * @client: the client to which the message will be sent - * @fmt: the printf() style format string of the message - * @...: optional parameters to the format string - * - * Sends a formatted message to a game client - */ void -wmud_client_send(wmudClient *client, const gchar *fmt, ...) -{ - va_list ap; - GString *buf = g_string_new(""); - - va_start(ap, fmt); - g_string_vprintf(buf, fmt, ap); - va_end(ap); - - /* TODO: error checking */ - g_socket_send(client->socket, buf->str, buf->len, NULL, NULL); - g_string_free(buf, TRUE); -} - -void -wmud_client_quitanswer(wmudClient *client, gboolean answer) +wmud_client_quitanswer(WmudClient *client, gboolean answer) { if (answer) { - wmud_client_close(client, TRUE); + remove_client(client, TRUE); } else { wmud_client_send(client, "Good boy!\r\n"); - client->state = WMUD_CLIENT_STATE_MENU; + wmud_client_set_state(client, WMUD_CLIENT_STATE_MENU); } } void -wmud_client_newchar_answer(wmudClient *client, gboolean answer) +wmud_client_newchar_answer(WmudClient *client, gboolean answer) { if (answer) { g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Creating new player\n"); wmud_client_send(client, "Welcome to this MUD!\r\nPlease enter your e-mail address: "); - client->state = WMUD_CLIENT_STATE_REGISTERING; + wmud_client_set_state(client, WMUD_CLIENT_STATE_REGISTERING); } else { wmud_client_send(client, "What is your player-name, then? "); - client->state = WMUD_CLIENT_STATE_FRESH; + wmud_client_set_state(client, WMUD_CLIENT_STATE_FRESH); } } static void -state_fresh(wmudClient *client) +state_fresh(WmudClient *client) { - if (*(client->buffer->str)) { + if (*(wmud_client_get_buffer(client)->str)) { wmudPlayer *player; - if ((player = wmud_player_exists(client->buffer->str)) != NULL) { + if ((player = wmud_player_exists(wmud_client_get_buffer(client)->str)) != NULL) { g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Trying to" " login with playername '%s'", - client->buffer->str); + wmud_client_get_buffer(client)->str); if (player->cpassword == NULL) { wmud_client_send(client, "Your registration is" " not finished yet.\r\n"); - wmud_client_close(client, TRUE); + remove_client(client, TRUE); } else { - client->state = WMUD_CLIENT_STATE_PASSWAIT; - client->player = player; - client->player->registered = TRUE; + wmud_client_set_state(client, WMUD_CLIENT_STATE_PASSWAIT); + player->registered = TRUE; + wmud_client_set_player(client, player); wmud_client_send(client, "Please provide us your password: %c%c%c", TELNET_IAC, TELNET_WILL, TELNET_ECHO); } } else { - client->player = g_new0(wmudPlayer, 1); - client->player->player_name = g_strdup(client->buffer->str); - client->state = WMUD_CLIENT_STATE_YESNO; - client->yesNoCallback = wmud_client_newchar_answer; - wmud_client_send(client, "Is %s new to this game? [Y/N] ", client->buffer->str); + wmudPlayer *player = g_new0(wmudPlayer, 1); + player->player_name = g_strdup(wmud_client_get_buffer(client)->str); + wmud_client_set_player(client, player); + wmud_client_set_state(client, WMUD_CLIENT_STATE_YESNO); + wmud_client_set_yesno_callback(client, wmud_client_newchar_answer); + wmud_client_send(client, "Is %s new to this game? [Y/N] ", wmud_client_get_buffer(client)->str); } } } static void -state_passwait(wmudClient *client) +state_passwait(WmudClient *client) { - if (*(client->buffer->str)) { + if (*(wmud_client_get_buffer(client)->str)) { if (wmud_player_auth(client)) { wmud_client_send(client, "%c%c%c\r\nLogin successful." "\r\n", TELNET_IAC, TELNET_WONT, TELNET_ECHO); - client->authenticated = TRUE; + wmud_client_set_authenticated(client, TRUE); - if (client->player->fail_count > 0) + if (wmud_client_get_player(client)->fail_count > 0) wmud_client_send(client, "There %s %d failed" " login attempt%s with your" " account since your last" - " visit\r\n", (client->player->fail_count == 1) ? "was" : "were", client->player->fail_count, (client->player->fail_count == 1) ? "" : "s"); + " visit\r\n", + (wmud_client_get_player(client)->fail_count == 1) ? "was" : "were", + wmud_client_get_player(client)->fail_count, + (wmud_client_get_player(client)->fail_count == 1) ? "" : "s"); wmud_text_send_to_client("motd", client); wmud_menu_present(client); @@ -496,22 +454,22 @@ state_passwait(wmudClient *client) " \r\nBy what name would you like to be" " be called? ", TELNET_IAC, TELNET_WONT, TELNET_ECHO); - client->state = WMUD_CLIENT_STATE_FRESH; - client->player->fail_count++; - client->login_try_count++; - if (client->login_try_count == 3) { + wmud_client_set_state(client, WMUD_CLIENT_STATE_FRESH); + wmud_client_get_player(client)->fail_count++; + wmud_client_increase_login_fail_count(client); + if (wmud_client_get_login_fail_count(client) == 3) { wmud_client_send(client, "You are trying " " these bad passwords for" " too many times. Please" " stop that!\r\n"); - wmud_client_close(client, TRUE); + remove_client(client, TRUE); /* TODO: Increase IP fail count, and ban IP if it's too high */ } /* TODO: Increase and save login fail count */ - client->player = NULL; + wmud_client_set_player(client, NULL); } } else { wmud_client_send(client, "\r\nEmpty passwords are" @@ -520,37 +478,37 @@ state_passwait(wmudClient *client) } static void -state_menu(wmudClient *client) +state_menu(WmudClient *client) { gchar *menu_command; - if ((menu_command = wmud_menu_get_command_by_menuchar(*(client->buffer->str), game_menu)) != NULL) + if ((menu_command = wmud_menu_get_command_by_menuchar(*(wmud_client_get_buffer(client)->str), game_menu)) != NULL) wmud_menu_execute_command(client, menu_command); else wmud_client_send(client, "Unknown menu command.\r\n"); } static void -state_yesno(wmudClient *client) +state_yesno(WmudClient *client) { - if (g_ascii_strcasecmp(client->buffer->str, "y") == 0) - (client->yesNoCallback)(client, TRUE); - else if (g_ascii_strcasecmp(client->buffer->str, "n") == 0) - (client->yesNoCallback)(client, FALSE); + if (g_ascii_strcasecmp(wmud_client_get_buffer(client)->str, "y") == 0) + (wmud_client_get_yesno_callback(client))(client, TRUE); + else if (g_ascii_strcasecmp(wmud_client_get_buffer(client)->str, "n") == 0) + (wmud_client_get_yesno_callback(client))(client, FALSE); else wmud_client_send(client, "Please enter a 'Y' or 'N'" " character: "); } static void -state_registering(wmudClient *client) +state_registering(WmudClient *client) { - if (!*(client->buffer->str) && (client->bademail)) - wmud_client_close(client, TRUE); + if (!*(wmud_client_get_buffer(client)->str) && (wmud_client_get_bademail(client) == TRUE)) + remove_client(client, TRUE); - if (g_regex_match(email_regex, client->buffer->str, 0, NULL)) { - client->player->email = g_strdup(client->buffer->str); - client->state = WMUD_CLIENT_STATE_REGEMAIL_CONFIRM; + if (g_regex_match(email_regex, wmud_client_get_buffer(client)->str, 0, NULL)) { + wmud_client_get_player(client)->email = g_strdup(wmud_client_get_buffer(client)->str); + wmud_client_set_state(client, WMUD_CLIENT_STATE_REGEMAIL_CONFIRM); wmud_client_send(client, "It seems to be a valid" " address to me, but could you" " write it again? "); @@ -567,32 +525,32 @@ state_registering(wmudClient *client) " it now: ", active_config->admin_email); - if (*(client->buffer->str)) - client->bademail = TRUE; + if (*(wmud_client_get_buffer(client)->str)) + wmud_client_set_bademail(client, TRUE); } } static void -state_regemail_confirm(wmudClient *client) +state_regemail_confirm(WmudClient *client) { GError *err = NULL; - if (g_ascii_strcasecmp(client->player->email, client->buffer->str) == 0) { - if (wmud_db_save_player(client->player, &err)) { + if (g_ascii_strcasecmp(wmud_client_get_player(client)->email, wmud_client_get_buffer(client)->str) == 0) { + if (wmud_db_save_player(wmud_client_get_player(client), &err)) { wmud_client_send(client, "Good. We will generate the password for this player name, and send it to you\r\nvia e-mail. Please come back to us, if you get that code, so you can log\r\nin.\r\n"); - players = g_slist_prepend(players, wmud_player_dup(client->player)); + players = g_slist_prepend(players, wmud_player_dup(wmud_client_get_player(client))); } else { g_critical("wmud_db_save_player() error: %s", err->message); wmud_client_send(client, "There was an error during the database update. Please try again later!\r\n"); } - wmud_client_close(client, TRUE); + remove_client(client, TRUE); } else { - g_free(client->player->email); - client->player->email = NULL; + g_free(wmud_client_get_player(client)->email); + wmud_client_get_player(client)->email = NULL; wmud_client_send(client, "This is not the same as you entered before.\r\nLet's just try it again: "); - client->state = WMUD_CLIENT_STATE_REGISTERING; + wmud_client_set_state(client, WMUD_CLIENT_STATE_REGISTERING); } } diff --git a/wmud/game-networking.h b/wmud/game-networking.h index bc3986d..fb9c538 100644 --- a/wmud/game-networking.h +++ b/wmud/game-networking.h @@ -21,6 +21,7 @@ #include +#include "wmudclient.h" #include "wmud-types.h" /** @@ -63,8 +64,7 @@ extern GSList *clients; gboolean wmud_networking_init(guint port_number, GMainContext *game_context, GSList *menu_items, GError **err); -void wmud_client_send(wmudClient *client, const gchar *fmt, ...); -void wmud_client_quitanswer(wmudClient *client, gboolean answer); -void wmud_client_newchar_answer(wmudClient *client, gboolean answer); +void wmud_client_quitanswer(WmudClient *client, gboolean answer); +void wmud_client_newchar_answer(WmudClient *client, gboolean answer); #endif diff --git a/wmud/interpreter.c b/wmud/interpreter.c index 6ea2b28..e736c38 100644 --- a/wmud/interpreter.c +++ b/wmud/interpreter.c @@ -148,13 +148,13 @@ wmud_interpreter_check_directions(GSList *directions, GError **err) /** * wmud_interpret_game_command: - * @client: the wmudClient whose command should be processed + * @client: the WmudClient whose command should be processed * - * Processes a wmudClient's buffer, and executes the game command if there is + * Processes a WmudClient's buffer, and executes the game command if there is * one */ void -wmud_interpret_game_command(wmudClient *client) +wmud_interpret_game_command(WmudClient *client) { GSList *command_parts = NULL; gchar *a, @@ -166,14 +166,14 @@ wmud_interpret_game_command(wmudClient *client) match_count = 0; GSList *matches = NULL; - if (strchr(client->buffer->str, '\r') || strchr(client->buffer->str, '\n')) { + if (strchr(wmud_client_get_buffer(client)->str, '\r') || strchr(wmud_client_get_buffer(client)->str, '\n')) { /* We should NEVER reach this point! */ g_assert_not_reached(); return; } - a = client->buffer->str; + a = wmud_client_get_buffer(client)->str; GString *token; @@ -282,6 +282,6 @@ wmud_interpret_game_command(wmudClient *client) WMUD_COMMAND(quit) { wmud_client_send(client, "Are you sure you want to get back to that freaky other reality? [y/N] "); - client->state = WMUD_CLIENT_STATE_YESNO; - client->yesNoCallback = wmud_client_quitanswer; + wmud_client_set_state(client, WMUD_CLIENT_STATE_YESNO); + wmud_client_set_yesno_callback(client, wmud_client_quitanswer); } diff --git a/wmud/interpreter.h b/wmud/interpreter.h index b4093c5..0265738 100644 --- a/wmud/interpreter.h +++ b/wmud/interpreter.h @@ -29,14 +29,14 @@ * * Command handler function type */ -typedef void (*wmudCommandFunc)(wmudClient *client, gchar *command, GSList *token_list); +typedef void (*wmudCommandFunc)(WmudClient *client, gchar *command, GSList *token_list); /** * WMUD_COMMAND: * @name: the name of the command. Should be in lowercase * * Shorthand to create the function header for command handlers */ -#define WMUD_COMMAND(name) void gcmd_ ## name(wmudClient *client, gchar *command, GSList *token_list) +#define WMUD_COMMAND(name) void gcmd_ ## name(WmudClient *client, gchar *command, GSList *token_list) /** * wmudCommand: @@ -59,7 +59,7 @@ typedef enum { } wmudInterpreterError; gboolean wmud_interpreter_check_directions(GSList *directions, GError **err); -void wmud_interpret_game_command(wmudClient *client); +void wmud_interpret_game_command(WmudClient *client); #endif /* __WMUD_INTERPRETER_H__ */ diff --git a/wmud/menu.c b/wmud/menu.c index 2a42d5c..d7e6d3b 100644 --- a/wmud/menu.c +++ b/wmud/menu.c @@ -189,9 +189,9 @@ WMUD_MENU_COMMAND(change_name) WMUD_MENU_COMMAND(quit) { - client->state = WMUD_CLIENT_STATE_YESNO; + wmud_client_set_state(client, WMUD_CLIENT_STATE_YESNO); + wmud_client_set_yesno_callback(client, wmud_client_quitanswer); wmud_client_send(client, "Are you sure you want to get back to the real world? [y/N] "); - client->yesNoCallback = wmud_client_quitanswer; } WMUD_MENU_COMMAND(redisplay_menu) @@ -277,7 +277,7 @@ wmud_menu_get_command_by_menuchar(gchar menuchar, GSList *game_menu) } void -wmud_menu_execute_command(wmudClient *client, gchar *command) +wmud_menu_execute_command(WmudClient *client, gchar *command) { wmudMenuCommandFunc func; @@ -288,17 +288,17 @@ wmud_menu_execute_command(wmudClient *client, gchar *command) } void -send_menu_item(wmudMenu *item, wmudClient *client) +send_menu_item(wmudMenu *item, WmudClient *client) { /* TODO: Send ANSI menu item only to ANSI players! */ wmud_client_send(client, "%s\r\n", item->display_text_ansi); } void -wmud_menu_present(wmudClient *client) +wmud_menu_present(WmudClient *client) { g_slist_foreach(game_menu, (GFunc)send_menu_item, client); - client->state = WMUD_CLIENT_STATE_MENU; + wmud_client_set_state(client, WMUD_CLIENT_STATE_MENU); /* TODO: send menu prologue */ } diff --git a/wmud/menu.h b/wmud/menu.h index 47e0a7f..d3ba679 100644 --- a/wmud/menu.h +++ b/wmud/menu.h @@ -49,14 +49,14 @@ typedef struct _wmudMenu { gchar *func; } wmudMenu; -typedef void (*wmudMenuCommandFunc)(wmudClient *client); +typedef void (*wmudMenuCommandFunc)(WmudClient *client); /** * WMUD_MENU_COMMAND: * @name: the name of the command. Should be in lowercase * * Shorthand to create the function header for menu command handlers */ -#define WMUD_MENU_COMMAND(name) void wmud_mcmd_ ## name(wmudClient *client) +#define WMUD_MENU_COMMAND(name) void wmud_mcmd_ ## name(WmudClient *client) GSList *game_menu; @@ -66,8 +66,8 @@ gboolean wmud_menu_init(GSList **menu); gboolean wmud_menu_items_check(GSList *menu_items, GError **err); void wmud_menu_items_free(GSList **menu_items); gchar *wmud_menu_get_command_by_menuchar(gchar menuchar, GSList *game_menu); -void wmud_menu_execute_command(wmudClient *client, gchar *command); -void wmud_menu_present(wmudClient *client); +void wmud_menu_execute_command(WmudClient *client, gchar *command); +void wmud_menu_present(WmudClient *client); #endif /* __WMUD_MENU_H__ */ diff --git a/wmud/players.c b/wmud/players.c index d37bbb6..a505c8d 100644 --- a/wmud/players.c +++ b/wmud/players.c @@ -53,9 +53,9 @@ GSList *players = NULL; * Return value: %TRUE if the password is valid, %FALSE otherwise. */ gboolean -wmud_player_auth(wmudClient *client) +wmud_player_auth(WmudClient *client) { - if (g_strcmp0(crypt(client->buffer->str, client->player->cpassword), client->player->cpassword) == 0) + if (g_strcmp0(crypt(wmud_client_get_buffer(client)->str, wmud_client_get_player(client)->cpassword), wmud_client_get_player(client)->cpassword) == 0) return TRUE; return FALSE; diff --git a/wmud/players.h b/wmud/players.h index 954f055..32a5a96 100644 --- a/wmud/players.h +++ b/wmud/players.h @@ -22,10 +22,11 @@ #include #include "wmud-types.h" +#include "wmudclient.h" extern GSList *players; -gboolean wmud_player_auth(wmudClient *client); +gboolean wmud_player_auth(WmudClient *client); wmudPlayer *wmud_player_exists(gchar *player_name); void wmud_player_free(wmudPlayer **player); wmudPlayer *wmud_player_dup(wmudPlayer *player); diff --git a/wmud/texts.c b/wmud/texts.c index 0971ce8..a377def 100644 --- a/wmud/texts.c +++ b/wmud/texts.c @@ -78,7 +78,7 @@ wmud_texts_init(void) } void -wmud_text_send_to_client(gchar *text_name, wmudClient *client) +wmud_text_send_to_client(gchar *text_name, WmudClient *client) { gchar *text = g_hash_table_lookup(text_table, text_name); wmud_client_send(client, "%s\r\n", text); diff --git a/wmud/texts.h b/wmud/texts.h index d06bd31..9c657ad 100644 --- a/wmud/texts.h +++ b/wmud/texts.h @@ -22,6 +22,6 @@ #include "wmud-types.h" void wmud_texts_init(void); -void wmud_text_send_to_client(gchar *text, wmudClient *client); +void wmud_text_send_to_client(gchar *text, WmudClient *client); #endif /* __WMUD_TEXTS_H__ */ diff --git a/wmud/wmud-types.h b/wmud/wmud-types.h index e4c176f..46a1e01 100644 --- a/wmud/wmud-types.h +++ b/wmud/wmud-types.h @@ -83,38 +83,5 @@ typedef struct _wmudPlayer { gboolean registered; } wmudPlayer; -typedef struct _wmudClient wmudClient; - -typedef void (*wmudYesNoCallback)(wmudClient *client, gboolean answer); - -/** - * wmudClient: - * @socket: The assigned GSocket object - * @buffer: The client receive buffer. It may hold partial or multiple lines - * until processed - * @state: The state of the client - * @authenticated: TRUE if the client is an authenticated game player - * @player: The associatec player structure. It is also used during - * registration, so it should be always checked if the player is a saved - * database user - * @bademail: indicates that the entered e-mail address is invalid - * @socket_source: the #GSource associated with the client socket - * @login_try_count: the failed login count of the client - * - * wmudClient contains all properties of a connected - * game client. - */ -struct _wmudClient { - GSocket *socket; - GSource *socket_source; - GString *buffer; - wmudClientState state; - gboolean authenticated; - wmudPlayer *player; - gboolean bademail; - gint login_try_count; - wmudYesNoCallback yesNoCallback; -}; - #endif /* __WMUD_TYPES_H__ */ diff --git a/wmud/wmudclient.c b/wmud/wmudclient.c new file mode 100644 index 0000000..becd01a --- /dev/null +++ b/wmud/wmudclient.c @@ -0,0 +1,237 @@ +/* wMUD - Yet another MUD codebase by W00d5t0ck + * Copyright (C) 2012 - Gergely POLONKAI + * + * wmudclient.c: the WmudClient GObject type + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "wmudclient.h" + +#include "players.h" + +#define WMUD_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WMUD_TYPE_CLIENT, WmudClientPrivate)) + +struct _WmudClientPrivate +{ + GSocket *socket; + GSource *socket_source; + GString *buffer; + wmudClientState state; + gboolean authenticated; + wmudPlayer *player; + gboolean bademail; + gint login_try_count; + WmudClientYesnoCallback yesno_callback; +}; + +G_DEFINE_TYPE(WmudClient, wmud_client, G_TYPE_OBJECT); + +static void +wmud_client_dispose(GObject *gobject) +{ + WmudClient *self = WMUD_CLIENT(gobject); + + if (self->priv->socket) { + g_object_unref(self->priv->socket); + + self->priv->socket = NULL; + } + + G_OBJECT_CLASS(wmud_client_parent_class)->dispose(gobject); +} + +static void +wmud_client_finalize(GObject *gobject) +{ + WmudClient *self = WMUD_CLIENT(gobject); + + g_string_free(self->priv->buffer, TRUE); + g_source_destroy(self->priv->socket_source); + + G_OBJECT_CLASS(wmud_client_parent_class)->finalize(gobject); +} + +static void +wmud_client_class_init(WmudClientClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = wmud_client_dispose; + gobject_class->finalize = wmud_client_finalize; + + g_type_class_add_private(klass, sizeof(WmudClientPrivate)); +} + +static void +wmud_client_init(WmudClient *self) +{ + self->priv = WMUD_CLIENT_GET_PRIVATE(self); + self->priv->socket_source = NULL; + self->priv->state = WMUD_CLIENT_STATE_FRESH; + self->priv->buffer = g_string_new(""); +} + +WmudClient * +wmud_client_new(void) +{ + return g_object_new(WMUD_TYPE_CLIENT, NULL, NULL); +} + +void +wmud_client_set_socket(WmudClient *self, GSocket *socket) +{ + /* TODO: Check if a socket is already set! */ + self->priv->socket = socket; + self->priv->socket_source = g_socket_create_source(socket, G_IO_IN | G_IO_OUT | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, NULL); +} + +GSocket * +wmud_client_get_socket(WmudClient *self) +{ + return self->priv->socket; +} + +GSource * +wmud_client_get_socket_source(WmudClient *self) +{ + return self->priv->socket_source; +} + +/** + * wmud_client_send: + * @client: the client to which the message will be sent + * @fmt: the printf() style format string of the message + * @...: optional parameters to the format string + * + * Sends a formatted message to a game client + */ +void +wmud_client_send(WmudClient *self, const gchar *fmt, ...) +{ + va_list ap; + GString *buf = g_string_new(""); + + va_start(ap, fmt); + g_string_vprintf(buf, fmt, ap); + va_end(ap); + + /* TODO: error checking */ + g_socket_send(self->priv->socket, buf->str, buf->len, NULL, NULL); + g_string_free(buf, TRUE); +} + +/** + * wmud_client_close: + * @client: the client whose connection should be dropped + * @send_goodbye: if set to %TRUE, we will send a nice good-bye message to the + * client before dropping the connection + * + * Closes a client connection. If send_goodbye is set to %TRUE, a good-bye + * message will be sent to the client. + */ +void +wmud_client_close(WmudClient *self, gboolean send_goodbye) +{ + if (send_goodbye) + wmud_client_send(self, "\r\nHave a nice real-world day!\r\n\r\n"); + + g_socket_shutdown(self->priv->socket, TRUE, TRUE, NULL); + g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Connection closed."); + + /* TODO: player->registered should be a wmud_player_get_registered() + * call after wmudPlayer is migrated to be a GObject */ + if (self->priv->player && !self->priv->player->registered) + wmud_player_free(&(self->priv->player)); + + g_object_unref(self); +} + +gsize +wmud_client_get_buffer_length(WmudClient *self) +{ + return self->priv->buffer->len; +} + +GString * +wmud_client_get_buffer(WmudClient *self) +{ + return self->priv->buffer; +} + +wmudClientState +wmud_client_get_state(WmudClient *self) +{ + return self->priv->state; +} + +void +wmud_client_set_state(WmudClient *self, wmudClientState state) +{ + self->priv->state = state; +} + +void +wmud_client_set_player(WmudClient *self, wmudPlayer *player) +{ + self->priv->player = player; +} + +wmudPlayer * +wmud_client_get_player(WmudClient *self) +{ + return self->priv->player; +} + +void +wmud_client_set_yesno_callback(WmudClient *self, WmudClientYesnoCallback yesno_callback) +{ + self->priv->yesno_callback = yesno_callback; +} + +WmudClientYesnoCallback +wmud_client_get_yesno_callback(WmudClient *self) +{ + return self->priv->yesno_callback; +} + +void +wmud_client_set_authenticated(WmudClient *self, gboolean authenticated) +{ + self->priv->authenticated = authenticated; +} + +void +wmud_client_increase_login_fail_count(WmudClient *self) +{ + self->priv->login_try_count++; +} + +gint +wmud_client_get_login_fail_count(WmudClient *self) +{ + return self->priv->login_try_count; +} + +void +wmud_client_set_bademail(WmudClient *self, gboolean bademail) +{ + self->priv->bademail = bademail; +} + +gboolean +wmud_client_get_bademail(WmudClient *self) +{ + return self->priv->bademail; +} + diff --git a/wmud/wmudclient.h b/wmud/wmudclient.h new file mode 100644 index 0000000..df6b937 --- /dev/null +++ b/wmud/wmudclient.h @@ -0,0 +1,74 @@ +/* wMUD - Yet another MUD codebase by W00d5t0ck + * Copyright (C) 2012 - Gergely POLONKAI + * + * wmudclient.h: the WmudClient GObject type + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef __WMUD_WMUDCLIENT_H__ +#define __WMUD_WMUDCLIENT_H__ + +#include +#include +#include +#include "wmud-types.h" + +#define WMUD_TYPE_CLIENT (wmud_client_get_type()) +#define WMUD_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WMUD_TYPE_CLIENT, WmudClient)) +#define WMUD_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WMUD_TYPE_CLIENT)) +#define WMUD_TYPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WMUD_TYPE_CLIENT, WmudClientClass)) +#define WMUD_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WMUD_TYPE_CLIENT)) +#define WMUD_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WMUT_TYPE_CLIENT, WmudClientClass)) + +typedef struct _WmudClient WmudClient; +typedef struct _WmudClientClass WmudClientClass; +typedef struct _WmudClientPrivate WmudClientPrivate; +typedef void (*WmudClientYesnoCallback)(WmudClient *client, gboolean answer); + +struct _WmudClient +{ + GObject parent_instance; + + /*< private >*/ + WmudClientPrivate *priv; +}; + +struct _WmudClientClass +{ + GObjectClass parent_class; +}; + +GType wmud_client_get_type(void); +WmudClient *wmud_client_new(void); +void wmud_client_set_socket(WmudClient *client, GSocket *socket); +GSocket *wmud_client_get_socket(WmudClient *client); +GSource *wmud_client_get_socket_source(WmudClient *client); +void wmud_client_send(WmudClient *client, const gchar *fmt, ...); +void wmud_client_close(WmudClient *self, gboolean send_goodbye); +GString *wmud_client_get_buffer(WmudClient *client); +gsize wmud_client_get_buffer_length(WmudClient *client); +void wmud_client_set_state(WmudClient *client, wmudClientState state); +wmudClientState wmud_client_get_state(WmudClient *client); +void wmud_client_set_player(WmudClient *client, wmudPlayer *player); +wmudPlayer *wmud_client_get_player(WmudClient *client); +void wmud_client_set_yesno_callback(WmudClient *client, WmudClientYesnoCallback yesno_callback); +WmudClientYesnoCallback wmud_client_get_yesno_callback(WmudClient *client); +void wmud_client_set_authenticated(WmudClient *client, gboolean authenticated); +void wmud_client_increase_login_fail_count(WmudClient *client); +gint wmud_client_get_login_fail_count(WmudClient *client); +void wmud_client_set_bademail(WmudClient *client, gboolean bademail); +gboolean wmud_client_get_bademail(WmudClient *client); + +#endif /* __WMUD_WMUDMENU_H__ */ +