mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-15 20:48:00 +01:00
handle invitations for excessive new addresses
Deal with somebody creating a new invitation, e.g. because it's been realized that an existing one won't be accepted. Unused channels are used first (though there will be none in a 4-device game), then channels with old invites (only) are recycled.
This commit is contained in:
parent
6d0686f737
commit
f3fb43e93b
2 changed files with 71 additions and 35 deletions
|
@ -1709,16 +1709,19 @@ haveRealChannel( const CommsCtxt* comms, XP_PlayerAddr channelNo )
|
|||
}
|
||||
|
||||
typedef struct _GetInviteChannelsData {
|
||||
XP_U16 mask;
|
||||
XP_U16 hasInvitesMask;
|
||||
XP_U16 hasNonInvitesMask;
|
||||
} GetInviteChannelsData;
|
||||
|
||||
static ForEachAct
|
||||
getInviteChannels( MsgQueueElem* elem, void* closure )
|
||||
{
|
||||
GetInviteChannelsData* gicdp = (GetInviteChannelsData*)closure;
|
||||
if ( IS_INVITE(elem) ) {
|
||||
GetInviteChannelsData* gicdp = (GetInviteChannelsData*)closure;
|
||||
XP_ASSERT( 0 == (gicdp->mask & (1 << elem->channelNo)) );
|
||||
gicdp->mask |= 1 << elem->channelNo;
|
||||
XP_ASSERT( 0 == (gicdp->hasInvitesMask & (1 << elem->channelNo)) );
|
||||
gicdp->hasInvitesMask |= 1 << elem->channelNo;
|
||||
} else {
|
||||
gicdp->hasNonInvitesMask |= 1 << elem->channelNo;
|
||||
}
|
||||
return FEA_OK;
|
||||
}
|
||||
|
@ -1742,17 +1745,33 @@ pickChannel( const CommsCtxt* comms, const NetLaunchInfo* nli,
|
|||
}
|
||||
|
||||
if ( 0 == result ) {
|
||||
/* Now find the first channelNo that doesn't have an invitation on it
|
||||
already */
|
||||
/* Data useful for next two steps: unused channel, then invites-only
|
||||
channel */
|
||||
GetInviteChannelsData gicd = {0};
|
||||
forEachElem( (CommsCtxt*)comms, getInviteChannels, &gicd );
|
||||
const XP_U16 nPlayers = comms->util->gameInfo->nPlayers;
|
||||
for ( XP_PlayerAddr chan = 1; chan <= nPlayers; ++chan ) {
|
||||
if ( 0 == (gicd.mask & (1 << chan)) ) {
|
||||
|
||||
/* Now find the first channelNo that doesn't have an invitation on it
|
||||
already */
|
||||
// const XP_U16 nPlayers = comms->util->gameInfo->nPlayers;
|
||||
for ( XP_PlayerAddr chan = 1; chan <= CHANNEL_MASK; ++chan ) {
|
||||
if ( 0 == (gicd.hasInvitesMask & (1 << chan)) ) {
|
||||
result = chan;
|
||||
XP_LOGFF( "using unused channel" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( 0 == result ) {
|
||||
/* We need to find a channel to recycle. It should be one that has
|
||||
only an invite on it.*/
|
||||
for ( XP_PlayerAddr chan = 1; chan <= CHANNEL_MASK; ++chan ) {
|
||||
if ( 0 == (gicd.hasNonInvitesMask & (1 << chan)) ) {
|
||||
result = chan;
|
||||
XP_LOGFF( "recycling channel" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_RETURNF( "%d", result );
|
||||
|
@ -1769,33 +1788,38 @@ comms_invite( CommsCtxt* comms, XWEnv xwe, const NetLaunchInfo* nli,
|
|||
XP_PlayerAddr forceChannel = pickChannel(comms, nli, destAddr);
|
||||
XP_LOGFF( "forceChannel: %d", forceChannel );
|
||||
XP_ASSERT( 0 < forceChannel && (forceChannel & CHANNEL_MASK) == forceChannel );
|
||||
if ( !haveRealChannel( comms, forceChannel ) ) {
|
||||
/* See if we have a channel for this address. Then see if we have an
|
||||
invite matching this one, and if not add one. Then trigger a send of
|
||||
it. */
|
||||
if ( 0 < forceChannel ) {
|
||||
XP_ASSERT( (forceChannel & CHANNEL_MASK) == forceChannel );
|
||||
if ( !haveRealChannel( comms, forceChannel ) ) {
|
||||
/* See if we have a channel for this address. Then see if we have an
|
||||
invite matching this one, and if not add one. Then trigger a send of
|
||||
it. */
|
||||
|
||||
/* remove the old rec, if found */
|
||||
nukeInvites( comms, xwe, forceChannel );
|
||||
/* remove the old rec, if found */
|
||||
nukeInvites( comms, xwe, forceChannel );
|
||||
|
||||
XP_U16 flags = COMMS_VERSION;
|
||||
/*AddressRecord* rec = */rememberChannelAddress( comms, forceChannel,
|
||||
0, destAddr, flags );
|
||||
MsgQueueElem* elem = makeInviteElem( comms, xwe, forceChannel, nli );
|
||||
XP_U16 flags = COMMS_VERSION;
|
||||
/*AddressRecord* rec = */rememberChannelAddress( comms, forceChannel,
|
||||
0, destAddr, flags );
|
||||
MsgQueueElem* elem = makeInviteElem( comms, xwe, forceChannel, nli );
|
||||
|
||||
elem = addToQueue( comms, xwe, elem, XP_TRUE );
|
||||
if ( !!elem ) {
|
||||
XP_ASSERT( !elem->smp.next );
|
||||
COMMS_LOGFF( "added invite with sum %s on channel %d", elem->sb.buf,
|
||||
elem->channelNo & CHANNEL_MASK );
|
||||
/* Let's let platform code decide whether to call sendMsg() . On
|
||||
Android creating a game with an invitation in its queue is always
|
||||
followed by opening the game, which results in comms_resendAll()
|
||||
getting called leading to a second send immediately after this. So
|
||||
let Android drop it. Linux, though, needs it for now. */
|
||||
if ( sendNow && !!comms->procs.sendInvt ) {
|
||||
sendMsg( comms, xwe, elem, COMMS_CONN_NONE );
|
||||
elem = addToQueue( comms, xwe, elem, XP_TRUE );
|
||||
if ( !!elem ) {
|
||||
XP_ASSERT( !elem->smp.next );
|
||||
COMMS_LOGFF( "added invite with sum %s on channel %d", elem->sb.buf,
|
||||
elem->channelNo & CHANNEL_MASK );
|
||||
/* Let's let platform code decide whether to call sendMsg() . On
|
||||
Android creating a game with an invitation in its queue is always
|
||||
followed by opening the game, which results in comms_resendAll()
|
||||
getting called leading to a second send immediately after this. So
|
||||
let Android drop it. Linux, though, needs it for now. */
|
||||
if ( sendNow && !!comms->procs.sendInvt ) {
|
||||
sendMsg( comms, xwe, elem, COMMS_CONN_NONE );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
XP_LOGFF( "dropping invite; no open channel found" );
|
||||
}
|
||||
COMMS_MUTEX_UNLOCK();
|
||||
LOG_RETURN_VOID();
|
||||
|
@ -2050,7 +2074,8 @@ removeProc( MsgQueueElem* elem, void* closure )
|
|||
|
||||
XP_PlayerAddr maskedElemChannelNo = ~CHANNEL_MASK & elem->channelNo;
|
||||
if ( (maskedElemChannelNo == 0) && (rdp->channelNo != 0) ) {
|
||||
XP_ASSERT( !rdp->comms->isServer || IS_INVITE(elem) );
|
||||
// not sure what this was doing....
|
||||
// XP_ASSERT( !rdp->comms->isServer || IS_INVITE(elem) );
|
||||
XP_ASSERT( elem->msgID == 0 );
|
||||
} else if ( maskedElemChannelNo != maskedChannelNo ) {
|
||||
knownGood = XP_TRUE;
|
||||
|
|
|
@ -108,7 +108,9 @@ class GameStatus():
|
|||
self.isSolo = False
|
||||
|
||||
def harvest(self, dev, isSolo):
|
||||
self.players.append(dev.host)
|
||||
# Sending lots of bogus invitations gets duplicates here
|
||||
if not dev.host in self.players:
|
||||
self.players.append(dev.host)
|
||||
self.allOver = self.allOver and dev.gameOver(self.gid)
|
||||
self.isSolo = isSolo
|
||||
|
||||
|
@ -424,12 +426,18 @@ class Device():
|
|||
def invite(self, game):
|
||||
remotes = []
|
||||
guestDevs = []
|
||||
useRandomDevID = random.randint(0, 100) < self.args.BAD_INVITE_PCT
|
||||
for ii in reversed(range(len(game.guestNames))):
|
||||
guestDev = Device.getForPlayer(game.guestNames[ii])
|
||||
guestDevs.append(guestDev)
|
||||
|
||||
addr = {}
|
||||
if self.args.WITH_MQTT: addr['mqtt'] = guestDev.mqttDevID
|
||||
if self.args.WITH_MQTT:
|
||||
if useRandomDevID:
|
||||
mqttAddr = '{:016X}'.format(random.randint(1, 0x7FFFFFF))
|
||||
else:
|
||||
mqttAddr = guestDev.mqttDevID
|
||||
addr['mqtt'] = mqttAddr
|
||||
if self.args.WITH_SMS: addr['sms'] = guestDev.smsNumber
|
||||
remotes.append({'addr': addr})
|
||||
|
||||
|
@ -439,7 +447,7 @@ class Device():
|
|||
if response['success']:
|
||||
for guestDev in guestDevs:
|
||||
guestDev.expectInvite(game.gid, game.rematchLevel)
|
||||
game.needsInvite = False
|
||||
game.needsInvite = useRandomDevID
|
||||
|
||||
def expectInvite(self, gid, rematchLevel):
|
||||
self.guestGames.append(GuestGameInfo(self, gid, rematchLevel))
|
||||
|
@ -824,6 +832,9 @@ def mkParser():
|
|||
help='what percent of moves will trade tiles')
|
||||
parser.add_argument('--sub7-trades-pct', dest = 'SUB7_TRADES_PCT', default = 10, type=int)
|
||||
|
||||
parser.add_argument('--bad-invite-pct', dest = 'BAD_INVITE_PCT', default = 0, type=int,
|
||||
help='What pct (0..99) of MQTT invitations will be to non-existant devices')
|
||||
|
||||
parser.add_argument('--timer-seconds', dest='TIMER_SECS', default=10, type=int,
|
||||
help='Enable game timer with game this many seconds long')
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue