mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-29 08:34:37 +01:00
get rematch working on linux, at least for two-device games. (Handling
the case where one of several guests wants to rematch is a hard problem for later.) Requires passing old-style relayIDs (connname plus device index) when devIDs aren't available, which they may not always be.
This commit is contained in:
parent
fd06bca151
commit
0f33228155
22 changed files with 484 additions and 185 deletions
|
@ -560,6 +560,7 @@ comms_setConnID( CommsCtxt* comms, XP_U32 connID )
|
|||
static void
|
||||
addrFromStreamOne( CommsAddrRec* addrP, XWStreamCtxt* stream, CommsConnType typ )
|
||||
{
|
||||
XP_U16 version = stream_getVersion( stream );
|
||||
switch( typ ) {
|
||||
case COMMS_CONN_NONE:
|
||||
break;
|
||||
|
@ -584,8 +585,11 @@ addrFromStreamOne( CommsAddrRec* addrP, XWStreamCtxt* stream, CommsConnType typ
|
|||
stringFromStreamHere( stream, addrP->u.ip_relay.hostName,
|
||||
sizeof(addrP->u.ip_relay.hostName) );
|
||||
addrP->u.ip_relay.ipAddr = stream_getU32( stream );
|
||||
if ( version >= STREAM_VERS_DEVIDS ) {
|
||||
addrP->u.ip_relay.devID = stream_getU32( stream );
|
||||
}
|
||||
addrP->u.ip_relay.port = stream_getU16( stream );
|
||||
if ( stream_getVersion( stream ) >= STREAM_VERS_DICTLANG ) {
|
||||
if ( version >= STREAM_VERS_DICTLANG ) {
|
||||
addrP->u.ip_relay.seeksPublicRoom = stream_getBits( stream, 1 );
|
||||
addrP->u.ip_relay.advertiseRoom = stream_getBits( stream, 1 );
|
||||
}
|
||||
|
@ -632,7 +636,8 @@ comms_makeFromStream( MPFORMAL XWStreamCtxt* stream, XW_UtilCtxt* util,
|
|||
isServer = stream_getU8( stream );
|
||||
addrFromStream( &addr, stream );
|
||||
|
||||
if ( addr_hasType( &addr, COMMS_CONN_RELAY ) ) {
|
||||
if ( version >= STREAM_VERS_DEVIDS
|
||||
|| addr_hasType( &addr, COMMS_CONN_RELAY ) ) {
|
||||
nPlayersHere = (XP_U16)stream_getBits( stream, 4 );
|
||||
nPlayersTotal = (XP_U16)stream_getBits( stream, 4 );
|
||||
} else {
|
||||
|
@ -810,6 +815,7 @@ addrToStreamOne( XWStreamCtxt* stream, CommsConnType typ, const CommsAddrRec* ad
|
|||
stringToStream( stream, addrP->u.ip_relay.invite );
|
||||
stringToStream( stream, addrP->u.ip_relay.hostName );
|
||||
stream_putU32( stream, addrP->u.ip_relay.ipAddr );
|
||||
stream_putU32( stream, addrP->u.ip_relay.devID );
|
||||
stream_putU16( stream, addrP->u.ip_relay.port );
|
||||
stream_putBits( stream, 1, addrP->u.ip_relay.seeksPublicRoom );
|
||||
stream_putBits( stream, 1, addrP->u.ip_relay.advertiseRoom );
|
||||
|
@ -827,6 +833,7 @@ addrToStreamOne( XWStreamCtxt* stream, CommsConnType typ, const CommsAddrRec* ad
|
|||
void
|
||||
addrToStream( XWStreamCtxt* stream, const CommsAddrRec* addrP )
|
||||
{
|
||||
stream_setVersion( stream, CUR_STREAM_VERS );
|
||||
stream_putU8( stream, addrP->_conTypes );
|
||||
|
||||
CommsConnType typ;
|
||||
|
@ -843,13 +850,13 @@ comms_writeToStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
|||
AddressRecord* rec;
|
||||
MsgQueueElem* msg;
|
||||
|
||||
stream_setVersion( stream, CUR_STREAM_VERS );
|
||||
|
||||
stream_putU8( stream, (XP_U8)comms->isServer );
|
||||
logAddr( comms, &comms->addr, __func__ );
|
||||
addrToStream( stream, &comms->addr );
|
||||
if ( addr_hasType( &comms->addr, COMMS_CONN_RELAY ) ) {
|
||||
stream_putBits( stream, 4, comms->rr.nPlayersHere );
|
||||
stream_putBits( stream, 4, comms->rr.nPlayersTotal );
|
||||
}
|
||||
stream_putBits( stream, 4, comms->rr.nPlayersHere );
|
||||
stream_putBits( stream, 4, comms->rr.nPlayersTotal );
|
||||
|
||||
stream_putU32( stream, comms->connID );
|
||||
stream_putU16( stream, comms->nextChannelNo );
|
||||
|
@ -982,6 +989,20 @@ formatRelayID( const CommsCtxt* comms, XWHostID hostID,
|
|||
return XP_TRUE;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
comms_formatRelayID( const CommsCtxt* comms, XP_U16 indx,
|
||||
XP_UCHAR* buf, XP_U16* lenp )
|
||||
{
|
||||
XP_LOGF( "%s(indx=%d)", __func__, indx );
|
||||
XWHostID hostID = HOST_ID_SERVER;
|
||||
if ( comms->isServer ) {
|
||||
hostID += 1 + indx;
|
||||
}
|
||||
XP_Bool success = formatRelayID( comms, hostID, buf, lenp );
|
||||
XP_LOGF( "%s(%d) => %s", __func__, indx, buf );
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Get *my* "relayID", a combo of connname and host id */
|
||||
XP_Bool
|
||||
comms_getRelayID( const CommsCtxt* comms, XP_UCHAR* buf, XP_U16* lenp )
|
||||
|
@ -997,12 +1018,14 @@ comms_getInitialAddr( CommsAddrRec* addr
|
|||
#ifdef XWFEATURE_RELAY
|
||||
, const XP_UCHAR* relayName
|
||||
, XP_U16 relayPort
|
||||
, XP_U32 devID
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if defined XWFEATURE_RELAY
|
||||
addr_setType( addr, COMMS_CONN_RELAY ); /* for temporary ease in debugging */
|
||||
addr->u.ip_relay.ipAddr = 0L; /* force 'em to set it */
|
||||
addr->u.ip_relay.devID = devID;
|
||||
addr->u.ip_relay.port = relayPort;
|
||||
{
|
||||
const char* name = relayName;
|
||||
|
@ -1051,7 +1074,7 @@ comms_getConTypes( const CommsCtxt* comms )
|
|||
XP_LOGF( "%s: returning COMMS_CONN_NONE for null comms", __func__ );
|
||||
}
|
||||
return typ;
|
||||
} /* comms_getConType */
|
||||
} /* comms_getConTypes */
|
||||
|
||||
XP_Bool
|
||||
comms_getIsServer( const CommsCtxt* comms )
|
||||
|
@ -2629,14 +2652,8 @@ augmentChannelAddr( CommsCtxt* comms, AddressRecord * const rec,
|
|||
switch( typ ) {
|
||||
case COMMS_CONN_RELAY:
|
||||
dest = &rec->addr.u.ip_relay;
|
||||
src = &addr->u.ip_relay;
|
||||
siz = sizeof( rec->addr.u.ip_relay );
|
||||
/* Special case for relay: use comms' relay info if caller
|
||||
didn't bother to fill it in */
|
||||
if ( addr->u.ip_relay.invite[0] ) {
|
||||
src = &addr->u.ip_relay;
|
||||
} else {
|
||||
src = &comms->addr.u.ip_relay;
|
||||
}
|
||||
if ( 0 != hostID ) {
|
||||
rec->rr.hostID = hostID;
|
||||
XP_LOGF( "%s: set hostID for rec %p to %d", __func__, rec, hostID );
|
||||
|
|
|
@ -90,6 +90,7 @@ typedef struct _CommsAddrRec {
|
|||
XP_UCHAR invite[MAX_INVITE_LEN + 1];
|
||||
XP_UCHAR hostName[MAX_HOSTNAME_LEN + 1];
|
||||
XP_U32 ipAddr; /* looked up from above */
|
||||
XP_U32 devID;
|
||||
XP_U16 port;
|
||||
XP_Bool seeksPublicRoom;
|
||||
XP_Bool advertiseRoom;
|
||||
|
@ -180,6 +181,7 @@ void comms_getInitialAddr( CommsAddrRec* addr
|
|||
#ifdef XWFEATURE_RELAY
|
||||
, const XP_UCHAR* relayName
|
||||
, XP_U16 relayPort
|
||||
, XP_U32 devID
|
||||
#endif
|
||||
);
|
||||
XP_Bool comms_checkAddr( DeviceRole role, const CommsAddrRec* addr,
|
||||
|
@ -189,6 +191,9 @@ void comms_getAddr( const CommsCtxt* comms, CommsAddrRec* addr );
|
|||
void comms_setAddr( CommsCtxt* comms, const CommsAddrRec* addr );
|
||||
void comms_getAddrs( const CommsCtxt* comms, CommsAddrRec addr[],
|
||||
XP_U16* nRecs );
|
||||
XP_Bool comms_formatRelayID( const CommsCtxt* comms, XP_U16 indx,
|
||||
XP_UCHAR* buf, XP_U16* lenp );
|
||||
|
||||
XP_U16 comms_countPendingPackets( const CommsCtxt* comms );
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#endif
|
||||
#define MAX_COLS MAX_ROWS
|
||||
|
||||
#define STREAM_VERS_DEVIDS 0x19
|
||||
#define STREAM_VERS_MULTIADDR 0x18
|
||||
#define STREAM_VERS_MODELDIVIDER 0x17
|
||||
#define STREAM_VERS_COMMSBACKOFF 0x16
|
||||
|
@ -86,7 +87,7 @@
|
|||
#define STREAM_VERS_405 0x01
|
||||
|
||||
/* search for FIX_NEXT_VERSION_CHANGE next time this is changed */
|
||||
#define CUR_STREAM_VERS STREAM_VERS_MULTIADDR
|
||||
#define CUR_STREAM_VERS STREAM_VERS_DEVIDS
|
||||
|
||||
typedef struct XP_Rect {
|
||||
XP_S16 left;
|
||||
|
|
|
@ -49,7 +49,8 @@ static void gi_setDict( MPFORMAL CurGameInfo* gi, const DictionaryCtxt* dict );
|
|||
#endif
|
||||
|
||||
static void
|
||||
checkServerRole( CurGameInfo* gi, XP_U16* nPlayersHere, XP_U16* nPlayersTotal )
|
||||
checkServerRole( CurGameInfo* gi, XP_U16* nPlayersHere,
|
||||
XP_U16* nPlayersTotal )
|
||||
{
|
||||
if ( !!gi ) {
|
||||
XP_U16 ii, remoteCount = 0;
|
||||
|
@ -87,7 +88,7 @@ makeGameID( XW_UtilCtxt* util )
|
|||
void
|
||||
game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||
XW_UtilCtxt* util, DrawCtx* draw,
|
||||
CommonPrefs* cp, const TransportProcs* procs
|
||||
const CommonPrefs* cp, const TransportProcs* procs
|
||||
#ifdef SET_GAMESEED
|
||||
,XP_U16 gameSeed
|
||||
#endif
|
||||
|
@ -280,6 +281,25 @@ game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
|||
return success;
|
||||
} /* game_makeFromStream */
|
||||
|
||||
void
|
||||
game_saveNewGame( MPFORMAL const CurGameInfo* gi, XW_UtilCtxt* util,
|
||||
const CommonPrefs* cp, XWStreamCtxt* out )
|
||||
{
|
||||
XWGame newGame = {0};
|
||||
CurGameInfo newGI = {0};
|
||||
gi_copy( MPPARM(mpool) &newGI, gi );
|
||||
|
||||
game_makeNewGame( MPPARM(mpool) &newGame, &newGI, util,
|
||||
NULL, /* DrawCtx*, */
|
||||
cp, NULL, /* TransportProcs* procs */
|
||||
0 );
|
||||
|
||||
game_saveToStream( &newGame, &newGI, out, 1 );
|
||||
game_saveSucceeded( &newGame, 1 );
|
||||
game_dispose( &newGame );
|
||||
gi_disposePlayerInfo( MPPARM(mpool) &newGI );
|
||||
}
|
||||
|
||||
void
|
||||
game_saveToStream( const XWGame* game, const CurGameInfo* gi,
|
||||
XWStreamCtxt* stream, XP_U16 saveToken )
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef struct XWGame {
|
|||
|
||||
void game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||
XW_UtilCtxt* util, DrawCtx* draw,
|
||||
CommonPrefs* cp, const TransportProcs* procs
|
||||
const CommonPrefs* cp, const TransportProcs* procs
|
||||
#ifdef SET_GAMESEED
|
||||
,XP_U16 gameSeed
|
||||
#endif
|
||||
|
@ -76,6 +76,9 @@ XP_Bool game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
|||
DrawCtx* draw, CommonPrefs* cp,
|
||||
const TransportProcs* procs );
|
||||
|
||||
void game_saveNewGame( MPFORMAL const CurGameInfo* gi, XW_UtilCtxt* util,
|
||||
const CommonPrefs* cp, XWStreamCtxt* out );
|
||||
|
||||
void game_saveToStream( const XWGame* game, const CurGameInfo* gi,
|
||||
XWStreamCtxt* stream, XP_U16 saveToken );
|
||||
void game_saveSucceeded( const XWGame* game, XP_U16 saveToken );
|
||||
|
|
|
@ -55,6 +55,7 @@ void
|
|||
invit_setDevID( InviteInfo* invit, XP_U32 devID )
|
||||
{
|
||||
invit->devID = devID;
|
||||
types_addType( &invit->_conTypes, COMMS_CONN_RELAY );
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -30,6 +30,12 @@
|
|||
|
||||
typedef enum {OSType_NONE, OSType_LINUX, OSType_ANDROID, } XP_OSType;
|
||||
|
||||
/* InviteInfo
|
||||
*
|
||||
* A representation of return addresses sent with an invitation so that the
|
||||
* recipient has all it needs to create a game and connect back.
|
||||
*/
|
||||
|
||||
typedef struct _InviteInfo {
|
||||
XP_U8 version; /* struct version for backward compatibility */
|
||||
XP_U16 _conTypes;
|
||||
|
|
|
@ -25,6 +25,7 @@ static void getColumnText( sqlite3_stmt *ppStmt, int iCol, XP_UCHAR* buf,
|
|||
int len );
|
||||
#ifdef DEBUG
|
||||
static char* sqliteErr2str( int err );
|
||||
static void assertPrintResult( sqlite3* pDb, int result, int expect );
|
||||
#endif
|
||||
|
||||
sqlite3*
|
||||
|
@ -41,6 +42,7 @@ openGamesDB( const char* dbName )
|
|||
"CREATE TABLE games ( "
|
||||
"rowid INTEGER PRIMARY KEY AUTOINCREMENT"
|
||||
",game BLOB"
|
||||
",inviteInfo BLOB"
|
||||
",room VARCHAR(32)"
|
||||
",connvia VARCHAR(32)"
|
||||
",ended INT(1)"
|
||||
|
@ -48,6 +50,7 @@ openGamesDB( const char* dbName )
|
|||
",nmoves INT"
|
||||
",seed INT"
|
||||
",gameid INT"
|
||||
",ntotal INT(2)"
|
||||
",nmissing INT(2)"
|
||||
")";
|
||||
result = sqlite3_exec( pDb, createGamesStr, NULL, NULL, NULL );
|
||||
|
@ -68,31 +71,32 @@ closeGamesDB( sqlite3* pDb )
|
|||
XP_LOGF( "%s finished", __func__ );
|
||||
}
|
||||
|
||||
void
|
||||
writeToDB( XWStreamCtxt* stream, void* closure )
|
||||
static sqlite3_int64
|
||||
writeBlobColumn( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 curRow,
|
||||
const char* column )
|
||||
{
|
||||
int result;
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)closure;
|
||||
sqlite3_int64 selRow = cGlobals->selRow;
|
||||
sqlite3* pDb = cGlobals->pDb;
|
||||
/* size includes stream version as header */
|
||||
XP_U16 len = stream_getSize( stream );
|
||||
char buf[256];
|
||||
char* query;
|
||||
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
XP_Bool newGame = -1 == selRow;
|
||||
XP_Bool newGame = -1 == curRow;
|
||||
if ( newGame ) { /* new row; need to insert blob first */
|
||||
query = "INSERT INTO games (game) VALUES (?)";
|
||||
const char* fmt = "INSERT INTO games (%s) VALUES (?)";
|
||||
snprintf( buf, sizeof(buf), fmt, column );
|
||||
query = buf;
|
||||
} else {
|
||||
const char* fmt = "UPDATE games SET game=? where rowid=%lld";
|
||||
snprintf( buf, sizeof(buf), fmt, selRow );
|
||||
const char* fmt = "UPDATE games SET %s=? where rowid=%lld";
|
||||
snprintf( buf, sizeof(buf), fmt, column, curRow );
|
||||
query = buf;
|
||||
}
|
||||
|
||||
result = sqlite3_prepare_v2( pDb, query, -1, &stmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
result = sqlite3_bind_zeroblob( stmt, 1 /*col 0 ??*/, len );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
result = sqlite3_prepare_v2( pDb, query, -1, &stmt, NULL );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_bind_zeroblob( stmt, 1 /*col 0 ??*/, sizeof(XP_U16) + len );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_step( stmt );
|
||||
if ( SQLITE_DONE != result ) {
|
||||
XP_LOGF( "%s: sqlite3_step => %s", __func__, sqliteErr2str( result ) );
|
||||
|
@ -101,24 +105,51 @@ writeToDB( XWStreamCtxt* stream, void* closure )
|
|||
XP_USE( result );
|
||||
|
||||
if ( newGame ) { /* new row; need to insert blob first */
|
||||
selRow = sqlite3_last_insert_rowid( pDb );
|
||||
XP_LOGF( "%s: new rowid: %lld", __func__, selRow );
|
||||
cGlobals->selRow = selRow;
|
||||
curRow = sqlite3_last_insert_rowid( pDb );
|
||||
XP_LOGF( "%s: new rowid: %lld", __func__, curRow );
|
||||
}
|
||||
|
||||
sqlite3_blob* blob;
|
||||
result = sqlite3_blob_open( pDb, "main", "games", "game",
|
||||
selRow, 1 /*flags: writeable*/, &blob );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
result = sqlite3_blob_open( pDb, "main", "games", column,
|
||||
curRow, 1 /*flags: writeable*/, &blob );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
XP_U16 strVersion = stream_getVersion( stream );
|
||||
XP_ASSERT( strVersion <= CUR_STREAM_VERS );
|
||||
result = sqlite3_blob_write( blob, &strVersion, sizeof(strVersion), 0 );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
const XP_U8* ptr = stream_getPtr( stream );
|
||||
result = sqlite3_blob_write( blob, ptr, len, 0 );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
result = sqlite3_blob_write( blob, ptr, len, sizeof(strVersion) );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_blob_close( blob );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
if ( !!stmt ) {
|
||||
sqlite3_finalize( stmt );
|
||||
}
|
||||
|
||||
return curRow;
|
||||
}
|
||||
|
||||
sqlite3_int64
|
||||
writeNewGameToDB( XWStreamCtxt* stream, sqlite3* pDb )
|
||||
{
|
||||
sqlite3_int64 newRow = writeBlobColumn( stream, pDb, -1, "game" );
|
||||
return newRow;
|
||||
}
|
||||
|
||||
void
|
||||
writeToDB( XWStreamCtxt* stream, void* closure )
|
||||
{
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)closure;
|
||||
sqlite3_int64 selRow = cGlobals->selRow;
|
||||
sqlite3* pDb = cGlobals->pDb;
|
||||
|
||||
XP_Bool newGame = -1 == selRow;
|
||||
selRow = writeBlobColumn( stream, pDb, selRow, "game" );
|
||||
|
||||
if ( newGame ) { /* new row; need to insert blob first */
|
||||
cGlobals->selRow = selRow;
|
||||
}
|
||||
|
||||
(*cGlobals->onSave)( cGlobals->onSaveClosure, selRow, newGame );
|
||||
}
|
||||
|
||||
|
@ -130,6 +161,7 @@ summarize( CommonGlobals* cGlobals )
|
|||
XP_S16 turn = server_getCurrentTurn( cGlobals->game.server );
|
||||
XP_U16 seed = 0;
|
||||
XP_S16 nMissing = 0;
|
||||
XP_U16 nTotal = cGlobals->gi->nPlayers;
|
||||
XP_U32 gameID = cGlobals->gi->gameID;
|
||||
XP_ASSERT( 0 != gameID );
|
||||
CommsAddrRec addr = {0};
|
||||
|
@ -171,15 +203,15 @@ summarize( CommonGlobals* cGlobals )
|
|||
}
|
||||
|
||||
const char* fmt = "UPDATE games "
|
||||
" SET room='%s', ended=%d, turn=%d, nmissing=%d, nmoves=%d, seed=%d, gameid=%d, connvia='%s'"
|
||||
" SET room='%s', ended=%d, turn=%d, ntotal=%d, nmissing=%d, nmoves=%d, seed=%d, gameid=%d, connvia='%s'"
|
||||
" WHERE rowid=%lld";
|
||||
XP_UCHAR buf[256];
|
||||
snprintf( buf, sizeof(buf), fmt, room, gameOver?1:0, turn, nMissing, nMoves,
|
||||
seed, gameID, connvia, cGlobals->selRow );
|
||||
snprintf( buf, sizeof(buf), fmt, room, gameOver?1:0, turn, nTotal, nMissing,
|
||||
nMoves, seed, gameID, connvia, cGlobals->selRow );
|
||||
XP_LOGF( "query: %s", buf );
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
int result = sqlite3_prepare_v2( cGlobals->pDb, buf, -1, &stmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( cGlobals->pDb, result, SQLITE_OK );
|
||||
result = sqlite3_step( stmt );
|
||||
if ( SQLITE_DONE != result ) {
|
||||
XP_LOGF( "sqlite3_step=>%s", sqliteErr2str( result ) );
|
||||
|
@ -198,7 +230,7 @@ listGames( sqlite3* pDb )
|
|||
int result = sqlite3_prepare_v2( pDb,
|
||||
"SELECT rowid FROM games ORDER BY rowid",
|
||||
-1, &ppStmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
XP_USE( result );
|
||||
while ( NULL != ppStmt ) {
|
||||
switch( sqlite3_step( ppStmt ) ) {
|
||||
|
@ -226,14 +258,15 @@ XP_Bool
|
|||
getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
|
||||
{
|
||||
XP_Bool success = XP_FALSE;
|
||||
const char* fmt = "SELECT room, ended, turn, nmoves, nmissing, seed, connvia, gameid "
|
||||
const char* fmt = "SELECT room, ended, turn, nmoves, ntotal, nmissing, "
|
||||
"seed, connvia, gameid "
|
||||
"FROM games WHERE rowid = %lld";
|
||||
XP_UCHAR query[256];
|
||||
snprintf( query, sizeof(query), fmt, rowid );
|
||||
|
||||
sqlite3_stmt* ppStmt;
|
||||
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_step( ppStmt );
|
||||
if ( SQLITE_ROW == result ) {
|
||||
success = XP_TRUE;
|
||||
|
@ -241,10 +274,11 @@ getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
|
|||
gib->gameOver = 1 == sqlite3_column_int( ppStmt, 1 );
|
||||
gib->turn = sqlite3_column_int( ppStmt, 2 );
|
||||
gib->nMoves = sqlite3_column_int( ppStmt, 3 );
|
||||
gib->nMissing = sqlite3_column_int( ppStmt, 4 );
|
||||
gib->seed = sqlite3_column_int( ppStmt, 5 );
|
||||
getColumnText( ppStmt, 6, gib->conn, sizeof(gib->conn) );
|
||||
gib->gameID = sqlite3_column_int( ppStmt, 7 );
|
||||
gib->nTotal = sqlite3_column_int( ppStmt, 4 );
|
||||
gib->nMissing = sqlite3_column_int( ppStmt, 5 );
|
||||
gib->seed = sqlite3_column_int( ppStmt, 6 );
|
||||
getColumnText( ppStmt, 7, gib->conn, sizeof(gib->conn) );
|
||||
gib->gameID = sqlite3_column_int( ppStmt, 8 );
|
||||
snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid );
|
||||
}
|
||||
sqlite3_finalize( ppStmt );
|
||||
|
@ -259,11 +293,11 @@ getRowsForGameID( sqlite3* pDb, XP_U32 gameID, sqlite3_int64* rowids,
|
|||
*nRowIDs = 0;
|
||||
|
||||
char buf[256];
|
||||
snprintf( buf, sizeof(buf), "SELECT rowid from games WHERE gameid = %d LIMIT %d",
|
||||
gameID, maxRowIDs );
|
||||
snprintf( buf, sizeof(buf), "SELECT rowid from games WHERE gameid = %d "
|
||||
"LIMIT %d", gameID, maxRowIDs );
|
||||
sqlite3_stmt *ppStmt;
|
||||
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
int ii;
|
||||
for ( ii = 0; ii < maxRowIDs; ++ii ) {
|
||||
result = sqlite3_step( ppStmt );
|
||||
|
@ -276,26 +310,56 @@ getRowsForGameID( sqlite3* pDb, XP_U32 gameID, sqlite3_int64* rowids,
|
|||
sqlite3_finalize( ppStmt );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid )
|
||||
static XP_Bool
|
||||
loadBlobColumn( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid,
|
||||
const char* column )
|
||||
{
|
||||
char buf[256];
|
||||
snprintf( buf, sizeof(buf), "SELECT game from games WHERE rowid = %lld", rowid );
|
||||
snprintf( buf, sizeof(buf), "SELECT %s from games WHERE rowid = %lld",
|
||||
column, rowid );
|
||||
|
||||
sqlite3_stmt *ppStmt;
|
||||
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_step( ppStmt );
|
||||
XP_Bool success = SQLITE_ROW == result;
|
||||
if ( success ) {
|
||||
const void* ptr = sqlite3_column_blob( ppStmt, 0 );
|
||||
int size = sqlite3_column_bytes( ppStmt, 0 );
|
||||
stream_putBytes( stream, ptr, size );
|
||||
success = 0 < size;
|
||||
if ( success ) {
|
||||
XP_U16 strVersion;
|
||||
XP_MEMCPY( &strVersion, ptr, sizeof(strVersion) );
|
||||
XP_ASSERT( strVersion <= CUR_STREAM_VERS );
|
||||
stream_setVersion( stream, strVersion );
|
||||
XP_ASSERT( size >= sizeof(strVersion) );
|
||||
stream_putBytes( stream, ptr + sizeof(strVersion),
|
||||
size - sizeof(strVersion) );
|
||||
}
|
||||
}
|
||||
sqlite3_finalize( ppStmt );
|
||||
return success;
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid )
|
||||
{
|
||||
return loadBlobColumn( stream, pDb, rowid, "game" );
|
||||
}
|
||||
|
||||
void
|
||||
saveInviteAddrs( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid )
|
||||
{
|
||||
sqlite3_int64 row = writeBlobColumn( stream, pDb, rowid, "inviteInfo" );
|
||||
assert( row == rowid );
|
||||
}
|
||||
|
||||
XP_Bool
|
||||
loadInviteAddrs( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid )
|
||||
{
|
||||
return loadBlobColumn( stream, pDb, rowid, "inviteInfo" );
|
||||
}
|
||||
|
||||
void
|
||||
deleteGame( sqlite3* pDb, sqlite3_int64 rowid )
|
||||
{
|
||||
|
@ -303,9 +367,9 @@ deleteGame( sqlite3* pDb, sqlite3_int64 rowid )
|
|||
snprintf( query, sizeof(query), "DELETE FROM games WHERE rowid = %lld", rowid );
|
||||
sqlite3_stmt* ppStmt;
|
||||
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_step( ppStmt );
|
||||
XP_ASSERT( SQLITE_DONE == result );
|
||||
assertPrintResult( pDb, result, SQLITE_DONE );
|
||||
XP_USE( result );
|
||||
sqlite3_finalize( ppStmt );
|
||||
}
|
||||
|
@ -319,9 +383,9 @@ db_store( sqlite3* pDb, const gchar* key, const gchar* value )
|
|||
key, value );
|
||||
sqlite3_stmt *ppStmt;
|
||||
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_step( ppStmt );
|
||||
XP_ASSERT( SQLITE_DONE == result );
|
||||
assertPrintResult( pDb, result, SQLITE_DONE );
|
||||
XP_USE( result );
|
||||
sqlite3_finalize( ppStmt );
|
||||
}
|
||||
|
@ -355,9 +419,9 @@ db_remove( sqlite3* pDb, const gchar* key )
|
|||
snprintf( query, sizeof(query), "DELETE FROM pairs WHERE key = '%s'", key );
|
||||
sqlite3_stmt *ppStmt;
|
||||
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
||||
XP_ASSERT( SQLITE_OK == result );
|
||||
assertPrintResult( pDb, result, SQLITE_OK );
|
||||
result = sqlite3_step( ppStmt );
|
||||
XP_ASSERT( SQLITE_DONE == result );
|
||||
assertPrintResult( pDb, result, SQLITE_DONE );
|
||||
XP_USE( result );
|
||||
sqlite3_finalize( ppStmt );
|
||||
}
|
||||
|
@ -413,4 +477,17 @@ sqliteErr2str( int err )
|
|||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
static void
|
||||
assertPrintResult( sqlite3* pDb, int result, int expect )
|
||||
{
|
||||
int code = sqlite3_errcode( pDb );
|
||||
XP_ASSERT( code == result ); /* do I need to pass it? */
|
||||
if ( code != expect ) {
|
||||
const char* msg = sqlite3_errmsg( pDb );
|
||||
XP_LOGF( "sqlite3 error: %s", msg );
|
||||
XP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,7 @@ typedef struct _GameInfo {
|
|||
XP_S16 nMoves;
|
||||
XP_Bool gameOver;
|
||||
XP_S16 turn;
|
||||
XP_U16 nTotal;
|
||||
XP_S16 nMissing;
|
||||
XP_U16 seed;
|
||||
} GameInfo;
|
||||
|
@ -44,6 +45,8 @@ sqlite3* openGamesDB( const char* dbName );
|
|||
void closeGamesDB( sqlite3* dbp );
|
||||
|
||||
void writeToDB( XWStreamCtxt* stream, void* closure );
|
||||
sqlite3_int64 writeNewGameToDB( XWStreamCtxt* stream, sqlite3* pDb );
|
||||
|
||||
void summarize( CommonGlobals* cGlobals );
|
||||
|
||||
/* Return GSList whose data is (ptrs to) rowids */
|
||||
|
@ -52,6 +55,10 @@ XP_Bool getGameInfo( sqlite3* dbp, sqlite3_int64 rowid, GameInfo* gib );
|
|||
void getRowsForGameID( sqlite3* dbp, XP_U32 gameID, sqlite3_int64* rowids,
|
||||
int* nRowIDs );
|
||||
XP_Bool loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid );
|
||||
void saveInviteAddrs( XWStreamCtxt* stream, sqlite3* pDb,
|
||||
sqlite3_int64 rowid );
|
||||
XP_Bool loadInviteAddrs( XWStreamCtxt* stream, sqlite3* pDb,
|
||||
sqlite3_int64 rowid );
|
||||
void deleteGame( sqlite3* pDb, sqlite3_int64 rowid );
|
||||
|
||||
#define KEY_RDEVID "RDEVID"
|
||||
|
|
|
@ -77,8 +77,8 @@ gtkaskm( const gchar* message, AskMInfo* infos, int nInfos )
|
|||
for ( ii = 0; ii < nInfos; ++ii ) {
|
||||
AskMInfo* info = &infos[ii];
|
||||
if ( !state.cancelled ) {
|
||||
const gchar* txt = gtk_entry_get_text( GTK_ENTRY(fields[ii]) );
|
||||
XP_LOGF( "%s: got text %s", __func__, txt );
|
||||
XP_LOGF( "%s: got text %s", __func__,
|
||||
gtk_entry_get_text( GTK_ENTRY(fields[ii]) ) );
|
||||
} else {
|
||||
*info->result = NULL;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "draw.h"
|
||||
#include "game.h"
|
||||
#include "movestak.h"
|
||||
#include "strutils.h"
|
||||
#include "gtkask.h"
|
||||
#include "gtkinvit.h"
|
||||
#include "gtkaskm.h"
|
||||
|
@ -82,6 +83,10 @@ static GtkWidget* addButton( GtkWidget* hbox, gchar* label, GCallback func,
|
|||
static void handle_invite_button( GtkWidget* widget, GtkGameGlobals* globals );
|
||||
static void gtkShowFinalScores( const GtkGameGlobals* globals,
|
||||
XP_Bool ignoreTimeout );
|
||||
static void send_invites( CommonGlobals* cGlobals,
|
||||
const CommsAddrRec* inviteAddr,
|
||||
const XP_UCHAR* relayID,
|
||||
XP_U16 nPlayers );
|
||||
|
||||
#define GTK_TRAY_HT_ROWS 3
|
||||
|
||||
|
@ -103,7 +108,7 @@ lookupClientStream( GtkGameGlobals* globals, int sock )
|
|||
|
||||
static void
|
||||
rememberClient( GtkGameGlobals* globals, guint key, int sock,
|
||||
XWStreamCtxt* stream )
|
||||
XWStreamCtxt* stream )
|
||||
{
|
||||
short i;
|
||||
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
|
||||
|
@ -868,10 +873,39 @@ destroy_board_window( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
|||
static void
|
||||
on_board_window_shown( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||
{
|
||||
if ( server_getGameIsOver( globals->cGlobals.game.server ) ) {
|
||||
LOG_FUNC();
|
||||
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||
if ( server_getGameIsOver( cGlobals->game.server ) ) {
|
||||
gtkShowFinalScores( globals, XP_TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
CommsCtxt* comms = cGlobals->game.comms;
|
||||
if ( !!comms /*&& COMMS_CONN_NONE == comms_getConTypes( comms )*/ ) {
|
||||
/* If it has pending invite info, send the invitation! */
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
||||
cGlobals->params->vtMgr,
|
||||
cGlobals, CHANNEL_NONE, NULL );
|
||||
if ( loadInviteAddrs( stream, cGlobals->pDb, cGlobals->selRow ) ) {
|
||||
CommsAddrRec addr = {0};
|
||||
addrFromStream( &addr, stream );
|
||||
comms_setAddr( cGlobals->game.comms, &addr );
|
||||
|
||||
XP_U16 nRecs = stream_getU8( stream );
|
||||
XP_LOGF( "%s: got invite info: %d records", __func__, nRecs );
|
||||
for ( int ii = 0; ii < nRecs; ++ii ) {
|
||||
XP_UCHAR relayID[32];
|
||||
stringFromStreamHere( stream, relayID, sizeof(relayID) );
|
||||
XP_LOGF( "%s: loaded relayID %s", __func__, relayID );
|
||||
|
||||
CommsAddrRec addr = {0};
|
||||
addrFromStream( &addr, stream );
|
||||
|
||||
send_invites( cGlobals, &addr, relayID, 1 /*nPlayers*/ );
|
||||
}
|
||||
}
|
||||
stream_destroy( stream );
|
||||
}
|
||||
} /* on_board_window_shown */
|
||||
|
||||
static void
|
||||
cleanup( GtkGameGlobals* globals )
|
||||
|
@ -986,7 +1020,9 @@ new_game_impl( GtkGameGlobals* globals, XP_Bool fireConnDlg )
|
|||
if ( !!cGlobals->game.comms ) {
|
||||
comms_getAddr( cGlobals->game.comms, &addr );
|
||||
} else {
|
||||
comms_getInitialAddr( &addr, RELAY_NAME_DEFAULT, RELAY_PORT_DEFAULT );
|
||||
XP_U32 devID = linux_getDevIDRelay( cGlobals->params );
|
||||
comms_getInitialAddr( &addr, RELAY_NAME_DEFAULT, RELAY_PORT_DEFAULT,
|
||||
devID );
|
||||
}
|
||||
|
||||
CurGameInfo* gi = cGlobals->gi;
|
||||
|
@ -1572,7 +1608,7 @@ static void
|
|||
handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||
{
|
||||
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||
const CurGameInfo* gi = cGlobals->gi;
|
||||
/* const CurGameInfo* gi = cGlobals->gi; */
|
||||
|
||||
/* gchar* countStr; */
|
||||
/* gchar* phone = NULL; */
|
||||
|
@ -1595,46 +1631,52 @@ handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
|||
|
||||
CommsAddrRec inviteAddr = {0};
|
||||
gint nPlayers = nMissing;
|
||||
XP_U32 devID;
|
||||
XP_Bool confirmed = gtkInviteDlg( globals, &inviteAddr, &nPlayers, &devID );
|
||||
XP_Bool confirmed = gtkInviteDlg( globals, &inviteAddr, &nPlayers );
|
||||
XP_LOGF( "%s: inviteDlg => %d", __func__, confirmed );
|
||||
|
||||
if ( confirmed ) {
|
||||
gchar gameName[64];
|
||||
snprintf( gameName, VSIZE(gameName), "Game %d", gi->gameID );
|
||||
send_invites( cGlobals, &inviteAddr, NULL, nPlayers );
|
||||
}
|
||||
} /* handle_invite_button */
|
||||
|
||||
CommsAddrRec addr;
|
||||
CommsCtxt* comms = cGlobals->game.comms;
|
||||
XP_ASSERT( comms );
|
||||
comms_getAddr( comms, &addr );
|
||||
static void
|
||||
send_invites( CommonGlobals* cGlobals, const CommsAddrRec* inviteAddr,
|
||||
const XP_UCHAR* relayID, XP_U16 nPlayers )
|
||||
{
|
||||
CommsAddrRec addr = {0};
|
||||
CommsCtxt* comms = cGlobals->game.comms;
|
||||
XP_ASSERT( comms );
|
||||
comms_getAddr( comms, &addr );
|
||||
|
||||
gint forceChannel = 0; /* PENDING */
|
||||
gint forceChannel = 0; /* PENDING */
|
||||
|
||||
InviteInfo invit = {0};
|
||||
invit_init( &invit, gi, &addr, nPlayers, forceChannel );
|
||||
invit_setDevID( &invit, linux_getDevIDRelay( cGlobals->params ) );
|
||||
InviteInfo invit = {0};
|
||||
invit_init( &invit, cGlobals->gi, &addr, nPlayers, forceChannel );
|
||||
invit_setDevID( &invit, linux_getDevIDRelay( cGlobals->params ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
||||
cGlobals->params->vtMgr,
|
||||
NULL, CHANNEL_NONE, NULL );
|
||||
invit_saveToStream( &invit, stream );
|
||||
InviteInfo tmp;
|
||||
invit_makeFromStream( &tmp, stream );
|
||||
stream_destroy( stream );
|
||||
XP_ASSERT( 0 == memcmp( &invit, &tmp, sizeof(invit) ) );
|
||||
}
|
||||
{
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
||||
cGlobals->params->vtMgr,
|
||||
NULL, CHANNEL_NONE, NULL );
|
||||
invit_saveToStream( &invit, stream );
|
||||
InviteInfo tmp;
|
||||
invit_makeFromStream( &tmp, stream );
|
||||
stream_destroy( stream );
|
||||
XP_ASSERT( 0 == memcmp( &invit, &tmp, sizeof(invit) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( addr_hasType( &inviteAddr, COMMS_CONN_SMS ) ) {
|
||||
linux_sms_invite( cGlobals->params, gi, &addr, gameName,
|
||||
nPlayers, forceChannel,
|
||||
inviteAddr.u.sms.phone, inviteAddr.u.sms.port );
|
||||
}
|
||||
if ( addr_hasType( &addr, COMMS_CONN_RELAY ) ) {
|
||||
relaycon_invite( cGlobals->params, devID, &invit );
|
||||
}
|
||||
if ( addr_hasType( inviteAddr, COMMS_CONN_SMS ) ) {
|
||||
XP_ASSERT( 0 ); /* not implemented */
|
||||
/* linux_sms_invite( cGlobals->params, gi, &addr, gameName, */
|
||||
/* nPlayers, forceChannel, */
|
||||
/* inviteAddr.u.sms.phone, inviteAddr.u.sms.port ); */
|
||||
}
|
||||
if ( addr_hasType( inviteAddr, COMMS_CONN_RELAY ) ) {
|
||||
XP_U32 devID = inviteAddr->u.ip_relay.devID;
|
||||
XP_ASSERT( 0 != devID || (!!relayID && !!relayID[0]) );
|
||||
relaycon_invite( cGlobals->params, devID, relayID, &invit );
|
||||
}
|
||||
|
||||
/* while ( gtkaskm( "Invite how many and how?", infos, VSIZE(infos) ) ) { */
|
||||
|
@ -1673,7 +1715,7 @@ handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
|||
/* for ( int ii = 0; ii < VSIZE(infos); ++ii ) { */
|
||||
/* g_free( *infos[ii].result ); */
|
||||
/* } */
|
||||
} /* handle_invite_button */
|
||||
}
|
||||
|
||||
static void
|
||||
gtkUserError( GtkGameGlobals* globals, const char* format, ... )
|
||||
|
@ -1805,8 +1847,7 @@ gtkShowFinalScores( const GtkGameGlobals* globals, XP_Bool ignoreTimeout )
|
|||
buttons, timeout );
|
||||
free( text );
|
||||
if ( 2 == chosen ) {
|
||||
XP_LOGF( "%s: rematch chosen!", __func__ );
|
||||
XP_ASSERT( 0 );
|
||||
make_rematch( globals->apg, cGlobals );
|
||||
}
|
||||
} /* gtkShowFinalScores */
|
||||
|
||||
|
@ -1847,7 +1888,7 @@ gtk_util_notifyGameOver( XW_UtilCtxt* uc, XP_S16 quitter )
|
|||
server_handleUndo( cGlobals->game.server, 0 );
|
||||
board_draw( cGlobals->game.board );
|
||||
} else if ( !cGlobals->params->skipGameOver ) {
|
||||
gtkShowFinalScores( globals, XP_FALSE );
|
||||
gtkShowFinalScores( globals, XP_TRUE );
|
||||
}
|
||||
} /* gtk_util_notifyGameOver */
|
||||
|
||||
|
@ -2785,7 +2826,8 @@ makeNewGame( GtkGameGlobals* globals )
|
|||
if ( 0 == relayPort ) {
|
||||
relayPort = RELAY_PORT_DEFAULT;
|
||||
}
|
||||
comms_getInitialAddr( &cGlobals->addr, relayName, relayPort );
|
||||
comms_getInitialAddr( &cGlobals->addr, relayName, relayPort,
|
||||
linux_getDevIDRelay( cGlobals->params ) );
|
||||
}
|
||||
|
||||
CurGameInfo* gi = cGlobals->gi;
|
||||
|
|
|
@ -36,7 +36,6 @@ typedef struct _GtkInviteState {
|
|||
GtkGameGlobals* globals;
|
||||
CommsAddrRec* addr;
|
||||
gint* nPlayersP;
|
||||
XP_U32* devIDP;
|
||||
gint maxPlayers;
|
||||
XP_UCHAR devIDBuf[32];
|
||||
|
||||
|
@ -94,7 +93,7 @@ handle_ok( GtkWidget* XP_UNUSED(widget), gpointer closure )
|
|||
#ifdef XWFEATURE_RELAY
|
||||
case COMMS_CONN_RELAY:
|
||||
txt = gtk_entry_get_text( GTK_ENTRY(state->devID) );
|
||||
*(state->devIDP) = atoi( txt );
|
||||
state->addr->u.ip_relay.devID = atoi( txt );
|
||||
break;
|
||||
#endif
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
|
@ -276,17 +275,15 @@ onPageChanged( GtkNotebook* XP_UNUSED(notebook), gpointer XP_UNUSED(arg1),
|
|||
}
|
||||
|
||||
XP_Bool
|
||||
gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr, gint* nPlayers,
|
||||
XP_U32* devIDP )
|
||||
gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr, gint* nPlayersP )
|
||||
{
|
||||
GtkInviteState state;
|
||||
XP_MEMSET( &state, 0, sizeof(state) );
|
||||
|
||||
state.globals = globals;
|
||||
state.addr = addr;
|
||||
state.nPlayersP = nPlayers;
|
||||
state.maxPlayers = *nPlayers;
|
||||
state.devIDP = devIDP;
|
||||
state.nPlayersP = nPlayersP;
|
||||
state.maxPlayers = *nPlayersP;
|
||||
|
||||
GtkWidget* dialog;
|
||||
GtkWidget* hbox;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
/* return true if not cancelled */
|
||||
XP_Bool gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr,
|
||||
/*inout*/ gint* nPlayers, XP_U32* devID );
|
||||
/*inout*/ gint* nPlayers );
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
static void onNewData( GtkAppGlobals* apg, sqlite3_int64 rowid,
|
||||
XP_Bool isNew );
|
||||
static void updateButtons( GtkAppGlobals* apg );
|
||||
static void open_row( GtkAppGlobals* apg, sqlite3_int64 row );
|
||||
|
||||
static void
|
||||
recordOpened( GtkAppGlobals* apg, GtkGameGlobals* globals )
|
||||
|
@ -77,7 +76,7 @@ findOpenGame( const GtkAppGlobals* apg, sqlite3_int64 rowid )
|
|||
}
|
||||
|
||||
enum { ROW_ITEM, NAME_ITEM, ROOM_ITEM, GAMEID_ITEM, SEED_ITEM, CONN_ITEM, OVER_ITEM, TURN_ITEM,
|
||||
NMOVES_ITEM, MISSING_ITEM, N_ITEMS };
|
||||
NMOVES_ITEM, NTOTAL_ITEM, MISSING_ITEM, N_ITEMS };
|
||||
|
||||
static void
|
||||
foreachProc( GtkTreeModel* model, GtkTreePath* XP_UNUSED(path),
|
||||
|
@ -111,7 +110,7 @@ row_activated_cb( GtkTreeView* tree_view, GtkTreePath* path,
|
|||
if ( gtk_tree_model_get_iter( model, &iter, path ) ) {
|
||||
sqlite3_int64 rowid;
|
||||
gtk_tree_model_get( model, &iter, ROW_ITEM, &rowid, -1 );
|
||||
open_row( apg, rowid );
|
||||
open_row( apg, rowid, XP_FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,6 +157,7 @@ init_games_list( GtkAppGlobals* apg )
|
|||
addTextColumn( list, "Ended", OVER_ITEM );
|
||||
addTextColumn( list, "Turn", TURN_ITEM );
|
||||
addTextColumn( list, "NMoves", NMOVES_ITEM );
|
||||
addTextColumn( list, "NTotal", NTOTAL_ITEM );
|
||||
addTextColumn( list, "NMissing", MISSING_ITEM );
|
||||
|
||||
GtkListStore* store = gtk_list_store_new( N_ITEMS,
|
||||
|
@ -170,6 +170,7 @@ init_games_list( GtkAppGlobals* apg )
|
|||
G_TYPE_BOOLEAN, /* OVER_ITEM */
|
||||
G_TYPE_INT, /* TURN_ITEM */
|
||||
G_TYPE_INT, /* NMOVES_ITEM */
|
||||
G_TYPE_INT, /* NTOTAL_ITEM */
|
||||
G_TYPE_INT /* MISSING_ITEM */
|
||||
);
|
||||
gtk_tree_view_set_model( GTK_TREE_VIEW(list), GTK_TREE_MODEL(store) );
|
||||
|
@ -217,6 +218,7 @@ add_to_list( GtkWidget* list, sqlite3_int64 rowid, XP_Bool isNew,
|
|||
OVER_ITEM, gib->gameOver,
|
||||
TURN_ITEM, gib->turn,
|
||||
NMOVES_ITEM, gib->nMoves,
|
||||
NTOTAL_ITEM, gib->nTotal,
|
||||
MISSING_ITEM, gib->nMissing,
|
||||
-1 );
|
||||
XP_LOGF( "DONE adding" );
|
||||
|
@ -226,7 +228,8 @@ static void updateButtons( GtkAppGlobals* apg )
|
|||
{
|
||||
guint count = apg->selRows->len;
|
||||
|
||||
gtk_widget_set_sensitive( apg->openButton, 1 == count );
|
||||
gtk_widget_set_sensitive( apg->openButton, 1 <= count );
|
||||
gtk_widget_set_sensitive( apg->rematchButton, 1 == count );
|
||||
gtk_widget_set_sensitive( apg->deleteButton, 1 <= count );
|
||||
}
|
||||
|
||||
|
@ -249,10 +252,14 @@ handle_newgame_button( GtkWidget* XP_UNUSED(widget), void* closure )
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
open_row( GtkAppGlobals* apg, sqlite3_int64 row )
|
||||
void
|
||||
open_row( GtkAppGlobals* apg, sqlite3_int64 row, XP_Bool isNew )
|
||||
{
|
||||
if ( -1 != row && !gameIsOpen( apg, row ) ) {
|
||||
if ( isNew ) {
|
||||
onNewData( apg, row, XP_TRUE );
|
||||
}
|
||||
|
||||
apg->params->needsNewGame = XP_FALSE;
|
||||
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
||||
initGlobals( globals, apg->params, NULL );
|
||||
|
@ -267,8 +274,82 @@ static void
|
|||
handle_open_button( GtkWidget* XP_UNUSED(widget), void* closure )
|
||||
{
|
||||
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
|
||||
sqlite3_int64 selRow = getSelRow( apg );
|
||||
open_row( apg, selRow );
|
||||
|
||||
GArray* selRows = apg->selRows;
|
||||
for ( int ii = 0; ii < selRows->len; ++ii ) {
|
||||
sqlite3_int64 row = g_array_index( selRows, sqlite3_int64, ii );
|
||||
open_row( apg, row, XP_FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
make_rematch( GtkAppGlobals* apg, const CommonGlobals* cGlobals )
|
||||
{
|
||||
// LaunchParams* params = apg->params;
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
||||
cGlobals->params->vtMgr,
|
||||
NULL, CHANNEL_NONE, NULL );
|
||||
|
||||
/* Create new game. But has no addressing info, so need to set that
|
||||
aside for later. */
|
||||
CurGameInfo gi = {0};
|
||||
gi_copy( MPPARM(cGlobals->util->mpool) &gi, cGlobals->gi );
|
||||
gi.gameID = 0; /* clear so will get generated */
|
||||
game_saveNewGame( MPPARM(cGlobals->util->mpool) &gi,
|
||||
cGlobals->util, &cGlobals->cp, stream );
|
||||
|
||||
sqlite3_int64 rowID = writeNewGameToDB( stream, cGlobals->pDb );
|
||||
stream_destroy( stream );
|
||||
gi_disposePlayerInfo( MPPARM(cGlobals->util->mpool) &gi );
|
||||
|
||||
/* If it's a multi-device game, save enough information with it than when
|
||||
opened it can invite the other device[s] join the rematch. */
|
||||
const CommsCtxt* comms = cGlobals->game.comms;
|
||||
if ( !!comms ) {
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
||||
cGlobals->params->vtMgr,
|
||||
NULL, CHANNEL_NONE, NULL );
|
||||
CommsAddrRec addr;
|
||||
comms_getAddr( comms, &addr );
|
||||
addrToStream( stream, &addr );
|
||||
|
||||
CommsAddrRec addrs[4];
|
||||
XP_U16 nRecs = VSIZE(addrs);
|
||||
comms_getAddrs( comms, addrs, &nRecs );
|
||||
|
||||
stream_putU8( stream, nRecs );
|
||||
for ( int ii = 0; ii < nRecs; ++ii ) {
|
||||
XP_UCHAR relayID[32];
|
||||
XP_U16 len = sizeof(relayID);
|
||||
comms_formatRelayID( comms, ii, relayID, &len );
|
||||
XP_LOGF( "%s: adding relayID: %s", __func__, relayID );
|
||||
stringToStream( stream, relayID );
|
||||
if ( addr_hasType( &addrs[ii], COMMS_CONN_RELAY ) ) {
|
||||
/* copy over room name */
|
||||
XP_STRCAT( addrs[ii].u.ip_relay.invite, addr.u.ip_relay.invite );
|
||||
}
|
||||
addrToStream( stream, &addrs[ii] );
|
||||
}
|
||||
saveInviteAddrs( stream, cGlobals->pDb, rowID );
|
||||
stream_destroy( stream );
|
||||
}
|
||||
|
||||
open_row( apg, rowID, XP_TRUE );
|
||||
}
|
||||
|
||||
static void
|
||||
handle_rematch_button( GtkWidget* XP_UNUSED(widget), void* closure )
|
||||
{
|
||||
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
|
||||
GArray* selRows = apg->selRows;
|
||||
for ( int ii = 0; ii < selRows->len; ++ii ) {
|
||||
sqlite3_int64 rowid = g_array_index( selRows, sqlite3_int64, ii );
|
||||
GtkGameGlobals tmpGlobals;
|
||||
if ( loadGameNoDraw( &tmpGlobals, apg->params, rowid ) ) {
|
||||
make_rematch( apg, &tmpGlobals.cGlobals );
|
||||
}
|
||||
freeGlobals( &tmpGlobals );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -396,6 +477,8 @@ makeGamesWindow( GtkAppGlobals* apg )
|
|||
(void)addButton( "New game", hbox, G_CALLBACK(handle_newgame_button), apg );
|
||||
apg->openButton = addButton( "Open", hbox,
|
||||
G_CALLBACK(handle_open_button), apg );
|
||||
apg->rematchButton = addButton( "Rematch", hbox,
|
||||
G_CALLBACK(handle_rematch_button), apg );
|
||||
apg->deleteButton = addButton( "Delete", hbox,
|
||||
G_CALLBACK(handle_delete_button), apg );
|
||||
(void)addButton( "Quit", hbox, G_CALLBACK(handle_quit_button), apg );
|
||||
|
@ -479,29 +562,38 @@ relayInviteReceived( void* closure, InviteInfo* invite )
|
|||
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
|
||||
LaunchParams* params = apg->params;
|
||||
|
||||
CurGameInfo gi = {0};
|
||||
gi_copy( MPPARM(params->mpool) &gi, ¶ms->pgi );
|
||||
XP_U32 gameID = invite->gameID;
|
||||
sqlite3_int64 rowids[1];
|
||||
int nRowIDs = VSIZE(rowids);
|
||||
getRowsForGameID( apg->params->pDb, gameID, rowids, &nRowIDs );
|
||||
|
||||
if ( 0 < nRowIDs ) {
|
||||
gtktell( apg->window, "Duplicate invite rejected" );
|
||||
} else {
|
||||
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;
|
||||
replaceStringIfDifferent( params->mpool, &gi.dictName, invite->dict );
|
||||
gi_setNPlayers( &gi, invite->nPlayersT, invite->nPlayersH );
|
||||
gi.gameID = gameID;
|
||||
gi.dictLang = invite->lang;
|
||||
gi.forceChannel = invite->forceChannel;
|
||||
replaceStringIfDifferent( params->mpool, &gi.dictName, invite->dict );
|
||||
|
||||
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
||||
params->needsNewGame = XP_FALSE;
|
||||
initGlobals( globals, params, &gi );
|
||||
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
||||
params->needsNewGame = XP_FALSE;
|
||||
initGlobals( globals, params, &gi );
|
||||
|
||||
invit_makeAddrRec( invite, &globals->cGlobals.addr );
|
||||
// globals->cGlobals.addr = *returnAddr;
|
||||
invit_makeAddrRec( invite, &globals->cGlobals.addr );
|
||||
// globals->cGlobals.addr = *returnAddr;
|
||||
|
||||
GtkWidget* gameWindow = globals->window;
|
||||
globals->cGlobals.pDb = apg->params->pDb;
|
||||
globals->cGlobals.selRow = -1;
|
||||
recordOpened( apg, globals );
|
||||
gtk_widget_show( gameWindow );
|
||||
GtkWidget* gameWindow = globals->window;
|
||||
globals->cGlobals.pDb = apg->params->pDb;
|
||||
globals->cGlobals.selRow = -1;
|
||||
recordOpened( apg, globals );
|
||||
gtk_widget_show( gameWindow );
|
||||
|
||||
gi_disposePlayerInfo( MPPARM(params->mpool) &gi );
|
||||
gi_disposePlayerInfo( MPPARM(params->mpool) &gi );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -646,17 +738,6 @@ onGameSaved( void* closure, sqlite3_int64 rowid,
|
|||
}
|
||||
}
|
||||
|
||||
sqlite3_int64
|
||||
getSelRow( const GtkAppGlobals* apg )
|
||||
{
|
||||
sqlite3_int64 result = -1;
|
||||
guint len = apg->selRows->len;
|
||||
if ( 1 == len ) {
|
||||
result = g_array_index( apg->selRows, sqlite3_int64, 0 );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkAppGlobals* g_globals_for_signal = NULL;
|
||||
|
||||
static void
|
||||
|
|
|
@ -26,5 +26,7 @@
|
|||
int gtkmain( LaunchParams* params );
|
||||
void windowDestroyed( GtkGameGlobals* globals );
|
||||
void onGameSaved( void* closure, sqlite3_int64 rowid, XP_Bool firstTime );
|
||||
void open_row( GtkAppGlobals* apg, sqlite3_int64 row, XP_Bool isNew );
|
||||
void make_rematch( GtkAppGlobals* apg, const CommonGlobals* cGlobals );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -918,6 +918,10 @@ linux_getDevID( LaunchParams* params, DevIDType* typ )
|
|||
if ( !!params->lDevID ) {
|
||||
result = params->lDevID;
|
||||
*typ = ID_TYPE_LINUX;
|
||||
} else if ( db_fetch( params->pDb, KEY_RDEVID, params->devIDStore,
|
||||
sizeof(params->devIDStore) ) ) {
|
||||
result = params->devIDStore;
|
||||
*typ = '\0' == result[0] ? ID_TYPE_ANON : ID_TYPE_RELAY;
|
||||
} else if ( db_fetch( params->pDb, KEY_LDEVID, params->devIDStore,
|
||||
sizeof(params->devIDStore) ) ) {
|
||||
result = params->devIDStore;
|
||||
|
|
|
@ -247,9 +247,8 @@ typedef struct _GtkAppGlobals {
|
|||
GtkWidget* window;
|
||||
GtkWidget* listWidget;
|
||||
GtkWidget* openButton;
|
||||
GtkWidget* rematchButton;
|
||||
GtkWidget* deleteButton;
|
||||
} GtkAppGlobals;
|
||||
|
||||
sqlite3_int64 getSelRow( const GtkAppGlobals* apg );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -48,14 +48,14 @@ static ssize_t sendIt( RelayConStorage* storage, const XP_U8* msgbuf, XP_U16 len
|
|||
static size_t addVLIStr( XP_U8* buf, size_t len, const XP_UCHAR* str );
|
||||
static void getNetString( const XP_U8** ptr, XP_U16 len, XP_UCHAR* buf );
|
||||
static XP_U16 getNetShort( const XP_U8** ptr );
|
||||
#ifdef DEBUG
|
||||
static XP_U32 getNetLong( const XP_U8** ptr );
|
||||
#endif
|
||||
static int writeHeader( RelayConStorage* storage, XP_U8* dest, XWRelayReg cmd );
|
||||
static bool readHeader( const XP_U8** buf, MsgHeader* header );
|
||||
static size_t writeDevID( XP_U8* buf, size_t len, const XP_UCHAR* str );
|
||||
static size_t writeShort( XP_U8* buf, size_t len, XP_U16 shrt );
|
||||
static size_t writeLong( XP_U8* buf, size_t len, XP_U32 lng );
|
||||
static size_t writeBytes( XP_U8* buf, size_t len, const XP_U8* bytes,
|
||||
size_t nBytes );
|
||||
static size_t writeVLI( XP_U8* out, uint32_t nn );
|
||||
static size_t un2vli( int nn, uint8_t* buf );
|
||||
static bool vli2un( const uint8_t** inp, uint32_t* outp );
|
||||
|
@ -113,7 +113,8 @@ relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
|
|||
}
|
||||
|
||||
void
|
||||
relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invit )
|
||||
relaycon_invite( LaunchParams* params, XP_U32 destDevID,
|
||||
const XP_UCHAR* relayID, InviteInfo* invit )
|
||||
{
|
||||
XP_U8 tmpbuf[256];
|
||||
int indx = 0;
|
||||
|
@ -122,7 +123,17 @@ relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invit )
|
|||
indx += writeHeader( storage, tmpbuf, XWPDEV_INVITE );
|
||||
XP_U32 me = linux_getDevIDRelay( params );
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, me );
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, dest );
|
||||
|
||||
/* write relayID <connname>/<hid>, or if we have an actual devID write a
|
||||
null byte plus it. */
|
||||
if ( 0 == destDevID ) {
|
||||
XP_ASSERT( '\0' != relayID[0] );
|
||||
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx,
|
||||
(XP_U8*)relayID, 1 + XP_STRLEN( relayID ) );
|
||||
} else {
|
||||
tmpbuf[indx++] = '\0'; /* null byte: zero-len str */
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, destDevID );
|
||||
}
|
||||
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(params->mpool)
|
||||
params->vtMgr, params,
|
||||
|
@ -132,8 +143,7 @@ relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invit )
|
|||
indx += writeShort( &tmpbuf[indx], sizeof(tmpbuf) - indx, len );
|
||||
XP_ASSERT( indx + len < sizeof(tmpbuf) );
|
||||
const XP_U8* ptr = stream_getPtr( stream );
|
||||
XP_MEMCPY( &tmpbuf[indx], ptr, len );
|
||||
indx += len;
|
||||
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx, ptr, len );
|
||||
stream_destroy( stream );
|
||||
|
||||
sendIt( storage, tmpbuf, indx );
|
||||
|
@ -151,11 +161,8 @@ relaycon_send( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
|
|||
XP_U8 tmpbuf[1 + 4 + 1 + sizeof(gameToken) + buflen];
|
||||
int indx = 0;
|
||||
indx += writeHeader( storage, tmpbuf, XWPDEV_MSG );
|
||||
XP_U32 inNBO = htonl(gameToken);
|
||||
XP_MEMCPY( &tmpbuf[indx], &inNBO, sizeof(inNBO) );
|
||||
indx += sizeof(inNBO);
|
||||
XP_MEMCPY( &tmpbuf[indx], buf, buflen );
|
||||
indx += buflen;
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, gameToken );
|
||||
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx, buf, buflen );
|
||||
nSent = sendIt( storage, tmpbuf, indx );
|
||||
if ( nSent > buflen ) {
|
||||
nSent = buflen;
|
||||
|
@ -179,14 +186,12 @@ relaycon_sendnoconn( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
|
|||
1 + idLen +
|
||||
sizeof(gameToken) + buflen];
|
||||
indx += writeHeader( storage, tmpbuf, XWPDEV_MSGNOCONN );
|
||||
gameToken = htonl( gameToken );
|
||||
XP_MEMCPY( &tmpbuf[indx], &gameToken, sizeof(gameToken) );
|
||||
indx += sizeof(gameToken);
|
||||
XP_MEMCPY( &tmpbuf[indx], relayID, idLen );
|
||||
indx += idLen;
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, gameToken );
|
||||
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx,
|
||||
(const XP_U8*)relayID, idLen );
|
||||
tmpbuf[indx++] = '\n';
|
||||
XP_MEMCPY( &tmpbuf[indx], buf, buflen );
|
||||
nSent = sendIt( storage, tmpbuf, sizeof(tmpbuf) );
|
||||
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx, buf, buflen );
|
||||
nSent = sendIt( storage, tmpbuf, indx );
|
||||
if ( nSent > buflen ) {
|
||||
nSent = buflen;
|
||||
}
|
||||
|
@ -218,9 +223,7 @@ relaycon_deleted( LaunchParams* params, const XP_UCHAR* devID,
|
|||
int indx = 0;
|
||||
indx += writeHeader( storage, tmpbuf, XWPDEV_DELGAME );
|
||||
indx += writeDevID( &tmpbuf[indx], sizeof(tmpbuf) - indx, devID );
|
||||
gameToken = htonl( gameToken );
|
||||
memcpy( &tmpbuf[indx], &gameToken, sizeof(gameToken) );
|
||||
indx += sizeof( gameToken );
|
||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, gameToken );
|
||||
|
||||
sendIt( storage, tmpbuf, indx );
|
||||
}
|
||||
|
@ -330,7 +333,10 @@ relaycon_receive( GIOChannel* source, GIOCondition XP_UNUSED_DBG(condition), gpo
|
|||
}
|
||||
case XWPDEV_GOTINVITE: {
|
||||
XP_LOGF( "%s(): got XWPDEV_GOTINVITE", __func__ );
|
||||
XP_U32 sender = getNetLong( &ptr );
|
||||
#ifdef DEBUG
|
||||
XP_U32 sender =
|
||||
#endif
|
||||
getNetLong( &ptr );
|
||||
XP_U16 len = getNetShort( &ptr );
|
||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(storage->params->mpool)
|
||||
storage->params->vtMgr, storage,
|
||||
|
@ -438,7 +444,7 @@ writeShort( XP_U8* buf, size_t len, XP_U16 shrt )
|
|||
{
|
||||
shrt = htons( shrt );
|
||||
assert( sizeof( shrt ) <= len );
|
||||
memcpy( buf, &shrt, sizeof(shrt) );
|
||||
XP_MEMCPY( buf, &shrt, sizeof(shrt) );
|
||||
return sizeof(shrt);
|
||||
}
|
||||
|
||||
|
@ -451,6 +457,14 @@ writeLong( XP_U8* buf, size_t len, XP_U32 lng )
|
|||
return sizeof(lng);
|
||||
}
|
||||
|
||||
static size_t
|
||||
writeBytes( XP_U8* buf, size_t len, const XP_U8* bytes, size_t nBytes )
|
||||
{
|
||||
assert( nBytes <= len );
|
||||
XP_MEMCPY( buf, bytes, nBytes );
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
static size_t
|
||||
writeVLI( XP_U8* out, uint32_t nn )
|
||||
{
|
||||
|
@ -469,7 +483,6 @@ getNetShort( const XP_U8** ptr )
|
|||
return ntohs( result );
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static XP_U32
|
||||
getNetLong( const XP_U8** ptr )
|
||||
{
|
||||
|
@ -478,7 +491,6 @@ getNetLong( const XP_U8** ptr )
|
|||
*ptr += sizeof(result);
|
||||
return ntohl( result );
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
getNetString( const XP_U8** ptr, XP_U16 len, XP_UCHAR* buf )
|
||||
|
|
|
@ -39,7 +39,10 @@ void relaycon_init( LaunchParams* params, const RelayConnProcs* procs,
|
|||
void* procsClosure, const char* host, int port );
|
||||
void relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
|
||||
DevIDType typ, const XP_UCHAR* devID );
|
||||
void relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invite );
|
||||
/* Need one of dest or relayID, with dest preferred. pass 0 for dest to use
|
||||
relayID (formatted per comms::formatRelayID()) */
|
||||
void relaycon_invite( LaunchParams* params, XP_U32 dest,
|
||||
const XP_UCHAR* relayID, InviteInfo* invite );
|
||||
XP_S16 relaycon_send( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
|
||||
XP_U32 gameToken, const CommsAddrRec* addrRec );
|
||||
XP_S16 relaycon_sendnoconn( LaunchParams* params, const XP_U8* buf,
|
||||
|
|
|
@ -873,6 +873,19 @@ DBMgr::readArray( const char* const connName, const char* column, int arr[] ) /
|
|||
PQclear( result );
|
||||
}
|
||||
|
||||
// parse something created by comms.c's formatRelayID
|
||||
DevIDRelay
|
||||
DBMgr::getDevID( string& relayID )
|
||||
{
|
||||
size_t pos = relayID.find_first_of( '/' );
|
||||
string connName = relayID.substr( 0, pos );
|
||||
int hid = relayID[pos + 1] - '0';
|
||||
DevIDRelay result = getDevID( connName.c_str(), hid );
|
||||
// Not an error. Remove or downlog when confirm working
|
||||
logf( XW_LOGERROR, "%s(%s) => %d", __func__, relayID.c_str(), result );
|
||||
return result;
|
||||
}
|
||||
|
||||
DevIDRelay
|
||||
DBMgr::getDevID( const char* connName, int hid )
|
||||
{
|
||||
|
|
|
@ -146,6 +146,8 @@ class DBMgr {
|
|||
void RemoveStoredMessage( const int msgID );
|
||||
void RemoveStoredMessages( vector<int>& ids );
|
||||
|
||||
DevIDRelay getDevID( string& relayID );
|
||||
|
||||
private:
|
||||
DBMgr();
|
||||
bool execSql( const string& query );
|
||||
|
|
|
@ -1779,17 +1779,24 @@ handle_udp_packet( UdpThreadClosure* utc )
|
|||
break;
|
||||
}
|
||||
|
||||
case XWPDEV_INVITE:
|
||||
case XWPDEV_INVITE: {
|
||||
DevIDRelay sender;
|
||||
DevIDRelay invitee;
|
||||
if ( getNetLong( &ptr, end, &sender )
|
||||
&& getNetLong( &ptr, end, &invitee) ) {
|
||||
string relayID;
|
||||
if ( getNetLong( &ptr, end, &sender )
|
||||
&& getNetString( &ptr, end, relayID ) ) {
|
||||
DevIDRelay invitee;
|
||||
if ( 0 < relayID.size() ) {
|
||||
invitee = DBMgr::Get()->getDevID( relayID );
|
||||
} else if ( !getNetLong( &ptr, end, &invitee ) ) {
|
||||
break; // failure
|
||||
}
|
||||
logf( XW_LOGVERBOSE0, "got invite from %d for %d",
|
||||
sender, invitee );
|
||||
post_invite( sender, invitee, ptr, end - ptr );
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case XWPDEV_KEEPALIVE:
|
||||
case XWPDEV_RQSTMSGS: {
|
||||
DevID devID( ID_TYPE_RELAY );
|
||||
|
|
Loading…
Add table
Reference in a new issue