diff --git a/xwords4/common/comms.c b/xwords4/common/comms.c index 4d64f03e4..af93a6d62 100644 --- a/xwords4/common/comms.c +++ b/xwords4/common/comms.c @@ -1267,43 +1267,43 @@ relayPreProcess( CommsCtxt* comms, XWStreamCtxt* stream, XWHostID* senderID ) || comms->r.myHostID == srcID ); if ( 0 == comms->r.cookieID ) { - XP_LOGF( "%s: cookieID still 0; most likely packet was lost", + XP_LOGF( "%s: cookieID still 0; background send?", __func__ ); - comms_transportFailed( comms ); - } else { - comms->r.myHostID = srcID; + } + comms->r.myHostID = srcID; - XP_LOGF( "%s: set hostid: %x", __func__, comms->r.myHostID ); + XP_LOGF( "%s: set hostid: %x", __func__, comms->r.myHostID ); #ifdef DEBUG - { - XP_UCHAR connName[MAX_CONNNAME_LEN+1]; - stringFromStreamHere( stream, connName, sizeof(connName) ); - XP_ASSERT( comms->r.connName[0] == '\0' - || 0 == XP_STRCMP( comms->r.connName, connName ) ); - XP_MEMCPY( comms->r.connName, connName, sizeof(comms->r.connName) ); - XP_LOGF( "%s: connName: \"%s\"", __func__, connName ); - } + { + XP_UCHAR connName[MAX_CONNNAME_LEN+1]; + stringFromStreamHere( stream, connName, sizeof(connName) ); + XP_ASSERT( comms->r.connName[0] == '\0' + || 0 == XP_STRCMP( comms->r.connName, connName ) ); + XP_MEMCPY( comms->r.connName, connName, + sizeof(comms->r.connName) ); + XP_LOGF( "%s: connName: \"%s\"", __func__, connName ); + } #else - stringFromStreamHere( stream, comms->r.connName, - sizeof(comms->r.connName) ); + stringFromStreamHere( stream, comms->r.connName, + sizeof(comms->r.connName) ); #endif - /* We're [re-]connected now. Send any pending messages. This may - need to be done later since we're inside the platform's socket read - proc now. But don't resend if we were previously REconnected, as - we'll have sent then. -- I don't see any send on RECONNECTED, so - removing the test for now to fix recon problems on android. */ - /* if ( COMMS_RELAYSTATE_RECONNECTED != comms->r.relayState ) { */ - comms_resendAll( comms ); - /* } */ - if ( XWRELAY_ALLHERE == cmd ) { /* initial connect? */ - (*comms->procs.rconnd)( comms->procs.closure, - comms->addr.u.ip_relay.invite, XP_FALSE, - comms->r.myHostID, XP_TRUE, 0 ); - } - set_relay_state( comms, COMMS_RELAYSTATE_ALLCONNECTED ); + /* We're [re-]connected now. Send any pending messages. This may + need to be done later since we're inside the platform's socket + read proc now. But don't resend if we were previously + REconnected, as we'll have sent then. -- I don't see any send + on RECONNECTED, so removing the test for now to fix recon + problems on android. */ + /* if ( COMMS_RELAYSTATE_RECONNECTED != comms->r.relayState ) { */ + comms_resendAll( comms ); + /* } */ + if ( XWRELAY_ALLHERE == cmd ) { /* initial connect? */ + (*comms->procs.rconnd)( comms->procs.closure, + comms->addr.u.ip_relay.invite, XP_FALSE, + comms->r.myHostID, XP_TRUE, 0 ); } + set_relay_state( comms, COMMS_RELAYSTATE_ALLCONNECTED ); break; case XWRELAY_MSG_FROMRELAY: cookieID = stream_getU16( stream ); diff --git a/xwords4/linux/linuxutl.c b/xwords4/linux/linuxutl.c index 7a21e9af0..9271d8b13 100644 --- a/xwords4/linux/linuxutl.c +++ b/xwords4/linux/linuxutl.c @@ -483,32 +483,35 @@ formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles, typedef struct _MsgRec { XP_U8* msg; - XP_U16 len; - gchar* relayID; + XP_U16 msglen; } MsgRec; void initNoConnStorage( CommonGlobals* cGlobals ) { XP_ASSERT( NULL == cGlobals->noConnMsgs ); - cGlobals->noConnMsgs = (GSList*)-1; /* -1 is flag meaning "use me" */ + cGlobals->noConnMsgs = g_hash_table_new( g_str_hash, g_str_equal ); } XP_Bool -storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 len, +storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 msglen, const XP_UCHAR* relayID ) { - XP_Bool inUse = NULL != cGlobals->noConnMsgs; + XP_ASSERT( 0 < msglen ); + XP_Bool inUse = NULL != cGlobals->noConnMsgs; if ( inUse ) { - if ( (GSList*)-1 == cGlobals->noConnMsgs ) { - cGlobals->noConnMsgs = NULL; - } + GSList* list = g_hash_table_lookup( cGlobals->noConnMsgs, relayID ); + gboolean missing = NULL == list; + MsgRec* msgrec = g_malloc( sizeof(*msgrec) ); - msgrec->msg = g_malloc( len ); - XP_MEMCPY( msgrec->msg, msg, len ); - msgrec->len = len; - msgrec->relayID = g_strdup( relayID ); - cGlobals->noConnMsgs = g_slist_append( cGlobals->noConnMsgs, msgrec ); + msgrec->msg = g_malloc( msglen ); + XP_MEMCPY( msgrec->msg, msg, msglen ); + msgrec->msglen = msglen; + list = g_slist_append( list, msgrec ); + if ( missing ) { + gchar* key = g_strdup( relayID ); /* will leak */ + g_hash_table_insert( cGlobals->noConnMsgs, key, list ); + } } return inUse; } @@ -516,12 +519,14 @@ storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 len, void writeNoConnMsgs( CommonGlobals* cGlobals, int fd ) { - guint nMsgs = (GSList*)-1 == cGlobals->noConnMsgs ? - 0 : g_slist_length( cGlobals->noConnMsgs ); - if ( 0 < nMsgs ) { - gchar relayID[128] = {0}; - - strcpy( relayID, ((MsgRec*)(cGlobals->noConnMsgs->data))->relayID ); + GHashTable* hash = cGlobals->noConnMsgs; + GList* keys = g_hash_table_get_keys( hash ); + GList* iter; + for ( iter = keys; !!iter; iter = iter->next ) { + XP_UCHAR* relayID = (XP_UCHAR*)iter->data; + GSList* list = (GSList*)g_hash_table_lookup( hash, relayID ); + guint nMsgs = g_slist_length( list ); + XP_ASSERT( 0 < nMsgs ); XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->params->util->mpool) @@ -534,17 +539,14 @@ writeNoConnMsgs( CommonGlobals* cGlobals, int fd ) int ii; for ( ii = 0; ii < nMsgs; ++ii ) { - MsgRec* rec = g_slist_nth_data( cGlobals->noConnMsgs, ii ); - stream_putU16( stream, rec->len ); - stream_putBytes( stream, rec->msg, rec->len ); + MsgRec* rec = g_slist_nth_data( list, ii ); + stream_putU16( stream, rec->msglen ); + stream_putBytes( stream, rec->msg, rec->msglen ); g_free( rec->msg ); - XP_ASSERT( 0 == strcmp( relayID, rec->relayID ) ); - g_free( rec->relayID ); g_free( rec ); } - g_slist_free( cGlobals->noConnMsgs ); - cGlobals->noConnMsgs = NULL; + g_slist_free( list ); XP_U16 siz = stream_getSize( stream ); /* XP_U8 buf[siz]; */ @@ -556,6 +558,9 @@ writeNoConnMsgs( CommonGlobals* cGlobals, int fd ) XP_ASSERT( nwritten == siz ); stream_destroy( stream ); } + g_list_free( keys ); + g_hash_table_unref( hash ); + cGlobals->noConnMsgs = NULL; } /* writeNoConnMsgs */ #ifdef TEXT_MODEL diff --git a/xwords4/linux/main.h b/xwords4/linux/main.h index acc155431..a22e7b453 100644 --- a/xwords4/linux/main.h +++ b/xwords4/linux/main.h @@ -163,7 +163,8 @@ struct CommonGlobals { AddAcceptorFunc addAcceptor; Acceptor acceptor; - GSList* noConnMsgs; + /* hash by relayID of lists of messages */ + GHashTable* noConnMsgs; #ifdef XWFEATURE_RELAY int socket; /* relay */ diff --git a/xwords4/linux/scripts/test_backsend.sh b/xwords4/linux/scripts/test_backsend.sh index 446dda640..36c128f06 100755 --- a/xwords4/linux/scripts/test_backsend.sh +++ b/xwords4/linux/scripts/test_backsend.sh @@ -5,6 +5,7 @@ set -e -u SEED="" RELAY_LOG="../relay/xwrelay.log" +NDEVS=${NDEVS:-2} usage() { echo "usage: $(basename $0) [--seed RANDOM_SEED]" @@ -38,7 +39,10 @@ DIR=$(basename $0)_$PID DICT=dict.xwd APP=./obj_linux_memdbg/xwords -COMMON_ARGS="--room $ROOM --curses --robot Eric --remote-player --game-dict $DICT --quit-after 2" +COMMON_ARGS="--room $ROOM --curses --robot Eric --game-dict $DICT --quit-after 2" +for NUM in $(seq 2 $NDEVS); do + COMMON_ARGS="$COMMON_ARGS --remote-player" +done mkdir -p $DIR @@ -50,7 +54,7 @@ else fi # Run once to connect each with the relay -for NUM in $(seq 1 2); do +for NUM in $(seq 1 $((NDEVS))); do LOG="$(logname $NUM)" ARGS=$COMMON_ARGS if [ -n "$SEED" ]; then @@ -58,7 +62,7 @@ for NUM in $(seq 1 2); do fi $APP $ARGS --file $DIR/game_${NUM}.xwg > /dev/null 2>>$LOG & PID1=$! - sleep 4 + sleep 2 kill $PID1 wait $PID1 done @@ -68,7 +72,7 @@ NBS=$DIR/nbs ZERO_COUNT=0 while [ $ZERO_COUNT -lt 2 ]; do WORK_DONE="" - for NUM in $(seq 1 2); do + for NUM in $(seq 1 $((NDEVS))); do LOG="$(logname $NUM)" RELAYID=$(./scripts/relayID.sh --short $LOG) MSG_COUNT=$(../relay/rq -m $RELAYID 2>/dev/null | sed 's,^.*-- ,,') @@ -79,7 +83,8 @@ while [ $ZERO_COUNT -lt 2 ]; do if [ -n "$SEED" ]; then ARGS="$ARGS --seed $((SEED+NUM))" fi - $APP $ARGS --file $DIR/game_${NUM}.xwg --with-nbs $NBS > /dev/null 2>>$LOG & + $APP $ARGS --file $DIR/game_${NUM}.xwg --with-nbs $NBS \ + > /dev/null 2>>$LOG & PID1=$! ../relay/rq -f $RELAYID -b $NBS @@ -98,7 +103,7 @@ done # the game's over. Strictly speaking we need to get beyond that, but # reaching it is the first step. Debug failure to get that far first. ENDED="" -for NUM in $(seq 1 2); do +for NUM in $(seq 1 $((NDEVS))); do LOG="$(logname $NUM)" if grep -q 'waiting for server to end game' $LOG; then ENDED=1 @@ -107,7 +112,7 @@ for NUM in $(seq 1 2); do done if [ -z "$ENDED" ]; then - for NUM in $(seq 1 2); do + for NUM in $(seq 1 $((NDEVS))); do LOG="$(logname $NUM)" if ! grep -q 'all remaining tiles' $LOG; then echo "$LOG didn't seem to end correctly" diff --git a/xwords4/relay/rq.c b/xwords4/relay/rq.c index 3d455b5b7..b626f6dd0 100644 --- a/xwords4/relay/rq.c +++ b/xwords4/relay/rq.c @@ -390,7 +390,8 @@ do_deletes( int sockfd, const char** connNames, int nConnNames ) char buf[4096]; int nused = 0; for ( ii = 0; ii < nConnNames; ++ii ) { - char tmp[32]; + char tmp[128]; + assert( strlen(connNames[ii]) < sizeof(tmp)-1 ); strcpy( tmp, connNames[ii] ); char* seedp = strrchr( tmp, '/' ); assert( !!seedp );