2012-03-23 15:45:38 +00:00
/* wMUD - Yet another MUD codebase by W00d5t0ck
* Copyright ( C ) 2012 - Gergely POLONKAI
*
2012-03-24 23:13:37 +00:00
* game - networking . c : basic networking functions
2012-03-23 15:45:38 +00:00
*
* 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/>.
*/
2012-03-12 12:55:53 +00:00
# include <glib.h>
# include <gio/gio.h>
2012-03-12 23:42:00 +00:00
# include <string.h>
2012-03-14 19:03:54 +00:00
# include <stdarg.h>
2012-03-12 12:55:53 +00:00
2012-03-22 18:49:59 +00:00
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif /* HAVE_CONFIG_H */
2012-03-12 12:55:53 +00:00
# include "main.h"
2012-03-24 23:13:37 +00:00
# include "game-networking.h"
2012-03-13 01:22:22 +00:00
# include "interpreter.h"
2012-03-21 15:07:02 +00:00
# include "players.h"
2012-03-22 17:34:39 +00:00
# include "db.h"
2012-03-26 14:55:36 +00:00
# include "configuration.h"
2012-04-06 08:31:08 +00:00
# include "menu.h"
2012-05-19 09:51:14 +00:00
# include "texts.h"
2013-01-05 02:43:31 +00:00
# include "wmudclient.h"
2013-01-05 03:47:04 +00:00
# include "wmudplayer.h"
2012-03-12 12:55:53 +00:00
2012-03-24 22:52:36 +00:00
/**
2012-03-26 14:49:04 +00:00
* SECTION : game - networking
2012-03-24 22:52:36 +00:00
* @ short_description : Game related networking code
*
2012-03-29 16:47:56 +00:00
* Functions to handle game connections . Each connection has a # GSocket and a
* # GSource , associated with the game thread ' s # GMainContext .
2012-03-24 22:52:36 +00:00
*/
2012-03-12 12:55:53 +00:00
struct AcceptData {
GMainContext * context ;
GSocketListener * listener ;
} ;
2012-03-29 16:47:56 +00:00
/**
* clients :
2013-01-05 02:43:31 +00:00
* The full # GSList of the currently connected # WmudClient objects .
2012-03-29 16:47:56 +00:00
*/
GSList * clients = NULL ;
2012-03-12 22:52:43 +00:00
2012-04-06 19:47:32 +00:00
static GRegex * email_regex = NULL ;
2013-01-05 02:43:31 +00:00
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 ) ;
2012-03-22 17:34:39 +00:00
2013-01-05 02:43:31 +00:00
static void
remove_client ( WmudClient * client , gboolean send_quitmessage )
2012-03-21 15:07:02 +00:00
{
clients = g_slist_remove ( clients , client ) ;
2013-01-05 02:43:31 +00:00
wmud_client_close ( client , send_quitmessage ) ;
2012-03-21 15:07:02 +00:00
}
2013-01-05 21:56:42 +00:00
static void
hup_client ( WmudClient * client )
{
remove_client ( client , FALSE ) ;
}
2012-03-24 19:34:36 +00:00
/**
* wmud_client_callback :
* @ client : the socket of the client on which the data arrived
* @ condition : the condition available on the client socket
2013-01-05 02:43:31 +00:00
* @ client : the WmudClient structure of the client
2012-03-24 19:34:36 +00:00
*
* Processes incoming client data , and client hangup
*/
2013-01-05 21:56:42 +00:00
static void
recv_client ( WmudClient * client )
2012-03-12 12:55:53 +00:00
{
GError * err = NULL ;
2013-01-05 21:56:42 +00:00
GSocket * client_socket ;
gssize len ;
gchar * buf2 ;
gchar * buf = g_malloc0 ( sizeof ( gchar ) * ( MAX_RECV_LEN + 1 ) ) ;
2012-03-12 12:55:53 +00:00
2013-01-05 21:56:42 +00:00
client_socket = wmud_client_get_socket ( client ) ;
if ( ( len = g_socket_receive ( client_socket , buf , MAX_RECV_LEN , NULL , & err ) ) = = 0 ) {
g_free ( buf ) ;
2013-01-05 02:43:31 +00:00
remove_client ( client , FALSE ) ;
2013-01-02 01:04:53 +00:00
2013-01-05 21:56:42 +00:00
return ;
}
2012-03-12 12:55:53 +00:00
2013-01-05 21:56:42 +00:00
buf2 = buf ;
while ( TRUE ) {
char * r = strchr ( ( char * ) buf2 , ' \r ' ) ,
* n = strchr ( ( char * ) buf2 , ' \n ' ) ;
2012-03-23 13:40:10 +00:00
2013-01-05 21:56:42 +00:00
if ( r | | n ) {
gint i ,
sloc = - 1 ;
2012-03-12 23:42:00 +00:00
2013-01-05 21:56:42 +00:00
if ( ( r < n ) & & r ) {
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 ( wmud_client_get_buffer ( client ) , 0 , buf2 , ( r - buf2 ) ) ;
buf2 = r ;
} else if ( n ) {
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 ( wmud_client_get_buffer ( client ) , 0 , buf2 , ( n - buf2 ) ) ;
buf2 = n ;
}
2012-03-12 23:42:00 +00:00
2013-01-05 21:56:42 +00:00
/* Remove telnet codes from the string */
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 ( wmud_client_get_buffer ( client ) , sloc , i - sloc ) ;
sloc = - 1 ;
2012-03-27 10:38:57 +00:00
}
}
2013-01-05 21:56:42 +00:00
}
2013-01-02 01:04:53 +00:00
2013-01-05 21:56:42 +00:00
if ( sloc ! = - 1 )
g_string_erase ( wmud_client_get_buffer ( client ) , sloc , - 1 ) ;
2013-01-02 01:04:53 +00:00
2013-01-05 21:56:42 +00:00
switch ( wmud_client_get_state ( client ) )
{
case WMUD_CLIENT_STATE_FRESH :
state_fresh ( client ) ;
2012-03-12 23:42:00 +00:00
break ;
2013-01-05 21:56:42 +00:00
case WMUD_CLIENT_STATE_PASSWAIT :
state_passwait ( client ) ;
break ;
case WMUD_CLIENT_STATE_MENU :
state_menu ( client ) ;
break ;
case WMUD_CLIENT_STATE_INGAME :
wmud_interpret_game_command ( client ) ;
break ;
case WMUD_CLIENT_STATE_YESNO :
state_yesno ( client ) ;
break ;
case WMUD_CLIENT_STATE_REGISTERING :
state_registering ( client ) ;
break ;
case WMUD_CLIENT_STATE_REGEMAIL_CONFIRM :
state_regemail_confirm ( client ) ;
break ;
}
g_string_erase ( wmud_client_get_buffer ( client ) , 0 , - 1 ) ;
for ( ; ( ( * buf2 = = ' \r ' ) | | ( * buf2 = = ' \n ' ) ) & & * buf2 ; buf2 + + ) ;
2012-03-12 23:42:00 +00:00
2013-01-05 21:56:42 +00:00
if ( ! * buf2 )
2012-03-12 23:42:00 +00:00
break ;
2013-01-05 21:56:42 +00:00
} else {
if ( wmud_client_get_buffer_length ( client ) > 0 )
g_string_append ( wmud_client_get_buffer ( client ) , buf2 ) ;
else
g_string_overwrite ( wmud_client_get_buffer ( client ) , 0 , buf2 ) ;
2012-03-12 23:42:00 +00:00
2013-01-05 21:56:42 +00:00
break ;
}
2012-03-12 12:55:53 +00:00
}
2013-01-05 21:56:42 +00:00
g_free ( buf ) ;
2012-03-12 12:55:53 +00:00
}
2012-03-24 19:34:36 +00:00
/**
* game_source_callback :
* @ socket : the listener socket on which the new connection arrived
* @ condition : not used
* @ accept_data : the AcceptData structure of the game listener
*
* Callback function to be called when a new connection is available on the
* game listener socket .
2012-03-21 15:07:02 +00:00
*
2012-03-24 19:34:36 +00:00
* Return value : this function always returns % TRUE
2012-03-21 15:07:02 +00:00
*/
2012-03-12 12:55:53 +00:00
gboolean
game_source_callback ( GSocket * socket , GIOCondition condition , struct AcceptData * accept_data )
{
GSocket * client_socket ;
GError * err = NULL ;
2012-03-29 16:32:02 +00:00
GSocketAddress * remote_addr ;
2013-01-05 02:43:31 +00:00
WmudClient * client ;
2012-03-12 12:55:53 +00:00
2012-03-29 16:50:12 +00:00
/* This function should never return an error. If so, it is a huge bug,
* and will trigger a higher level error . */
2012-03-12 12:55:53 +00:00
client_socket = g_socket_listener_accept_socket ( accept_data - > listener , NULL , NULL , & err ) ;
2012-03-12 22:52:43 +00:00
2013-01-05 02:43:31 +00:00
client = wmud_client_new ( ) ;
wmud_client_set_socket ( WMUD_CLIENT ( client ) , client_socket ) ;
2013-01-05 21:56:42 +00:00
wmud_client_set_context ( client , accept_data - > context ) ;
g_signal_connect ( client , " net-hup " , G_CALLBACK ( hup_client ) , NULL ) ;
g_signal_connect ( client , " net-recv " , G_CALLBACK ( recv_client ) , NULL ) ;
2013-01-05 02:43:31 +00:00
2012-03-24 19:35:47 +00:00
clients = g_slist_prepend ( clients , client ) ;
2012-03-12 22:52:43 +00:00
2012-03-29 16:32:02 +00:00
g_clear_error ( & err ) ;
2013-01-02 01:04:53 +00:00
if ( ( remote_addr = g_socket_get_remote_address ( client_socket , & err ) ) ! = NULL ) {
2012-03-29 16:32:02 +00:00
GInetAddress * addr ;
gchar * ip_addr ;
addr = g_inet_socket_address_get_address ( G_INET_SOCKET_ADDRESS ( remote_addr ) ) ;
ip_addr = g_inet_address_to_string ( addr ) ;
g_log ( G_LOG_DOMAIN , G_LOG_LEVEL_INFO , " New game connection from %s " , ip_addr ) ;
g_free ( ip_addr ) ;
g_object_unref ( addr ) ;
g_object_unref ( remote_addr ) ;
2013-01-02 01:04:53 +00:00
} else {
2012-03-29 16:32:02 +00:00
if ( err )
g_log ( G_LOG_DOMAIN , G_LOG_LEVEL_WARNING , " New game connection. The remote address is unknown. This is a bug. Message from upper level: %s " , err - > message ) ;
else
g_log ( G_LOG_DOMAIN , G_LOG_LEVEL_WARNING , " New game connection. The remote address is unknown. This is a bug. " ) ;
}
2013-01-02 01:04:53 +00:00
2012-03-29 16:32:02 +00:00
g_clear_error ( & err ) ;
2013-01-05 02:43:31 +00:00
wmud_client_send ( WMUD_CLIENT ( client ) , " By what name shall we call you? " ) ;
2012-03-12 12:55:53 +00:00
return TRUE ;
}
2012-03-24 19:34:36 +00:00
/**
* wmud_networking_init :
* @ port_number : the port number on which the game listener should listen
2012-03-26 14:49:04 +00:00
* @ game_context : the # GMainContext of the game thread
2012-03-24 19:34:36 +00:00
* @ err : the GError in which possible errors will be reported
*
* Initializes the game network listener
*
* Return value : Returns % TRUE on success . Upon failure , % FALSE is return , and
* err is set accordingly ( if not NULL )
*/
2012-03-12 12:55:53 +00:00
gboolean
2012-04-06 08:31:08 +00:00
wmud_networking_init ( guint port_number , GMainContext * game_context , GSList * menu_items , GError * * err )
2012-03-12 12:55:53 +00:00
{
struct AcceptData * accept_data ;
GSocketListener * game_listener ;
gboolean need_ipv4_socket = TRUE ;
GSocket * game_socket6 ,
2013-01-02 01:04:53 +00:00
* game_socket4 ;
2012-03-22 17:34:39 +00:00
GError * in_err = NULL ;
2012-03-12 12:55:53 +00:00
GSource * game_net_source4 = NULL ,
2013-01-02 01:04:53 +00:00
* game_net_source6 = NULL ;
2012-03-12 12:55:53 +00:00
2012-03-12 22:52:43 +00:00
clients = NULL ;
2012-03-12 12:55:53 +00:00
game_listener = g_socket_listener_new ( ) ;
/* The following snippet is borrowed from GLib 2.30's gsocketlistener.c
* code , to create the necessary sockets to listen on both IPv4 and
* IPv6 address */
2013-01-02 01:04:53 +00:00
if ( ( game_socket6 = g_socket_new ( G_SOCKET_FAMILY_IPV6 , G_SOCKET_TYPE_STREAM , G_SOCKET_PROTOCOL_DEFAULT , NULL ) ) ! = NULL ) {
2012-03-12 12:55:53 +00:00
GInetAddress * inet_address ;
GSocketAddress * address ;
gboolean result ;
inet_address = g_inet_address_new_any ( G_SOCKET_FAMILY_IPV6 ) ;
address = g_inet_socket_address_new ( inet_address , port_number ) ;
g_object_unref ( inet_address ) ;
g_socket_set_listen_backlog ( game_socket6 , 10 ) ;
2013-01-02 01:04:53 +00:00
result =
g_socket_bind ( game_socket6 , address , TRUE , NULL )
& & g_socket_listen ( game_socket6 , NULL ) ;
2012-03-12 12:55:53 +00:00
g_object_unref ( address ) ;
2013-01-02 01:04:53 +00:00
if ( ! result ) {
2012-03-12 12:55:53 +00:00
g_object_unref ( game_socket6 ) ;
2012-03-22 17:34:39 +00:00
g_log ( G_LOG_DOMAIN , G_LOG_LEVEL_WARNING , " Unable to create listener IPv6 socket " ) ;
2013-01-02 01:04:53 +00:00
2012-03-12 12:55:53 +00:00
return FALSE ;
}
if ( g_socket_speaks_ipv4 ( game_socket6 ) )
need_ipv4_socket = FALSE ;
game_net_source6 = g_socket_create_source ( game_socket6 , G_IO_IN , NULL ) ;
2013-01-02 01:04:53 +00:00
/* This function should never return error. If so, that would be a
* really big bug which will trigger a higher level problem for sure */
2012-03-29 16:50:12 +00:00
g_socket_listener_add_socket ( game_listener , game_socket6 , NULL , NULL ) ;
2012-03-12 12:55:53 +00:00
}
2013-01-02 01:04:53 +00:00
if ( need_ipv4_socket ) {
if ( ( game_socket4 = g_socket_new ( G_SOCKET_FAMILY_IPV4 , G_SOCKET_TYPE_STREAM , G_SOCKET_PROTOCOL_DEFAULT , NULL ) ) ! = NULL ) {
2012-03-12 12:55:53 +00:00
GInetAddress * inet_address ;
GSocketAddress * address ;
gboolean result ;
inet_address = g_inet_address_new_any ( G_SOCKET_FAMILY_IPV4 ) ;
address = g_inet_socket_address_new ( inet_address , port_number ) ;
g_object_unref ( inet_address ) ;
g_socket_set_listen_backlog ( game_socket4 , 10 ) ;
2012-03-29 16:50:12 +00:00
result = g_socket_bind ( game_socket4 , address , TRUE , NULL )
& & g_socket_listen ( game_socket4 , NULL ) ;
2012-03-12 12:55:53 +00:00
g_object_unref ( address ) ;
2013-01-02 01:04:53 +00:00
if ( ! result ) {
2012-03-12 12:55:53 +00:00
g_object_unref ( game_socket4 ) ;
2013-01-02 01:04:53 +00:00
2012-03-12 12:55:53 +00:00
if ( ! game_socket6 )
g_object_unref ( game_socket6 ) ;
2012-03-22 17:34:39 +00:00
g_log ( G_LOG_DOMAIN , G_LOG_LEVEL_WARNING , " Unable to create listener IPv4 socket! \n " ) ;
2013-01-02 01:04:53 +00:00
2012-03-12 12:55:53 +00:00
return FALSE ;
}
game_net_source4 = g_socket_create_source ( game_socket4 , G_IO_IN , NULL ) ;
2012-03-29 16:50:12 +00:00
g_socket_listener_add_socket ( game_listener , game_socket4 , NULL , NULL ) ;
2012-03-12 12:55:53 +00:00
}
2013-01-02 01:04:53 +00:00
} else {
2012-03-12 12:55:53 +00:00
if ( game_socket6 ! = NULL )
2012-03-22 17:34:39 +00:00
g_clear_error ( & in_err ) ;
2012-03-12 12:55:53 +00:00
else
return FALSE ;
}
accept_data = g_new ( struct AcceptData , 1 ) ;
accept_data - > listener = game_listener ;
accept_data - > context = game_context ;
2013-01-02 01:04:53 +00:00
if ( game_net_source6 ) {
2012-03-12 12:55:53 +00:00
g_source_set_callback ( game_net_source6 , ( GSourceFunc ) game_source_callback , ( gpointer ) accept_data , NULL ) ;
g_source_attach ( game_net_source6 , game_context ) ;
}
2013-01-02 01:04:53 +00:00
if ( game_net_source4 ) {
2012-03-12 12:55:53 +00:00
g_source_set_callback ( game_net_source4 , ( GSourceFunc ) game_source_callback , ( gpointer ) accept_data , NULL ) ;
g_source_attach ( game_net_source4 , game_context ) ;
}
2012-04-06 08:31:08 +00:00
game_menu = menu_items ;
2012-04-06 19:47:32 +00:00
email_regex = g_regex_new ( " ^[A-Z0-9._%+-]+@[A-Z0-9.-]+ \\ .[A-Z]{2,4}$ " , G_REGEX_CASELESS , 0 , NULL ) ;
2013-01-02 01:04:53 +00:00
2012-03-12 12:55:53 +00:00
return TRUE ;
}
2012-05-17 16:54:16 +00:00
void
2013-01-05 02:43:31 +00:00
wmud_client_quitanswer ( WmudClient * client , gboolean answer )
2012-05-17 16:54:16 +00:00
{
2013-01-02 01:04:53 +00:00
if ( answer ) {
2013-01-05 02:43:31 +00:00
remove_client ( client , TRUE ) ;
2013-01-02 01:04:53 +00:00
} else {
2012-05-17 16:54:16 +00:00
wmud_client_send ( client , " Good boy! \r \n " ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_state ( client , WMUD_CLIENT_STATE_MENU ) ;
2012-05-17 16:54:16 +00:00
}
}
2012-05-17 20:30:06 +00:00
void
2013-01-05 02:43:31 +00:00
wmud_client_newchar_answer ( WmudClient * client , gboolean answer )
2012-05-17 20:30:06 +00:00
{
2013-01-02 01:04:53 +00:00
if ( answer ) {
2012-05-17 20:30:06 +00:00
g_log ( G_LOG_DOMAIN , G_LOG_LEVEL_DEBUG , " Creating new player \n " ) ;
wmud_client_send ( client , " Welcome to this MUD! \r \n Please enter your e-mail address: " ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_state ( client , WMUD_CLIENT_STATE_REGISTERING ) ;
2013-01-02 01:04:53 +00:00
} else {
2012-05-17 20:30:06 +00:00
wmud_client_send ( client , " What is your player-name, then? " ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_state ( client , WMUD_CLIENT_STATE_FRESH ) ;
2012-05-17 20:30:06 +00:00
}
}
2013-01-02 01:05:53 +00:00
static void
2013-01-05 02:43:31 +00:00
state_fresh ( WmudClient * client )
2013-01-02 01:05:53 +00:00
{
2013-01-05 02:43:31 +00:00
if ( * ( wmud_client_get_buffer ( client ) - > str ) ) {
2013-01-05 03:47:04 +00:00
WmudPlayer * player ;
2013-01-02 01:05:53 +00:00
2013-01-05 02:43:31 +00:00
if ( ( player = wmud_player_exists ( wmud_client_get_buffer ( client ) - > str ) ) ! = NULL ) {
2013-01-02 01:05:53 +00:00
g_log ( G_LOG_DOMAIN , G_LOG_LEVEL_DEBUG , " Trying to "
" login with playername '%s' " ,
2013-01-05 02:43:31 +00:00
wmud_client_get_buffer ( client ) - > str ) ;
2013-01-02 01:05:53 +00:00
2013-01-05 03:47:04 +00:00
if ( wmud_player_get_cpassword ( player ) = = NULL ) {
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " Your registration is "
" not finished yet. \r \n " ) ;
2013-01-05 02:43:31 +00:00
remove_client ( client , TRUE ) ;
2013-01-02 01:05:53 +00:00
} else {
2013-01-05 02:43:31 +00:00
wmud_client_set_state ( client , WMUD_CLIENT_STATE_PASSWAIT ) ;
2013-01-05 03:47:04 +00:00
wmud_player_set_registered ( player , TRUE ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_player ( client , player ) ;
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " Please provide us your password: %c%c%c " , TELNET_IAC , TELNET_WILL , TELNET_ECHO ) ;
}
} else {
2013-01-06 20:44:23 +00:00
WmudPlayer * player = wmud_player_new ( ) ;
2013-01-05 03:47:04 +00:00
wmud_player_set_player_name ( player , wmud_client_get_buffer ( client ) - > str ) ;
2013-01-05 02:43:31 +00:00
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 ) ;
2013-01-02 01:05:53 +00:00
}
}
}
static void
2013-01-05 02:43:31 +00:00
state_passwait ( WmudClient * client )
2013-01-02 01:05:53 +00:00
{
2013-01-05 02:43:31 +00:00
if ( * ( wmud_client_get_buffer ( client ) - > str ) ) {
2013-01-05 03:47:04 +00:00
WmudPlayer * player ;
player = wmud_client_get_player ( client ) ;
if ( wmud_player_password_valid ( player , wmud_client_get_buffer ( client ) - > str ) ) {
gint fail_count ;
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " %c%c%c \r \n Login successful. "
" \r \n " , TELNET_IAC , TELNET_WONT ,
TELNET_ECHO ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_authenticated ( client , TRUE ) ;
2013-01-02 01:05:53 +00:00
2013-01-05 03:47:04 +00:00
if ( ( fail_count = wmud_player_get_fail_count ( player ) ) > 0 ) {
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " There %s %d failed "
" login attempt%s with your "
" account since your last "
2013-01-05 02:43:31 +00:00
" visit \r \n " ,
2013-01-05 03:47:04 +00:00
( fail_count = = 1 ) ? " was " : " were " ,
fail_count ,
( fail_count = = 1 ) ? " " : " s " ) ;
}
2013-01-02 01:05:53 +00:00
wmud_text_send_to_client ( " motd " , client ) ;
2013-01-02 01:39:20 +00:00
wmud_menu_present ( client ) ;
2013-01-02 01:05:53 +00:00
} else {
wmud_client_send ( client , " %c%c%cThis password doesn't "
" seem to be valid. Let's try it again... "
" \r \n By what name would you like to be "
" be called? " , TELNET_IAC ,
TELNET_WONT , TELNET_ECHO ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_state ( client , WMUD_CLIENT_STATE_FRESH ) ;
2013-01-05 03:47:04 +00:00
wmud_player_increase_fail_count ( player ) ;
2013-01-05 02:43:31 +00:00
wmud_client_increase_login_fail_count ( client ) ;
if ( wmud_client_get_login_fail_count ( client ) = = 3 ) {
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " You are trying "
" these bad passwords for "
" too many times. Please "
" stop that! \r \n " ) ;
2013-01-05 02:43:31 +00:00
remove_client ( client , TRUE ) ;
2013-01-02 01:05:53 +00:00
/* TODO: Increase IP fail count, and ban IP if it's too high */
}
/* TODO: Increase and save login fail count */
2013-01-05 02:43:31 +00:00
wmud_client_set_player ( client , NULL ) ;
2013-01-02 01:05:53 +00:00
}
} else {
wmud_client_send ( client , " \r \n Empty passwords are "
" not valid. \r \n Try again: " ) ;
}
}
static void
2013-01-05 02:43:31 +00:00
state_menu ( WmudClient * client )
2013-01-02 01:05:53 +00:00
{
gchar * menu_command ;
2013-01-05 02:43:31 +00:00
if ( ( menu_command = wmud_menu_get_command_by_menuchar ( * ( wmud_client_get_buffer ( client ) - > str ) , game_menu ) ) ! = NULL )
2013-01-02 01:05:53 +00:00
wmud_menu_execute_command ( client , menu_command ) ;
else
wmud_client_send ( client , " Unknown menu command. \r \n " ) ;
}
static void
2013-01-05 02:43:31 +00:00
state_yesno ( WmudClient * client )
2013-01-02 01:05:53 +00:00
{
2013-01-05 02:43:31 +00:00
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 ) ;
2013-01-02 01:05:53 +00:00
else
wmud_client_send ( client , " Please enter a 'Y' or 'N' "
" character: " ) ;
}
static void
2013-01-05 02:43:31 +00:00
state_registering ( WmudClient * client )
2013-01-02 01:05:53 +00:00
{
2013-01-05 02:43:31 +00:00
if ( ! * ( wmud_client_get_buffer ( client ) - > str ) & & ( wmud_client_get_bademail ( client ) = = TRUE ) )
remove_client ( client , TRUE ) ;
2013-01-02 01:05:53 +00:00
2013-01-05 02:43:31 +00:00
if ( g_regex_match ( email_regex , wmud_client_get_buffer ( client ) - > str , 0 , NULL ) ) {
2013-01-05 03:47:04 +00:00
wmud_player_set_email ( wmud_client_get_player ( client ) , wmud_client_get_buffer ( client ) - > str ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_state ( client , WMUD_CLIENT_STATE_REGEMAIL_CONFIRM ) ;
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " It seems to be a valid "
" address to me, but could you "
" write it again? " ) ;
} else {
wmud_client_send ( client , " \r \n Sorry, but this "
" e-mail address doesn't seem to be "
" valid to me. \r \n \r \n If you think "
" this is a valid address, simply "
" press enter to quit, and send an "
" e-mail to %s from that address, "
" so we can fix our e-mail "
" validation code. \r \n \r \n If you "
" just mistyped your address, type "
" it now: " ,
active_config - > admin_email ) ;
2013-01-05 02:43:31 +00:00
if ( * ( wmud_client_get_buffer ( client ) - > str ) )
wmud_client_set_bademail ( client , TRUE ) ;
2013-01-02 01:05:53 +00:00
}
}
static void
2013-01-05 02:43:31 +00:00
state_regemail_confirm ( WmudClient * client )
2013-01-02 01:05:53 +00:00
{
GError * err = NULL ;
2013-01-05 03:47:04 +00:00
if ( g_ascii_strcasecmp ( wmud_player_get_email ( wmud_client_get_player ( client ) ) , wmud_client_get_buffer ( client ) - > str ) = = 0 ) {
2013-01-05 02:43:31 +00:00
if ( wmud_db_save_player ( wmud_client_get_player ( client ) , & err ) ) {
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " Good. We will generate the password for this player name, and send it to you \r \n via e-mail. Please come back to us, if you get that code, so you can log \r \n in. \r \n " ) ;
2013-01-05 02:43:31 +00:00
players = g_slist_prepend ( players , wmud_player_dup ( wmud_client_get_player ( client ) ) ) ;
2013-01-02 01:05:53 +00:00
} 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 " ) ;
}
2013-01-05 02:43:31 +00:00
remove_client ( client , TRUE ) ;
2013-01-02 01:05:53 +00:00
} else {
2013-01-05 03:47:04 +00:00
wmud_player_set_email ( wmud_client_get_player ( client ) , NULL ) ;
2013-01-02 01:05:53 +00:00
wmud_client_send ( client , " This is not the same as you entered before. \r \n Let's just try it again: " ) ;
2013-01-05 02:43:31 +00:00
wmud_client_set_state ( client , WMUD_CLIENT_STATE_REGISTERING ) ;
2013-01-02 01:05:53 +00:00
}
}