mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-30 10:26:58 +01:00
Re-add direct-via-ip transport, and implement for linux in order to
better test heartbeats. Fix so can play against Palm over BT. Assertions failing on Linux when reset, but it's otherwise done.
This commit is contained in:
parent
044a889d6d
commit
42615345c9
8 changed files with 373 additions and 264 deletions
253
common/comms.c
253
common/comms.c
|
@ -53,14 +53,15 @@ typedef struct MsgQueueElem {
|
|||
XP_U8* msg;
|
||||
XP_U16 len;
|
||||
XP_U16 channelNo;
|
||||
XP_U16 sendCount; /* how many times sent? */
|
||||
MsgID msgID; /* saved for ease of deletion */
|
||||
} MsgQueueElem;
|
||||
|
||||
typedef struct AddressRecord {
|
||||
struct AddressRecord* next;
|
||||
CommsAddrRec addr;
|
||||
#ifdef DEBUG
|
||||
XP_U16 lastACK;
|
||||
#ifdef DEBUG
|
||||
XP_U16 nUniqueBytes;
|
||||
#endif
|
||||
MsgID nextMsgID; /* on a per-channel basis */
|
||||
|
@ -136,11 +137,12 @@ struct CommsCtxt {
|
|||
MPSLOT
|
||||
};
|
||||
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
typedef enum {
|
||||
BTMSG_DATA = 0
|
||||
,BTMSG_RESET
|
||||
} BTMsgType;
|
||||
BTIPMSG_NONE = 0
|
||||
,BTIPMSG_DATA
|
||||
,BTIPMSG_RESET
|
||||
} BTIPMsgType;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -157,6 +159,8 @@ static AddressRecord* getRecordFor( CommsCtxt* comms,
|
|||
static XP_S16 sendMsg( CommsCtxt* comms, MsgQueueElem* elem );
|
||||
static void addToQueue( CommsCtxt* comms, MsgQueueElem* newMsgElem );
|
||||
static XP_U16 countAddrRecs( const CommsCtxt* comms );
|
||||
static void sendConnect( CommsCtxt* comms );
|
||||
|
||||
#ifdef XWFEATURE_RELAY
|
||||
static void relayConnect( CommsCtxt* comms );
|
||||
static void relayDisconnect( CommsCtxt* comms );
|
||||
|
@ -166,12 +170,13 @@ static XWHostID getDestID( CommsCtxt* comms, XP_PlayerAddr channelNo );
|
|||
#endif
|
||||
#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT
|
||||
static void setHeartbeatTimer( CommsCtxt* comms );
|
||||
#else
|
||||
# define setHeartbeatTimer( comms )
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
static XP_S16 send_via_bt( CommsCtxt* comms, BTMsgType typ,
|
||||
XP_PlayerAddr channelNo,
|
||||
void* data, int dlen );
|
||||
static void btConnect( CommsCtxt* comms );
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
static XP_S16 send_via_bt_or_ip( CommsCtxt* comms, BTIPMsgType typ,
|
||||
XP_PlayerAddr channelNo,
|
||||
void* data, int dlen );
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -299,7 +304,7 @@ addrFromStream( CommsAddrRec* addrP, XWStreamCtxt* stream )
|
|||
case COMMS_CONN_IR:
|
||||
/* nothing to save */
|
||||
break;
|
||||
case COMMS_CONN_IP_NOUSE:
|
||||
case COMMS_CONN_IP_DIRECT:
|
||||
stringFromStreamHere( stream, addr.u.ip.hostName_ip,
|
||||
sizeof(addr.u.ip.hostName_ip) );
|
||||
addr.u.ip.ipAddr_ip = stream_getU32( stream );
|
||||
|
@ -398,7 +403,9 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util,
|
|||
|
||||
msg->channelNo = stream_getU16( stream );
|
||||
msg->msgID = stream_getU32( stream );
|
||||
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
msg->sendCount = 0;
|
||||
#endif
|
||||
msg->len = stream_getU16( stream );
|
||||
msg->msg = (XP_U8*)XP_MALLOC( mpool, msg->len );
|
||||
stream_getBytes( stream, msg->msg, msg->len );
|
||||
|
@ -419,21 +426,36 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util,
|
|||
void
|
||||
comms_start( CommsCtxt* comms )
|
||||
{
|
||||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
} else if ( comms->addr.conType == COMMS_CONN_RELAY ) {
|
||||
comms->r.relayState = COMMS_RELAYSTATE_UNCONNECTED;
|
||||
relayConnect( comms );
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( comms->addr.conType == COMMS_CONN_BT ) {
|
||||
btConnect( comms );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
comms->doHeartbeat = comms->addr.conType != COMMS_CONN_IR;
|
||||
#endif
|
||||
|
||||
sendConnect( comms );
|
||||
} /* comms_start */
|
||||
|
||||
static void
|
||||
sendConnect( CommsCtxt* comms )
|
||||
{
|
||||
switch( comms->addr.conType ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
case COMMS_CONN_RELAY:
|
||||
comms->r.relayState = COMMS_RELAYSTATE_UNCONNECTED;
|
||||
relayConnect( comms );
|
||||
break;
|
||||
#endif
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
case COMMS_CONN_BT:
|
||||
case COMMS_CONN_IP_DIRECT:
|
||||
send_via_bt_or_ip( comms, BTIPMSG_RESET,
|
||||
CHANNEL_NONE, NULL, 0 );
|
||||
(void)comms_resendAll( comms );
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setHeartbeatTimer( comms );
|
||||
} /* comms_start */
|
||||
|
||||
static void
|
||||
|
@ -460,7 +482,7 @@ addrToStream( XWStreamCtxt* stream, const CommsAddrRec* addrP )
|
|||
case COMMS_CONN_IR:
|
||||
/* nothing to save */
|
||||
break;
|
||||
case COMMS_CONN_IP_NOUSE:
|
||||
case COMMS_CONN_IP_DIRECT:
|
||||
stringToStream( stream, addr.u.ip.hostName_ip );
|
||||
stream_putU32( stream, addr.u.ip.ipAddr_ip );
|
||||
stream_putU16( stream, addr.u.ip.port_ip );
|
||||
|
@ -546,22 +568,16 @@ void
|
|||
comms_setAddr( CommsCtxt* comms, const CommsAddrRec* addr )
|
||||
{
|
||||
XP_ASSERT( comms != NULL );
|
||||
#if defined XWFEATURE_RELAY || defined XWFEATURE_BLUETOOTH
|
||||
#if defined XWFEATURE_RELAY || defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
util_addrChange( comms->util, &comms->addr, addr );
|
||||
#endif
|
||||
XP_MEMCPY( &comms->addr, addr, sizeof(comms->addr) );
|
||||
|
||||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
/* We should now have a cookie so we can connect??? */
|
||||
} else if ( addr->conType == COMMS_CONN_RELAY ) {
|
||||
relayConnect( comms );
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
comms->doHeartbeat = comms->addr.conType != COMMS_CONN_IR;
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( addr->conType == COMMS_CONN_BT ) {
|
||||
btConnect( comms );
|
||||
#endif
|
||||
}
|
||||
sendConnect( comms );
|
||||
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
comms->doHeartbeat = comms->addr.conType != COMMS_CONN_IR;
|
||||
#endif
|
||||
|
@ -601,9 +617,9 @@ comms_getIsServer( const CommsCtxt* comms )
|
|||
return comms->isServer;
|
||||
}
|
||||
|
||||
static XP_S16
|
||||
sendWithID( CommsCtxt* comms, MsgID msgID, AddressRecord* rec,
|
||||
XP_PlayerAddr channelNo, XWStreamCtxt* stream )
|
||||
static MsgQueueElem*
|
||||
makeElemWithID( CommsCtxt* comms, MsgID msgID, AddressRecord* rec,
|
||||
XP_PlayerAddr channelNo, XWStreamCtxt* stream )
|
||||
{
|
||||
XP_U16 headerLen;
|
||||
XP_U16 streamSize = NULL == stream? 0 : stream_getSize( stream );
|
||||
|
@ -623,6 +639,9 @@ sendWithID( CommsCtxt* comms, MsgID msgID, AddressRecord* rec,
|
|||
sizeof( *newMsgElem ) );
|
||||
newMsgElem->channelNo = channelNo;
|
||||
newMsgElem->msgID = msgID;
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
newMsgElem->sendCount = 0;
|
||||
#endif
|
||||
|
||||
msgStream = mem_stream_make( MPPARM(comms->mpool)
|
||||
util_getVTManager(comms->util),
|
||||
|
@ -646,10 +665,8 @@ sendWithID( CommsCtxt* comms, MsgID msgID, AddressRecord* rec,
|
|||
stream_getBytes( stream, newMsgElem->msg + headerLen, streamSize );
|
||||
}
|
||||
|
||||
addToQueue( comms, newMsgElem );
|
||||
|
||||
return sendMsg( comms, newMsgElem );
|
||||
} /* sendWithID */
|
||||
return newMsgElem;
|
||||
} /* makeElemWithID */
|
||||
|
||||
/* Send a message using the sequentially next MsgID. Save the message so
|
||||
* resend can work. */
|
||||
|
@ -659,9 +676,17 @@ comms_send( CommsCtxt* comms, XWStreamCtxt* stream )
|
|||
XP_PlayerAddr channelNo = stream_getAddress( stream );
|
||||
AddressRecord* rec = getRecordFor( comms, channelNo );
|
||||
MsgID msgID = (!!rec)? ++rec->nextMsgID : 0;
|
||||
MsgQueueElem* elem;
|
||||
XP_S16 result = -1;
|
||||
|
||||
XP_DEBUGF( "assigning msgID=" XP_LD " on chnl %d", msgID, channelNo );
|
||||
return sendWithID( comms, msgID, rec, channelNo, stream );
|
||||
|
||||
elem = makeElemWithID( comms, msgID, rec, channelNo, stream );
|
||||
if ( NULL != elem ) {
|
||||
addToQueue( comms, elem );
|
||||
result = sendMsg( comms, elem );
|
||||
}
|
||||
return result;
|
||||
} /* comms_send */
|
||||
|
||||
/* Add new message to the end of the list. The list needs to be kept in order
|
||||
|
@ -702,6 +727,13 @@ printQueue( CommsCtxt* comms )
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
freeElem( const CommsCtxt* comms, MsgQueueElem* elem )
|
||||
{
|
||||
XP_FREE( comms->mpool, elem->msg );
|
||||
XP_FREE( comms->mpool, elem );
|
||||
}
|
||||
|
||||
/* We've received on some channel a message with a certain ID. This means
|
||||
* that all messages sent on that channel with lower IDs have been received
|
||||
* and can be removed from our queue. BUT: if this ID is higher than any
|
||||
|
@ -737,8 +769,7 @@ removeFromQueue( CommsCtxt* comms, XP_PlayerAddr channelNo, MsgID msgID )
|
|||
}
|
||||
|
||||
if ( !knownGood && (elem->msgID <= msgID) ) {
|
||||
XP_FREE( comms->mpool, elem->msg );
|
||||
XP_FREE( comms->mpool, elem );
|
||||
freeElem( comms, elem );
|
||||
--comms->queueLen;
|
||||
} else {
|
||||
keep->next = elem;
|
||||
|
@ -762,7 +793,7 @@ removeFromQueue( CommsCtxt* comms, XP_PlayerAddr channelNo, MsgID msgID )
|
|||
static XP_S16
|
||||
sendMsg( CommsCtxt* comms, MsgQueueElem* elem )
|
||||
{
|
||||
XP_S16 result = 0;
|
||||
XP_S16 result = -1;
|
||||
XP_PlayerAddr channelNo;
|
||||
#if defined XWFEATURE_RELAY || defined XWFEATURE_BLUETOOTH
|
||||
CommsConnType conType = comms_getConType( comms );
|
||||
|
@ -781,10 +812,13 @@ sendMsg( CommsCtxt* comms, MsgQueueElem* elem )
|
|||
XP_LOGF( "%s: skipping message: not connected", __func__ );
|
||||
}
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( conType == COMMS_CONN_BT ) {
|
||||
result = send_via_bt( comms, BTMSG_DATA, channelNo,
|
||||
elem->msg, elem->len );
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
} else if ( conType == COMMS_CONN_BT || conType == COMMS_CONN_IP_DIRECT ) {
|
||||
result = send_via_bt_or_ip( comms, BTIPMSG_DATA, channelNo,
|
||||
elem->msg, elem->len );
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
setHeartbeatTimer( comms );
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
const CommsAddrRec* addr;
|
||||
|
@ -794,6 +828,12 @@ sendMsg( CommsCtxt* comms, MsgQueueElem* elem )
|
|||
result = (*comms->sendproc)( elem->msg, elem->len, addr,
|
||||
comms->sendClosure );
|
||||
}
|
||||
|
||||
if ( result == elem->len ) {
|
||||
++elem->sendCount;
|
||||
XP_LOGF( "sendCount now %d", elem->sendCount );
|
||||
}
|
||||
|
||||
return result;
|
||||
} /* sendMsg */
|
||||
|
||||
|
@ -898,22 +938,51 @@ relayPreProcess( CommsCtxt* comms, XWStreamCtxt* stream, XWHostID* senderID )
|
|||
} /* relayPreProcess */
|
||||
#endif
|
||||
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
static XP_Bool
|
||||
btPreProcess( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||
btIpPreProcess( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||
{
|
||||
BTMsgType typ = (BTMsgType)stream_getU8( stream );
|
||||
XP_Bool consumed = typ != BTMSG_DATA;
|
||||
BTIPMsgType typ = (BTIPMsgType)stream_getU8( stream );
|
||||
XP_Bool consumed = typ != BTIPMSG_DATA;
|
||||
|
||||
if ( consumed ) {
|
||||
XP_ASSERT( typ == BTMSG_RESET );
|
||||
/* This is all there is so far */
|
||||
XP_ASSERT( typ == BTIPMSG_RESET );
|
||||
(void)comms_resendAll( comms );
|
||||
}
|
||||
|
||||
return consumed;
|
||||
} /* btPreProcess */
|
||||
} /* btIpPreProcess */
|
||||
#endif
|
||||
|
||||
static XP_Bool
|
||||
preProcess( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||
XP_Bool* usingRelay, XWHostID* senderID )
|
||||
{
|
||||
XP_Bool consumed = XP_FALSE;
|
||||
switch ( comms->addr.conType ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
/* relayPreProcess returns true if consumes the message. May just eat the
|
||||
header and leave a regular message to be processed below. */
|
||||
case COMMS_CONN_RELAY:
|
||||
consumed = relayPreProcess( comms, stream, senderID );
|
||||
if ( !consumed ) {
|
||||
*usingRelay = comms->addr.conType == COMMS_CONN_RELAY;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
case COMMS_CONN_BT:
|
||||
case COMMS_CONN_IP_DIRECT:
|
||||
consumed = btIpPreProcess( comms, stream );
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return consumed;
|
||||
} /* preProcess */
|
||||
|
||||
static XP_Bool
|
||||
addressUnknown( CommsCtxt* comms, const CommsAddrRec* addr )
|
||||
{
|
||||
|
@ -976,27 +1045,10 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
|||
XWHostID senderID = 0; /* unset; default for non-relay cases */
|
||||
XP_Bool usingRelay = XP_FALSE;
|
||||
XP_Bool channelWas0 = XP_FALSE;
|
||||
XP_Bool done = XP_FALSE;
|
||||
|
||||
XP_ASSERT( addr == NULL || comms->addr.conType == addr->conType );
|
||||
|
||||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
/* relayPreProcess returns true if consumes the message. May just eat the
|
||||
header and leave a regular message to be processed below. */
|
||||
} else if ( comms->addr.conType == COMMS_CONN_RELAY ) {
|
||||
done = relayPreProcess( comms, stream, &senderID );
|
||||
if ( !done ) {
|
||||
usingRelay = comms->addr.conType == COMMS_CONN_RELAY;
|
||||
}
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( comms->addr.conType == COMMS_CONN_BT ) {
|
||||
done = btPreProcess( comms, stream );
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( !done ) {
|
||||
if ( !preProcess( comms, stream, &usingRelay, &senderID ) ) {
|
||||
if ( stream_getSize( stream ) >= sizeof(connID) ) {
|
||||
connID = stream_getU32( stream );
|
||||
XP_STATUSF( "%s: read connID of %lx", __func__, connID );
|
||||
|
@ -1073,14 +1125,16 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
|||
}
|
||||
#ifdef DEBUG
|
||||
if ( !!recs ) {
|
||||
XP_ASSERT( lastMsgRcd <= recs->nextMsgID );
|
||||
/* XP_ASSERT( lastMsgRcd <= recs->nextMsgID ); */
|
||||
if ( lastMsgRcd > recs->nextMsgID ) {
|
||||
XP_LOGF( "bad: got lastMsgRcd of %ld, "
|
||||
"nextMsgID is %ld",
|
||||
lastMsgRcd, recs->nextMsgID );
|
||||
validMessage = XP_FALSE;
|
||||
} else {
|
||||
XP_ASSERT( lastMsgRcd < 0x0000FFFF );
|
||||
recs->lastACK = (XP_U16)lastMsgRcd;
|
||||
}
|
||||
XP_ASSERT( lastMsgRcd < 0x0000FFFF );
|
||||
recs->lastACK = (XP_U16)lastMsgRcd;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1146,7 +1200,9 @@ heartbeat_checks( CommsCtxt* comms )
|
|||
|
||||
for ( elem = comms->msgQueueHead; !!elem; elem = elem->next ) {
|
||||
XP_ASSERT( elem->channelNo < MAX_NUM_PLAYERS );
|
||||
++pendingPacks[elem->channelNo];
|
||||
if ( elem->sendCount == 0 ) { /* still waiting being sent? */
|
||||
++pendingPacks[elem->channelNo];
|
||||
}
|
||||
}
|
||||
|
||||
now = util_getCurSeconds( comms->util );
|
||||
|
@ -1154,17 +1210,27 @@ heartbeat_checks( CommsCtxt* comms )
|
|||
for ( rec = comms->recs; !!rec; rec = rec->next ) {
|
||||
XP_U32 lastMsgRcvdTime = rec->lastMsgRcvdTime;
|
||||
if ( lastMsgRcvdTime == 0 ) { /* nothing received yet */
|
||||
XP_LOGF( "no last message" );
|
||||
/* do nothing; or should we send? */
|
||||
} else if ( (lastMsgRcvdTime > 0) && (lastMsgRcvdTime < tooLongAgo) ) {
|
||||
XP_LOGF( "calling reset proc" );
|
||||
XP_LOGF( "calling reset proc; last was %ld secs too long ago",
|
||||
tooLongAgo-lastMsgRcvdTime );
|
||||
(*comms->resetproc)(comms->sendClosure);
|
||||
resetTimer = XP_FALSE;
|
||||
break;
|
||||
} else if ( 0 == pendingPacks[rec->channelNo] ) {
|
||||
XP_LOGF( "sending heartbeat on channel %d", rec->channelNo );
|
||||
sendWithID( comms, rec->lastMsgReceived, rec, rec->channelNo, NULL );
|
||||
MsgQueueElem* hb;
|
||||
XP_LOGF( "sending heartbeat on channel %d with msgID %d",
|
||||
rec->channelNo, rec->lastMsgReceived );
|
||||
hb = makeElemWithID( comms, rec->lastACK, rec, rec->channelNo, NULL );
|
||||
if ( NULL != hb ) {
|
||||
sendMsg( comms, hb );
|
||||
freeElem( comms, hb );
|
||||
} else {
|
||||
XP_ASSERT( XP_FALSE );
|
||||
}
|
||||
} else {
|
||||
XP_LOGF( "All's well" );
|
||||
XP_LOGF( "All's well (%d pending)", pendingPacks[rec->channelNo] );
|
||||
resetTimer = XP_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -1199,6 +1265,7 @@ p_comms_timerFired( void* closure, XWTimerReason XP_UNUSED_DBG(why) )
|
|||
static void
|
||||
setHeartbeatTimer( CommsCtxt* comms )
|
||||
{
|
||||
LOG_FUNC();
|
||||
#ifdef RELAY_HEARTBEAT
|
||||
if ( comms->addr.conType == COMMS_CONN_RELAY ) {
|
||||
util_setTimer( comms->util, TIMER_HEARTBEAT, comms->r.heartbeat,
|
||||
|
@ -1463,22 +1530,10 @@ relayConnect( CommsCtxt* comms )
|
|||
} /* relayConnect */
|
||||
#endif
|
||||
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
static void
|
||||
btConnect( CommsCtxt* comms )
|
||||
{
|
||||
XP_ASSERT( !!comms );
|
||||
/* Ping the bt layer so it'll get sockets set up. PENDING: if I'm server
|
||||
need to do this once per guest record with non-null address. Might as
|
||||
well use real messages if we have 'em. Otherwise a fake size-0 msg. */
|
||||
|
||||
send_via_bt( comms, BTMSG_RESET, CHANNEL_NONE, NULL, 0 );
|
||||
(void)( comms_resendAll( comms ) );
|
||||
} /* btConnect */
|
||||
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT
|
||||
static XP_S16
|
||||
send_via_bt( CommsCtxt* comms, BTMsgType typ, XP_PlayerAddr channelNo,
|
||||
void* data, int dlen )
|
||||
send_via_bt_or_ip( CommsCtxt* comms, BTIPMsgType typ, XP_PlayerAddr channelNo,
|
||||
void* data, int dlen )
|
||||
{
|
||||
XP_U8* buf;
|
||||
XP_S16 nSent = -1;
|
||||
|
@ -1499,7 +1554,7 @@ send_via_bt( CommsCtxt* comms, BTMsgType typ, XP_PlayerAddr channelNo,
|
|||
setHeartbeatTimer( comms );
|
||||
}
|
||||
return nSent;
|
||||
} /* send_via_bt */
|
||||
} /* send_via_bt_or_ip */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef XP_U8 XWHostID;
|
|||
typedef enum {
|
||||
COMMS_CONN_UNUSED, /* I want errors on uninited case */
|
||||
COMMS_CONN_IR,
|
||||
COMMS_CONN_IP_NOUSE,
|
||||
COMMS_CONN_IP_DIRECT,
|
||||
COMMS_CONN_RELAY,
|
||||
COMMS_CONN_BT,
|
||||
|
||||
|
|
|
@ -70,6 +70,10 @@ BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_L2CAP
|
|||
DEFINES += ${BLUETOOTH}
|
||||
DEFINES += -DXWFEATURE_RELAY
|
||||
|
||||
# Support device-to-device connection via UDP, e.g. using wifi on a
|
||||
# LAN or where the host/server isn't behind a firewall.
|
||||
DEFINES += -DXWFEATURE_IP_DIRECT
|
||||
|
||||
# Choose one of these. RELAY_HEARTBEAT means relay (must be compiled
|
||||
# with same -D) works with comms on heartbeat. Works only with relay.
|
||||
# COMMS_HEARTBEAT should work on any comms transport (even IR, but
|
||||
|
@ -106,6 +110,7 @@ OBJ = $(PLATFORM)/linuxmain.o \
|
|||
$(PLATFORM)/cursesletterask.o \
|
||||
$(PLATFORM)/filestream.o \
|
||||
$(PLATFORM)/linuxbt.o \
|
||||
$(PLATFORM)/linuxudp.o \
|
||||
|
||||
# $(PLATFORM)/linuxcommpipe.o \
|
||||
|
||||
|
|
|
@ -665,11 +665,12 @@ static void
|
|||
curses_stop_listening( CursesAppGlobals* globals, int sock )
|
||||
{
|
||||
int count = globals->fdCount;
|
||||
int i, found = 0;
|
||||
int i;
|
||||
bool found = false;
|
||||
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
if ( globals->fdArray[i].fd == sock ) {
|
||||
found = 1;
|
||||
found = true;
|
||||
} else if ( found ) {
|
||||
globals->fdArray[i-1].fd = globals->fdArray[i].fd;
|
||||
}
|
||||
|
@ -680,7 +681,8 @@ curses_stop_listening( CursesAppGlobals* globals, int sock )
|
|||
} /* curses_stop_listening */
|
||||
|
||||
static void
|
||||
curses_socket_changed( void* closure, int oldSock, int newSock )
|
||||
curses_socket_changed( void* closure, int oldSock, int newSock,
|
||||
void** XP_UNUSED(storage) )
|
||||
{
|
||||
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
|
||||
if ( oldSock != -1 ) {
|
||||
|
@ -1014,7 +1016,9 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
|||
|
||||
globals.amServer = isServer;
|
||||
globals.cGlobals.params = params;
|
||||
#ifdef XWFEATURE_RELAY
|
||||
globals.cGlobals.socket = -1;
|
||||
#endif
|
||||
|
||||
globals.cGlobals.socketChanged = curses_socket_changed;
|
||||
globals.cGlobals.socketChangedClosure = &globals;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "main.h"
|
||||
#include "linuxmain.h"
|
||||
#include "linuxbt.h"
|
||||
#include "linuxudp.h"
|
||||
/* #include "gtkmain.h" */
|
||||
|
||||
#include "draw.h"
|
||||
|
@ -59,7 +60,6 @@
|
|||
/* static guint gtkSetupClientSocket( GtkAppGlobals* globals, int sock ); */
|
||||
static void sendOnClose( XWStreamCtxt* stream, void* closure );
|
||||
static XP_Bool file_exists( const char* fileName );
|
||||
static void gtkListenOnSocket( GtkAppGlobals* globals, int newSock );
|
||||
static void setCtrlsForTray( GtkAppGlobals* globals );
|
||||
static void printFinalScores( GtkAppGlobals* globals );
|
||||
|
||||
|
@ -317,6 +317,7 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
|||
XP_U16 gameID;
|
||||
CommsAddrRec addr;
|
||||
|
||||
XP_MEMSET( &addr, 0, sizeof(addr) );
|
||||
addr.conType = params->conType;
|
||||
|
||||
gameID = (XP_U16)util_getCurSeconds( globals->cGlobals.params->util );
|
||||
|
@ -354,6 +355,12 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
|||
>= sizeof(params->connInfo.bt.hostAddr));
|
||||
XP_MEMCPY( &addr.u.bt.btAddr, ¶ms->connInfo.bt.hostAddr,
|
||||
sizeof(params->connInfo.bt.hostAddr) );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
} else if ( addr.conType == COMMS_CONN_IP_DIRECT ) {
|
||||
XP_STRNCPY( addr.u.ip.hostName_ip, params->connInfo.ip.hostName,
|
||||
sizeof(addr.u.ip.hostName_ip) - 1 );
|
||||
addr.u.ip.port_ip = params->connInfo.ip.port;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -378,6 +385,10 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
|||
}
|
||||
}
|
||||
|
||||
if ( !!globals->cGlobals.game.comms ) {
|
||||
comms_start( globals->cGlobals.game.comms );
|
||||
}
|
||||
|
||||
server_do( globals->cGlobals.game.server );
|
||||
|
||||
} /* createOrLoadObjects */
|
||||
|
@ -548,6 +559,9 @@ quit( void* XP_UNUSED(dunno), GtkAppGlobals* globals )
|
|||
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
linux_bt_close( &globals->cGlobals );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
linux_udp_close( &globals->cGlobals );
|
||||
#endif
|
||||
vtmgr_destroy( MEMPOOL globals->cGlobals.params->vtMgr );
|
||||
|
||||
|
@ -1201,7 +1215,7 @@ score_timer_func( gpointer data )
|
|||
return XP_FALSE;
|
||||
} /* score_timer_func */
|
||||
|
||||
#ifdef XWFEATURE_RELAY
|
||||
#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT
|
||||
static gint
|
||||
heartbeat_timer_func( gpointer data )
|
||||
{
|
||||
|
@ -1217,7 +1231,7 @@ heartbeat_timer_func( gpointer data )
|
|||
|
||||
static void
|
||||
gtk_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why,
|
||||
XP_U16 XP_UNUSED_RELAY(when),
|
||||
XP_U16 when,
|
||||
XWTimerProc proc, void* closure )
|
||||
{
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
|
||||
|
@ -1236,7 +1250,7 @@ gtk_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why,
|
|||
(void)gettimeofday( &globals->scoreTv, NULL );
|
||||
|
||||
newSrc = g_timeout_add( 1000, score_timer_func, globals );
|
||||
#ifdef XWFEATURE_RELAY
|
||||
#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT
|
||||
} else if ( why == TIMER_HEARTBEAT ) {
|
||||
newSrc = g_timeout_add( 1000 * when, heartbeat_timer_func, globals );
|
||||
#endif
|
||||
|
@ -1570,17 +1584,26 @@ newConnectionInput( GIOChannel *source,
|
|||
if ( (condition & (G_IO_HUP | G_IO_ERR)) != 0 ) {
|
||||
XP_LOGF( "dropping socket %d", sock );
|
||||
close( sock );
|
||||
#ifdef XWFEATURE_RELAY
|
||||
globals->cGlobals.socket = -1;
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
if ( COMMS_CONN_BT == globals->cGlobals.params->conType ) {
|
||||
linux_bt_socketclosed( &globals->cGlobals, sock );
|
||||
}
|
||||
#endif
|
||||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( COMMS_CONN_BT == globals->cGlobals.params->conType ) {
|
||||
linux_bt_socketclosed( &globals->cGlobals, sock );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
} else if ( COMMS_CONN_IP_DIRECT == globals->cGlobals.params->conType ) {
|
||||
linux_udp_socketclosed( &globals->cGlobals, sock );
|
||||
#endif
|
||||
}
|
||||
keepSource = FALSE; /* remove the event source */
|
||||
|
||||
} else if ( (condition & G_IO_IN) != 0 ) {
|
||||
ssize_t nRead;
|
||||
unsigned char buf[512];
|
||||
CommsAddrRec addr;
|
||||
CommsAddrRec* addrp = NULL;
|
||||
|
||||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
|
@ -1591,6 +1614,11 @@ newConnectionInput( GIOChannel *source,
|
|||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( globals->cGlobals.params->conType == COMMS_CONN_BT ) {
|
||||
nRead = linux_bt_receive( sock, buf, sizeof(buf) );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
} else if ( globals->cGlobals.params->conType == COMMS_CONN_IP_DIRECT ) {
|
||||
addrp = &addr;
|
||||
nRead = linux_udp_receive( sock, buf, sizeof(buf), addrp, &globals->cGlobals );
|
||||
#endif
|
||||
} else {
|
||||
XP_ASSERT( 0 );
|
||||
|
@ -1603,7 +1631,7 @@ newConnectionInput( GIOChannel *source,
|
|||
inboundS = stream_from_msgbuf( &globals->cGlobals, buf, nRead );
|
||||
if ( !!inboundS ) {
|
||||
if ( comms_checkIncomingStream( globals->cGlobals.game.comms,
|
||||
inboundS, NULL ) ) {
|
||||
inboundS, addrp ) ) {
|
||||
redraw =
|
||||
server_receiveMessage(globals->cGlobals.game.server,
|
||||
inboundS );
|
||||
|
@ -1631,40 +1659,50 @@ newConnectionInput( GIOChannel *source,
|
|||
return keepSource; /* FALSE means to remove event source */
|
||||
} /* newConnectionInput */
|
||||
|
||||
/* Make gtk listen for events on the socket that clients will use to
|
||||
* connect to us.
|
||||
*/
|
||||
static void
|
||||
gtkListenOnSocket( GtkAppGlobals* globals, int newSock )
|
||||
{
|
||||
|
||||
GIOChannel* channel = g_io_channel_unix_new( newSock );
|
||||
guint result = g_io_add_watch( channel,
|
||||
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI,
|
||||
newConnectionInput,
|
||||
globals );
|
||||
XP_LOGF( "g_io_add_watch(%d) => %d", newSock, result );
|
||||
} /* gtkListenOnSocket */
|
||||
typedef struct SockInfo {
|
||||
GIOChannel* channel;
|
||||
guint watch;
|
||||
int socket;
|
||||
} SockInfo;
|
||||
|
||||
static void
|
||||
gtk_socket_changed( void* closure, int oldSock, int newSock )
|
||||
gtk_socket_changed( void* closure, int oldSock, int newSock, void** storage )
|
||||
{
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)closure;
|
||||
SockInfo* info = (SockInfo*)*storage;
|
||||
XP_LOGF( "%s(old:%d; new:%d)", __func__, oldSock, newSock );
|
||||
|
||||
if ( oldSock != -1 ) {
|
||||
g_source_remove( oldSock );
|
||||
XP_LOGF( "Removed %d from gtk's list of listened-to sockets" );
|
||||
XP_ASSERT( info != NULL );
|
||||
g_source_remove( info->watch );
|
||||
g_io_channel_unref( info->channel );
|
||||
XP_FREE( globals->cGlobals.params->util->mpool, info );
|
||||
*storage = NULL;
|
||||
XP_LOGF( "Removed socket %d from gtk's list of listened-to sockets", oldSock );
|
||||
}
|
||||
if ( newSock != -1 ) {
|
||||
gtkListenOnSocket( globals, newSock );
|
||||
info = (SockInfo*)XP_MALLOC( globals->cGlobals.params->util->mpool,
|
||||
sizeof(*info) );
|
||||
GIOChannel* channel = g_io_channel_unix_new( newSock );
|
||||
g_io_channel_set_close_on_unref( channel, TRUE );
|
||||
guint result = g_io_add_watch( channel,
|
||||
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI,
|
||||
newConnectionInput,
|
||||
globals );
|
||||
info->channel = channel;
|
||||
info->watch = result;
|
||||
*storage = info;
|
||||
XP_LOGF( "g_io_add_watch(%d) => %d", newSock, result );
|
||||
}
|
||||
#ifdef XWFEATURE_RELAY
|
||||
globals->cGlobals.socket = newSock;
|
||||
|
||||
#endif
|
||||
/* A hack for the bluetooth case. */
|
||||
CommsCtxt* comms = globals->cGlobals.game.comms;
|
||||
if ( comms != NULL ) {
|
||||
if ( (comms != NULL) && (comms_getConType(comms) == COMMS_CONN_BT) ) {
|
||||
comms_resendAll( comms );
|
||||
}
|
||||
LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1739,7 +1777,9 @@ gtkmain( LaunchParams* params, int argc, char *argv[] )
|
|||
|
||||
globals.cGlobals.params = params;
|
||||
globals.cGlobals.lastNTilesToUse = MAX_TRAY_TILES;
|
||||
#ifdef XWFEATURE_RELAY
|
||||
globals.cGlobals.socket = -1;
|
||||
#endif
|
||||
|
||||
globals.cGlobals.socketChanged = gtk_socket_changed;
|
||||
globals.cGlobals.socketChangedClosure = &globals;
|
||||
|
|
124
linux/linuxbt.c
124
linux/linuxbt.c
|
@ -42,7 +42,7 @@
|
|||
#include "comms.h"
|
||||
#include "strutils.h"
|
||||
|
||||
#define MAX_CLIENTS 3
|
||||
#define MAX_CLIENTS 1
|
||||
|
||||
#if defined BT_USE_L2CAP
|
||||
# define L2_RF_ADDR struct sockaddr_l2
|
||||
|
@ -50,81 +50,22 @@
|
|||
# define L2_RF_ADDR struct sockaddr_rc
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct BtaddrSockMap {
|
||||
bdaddr_t btaddr;
|
||||
int sock;
|
||||
} BtaddrSockMap;
|
||||
|
||||
typedef struct LinBtStuff {
|
||||
CommonGlobals* globals;
|
||||
|
||||
void* sockStorage;
|
||||
union {
|
||||
struct {
|
||||
BtaddrSockMap socks[MAX_CLIENTS];
|
||||
int listener; /* socket */
|
||||
XP_U16 nSocks;
|
||||
XP_Bool threadDie;
|
||||
sdp_session_t* session;
|
||||
} master;
|
||||
} u;
|
||||
|
||||
/* A single socket's fine as long as there's only one client allowed. */
|
||||
int socket;
|
||||
XP_Bool amMaster;
|
||||
} LinBtStuff;
|
||||
|
||||
static void
|
||||
lbt_addSock( LinBtStuff* btStuff, const bdaddr_t* btaddr, int sock )
|
||||
{
|
||||
XP_U16 i;
|
||||
XP_Bool done = XP_FALSE;
|
||||
|
||||
XP_ASSERT( btStuff->amMaster );
|
||||
XP_ASSERT( btStuff->u.master.nSocks < MAX_CLIENTS - 1 );
|
||||
|
||||
/* first look for an older entry for the same device. If found, close the
|
||||
socket and replace. No change in nSocks. */
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||
if ( (mp->sock != -1) && (0 == memcmp( btaddr, &mp->btaddr, sizeof(*btaddr) )) ) {
|
||||
(void)close( mp->sock );
|
||||
mp->sock = sock;
|
||||
done = XP_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !done ) {
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||
if ( mp->sock == -1 ) {
|
||||
XP_MEMCPY( &mp->btaddr, btaddr, sizeof(mp->btaddr) );
|
||||
mp->sock = sock;
|
||||
++btStuff->u.master.nSocks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
XP_ASSERT( i < MAX_CLIENTS );
|
||||
} /* lbt_addSock */
|
||||
|
||||
static void
|
||||
lbt_removeSock( LinBtStuff* btStuff, int sock )
|
||||
{
|
||||
XP_U16 i;
|
||||
|
||||
XP_ASSERT( btStuff->amMaster );
|
||||
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||
if ( mp->sock == sock ) {
|
||||
mp->sock = -1;
|
||||
XP_ASSERT( btStuff->u.master.nSocks > 0 );
|
||||
--btStuff->u.master.nSocks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* lbt_removeSock */
|
||||
|
||||
static LinBtStuff*
|
||||
lbt_make( MPFORMAL XP_Bool amMaster )
|
||||
{
|
||||
|
@ -132,13 +73,7 @@ lbt_make( MPFORMAL XP_Bool amMaster )
|
|||
XP_MEMSET( btStuff, 0, sizeof(*btStuff) );
|
||||
|
||||
btStuff->amMaster = amMaster;
|
||||
|
||||
if ( amMaster ) {
|
||||
XP_U16 i;
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
btStuff->u.master.socks[i].sock = -1;
|
||||
}
|
||||
}
|
||||
btStuff->socket = -1;
|
||||
|
||||
return btStuff;
|
||||
} /* lbt_make */
|
||||
|
@ -217,6 +152,7 @@ getL2Addr( const CommsAddrRec const* addrP, L2_RF_ADDR* const saddr )
|
|||
sdp_close( session );
|
||||
}
|
||||
|
||||
LOG_RETURNF( "%p", result );
|
||||
return result;
|
||||
} /* getL2Addr */
|
||||
|
||||
|
@ -224,6 +160,7 @@ static void
|
|||
lbt_connectSocket( LinBtStuff* btStuff, const CommsAddrRec* addrP )
|
||||
{
|
||||
int sock;
|
||||
LOG_FUNC();
|
||||
|
||||
// allocate a socket
|
||||
sock = socket( AF_BLUETOOTH,
|
||||
|
@ -244,7 +181,8 @@ lbt_connectSocket( LinBtStuff* btStuff, const CommsAddrRec* addrP )
|
|||
&& (0 == connect( sock, (struct sockaddr *)&saddr, sizeof(saddr) )) ) {
|
||||
CommonGlobals* globals = btStuff->globals;
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
-1, sock );
|
||||
-1, sock, &btStuff->sockStorage );
|
||||
btStuff->socket = sock;
|
||||
} else {
|
||||
XP_LOGF( "%s: connect->%s; closing socket %d", __FUNCTION__, strerror(errno), sock );
|
||||
close( sock );
|
||||
|
@ -272,13 +210,10 @@ lbt_accept( int listener, void* ctxt )
|
|||
|
||||
success = sock >= 0;
|
||||
if ( success ) {
|
||||
#if defined BT_USE_L2CAP
|
||||
lbt_addSock( btStuff, &inaddr.l2_bdaddr, sock );
|
||||
#elif defined BT_USE_RFCOMM
|
||||
lbt_addSock( btStuff, &inaddr.rc_bdaddr, sock );
|
||||
#endif
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
-1, sock );
|
||||
-1, sock, &btStuff->sockStorage );
|
||||
XP_ASSERT( btStuff->socket == -1 );
|
||||
btStuff->socket = sock;
|
||||
} else {
|
||||
XP_LOGF( "%s: accept->%s", __FUNCTION__, strerror(errno) );
|
||||
}
|
||||
|
@ -423,12 +358,14 @@ linux_bt_open( CommonGlobals* globals, XP_Bool amMaster )
|
|||
btStuff = globals->btStuff
|
||||
= lbt_make( MPPARM(globals->params->util->mpool) amMaster );
|
||||
btStuff->globals = globals;
|
||||
btStuff->socket = -1;
|
||||
|
||||
globals->btStuff = btStuff;
|
||||
|
||||
if ( amMaster ) {
|
||||
lbt_listenerSetup( globals );
|
||||
} else {
|
||||
if ( globals->socket < 0 ) {
|
||||
if ( btStuff->socket < 0 ) {
|
||||
CommsAddrRec addr;
|
||||
comms_getAddr( globals->game.comms, &addr );
|
||||
lbt_connectSocket( btStuff, &addr );
|
||||
|
@ -451,7 +388,6 @@ void
|
|||
linux_bt_close( CommonGlobals* globals )
|
||||
{
|
||||
LinBtStuff* btStuff = globals->btStuff;
|
||||
XP_U16 i;
|
||||
|
||||
if ( !!btStuff ) {
|
||||
if ( btStuff->amMaster ) {
|
||||
|
@ -459,18 +395,17 @@ linux_bt_close( CommonGlobals* globals )
|
|||
close( btStuff->u.master.listener );
|
||||
btStuff->u.master.listener = -1;
|
||||
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||
if ( mp->sock != -1 ) {
|
||||
XP_LOGF( "%s: closing data socket %d", __func__, mp->sock );
|
||||
(void)close( mp->sock );
|
||||
}
|
||||
}
|
||||
|
||||
sdp_close( btStuff->u.master.session );
|
||||
XP_LOGF( "sleeping for Palm's sake..." );
|
||||
sleep( 2 ); /* see if this gives palm a chance to not hang */
|
||||
}
|
||||
|
||||
if ( btStuff->socket != -1 ) {
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
btStuff->socket, -1, &btStuff->sockStorage );
|
||||
(void)close( btStuff->socket );
|
||||
}
|
||||
|
||||
XP_FREE( globals->params->util->mpool, btStuff );
|
||||
globals->btStuff = NULL;
|
||||
}
|
||||
|
@ -495,17 +430,17 @@ linux_bt_send( const XP_U8* buf, XP_U16 buflen,
|
|||
addrP = &addr;
|
||||
}
|
||||
|
||||
if ( globals->socket < 0 && !btStuff->amMaster ) {
|
||||
if ( btStuff->socket < 0 && !btStuff->amMaster ) {
|
||||
lbt_connectSocket( btStuff, addrP );
|
||||
}
|
||||
|
||||
if ( globals->socket >= 0 ) {
|
||||
if ( btStuff->socket >= 0 ) {
|
||||
#if defined BT_USE_RFCOMM
|
||||
unsigned short len = htons(buflen);
|
||||
nSent = write( globals->socket, &len, sizeof(len) );
|
||||
nSent = write( btStuff->socket, &len, sizeof(len) );
|
||||
assert( nSent == sizeof(len) );
|
||||
#endif
|
||||
nSent = write( globals->socket, buf, buflen );
|
||||
nSent = write( btStuff->socket, buf, buflen );
|
||||
if ( nSent < 0 ) {
|
||||
XP_LOGF( "%s: send->%s", __FUNCTION__, strerror(errno) );
|
||||
} else if ( nSent < buflen ) {
|
||||
|
@ -569,10 +504,9 @@ void
|
|||
linux_bt_socketclosed( CommonGlobals* globals, int sock )
|
||||
{
|
||||
LinBtStuff* btStuff = globals->btStuff;
|
||||
if ( btStuff->amMaster ) {
|
||||
lbt_removeSock( btStuff, sock );
|
||||
}
|
||||
LOG_FUNC();
|
||||
XP_ASSERT( sock == btStuff->socket );
|
||||
btStuff->socket = -1;
|
||||
}
|
||||
|
||||
#endif /* XWFEATURE_BLUETOOTH */
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include "linuxmain.h"
|
||||
#include "linuxbt.h"
|
||||
#include "linuxudp.h"
|
||||
#include "main.h"
|
||||
#ifdef PLATFORM_NCURSES
|
||||
# include "cursesmain.h"
|
||||
|
@ -57,7 +58,7 @@
|
|||
#include "memstream.h"
|
||||
#include "LocalizedStrIncludes.h"
|
||||
|
||||
#define DEFAULT_SEND_PORT 10999
|
||||
#define DEFAULT_PORT 10999
|
||||
#define DEFAULT_LISTEN_PORT 4998
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -266,24 +267,30 @@ usage( char* appName, char* msg )
|
|||
"\t [-B n:name|a:00:11:22:33:44:55]\n"
|
||||
"\t\t\t# connect via bluetooth [param ignored if -s]\n"
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
"\t [-D host_addr]\t\t\tConnect directly to host [param ignored if -s]\n"
|
||||
"\t [-p host_port] # put/look for host on this port\n"
|
||||
#endif
|
||||
|
||||
/* "# --------------- OR client-only ----------\n" */
|
||||
/* "\t [-p client_port] # must != server's port if on same device" */
|
||||
"\nexample: \n"
|
||||
"\tserver: ./xwords -d dict.xwd -s -r Eric -N"
|
||||
#ifdef XWFEATURE_RELAY
|
||||
" -a localhost -p 10999"
|
||||
"\nrelay example: \n"
|
||||
"\t host: ./xwords -d dict.xwd -r Eric -s -N -a localhost -p 10999 -C COOKIE\n"
|
||||
"\tguest: ./xwords -d dict.xwd -r Kati -a localhost -p 10999 -C COOKIE"
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
" -B ignored "
|
||||
"\nBluetooth example: \n"
|
||||
"\t host: ./xwords -d dict.xwd -r Eric -s -N -B ignored\n"
|
||||
"\tguest: ./xwords -d dict.xwd -r Kati -B n:treo_bt_name (OR b:11:22:33:44:55:66)"
|
||||
#endif
|
||||
"\n"
|
||||
"\tclient: ./xwords -d dict.xwd -r Kati"
|
||||
#ifdef XWFEATURE_RELAY
|
||||
" -a localhost -p 10999"
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
" -B a:11:22:33:44:55:66 | n:my_treo "
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
"\nDirect example: \n"
|
||||
"\t host: ./xwords -d dict.xwd -r Eric -s -N -N -D localhost -p 10999\n"
|
||||
"\tguest: ./xwords -d dict.xwd -r Kati -D localhost -p 10999\n"
|
||||
"\tguest: ./xwords -d dict.xwd -r Ariynn -D localhost -p 10999"
|
||||
#endif
|
||||
|
||||
"\n"
|
||||
, appName );
|
||||
fprintf( stderr, "\n(revision: %s)\n", SVN_REV);
|
||||
|
@ -394,7 +401,8 @@ linux_tcp_send( const XP_U8* buf, XP_U16 buflen,
|
|||
if ( socket != -1 ) {
|
||||
assert( globals->socket == socket );
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
-1, socket );
|
||||
-1, socket,
|
||||
&globals->storage );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,7 +418,7 @@ linux_tcp_send( const XP_U8* buf, XP_U16 buflen,
|
|||
XP_STATUSF( "closing non-functional socket" );
|
||||
close( socket );
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
socket, -1 );
|
||||
socket, -1, &globals->storage );
|
||||
globals->socket = -1;
|
||||
}
|
||||
|
||||
|
@ -420,7 +428,17 @@ linux_tcp_send( const XP_U8* buf, XP_U16 buflen,
|
|||
|
||||
return result;
|
||||
} /* linux_tcp_send */
|
||||
#endif
|
||||
|
||||
static void
|
||||
linux_tcp_reset( CommonGlobals* globals )
|
||||
{
|
||||
LOG_FUNC();
|
||||
if ( globals->socket != -1 ) {
|
||||
(void)close( globals->socket );
|
||||
globals->socket = -1;
|
||||
}
|
||||
}
|
||||
#endif /* XWFEATURE_RELAY */
|
||||
|
||||
#ifdef COMMS_HEARTBEAT
|
||||
void
|
||||
|
@ -432,6 +450,14 @@ linux_reset( void* closure )
|
|||
#ifdef XWFEATURE_BLUETOOTH
|
||||
} else if ( conType == COMMS_CONN_BT ) {
|
||||
linux_bt_reset( globals );
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
} else if ( conType == COMMS_CONN_IP_DIRECT ) {
|
||||
linux_udp_reset( globals );
|
||||
#endif
|
||||
#ifdef XWFEATURE_RELAY
|
||||
} else if ( conType == COMMS_CONN_RELAY ) {
|
||||
linux_tcp_reset( globals );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -458,11 +484,18 @@ linux_send( const XP_U8* buf, XP_U16 buflen,
|
|||
} else if ( conType == COMMS_CONN_RELAY ) {
|
||||
nSent = linux_tcp_send( buf, buflen, addrRec, globals );
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
#if defined XWFEATURE_BLUETOOTH
|
||||
} else if ( conType == COMMS_CONN_BT ) {
|
||||
XP_Bool isServer = comms_getIsServer( globals->game.comms );
|
||||
linux_bt_open( globals, isServer );
|
||||
nSent = linux_bt_send( buf, buflen, addrRec, globals );
|
||||
#endif
|
||||
#if defined XWFEATURE_IP_DIRECT
|
||||
} else if ( conType == COMMS_CONN_IP_DIRECT ) {
|
||||
CommsAddrRec addr;
|
||||
comms_getAddr( globals->game.comms, &addr );
|
||||
linux_udp_open( globals, &addr );
|
||||
nSent = linux_udp_send( buf, buflen, addrRec, globals );
|
||||
#endif
|
||||
} else {
|
||||
XP_ASSERT(0);
|
||||
|
@ -470,6 +503,7 @@ linux_send( const XP_U8* buf, XP_U16 buflen,
|
|||
return nSent;
|
||||
} /* linux_send */
|
||||
|
||||
#ifdef XWFEATURE_RELAY
|
||||
static void
|
||||
linux_close_socket( CommonGlobals* cGlobals )
|
||||
{
|
||||
|
@ -502,6 +536,7 @@ linux_relay_receive( CommonGlobals* cGlobals, unsigned char* buf, int bufSize )
|
|||
}
|
||||
return nRead;
|
||||
} /* linuxReceive */
|
||||
#endif
|
||||
|
||||
/* Create a stream for the incoming message buffer, and read in any
|
||||
information specific to our platform's comms layer (return address, say)
|
||||
|
@ -684,9 +719,9 @@ linux_util_getUserString( XW_UtilCtxt* XP_UNUSED(uc), XP_U16 code )
|
|||
|
||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_RELAY
|
||||
static void
|
||||
linux_util_addrChange( XW_UtilCtxt* XP_UNUSED_BT(uc),
|
||||
linux_util_addrChange( XW_UtilCtxt* uc,
|
||||
const CommsAddrRec* XP_UNUSED(oldAddr),
|
||||
const CommsAddrRec* XP_UNUSED_BT(newAddr) )
|
||||
const CommsAddrRec* newAddr )
|
||||
{
|
||||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
|
@ -694,6 +729,11 @@ linux_util_addrChange( XW_UtilCtxt* XP_UNUSED_BT(uc),
|
|||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
XP_Bool isServer = comms_getIsServer( cGlobals->game.comms );
|
||||
linux_bt_open( cGlobals, isServer );
|
||||
#endif
|
||||
#if defined XWFEATURE_IP_DIRECT
|
||||
} else if ( newAddr->conType == COMMS_CONN_IP_DIRECT ) {
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
linux_udp_open( cGlobals, newAddr );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -757,8 +797,8 @@ main( int argc, char** argv )
|
|||
int opt;
|
||||
int totalPlayerCount = 0;
|
||||
XP_Bool isServer = XP_FALSE;
|
||||
char* sendPortNumString = NULL;
|
||||
char* relayName = "localhost";
|
||||
char* portNum = "10999";
|
||||
char* hostName = "localhost";
|
||||
unsigned int seed = defaultRandomSeed();
|
||||
LaunchParams mainParams;
|
||||
XP_U16 robotCount = 0;
|
||||
|
@ -798,9 +838,12 @@ main( int argc, char** argv )
|
|||
|
||||
/* defaults */
|
||||
#ifdef XWFEATURE_RELAY
|
||||
mainParams.connInfo.relay.defaultListenPort = DEFAULT_LISTEN_PORT;
|
||||
mainParams.connInfo.relay.defaultSendPort = DEFAULT_SEND_PORT;
|
||||
mainParams.connInfo.relay.defaultSendPort = DEFAULT_PORT;
|
||||
mainParams.connInfo.relay.cookie = "COOKIE";
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
mainParams.connInfo.ip.port = DEFAULT_PORT;
|
||||
mainParams.connInfo.ip.hostName = "localhost";
|
||||
#endif
|
||||
mainParams.gi.boardSize = 15;
|
||||
mainParams.quitAfter = XP_FALSE;
|
||||
|
@ -837,8 +880,14 @@ main( int argc, char** argv )
|
|||
#ifdef XWFEATURE_RELAY
|
||||
"a:p:C:H"
|
||||
#endif
|
||||
#if defined XWFEATURE_RELAY || defined XWFEATURE_IP_DIRECT
|
||||
"p:"
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
"B:"
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
"D:"
|
||||
#endif
|
||||
);
|
||||
switch( opt ) {
|
||||
|
@ -856,6 +905,12 @@ main( int argc, char** argv )
|
|||
conType = COMMS_CONN_RELAY;
|
||||
break;
|
||||
#endif
|
||||
case 'D':
|
||||
XP_ASSERT( conType == COMMS_CONN_UNUSED ||
|
||||
conType == COMMS_CONN_IP_DIRECT );
|
||||
hostName = optarg;
|
||||
conType = COMMS_CONN_IP_DIRECT;
|
||||
break;
|
||||
case 'd':
|
||||
mainParams.gi.dictName = copyString( mainParams.util->mpool,
|
||||
(XP_UCHAR*)optarg );
|
||||
|
@ -893,10 +948,8 @@ main( int argc, char** argv )
|
|||
++mainParams.info.serverInfo.nRemotePlayers;
|
||||
break;
|
||||
case 'p':
|
||||
sendPortNumString = optarg;
|
||||
XP_ASSERT( conType == COMMS_CONN_UNUSED ||
|
||||
conType == COMMS_CONN_RELAY );
|
||||
conType = COMMS_CONN_RELAY;
|
||||
/* could be RELAY or IP_DIRECT */
|
||||
portNum = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
++robotCount;
|
||||
|
@ -928,7 +981,7 @@ main( int argc, char** argv )
|
|||
XP_ASSERT( conType == COMMS_CONN_UNUSED ||
|
||||
conType == COMMS_CONN_RELAY );
|
||||
conType = COMMS_CONN_RELAY;
|
||||
relayName = optarg;
|
||||
hostName = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
mainParams.quitAfter = XP_TRUE;
|
||||
|
@ -1015,12 +1068,19 @@ main( int argc, char** argv )
|
|||
if ( 0 ) {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
} else if ( conType == COMMS_CONN_RELAY ) {
|
||||
mainParams.connInfo.relay.relayName = relayName;
|
||||
mainParams.connInfo.relay.relayName = hostName;
|
||||
|
||||
/* convert strings to whatever */
|
||||
if ( sendPortNumString != NULL ) {
|
||||
if ( portNum != NULL ) {
|
||||
mainParams.connInfo.relay.defaultSendPort =
|
||||
atoi( sendPortNumString );
|
||||
atoi( portNum );
|
||||
}
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
} else if ( conType == COMMS_CONN_IP_DIRECT ) {
|
||||
mainParams.connInfo.ip.hostName = hostName;
|
||||
if ( portNum != NULL ) {
|
||||
mainParams.connInfo.ip.port = atoi( portNum );
|
||||
}
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
|
|
25
linux/main.h
25
linux/main.h
|
@ -65,19 +65,24 @@ typedef struct LaunchParams {
|
|||
DeviceRole serverRole;
|
||||
|
||||
CommsConnType conType;
|
||||
union {
|
||||
struct {
|
||||
#ifdef XWFEATURE_RELAY
|
||||
struct {
|
||||
char* relayName;
|
||||
char* cookie;
|
||||
short defaultSendPort;
|
||||
short defaultListenPort;
|
||||
} relay;
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
struct {
|
||||
bdaddr_t hostAddr; /* unused if a host */
|
||||
} bt;
|
||||
#endif
|
||||
#ifdef XWFEATURE_IP_DIRECT
|
||||
struct {
|
||||
const char* hostName;
|
||||
int port;
|
||||
} ip;
|
||||
#endif
|
||||
} connInfo;
|
||||
|
||||
|
@ -90,7 +95,8 @@ typedef struct LaunchParams {
|
|||
|
||||
typedef struct CommonGlobals CommonGlobals;
|
||||
|
||||
typedef void (*SocketChangedFunc)(void* closure, int oldsock, int newsock );
|
||||
typedef void (*SocketChangedFunc)(void* closure, int oldsock, int newsock,
|
||||
void** storage );
|
||||
typedef XP_Bool (*Acceptor)( int sock, void* ctxt );
|
||||
typedef void (*AddAcceptorFunc)(int listener, Acceptor func,
|
||||
CommonGlobals* globals );
|
||||
|
@ -109,13 +115,18 @@ struct CommonGlobals {
|
|||
AddAcceptorFunc addAcceptor;
|
||||
Acceptor acceptor;
|
||||
|
||||
int socket; /* either relay or bt */
|
||||
|
||||
/* Used only for relay case */
|
||||
#ifdef XWFEATURE_RELAY
|
||||
int socket; /* relay */
|
||||
void* storage;
|
||||
char* defaultServerName;
|
||||
#endif
|
||||
|
||||
/* Used only for bluetooth case */
|
||||
#if defined XWFEATURE_BLUETOOTH
|
||||
struct LinBtStuff* btStuff;
|
||||
#endif
|
||||
#if defined XWFEATURE_IP_DIRECT
|
||||
struct LinUDPStuff* udpStuff;
|
||||
#endif
|
||||
|
||||
XWTimerProc timerProcs[NUM_TIMERS_PLUS_ONE];
|
||||
void* timerClosures[NUM_TIMERS_PLUS_ONE];
|
||||
|
|
Loading…
Reference in a new issue