Fix relay devid protocol to deal with case where client submits a

ID_TYPE_RELAY id that's not in the devices table (as has happened when
a device switches relay URLs during testing, but might also happen if
I have to delete an entry from the devices table.)  In that case,
return ID_TYPE_NONE to the client, which will be its clue to delete
its ID_TYPE_RELAY id and submit the platform-specific id again.

Note: android won't compile this revision thanks to util.h change
This commit is contained in:
Eric House 2012-11-10 15:05:44 -08:00
parent b53412d98d
commit 1316ae4b67
6 changed files with 63 additions and 36 deletions

View file

@ -1331,10 +1331,14 @@ got_connect_cmd( CommsCtxt* comms, XWStreamCtxt* stream,
#endif #endif
#ifdef XWFEATURE_DEVID #ifdef XWFEATURE_DEVID
XP_UCHAR devID[MAX_DEVID_LEN + 1]; DevIDType typ = stream_getU8( stream );
XP_UCHAR devID[MAX_DEVID_LEN + 1] = {0};
if ( ID_TYPE_NONE != typ ) {
stringFromStreamHere( stream, devID, sizeof(devID) ); stringFromStreamHere( stream, devID, sizeof(devID) );
if ( devID[0] != '\0' ) { }
util_deviceRegistered( comms->util, devID ); if ( ID_TYPE_NONE == typ /* error case */
|| '\0' != devID[0] ) /* new info case */ {
util_deviceRegistered( comms->util, typ, devID );
} }
#endif #endif

View file

@ -154,7 +154,8 @@ typedef struct UtilVtable {
XP_U32 (*m_util_getCurSeconds)( XW_UtilCtxt* uc ); XP_U32 (*m_util_getCurSeconds)( XW_UtilCtxt* uc );
#ifdef XWFEATURE_DEVID #ifdef XWFEATURE_DEVID
const XP_UCHAR* (*m_util_getDevID)( XW_UtilCtxt* uc, DevIDType* typ ); const XP_UCHAR* (*m_util_getDevID)( XW_UtilCtxt* uc, DevIDType* typ );
void (*m_util_deviceRegistered)( XW_UtilCtxt* uc, const XP_UCHAR* idRelay ); void (*m_util_deviceRegistered)( XW_UtilCtxt* uc, DevIDType typ,
const XP_UCHAR* idRelay );
#endif #endif
DictionaryCtxt* (*m_util_makeEmptyDict)( XW_UtilCtxt* uc ); DictionaryCtxt* (*m_util_makeEmptyDict)( XW_UtilCtxt* uc );
@ -286,8 +287,8 @@ struct XW_UtilCtxt {
#ifdef XWFEATURE_DEVID #ifdef XWFEATURE_DEVID
# define util_getDevID( uc, t ) \ # define util_getDevID( uc, t ) \
(uc)->vtable->m_util_getDevID((uc),(t)) (uc)->vtable->m_util_getDevID((uc),(t))
# define util_deviceRegistered( uc, id ) \ # define util_deviceRegistered( uc, typ, id ) \
(uc)->vtable->m_util_deviceRegistered( (uc), (id) ) (uc)->vtable->m_util_deviceRegistered( (uc), (typ), (id) )
#endif #endif
#define util_makeEmptyDict( uc ) \ #define util_makeEmptyDict( uc ) \

View file

@ -1593,9 +1593,6 @@ main( int argc, char** argv )
mainParams.allowPeek = XP_TRUE; mainParams.allowPeek = XP_TRUE;
mainParams.showRobotScores = XP_FALSE; mainParams.showRobotScores = XP_FALSE;
mainParams.useMmap = XP_TRUE; mainParams.useMmap = XP_TRUE;
#ifdef XWFEATURE_DEVID
mainParams.devID = "";
#endif
char* envDictPath = getenv( "XW_DICTSPATH" ); char* envDictPath = getenv( "XW_DICTSPATH" );
if ( !!envDictPath ) { if ( !!envDictPath ) {

View file

@ -353,19 +353,24 @@ linux_util_getDevID( XW_UtilCtxt* uc, DevIDType* typ )
if ( !!cGlobals->params->rDevID ) { if ( !!cGlobals->params->rDevID ) {
*typ = ID_TYPE_RELAY; *typ = ID_TYPE_RELAY;
result = cGlobals->params->rDevID; result = cGlobals->params->rDevID;
} else { } else if ( !!cGlobals->params->devID ) {
*typ = ID_TYPE_LINUX; *typ = ID_TYPE_LINUX;
result = cGlobals->params->devID; result = cGlobals->params->devID;
} else {
*typ = ID_TYPE_NONE;
result = NULL;
} }
return result; return result;
} }
static void static void
linux_util_deviceRegistered( XW_UtilCtxt* XP_UNUSED(uc), linux_util_deviceRegistered( XW_UtilCtxt* XP_UNUSED(uc),
DevIDType XP_UNUSED_DBG(typ),
const XP_UCHAR* idRelay ) const XP_UCHAR* idRelay )
{ {
/* Script discon_ok2.sh is grepping for this in logs, so don't change /* Script discon_ok2.sh is grepping for this in logs, so don't change
it! */ it! */
XP_ASSERT( ID_TYPE_RELAY == typ ); /* all the linux client deals with */
XP_LOGF( "%s: new id: %s", __func__, idRelay ); XP_LOGF( "%s: new id: %s", __func__, idRelay );
} }
#endif #endif

View file

@ -891,14 +891,8 @@ CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp,
DevIDType devIDType = evt->u.con.devID->m_devIDType; DevIDType devIDType = evt->u.con.devID->m_devIDType;
// does client support devID // does client support devID
if ( ID_TYPE_NONE != devIDType ) { if ( ID_TYPE_NONE != devIDType ) {
// have we not already converted it?
if ( ID_TYPE_RELAY == devIDType ) {
devID = (DBMgr::DevIDRelay)strtoul( evt->u.con.devID->m_devIDString.c_str(),
NULL, 16 );
} else {
devID = DBMgr::Get()->RegisterDevice( evt->u.con.devID ); devID = DBMgr::Get()->RegisterDevice( evt->u.con.devID );
} }
}
*devIDp = devID; *devIDp = devID;
} }
@ -1071,23 +1065,39 @@ CookieRef::sendResponse( const CRefEvent* evt, bool initial,
bufp += len; bufp += len;
// we always write at least empty string // we always write at least empty string
char idbuf[MAX_DEVID_LEN + 1] = {0};
// If client supports devid, and we have one (response case), write it as // If client supports devid, and we have one (response case), write it as
// 8-byte hex string plus a length byte -- but only if we didn't already // 8-byte hex string plus a length byte -- but only if we didn't already
// receive it. // receive it.
if ( !!devID && ID_TYPE_RELAY < evt->u.con.devID->m_devIDType ) {
// there are three possibilities: it sent us a platform-specific ID and we
// need to return the relay version; or it sent us a valid relay version;
// or it sent us an invalid one (for whatever reason, e.g. we've wiped the
// devices table entry for a problematic GCM id to force reregistration.)
// In the first case, we return the new relay version. In the second, we
// return that the type is ID_TYPE_RELAY but don't bother with the version
// string; and in the third, we return ID_TYPE_NONE.
if ( DBMgr::DEVID_NONE == *devID ) { // first case
*bufp++ = ID_TYPE_NONE;
} else {
*bufp++ = ID_TYPE_RELAY;
// Write an empty string if the client passed the ID to us, or the id
// if it's new to the client.
char idbuf[MAX_DEVID_LEN + 1];
if ( !!ID_TYPE_RELAY < evt->u.con.devID->m_devIDType ) {
len = snprintf( idbuf, sizeof(idbuf), "%.8X", *devID ); len = snprintf( idbuf, sizeof(idbuf), "%.8X", *devID );
assert( len < sizeof(idbuf) ); assert( len < sizeof(idbuf) );
} else {
len = 0;
} }
len = strlen( idbuf );
assert( len <= MAX_DEVID_LEN );
*bufp++ = (char)len; *bufp++ = (char)len;
if ( 0 < len ) { if ( 0 < len ) {
memcpy( bufp, idbuf, len ); memcpy( bufp, idbuf, len );
bufp += len; bufp += len;
} }
}
send_with_length( socket, buf, bufp - buf, true ); send_with_length( socket, buf, bufp - buf, true );
logf( XW_LOGVERBOSE0, "sent %s", cmdToStr( XWRELAY_Cmd(buf[0]) ) ); logf( XW_LOGVERBOSE0, "sent %s", cmdToStr( XWRELAY_Cmd(buf[0]) ) );

View file

@ -253,13 +253,16 @@ DBMgr::DevIDRelay
DBMgr::RegisterDevice( const DevID* host ) DBMgr::RegisterDevice( const DevID* host )
{ {
DBMgr::DevIDRelay devID; DBMgr::DevIDRelay devID;
assert( host->m_devIDType != ID_TYPE_RELAY ); assert( host->m_devIDType != ID_TYPE_NONE );
int ii; int ii;
bool success; bool success;
// if it's already present, just return // if it's already present, just return
devID = getDevID( host ); devID = getDevID( host );
if ( DEVID_NONE == devID ) {
// If it's not present *and* of type ID_TYPE_RELAY, we can do nothing.
// Fail.
if ( DEVID_NONE == devID && ID_TYPE_RELAY < host->m_devIDType ) {
// loop until we're successful inserting the unique key. Ship with this // loop until we're successful inserting the unique key. Ship with this
// coming from random, but test with increasing values initially to make // coming from random, but test with increasing values initially to make
// sure duplicates are detected. // sure duplicates are detected.
@ -641,16 +644,23 @@ DBMgr::getDevID( const DevID* devID )
{ {
DBMgr::DevIDRelay rDevID = DEVID_NONE; DBMgr::DevIDRelay rDevID = DEVID_NONE;
DevIDType devIDType = devID->m_devIDType; DevIDType devIDType = devID->m_devIDType;
char query[512] = {0};
assert( ID_TYPE_NONE < devIDType ); assert( ID_TYPE_NONE < devIDType );
const char* asStr = devID->m_devIDString.c_str(); const char* asStr = devID->m_devIDString.c_str();
if ( ID_TYPE_RELAY == devIDType ) { if ( ID_TYPE_RELAY == devIDType ) {
rDevID = strtoul( asStr, NULL, 16 ); // confirm it's there
DBMgr::DevIDRelay cur = strtoul( asStr, NULL, 16 );
if ( DEVID_NONE != cur ) {
const char* fmt = "SELECT id FROM " DEVICES_TABLE " WHERE id=%d";
snprintf( query, sizeof(query), fmt, cur );
}
} else { } else {
const char* fmt = "SELECT id FROM " DEVICES_TABLE " WHERE devtype=%d and devid = '%s'"; const char* fmt = "SELECT id FROM " DEVICES_TABLE " WHERE devtype=%d and devid = '%s'";
char query[512];
snprintf( query, sizeof(query), fmt, devIDType, asStr ); snprintf( query, sizeof(query), fmt, devIDType, asStr );
logf( XW_LOGINFO, "%s: query: %s", __func__, query ); }
if ( '\0' != query[0] ) {
logf( XW_LOGINFO, "%s: query: %s", __func__, query );
PGresult* result = PQexec( getThreadConn(), query ); PGresult* result = PQexec( getThreadConn(), query );
assert( 1 >= PQntuples( result ) ); assert( 1 >= PQntuples( result ) );
if ( 1 == PQntuples( result ) ) { if ( 1 == PQntuples( result ) ) {