From 7556ecf49ff14ce57f69885d3917a9d78364b94f Mon Sep 17 00:00:00 2001 From: ehouse Date: Sun, 1 Feb 2009 15:50:58 +0000 Subject: [PATCH] Make it possible to run same binary against relay with relay heartbeat and direct with comms heartbeat. This mostly means changing ifdefs. --- common/comms.c | 115 +++++++++++++++++++++++++++++++++------------ common/comms.h | 5 +- common/comtypes.h | 11 +++-- linux/Makefile | 12 ++--- linux/cursesmain.c | 10 ++-- linux/gtkmain.c | 30 ++++++------ linux/linuxmain.c | 23 +++++---- palm/palmmain.c | 2 +- wince/cemain.c | 4 +- 9 files changed, 138 insertions(+), 74 deletions(-) diff --git a/common/comms.c b/common/comms.c index d40774373..786e2a9c2 100644 --- a/common/comms.c +++ b/common/comms.c @@ -1,4 +1,4 @@ -/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */ +/* -*- compile-command: "cd ../linux && make MEMDEBUG=TRUE"; -*- */ /* * Copyright 2001-2009 by Eric House (xwords@eehouse.org). All rights * reserved. @@ -36,10 +36,6 @@ #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 @@ -109,9 +105,12 @@ struct CommsCtxt { #ifdef COMMS_HEARTBEAT XP_Bool doHeartbeat; - XP_Bool hbTimerPending; XP_U32 lastMsgRcvdTime; #endif +#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT + XP_Bool hbTimerPending; + XP_Bool reconTimerPending; +#endif /* The following fields, down to isServer, are only used if XWFEATURE_RELAY is defined, but I'm leaving them in here so apps built @@ -172,14 +171,16 @@ static XP_U16 countAddrRecs( const CommsCtxt* comms ); static void sendConnect( CommsCtxt* comms ); #ifdef XWFEATURE_RELAY -static void relayConnect( CommsCtxt* comms ); +static XP_Bool relayConnect( CommsCtxt* comms ); static void relayDisconnect( CommsCtxt* comms ); static XP_Bool send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd, XWHostID destID, void* data, int dlen ); static XWHostID getDestID( CommsCtxt* comms, XP_PlayerAddr channelNo ); +static void set_reset_timer( CommsCtxt* comms ); #endif -#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT +#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT static void setHeartbeatTimer( CommsCtxt* comms ); + #else # define setHeartbeatTimer( comms ) #endif @@ -273,11 +274,57 @@ comms_reset( CommsCtxt* comms, XP_Bool isServer, comms->r.cookieID = COOKIE_ID_NONE; comms->r.nPlayersHere = nPlayersHere; comms->r.nPlayersTotal = nPlayersTotal; - relayConnect( comms ); + (void)relayConnect( comms ); #endif LOG_RETURN_VOID(); } /* comms_reset */ +#ifdef XWFEATURE_RELAY + +static XP_Bool +p_comms_resetTimer( void* closure, XWTimerReason XP_UNUSED_DBG(why) ) +{ + CommsCtxt* comms = (CommsCtxt*)closure; + XP_Bool success; + LOG_FUNC(); + XP_ASSERT( why == TIMER_COMMS ); + success = relayConnect( comms ); + + if ( success ) { + comms->reconTimerPending = XP_FALSE; + setHeartbeatTimer( comms ); /* in case we killed it with this + one.... */ + } else { + set_reset_timer( comms ); + } + + return XP_FALSE; +} /* p_comms_resetTimer */ + +static void +set_reset_timer( CommsCtxt* comms ) +{ + /* This timer is allowed to overwrite a heartbeat timer, but not + vice-versa. Make sure we can restart it. */ + comms->hbTimerPending = XP_FALSE; + util_setTimer( comms->util, TIMER_COMMS, 15, /* five seconds */ + p_comms_resetTimer, comms ); + comms->reconTimerPending = XP_TRUE; +} + +void +comms_transportFailed( CommsCtxt* comms ) +{ + LOG_FUNC(); + if ( COMMS_CONN_RELAY == comms->addr.conType ) { + relayDisconnect( comms ); + + set_reset_timer( comms ); + } + LOG_RETURN_VOID(); +} +#endif /* XWFEATURE_RELAY */ + void comms_destroy( CommsCtxt* comms ) { @@ -693,7 +740,7 @@ makeElemWithID( CommsCtxt* comms, MsgID msgID, AddressRecord* rec, NULL, 0, (MemStreamCloseCallback)NULL ); stream_open( msgStream ); - XP_LOGF( "%s: putting connID %ld", __func__, comms->connID ); + XP_LOGF( "%s: putting connID %lx", __func__, comms->connID ); stream_putU32( msgStream, comms->connID ); stream_putU16( msgStream, channelNo ); @@ -1122,7 +1169,8 @@ getRecordFor( CommsCtxt* comms, const CommsAddrRec* addr, * it invalid */ static AddressRecord* -validateInitialMessage( CommsCtxt* comms, XP_Bool hasPayload, +validateInitialMessage( CommsCtxt* comms, + XP_Bool XP_UNUSED_HEARTBEAT(hasPayload), const CommsAddrRec* addr, XWHostID senderID, XP_PlayerAddr* channelNo ) { @@ -1335,21 +1383,22 @@ heartbeat_checks( CommsCtxt* comms ) } /* heartbeat_checks */ #endif -#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT +#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT static XP_Bool p_comms_timerFired( void* closure, XWTimerReason XP_UNUSED_DBG(why) ) { CommsCtxt* comms = (CommsCtxt*)closure; - XP_ASSERT( why == TIMER_HEARTBEAT ); + XP_ASSERT( why == TIMER_COMMS ); LOG_FUNC(); comms->hbTimerPending = XP_FALSE; if (0 ) { -#ifdef RELAY_HEARTBEAT +#ifdef XWFEATURE_RELAY } else if ( (comms->addr.conType == COMMS_CONN_RELAY ) && (comms->r.heartbeat != HEARTBEAT_NONE) ) { send_via_relay( comms, XWRELAY_HEARTBEAT, HOST_ID_NONE, NULL, 0 ); /* No need to reset timer. send_via_relay does that. */ -#elif defined COMMS_HEARTBEAT +#endif +#ifdef COMMS_HEARTBEAT } else { XP_ASSERT( comms->doHeartbeat ); heartbeat_checks( comms ); @@ -1363,27 +1412,29 @@ setHeartbeatTimer( CommsCtxt* comms ) { LOG_FUNC(); XP_ASSERT( !!comms ); - if ( !comms->hbTimerPending ) { + + if ( comms->hbTimerPending ) { + XP_LOGF( "%s: skipping b/c hbTimerPending", __func__ ); + } else if ( comms->reconTimerPending ) { + XP_LOGF( "%s: skipping b/c reconTimerPending", __func__ ); + } else { XP_U16 when = 0; -#ifdef RELAY_HEARTBEAT +#ifdef XWFEATURE_RELAY if ( comms->addr.conType == COMMS_CONN_RELAY ) { when = comms->r.heartbeat; } -#elif defined COMMS_HEARTBEAT +#endif +#ifdef COMMS_HEARTBEAT if ( comms->doHeartbeat ) { XP_LOGF( "%s: calling util_setTimer", __func__ ); when = HB_INTERVAL; - } else { - XP_LOGF( "%s: doHeartbeat not set", __func__ ); } #endif if ( when != 0 ) { - util_setTimer( comms->util, TIMER_HEARTBEAT, when, + util_setTimer( comms->util, TIMER_COMMS, when, p_comms_timerFired, comms ); comms->hbTimerPending = XP_TRUE; } - } else { - XP_LOGF( "%s: skipping b/c pending", __func__ ); } } /* setHeartbeatTimer */ #endif @@ -1474,7 +1525,9 @@ static void updateChannelAddress( AddressRecord* rec, const CommsAddrRec* addr ) { XP_ASSERT( !!rec ); - XP_MEMCPY( &rec->addr, addr, sizeof(rec->addr) ); + if ( !!addr ) { + XP_MEMCPY( &rec->addr, addr, sizeof(rec->addr) ); + } } /* updateChannelAddress */ static XP_Bool @@ -1570,7 +1623,7 @@ send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd, XWHostID destID, stream_putU8( tmpStream, comms->r.myHostID ); break; -#ifdef RELAY_HEARTBEAT +#ifdef XWFEATURE_RELAY case XWRELAY_HEARTBEAT: /* Add these for grins. Server can assert they match the IP address it expects 'em on. */ @@ -1606,18 +1659,20 @@ send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd, XWHostID destID, * relay, and tells it our hostID and cookie so that it can associatate it * with a socket. In the CONNECT_RESP we should get back what? */ -static void +static XP_Bool relayConnect( CommsCtxt* comms ) { + XP_Bool success = XP_TRUE; LOG_FUNC(); if ( comms->addr.conType == COMMS_CONN_RELAY && !comms->r.connecting ) { comms->r.connecting = XP_TRUE; - send_via_relay( comms, - comms->r.connName[0] == '\0' ? - XWRELAY_GAME_CONNECT:XWRELAY_GAME_RECONNECT, - comms->r.myHostID, NULL, 0 ); + success = send_via_relay( comms, + comms->r.connName[0] == '\0' ? + XWRELAY_GAME_CONNECT:XWRELAY_GAME_RECONNECT, + comms->r.myHostID, NULL, 0 ); comms->r.connecting = XP_FALSE; } + return success; } /* relayConnect */ #endif diff --git a/common/comms.h b/common/comms.h index a1cfb66e3..13b741bbc 100644 --- a/common/comms.h +++ b/common/comms.h @@ -1,6 +1,7 @@ /* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */ /* - * Copyright 2001 by Eric House (xwords@eehouse.org). All rights reserved. + * Copyright 2001-2009 by Eric House (xwords@eehouse.org). All rights + * reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -107,6 +108,8 @@ CommsCtxt* comms_make( MPFORMAL XW_UtilCtxt* util, void comms_reset( CommsCtxt* comms, XP_Bool isServer, XP_U16 nPlayersHere, XP_U16 nPlayersTotal ); +void comms_transportFailed( CommsCtxt* comms ); + void comms_destroy( CommsCtxt* comms ); void comms_setConnID( CommsCtxt* comms, XP_U32 connID ); diff --git a/common/comtypes.h b/common/comtypes.h index 88b84bf44..be7a9664a 100644 --- a/common/comtypes.h +++ b/common/comtypes.h @@ -104,10 +104,9 @@ typedef XP_S16 XP_PlayerAddr; typedef enum { TIMER_PENDOWN = 1, /* ARM doesn't like ids of 0... */ TIMER_TIMERTICK, -#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT - TIMER_HEARTBEAT, +#ifndef XWFEATURE_STANDALONE_ONLY + TIMER_COMMS, #endif - NUM_TIMERS_PLUS_ONE /* must be last */ } XWTimerReason; @@ -217,6 +216,12 @@ typedef struct CommonPrefs { # define XP_UNUSED_RELAY(x) UNUSED__ ## x __attribute__((unused)) #endif +#ifdef COMMS_HEARTBEAT +# define XP_UNUSED_HEARTBEAT(x) x +#else +# define XP_UNUSED_HEARTBEAT(x) UNUSED__ ## x __attribute__((unused)) +#endif + #ifdef XWFEATURE_BLUETOOTH # define XP_UNUSED_BT(x) x #else diff --git a/linux/Makefile b/linux/Makefile index 7d2fd3b60..addb52da6 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -94,13 +94,13 @@ DEFINES += -DXWFEATURE_SMS # 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 +# 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 -# user experience will be very bad!). Is particularly useful with BT. -# DEFINES += -DRELAY_HEARTBEAT +# 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. Is not used +# for relay. DEFINES += -DCOMMS_HEARTBEAT endif DEFINES += $(STANDALONE) diff --git a/linux/cursesmain.c b/linux/cursesmain.c index a72f69d6c..defcd6497 100644 --- a/linux/cursesmain.c +++ b/linux/cursesmain.c @@ -894,12 +894,12 @@ curses_socket_acceptor( int listener, Acceptor func, CommonGlobals* cGlobals, cursesListenOnSocket( globals, listener ); } -#ifdef RELAY_HEARTBEAT +#ifdef XWFEATURE_RELAY static int figureTimeout( CursesAppGlobals* globals ) { int result = INFINITE_TIMEOUT; - if ( globals->cGlobals.timerProcs[TIMER_HEARTBEAT] != 0 ) { + if ( globals->cGlobals.timerProcs[TIMER_COMMS] != 0 ) { XP_U32 now = util_getCurSeconds( globals->cGlobals.params->util ); XP_U32 then = globals->nextTimer; if ( now >= then ) { @@ -929,10 +929,8 @@ blocking_gotEvent( CursesAppGlobals* globals, int* ch ) numEvents = poll( globals->fdArray, globals->fdCount, timeout ); if ( timeout != INFINITE_TIMEOUT && numEvents == 0 ) { -#ifdef RELAY_HEARTBEAT - if ( !globals->cGlobals.params->noHeartbeat ) { - linuxFireTimer( &globals->cGlobals, TIMER_HEARTBEAT ); - } +#ifdef XWFEATURE_RELAY + linuxFireTimer( &globals->cGlobals, TIMER_COMMS ); #endif } else if ( numEvents > 0 ) { diff --git a/linux/gtkmain.c b/linux/gtkmain.c index daf98392d..b24e2fea4 100644 --- a/linux/gtkmain.c +++ b/linux/gtkmain.c @@ -562,6 +562,7 @@ quit( void* XP_UNUSED(dunno), GtkAppGlobals* globals ) #ifdef XWFEATURE_IP_DIRECT linux_udp_close( &globals->cGlobals ); #endif + vtmgr_destroy( MEMPOOL globals->cGlobals.params->vtMgr ); mpool_destroy( globals->cGlobals.params->util->mpool ); @@ -1223,15 +1224,13 @@ score_timer_func( gpointer data ) return XP_FALSE; } /* score_timer_func */ -#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT +#ifndef XWFEATURE_STANDALONE_ONLY static gint -heartbeat_timer_func( gpointer data ) +comms_timer_func( gpointer data ) { GtkAppGlobals* globals = (GtkAppGlobals*)data; - if ( !globals->cGlobals.params->noHeartbeat ) { - linuxFireTimer( &globals->cGlobals, TIMER_HEARTBEAT ); - } + linuxFireTimer( &globals->cGlobals, TIMER_COMMS ); return (gint)0; } @@ -1260,9 +1259,9 @@ gtk_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why, (void)gettimeofday( &globals->scoreTv, NULL ); newSrc = g_timeout_add( 1000, score_timer_func, globals ); -#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT - } else if ( why == TIMER_HEARTBEAT ) { - newSrc = g_timeout_add( 1000 * when, heartbeat_timer_func, globals ); +#ifndef XWFEATURE_STANDALONE_ONLY + } else if ( why == TIMER_COMMS ) { + newSrc = g_timeout_add( 1000 * when, comms_timer_func, globals ); #endif } else { XP_ASSERT( 0 ); @@ -1589,7 +1588,7 @@ newConnectionInput( GIOChannel *source, int sock = g_io_channel_unix_get_fd( source ); GtkAppGlobals* globals = (GtkAppGlobals*)data; - XP_LOGF( "%s:condition = 0x%x", __func__, (int)condition ); + XP_LOGF( "%s(%p):condition = 0x%x", __func__, source, (int)condition ); /* XP_ASSERT( sock == globals->cGlobals.socket ); */ @@ -1614,14 +1613,16 @@ newConnectionInput( GIOChannel *source, } else if ( (condition & G_IO_IN) != 0 ) { ssize_t nRead; unsigned char buf[512]; - CommsAddrRec addr; CommsAddrRec* addrp = NULL; +#if defined XWFEATURE_IP_DIRECT || defined XWFEATURE_SMS + CommsAddrRec addr; +#endif switch ( globals->cGlobals.params->conType ) { #ifdef XWFEATURE_RELAY case COMMS_CONN_RELAY: - nRead = linux_relay_receive( &globals->cGlobals, - buf, sizeof(buf) ); + XP_ASSERT( globals->cGlobals.socket == sock ); + nRead = linux_relay_receive( &globals->cGlobals, buf, sizeof(buf) ); break; #endif #ifdef XWFEATURE_BLUETOOTH @@ -1726,7 +1727,7 @@ gtk_socket_changed( void* closure, int oldSock, int newSock, void** storage ) comms_resendAll( comms ); } LOG_RETURN_VOID(); -} +} /* gtk_socket_changed */ static gboolean acceptorInput( GIOChannel* source, GIOCondition condition, gpointer data ) @@ -1792,11 +1793,10 @@ gtk_socket_acceptor( int listener, Acceptor func, CommonGlobals* globals, static void sendOnClose( XWStreamCtxt* stream, void* closure ) { - XP_S16 result; GtkAppGlobals* globals = closure; XP_LOGF( "sendOnClose called" ); - result = comms_send( globals->cGlobals.game.comms, stream ); + (void)comms_send( globals->cGlobals.game.comms, stream ); } /* sendOnClose */ static void diff --git a/linux/linuxmain.c b/linux/linuxmain.c index bbbab129e..3edb71180 100644 --- a/linux/linuxmain.c +++ b/linux/linuxmain.c @@ -302,7 +302,6 @@ linShiftFocus( CommonGlobals* cGlobals, XP_Key key, const BoardObjectType* order } /* linShiftFocus */ #endif -#ifndef XWFEATURE_STANDALONE_ONLY #ifdef XWFEATURE_RELAY static int linux_init_relay_socket( CommonGlobals* cGlobals ) @@ -351,7 +350,6 @@ linux_init_relay_socket( CommonGlobals* cGlobals ) static XP_S16 linux_tcp_send( const XP_U8* buf, XP_U16 buflen, - const CommsAddrRec* XP_UNUSED(addrRec), CommonGlobals* globals ) { XP_S16 result = 0; @@ -384,15 +382,16 @@ linux_tcp_send( const XP_U8* buf, XP_U16 buflen, globals->socket = -1; } - XP_STATUSF( "linux_tcp_send: send returned %d of %d (err=%d)", - result, buflen, errno ); + XP_STATUSF( "%s: send(sock=%d) returned %d of %d (err=%d)", + __func__, socket, result, buflen, errno ); } return result; } /* linux_tcp_send */ #endif /* XWFEATURE_RELAY */ -#ifdef XWFEATURE_RELAY +#ifdef COMMS_HEARTBEAT +# ifdef XWFEATURE_RELAY static void linux_tcp_reset( CommonGlobals* globals ) { @@ -402,9 +401,8 @@ linux_tcp_reset( CommonGlobals* globals ) globals->socket = -1; } } -#endif +# endif -#ifdef COMMS_HEARTBEAT void linux_reset( void* closure ) { @@ -446,7 +444,7 @@ linux_send( const XP_U8* buf, XP_U16 buflen, if ( 0 ) { #ifdef XWFEATURE_RELAY } else if ( conType == COMMS_CONN_RELAY ) { - nSent = linux_tcp_send( buf, buflen, addrRec, globals ); + nSent = linux_tcp_send( buf, buflen, globals ); #endif #if defined XWFEATURE_BLUETOOTH } else if ( conType == COMMS_CONN_BT ) { @@ -482,7 +480,11 @@ static void linux_close_socket( CommonGlobals* cGlobals ) { int socket = cGlobals->socket; - cGlobals->socket = -1; + + (*cGlobals->socketChanged)( cGlobals->socketChangedClosure, + socket, -1, &cGlobals->storage ); + + XP_ASSERT( -1 == cGlobals->socket ); XP_LOGF( "linux_close_socket" ); close( socket ); @@ -498,6 +500,7 @@ linux_relay_receive( CommonGlobals* cGlobals, unsigned char* buf, int bufSize ) if ( nRead != 2 ) { XP_LOGF( "recv => %d, errno=%d", nRead, errno ); linux_close_socket( cGlobals ); + comms_transportFailed( cGlobals->game.comms ); nRead = -1; } else { @@ -511,7 +514,6 @@ linux_relay_receive( CommonGlobals* cGlobals, unsigned char* buf, int bufSize ) return nRead; } /* linuxReceive */ #endif /* XWFEATURE_RELAY */ -#endif /* XWFEATURE_STANDALONE_ONLY */ /* Create a stream for the incoming message buffer, and read in any information specific to our platform's comms layer (return address, say) @@ -859,6 +861,7 @@ main( int argc, char** argv ) break; case 'H': mainParams.noHeartbeat = XP_TRUE; + XP_ASSERT(0); /* not implemented!!! Needs to talk to comms... */ break; case 'a': /* mainParams.info.clientInfo.serverName = */ diff --git a/palm/palmmain.c b/palm/palmmain.c index b6d77dd78..0ce25d480 100644 --- a/palm/palmmain.c +++ b/palm/palmmain.c @@ -3870,7 +3870,7 @@ palm_util_setTimer( XW_UtilCtxt* uc, XWTimerReason why, now += PALM_TIMER_DELAY; } else if ( why == TIMER_TIMERTICK ) { now += SysTicksPerSecond(); -#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT +#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT } else if ( why == TIMER_HEARTBEAT ) { now += (secsFromNow * SysTicksPerSecond()); #endif diff --git a/wince/cemain.c b/wince/cemain.c index e2dba6bc1..03b24b03c 100755 --- a/wince/cemain.c +++ b/wince/cemain.c @@ -2013,7 +2013,7 @@ checkFireLateKeyTimer( CEAppGlobals* globals ) { XP_Bool drop = XP_FALSE; XWTimerReason whys[] = { TIMER_PENDOWN, TIMER_TIMERTICK -#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT +#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT , TIMER_HEARTBEAT #endif }; @@ -2476,7 +2476,7 @@ WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_TIMER: why = (XWTimerReason)wParam; if ( why == TIMER_PENDOWN || why == TIMER_TIMERTICK -#if defined RELAY_HEARTBEAT || defined COMMS_HEARTBEAT +#if defined XWFEATURE_RELAY || defined COMMS_HEARTBEAT || why == TIMER_HEARTBEAT #endif ) {