Migrated struct wmudClient to the WmudClient GObject

This commit is contained in:
Gergely Polonkai 2013-01-05 03:43:31 +01:00
parent 50a487b7e2
commit 1489be34bf
14 changed files with 436 additions and 199 deletions

View File

@ -1,5 +1,5 @@
bin_PROGRAMS = wmud bin_PROGRAMS = wmud
AM_CPPFLAGS = -DWMUD_STATEDIR=\""$(localstatedir)"\" -DWMUD_CONFDIR=\""$(sysconfdir)"\" $(MEMCACHED_CFLAGS) $(GLIB_CFLAGS) $(GIO_CFLAGS) $(GTHREAD_CFLAGS) $(SQLITE3_CFLAGS) $(CURL_CFLAGS) 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) wmud_LDADD = $(MEMCACHED_LIBS) $(GLIB_LIBS) $(GIO_LIBS) $(GTHREAD_LIBS) $(SQLITE3_LIBS) $(CURL_LIBS)

View File

@ -33,6 +33,7 @@
#include "configuration.h" #include "configuration.h"
#include "menu.h" #include "menu.h"
#include "texts.h" #include "texts.h"
#include "wmudclient.h"
/** /**
* SECTION:game-networking * SECTION:game-networking
@ -49,55 +50,33 @@ struct AcceptData {
/** /**
* clients: * clients:
* The full #GSList of the currently connected #wmudClient structs. * The full #GSList of the currently connected #WmudClient objects.
*/ */
GSList *clients = NULL; GSList *clients = NULL;
static GRegex *email_regex = NULL; static GRegex *email_regex = NULL;
void wmud_client_interpret_newplayer_email(wmudClient *client); void wmud_client_interpret_newplayer_email(WmudClient *client);
void wmud_client_interpret_newplayer_mailconfirm(wmudClient *client); void wmud_client_interpret_newplayer_mailconfirm(WmudClient *client);
static void state_fresh(wmudClient *client); static void state_fresh(WmudClient *client);
static void state_passwait(wmudClient *client); static void state_passwait(WmudClient *client);
static void state_menu(wmudClient *client); static void state_menu(WmudClient *client);
static void state_yesno(wmudClient *client); static void state_yesno(WmudClient *client);
static void state_registering(wmudClient *client); static void state_registering(WmudClient *client);
static void state_regemail_confirm(wmudClient *client); static void state_regemail_confirm(WmudClient *client);
/** static void
* wmud_client_close: remove_client(WmudClient *client, gboolean send_quitmessage)
* @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)
{ {
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); clients = g_slist_remove(clients, client);
wmud_client_close(client, send_quitmessage);
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_callback: * wmud_client_callback:
* @client: the socket of the client on which the data arrived * @client: the socket of the client on which the data arrived
* @condition: the condition available on the client socket * @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 * Processes incoming client data, and client hangup
* *
@ -105,12 +84,12 @@ wmud_client_close(wmudClient *client, gboolean send_goodbye)
* otherwise * otherwise
*/ */
static gboolean 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; GError *err = NULL;
if (condition & G_IO_HUP) { if (condition & G_IO_HUP) {
wmud_client_close(client, FALSE); remove_client(client, FALSE);
return FALSE; return FALSE;
} else if ((condition & G_IO_IN) || (condition & G_IO_PRI)) { } 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) { if ((len = g_socket_receive(client_socket, buf, MAX_RECV_LEN, NULL, &err)) == 0) {
g_free(buf); g_free(buf);
wmud_client_close(client, FALSE); remove_client(client, FALSE);
return FALSE; return FALSE;
} }
@ -135,38 +114,38 @@ wmud_client_callback(GSocket *client_socket, GIOCondition condition, wmudClient
sloc = -1; sloc = -1;
if ((r < n) && r) { if ((r < n) && r) {
if (client->buffer->len > 0) if (wmud_client_get_buffer_length(client) > 0)
g_string_append_len(client->buffer, buf2, (r - buf2)); g_string_append_len(wmud_client_get_buffer(client), buf2, (r - buf2));
else 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; buf2 = r;
} else if (n) { } else if (n) {
if (client->buffer->len > 0) if (wmud_client_get_buffer_length(client) > 0)
g_string_append_len(client->buffer, buf2, (n - buf2)); g_string_append_len(wmud_client_get_buffer(client), buf2, (n - buf2));
else 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; buf2 = n;
} }
/* Remove telnet codes from the string */ /* Remove telnet codes from the string */
for (i = 0; i < client->buffer->len; i++) { for (i = 0; i < wmud_client_get_buffer_length(client); i++) {
guchar c = (client->buffer->str)[i]; guchar c = (wmud_client_get_buffer(client)->str)[i];
if ((c >= 240) || (c == 1)) { if ((c >= 240) || (c == 1)) {
if (sloc == -1) if (sloc == -1)
sloc = i; sloc = i;
} else { } else {
if (sloc != -1) { if (sloc != -1) {
g_string_erase(client->buffer, sloc, i - sloc); g_string_erase(wmud_client_get_buffer(client), sloc, i - sloc);
sloc = -1; sloc = -1;
} }
} }
} }
if (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: case WMUD_CLIENT_STATE_FRESH:
state_fresh(client); state_fresh(client);
@ -190,17 +169,17 @@ wmud_client_callback(GSocket *client_socket, GIOCondition condition, wmudClient
state_regemail_confirm(client); state_regemail_confirm(client);
break; 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++); for (; ((*buf2 == '\r') || (*buf2 == '\n')) && *buf2; buf2++);
if (!*buf2) if (!*buf2)
break; break;
} else { } else {
if (client->buffer->len > 0) if (wmud_client_get_buffer_length(client) > 0)
g_string_append(client->buffer, buf2); g_string_append(wmud_client_get_buffer(client), buf2);
else else
g_string_overwrite(client->buffer, 0, buf2); g_string_overwrite(wmud_client_get_buffer(client), 0, buf2);
break; break;
} }
@ -229,21 +208,19 @@ game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData
GSocket *client_socket; GSocket *client_socket;
GSource *client_source; GSource *client_source;
GError *err = NULL; GError *err = NULL;
wmudClient *client;
GSocketAddress *remote_addr; GSocketAddress *remote_addr;
WmudClient *client;
/* This function should never return an error. If so, it is a huge bug, /* This function should never return an error. If so, it is a huge bug,
* and will trigger a higher level error. */ * and will trigger a higher level error. */
client_socket = g_socket_listener_accept_socket(accept_data->listener, NULL, NULL, &err); client_socket = g_socket_listener_accept_socket(accept_data->listener, NULL, NULL, &err);
client = g_new0(wmudClient, 1); client = wmud_client_new();
client->socket = client_socket; wmud_client_set_socket(WMUD_CLIENT(client), client_socket);
client->buffer = g_string_new(""); client_source = wmud_client_get_socket_source(client);
client->state = WMUD_CLIENT_STATE_FRESH;
clients = g_slist_prepend(clients, 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_set_callback(client_source, (GSourceFunc)wmud_client_callback, client, NULL);
g_source_attach(client_source, accept_data->context); 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); 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; return TRUE;
} }
@ -394,99 +371,80 @@ wmud_networking_init(guint port_number, GMainContext *game_context, GSList *menu
return TRUE; 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 void
wmud_client_send(wmudClient *client, const gchar *fmt, ...) wmud_client_quitanswer(WmudClient *client, gboolean answer)
{
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)
{ {
if (answer) { if (answer) {
wmud_client_close(client, TRUE); remove_client(client, TRUE);
} else { } else {
wmud_client_send(client, "Good boy!\r\n"); wmud_client_send(client, "Good boy!\r\n");
client->state = WMUD_CLIENT_STATE_MENU; wmud_client_set_state(client, WMUD_CLIENT_STATE_MENU);
} }
} }
void void
wmud_client_newchar_answer(wmudClient *client, gboolean answer) wmud_client_newchar_answer(WmudClient *client, gboolean answer)
{ {
if (answer) { if (answer) {
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Creating new player\n"); 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: "); 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 { } else {
wmud_client_send(client, "What is your player-name, then? "); 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 static void
state_fresh(wmudClient *client) state_fresh(WmudClient *client)
{ {
if (*(client->buffer->str)) { if (*(wmud_client_get_buffer(client)->str)) {
wmudPlayer *player; 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" g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Trying to"
" login with playername '%s'", " login with playername '%s'",
client->buffer->str); wmud_client_get_buffer(client)->str);
if (player->cpassword == NULL) { if (player->cpassword == NULL) {
wmud_client_send(client, "Your registration is" wmud_client_send(client, "Your registration is"
" not finished yet.\r\n"); " not finished yet.\r\n");
wmud_client_close(client, TRUE); remove_client(client, TRUE);
} else { } else {
client->state = WMUD_CLIENT_STATE_PASSWAIT; wmud_client_set_state(client, WMUD_CLIENT_STATE_PASSWAIT);
client->player = player; player->registered = TRUE;
client->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); wmud_client_send(client, "Please provide us your password: %c%c%c", TELNET_IAC, TELNET_WILL, TELNET_ECHO);
} }
} else { } else {
client->player = g_new0(wmudPlayer, 1); wmudPlayer *player = g_new0(wmudPlayer, 1);
client->player->player_name = g_strdup(client->buffer->str); player->player_name = g_strdup(wmud_client_get_buffer(client)->str);
client->state = WMUD_CLIENT_STATE_YESNO; wmud_client_set_player(client, player);
client->yesNoCallback = wmud_client_newchar_answer; wmud_client_set_state(client, WMUD_CLIENT_STATE_YESNO);
wmud_client_send(client, "Is %s new to this game? [Y/N] ", client->buffer->str); 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 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)) { if (wmud_player_auth(client)) {
wmud_client_send(client, "%c%c%c\r\nLogin successful." wmud_client_send(client, "%c%c%c\r\nLogin successful."
"\r\n", TELNET_IAC, TELNET_WONT, "\r\n", TELNET_IAC, TELNET_WONT,
TELNET_ECHO); 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" wmud_client_send(client, "There %s %d failed"
" login attempt%s with your" " login attempt%s with your"
" account since your last" " 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_text_send_to_client("motd", client);
wmud_menu_present(client); wmud_menu_present(client);
@ -496,22 +454,22 @@ state_passwait(wmudClient *client)
" \r\nBy what name would you like to be" " \r\nBy what name would you like to be"
" be called? ", TELNET_IAC, " be called? ", TELNET_IAC,
TELNET_WONT, TELNET_ECHO); TELNET_WONT, TELNET_ECHO);
client->state = WMUD_CLIENT_STATE_FRESH; wmud_client_set_state(client, WMUD_CLIENT_STATE_FRESH);
client->player->fail_count++; wmud_client_get_player(client)->fail_count++;
client->login_try_count++; wmud_client_increase_login_fail_count(client);
if (client->login_try_count == 3) { if (wmud_client_get_login_fail_count(client) == 3) {
wmud_client_send(client, "You are trying " wmud_client_send(client, "You are trying "
" these bad passwords for" " these bad passwords for"
" too many times. Please" " too many times. Please"
" stop that!\r\n"); " 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 IP fail count, and ban IP if it's too high */
} }
/* TODO: Increase and save login fail count */ /* TODO: Increase and save login fail count */
client->player = NULL; wmud_client_set_player(client, NULL);
} }
} else { } else {
wmud_client_send(client, "\r\nEmpty passwords are" wmud_client_send(client, "\r\nEmpty passwords are"
@ -520,37 +478,37 @@ state_passwait(wmudClient *client)
} }
static void static void
state_menu(wmudClient *client) state_menu(WmudClient *client)
{ {
gchar *menu_command; 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); wmud_menu_execute_command(client, menu_command);
else else
wmud_client_send(client, "Unknown menu command.\r\n"); wmud_client_send(client, "Unknown menu command.\r\n");
} }
static void static void
state_yesno(wmudClient *client) state_yesno(WmudClient *client)
{ {
if (g_ascii_strcasecmp(client->buffer->str, "y") == 0) if (g_ascii_strcasecmp(wmud_client_get_buffer(client)->str, "y") == 0)
(client->yesNoCallback)(client, TRUE); (wmud_client_get_yesno_callback(client))(client, TRUE);
else if (g_ascii_strcasecmp(client->buffer->str, "n") == 0) else if (g_ascii_strcasecmp(wmud_client_get_buffer(client)->str, "n") == 0)
(client->yesNoCallback)(client, FALSE); (wmud_client_get_yesno_callback(client))(client, FALSE);
else else
wmud_client_send(client, "Please enter a 'Y' or 'N'" wmud_client_send(client, "Please enter a 'Y' or 'N'"
" character: "); " character: ");
} }
static void static void
state_registering(wmudClient *client) state_registering(WmudClient *client)
{ {
if (!*(client->buffer->str) && (client->bademail)) if (!*(wmud_client_get_buffer(client)->str) && (wmud_client_get_bademail(client) == TRUE))
wmud_client_close(client, TRUE); remove_client(client, TRUE);
if (g_regex_match(email_regex, client->buffer->str, 0, NULL)) { if (g_regex_match(email_regex, wmud_client_get_buffer(client)->str, 0, NULL)) {
client->player->email = g_strdup(client->buffer->str); wmud_client_get_player(client)->email = g_strdup(wmud_client_get_buffer(client)->str);
client->state = WMUD_CLIENT_STATE_REGEMAIL_CONFIRM; wmud_client_set_state(client, WMUD_CLIENT_STATE_REGEMAIL_CONFIRM);
wmud_client_send(client, "It seems to be a valid" wmud_client_send(client, "It seems to be a valid"
" address to me, but could you" " address to me, but could you"
" write it again? "); " write it again? ");
@ -567,32 +525,32 @@ state_registering(wmudClient *client)
" it now: ", " it now: ",
active_config->admin_email); active_config->admin_email);
if (*(client->buffer->str)) if (*(wmud_client_get_buffer(client)->str))
client->bademail = TRUE; wmud_client_set_bademail(client, TRUE);
} }
} }
static void static void
state_regemail_confirm(wmudClient *client) state_regemail_confirm(WmudClient *client)
{ {
GError *err = NULL; GError *err = NULL;
if (g_ascii_strcasecmp(client->player->email, client->buffer->str) == 0) { if (g_ascii_strcasecmp(wmud_client_get_player(client)->email, wmud_client_get_buffer(client)->str) == 0) {
if (wmud_db_save_player(client->player, &err)) { 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"); 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 { } else {
g_critical("wmud_db_save_player() error: %s", err->message); 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_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 { } else {
g_free(client->player->email); g_free(wmud_client_get_player(client)->email);
client->player->email = NULL; 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: "); 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);
} }
} }

View File

@ -21,6 +21,7 @@
#include <glib.h> #include <glib.h>
#include "wmudclient.h"
#include "wmud-types.h" #include "wmud-types.h"
/** /**
@ -63,8 +64,7 @@
extern GSList *clients; extern GSList *clients;
gboolean wmud_networking_init(guint port_number, GMainContext *game_context, GSList *menu_items, GError **err); 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_quitanswer(wmudClient *client, gboolean answer); void wmud_client_newchar_answer(WmudClient *client, gboolean answer);
void wmud_client_newchar_answer(wmudClient *client, gboolean answer);
#endif #endif

View File

@ -148,13 +148,13 @@ wmud_interpreter_check_directions(GSList *directions, GError **err)
/** /**
* wmud_interpret_game_command: * 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 * one
*/ */
void void
wmud_interpret_game_command(wmudClient *client) wmud_interpret_game_command(WmudClient *client)
{ {
GSList *command_parts = NULL; GSList *command_parts = NULL;
gchar *a, gchar *a,
@ -166,14 +166,14 @@ wmud_interpret_game_command(wmudClient *client)
match_count = 0; match_count = 0;
GSList *matches = NULL; 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! */ /* We should NEVER reach this point! */
g_assert_not_reached(); g_assert_not_reached();
return; return;
} }
a = client->buffer->str; a = wmud_client_get_buffer(client)->str;
GString *token; GString *token;
@ -282,6 +282,6 @@ wmud_interpret_game_command(wmudClient *client)
WMUD_COMMAND(quit) WMUD_COMMAND(quit)
{ {
wmud_client_send(client, "Are you sure you want to get back to that freaky other reality? [y/N] "); 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; wmud_client_set_state(client, WMUD_CLIENT_STATE_YESNO);
client->yesNoCallback = wmud_client_quitanswer; wmud_client_set_yesno_callback(client, wmud_client_quitanswer);
} }

View File

@ -29,14 +29,14 @@
* *
* Command handler function type * 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: * WMUD_COMMAND:
* @name: the name of the command. Should be in lowercase * @name: the name of the command. Should be in lowercase
* *
* Shorthand to create the function header for command handlers * 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: * wmudCommand:
@ -59,7 +59,7 @@ typedef enum {
} wmudInterpreterError; } wmudInterpreterError;
gboolean wmud_interpreter_check_directions(GSList *directions, GError **err); 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__ */ #endif /* __WMUD_INTERPRETER_H__ */

View File

@ -189,9 +189,9 @@ WMUD_MENU_COMMAND(change_name)
WMUD_MENU_COMMAND(quit) 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] "); 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) WMUD_MENU_COMMAND(redisplay_menu)
@ -277,7 +277,7 @@ wmud_menu_get_command_by_menuchar(gchar menuchar, GSList *game_menu)
} }
void void
wmud_menu_execute_command(wmudClient *client, gchar *command) wmud_menu_execute_command(WmudClient *client, gchar *command)
{ {
wmudMenuCommandFunc func; wmudMenuCommandFunc func;
@ -288,17 +288,17 @@ wmud_menu_execute_command(wmudClient *client, gchar *command)
} }
void void
send_menu_item(wmudMenu *item, wmudClient *client) send_menu_item(wmudMenu *item, WmudClient *client)
{ {
/* TODO: Send ANSI menu item only to ANSI players! */ /* TODO: Send ANSI menu item only to ANSI players! */
wmud_client_send(client, "%s\r\n", item->display_text_ansi); wmud_client_send(client, "%s\r\n", item->display_text_ansi);
} }
void void
wmud_menu_present(wmudClient *client) wmud_menu_present(WmudClient *client)
{ {
g_slist_foreach(game_menu, (GFunc)send_menu_item, 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 */ /* TODO: send menu prologue */
} }

View File

@ -49,14 +49,14 @@ typedef struct _wmudMenu {
gchar *func; gchar *func;
} wmudMenu; } wmudMenu;
typedef void (*wmudMenuCommandFunc)(wmudClient *client); typedef void (*wmudMenuCommandFunc)(WmudClient *client);
/** /**
* WMUD_MENU_COMMAND: * WMUD_MENU_COMMAND:
* @name: the name of the command. Should be in lowercase * @name: the name of the command. Should be in lowercase
* *
* Shorthand to create the function header for menu command handlers * 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; GSList *game_menu;
@ -66,8 +66,8 @@ gboolean wmud_menu_init(GSList **menu);
gboolean wmud_menu_items_check(GSList *menu_items, GError **err); gboolean wmud_menu_items_check(GSList *menu_items, GError **err);
void wmud_menu_items_free(GSList **menu_items); void wmud_menu_items_free(GSList **menu_items);
gchar *wmud_menu_get_command_by_menuchar(gchar menuchar, GSList *game_menu); gchar *wmud_menu_get_command_by_menuchar(gchar menuchar, GSList *game_menu);
void wmud_menu_execute_command(wmudClient *client, gchar *command); void wmud_menu_execute_command(WmudClient *client, gchar *command);
void wmud_menu_present(wmudClient *client); void wmud_menu_present(WmudClient *client);
#endif /* __WMUD_MENU_H__ */ #endif /* __WMUD_MENU_H__ */

