From fad252d8c0a6b4f5fe99ee3917d7b382bdbaecb0 Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 25 Sep 2020 10:17:47 -0700 Subject: [PATCH] use created stamp to decide between conflicting addresses Not at all tested, but now the game's timestamp is kept and passed in to where it can be used to determine, e.g., which of two Bluetooth device names to keep for a given opponent. --- xwords4/android/jni/xwjni.c | 4 ++-- xwords4/common/comms.c | 45 ++++++++++++++++++++----------------- xwords4/common/comms.h | 5 +++-- xwords4/common/comtypes.h | 2 +- xwords4/common/game.c | 13 ++++++----- xwords4/common/game.h | 2 +- xwords4/common/knownplyr.c | 27 ++++++++++++++-------- xwords4/common/knownplyr.h | 6 ++--- xwords4/linux/gtkinvit.c | 4 ++-- 9 files changed, 62 insertions(+), 46 deletions(-) diff --git a/xwords4/android/jni/xwjni.c b/xwords4/android/jni/xwjni.c index 1aa737a6c..0f19529fb 100644 --- a/xwords4/android/jni/xwjni.c +++ b/xwords4/android/jni/xwjni.c @@ -780,10 +780,10 @@ Java_org_eehouse_android_xw4_jni_XwJNI_kplr_1getPlayers DVC_HEADER(jniGlobalPtr); XP_U16 nFound = 0; - kplr_getPlayers( globalState->dutil, env, NULL, &nFound ); + kplr_getNames( globalState->dutil, env, NULL, &nFound ); if ( 0 < nFound ) { const XP_UCHAR* names[nFound]; - kplr_getPlayers( globalState->dutil, env, names, &nFound ); + kplr_getNames( globalState->dutil, env, names, &nFound ); jnames = makeStringArray( env, nFound, names ); } DVC_HEADER_END(); diff --git a/xwords4/common/comms.c b/xwords4/common/comms.c index 06573c3a6..012661ae1 100644 --- a/xwords4/common/comms.c +++ b/xwords4/common/comms.c @@ -202,7 +202,7 @@ static AddressRecord* rememberChannelAddress( CommsCtxt* comms, XWEnv xwe, static void augmentChannelAddr( CommsCtxt* comms, AddressRecord* rec, const CommsAddrRec* addr, XWHostID hostID ); static XP_Bool augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* dest, - const CommsAddrRec* src ); + const CommsAddrRec* src, XP_Bool isNewer ); static XP_Bool channelToAddress( CommsCtxt* comms, XWEnv xwe, XP_PlayerAddr channelNo, const CommsAddrRec** addr ); static AddressRecord* getRecordFor( CommsCtxt* comms, XWEnv xwe, @@ -1039,7 +1039,7 @@ comms_augmentHostAddr( CommsCtxt* comms, XWEnv xwe, const CommsAddrRec* addr ) && ! addr_hasType( &comms->addr, COMMS_CONN_RELAY ); CommsAddrRec tmp = comms->addr; - augmentAddrIntrnl( comms, &tmp, addr ); + augmentAddrIntrnl( comms, &tmp, addr, XP_TRUE ); util_addrChange( comms->util, xwe, &comms->addr, &tmp ); comms->addr = tmp; @@ -1069,7 +1069,7 @@ comms_addMQTTDevID( CommsCtxt* comms, XP_PlayerAddr channelNo, CommsAddrRec addr = {0}; addr_setType( &addr, COMMS_CONN_MQTT ); addr.u.mqtt.devID = *devID; - augmentAddrIntrnl( comms, &rec->addr, &addr ); + augmentAddrIntrnl( comms, &rec->addr, &addr, XP_TRUE ); } } if ( !found ) { @@ -2594,7 +2594,7 @@ comms_isConnected( const CommsCtxt* const comms ) } void -comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe ) +comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe, XP_U32 created ) { #ifdef XWFEATURE_KNOWNPLAYERS LOG_FUNC(); @@ -2604,7 +2604,7 @@ comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe ) comms_getAddrs( comms, NULL, addrs, &nRecs ); const CurGameInfo* gi = comms->util->gameInfo; - if ( kplr_addAddrs( comms->dutil, xwe, gi, addrs, nRecs ) ) { + if ( kplr_addAddrs( comms->dutil, xwe, gi, addrs, nRecs, created ) ) { XP_LOGFF( "not setting flag :-)" ); // comms->flags |= FLAG_HARVEST_DONE; } @@ -2956,7 +2956,7 @@ static void augmentChannelAddr( CommsCtxt* comms, AddressRecord* const rec, const CommsAddrRec* addr, XWHostID hostID ) { - augmentAddrIntrnl( comms, &rec->addr, addr ); + augmentAddrIntrnl( comms, &rec->addr, addr, XP_TRUE ); if ( addr_hasType( &rec->addr, COMMS_CONN_RELAY ) ) { if ( 0 != hostID ) { rec->rr.hostID = hostID; @@ -2977,13 +2977,15 @@ augmentChannelAddr( CommsCtxt* comms, AddressRecord* const rec, static XP_Bool augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* destAddr, - const CommsAddrRec* srcAddr ) + const CommsAddrRec* srcAddr, XP_Bool isNewer ) { XP_Bool changed = XP_FALSE; + const CommsAddrRec empty = {0}; if ( !!srcAddr ) { CommsConnType typ; for ( XP_U32 st = 0; addr_iter( srcAddr, &typ, &st ); ) { - if ( ! addr_hasType( destAddr, typ ) ) { + XP_Bool newType = !addr_hasType( destAddr, typ ); + if ( newType ) { XP_LOGFF( "adding new type %s to rec", ConnType2Str(typ) ); addr_addType( destAddr, typ ); @@ -3040,19 +3042,20 @@ augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* destAddr, break; } if ( !!dest ) { - XP_Bool changing = 0 != XP_MEMCMP( dest, src, siz ); - if ( changing ) { -#ifdef DEBUG - CommsAddrRec dummy = {0}; - if ( 0 == XP_MEMCMP( &dummy, dest, siz ) ) { - XP_LOGFF( "setting %s-type addr for first time", ConnType2Str(typ) ); - } else if ( 0 != XP_MEMCMP( dest, src, siz ) ) { - XP_LOGFF( "actually changing addr info for typ %s", ConnType2Str(typ) ); + XP_Bool different = 0 != XP_MEMCMP( dest, src, siz ); + if ( different ) { + /* If the dest is non-empty AND the src is older, don't do + anything: don't replace newer info with older. Note + that this assumes unset values are empty!!! */ + if ( !isNewer && !newType + && 0 != XP_MEMCMP( &empty, dest, siz ) ) { + XP_LOGFF( "%s: not replacing new info with old", + ConnType2Str(typ) ); + } else { + XP_MEMCPY( dest, src, siz ); + changed = XP_TRUE; } -#endif - XP_MEMCPY( dest, src, siz ); } - changed = changed || changing; } } } @@ -3060,9 +3063,9 @@ augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* destAddr, } XP_Bool -augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer ) +augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer, XP_Bool isNewer ) { - return augmentAddrIntrnl( NULL, addr, newer ); + return augmentAddrIntrnl( NULL, addr, newer, isNewer ); } static XP_Bool diff --git a/xwords4/common/comms.h b/xwords4/common/comms.h index ef857196e..8ee68d031 100644 --- a/xwords4/common/comms.h +++ b/xwords4/common/comms.h @@ -238,7 +238,8 @@ XP_Bool comms_isConnected( const CommsCtxt* const comms ); void comms_gameJoined( CommsCtxt* comms, const XP_UCHAR* connname, XWHostID hid ); #endif -XP_Bool augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer ); +XP_Bool augmentAddr( CommsAddrRec* addr, const CommsAddrRec* newer, + XP_Bool isNewer ); CommsConnType addr_getType( const CommsAddrRec* addr ); void addr_setType( CommsAddrRec* addr, CommsConnType type ); @@ -262,7 +263,7 @@ void comms_setAddrDisabled( CommsCtxt* comms, CommsConnType typ, XP_Bool comms_getAddrDisabled( const CommsCtxt* comms, CommsConnType typ, XP_Bool send ); -void comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe ); +void comms_gatherPlayers( CommsCtxt* comms, XWEnv xwe, XP_U32 created ); # else # define comms_setAddrDisabled( comms, typ, send, enabled ) diff --git a/xwords4/common/comtypes.h b/xwords4/common/comtypes.h index 1d275227e..59a4f253e 100644 --- a/xwords4/common/comtypes.h +++ b/xwords4/common/comtypes.h @@ -229,7 +229,7 @@ typedef enum { #define SUFFIX_NEXTID "nextID" #define SUFFIX_DEVSTATE "devState" #define SUFFIX_MQTT_DEVID "mqtt_devid_key" -#define SUFFIX_KNOWN_PLAYERS "known_players_key" +#define SUFFIX_KNOWN_PLAYERS "known_players_key_dev1" #define FULL_KEY(PARTIAL) "persist_key:" PARTIAL diff --git a/xwords4/common/game.c b/xwords4/common/game.c index 91a61e3dd..0a2e97b1c 100644 --- a/xwords4/common/game.c +++ b/xwords4/common/game.c @@ -136,7 +136,6 @@ game_makeNewGame( MPFORMAL XWEnv xwe, XWGame* game, CurGameInfo* gi, gi->gameID = makeGameID( util ); } game->created = dutil_getCurSeconds( util_getDevUtilCtxt( util, xwe ), xwe ); - game->util = util; game->model = model_make( MPPARM(mpool) xwe, (DictionaryCtxt*)NULL, @@ -328,9 +327,6 @@ game_makeFromStream( MPFORMAL XWEnv xwe, XWStreamCtxt* stream, XWGame* game, if ( success && !!game && !!game->comms ) { XP_ASSERT( comms_getIsServer(game->comms) == server_getIsServer(game->server) ); - if ( server_getGameIsConnected( game->server ) ) { - comms_gatherPlayers( game->comms, xwe ); - } } return success; @@ -368,7 +364,14 @@ game_saveToStream( const XWGame* game, XWEnv xwe, const CurGameInfo* gi, gi_writeToStream( stream, gi ); if ( !!game ) { - stream_putU32( stream, game->created ); + const XP_U32 created = game->created; + if ( !!game->comms + && 0 != created + && server_getGameIsConnected( game->server ) ) { + comms_gatherPlayers( game->comms, xwe, created ); + } + + stream_putU32( stream, created ); XP_ASSERT( 0 != saveToken ); XP_U8 flags = NULL == game->comms ? 0 : FLAG_HASCOMMS; diff --git a/xwords4/common/game.h b/xwords4/common/game.h index 856e26ba2..69ce2f15c 100644 --- a/xwords4/common/game.h +++ b/xwords4/common/game.h @@ -51,7 +51,7 @@ typedef struct _GameStateInfo { XP_Bool canUnpause; /* duplicate-mode only */ } GameStateInfo; -typedef struct XWGame { +typedef struct _XWGame { XW_UtilCtxt* util; BoardCtxt* board; ModelCtxt* model; diff --git a/xwords4/common/knownplyr.c b/xwords4/common/knownplyr.c index 3da259c77..2e81af859 100644 --- a/xwords4/common/knownplyr.c +++ b/xwords4/common/knownplyr.c @@ -26,6 +26,7 @@ typedef struct _KnownPlayer { struct _KnownPlayer* next; + XP_U32 newestMod; XP_UCHAR* name; CommsAddrRec addr; } KnownPlayer; @@ -38,7 +39,8 @@ typedef struct _KPState { } KPState; static void addPlayer( XW_DUtilCtxt* dutil, KPState* state, - const XP_UCHAR* name, const CommsAddrRec* addr ); + const XP_UCHAR* name, const CommsAddrRec* addr, + XP_U32 newestMod ); static void getPlayersImpl( const KPState* state, const XP_UCHAR** players, XP_U16* nFound ); @@ -47,13 +49,14 @@ loadFromStream( XW_DUtilCtxt* dutil, KPState* state, XWStreamCtxt* stream ) { LOG_FUNC(); while ( 0 < stream_getSize( stream ) ) { + XP_U32 newestMod = stream_getU32( stream ); XP_UCHAR buf[64]; stringFromStreamHere( stream, buf, VSIZE(buf) ); CommsAddrRec addr = {0}; addrFromStream( &addr, stream ); - addPlayer( dutil, state, buf, &addr ); + addPlayer( dutil, state, buf, &addr, newestMod ); } } @@ -88,6 +91,7 @@ saveState( XW_DUtilCtxt* dutil, XWEnv xwe, KPState* state ) dutil_getVTManager(dutil) ); stream_putU8( stream, CUR_STREAM_VERS ); for ( KnownPlayer* kp = state->players; !!kp; kp = kp->next ) { + stream_putU32( stream, kp->newestMod ); stringToStream( stream, kp->name ); addrToStream( stream, &kp->addr ); } @@ -156,8 +160,8 @@ makeUniqueName( const KPState* state, const XP_UCHAR* name, * For early testing, however, just make a new name. */ static void -addPlayer( XW_DUtilCtxt* dutil, KPState* state, - const XP_UCHAR* name, const CommsAddrRec* addr ) +addPlayer( XW_DUtilCtxt* dutil, KPState* state, const XP_UCHAR* name, + const CommsAddrRec* addr, XP_U32 newestMod ) { XP_LOGFF( "(name=%s)", name ); KnownPlayer* withSameDevID = NULL; @@ -176,7 +180,12 @@ addPlayer( XW_DUtilCtxt* dutil, KPState* state, XP_UCHAR tmpName[64]; if ( !!withSameDevID ) { /* only one allowed */ - state->dirty = augmentAddr( &withSameDevID->addr, addr ) || state->dirty; + XP_Bool isNewer = newestMod > withSameDevID->newestMod; + XP_Bool changed = augmentAddr( &withSameDevID->addr, addr, isNewer ); + if ( isNewer ) { + withSameDevID->newestMod = newestMod; + } + state->dirty = changed || state->dirty; } else { if ( !!withSameName ) { /* Same name but different devID? Create a unique name */ @@ -197,7 +206,7 @@ addPlayer( XW_DUtilCtxt* dutil, KPState* state, XP_Bool kplr_addAddrs( XW_DUtilCtxt* dutil, XWEnv xwe, const CurGameInfo* gi, - CommsAddrRec addrs[], XP_U16 nAddrs ) + CommsAddrRec addrs[], XP_U16 nAddrs, XP_U32 modTime ) { LOG_FUNC(); XP_Bool canUse = XP_TRUE; @@ -213,7 +222,7 @@ kplr_addAddrs( XW_DUtilCtxt* dutil, XWEnv xwe, const CurGameInfo* gi, for ( int ii = 0; ii < nAddrs && canUse; ++ii ) { const XP_UCHAR* name = figureNameFor( ii, gi ); if ( !!name ) { - addPlayer( dutil, state, name, &addrs[ii] ); + addPlayer( dutil, state, name, &addrs[ii], modTime ); } else { XP_LOGFF( "unable to find %dth name", ii ); } @@ -247,8 +256,8 @@ getPlayersImpl( const KPState* state, const XP_UCHAR** players, XP_U16* nFound ) } void -kplr_getPlayers( XW_DUtilCtxt* dutil, XWEnv xwe, - const XP_UCHAR** players, XP_U16* nFound ) +kplr_getNames( XW_DUtilCtxt* dutil, XWEnv xwe, + const XP_UCHAR** players, XP_U16* nFound ) { KPState* state = loadState( dutil, xwe ); getPlayersImpl( state, players, nFound ); diff --git a/xwords4/common/knownplyr.h b/xwords4/common/knownplyr.h index 1adc712b4..ae6a6a5ca 100644 --- a/xwords4/common/knownplyr.h +++ b/xwords4/common/knownplyr.h @@ -32,13 +32,13 @@ void kplr_cleanup( XW_DUtilCtxt* dutil ); XP_Bool kplr_havePlayers( XW_DUtilCtxt* dutil, XWEnv xwe ); -void kplr_getPlayers( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR** players, - XP_U16* nFound ); +void kplr_getNames( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR** players, + XP_U16* nFound ); XP_Bool kplr_getAddr( XW_DUtilCtxt* dutil, XWEnv xwe, const XP_UCHAR* name, CommsAddrRec* addr ); XP_Bool kplr_addAddrs( XW_DUtilCtxt* dutil, XWEnv xwe, const CurGameInfo* gi, - CommsAddrRec addrs[], XP_U16 nAddrs ); + CommsAddrRec addrs[], XP_U16 nAddrs, XP_U32 modTime ); # else # define kplr_cleanup( dutil ) # endif diff --git a/xwords4/linux/gtkinvit.c b/xwords4/linux/gtkinvit.c index eb2cbadef..5333e4b55 100644 --- a/xwords4/linux/gtkinvit.c +++ b/xwords4/linux/gtkinvit.c @@ -286,10 +286,10 @@ makeKnownsPage( GtkInviteState* state, PageData* data ) gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 ); XP_U16 nFound = 0; - kplr_getPlayers( state->dutil, NULL_XWE, NULL, &nFound ); + kplr_getNames( state->dutil, NULL_XWE, NULL, &nFound ); XP_ASSERT( nFound > 0 ); const XP_UCHAR* names[nFound]; - kplr_getPlayers( state->dutil, NULL_XWE, names, &nFound ); + kplr_getNames( state->dutil, NULL_XWE, names, &nFound ); GtkWidget* combo = state->knownsCombo = gtk_combo_box_text_new(); for ( int ii = 0; ii < nFound; ++ii ) {