mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-18 22:26:30 +01:00
Add and set a compile-time option so comms will set a periodic timer
and use it to send and check for heartbeats over any transport. Caller must supply a reset proc which is called when heartbeat hasn't been received in too long. No changes required to comms protocol, but that means the heartbeat interval is fixed at compile time: can't be negotiated, and the two ends had better agree. Currently tested with linux host and PalmOS guest, where only the first heartbeat failure is recovered from. So there's some debugging to be done still.
This commit is contained in:
parent
cb1222c0f9
commit
4c8cf98d24
17 changed files with 356 additions and 72 deletions
|
@ -35,6 +35,17 @@
|
||||||
|
|
||||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||||
|
|
||||||
|
#if defined RELAY_HEARTBEAT && defined COMMS_HEARTBEAT
|
||||||
|
compilation_error_here( "Choose one or the other or none." );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
/* It might make sense for this to be a parameter or somehow tied to the
|
||||||
|
platform and transport. But in that case it'd have to be passed across
|
||||||
|
since all devices must agree. */
|
||||||
|
# define HB_INTERVAL 5
|
||||||
|
#endif
|
||||||
|
|
||||||
EXTERN_C_START
|
EXTERN_C_START
|
||||||
|
|
||||||
typedef struct MsgQueueElem {
|
typedef struct MsgQueueElem {
|
||||||
|
@ -54,6 +65,8 @@ typedef struct AddressRecord {
|
||||||
#endif
|
#endif
|
||||||
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 */
|
||||||
|
/* only used if COMMS_HEARTBEAT set except for serialization (to_stream) */
|
||||||
|
XP_U32 lastMsgRcvdTime; /* when did we set lastMsgReceived? */
|
||||||
XP_PlayerAddr channelNo;
|
XP_PlayerAddr channelNo;
|
||||||
struct {
|
struct {
|
||||||
XWHostID hostID; /* used for relay case */
|
XWHostID hostID; /* used for relay case */
|
||||||
|
@ -78,12 +91,19 @@ struct CommsCtxt {
|
||||||
AddressRecord* recs; /* return addresses */
|
AddressRecord* recs; /* return addresses */
|
||||||
|
|
||||||
TransportSend sendproc;
|
TransportSend sendproc;
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
TransportReset resetproc;
|
||||||
|
#endif
|
||||||
void* sendClosure;
|
void* sendClosure;
|
||||||
|
|
||||||
MsgQueueElem* msgQueueHead;
|
MsgQueueElem* msgQueueHead;
|
||||||
MsgQueueElem* msgQueueTail;
|
MsgQueueElem* msgQueueTail;
|
||||||
XP_U16 queueLen;
|
XP_U16 queueLen;
|
||||||
|
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
XP_Bool doHeartbeat;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The following fields, down to isServer, are only used if
|
/* The following fields, down to isServer, are only used if
|
||||||
XWFEATURE_RELAY is defined, but I'm leaving them in here so apps built
|
XWFEATURE_RELAY is defined, but I'm leaving them in here so apps built
|
||||||
both ways can open each other's saved games files.*/
|
both ways can open each other's saved games files.*/
|
||||||
|
@ -143,6 +163,8 @@ static void relayDisconnect( CommsCtxt* comms );
|
||||||
static XP_Bool send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd,
|
static XP_Bool send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd,
|
||||||
XWHostID destID, void* data, int dlen );
|
XWHostID destID, void* data, int dlen );
|
||||||
static XWHostID getDestID( CommsCtxt* comms, XP_PlayerAddr channelNo );
|
static XWHostID getDestID( CommsCtxt* comms, XP_PlayerAddr channelNo );
|
||||||
|
#endif
|
||||||
|
#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT
|
||||||
static void setHeartbeatTimer( CommsCtxt* comms );
|
static void setHeartbeatTimer( CommsCtxt* comms );
|
||||||
#endif
|
#endif
|
||||||
#ifdef XWFEATURE_BLUETOOTH
|
#ifdef XWFEATURE_BLUETOOTH
|
||||||
|
@ -159,7 +181,8 @@ CommsCtxt*
|
||||||
comms_make( MPFORMAL XW_UtilCtxt* util, XP_Bool isServer,
|
comms_make( MPFORMAL XW_UtilCtxt* util, XP_Bool isServer,
|
||||||
XP_U16 XP_UNUSED_RELAY(nPlayersHere),
|
XP_U16 XP_UNUSED_RELAY(nPlayersHere),
|
||||||
XP_U16 XP_UNUSED_RELAY(nPlayersTotal),
|
XP_U16 XP_UNUSED_RELAY(nPlayersTotal),
|
||||||
TransportSend sendproc, void* closure )
|
TransportSend sendproc, IF_CH(TransportReset resetproc)
|
||||||
|
void* closure )
|
||||||
{
|
{
|
||||||
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) );
|
||||||
|
@ -168,6 +191,9 @@ comms_make( MPFORMAL XW_UtilCtxt* util, XP_Bool isServer,
|
||||||
|
|
||||||
result->isServer = isServer;
|
result->isServer = isServer;
|
||||||
result->sendproc = sendproc;
|
result->sendproc = sendproc;
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
result->resetproc = resetproc;
|
||||||
|
#endif
|
||||||
result->sendClosure = closure;
|
result->sendClosure = closure;
|
||||||
result->util = util;
|
result->util = util;
|
||||||
|
|
||||||
|
@ -297,7 +323,8 @@ addrFromStream( CommsAddrRec* addrP, XWStreamCtxt* stream )
|
||||||
|
|
||||||
CommsCtxt*
|
CommsCtxt*
|
||||||
comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util,
|
comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util,
|
||||||
TransportSend sendproc, void* closure )
|
TransportSend sendproc,
|
||||||
|
IF_CH(TransportReset resetproc ) void* closure )
|
||||||
{
|
{
|
||||||
CommsCtxt* comms;
|
CommsCtxt* comms;
|
||||||
XP_Bool isServer;
|
XP_Bool isServer;
|
||||||
|
@ -325,7 +352,7 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util,
|
||||||
}
|
}
|
||||||
comms = comms_make( MPPARM(mpool) util, isServer,
|
comms = comms_make( MPPARM(mpool) util, isServer,
|
||||||
nPlayersHere, nPlayersTotal,
|
nPlayersHere, nPlayersTotal,
|
||||||
sendproc, closure );
|
sendproc, IF_CH(resetproc) closure );
|
||||||
XP_MEMCPY( &comms->addr, &addr, sizeof(comms->addr) );
|
XP_MEMCPY( &comms->addr, &addr, sizeof(comms->addr) );
|
||||||
|
|
||||||
comms->connID = stream_getU32( stream );
|
comms->connID = stream_getU32( stream );
|
||||||
|
@ -403,6 +430,10 @@ comms_start( CommsCtxt* comms )
|
||||||
btConnect( comms );
|
btConnect( comms );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
comms->doHeartbeat = comms->addr.conType != COMMS_CONN_IR;
|
||||||
|
#endif
|
||||||
} /* comms_start */
|
} /* comms_start */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -531,6 +562,9 @@ comms_setAddr( CommsCtxt* comms, const CommsAddrRec* addr )
|
||||||
btConnect( comms );
|
btConnect( comms );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
comms->doHeartbeat = comms->addr.conType != COMMS_CONN_IR;
|
||||||
|
#endif
|
||||||
} /* comms_setAddr */
|
} /* comms_setAddr */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -567,22 +601,16 @@ comms_getIsServer( const CommsCtxt* comms )
|
||||||
return comms->isServer;
|
return comms->isServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a message using the sequentially next MsgID. Save the message so
|
static XP_S16
|
||||||
* resend can work. */
|
sendWithID( CommsCtxt* comms, MsgID msgID, AddressRecord* rec,
|
||||||
XP_S16
|
XP_PlayerAddr channelNo, XWStreamCtxt* stream )
|
||||||
comms_send( CommsCtxt* comms, XWStreamCtxt* stream )
|
|
||||||
{
|
{
|
||||||
XP_U16 streamSize = stream_getSize( stream );
|
|
||||||
XP_U16 headerLen;
|
XP_U16 headerLen;
|
||||||
XP_PlayerAddr channelNo = stream_getAddress( stream );
|
XP_U16 streamSize = NULL == stream? 0 : stream_getSize( stream );
|
||||||
AddressRecord* rec = getRecordFor( comms, channelNo );
|
|
||||||
MsgID msgID = (!!rec)? ++rec->nextMsgID : 0;
|
|
||||||
MsgID lastMsgRcd = (!!rec)? rec->lastMsgReceived : 0;
|
MsgID lastMsgRcd = (!!rec)? rec->lastMsgReceived : 0;
|
||||||
MsgQueueElem* newMsgElem;
|
MsgQueueElem* newMsgElem;
|
||||||
XWStreamCtxt* msgStream;
|
XWStreamCtxt* msgStream;
|
||||||
|
|
||||||
XP_DEBUGF( "assigning msgID=" XP_LD " on chnl %d", msgID, channelNo );
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if ( !!rec ) {
|
if ( !!rec ) {
|
||||||
rec->nUniqueBytes += streamSize;
|
rec->nUniqueBytes += streamSize;
|
||||||
|
@ -614,11 +642,26 @@ comms_send( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||||
stream_getBytes( msgStream, newMsgElem->msg, headerLen );
|
stream_getBytes( msgStream, newMsgElem->msg, headerLen );
|
||||||
stream_destroy( msgStream );
|
stream_destroy( msgStream );
|
||||||
|
|
||||||
stream_getBytes( stream, newMsgElem->msg + headerLen, streamSize );
|
if ( 0 < streamSize ) {
|
||||||
|
stream_getBytes( stream, newMsgElem->msg + headerLen, streamSize );
|
||||||
|
}
|
||||||
|
|
||||||
addToQueue( comms, newMsgElem );
|
addToQueue( comms, newMsgElem );
|
||||||
|
|
||||||
return sendMsg( comms, newMsgElem );
|
return sendMsg( comms, newMsgElem );
|
||||||
|
} /* sendWithID */
|
||||||
|
|
||||||
|
/* Send a message using the sequentially next MsgID. Save the message so
|
||||||
|
* resend can work. */
|
||||||
|
XP_S16
|
||||||
|
comms_send( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||||
|
{
|
||||||
|
XP_PlayerAddr channelNo = stream_getAddress( stream );
|
||||||
|
AddressRecord* rec = getRecordFor( comms, channelNo );
|
||||||
|
MsgID msgID = (!!rec)? ++rec->nextMsgID : 0;
|
||||||
|
|
||||||
|
XP_DEBUGF( "assigning msgID=" XP_LD " on chnl %d", msgID, channelNo );
|
||||||
|
return sendWithID( comms, msgID, rec, channelNo, stream );
|
||||||
} /* comms_send */
|
} /* comms_send */
|
||||||
|
|
||||||
/* Add new message to the end of the list. The list needs to be kept in order
|
/* Add new message to the end of the list. The list needs to be kept in order
|
||||||
|
@ -1013,6 +1056,11 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||||
* greater than the id most recently used for that
|
* greater than the id most recently used for that
|
||||||
* channel. */
|
* channel. */
|
||||||
if ( !!recs ) {
|
if ( !!recs ) {
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
/* Good for heartbeat even if not "valid." In
|
||||||
|
fact, all HB messages are invalid by design. */
|
||||||
|
recs->lastMsgRcvdTime = util_getCurSeconds( comms->util );
|
||||||
|
#endif
|
||||||
if ( msgID != recs->lastMsgReceived + 1 ) {
|
if ( msgID != recs->lastMsgReceived + 1 ) {
|
||||||
XP_DEBUGF( "on channel %d, msgID=" XP_LD
|
XP_DEBUGF( "on channel %d, msgID=" XP_LD
|
||||||
" (next should be " XP_LD ")",
|
" (next should be " XP_LD ")",
|
||||||
|
@ -1047,9 +1095,9 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||||
|
|
||||||
if ( !!recs ) {
|
if ( !!recs ) {
|
||||||
recs->lastMsgReceived = msgID;
|
recs->lastMsgReceived = msgID;
|
||||||
|
XP_STATUSF( "set channel %d's lastMsgReceived to "
|
||||||
|
XP_LD, channelNo, msgID );
|
||||||
}
|
}
|
||||||
XP_STATUSF( "set channel %d's lastMsgReceived to "
|
|
||||||
XP_LD, channelNo, msgID );
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
XP_LOGF( "%s: message too small", __FUNCTION__ );
|
XP_LOGF( "%s: message too small", __FUNCTION__ );
|
||||||
|
@ -1066,25 +1114,103 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||||
return validMessage;
|
return validMessage;
|
||||||
} /* comms_checkIncomingStream */
|
} /* comms_checkIncomingStream */
|
||||||
|
|
||||||
#ifdef XWFEATURE_RELAY
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
/* Heartbeat.
|
||||||
|
*
|
||||||
|
* Goal is to allow all participants to detect when another is gone quickly.
|
||||||
|
* Assumption is that transport is cheap: sending extra packets doesn't cost
|
||||||
|
* much money or bother (meaning: don't do this over IR! :-).
|
||||||
|
*
|
||||||
|
* Keep track of last time we heard from each channel and of when we last sent
|
||||||
|
* a packet. Run a timer, and when it fires: 1) check if we haven't heard
|
||||||
|
* since 2x the timer interval. If so, call alert function and reset the
|
||||||
|
* underlying (ip, bt) channel. If not, check how long since we last sent a
|
||||||
|
* packet on each channel. If it's been longer than since the last timer, and
|
||||||
|
* if there are not already packets in the queue on that channel, fire a HB
|
||||||
|
* packet.
|
||||||
|
*
|
||||||
|
* A HB packet is one whose msg ID is lower than the most recent ACK'd so that
|
||||||
|
* it's sure to be dropped on the other end and not to interfere with packets
|
||||||
|
* that might be resent.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
heartbeat_checks( CommsCtxt* comms )
|
||||||
|
{
|
||||||
|
XP_U32 now, tooLongAgo;
|
||||||
|
XP_U16 pendingPacks[MAX_NUM_PLAYERS] = { 0 };
|
||||||
|
AddressRecord* rec;
|
||||||
|
const MsgQueueElem* elem;
|
||||||
|
XP_Bool resetTimer = XP_FALSE;
|
||||||
|
|
||||||
|
LOG_FUNC();
|
||||||
|
|
||||||
|
for ( elem = comms->msgQueueHead; !!elem; elem = elem->next ) {
|
||||||
|
XP_ASSERT( elem->channelNo < MAX_NUM_PLAYERS );
|
||||||
|
++pendingPacks[elem->channelNo];
|
||||||
|
}
|
||||||
|
|
||||||
|
now = util_getCurSeconds( comms->util );
|
||||||
|
tooLongAgo = now - (HB_INTERVAL * 2);
|
||||||
|
for ( rec = comms->recs; !!rec; rec = rec->next ) {
|
||||||
|
XP_U32 lastMsgRcvdTime = rec->lastMsgRcvdTime;
|
||||||
|
if ( lastMsgRcvdTime == 0 ) { /* nothing received yet */
|
||||||
|
/* do nothing; or should we send? */
|
||||||
|
} else if ( (lastMsgRcvdTime > 0) && (lastMsgRcvdTime < tooLongAgo) ) {
|
||||||
|
XP_LOGF( "calling reset proc" );
|
||||||
|
(*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 );
|
||||||
|
} else {
|
||||||
|
XP_LOGF( "All's well" );
|
||||||
|
resetTimer = XP_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( resetTimer ) {
|
||||||
|
setHeartbeatTimer( comms );
|
||||||
|
}
|
||||||
|
} /* heartbeat_checks */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT
|
||||||
static void
|
static void
|
||||||
p_comms_timerFired( void* closure, XWTimerReason XP_UNUSED_DBG(why) )
|
p_comms_timerFired( void* closure, XWTimerReason XP_UNUSED_DBG(why) )
|
||||||
{
|
{
|
||||||
CommsCtxt* comms = (CommsCtxt*)closure;
|
CommsCtxt* comms = (CommsCtxt*)closure;
|
||||||
XP_ASSERT( why == TIMER_HEARTBEAT );
|
XP_ASSERT( why == TIMER_HEARTBEAT );
|
||||||
XP_LOGF( "comms_timerFired" );
|
XP_LOGF( "comms_timerFired" );
|
||||||
if ( comms->r.heartbeat != HEARTBEAT_NONE ) {
|
if (0 ) {
|
||||||
|
#ifdef RELAY_HEARTBEAT
|
||||||
|
} else if ( (comms->addr.conType == COMMS_CONN_RELAY )
|
||||||
|
&& (comms->r.heartbeat != HEARTBEAT_NONE) ) {
|
||||||
send_via_relay( comms, XWRELAY_HEARTBEAT, HOST_ID_NONE, NULL, 0 );
|
send_via_relay( comms, XWRELAY_HEARTBEAT, HOST_ID_NONE, NULL, 0 );
|
||||||
/* No need to reset timer. send_via_relay does that. */
|
/* No need to reset timer. send_via_relay does that. */
|
||||||
|
#elif defined COMMS_HEARTBEAT
|
||||||
|
} else {
|
||||||
|
XP_ASSERT( comms->doHeartbeat );
|
||||||
|
heartbeat_checks( comms );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} /* comms_timerFired */
|
} /* p_comms_timerFired */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setHeartbeatTimer( CommsCtxt* comms )
|
setHeartbeatTimer( CommsCtxt* comms )
|
||||||
{
|
{
|
||||||
util_setTimer( comms->util, TIMER_HEARTBEAT, comms->r.heartbeat,
|
#ifdef RELAY_HEARTBEAT
|
||||||
p_comms_timerFired, comms );
|
if ( comms->addr.conType == COMMS_CONN_RELAY ) {
|
||||||
}
|
util_setTimer( comms->util, TIMER_HEARTBEAT, comms->r.heartbeat,
|
||||||
|
p_comms_timerFired, comms );
|
||||||
|
}
|
||||||
|
#elif defined COMMS_HEARTBEAT
|
||||||
|
if ( comms->doHeartbeat ) {
|
||||||
|
util_setTimer( comms->util, TIMER_HEARTBEAT, HB_INTERVAL,
|
||||||
|
p_comms_timerFired, comms );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} /* setHeartbeatTimer */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -1094,6 +1220,7 @@ comms_getStats( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||||
XP_UCHAR buf[100];
|
XP_UCHAR buf[100];
|
||||||
AddressRecord* rec;
|
AddressRecord* rec;
|
||||||
MsgQueueElem* elem;
|
MsgQueueElem* elem;
|
||||||
|
XP_U32 now;
|
||||||
|
|
||||||
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
||||||
(XP_UCHAR*)"msg queue len: %d\n", comms->queueLen );
|
(XP_UCHAR*)"msg queue len: %d\n", comms->queueLen );
|
||||||
|
@ -1111,6 +1238,7 @@ comms_getStats( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||||
comms->nUniqueBytes );
|
comms->nUniqueBytes );
|
||||||
stream_putString( stream, buf );
|
stream_putString( stream, buf );
|
||||||
|
|
||||||
|
now = util_getCurSeconds( comms->util );
|
||||||
for ( rec = comms->recs; !!rec; rec = rec->next ) {
|
for ( rec = comms->recs; !!rec; rec = rec->next ) {
|
||||||
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
||||||
(XP_UCHAR*)" Stats for channel: %d\n",
|
(XP_UCHAR*)" Stats for channel: %d\n",
|
||||||
|
@ -1131,6 +1259,13 @@ comms_getStats( CommsCtxt* comms, XWStreamCtxt* stream )
|
||||||
(XP_UCHAR*)"Last message acknowledged: %d\n",
|
(XP_UCHAR*)"Last message acknowledged: %d\n",
|
||||||
rec->lastACK);
|
rec->lastACK);
|
||||||
stream_putString( stream, buf );
|
stream_putString( stream, buf );
|
||||||
|
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
XP_SNPRINTF( (XP_UCHAR*)buf, sizeof(buf),
|
||||||
|
(XP_UCHAR*)"Last ack'd %ld secs ago\n",
|
||||||
|
now - rec->lastMsgRcvdTime );
|
||||||
|
stream_putString( stream, buf );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} /* comms_getStats */
|
} /* comms_getStats */
|
||||||
#endif
|
#endif
|
||||||
|
@ -1277,13 +1412,14 @@ send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd, XWHostID destID,
|
||||||
stream_putU8( tmpStream, comms->r.myHostID );
|
stream_putU8( tmpStream, comms->r.myHostID );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef RELAY_HEARTBEAT
|
||||||
case XWRELAY_HEARTBEAT:
|
case XWRELAY_HEARTBEAT:
|
||||||
/* Add these for grins. Server can assert they match the IP
|
/* Add these for grins. Server can assert they match the IP
|
||||||
address it expects 'em on. */
|
address it expects 'em on. */
|
||||||
stream_putU16( tmpStream, comms->r.cookieID );
|
stream_putU16( tmpStream, comms->r.cookieID );
|
||||||
stream_putU8( tmpStream, comms->r.myHostID );
|
stream_putU8( tmpStream, comms->r.myHostID );
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
XP_ASSERT(0);
|
XP_ASSERT(0);
|
||||||
}
|
}
|
||||||
|
@ -1359,6 +1495,8 @@ send_via_bt( CommsCtxt* comms, BTMsgType typ, XP_PlayerAddr channelNo,
|
||||||
|
|
||||||
nSent = (*comms->sendproc)( buf, dlen+1, addr, comms->sendClosure );
|
nSent = (*comms->sendproc)( buf, dlen+1, addr, comms->sendClosure );
|
||||||
XP_FREE( comms->mpool, buf );
|
XP_FREE( comms->mpool, buf );
|
||||||
|
|
||||||
|
setHeartbeatTimer( comms );
|
||||||
}
|
}
|
||||||
return nSent;
|
return nSent;
|
||||||
} /* send_via_bt */
|
} /* send_via_bt */
|
||||||
|
|
|
@ -54,6 +54,12 @@ typedef enum {
|
||||||
typedef struct XP_BtAddr { XP_U8 bits[6]; } XP_BtAddr;
|
typedef struct XP_BtAddr { XP_U8 bits[6]; } XP_BtAddr;
|
||||||
typedef struct XP_BtAddrStr { XP_UCHAR chars[18]; } XP_BtAddrStr;
|
typedef struct XP_BtAddrStr { XP_UCHAR chars[18]; } XP_BtAddrStr;
|
||||||
|
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
# define IF_CH(a) a,
|
||||||
|
#else
|
||||||
|
# define IF_CH(a)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_HOSTNAME_LEN 63
|
#define MAX_HOSTNAME_LEN 63
|
||||||
typedef struct CommsAddrRec {
|
typedef struct CommsAddrRec {
|
||||||
CommsConnType conType;
|
CommsConnType conType;
|
||||||
|
@ -85,11 +91,13 @@ typedef struct CommsAddrRec {
|
||||||
typedef XP_S16 (*TransportSend)( const XP_U8* buf, XP_U16 len,
|
typedef XP_S16 (*TransportSend)( const XP_U8* buf, XP_U16 len,
|
||||||
const CommsAddrRec* addr,
|
const CommsAddrRec* addr,
|
||||||
void* closure );
|
void* closure );
|
||||||
|
typedef void (*TransportReset)( void* closure );
|
||||||
|
|
||||||
CommsCtxt* comms_make( MPFORMAL XW_UtilCtxt* util,
|
CommsCtxt* comms_make( MPFORMAL XW_UtilCtxt* util,
|
||||||
XP_Bool isServer,
|
XP_Bool isServer,
|
||||||
XP_U16 nPlayersHere, XP_U16 nPlayersTotal,
|
XP_U16 nPlayersHere, XP_U16 nPlayersTotal,
|
||||||
TransportSend sendproc, void* closure );
|
TransportSend sendproc, IF_CH(TransportReset resetproc)
|
||||||
|
void* closure );
|
||||||
|
|
||||||
void comms_reset( CommsCtxt* comms, XP_Bool isServer,
|
void comms_reset( CommsCtxt* comms, XP_Bool isServer,
|
||||||
XP_U16 nPlayersHere, XP_U16 nPlayersTotal );
|
XP_U16 nPlayersHere, XP_U16 nPlayersTotal );
|
||||||
|
@ -107,6 +115,7 @@ XP_Bool comms_getIsServer( const CommsCtxt* comms );
|
||||||
|
|
||||||
CommsCtxt* comms_makeFromStream( MPFORMAL XWStreamCtxt* stream,
|
CommsCtxt* comms_makeFromStream( MPFORMAL XWStreamCtxt* stream,
|
||||||
XW_UtilCtxt* util, TransportSend sendproc,
|
XW_UtilCtxt* util, TransportSend sendproc,
|
||||||
|
IF_CH(TransportReset resetproc)
|
||||||
void* closure );
|
void* closure );
|
||||||
void comms_start( CommsCtxt* comms );
|
void comms_start( CommsCtxt* comms );
|
||||||
void comms_writeToStream( const CommsCtxt* comms, XWStreamCtxt* stream );
|
void comms_writeToStream( const CommsCtxt* comms, XWStreamCtxt* stream );
|
||||||
|
|
|
@ -103,7 +103,7 @@ typedef XP_U16 XP_PlayerAddr;
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TIMER_PENDOWN = 1, /* ARM doesn't like ids of 0... */
|
TIMER_PENDOWN = 1, /* ARM doesn't like ids of 0... */
|
||||||
TIMER_TIMERTICK,
|
TIMER_TIMERTICK,
|
||||||
#ifdef XWFEATURE_RELAY
|
#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT
|
||||||
TIMER_HEARTBEAT,
|
TIMER_HEARTBEAT,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,8 @@ void
|
||||||
game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||||
XW_UtilCtxt* util, DrawCtx* draw,
|
XW_UtilCtxt* util, DrawCtx* draw,
|
||||||
XP_U16 gameID, CommonPrefs* cp,
|
XP_U16 gameID, CommonPrefs* cp,
|
||||||
TransportSend sendproc, void* closure )
|
TransportSend sendproc, IF_CH( TransportReset resetproc )
|
||||||
|
void* closure )
|
||||||
{
|
{
|
||||||
XP_U16 nPlayersHere, nPlayersTotal;
|
XP_U16 nPlayersHere, nPlayersTotal;
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||||
game->comms = comms_make( MPPARM(mpool) util,
|
game->comms = comms_make( MPPARM(mpool) util,
|
||||||
gi->serverRole != SERVER_ISCLIENT,
|
gi->serverRole != SERVER_ISCLIENT,
|
||||||
nPlayersHere, nPlayersTotal,
|
nPlayersHere, nPlayersTotal,
|
||||||
sendproc, closure );
|
sendproc, IF_CH(resetproc) closure );
|
||||||
} else {
|
} else {
|
||||||
game->comms = (CommsCtxt*)NULL;
|
game->comms = (CommsCtxt*)NULL;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +113,7 @@ game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||||
void
|
void
|
||||||
game_reset( MPFORMAL XWGame* game, CurGameInfo* gi, XW_UtilCtxt* util,
|
game_reset( MPFORMAL XWGame* game, CurGameInfo* gi, XW_UtilCtxt* util,
|
||||||
XP_U16 gameID, CommonPrefs* cp, TransportSend sendproc,
|
XP_U16 gameID, CommonPrefs* cp, TransportSend sendproc,
|
||||||
void* closure )
|
IF_CH(TransportReset resetproc) void* closure )
|
||||||
{
|
{
|
||||||
XP_U16 i;
|
XP_U16 i;
|
||||||
XP_U16 nPlayersHere, nPlayersTotal;
|
XP_U16 nPlayersHere, nPlayersTotal;
|
||||||
|
@ -136,7 +137,7 @@ game_reset( MPFORMAL XWGame* game, CurGameInfo* gi, XW_UtilCtxt* util,
|
||||||
game->comms = comms_make( MPPARM(mpool) util,
|
game->comms = comms_make( MPPARM(mpool) util,
|
||||||
gi->serverRole != SERVER_ISCLIENT,
|
gi->serverRole != SERVER_ISCLIENT,
|
||||||
nPlayersHere, nPlayersTotal,
|
nPlayersHere, nPlayersTotal,
|
||||||
sendproc, closure );
|
sendproc, IF_CH(resetproc) closure );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -162,7 +163,8 @@ XP_Bool
|
||||||
game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
||||||
CurGameInfo* gi, DictionaryCtxt* dict,
|
CurGameInfo* gi, DictionaryCtxt* dict,
|
||||||
XW_UtilCtxt* util, DrawCtx* draw, CommonPrefs* cp,
|
XW_UtilCtxt* util, DrawCtx* draw, CommonPrefs* cp,
|
||||||
TransportSend sendProc, void* closure )
|
TransportSend sendProc, IF_CH(TransportReset resetProc)
|
||||||
|
void* closure )
|
||||||
{
|
{
|
||||||
XP_Bool success = XP_FALSE;
|
XP_Bool success = XP_FALSE;
|
||||||
XP_U8 strVersion;
|
XP_U8 strVersion;
|
||||||
|
@ -181,7 +183,7 @@ game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
||||||
hasComms = stream_getU8( stream );
|
hasComms = stream_getU8( stream );
|
||||||
if ( hasComms ) {
|
if ( hasComms ) {
|
||||||
game->comms = comms_makeFromStream( MPPARM(mpool) stream, util,
|
game->comms = comms_makeFromStream( MPPARM(mpool) stream, util,
|
||||||
sendProc, closure );
|
sendProc, IF_CH(resetProc) closure );
|
||||||
} else {
|
} else {
|
||||||
game->comms = NULL;
|
game->comms = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,16 +81,18 @@ typedef struct XWGame {
|
||||||
|
|
||||||
void game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
void game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||||
XW_UtilCtxt* util, DrawCtx* draw, XP_U16 gameID,
|
XW_UtilCtxt* util, DrawCtx* draw, XP_U16 gameID,
|
||||||
CommonPrefs* cp, TransportSend sendproc, void* closure);
|
CommonPrefs* cp, TransportSend sendproc,
|
||||||
|
IF_CH(TransportReset resetproc) void* closure);
|
||||||
void game_reset( MPFORMAL XWGame* game, CurGameInfo* gi, XW_UtilCtxt* util,
|
void game_reset( MPFORMAL XWGame* game, CurGameInfo* gi, XW_UtilCtxt* util,
|
||||||
XP_U16 gameID, CommonPrefs* cp, TransportSend sendproc,
|
XP_U16 gameID, CommonPrefs* cp, TransportSend sendproc,
|
||||||
void* closure );
|
IF_CH(TransportReset resetproc) void* closure );
|
||||||
|
|
||||||
XP_Bool game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
XP_Bool game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
||||||
CurGameInfo* gi,
|
CurGameInfo* gi,
|
||||||
DictionaryCtxt* dict, XW_UtilCtxt* util,
|
DictionaryCtxt* dict, XW_UtilCtxt* util,
|
||||||
DrawCtx* draw, CommonPrefs* cp,
|
DrawCtx* draw, CommonPrefs* cp,
|
||||||
TransportSend sendProc, void* closure );
|
TransportSend sendProc, IF_CH(TransportReset rp)
|
||||||
|
void* closure );
|
||||||
|
|
||||||
void game_saveToStream( const XWGame* game, const CurGameInfo* gi,
|
void game_saveToStream( const XWGame* game, const CurGameInfo* gi,
|
||||||
XWStreamCtxt* stream );
|
XWStreamCtxt* stream );
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#define LETTER_NONE '\0'
|
#define LETTER_NONE '\0'
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
ERR_NONE, /* 0 is special case */
|
||||||
ERR_TILES_NOT_IN_LINE, /* scoring a move where tiles aren't in line */
|
ERR_TILES_NOT_IN_LINE, /* scoring a move where tiles aren't in line */
|
||||||
ERR_NO_EMPTIES_IN_TURN,
|
ERR_NO_EMPTIES_IN_TURN,
|
||||||
ERR_TWO_TILES_FIRST_MOVE,
|
ERR_TWO_TILES_FIRST_MOVE,
|
||||||
|
|
|
@ -64,12 +64,19 @@ DEFINES += -DFEATURE_TRAY_EDIT
|
||||||
#DEFINES += -DDRAW_WITH_PRIMITIVES
|
#DEFINES += -DDRAW_WITH_PRIMITIVES
|
||||||
|
|
||||||
# Bluetooth support
|
# Bluetooth support
|
||||||
#BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_L2CAP
|
BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_L2CAP
|
||||||
BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_RFCOMM
|
#BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_RFCOMM
|
||||||
# DEFINES += -DXWFEATURE_IR
|
# DEFINES += -DXWFEATURE_IR
|
||||||
DEFINES += ${BLUETOOTH}
|
DEFINES += ${BLUETOOTH}
|
||||||
DEFINES += -DXWFEATURE_RELAY
|
DEFINES += -DXWFEATURE_RELAY
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# user experience will be very bad!). Is particularly useful with BT.
|
||||||
|
# DEFINES += -DRELAY_HEARTBEAT
|
||||||
|
DEFINES += -DCOMMS_HEARTBEAT
|
||||||
|
|
||||||
# Let users pick the tiles going into their trays
|
# Let users pick the tiles going into their trays
|
||||||
#DEFINES += -DFEATURE_TRAY_EDIT
|
#DEFINES += -DFEATURE_TRAY_EDIT
|
||||||
DEFINES += -DDONT_ABORT_ENGINE
|
DEFINES += -DDONT_ABORT_ENGINE
|
||||||
|
|
|
@ -1048,7 +1048,8 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
||||||
gameID = (XP_U16)util_getCurSeconds( globals.cGlobals.params->util );
|
gameID = (XP_U16)util_getCurSeconds( globals.cGlobals.params->util );
|
||||||
game_makeNewGame( MEMPOOL &globals.cGlobals.game, ¶ms->gi,
|
game_makeNewGame( MEMPOOL &globals.cGlobals.game, ¶ms->gi,
|
||||||
params->util, (DrawCtx*)globals.draw,
|
params->util, (DrawCtx*)globals.draw,
|
||||||
gameID, &globals.cp, linux_send, &globals );
|
gameID, &globals.cp, linux_send,
|
||||||
|
IF_CH(linux_reset) &globals );
|
||||||
|
|
||||||
if ( globals.cGlobals.game.comms ) {
|
if ( globals.cGlobals.game.comms ) {
|
||||||
CommsAddrRec addr;
|
CommsAddrRec addr;
|
||||||
|
|
|
@ -308,7 +308,7 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
||||||
params->dict, params->util,
|
params->dict, params->util,
|
||||||
(DrawCtx*)globals->draw,
|
(DrawCtx*)globals->draw,
|
||||||
&globals->cp,
|
&globals->cp,
|
||||||
linux_send, globals );
|
linux_send, IF_CH(linux_reset) globals );
|
||||||
|
|
||||||
stream_destroy( stream );
|
stream_destroy( stream );
|
||||||
}
|
}
|
||||||
|
@ -334,7 +334,8 @@ createOrLoadObjects( GtkAppGlobals* globals )
|
||||||
|
|
||||||
game_makeNewGame( MEMPOOL &globals->cGlobals.game, ¶ms->gi,
|
game_makeNewGame( MEMPOOL &globals->cGlobals.game, ¶ms->gi,
|
||||||
params->util, (DrawCtx*)globals->draw,
|
params->util, (DrawCtx*)globals->draw,
|
||||||
gameID, &globals->cp, linux_send, globals );
|
gameID, &globals->cp, linux_send,
|
||||||
|
IF_CH(linux_reset) globals );
|
||||||
|
|
||||||
addr.conType = params->conType;
|
addr.conType = params->conType;
|
||||||
if ( 0 ) {
|
if ( 0 ) {
|
||||||
|
@ -631,7 +632,8 @@ new_game( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
|
||||||
XP_STATUSF( "grabbed gameID: %ld\n", gameID );
|
XP_STATUSF( "grabbed gameID: %ld\n", gameID );
|
||||||
game_reset( MEMPOOL &globals->cGlobals.game, gi,
|
game_reset( MEMPOOL &globals->cGlobals.game, gi,
|
||||||
globals->cGlobals.params->util,
|
globals->cGlobals.params->util,
|
||||||
gameID, &globals->cp, linux_send, globals );
|
gameID, &globals->cp, linux_send,
|
||||||
|
IF_CH(linux_reset) globals );
|
||||||
|
|
||||||
if ( isClient ) {
|
if ( isClient ) {
|
||||||
XWStreamCtxt* stream =
|
XWStreamCtxt* stream =
|
||||||
|
@ -1674,6 +1676,7 @@ acceptorInput( GIOChannel* source, GIOCondition condition, gpointer data )
|
||||||
|
|
||||||
if ( (condition & G_IO_IN) != 0 ) {
|
if ( (condition & G_IO_IN) != 0 ) {
|
||||||
int listener = g_io_channel_unix_get_fd( source );
|
int listener = g_io_channel_unix_get_fd( source );
|
||||||
|
XP_LOGF( "%s: input on socket %d", __func__, listener );
|
||||||
keepSource = (*globals->acceptor)( listener, data );
|
keepSource = (*globals->acceptor)( listener, data );
|
||||||
} else {
|
} else {
|
||||||
keepSource = FALSE;
|
keepSource = FALSE;
|
||||||
|
@ -1694,9 +1697,11 @@ gtk_socket_acceptor( int listener, Acceptor func, CommonGlobals* globals )
|
||||||
globals->acceptor = func;
|
globals->acceptor = func;
|
||||||
|
|
||||||
channel = g_io_channel_unix_new( listener );
|
channel = g_io_channel_unix_new( listener );
|
||||||
|
g_io_channel_set_close_on_unref( channel, TRUE );
|
||||||
result = g_io_add_watch( channel,
|
result = g_io_add_watch( channel,
|
||||||
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI,
|
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI,
|
||||||
acceptorInput, globals );
|
acceptorInput, globals );
|
||||||
|
g_io_channel_unref( channel ); /* only main loop holds it now */
|
||||||
XP_LOGF( "%s: g_io_add_watch(%d) => %d", __FUNCTION__, listener, result );
|
XP_LOGF( "%s: g_io_add_watch(%d) => %d", __FUNCTION__, listener, result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,19 +76,34 @@ static void
|
||||||
lbt_addSock( LinBtStuff* btStuff, const bdaddr_t* btaddr, int sock )
|
lbt_addSock( LinBtStuff* btStuff, const bdaddr_t* btaddr, int sock )
|
||||||
{
|
{
|
||||||
XP_U16 i;
|
XP_U16 i;
|
||||||
|
XP_Bool done = XP_FALSE;
|
||||||
|
|
||||||
XP_ASSERT( btStuff->amMaster );
|
XP_ASSERT( btStuff->amMaster );
|
||||||
XP_ASSERT( btStuff->u.master.nSocks < MAX_CLIENTS - 1 );
|
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 ) {
|
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||||
if ( mp->sock == -1 ) {
|
if ( (mp->sock != -1) && (0 == memcmp( btaddr, &mp->btaddr, sizeof(*btaddr) )) ) {
|
||||||
XP_MEMCPY( &mp->btaddr, btaddr, sizeof(mp->btaddr) );
|
(void)close( mp->sock );
|
||||||
mp->sock = sock;
|
mp->sock = sock;
|
||||||
++btStuff->u.master.nSocks;
|
done = XP_TRUE;
|
||||||
break;
|
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 );
|
XP_ASSERT( i < MAX_CLIENTS );
|
||||||
} /* lbt_addSock */
|
} /* lbt_addSock */
|
||||||
|
|
||||||
|
@ -98,17 +113,16 @@ lbt_removeSock( LinBtStuff* btStuff, int sock )
|
||||||
XP_U16 i;
|
XP_U16 i;
|
||||||
|
|
||||||
XP_ASSERT( btStuff->amMaster );
|
XP_ASSERT( btStuff->amMaster );
|
||||||
XP_ASSERT( btStuff->u.master.nSocks > 0 );
|
|
||||||
|
|
||||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||||
if ( mp->sock == sock ) {
|
if ( mp->sock == sock ) {
|
||||||
mp->sock = -1;
|
mp->sock = -1;
|
||||||
|
XP_ASSERT( btStuff->u.master.nSocks > 0 );
|
||||||
--btStuff->u.master.nSocks;
|
--btStuff->u.master.nSocks;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XP_ASSERT( i < MAX_CLIENTS );
|
|
||||||
} /* lbt_removeSock */
|
} /* lbt_removeSock */
|
||||||
|
|
||||||
static LinBtStuff*
|
static LinBtStuff*
|
||||||
|
@ -232,7 +246,7 @@ lbt_connectSocket( LinBtStuff* btStuff, const CommsAddrRec* addrP )
|
||||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||||
-1, sock );
|
-1, sock );
|
||||||
} else {
|
} else {
|
||||||
XP_LOGF( "%s: connect->%s", __FUNCTION__, strerror(errno) );
|
XP_LOGF( "%s: connect->%s; closing socket %d", __FUNCTION__, strerror(errno), sock );
|
||||||
close( sock );
|
close( sock );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,11 +264,11 @@ lbt_accept( int listener, void* ctxt )
|
||||||
|
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
|
|
||||||
XP_LOGF( "%s: calling accept", __FUNCTION__ );
|
XP_LOGF( "%s: calling accept", __func__ );
|
||||||
slen = sizeof( inaddr );
|
slen = sizeof( inaddr );
|
||||||
XP_ASSERT( listener == btStuff->u.master.listener );
|
XP_ASSERT( listener == btStuff->u.master.listener );
|
||||||
sock = accept( listener, (struct sockaddr *)&inaddr, &slen );
|
sock = accept( listener, (struct sockaddr *)&inaddr, &slen );
|
||||||
XP_LOGF( "%s: accept returned; sock = %d", __FUNCTION__, sock );
|
XP_LOGF( "%s: accept returned; socket = %d", __func__, sock );
|
||||||
|
|
||||||
success = sock >= 0;
|
success = sock >= 0;
|
||||||
if ( success ) {
|
if ( success ) {
|
||||||
|
@ -393,6 +407,7 @@ lbt_listenerSetup( CommonGlobals* globals )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
XP_LOGF( "%s: calling listen on socket %d", __func__, listener );
|
||||||
listen( listener, MAX_CLIENTS );
|
listen( listener, MAX_CLIENTS );
|
||||||
|
|
||||||
lbt_register( btStuff, htobs( XW_PSM ), rc_channel );
|
lbt_register( btStuff, htobs( XW_PSM ), rc_channel );
|
||||||
|
@ -422,14 +437,36 @@ linux_bt_open( CommonGlobals* globals, XP_Bool amMaster )
|
||||||
}
|
}
|
||||||
} /* linux_bt_open */
|
} /* linux_bt_open */
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_bt_reset( CommonGlobals* globals )
|
||||||
|
{
|
||||||
|
XP_Bool amMaster = globals->btStuff->amMaster;
|
||||||
|
LOG_FUNC();
|
||||||
|
linux_bt_close( globals );
|
||||||
|
linux_bt_open( globals, amMaster );
|
||||||
|
LOG_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
linux_bt_close( CommonGlobals* globals )
|
linux_bt_close( CommonGlobals* globals )
|
||||||
{
|
{
|
||||||
LinBtStuff* btStuff = globals->btStuff;
|
LinBtStuff* btStuff = globals->btStuff;
|
||||||
|
XP_U16 i;
|
||||||
|
|
||||||
if ( !!btStuff ) {
|
if ( !!btStuff ) {
|
||||||
if ( btStuff->amMaster ) {
|
if ( btStuff->amMaster ) {
|
||||||
|
XP_LOGF( "%s: closing listener socket %d", __func__, btStuff->u.master.listener );
|
||||||
close( btStuff->u.master.listener );
|
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 );
|
sdp_close( btStuff->u.master.session );
|
||||||
XP_LOGF( "sleeping for Palm's sake..." );
|
XP_LOGF( "sleeping for Palm's sake..." );
|
||||||
sleep( 2 ); /* see if this gives palm a chance to not hang */
|
sleep( 2 ); /* see if this gives palm a chance to not hang */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
void linux_bt_open( CommonGlobals* globals, XP_Bool amMaster );
|
void linux_bt_open( CommonGlobals* globals, XP_Bool amMaster );
|
||||||
|
void linux_bt_reset( CommonGlobals* globals );
|
||||||
void linux_bt_close( CommonGlobals* globals );
|
void linux_bt_close( CommonGlobals* globals );
|
||||||
|
|
||||||
XP_S16 linux_bt_send( const XP_U8* buf, XP_U16 buflen,
|
XP_S16 linux_bt_send( const XP_U8* buf, XP_U16 buflen,
|
||||||
|
|
|
@ -422,6 +422,22 @@ linux_tcp_send( const XP_U8* buf, XP_U16 buflen,
|
||||||
} /* linux_tcp_send */
|
} /* linux_tcp_send */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
void
|
||||||
|
linux_reset( void* closure )
|
||||||
|
{
|
||||||
|
CommonGlobals* globals = (CommonGlobals*)closure;
|
||||||
|
CommsConnType conType = globals->params->conType;
|
||||||
|
if ( 0 ) {
|
||||||
|
#ifdef XWFEATURE_BLUETOOTH
|
||||||
|
} else if ( conType == COMMS_CONN_BT ) {
|
||||||
|
linux_bt_reset( globals );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
XP_S16
|
XP_S16
|
||||||
linux_send( const XP_U8* buf, XP_U16 buflen,
|
linux_send( const XP_U8* buf, XP_U16 buflen,
|
||||||
const CommsAddrRec* addrRec,
|
const CommsAddrRec* addrRec,
|
||||||
|
|
|
@ -39,6 +39,9 @@ DictionaryCtxt* linux_dictionary_make( MPFORMAL const char* dictFileName );
|
||||||
int initListenerSocket( int port );
|
int initListenerSocket( int port );
|
||||||
XP_S16 linux_send( const XP_U8* buf, XP_U16 buflen,
|
XP_S16 linux_send( const XP_U8* buf, XP_U16 buflen,
|
||||||
const CommsAddrRec* addrRec, void* closure );
|
const CommsAddrRec* addrRec, void* closure );
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
void linux_reset( void* closure );
|
||||||
|
#endif
|
||||||
int linux_relay_receive( CommonGlobals* cGlobals, unsigned char* buf,
|
int linux_relay_receive( CommonGlobals* cGlobals, unsigned char* buf,
|
||||||
int bufSize );
|
int bufSize );
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ MYDEFS_COMMON += -DXWFEATURE_SEARCHLIMIT
|
||||||
# MYDEFS_COMMON += -DXWFEATURE_RELAY
|
# MYDEFS_COMMON += -DXWFEATURE_RELAY
|
||||||
|
|
||||||
# turn on bluetooth comms option for 68K and ARM
|
# turn on bluetooth comms option for 68K and ARM
|
||||||
BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_L2CAP
|
BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_L2CAP -DCOMMS_HEARTBEAT
|
||||||
#BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_RFCOMM
|
#BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_RFCOMM
|
||||||
MYDEFS_COMMON += $(BLUETOOTH)
|
MYDEFS_COMMON += $(BLUETOOTH)
|
||||||
|
|
||||||
|
|
|
@ -158,8 +158,8 @@ static XP_S16 pbt_enqueue( PBT_queue* queue, const XP_U8* data, XP_S16 len,
|
||||||
static void pbt_handoffIncoming( PalmBTStuff* btStuff, BtCbEvtProc proc );
|
static void pbt_handoffIncoming( PalmBTStuff* btStuff, BtCbEvtProc proc );
|
||||||
|
|
||||||
static void waitACL( PalmBTStuff* btStuff );
|
static void waitACL( PalmBTStuff* btStuff );
|
||||||
static void pbt_reset( PalmBTStuff* btStuff );
|
static void pbt_reset_buffers( PalmBTStuff* btStuff );
|
||||||
static void pbt_killL2C( PalmBTStuff* btStuff, BtLibSocketRef sock );
|
static void pbt_killLinks( PalmBTStuff* btStuff, BtLibSocketRef sock );
|
||||||
static XP_Bool pbt_checkAddress( PalmBTStuff* btStuff, const CommsAddrRec* addr );
|
static XP_Bool pbt_checkAddress( PalmBTStuff* btStuff, const CommsAddrRec* addr );
|
||||||
static void pbt_setstate( PalmBTStuff* btStuff, PBT_STATE newState,
|
static void pbt_setstate( PalmBTStuff* btStuff, PBT_STATE newState,
|
||||||
const char* whence );
|
const char* whence );
|
||||||
|
@ -202,7 +202,7 @@ palm_bt_init( PalmAppGlobals* globals, XP_Bool* userCancelled )
|
||||||
btStuff = pbt_checkInit( globals, userCancelled );
|
btStuff = pbt_checkInit( globals, userCancelled );
|
||||||
/* Should I start master/slave setup here? If not, how? */
|
/* Should I start master/slave setup here? If not, how? */
|
||||||
} else {
|
} else {
|
||||||
pbt_reset( btStuff );
|
pbt_reset_buffers( btStuff );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're the master, and a new game is starting without shutting down,
|
/* If we're the master, and a new game is starting without shutting down,
|
||||||
|
@ -222,6 +222,28 @@ palm_bt_init( PalmAppGlobals* globals, XP_Bool* userCancelled )
|
||||||
return inited;
|
return inited;
|
||||||
} /* palm_bt_init */
|
} /* palm_bt_init */
|
||||||
|
|
||||||
|
void
|
||||||
|
palm_bt_reset( PalmAppGlobals* globals )
|
||||||
|
{
|
||||||
|
PalmBTStuff* btStuff = globals->btStuff;
|
||||||
|
if ( !!btStuff ) {
|
||||||
|
if ( btStuff->dataSocket != SOCK_INVAL ) {
|
||||||
|
pbt_killLinks( btStuff, btStuff->dataSocket );
|
||||||
|
}
|
||||||
|
/* nuke all pending messages */
|
||||||
|
pbt_reset_buffers( btStuff );
|
||||||
|
btStuff->queueLen = 0;
|
||||||
|
|
||||||
|
if ( btStuff->picoRole == PBT_MASTER ) {
|
||||||
|
pbt_setup_master( btStuff );
|
||||||
|
} else if ( btStuff->picoRole == PBT_SLAVE ) {
|
||||||
|
CommsAddrRec remoteAddr;
|
||||||
|
comms_getAddr( globals->game.comms, &remoteAddr );
|
||||||
|
pbt_setup_slave( btStuff, &remoteAddr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
palm_bt_close( PalmAppGlobals* globals )
|
palm_bt_close( PalmAppGlobals* globals )
|
||||||
{
|
{
|
||||||
|
@ -431,6 +453,7 @@ pbt_send_pending( PalmBTStuff* btStuff )
|
||||||
#ifdef LOG_BTIO
|
#ifdef LOG_BTIO
|
||||||
LOG_HEX( buf, len, "to BtLibSocketSend" );
|
LOG_HEX( buf, len, "to BtLibSocketSend" );
|
||||||
#endif
|
#endif
|
||||||
|
XP_LOGF( "sending on socket %d", btStuff->dataSocket );
|
||||||
CALL_ERR( err, BtLibSocketSend, btStuff->btLibRefNum,
|
CALL_ERR( err, BtLibSocketSend, btStuff->btLibRefNum,
|
||||||
btStuff->dataSocket, (char*)buf, len );
|
btStuff->dataSocket, (char*)buf, len );
|
||||||
if ( btLibErrPending == err ) {
|
if ( btLibErrPending == err ) {
|
||||||
|
@ -578,6 +601,17 @@ pbt_close_datasocket( PalmBTStuff* btStuff )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pbt_close_sdpsocket( PalmBTStuff* btStuff )
|
||||||
|
{
|
||||||
|
XP_ASSERT( PBT_SLAVE == btStuff->picoRole );
|
||||||
|
if ( SOCK_INVAL != btStuff->u.slave.sdpSocket ) {
|
||||||
|
Err err;
|
||||||
|
CALL_ERR( err, BtLibSocketClose, btStuff->btLibRefNum, btStuff->u.slave.sdpSocket );
|
||||||
|
btStuff->u.slave.sdpSocket = SOCK_INVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pbt_takedown_master( PalmBTStuff* btStuff )
|
pbt_takedown_master( PalmBTStuff* btStuff )
|
||||||
{
|
{
|
||||||
|
@ -669,11 +703,13 @@ pbt_do_work( PalmBTStuff* btStuff, BtCbEvtProc proc )
|
||||||
|
|
||||||
case PBT_ACT_GETSDP:
|
case PBT_ACT_GETSDP:
|
||||||
if ( PBTST_ACL_CONNECTED == GET_STATE(btStuff) ) {
|
if ( PBTST_ACL_CONNECTED == GET_STATE(btStuff) ) {
|
||||||
|
XP_ASSERT( SOCK_INVAL == btStuff->u.slave.sdpSocket );
|
||||||
CALL_ERR( err, BtLibSocketCreate, btStuff->btLibRefNum,
|
CALL_ERR( err, BtLibSocketCreate, btStuff->btLibRefNum,
|
||||||
&btStuff->u.slave.sdpSocket, socketCallback, (UInt32)btStuff,
|
&btStuff->u.slave.sdpSocket, socketCallback, (UInt32)btStuff,
|
||||||
btLibSdpProtocol );
|
btLibSdpProtocol );
|
||||||
if ( err == errNone ) {
|
if ( err == errNone ) {
|
||||||
#if defined BT_USE_L2CAP
|
#if defined BT_USE_L2CAP
|
||||||
|
XP_LOGF( "sending on sdpSocket socket %d", btStuff->u.slave.sdpSocket );
|
||||||
CALL_ERR( err, BtLibSdpGetPsmByUuid, btStuff->btLibRefNum,
|
CALL_ERR( err, BtLibSdpGetPsmByUuid, btStuff->btLibRefNum,
|
||||||
btStuff->u.slave.sdpSocket, &btStuff->otherAddr,
|
btStuff->u.slave.sdpSocket, &btStuff->otherAddr,
|
||||||
(BtLibSdpUuidType*)&XWORDS_UUID, 1 );
|
(BtLibSdpUuidType*)&XWORDS_UUID, 1 );
|
||||||
|
@ -699,6 +735,7 @@ pbt_do_work( PalmBTStuff* btStuff, BtCbEvtProc proc )
|
||||||
}
|
}
|
||||||
/* Presumably state's been reset since PBT_ACT_GETSDP issued */
|
/* Presumably state's been reset since PBT_ACT_GETSDP issued */
|
||||||
XP_LOGF( "aborting b/c state wrong" );
|
XP_LOGF( "aborting b/c state wrong" );
|
||||||
|
pbt_close_sdpsocket( btStuff );
|
||||||
SET_STATE( btStuff, PBTST_NONE );
|
SET_STATE( btStuff, PBTST_NONE );
|
||||||
waitACL( btStuff );
|
waitACL( btStuff );
|
||||||
break;
|
break;
|
||||||
|
@ -745,7 +782,9 @@ pbt_do_work( PalmBTStuff* btStuff, BtCbEvtProc proc )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PBT_ACT_GOTDATA:
|
case PBT_ACT_GOTDATA:
|
||||||
CALL_ERR( err, BtLibSocketAdvanceCredit, btLibRefNum, btStuff->dataSocket, 1 );
|
#ifdef BT_USE_RFCOMM
|
||||||
|
CALL_ERR( err, BtLibSocketAdvanceCredit, btLibRefNum, btStuff->dataSocket, 5 );
|
||||||
|
#endif
|
||||||
pbt_handoffIncoming( btStuff, proc );
|
pbt_handoffIncoming( btStuff, proc );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -892,7 +931,7 @@ pbt_handoffIncoming( PalmBTStuff* btStuff, BtCbEvtProc proc )
|
||||||
} /* pbt_handoffIncoming */
|
} /* pbt_handoffIncoming */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pbt_reset( PalmBTStuff* btStuff )
|
pbt_reset_buffers( PalmBTStuff* btStuff )
|
||||||
{
|
{
|
||||||
LOG_FUNC();
|
LOG_FUNC();
|
||||||
XP_MEMSET( &btStuff->vol, 0, sizeof(btStuff->vol) );
|
XP_MEMSET( &btStuff->vol, 0, sizeof(btStuff->vol) );
|
||||||
|
@ -940,6 +979,7 @@ pbt_setup_slave( PalmBTStuff* btStuff, const CommsAddrRec* addr )
|
||||||
pbt_takedown_master( btStuff );
|
pbt_takedown_master( btStuff );
|
||||||
}
|
}
|
||||||
btStuff->picoRole = PBT_SLAVE;
|
btStuff->picoRole = PBT_SLAVE;
|
||||||
|
btStuff->u.slave.sdpSocket = SOCK_INVAL;
|
||||||
|
|
||||||
if ( !!addr ) {
|
if ( !!addr ) {
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
@ -964,7 +1004,7 @@ pbt_setup_slave( PalmBTStuff* btStuff, const CommsAddrRec* addr )
|
||||||
static void
|
static void
|
||||||
pbt_takedown_slave( PalmBTStuff* btStuff )
|
pbt_takedown_slave( PalmBTStuff* btStuff )
|
||||||
{
|
{
|
||||||
pbt_killL2C( btStuff, btStuff->dataSocket );
|
pbt_killLinks( btStuff, btStuff->dataSocket );
|
||||||
btStuff->picoRole = PBT_UNINIT;
|
btStuff->picoRole = PBT_UNINIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,6 +1035,7 @@ pbt_checkInit( PalmAppGlobals* globals, XP_Bool* userCancelledP )
|
||||||
|
|
||||||
btStuff->dataSocket = SOCK_INVAL;
|
btStuff->dataSocket = SOCK_INVAL;
|
||||||
btStuff->u.master.listenSocket = SOCK_INVAL;
|
btStuff->u.master.listenSocket = SOCK_INVAL;
|
||||||
|
btStuff->u.slave.sdpSocket = SOCK_INVAL;
|
||||||
|
|
||||||
CALL_ERR( err, BtLibRegisterManagementNotification,
|
CALL_ERR( err, BtLibRegisterManagementNotification,
|
||||||
btLibRefNum, libMgmtCallback, (UInt32)btStuff );
|
btLibRefNum, libMgmtCallback, (UInt32)btStuff );
|
||||||
|
@ -1010,13 +1051,17 @@ pbt_checkInit( PalmAppGlobals* globals, XP_Bool* userCancelledP )
|
||||||
} /* pbt_checkInit */
|
} /* pbt_checkInit */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pbt_killL2C( PalmBTStuff* btStuff, BtLibSocketRef sock )
|
pbt_killLinks( PalmBTStuff* btStuff, BtLibSocketRef sock )
|
||||||
{
|
{
|
||||||
Err err;
|
Err err;
|
||||||
|
|
||||||
XP_ASSERT( sock == btStuff->dataSocket );
|
XP_ASSERT( sock == btStuff->dataSocket );
|
||||||
pbt_close_datasocket( btStuff );
|
pbt_close_datasocket( btStuff );
|
||||||
|
|
||||||
|
if ( PBT_SLAVE == btStuff->picoRole ) {
|
||||||
|
pbt_close_sdpsocket( btStuff );
|
||||||
|
}
|
||||||
|
|
||||||
/* Harm in calling this when not connected? */
|
/* Harm in calling this when not connected? */
|
||||||
if ( GET_STATE(btStuff) != PBTST_NONE ) {
|
if ( GET_STATE(btStuff) != PBTST_NONE ) {
|
||||||
SET_STATE( btStuff, PBTST_NONE ); /* set first */
|
SET_STATE( btStuff, PBTST_NONE ); /* set first */
|
||||||
|
@ -1024,7 +1069,7 @@ pbt_killL2C( PalmBTStuff* btStuff, BtLibSocketRef sock )
|
||||||
CALL_ERR( err, BtLibLinkDisconnect, btStuff->btLibRefNum,
|
CALL_ERR( err, BtLibLinkDisconnect, btStuff->btLibRefNum,
|
||||||
&btStuff->otherAddr );
|
&btStuff->otherAddr );
|
||||||
}
|
}
|
||||||
} /* pbt_killL2C */
|
} /* pbt_killLinks */
|
||||||
|
|
||||||
static XP_Bool
|
static XP_Bool
|
||||||
pbt_checkAddress( PalmBTStuff* btStuff, const CommsAddrRec* addr )
|
pbt_checkAddress( PalmBTStuff* btStuff, const CommsAddrRec* addr )
|
||||||
|
@ -1041,7 +1086,7 @@ pbt_checkAddress( PalmBTStuff* btStuff, const CommsAddrRec* addr )
|
||||||
LOG_HEX( &addr->u.bt.btAddr.bits, sizeof(addr->u.bt.btAddr.bits),
|
LOG_HEX( &addr->u.bt.btAddr.bits, sizeof(addr->u.bt.btAddr.bits),
|
||||||
"new" );
|
"new" );
|
||||||
|
|
||||||
pbt_killL2C( btStuff, btStuff->dataSocket );
|
pbt_killLinks( btStuff, btStuff->dataSocket );
|
||||||
|
|
||||||
XP_MEMCPY( &btStuff->otherAddr, &addr->u.bt.btAddr,
|
XP_MEMCPY( &btStuff->otherAddr, &addr->u.bt.btAddr,
|
||||||
sizeof(btStuff->otherAddr) );
|
sizeof(btStuff->otherAddr) );
|
||||||
|
@ -1204,7 +1249,7 @@ socketCallback( BtLibSocketEventType* sEvent, UInt32 refCon )
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( PBT_SLAVE == btStuff->picoRole ) {
|
if ( PBT_SLAVE == btStuff->picoRole ) {
|
||||||
pbt_killL2C( btStuff, sEvent->socket );
|
pbt_killLinks( btStuff, sEvent->socket );
|
||||||
waitACL( btStuff );
|
waitACL( btStuff );
|
||||||
} else if ( PBT_MASTER == btStuff->picoRole ) {
|
} else if ( PBT_MASTER == btStuff->picoRole ) {
|
||||||
pbt_close_datasocket( btStuff );
|
pbt_close_datasocket( btStuff );
|
||||||
|
@ -1215,9 +1260,7 @@ socketCallback( BtLibSocketEventType* sEvent, UInt32 refCon )
|
||||||
case btLibSocketEventSdpGetPsmByUuid:
|
case btLibSocketEventSdpGetPsmByUuid:
|
||||||
case btLibSocketEventSdpGetServerChannelByUuid:
|
case btLibSocketEventSdpGetServerChannelByUuid:
|
||||||
XP_ASSERT( sEvent->socket == btStuff->u.slave.sdpSocket );
|
XP_ASSERT( sEvent->socket == btStuff->u.slave.sdpSocket );
|
||||||
CALL_ERR( err, BtLibSocketClose, btStuff->btLibRefNum, sEvent->socket );
|
pbt_close_sdpsocket( btStuff );
|
||||||
XP_ASSERT( err == errNone );
|
|
||||||
btStuff->u.slave.sdpSocket = SOCK_INVAL;
|
|
||||||
if ( sEvent->status == errNone ) {
|
if ( sEvent->status == errNone ) {
|
||||||
#if defined BT_USE_L2CAP
|
#if defined BT_USE_L2CAP
|
||||||
btStuff->u.slave.remotePsm = sEvent->eventData.sdpByUuid.param.psm;
|
btStuff->u.slave.remotePsm = sEvent->eventData.sdpByUuid.param.psm;
|
||||||
|
@ -1269,7 +1312,6 @@ socketCallback( BtLibSocketEventType* sEvent, UInt32 refCon )
|
||||||
static void
|
static void
|
||||||
libMgmtCallback( BtLibManagementEventType* mEvent, UInt32 refCon )
|
libMgmtCallback( BtLibManagementEventType* mEvent, UInt32 refCon )
|
||||||
{
|
{
|
||||||
Err err;
|
|
||||||
PalmBTStuff* btStuff = (PalmBTStuff*)refCon;
|
PalmBTStuff* btStuff = (PalmBTStuff*)refCon;
|
||||||
BtLibManagementEventEnum event = mEvent->event;
|
BtLibManagementEventEnum event = mEvent->event;
|
||||||
XP_LOGF( "%s(%s); status=%s", __FUNCTION__, mgmtEvtToStr(event),
|
XP_LOGF( "%s(%s); status=%s", __FUNCTION__, mgmtEvtToStr(event),
|
||||||
|
@ -1312,11 +1354,7 @@ libMgmtCallback( BtLibManagementEventType* mEvent, UInt32 refCon )
|
||||||
call!!!! */
|
call!!!! */
|
||||||
XP_ASSERT( 0 == XP_MEMCMP( &mEvent->eventData.bdAddr,
|
XP_ASSERT( 0 == XP_MEMCMP( &mEvent->eventData.bdAddr,
|
||||||
&btStuff->otherAddr, 6 ) );
|
&btStuff->otherAddr, 6 ) );
|
||||||
if ( SOCK_INVAL != btStuff->dataSocket ) {
|
pbt_close_datasocket( btStuff );
|
||||||
CALL_ERR( err, BtLibSocketClose, btStuff->btLibRefNum,
|
|
||||||
btStuff->dataSocket );
|
|
||||||
btStuff->dataSocket = SOCK_INVAL;
|
|
||||||
}
|
|
||||||
SET_STATE( btStuff, PBTST_NONE );
|
SET_STATE( btStuff, PBTST_NONE );
|
||||||
/* See comment at btLibSocketEventDisconnected */
|
/* See comment at btLibSocketEventDisconnected */
|
||||||
if ( PBT_SLAVE == btStuff->picoRole ) {
|
if ( PBT_SLAVE == btStuff->picoRole ) {
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
void palm_bt_amendWaitTicks( PalmAppGlobals* globals, Int32* result );
|
void palm_bt_amendWaitTicks( PalmAppGlobals* globals, Int32* result );
|
||||||
|
|
||||||
XP_Bool palm_bt_init( PalmAppGlobals* globals, XP_Bool* userCancelled );
|
XP_Bool palm_bt_init( PalmAppGlobals* globals, XP_Bool* userCancelled );
|
||||||
|
void palm_bt_reset( PalmAppGlobals* globals );
|
||||||
void palm_bt_close( PalmAppGlobals* globals );
|
void palm_bt_close( PalmAppGlobals* globals );
|
||||||
|
|
||||||
typedef enum { BTCBEVT_CONN, BTCBEVT_DATA, BTCBEVT_HOSTFAIL } BtCbEvt;
|
typedef enum { BTCBEVT_CONN, BTCBEVT_DATA, BTCBEVT_HOSTFAIL } BtCbEvt;
|
||||||
|
|
|
@ -91,6 +91,9 @@ static XP_Bool timeForTimer( PalmAppGlobals* globals, XWTimerReason* why,
|
||||||
XP_U32* when );
|
XP_U32* when );
|
||||||
static XP_S16 palm_send( const XP_U8* buf, XP_U16 len,
|
static XP_S16 palm_send( const XP_U8* buf, XP_U16 len,
|
||||||
const CommsAddrRec* addr, void* closure );
|
const CommsAddrRec* addr, void* closure );
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
static void palm_reset( void* closure );
|
||||||
|
#endif
|
||||||
static void palm_send_on_close( XWStreamCtxt* stream, void* closure );
|
static void palm_send_on_close( XWStreamCtxt* stream, void* closure );
|
||||||
|
|
||||||
/* callbacks */
|
/* callbacks */
|
||||||
|
@ -597,7 +600,7 @@ loadCurrentGame( PalmAppGlobals* globals, XP_U16 gIndex,
|
||||||
success = game_makeFromStream( MEMPOOL recStream, game, ginfo,
|
success = game_makeFromStream( MEMPOOL recStream, game, ginfo,
|
||||||
dict, &globals->util,
|
dict, &globals->util,
|
||||||
globals->draw, &globals->gState.cp,
|
globals->draw, &globals->gState.cp,
|
||||||
palm_send, globals );
|
palm_send, IF_CH(palm_reset) globals );
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_destroy( recStream );
|
stream_destroy( recStream );
|
||||||
|
@ -1190,7 +1193,7 @@ startApplication( PalmAppGlobals** globalsP )
|
||||||
game_makeNewGame( MEMPOOL &globals->game, &globals->gameInfo,
|
game_makeNewGame( MEMPOOL &globals->game, &globals->gameInfo,
|
||||||
&globals->util, globals->draw, gameID,
|
&globals->util, globals->draw, gameID,
|
||||||
&globals->gState.cp,
|
&globals->gState.cp,
|
||||||
palm_send, globals );
|
palm_send, IF_CH(palm_reset) globals );
|
||||||
FrmPopupForm( XW_NEWGAMES_FORM );
|
FrmPopupForm( XW_NEWGAMES_FORM );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1989,7 +1992,7 @@ initAndStartBoard( PalmAppGlobals* globals, XP_Bool newGame )
|
||||||
XP_U32 newGameID = TimGetSeconds();
|
XP_U32 newGameID = TimGetSeconds();
|
||||||
game_reset( MEMPOOL &globals->game, &globals->gameInfo,
|
game_reset( MEMPOOL &globals->game, &globals->gameInfo,
|
||||||
&globals->util, newGameID, &globals->gState.cp,
|
&globals->util, newGameID, &globals->gState.cp,
|
||||||
palm_send, globals );
|
palm_send, IF_CH(palm_reset) globals );
|
||||||
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_RELAY || defined XWFEATURE_IR
|
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_RELAY || defined XWFEATURE_IR
|
||||||
if ( !!globals->game.comms ) {
|
if ( !!globals->game.comms ) {
|
||||||
comms_setAddr( globals->game.comms,
|
comms_setAddr( globals->game.comms,
|
||||||
|
@ -3812,7 +3815,7 @@ palm_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why,
|
||||||
now += PALM_TIMER_DELAY;
|
now += PALM_TIMER_DELAY;
|
||||||
} else if ( why == TIMER_TIMERTICK ) {
|
} else if ( why == TIMER_TIMERTICK ) {
|
||||||
now += SysTicksPerSecond();
|
now += SysTicksPerSecond();
|
||||||
#ifdef XWFEATURE_RELAY
|
#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT
|
||||||
} else if ( why == TIMER_HEARTBEAT ) {
|
} else if ( why == TIMER_HEARTBEAT ) {
|
||||||
now += (secsFromNow * SysTicksPerSecond());
|
now += (secsFromNow * SysTicksPerSecond());
|
||||||
#endif
|
#endif
|
||||||
|
@ -3927,6 +3930,26 @@ palm_send( const XP_U8* buf, XP_U16 len,
|
||||||
return result;
|
return result;
|
||||||
} /* palm_send */
|
} /* palm_send */
|
||||||
|
|
||||||
|
#ifdef COMMS_HEARTBEAT
|
||||||
|
static void
|
||||||
|
palm_reset( void* closure )
|
||||||
|
{
|
||||||
|
PalmAppGlobals* globals = (PalmAppGlobals*)closure;
|
||||||
|
XP_ASSERT( !!globals->game.comms );
|
||||||
|
|
||||||
|
switch( comms_getConType( globals->game.comms ) ) {
|
||||||
|
#ifdef XWFEATURE_BLUETOOTH
|
||||||
|
case COMMS_CONN_BT:
|
||||||
|
palm_bt_reset( globals );
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
XP_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
checkAndDeliver( PalmAppGlobals* globals, const CommsAddrRec* addr,
|
checkAndDeliver( PalmAppGlobals* globals, const CommsAddrRec* addr,
|
||||||
XWStreamCtxt* instream )
|
XWStreamCtxt* instream )
|
||||||
|
|
Loading…
Reference in a new issue