do a better job of rejecting messages that have strayed in from a different game.

This commit is contained in:
ehouse 2006-09-15 07:33:59 +00:00
parent 5d64862ba6
commit e61414933f

View file

@ -494,6 +494,7 @@ comms_getInitialAddr( CommsAddrRec* addr )
#ifdef XWFEATURE_BLUETOOTH #ifdef XWFEATURE_BLUETOOTH
addr->conType = COMMS_CONN_BT; /* for temporary ease in debugging */ addr->conType = COMMS_CONN_BT; /* for temporary ease in debugging */
#else #else
addr->conType = COMMS_CONN_RELAY; /* for temporary ease in debugging */
addr->u.ip_relay.ipAddr = 0L; /* force 'em to set it */ addr->u.ip_relay.ipAddr = 0L; /* force 'em to set it */
addr->u.ip_relay.port = 10999; addr->u.ip_relay.port = 10999;
{ {
@ -622,44 +623,44 @@ removeFromQueue( CommsCtxt* comms, XP_PlayerAddr channelNo, MsgID msgID )
XP_STATUSF( "looking to remove msgs prior or equal to " XP_LD XP_STATUSF( "looking to remove msgs prior or equal to " XP_LD
" for channel %d (queue len now %d)", " for channel %d (queue len now %d)",
msgID, channelNo, comms->queueLen ); msgID, channelNo, comms->queueLen );
for ( prev = (MsgQueueElem*)NULL, elem = comms->msgQueueHead; for ( prev = (MsgQueueElem*)NULL, elem = comms->msgQueueHead;
!!elem; prev = elem, elem = elem->next ) { !!elem; prev = elem, elem = elem->next ) {
/* remove the 0-channel message if we've established a channel number. /* remove the 0-channel message if we've established a channel number.
Only clients should have any 0-channel messages in the queue, and Only clients should have any 0-channel messages in the queue, and
receiving something from the server is an implicit ACK */ receiving something from the server is an implicit ACK */
if ( elem->channelNo == 0 && channelNo != 0 ) { if ( elem->channelNo == 0 && channelNo != 0 ) {
XP_ASSERT( !comms->isServer ); /* I've seen this fail once */ XP_ASSERT( !comms->isServer ); /* I've seen this fail once */
XP_ASSERT( elem->msgID == 0 ); /* will the check below pass? */ XP_ASSERT( elem->msgID == 0 ); /* will the check below pass? */
} else if ( elem->channelNo != channelNo ) { } else if ( elem->channelNo != channelNo ) {
continue; continue;
} }
if ( elem->msgID <= msgID ) { if ( elem->msgID <= msgID ) {
if ( !prev ) { /* it's the first element */ if ( !prev ) { /* it's the first element */
comms->msgQueueHead = elem->next; comms->msgQueueHead = elem->next;
prev = comms->msgQueueHead; /* so elem=prev below will work */ prev = comms->msgQueueHead; /* so elem=prev below will work */
} else { } else {
prev->next = elem->next; prev->next = elem->next;
} }
if ( comms->msgQueueTail == elem ) { if ( comms->msgQueueTail == elem ) {
comms->msgQueueTail = prev; comms->msgQueueTail = prev;
} }
XP_FREE( comms->mpool, elem->msg ); XP_FREE( comms->mpool, elem->msg );
XP_FREE( comms->mpool, elem ); XP_FREE( comms->mpool, elem );
elem = prev; elem = prev;
--comms->queueLen; --comms->queueLen;
if ( !elem ) { if ( !elem ) {
break; break;
} }
} }
} }
XP_STATUSF( "removeFromQueue: queueLen now %d", comms->queueLen ); XP_STATUSF( "removeFromQueue: queueLen now %d", comms->queueLen );
@ -853,52 +854,58 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
if ( stream_getSize( stream ) if ( stream_getSize( stream )
>= sizeof(channelNo) + sizeof(msgID) + sizeof(lastMsgRcd) ) { >= sizeof(channelNo) + sizeof(msgID) + sizeof(lastMsgRcd) ) {
validMessage = XP_TRUE;
channelNo = stream_getU16( stream ); channelNo = stream_getU16( stream );
msgID = stream_getU32( stream ); XP_STATUSF( "read channelNo %d", channelNo );
lastMsgRcd = stream_getU32( stream ); if ( channelNo == 0 || channelNo <= comms->nextChannelNo ) {
XP_DEBUGF( "rcd: msg " XP_LD " on chnl %d", msgID, channelNo ); validMessage = XP_TRUE;
removeFromQueue( comms, channelNo, lastMsgRcd ); msgID = stream_getU32( stream );
lastMsgRcd = stream_getU32( stream );
/* Problem: need to detect duplicate messages even before the XP_DEBUGF( "rcd: msg " XP_LD " on chnl %d", msgID,
server's had a chance to assign channels. Solution, which channelNo );
is a hack: since hostID does the same thing, use it in the
relay case. But in the relay-less case, which still needs
to work, do assign channels. The dup message problem is
far less common there. */
if ( channelNo == 0 ) { removeFromQueue( comms, channelNo, lastMsgRcd );
XP_ASSERT( comms->isServer );
if ( usingRelay ) { /* Problem: need to detect duplicate messages even before
XP_ASSERT( senderID != 0 ); the server's had a chance to assign channels.
channelNo = senderID; Solution, which is a hack: since hostID does the same
} else { thing, use it in the relay case. But in the relay-less
XP_ASSERT( msgID == 0 ); case, which still needs to work, do assign channels.
channelNo = ++comms->nextChannelNo; The dup message problem is far less common there. */
channelWas0 = XP_TRUE;
} if ( channelNo == 0 ) {
XP_STATUSF( "assigning channelNo=%d", channelNo ); XP_ASSERT( comms->isServer );
} if ( usingRelay ) {
if ( usingRelay || !channelWas0 ) { XP_ASSERT( senderID != 0 );
recs = getRecordFor( comms, channelNo ); channelNo = senderID;
/* messageID for an incomming message should be one } else {
* greater than the id most recently used for that XP_ASSERT( msgID == 0 );
* channel. */ channelNo = ++comms->nextChannelNo;
if ( !!recs && (msgID != recs->lastMsgReceived + 1) ) { channelWas0 = XP_TRUE;
XP_DEBUGF( "on channel %d, old msgID " XP_LD }
" (next should be " XP_LD ")", channelNo, XP_STATUSF( "assigning channelNo=%d", channelNo );
msgID, recs->lastMsgReceived+1 ); }
validMessage = XP_FALSE; if ( usingRelay || !channelWas0 ) {
} recs = getRecordFor( comms, channelNo );
/* messageID for an incomming message should be one
* greater than the id most recently used for that
* channel. */
if ( !!recs && (msgID != recs->lastMsgReceived + 1) ) {
XP_DEBUGF( "on channel %d, old msgID " XP_LD
" (next should be " XP_LD ")", channelNo,
msgID, recs->lastMsgReceived+1 );
validMessage = XP_FALSE;
}
#ifdef DEBUG #ifdef DEBUG
if ( !!recs ) { if ( !!recs ) {
XP_ASSERT( lastMsgRcd < 0x0000FFFF ); XP_ASSERT( lastMsgRcd <= recs->nextMsgID );
recs->lastACK = (XP_U16)lastMsgRcd; XP_ASSERT( lastMsgRcd < 0x0000FFFF );
} recs->lastACK = (XP_U16)lastMsgRcd;
}
#endif #endif
}
} }
if ( validMessage ) { if ( validMessage ) {
@ -925,6 +932,7 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
} else { } else {
XP_LOGF( "%s: message too small", __FUNCTION__ ); XP_LOGF( "%s: message too small", __FUNCTION__ );
} }
LOG_RETURNF( "%d", (XP_U16)validMessage );
return validMessage; return validMessage;
} /* comms_checkIncomingStream */ } /* comms_checkIncomingStream */