diff --git a/xwords4/relay/crefmgr.cpp b/xwords4/relay/crefmgr.cpp index 43d09b618..882f0eb27 100644 --- a/xwords4/relay/crefmgr.cpp +++ b/xwords4/relay/crefmgr.cpp @@ -375,6 +375,48 @@ CRefMgr::getMakeCookieRef( const char* const connName, HostID hid, bool* isDead return cinfo; } +CidInfo* +CRefMgr::getMakeCookieRef( const AddrInfo::ClientToken clientToken, HostID srcID ) +{ + CookieRef* cref = NULL; + CidInfo* cinfo = NULL; + char curCookie[MAX_INVITE_LEN+1]; + int curLangCode; + int nPlayersT = 0; + int nAlreadyHere = 0; + + for ( ; ; ) { /* for: see comment above */ + char connName[MAX_CONNNAME_LEN+1] = {0}; + CookieID cid = m_db->FindGame( clientToken, srcID, + connName, sizeof(connName), + curCookie, sizeof(curCookie), + &curLangCode, &nPlayersT, &nAlreadyHere ); + // &seed ); + if ( 0 != cid ) { /* already open */ + cinfo = m_cidlock->Claim( cid ); + if ( NULL == cinfo->GetRef() ) { + m_cidlock->Relinquish( cinfo, true ); + continue; + } + } else if ( nPlayersT == 0 ) { /* wasn't in the DB */ + /* do nothing; insufficient info to fake it */ + } else { + cinfo = m_cidlock->Claim(); + if ( !m_db->AddCID( connName, cinfo->GetCid() ) ) { + m_cidlock->Relinquish( cinfo, true ); + continue; + } + logf( XW_LOGINFO, "%s(): added cid???", __func__ ); + cref = AddNew( curCookie, connName, cinfo->GetCid(), curLangCode, + nPlayersT, nAlreadyHere ); + cinfo->SetRef( cref ); + } + break; + } + logf( XW_LOGINFO, "%s() => %p", __func__, cinfo ); + return cinfo; +} + void CRefMgr::RemoveSocketRefs( const AddrInfo* addr ) { @@ -722,6 +764,19 @@ SafeCref::SafeCref( const AddrInfo* addr ) } } +SafeCref::SafeCref( const AddrInfo::ClientToken clientToken, HostID srcID ) + : m_cinfo( NULL ) + , m_mgr( CRefMgr::Get() ) + , m_isValid( false ) +{ + CidInfo* cinfo = m_mgr->getMakeCookieRef( clientToken, srcID ); + if ( NULL != cinfo && NULL != cinfo->GetRef() ) { + m_locked = cinfo->GetRef()->Lock(); + m_cinfo = cinfo; + m_isValid = true; + } +} + SafeCref::~SafeCref() { if ( m_cinfo != NULL ) { diff --git a/xwords4/relay/crefmgr.h b/xwords4/relay/crefmgr.h index 809dea796..7694759dd 100644 --- a/xwords4/relay/crefmgr.h +++ b/xwords4/relay/crefmgr.h @@ -129,6 +129,7 @@ class CRefMgr { bool isPublic, bool* isDead ); CidInfo* getMakeCookieRef( const char* const connName, HostID hid, bool* isDead ); + CidInfo* getMakeCookieRef( const AddrInfo::ClientToken clientToken, HostID srcID ); CidInfo* getCookieRef( CookieID cid, bool failOk = false ); CidInfo* getCookieRef( const AddrInfo* addr ); @@ -182,6 +183,7 @@ class SafeCref { SafeCref( const char* const connName, HostID hid ); SafeCref( CookieID cid, bool failOk = false ); SafeCref( const AddrInfo* addr ); + SafeCref( const AddrInfo::ClientToken clientToken, HostID srcID ); /* SafeCref( CookieRef* cref ); */ ~SafeCref(); diff --git a/xwords4/relay/dbmgr.cpp b/xwords4/relay/dbmgr.cpp index 47f5da3c8..eb55898cd 100644 --- a/xwords4/relay/dbmgr.cpp +++ b/xwords4/relay/dbmgr.cpp @@ -185,6 +185,41 @@ DBMgr::FindGame( const char* connName, HostID hid, char* roomBuf, int roomBufLen return cid; } /* FindGame */ +CookieID +DBMgr::FindGame( const AddrInfo::ClientToken clientToken, HostID hid, + char* connNameBuf, int connNameBufLen, + char* roomBuf, int roomBufLen, + int* langP, int* nPlayersTP, int* nPlayersHP ) +{ + CookieID cid = 0; + const char* fmt = "SELECT room, lang, nTotal, nPerDevice[%d], connname FROM " + GAMES_TABLE " WHERE tokens[%d] = %d and NOT dead"; + // " LIMIT 1" + ; + StrWPF query; + query.catf( fmt, hid, hid, clientToken ); + logf( XW_LOGINFO, "query: %s", query.c_str() ); + + PGresult* result = PQexec( getThreadConn(), query.c_str() ); + assert( 1 >= PQntuples( result ) ); + if ( 1 == PQntuples( result ) ) { + int col = 0; + // room + snprintf( roomBuf, roomBufLen, "%s", PQgetvalue( result, 0, col++ ) ); + // lang + *langP = atoi( PQgetvalue( result, 0, col++ ) ); + *nPlayersTP = atoi( PQgetvalue( result, 0, col++ ) ); + *nPlayersHP = atoi( PQgetvalue( result, 0, col++ ) ); + snprintf( connNameBuf, connNameBufLen, "%s", PQgetvalue( result, 0, col++ ) ); + cid = GetCIDImpl(connNameBuf); + } + PQclear( result ); + + logf( XW_LOGINFO, "%s(ct=%d,hid=%d) => %d (connname=%s)", __func__, clientToken, + hid, cid, connNameBuf ); + return cid; +} + bool DBMgr::FindPlayer( DevIDRelay relayID, AddrInfo::ClientToken token, string& connName, HostID* hidp, unsigned short* seed ) diff --git a/xwords4/relay/dbmgr.h b/xwords4/relay/dbmgr.h index 643096057..1185b7d7c 100644 --- a/xwords4/relay/dbmgr.h +++ b/xwords4/relay/dbmgr.h @@ -76,6 +76,10 @@ class DBMgr { CookieID FindGame( const char* connName, HostID hid, char* cookieBuf, int bufLen, int* langP, int* nPlayersTP, int* nPlayersHP, bool* isDead ); + CookieID FindGame( const AddrInfo::ClientToken clientToken, HostID hid, + char* connNameBuf, int connNameBufLen, + char* cookieBuf, int cookieBufLen, + int* langP, int* nPlayersTP, int* nPlayersHP ); bool FindGameFor( const char* connName, char* cookieBuf, int bufLen, unsigned short seed, HostID hid, diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp index d17da9c06..2bfcfc017 100644 --- a/xwords4/relay/xwrelay.cpp +++ b/xwords4/relay/xwrelay.cpp @@ -996,13 +996,13 @@ processReconnect( const uint8_t* bufp, int bufLen, const AddrInfo* addr ) } /* processReconnect */ static bool -processAck( const uint8_t* bufp, int bufLen, const AddrInfo* addr ) +processAck( const uint8_t* bufp, int bufLen, AddrInfo::ClientToken clientToken ) { bool success = false; const uint8_t* end = bufp + bufLen; HostID srcID; if ( getNetByte( &bufp, end, &srcID ) ) { - SafeCref scr( addr ); + SafeCref scr( clientToken, srcID ); success = scr.HandleAck( srcID ); } return success; @@ -1092,7 +1092,8 @@ forwardMessage( const uint8_t* buf, int buflen, const AddrInfo* addr ) } /* forwardMessage */ static bool -processMessage( const uint8_t* buf, int bufLen, const AddrInfo* addr ) +processMessage( const uint8_t* buf, int bufLen, const AddrInfo* addr, + AddrInfo::ClientToken clientToken ) { bool success = false; /* default is failure */ XWRELAY_Cmd cmd = *buf; @@ -1107,7 +1108,11 @@ processMessage( const uint8_t* buf, int bufLen, const AddrInfo* addr ) success = processReconnect( buf+1, bufLen-1, addr ); break; case XWRELAY_ACK: - success = processAck( buf+1, bufLen-1, addr ); + if ( clientToken != 0 ) { + success = processAck( buf+1, bufLen-1, clientToken ); + } else { + logf( XW_LOGERROR, "%s(): null client token", __func__ ); + } break; case XWRELAY_GAME_DISCONNECT: success = processDisconnect( buf+1, bufLen-1, addr ); @@ -1468,7 +1473,7 @@ handleProxyMsgs( int sock, const AddrInfo* addr, const uint8_t* bufp, static void game_thread_proc( UdpThreadClosure* utc ) { - if ( !processMessage( utc->buf(), utc->len(), utc->addr() ) ) { + if ( !processMessage( utc->buf(), utc->len(), utc->addr(), 0 ) ) { XWThreadPool::GetTPool()->CloseSocket( utc->addr() ); } } @@ -1756,7 +1761,7 @@ handle_udp_packet( UdpThreadClosure* utc ) clientToken = ntohl( clientToken ); if ( AddrInfo::NULL_TOKEN != clientToken ) { AddrInfo addr( g_udpsock, clientToken, utc->saddr() ); - (void)processMessage( ptr, end - ptr, &addr ); + (void)processMessage( ptr, end - ptr, &addr, clientToken ); } else { logf( XW_LOGERROR, "%s: dropping packet with token of 0", __func__ );