View File

@ -53,9 +53,9 @@ GSList *players = NULL;
* Return value: %TRUE if the password is valid, %FALSE otherwise. * Return value: %TRUE if the password is valid, %FALSE otherwise.
*/ */
gboolean 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 TRUE;
return FALSE; return FALSE;

View File

@ -22,10 +22,11 @@
#include <glib.h> #include <glib.h>
#include "wmud-types.h" #include "wmud-types.h"
#include "wmudclient.h"
extern GSList *players; extern GSList *players;
gboolean wmud_player_auth(wmudClient *client); gboolean wmud_player_auth(WmudClient *client);
wmudPlayer *wmud_player_exists(gchar *player_name); wmudPlayer *wmud_player_exists(gchar *player_name);
void wmud_player_free(wmudPlayer **player); void wmud_player_free(wmudPlayer **player);
wmudPlayer *wmud_player_dup(wmudPlayer *player); wmudPlayer *wmud_player_dup(wmudPlayer *player);

View File

@ -78,7 +78,7 @@ wmud_texts_init(void)
} }
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); gchar *text = g_hash_table_lookup(text_table, text_name);
wmud_client_send(client, "%s\r\n", text); wmud_client_send(client, "%s\r\n", text);

View File

@ -22,6 +22,6 @@
#include "wmud-types.h" #include "wmud-types.h"
void wmud_texts_init(void); 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__ */ #endif /* __WMUD_TEXTS_H__ */

View File

@ -83,38 +83,5 @@ typedef struct _wmudPlayer {
gboolean registered; gboolean registered;
} wmudPlayer; } 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
*
* <structname>wmudClient</structname> 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__ */ #endif /* __WMUD_TYPES_H__ */

237
wmud/wmudclient.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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;
}

74
wmud/wmudclient.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef __WMUD_WMUDCLIENT_H__
#define __WMUD_WMUDCLIENT_H__
#include <glib-object.h>
#include <glib.h>
#include <gio/gio.h>
#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__ */