use a hash of lists rather than a single list to store pending

background messages to fix assertion failure when more than two
devices are playing: messages must be sent grouped by relayID.
This commit is contained in:
Eric House 2011-11-21 17:57:38 -08:00
parent eec83fe5b6
commit 9115b344fb
2 changed files with 33 additions and 27 deletions

View file

@ -440,32 +440,35 @@ formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles,
typedef struct _MsgRec { typedef struct _MsgRec {
XP_U8* msg; XP_U8* msg;
XP_U16 len; XP_U16 msglen;
gchar* relayID;
} MsgRec; } MsgRec;
void void
initNoConnStorage( CommonGlobals* cGlobals ) initNoConnStorage( CommonGlobals* cGlobals )
{ {
XP_ASSERT( NULL == cGlobals->noConnMsgs ); 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 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 ) const XP_UCHAR* relayID )
{ {
XP_ASSERT( 0 < msglen );
XP_Bool inUse = NULL != cGlobals->noConnMsgs; XP_Bool inUse = NULL != cGlobals->noConnMsgs;
if ( inUse ) { if ( inUse ) {
if ( (GSList*)-1 == cGlobals->noConnMsgs ) { GSList* list = g_hash_table_lookup( cGlobals->noConnMsgs, relayID );
cGlobals->noConnMsgs = NULL; gboolean missing = NULL == list;
}
MsgRec* msgrec = g_malloc( sizeof(*msgrec) ); MsgRec* msgrec = g_malloc( sizeof(*msgrec) );
msgrec->msg = g_malloc( len ); msgrec->msg = g_malloc( msglen );
XP_MEMCPY( msgrec->msg, msg, len ); XP_MEMCPY( msgrec->msg, msg, msglen );
msgrec->len = len; msgrec->msglen = msglen;
msgrec->relayID = g_strdup( relayID ); list = g_slist_append( list, msgrec );
cGlobals->noConnMsgs = g_slist_append( cGlobals->noConnMsgs, msgrec ); if ( missing ) {
gchar* key = g_strdup( relayID ); /* will leak */
g_hash_table_insert( cGlobals->noConnMsgs, key, list );
}
} }
return inUse; return inUse;
} }
@ -473,12 +476,14 @@ storeNoConnMsg( CommonGlobals* cGlobals, const XP_U8* msg, XP_U16 len,
void void
writeNoConnMsgs( CommonGlobals* cGlobals, int fd ) writeNoConnMsgs( CommonGlobals* cGlobals, int fd )
{ {
guint nMsgs = (GSList*)-1 == cGlobals->noConnMsgs ? GHashTable* hash = cGlobals->noConnMsgs;
0 : g_slist_length( cGlobals->noConnMsgs ); GList* keys = g_hash_table_get_keys( hash );
if ( 0 < nMsgs ) { GList* iter;
gchar relayID[128] = {0}; for ( iter = keys; !!iter; iter = iter->next ) {
XP_UCHAR* relayID = (XP_UCHAR*)iter->data;
strcpy( relayID, ((MsgRec*)(cGlobals->noConnMsgs->data))->relayID ); GSList* list = (GSList*)g_hash_table_lookup( hash, relayID );
guint nMsgs = g_slist_length( list );
XP_ASSERT( 0 < nMsgs );
XWStreamCtxt* stream = XWStreamCtxt* stream =
mem_stream_make( MPPARM(cGlobals->params->util->mpool) mem_stream_make( MPPARM(cGlobals->params->util->mpool)
@ -491,17 +496,14 @@ writeNoConnMsgs( CommonGlobals* cGlobals, int fd )
int ii; int ii;
for ( ii = 0; ii < nMsgs; ++ii ) { for ( ii = 0; ii < nMsgs; ++ii ) {
MsgRec* rec = g_slist_nth_data( cGlobals->noConnMsgs, ii ); MsgRec* rec = g_slist_nth_data( list, ii );
stream_putU16( stream, rec->len ); stream_putU16( stream, rec->msglen );
stream_putBytes( stream, rec->msg, rec->len ); stream_putBytes( stream, rec->msg, rec->msglen );
g_free( rec->msg ); g_free( rec->msg );
XP_ASSERT( 0 == strcmp( relayID, rec->relayID ) );
g_free( rec->relayID );
g_free( rec ); g_free( rec );
} }
g_slist_free( cGlobals->noConnMsgs ); g_slist_free( list );
cGlobals->noConnMsgs = NULL;
XP_U16 siz = stream_getSize( stream ); XP_U16 siz = stream_getSize( stream );
/* XP_U8 buf[siz]; */ /* XP_U8 buf[siz]; */
@ -513,6 +515,9 @@ writeNoConnMsgs( CommonGlobals* cGlobals, int fd )
XP_ASSERT( nwritten == siz ); XP_ASSERT( nwritten == siz );
stream_destroy( stream ); stream_destroy( stream );
} }
g_list_free( keys );
g_hash_table_unref( hash );
cGlobals->noConnMsgs = NULL;
} /* writeNoConnMsgs */ } /* writeNoConnMsgs */
#ifdef TEXT_MODEL #ifdef TEXT_MODEL

View file

@ -163,7 +163,8 @@ struct CommonGlobals {
AddAcceptorFunc addAcceptor; AddAcceptorFunc addAcceptor;
Acceptor acceptor; Acceptor acceptor;
GSList* noConnMsgs; /* hash by relayID of lists of messages */
GHashTable* noConnMsgs;
#ifdef XWFEATURE_RELAY #ifdef XWFEATURE_RELAY
int socket; /* relay */ int socket; /* relay */