diff --git a/xwords4/common/comms.c b/xwords4/common/comms.c index bb67d4ef2..3895555f5 100644 --- a/xwords4/common/comms.c +++ b/xwords4/common/comms.c @@ -1014,9 +1014,13 @@ preProcess( CommsCtxt* comms, XWStreamCtxt* stream, static AddressRecord* addrToRecord( CommsCtxt* comms, const CommsAddrRec* addr ) { - CommsConnType conType = addr->conType; + CommsConnType conType; AddressRecord* rec; XP_Bool matched = XP_FALSE; + + XP_ASSERT( !!addr ); + + conType = addr->conType; for ( rec = comms->recs; !!rec; rec = rec->next ) { XP_ASSERT( conType == rec->addr.conType ); switch( conType ) { @@ -1039,7 +1043,9 @@ addrToRecord( CommsCtxt* comms, const CommsAddrRec* addr ) } break; case COMMS_CONN_IR: /* no way to test */ + break; default: + XP_ASSERT(0); break; } if ( matched ) { diff --git a/xwords4/common/game.c b/xwords4/common/game.c index ce54ee424..2d99f6b3d 100644 --- a/xwords4/common/game.c +++ b/xwords4/common/game.c @@ -315,10 +315,10 @@ gi_disposePlayerInfo( MPFORMAL CurGameInfo* gi ) } /* gi_disposePlayerInfo */ void -gi_copy( MPFORMAL CurGameInfo* destGI, CurGameInfo* srcGI ) +gi_copy( MPFORMAL CurGameInfo* destGI, const CurGameInfo* srcGI ) { XP_U16 nPlayers, i; - LocalPlayer* srcPl; + const LocalPlayer* srcPl; LocalPlayer* destPl; replaceStringIfDifferent( mpool, &destGI->dictName, diff --git a/xwords4/common/game.h b/xwords4/common/game.h index ead03279b..8e578932c 100644 --- a/xwords4/common/game.h +++ b/xwords4/common/game.h @@ -99,7 +99,7 @@ void gi_initPlayerInfo( MPFORMAL CurGameInfo* gi, void gi_disposePlayerInfo( MPFORMAL CurGameInfo* gi ); void gi_writeToStream( XWStreamCtxt* stream, const CurGameInfo* gi ); void gi_readFromStream( MPFORMAL XWStreamCtxt* stream, CurGameInfo* gi ); -void gi_copy( MPFORMAL CurGameInfo* destGI, CurGameInfo* srcGi ); +void gi_copy( MPFORMAL CurGameInfo* destGI, const CurGameInfo* srcGi ); XP_U16 gi_countLocalHumans( const CurGameInfo* gi ); XP_Bool player_hasPasswd( LocalPlayer* player ); diff --git a/xwords4/common/server.c b/xwords4/common/server.c index 707f1fa3e..de0e3bd1d 100644 --- a/xwords4/common/server.c +++ b/xwords4/common/server.c @@ -940,103 +940,108 @@ clearLocalRobots( ServerCtxt* server ) static XP_Bool client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream ) { - DictionaryCtxt* newDict; - DictionaryCtxt* curDict; - XP_U16 nPlayers, nCols; - XP_PlayerAddr channelNo; - short i; - ModelCtxt* model = server->vol.model; - CurGameInfo* gi = server->vol.gi; - CurGameInfo localGI; - XP_U32 gameID; - PoolContext* pool; + XP_Bool accepted = 0 == server->nv.addresses[0].channelNo; - /* version */ - XP_U8 streamVersion = stream_getU8( stream ); - XP_ASSERT( streamVersion == STREAM_VERS_41B4 ); - if ( streamVersion != STREAM_VERS_41B4 ) { - return XP_FALSE; + /* We should never get this message a second time, but very rarely we do. + Drop it in that case. */ + XP_ASSERT( accepted ); + if ( accepted ) { + DictionaryCtxt* newDict; + DictionaryCtxt* curDict; + XP_U16 nPlayers, nCols; + XP_PlayerAddr channelNo; + short i; + ModelCtxt* model = server->vol.model; + CurGameInfo* gi = server->vol.gi; + CurGameInfo localGI; + XP_U32 gameID; + PoolContext* pool; + + /* version */ + XP_U8 streamVersion = stream_getU8( stream ); + XP_ASSERT( streamVersion == STREAM_VERS_41B4 ); + if ( streamVersion != STREAM_VERS_41B4 ) { + return XP_FALSE; + } + stream_setVersion( stream, streamVersion ); + + gameID = stream_getU32( stream ); + XP_STATUSF( "read gameID of %lx; calling comms_setConnID", gameID ); + server->vol.gi->gameID = gameID; + comms_setConnID( server->vol.comms, gameID ); + + XP_MEMSET( &localGI, 0, sizeof(localGI) ); + gi_readFromStream( MPPARM(server->mpool) stream, &localGI ); + localGI.serverRole = SERVER_ISCLIENT; + + /* so it's not lost (HACK!). Without this, a client won't have a default + dict name when a new game is started. */ + localGI.dictName = copyString( server->mpool, gi->dictName ); + gi_copy( MPPARM(server->mpool) gi, &localGI ); + + nCols = localGI.boardSize; + + newDict = util_makeEmptyDict( server->vol.util ); + dict_loadFromStream( newDict, stream ); + + channelNo = stream_getAddress( stream ); + XP_ASSERT( channelNo != 0 ); + server->nv.addresses[0].channelNo = channelNo; + + /* PENDING init's a bit harsh for setting the size */ + model_init( model, nCols, nCols ); + + nPlayers = localGI.nPlayers; + XP_STATUSF( "reading in %d players", localGI.nPlayers ); + + gi_disposePlayerInfo( MPPARM(server->mpool) &localGI ); + + gi->nPlayers = nPlayers; + model_setNPlayers( model, nPlayers ); + + curDict = model_getDictionary( model ); + + XP_ASSERT( !!newDict ); + + if ( curDict == NULL ) { + model_setDictionary( model, newDict ); + } else if ( dict_tilesAreSame( newDict, curDict ) ) { + /* keep the dict the local user installed */ + dict_destroy( newDict ); + } else { + dict_destroy( curDict ); + model_setDictionary( model, newDict ); + util_userError( server->vol.util, ERR_SERVER_DICT_WINS ); + clearLocalRobots( server ); + } + + XP_ASSERT( !server->pool ); + pool = server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) ); + pool_initFromDict( server->pool, model_getDictionary(model)); + + /* now read the assigned tiles for each player from the stream, and remove + them from the newly-created local pool. */ + for ( i = 0; i < nPlayers; ++i ) { + TrayTileSet tiles; + + traySetFromStream( stream, &tiles ); + XP_ASSERT( tiles.nTiles <= MAX_TRAY_TILES ); + + XP_STATUSF( "got %d tiles for player %d", tiles.nTiles, i ); + + model_assignPlayerTiles( model, i, &tiles ); + + /* remove what the server's assigned so we won't conflict later. */ + pool_removeTiles( pool, &tiles ); + } + + SETSTATE( server, XWSTATE_INTURN ); + + /* Give board a chance to redraw self with the full compliment of known + players */ + setTurn( server, 0 ); } - stream_setVersion( stream, streamVersion ); - - gameID = stream_getU32( stream ); - XP_STATUSF( "read gameID of %lx; calling comms_setConnID", gameID ); - server->vol.gi->gameID = gameID; - comms_setConnID( server->vol.comms, gameID ); - - XP_MEMSET( &localGI, 0, sizeof(localGI) ); - gi_readFromStream( MPPARM(server->mpool) stream, &localGI ); - localGI.serverRole = SERVER_ISCLIENT; - - /* so it's not lost (HACK!). Without this, a client won't have a default - dict name when a new game is started. */ - localGI.dictName = copyString( server->mpool, gi->dictName ); - gi_copy( MPPARM(server->mpool) gi, &localGI ); - - nCols = localGI.boardSize; - - newDict = util_makeEmptyDict( server->vol.util ); - dict_loadFromStream( newDict, stream ); - - channelNo = stream_getAddress( stream ); - XP_ASSERT( channelNo != 0 ); - XP_ASSERT( server->nv.addresses[0].channelNo == 0 ); - server->nv.addresses[0].channelNo = channelNo; - - /* PENDING init's a bit harsh for setting the size */ - model_init( model, nCols, nCols ); - - nPlayers = localGI.nPlayers; - XP_STATUSF( "reading in %d players", localGI.nPlayers ); - - gi_disposePlayerInfo( MPPARM(server->mpool) &localGI ); - - gi->nPlayers = nPlayers; - model_setNPlayers( model, nPlayers ); - - curDict = model_getDictionary( model ); - - XP_ASSERT( !!newDict ); - - if ( curDict == NULL ) { - model_setDictionary( model, newDict ); - } else if ( dict_tilesAreSame( newDict, curDict ) ) { - /* keep the dict the local user installed */ - dict_destroy( newDict ); - } else { - dict_destroy( curDict ); - model_setDictionary( model, newDict ); - util_userError( server->vol.util, ERR_SERVER_DICT_WINS ); - clearLocalRobots( server ); - } - - XP_ASSERT( !server->pool ); - pool = server->pool = pool_make( MPPARM_NOCOMMA(server->mpool) ); - pool_initFromDict( server->pool, model_getDictionary(model)); - - /* now read the assigned tiles for each player from the stream, and remove - them from the newly-created local pool. */ - for ( i = 0; i < nPlayers; ++i ) { - TrayTileSet tiles; - - traySetFromStream( stream, &tiles ); - XP_ASSERT( tiles.nTiles <= MAX_TRAY_TILES ); - - XP_STATUSF( "got %d tiles for player %d", tiles.nTiles, i ); - - model_assignPlayerTiles( model, i, &tiles ); - - /* remove what the server's assigned so we won't conflict later. */ - pool_removeTiles( pool, &tiles ); - } - - SETSTATE( server, XWSTATE_INTURN ); - - /* Give board a chance to redraw self with the full compliment of known - players */ - setTurn( server, 0 ); - - return XP_TRUE; + return accepted; } /* client_readInitialMessage */ #endif