mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-17 18:12:01 +01:00
add support for relay for use by NAT'd/firewalled devices: cellphones.
Include cookie users will agree on on for relay rendevouz, and sender/receiver IDs for when there are >2 devices in game. Supports games between linux clients now, but needs a lot more work.
This commit is contained in:
parent
71870695cc
commit
cb3a3854e9
1 changed files with 77 additions and 39 deletions
|
@ -27,6 +27,7 @@
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "xwstream.h"
|
#include "xwstream.h"
|
||||||
#include "memstream.h"
|
#include "memstream.h"
|
||||||
|
#include "strutils.h"
|
||||||
|
|
||||||
#define cEND 0x65454e44
|
#define cEND 0x65454e44
|
||||||
|
|
||||||
|
@ -42,6 +43,8 @@ typedef struct MsgQueueElem {
|
||||||
MsgID msgID;
|
MsgID msgID;
|
||||||
} MsgQueueElem;
|
} MsgQueueElem;
|
||||||
|
|
||||||
|
typedef XP_U16 HostID;
|
||||||
|
|
||||||
typedef struct AddressRecord {
|
typedef struct AddressRecord {
|
||||||
struct AddressRecord* next;
|
struct AddressRecord* next;
|
||||||
CommsAddrRec addr;
|
CommsAddrRec addr;
|
||||||
|
@ -52,6 +55,7 @@ typedef struct AddressRecord {
|
||||||
MsgID nextMsgID; /* on a per-channel basis */
|
MsgID nextMsgID; /* on a per-channel basis */
|
||||||
MsgID lastMsgReceived; /* on a per-channel basis */
|
MsgID lastMsgReceived; /* on a per-channel basis */
|
||||||
XP_PlayerAddr channelNo;
|
XP_PlayerAddr channelNo;
|
||||||
|
HostID remotesID;
|
||||||
} AddressRecord;
|
} AddressRecord;
|
||||||
|
|
||||||
#define ADDRESSRECORD_SIZE_68K 20
|
#define ADDRESSRECORD_SIZE_68K 20
|
||||||
|
@ -62,6 +66,7 @@ struct CommsCtxt {
|
||||||
XP_U32 connID; /* 0 means ignore; otherwise must match */
|
XP_U32 connID; /* 0 means ignore; otherwise must match */
|
||||||
XP_U16 nextChannelNo;
|
XP_U16 nextChannelNo;
|
||||||
AddressRecord* recs; /* return addresses */
|
AddressRecord* recs; /* return addresses */
|
||||||
|
HostID localID; /* allows relay to match host with socket */
|
||||||
|
|
||||||
TransportSend sendproc;
|
TransportSend sendproc;
|
||||||
void* sendClosure;
|
void* sendClosure;
|
||||||
|
@ -87,6 +92,7 @@ struct CommsCtxt {
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static AddressRecord* rememberChannelAddress( CommsCtxt* comms,
|
static AddressRecord* rememberChannelAddress( CommsCtxt* comms,
|
||||||
XP_PlayerAddr channelNo,
|
XP_PlayerAddr channelNo,
|
||||||
|
HostID hostID,
|
||||||
CommsAddrRec* addr );
|
CommsAddrRec* addr );
|
||||||
static XP_Bool channelToAddress( CommsCtxt* comms, XP_PlayerAddr channelNo,
|
static XP_Bool channelToAddress( CommsCtxt* comms, XP_PlayerAddr channelNo,
|
||||||
CommsAddrRec** addr );
|
CommsAddrRec** addr );
|
||||||
|
@ -103,6 +109,7 @@ CommsCtxt*
|
||||||
comms_make( MPFORMAL XW_UtilCtxt* util, XP_Bool isServer,
|
comms_make( MPFORMAL XW_UtilCtxt* util, XP_Bool isServer,
|
||||||
TransportSend sendproc, void* closure )
|
TransportSend sendproc, void* closure )
|
||||||
{
|
{
|
||||||
|
HostID localID;
|
||||||
CommsCtxt* result = (CommsCtxt*)XP_MALLOC( mpool, sizeof(*result) );
|
CommsCtxt* result = (CommsCtxt*)XP_MALLOC( mpool, sizeof(*result) );
|
||||||
XP_MEMSET( result, 0, sizeof(*result) );
|
XP_MEMSET( result, 0, sizeof(*result) );
|
||||||
|
|
||||||
|
@ -124,6 +131,10 @@ comms_make( MPFORMAL XW_UtilCtxt* util, XP_Bool isServer,
|
||||||
XP_MEMCPY( result->addr.u.ip.hostName, name, XP_STRLEN(name) );
|
XP_MEMCPY( result->addr.u.ip.hostName, name, XP_STRLEN(name) );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
do {
|
||||||
|
localID = XP_RANDOM();
|
||||||
|
} while ( localID == 0 );
|
||||||
|
result->localID = localID;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} /* comms_make */
|
} /* comms_make */
|
||||||
|
@ -375,6 +386,7 @@ comms_send( CommsCtxt* comms, CommsConnType conType, XWStreamCtxt* stream )
|
||||||
AddressRecord* rec = getRecordFor( comms, channelNo );
|
AddressRecord* rec = getRecordFor( comms, channelNo );
|
||||||
MsgID msgID = (!!rec)? ++rec->nextMsgID : 0;
|
MsgID msgID = (!!rec)? ++rec->nextMsgID : 0;
|
||||||
MsgID lastMsgRcd = (!!rec)? rec->lastMsgReceived : 0;
|
MsgID lastMsgRcd = (!!rec)? rec->lastMsgReceived : 0;
|
||||||
|
HostID remotesID = (!!rec)? rec->remotesID : 0;
|
||||||
MsgQueueElem* newMsgElem;
|
MsgQueueElem* newMsgElem;
|
||||||
XWStreamCtxt* msgStream;
|
XWStreamCtxt* msgStream;
|
||||||
|
|
||||||
|
@ -398,16 +410,24 @@ comms_send( CommsCtxt* comms, CommsConnType conType, XWStreamCtxt* stream )
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
(MemStreamCloseCallback)NULL );
|
(MemStreamCloseCallback)NULL );
|
||||||
stream_open( msgStream );
|
stream_open( msgStream );
|
||||||
stream_putU32( msgStream, comms->connID );
|
|
||||||
|
|
||||||
#ifdef BEYOND_IR
|
#ifdef BEYOND_IR
|
||||||
if ( conType == COMMS_CONN_IP ) {
|
/* This will change, of course!!! */
|
||||||
stream_putU16( msgStream, comms->listenPort );
|
stringToStream( msgStream, "COOKIE" );
|
||||||
XP_LOGF( "wrote return port to stream: %d", comms->listenPort );
|
stream_putU16( msgStream, comms->localID );
|
||||||
}
|
XP_LOGF( "localID = 0x%x", comms->localID );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
stream_putU32( msgStream, comms->connID );
|
||||||
|
XP_LOGF( "connID: %ld", comms->connID );
|
||||||
|
|
||||||
stream_putU16( msgStream, channelNo );
|
stream_putU16( msgStream, channelNo );
|
||||||
|
XP_LOGF( "channelNo: %d", channelNo );
|
||||||
|
#ifdef BEYOND_IR
|
||||||
|
stream_putU16( msgStream, remotesID ); /* for the relay's use */
|
||||||
|
XP_LOGF( "remotesID = %ld", remotesID );
|
||||||
|
#endif
|
||||||
|
/* Beyond this point the relay doesn't peek */
|
||||||
stream_putU32( msgStream, msgID );
|
stream_putU32( msgStream, msgID );
|
||||||
stream_putU32( msgStream, lastMsgRcd );
|
stream_putU32( msgStream, lastMsgRcd );
|
||||||
|
|
||||||
|
@ -585,20 +605,30 @@ comms_checkIncommingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||||
MsgID lastMsgRcd;
|
MsgID lastMsgRcd;
|
||||||
XP_Bool validMessage = XP_TRUE;
|
XP_Bool validMessage = XP_TRUE;
|
||||||
AddressRecord* recs = (AddressRecord*)NULL;
|
AddressRecord* recs = (AddressRecord*)NULL;
|
||||||
|
XP_UCHAR* cookie;
|
||||||
|
HostID senderID, hostID;
|
||||||
|
|
||||||
|
#ifdef BEYOND_IR
|
||||||
|
cookie = stringFromStream( MPPARM(comms->mpool) stream );
|
||||||
|
XP_LOGF( "got cookie %s from message", cookie );
|
||||||
|
XP_ASSERT( 0 == XP_MEMCMP( cookie, "COOKIE", 6 ) );
|
||||||
|
senderID = stream_getU16( stream );
|
||||||
|
XP_LOGF( "senderID = 0x%x", senderID );
|
||||||
|
#endif
|
||||||
|
|
||||||
connID = stream_getU32( stream );
|
connID = stream_getU32( stream );
|
||||||
XP_STATUSF( "read connID of %lx", connID );
|
XP_STATUSF( "read connID of %lx", connID );
|
||||||
|
|
||||||
#ifdef BEYOND_IR
|
if ( senderID != 0 && senderID == comms->localID ) {
|
||||||
if ( addr->conType == COMMS_CONN_IP ) {
|
validMessage = XP_FALSE; /* hack around relay bug */
|
||||||
addr->u.ip.port = stream_getU16( stream );
|
} else if ( comms->connID == connID || comms->connID == CONN_ID_NONE ) {
|
||||||
XP_LOGF( "read return port from stream: %d", addr->u.ip.port );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( comms->connID == connID || comms->connID == CONN_ID_NONE ) {
|
|
||||||
|
|
||||||
channelNo = stream_getU16( stream );
|
channelNo = stream_getU16( stream );
|
||||||
|
#ifdef BEYOND_IR
|
||||||
|
hostID = stream_getU16( stream );
|
||||||
|
XP_LOGF( "got hostID: %d", hostID );
|
||||||
|
XP_ASSERT( hostID == 0 || hostID == comms->localID );
|
||||||
|
#endif
|
||||||
msgID = stream_getU32( stream );
|
msgID = stream_getU32( stream );
|
||||||
lastMsgRcd = stream_getU32( stream );
|
lastMsgRcd = stream_getU32( stream );
|
||||||
|
|
||||||
|
@ -607,10 +637,13 @@ comms_checkIncommingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||||
removeFromQueue( comms, channelNo, lastMsgRcd );
|
removeFromQueue( comms, channelNo, lastMsgRcd );
|
||||||
|
|
||||||
if ( channelNo == 0 ) {
|
if ( channelNo == 0 ) {
|
||||||
XP_ASSERT( comms->isServer );
|
if ( !comms->isServer ) {
|
||||||
XP_ASSERT( msgID == 0 );
|
validMessage = XP_FALSE;
|
||||||
channelNo = ++comms->nextChannelNo;
|
} else {
|
||||||
XP_STATUSF( "assigning channelNo=%d", channelNo );
|
XP_ASSERT( msgID == 0 );
|
||||||
|
channelNo = ++comms->nextChannelNo;
|
||||||
|
XP_STATUSF( "assigning channelNo=%d", channelNo );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
recs = getRecordFor( comms, channelNo );
|
recs = getRecordFor( comms, channelNo );
|
||||||
/* messageID for an incomming message should be one greater than
|
/* messageID for an incomming message should be one greater than
|
||||||
|
@ -629,7 +662,7 @@ comms_checkIncommingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( validMessage ) {
|
if ( validMessage ) {
|
||||||
recs = rememberChannelAddress( comms, channelNo, addr );
|
recs = rememberChannelAddress( comms, channelNo, senderID, addr);
|
||||||
|
|
||||||
stream_setAddress( stream, channelNo );
|
stream_setAddress( stream, channelNo );
|
||||||
|
|
||||||
|
@ -689,27 +722,32 @@ comms_getStats( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||||
|
|
||||||
static AddressRecord*
|
static AddressRecord*
|
||||||
rememberChannelAddress( CommsCtxt* comms, XP_PlayerAddr channelNo,
|
rememberChannelAddress( CommsCtxt* comms, XP_PlayerAddr channelNo,
|
||||||
CommsAddrRec* addr )
|
HostID hostID, CommsAddrRec* addr )
|
||||||
{
|
{
|
||||||
AddressRecord* recs = NULL;
|
AddressRecord* recs = NULL;
|
||||||
if ( addr != NULL ) {
|
recs = getRecordFor( comms, channelNo );
|
||||||
recs = getRecordFor( comms, channelNo );
|
if ( !recs ) {
|
||||||
if ( !!recs ) {
|
/* not found; add a new entry */
|
||||||
/* Looks as if this will overwrite the address each time a new
|
recs = (AddressRecord*)XP_MALLOC( comms->mpool, sizeof(*recs) );
|
||||||
message comes in. I *guess* that's right... */
|
|
||||||
XP_MEMCPY( &recs->addr, addr, sizeof(recs->addr) );
|
|
||||||
} else {
|
|
||||||
/* not found; add a new entry */
|
|
||||||
recs = (AddressRecord*)XP_MALLOC( comms->mpool, sizeof(*recs) );
|
|
||||||
|
|
||||||
recs->nextMsgID = 0;
|
recs->nextMsgID = 0;
|
||||||
recs->channelNo = channelNo;
|
recs->channelNo = channelNo;
|
||||||
XP_MEMCPY( &recs->addr, addr, sizeof(recs->addr) );
|
recs->remotesID = hostID;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
recs->nUniqueBytes = 0;
|
recs->nUniqueBytes = 0;
|
||||||
#endif
|
#endif
|
||||||
recs->next = comms->recs;
|
recs->next = comms->recs;
|
||||||
comms->recs = recs;
|
comms->recs = recs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* overwrite existing address with new one. I assume that's the right
|
||||||
|
move. */
|
||||||
|
if ( !!recs ) {
|
||||||
|
if ( !!addr ) {
|
||||||
|
XP_MEMCPY( &recs->addr, addr, sizeof(recs->addr) );
|
||||||
|
XP_ASSERT( recs->remotesID == hostID );
|
||||||
|
} else {
|
||||||
|
XP_MEMSET( &recs->addr, 0, sizeof(recs->addr) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return recs;
|
return recs;
|
||||||
|
@ -735,13 +773,13 @@ getRecordFor( CommsCtxt* comms, XP_PlayerAddr channelNo )
|
||||||
AddressRecord* recs;
|
AddressRecord* recs;
|
||||||
|
|
||||||
if ( channelNo == CHANNEL_NONE ) {
|
if ( channelNo == CHANNEL_NONE ) {
|
||||||
return (AddressRecord*)NULL;
|
return (AddressRecord*)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( recs = comms->recs; !!recs; recs = recs->next ) {
|
for ( recs = comms->recs; !!recs; recs = recs->next ) {
|
||||||
if ( recs->channelNo == channelNo ) {
|
if ( recs->channelNo == channelNo ) {
|
||||||
return recs;
|
return recs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (AddressRecord*)NULL;
|
return (AddressRecord*)NULL;
|
||||||
} /* getRecordFor */
|
} /* getRecordFor */
|
||||||
|
|
Loading…
Reference in a new issue