From f22d9530b1f0b000fa68f99a27188206b897bb82 Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 13 Apr 2012 20:21:59 -0700 Subject: [PATCH] track what's been ack'd, and add method to ack what hasn't been. --- xwords4/common/comms.c | 49 +++++++++++++++++++++++++++++++-------- xwords4/common/comms.h | 3 +++ xwords4/common/comtypes.h | 5 ++-- xwords4/linux/gtkmain.c | 15 ++++++++++++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/xwords4/common/comms.c b/xwords4/common/comms.c index a38fd7aa0..73d8550e7 100644 --- a/xwords4/common/comms.c +++ b/xwords4/common/comms.c @@ -66,7 +66,8 @@ typedef struct AddressRecord { struct AddressRecord* next; CommsAddrRec addr; MsgID nextMsgID; /* on a per-channel basis */ - MsgID lastMsgRcd; /* on a per-channel basis */ + MsgID lastMsgRcd; /* on a per-channel basis */ + MsgID lastMsgAckd; /* on a per-channel basis */ /* only used if COMMS_HEARTBEAT set except for serialization (to_stream) */ XP_PlayerAddr channelNo; struct { @@ -180,12 +181,17 @@ static void set_reset_timer( CommsCtxt* comms ); static const char* relayCmdToStr( XWRELAY_Cmd cmd ); # endif #endif -#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT +#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT static void setHeartbeatTimer( CommsCtxt* comms ); #else # define setHeartbeatTimer( comms ) #endif + +#if defined COMMS_HEARTBEAT || defined XWFEATURE_COMMSACK +static void sendEmptyMsg( CommsCtxt* comms, AddressRecord* rec ); +#endif + #if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_IP_DIRECT static XP_S16 send_via_bt_or_ip( CommsCtxt* comms, BTIPMsgType typ, XP_PlayerAddr channelNo, @@ -520,7 +526,7 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util, MsgQueueElem** prevsQueueNext; XP_U16 version = stream_getVersion( stream ); CommsAddrRec addr; - short i; + short ii; isServer = stream_getU8( stream ); if ( version < STREAM_VERS_RELAY ) { @@ -563,14 +569,16 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util, nAddrRecs = stream_getU8( stream ); prevsAddrNext = &comms->recs; - for ( i = 0; i < nAddrRecs; ++i ) { - AddressRecord* rec = (AddressRecord*)XP_MALLOC( mpool, sizeof(*rec)); - XP_MEMSET( rec, 0, sizeof(*rec) ); + for ( ii = 0; ii < nAddrRecs; ++ii ) { + AddressRecord* rec = (AddressRecord*)XP_CALLOC( mpool, sizeof(*rec)); addrFromStream( &rec->addr, stream ); rec->nextMsgID = stream_getU16( stream ); rec->lastMsgRcd = stream_getU16( stream ); + if ( version >= STREAM_SAVE_LASTACK ) { + rec->lastMsgAckd = stream_getU16( stream ); + } rec->channelNo = stream_getU16( stream ); if ( rec->addr.conType == COMMS_CONN_RELAY ) { rec->r.hostID = stream_getU8( stream ); @@ -581,8 +589,8 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util, } prevsQueueNext = &comms->msgQueueHead; - for ( i = 0; i < comms->queueLen; ++i ) { - MsgQueueElem* msg = (MsgQueueElem*)XP_MALLOC( mpool, sizeof(*msg) ); + for ( ii = 0; ii < comms->queueLen; ++ii ) { + MsgQueueElem* msg = (MsgQueueElem*)XP_CALLOC( mpool, sizeof(*msg) ); msg->channelNo = stream_getU16( stream ); msg->msgID = stream_getU32( stream ); @@ -740,6 +748,7 @@ comms_writeToStream( const CommsCtxt* comms, XWStreamCtxt* stream ) stream_putU16( stream, (XP_U16)rec->nextMsgID ); stream_putU16( stream, (XP_U16)rec->lastMsgRcd ); + stream_putU16( stream, (XP_U16)rec->lastMsgAckd ); stream_putU16( stream, rec->channelNo ); if ( rec->addr.conType == COMMS_CONN_RELAY ) { stream_putU8( stream, rec->r.hostID ); /* unneeded unless RELAY */ @@ -905,6 +914,9 @@ makeElemWithID( CommsCtxt* comms, MsgID msgID, AddressRecord* rec, stream_putU32( msgStream, msgID ); XP_LOGF( "put lastMsgRcd: %ld", lastMsgRcd ); stream_putU32( msgStream, lastMsgRcd ); + if ( !!rec ) { + rec->lastMsgAckd = lastMsgRcd; + } headerLen = stream_getSize( msgStream ); newMsgElem->len = streamSize + headerLen; @@ -1169,6 +1181,21 @@ comms_resendAll( CommsCtxt* comms ) return success; } /* comms_resend */ +#ifdef XWFEATURE_COMMSACK +void +comms_ackAny( CommsCtxt* comms ) +{ + AddressRecord* rec; + for ( rec = comms->recs; !!rec; rec = rec->next ) { + if ( rec->lastMsgAckd < rec->lastMsgRcd ) { + XP_LOGF( "%s: %ld < %ld: rec needs ack", __func__, + rec->lastMsgAckd, rec->lastMsgRcd ); + sendEmptyMsg( comms, rec ); + } + } +} +#endif + #ifdef XWFEATURE_RELAY # ifdef DEBUG # define CASESTR(s) case s: return #s @@ -1733,7 +1760,7 @@ comms_isConnected( const CommsCtxt* const comms ) return result; } -#ifdef COMMS_HEARTBEAT +#if defined COMMS_HEARTBEAT || defined XWFEATURE_COMMSACK static void sendEmptyMsg( CommsCtxt* comms, AddressRecord* rec ) { @@ -1744,7 +1771,9 @@ sendEmptyMsg( CommsCtxt* comms, AddressRecord* rec ) sendMsg( comms, elem ); freeElem( comms, elem ); } /* sendEmptyMsg */ +#endif +#ifdef COMMS_HEARTBEAT /* Heartbeat. * * Goal is to allow all participants to detect when another is gone quickly. @@ -1796,7 +1825,7 @@ heartbeat_checks( CommsCtxt* comms ) } /* heartbeat_checks */ #endif -#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT +#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT static XP_Bool p_comms_timerFired( void* closure, XWTimerReason XP_UNUSED_DBG(why) ) { diff --git a/xwords4/common/comms.h b/xwords4/common/comms.h index 2c07b4128..d288d8459 100644 --- a/xwords4/common/comms.h +++ b/xwords4/common/comms.h @@ -204,6 +204,9 @@ XP_S16 comms_send( CommsCtxt* comms, XWStreamCtxt* stream ); XP_Bool comms_resendAll( CommsCtxt* comms ); XP_U16 comms_getChannelSeed( CommsCtxt* comms ); +#ifdef XWFEATURE_COMMSACK +void comms_ackAny( CommsCtxt* comms ); +#endif XP_Bool comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream, const CommsAddrRec* addr ); diff --git a/xwords4/common/comtypes.h b/xwords4/common/comtypes.h index 2309ba77b..9d72ee37d 100644 --- a/xwords4/common/comtypes.h +++ b/xwords4/common/comtypes.h @@ -48,8 +48,9 @@ #define MAX_COLS MAX_ROWS #if MAX_COLS > 16 -# define STREAM_VERS_BIGBOARD 0x12 +# define STREAM_VERS_BIGBOARD 0x13 #endif +#define STREAM_SAVE_LASTACK 0x12 #define STREAM_SAVE_PREVWORDS 0x11 #define STREAM_VERS_SERVER_SAVES_TOSHOW 0x10 /* STREAM_VERS_PLAYERDICTS affects stream sent between devices. May not be @@ -80,7 +81,7 @@ #if MAX_COLS > 16 # define CUR_STREAM_VERS STREAM_VERS_BIGBOARD #else -# define CUR_STREAM_VERS STREAM_SAVE_PREVWORDS +# define CUR_STREAM_VERS STREAM_SAVE_LASTACK #endif typedef struct XP_Rect { diff --git a/xwords4/linux/gtkmain.c b/xwords4/linux/gtkmain.c index 06b330a1e..2ad4a3de2 100644 --- a/xwords4/linux/gtkmain.c +++ b/xwords4/linux/gtkmain.c @@ -917,6 +917,17 @@ handle_resend( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) } } /* handle_resend */ +#ifdef XWFEATURE_COMMSACK +static void +handle_ack( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) +{ + CommsCtxt* comms = globals->cGlobals.game.comms; + if ( comms != NULL ) { + comms_ackAny( comms ); + } +} +#endif + #ifdef DEBUG static void handle_commstats( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals ) @@ -1023,6 +1034,10 @@ makeMenus( GtkAppGlobals* globals, int XP_UNUSED(argc), #ifndef XWFEATURE_STANDALONE_ONLY (void)createAddItem( fileMenu, "Resend", GTK_SIGNAL_FUNC(handle_resend), globals ); +#ifdef XWFEATURE_COMMSACK + (void)createAddItem( fileMenu, "ack any", + GTK_SIGNAL_FUNC(handle_ack), globals ); +#endif # ifdef DEBUG (void)createAddItem( fileMenu, "Stats", GTK_SIGNAL_FUNC(handle_commstats), globals );