snapshot: still not correctly recording return address

This commit is contained in:
Eric House 2013-12-16 08:06:29 -08:00
parent f1f13c65a2
commit 8d20c33b76
13 changed files with 257 additions and 350 deletions

View file

@ -1776,7 +1776,7 @@ cursesGotBuf( void* closure, const XP_U8* buf, XP_U16 len )
rowidFromToken( XP_NTOHL( clientToken ), &ignore, &seed );
XP_ASSERT( seed == comms_getChannelSeed( globals->cGlobals.game.comms ) );
if ( seed == comms_getChannelSeed( globals->cGlobals.game.comms ) ) {
gameGotBuf( &globals->cGlobals, XP_TRUE, buf, len );
gameGotBuf( &globals->cGlobals, XP_TRUE, buf, len, NULL );
} else {
XP_LOGF( "%s: dropping packet; meant for a different device",
__func__ );

View file

@ -42,6 +42,7 @@ openGamesDB( const char* dbName )
",turn INT(2)"
",nmoves INT"
",seed INT"
",gameid INT"
",nmissing INT(2)"
")";
result = sqlite3_exec( pDb, createGamesStr, NULL, NULL, NULL );
@ -121,6 +122,8 @@ summarize( CommonGlobals* cGlobals )
XP_S16 turn = server_getCurrentTurn( cGlobals->game.server );
XP_U16 seed = 0;
XP_S16 nMissing = 0;
XP_U32 gameID = cGlobals->gi->gameID;
XP_ASSERT( 0 != gameID );
CommsAddrRec addr = {0};
gchar* room = "";
@ -148,11 +151,11 @@ summarize( CommonGlobals* cGlobals )
}
const char* fmt = "UPDATE games "
" SET room='%s', ended=%d, turn=%d, nmissing=%d, nmoves=%d, seed=%d, connvia='%s'"
" SET room='%s', ended=%d, turn=%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, connvia, cGlobals->selRow );
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 );
@ -200,7 +203,7 @@ 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 "
const char* fmt = "SELECT room, ended, turn, nmoves, nmissing, seed, connvia, gameid "
"FROM games WHERE rowid = %lld";
XP_UCHAR query[256];
snprintf( query, sizeof(query), fmt, rowid );
@ -218,12 +221,38 @@ getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
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 );
snprintf( gib->name, sizeof(gib->name), "Game %lld", rowid );
}
sqlite3_finalize( ppStmt );
return success;
}
void
getRowsForGameID( sqlite3* pDb, XP_U32 gameID, sqlite3_int64* rowids,
int* nRowIDs )
{
int maxRowIDs = *nRowIDs;
*nRowIDs = 0;
char buf[256];
snprintf( buf, sizeof(buf), "SELECT rowid from games WHERE gameid = %ld LIMIT %d",
gameID, maxRowIDs );
sqlite3_stmt *ppStmt;
int result = sqlite3_prepare_v2( pDb, buf, -1, &ppStmt, NULL );
XP_ASSERT( SQLITE_OK == result );
int ii;
for ( ii = 0; ii < maxRowIDs; ++ii ) {
result = sqlite3_step( ppStmt );
if ( SQLITE_ROW != result ) {
break;
}
rowids[ii] = sqlite3_column_int64( ppStmt, 0 );
++*nRowIDs;
}
sqlite3_finalize( ppStmt );
}
XP_Bool
loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid )
{

View file

@ -31,6 +31,7 @@ typedef struct _GameInfo {
XP_UCHAR name[128];
XP_UCHAR room[128];
XP_UCHAR conn[8];
XP_U32 gameID;
XP_S16 nMoves;
XP_Bool gameOver;
XP_S16 turn;
@ -48,6 +49,8 @@ void summarize( CommonGlobals* cGlobals );
/* Return GSList whose data is (ptrs to) rowids */
GSList* listGames( sqlite3* dbp );
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 deleteGame( sqlite3* pDb, sqlite3_int64 rowid );

View file

@ -12,7 +12,7 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
n *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@ -53,7 +53,7 @@ gtkaskm( const gchar* message, AskMInfo* infos, int nInfos )
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
for ( ii = 0; ii < nInfos; ++ii ) {
AskMInfo* info = &infos[ii];
GtkWidget* row = makeLabeledField( info->label, &fields[ii] );
GtkWidget* row = makeLabeledField( info->label, &fields[ii], *info->result );
gtk_box_pack_start( GTK_BOX(vbox), row, FALSE, TRUE, 0 );
gtk_widget_show( row );
}

View file

@ -506,9 +506,9 @@ createOrLoadObjects( GtkGameGlobals* globals )
&cGlobals->cp, &procs, params->gameSeed );
// addr.conType = params->conType;
if ( 0 ) {
switch( addr.conType ) {
#ifdef XWFEATURE_RELAY
} else if ( addr.conType == COMMS_CONN_RELAY ) {
case COMMS_CONN_RELAY:
/* addr.u.ip_relay.ipAddr = 0; */
/* addr.u.ip_relay.port = params->connInfo.relay.defaultSendPort; */
/* addr.u.ip_relay.seeksPublicRoom = params->connInfo.relay.seeksPublicRoom; */
@ -517,26 +517,32 @@ createOrLoadObjects( GtkGameGlobals* globals )
/* sizeof(addr.u.ip_relay.hostName) - 1 ); */
/* XP_STRNCPY( addr.u.ip_relay.invite, params->connInfo.relay.invite, */
/* sizeof(addr.u.ip_relay.invite) - 1 ); */
break;
#endif
#ifdef XWFEATURE_BLUETOOTH
} else if ( addr.conType == COMMS_CONN_BT ) {
case COMMS_CONN_BT:
XP_ASSERT( sizeof(addr.u.bt.btAddr)
>= sizeof(params->connInfo.bt.hostAddr));
XP_MEMCPY( &addr.u.bt.btAddr, &params->connInfo.bt.hostAddr,
sizeof(params->connInfo.bt.hostAddr) );
break;
#endif
#ifdef XWFEATURE_IP_DIRECT
} else if ( addr.conType == COMMS_CONN_IP_DIRECT ) {
case COMMS_CONN_IP_DIRECT:
XP_STRNCPY( addr.u.ip.hostName_ip, params->connInfo.ip.hostName,
sizeof(addr.u.ip.hostName_ip) - 1 );
addr.u.ip.port_ip = params->connInfo.ip.port;
break;
#endif
#ifdef XWFEATURE_SMS
} else if ( addr.conType == COMMS_CONN_SMS ) {
case COMMS_CONN_SMS:
XP_STRNCPY( addr.u.sms.phone, params->connInfo.sms.phone,
sizeof(addr.u.sms.phone) - 1 );
addr.u.sms.port = params->connInfo.sms.port;
break;
#endif
default:
break;
}
/* Need to save in order to have a valid selRow for the first send */
@ -556,7 +562,6 @@ createOrLoadObjects( GtkGameGlobals* globals )
cGlobals->gi->allowHintRect = params->allowHintRect;
#endif
if ( params->needsNewGame ) {
new_game_impl( globals, XP_FALSE );
#ifndef XWFEATURE_STANDALONE_ONLY
@ -587,6 +592,7 @@ createOrLoadObjects( GtkGameGlobals* globals )
}
#endif
server_do( globals->cGlobals.game.server );
saveGame( cGlobals ); /* again, to include address etc. */
disenable_buttons( globals );
} /* createOrLoadObjects */
@ -1462,24 +1468,24 @@ handle_invite_button( GtkWidget* XP_UNUSED(widget), GtkGameGlobals* globals )
switch ( comms_getConType( comms ) ) {
#ifdef XWFEATURE_SMS
case COMMS_CONN_SMS: {
gchar* phone = NULL;
gchar* portstr = NULL;
AskMInfo infos[] = {
{ "Remote phone#", &phone },
{ "Remote port", &portstr },
};
if ( gtkaskm( "Invite whom?", infos, VSIZE(infos) ) ) {
int port = atoi( portstr );
XP_LOGF( "need to invite using number %s and port %d", phone, port );
XP_ASSERT( 0 != port );
const CurGameInfo* gi = globals->cGlobals.gi;
gchar gameName[64];
snprintf( gameName, VSIZE(gameName), "Game %ld", gi->gameID );
linux_sms2_invite( globals->cGlobals.params, gi, gameName, 1,
phone, port );
}
g_free( phone );
g_free( portstr );
gchar* phone = NULL;
gchar* portstr = NULL;
AskMInfo infos[] = {
{ "Remote phone#", &phone },
{ "Remote port", &portstr },
};
if ( gtkaskm( "Invite whom?", infos, VSIZE(infos) ) ) {
int port = atoi( portstr );
XP_LOGF( "need to invite using number %s and port %d", phone, port );
XP_ASSERT( 0 != port );
const CurGameInfo* gi = globals->cGlobals.gi;
gchar gameName[64];
snprintf( gameName, VSIZE(gameName), "Game %ld", gi->gameID );
linux_sms2_invite( globals->cGlobals.params, gi, gameName, 1,
phone, port );
}
g_free( phone );
g_free( portstr );
}
break;
#endif

View file

@ -171,7 +171,7 @@ makeRelayPage( GtkConnsState* state )
gtk_box_pack_start( GTK_BOX(vbox), gtk_label_new( hint ), FALSE, TRUE, 0 );
GtkWidget* hbox = makeLabeledField( "Room", &state->invite );
GtkWidget* hbox = makeLabeledField( "Room", &state->invite, NULL );
if ( COMMS_CONN_RELAY == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->invite),
state->addr->u.ip_relay.invite );
@ -179,7 +179,7 @@ makeRelayPage( GtkConnsState* state )
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->invite, !state->readOnly );
hbox = makeLabeledField( "Relay address", &state->hostName );
hbox = makeLabeledField( "Relay address", &state->hostName, NULL );
if ( COMMS_CONN_RELAY == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->hostName),
state->addr->u.ip_relay.hostName );
@ -187,7 +187,7 @@ makeRelayPage( GtkConnsState* state )
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->hostName, !state->readOnly );
hbox = makeLabeledField( "Relay port", &state->port );
hbox = makeLabeledField( "Relay port", &state->port, NULL );
if ( COMMS_CONN_RELAY == state->addr->conType ) {
char buf[16];
snprintf( buf, sizeof(buf), "%d", state->addr->u.ip_relay.port );
@ -206,7 +206,7 @@ makeBTPage( GtkConnsState* state )
{
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
GtkWidget* hbox = makeLabeledField( "Host device", &state->bthost );
GtkWidget* hbox = makeLabeledField( "Host device", &state->bthost, NULL );
if ( COMMS_CONN_BT == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->bthost), state->addr->u.bt.hostName );
}
@ -227,19 +227,18 @@ makeSMSPage( GtkConnsState* state )
{
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
GtkWidget* hbox = makeLabeledField( "Host phone", &state->smsphone );
if ( COMMS_CONN_SMS == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->smsphone), state->addr->u.sms.phone );
}
const gchar* phone = COMMS_CONN_SMS == state->addr->conType ?
state->addr->u.sms.phone : state->globals->cGlobals.params->connInfo.sms.phone;
GtkWidget* hbox = makeLabeledField( "Host phone", &state->smsphone, phone );
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->smsphone, !state->readOnly );
hbox = makeLabeledField( "Host port", &state->smsport );
if ( COMMS_CONN_SMS == state->addr->conType ) {
gchar port[32];
snprintf( port, sizeof(port), "%d", state->addr->u.sms.port );
gtk_entry_set_text( GTK_ENTRY(state->smsport), port );
}
int portVal = COMMS_CONN_SMS == state->addr->conType
? state->addr->u.sms.port
: state->globals->cGlobals.params->connInfo.sms.port;
gchar port[32];
snprintf( port, sizeof(port), "%d", portVal );
hbox = makeLabeledField( "Host port", &state->smsport, port );
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->smsport, !state->readOnly );

