mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-27 07:58:49 +01:00
fix relay game failure to change roles
If a configured-as-host game joined an existing game the relay would make it a guest. The android util_ callback for that change was only implemented in BoardDelegate and so the change was dropped unless the game was open/visible. Because comms recorded the change, though, the callback would never be called again and so the game never learned to behave as a guest and never registered: permanent failure to join game! Implemented with a new server state so initClientConnection can be called from server_do() instead of inside comms while processing an incoming packet.
This commit is contained in:
parent
15fde8044f
commit
b0f7176b6c
14 changed files with 85 additions and 89 deletions
|
@ -1828,22 +1828,6 @@ public class BoardDelegate extends DelegateBase
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsServer( boolean isServer )
|
||||
{
|
||||
Log.d( TAG, "setIsServer(isServer=%b)", isServer );
|
||||
DeviceRole newRole = isServer? DeviceRole.SERVER_ISSERVER
|
||||
: DeviceRole.SERVER_ISCLIENT;
|
||||
if ( newRole != m_gi.serverRole ) {
|
||||
m_gi.serverRole = newRole;
|
||||
if ( !isServer ) {
|
||||
handleViaThread( JNICmd.CMD_SWITCHCLIENT );
|
||||
}
|
||||
} else {
|
||||
Log.d( TAG, "setIsServer(): no change" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bonusSquareHeld( int bonus )
|
||||
{
|
||||
|
|
|
@ -60,7 +60,6 @@ public class JNIThread extends Thread implements AutoCloseable {
|
|||
CMD_INVALALL,
|
||||
CMD_LAYOUT,
|
||||
CMD_START,
|
||||
CMD_SWITCHCLIENT,
|
||||
CMD_RESET,
|
||||
CMD_SAVE,
|
||||
CMD_DO,
|
||||
|
@ -524,12 +523,6 @@ public class JNIThread extends Thread implements AutoCloseable {
|
|||
draw = tryConnect( m_jniGamePtr, m_gi );
|
||||
break;
|
||||
|
||||
case CMD_SWITCHCLIENT:
|
||||
XwJNI.server_reset( m_jniGamePtr );
|
||||
XwJNI.server_initClientConnection( m_jniGamePtr );
|
||||
draw = XwJNI.server_do( m_jniGamePtr );
|
||||
break;
|
||||
|
||||
case CMD_DO:
|
||||
if ( nextSame( JNICmd.CMD_DO ) ) {
|
||||
continue;
|
||||
|
|
|
@ -61,7 +61,6 @@ public interface UtilCtxt {
|
|||
void requestTime();
|
||||
void remSelected();
|
||||
void timerSelected( boolean inDuplicateMode, boolean canPause );
|
||||
void setIsServer( boolean isServer );
|
||||
void informWordsBlocked( int nWords, String words, String dict );
|
||||
|
||||
void bonusSquareHeld( int bonus );
|
||||
|
|
|
@ -79,12 +79,14 @@ public class UtilCtxtImpl implements UtilCtxt {
|
|||
@Override
|
||||
public void setTimer( int why, int when, int handle )
|
||||
{
|
||||
Log.e( TAG, "setTimer(%d) not doing anything...", why );
|
||||
subclassOverride( "setTimer" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTimer( int why )
|
||||
{
|
||||
Log.e( TAG, "setTimer(%d) not doing anything...", why );
|
||||
subclassOverride( "clearTimer" );
|
||||
}
|
||||
|
||||
|
@ -100,13 +102,6 @@ public class UtilCtxtImpl implements UtilCtxt {
|
|||
subclassOverride( "timerSelected" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIsServer( boolean isServer )
|
||||
{
|
||||
subclassOverride( "setIsServer" );
|
||||
Assert.failDbg();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void informWordsBlocked( int nWords, String words, String dict )
|
||||
{
|
||||
|
|
|
@ -703,16 +703,6 @@ and_util_addrChange( XW_UtilCtxt* uc, XWEnv xwe,
|
|||
// LOG_FUNC();
|
||||
}
|
||||
|
||||
static void
|
||||
and_util_setIsServer( XW_UtilCtxt* uc, XWEnv xwe, XP_Bool isServer )
|
||||
{
|
||||
/* Change both the C and Java structs, which need to stay in sync */
|
||||
uc->gameInfo->serverRole = isServer? SERVER_ISSERVER : SERVER_ISCLIENT;
|
||||
UTIL_CBK_HEADER( "setIsServer", "(Z)V" );
|
||||
(*env)->CallVoidMethod( env, util->jutil, mid, isServer );
|
||||
UTIL_CBK_TAIL();
|
||||
}
|
||||
|
||||
static void
|
||||
and_util_informWordsBlocked( XW_UtilCtxt* uc, XWEnv xwe, XP_U16 nBadWords,
|
||||
XWStreamCtxt* words, const XP_UCHAR* dict )
|
||||
|
@ -975,7 +965,6 @@ makeUtil( MPFORMAL JNIEnv* env,
|
|||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
SET_PROC(informMissing);
|
||||
SET_PROC(addrChange);
|
||||
SET_PROC(setIsServer);
|
||||
#endif
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
SET_PROC(getTraySearchLimits);
|
||||
|
|
|
@ -1221,6 +1221,7 @@ struct _JNIState {
|
|||
#define XWJNI_START_GLOBALS() \
|
||||
XWJNI_START() \
|
||||
AndGameGlobals* globals = &state->globals; \
|
||||
XP_USE(globals); /*no warnings */ \
|
||||
|
||||
#define XWJNI_END() \
|
||||
} \
|
||||
|
|
|
@ -110,6 +110,10 @@ struct CommsCtxt {
|
|||
AddressRecord* recs; /* return addresses */
|
||||
|
||||
TransportProcs procs;
|
||||
|
||||
RoleChangeProc rcProc;
|
||||
void* rcClosure;
|
||||
|
||||
XP_U32 xportFlags;
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
XP_U32 lastMsgRcd;
|
||||
|
@ -355,7 +359,9 @@ CommsCtxt*
|
|||
comms_make( MPFORMAL XWEnv xwe, XW_UtilCtxt* util, XP_Bool isServer,
|
||||
XP_U16 XP_UNUSED_RELAY(nPlayersHere),
|
||||
XP_U16 XP_UNUSED_RELAY(nPlayersTotal),
|
||||
const TransportProcs* procs, XP_U16 forceChannel
|
||||
const TransportProcs* procs,
|
||||
RoleChangeProc rcp, void* rcClosure,
|
||||
XP_U16 forceChannel
|
||||
#ifdef SET_GAMESEED
|
||||
, XP_U16 gameSeed
|
||||
#endif
|
||||
|
@ -379,6 +385,10 @@ comms_make( MPFORMAL XWEnv xwe, XW_UtilCtxt* util, XP_Bool isServer,
|
|||
comms->xportFlags = comms->procs.flags;
|
||||
#endif
|
||||
}
|
||||
XP_ASSERT( rcp );
|
||||
comms->rcProc = rcp;
|
||||
comms->rcClosure = rcClosure;
|
||||
|
||||
comms->dutil = util_getDevUtilCtxt( util, xwe );
|
||||
comms->util = util;
|
||||
comms->dutil = util_getDevUtilCtxt( util, xwe );
|
||||
|
@ -648,8 +658,11 @@ addrFromStream( CommsAddrRec* addrP, XWStreamCtxt* stream )
|
|||
}
|
||||
|
||||
CommsCtxt*
|
||||
comms_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XW_UtilCtxt* util,
|
||||
const TransportProcs* procs, XP_U16 forceChannel )
|
||||
comms_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream,
|
||||
XW_UtilCtxt* util,
|
||||
const TransportProcs* procs,
|
||||
RoleChangeProc rcp, void* rcClosure,
|
||||
XP_U16 forceChannel )
|
||||
{
|
||||
XP_U16 nPlayersHere, nPlayersTotal;
|
||||
AddressRecord** prevsAddrNext;
|
||||
|
@ -670,8 +683,8 @@ comms_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XW_UtilCtxt* uti
|
|||
nPlayersTotal = 0;
|
||||
}
|
||||
CommsCtxt* comms = comms_make( MPPARM(mpool) xwe, util, isServer,
|
||||
nPlayersHere, nPlayersTotal, procs,
|
||||
forceChannel
|
||||
nPlayersHere, nPlayersTotal, procs,
|
||||
rcp, rcClosure, forceChannel
|
||||
#ifdef SET_GAMESEED
|
||||
, 0
|
||||
#endif
|
||||
|
@ -1768,8 +1781,11 @@ got_connect_cmd( CommsCtxt* comms, XWEnv xwe, XWStreamCtxt* stream,
|
|||
if ( isServer != comms->isServer ) {
|
||||
XP_LOGFF( "becoming%s a server", isServer ? "" : " NOT" );
|
||||
comms->isServer = isServer;
|
||||
util_setIsServer( comms->util, xwe, comms->isServer );
|
||||
|
||||
#ifdef DEBUG
|
||||
XP_U16 queueLen = comms->queueLen;
|
||||
#endif
|
||||
(*comms->rcProc)( xwe, comms->rcClosure, !isServer );
|
||||
XP_ASSERT( queueLen == comms->queueLen ); /* callback should not send!!! */
|
||||
reset_internal( comms, xwe, isServer, comms->rr.nPlayersHere,
|
||||
comms->rr.nPlayersTotal, XP_FALSE );
|
||||
}
|
||||
|
@ -2732,7 +2748,8 @@ comms_getStats( CommsCtxt* comms, XWStreamCtxt* stream )
|
|||
}
|
||||
|
||||
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
||||
(XP_UCHAR*)"msg queue len: %d; have %d channels\n",
|
||||
(XP_UCHAR*)"role: %s; msg queue len: %d; have %d channels\n",
|
||||
comms->isServer ? "host" : "guest",
|
||||
comms->queueLen, nChannels );
|
||||
stream_catString( stream, buf );
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ typedef void (*RelayRequestJoinProc)( XWEnv xwe, void* closure, const XP_UCHAR*
|
|||
#endif
|
||||
|
||||
typedef void (*MsgCountChange)( XWEnv xwe, void* closure, XP_U16 msgCount );
|
||||
typedef void (*RoleChangeProc)( XWEnv xwe, void* closure, XP_Bool amNowGuest );
|
||||
|
||||
typedef enum {
|
||||
COMMS_XPORT_FLAGS_NONE = 0
|
||||
|
@ -138,7 +139,9 @@ typedef struct _TransportProcs {
|
|||
CommsCtxt* comms_make( MPFORMAL XWEnv xwe, XW_UtilCtxt* util,
|
||||
XP_Bool isServer,
|
||||
XP_U16 nPlayersHere, XP_U16 nPlayersTotal,
|
||||
const TransportProcs* procs, XP_U16 forceChannel
|
||||
const TransportProcs* procs,
|
||||
RoleChangeProc rcp, void* rcClosure,
|
||||
XP_U16 forceChannel
|
||||
#ifdef SET_GAMESEED
|
||||
,XP_U16 gameSeed
|
||||
#endif
|
||||
|
@ -187,6 +190,7 @@ XP_Bool comms_getIsServer( const CommsCtxt* comms );
|
|||
CommsCtxt* comms_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream,
|
||||
XW_UtilCtxt* util,
|
||||
const TransportProcs* procs,
|
||||
RoleChangeProc rcp, void* rcClosure,
|
||||
XP_U16 forceChannel );
|
||||
void comms_start( CommsCtxt* comms, XWEnv xwe );
|
||||
void comms_stop( CommsCtxt* comms, XWEnv xwe );
|
||||
|
|
|
@ -98,6 +98,14 @@ timerChangeListener( XWEnv xwe, void* data, const XP_U32 gameID,
|
|||
gameID, oldVal, newVal );
|
||||
}
|
||||
|
||||
static void
|
||||
onRoleChanged( XWEnv xwe, void* closure, XP_Bool amNowGuest )
|
||||
{
|
||||
XP_ASSERT( amNowGuest );
|
||||
XWGame* game = (XWGame*)closure;
|
||||
server_onRoleChanged( game->server, xwe, amNowGuest );
|
||||
}
|
||||
|
||||
static void
|
||||
setListeners( XWGame* game, const CommonPrefs* cp )
|
||||
{
|
||||
|
@ -136,7 +144,8 @@ game_makeNewGame( MPFORMAL XWEnv xwe, XWGame* game, CurGameInfo* gi,
|
|||
game->comms = comms_make( MPPARM(mpool) xwe, util,
|
||||
gi->serverRole != SERVER_ISCLIENT,
|
||||
nPlayersHere, nPlayersTotal,
|
||||
procs, gi->forceChannel
|
||||
procs, onRoleChanged, game,
|
||||
gi->forceChannel
|
||||
#ifdef SET_GAMESEED
|
||||
, gameSeed
|
||||
#endif
|
||||
|
@ -191,6 +200,7 @@ game_reset( MPFORMAL XWGame* game, XWEnv xwe, CurGameInfo* gi, XW_UtilCtxt* util
|
|||
game->comms = comms_make( MPPARM(mpool) xwe, util,
|
||||
gi->serverRole != SERVER_ISCLIENT,
|
||||
nPlayersHere, nPlayersTotal, procs,
|
||||
onRoleChanged, game,
|
||||
gi->forceChannel
|
||||
#ifdef SET_GAMESEED
|
||||
, 0
|
||||
|
@ -281,7 +291,8 @@ game_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XWGame* game,
|
|||
|
||||
if ( hasComms ) {
|
||||
game->comms = comms_makeFromStream( MPPARM(mpool) xwe, stream, util,
|
||||
procs, gi->forceChannel );
|
||||
procs, onRoleChanged, game,
|
||||
gi->forceChannel );
|
||||
} else {
|
||||
game->comms = NULL;
|
||||
}
|
||||
|
@ -301,6 +312,11 @@ game_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XWGame* game,
|
|||
success = XP_TRUE;
|
||||
} while( XP_FALSE );
|
||||
}
|
||||
|
||||
if ( success && !!game && !!game->comms ) {
|
||||
XP_ASSERT( comms_getIsServer(game->comms) == server_getIsServer(game->server) );
|
||||
}
|
||||
|
||||
return success;
|
||||
} /* game_makeFromStream */
|
||||
|
||||
|
|
|
@ -217,6 +217,7 @@ getStateStr( XW_State st )
|
|||
switch( st ) {
|
||||
CASESTR(XWSTATE_NONE);
|
||||
CASESTR(XWSTATE_BEGIN);
|
||||
CASESTR(XWSTATE_NEWCLIENT);
|
||||
CASESTR(XWSTATE_NEED_SHOWSCORE);
|
||||
CASESTR(XWSTATE_RECEIVED_ALL_REG);
|
||||
CASESTR(XWSTATE_NEEDSEND_BADWORD_INFO);
|
||||
|
@ -226,6 +227,7 @@ getStateStr( XW_State st )
|
|||
CASESTR(XWSTATE_INTURN);
|
||||
CASESTR(XWSTATE_GAMEOVER);
|
||||
default:
|
||||
XP_ASSERT(0);
|
||||
return "unknown";
|
||||
}
|
||||
# undef CASESTR
|
||||
|
@ -289,6 +291,10 @@ amServer( const ServerCtxt* server )
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
XP_Bool server_getIsServer( const ServerCtxt* server ) { return amServer(server); }
|
||||
#endif
|
||||
|
||||
static void
|
||||
initServer( ServerCtxt* server, XWEnv xwe )
|
||||
{
|
||||
|
@ -558,6 +564,21 @@ server_writeToStream( const ServerCtxt* server, XWStreamCtxt* stream )
|
|||
writeStreamIf( stream, server->nv.prevWordsStream );
|
||||
} /* server_writeToStream */
|
||||
|
||||
void
|
||||
server_onRoleChanged( ServerCtxt* server, XWEnv xwe, XP_Bool amNowGuest )
|
||||
{
|
||||
if ( amNowGuest == amServer(server) ) { /* do I need to change */
|
||||
XP_ASSERT ( amNowGuest );
|
||||
if ( amNowGuest ) {
|
||||
server->vol.gi->serverRole = SERVER_ISCLIENT;
|
||||
server_reset( server, xwe, server->vol.comms );
|
||||
|
||||
SETSTATE( server, XWSTATE_NEWCLIENT );
|
||||
util_requestTime( server->vol.util, xwe );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cleanupServer( ServerCtxt* server, XWEnv xwe )
|
||||
{
|
||||
|
@ -1630,6 +1651,12 @@ server_do( ServerCtxt* server, XWEnv xwe )
|
|||
}
|
||||
break;
|
||||
|
||||
case XWSTATE_NEWCLIENT:
|
||||
XP_ASSERT( !amServer( server ) );
|
||||
SETSTATE( server, XWSTATE_NONE ); /* server_initClientConnection expects this */
|
||||
server_initClientConnection( server, xwe );
|
||||
break;
|
||||
|
||||
case XWSTATE_NEEDSEND_BADWORD_INFO:
|
||||
XP_ASSERT( server->vol.gi->serverRole == SERVER_ISSERVER );
|
||||
badWordMoveUndoAndTellUser( server, xwe, &server->illegalWordInfo );
|
||||
|
|
|
@ -43,6 +43,7 @@ void server_reset( ServerCtxt* server, XWEnv xwe, CommsCtxt* comms );
|
|||
void server_destroy( ServerCtxt* server, XWEnv xwe );
|
||||
|
||||
void server_prefsChanged( ServerCtxt* server, const CommonPrefs* cp );
|
||||
void server_onRoleChanged( ServerCtxt* server, XWEnv xwe, XP_Bool amNowGuest );
|
||||
|
||||
typedef void (*TurnChangeListener)( XWEnv xwe, void* data );
|
||||
void server_setTurnChangeListener( ServerCtxt* server, TurnChangeListener tl,
|
||||
|
@ -134,6 +135,10 @@ void server_writeFinalScores( ServerCtxt* server, XWEnv xwe, XWStreamCtxt* strea
|
|||
XP_U16 server_figureFinishBonus( const ServerCtxt* server, XP_U16 turn );
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
XP_Bool server_getIsServer( const ServerCtxt* server );
|
||||
#endif
|
||||
|
||||
#ifdef CPLUS
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
enum {
|
||||
XWSTATE_NONE, /* 0 */
|
||||
XWSTATE_BEGIN, /* 1 */
|
||||
__UNUSED1, /* was XWSTATE_POOL_INITED */
|
||||
XWSTATE_NEWCLIENT, /* was a host, now a reset client */
|
||||
XWSTATE_NEED_SHOWSCORE, /* client-only */
|
||||
__XWSTATE_WAITING_ALL_REG, /* 4 (unused) */
|
||||
XWSTATE_RECEIVED_ALL_REG, /* includes waiting for dict from server */
|
||||
|
@ -34,7 +34,7 @@ enum {
|
|||
XWSTATE_INTURN, /* 10 */
|
||||
XWSTATE_GAMEOVER, /* 11 */
|
||||
|
||||
XWSTATE_LAST /* for asserts only :-) */
|
||||
XWSTATE_LAST, /* for asserts only :-) */
|
||||
};
|
||||
typedef XP_U8 XW_State;
|
||||
#define XWSTATE_NBITS 4
|
||||
|
|
|
@ -171,7 +171,6 @@ typedef struct UtilVtable {
|
|||
XP_U16 nMissing );
|
||||
void (*m_util_addrChange)( XW_UtilCtxt* uc, XWEnv xwe, const CommsAddrRec* oldAddr,
|
||||
const CommsAddrRec* newAddr );
|
||||
void (*m_util_setIsServer)(XW_UtilCtxt* uc, XWEnv xwe, XP_Bool isServer );
|
||||
#endif
|
||||
|
||||
void (*m_util_informWordsBlocked)( XW_UtilCtxt* uc, XWEnv xwe, XP_U16 nBadWords,
|
||||
|
@ -306,8 +305,6 @@ struct XW_UtilCtxt {
|
|||
(uc)->vtable->m_util_informMissing((uc), (e), (is), (ct), (nd), (nm) )
|
||||
# define util_addrChange( uc,e, addro, addrn ) \
|
||||
(uc)->vtable->m_util_addrChange((uc), (e), (addro), (addrn))
|
||||
# define util_setIsServer( uc,e, is ) \
|
||||
(uc)->vtable->m_util_setIsServer((uc), (e), (is))
|
||||
# else
|
||||
# define util_addrChange( uc,e, addro, addrn )
|
||||
#endif
|
||||
|
|
|
@ -1865,36 +1865,6 @@ linux_util_addrChange( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe),
|
|||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
changeRolesIdle( gpointer data )
|
||||
{
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)data;
|
||||
ServerCtxt* server = cGlobals->game.server;
|
||||
server_reset( server, NULL_XWE, cGlobals->game.comms );
|
||||
if ( SERVER_ISCLIENT == cGlobals->gi->serverRole ) {
|
||||
XWStreamCtxt* stream =
|
||||
mem_stream_make( MPPARM(cGlobals->util->mpool) cGlobals->params->vtMgr,
|
||||
cGlobals, CHANNEL_NONE, sendOnClose );
|
||||
(void)server_initClientConnection( server, NULL_XWE, stream );
|
||||
}
|
||||
(void)server_do( server, NULL_XWE );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
linux_util_setIsServer( XW_UtilCtxt* uc, XWEnv XP_UNUSED(xwe),XP_Bool isServer )
|
||||
{
|
||||
XP_LOGF( "%s(isServer=%d)", __func__, isServer );
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
|
||||
DeviceRole newRole = isServer? SERVER_ISSERVER : SERVER_ISCLIENT;
|
||||
cGlobals->params->serverRole = newRole;
|
||||
cGlobals->gi->serverRole = newRole;
|
||||
|
||||
(void)ADD_ONETIME_IDLE( changeRolesIdle, cGlobals );
|
||||
XP_ASSERT( isServer == game_getIsServer( &cGlobals->game ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned int
|
||||
|
@ -2552,7 +2522,6 @@ setupLinuxUtilCallbacks( XW_UtilCtxt* util )
|
|||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
SET_PROC(informMissing);
|
||||
SET_PROC(addrChange);
|
||||
SET_PROC(setIsServer);
|
||||
#endif
|
||||
SET_PROC(formatPauseHistory);
|
||||
SET_PROC(setTimer);
|
||||
|
|
Loading…
Add table
Reference in a new issue