diff --git a/xwords4/common/dictnry.c b/xwords4/common/dictnry.c index c72f88821..2f22a107d 100644 --- a/xwords4/common/dictnry.c +++ b/xwords4/common/dictnry.c @@ -456,7 +456,9 @@ dict_loadFromStream( DictionaryCtxt* dict, XWStreamCtxt* stream ) XP_UCHAR* localTexts[32]; XP_U8 utf8[MAX_UNIQUE_TILES]; - XP_ASSERT( !dict->destructor ); + if ( !!dict->destructor ) { + XP_LOGF( "%s(): replacing destructor!!", __func__ ); + } dict->destructor = common_destructor; dict->func_dict_getShortName = dict_getName; /* default */ diff --git a/xwords4/linux/curgamlistwin.c b/xwords4/linux/curgamlistwin.c index ccb382ea9..5d34f3674 100644 --- a/xwords4/linux/curgamlistwin.c +++ b/xwords4/linux/curgamlistwin.c @@ -142,15 +142,18 @@ cgl_moveSel( CursGameList* cgl, bool down ) static void adjustCurSel( CursGameList* cgl ) { - XP_LOGF( "%s() start: curSel: %d; yOffset: %d", __func__, cgl->curSel, cgl->yOffset ); int nGames = g_slist_length( cgl->games ); + XP_LOGF( "%s() start: curSel: %d; yOffset: %d; nGames: %d", __func__, + cgl->curSel, cgl->yOffset, nGames ); if ( cgl->curSel >= nGames ) { cgl->curSel = nGames - 1; } /* Now adjust yOffset */ int nVisRows = cgl->height - 2; /* 1 for the title and header rows */ - if ( cgl->curSel - cgl->yOffset >= nVisRows ) { + if ( nGames < nVisRows ) { + cgl->yOffset = 0; + } else if ( cgl->curSel - cgl->yOffset >= nVisRows ) { cgl->yOffset = cgl->curSel - nVisRows + 1; } else { while ( cgl->curSel < cgl->yOffset ) { diff --git a/xwords4/linux/cursesask.c b/xwords4/linux/cursesask.c index 5e7314310..8edc3f1d2 100644 --- a/xwords4/linux/cursesask.c +++ b/xwords4/linux/cursesask.c @@ -127,4 +127,11 @@ cursesask( WINDOW* window, const char* question, short numButtons, return curSelButton; } /* cursesask */ +void +ca_inform( WINDOW* window, const char* message ) +{ + const char* buttons[] = { "Ok" }; + (void)cursesask( window, message, VSIZE(buttons), buttons ); +} + #endif /* PLATFORM_NCURSES */ diff --git a/xwords4/linux/cursesask.h b/xwords4/linux/cursesask.h index c53fd05b7..d9c173f52 100644 --- a/xwords4/linux/cursesask.h +++ b/xwords4/linux/cursesask.h @@ -25,5 +25,7 @@ int cursesask( WINDOW* window, const char* question, short numButtons, const char** buttons ); +void ca_inform( WINDOW* window, const char* message ); + #endif diff --git a/xwords4/linux/cursesboard.c b/xwords4/linux/cursesboard.c index f72840b8d..eb12cf51f 100644 --- a/xwords4/linux/cursesboard.c +++ b/xwords4/linux/cursesboard.c @@ -32,6 +32,8 @@ #include "gamesdb.h" #include "game.h" #include "gsrcwrap.h" +#include "linuxsms.h" +#include "strutils.h" typedef struct CursesBoardState { CursesAppGlobals* aGlobals; @@ -72,9 +74,10 @@ struct CursesBoardGlobals { }; static CursesBoardGlobals* findOrOpen( CursesBoardState* cbState, - sqlite3_int64 rowid ); -static void enableDraw( CursesBoardGlobals* bGlobals, - int width, int top, int height ); + sqlite3_int64 rowid, + const CurGameInfo* gi, + const CommsAddrRec* addrP ); +static void enableDraw( CursesBoardGlobals* bGlobals, const cb_dims* dims ); static CursesBoardGlobals* ref( CursesBoardGlobals* bGlobals ); static void unref( CursesBoardGlobals* bGlobals ); static void setupBoard( CursesBoardGlobals* bGlobals ); @@ -92,12 +95,11 @@ cb_init( CursesAppGlobals* aGlobals, LaunchParams* params, } void -cb_open( CursesBoardState* cbState, sqlite3_int64 rowid, - int width, int top, int height ) +cb_open( CursesBoardState* cbState, sqlite3_int64 rowid, const cb_dims* dims ) { LOG_FUNC(); - CursesBoardGlobals* bGlobals = findOrOpen( cbState, rowid ); - enableDraw( bGlobals, width, top, height ); + CursesBoardGlobals* bGlobals = findOrOpen( cbState, rowid, NULL, NULL ); + enableDraw( bGlobals, dims ); setupBoard( bGlobals ); CommonGlobals* cGlobals = &bGlobals->cGlobals; @@ -107,16 +109,39 @@ cb_open( CursesBoardState* cbState, sqlite3_int64 rowid, } bool -cb_new( CursesBoardState* cbState, int width, int top, int height ) +cb_new( CursesBoardState* cbState, const cb_dims* dims ) { - CursesBoardGlobals* bGlobals = findOrOpen( cbState, -1 ); + CursesBoardGlobals* bGlobals = findOrOpen( cbState, -1, NULL, NULL ); if ( !!bGlobals ) { - enableDraw( bGlobals, width, top, height ); + enableDraw( bGlobals, dims ); setupBoard( bGlobals ); } return NULL != bGlobals; } +void +cb_newFor( CursesBoardState* cbState, const NetLaunchInfo* nli, + const CommsAddrRec* returnAddr, + const cb_dims* dims ) +{ + LaunchParams* params = cbState->params; + CurGameInfo gi = {0}; + gi_copy( MPPARM(params->mpool) &gi, ¶ms->pgi ); + gi_setNPlayers( &gi, nli->nPlayersT, nli->nPlayersH ); + gi.gameID = nli->gameID; + gi.dictLang = nli->lang; + gi.forceChannel = nli->forceChannel; + gi.serverRole = SERVER_ISCLIENT; /* recipient of invitation is client */ + replaceStringIfDifferent( params->mpool, &gi.dictName, nli->dict ); + + CursesBoardGlobals* bGlobals = findOrOpen( cbState, -1, &gi, returnAddr ); + + gi_disposePlayerInfo( MPPARM(params->mpool) &gi ); + + enableDraw( bGlobals, dims ); + setupBoard( bGlobals ); +} + #ifdef KEYBOARD_NAV static bool handleLeft( void* closure, int key ); static bool handleRight( void* closure, int key ); @@ -143,6 +168,7 @@ static bool handleToggleValues( void* closure, int key ); static bool handleBackspace( void* closure, int key ); static bool handleUndo( void* closure, int key ); static bool handleReplace( void* closure, int key ); +static bool handleInvite( void* closure, int key ); #ifdef CURSES_SMALL_SCREEN static bool handleRootKeyShow( void* closure, int key ); static bool handleRootKeyHide( void* closure, int key ); @@ -192,6 +218,8 @@ const MenuList g_boardMenuList[] = { { handleUndo, "Undo prev", "U", 'U' }, { handleReplace, "uNdo cur", "N", 'N' }, + { handleInvite, "invitE", "E", 'E' }, + { NULL, NULL, NULL, '\0'} }; @@ -338,7 +366,8 @@ copyParmsAddr( CommonGlobals* cGlobals ) } static CursesBoardGlobals* -commonInit( CursesBoardState* cbState, sqlite3_int64 rowid ) +commonInit( CursesBoardState* cbState, sqlite3_int64 rowid, + const CurGameInfo* gip ) { CursesBoardGlobals* bGlobals = g_malloc0( sizeof(*bGlobals) ); XP_LOGF( "%s(): alloc'd bGlobals %p", __func__, bGlobals ); @@ -346,7 +375,7 @@ commonInit( CursesBoardState* cbState, sqlite3_int64 rowid ) LaunchParams* params = cbState->params; cGlobals->gi = &cGlobals->_gi; - gi_copy( MPPARM(params->mpool) cGlobals->gi, ¶ms->pgi ); + gi_copy( MPPARM(params->mpool) cGlobals->gi, !!gip? gip : ¶ms->pgi ); cGlobals->rowid = rowid; bGlobals->cbState = cbState; @@ -505,10 +534,11 @@ setupBoard( CursesBoardGlobals* bGlobals ) } static CursesBoardGlobals* -initNoDraw( CursesBoardState* cbState, sqlite3_int64 rowid ) +initNoDraw( CursesBoardState* cbState, sqlite3_int64 rowid, + const CurGameInfo* gi, const CommsAddrRec* addr ) { LOG_FUNC(); - CursesBoardGlobals* result = commonInit( cbState, rowid ); + CursesBoardGlobals* result = commonInit( cbState, rowid, gi ); CommonGlobals* cGlobals = &result->cGlobals; LaunchParams* params = cGlobals->params; @@ -525,14 +555,10 @@ initNoDraw( CursesBoardState* cbState, sqlite3_int64 rowid ) cGlobals->cp.robotTradePct = params->robotTradePct; #endif - if ( -1 == rowid ) { - cGlobals->rowid = -1; - } - initMenus( result ); - if ( linuxOpenGame( cGlobals, &result->procs ) ) { - result = ref( result ); + if ( linuxOpenGame( cGlobals, &result->procs, gi, addr ) ) { + result = ref( result ); } else { disposeBoard( result ); result = NULL; @@ -541,11 +567,11 @@ initNoDraw( CursesBoardState* cbState, sqlite3_int64 rowid ) } static void -enableDraw( CursesBoardGlobals* bGlobals, int width, int top, int height ) +enableDraw( CursesBoardGlobals* bGlobals, const cb_dims* dims ) { LOG_FUNC(); - XP_ASSERT( 0 != width ); - bGlobals->boardWin = newwin( height, width, top, 0 ); + XP_ASSERT( !!dims ); + bGlobals->boardWin = newwin( dims->height, dims->width, dims->top, 0 ); getmaxyx( bGlobals->boardWin, bGlobals->winHeight, bGlobals->winWidth ); CommonGlobals* cGlobals = &bGlobals->cGlobals; @@ -556,11 +582,12 @@ enableDraw( CursesBoardGlobals* bGlobals, int width, int top, int height ) } static CursesBoardGlobals* -findOrOpen( CursesBoardState* cbState, sqlite3_int64 rowid ) +findOrOpen( CursesBoardState* cbState, sqlite3_int64 rowid, + const CurGameInfo* gi, const CommsAddrRec* addr ) { CursesBoardGlobals* result = NULL; for ( GSList* iter = cbState->games; - rowid != 0 && !!iter && !result; iter = iter->next ) { + rowid >= 0 && !!iter && !result; iter = iter->next ) { CursesBoardGlobals* one = (CursesBoardGlobals*)iter->data; if ( one->cGlobals.rowid == rowid ) { result = one; @@ -568,7 +595,7 @@ findOrOpen( CursesBoardState* cbState, sqlite3_int64 rowid ) } if ( !result ) { - result = initNoDraw( cbState, rowid ); + result = initNoDraw( cbState, rowid, gi, addr ); if ( !!result ) { setupBoard( result ); cbState->games = g_slist_append( cbState->games, result ); @@ -578,16 +605,32 @@ findOrOpen( CursesBoardState* cbState, sqlite3_int64 rowid ) } XP_U16 -cb_feedBuffer( CursesBoardState* cbState, sqlite3_int64 rowid, - const XP_U8* buf, XP_U16 len, const CommsAddrRec* from ) +cb_feedRow( CursesBoardState* cbState, sqlite3_int64 rowid, + const XP_U8* buf, XP_U16 len, const CommsAddrRec* from ) { - CursesBoardGlobals* bGlobals = findOrOpen( cbState, rowid ); + LOG_FUNC(); + CursesBoardGlobals* bGlobals = findOrOpen( cbState, rowid, NULL, NULL ); CommonGlobals* cGlobals = &bGlobals->cGlobals; gameGotBuf( cGlobals, XP_TRUE, buf, len, from ); XP_U16 seed = comms_getChannelSeed( cGlobals->game.comms ); return seed; } +void +cb_feedGame( CursesBoardState* cbState, XP_U32 gameID, + const XP_U8* buf, XP_U16 len, const CommsAddrRec* from ) +{ + LOG_FUNC(); + sqlite3_int64 rowids[4]; + int nRows = VSIZE( rowids ); + LaunchParams* params = cbState->params; + getRowsForGameID( params->pDb, gameID, rowids, &nRows ); + XP_LOGF( "%s(): found %d rows for gameID %d", __func__, nRows, gameID ); + for ( int ii = 0; ii < nRows; ++ii ) { + (void)cb_feedRow( cbState, rowids[ii], buf, len, from ); + } +} + static void kill_board( gpointer data ) { @@ -1146,6 +1189,33 @@ handleReplace( void* closure, int XP_UNUSED(key) ) return XP_TRUE; } /* handleReplace */ +static bool +handleInvite( void* closure, int XP_UNUSED(key) ) +{ + CursesBoardGlobals* bGlobals = (CursesBoardGlobals*)closure; + CommonGlobals* cGlobals = &bGlobals->cGlobals; + LaunchParams* params = cGlobals->params; + CommsAddrRec addr = {0}; + CommsCtxt* comms = cGlobals->game.comms; + XP_ASSERT( comms ); + comms_getAddr( comms, &addr ); + if ( SERVER_ISSERVER != cGlobals->gi->serverRole ) { + ca_inform( bGlobals->boardWin, "Only hosts can invite" ); + } else if ( !params->connInfo.sms.inviteePhone ) { + ca_inform( bGlobals->boardWin, "No way to invite; use --invitee-sms-number" ); + } else { + /* These should both be settable/derivable */ + XP_U16 nPlayers = 1; + gint forceChannel = 1; + NetLaunchInfo nli = {0}; + nli_init( &nli, cGlobals->gi, &addr, nPlayers, forceChannel ); + + linux_sms_invite( params, &nli, params->connInfo.sms.inviteePhone, + params->connInfo.sms.port ); + } + return XP_TRUE; +} + static bool handleCommit( void* closure, int XP_UNUSED(key) ) { diff --git a/xwords4/linux/cursesboard.h b/xwords4/linux/cursesboard.h index 5ec78145a..91d38dd89 100644 --- a/xwords4/linux/cursesboard.h +++ b/xwords4/linux/cursesboard.h @@ -22,6 +22,7 @@ #define _CURSESBOARD_H_ #include "cursesmain.h" +#include "nli.h" typedef struct CursesAppGlobals CursesAppGlobals; typedef struct CursesBoardState CursesBoardState; @@ -31,12 +32,21 @@ typedef void (*OnGameSaved)( CursesAppGlobals* aGlobals, sqlite3_int64 rowid, bo CursesBoardState* cb_init( CursesAppGlobals* aGlobals, LaunchParams* params, CursesMenuState* menuState, OnGameSaved onGameSaved ); -void cb_open( CursesBoardState* cbState, sqlite3_int64 rowid, - int width, int top, int height ); -bool cb_new( CursesBoardState* cbState, int width, int top, int height ); +typedef struct _cb_dims { + int width; + int top; + int height; +} cb_dims; -XP_U16 cb_feedBuffer( CursesBoardState* cbState, sqlite3_int64 rowid, - const XP_U8* buf, XP_U16 len, const CommsAddrRec* from ); +void cb_open( CursesBoardState* cbState, sqlite3_int64 rowid, const cb_dims* dims ); +bool cb_new( CursesBoardState* cbState, const cb_dims* dims ); +void cb_newFor( CursesBoardState* cbState, const NetLaunchInfo* nli, + const CommsAddrRec* returnAddr, const cb_dims* dims ); + +XP_U16 cb_feedRow( CursesBoardState* cbState, sqlite3_int64 rowid, + const XP_U8* buf, XP_U16 len, const CommsAddrRec* from ); +void cb_feedGame( CursesBoardState* cbState, XP_U32 gameID, + const XP_U8* buf, XP_U16 len, const CommsAddrRec* from ); void cb_closeAll( CursesBoardState* cbState ); #endif diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c index 0422b89bf..1697c77b6 100644 --- a/xwords4/linux/cursesmain.c +++ b/xwords4/linux/cursesmain.c @@ -243,12 +243,12 @@ handleQuit( void* closure, int XP_UNUSED(key) ) } /* handleQuit */ static void -figureDims( CursesAppGlobals* aGlobals, int* widthP, int* topP, int* heightP ) +figureDims( CursesAppGlobals* aGlobals, cb_dims* dims ) { LaunchParams* params = aGlobals->cag.params; - *widthP = aGlobals->winWidth; - *topP = params->cursesListWinHt; - *heightP = aGlobals->winHeight - params->cursesListWinHt - MENU_WINDOW_HEIGHT; + dims->width = aGlobals->winWidth; + dims->top = params->cursesListWinHt; + dims->height = aGlobals->winHeight - params->cursesListWinHt - MENU_WINDOW_HEIGHT; } static bool @@ -258,9 +258,9 @@ handleOpenGame( void* closure, int XP_UNUSED(key) ) CursesAppGlobals* aGlobals = (CursesAppGlobals*)closure; const GameInfo* gi = cgl_getSel( aGlobals->gameList ); if ( !!gi ) { - int width, top, height; - figureDims( aGlobals, &width, &top, &height ); - cb_open( aGlobals->cbState, gi->rowid, width, top, height ); + cb_dims dims; + figureDims( aGlobals, &dims ); + cb_open( aGlobals->cbState, gi->rowid, &dims ); } return XP_TRUE; } @@ -273,9 +273,9 @@ handleNewGame( void* closure, int XP_UNUSED(key) ) // aGlobals->cag.params->needsNewGame = XP_FALSE; - int width, top, height; - figureDims( aGlobals, &width, &top, &height ); - if ( !cb_new( aGlobals->cbState, width, top, height ) ) { + cb_dims dims; + figureDims( aGlobals, &dims ); + if ( !cb_new( aGlobals->cbState, &dims ) ) { /* This erases the whole screen. Fix later. PENDING */ /* const char* buttons[] = { "Ok", }; */ /* (void)cursesask( aGlobals->mainWin, "Unable to create game (check params?)", */ @@ -931,7 +931,7 @@ cursesGotBuf( void* closure, const CommsAddrRec* addr, rowidFromToken( XP_NTOHL( clientToken ), &rowid, &gotSeed ); /* Figure out if the device is live, or we need to open the game */ - XP_U16 seed = cb_feedBuffer( aGlobals->cbState, rowid, buf, len, addr ); + XP_U16 seed = cb_feedRow( aGlobals->cbState, rowid, buf, len, addr ); XP_ASSERT( seed == 0 || gotSeed == seed ); XP_USE( seed ); @@ -944,6 +944,35 @@ cursesGotBuf( void* closure, const CommsAddrRec* addr, /* LOG_RETURN_VOID(); */ } +static void +smsInviteReceivedCurses( void* closure, const NetLaunchInfo* nli, + const CommsAddrRec* returnAddr ) +{ + CursesAppGlobals* aGlobals = (CursesAppGlobals*)closure; + /* LaunchParams* params = aGlobals->cag.params; */ + /* CurGameInfo gi = {0}; */ + /* gi_copy( MPPARM(params->mpool) &gi, ¶ms->pgi ); */ + + /* gi_setNPlayers( &gi, invite->nPlayersT, invite->nPlayersH ); */ + /* gi.gameID = invite->gameID; */ + /* gi.dictLang = invite->lang; */ + /* gi.forceChannel = invite->forceChannel; */ + /* gi.serverRole = SERVER_ISCLIENT; /\* recipient of invitation is client *\/ */ + /* replaceStringIfDifferent( params->mpool, &gi.dictName, invite->dict ); */ + + cb_dims dims; + figureDims( aGlobals, &dims ); + cb_newFor( aGlobals->cbState, nli, returnAddr, &dims ); +} + +static void +smsMsgReceivedCurses( void* closure, const CommsAddrRec* from, XP_U32 gameID, + const XP_U8* buf, XP_U16 len ) +{ + CursesAppGlobals* aGlobals = (CursesAppGlobals*)closure; + cb_feedGame( aGlobals->cbState, gameID, buf, len, from ); +} + static void cursesGotForRow( void* XP_UNUSED(closure), const CommsAddrRec* XP_UNUSED(from), sqlite3_int64 XP_UNUSED(rowid), const XP_U8* XP_UNUSED(buf), @@ -1206,6 +1235,18 @@ cursesmain( XP_Bool XP_UNUSED(isServer), LaunchParams* params ) linux_doInitialReg( params, idIsNew ); } +#ifdef XWFEATURE_SMS + gchar* myPhone = NULL; + XP_U16 myPort = 0; + if ( parseSMSParams( params, &myPhone, &myPort ) ) { + SMSProcs smsProcs = { + .inviteReceived = smsInviteReceivedCurses, + .msgReceived = smsMsgReceivedCurses, + }; + linux_sms_init( params, myPhone, myPort, &smsProcs, &g_globals ); + } +#endif + if ( 0 == cgl_getNGames( g_globals.gameList ) ) { handleNewGame( &g_globals, 0 ); } diff --git a/xwords4/linux/gtkboard.c b/xwords4/linux/gtkboard.c index d00704bff..7891907c2 100644 --- a/xwords4/linux/gtkboard.c +++ b/xwords4/linux/gtkboard.c @@ -584,7 +584,7 @@ createOrLoadObjects( GtkGameGlobals* globals ) TransportProcs procs; setTransportProcs( &procs, globals ); - linuxOpenGame( cGlobals, &procs ); + linuxOpenGame( cGlobals, &procs, NULL, NULL ); if ( !params->fileName && !!params->dbName ) { XP_UCHAR buf[64]; @@ -1381,26 +1381,7 @@ static void handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals ) { CommonGlobals* cGlobals = &globals->cGlobals; - /* const CurGameInfo* gi = cGlobals->gi; */ - - /* gchar* countStr; */ - /* gchar* phone = NULL; */ - /* gchar* portstr = NULL; */ - /* gchar* forceChannelStr; */ - /* AskMInfo infos[] = { */ - /* { "Number of players", &countStr }, */ - /* { "Remote phone#", &phone }, */ - /* { "Remote port", &portstr }, */ - /* { "Force channel", &forceChannelStr }, */ - /* }; */ - XP_U16 nMissing = server_getPendingRegs( globals->cGlobals.game.server ); - /* gchar buf[64]; */ - /* sprintf( buf, "%d", nMissing ); */ - /* countStr = buf; */ - /* gchar forceChannelBuf[64]; */ - /* sprintf( forceChannelBuf, "%d", 1 ); */ - /* forceChannelStr = forceChannelBuf; */ CommsAddrRec inviteAddr = {0}; gint nPlayers = nMissing; diff --git a/xwords4/linux/gtkmain.c b/xwords4/linux/gtkmain.c index eaba9f608..f81494bed 100644 --- a/xwords4/linux/gtkmain.c +++ b/xwords4/linux/gtkmain.c @@ -895,22 +895,9 @@ gtkmain( LaunchParams* params ) } #ifdef XWFEATURE_SMS - gchar buf[32]; - const gchar* myPhone = params->connInfo.sms.myPhone; - if ( !!myPhone ) { - db_store( params->pDb, KEY_SMSPHONE, myPhone ); - } else if ( !myPhone && db_fetch_safe( params->pDb, KEY_SMSPHONE, buf, VSIZE(buf) ) ) { - params->connInfo.sms.myPhone = myPhone = buf; - } - XP_U16 myPort = params->connInfo.sms.port; - gchar portbuf[8]; - if ( 0 < myPort ) { - sprintf( portbuf, "%d", myPort ); - db_store( params->pDb, KEY_SMSPORT, portbuf ); - } else if ( db_fetch_safe( params->pDb, KEY_SMSPORT, portbuf, VSIZE(portbuf) ) ) { - params->connInfo.sms.port = myPort = atoi( portbuf ); - } - if ( !!myPhone && 0 < myPort ) { + gchar* myPhone; + XP_U16 myPort; + if ( parseSMSParams( params, &myPhone, &myPort ) ) { SMSProcs smsProcs = { .inviteReceived = smsInviteReceived, .msgReceived = smsMsgReceivedGTK, diff --git a/xwords4/linux/linuxmain.c b/xwords4/linux/linuxmain.c index cd12deb3a..96f871034 100644 --- a/xwords4/linux/linuxmain.c +++ b/xwords4/linux/linuxmain.c @@ -163,7 +163,8 @@ canMakeFromGI( const CurGameInfo* gi ) } bool -linuxOpenGame( CommonGlobals* cGlobals, const TransportProcs* procs ) +linuxOpenGame( CommonGlobals* cGlobals, const TransportProcs* procs, + const CurGameInfo* gi, const CommsAddrRec* addrP ) { LOG_FUNC(); XWStreamCtxt* stream = NULL; @@ -202,108 +203,115 @@ linuxOpenGame( CommonGlobals* cGlobals, const TransportProcs* procs ) stream_destroy( stream ); } - if ( !opened && canMakeFromGI( cGlobals->gi ) ) { - opened = XP_TRUE; + if ( !opened ) { + if ( !gi ) { + gi = cGlobals->gi; + } + if ( canMakeFromGI( gi ) ) { + opened = XP_TRUE; #ifdef XWFEATURE_RELAY - /* if ( addr.conType == COMMS_CONN_RELAY ) { */ - /* XP_ASSERT( !!params->connInfo.relay.relayName ); */ - /* globals->cGlobals.defaultServerName */ - /* = params->connInfo.relay.relayName; */ - /* } */ + /* if ( addr.conType == COMMS_CONN_RELAY ) { */ + /* XP_ASSERT( !!params->connInfo.relay.relayName ); */ + /* globals->cGlobals.defaultServerName */ + /* = params->connInfo.relay.relayName; */ + /* } */ #endif - game_makeNewGame( MEMPOOL &cGlobals->game, cGlobals->gi, - cGlobals->util, cGlobals->draw, - &cGlobals->cp, procs + game_makeNewGame( MEMPOOL &cGlobals->game, cGlobals->gi, + cGlobals->util, cGlobals->draw, + &cGlobals->cp, procs #ifdef SET_GAMESEED - , params->gameSeed + , params->gameSeed #endif - ); + ); - CommsAddrRec addr = cGlobals->addr; - // addr.conType = params->conType; - CommsConnType typ; - for ( XP_U32 st = 0; addr_iter( &addr, &typ, &st ); ) { - if ( params->commsDisableds[typ][0] ) { - comms_setAddrDisabled( cGlobals->game.comms, typ, XP_FALSE, XP_TRUE ); - } - if ( params->commsDisableds[typ][1] ) { - comms_setAddrDisabled( cGlobals->game.comms, typ, XP_TRUE, XP_TRUE ); - } - switch( typ ) { + CommsAddrRec addr = !!addrP ? *addrP : cGlobals->addr; + // addr.conType = params->conType; + CommsConnType typ; + for ( XP_U32 st = 0; addr_iter( &addr, &typ, &st ); ) { + if ( params->commsDisableds[typ][0] ) { + comms_setAddrDisabled( cGlobals->game.comms, typ, XP_FALSE, XP_TRUE ); + } + if ( params->commsDisableds[typ][1] ) { + comms_setAddrDisabled( cGlobals->game.comms, typ, XP_TRUE, XP_TRUE ); + } + switch( typ ) { #ifdef XWFEATURE_RELAY - case COMMS_CONN_RELAY: - /* addr.u.ip_relay.ipAddr = 0; */ - /* addr.u.ip_relay.port = params->connInfo.relay.defaultSendPort; */ - /* addr.u.ip_relay.seeksPublicRoom = params->connInfo.relay.seeksPublicRoom; */ - /* addr.u.ip_relay.advertiseRoom = params->connInfo.relay.advertiseRoom; */ - /* XP_STRNCPY( addr.u.ip_relay.hostName, params->connInfo.relay.relayName, */ - /* sizeof(addr.u.ip_relay.hostName) - 1 ); */ - /* XP_STRNCPY( addr.u.ip_relay.invite, params->connInfo.relay.invite, */ - /* sizeof(addr.u.ip_relay.invite) - 1 ); */ - break; + case COMMS_CONN_RELAY: + /* addr.u.ip_relay.ipAddr = 0; */ + /* addr.u.ip_relay.port = params->connInfo.relay.defaultSendPort; */ + /* addr.u.ip_relay.seeksPublicRoom = params->connInfo.relay.seeksPublicRoom; */ + /* addr.u.ip_relay.advertiseRoom = params->connInfo.relay.advertiseRoom; */ + /* XP_STRNCPY( addr.u.ip_relay.hostName, params->connInfo.relay.relayName, */ + /* sizeof(addr.u.ip_relay.hostName) - 1 ); */ + /* XP_STRNCPY( addr.u.ip_relay.invite, params->connInfo.relay.invite, */ + /* sizeof(addr.u.ip_relay.invite) - 1 ); */ + break; #endif #ifdef XWFEATURE_BLUETOOTH - case COMMS_CONN_BT: - XP_ASSERT( sizeof(addr.u.bt.btAddr) - >= sizeof(params->connInfo.bt.hostAddr)); - XP_MEMCPY( &addr.u.bt.btAddr, ¶ms->connInfo.bt.hostAddr, - sizeof(params->connInfo.bt.hostAddr) ); - break; + case COMMS_CONN_BT: + XP_ASSERT( sizeof(addr.u.bt.btAddr) + >= sizeof(params->connInfo.bt.hostAddr)); + XP_MEMCPY( &addr.u.bt.btAddr, ¶ms->connInfo.bt.hostAddr, + sizeof(params->connInfo.bt.hostAddr) ); + break; #endif #ifdef XWFEATURE_IP_DIRECT - case COMMS_CONN_IP_DIRECT: - XP_STRNCPY( addr.u.ip.hostName_ip, params->connInfo.ip.hostName, - sizeof(addr.u.ip.hostName_ip) - 1 ); - addr.u.ip.port_ip = params->connInfo.ip.port; - break; + case COMMS_CONN_IP_DIRECT: + XP_STRNCPY( addr.u.ip.hostName_ip, params->connInfo.ip.hostName, + sizeof(addr.u.ip.hostName_ip) - 1 ); + addr.u.ip.port_ip = params->connInfo.ip.port; + break; #endif #ifdef XWFEATURE_SMS - case COMMS_CONN_SMS: - /* No! Don't overwrite what may be a return address with local - stuff */ - /* XP_STRNCPY( addr.u.sms.phone, params->connInfo.sms.phone, */ - /* sizeof(addr.u.sms.phone) - 1 ); */ - /* addr.u.sms.port = params->connInfo.sms.port; */ - break; + case COMMS_CONN_SMS: + XP_LOGF( "%s(): SMS is on at least", __func__ ); + /* No! Don't overwrite what may be a return address with local + stuff */ + /* XP_STRNCPY( addr.u.sms.phone, params->connInfo.sms.phone, */ + /* sizeof(addr.u.sms.phone) - 1 ); */ + /* addr.u.sms.port = params->connInfo.sms.port; */ + break; #endif - default: - break; + default: + break; + } } - } - model_setDictionary( cGlobals->game.model, cGlobals->dict ); - setSquareBonuses( cGlobals ); - model_setPlayerDicts( cGlobals->game.model, &cGlobals->dicts ); + model_setDictionary( cGlobals->game.model, cGlobals->dict ); + setSquareBonuses( cGlobals ); + model_setPlayerDicts( cGlobals->game.model, &cGlobals->dicts ); - /* Need to save in order to have a valid selRow for the first send */ - linuxSaveGame( cGlobals ); + /* Need to save in order to have a valid selRow for the first send */ + linuxSaveGame( cGlobals ); #ifndef XWFEATURE_STANDALONE_ONLY - /* This may trigger network activity */ - if ( !!cGlobals->game.comms ) { - comms_setAddr( cGlobals->game.comms, &addr ); - } + /* This may trigger network activity */ + if ( !!cGlobals->game.comms ) { + comms_setAddr( cGlobals->game.comms, &addr ); + } #endif #ifdef XWFEATURE_SEARCHLIMIT - cGlobals->gi->allowHintRect = params->allowHintRect; + cGlobals->gi->allowHintRect = params->allowHintRect; #endif - if ( params->needsNewGame ) { - XP_ASSERT(0); - // new_game_impl( globals, XP_FALSE ); -#ifndef XWFEATURE_STANDALONE_ONLY - } else { - DeviceRole serverRole = cGlobals->gi->serverRole; - if ( serverRole == SERVER_ISCLIENT ) { - tryConnectToServer( cGlobals ); + if ( params->needsNewGame ) { + XP_ASSERT(0); + // new_game_impl( globals, XP_FALSE ); } -#endif } } if ( opened ) { +#ifndef XWFEATURE_STANDALONE_ONLY + DeviceRole serverRole = cGlobals->gi->serverRole; + XP_LOGF( "%s(): server role: %d", __func__, serverRole ); + if ( serverRole == SERVER_ISCLIENT ) { + tryConnectToServer( cGlobals ); + } +#endif + #ifndef XWFEATURE_STANDALONE_ONLY if ( !!cGlobals->game.comms ) { comms_start( cGlobals->game.comms ); @@ -564,7 +572,7 @@ linuxSaveGame( CommonGlobals* cGlobals ) XP_LOGF( "%s: simulating save failure", __func__ ); } } -} +} /* linuxSaveGame */ static void handle_messages_from( CommonGlobals* cGlobals, const TransportProcs* procs, @@ -835,7 +843,7 @@ typedef enum { #endif #ifdef XWFEATURE_SMS ,CMD_SMSNUMBER /* SMS phone number */ - ,CMD_SERVER_SMSNUMBER + ,CMD_INVITEE_SMSNUMBER ,CMD_SMSPORT #endif #ifdef XWFEATURE_RELAY @@ -963,7 +971,7 @@ static CmdInfoRec CmdInfoRecs[] = { #endif #ifdef XWFEATURE_SMS ,{ CMD_SMSNUMBER, true, "sms-number", "this devices's sms phone number" } - ,{ CMD_SERVER_SMSNUMBER, true, "server-sms-number", "number this device should connect to" } + ,{ CMD_INVITEE_SMSNUMBER, true, "invitee-sms-number", "number to send any invitation to" } ,{ CMD_SMSPORT, true, "sms-port", "this devices's sms port" } #endif #ifdef XWFEATURE_RELAY @@ -1170,6 +1178,29 @@ linux_setupDevidParams( LaunchParams* params ) return idIsNew; } +XP_Bool +parseSMSParams( LaunchParams* params, gchar** myPhone, XP_U16* myPort ) +{ + gchar buf[32]; + const XP_UCHAR* phone = params->connInfo.sms.myPhone; + if ( !!phone ) { + db_store( params->pDb, KEY_SMSPHONE, *myPhone ); + *myPhone = g_strdup( phone ); + } else if ( !phone && db_fetch_safe( params->pDb, KEY_SMSPHONE, buf, VSIZE(buf) ) ) { + params->connInfo.sms.myPhone = *myPhone = g_strdup(buf); + } + + *myPort = params->connInfo.sms.port; + gchar portbuf[8]; + if ( 0 < *myPort ) { + sprintf( portbuf, "%d", *myPort ); + db_store( params->pDb, KEY_SMSPORT, portbuf ); + } else if ( db_fetch_safe( params->pDb, KEY_SMSPORT, portbuf, VSIZE(portbuf) ) ) { + params->connInfo.sms.port = *myPort = atoi( portbuf ); + } + return NULL != *myPhone && 0 < *myPort; +} + #ifdef XWFEATURE_RELAY static int linux_init_relay_socket( CommonGlobals* cGlobals, const CommsAddrRec* addrRec ) @@ -1496,12 +1527,9 @@ linux_send( const XP_U8* buf, XP_U16 buflen, const XP_UCHAR* XP_UNUSED_DBG(msgNo // use serverphone if I'm a client, else hope one's provided (this is // a reply) - const XP_UCHAR* phone = cGlobals->params->connInfo.sms.serverPhone; - if ( !phone ) { - phone = addrRec->u.sms.phone; - } nSent = linux_sms_send( cGlobals->params, buf, buflen, - phone, addrRec->u.sms.port, gameID ); + addrRec->u.sms.phone, addrRec->u.sms.port, + gameID ); } break; #endif @@ -2464,8 +2492,8 @@ main( int argc, char** argv ) mainParams.connInfo.sms.myPhone = optarg; addr_addType( &mainParams.addr, COMMS_CONN_SMS ); break; - case CMD_SERVER_SMSNUMBER: - mainParams.connInfo.sms.serverPhone = optarg; + case CMD_INVITEE_SMSNUMBER: + mainParams.connInfo.sms.inviteePhone = optarg; addr_addType( &mainParams.addr, COMMS_CONN_SMS ); break; case CMD_SMSPORT: @@ -2836,6 +2864,15 @@ main( int argc, char** argv ) } break; #endif +/* #ifdef XWFEATURE_SMS */ +/* case COMMS_CONN_SMS: */ +/* XP_MEMCPY( &mainParams.connInfo.sms.myPhone, sms-phone */ +/* const char* serverPhone; */ +/* int port; */ + + +/* break; */ +/* #endif */ default: break; } diff --git a/xwords4/linux/linuxmain.h b/xwords4/linux/linuxmain.h index c557c6df7..71a5b184c 100644 --- a/xwords4/linux/linuxmain.h +++ b/xwords4/linux/linuxmain.h @@ -111,9 +111,11 @@ const XP_U32 linux_getDevIDRelay( LaunchParams* params ); const XP_UCHAR* linux_getDevID( LaunchParams* params, DevIDType* typ ); void linux_doInitialReg( LaunchParams* params, XP_Bool idIsNew ); XP_Bool linux_setupDevidParams( LaunchParams* params ); +XP_Bool parseSMSParams( LaunchParams* params, gchar** myPhone, XP_U16* myPort ); unsigned int makeRandomInt(); -bool linuxOpenGame( CommonGlobals* cGlobals, const TransportProcs* procs ); +bool linuxOpenGame( CommonGlobals* cGlobals, const TransportProcs* procs, + const CurGameInfo* gi, const CommsAddrRec* addrP ); void tryConnectToServer( CommonGlobals* cGlobals ); /* void initParams( LaunchParams* params ); */ diff --git a/xwords4/linux/main.h b/xwords4/linux/main.h index 74f01fc73..cd5be1b0b 100644 --- a/xwords4/linux/main.h +++ b/xwords4/linux/main.h @@ -156,7 +156,7 @@ typedef struct LaunchParams { #ifdef XWFEATURE_SMS struct { const char* myPhone; - const char* serverPhone; + const char* inviteePhone; int port; } sms; #endif