mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-05 20:45:49 +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
|
static void
|
||||||
addrFromStreamOne( CommsAddrRec* addrP, XWStreamCtxt* stream, CommsConnType typ )
|
addrFromStreamOne( CommsAddrRec* addrP, XWStreamCtxt* stream, CommsConnType typ )
|
||||||
{
|
{
|
||||||
|
XP_U16 version = stream_getVersion( stream );
|
||||||
switch( typ ) {
|
switch( typ ) {
|
||||||
case COMMS_CONN_NONE:
|
case COMMS_CONN_NONE:
|
||||||
break;
|
break;
|
||||||
|
@ -584,8 +585,11 @@ addrFromStreamOne( CommsAddrRec* addrP, XWStreamCtxt* stream, CommsConnType typ
|
||||||
stringFromStreamHere( stream, addrP->u.ip_relay.hostName,
|
stringFromStreamHere( stream, addrP->u.ip_relay.hostName,
|
||||||
sizeof(addrP->u.ip_relay.hostName) );
|
sizeof(addrP->u.ip_relay.hostName) );
|
||||||
addrP->u.ip_relay.ipAddr = stream_getU32( stream );
|
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 );
|
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.seeksPublicRoom = stream_getBits( stream, 1 );
|
||||||
addrP->u.ip_relay.advertiseRoom = 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 );
|
isServer = stream_getU8( stream );
|
||||||
addrFromStream( &addr, 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 );
|
nPlayersHere = (XP_U16)stream_getBits( stream, 4 );
|
||||||
nPlayersTotal = (XP_U16)stream_getBits( stream, 4 );
|
nPlayersTotal = (XP_U16)stream_getBits( stream, 4 );
|
||||||
} else {
|
} 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.invite );
|
||||||
stringToStream( stream, addrP->u.ip_relay.hostName );
|
stringToStream( stream, addrP->u.ip_relay.hostName );
|
||||||
stream_putU32( stream, addrP->u.ip_relay.ipAddr );
|
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_putU16( stream, addrP->u.ip_relay.port );
|
||||||
stream_putBits( stream, 1, addrP->u.ip_relay.seeksPublicRoom );
|
stream_putBits( stream, 1, addrP->u.ip_relay.seeksPublicRoom );
|
||||||
stream_putBits( stream, 1, addrP->u.ip_relay.advertiseRoom );
|
stream_putBits( stream, 1, addrP->u.ip_relay.advertiseRoom );
|
||||||
|
@ -827,6 +833,7 @@ addrToStreamOne( XWStreamCtxt* stream, CommsConnType typ, const CommsAddrRec* ad
|
||||||
void
|
void
|
||||||
addrToStream( XWStreamCtxt* stream, const CommsAddrRec* addrP )
|
addrToStream( XWStreamCtxt* stream, const CommsAddrRec* addrP )
|
||||||
{
|
{
|
||||||
|
stream_setVersion( stream, CUR_STREAM_VERS );
|
||||||
stream_putU8( stream, addrP->_conTypes );
|
stream_putU8( stream, addrP->_conTypes );
|
||||||
|
|
||||||
CommsConnType typ;
|
CommsConnType typ;
|
||||||
|
@ -843,13 +850,13 @@ comms_writeToStream( CommsCtxt* comms, XWStreamCtxt* stream,
|
||||||
AddressRecord* rec;
|
AddressRecord* rec;
|
||||||
MsgQueueElem* msg;
|
MsgQueueElem* msg;
|
||||||
|
|
||||||
|
stream_setVersion( stream, CUR_STREAM_VERS );
|
||||||
|
|
||||||
stream_putU8( stream, (XP_U8)comms->isServer );
|
stream_putU8( stream, (XP_U8)comms->isServer );
|
||||||
logAddr( comms, &comms->addr, __func__ );
|
logAddr( comms, &comms->addr, __func__ );
|
||||||
addrToStream( stream, &comms->addr );
|
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.nPlayersHere );
|
stream_putBits( stream, 4, comms->rr.nPlayersTotal );
|
||||||
stream_putBits( stream, 4, comms->rr.nPlayersTotal );
|
|
||||||
}
|
|
||||||
|
|
||||||
stream_putU32( stream, comms->connID );
|
stream_putU32( stream, comms->connID );
|
||||||
stream_putU16( stream, comms->nextChannelNo );
|
stream_putU16( stream, comms->nextChannelNo );
|
||||||
|
@ -982,6 +989,20 @@ formatRelayID( const CommsCtxt* comms, XWHostID hostID,
|
||||||
return XP_TRUE;
|
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 */
|
/* Get *my* "relayID", a combo of connname and host id */
|
||||||
XP_Bool
|
XP_Bool
|
||||||
comms_getRelayID( const CommsCtxt* comms, XP_UCHAR* buf, XP_U16* lenp )
|
comms_getRelayID( const CommsCtxt* comms, XP_UCHAR* buf, XP_U16* lenp )
|
||||||
|
@ -997,12 +1018,14 @@ comms_getInitialAddr( CommsAddrRec* addr
|
||||||
#ifdef XWFEATURE_RELAY
|
#ifdef XWFEATURE_RELAY
|
||||||
, const XP_UCHAR* relayName
|
, const XP_UCHAR* relayName
|
||||||
, XP_U16 relayPort
|
, XP_U16 relayPort
|
||||||
|
, XP_U32 devID
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#if defined XWFEATURE_RELAY
|
#if defined XWFEATURE_RELAY
|
||||||
addr_setType( addr, COMMS_CONN_RELAY ); /* for temporary ease in debugging */
|
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.ipAddr = 0L; /* force 'em to set it */
|
||||||
|
addr->u.ip_relay.devID = devID;
|
||||||
addr->u.ip_relay.port = relayPort;
|
addr->u.ip_relay.port = relayPort;
|
||||||
{
|
{
|
||||||
const char* name = relayName;
|
const char* name = relayName;
|
||||||
|
@ -1051,7 +1074,7 @@ comms_getConTypes( const CommsCtxt* comms )
|
||||||
XP_LOGF( "%s: returning COMMS_CONN_NONE for null comms", __func__ );
|
XP_LOGF( "%s: returning COMMS_CONN_NONE for null comms", __func__ );
|
||||||
}
|
}
|
||||||
return typ;
|
return typ;
|
||||||
} /* comms_getConType */
|
} /* comms_getConTypes */
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
comms_getIsServer( const CommsCtxt* comms )
|
comms_getIsServer( const CommsCtxt* comms )
|
||||||
|
@ -2629,14 +2652,8 @@ augmentChannelAddr( CommsCtxt* comms, AddressRecord * const rec,
|
||||||
switch( typ ) {
|
switch( typ ) {
|
||||||
case COMMS_CONN_RELAY:
|
case COMMS_CONN_RELAY:
|
||||||
dest = &rec->addr.u.ip_relay;
|
dest = &rec->addr.u.ip_relay;
|
||||||
|
src = &addr->u.ip_relay;
|
||||||
siz = sizeof( rec->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 ) {
|
if ( 0 != hostID ) {
|
||||||
rec->rr.hostID = hostID;
|
rec->rr.hostID = hostID;
|
||||||
XP_LOGF( "%s: set hostID for rec %p to %d", __func__, rec, 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 invite[MAX_INVITE_LEN + 1];
|
||||||
XP_UCHAR hostName[MAX_HOSTNAME_LEN + 1];
|
XP_UCHAR hostName[MAX_HOSTNAME_LEN + 1];
|
||||||
XP_U32 ipAddr; /* looked up from above */
|
XP_U32 ipAddr; /* looked up from above */
|
||||||
|
XP_U32 devID;
|
||||||
XP_U16 port;
|
XP_U16 port;
|
||||||
XP_Bool seeksPublicRoom;
|
XP_Bool seeksPublicRoom;
|
||||||
XP_Bool advertiseRoom;
|
XP_Bool advertiseRoom;
|
||||||
|
@ -180,6 +181,7 @@ void comms_getInitialAddr( CommsAddrRec* addr
|
||||||
#ifdef XWFEATURE_RELAY
|
#ifdef XWFEATURE_RELAY
|
||||||
, const XP_UCHAR* relayName
|
, const XP_UCHAR* relayName
|
||||||
, XP_U16 relayPort
|
, XP_U16 relayPort
|
||||||
|
, XP_U32 devID
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
XP_Bool comms_checkAddr( DeviceRole role, const CommsAddrRec* addr,
|
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_setAddr( CommsCtxt* comms, const CommsAddrRec* addr );
|
||||||
void comms_getAddrs( const CommsCtxt* comms, CommsAddrRec addr[],
|
void comms_getAddrs( const CommsCtxt* comms, CommsAddrRec addr[],
|
||||||
XP_U16* nRecs );
|
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 );
|
XP_U16 comms_countPendingPackets( const CommsCtxt* comms );
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#endif
|
#endif
|
||||||
#define MAX_COLS MAX_ROWS
|
#define MAX_COLS MAX_ROWS
|
||||||
|
|
||||||
|
#define STREAM_VERS_DEVIDS 0x19
|
||||||
#define STREAM_VERS_MULTIADDR 0x18
|
#define STREAM_VERS_MULTIADDR 0x18
|
||||||
#define STREAM_VERS_MODELDIVIDER 0x17
|
#define STREAM_VERS_MODELDIVIDER 0x17
|
||||||
#define STREAM_VERS_COMMSBACKOFF 0x16
|
#define STREAM_VERS_COMMSBACKOFF 0x16
|
||||||
|
@ -86,7 +87,7 @@
|
||||||
#define STREAM_VERS_405 0x01
|
#define STREAM_VERS_405 0x01
|
||||||
|
|
||||||
/* search for FIX_NEXT_VERSION_CHANGE next time this is changed */
|
/* 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 {
|
typedef struct XP_Rect {
|
||||||
XP_S16 left;
|
XP_S16 left;
|
||||||
|
|
|
@ -49,7 +49,8 @@ static void gi_setDict( MPFORMAL CurGameInfo* gi, const DictionaryCtxt* dict );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
checkServerRole( CurGameInfo* gi, XP_U16* nPlayersHere, XP_U16* nPlayersTotal )
|
checkServerRole( CurGameInfo* gi, XP_U16* nPlayersHere,
|
||||||
|
XP_U16* nPlayersTotal )
|
||||||
{
|
{
|
||||||
if ( !!gi ) {
|
if ( !!gi ) {
|
||||||
XP_U16 ii, remoteCount = 0;
|
XP_U16 ii, remoteCount = 0;
|
||||||
|
@ -87,7 +88,7 @@ makeGameID( XW_UtilCtxt* util )
|
||||||
void
|
void
|
||||||
game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||||
XW_UtilCtxt* util, DrawCtx* draw,
|
XW_UtilCtxt* util, DrawCtx* draw,
|
||||||
CommonPrefs* cp, const TransportProcs* procs
|
const CommonPrefs* cp, const TransportProcs* procs
|
||||||
#ifdef SET_GAMESEED
|
#ifdef SET_GAMESEED
|
||||||
,XP_U16 gameSeed
|
,XP_U16 gameSeed
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,6 +281,25 @@ game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
||||||
return success;
|
return success;
|
||||||
} /* game_makeFromStream */
|
} /* 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
|
void
|
||||||
game_saveToStream( const XWGame* game, const CurGameInfo* gi,
|
game_saveToStream( const XWGame* game, const CurGameInfo* gi,
|
||||||
XWStreamCtxt* stream, XP_U16 saveToken )
|
XWStreamCtxt* stream, XP_U16 saveToken )
|
||||||
|
|
|
@ -60,7 +60,7 @@ typedef struct XWGame {
|
||||||
|
|
||||||
void game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
void game_makeNewGame( MPFORMAL XWGame* game, CurGameInfo* gi,
|
||||||
XW_UtilCtxt* util, DrawCtx* draw,
|
XW_UtilCtxt* util, DrawCtx* draw,
|
||||||
CommonPrefs* cp, const TransportProcs* procs
|
const CommonPrefs* cp, const TransportProcs* procs
|
||||||
#ifdef SET_GAMESEED
|
#ifdef SET_GAMESEED
|
||||||
,XP_U16 gameSeed
|
,XP_U16 gameSeed
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,6 +76,9 @@ XP_Bool game_makeFromStream( MPFORMAL XWStreamCtxt* stream, XWGame* game,
|
||||||
DrawCtx* draw, CommonPrefs* cp,
|
DrawCtx* draw, CommonPrefs* cp,
|
||||||
const TransportProcs* procs );
|
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,
|
void game_saveToStream( const XWGame* game, const CurGameInfo* gi,
|
||||||
XWStreamCtxt* stream, XP_U16 saveToken );
|
XWStreamCtxt* stream, XP_U16 saveToken );
|
||||||
void game_saveSucceeded( const XWGame* game, 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_setDevID( InviteInfo* invit, XP_U32 devID )
|
||||||
{
|
{
|
||||||
invit->devID = devID;
|
invit->devID = devID;
|
||||||
|
types_addType( &invit->_conTypes, COMMS_CONN_RELAY );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -30,6 +30,12 @@
|
||||||
|
|
||||||
typedef enum {OSType_NONE, OSType_LINUX, OSType_ANDROID, } XP_OSType;
|
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 {
|
typedef struct _InviteInfo {
|
||||||
XP_U8 version; /* struct version for backward compatibility */
|
XP_U8 version; /* struct version for backward compatibility */
|
||||||
XP_U16 _conTypes;
|
XP_U16 _conTypes;
|
||||||
|
|
|
@ -25,6 +25,7 @@ static void getColumnText( sqlite3_stmt *ppStmt, int iCol, XP_UCHAR* buf,
|
||||||
int len );
|
int len );
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static char* sqliteErr2str( int err );
|
static char* sqliteErr2str( int err );
|
||||||
|
static void assertPrintResult( sqlite3* pDb, int result, int expect );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sqlite3*
|
sqlite3*
|
||||||
|
@ -41,6 +42,7 @@ openGamesDB( const char* dbName )
|
||||||
"CREATE TABLE games ( "
|
"CREATE TABLE games ( "
|
||||||
"rowid INTEGER PRIMARY KEY AUTOINCREMENT"
|
"rowid INTEGER PRIMARY KEY AUTOINCREMENT"
|
||||||
",game BLOB"
|
",game BLOB"
|
||||||
|
",inviteInfo BLOB"
|
||||||
",room VARCHAR(32)"
|
",room VARCHAR(32)"
|
||||||
",connvia VARCHAR(32)"
|
",connvia VARCHAR(32)"
|
||||||
",ended INT(1)"
|
",ended INT(1)"
|
||||||
|
@ -48,6 +50,7 @@ openGamesDB( const char* dbName )
|
||||||
",nmoves INT"
|
",nmoves INT"
|
||||||
",seed INT"
|
",seed INT"
|
||||||
",gameid INT"
|
",gameid INT"
|
||||||
|
",ntotal INT(2)"
|
||||||
",nmissing INT(2)"
|
",nmissing INT(2)"
|
||||||
")";
|
")";
|
||||||
result = sqlite3_exec( pDb, createGamesStr, NULL, NULL, NULL );
|
result = sqlite3_exec( pDb, createGamesStr, NULL, NULL, NULL );
|
||||||
|
@ -68,31 +71,32 @@ closeGamesDB( sqlite3* pDb )
|
||||||
XP_LOGF( "%s finished", __func__ );
|
XP_LOGF( "%s finished", __func__ );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static sqlite3_int64
|
||||||
writeToDB( XWStreamCtxt* stream, void* closure )
|
writeBlobColumn( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 curRow,
|
||||||
|
const char* column )
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
CommonGlobals* cGlobals = (CommonGlobals*)closure;
|
/* size includes stream version as header */
|
||||||
sqlite3_int64 selRow = cGlobals->selRow;
|
|
||||||
sqlite3* pDb = cGlobals->pDb;
|
|
||||||
XP_U16 len = stream_getSize( stream );
|
XP_U16 len = stream_getSize( stream );
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char* query;
|
char* query;
|
||||||
|
|
||||||
sqlite3_stmt* stmt = NULL;
|
sqlite3_stmt* stmt = NULL;
|
||||||
XP_Bool newGame = -1 == selRow;
|
XP_Bool newGame = -1 == curRow;
|
||||||
if ( newGame ) { /* new row; need to insert blob first */
|
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 {
|
} else {
|
||||||
const char* fmt = "UPDATE games SET game=? where rowid=%lld";
|
const char* fmt = "UPDATE games SET %s=? where rowid=%lld";
|
||||||
snprintf( buf, sizeof(buf), fmt, selRow );
|
snprintf( buf, sizeof(buf), fmt, column, curRow );
|
||||||
query = buf;
|
query = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = sqlite3_prepare_v2( pDb, query, -1, &stmt, NULL );
|
result = sqlite3_prepare_v2( pDb, query, -1, &stmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_bind_zeroblob( stmt, 1 /*col 0 ??*/, len );
|
result = sqlite3_bind_zeroblob( stmt, 1 /*col 0 ??*/, sizeof(XP_U16) + len );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_step( stmt );
|
result = sqlite3_step( stmt );
|
||||||
if ( SQLITE_DONE != result ) {
|
if ( SQLITE_DONE != result ) {
|
||||||
XP_LOGF( "%s: sqlite3_step => %s", __func__, sqliteErr2str( result ) );
|
XP_LOGF( "%s: sqlite3_step => %s", __func__, sqliteErr2str( result ) );
|
||||||
|
@ -101,24 +105,51 @@ writeToDB( XWStreamCtxt* stream, void* closure )
|
||||||
XP_USE( result );
|
XP_USE( result );
|
||||||
|
|
||||||
if ( newGame ) { /* new row; need to insert blob first */
|
if ( newGame ) { /* new row; need to insert blob first */
|
||||||
selRow = sqlite3_last_insert_rowid( pDb );
|
curRow = sqlite3_last_insert_rowid( pDb );
|
||||||
XP_LOGF( "%s: new rowid: %lld", __func__, selRow );
|
XP_LOGF( "%s: new rowid: %lld", __func__, curRow );
|
||||||
cGlobals->selRow = selRow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_blob* blob;
|
sqlite3_blob* blob;
|
||||||
result = sqlite3_blob_open( pDb, "main", "games", "game",
|
result = sqlite3_blob_open( pDb, "main", "games", column,
|
||||||
selRow, 1 /*flags: writeable*/, &blob );
|
curRow, 1 /*flags: writeable*/, &blob );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
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 );
|
const XP_U8* ptr = stream_getPtr( stream );
|
||||||
result = sqlite3_blob_write( blob, ptr, len, 0 );
|
result = sqlite3_blob_write( blob, ptr, len, sizeof(strVersion) );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_blob_close( blob );
|
result = sqlite3_blob_close( blob );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
if ( !!stmt ) {
|
if ( !!stmt ) {
|
||||||
sqlite3_finalize( 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 );
|
(*cGlobals->onSave)( cGlobals->onSaveClosure, selRow, newGame );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +161,7 @@ summarize( CommonGlobals* cGlobals )
|
||||||
XP_S16 turn = server_getCurrentTurn( cGlobals->game.server );
|
XP_S16 turn = server_getCurrentTurn( cGlobals->game.server );
|
||||||
XP_U16 seed = 0;
|
XP_U16 seed = 0;
|
||||||
XP_S16 nMissing = 0;
|
XP_S16 nMissing = 0;
|
||||||
|
XP_U16 nTotal = cGlobals->gi->nPlayers;
|
||||||
XP_U32 gameID = cGlobals->gi->gameID;
|
XP_U32 gameID = cGlobals->gi->gameID;
|
||||||
XP_ASSERT( 0 != gameID );
|
XP_ASSERT( 0 != gameID );
|
||||||
CommsAddrRec addr = {0};
|
CommsAddrRec addr = {0};
|
||||||
|
@ -171,15 +203,15 @@ summarize( CommonGlobals* cGlobals )
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* fmt = "UPDATE games "
|
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";
|
" WHERE rowid=%lld";
|
||||||
XP_UCHAR buf[256];
|
XP_UCHAR buf[256];
|
||||||
snprintf( buf, sizeof(buf), fmt, room, gameOver?1:0, turn, nMissing, nMoves,
|
snprintf( buf, sizeof(buf), fmt, room, gameOver?1:0, turn, nTotal, nMissing,
|
||||||
seed, gameID, connvia, cGlobals->selRow );
|
nMoves, seed, gameID, connvia, cGlobals->selRow );
|
||||||
XP_LOGF( "query: %s", buf );
|
XP_LOGF( "query: %s", buf );
|
||||||
sqlite3_stmt* stmt = NULL;
|
sqlite3_stmt* stmt = NULL;
|
||||||
int result = sqlite3_prepare_v2( cGlobals->pDb, buf, -1, &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 );
|
result = sqlite3_step( stmt );
|
||||||
if ( SQLITE_DONE != result ) {
|
if ( SQLITE_DONE != result ) {
|
||||||
XP_LOGF( "sqlite3_step=>%s", sqliteErr2str( result ) );
|
XP_LOGF( "sqlite3_step=>%s", sqliteErr2str( result ) );
|
||||||
|
@ -198,7 +230,7 @@ listGames( sqlite3* pDb )
|
||||||
int result = sqlite3_prepare_v2( pDb,
|
int result = sqlite3_prepare_v2( pDb,
|
||||||
"SELECT rowid FROM games ORDER BY rowid",
|
"SELECT rowid FROM games ORDER BY rowid",
|
||||||
-1, &ppStmt, NULL );
|
-1, &ppStmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
XP_USE( result );
|
XP_USE( result );
|
||||||
while ( NULL != ppStmt ) {
|
while ( NULL != ppStmt ) {
|
||||||
switch( sqlite3_step( ppStmt ) ) {
|
switch( sqlite3_step( ppStmt ) ) {
|
||||||
|
@ -226,14 +258,15 @@ XP_Bool
|
||||||
getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
|
getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
|
||||||
{
|
{
|
||||||
XP_Bool success = XP_FALSE;
|
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";
|
"FROM games WHERE rowid = %lld";
|
||||||
XP_UCHAR query[256];
|
XP_UCHAR query[256];
|
||||||
snprintf( query, sizeof(query), fmt, rowid );
|
snprintf( query, sizeof(query), fmt, rowid );
|
||||||
|
|
||||||
sqlite3_stmt* ppStmt;
|
sqlite3_stmt* ppStmt;
|
||||||
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_step( ppStmt );
|
result = sqlite3_step( ppStmt );
|
||||||
if ( SQLITE_ROW == result ) {
|
if ( SQLITE_ROW == result ) {
|
||||||
success = XP_TRUE;
|
success = XP_TRUE;
|
||||||
|
@ -241,10 +274,11 @@ getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
|
||||||
gib->gameOver = 1 == sqlite3_column_int( ppStmt, 1 );
|
gib->gameOver = 1 == sqlite3_column_int( ppStmt, 1 );
|
||||||
gib->turn = sqlite3_column_int( ppStmt, 2 );
|
gib->turn = sqlite3_column_int( ppStmt, 2 );
|
||||||
gib->nMoves = sqlite3_column_int( ppStmt, 3 );
|
gib->nMoves = sqlite3_column_int( ppStmt, 3 );
|
||||||
gib->nMissing = sqlite3_column_int( ppStmt, 4 );
|
gib->nTotal = sqlite3_column_int( ppStmt, 4 );
|
||||||
gib->seed = sqlite3_column_int( ppStmt, 5 );
|
gib->nMissing = sqlite3_column_int( ppStmt, 5 );
|
||||||
getColumnText( ppStmt, 6, gib->conn, sizeof(gib->conn) );
|
gib->seed = sqlite3_column_int( ppStmt, 6 );
|
||||||
gib->gameID = sqlite3_column_int( ppStmt, 7 );
|
getColumnText( ppStmt, 7, gib->conn, sizeof(gib->conn) );
|
||||||
|
gib->gameID = sqlite3_column_int( ppStmt, 8 );
|
||||||
snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid );
|
snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid );
|
||||||
}
|
}
|
||||||
sqlite3_finalize( ppStmt );
|
sqlite3_finalize( ppStmt );
|
||||||
|
@ -259,11 +293,11 @@ getRowsForGameID( sqlite3* pDb, XP_U32 gameID, sqlite3_int64* rowids,
|
||||||
*nRowIDs = 0;
|
*nRowIDs = 0;
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
snprintf( buf, sizeof(buf), "SELECT rowid from games WHERE gameid = %d LIMIT %d",
|
snprintf( buf, sizeof(buf), "SELECT rowid from games WHERE gameid = %d "
|
||||||
gameID, maxRowIDs );
|
"LIMIT %d", gameID, maxRowIDs );
|
||||||
sqlite3_stmt *ppStmt;
|
sqlite3_stmt *ppStmt;
|
||||||
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
int ii;
|
int ii;
|
||||||
for ( ii = 0; ii < maxRowIDs; ++ii ) {
|
for ( ii = 0; ii < maxRowIDs; ++ii ) {
|
||||||
result = sqlite3_step( ppStmt );
|
result = sqlite3_step( ppStmt );
|
||||||
|
@ -276,26 +310,56 @@ getRowsForGameID( sqlite3* pDb, XP_U32 gameID, sqlite3_int64* rowids,
|
||||||
sqlite3_finalize( ppStmt );
|
sqlite3_finalize( ppStmt );
|
||||||
}
|
}
|
||||||
|
|
||||||
XP_Bool
|
static XP_Bool
|
||||||
loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid )
|
loadBlobColumn( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid,
|
||||||
|
const char* column )
|
||||||
{
|
{
|
||||||
char buf[256];
|
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;
|
sqlite3_stmt *ppStmt;
|
||||||
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_step( ppStmt );
|
result = sqlite3_step( ppStmt );
|
||||||
XP_Bool success = SQLITE_ROW == result;
|
XP_Bool success = SQLITE_ROW == result;
|
||||||
if ( success ) {
|
if ( success ) {
|
||||||
const void* ptr = sqlite3_column_blob( ppStmt, 0 );
|
const void* ptr = sqlite3_column_blob( ppStmt, 0 );
|
||||||
int size = sqlite3_column_bytes( 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 );
|
sqlite3_finalize( ppStmt );
|
||||||
return success;
|
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
|
void
|
||||||
deleteGame( sqlite3* pDb, sqlite3_int64 rowid )
|
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 );
|
snprintf( query, sizeof(query), "DELETE FROM games WHERE rowid = %lld", rowid );
|
||||||
sqlite3_stmt* ppStmt;
|
sqlite3_stmt* ppStmt;
|
||||||
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_step( ppStmt );
|
result = sqlite3_step( ppStmt );
|
||||||
XP_ASSERT( SQLITE_DONE == result );
|
assertPrintResult( pDb, result, SQLITE_DONE );
|
||||||
XP_USE( result );
|
XP_USE( result );
|
||||||
sqlite3_finalize( ppStmt );
|
sqlite3_finalize( ppStmt );
|
||||||
}
|
}
|
||||||
|
@ -319,9 +383,9 @@ db_store( sqlite3* pDb, const gchar* key, const gchar* value )
|
||||||
key, value );
|
key, value );
|
||||||
sqlite3_stmt *ppStmt;
|
sqlite3_stmt *ppStmt;
|
||||||
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_step( ppStmt );
|
result = sqlite3_step( ppStmt );
|
||||||
XP_ASSERT( SQLITE_DONE == result );
|
assertPrintResult( pDb, result, SQLITE_DONE );
|
||||||
XP_USE( result );
|
XP_USE( result );
|
||||||
sqlite3_finalize( ppStmt );
|
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 );
|
snprintf( query, sizeof(query), "DELETE FROM pairs WHERE key = '%s'", key );
|
||||||
sqlite3_stmt *ppStmt;
|
sqlite3_stmt *ppStmt;
|
||||||
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
|
||||||
XP_ASSERT( SQLITE_OK == result );
|
assertPrintResult( pDb, result, SQLITE_OK );
|
||||||
result = sqlite3_step( ppStmt );
|
result = sqlite3_step( ppStmt );
|
||||||
XP_ASSERT( SQLITE_DONE == result );
|
assertPrintResult( pDb, result, SQLITE_DONE );
|
||||||
XP_USE( result );
|
XP_USE( result );
|
||||||
sqlite3_finalize( ppStmt );
|
sqlite3_finalize( ppStmt );
|
||||||
}
|
}
|
||||||
|
@ -413,4 +477,17 @@ sqliteErr2str( int err )
|
||||||
}
|
}
|
||||||
return "<unknown>";
|
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
|
#endif
|
||||||
|
|
|
@ -35,6 +35,7 @@ typedef struct _GameInfo {
|
||||||
XP_S16 nMoves;
|
XP_S16 nMoves;
|
||||||
XP_Bool gameOver;
|
XP_Bool gameOver;
|
||||||
XP_S16 turn;
|
XP_S16 turn;
|
||||||
|
XP_U16 nTotal;
|
||||||
XP_S16 nMissing;
|
XP_S16 nMissing;
|
||||||
XP_U16 seed;
|
XP_U16 seed;
|
||||||
} GameInfo;
|
} GameInfo;
|
||||||
|
@ -44,6 +45,8 @@ sqlite3* openGamesDB( const char* dbName );
|
||||||
void closeGamesDB( sqlite3* dbp );
|
void closeGamesDB( sqlite3* dbp );
|
||||||
|
|
||||||
void writeToDB( XWStreamCtxt* stream, void* closure );
|
void writeToDB( XWStreamCtxt* stream, void* closure );
|
||||||
|
sqlite3_int64 writeNewGameToDB( XWStreamCtxt* stream, sqlite3* pDb );
|
||||||
|
|
||||||
void summarize( CommonGlobals* cGlobals );
|
void summarize( CommonGlobals* cGlobals );
|
||||||
|
|
||||||
/* Return GSList whose data is (ptrs to) rowids */
|
/* 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,
|
void getRowsForGameID( sqlite3* dbp, XP_U32 gameID, sqlite3_int64* rowids,
|
||||||
int* nRowIDs );
|
int* nRowIDs );
|
||||||
XP_Bool loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid );
|
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 );
|
void deleteGame( sqlite3* pDb, sqlite3_int64 rowid );
|
||||||
|
|
||||||
#define KEY_RDEVID "RDEVID"
|
#define KEY_RDEVID "RDEVID"
|
||||||
|
|
|
@ -77,8 +77,8 @@ gtkaskm( const gchar* message, AskMInfo* infos, int nInfos )
|
||||||
for ( ii = 0; ii < nInfos; ++ii ) {
|
for ( ii = 0; ii < nInfos; ++ii ) {
|
||||||
AskMInfo* info = &infos[ii];
|
AskMInfo* info = &infos[ii];
|
||||||
if ( !state.cancelled ) {
|
if ( !state.cancelled ) {
|
||||||
const gchar* txt = gtk_entry_get_text( GTK_ENTRY(fields[ii]) );
|
XP_LOGF( "%s: got text %s", __func__,
|
||||||
XP_LOGF( "%s: got text %s", __func__, txt );
|
gtk_entry_get_text( GTK_ENTRY(fields[ii]) ) );
|
||||||
} else {
|
} else {
|
||||||
*info->result = NULL;
|
*info->result = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "movestak.h"
|
#include "movestak.h"
|
||||||
|
#include "strutils.h"
|
||||||
#include "gtkask.h"
|
#include "gtkask.h"
|
||||||
#include "gtkinvit.h"
|
#include "gtkinvit.h"
|
||||||
#include "gtkaskm.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 handle_invite_button( GtkWidget* widget, GtkGameGlobals* globals );
|
||||||
static void gtkShowFinalScores( const GtkGameGlobals* globals,
|
static void gtkShowFinalScores( const GtkGameGlobals* globals,
|
||||||
XP_Bool ignoreTimeout );
|
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
|
#define GTK_TRAY_HT_ROWS 3
|
||||||
|
|
||||||
|
@ -103,7 +108,7 @@ lookupClientStream( GtkGameGlobals* globals, int sock )
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rememberClient( GtkGameGlobals* globals, guint key, int sock,
|
rememberClient( GtkGameGlobals* globals, guint key, int sock,
|
||||||
XWStreamCtxt* stream )
|
XWStreamCtxt* stream )
|
||||||
{
|
{
|
||||||
short i;
|
short i;
|
||||||
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
|
for ( i = 0; i < MAX_NUM_PLAYERS; ++i ) {
|
||||||
|
@ -868,10 +873,39 @@ destroy_board_window( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||||
static void
|
static void
|
||||||
on_board_window_shown( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
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 );
|
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
|
static void
|
||||||
cleanup( GtkGameGlobals* globals )
|
cleanup( GtkGameGlobals* globals )
|
||||||
|
@ -986,7 +1020,9 @@ new_game_impl( GtkGameGlobals* globals, XP_Bool fireConnDlg )
|
||||||
if ( !!cGlobals->game.comms ) {
|
if ( !!cGlobals->game.comms ) {
|
||||||
comms_getAddr( cGlobals->game.comms, &addr );
|
comms_getAddr( cGlobals->game.comms, &addr );
|
||||||
} else {
|
} 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;
|
CurGameInfo* gi = cGlobals->gi;
|
||||||
|
@ -1572,7 +1608,7 @@ static void
|
||||||
handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||||
{
|
{
|
||||||
CommonGlobals* cGlobals = &globals->cGlobals;
|
CommonGlobals* cGlobals = &globals->cGlobals;
|
||||||
const CurGameInfo* gi = cGlobals->gi;
|
/* const CurGameInfo* gi = cGlobals->gi; */
|
||||||
|
|
||||||
/* gchar* countStr; */
|
/* gchar* countStr; */
|
||||||
/* gchar* phone = NULL; */
|
/* gchar* phone = NULL; */
|
||||||
|
@ -1595,46 +1631,52 @@ handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
|
||||||
|
|
||||||
CommsAddrRec inviteAddr = {0};
|
CommsAddrRec inviteAddr = {0};
|
||||||
gint nPlayers = nMissing;
|
gint nPlayers = nMissing;
|
||||||
XP_U32 devID;
|
XP_Bool confirmed = gtkInviteDlg( globals, &inviteAddr, &nPlayers );
|
||||||
XP_Bool confirmed = gtkInviteDlg( globals, &inviteAddr, &nPlayers, &devID );
|
|
||||||
XP_LOGF( "%s: inviteDlg => %d", __func__, confirmed );
|
XP_LOGF( "%s: inviteDlg => %d", __func__, confirmed );
|
||||||
|
|
||||||
if ( confirmed ) {
|
if ( confirmed ) {
|
||||||
gchar gameName[64];
|
send_invites( cGlobals, &inviteAddr, NULL, nPlayers );
|
||||||
snprintf( gameName, VSIZE(gameName), "Game %d", gi->gameID );
|
}
|
||||||
|
} /* handle_invite_button */
|
||||||
|
|
||||||
CommsAddrRec addr;
|
static void
|
||||||
CommsCtxt* comms = cGlobals->game.comms;
|
send_invites( CommonGlobals* cGlobals, const CommsAddrRec* inviteAddr,
|
||||||
XP_ASSERT( comms );
|
const XP_UCHAR* relayID, XP_U16 nPlayers )
|
||||||
comms_getAddr( comms, &addr );
|
{
|
||||||
|
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};
|
InviteInfo invit = {0};
|
||||||
invit_init( &invit, gi, &addr, nPlayers, forceChannel );
|
invit_init( &invit, cGlobals->gi, &addr, nPlayers, forceChannel );
|
||||||
invit_setDevID( &invit, linux_getDevIDRelay( cGlobals->params ) );
|
invit_setDevID( &invit, linux_getDevIDRelay( cGlobals->params ) );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
{
|
{
|
||||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
XWStreamCtxt* stream = mem_stream_make( MPPARM(cGlobals->util->mpool)
|
||||||
cGlobals->params->vtMgr,
|
cGlobals->params->vtMgr,
|
||||||
NULL, CHANNEL_NONE, NULL );
|
NULL, CHANNEL_NONE, NULL );
|
||||||
invit_saveToStream( &invit, stream );
|
invit_saveToStream( &invit, stream );
|
||||||
InviteInfo tmp;
|
InviteInfo tmp;
|
||||||
invit_makeFromStream( &tmp, stream );
|
invit_makeFromStream( &tmp, stream );
|
||||||
stream_destroy( stream );
|
stream_destroy( stream );
|
||||||
XP_ASSERT( 0 == memcmp( &invit, &tmp, sizeof(invit) ) );
|
XP_ASSERT( 0 == memcmp( &invit, &tmp, sizeof(invit) ) );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( addr_hasType( &inviteAddr, COMMS_CONN_SMS ) ) {
|
if ( addr_hasType( inviteAddr, COMMS_CONN_SMS ) ) {
|
||||||
linux_sms_invite( cGlobals->params, gi, &addr, gameName,
|
XP_ASSERT( 0 ); /* not implemented */
|
||||||
nPlayers, forceChannel,
|
/* linux_sms_invite( cGlobals->params, gi, &addr, gameName, */
|
||||||
inviteAddr.u.sms.phone, inviteAddr.u.sms.port );
|
/* 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_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) ) ) { */
|
/* 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 ) { */
|
/* for ( int ii = 0; ii < VSIZE(infos); ++ii ) { */
|
||||||
/* g_free( *infos[ii].result ); */
|
/* g_free( *infos[ii].result ); */
|
||||||
/* } */
|
/* } */
|
||||||
} /* handle_invite_button */
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtkUserError( GtkGameGlobals* globals, const char* format, ... )
|
gtkUserError( GtkGameGlobals* globals, const char* format, ... )
|
||||||
|
@ -1805,8 +1847,7 @@ gtkShowFinalScores( const GtkGameGlobals* globals, XP_Bool ignoreTimeout )
|
||||||
buttons, timeout );
|
buttons, timeout );
|
||||||
free( text );
|
free( text );
|
||||||
if ( 2 == chosen ) {
|
if ( 2 == chosen ) {
|
||||||
XP_LOGF( "%s: rematch chosen!", __func__ );
|
make_rematch( globals->apg, cGlobals );
|
||||||
XP_ASSERT( 0 );
|
|
||||||
}
|
}
|
||||||
} /* gtkShowFinalScores */
|
} /* gtkShowFinalScores */
|
||||||
|
|
||||||
|
@ -1847,7 +1888,7 @@ gtk_util_notifyGameOver( XW_UtilCtxt* uc, XP_S16 quitter )
|
||||||
server_handleUndo( cGlobals->game.server, 0 );
|
server_handleUndo( cGlobals->game.server, 0 );
|
||||||
board_draw( cGlobals->game.board );
|
board_draw( cGlobals->game.board );
|
||||||
} else if ( !cGlobals->params->skipGameOver ) {
|
} else if ( !cGlobals->params->skipGameOver ) {
|
||||||
gtkShowFinalScores( globals, XP_FALSE );
|
gtkShowFinalScores( globals, XP_TRUE );
|
||||||
}
|
}
|
||||||
} /* gtk_util_notifyGameOver */
|
} /* gtk_util_notifyGameOver */
|
||||||
|
|
||||||
|
@ -2785,7 +2826,8 @@ makeNewGame( GtkGameGlobals* globals )
|
||||||
if ( 0 == relayPort ) {
|
if ( 0 == relayPort ) {
|
||||||
relayPort = RELAY_PORT_DEFAULT;
|
relayPort = RELAY_PORT_DEFAULT;
|
||||||
}
|
}
|
||||||
comms_getInitialAddr( &cGlobals->addr, relayName, relayPort );
|
comms_getInitialAddr( &cGlobals->addr, relayName, relayPort,
|
||||||
|
linux_getDevIDRelay( cGlobals->params ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
CurGameInfo* gi = cGlobals->gi;
|
CurGameInfo* gi = cGlobals->gi;
|
||||||
|
|
|
@ -36,7 +36,6 @@ typedef struct _GtkInviteState {
|
||||||
GtkGameGlobals* globals;
|
GtkGameGlobals* globals;
|
||||||
CommsAddrRec* addr;
|
CommsAddrRec* addr;
|
||||||
gint* nPlayersP;
|
gint* nPlayersP;
|
||||||
XP_U32* devIDP;
|
|
||||||
gint maxPlayers;
|
gint maxPlayers;
|
||||||
XP_UCHAR devIDBuf[32];
|
XP_UCHAR devIDBuf[32];
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ handle_ok( GtkWidget* XP_UNUSED(widget), gpointer closure )
|
||||||
#ifdef XWFEATURE_RELAY
|
#ifdef XWFEATURE_RELAY
|
||||||
case COMMS_CONN_RELAY:
|
case COMMS_CONN_RELAY:
|
||||||
txt = gtk_entry_get_text( GTK_ENTRY(state->devID) );
|
txt = gtk_entry_get_text( GTK_ENTRY(state->devID) );
|
||||||
*(state->devIDP) = atoi( txt );
|
state->addr->u.ip_relay.devID = atoi( txt );
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef XWFEATURE_BLUETOOTH
|
#ifdef XWFEATURE_BLUETOOTH
|
||||||
|
@ -276,17 +275,15 @@ onPageChanged( GtkNotebook* XP_UNUSED(notebook), gpointer XP_UNUSED(arg1),
|
||||||
}
|
}
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr, gint* nPlayers,
|
gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr, gint* nPlayersP )
|
||||||
XP_U32* devIDP )
|
|
||||||
{
|
{
|
||||||
GtkInviteState state;
|
GtkInviteState state;
|
||||||
XP_MEMSET( &state, 0, sizeof(state) );
|
XP_MEMSET( &state, 0, sizeof(state) );
|
||||||
|
|
||||||
state.globals = globals;
|
state.globals = globals;
|
||||||
state.addr = addr;
|
state.addr = addr;
|
||||||
state.nPlayersP = nPlayers;
|
state.nPlayersP = nPlayersP;
|
||||||
state.maxPlayers = *nPlayers;
|
state.maxPlayers = *nPlayersP;
|
||||||
state.devIDP = devIDP;
|
|
||||||
|
|
||||||
GtkWidget* dialog;
|
GtkWidget* dialog;
|
||||||
GtkWidget* hbox;
|
GtkWidget* hbox;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
/* return true if not cancelled */
|
/* return true if not cancelled */
|
||||||
XP_Bool gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr,
|
XP_Bool gtkInviteDlg( GtkGameGlobals* globals, CommsAddrRec* addr,
|
||||||
/*inout*/ gint* nPlayers, XP_U32* devID );
|
/*inout*/ gint* nPlayers );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
static void onNewData( GtkAppGlobals* apg, sqlite3_int64 rowid,
|
static void onNewData( GtkAppGlobals* apg, sqlite3_int64 rowid,
|
||||||
XP_Bool isNew );
|
XP_Bool isNew );
|
||||||
static void updateButtons( GtkAppGlobals* apg );
|
static void updateButtons( GtkAppGlobals* apg );
|
||||||
static void open_row( GtkAppGlobals* apg, sqlite3_int64 row );
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recordOpened( GtkAppGlobals* apg, GtkGameGlobals* globals )
|
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,
|
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
|
static void
|
||||||
foreachProc( GtkTreeModel* model, GtkTreePath* XP_UNUSED(path),
|
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 ) ) {
|
if ( gtk_tree_model_get_iter( model, &iter, path ) ) {
|
||||||
sqlite3_int64 rowid;
|
sqlite3_int64 rowid;
|
||||||
gtk_tree_model_get( model, &iter, ROW_ITEM, &rowid, -1 );
|
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, "Ended", OVER_ITEM );
|
||||||
addTextColumn( list, "Turn", TURN_ITEM );
|
addTextColumn( list, "Turn", TURN_ITEM );
|
||||||
addTextColumn( list, "NMoves", NMOVES_ITEM );
|
addTextColumn( list, "NMoves", NMOVES_ITEM );
|
||||||
|
addTextColumn( list, "NTotal", NTOTAL_ITEM );
|
||||||
addTextColumn( list, "NMissing", MISSING_ITEM );
|
addTextColumn( list, "NMissing", MISSING_ITEM );
|
||||||
|
|
||||||
GtkListStore* store = gtk_list_store_new( N_ITEMS,
|
GtkListStore* store = gtk_list_store_new( N_ITEMS,
|
||||||
|
@ -170,6 +170,7 @@ init_games_list( GtkAppGlobals* apg )
|
||||||
G_TYPE_BOOLEAN, /* OVER_ITEM */
|
G_TYPE_BOOLEAN, /* OVER_ITEM */
|
||||||
G_TYPE_INT, /* TURN_ITEM */
|
G_TYPE_INT, /* TURN_ITEM */
|
||||||
G_TYPE_INT, /* NMOVES_ITEM */
|
G_TYPE_INT, /* NMOVES_ITEM */
|
||||||
|
G_TYPE_INT, /* NTOTAL_ITEM */
|
||||||
G_TYPE_INT /* MISSING_ITEM */
|
G_TYPE_INT /* MISSING_ITEM */
|
||||||
);
|
);
|
||||||
gtk_tree_view_set_model( GTK_TREE_VIEW(list), GTK_TREE_MODEL(store) );
|
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,
|
OVER_ITEM, gib->gameOver,
|
||||||
TURN_ITEM, gib->turn,
|
TURN_ITEM, gib->turn,
|
||||||
NMOVES_ITEM, gib->nMoves,
|
NMOVES_ITEM, gib->nMoves,
|
||||||
|
NTOTAL_ITEM, gib->nTotal,
|
||||||
MISSING_ITEM, gib->nMissing,
|
MISSING_ITEM, gib->nMissing,
|
||||||
-1 );
|
-1 );
|
||||||
XP_LOGF( "DONE adding" );
|
XP_LOGF( "DONE adding" );
|
||||||
|
@ -226,7 +228,8 @@ static void updateButtons( GtkAppGlobals* apg )
|
||||||
{
|
{
|
||||||
guint count = apg->selRows->len;
|
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 );
|
gtk_widget_set_sensitive( apg->deleteButton, 1 <= count );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,10 +252,14 @@ handle_newgame_button( GtkWidget* XP_UNUSED(widget), void* closure )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
open_row( GtkAppGlobals* apg, sqlite3_int64 row )
|
open_row( GtkAppGlobals* apg, sqlite3_int64 row, XP_Bool isNew )
|
||||||
{
|
{
|
||||||
if ( -1 != row && !gameIsOpen( apg, row ) ) {
|
if ( -1 != row && !gameIsOpen( apg, row ) ) {
|
||||||
|
if ( isNew ) {
|
||||||
|
onNewData( apg, row, XP_TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
apg->params->needsNewGame = XP_FALSE;
|
apg->params->needsNewGame = XP_FALSE;
|
||||||
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
||||||
initGlobals( globals, apg->params, NULL );
|
initGlobals( globals, apg->params, NULL );
|
||||||
|
@ -267,8 +274,82 @@ static void
|
||||||
handle_open_button( GtkWidget* XP_UNUSED(widget), void* closure )
|
handle_open_button( GtkWidget* XP_UNUSED(widget), void* closure )
|
||||||
{
|
{
|
||||||
GtkAppGlobals* apg = (GtkAppGlobals*)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
|
static void
|
||||||
|
@ -396,6 +477,8 @@ makeGamesWindow( GtkAppGlobals* apg )
|
||||||
(void)addButton( "New game", hbox, G_CALLBACK(handle_newgame_button), apg );
|
(void)addButton( "New game", hbox, G_CALLBACK(handle_newgame_button), apg );
|
||||||
apg->openButton = addButton( "Open", hbox,
|
apg->openButton = addButton( "Open", hbox,
|
||||||
G_CALLBACK(handle_open_button), apg );
|
G_CALLBACK(handle_open_button), apg );
|
||||||
|
apg->rematchButton = addButton( "Rematch", hbox,
|
||||||
|
G_CALLBACK(handle_rematch_button), apg );
|
||||||
apg->deleteButton = addButton( "Delete", hbox,
|
apg->deleteButton = addButton( "Delete", hbox,
|
||||||
G_CALLBACK(handle_delete_button), apg );
|
G_CALLBACK(handle_delete_button), apg );
|
||||||
(void)addButton( "Quit", hbox, G_CALLBACK(handle_quit_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;
|
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
|
||||||
LaunchParams* params = apg->params;
|
LaunchParams* params = apg->params;
|
||||||
|
|
||||||
CurGameInfo gi = {0};
|
XP_U32 gameID = invite->gameID;
|
||||||
gi_copy( MPPARM(params->mpool) &gi, ¶ms->pgi );
|
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_setNPlayers( &gi, invite->nPlayersT, invite->nPlayersH );
|
||||||
gi.gameID = invite->gameID;
|
gi.gameID = gameID;
|
||||||
gi.dictLang = invite->lang;
|
gi.dictLang = invite->lang;
|
||||||
gi.forceChannel = invite->forceChannel;
|
gi.forceChannel = invite->forceChannel;
|
||||||
replaceStringIfDifferent( params->mpool, &gi.dictName, invite->dict );
|
replaceStringIfDifferent( params->mpool, &gi.dictName, invite->dict );
|
||||||
|
|
||||||
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
GtkGameGlobals* globals = malloc( sizeof(*globals) );
|
||||||
params->needsNewGame = XP_FALSE;
|
params->needsNewGame = XP_FALSE;
|
||||||
initGlobals( globals, params, &gi );
|
initGlobals( globals, params, &gi );
|
||||||
|
|
||||||
invit_makeAddrRec( invite, &globals->cGlobals.addr );
|
invit_makeAddrRec( invite, &globals->cGlobals.addr );
|
||||||
// globals->cGlobals.addr = *returnAddr;
|
// globals->cGlobals.addr = *returnAddr;
|
||||||
|
|
||||||
GtkWidget* gameWindow = globals->window;
|
GtkWidget* gameWindow = globals->window;
|
||||||
globals->cGlobals.pDb = apg->params->pDb;
|
globals->cGlobals.pDb = apg->params->pDb;
|
||||||
globals->cGlobals.selRow = -1;
|
globals->cGlobals.selRow = -1;
|
||||||
recordOpened( apg, globals );
|
recordOpened( apg, globals );
|
||||||
gtk_widget_show( gameWindow );
|
gtk_widget_show( gameWindow );
|
||||||
|
|
||||||
gi_disposePlayerInfo( MPPARM(params->mpool) &gi );
|
gi_disposePlayerInfo( MPPARM(params->mpool) &gi );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 GtkAppGlobals* g_globals_for_signal = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -26,5 +26,7 @@
|
||||||
int gtkmain( LaunchParams* params );
|
int gtkmain( LaunchParams* params );
|
||||||
void windowDestroyed( GtkGameGlobals* globals );
|
void windowDestroyed( GtkGameGlobals* globals );
|
||||||
void onGameSaved( void* closure, sqlite3_int64 rowid, XP_Bool firstTime );
|
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
|
#endif
|
||||||
|
|
|
@ -918,6 +918,10 @@ linux_getDevID( LaunchParams* params, DevIDType* typ )
|
||||||
if ( !!params->lDevID ) {
|
if ( !!params->lDevID ) {
|
||||||
result = params->lDevID;
|
result = params->lDevID;
|
||||||
*typ = ID_TYPE_LINUX;
|
*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,
|
} else if ( db_fetch( params->pDb, KEY_LDEVID, params->devIDStore,
|
||||||
sizeof(params->devIDStore) ) ) {
|
sizeof(params->devIDStore) ) ) {
|
||||||
result = params->devIDStore;
|
result = params->devIDStore;
|
||||||
|
|
|
@ -247,9 +247,8 @@ typedef struct _GtkAppGlobals {
|
||||||
GtkWidget* window;
|
GtkWidget* window;
|
||||||
GtkWidget* listWidget;
|
GtkWidget* listWidget;
|
||||||
GtkWidget* openButton;
|
GtkWidget* openButton;
|
||||||
|
GtkWidget* rematchButton;
|
||||||
GtkWidget* deleteButton;
|
GtkWidget* deleteButton;
|
||||||
} GtkAppGlobals;
|
} GtkAppGlobals;
|
||||||
|
|
||||||
sqlite3_int64 getSelRow( const GtkAppGlobals* apg );
|
|
||||||
|
|
||||||
#endif
|
#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 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 void getNetString( const XP_U8** ptr, XP_U16 len, XP_UCHAR* buf );
|
||||||
static XP_U16 getNetShort( const XP_U8** ptr );
|
static XP_U16 getNetShort( const XP_U8** ptr );
|
||||||
#ifdef DEBUG
|
|
||||||
static XP_U32 getNetLong( const XP_U8** ptr );
|
static XP_U32 getNetLong( const XP_U8** ptr );
|
||||||
#endif
|
|
||||||
static int writeHeader( RelayConStorage* storage, XP_U8* dest, XWRelayReg cmd );
|
static int writeHeader( RelayConStorage* storage, XP_U8* dest, XWRelayReg cmd );
|
||||||
static bool readHeader( const XP_U8** buf, MsgHeader* header );
|
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 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 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 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 writeVLI( XP_U8* out, uint32_t nn );
|
||||||
static size_t un2vli( int nn, uint8_t* buf );
|
static size_t un2vli( int nn, uint8_t* buf );
|
||||||
static bool vli2un( const uint8_t** inp, uint32_t* outp );
|
static bool vli2un( const uint8_t** inp, uint32_t* outp );
|
||||||
|
@ -113,7 +113,8 @@ relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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];
|
XP_U8 tmpbuf[256];
|
||||||
int indx = 0;
|
int indx = 0;
|
||||||
|
@ -122,7 +123,17 @@ relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invit )
|
||||||
indx += writeHeader( storage, tmpbuf, XWPDEV_INVITE );
|
indx += writeHeader( storage, tmpbuf, XWPDEV_INVITE );
|
||||||
XP_U32 me = linux_getDevIDRelay( params );
|
XP_U32 me = linux_getDevIDRelay( params );
|
||||||
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, me );
|
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)
|
XWStreamCtxt* stream = mem_stream_make( MPPARM(params->mpool)
|
||||||
params->vtMgr, params,
|
params->vtMgr, params,
|
||||||
|
@ -132,8 +143,7 @@ relaycon_invite( LaunchParams* params, XP_U32 dest, InviteInfo* invit )
|
||||||
indx += writeShort( &tmpbuf[indx], sizeof(tmpbuf) - indx, len );
|
indx += writeShort( &tmpbuf[indx], sizeof(tmpbuf) - indx, len );
|
||||||
XP_ASSERT( indx + len < sizeof(tmpbuf) );
|
XP_ASSERT( indx + len < sizeof(tmpbuf) );
|
||||||
const XP_U8* ptr = stream_getPtr( stream );
|
const XP_U8* ptr = stream_getPtr( stream );
|
||||||
XP_MEMCPY( &tmpbuf[indx], ptr, len );
|
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx, ptr, len );
|
||||||
indx += len;
|
|
||||||
stream_destroy( stream );
|
stream_destroy( stream );
|
||||||
|
|
||||||
sendIt( storage, tmpbuf, indx );
|
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];
|
XP_U8 tmpbuf[1 + 4 + 1 + sizeof(gameToken) + buflen];
|
||||||
int indx = 0;
|
int indx = 0;
|
||||||
indx += writeHeader( storage, tmpbuf, XWPDEV_MSG );
|
indx += writeHeader( storage, tmpbuf, XWPDEV_MSG );
|
||||||
XP_U32 inNBO = htonl(gameToken);
|
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, gameToken );
|
||||||
XP_MEMCPY( &tmpbuf[indx], &inNBO, sizeof(inNBO) );
|
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx, buf, buflen );
|
||||||
indx += sizeof(inNBO);
|
|
||||||
XP_MEMCPY( &tmpbuf[indx], buf, buflen );
|
|
||||||
indx += buflen;
|
|
||||||
nSent = sendIt( storage, tmpbuf, indx );
|
nSent = sendIt( storage, tmpbuf, indx );
|
||||||
if ( nSent > buflen ) {
|
if ( nSent > buflen ) {
|
||||||
nSent = buflen;
|
nSent = buflen;
|
||||||
|
@ -179,14 +186,12 @@ relaycon_sendnoconn( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
|
||||||
1 + idLen +
|
1 + idLen +
|
||||||
sizeof(gameToken) + buflen];
|
sizeof(gameToken) + buflen];
|
||||||
indx += writeHeader( storage, tmpbuf, XWPDEV_MSGNOCONN );
|
indx += writeHeader( storage, tmpbuf, XWPDEV_MSGNOCONN );
|
||||||
gameToken = htonl( gameToken );
|
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, gameToken );
|
||||||
XP_MEMCPY( &tmpbuf[indx], &gameToken, sizeof(gameToken) );
|
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx,
|
||||||
indx += sizeof(gameToken);
|
(const XP_U8*)relayID, idLen );
|
||||||
XP_MEMCPY( &tmpbuf[indx], relayID, idLen );
|
|
||||||
indx += idLen;
|
|
||||||
tmpbuf[indx++] = '\n';
|
tmpbuf[indx++] = '\n';
|
||||||
XP_MEMCPY( &tmpbuf[indx], buf, buflen );
|
indx += writeBytes( &tmpbuf[indx], sizeof(tmpbuf) - indx, buf, buflen );
|
||||||
nSent = sendIt( storage, tmpbuf, sizeof(tmpbuf) );
|
nSent = sendIt( storage, tmpbuf, indx );
|
||||||
if ( nSent > buflen ) {
|
if ( nSent > buflen ) {
|
||||||
nSent = buflen;
|
nSent = buflen;
|
||||||
}
|
}
|
||||||
|
@ -218,9 +223,7 @@ relaycon_deleted( LaunchParams* params, const XP_UCHAR* devID,
|
||||||
int indx = 0;
|
int indx = 0;
|
||||||
indx += writeHeader( storage, tmpbuf, XWPDEV_DELGAME );
|
indx += writeHeader( storage, tmpbuf, XWPDEV_DELGAME );
|
||||||
indx += writeDevID( &tmpbuf[indx], sizeof(tmpbuf) - indx, devID );
|
indx += writeDevID( &tmpbuf[indx], sizeof(tmpbuf) - indx, devID );
|
||||||
gameToken = htonl( gameToken );
|
indx += writeLong( &tmpbuf[indx], sizeof(tmpbuf) - indx, gameToken );
|
||||||
memcpy( &tmpbuf[indx], &gameToken, sizeof(gameToken) );
|
|
||||||
indx += sizeof( gameToken );
|
|
||||||
|
|
||||||
sendIt( storage, tmpbuf, indx );
|
sendIt( storage, tmpbuf, indx );
|
||||||
}
|
}
|
||||||
|
@ -330,7 +333,10 @@ relaycon_receive( GIOChannel* source, GIOCondition XP_UNUSED_DBG(condition), gpo
|
||||||
}
|
}
|
||||||
case XWPDEV_GOTINVITE: {
|
case XWPDEV_GOTINVITE: {
|
||||||
XP_LOGF( "%s(): got XWPDEV_GOTINVITE", __func__ );
|
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 );
|
XP_U16 len = getNetShort( &ptr );
|
||||||
XWStreamCtxt* stream = mem_stream_make( MPPARM(storage->params->mpool)
|
XWStreamCtxt* stream = mem_stream_make( MPPARM(storage->params->mpool)
|
||||||
storage->params->vtMgr, storage,
|
storage->params->vtMgr, storage,
|
||||||
|
@ -438,7 +444,7 @@ writeShort( XP_U8* buf, size_t len, XP_U16 shrt )
|
||||||
{
|
{
|
||||||
shrt = htons( shrt );
|
shrt = htons( shrt );
|
||||||
assert( sizeof( shrt ) <= len );
|
assert( sizeof( shrt ) <= len );
|
||||||
memcpy( buf, &shrt, sizeof(shrt) );
|
XP_MEMCPY( buf, &shrt, sizeof(shrt) );
|
||||||
return sizeof(shrt);
|
return sizeof(shrt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +457,14 @@ writeLong( XP_U8* buf, size_t len, XP_U32 lng )
|
||||||
return sizeof(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
|
static size_t
|
||||||
writeVLI( XP_U8* out, uint32_t nn )
|
writeVLI( XP_U8* out, uint32_t nn )
|
||||||
{
|
{
|
||||||
|
@ -469,7 +483,6 @@ getNetShort( const XP_U8** ptr )
|
||||||
return ntohs( result );
|
return ntohs( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static XP_U32
|
static XP_U32
|
||||||
getNetLong( const XP_U8** ptr )
|
getNetLong( const XP_U8** ptr )
|
||||||
{
|
{
|
||||||
|
@ -478,7 +491,6 @@ getNetLong( const XP_U8** ptr )
|
||||||
*ptr += sizeof(result);
|
*ptr += sizeof(result);
|
||||||
return ntohl( result );
|
return ntohl( result );
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
getNetString( const XP_U8** ptr, XP_U16 len, XP_UCHAR* buf )
|
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* procsClosure, const char* host, int port );
|
||||||
void relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
|
void relaycon_reg( LaunchParams* params, const XP_UCHAR* rDevID,
|
||||||
DevIDType typ, const XP_UCHAR* devID );
|
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_S16 relaycon_send( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
|
||||||
XP_U32 gameToken, const CommsAddrRec* addrRec );
|
XP_U32 gameToken, const CommsAddrRec* addrRec );
|
||||||
XP_S16 relaycon_sendnoconn( LaunchParams* params, const XP_U8* buf,
|
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 );
|
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
|
DevIDRelay
|
||||||
DBMgr::getDevID( const char* connName, int hid )
|
DBMgr::getDevID( const char* connName, int hid )
|
||||||
{
|
{
|
||||||
|
|
|
@ -146,6 +146,8 @@ class DBMgr {
|
||||||
void RemoveStoredMessage( const int msgID );
|
void RemoveStoredMessage( const int msgID );
|
||||||
void RemoveStoredMessages( vector<int>& ids );
|
void RemoveStoredMessages( vector<int>& ids );
|
||||||
|
|
||||||
|
DevIDRelay getDevID( string& relayID );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DBMgr();
|
DBMgr();
|
||||||
bool execSql( const string& query );
|
bool execSql( const string& query );
|
||||||
|
|
|
@ -1779,17 +1779,24 @@ handle_udp_packet( UdpThreadClosure* utc )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case XWPDEV_INVITE:
|
case XWPDEV_INVITE: {
|
||||||
DevIDRelay sender;
|
DevIDRelay sender;
|
||||||
DevIDRelay invitee;
|
string relayID;
|
||||||
if ( getNetLong( &ptr, end, &sender )
|
if ( getNetLong( &ptr, end, &sender )
|
||||||
&& getNetLong( &ptr, end, &invitee) ) {
|
&& 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",
|
logf( XW_LOGVERBOSE0, "got invite from %d for %d",
|
||||||
sender, invitee );
|
sender, invitee );
|
||||||
post_invite( sender, invitee, ptr, end - ptr );
|
post_invite( sender, invitee, ptr, end - ptr );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case XWPDEV_KEEPALIVE:
|
case XWPDEV_KEEPALIVE:
|
||||||
case XWPDEV_RQSTMSGS: {
|
case XWPDEV_RQSTMSGS: {
|
||||||
DevID devID( ID_TYPE_RELAY );
|
DevID devID( ID_TYPE_RELAY );
|
||||||
|
|
Loading…
Add table
Reference in a new issue