mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-28 07:58:08 +01:00
major mod to deal with devices that fail to receive ACK and then
reconnect. I was putting both (i.e. the same device twice) in the same game. Now I detect this based on the seed being duplicated and treat the device as having failed to ACK then proceed with the CONNECT as if it were new. Tested pretty heavily but only with two-device games.
This commit is contained in:
parent
44af266db6
commit
85d484a881
9 changed files with 333 additions and 134 deletions
|
@ -86,14 +86,13 @@ CookieRef::ReInit( const char* cookie, const char* connName, CookieID id,
|
|||
m_cookie = cookie==NULL?"":cookie;
|
||||
m_connName = connName==NULL?"":connName;
|
||||
m_cookieID = id;
|
||||
m_curState = XWS_INITED;
|
||||
m_curState = XWS_EMPTY;
|
||||
m_nPlayersSought = nPlayers;
|
||||
m_nPlayersHere = nAlreadyHere;
|
||||
m_locking_thread = 0;
|
||||
m_starttime = uptime();
|
||||
m_in_handleEvents = false;
|
||||
m_langCode = langCode;
|
||||
m_nPendingAcks = 0;
|
||||
|
||||
if ( RelayConfigs::GetConfigs()->GetValueFor( "SEND_DELAY_MILLIS",
|
||||
&m_delayMicros ) ) {
|
||||
|
@ -104,8 +103,13 @@ CookieRef::ReInit( const char* cookie, const char* connName, CookieID id,
|
|||
RelayConfigs::GetConfigs()->GetValueFor( "HEARTBEAT", &m_heatbeat );
|
||||
logf( XW_LOGINFO, "initing cref for cookie %s, connName %s",
|
||||
m_cookie.c_str(), m_connName.c_str() );
|
||||
}
|
||||
|
||||
unsigned int ii;
|
||||
for ( ii = 0; ii < sizeof(m_timers)/sizeof(m_timers[0]); ++ii ) {
|
||||
m_timers[ii].m_this = NULL;
|
||||
m_timers[ii].m_hid = ii + 1;
|
||||
}
|
||||
}
|
||||
|
||||
CookieRef::CookieRef( const char* cookie, const char* connName, CookieID id,
|
||||
int langCode, int nPlayersT, int nAlreadyHere )
|
||||
|
@ -176,19 +180,31 @@ CookieRef::Unlock() {
|
|||
}
|
||||
|
||||
bool
|
||||
CookieRef::_Connect( int socket, int nPlayersH, int nPlayersS, int seed )
|
||||
CookieRef::_Connect( int socket, int nPlayersH, int nPlayersS, int seed,
|
||||
bool seenSeed )
|
||||
{
|
||||
bool connected = false;
|
||||
if ( AlreadyHere( seed, socket ) ) {
|
||||
connected = true; /* but drop the packet */
|
||||
/* } else if ( AlreadyHere( seed, -1 ) ) { */
|
||||
/* dupe packet on different socket; need host record */
|
||||
} else if ( CRefMgr::Get()->Associate( socket, this ) ) {
|
||||
pushConnectEvent( socket, nPlayersH, nPlayersS, seed );
|
||||
handleEvents();
|
||||
connected = HasSocket_locked( socket );
|
||||
} else {
|
||||
logf( XW_LOGINFO, "dropping connect event; already connected" );
|
||||
HostID prevHostID = HOST_ID_NONE;
|
||||
bool alreadyHere = AlreadyHere( seed, socket, &prevHostID );
|
||||
|
||||
if ( alreadyHere ) {
|
||||
if ( seenSeed ) { /* we need to get rid of the current entry, then
|
||||
proceed as if this were a new connection */
|
||||
assert( HOST_ID_NONE != prevHostID );
|
||||
postDropDevice( prevHostID );
|
||||
} else {
|
||||
connected = true; /* but drop the packet */
|
||||
}
|
||||
}
|
||||
|
||||
if ( !connected ) {
|
||||
if ( CRefMgr::Get()->Associate( socket, this ) ) {
|
||||
pushConnectEvent( socket, nPlayersH, nPlayersS, seed );
|
||||
handleEvents();
|
||||
connected = HasSocket_locked( socket );
|
||||
} else {
|
||||
logf( XW_LOGINFO, "dropping connect event; already connected" );
|
||||
}
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
@ -212,7 +228,6 @@ CookieRef::_Reconnect( int socket, HostID hid, int nPlayersH, int nPlayersS,
|
|||
void
|
||||
CookieRef::_HandleAck( HostID hostID )
|
||||
{
|
||||
assert( m_nPendingAcks > 0 && m_nPendingAcks <= 4 );
|
||||
CRefEvent evt( XWE_GOTONEACK );
|
||||
evt.u.ack.srcID = hostID;
|
||||
m_eventQueue.push_back( evt );
|
||||
|
@ -288,22 +303,19 @@ CookieRef::SocketForHost( HostID dest )
|
|||
}
|
||||
|
||||
bool
|
||||
CookieRef::AlreadyHere( unsigned short seed, int socket )
|
||||
CookieRef::AlreadyHere( unsigned short seed, int socket, HostID* prevHostID )
|
||||
{
|
||||
logf( XW_LOGINFO, "%s(seed=%x,socket=%d)", __func__, seed, socket );
|
||||
bool here = false;
|
||||
|
||||
vector<HostRec>::iterator iter;
|
||||
for ( iter = m_sockets.begin(); iter != m_sockets.end(); ++iter ) {
|
||||
if ( iter->m_seed == seed ) { /* client already registered */
|
||||
if ( iter->m_socket == socket ) {
|
||||
/* dup packet */
|
||||
here = true;
|
||||
} else {
|
||||
logf( XW_LOGINFO, "%s: seeds match; nuking existing record"
|
||||
" for socket %d b/c assumed closed", __func__,
|
||||
iter->m_socket );
|
||||
m_sockets.erase( iter );
|
||||
here = iter->m_seed == seed; /* client already registered */
|
||||
if ( here ) {
|
||||
if ( iter->m_socket != socket ) { /* not just a dupe packet */
|
||||
logf( XW_LOGINFO, "%s: seeds match; socket %d assumed closed",
|
||||
__func__, iter->m_socket );
|
||||
*prevHostID = iter->m_hostID;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -370,11 +382,10 @@ CookieRef::removeSocket( int socket )
|
|||
if ( iter->m_socket == socket ) {
|
||||
if ( iter->m_ackPending ) {
|
||||
logf( XW_LOGINFO,
|
||||
"Never got ack; removing %d players from DB",
|
||||
iter->m_nPlayersH );
|
||||
DBMgr::Get()->RmDevice( ConnName(), iter->m_hostID );
|
||||
"Never got ack; removing hid %d from DB",
|
||||
iter->m_hostID );
|
||||
DBMgr::Get()->RmDeviceByHid( ConnName(), iter->m_hostID );
|
||||
m_nPlayersHere -= iter->m_nPlayersH;
|
||||
--m_nPendingAcks;
|
||||
}
|
||||
m_sockets.erase(iter);
|
||||
--count;
|
||||
|
@ -577,22 +588,24 @@ CookieRef::handleEvents()
|
|||
|
||||
switch( takeAction ) {
|
||||
|
||||
case XWA_SEND_CONNRSP:
|
||||
if ( increasePlayerCounts( &evt, false ) ) {
|
||||
setAllConnectedTimer();
|
||||
sendResponse( &evt, takeAction != XWA_SEND_1ST_RERSP );
|
||||
setAckTimer();
|
||||
case XWA_SEND_CONNRSP:
|
||||
{
|
||||
HostID hid;
|
||||
if ( increasePlayerCounts( &evt, false, &hid ) ) {
|
||||
setAllConnectedTimer();
|
||||
sendResponse( &evt, takeAction != XWA_SEND_1ST_RERSP );
|
||||
setAckTimer( hid );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XWA_NOTEACKCHECK:
|
||||
case XWA_NOTEACK:
|
||||
modPending( &evt, true );
|
||||
updateAck( evt.u.ack.srcID, true );
|
||||
postCheckAllHere();
|
||||
break;
|
||||
|
||||
case XWA_DROPDEVICE:
|
||||
modPending( &evt, false );
|
||||
updateAck( evt.u.ack.srcID, false );
|
||||
break;
|
||||
|
||||
/* case XWA_SEND_1ST_RERSP: */
|
||||
|
@ -603,7 +616,7 @@ CookieRef::handleEvents()
|
|||
/* break; */
|
||||
|
||||
case XWA_SEND_RERSP:
|
||||
increasePlayerCounts( &evt, true );
|
||||
increasePlayerCounts( &evt, true, NULL );
|
||||
sendResponse( &evt, false );
|
||||
sendAnyStored( &evt );
|
||||
postCheckAllHere();
|
||||
|
@ -708,6 +721,16 @@ CookieRef::handleEvents()
|
|||
}
|
||||
|
||||
m_curState = nextState;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( XWS_EMPTY == m_curState ) {
|
||||
assert( 0 == m_sockets.size() );
|
||||
|
||||
int nTotal, nHere;
|
||||
GetPlayerCounts( ConnName(), &nTotal, &nHere );
|
||||
assert( 0 == nHere );
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
logf( XW_LOGERROR, "Killing cref b/c unable to find transition "
|
||||
"from %s on event %s", stateString(m_curState),
|
||||
|
@ -779,7 +802,7 @@ CookieRef::send_stored_messages( HostID dest, int socket )
|
|||
} /* send_stored_messages */
|
||||
|
||||
bool
|
||||
CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn )
|
||||
CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp )
|
||||
{
|
||||
int nPlayersH = evt->u.con.nPlayersH;
|
||||
int socket = evt->u.con.socket;
|
||||
|
@ -808,9 +831,12 @@ CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn )
|
|||
}
|
||||
|
||||
evt->u.con.srcID = DBMgr::Get()->AddDevice( ConnName(), evt->u.con.srcID,
|
||||
nPlayersH, seed );
|
||||
nPlayersH, seed, reconn );
|
||||
|
||||
HostID hostid = evt->u.con.srcID;
|
||||
if ( NULL != hidp ) {
|
||||
*hidp = hostid;
|
||||
}
|
||||
|
||||
/* first add the rec here, whether it'll get ack'd or not */
|
||||
logf( XW_LOGINFO, "%s: remembering pair: hostid=%x, "
|
||||
|
@ -831,36 +857,53 @@ CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn )
|
|||
} /* increasePlayerCounts */
|
||||
|
||||
void
|
||||
CookieRef::modPending( const CRefEvent* evt, bool keep )
|
||||
CookieRef::updateAck( HostID hostID, bool keep )
|
||||
{
|
||||
HostID hostID = evt->u.ack.srcID;
|
||||
assert( hostID >= HOST_ID_SERVER );
|
||||
assert( hostID <= 4 );
|
||||
int socket = 0;
|
||||
|
||||
cancelAckTimer( hostID );
|
||||
|
||||
vector<HostRec>::iterator iter;
|
||||
for ( iter = m_sockets.begin(); iter != m_sockets.end(); ++iter ) {
|
||||
if ( iter->m_ackPending && iter->m_hostID == hostID ) {
|
||||
--m_nPendingAcks;
|
||||
|
||||
if ( keep ) {
|
||||
iter->m_ackPending = false;
|
||||
DBMgr::Get()->NoteAckd( ConnName(), hostID );
|
||||
} else {
|
||||
DBMgr::Get()->RmDevice( ConnName(), iter->m_hostID );
|
||||
m_sockets.erase( iter );
|
||||
socket = iter->m_socket;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( 0 != socket ) {
|
||||
removeSocket( socket );
|
||||
}
|
||||
|
||||
printSeeds(__func__);
|
||||
}
|
||||
|
||||
void
|
||||
CookieRef::postCheckAllHere()
|
||||
{
|
||||
if ( m_nPendingAcks == 0 && DBMgr::Get()->GameFull( ConnName() ) ) {
|
||||
/* && m_nPlayersHere == m_nPlayersSought ) { /\* complete! *\/ */
|
||||
if ( DBMgr::Get()->AllDevsAckd( ConnName() ) ) {
|
||||
CRefEvent evt( XWE_ALLHERE );
|
||||
m_eventQueue.push_back( evt );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CookieRef::postDropDevice( HostID hostID )
|
||||
{
|
||||
CRefEvent evt( XWE_ACKTIMEOUT );
|
||||
evt.u.ack.srcID = hostID;
|
||||
m_eventQueue.push_back( evt );
|
||||
handleEvents();
|
||||
}
|
||||
|
||||
void
|
||||
CookieRef::setAllConnectedTimer()
|
||||
{
|
||||
|
@ -872,23 +915,39 @@ CookieRef::setAllConnectedTimer()
|
|||
}
|
||||
|
||||
void
|
||||
CookieRef::setAckTimer( void )
|
||||
CookieRef::setAckTimer( HostID hid )
|
||||
{
|
||||
logf( XW_LOGINFO, "%s()", __func__ );
|
||||
ASSERT_LOCKED();
|
||||
logf( XW_LOGINFO, "%s(%d)", __func__, hid );
|
||||
|
||||
assert( hid >= HOST_ID_SERVER );
|
||||
assert( hid <= 4 );
|
||||
--hid;
|
||||
|
||||
assert( NULL == m_timers[hid].m_this );
|
||||
m_timers[hid].m_this = this;
|
||||
|
||||
time_t inHowLong;
|
||||
if ( RelayConfigs::GetConfigs()->GetValueFor( "DEVACK", &inHowLong ) ) {
|
||||
TimerMgr::GetTimerMgr()->SetTimer( inHowLong,
|
||||
s_checkAck, this, 0 );
|
||||
++m_nPendingAcks;
|
||||
s_checkAck, &m_timers[hid], 0 );
|
||||
} else {
|
||||
logf( XW_LOGINFO, "not setting timer" );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CookieRef::cancelAckTimer( void )
|
||||
CookieRef::cancelAckTimer( HostID hid )
|
||||
{
|
||||
TimerMgr::GetTimerMgr()->ClearTimer( s_checkAck, this );
|
||||
ASSERT_LOCKED();
|
||||
logf( XW_LOGINFO, "%s(%d)", __func__, hid );
|
||||
|
||||
assert( hid >= HOST_ID_SERVER );
|
||||
assert( hid <= 4 );
|
||||
--hid;
|
||||
m_timers[hid].m_this = NULL;
|
||||
|
||||
// TimerMgr::GetTimerMgr()->ClearTimer( s_checkAck, this );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1231,9 +1290,13 @@ CookieRef::s_checkAllConnected( void* closure )
|
|||
/* static */ void
|
||||
CookieRef::s_checkAck( void* closure )
|
||||
{
|
||||
CookieRef* self = (CookieRef*)closure;
|
||||
SafeCref scr(self);
|
||||
scr.CheckNotAcked();
|
||||
AckTimer* at = (AckTimer*)closure;
|
||||
CookieRef* self = at->m_this;
|
||||
if ( NULL != self ) {
|
||||
at->m_this = NULL;
|
||||
SafeCref scr(self);
|
||||
scr.CheckNotAcked( at->m_hid );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1247,14 +1310,13 @@ CookieRef::_CheckAllConnected()
|
|||
}
|
||||
|
||||
void
|
||||
CookieRef::_CheckNotAcked()
|
||||
CookieRef::_CheckNotAcked( HostID hid )
|
||||
{
|
||||
logf( XW_LOGINFO, "%s", __func__ );
|
||||
if ( m_nPendingAcks > 0 ) {
|
||||
CRefEvent newEvt( XWE_ACKTIMEOUT );
|
||||
m_eventQueue.push_back( newEvt );
|
||||
handleEvents();
|
||||
}
|
||||
logf( XW_LOGINFO, "%s(hid=%d)", __func__, hid );
|
||||
CRefEvent newEvt( XWE_ACKTIMEOUT );
|
||||
newEvt.u.ack.srcID = hid;
|
||||
m_eventQueue.push_back( newEvt );
|
||||
handleEvents();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1264,10 +1326,11 @@ CookieRef::printSeeds( const char* caller )
|
|||
char buf[64] = {0};
|
||||
vector<HostRec>::iterator iter;
|
||||
for ( iter = m_sockets.begin(); iter != m_sockets.end(); ++iter ) {
|
||||
len += snprintf( &buf[len], sizeof(buf)-len, "%.4x/%d ",
|
||||
iter->m_seed, iter->m_socket );
|
||||
len += snprintf( &buf[len], sizeof(buf)-len, "%.4x/%d/%c ",
|
||||
iter->m_seed, iter->m_socket,
|
||||
iter->m_ackPending?'a':'A' );
|
||||
}
|
||||
logf( XW_LOGINFO, "seeds/sockets after %s(): %s", caller, buf );
|
||||
logf( XW_LOGINFO, "seeds/sockets/ack'd after %s(): %s", caller, buf );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -58,6 +58,12 @@ HostRec(HostID hostID, int socket, int nPlayersH, int seed, bool ackPending )
|
|||
bool m_ackPending;
|
||||
};
|
||||
|
||||
struct AckTimer {
|
||||
public:
|
||||
HostID m_hid;
|
||||
class CookieRef* m_this;
|
||||
};
|
||||
|
||||
class CookieRef {
|
||||
|
||||
private:
|
||||
|
@ -95,7 +101,7 @@ class CookieRef {
|
|||
HostID HostForSocket( int sock );
|
||||
|
||||
/* connect case */
|
||||
bool AlreadyHere( unsigned short seed, int socket );
|
||||
bool AlreadyHere( unsigned short seed, int socket, HostID* prevHostID );
|
||||
/* reconnect case */
|
||||
bool AlreadyHere( HostID hid, unsigned short seed, int socket );
|
||||
|
||||
|
@ -110,7 +116,8 @@ class CookieRef {
|
|||
static void Delete( CookieID id );
|
||||
static void Delete( const char* name );
|
||||
|
||||
bool _Connect( int socket, int nPlayersH, int nPlayersS, int seed );
|
||||
bool _Connect( int socket, int nPlayersH, int nPlayersS, int seed,
|
||||
bool seenSeed );
|
||||
void _Reconnect( int socket, HostID srcID, int nPlayersH, int nPlayersS,
|
||||
int seed, bool gameDead );
|
||||
void _HandleAck( HostID hostID );
|
||||
|
@ -122,9 +129,9 @@ class CookieRef {
|
|||
void _Forward( HostID src, HostID dest, unsigned char* buf, int buflen );
|
||||
void _Remove( int socket );
|
||||
void _CheckAllConnected();
|
||||
void _CheckNotAcked();
|
||||
void _CheckNotAcked( HostID hid );
|
||||
|
||||
bool ShouldDie() { return m_curState == XWS_DEAD; }
|
||||
bool ShouldDie() { return m_curState == XWS_EMPTY; }
|
||||
XW_RELAY_STATE CurState() { return m_curState; }
|
||||
|
||||
void logf( XW_LogLevel level, const char* format, ... );
|
||||
|
@ -202,18 +209,21 @@ class CookieRef {
|
|||
void sendResponse( const CRefEvent* evt, bool initial );
|
||||
void sendAnyStored( const CRefEvent* evt );
|
||||
void initPlayerCounts( const CRefEvent* evt );
|
||||
bool increasePlayerCounts( CRefEvent* evt, bool reconn );
|
||||
void modPending( const CRefEvent* evt, bool keep );
|
||||
bool increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp );
|
||||
void updateAck( HostID hostID, bool keep );
|
||||
void dropPending( int seed );
|
||||
|
||||
void postCheckAllHere();
|
||||
void postDropDevice( HostID hostID );
|
||||
|
||||
bool hostAlreadyHere( int seed, int socket );
|
||||
|
||||
void reducePlayerCounts( int socket );
|
||||
|
||||
void setAllConnectedTimer();
|
||||
void cancelAllConnectedTimer();
|
||||
void setAckTimer();
|
||||
void cancelAckTimer();
|
||||
void setAckTimer( HostID hid );
|
||||
void cancelAckTimer( HostID hid );
|
||||
|
||||
void forward_or_store( const CRefEvent* evt );
|
||||
void send_denied( const CRefEvent* evt, XWREASON why );
|
||||
|
@ -271,7 +281,8 @@ class CookieRef {
|
|||
int m_langCode;
|
||||
|
||||
time_t m_starttime;
|
||||
int m_nPendingAcks;
|
||||
|
||||
AckTimer m_timers[4];
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
|
|
|
@ -180,7 +180,8 @@ CRefMgr::GetStats( CrefMgrInfo& mgrInfo )
|
|||
info.m_langCode = cref->GetLangCode();
|
||||
|
||||
SafeCref sc(cref);
|
||||
sc.GetHostsConnected( &info.m_hostsIds, &info.m_hostSeeds, &info.m_hostIps );
|
||||
sc.GetHostsConnected( &info.m_hostsIds, &info.m_hostSeeds,
|
||||
&info.m_hostIps );
|
||||
|
||||
mgrInfo.m_crefInfo.push_back( info );
|
||||
}
|
||||
|
@ -231,25 +232,31 @@ CRefMgr::getFromFreeList( void )
|
|||
CookieRef*
|
||||
CRefMgr::getMakeCookieRef( const char* cookie, HostID hid, int socket,
|
||||
int nPlayersH, int nPlayersT, int langCode,
|
||||
int gameSeed, bool wantsPublic,
|
||||
bool makePublic )
|
||||
int seed, bool wantsPublic,
|
||||
bool makePublic, bool* seenSeed )
|
||||
{
|
||||
CookieRef* cref;
|
||||
CookieID cid;
|
||||
char connNameBuf[MAX_CONNNAME_LEN+1] = {0};
|
||||
int alreadyHere = 0;
|
||||
|
||||
/* We have a cookie from a new connection or from a reconnect. This may
|
||||
be the first time it's been seen, or there may be a game currently in
|
||||
the XW_ST_CONNECTING state, or it may be a dupe of a connect packet.
|
||||
If there's a game, cool. Otherwise add a new one. Pass the connName
|
||||
which will be used if set, but if not set we'll be generating another
|
||||
later when the game is complete.
|
||||
the XW_ST_CONNECTING state, or it may be a dupe of a connect packet on
|
||||
the same or a different socket. If there's a game, cool. Otherwise add
|
||||
a new one. Pass the connName which will be used if set, but if not set
|
||||
we'll be generating another later when the game is complete.
|
||||
*/
|
||||
|
||||
char connNameBuf[MAX_CONNNAME_LEN+1] = {0};
|
||||
int alreadyHere = 0;
|
||||
CookieID cid = m_db->FindOpen( cookie, langCode, nPlayersT, nPlayersH,
|
||||
wantsPublic,
|
||||
connNameBuf, sizeof(connNameBuf),
|
||||
&alreadyHere );
|
||||
*seenSeed = m_db->SeenSeed( cookie, seed, langCode, nPlayersT,
|
||||
wantsPublic, connNameBuf,
|
||||
sizeof(connNameBuf), &alreadyHere, &cid );
|
||||
if ( !*seenSeed ) {
|
||||
cid = m_db->FindOpen( cookie, langCode, nPlayersT, nPlayersH,
|
||||
wantsPublic, connNameBuf, sizeof(connNameBuf),
|
||||
&alreadyHere );
|
||||
}
|
||||
|
||||
if ( cid > 0 ) {
|
||||
cref = getCookieRef_impl( cid );
|
||||
} else {
|
||||
|
@ -657,12 +664,14 @@ SafeCref::SafeCref( const char* cookie, int socket, int nPlayersH, int nPlayersS
|
|||
: m_cref( NULL )
|
||||
, m_mgr( CRefMgr::Get() )
|
||||
, m_isValid( false )
|
||||
, m_seenSeed( false )
|
||||
{
|
||||
CookieRef* cref;
|
||||
|
||||
cref = m_mgr->getMakeCookieRef( cookie, 0, socket,
|
||||
nPlayersH, nPlayersS, langCode,
|
||||
gameSeed, wantsPublic, makePublic );
|
||||
gameSeed, wantsPublic, makePublic,
|
||||
&m_seenSeed );
|
||||
if ( cref != NULL ) {
|
||||
m_locked = cref->Lock();
|
||||
m_cref = cref;
|
||||
|
|
|
@ -138,7 +138,8 @@ class CRefMgr {
|
|||
CookieRef* getMakeCookieRef( const char* cookie,
|
||||
HostID hid, int socket, int nPlayersH,
|
||||
int nPlayersS, int langCode, int seed,
|
||||
bool wantsPublic, bool makePublic );
|
||||
bool wantsPublic, bool makePublic,
|
||||
bool* seenSeed );
|
||||
|
||||
/* reconnect case; just the stuff we don't have in db */
|
||||
CookieRef* getMakeCookieRef( const char* connName, const char* cookie,
|
||||
|
@ -219,7 +220,8 @@ class SafeCref {
|
|||
bool Connect( int socket, int nPlayersH, int nPlayersS, int seed ) {
|
||||
if ( IsValid() ) {
|
||||
assert( 0 != m_cref->GetCookieID() );
|
||||
return m_cref->_Connect( socket, nPlayersH, nPlayersS, seed );
|
||||
return m_cref->_Connect( socket, nPlayersH, nPlayersS, seed,
|
||||
m_seenSeed );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -300,9 +302,9 @@ class SafeCref {
|
|||
m_cref->_CheckAllConnected();
|
||||
}
|
||||
}
|
||||
void CheckNotAcked() {
|
||||
void CheckNotAcked( HostID hid ) {
|
||||
if ( IsValid() ) {
|
||||
m_cref->_CheckNotAcked();
|
||||
m_cref->_CheckNotAcked( hid );
|
||||
}
|
||||
}
|
||||
const char* Cookie() {
|
||||
|
@ -366,6 +368,7 @@ class SafeCref {
|
|||
}
|
||||
|
||||
bool IsValid() { return m_isValid; }
|
||||
bool SeenSeed() { return m_seenSeed; }
|
||||
|
||||
private:
|
||||
CookieRef* m_cref;
|
||||
|
@ -373,6 +376,7 @@ class SafeCref {
|
|||
bool m_isValid;
|
||||
bool m_locked;
|
||||
bool m_dead;
|
||||
bool m_seenSeed;
|
||||
}; /* SafeCref class */
|
||||
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ static DBMgr* s_instance = NULL;
|
|||
|
||||
static void formatParams( char* paramValues[], int nParams, const char* fmt,
|
||||
char* buf, int bufLen, ... );
|
||||
static int here_less_seed( const char* seeds, int perDeviceSum,
|
||||
unsigned short seed );
|
||||
|
||||
/* static */ DBMgr*
|
||||
DBMgr::Get()
|
||||
|
@ -130,6 +132,48 @@ DBMgr::FindGame( const char* connName, char* cookieBuf, int bufLen,
|
|||
|
||||
logf( XW_LOGINFO, "%s(%s)=>%d", __func__, connName, cid );
|
||||
return cid;
|
||||
} /* FindGame */
|
||||
|
||||
bool
|
||||
DBMgr::SeenSeed( const char* cookie, unsigned short seed,
|
||||
int langCode, int nPlayersT, bool wantsPublic,
|
||||
char* connNameBuf, int bufLen, int* nPlayersHP,
|
||||
CookieID* cid )
|
||||
{
|
||||
int nParams = 5;
|
||||
char* paramValues[nParams];
|
||||
char buf[512];
|
||||
formatParams( paramValues, nParams,
|
||||
"%s"DELIM"%d"DELIM"%d"DELIM"%d"DELIM"%s", buf, sizeof(buf),
|
||||
cookie, langCode, nPlayersT, seed,
|
||||
wantsPublic?"TRUE":"FALSE" );
|
||||
|
||||
const char* cmd = "SELECT cid, connName, seeds, sum_array(nPerDevice) FROM "
|
||||
GAMES_TABLE
|
||||
" WHERE NOT dead"
|
||||
" AND room ILIKE $1"
|
||||
" AND lang = $2"
|
||||
" AND nTotal = $3"
|
||||
" AND $4 = ANY(seeds)"
|
||||
" AND $5 = pub"
|
||||
" ORDER BY ctime DESC"
|
||||
" LIMIT 1";
|
||||
|
||||
PGresult* result = PQexecParams( getThreadConn(), cmd,
|
||||
nParams, NULL,
|
||||
paramValues,
|
||||
NULL, NULL, 0 );
|
||||
bool found = 1 == PQntuples( result );
|
||||
if ( found ) {
|
||||
*cid = atoi( PQgetvalue( result, 0, 0 ) );
|
||||
*nPlayersHP = here_less_seed( PQgetvalue( result, 0, 2 ),
|
||||
atoi( PQgetvalue( result, 0, 3 ) ),
|
||||
seed );
|
||||
snprintf( connNameBuf, bufLen, "%s", PQgetvalue( result, 0, 1 ) );
|
||||
}
|
||||
PQclear( result );
|
||||
logf( XW_LOGINFO, "%s(%4X)=>%s", __func__, seed, found?"true":"false" );
|
||||
return found;
|
||||
}
|
||||
|
||||
CookieID
|
||||
|
@ -174,9 +218,9 @@ DBMgr::FindOpen( const char* cookie, int lang, int nPlayersT, int nPlayersH,
|
|||
} /* FindOpen */
|
||||
|
||||
bool
|
||||
DBMgr::GameFull( const char* const connName )
|
||||
DBMgr::AllDevsAckd( const char* const connName )
|
||||
{
|
||||
const char* cmd = "SELECT ntotal=sum_array(nperdevice) from " GAMES_TABLE
|
||||
const char* cmd = "SELECT ntotal=sum_array(nperdevice) AND 'A'=ALL(ack) from " GAMES_TABLE
|
||||
" WHERE connName='%s'";
|
||||
char query[256];
|
||||
snprintf( query, sizeof(query), cmd, connName );
|
||||
|
@ -187,12 +231,13 @@ DBMgr::GameFull( const char* const connName )
|
|||
assert( nTuples <= 1 );
|
||||
bool full = 't' == PQgetvalue( result, 0, 0 )[0];
|
||||
PQclear( result );
|
||||
logf( XW_LOGINFO, "%s=>%d", __func__, full );
|
||||
return full;
|
||||
}
|
||||
|
||||
HostID
|
||||
DBMgr::AddDevice( const char* connName, HostID curID, int nToAdd,
|
||||
unsigned short seed )
|
||||
unsigned short seed, bool ackd )
|
||||
{
|
||||
HostID newID = curID;
|
||||
|
||||
|
@ -208,29 +253,79 @@ DBMgr::AddDevice( const char* connName, HostID curID, int nToAdd,
|
|||
assert( newID <= 4 );
|
||||
|
||||
const char* fmt = "UPDATE " GAMES_TABLE " SET nPerDevice[%d] = %d,"
|
||||
" seeds[%d] = %d, mtimes[%d]='now'"
|
||||
" seeds[%d] = %d, mtimes[%d]='now', ack[%d]=\'%c\'"
|
||||
" WHERE connName = '%s'";
|
||||
char query[256];
|
||||
snprintf( query, sizeof(query), fmt, newID, nToAdd, newID, seed, newID, connName );
|
||||
snprintf( query, sizeof(query), fmt, newID, nToAdd, newID, seed, newID,
|
||||
newID, ackd?'A':'a', connName );
|
||||
logf( XW_LOGINFO, "%s: query: %s", __func__, query );
|
||||
|
||||
execSql( query );
|
||||
|
||||
return newID;
|
||||
} /* AddDevice */
|
||||
|
||||
void
|
||||
DBMgr::NoteAckd( const char* const connName, HostID id )
|
||||
{
|
||||
char query[256];
|
||||
const char* fmt = "UPDATE " GAMES_TABLE " SET ack[%d]='A'"
|
||||
" WHERE connName = '%s'";
|
||||
snprintf( query, sizeof(query), fmt, id, connName );
|
||||
logf( XW_LOGINFO, "%s: query: %s", __func__, query );
|
||||
|
||||
execSql( query );
|
||||
}
|
||||
|
||||
bool
|
||||
DBMgr::RmDevice( const char* connName, HostID hid )
|
||||
DBMgr::RmDeviceByHid( const char* connName, HostID hid )
|
||||
{
|
||||
const char* fmt = "UPDATE " GAMES_TABLE " SET nPerDevice[%d] = 0, "
|
||||
"seeds[%d] = 0, mtimes[%d]='now' WHERE connName = '%s'";
|
||||
"seeds[%d] = 0, ack[%d]='-', mtimes[%d]='now' WHERE connName = '%s'";
|
||||
char query[256];
|
||||
snprintf( query, sizeof(query), fmt, hid, hid, hid, connName );
|
||||
snprintf( query, sizeof(query), fmt, hid, hid, hid, hid, connName );
|
||||
logf( XW_LOGINFO, "%s: query: %s", __func__, query );
|
||||
|
||||
return execSql( query );
|
||||
}
|
||||
|
||||
void
|
||||
DBMgr::RmDeviceBySeed( const char* const connName, unsigned short seed )
|
||||
{
|
||||
char seeds[128] = {0};
|
||||
const char* fmt = "SELECT seeds FROM " GAMES_TABLE
|
||||
" WHERE connName = '%s'"
|
||||
" AND %d = ANY(seeds)";
|
||||
char query[256];
|
||||
snprintf( query, sizeof(query), fmt, connName, seed );
|
||||
logf( XW_LOGINFO, "%s: query: %s", __func__, query );
|
||||
PGresult* result = PQexec( getThreadConn(), query );
|
||||
if ( 1 == PQntuples( result ) ) {
|
||||
snprintf( seeds, sizeof(seeds), "%s", PQgetvalue( result, 0, 0 ) );
|
||||
}
|
||||
PQclear( result );
|
||||
|
||||
if ( 0 != seeds[0] ) {
|
||||
char *saveptr = NULL;
|
||||
int ii;
|
||||
char* str;
|
||||
for ( str = seeds, ii = 0; ; str = NULL, ++ii ) {
|
||||
char* tok = strtok_r( str, "{},", &saveptr );
|
||||
if ( NULL == tok ) {
|
||||
break;
|
||||
} else {
|
||||
int asint = atoi( tok );
|
||||
if ( asint == seed ) {
|
||||
RmDeviceByHid( connName, ii + 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(0); /* but don't ship with this!!!! */
|
||||
}
|
||||
} /* RmDeviceSeed */
|
||||
|
||||
bool
|
||||
DBMgr::HaveDevice( const char* connName, HostID hid, int seed )
|
||||
{
|
||||
|
@ -537,7 +632,15 @@ formatParams( char* paramValues[], int nParams, const char* fmt, char* buf,
|
|||
}
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
here_less_seed( const char* seeds, int sumPerDevice, unsigned short seed )
|
||||
{
|
||||
logf( XW_LOGINFO, "%s: find %x in \"%s\", sub from \"%d\"", __func__,
|
||||
seed, seeds, sumPerDevice );
|
||||
return sumPerDevice - 1; /* FIXME */
|
||||
}
|
||||
|
||||
static void
|
||||
destr_function( void* conn )
|
||||
|
|
|
@ -43,14 +43,22 @@ class DBMgr {
|
|||
CookieID FindGame( const char* connName, char* cookieBuf, int bufLen,
|
||||
int* langP, int* nPlayersTP, int* nPlayersHP,
|
||||
bool* isDead );
|
||||
|
||||
bool SeenSeed( const char* cookie, unsigned short seed,
|
||||
int langCode, int nPlayersT, bool wantsPublic,
|
||||
char* connNameBuf, int bufLen, int* nPlayersHP,
|
||||
CookieID* cid );
|
||||
|
||||
CookieID FindOpen( const char* cookie, int lang, int nPlayersT,
|
||||
int nPlayersH, bool wantsPublic,
|
||||
char* connNameBuf, int bufLen, int* nPlayersHP );
|
||||
bool GameFull( const char* const connName );
|
||||
bool AllDevsAckd( const char* const connName );
|
||||
|
||||
HostID AddDevice( const char* const connName, HostID curID,
|
||||
int nToAdd, unsigned short seed );
|
||||
bool RmDevice( const char* const connName, HostID id );
|
||||
int nToAdd, unsigned short seed, bool unAckd );
|
||||
void NoteAckd( const char* const connName, HostID id );
|
||||
bool RmDeviceByHid( const char* const connName, HostID id );
|
||||
void RmDeviceBySeed( const char* const connName, unsigned short seed );
|
||||
bool HaveDevice( const char* const connName, HostID id, int seed );
|
||||
void AddCID( const char* const connName, CookieID cid );
|
||||
void ClearCID( const char* connName );
|
||||
|
|
|
@ -61,7 +61,7 @@ typedef struct StateTable {
|
|||
*/
|
||||
|
||||
static StateTable g_stateTable[] = {
|
||||
{ XWS_INITED, XWE_DEVCONNECT, XWA_SEND_CONNRSP, XWS_WAITMORE },
|
||||
{ XWS_EMPTY, XWE_DEVCONNECT, XWA_SEND_CONNRSP, XWS_WAITMORE },
|
||||
{ XWS_WAITMORE, XWE_DEVCONNECT, XWA_SEND_CONNRSP, XWS_WAITMORE },
|
||||
{ XWS_WAITMORE, XWE_GOTONEACK, XWA_NOTEACK, XWS_WAITMORE },
|
||||
{ XWS_WAITMORE, XWE_ACKTIMEOUT, XWA_DROPDEVICE, XWS_WAITMORE },
|
||||
|
@ -73,6 +73,7 @@ static StateTable g_stateTable[] = {
|
|||
{ XWS_ALLCONND, XWE_RECONNECT, XWA_SEND_RERSP, XWS_ALLCONND },
|
||||
{ XWS_ALLCONND, XWE_ALLHERE, XWA_NONE, XWS_ALLCONND },
|
||||
{ XWS_ALLCONND, XWE_REMOVESOCKET, XWA_REMOVESOCK_1, XWS_ALLCONND },
|
||||
{ XWS_ALLCONND, XWE_GOTONEACK, XWA_NONE, XWS_ALLCONND },
|
||||
|
||||
/* { XWS_WAITMORE, XWE_GAMEFULL, XWA_SENDALLHERE, XWS_ALLCONND }, */
|
||||
/* { XWS_WAITMORE, XWE_CHECKFULL, XWA_, XWS_WAITMORE }, */
|
||||
|
@ -107,12 +108,14 @@ static StateTable g_stateTable[] = {
|
|||
/* { XWS_MSGONLY, XWE_NOMOREMSGS, XWA_NONE, XWS_DEAD }, */
|
||||
/* { XWS_MSGONLY, XWE_NOMOREMSGS, XWA_NONE, XWS_DEAD }, */
|
||||
|
||||
{ XWS_ANY, XWE_NOMORESOCKETS, XWA_NONE, XWS_DEAD },
|
||||
{ XWS_ANY, XWE_SHUTDOWN, XWA_SHUTDOWN, XWS_DEAD },
|
||||
{ XWS_ANY, XWE_NOMORESOCKETS, XWA_NONE, XWS_EMPTY },
|
||||
{ XWS_ANY, XWE_SHUTDOWN, XWA_SHUTDOWN, XWS_EMPTY },
|
||||
/* drop timeout (unless we're in XWS_WAITMORE; see above) */
|
||||
{ XWS_ANY, XWE_ACKTIMEOUT, XWA_NONE, XWS_SAME },
|
||||
|
||||
/* This doesn't make sense. Can't go straight to ALLCOND if don't have all
|
||||
players/devices. */
|
||||
{ XWS_INITED, XWE_RECONNECT, XWA_SEND_RERSP, XWS_WAITMORE },
|
||||
{ XWS_EMPTY, XWE_RECONNECT, XWA_SEND_RERSP, XWS_WAITMORE },
|
||||
{ XWS_MSGONLY, XWE_RECONNECT, XWA_SEND_RERSP, XWS_WAITMORE },
|
||||
|
||||
/* { XWS_MISSING, XWE_RECONNECT, XWA_SEND_RERSP, XWS_CHK_ALLHERE_2 }, */
|
||||
|
@ -134,7 +137,7 @@ static StateTable g_stateTable[] = {
|
|||
{ XWS_MISSING, XWE_HEARTRCVD, XWA_NOTEHEART, XWS_MISSING },
|
||||
#endif
|
||||
|
||||
{ XWS_INITED, XWE_DEVGONE, XWA_RMDEV, XWS_DEAD },
|
||||
{ XWS_EMPTY, XWE_DEVGONE, XWA_RMDEV, XWS_EMPTY },
|
||||
{ XWS_WAITMORE, XWE_DEVGONE, XWA_RMDEV, XWS_WAITMORE },
|
||||
/* This should be impossible unless device allows deleting an open/connected
|
||||
game */
|
||||
|
@ -143,20 +146,20 @@ static StateTable g_stateTable[] = {
|
|||
{ XWS_ALLCONND, XWE_GAMEDEAD, XWA_TELLGAMEDEAD, XWS_ALLCONND },
|
||||
|
||||
/* Connect timer */
|
||||
{ XWS_WAITMORE, XWE_CONNTIMER, XWA_TIMERDISCONN, XWS_DEAD },
|
||||
{ XWS_WAITMORE, XWE_CONNTIMER, XWA_TIMERDISCONN, XWS_EMPTY },
|
||||
/* { XWS_MISSING, XWE_CONNTIMER, XWA_NONE, XWS_MISSING }, */
|
||||
{ XWS_ALLCONND, XWE_CONNTIMER, XWA_NONE, XWS_ALLCONND },
|
||||
|
||||
{ XWS_WAITMORE, XWE_NOTIFYDISCON, XWA_NOTIFYDISCON, XWS_WAITMORE },
|
||||
/* { XWS_ALLCONND, XWE_NOTIFYDISCON, XWA_NOTIFYDISCON, XWS_MISSING }, */
|
||||
/* { XWS_MISSING, XWE_NOTIFYDISCON, XWA_NOTIFYDISCON, XWS_MISSING }, */
|
||||
{ XWS_DEAD, XWE_NOTIFYDISCON, XWA_NOTIFYDISCON, XWS_DEAD },
|
||||
{ XWS_EMPTY, XWE_NOTIFYDISCON, XWA_NOTIFYDISCON, XWS_EMPTY },
|
||||
|
||||
/* This is our bread-n-butter */
|
||||
{ XWS_ALLCONND, XWE_FORWARDMSG, XWA_FWD, XWS_ALLCONND },
|
||||
/* { XWS_MISSING, XWE_FORWARDMSG, XWA_FWD, XWS_MISSING }, */
|
||||
|
||||
{ XWS_DEAD, XWE_REMOVESOCKET, XWA_REMOVESOCK_1, XWS_DEAD }
|
||||
{ XWS_EMPTY, XWE_REMOVESOCKET, XWA_REMOVESOCK_1, XWS_EMPTY }
|
||||
|
||||
};
|
||||
|
||||
|
@ -172,7 +175,8 @@ getFromTable( XW_RELAY_STATE curState, XW_RELAY_EVENT curEvent,
|
|||
if ( stp->stateStart == curState || stp->stateStart == XWS_ANY ) {
|
||||
if ( stp->stateEvent == curEvent || stp->stateEvent == XWE_ANY ) {
|
||||
*takeAction = stp->stateAction;
|
||||
*nextState = stp->stateEnd;
|
||||
*nextState =
|
||||
stp->stateEnd == XWS_SAME? curState : stp->stateEnd;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -192,11 +196,10 @@ stateString( XW_RELAY_STATE state )
|
|||
switch( state ) {
|
||||
CASESTR(XWS_NONE);
|
||||
CASESTR(XWS_ANY);
|
||||
CASESTR(XWS_INITED);
|
||||
CASESTR(XWS_EMPTY);
|
||||
CASESTR(XWS_WAITMORE);
|
||||
CASESTR(XWS_WAITING_ACKS);
|
||||
CASESTR(XWS_ALLCONND);
|
||||
CASESTR(XWS_DEAD);
|
||||
/* CASESTR(XWS_MISSING); */
|
||||
CASESTR(XWS_MSGONLY);
|
||||
/* CASESTR(XWS_CHK_ALLHERE); */
|
||||
|
@ -264,7 +267,6 @@ actString( XW_RELAY_ACTION act )
|
|||
CASESTR(XWA_SEND_INITRSP);
|
||||
CASESTR(XWA_SEND_CONNRSP);
|
||||
CASESTR(XWA_NOTEACK);
|
||||
CASESTR(XWA_NOTEACKCHECK);
|
||||
/* CASESTR(XWA_ADDDEVICE); */
|
||||
CASESTR(XWA_DROPDEVICE);
|
||||
CASESTR(XWA_SNDALLHERE_2);
|
||||
|
|
|
@ -27,6 +27,7 @@ typedef
|
|||
enum {
|
||||
XWS_NONE
|
||||
,XWS_ANY /* wildcard */
|
||||
,XWS_SAME /* wildcard: means use same state as current */
|
||||
|
||||
/* ,XWS_CHKCOUNTS_INIT */ /* from initial state, check if all players
|
||||
are here. Success should be an error,
|
||||
|
@ -40,11 +41,13 @@ enum {
|
|||
/* ,XWS_CHK_ALLHERE_2 */ /* same as above, but triggered by a reconnect
|
||||
rather than a connect request */
|
||||
|
||||
,XWS_INITED /* Relay's running and the object's been
|
||||
created, but nobody's signed up yet. This
|
||||
is a very short-lived state since an
|
||||
incoming connection is why the object was
|
||||
created. */
|
||||
,XWS_EMPTY /* Relay's running and the object's been
|
||||
created, and nobody's signed up yet. The
|
||||
object should never be in this state except
|
||||
immediately after created, just before
|
||||
deleted, or transitionally, as after a
|
||||
device is removed prior to replacing its
|
||||
record with another. */
|
||||
|
||||
,XWS_WAITMORE /* At least one device has connected, but no
|
||||
packets have yet arrived to be
|
||||
|
@ -63,8 +66,6 @@ enum {
|
|||
|
||||
/* ,XWS_ROOMCHK */ /* do we have room for as many players as are
|
||||
being provided */
|
||||
|
||||
,XWS_DEAD /* About to kill the object */
|
||||
} XW_RELAY_STATE;
|
||||
|
||||
|
||||
|
@ -129,7 +130,6 @@ typedef enum {
|
|||
|
||||
// ,XWA_ADDDEVICE /* got ack, so device is in for sure */
|
||||
,XWA_NOTEACK
|
||||
,XWA_NOTEACKCHECK
|
||||
,XWA_DROPDEVICE /* no ack; remove all traces of device */
|
||||
|
||||
,XWA_SEND_INITRSP /* response to first to connect */
|
||||
|
|
|
@ -314,8 +314,6 @@ processConnect( unsigned char* bufp, int bufLen, int socket )
|
|||
unsigned char* end = bufp + bufLen;
|
||||
bool success = false;
|
||||
|
||||
logf( XW_LOGINFO, "%s()", __func__ );
|
||||
|
||||
cookie[0] = '\0';
|
||||
|
||||
unsigned char flags = *bufp++;
|
||||
|
@ -324,7 +322,7 @@ processConnect( unsigned char* bufp, int bufLen, int socket )
|
|||
/* HostID srcID; */
|
||||
unsigned char nPlayersH;
|
||||
unsigned char nPlayersT;
|
||||
unsigned short gameSeed;
|
||||
unsigned short seed;
|
||||
unsigned char langCode;
|
||||
unsigned char makePublic, wantsPublic;
|
||||
if ( readStr( &bufp, end, cookie, sizeof(cookie) )
|
||||
|
@ -333,10 +331,11 @@ processConnect( unsigned char* bufp, int bufLen, int socket )
|
|||
/* && getNetByte( &bufp, end, &srcID ) */
|
||||
&& getNetByte( &bufp, end, &nPlayersH )
|
||||
&& getNetByte( &bufp, end, &nPlayersT )
|
||||
&& getNetShort( &bufp, end, &gameSeed )
|
||||
&& getNetShort( &bufp, end, &seed )
|
||||
&& getNetByte( &bufp, end, &langCode ) ) {
|
||||
logf( XW_LOGINFO, "%s(): langCode=%d; nPlayersT=%d; wantsPublic=%d", __func__,
|
||||
langCode, nPlayersT, wantsPublic );
|
||||
logf( XW_LOGINFO, "%s(): langCode=%d; nPlayersT=%d; "
|
||||
"wantsPublic=%d; seed=%.4X",
|
||||
__func__, langCode, nPlayersT, wantsPublic, seed );
|
||||
|
||||
/* Make sure second thread can't create new cref for same cookie
|
||||
this one just handled.*/
|
||||
|
@ -344,10 +343,10 @@ processConnect( unsigned char* bufp, int bufLen, int socket )
|
|||
MutexLock ml( &s_newCookieLock );
|
||||
|
||||
SafeCref scr( cookie, socket, nPlayersH, nPlayersT,
|
||||
gameSeed, langCode, wantsPublic, makePublic );
|
||||
seed, langCode, wantsPublic, makePublic );
|
||||
/* nPlayersT etc could be slots in SafeCref to avoid passing
|
||||
here */
|
||||
success = scr.Connect( socket, nPlayersH, nPlayersT, gameSeed );
|
||||
success = scr.Connect( socket, nPlayersH, nPlayersT, seed );
|
||||
} else {
|
||||
err = XWRELAY_ERROR_BADPROTO;
|
||||
}
|
||||
|
@ -442,7 +441,7 @@ processDisconnect( unsigned char* bufp, int bufLen, int socket )
|
|||
static void
|
||||
killSocket( int socket )
|
||||
{
|
||||
logf( XW_LOGINFO, "killSocket(%d)", socket );
|
||||
logf( XW_LOGINFO, "%s(%d)", __func__, socket );
|
||||
CRefMgr::Get()->RemoveSocketRefs( socket );
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue