snapshot: message exchange mostly works

This commit is contained in:
Eric House 2021-02-07 16:31:32 -08:00
parent e3814bf0eb
commit 4612ca70c7
9 changed files with 198 additions and 63 deletions

View file

@ -1338,7 +1338,9 @@ static void
notifyQueueChanged( const CommsCtxt* comms, XWEnv xwe )
{
XP_U16 count = comms->queueLen;
(*comms->procs.countChanged)( xwe, comms->procs.closure, count );
if ( !!comms->procs.countChanged ) {
(*comms->procs.countChanged)( xwe, comms->procs.closure, count );
}
}
/* Add new message to the end of the list. The list needs to be kept in order
@ -1553,8 +1555,10 @@ sendMsg( CommsCtxt* comms, XWEnv xwe, MsgQueueElem* elem, const CommsConnType fi
XP_LOGF( "%s: dropping message because not of type %s", __func__,
ConnType2Str( filter ) );
} else {
#ifdef COMMS_CHECKSUM
XP_LOGF( TAGFMT() "sending msg with sum %s using typ %s", TAGPRMS,
elem->checksum, ConnType2Str(typ) );
#endif
switch ( typ ) {
#ifdef XWFEATURE_RELAY
case COMMS_CONN_RELAY: {
@ -1854,10 +1858,12 @@ got_connect_cmd( CommsCtxt* comms, XWEnv xwe, XWStreamCtxt* stream,
/* Don't bother notifying if the game's already in play on some other
transport */
if ( CONN_ID_NONE == comms->connID ) {
(*comms->procs.rconnd)( xwe, comms->procs.closure,
comms->addr.u.ip_relay.invite, reconnected,
comms->rr.myHostID, XP_FALSE, nSought - nHere );
XP_LOGFF( "have %d of %d players", nHere, nSought );
if ( !!comms->procs.rconnd ) {
(*comms->procs.rconnd)( xwe, comms->procs.closure,
comms->addr.u.ip_relay.invite, reconnected,
comms->rr.myHostID, XP_FALSE, nSought - nHere );
XP_LOGFF( "have %d of %d players", nHere, nSought );
}
}
setHeartbeatTimer( comms );
} /* got_connect_cmd */
@ -3050,13 +3056,13 @@ augmentAddrIntrnl( CommsCtxt* comms, CommsAddrRec* destAddr,
src = &srcAddr->u.p2p;
siz = sizeof(destAddr->u.p2p);
break;
#ifdef XWFEATURE_BLUETOOTH
case COMMS_CONN_BT:
#ifdef XWFEATURE_BLUETOOTH
dest = &destAddr->u.bt;
src = &srcAddr->u.bt;
siz = sizeof(destAddr->u.bt);
break;
#endif
break;
case COMMS_CONN_NFC:
break;
case COMMS_CONN_MQTT:

View file

@ -54,8 +54,8 @@ p_dict_ref( const DictionaryCtxt* dict, XWEnv XP_UNUSED(xwe)
pthread_mutex_lock( &_dict->mutex );
++_dict->refCount;
#ifdef DEBUG_REF
XP_LOGF( "%s(dict=%p): refCount now %d (from line %d of %s() in %s)",
__func__, dict, dict->refCount, line, func, file );
XP_LOGFF( "(dict=%p): refCount now %d (from line %d of %s() in %s)",
dict, dict->refCount, line, func, file );
#endif
pthread_mutex_unlock( &_dict->mutex );
}
@ -76,8 +76,8 @@ p_dict_unref( const DictionaryCtxt* dict, XWEnv xwe
--_dict->refCount;
XP_ASSERT( 0 <= _dict->refCount );
#ifdef DEBUG_REF
XP_LOGF( "%s(dict=%p): refCount now %d (from line %d of %s() in %s)",
__func__, dict, dict->refCount, line, func, file );
XP_LOGF( "(dict=%p): refCount now %d (from line %d of %s() in %s)",
dict, dict->refCount, line, func, file );
#endif
pthread_mutex_unlock( &_dict->mutex );
if ( 0 == _dict->refCount ) {

View file

@ -334,13 +334,13 @@ mem_stream_putBits( XWStreamCtxt* p_sctx, XP_U16 nBits, XP_U32 data
putOneBit( stream, (XP_U16)(((data & 1L) != 0)? 1:0) );
data >>= 1;
}
XP_ASSERT( data == 0 ); /* otherwise nBits was too small */
#ifdef DEBUG
if ( data != 0 ) {
XP_LOGF( "%s: nBits was %d from line %d, %s", __func__,
origBits, lin, fil );
}
#endif
XP_ASSERT( data == 0 ); /* otherwise nBits was too small */
} /* mem_stream_putBits */
static void

View file

@ -51,6 +51,7 @@
#define BDHEIGHT WINDOW_HEIGHT
#define KEY_GAME "the_game"
#define DICTNAME "assets_dir/CollegeEng_2to8.xwd"
EM_JS(bool, call_confirm, (const char* str), {
return confirm(UTF8ToString(str));
@ -120,7 +121,10 @@ initDeviceGlobals( Globals* globals )
globals->mpool = mpool_make( "wasm" );
globals->vtMgr = make_vtablemgr( globals->mpool );
globals->dutil = wasm_dutil_make( globals->mpool, globals->vtMgr, globals );
globals->dict = wasm_load_dict( globals->mpool );
globals->dictMgr = dmgr_make( MPPARM_NOCOMMA(globals->mpool) );
globals->dict = wasm_dictionary_make( MPPARM(globals->mpool) NULL,
globals, DICTNAME, true );
dict_ref( globals->dict, NULL );
globals->draw = wasm_draw_make( MPPARM(globals->mpool)
@ -260,6 +264,7 @@ main_gameFromInvite( Globals* globals, const NetLaunchInfo* invite )
CommsAddrRec returnAddr;
nli_makeAddrRec( invite, &returnAddr );
addr_setType( &returnAddr, COMMS_CONN_MQTT ); /* nuke everything else */
comms_augmentHostAddr( globals->game.comms, NULL, &returnAddr );
startGame( globals );
@ -267,6 +272,16 @@ main_gameFromInvite( Globals* globals, const NetLaunchInfo* invite )
LOG_RETURN_VOID();
}
void
main_onGameMessage( Globals* globals, XP_U32 gameID,
const CommsAddrRec* from, XWStreamCtxt* stream )
{
XP_Bool draw = game_receiveMessage( &globals->game, NULL, stream, from );
if ( draw ) {
updateScreen( globals );
}
}
void
main_sendOnClose( XWStreamCtxt* stream, XWEnv env, void* closure )
{

View file

@ -6,6 +6,7 @@
#include <SDL2/SDL_ttf.h>
#include "game.h"
#include "dictmgr.h"
typedef struct _TimerState {
void* closure;
@ -28,6 +29,7 @@ typedef struct _Globals {
DictionaryCtxt* dict;
TransportProcs procs;
CommonPrefs cp;
DictMgrCtxt* dictMgr;
TimerState timers[NUM_TIMERS_PLUS_ONE];
@ -52,6 +54,8 @@ void main_set_idle( Globals* globals, IdleProc proc, void* closure );
void main_alert( Globals* globals, const XP_UCHAR* msg );
void main_gameFromInvite( Globals* globals, const NetLaunchInfo* invite );
void main_onGameMessage( Globals* globals, XP_U32 gameID,
const CommsAddrRec* from, XWStreamCtxt* stream );
void main_sendOnClose( XWStreamCtxt* stream, XWEnv env, void* closure );

View file

@ -4,34 +4,49 @@
#include <sys/mman.h>
#include "wasmdict.h"
#include "dictnryp.h"
#include "strutils.h"
#define DICTNAME "assets_dir/CollegeEng_2to8.xwd"
#include "dictmgr.h"
typedef struct _WasmDictionaryCtxt {
DictionaryCtxt super;
Globals* globals;
size_t dictLength;
XP_U8* dictBase;
XP_Bool useMMap;
} WasmDictionaryCtxt;
static XP_Bool
initFromDictFile( WasmDictionaryCtxt* dctx, const char* path )
static const XP_UCHAR*
getShortName( const DictionaryCtxt* dict )
{
LOG_FUNC();
XP_Bool formatOk = XP_TRUE;
XP_U32 topOffset;
struct stat statbuf;
int err = stat( DICTNAME, &statbuf );
XP_LOGFF( "stat(%s) => %d; size: %d", DICTNAME, err, statbuf.st_size );
if ( 0 == err && 0 != statbuf.st_size ) {
/* do nothing */
const XP_UCHAR* full = dict_getName( dict );
const XP_UCHAR* ch = strchr( full, '/' );
if ( !!ch ) {
++ch;
} else {
ch = full;
}
return ch;
}
static XP_Bool
initFromDictFile( WasmDictionaryCtxt* dctx, const char* fileName )
{
XP_Bool formatOk = XP_TRUE;
size_t dictLength;
XP_U32 topOffset;
char path[256];
if ( !!fileName ) {
snprintf( path, VSIZE(path), "%s", fileName );
} else { // if ( !getDictPath( params, fileName, path, VSIZE(path) ) ) {
XP_LOGF( "%s: path=%s", __func__, path );
goto closeAndExit;
}
struct stat statbuf;
if ( 0 != stat( path, &statbuf ) || 0 == statbuf.st_size ) {
goto closeAndExit;
}
dctx->dictLength = statbuf.st_size;
{
@ -57,7 +72,7 @@ initFromDictFile( WasmDictionaryCtxt* dctx, const char* path )
if ( formatOk ) {
size_t curPos = ptr - dctx->dictBase;
size_t dictLength = dctx->dictLength - curPos;
dictLength = dctx->dictLength - curPos;
if ( dictLength > 0 ) {
memcpy( &topOffset, ptr, sizeof(topOffset) );
@ -83,7 +98,7 @@ initFromDictFile( WasmDictionaryCtxt* dctx, const char* path )
numEdges = 0;
}
dctx->super.name = copyString( dctx->super.mpool, path );
dctx->super.name = copyString( dctx->super.mpool, fileName );
if ( ! checkSanity( &dctx->super, numEdges ) ) {
goto closeAndExit;
@ -95,12 +110,106 @@ initFromDictFile( WasmDictionaryCtxt* dctx, const char* path )
formatOk = XP_FALSE;
ok:
LOG_RETURNF( "%d", formatOk );
return formatOk;
} /* initFromDictFile */
static void
freeSpecials( WasmDictionaryCtxt* ctxt )
{
XP_U16 nSpecials = 0;
for ( XP_U16 ii = 0; ii < ctxt->super.nFaces; ++ii ) {
if ( IS_SPECIAL(ctxt->super.facePtrs[ii][0] ) ) {
if ( !!ctxt->super.bitmaps ) {
XP_Bitmap* bmp = ctxt->super.bitmaps[nSpecials].largeBM;
if ( !!bmp ) {
XP_FREE( ctxt->super.mpool, bmp );
}
bmp = ctxt->super.bitmaps[nSpecials].smallBM;
if ( !!bmp ) {
XP_FREE( ctxt->super.mpool, bmp );
}
}
if ( !!ctxt->super.chars && !!ctxt->super.chars[nSpecials]) {
XP_FREE( ctxt->super.mpool, ctxt->super.chars[nSpecials] );
}
++nSpecials;
}
}
if ( !!ctxt->super.bitmaps ) {
XP_FREE( ctxt->super.mpool, ctxt->super.bitmaps );
}
XP_FREEP( ctxt->super.mpool, &ctxt->super.chars );
XP_FREEP( ctxt->super.mpool, &ctxt->super.charEnds );
} /* freeSpecials */
static void
wasm_dictionary_destroy( DictionaryCtxt* dict, XWEnv xwe )
{
WasmDictionaryCtxt* ctxt = (WasmDictionaryCtxt*)dict;
freeSpecials( ctxt );
if ( !!ctxt->dictBase ) {
if ( ctxt->useMMap ) {
(void)munmap( ctxt->dictBase, ctxt->dictLength );
} else {
XP_FREE( dict->mpool, ctxt->dictBase );
}
}
/* super's destructor should do this!!!! */
XP_FREEP( dict->mpool, &ctxt->super.desc );
XP_FREEP( dict->mpool, &ctxt->super.md5Sum );
XP_FREEP( dict->mpool, &ctxt->super.countsAndValues );
XP_FREEP( dict->mpool, &ctxt->super.faces );
XP_FREEP( dict->mpool, &ctxt->super.facePtrs );
XP_FREEP( dict->mpool, &ctxt->super.name );
XP_FREE( dict->mpool, ctxt );
}
DictionaryCtxt*
wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
const char* dictFileName, bool useMMap )
{
WasmDictionaryCtxt* result = NULL;
if ( !!dictFileName ) {
/* dmgr_get increments ref count before returning! */
result = (WasmDictionaryCtxt*)dmgr_get( globals->dictMgr, xwe,
dictFileName );
}
if ( !result ) {
result = (WasmDictionaryCtxt*)XP_CALLOC(mpool, sizeof(*result));
result->globals = globals;
dict_super_init( MPPARM(mpool) &result->super );
result->super.destructor = wasm_dictionary_destroy;
result->useMMap = useMMap;
if ( !!dictFileName ) {
XP_Bool success = initFromDictFile( result, dictFileName );
if ( success ) {
result->super.func_dict_getShortName = getShortName;
setBlankTile( &result->super );
} else {
XP_ASSERT( 0 ); /* gonna crash anyway */
XP_FREE( mpool, result );
result = NULL;
}
dmgr_put( globals->dictMgr, xwe, dictFileName, &result->super );
} else {
XP_LOGF( "%s(): no file name!!", __func__ );
}
(void)dict_ref( &result->super, xwe );
}
return &result->super;
}
void
dict_splitFaces( DictionaryCtxt* dict, XWEnv XP_UNUSED(xwe), const XP_U8* utf8,
dict_splitFaces( DictionaryCtxt* dict, XWEnv xwe, const XP_U8* utf8,
XP_U16 nBytes, XP_U16 nFaces )
{
XP_UCHAR* faces = XP_MALLOC( dict->mpool, nBytes + nFaces );
@ -140,9 +249,9 @@ dict_splitFaces( DictionaryCtxt* dict, XWEnv XP_UNUSED(xwe), const XP_U8* utf8,
XP_ASSERT( !dict->facePtrs );
dict->facePtrs = ptrs;
/* for ( int ii = 0; ii < nFaces; ++ii ) { */
/* XP_LOGFF( "face %d: %s", ii, dict->facePtrs[ii] ); */
/* } */
for ( int ii = 0; ii < nFaces; ++ii ) {
XP_LOGFF( "face %d: %s", ii, dict->facePtrs[ii] );
}
} /* dict_splitFaces */
void
@ -151,17 +260,3 @@ computeChecksum( DictionaryCtxt* dctx, XWEnv xwe, const XP_U8* ptr,
{
*out = '\0';
}
DictionaryCtxt*
wasm_load_dict( MPFORMAL_NOCOMMA )
{
LOG_FUNC();
WasmDictionaryCtxt* wdctxt = XP_MALLOC( mpool, sizeof(*wdctxt) );
dict_super_init( mpool, &wdctxt->super );
wdctxt->useMMap = XP_TRUE;
initFromDictFile( wdctxt, DICTNAME );
return &wdctxt->super;
}

View file

@ -1,9 +1,30 @@
#include "dictnry.h"
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
/*
* Copyright 2013 - 2021 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _WASMDICT_H_
#define _WASMDICT_H_
DictionaryCtxt* wasm_load_dict( MPFORMAL_NOCOMMA );
#include "dictnry.h"
#include "main.h"
DictionaryCtxt* wasm_dictionary_make( MPFORMAL XWEnv xwe, Globals* globals,
const char* dictFileName, bool useMMap );
#endif

View file

@ -3,6 +3,7 @@
#include <emscripten.h>
#include "wasmdutil.h"
#include "main.h"
#include "dbgutil.h"
#include "LocalizedStrIncludes.h"
@ -182,8 +183,6 @@ static void
wasm_dutil_loadPtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
const XP_UCHAR* keySuffix, void* data, XP_U16* lenp )
{
XP_LOGFF( "(key: %s, keySuffix: %s)", key, keySuffix );
const char* val = get_stored_value(key);
XP_LOGFF( "get_stored_value(%s) => %s", key, val );
if ( !!val ) {
@ -200,23 +199,16 @@ wasm_dutil_loadPtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
} else {
*lenp = 0; /* signal failure */
}
LOG_RETURN_VOID();
}
static void
wasm_dutil_storePtr( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* key,
const void* data, XP_U16 len )
{
XP_LOGFF( "(key: %s; len: %d)", key, len );
XP_UCHAR out[len*2+1];
base16Encode( data, len, out, sizeof(out) );
set_stored_value( key, out );
/* const char* tmp = get_stored_value( key ); */
/* XP_LOGFF( "TEST: got back %s for key %s", tmp, key ); */
LOG_RETURN_VOID();
}
static const XP_UCHAR*
@ -274,7 +266,8 @@ wasm_dutil_onMessageReceived( XW_DUtilCtxt* duc, XWEnv XP_UNUSED(xwe),
XP_U32 gameID, const CommsAddrRec* from,
XWStreamCtxt* stream )
{
LOG_FUNC();
Globals* globals = (Globals*)duc->closure;
main_onGameMessage( globals, gameID, from, stream );
}
static void

View file

@ -3,6 +3,7 @@
#include "comtypes.h"
#include "main.h"
#include "dbgutil.h"
#include "wasmdict.h"
typedef struct _WasmUtilCtx {
XW_UtilCtxt super;
@ -382,8 +383,8 @@ wasm_util_altKeyDown( XW_UtilCtxt* uc, XWEnv xwe )
static DictionaryCtxt*
wasm_util_makeEmptyDict( XW_UtilCtxt* uc, XWEnv xwe )
{
LOG_FUNC();
return NULL;
LOG_FUNC(); /* firing */
return wasm_dictionary_make( MPPARM(uc->mpool) NULL, uc->closure, NULL, false );
}
static void