From c893fd4a9e6557dcac2e639932da31f4373164ac Mon Sep 17 00:00:00 2001 From: ehouse Date: Fri, 4 Dec 2009 08:18:49 +0000 Subject: [PATCH] On receipt of connection-denied message via new rerror callback, put up new error messages and then conns dialog so user can connect again after changing room name or just waiting. A new game is started so that comms is re-inited and will try again to connect to relay. --- xwords4/linux/cursesmain.c | 16 +++++++++++++ xwords4/linux/gtkconnsdlg.c | 17 +++++++++++++- xwords4/linux/gtkconnsdlg.h | 2 +- xwords4/linux/gtkmain.c | 47 +++++++++++++++++++++++++++++++++---- xwords4/linux/gtknewgame.c | 24 ++++++++++++++++--- xwords4/linux/gtknewgame.h | 2 +- xwords4/linux/linuxutl.c | 8 +++++++ 7 files changed, 105 insertions(+), 11 deletions(-) diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c index 91641e77b..b2a8d1ca5 100644 --- a/xwords4/linux/cursesmain.c +++ b/xwords4/linux/cursesmain.c @@ -1400,6 +1400,18 @@ positionSizeStuff( CursesAppGlobals* globals, int width, int height ) board_invalAll( board ); } /* positionSizeStuff */ +static void +relay_status_curses( void* XP_UNUSED(closure), CommsRelayState state ) +{ + XP_LOGF( "%s got status: %s", __func__, CommsRelayState2Str(state) ); +} + +static void +relay_error_curses( void* XP_UNUSED(closure), XWREASON XP_UNUSED(relayErr) ) +{ + LOG_FUNC(); +} + void cursesmain( XP_Bool isServer, LaunchParams* params ) { @@ -1463,6 +1475,10 @@ cursesmain( XP_Bool isServer, LaunchParams* params ) .send = LINUX_SEND, #ifdef COMMS_HEARTBEAT .reset = linux_reset, +#endif +#ifdef XWFEATURE_RELAY + .rstatus = relay_status_curses, + .rerror = relay_error_curses, #endif }; diff --git a/xwords4/linux/gtkconnsdlg.c b/xwords4/linux/gtkconnsdlg.c index fe053a841..10cfa1204 100644 --- a/xwords4/linux/gtkconnsdlg.c +++ b/xwords4/linux/gtkconnsdlg.c @@ -26,6 +26,7 @@ typedef struct _GtkConnsState { GtkAppGlobals* globals; CommsAddrRec* addr; + DeviceRole role; GtkWidget* invite; GtkWidget* hostName; @@ -125,6 +126,18 @@ static GtkWidget* makeRelayPage( GtkConnsState* state ) { GtkWidget* vbox = gtk_vbox_new( FALSE, 0 ); + const gchar* hint = NULL; + + if ( SERVER_ISSERVER == state->role ) { + hint = "As host, you pick the room name for the game, and must " + "connect first"; + } else { + XP_ASSERT( SERVER_ISCLIENT == state->role ); + hint = "As guest, you get the room name from the host. Be sure to " + "let the host connect first to validate the name."; + } + + gtk_box_pack_start( GTK_BOX(vbox), gtk_label_new( hint ), FALSE, TRUE, 0 ); GtkWidget* hbox = makeLabeledField( "Room", &state->invite ); gtk_entry_set_text( GTK_ENTRY(state->invite), @@ -166,7 +179,8 @@ makeBTPage( GtkConnsState* state ) } /* makeBTPage */ gboolean -gtkConnsDlg( GtkAppGlobals* globals, CommsAddrRec* addr, XP_Bool readOnly ) +gtkConnsDlg( GtkAppGlobals* globals, CommsAddrRec* addr, DeviceRole role, + XP_Bool readOnly ) { GtkConnsState state; XP_MEMSET( &state, 0, sizeof(state) ); @@ -176,6 +190,7 @@ gtkConnsDlg( GtkAppGlobals* globals, CommsAddrRec* addr, XP_Bool readOnly ) state.readOnly = readOnly; state.globals = globals; state.addr = addr; + state.role = role; GtkWidget* dialog; GtkWidget* vbox; diff --git a/xwords4/linux/gtkconnsdlg.h b/xwords4/linux/gtkconnsdlg.h index a5983b419..8581b22a5 100644 --- a/xwords4/linux/gtkconnsdlg.h +++ b/xwords4/linux/gtkconnsdlg.h @@ -27,7 +27,7 @@ #include "gtkmain.h" gboolean gtkConnsDlg( GtkAppGlobals* globals, CommsAddrRec* addr, - XP_Bool readOnly ); + DeviceRole role, XP_Bool readOnly ); #endif /* _GTKCONNSDLG_H_ */ #endif /* PLATFORM_GTK */ diff --git a/xwords4/linux/gtkmain.c b/xwords4/linux/gtkmain.c index 909c42f64..58f4ceef9 100644 --- a/xwords4/linux/gtkmain.c +++ b/xwords4/linux/gtkmain.c @@ -67,6 +67,8 @@ static void sendOnClose( XWStreamCtxt* stream, void* closure ); static void setCtrlsForTray( GtkAppGlobals* globals ); static void printFinalScores( GtkAppGlobals* globals ); static void new_game( GtkWidget* widget, GtkAppGlobals* globals ); +static void new_game_impl( GtkAppGlobals* globals, XP_Bool fireConnDlg ); + #define GTK_TRAY_HT_ROWS 3 @@ -301,6 +303,34 @@ relay_status_gtk( void* closure, CommsRelayState state ) draw_gtk_status( globals->draw, globals->stateChar ); } +static gint +invoke_new_game( gpointer data ) +{ + GtkAppGlobals* globals = (GtkAppGlobals*)data; + new_game_impl( globals, XP_TRUE ); + return 0; +} + +static void +relay_error_gtk( void* closure, XWREASON relayErr ) +{ + LOG_FUNC(); + GtkAppGlobals* globals = (GtkAppGlobals*)closure; + + gint (*proc)( gpointer data ); + switch( relayErr ) { + case XWRELAY_ERROR_NO_ROOM: + case XWRELAY_ERROR_DUP_ROOM: + proc = invoke_new_game; + break; + default: + assert(0); + break; + } + + (void)g_idle_add( proc, globals ); +} + static void createOrLoadObjects( GtkAppGlobals* globals ) { @@ -324,6 +354,7 @@ createOrLoadObjects( GtkAppGlobals* globals ) #endif #ifdef XWFEATURE_RELAY .rstatus = relay_status_gtk, + .rerror = relay_error_gtk, #endif }; @@ -407,7 +438,7 @@ createOrLoadObjects( GtkAppGlobals* globals ) #endif if ( params->needsNewGame ) { - new_game( NULL, globals ); + new_game_impl( globals, XP_FALSE ); #ifndef XWFEATURE_STANDALONE_ONLY } else if ( !isServer ) { XWStreamCtxt* stream = @@ -663,7 +694,7 @@ final_scores( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) } /* final_scores */ static void -new_game( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) +new_game_impl( GtkAppGlobals* globals, XP_Bool fireConnDlg ) { CommsAddrRec addr; @@ -673,7 +704,7 @@ new_game( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) comms_getInitialAddr( &addr ); } - if ( newGameDialog( globals, &addr, XP_TRUE ) ) { + if ( newGameDialog( globals, &addr, XP_TRUE, fireConnDlg ) ) { CurGameInfo* gi = &globals->cGlobals.params->gi; #ifndef XWFEATURE_STANDALONE_ONLY XP_Bool isClient = gi->serverRole == SERVER_ISCLIENT; @@ -713,6 +744,12 @@ new_game( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) board_draw( globals->cGlobals.game.board ); } +} /* new_game_impl */ + +static void +new_game( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) +{ + new_game_impl( globals, XP_FALSE ); } /* new_game */ static void @@ -723,7 +760,7 @@ game_info( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) /* Anything to do if OK is clicked? Changed names etc. already saved. Try server_do in case one's become a robot. */ - if ( newGameDialog( globals, &addr, XP_FALSE ) ) { + if ( newGameDialog( globals, &addr, XP_FALSE, XP_FALSE ) ) { if ( server_do( globals->cGlobals.game.server ) ) { board_draw( globals->cGlobals.game.board ); } @@ -1263,7 +1300,7 @@ pentimer_idle_func( gpointer data ) } return callAgain; -} /* timer_idle_func */ +} /* pentimer_idle_func */ static gint score_timer_func( gpointer data ) diff --git a/xwords4/linux/gtknewgame.c b/xwords4/linux/gtknewgame.c index d917979a6..6047c0563 100644 --- a/xwords4/linux/gtknewgame.c +++ b/xwords4/linux/gtknewgame.c @@ -40,6 +40,7 @@ typedef struct GtkNewGameState { gboolean revert; gboolean cancelled; XP_Bool loaded; + XP_Bool fireConnDlg; gboolean isNewGame; short nCols; /* for board size */ @@ -89,7 +90,8 @@ role_combo_changed( GtkComboBox* combo, gpointer gp ) #ifndef XWFEATURE_STANDALONE_ONLY if ( state->loaded && SERVER_STANDALONE != role ) { - gtkConnsDlg( state->globals, &state->addr, !state->isNewGame ); + gtkConnsDlg( state->globals, &state->addr, role, + !state->isNewGame ); } #endif } @@ -98,7 +100,7 @@ role_combo_changed( GtkComboBox* combo, gpointer gp ) static void handle_settings( GtkWidget* XP_UNUSED(item), GtkNewGameState* state ) { - gtkConnsDlg( state->globals, &state->addr, !state->isNewGame ); + gtkConnsDlg( state->globals, &state->addr, state->role, !state->isNewGame ); } #endif @@ -177,6 +179,15 @@ handle_revert( GtkWidget* XP_UNUSED(widget), void* closure ) gtk_main_quit(); } /* handle_revert */ +static gint +call_connsdlg_func( gpointer data ) +{ + GtkNewGameState* state = (GtkNewGameState*)data; + gtkConnsDlg( state->globals, &state->addr, state->role, + !state->isNewGame ); + return 0; +} + static GtkWidget* makeNewGameDialog( GtkNewGameState* state ) { @@ -359,6 +370,10 @@ makeNewGameDialog( GtkNewGameState* state ) gtk_widget_show_all (dialog); + if ( state->fireConnDlg ) { + (void)g_idle_add( call_connsdlg_func, state ); + } + return dialog; } /* makeNewGameDialog */ @@ -502,7 +517,8 @@ gtk_newgame_attr_set( void* closure, NewGameAttr attr, NGValue value ) } gboolean -newGameDialog( GtkAppGlobals* globals, CommsAddrRec* addr, XP_Bool isNewGame ) +newGameDialog( GtkAppGlobals* globals, CommsAddrRec* addr, XP_Bool isNewGame, + XP_Bool fireConnDlg ) { GtkNewGameState state; XP_MEMSET( &state, 0, sizeof(state) ); @@ -519,6 +535,7 @@ newGameDialog( GtkAppGlobals* globals, CommsAddrRec* addr, XP_Bool isNewGame ) gtk_newgame_attr_set, &state ); state.isNewGame = isNewGame; + state.fireConnDlg = fireConnDlg; /* returns when button handler calls gtk_main_quit */ do { @@ -549,6 +566,7 @@ newGameDialog( GtkAppGlobals* globals, CommsAddrRec* addr, XP_Bool isNewGame ) } gtk_widget_destroy( dialog ); + state.fireConnDlg = XP_FALSE; } while ( state.revert ); newg_destroy( state.newGameCtxt ); diff --git a/xwords4/linux/gtknewgame.h b/xwords4/linux/gtknewgame.h index 15cc78de7..5d156333e 100644 --- a/xwords4/linux/gtknewgame.h +++ b/xwords4/linux/gtknewgame.h @@ -27,7 +27,7 @@ #include "gtkmain.h" gboolean newGameDialog( GtkAppGlobals* globals, CommsAddrRec* addr, - XP_Bool isNewGame ); + XP_Bool isNewGame, XP_Bool fireConnDlg ); #endif /* _GTKNEWGAME_H_ */ #endif /* PLATFORM_GTK */ diff --git a/xwords4/linux/linuxutl.c b/xwords4/linux/linuxutl.c index ae3f7d28f..2da7a5893 100644 --- a/xwords4/linux/linuxutl.c +++ b/xwords4/linux/linuxutl.c @@ -297,6 +297,14 @@ linux_getErrString( UtilErrID id, XP_Bool* silent ) message = "XWRELAY_ERROR_OTHER_DISCON"; break; + case ERR_RELAY_BASE + XWRELAY_ERROR_NO_ROOM: + message = "No such room. Has the host connected yet to reserve it?"; + break; + case ERR_RELAY_BASE + XWRELAY_ERROR_DUP_ROOM: + message = "That room is reserved by another host. Rename your room, " + "become a guest, or try again in a few minutes."; + break; + default: XP_LOGF( "no code for error: %d", id ); message = "";