From e4594f36e0a3bbbc223f27de570789f75721159d Mon Sep 17 00:00:00 2001 From: Eric House Date: Sun, 13 Sep 2020 14:48:36 -0700 Subject: [PATCH] generate new mqtt devid when server reports dupe Thanks to my use of unseeded() rand() early on to generate mqtt device IDs, a handful of devices are using the same devIDs. The server notices this and passes a new response which triggers generating a new id that should be unique (rand() being seeded earlier now.) Testing says the games that are left behind with the old devid will limp along thanks to their relay connection while newer games will be better. --- .../org/eehouse/android/xw4/MQTTUtils.java | 11 ++++ .../org/eehouse/android/xw4/jni/XwJNI.java | 6 ++ xwords4/android/jni/xwjni.c | 9 +++ xwords4/common/device.c | 57 ++++++++++++++++--- xwords4/common/device.h | 2 +- xwords4/linux/scripts/discon_ok2.py | 2 +- 6 files changed, 78 insertions(+), 9 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java index 32b56fc47..283e2798d 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/MQTTUtils.java @@ -313,6 +313,7 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba params.put( "dbg", BuildConfig.DEBUG ); params.put( "myNow", now ); params.put( "loc", LocUtils.getCurLocale( mContext ) ); + params.put( "knowsDup", true ); String fcmid = FBMService.getFCMDevID( mContext ); if ( null != fcmid ) { @@ -335,6 +336,16 @@ public class MQTTUtils extends Thread implements IMqttActionListener, MqttCallba DBUtils.setStringFor( mContext, KEY_LAST_WRITE, BuildConfig.GIT_REV ); sLastRev = BuildConfig.GIT_REV; } + + String dupID = response.optString( "dupID", "" ); + if ( dupID.equals( mDevID ) ) { + Log.e( TAG, "********** %s bad; need new devID!!! **********", dupID ); + XwJNI.dvc_resetMQTTDevID(); + // Force a reconnect asap + DBUtils.setLongFor( mContext, KEY_NEXT_REG, 0 ); + sNextReg = 0; + clearInstance(); + } } } else { Log.e( TAG, "registerOnce(): null back from runConn()" ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/XwJNI.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/XwJNI.java index b7ddf995a..63085d447 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/XwJNI.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/XwJNI.java @@ -138,6 +138,11 @@ public class XwJNI { return dvc_getMQTTDevID( getJNI().m_ptrGlobals, topic ); } + public static void dvc_resetMQTTDevID() + { + dvc_resetMQTTDevID( getJNI().m_ptrGlobals ); + } + public static byte[] dvc_makeMQTTInvite( NetLaunchInfo nli, String[] addrToTopic ) { return dvc_makeMQTTInvite( getJNI().m_ptrGlobals, nli, addrToTopic ); @@ -664,6 +669,7 @@ public class XwJNI { // Private methods -- called only here private static native long globalsInit( DUtilCtxt dutil, JNIUtils jniu, long seed ); private static native String dvc_getMQTTDevID( long jniState, String[] topic ); + private static native void dvc_resetMQTTDevID( long jniState ); private static native byte[] dvc_makeMQTTInvite( long jniState, NetLaunchInfo nli, String[] addrToTopic ); private static native byte[] dvc_makeMQTTMessage( long jniState, int gameID, byte[] buf, diff --git a/xwords4/android/jni/xwjni.c b/xwords4/android/jni/xwjni.c index 76a18d9c4..57010dcf2 100644 --- a/xwords4/android/jni/xwjni.c +++ b/xwords4/android/jni/xwjni.c @@ -648,6 +648,15 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dvc_1getMQTTDevID return result; } +JNIEXPORT void JNICALL +Java_org_eehouse_android_xw4_jni_XwJNI_dvc_1resetMQTTDevID +( JNIEnv* env, jclass C, jlong jniGlobalPtr ) +{ + DVC_HEADER(jniGlobalPtr); + dvc_resetMQTTDevID( globalState->dutil, env ); + DVC_HEADER_END(); +} + static void addrToTopic( JNIEnv* env, jobjectArray jAddrToTopic ) { diff --git a/xwords4/common/device.c b/xwords4/common/device.c index a79e5a125..c524a3ba4 100644 --- a/xwords4/common/device.c +++ b/xwords4/common/device.c @@ -80,30 +80,73 @@ dvc_store( XW_DUtilCtxt* dutil, XWEnv xwe ) #endif -void -dvc_getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTDevID* devID ) +// #define BOGUS_ALL_SAME_DEVID + +static void +getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, XP_Bool forceNew, MQTTDevID* devID ) { +#ifdef BOGUS_ALL_SAME_DEVID + XP_USE(forceNew); + MQTTDevID bogusID = 0; + XP_UCHAR* str = "ABCDEF0123456789"; + XP_Bool ok = strToMQTTCDevID( str, &bogusID ); + XP_ASSERT( ok ); + MQTTDevID tmp = 0; XP_U16 len = sizeof(tmp); dutil_loadPtr( dutil, xwe, MQTT_DEVID_KEY, SUFFIX_MQTT_DEVID, &tmp, &len ); + if ( len != sizeof(tmp) || 0 != XP_MEMCMP( &bogusID, &tmp, sizeof(tmp) ) ) { + dutil_storePtr( dutil, xwe, MQTT_DEVID_KEY, &bogusID, sizeof(bogusID) ); + } + *devID = bogusID; - // XP_LOGFF( "len: %d; sizeof(tmp): %d", len, sizeof(tmp) ); - if ( len != sizeof(tmp) ) { /* not found, or bogus somehow */ +#else + + MQTTDevID tmp = 0; + XP_U16 len = sizeof(tmp); + if ( !forceNew ) { + dutil_loadPtr( dutil, xwe, MQTT_DEVID_KEY, SUFFIX_MQTT_DEVID, &tmp, &len ); + } + + XP_LOGFF( "len: %d; sizeof(tmp): %zu", len, sizeof(tmp) ); + if ( forceNew || len != sizeof(tmp) ) { /* not found, or bogus somehow */ tmp = XP_RANDOM(); tmp <<= 27; tmp ^= XP_RANDOM(); tmp <<= 27; tmp ^= XP_RANDOM(); dutil_storePtr( dutil, xwe, MQTT_DEVID_KEY, &tmp, sizeof(tmp) ); -#ifdef DEBUG + +# ifdef DEBUG XP_UCHAR buf[32]; formatMQTTDevID( &tmp, buf, VSIZE(buf) ); /* This log statement is required by discon_ok2.py!!! (keep in sync) */ XP_LOGFF( "generated id: %s; key: %s", buf, MQTT_DEVID_KEY ); -#endif +# endif } *devID = tmp; - // LOG_RETURNF( MQTTDevID_FMT " key: %s", *devID, MQTT_DEVID_KEY ); +#endif + LOG_RETURNF( MQTTDevID_FMT " key: %s", *devID, MQTT_DEVID_KEY ); +} + +void +dvc_getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTDevID* devID ) +{ + getMQTTDevID( dutil, xwe, XP_FALSE, devID ); +} + +void +dvc_resetMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe ) +{ + LOG_FUNC(); +#ifdef BOGUS_ALL_SAME_DEVID + XP_LOGFF( "doing nothing" ); + XP_USE( dutil ); + XP_USE( xwe ); +#else + MQTTDevID ignored; + getMQTTDevID( dutil, xwe, XP_TRUE, &ignored ); +#endif } typedef enum { CMD_INVITE, CMD_MSG, CMD_DEVGONE, } MQTTCmd; diff --git a/xwords4/common/device.h b/xwords4/common/device.h index 37978edff..3ae2fe9f4 100644 --- a/xwords4/common/device.h +++ b/xwords4/common/device.h @@ -31,7 +31,7 @@ void dvc_store( XW_DUtilCtxt* dctxt, XWEnv xwe ); # endif void dvc_getMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe, MQTTDevID* devID ); - +void dvc_resetMQTTDevID( XW_DUtilCtxt* dutil, XWEnv xwe ); void dvc_makeMQTTInvite( XW_DUtilCtxt* dutil, XWEnv xwe, XWStreamCtxt* stream, const NetLaunchInfo* nli ); void dvc_makeMQTTMessage( XW_DUtilCtxt* dutil, XWEnv xwe, XWStreamCtxt* stream, diff --git a/xwords4/linux/scripts/discon_ok2.py b/xwords4/linux/scripts/discon_ok2.py index 55e392c64..ea1faacfb 100755 --- a/xwords4/linux/scripts/discon_ok2.py +++ b/xwords4/linux/scripts/discon_ok2.py @@ -165,7 +165,7 @@ class Device(): sTilesLeftTrayPat = re.compile('.*player \d+ now has (\d+) tiles') sRelayIDPat = re.compile('.*UPDATE games.*seed=(\d+),.*relayid=\'([^\']+)\'.*') sDevIDPat = re.compile('.*storing new devid: ([\da-fA-F]+).*') - sMQTTDevIDPat = re.compile('.*dvc_getMQTTDevID.*: generated id: ([\d[A-F]+).*') + sMQTTDevIDPat = re.compile('.*getMQTTDevID.*: generated id: ([\d[A-F]+).*') sConnPat = re.compile('.*linux_util_informMissing\(isServer.*nMissing=0\).*') sScoresDup = []