add support for udp-based delete and anonymous (relay-provided) regIDs

This commit is contained in:
Eric House 2013-01-29 07:38:07 -08:00
parent 72e100ccac
commit 9ee16adc3a
4 changed files with 107 additions and 17 deletions

View file

@ -43,6 +43,7 @@
static DBMgr* s_instance = NULL;
#define DELIM "\1"
#define MAX_NUM_PLAYERS 4
static void formatParams( char* paramValues[], int nParams, const char* fmt,
char* buf, int bufLen, ... );
@ -149,6 +150,54 @@ DBMgr::FindGame( const char* connName, char* cookieBuf, int bufLen,
return cid;
} /* FindGame */
bool
DBMgr::FindPlayer( DevIDRelay relayID, AddrInfo::ClientToken token,
string& connName, HostID* hidp, unsigned short* seed )
{
int nSuccesses = 0;
const char* fmt =
"SELECT connName FROM %s WHERE %d = ANY(devids) AND %d = ANY(tokens)";
string query;
string_printf( query, fmt, GAMES_TABLE, relayID, token );
PGresult* result = PQexec( getThreadConn(), query.c_str() );
int nTuples = PQntuples( result );
vector<string> names(nTuples);
for ( int ii = 0; ii < nTuples; ++ii ) {
string name( PQgetvalue( result, ii, 0 ) );
names.push_back( name );
}
PQclear( result );
for ( vector<string>::const_iterator iter = names.begin();
iter != names.end(); ++iter ) {
const char* name = iter->c_str();
for ( HostID hid = 1; hid <= MAX_NUM_PLAYERS; ++hid ) {
fmt = "SELECT seeds[%d] FROM %s WHERE connname = '%s' "
"AND devids[%d] = %d AND tokens[%d] = %d";
string query;
string_printf( query, fmt, hid, GAMES_TABLE, name,
hid, relayID, hid, token );
result = PQexec( getThreadConn(), query.c_str() );
int nTuples2 = PQntuples( result );
for ( int jj = 0; jj < nTuples2; ++jj ) {
connName = name;
*hidp = hid;
*seed = atoi( PQgetvalue( result, 0, 0 ) );
++nSuccesses;
}
PQclear( result );
}
}
if ( 1 < nSuccesses ) {
logf( XW_LOGERROR, "%s found %d matches!!!", __func__, nSuccesses );
}
return nSuccesses >= 1;
} // FindPlayer
bool
DBMgr::SeenSeed( const char* cookie, unsigned short seed,
int langCode, int nPlayersT, bool wantsPublic,
@ -295,7 +344,8 @@ DBMgr::RegisterDevice( const DevID* host )
NULL, NULL, 0 );
success = PGRES_COMMAND_OK == PQresultStatus(result);
if ( !success ) {
logf( XW_LOGERROR, "PQexec=>%s;%s", PQresStatus(PQresultStatus(result)),
logf( XW_LOGERROR, "PQexec=>%s;%s",
PQresStatus(PQresultStatus(result)),
PQresultErrorMessage(result) );
}
PQclear( result );
@ -315,7 +365,8 @@ DBMgr::updateDevice( DevIDRelay relayID, bool check )
}
if ( exists ) {
const char* fmt = "UPDATE " DEVICES_TABLE " SET mtime='now' WHERE id = %d";
const char* fmt =
"UPDATE " DEVICES_TABLE " SET mtime='now' WHERE id = %d";
string query;
string_printf( query, fmt, relayID );
execSql( query );

View file

@ -47,6 +47,9 @@ class DBMgr {
void AddNew( const char* cookie, const char* connName, CookieID cid,
int langCode, int nPlayersT, bool isPublic );
bool FindPlayer( DevIDRelay relayID, AddrInfo::ClientToken,
string& connName, HostID* hid, unsigned short* seed );
CookieID FindGame( const char* connName, char* cookieBuf, int bufLen,
int* langP, int* nPlayersTP, int* nPlayersHP,
bool* isDead );

View file

@ -271,6 +271,24 @@ getNetString( const unsigned char** bufpp, const unsigned char* end, string& out
return success;
}
static bool
getRelayDevID( const unsigned char** bufpp, const unsigned char* end,
DevID& devID )
{
bool success = false;
unsigned short idLen;
if ( getNetShort( bufpp, end, &idLen ) ) {
if ( end - *bufpp < idLen/* && ID_TYPE_ANON != typ*/ ) {
logf( XW_LOGERROR, "full devID not received" );
} else {
devID.m_devIDString.append( (const char*)*bufpp, idLen );
*bufpp += idLen;
success = true;
}
}
return success;
}
static bool
getHeader( const unsigned char** bufpp, const unsigned char* end,
UDPHeader* header )
@ -1284,6 +1302,7 @@ msgToStr( XWRelayReg msg )
CASE_STR(XWPDEV_BADREG);
CASE_STR(XWPDEV_ALERT); // should not receive this....
CASE_STR(XWPDEV_ACK);
CASE_STR(XWPDEV_DELGAME);
default:
str = "<unknown>";
break;
@ -1318,20 +1337,12 @@ udp_thread_proc( UdpThreadClosure* utc )
switch( header.cmd ) {
case XWPDEV_REG: {
DevIDType typ = (DevIDType)*ptr++;
unsigned short idLen;
if ( !getNetShort( &ptr, end, &idLen ) ) {
break;
}
if ( end - ptr > idLen ) {
logf( XW_LOGERROR, "full devID not received" );
break;
}
DevID devID( typ );
devID.m_devIDString.append( (const char*)ptr, idLen );
ptr += idLen;
registerDevice( &devID, utc->saddr() );
}
if ( getRelayDevID( &ptr, end, devID ) ) {
registerDevice( &devID, utc->saddr() );
}
break;
}
case XWPDEV_MSG: {
AddrInfo::ClientToken clientToken;
memcpy( &clientToken, ptr, sizeof(clientToken) );
@ -1393,14 +1404,30 @@ udp_thread_proc( UdpThreadClosure* utc )
}
break;
}
case XWPDEV_DELGAME: {
DevID devID( ID_TYPE_RELAY );
if ( !getRelayDevID( &ptr, end, devID ) ) {
break;
}
AddrInfo::ClientToken clientToken;
if ( getNetLong( &ptr, end, &clientToken ) && 0 != clientToken ) {
unsigned short seed;
HostID hid;
string connName;
if ( DBMgr::Get()->FindPlayer( devID.asRelayID(), clientToken,
connName, &hid, &seed ) ) {
SafeCref scr( connName.c_str() );
scr.DeviceGone( hid, seed );
}
}
break;
}
default:
logf( XW_LOGERROR, "%s: unexpected msg %d", __func__, header.cmd );
}
}
}
// This will need to be done in a thread before there can be simulaneous
// connections.
static void
handle_udp_packet( int udpsock )
{

View file

@ -27,7 +27,12 @@
/* Set if device is acting a server; cleared if as client */
#define FLAGS_SERVER_BIT 0x01
/* message types for the udp-based per-device (not per-game) protocol */
/* message types for the udp-based per-device (not per-game) protocol
*
* A number of these rely on a "clientToken", which is a 32-bit value the
* client provides and that it guarantees uniquely identifies a game on the
* device. A database rowid works great as long as they aren't reused.
*/
#define XWPDEV_PROTO_VERSION 0
#ifndef CANT_DO_TYPEDEF
typedef
@ -86,6 +91,9 @@ enum { XWPDEV_NONE /* 0 is an illegal value */
msgID: 4
*/
,XWPDEV_DELGAME /* dev->relay: game's been deleted. format:
header, relayid: 4, clientToken: 4 */
}
#ifndef CANT_DO_TYPEDEF
XWRelayReg
@ -176,6 +184,7 @@ typedef enum {
,ID_TYPE_LINUX
,ID_TYPE_ANDROID_GCM
,ID_TYPE_ANDROID_OTHER
,ID_TYPE_ANON /* please assign me one based on nothing */
,ID_TYPE_NTYPES
} DevIDType;