View file

@ -75,7 +75,7 @@ findOpenGame( const GtkAppGlobals* apg, sqlite3_int64 rowid )
return result;
}
enum { ROW_ITEM, NAME_ITEM, ROOM_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 };
static void
@ -136,6 +136,7 @@ init_games_list( GtkAppGlobals* apg )
addTextColumn( list, "Row", ROW_ITEM );
addTextColumn( list, "Name", NAME_ITEM );
addTextColumn( list, "Room", ROOM_ITEM );
addTextColumn( list, "GameID", GAMEID_ITEM );
addTextColumn( list, "Seed", SEED_ITEM );
addTextColumn( list, "Conn. via", CONN_ITEM );
addTextColumn( list, "Ended", OVER_ITEM );
@ -147,6 +148,7 @@ init_games_list( GtkAppGlobals* apg )
G_TYPE_INT64, /* ROW_ITEM */
G_TYPE_STRING, /* NAME_ITEM */
G_TYPE_STRING, /* ROOM_ITEM */
G_TYPE_INT, /* GAMEID_ITEM */
G_TYPE_INT, /* SEED_ITEM */
G_TYPE_STRING, /* CONN_ITEM */
G_TYPE_BOOLEAN, /* OVER_ITEM */
@ -190,6 +192,7 @@ add_to_list( GtkWidget* list, sqlite3_int64 rowid, XP_Bool isNew,
ROW_ITEM, rowid,
NAME_ITEM, gib->name,
ROOM_ITEM, gib->room,
GAMEID_ITEM, gib->gameID,
SEED_ITEM, gib->seed,
CONN_ITEM, gib->conn,
OVER_ITEM, gib->gameOver,
@ -323,11 +326,8 @@ makeGamesWindow( GtkAppGlobals* apg )
strcat( title, params->dbName );
}
#ifdef XWFEATURE_SMS
gchar buf[32];
if ( db_fetch( params->pDb, KEY_SMSPHONE, buf, VSIZE(buf) ) ) {
int len = strlen( title );
snprintf( &title[len], VSIZE(title) - len, " (phone: %s)", buf );
}
int len = strlen( title );
snprintf( &title[len], VSIZE(title) - len, " (phone: %s)", params->connInfo.sms.phone );
#endif
gtk_window_set_title( GTK_WINDOW(window), title );
@ -390,6 +390,28 @@ onNewData( GtkAppGlobals* apg, sqlite3_int64 rowid, XP_Bool isNew )
}
}
static XP_U16
feedBuffer( GtkAppGlobals* apg, sqlite3_int64 rowid,
const XP_U8* buf, XP_U16 len, const CommsAddrRec* from )
{
XP_U16 seed = 0;
GtkGameGlobals* globals = findOpenGame( apg, rowid );
if ( !!globals ) {
gameGotBuf( &globals->cGlobals, XP_TRUE, buf, len, from );
seed = comms_getChannelSeed( globals->cGlobals.game.comms );
} else {
GtkGameGlobals tmpGlobals;
if ( loadGameNoDraw( &tmpGlobals, apg->params, rowid ) ) {
gameGotBuf( &tmpGlobals.cGlobals, XP_FALSE, buf, len, from );
seed = comms_getChannelSeed( tmpGlobals.cGlobals.game.comms );
saveGame( &tmpGlobals.cGlobals );
}
freeGlobals( &tmpGlobals );
}
return seed;
}
static gboolean
gtk_app_socket_proc( GIOChannel* source, GIOCondition condition, gpointer data )
{
@ -480,20 +502,7 @@ gtkGotBuf( void* closure, const XP_U8* buf, XP_U16 len )
XP_U16 gotSeed;
rowidFromToken( ntohl( clientToken ), &rowid, &gotSeed );
XP_U16 seed = 0;
GtkGameGlobals* globals = findOpenGame( apg, rowid );
if ( !!globals ) {
gameGotBuf( &globals->cGlobals, XP_TRUE, buf, len );
seed = comms_getChannelSeed( globals->cGlobals.game.comms );
} else {
GtkGameGlobals tmpGlobals;
if ( loadGameNoDraw( &tmpGlobals, apg->params, rowid ) ) {
gameGotBuf( &tmpGlobals.cGlobals, XP_FALSE, buf, len );
seed = comms_getChannelSeed( tmpGlobals.cGlobals.game.comms );
saveGame( &tmpGlobals.cGlobals );
}
freeGlobals( &tmpGlobals );
}
XP_U16 seed = feedBuffer( apg, rowid, buf, len, NULL );
XP_ASSERT( seed == 0 || gotSeed == seed );
XP_USE( seed );
}
@ -521,14 +530,14 @@ gtkNoticeRcvd( void* closure )
}
static void
gtkInviteReceived( void* closure, const XP_UCHAR* gameName, XP_U32 gameID,
smsInviteReceived( void* closure, const XP_UCHAR* gameName, XP_U32 gameID,
XP_U16 dictLang, const XP_UCHAR* dictName, XP_U16 nPlayers,
XP_U16 nHere )
XP_U16 nHere, const CommsAddrRec* returnAddr )
{
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
LaunchParams* params = apg->params;
XP_LOGF( "%s(gameName=%s, dictName=%s, nPlayers=%d, nHere=%d)", __func__,
gameName, dictName, nPlayers, nHere );
XP_LOGF( "%s(gameName=%s, gameID=%ld, dictName=%s, nPlayers=%d, nHere=%d)",
__func__, gameName, gameID, dictName, nPlayers, nHere );
CurGameInfo gi = {0};
gi_copy( MPPARM(params->mpool) &gi, &params->pgi );
@ -541,9 +550,7 @@ gtkInviteReceived( void* closure, const XP_UCHAR* gameName, XP_U32 gameID,
GtkGameGlobals* globals = malloc( sizeof(*globals) );
params->needsNewGame = XP_FALSE;
initGlobals( globals, params, &gi );
/* if ( !makeNewGame( globals ) ) { */
/* } */
globals->cGlobals.addr = *returnAddr;
GtkWidget* gameWindow = globals->window;
globals->cGlobals.pDb = apg->params->pDb;
@ -552,6 +559,23 @@ gtkInviteReceived( void* closure, const XP_UCHAR* gameName, XP_U32 gameID,
gtk_widget_show( gameWindow );
}
static void
smsMsgReceived( void* closure, XP_U32 gameID, const XP_U8* buf, XP_U16 len,
const CommsAddrRec* from )
{
LOG_FUNC();
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
LaunchParams* params = apg->params;
sqlite3_int64 rowids[4];
int nRowIDs = VSIZE(rowids);
getRowsForGameID( params->pDb, gameID, rowids, &nRowIDs );
int ii;
for ( ii = 0; ii < nRowIDs; ++ii ) {
feedBuffer( apg, rowids[ii], buf, len, from );
}
}
static gboolean
keepalive_timer( gpointer data )
{
@ -660,12 +684,13 @@ gtkmain( LaunchParams* params )
if ( !!phone ) {
db_store( params->pDb, KEY_SMSPHONE, phone );
} else if ( !phone && db_fetch( params->pDb, KEY_SMSPHONE, buf, VSIZE(buf) ) ) {
phone = buf;
params->connInfo.sms.phone = phone = buf;
}
if ( !!phone ) {
SMSProcs smsProcs = {
.socketChanged = gtkSocketChanged,
.inviteReceived = gtkInviteReceived,
.inviteReceived = smsInviteReceived,
.msgReceived = smsMsgReceived,
};
linux_sms2_init( params, phone, &smsProcs, &apg );
} else {

View file

@ -35,13 +35,17 @@ makeButton( char* text, GCallback func, gpointer data )
GtkWidget*
makeLabeledField( const char* labelText, GtkWidget** field )
makeLabeledField( const char* labelText, GtkWidget** field,
const gchar* initialVal )
{
char buf[64];
snprintf( buf, sizeof(buf), "%s:", labelText );
GtkWidget* label = gtk_label_new( buf );
*field = gtk_entry_new();
if ( !!initialVal ) {
gtk_entry_set_text( GTK_ENTRY(*field), initialVal );
}
GtkWidget* hbox = gtk_hbox_new( FALSE, 0 );
gtk_box_pack_start( GTK_BOX(hbox), label, FALSE, TRUE, 0 );

View file

@ -27,7 +27,8 @@
#include "gtkboard.h"
GtkWidget* makeButton( char* text, GCallback func, gpointer data );
GtkWidget* makeLabeledField( const char* labelText, GtkWidget** field );
GtkWidget* makeLabeledField( const char* labelText, GtkWidget** field,
const gchar* initialVal );
#endif /* _GTKUTILS_H_ */
#endif /* PLATFORM_GTK */

View file

@ -174,14 +174,14 @@ makeDictForStream( CommonGlobals* cGlobals, XWStreamCtxt* stream )
void
gameGotBuf( CommonGlobals* cGlobals, XP_Bool hasDraw, const XP_U8* buf,
XP_U16 len )
XP_U16 len, const CommsAddrRec* from )
{
XP_LOGF( "%s(hasDraw=%d)", __func__, hasDraw );
XP_Bool redraw = XP_FALSE;
XWGame* game = &cGlobals->game;
XWStreamCtxt* stream = stream_from_msgbuf( cGlobals, buf, len );
if ( !!stream ) {
if ( comms_checkIncomingStream( game->comms, stream, NULL ) ) {
if ( comms_checkIncomingStream( game->comms, stream, from ) ) {
redraw = server_receiveMessage( game->server, stream );
if ( redraw ) {
saveGame( cGlobals );
@ -1134,7 +1134,7 @@ linux_reset( void* closure )
XP_S16
linux_send( const XP_U8* buf, XP_U16 buflen, const CommsAddrRec* addrRec,
XP_U32 XP_UNUSED(gameID), void* closure )
XP_U32 gameID, void* closure )
{
XP_S16 nSent = -1;
CommonGlobals* cGlobals = (CommonGlobals*)closure;
@ -1180,7 +1180,8 @@ linux_send( const XP_U8* buf, XP_U16 buflen, const CommsAddrRec* addrRec,
addrRec = &addr;
}
nSent = linux_sms2_send( cGlobals->params, buf, buflen,
addrRec->u.sms.phone, addrRec->u.sms.port );
addrRec->u.sms.phone, addrRec->u.sms.port,
gameID );
#endif
} else {
XP_ASSERT(0);
@ -1406,12 +1407,14 @@ linux_util_addrChange( XW_UtilCtxt* uc,
#endif
#ifdef XWFEATURE_SMS
case COMMS_CONN_SMS:
XP_ASSERT(0);
/* nothing to do??? */
// XP_ASSERT(0);
// linux_sms_init( cGlobals, newAddr );
break;
#endif
default:
XP_ASSERT(0);
// XP_ASSERT(0);
break;
}
}

View file

@ -103,7 +103,7 @@ void linuxChangeRoles( CommonGlobals* cGlobals );
void sendRelayReg( LaunchParams* params, sqlite3* pDb );
void gameGotBuf( CommonGlobals* globals, XP_Bool haveDraw,
const XP_U8* buf, XP_U16 len );
const XP_U8* buf, XP_U16 len, const CommsAddrRec* from );
gboolean app_socket_proc( GIOChannel* source, GIOCondition condition,
gpointer data );
const XP_UCHAR* linux_getDevID( LaunchParams* params, DevIDType* typ );

View file

@ -59,214 +59,6 @@ makeQueuePath( const XP_UCHAR* phone, XP_U16 port,
snprintf( path, pathlen, "%s/%s_%d", SMS_DIR, phone, port );
}
#if 0
struct LinSMSData {
XP_UCHAR myPhone[MAX_PHONE_LEN+1];
XP_UCHAR myQueue[256];
FILE* lock;
int wd, fd; /* for inotify */
void* storage;
XP_U16 count;
XP_U16 port;
XP_Bool amServer;
};
static void
lock_queue( LinSMSData* data )
{
char lock[256];
snprintf( lock, sizeof(lock), "%s/%s", data->myQueue, LOCK_FILE );
FILE* fp = fopen( lock, "w" );
XP_ASSERT( NULL == data->lock );
data->lock = fp;
}
static void
unlock_queue( LinSMSData* data )
{
XP_ASSERT( NULL != data->lock );
fclose( data->lock );
data->lock = NULL;
}
void
linux_sms_init( CommonGlobals* globals, const CommsAddrRec* addr )
{
LinSMSData* data = globals->smsData;
if ( !data ) {
data = XP_MALLOC( globals->util->mpool, sizeof(*data) );
XP_ASSERT( !!data );
XP_MEMSET( data, 0, sizeof(*data) );
globals->smsData = data;
data->amServer = comms_getIsServer( globals->game.comms );
if ( data->amServer ) {
XP_STRNCPY( data->myPhone, addr->u.sms.phone,
sizeof(data->myPhone) );
} else {
snprintf( data->myPhone, sizeof(data->myPhone), "%.6d", getpid() );
}
makeQueuePath( data->myPhone, addr->u.sms.port,
data->myQueue, sizeof(data->myQueue) );
data->port = addr->u.sms.port;
(void)g_mkdir_with_parents( data->myQueue, 0777 );
int fd = inotify_init();
data->fd = fd;
data->wd = inotify_add_watch( fd, data->myQueue, IN_MODIFY );
(*globals->socketChanged)( globals, -1, fd, &data->storage );
}
} /* linux_sms_init */
void
linux_sms_close( CommonGlobals* globals )
{
LinSMSData* data = globals->smsData;
if ( !!data ) {
XP_FREE( globals->util->mpool, data );
globals->smsData = NULL;
}
} /* linux_sms_close */
XP_S16
linux_sms_send( CommonGlobals* globals,
const XP_U8* buf, XP_U16 buflen,
const XP_UCHAR* phone, XP_U16 port )
{
XP_S16 nSent = -1;
LinSMSData* data = globals->smsData;
XP_ASSERT( !!data );
char path[256];
lock_queue( data );
#ifdef DEBUG
gchar* str64 = g_base64_encode( buf, buflen );
#endif
makeQueuePath( phone, port, path, sizeof(path) );
g_mkdir_with_parents( path, 0777 ); /* just in case */
int len = strlen( path );
snprintf( &path[len], sizeof(path)-len, "/%d", ++data->count );
XP_UCHAR sms[buflen*2]; /* more like (buflen*4/3) */
XP_U16 smslen = sizeof(sms);
binToSms( sms, &smslen, buf, buflen );
XP_ASSERT( smslen == strlen(sms) );
#ifdef DEBUG
XP_ASSERT( !strcmp( str64, sms ) );
g_free( str64 );
XP_U8 testout[buflen];
XP_U16 lenout = sizeof( testout );
XP_ASSERT( smsToBin( testout, &lenout, sms, smslen ) );
XP_ASSERT( lenout == buflen );
XP_ASSERT( XP_MEMCMP( testout, buf, smslen ) );
#endif
FILE* fp = fopen( path, "w" );
XP_ASSERT( !!fp );
(void)fprintf( fp, "from: %s\n", data->myPhone );
(void)fprintf( fp, "%s\n", sms );
fclose( fp );
sync();
unlock_queue( data );
nSent = buflen;
return nSent;
} /* linux_sms_send */
static XP_S16
decodeAndDelete( LinSMSData* data, const gchar* name,
XP_U8* buf, XP_U16 buflen, CommsAddrRec* addr )
{
XP_S16 nRead = -1;
char path[256];
snprintf( path, sizeof(path), "%s/%s", data->myQueue, name );
gchar* contents;
gsize length;
#ifdef DEBUG
gboolean success =
#endif
g_file_get_contents( path, &contents, &length, NULL );
XP_ASSERT( success );
unlink( path );
if ( 0 == strncmp( "from: ", contents, 6 ) ) {
gchar* eol = strstr( contents, "\n" );
*eol = '\0';
XP_STRNCPY( addr->u.sms.phone, &contents[6], sizeof(addr->u.sms.phone) );
XP_ASSERT( !*eol );
++eol; /* skip NULL */
*strstr(eol, "\n" ) = '\0';
XP_U16 inlen = strlen(eol); /* skip \n */
XP_U8 out[inlen];
XP_U16 outlen = sizeof(out);
XP_Bool valid = smsToBin( out, &outlen, eol, inlen );
if ( valid && outlen <= buflen ) {
XP_MEMCPY( buf, out, outlen );
nRead = outlen;
addr->conType = COMMS_CONN_SMS;
addr->u.sms.port = data->port;
}
}
g_free( contents );
return nRead;
} /* decodeAndDelete */
XP_S16
linux_sms_receive( CommonGlobals* globals, int sock,
XP_U8* buf, XP_U16 buflen, CommsAddrRec* addr )
{
XP_S16 nRead = -1;
LinSMSData* data = globals->smsData;
XP_ASSERT( sock == data->fd );
lock_queue( data );
/* read required or we'll just get the event again. But we don't care
about the result or the buffer contents. */
XP_U8 buffer[sizeof(struct inotify_event) + 16];
if ( 0 > read( sock, buffer, sizeof(buffer) ) ) {
}
char shortest[256] = { '\0' };
GDir* dir = g_dir_open( data->myQueue, 0, NULL );
for ( ; ; ) {
const gchar* name = g_dir_read_name( dir );
if ( NULL == name ) {
break;
} else if ( 0 == strcmp( name, LOCK_FILE ) ) {
continue;
}
if ( !shortest[0] || 0 < strcmp( shortest, name ) ) {
snprintf( shortest, sizeof(shortest), "%s", name );
}
}
g_dir_close( dir );
if ( !!shortest[0] ) {
nRead = decodeAndDelete( data, shortest, buf, buflen, addr );
}
unlock_queue( data );
return nRead;
} /* linux_sms_receive */
#endif
typedef struct _LinSMS2Data {
int fd, wd;
XP_UCHAR myQueue[256];
@ -284,45 +76,50 @@ typedef enum { NONE, INVITE, DATA, DEATH, ACK, } SMS_CMD;
static LinSMS2Data* getStorage( LaunchParams* params );
static void writeHeader( XWStreamCtxt* stream, SMS_CMD cmd );
static void
lock_queue2( LinSMS2Data* data )
lock_queue2( LinSMS2Data* storage )
{
char lock[256];
snprintf( lock, sizeof(lock), "%s/%s", data->myQueue, LOCK_FILE );
snprintf( lock, sizeof(lock), "%s/%s", storage->myQueue, LOCK_FILE );
FILE* fp = fopen( lock, "w" );
XP_ASSERT( NULL == data->lock );
data->lock = fp;
XP_ASSERT( NULL == storage->lock );
storage->lock = fp;
}
static void
unlock_queue2( LinSMS2Data* data )
unlock_queue2( LinSMS2Data* storage )
{
XP_ASSERT( NULL != data->lock );
fclose( data->lock );
data->lock = NULL;
XP_ASSERT( NULL != storage->lock );
fclose( storage->lock );
storage->lock = NULL;
}
XP_S16
linux_sms_send2( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
const XP_UCHAR* phone, XP_U16 port )
static XP_S16
send_sms( LinSMS2Data* storage, XWStreamCtxt* stream,
const XP_UCHAR* phone, XP_U16 port )
{
const XP_U8* buf = stream_getPtr( stream );
XP_U16 buflen = stream_getSize( stream );
XP_S16 nSent = -1;
LinSMS2Data* data = getStorage( params );
XP_ASSERT( !!data );
XP_ASSERT( !!storage );
char path[256];
lock_queue2( data );
lock_queue2( storage );
#ifdef DEBUG
gchar* str64 = g_base64_encode( buf, buflen );
#endif
makeQueuePath( phone, port, path, sizeof(path) );
XP_LOGF( "%s: writing to %s", __func__, path );
g_mkdir_with_parents( path, 0777 ); /* just in case */
int len = strlen( path );
snprintf( &path[len], sizeof(path)-len, "/%d", ++data->count );
snprintf( &path[len], sizeof(path)-len, "/%d", ++storage->count );
XP_UCHAR sms[buflen*2]; /* more like (buflen*4/3) */
XP_U16 smslen = sizeof(sms);
@ -342,12 +139,12 @@ linux_sms_send2( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
FILE* fp = fopen( path, "w" );
XP_ASSERT( !!fp );
(void)fprintf( fp, "from: %s\n", data->myPhone );
(void)fprintf( fp, "from: %s\n", storage->myPhone );
(void)fprintf( fp, "%s\n", sms );
fclose( fp );
sync();
unlock_queue2( data );
unlock_queue2( storage );
nSent = buflen;
@ -355,13 +152,13 @@ linux_sms_send2( LaunchParams* params, const XP_U8* buf, XP_U16 buflen,
} /* linux_sms_send */
static XP_S16
decodeAndDelete2( LinSMS2Data* data, const gchar* name,
XP_U8* buf, XP_U16 buflen )
decodeAndDelete2( LinSMS2Data* storage, const gchar* name,
XP_U8* buf, XP_U16 buflen, CommsAddrRec* addr )
{
LOG_FUNC();
XP_S16 nRead = -1;
char path[256];
snprintf( path, sizeof(path), "%s/%s", data->myQueue, name );
snprintf( path, sizeof(path), "%s/%s", storage->myQueue, name );
gchar* contents;
gsize length;
@ -389,8 +186,10 @@ decodeAndDelete2( LinSMS2Data* data, const gchar* name,
if ( valid && outlen <= buflen ) {
XP_MEMCPY( buf, out, outlen );
nRead = outlen;
/* addr->conType = COMMS_CONN_SMS; */
/* addr->u.sms.port = data->port; */
addr->conType = COMMS_CONN_SMS;
XP_STRNCPY( addr->u.sms.phone, phone, sizeof(addr->u.sms.phone) );
XP_LOGF( "%s: message came from phone: %s", __func__, phone );
addr->u.sms.port = 1; /* for now */
}
}
@ -401,26 +200,43 @@ decodeAndDelete2( LinSMS2Data* data, const gchar* name,
} /* decodeAndDelete2 */
static void
dispatch_invite( LinSMS2Data* data, XP_U16 XP_UNUSED(proto), XWStreamCtxt* stream )
dispatch_invite( LinSMS2Data* storage, XP_U16 XP_UNUSED(proto),
XWStreamCtxt* stream, const CommsAddrRec* addr )
{
XP_UCHAR gameName[256];
XP_UCHAR dictName[256];
XP_U32 gameID = stream_getU32( stream );
XP_LOGF( "%s: got gameID %ld", __func__, gameID );
stringFromStreamHere( stream, gameName, VSIZE(gameName) );
XP_U32 dictLang = stream_getU32( stream );
stringFromStreamHere( stream, dictName, VSIZE(dictName) );
XP_U8 nMissing = stream_getU8( stream );
XP_U8 nPlayers = stream_getU8( stream );
(*data->procs->inviteReceived)( data->procClosure, gameName, gameID,
dictLang, dictName, nPlayers, nMissing );
(*storage->procs->inviteReceived)( storage->procClosure, gameName, gameID,
dictLang, dictName, nPlayers, nMissing,
addr );
}
static void
parseAndDispatch( LaunchParams* params, uint8_t* buf, int len )
dispatch_data( LinSMS2Data* storage, XP_U16 XP_UNUSED(proto),
XWStreamCtxt* stream, const CommsAddrRec* addr )
{
LinSMS2Data* data = getStorage( params );
XP_USE( addr );
XP_U32 gameID = stream_getU32( stream );
const XP_U8* data = stream_getPtr( stream );
XP_U16 len = stream_getSize( stream );
(*storage->procs->msgReceived)( storage->procClosure, gameID,
data, len, addr );
}
static void
parseAndDispatch( LaunchParams* params, uint8_t* buf, int len,
const CommsAddrRec* addr )
{
LinSMS2Data* storage = getStorage( params );
XWStreamCtxt* stream = mem_stream_make( MPPARM(params->mpool)
params->vtMgr,
NULL, CHANNEL_NONE, NULL );
@ -431,9 +247,11 @@ parseAndDispatch( LaunchParams* params, uint8_t* buf, int len )
XP_U8 cmd = stream_getU8( stream );
switch( cmd ) {
case INVITE:
dispatch_invite( data, proto, stream );
dispatch_invite( storage, proto, stream, addr );
break;
case DATA:
dispatch_data( storage, proto, stream, addr );
break;
case DEATH:
case ACK:
break;
@ -450,13 +268,13 @@ sms2_receive( void* closure, int socket )
LOG_FUNC();
LaunchParams* params = (LaunchParams*)closure;
XP_ASSERT( !!params->sms2Storage );
LinSMS2Data* data = getStorage( params );
LinSMS2Data* storage = getStorage( params );
XP_S16 nRead = -1;
XP_ASSERT( socket == data->fd );
XP_ASSERT( socket == storage->fd );
lock_queue2( data );
lock_queue2( storage );
/* read required or we'll just get the event again. But we don't care
about the result or the buffer contents. */
@ -464,7 +282,8 @@ sms2_receive( void* closure, int socket )
if ( 0 > read( socket, buffer, sizeof(buffer) ) ) {
}
char shortest[256] = { '\0' };
GDir* dir = g_dir_open( data->myQueue, 0, NULL );
GDir* dir = g_dir_open( storage->myQueue, 0, NULL );
XP_LOGF( "%s: opening %s", __func__, storage->myQueue );
for ( ; ; ) {
const gchar* name = g_dir_read_name( dir );
if ( NULL == name ) {
@ -479,52 +298,53 @@ sms2_receive( void* closure, int socket )
g_dir_close( dir );
uint8_t buf[256];
CommsAddrRec fromAddr = {0};
if ( !!shortest[0] ) {
nRead = decodeAndDelete2( data, shortest, buf, sizeof(buf) );
nRead = decodeAndDelete2( storage, shortest, buf, sizeof(buf), &fromAddr );
}
unlock_queue2( data );
unlock_queue2( storage );
if ( 0 < nRead ) {
parseAndDispatch( params, buf, nRead );
parseAndDispatch( params, buf, nRead, &fromAddr );
}
}
} /* sms2_receive */
void
linux_sms2_init( LaunchParams* params, const gchar* phone,
const SMSProcs* procs, void* procClosure )
{
XP_ASSERT( !!phone );
LinSMS2Data* data = getStorage( params );
XP_ASSERT( !!data );
data->myPhone = phone;
data->procs = procs;
data->procClosure = procClosure;
LinSMS2Data* storage = getStorage( params );
XP_ASSERT( !!storage );
storage->myPhone = phone;
storage->procs = procs;
storage->procClosure = procClosure;
makeQueuePath( phone, params->connInfo.sms.port,
data->myQueue, sizeof(data->myQueue) );
data->port = params->connInfo.sms.port;
storage->myQueue, sizeof(storage->myQueue) );
XP_LOGF( "%s: my queue: %s", __func__, storage->myQueue );
storage->port = params->connInfo.sms.port;
(void)g_mkdir_with_parents( data->myQueue, 0777 );
(void)g_mkdir_with_parents( storage->myQueue, 0777 );
int fd = inotify_init();
data->fd = fd;
data->wd = inotify_add_watch( fd, data->myQueue, IN_MODIFY );
storage->fd = fd;
storage->wd = inotify_add_watch( fd, storage->myQueue, IN_MODIFY );
(*procs->socketChanged)( procClosure, fd, -1, sms2_receive, params );
} /* linux_sms2_init */
void
linux_sms2_invite( LaunchParams* params, const CurGameInfo* gi,
const gchar* gameName, XP_U16 nMissing, const gchar* phone,
const gchar* gameName, XP_U16 nMissing, const gchar* phone,
int port )
{
LOG_FUNC();
XWStreamCtxt* stream;
stream = mem_stream_make( MPPARM(params->mpool) params->vtMgr,
NULL, CHANNEL_NONE, NULL );
stream_putU8( stream, SMS_PROTO_VERSION );
stream_putU8( stream, INVITE );
writeHeader( stream, INVITE );
stream_putU32( stream, gi->gameID );
stringToStream( stream, gameName );
stream_putU32( stream, gi->dictLang );
@ -532,21 +352,29 @@ linux_sms2_invite( LaunchParams* params, const CurGameInfo* gi,
stream_putU8( stream, nMissing );
stream_putU8( stream, gi->nPlayers );
linux_sms_send2( params, stream_getPtr( stream ),
stream_getSize( stream ), phone, port );
LinSMS2Data* storage = getStorage( params );
send_sms( storage, stream, phone, port );
stream_destroy( stream );
}
XP_S16
linux_sms2_send( LaunchParams* params, const XP_U8* buf,
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port )
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port,
XP_U32 gameID )
{
XP_ASSERT(0);
XP_USE( params );
XP_USE( buf );
XP_USE( phone );
XP_USE( port );
LOG_FUNC();
XWStreamCtxt* stream = mem_stream_make( MPPARM(params->mpool) params->vtMgr,
NULL, CHANNEL_NONE, NULL );
writeHeader( stream, DATA );
stream_putU32( stream, gameID );
stream_putBytes( stream, buf, buflen );
LinSMS2Data* storage = getStorage( params );
if ( 0 >= send_sms( storage, stream, phone, port ) ) {
buflen = -1;
}
return buflen;
}
@ -567,4 +395,11 @@ getStorage( LaunchParams* params )
return storage;
}
static void
writeHeader( XWStreamCtxt* stream, SMS_CMD cmd )
{
stream_putU8( stream, SMS_PROTO_VERSION );
stream_putU8( stream, cmd );
}
#endif /* XWFEATURE_SMS */

View file

@ -36,8 +36,9 @@ typedef struct _SMSProcs {
void (*inviteReceived)( void* closure, const XP_UCHAR* gameName,
XP_U32 gameID, XP_U16 dictLang,
const XP_UCHAR* dictName, XP_U16 nPlayers,
XP_U16 nHere );
void (*msgReceived)( void* closure, const XP_U8* buf, XP_U16 len );
XP_U16 nHere, const CommsAddrRec* returnAddr );
void (*msgReceived)( void* closure, XP_U32 gameID, const XP_U8* buf,
XP_U16 len, const CommsAddrRec* from );
void (*msgNoticeReceived)( void* closure );
void (*devIDReceived)( void* closure, const XP_UCHAR* devID,
XP_U16 maxInterval );
@ -51,7 +52,8 @@ typedef struct _SMSProcs {
void linux_sms2_init( LaunchParams* params, const gchar* phone,
const SMSProcs* procs, void* procClosure );
XP_S16 linux_sms2_send( LaunchParams* params, const XP_U8* buf,
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port );
XP_U16 buflen, const XP_UCHAR* phone, XP_U16 port,
XP_U32 gameID );
void linux_sms2_invite( LaunchParams* params, const CurGameInfo* info,
const gchar* gameName, XP_U16 nMissing,
const gchar* phone, int port );