From 3469975d2ab7c25fd75d4ac747b391d54a0c10cb Mon Sep 17 00:00:00 2001 From: Eric House Date: Tue, 30 Oct 2012 07:01:47 -0700 Subject: [PATCH] add, still disabled by compile-time flags, code to transmit device ID (e.g. ID Android devices get via GCM) to relay and to associate it there with messages that need to be delivered. --- xwords4/common/comms.c | 27 +++++++++++++++ xwords4/common/comms.h | 6 ++++ xwords4/common/util.h | 9 ++++- xwords4/linux/Makefile | 1 + xwords4/linux/linuxmain.c | 14 ++++++++ xwords4/linux/linuxutl.c | 13 ++++++++ xwords4/linux/main.h | 3 ++ xwords4/relay/cref.cpp | 29 +++++++++------- xwords4/relay/cref.h | 24 ++++++++++---- xwords4/relay/crefmgr.cpp | 4 ++- xwords4/relay/crefmgr.h | 13 ++++---- xwords4/relay/dbmgr.cpp | 51 +++++++++++++++++++++++------ xwords4/relay/dbmgr.h | 5 ++- xwords4/relay/scripts/showinplay.sh | 6 ++-- xwords4/relay/xwrelay.cpp | 40 +++++++++++++++++++--- xwords4/relay/xwrelay.h | 1 + xwords4/relay/xwrelay.sh | 4 +++ 17 files changed, 205 insertions(+), 45 deletions(-) diff --git a/xwords4/common/comms.c b/xwords4/common/comms.c index 62716a842..3f4bd03fe 100644 --- a/xwords4/common/comms.c +++ b/xwords4/common/comms.c @@ -185,6 +185,11 @@ static XP_Bool sendNoConn( CommsCtxt* comms, const MsgQueueElem* elem, XWHostID destID ); static XWHostID getDestID( CommsCtxt* comms, XP_PlayerAddr channelNo ); static void set_reset_timer( CommsCtxt* comms ); +# ifdef XWFEATURE_DEVID +static void putDevID( const CommsCtxt* comms, XWStreamCtxt* stream ); +# else +# define putDevID( comms, stream ) +# endif # ifdef DEBUG static const char* relayCmdToStr( XWRELAY_Cmd cmd ); # endif @@ -2120,6 +2125,7 @@ msg_to_stream( CommsCtxt* comms, XWRELAY_Cmd cmd, XWHostID destID, stream_putU8( stream, comms->r.nPlayersTotal ); stream_putU16( stream, comms_getChannelSeed(comms) ); stream_putU8( stream, comms->util->gameInfo->dictLang ); + putDevID( comms, stream ); set_relay_state( comms, COMMS_RELAYSTATE_CONNECT_PENDING ); break; @@ -2292,6 +2298,27 @@ relayDisconnect( CommsCtxt* comms ) set_relay_state( comms, COMMS_RELAYSTATE_UNCONNECTED ); } } /* relayDisconnect */ + +#ifdef XWFEATURE_DEVID +static void +putDevID( const CommsCtxt* comms, XWStreamCtxt* stream ) +{ +# if XWRELAY_PROTO_VERSION >= XWRELAY_PROTO_VERSION_CLIENTID + DevIDType typ; + const XP_UCHAR* devID = util_getDevID( comms->util, &typ ); + stream_putU8( stream, typ ); + if ( ID_TYPE_NONE != typ ) { + stream_catString( stream, devID ); + stream_putU8( stream, '\0' ); + } +# else + XP_ASSERT(0); + XP_USE(comms); + XP_USE(stream); +# endif +} +#endif + #endif EXTERN_C_END diff --git a/xwords4/common/comms.h b/xwords4/common/comms.h index 7907be490..4585d21a8 100644 --- a/xwords4/common/comms.h +++ b/xwords4/common/comms.h @@ -55,6 +55,12 @@ typedef enum { , COMMS_RELAYSTATE_ALLCONNECTED } CommsRelayState; +typedef enum { + ID_TYPE_NONE + ,ID_TYPE_LINUX + ,ID_TYPE_ANDROID_GCM +} DevIDType; + #ifdef XWFEATURE_BLUETOOTH # define XW_BT_UUID "7be0d084-ff89-4d6d-9c78-594773a6f963" diff --git a/xwords4/common/util.h b/xwords4/common/util.h index 6e2c46ee4..46da6a5ea 100644 --- a/xwords4/common/util.h +++ b/xwords4/common/util.h @@ -152,7 +152,9 @@ typedef struct UtilVtable { XP_Bool (*m_util_altKeyDown)( XW_UtilCtxt* uc ); XP_U32 (*m_util_getCurSeconds)( XW_UtilCtxt* uc ); - +#ifdef XWFEATURE_DEVID + const XP_UCHAR* (*m_util_getDevID)( XW_UtilCtxt* uc, DevIDType* typ ); +#endif DictionaryCtxt* (*m_util_makeEmptyDict)( XW_UtilCtxt* uc ); const XP_UCHAR* (*m_util_getUserString)( XW_UtilCtxt* uc, @@ -280,6 +282,11 @@ struct XW_UtilCtxt { #define util_getCurSeconds(uc) \ (uc)->vtable->m_util_getCurSeconds((uc)) +#ifdef XWFEATURE_DEVID +# define util_getDevID( uc, t ) \ + (uc)->vtable->m_util_getDevID((uc),(t)) +#endif + #define util_makeEmptyDict( uc ) \ (uc)->vtable->m_util_makeEmptyDict((uc)) diff --git a/xwords4/linux/Makefile b/xwords4/linux/Makefile index 1459e6580..d4f25f745 100644 --- a/xwords4/linux/Makefile +++ b/xwords4/linux/Makefile @@ -110,6 +110,7 @@ DEFINES += -DXWFEATURE_BONUSALL DEFINES += -DXWFEATURE_HILITECELL # allow change dict inside running game DEFINES += -DXWFEATURE_CHANGEDICT +# DEFINES += -DXWFEATURE_DEVID # MAX_ROWS controls STREAM_VERS_BIGBOARD and with it move hashing DEFINES += -DMAX_ROWS=32 diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index 0587fbad7..70bab7cf8 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -503,6 +503,9 @@ typedef enum { ,CMD_DICTDIR ,CMD_PLAYERDICT ,CMD_SEED +#ifdef XWFEATURE_DEVID + ,CMD_DEVID +#endif ,CMD_GAMESEED ,CMD_GAMEFILE ,CMD_SAVEFAIL_PCT @@ -596,6 +599,9 @@ static CmdInfoRec CmdInfoRecs[] = { ,{ CMD_DICTDIR, true, "dict-dir", "path to dir in which dicts will be sought" } ,{ CMD_PLAYERDICT, true, "player-dict", "dictionary name for player (in sequence)" } ,{ CMD_SEED, true, "seed", "random seed" } +#ifdef XWFEATURE_DEVID + ,{ CMD_DEVID, true, "devid", "device ID (for testing GCM stuff)" } +#endif ,{ CMD_GAMESEED, true, "game-seed", "game seed (for relay play)" } ,{ CMD_GAMEFILE, true, "file", "file to save to/read from" } ,{ CMD_SAVEFAIL_PCT, true, "savefail-pct", "How often, at random, does save fail?" } @@ -1585,6 +1591,9 @@ main( int argc, char** argv ) mainParams.allowPeek = XP_TRUE; mainParams.showRobotScores = XP_FALSE; mainParams.useMmap = XP_TRUE; +#ifdef XWFEATURE_DEVID + mainParams.devID = ""; +#endif char* envDictPath = getenv( "XW_DICTSPATH" ); if ( !!envDictPath ) { @@ -1670,6 +1679,11 @@ main( int argc, char** argv ) case CMD_SEED: seed = atoi(optarg); break; +#ifdef XWFEATURE_DEVID + case CMD_DEVID: + mainParams.devID = optarg; + break; +#endif case CMD_GAMESEED: mainParams.gameSeed = atoi(optarg); break; diff --git a/xwords4/linux/linuxutl.c b/xwords4/linux/linuxutl.c index 94c1cdcf1..12a997f7e 100644 --- a/xwords4/linux/linuxutl.c +++ b/xwords4/linux/linuxutl.c @@ -344,6 +344,16 @@ linux_util_getUserString( XW_UtilCtxt* XP_UNUSED(uc), XP_U16 code ) } } /* linux_util_getUserString */ +#ifdef XWFEATURE_DEVID +static const XP_UCHAR* +linux_util_getDevID( XW_UtilCtxt* uc, DevIDType* typ ) +{ + CommonGlobals* cGlobals = (CommonGlobals*)uc->closure; + *typ = ID_TYPE_LINUX; + return cGlobals->params->devID; +} +#endif + void linux_util_vt_init( MPFORMAL XW_UtilCtxt* util ) { @@ -353,6 +363,9 @@ linux_util_vt_init( MPFORMAL XW_UtilCtxt* util ) util->vtable->m_util_getSquareBonus = linux_util_getSquareBonus; util->vtable->m_util_getCurSeconds = linux_util_getCurSeconds; util->vtable->m_util_getUserString = linux_util_getUserString; +#ifdef XWFEATURE_DEVID + util->vtable->m_util_getDevID = linux_util_getDevID; +#endif } void diff --git a/xwords4/linux/main.h b/xwords4/linux/main.h index fd9b3bf70..985fd6f98 100644 --- a/xwords4/linux/main.h +++ b/xwords4/linux/main.h @@ -59,6 +59,9 @@ typedef struct LaunchParams { char* pipe; char* nbs; char* bonusFile; +#ifdef XWFEATURE_DEVID + char* devID; +#endif VTableMgr* vtMgr; XP_U16 nLocalPlayers; XP_U16 nHidden; diff --git a/xwords4/relay/cref.cpp b/xwords4/relay/cref.cpp index 5d22a4866..e2c63287b 100644 --- a/xwords4/relay/cref.cpp +++ b/xwords4/relay/cref.cpp @@ -179,7 +179,8 @@ CookieRef::Unlock() { } bool -CookieRef::_Connect( int socket, int clientVersion, int nPlayersH, int nPlayersS, int seed, +CookieRef::_Connect( int socket, int clientVersion, DevID* devID, + int nPlayersH, int nPlayersS, int seed, bool seenSeed, in_addr& addr ) { bool connected = false; @@ -199,7 +200,8 @@ CookieRef::_Connect( int socket, int clientVersion, int nPlayersH, int nPlayersS if ( !connected ) { set sockets = GetSockets(); if ( sockets.end() == sockets.find( socket ) ) { - pushConnectEvent( socket, clientVersion, nPlayersH, nPlayersS, seed, addr ); + pushConnectEvent( socket, clientVersion, devID, nPlayersH, + nPlayersS, seed, addr ); handleEvents(); connected = HasSocket_locked( socket ); } else { @@ -210,8 +212,8 @@ CookieRef::_Connect( int socket, int clientVersion, int nPlayersH, int nPlayersS } bool -CookieRef::_Reconnect( int socket, int clientVersion, HostID hid, - int nPlayersH, int nPlayersS, +CookieRef::_Reconnect( int socket, int clientVersion, DevID* devID, + HostID hid, int nPlayersH, int nPlayersS, int seed, in_addr& addr, bool gameDead ) { bool spotTaken = false; @@ -223,7 +225,8 @@ CookieRef::_Reconnect( int socket, int clientVersion, HostID hid, logf( XW_LOGINFO, "%s: dropping because already here", __func__ ); } else { - pushReconnectEvent( socket, clientVersion, hid, nPlayersH, nPlayersS, seed, addr ); + pushReconnectEvent( socket, clientVersion, devID, hid, nPlayersH, + nPlayersS, seed, addr ); } if ( gameDead ) { pushGameDead( socket ); @@ -243,7 +246,8 @@ CookieRef::_HandleAck( HostID hostID ) } void -CookieRef::_PutMsg( HostID srcID, in_addr& addr, HostID destID, unsigned char* buf, int buflen ) +CookieRef::_PutMsg( HostID srcID, in_addr& addr, HostID destID, + unsigned char* buf, int buflen ) { CRefEvent evt( XWE_PROXYMSG ); evt.u.fwd.src = srcID; @@ -513,13 +517,15 @@ CookieRef::_Remove( int socket ) } /* Forward */ void -CookieRef::pushConnectEvent( int socket, int clientVersion, int nPlayersH, int nPlayersS, +CookieRef::pushConnectEvent( int socket, int clientVersion, DevID* devID, + int nPlayersH, int nPlayersS, int seed, in_addr& addr ) { CRefEvent evt; evt.type = XWE_DEVCONNECT; evt.u.con.socket = socket; evt.u.con.clientVersion = clientVersion; + evt.u.con.devID = devID; evt.u.con.srcID = HOST_ID_NONE; evt.u.con.nPlayersH = nPlayersH; evt.u.con.nPlayersS = nPlayersS; @@ -529,13 +535,14 @@ CookieRef::pushConnectEvent( int socket, int clientVersion, int nPlayersH, int n } /* pushConnectEvent */ void -CookieRef::pushReconnectEvent( int socket, int clientVersion, HostID srcID, - int nPlayersH, int nPlayersS, int seed, - in_addr& addr ) +CookieRef::pushReconnectEvent( int socket, int clientVersion, DevID* devID, + HostID srcID, int nPlayersH, int nPlayersS, + int seed, in_addr& addr ) { CRefEvent evt( XWE_RECONNECT ); evt.u.con.socket = socket; evt.u.con.clientVersion = clientVersion; + evt.u.con.devID = devID; evt.u.con.srcID = srcID; evt.u.con.nPlayersH = nPlayersH; evt.u.con.nPlayersS = nPlayersS; @@ -879,7 +886,7 @@ CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp ) evt->u.con.srcID = DBMgr::Get()->AddDevice( ConnName(), evt->u.con.srcID, evt->u.con.clientVersion, nPlayersH, seed, - evt->u.con.addr, reconn ); + evt->u.con.addr, evt->u.con.devID, reconn ); HostID hostid = evt->u.con.srcID; if ( NULL != hidp ) { diff --git a/xwords4/relay/cref.h b/xwords4/relay/cref.h index d5949f82c..4581249b6 100644 --- a/xwords4/relay/cref.h +++ b/xwords4/relay/cref.h @@ -63,6 +63,13 @@ public: class CookieRef* m_this; }; +class DevID { + public: + DevID() { m_devIDType = 0; } + string m_devIDString; + unsigned char m_devIDType; +}; + class CookieRef { public: set GetSockets(); @@ -119,10 +126,11 @@ class CookieRef { static void Delete( CookieID cid ); static void Delete( const char* name ); - bool _Connect( int socket, int clientVersion, int nPlayersH, int nPlayersS, - int seed, bool seenSeed, in_addr& addr ); - bool _Reconnect( int socket, int clientVersion, HostID srcID, - int nPlayersH, int nPlayersS, + bool _Connect( int socket, int clientVersion, DevID* devID, + int nPlayersH, int nPlayersS, int seed, bool seenSeed, + in_addr& addr ); + bool _Reconnect( int socket, int clientVersion, DevID* devID, + HostID srcID, int nPlayersH, int nPlayersS, int seed, in_addr& addr, bool gameDead ); void _HandleAck( HostID hostID ); void _PutMsg( HostID srcID, in_addr& addr, HostID destID, unsigned char* buf, int buflen ); @@ -157,6 +165,7 @@ class CookieRef { struct { int socket; int clientVersion; + DevID* devID; int nPlayersH; int nPlayersS; int seed; @@ -195,10 +204,11 @@ class CookieRef { bool cascade ); void send_msg( int socket, HostID id, XWRelayMsg msg, XWREASON why, bool cascade ); - void pushConnectEvent( int socket, int clientVersion, int nPlayersH, int nPlayersS, + void pushConnectEvent( int socket, int clientVersion, DevID* devID, + int nPlayersH, int nPlayersS, int seed, in_addr& addr ); - void pushReconnectEvent( int socket, int clientVersion, HostID srcID, - int nPlayersH, int nPlayersS, + void pushReconnectEvent( int socket, int clientVersion, DevID* devID, + HostID srcID, int nPlayersH, int nPlayersS, int seed, in_addr& addr ); void pushHeartbeatEvent( HostID id, int socket ); void pushHeartFailedEvent( int socket ); diff --git a/xwords4/relay/crefmgr.cpp b/xwords4/relay/crefmgr.cpp index b7a18ba8b..f86288d93 100644 --- a/xwords4/relay/crefmgr.cpp +++ b/xwords4/relay/crefmgr.cpp @@ -590,12 +590,13 @@ CookieMapIterator::Next() /* connect case */ SafeCref::SafeCref( const char* cookie, int socket, int clientVersion, - int nPlayersH, int nPlayersS, + DevID* devID, int nPlayersH, int nPlayersS, unsigned short gameSeed, int langCode, bool wantsPublic, bool makePublic ) : m_cinfo( NULL ) , m_mgr( CRefMgr::Get() ) , m_clientVersion( clientVersion ) + , m_devID( devID ) , m_isValid( false ) , m_seenSeed( false ) { @@ -621,6 +622,7 @@ SafeCref::SafeCref( const char* connName, const char* cookie, HostID hid, : m_cinfo( NULL ) , m_mgr( CRefMgr::Get() ) , m_clientVersion( clientVersion ) + , m_devID( NULL ) , m_isValid( false ) { CidInfo* cinfo; diff --git a/xwords4/relay/crefmgr.h b/xwords4/relay/crefmgr.h index 138d76a8e..e605b88f0 100644 --- a/xwords4/relay/crefmgr.h +++ b/xwords4/relay/crefmgr.h @@ -172,7 +172,7 @@ class SafeCref { public: /* for connect */ SafeCref( const char* cookie, int socket, int clientVersion, - int nPlayersH, int nPlayersS, + DevID* devID, int nPlayersH, int nPlayersS, unsigned short gameSeed, int langCode, bool wantsPublic, bool makePublic ); /* for reconnect */ @@ -212,8 +212,8 @@ class SafeCref { if ( IsValid() ) { CookieRef* cref = m_cinfo->GetRef(); assert( 0 != cref->GetCid() ); - return cref->_Connect( socket, m_clientVersion, nPlayersH, - nPlayersS, seed, + return cref->_Connect( socket, m_clientVersion, m_devID, + nPlayersH, nPlayersS, seed, m_seenSeed, addr ); } else { return false; @@ -229,9 +229,9 @@ class SafeCref { if ( m_dead ) { *errp = XWRELAY_ERROR_DEADGAME; } else { - success = cref->_Reconnect( socket, m_clientVersion, srcID, - nPlayersH, nPlayersS, seed, addr, - m_dead ); + success = cref->_Reconnect( socket, m_clientVersion, m_devID, + srcID, nPlayersH, nPlayersS, seed, + addr, m_dead ); } } return success; @@ -391,6 +391,7 @@ class SafeCref { CidInfo* m_cinfo; CRefMgr* m_mgr; int m_clientVersion; + DevID* m_devID; bool m_isValid; bool m_locked; bool m_dead; diff --git a/xwords4/relay/dbmgr.cpp b/xwords4/relay/dbmgr.cpp index 57d1dc9ee..c03ff070f 100644 --- a/xwords4/relay/dbmgr.cpp +++ b/xwords4/relay/dbmgr.cpp @@ -244,8 +244,9 @@ DBMgr::AllDevsAckd( const char* const connName ) } HostID -DBMgr::AddDevice( const char* connName, HostID curID, int clientVersion, int nToAdd, - unsigned short seed, const in_addr& addr, bool ackd ) +DBMgr::AddDevice( const char* connName, HostID curID, int clientVersion, + int nToAdd, unsigned short seed, const in_addr& addr, + const DevID* devID, bool ackd ) { HostID newID = curID; @@ -260,14 +261,23 @@ DBMgr::AddDevice( const char* connName, HostID curID, int clientVersion, int nTo } assert( newID <= 4 ); + char devIDBuf[512] = {0}; + if ( !!devID ) { + snprintf( devIDBuf, sizeof(devIDBuf), + "devids[%d] = \'%s\', devTypes[%d] = %d,", + newID, devID->m_devIDString.c_str(), + newID, devID->m_devIDType ); + } + const char* fmt = "UPDATE " GAMES_TABLE " SET nPerDevice[%d] = %d," " clntVers[%d] = %d," - " seeds[%d] = %d, addrs[%d] = \'%s\', mtimes[%d]='now', ack[%d]=\'%c\'" + " seeds[%d] = %d, addrs[%d] = \'%s\', %s" + " mtimes[%d]='now', ack[%d]=\'%c\'" " WHERE connName = '%s'"; - char query[256]; + char query[1024]; snprintf( query, sizeof(query), fmt, newID, nToAdd, newID, clientVersion, - newID, seed, newID, inet_ntoa(addr), newID, - newID, ackd?'A':'a', connName ); + newID, seed, newID, inet_ntoa(addr), devIDBuf, + newID, newID, ackd?'A':'a', connName ); logf( XW_LOGINFO, "%s: query: %s", __func__, query ); execSql( query ); @@ -437,7 +447,8 @@ DBMgr::RecordSent( const int* msgIDs, int nMsgIDs ) } void -DBMgr::RecordAddress( const char* const connName, HostID hid, const in_addr& addr ) +DBMgr::RecordAddress( const char* const connName, HostID hid, + const in_addr& addr ) { assert( hid >= 0 && hid <= 4 ); const char* fmt = "UPDATE " GAMES_TABLE " SET addrs[%d] = \'%s\'" @@ -558,6 +569,22 @@ DBMgr::readArray( const char* const connName, int arr[] ) /* len 4 */ PQclear( result ); } +void +DBMgr::getDevID( const char* connName, int hid, DevID& devID ) +{ + const char* fmt = "SELECT devids[%d], devTypes[%d] FROM " GAMES_TABLE " WHERE connName='%s'"; + char query[256]; + snprintf( query, sizeof(query), fmt, hid, hid, connName ); + logf( XW_LOGINFO, "%s: query: %s", __func__, query ); + + PGresult* result = PQexec( getThreadConn(), query ); + assert( 1 == PQntuples( result ) ); + devID.m_devIDString = PQgetvalue( result, 0, 0 ); + devID.m_devIDType = (unsigned char)atoi( PQgetvalue( result, 0, 1 ) ); + assert( devID.m_devIDType <= 2 ); // for now!!! + PQclear( result ); +} + /* id | connname | hid | msg ----+-----------+-----+--------- @@ -598,16 +625,20 @@ void DBMgr::StoreMessage( const char* const connName, int hid, const unsigned char* buf, int len ) { + DevID devID; + getDevID( connName, hid, devID ); + size_t newLen; - const char* fmt = "INSERT INTO " MSGS_TABLE " (connname, hid, msg, msglen)" - " VALUES( '%s', %d, E'%s', %d)"; + const char* fmt = "INSERT INTO " MSGS_TABLE " (connname, hid, devid, devType, msg, msglen)" + " VALUES( '%s', %d, '%s', %d, E'%s', %d)"; unsigned char* bytes = PQescapeByteaConn( getThreadConn(), buf, len, &newLen ); assert( NULL != bytes ); char query[newLen+128]; unsigned int siz = snprintf( query, sizeof(query), fmt, connName, hid, - bytes, len ); + devID.m_devIDString.c_str(), + devID.m_devIDType, bytes, len ); logf( XW_LOGINFO, "%s: query: %s", __func__, query ); PQfreemem( bytes ); assert( siz < sizeof(query) ); diff --git a/xwords4/relay/dbmgr.h b/xwords4/relay/dbmgr.h index 3dbe226b6..035d150f3 100644 --- a/xwords4/relay/dbmgr.h +++ b/xwords4/relay/dbmgr.h @@ -26,6 +26,7 @@ #include "xwrelay.h" #include "xwrelay_priv.h" +#include "cref.h" #include using namespace std; @@ -56,7 +57,8 @@ class DBMgr { bool AllDevsAckd( const char* const connName ); HostID AddDevice( const char* const connName, HostID curID, int clientVersion, - int nToAdd, unsigned short seed, const in_addr& addr, bool unAckd ); + int nToAdd, unsigned short seed, const in_addr& addr, + const DevID* devID, bool unAckd ); void NoteAckd( const char* const connName, HostID id ); HostID HIDForSeed( const char* const connName, unsigned short seed ); bool RmDeviceByHid( const char* const connName, HostID id ); @@ -97,6 +99,7 @@ class DBMgr { DBMgr(); bool execSql( const char* const query ); /* no-results query */ void readArray( const char* const connName, int arr[] ); + void getDevID( const char* connName, int hid, DevID& devID ); PGconn* getThreadConn( void ); diff --git a/xwords4/relay/scripts/showinplay.sh b/xwords4/relay/scripts/showinplay.sh index 9085a54ec..fcd926934 100755 --- a/xwords4/relay/scripts/showinplay.sh +++ b/xwords4/relay/scripts/showinplay.sh @@ -26,12 +26,12 @@ QUERY="WHERE NOT -NTOTAL = sum_array(nperdevice)" echo "Device (pid) count: $(pidof xwords | wc | awk '{print $2}')" echo "Row count:" $(psql -t xwgames -c "select count(*) FROM games $QUERY;") -echo "SELECT dead,connname,cid,room,lang,clntVers,ntotal,nperdevice,seeds,ack,nsent "\ +echo "SELECT dead,connname,cid,room,lang,clntVers,ntotal,nperdevice,seeds,devTypes,devids,ack,nsent "\ "FROM games $QUERY ORDER BY NOT dead, connname LIMIT $LIMIT;" \ | psql xwgames -echo "SELECT connname, hid, count(*), sum(msglen) "\ +echo "SELECT connname, hid, devType, devid, count(*), sum(msglen) "\ "FROM msgs where connname in (SELECT connname from games where not games.dead group by connname)" \ - "GROUP BY connname, hid ORDER BY connname;" \ + "GROUP BY connname, hid, devType, devid ORDER BY connname;" \ | psql xwgames diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp index 563846f80..fb6ceac40 100644 --- a/xwords4/relay/xwrelay.cpp +++ b/xwords4/relay/xwrelay.cpp @@ -228,6 +228,20 @@ getNetByte( unsigned char** bufpp, const unsigned char* end, return ok; } /* getNetByte */ +static bool +getNetString( unsigned char** bufpp, const unsigned char* end, string& out ) +{ + char* str = (char*)*bufpp; + size_t len = 1 + strlen( str ); + bool success = str + len <= (char*)end; + if ( success ) { + out = str; + *bufpp += len; + } + // logf( XW_LOGERROR, "%s => %d", __func__, out.c_str() ); + return success; +} + #ifdef RELAY_HEARTBEAT static bool processHeartbeat( unsigned char* buf, int bufLen, int socket ) @@ -268,12 +282,14 @@ readStr( unsigned char** bufp, const unsigned char* end, static XWREASON flagsOK( unsigned char** bufp, unsigned char const* end, - unsigned short* clientVersion ) + unsigned short* clientVersion, unsigned short* flagsp ) { XWREASON err = XWRELAY_ERROR_OLDFLAGS; unsigned char flags; if ( getNetByte( bufp, end, &flags ) ) { + *flagsp = flags; switch ( flags ) { + case XWRELAY_PROTO_VERSION_CLIENTID: case XWRELAY_PROTO_VERSION_CLIENTVERS: if ( getNetShort( bufp, end, clientVersion ) ) { err = XWRELAY_ERROR_NONE; @@ -346,7 +362,8 @@ processConnect( unsigned char* bufp, int bufLen, int socket, in_addr& addr ) cookie[0] = '\0'; unsigned short clientVersion; - XWREASON err = flagsOK( &bufp, end, &clientVersion ); + unsigned short flags; + XWREASON err = flagsOK( &bufp, end, &clientVersion, &flags ); if ( err == XWRELAY_ERROR_NONE ) { /* HostID srcID; */ unsigned char nPlayersH; @@ -362,6 +379,17 @@ processConnect( unsigned char* bufp, int bufLen, int socket, in_addr& addr ) && getNetByte( &bufp, end, &nPlayersT ) && getNetShort( &bufp, end, &seed ) && getNetByte( &bufp, end, &langCode ) ) { + + DevID devID; + if ( XWRELAY_PROTO_VERSION_CLIENTID <= flags ) { + unsigned char devIDType = 0; + if ( getNetByte( &bufp, end, &devIDType ) + && 0 != devIDType ) { + getNetString( &bufp, end, devID.m_devIDString ); + devID.m_devIDType = devIDType; + } + } + logf( XW_LOGINFO, "%s(): langCode=%d; nPlayersT=%d; " "wantsPublic=%d; seed=%.4X", __func__, langCode, nPlayersT, wantsPublic, seed ); @@ -371,8 +399,9 @@ processConnect( unsigned char* bufp, int bufLen, int socket, in_addr& addr ) static pthread_mutex_t s_newCookieLock = PTHREAD_MUTEX_INITIALIZER; MutexLock ml( &s_newCookieLock ); - SafeCref scr( cookie, socket, clientVersion, nPlayersH, nPlayersT, - seed, langCode, wantsPublic, makePublic ); + SafeCref scr( cookie, socket, clientVersion, &devID, + nPlayersH, nPlayersT, seed, langCode, + wantsPublic, makePublic ); /* nPlayersT etc could be slots in SafeCref to avoid passing here */ success = scr.Connect( socket, nPlayersH, nPlayersT, seed, addr ); @@ -396,7 +425,8 @@ processReconnect( unsigned char* bufp, int bufLen, int socket, in_addr& addr ) logf( XW_LOGINFO, "%s()", __func__ ); unsigned short clientVersion; - XWREASON err = flagsOK( &bufp, end, &clientVersion ); + unsigned short flags; + XWREASON err = flagsOK( &bufp, end, &clientVersion, &flags ); if ( err == XWRELAY_ERROR_NONE ) { char cookie[MAX_INVITE_LEN+1]; char connName[MAX_CONNNAME_LEN+1] = {0}; diff --git a/xwords4/relay/xwrelay.h b/xwords4/relay/xwrelay.h index 312bf2b7c..cdda995dd 100644 --- a/xwords4/relay/xwrelay.h +++ b/xwords4/relay/xwrelay.h @@ -121,6 +121,7 @@ typedef unsigned char XWRELAY_Cmd; #define XWRELAY_PROTO_VERSION_LATE_COOKIEID 0x03 #define XWRELAY_PROTO_VERSION_NOCLIENT 0x04 #define XWRELAY_PROTO_VERSION_CLIENTVERS 0x05 +#define XWRELAY_PROTO_VERSION_CLIENTID 0x06 #define XWRELAY_PROTO_VERSION XWRELAY_PROTO_VERSION_CLIENTVERS /* Errors passed with denied */ diff --git a/xwords4/relay/xwrelay.sh b/xwords4/relay/xwrelay.sh index d8b729a31..e25b5ba90 100755 --- a/xwords4/relay/xwrelay.sh +++ b/xwords4/relay/xwrelay.sh @@ -58,6 +58,8 @@ cid integer ,ctime TIMESTAMP (0) DEFAULT CURRENT_TIMESTAMP ,mtimes TIMESTAMP(0)[] ,addrs INET[] +,devTypes INTEGER[] +,devids TEXT[] ); EOF @@ -67,6 +69,8 @@ id SERIAL ,connName VARCHAR(64) ,hid INTEGER ,ctime TIMESTAMP DEFAULT CURRENT_TIMESTAMP +,devType INTEGER +,devid TEXT ,msg BYTEA ,msglen INTEGER ,UNIQUE ( connName, hid, msg )