make curses version use udp socket when --db param passed. There's no

UI for the DB and the assumption is only one game will be stored but
this should let the test script be modified to test the new protocol.
This commit is contained in:
Eric House 2013-01-24 07:49:49 -08:00
parent c465a0bb0c
commit 9f3250cb3f
17 changed files with 259 additions and 93 deletions

View file

@ -32,8 +32,8 @@
/* Figure out how many lines there are and how wide the widest is.
*/
short
cursesask( CursesAppGlobals* globals, char* question, short numButtons,
char* button1, ... )
cursesask( CursesAppGlobals* globals, const char* question, short numButtons,
const char* button1, ... )
{
WINDOW* confWin;
int x, y, rows, row, nLines;

View file

@ -22,8 +22,8 @@
#include "cursesmain.h"
short cursesask( CursesAppGlobals* globals, char* question,
short numButtons, char* button1, ... );
short cursesask( CursesAppGlobals* globals, const char* question,
short numButtons, const char* button1, ... );
#endif

View file

@ -70,7 +70,7 @@ measureAskText( const XP_UCHAR* question, int width, FormatInfo* fip )
void
drawButtons( WINDOW* win, XP_U16 line, short spacePerButton,
short numButtons, short curSelButton, char** button1 )
short numButtons, short curSelButton, const char** button1 )
{
short i;
for ( i = 0; i < numButtons; ++i ) {

View file

@ -44,6 +44,6 @@ typedef struct FormatInfo {
void measureAskText( const XP_UCHAR* question, int maxWidth, FormatInfo* fip );
void drawButtons( WINDOW* confWin, XP_U16 line, short spacePerButton,
short numButtons, short curSelButton, char** button1 );
short numButtons, short curSelButton, const char** button1 );
#endif

View file

@ -57,7 +57,7 @@ curses_askLetter( CursesAppGlobals* globals, XP_UCHAR* query,
short curSelButton = 1; /* force draw by being different */
short maxWidth;
short numCtlButtons;
char* ctlButtons[] = { "Ok", "Cancel" };
const char* ctlButtons[] = { "Ok", "Cancel" };
XP_Bool dismissed = XP_FALSE;
FormatInfo fi;
int len;
@ -138,7 +138,7 @@ curses_askLetter( CursesAppGlobals* globals, XP_UCHAR* query,
MAX_TILE_BUTTON_WIDTH-1,
nInRow,
newSelButton - textsOffsets[i],
(char**)&textPtrs[textsOffsets[i]] );
(const char**)&textPtrs[textsOffsets[i]] );
}

View file

@ -60,6 +60,8 @@
#include "dbgutil.h"
#include "linuxsms.h"
#include "linuxudp.h"
#include "gamesdb.h"
#include "relaycon.h"
#ifdef CURSES_SMALL_SCREEN
# define MENU_WINDOW_HEIGHT 1
@ -1121,6 +1123,15 @@ curses_socket_changed( void* closure, int oldSock, int newSock,
#endif
} /* curses_socket_changed */
static void
curses_onGameSaved( void* closure, sqlite3_int64 rowid,
XP_Bool XP_UNUSED(firstTime) )
{
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
/* May not be recorded */
globals->cGlobals.selRow = rowid;
}
#ifdef USE_GLIBLOOP
static gboolean
fire_acceptor( GIOChannel* source, GIOCondition condition, gpointer data )
@ -1717,6 +1728,107 @@ curses_getFlags( void* XP_UNUSED(closure) )
}
#endif
static void
cursesGotBuf( void* closure, const XP_U8* buf, XP_U16 len )
{
LOG_FUNC();
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
XP_U32 gameToken;
XP_ASSERT( sizeof(gameToken) < len );
gameToken = ntohl(*(XP_U32*)&buf[0]);
buf += sizeof(gameToken);
len -= sizeof(gameToken);
gameGotBuf( &globals->cGlobals, XP_TRUE, buf, len );
}
static gint
curses_requestMsgs( gpointer data )
{
CursesAppGlobals* globals = (CursesAppGlobals*)data;
XP_UCHAR devIDBuf[64] = {0};
db_fetch( globals->cGlobals.pDb, KEY_RDEVID, devIDBuf, sizeof(devIDBuf) );
if ( '\0' != devIDBuf[0] ) {
relaycon_requestMsgs( globals->cGlobals.params, devIDBuf );
} else {
XP_LOGF( "%s: not requesting messages as don't have relay id", __func__ );
}
return 0; /* don't run again */
}
static void
cursesNoticeRcvd( void* closure, XP_U32 XP_UNUSED(gameToken) )
{
LOG_FUNC();
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
(void)g_idle_add( curses_requestMsgs, globals );
}
static void
cursesDevIDChanged( void* closure, const XP_UCHAR* devID )
{
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
sqlite3* pDb = globals->cGlobals.pDb;
if ( !!devID ) {
XP_LOGF( "%s(devID=%s)", __func__, devID );
db_store( pDb, KEY_RDEVID, devID );
} else {
XP_LOGF( "%s: bad relayid", __func__ );
db_remove( pDb, KEY_RDEVID );
sendRelayReg( globals->cGlobals.params, pDb );
}
}
static void
cursesErrorMsgRcvd( void* closure, const XP_UCHAR* msg )
{
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
if ( !!globals->lastErr && 0 == strcmp( globals->lastErr, msg ) ) {
XP_LOGF( "skipping error message from relay" );
} else {
g_free( globals->lastErr );
globals->lastErr = g_strdup( msg );
(void)cursesask( globals, msg, 1, "Ok" );
}
}
static gboolean
curses_app_socket_proc( GIOChannel* source, GIOCondition condition,
gpointer data )
{
if ( 0 != (G_IO_IN & condition) ) {
CursesAppGlobals* globals = (CursesAppGlobals*)data;
int socket = g_io_channel_unix_get_fd( source );
GList* iter;
for ( iter = globals->sources; !!iter; iter = iter->next ) {
SourceData* sd = (SourceData*)iter->data;
if ( sd->channel == source ) {
(*sd->proc)( sd->procClosure, socket );
break;
}
}
XP_ASSERT( !!iter ); /* didn't fail to find it */
}
return TRUE;
}
static void
cursesUDPSocketChanged( void* closure, int newSock, int XP_UNUSED(oldSock),
SockReceiver proc, void* procClosure )
{
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
SourceData* sd = g_malloc( sizeof(*sd) );
sd->channel = g_io_channel_unix_new( newSock );
sd->watch = g_io_add_watch( sd->channel, G_IO_IN | G_IO_ERR,
curses_app_socket_proc, globals );
sd->proc = proc;
sd->procClosure = procClosure;
globals->sources = g_list_append( globals->sources, sd );
}
void
cursesmain( XP_Bool isServer, LaunchParams* params )
{
@ -1737,6 +1849,9 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
g_globals.cGlobals.socketChanged = curses_socket_changed;
g_globals.cGlobals.socketChangedClosure = &g_globals;
g_globals.cGlobals.onSave = curses_onGameSaved;
g_globals.cGlobals.onSaveClosure = &g_globals;
g_globals.cGlobals.addAcceptor = curses_socket_acceptor;
g_globals.cGlobals.cp.showBoardArrow = XP_TRUE;
@ -1816,7 +1931,38 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
cursesDrawCtxtMake( g_globals.boardWin );
XWStreamCtxt* stream = NULL;
if ( !!params->fileName && file_exists( params->fileName ) ) {
if ( !!params->dbName ) {
g_globals.cGlobals.pDb = openGamesDB( params->dbName );
RelayConnProcs procs = {
.msgReceived = cursesGotBuf,
.msgNoticeReceived = cursesNoticeRcvd,
.devIDChanged = cursesDevIDChanged,
.msgErrorMsg = cursesErrorMsgRcvd,
.socketChanged = cursesUDPSocketChanged,
};
relaycon_init( params, &procs, &g_globals,
params->connInfo.relay.relayName,
params->connInfo.relay.defaultSendPort );
sendRelayReg( params, g_globals.cGlobals.pDb );
GSList* games = listGames( g_globals.cGlobals.pDb );
if ( !!games ) {
stream = mem_stream_make( MEMPOOL params->vtMgr,
&g_globals.cGlobals, CHANNEL_NONE,
NULL );
sqlite3_int64 selRow = *(sqlite3_int64*)games->data;
if ( loadGame( stream, g_globals.cGlobals.pDb, selRow ) ) {
g_globals.cGlobals.selRow = selRow;
} else {
stream_destroy( stream );
stream = NULL;
}
g_slist_free( games );
}
} else if ( !!params->fileName && file_exists( params->fileName ) ) {
stream = streamFromFile( &g_globals.cGlobals, params->fileName,
&g_globals );
#ifdef USE_SQLITE
@ -1830,8 +1976,8 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
cGlobals->dict = makeDictForStream( cGlobals, stream );
}
(void)game_makeFromStream( MEMPOOL stream, &cGlobals->game,
&cGlobals->gi, cGlobals->dict, &cGlobals->dicts,
cGlobals->util,
&cGlobals->gi, cGlobals->dict,
&cGlobals->dicts, cGlobals->util,
(DrawCtx*)g_globals.draw,
&g_globals.cGlobals.cp, &procs );
@ -1845,6 +1991,8 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
game_makeNewGame( MEMPOOL &cGlobals->game, &cGlobals->gi,
cGlobals->util, (DrawCtx*)g_globals.draw,
&g_globals.cGlobals.cp, &procs, params->gameSeed );
g_globals.cGlobals.selRow = -1;
saveGame( &g_globals.cGlobals );
}
#ifndef XWFEATURE_STANDALONE_ONLY

View file

@ -68,6 +68,7 @@ struct CursesAppGlobals {
XP_Bool doDraw;
const struct MenuList* menuList;
XP_U16 nLinesMenu;
gchar* lastErr;
union {
struct {

View file

@ -141,14 +141,14 @@ summarize( CommonGlobals* cGlobals )
}
GSList*
listGames( GtkAppGlobals* apg )
listGames( sqlite3* pDb )
{
GSList* list = NULL;
sqlite3_stmt *ppStmt;
int result = sqlite3_prepare_v2( apg->pDb,
"SELECT rowid FROM games ORDER BY rowid", -1,
&ppStmt, NULL );
int result = sqlite3_prepare_v2( pDb,
"SELECT rowid FROM games ORDER BY rowid",
-1, &ppStmt, NULL );
XP_ASSERT( SQLITE_OK == result );
while ( NULL != ppStmt ) {
switch( sqlite3_step( ppStmt ) ) {
@ -173,7 +173,7 @@ listGames( GtkAppGlobals* apg )
}
XP_Bool
getGameInfo( GtkAppGlobals* apg, sqlite3_int64 rowid, GameInfo* gib )
getGameInfo( sqlite3* pDb, sqlite3_int64 rowid, GameInfo* gib )
{
XP_Bool success = XP_FALSE;
const char* fmt = "SELECT room, ended, turn, nmoves, nmissing "
@ -182,7 +182,7 @@ getGameInfo( GtkAppGlobals* apg, sqlite3_int64 rowid, GameInfo* gib )
snprintf( query, sizeof(query), fmt, rowid );
sqlite3_stmt* ppStmt;
int result = sqlite3_prepare_v2( apg->pDb, query, -1, &ppStmt, NULL );
int result = sqlite3_prepare_v2( pDb, query, -1, &ppStmt, NULL );
XP_ASSERT( SQLITE_OK == result );
result = sqlite3_step( ppStmt );
if ( SQLITE_ROW == result ) {

View file

@ -44,8 +44,8 @@ void writeToDB( XWStreamCtxt* stream, void* closure );
void summarize( CommonGlobals* cGlobals );
/* Return GSList whose data is (ptrs to) rowids */
GSList* listGames( GtkAppGlobals* apg );
XP_Bool getGameInfo( GtkAppGlobals* apg, sqlite3_int64 rowid, GameInfo* gib );
GSList* listGames( sqlite3* dbp );
XP_Bool getGameInfo( sqlite3* dbp, sqlite3_int64 rowid, GameInfo* gib );
XP_Bool loadGame( XWStreamCtxt* stream, sqlite3* pDb, sqlite3_int64 rowid );
void deleteGame( sqlite3* pDb, sqlite3_int64 rowid );

View file

@ -2629,38 +2629,4 @@ makeNewGame( GtkGameGlobals* globals )
return success;
}
void
gameGotBuf( GtkGameGlobals* globals, XP_Bool hasDraw, const XP_U8* buf,
XP_U16 len )
{
XP_LOGF( "%s(hasDraw=%d)", __func__, hasDraw );
XP_Bool redraw = XP_FALSE;
XWGame* game = &globals->cGlobals.game;
XWStreamCtxt* stream = stream_from_msgbuf( &globals->cGlobals, buf, len );
if ( !!stream ) {
if ( comms_checkIncomingStream( game->comms, stream, NULL ) ) {
redraw = server_receiveMessage( game->server, stream );
if ( redraw ) {
saveGame( &globals->cGlobals );
}
}
stream_destroy( stream );
/* if there's something to draw resulting from the message, we
need to give the main loop time to reflect that on the screen
before giving the server another shot. So just call the idle
proc. */
if ( hasDraw && redraw ) {
gtk_util_requestTime( globals->cGlobals.util );
} else {
for ( int ii = 0; ii < 4; ++ii ) {
redraw = server_do( game->server ) || redraw;
}
}
if ( hasDraw && redraw ) {
board_draw( game->board );
}
}
}
#endif /* PLATFORM_GTK */

View file

@ -169,8 +169,6 @@ typedef struct GtkGameGlobals {
void initGlobals( GtkGameGlobals* globals, LaunchParams* params );
void freeGlobals( GtkGameGlobals* globals );
XP_Bool makeNewGame( GtkGameGlobals* globals );
void gameGotBuf( GtkGameGlobals* globals, XP_Bool haveDraw,
const XP_U8* buf, XP_U16 len );
XP_Bool loadGameNoDraw( GtkGameGlobals* globals, LaunchParams* params,
sqlite3* pDb, sqlite3_int64 rowid );
void destroy_board_window( GtkWidget* widget, GtkGameGlobals* globals );

View file

@ -31,7 +31,6 @@
static void onNewData( GtkAppGlobals* apg, sqlite3_int64 rowid,
XP_Bool isNew );
static void updateButtons( GtkAppGlobals* apg );
static void sendRelayReg( GtkAppGlobals* apg );
static void
recordOpened( GtkAppGlobals* apg, GtkGameGlobals* globals )
@ -302,7 +301,7 @@ makeGamesWindow( GtkAppGlobals* apg )
gtk_widget_show( list );
GSList* games = listGames( apg );
GSList* games = listGames( apg->pDb );
for ( GSList* iter = games; !!iter; iter = iter->next ) {
sqlite3_int64* rowid = (sqlite3_int64*)iter->data;
onNewData( apg, *rowid, XP_TRUE );
@ -347,13 +346,13 @@ static void
onNewData( GtkAppGlobals* apg, sqlite3_int64 rowid, XP_Bool isNew )
{
GameInfo gib;
if ( getGameInfo( apg, rowid, &gib ) ) {
if ( getGameInfo( apg->pDb, rowid, &gib ) ) {
add_to_list( apg->listWidget, rowid, isNew, &gib );
}
}
static gboolean
app_socket_proc( GIOChannel* source, GIOCondition condition, gpointer data )
gtk_app_socket_proc( GIOChannel* source, GIOCondition condition, gpointer data )
{
if ( 0 != (G_IO_IN & condition) ) {
GtkAppGlobals* apg = (GtkAppGlobals*)data;
@ -372,13 +371,14 @@ app_socket_proc( GIOChannel* source, GIOCondition condition, gpointer data )
}
static void
socketChanged( void* closure, int newSock, int XP_UNUSED(oldSock),
SockReceiver proc, void* procClosure )
gtkSocketChanged( void* closure, int newSock, int XP_UNUSED(oldSock),
SockReceiver proc, void* procClosure )
{
GtkAppGlobals* apg = (GtkAppGlobals*)closure;
SourceData* sd = g_malloc( sizeof(*sd) );
sd->channel = g_io_channel_unix_new( newSock );
sd->watch = g_io_add_watch( sd->channel, G_IO_IN | G_IO_ERR, app_socket_proc, apg );
sd->watch = g_io_add_watch( sd->channel, G_IO_IN | G_IO_ERR,
gtk_app_socket_proc, apg );
sd->proc = proc;
sd->procClosure = procClosure;
apg->sources = g_list_append( apg->sources, sd );
@ -397,11 +397,11 @@ gtkGotBuf( void* closure, const XP_U8* buf, XP_U16 len )
GtkGameGlobals* globals = findGame( apg, gameToken );
if ( !!globals ) {
gameGotBuf( globals, XP_TRUE, buf, len );
gameGotBuf( &globals->cGlobals, XP_TRUE, buf, len );
} else {
GtkGameGlobals tmpGlobals;
if ( loadGameNoDraw( &tmpGlobals, apg->params, apg->pDb, gameToken ) ) {
gameGotBuf( &tmpGlobals, XP_FALSE, buf, len );
gameGotBuf( &tmpGlobals.cGlobals, XP_FALSE, buf, len );
saveGame( &tmpGlobals.cGlobals );
}
freeGlobals( &tmpGlobals );
@ -440,7 +440,7 @@ gtkDevIDChanged( void* closure, const XP_UCHAR* devID )
} else {
XP_LOGF( "%s: bad relayid", __func__ );
db_remove( apg->pDb, KEY_RDEVID );
sendRelayReg( apg );
sendRelayReg( apg->params, apg->pDb );
}
}
@ -482,27 +482,6 @@ handle_sigintterm( int XP_UNUSED(sig) )
handle_destroy( NULL, g_globals_for_signal );
}
static void
sendRelayReg( GtkAppGlobals* apg )
{
LaunchParams* params = apg->params;
XP_UCHAR devIDBuf[64] = {0};
XP_UCHAR* devID;
DevIDType typ = ID_TYPE_RELAY;
if ( !!params->rDevID ) {
devID = params->rDevID;
} else {
db_fetch( apg->pDb, KEY_RDEVID, devIDBuf, sizeof(devIDBuf) );
if ( '\0' != devIDBuf[0] ) {
devID = devIDBuf;
} else {
devID = params->devID;
typ = ID_TYPE_LINUX;
}
}
relaycon_reg( params, devID, typ );
}
int
gtkmain( LaunchParams* params )
{
@ -516,20 +495,19 @@ gtkmain( LaunchParams* params )
apg.selRows = g_array_new( FALSE, FALSE, sizeof( sqlite3_int64 ) );
apg.params = params;
apg.pDb = openGamesDB( params->dbName );
params->socketChanged = socketChanged;
params->socketChangedClosure = &apg;
RelayConnProcs procs = {
.msgReceived = gtkGotBuf,
.msgNoticeReceived = gtkNoticeRcvd,
.devIDChanged = gtkDevIDChanged,
.msgErrorMsg = gtkErrorMsgRcvd,
.socketChanged = gtkSocketChanged,
};
relaycon_init( params, &procs, &apg,
params->connInfo.relay.relayName,
params->connInfo.relay.defaultSendPort );
sendRelayReg( &apg );
sendRelayReg( params, apg.pDb );
apg.window = makeGamesWindow( &apg );
gtk_main();

View file

@ -172,6 +172,54 @@ makeDictForStream( CommonGlobals* cGlobals, XWStreamCtxt* stream )
return dict;
}
void
gameGotBuf( CommonGlobals* cGlobals, XP_Bool hasDraw, const XP_U8* buf,
XP_U16 len )
{
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 ) ) {
redraw = server_receiveMessage( game->server, stream );
if ( redraw ) {
saveGame( cGlobals );
}
}
stream_destroy( stream );
/* if there's something to draw resulting from the message, we
need to give the main loop time to reflect that on the screen
before giving the server another shot. So just call the idle
proc. */
if ( hasDraw && redraw ) {
util_requestTime( cGlobals->util );
} else {
for ( int ii = 0; ii < 4; ++ii ) {
redraw = server_do( game->server ) || redraw;
}
}
if ( hasDraw && redraw ) {
board_draw( game->board );
}
}
}
gint
requestMsgsIdle( gpointer data )
{
CommonGlobals* cGlobals = (CommonGlobals*)data;
XP_UCHAR devIDBuf[64] = {0};
db_fetch( cGlobals->pDb, KEY_RDEVID, devIDBuf, sizeof(devIDBuf) );
if ( '\0' != devIDBuf[0] ) {
relaycon_requestMsgs( cGlobals->params, devIDBuf );
} else {
XP_LOGF( "%s: not requesting messages as don't have relay id", __func__ );
}
return 0; /* don't run again */
}
void
writeToFile( XWStreamCtxt* stream, void* closure )
{
@ -801,6 +849,26 @@ linShiftFocus( CommonGlobals* cGlobals, XP_Key key, const BoardObjectType* order
} /* linShiftFocus */
#endif
void
sendRelayReg( LaunchParams* params, sqlite3* pDb )
{
XP_UCHAR devIDBuf[64] = {0};
XP_UCHAR* devID;
DevIDType typ = ID_TYPE_RELAY;
if ( !!params->rDevID ) {
devID = params->rDevID;
} else {
db_fetch( pDb, KEY_RDEVID, devIDBuf, sizeof(devIDBuf) );
if ( '\0' != devIDBuf[0] ) {
devID = devIDBuf;
} else {
devID = params->devID;
typ = ID_TYPE_LINUX;
}
}
relaycon_reg( params, devID, typ );
}
#ifdef XWFEATURE_RELAY
static int
linux_init_relay_socket( CommonGlobals* cGlobals, const CommsAddrRec* addrRec )

View file

@ -103,6 +103,12 @@ DictionaryCtxt* makeDictForStream( CommonGlobals* cGlobals,
void linuxSetIsServer( CommonGlobals* cGlobals, XP_Bool isServer );
void linuxChangeRoles( CommonGlobals* cGlobals );
void sendRelayReg( LaunchParams* params, sqlite3* pDb );
void gameGotBuf( CommonGlobals* globals, XP_Bool haveDraw,
const XP_U8* buf, XP_U16 len );
gboolean app_socket_proc( GIOChannel* source, GIOCondition condition,
gpointer data );
/* void initParams( LaunchParams* params ); */
/* void freeParams( LaunchParams* params ); */

View file

@ -55,8 +55,6 @@ typedef struct LaunchParams {
GSList* dictDirs;
char* fileName;
char* dbName;
NewSocketProc socketChanged;
void* socketChangedClosure;
XP_U16 saveFailPct;
const XP_UCHAR* playerDictNames[MAX_NUM_PLAYERS];
#ifdef USE_SQLITE

View file

@ -56,8 +56,8 @@ relaycon_init( LaunchParams* params, const RelayConnProcs* procs,
storage->procsClosure = procsClosure;
storage->socket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
(*params->socketChanged)( params->socketChangedClosure, storage->socket, -1,
relaycon_receive, params );
(*procs->socketChanged)( procsClosure, storage->socket, -1,
relaycon_receive, params );
XP_MEMSET( &storage->saddr, 0, sizeof(storage->saddr) );
storage->saddr.sin_family = PF_INET;

View file

@ -27,6 +27,9 @@ typedef struct _Procs {
void (*msgNoticeReceived)( void* closure, XP_U32 gameToken );
void (*devIDChanged)( void* closure, const XP_UCHAR* devID );
void (*msgErrorMsg)( void* closure, const XP_UCHAR* msg );
void (*socketChanged)( void* closure, int newSock, int oldSock,
SockReceiver proc, void* procClosure );
} RelayConnProcs;
void relaycon_init( LaunchParams* params, const RelayConnProcs* procs,