changes to support automated testing of background messages sends: new

param gives name of Unix domain socket to be used to accept connection
that passes in messages from relay and receives messages to be sent
back.  Works once but needs debugging....
This commit is contained in:
Andy2 2011-09-30 06:32:21 -07:00
parent c952ebd8e6
commit c992c65015
4 changed files with 239 additions and 47 deletions

View file

@ -1,6 +1,6 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */ /* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
/* /*
* Copyright 2000-2009 by Eric House (xwords@eehouse.org). All rights * Copyright 2000-2011 by Eric House (xwords@eehouse.org). All rights
* reserved. * reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -52,6 +52,7 @@
#include "xwproto.h" #include "xwproto.h"
#include "xwstream.h" #include "xwstream.h"
#include "xwstate.h" #include "xwstate.h"
#include "strutils.h"
#include "server.h" #include "server.h"
#include "memstream.h" #include "memstream.h"
#include "util.h" #include "util.h"
@ -1575,6 +1576,53 @@ positionSizeStuff( CursesAppGlobals* globals, int width, int height )
board_invalAll( board ); board_invalAll( board );
} /* positionSizeStuff */ } /* positionSizeStuff */
static XP_Bool
relay_sendNoConn_curses( const XP_U8* msg, XP_U16 len,
const XP_UCHAR* relayID, void* closure )
{
LOG_FUNC();
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
CommonGlobals* cGlobals = &globals->cGlobals;
int fd = cGlobals->nbsFD;
XP_Bool success = 0 <= fd;
if ( success ) {
XP_LOGF( "%s: given %d bytes for %s", __func__, len, relayID );
// format: total msg lenth: 2
// number-of-relayIDs: 2
// for-each-relayid: relayid + '\n': varies
// message count: 1
// for-each-message: length: 2
// message: varies
XWStreamCtxt* stream =
mem_stream_make( MPPARM(globals->cGlobals.params->util->mpool)
globals->cGlobals.params->vtMgr,
globals, CHANNEL_NONE, NULL );
stream_putU16( stream, 1 ); /* number of relayIDs */
stream_catString( stream, relayID );
stream_putU8( stream, '\n' );
stream_putU16( stream, 1 ); /* message count */
stream_putU16( stream, len );
stream_putBytes( stream, msg, len );
XP_U16 siz = stream_getSize( stream );
XP_U8 buf[siz];
stream_getBytes( stream, buf, siz );
XP_U16 tmp = XP_HTONS( siz );
ssize_t nwritten = write( fd, &tmp, sizeof(tmp) );
XP_ASSERT( nwritten == sizeof(tmp) );
nwritten = write( fd, buf/*stream_getPtr( stream )*/, siz );
log_hex( buf/*stream_getPtr( stream )*/, siz, __func__ );
XP_ASSERT( nwritten == siz );
stream_destroy( stream );
} else {
XP_LOGF( "%s: nbsFD=%d", __func__, fd );
}
LOG_RETURNF( "%d", success );
return success;
} /* relay_sendNoConn_curses */
static void static void
relay_status_curses( void* XP_UNUSED(closure), relay_status_curses( void* XP_UNUSED(closure),
CommsRelayState XP_UNUSED_DBG(state) ) CommsRelayState XP_UNUSED_DBG(state) )
@ -1654,6 +1702,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
g_globals.cGlobals.cp.robotThinkMin = params->robotThinkMin; g_globals.cGlobals.cp.robotThinkMin = params->robotThinkMin;
g_globals.cGlobals.cp.robotThinkMax = params->robotThinkMax; g_globals.cGlobals.cp.robotThinkMax = params->robotThinkMax;
#endif #endif
g_globals.cGlobals.nbsFD = -1;
setupCursesUtilCallbacks( &g_globals, params->util ); setupCursesUtilCallbacks( &g_globals, params->util );
@ -1681,8 +1730,26 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
struct sigaction act2 = { .sa_handler = SIGWINCH_handler }; struct sigaction act2 = { .sa_handler = SIGWINCH_handler };
sigaction( SIGWINCH, &act2, NULL ); sigaction( SIGWINCH, &act2, NULL );
TransportProcs procs = {
.closure = &g_globals,
.send = LINUX_SEND,
#ifdef COMMS_HEARTBEAT
.reset = linux_reset,
#endif
#ifdef XWFEATURE_RELAY
.rstatus = relay_status_curses,
.rconnd = relay_connd_curses,
.rerror = relay_error_curses,
.sendNoConn = relay_sendNoConn_curses,
.flags = COMMS_XPORT_FLAGS_HASNOCONN,
#endif
};
if ( !!params->pipe && !!params->fileName ) { if ( !!params->pipe && !!params->fileName ) {
read_pipe_then_close( &g_globals.cGlobals ); read_pipe_then_close( &g_globals.cGlobals, &procs );
} else if ( !!params->nbs && !!params->fileName ) {
do_nbs_then_close( &g_globals.cGlobals, &procs );
} else { } else {
initCurses( &g_globals ); initCurses( &g_globals );
@ -1691,19 +1758,6 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
g_globals.draw = (struct CursesDrawCtx*) g_globals.draw = (struct CursesDrawCtx*)
cursesDrawCtxtMake( g_globals.boardWin ); cursesDrawCtxtMake( g_globals.boardWin );
TransportProcs procs = {
.closure = &g_globals,
.send = LINUX_SEND,
#ifdef COMMS_HEARTBEAT
.reset = linux_reset,
#endif
#ifdef XWFEATURE_RELAY
.rstatus = relay_status_curses,
.rconnd = relay_connd_curses,
.rerror = relay_error_curses,
#endif
};
if ( !!params->fileName && file_exists( params->fileName ) ) { if ( !!params->fileName && file_exists( params->fileName ) ) {
XWStreamCtxt* stream; XWStreamCtxt* stream;
stream = streamFromFile( &g_globals.cGlobals, params->fileName, stream = streamFromFile( &g_globals.cGlobals, params->fileName,

View file

@ -35,6 +35,7 @@
#include <time.h> #include <time.h>
#include <syslog.h> #include <syslog.h>
#include <stdarg.h> #include <stdarg.h>
#include <linux/un.h>
#ifdef XWFEATURE_BLUETOOTH #ifdef XWFEATURE_BLUETOOTH
# include <bluetooth/bluetooth.h> # include <bluetooth/bluetooth.h>
@ -189,9 +190,11 @@ strFromStream( XWStreamCtxt* stream )
return buf; return buf;
} /* strFromStream */ } /* strFromStream */
void static void
read_pipe_then_close( CommonGlobals* cGlobals ) handle_messages_from( CommonGlobals* cGlobals, const TransportProcs* procs,
int fdin )
{ {
LOG_FUNC();
LaunchParams* params = cGlobals->params; LaunchParams* params = cGlobals->params;
XWStreamCtxt* stream = XWStreamCtxt* stream =
streamFromFile( cGlobals, params->fileName, cGlobals ); streamFromFile( cGlobals, params->fileName, cGlobals );
@ -204,45 +207,167 @@ read_pipe_then_close( CommonGlobals* cGlobals )
&params->gi, params->dict, &params->gi, params->dict,
&params->dicts, params->util, &params->dicts, params->util,
NULL /*draw*/, NULL /*draw*/,
&cGlobals->cp, NULL ); &cGlobals->cp, procs );
XP_ASSERT( opened ); XP_ASSERT( opened );
stream_destroy( stream ); stream_destroy( stream );
XP_Bool handled = XP_FALSE; XP_Bool handled = XP_FALSE;
int fd = open( params->pipe, O_RDONLY ); unsigned short len;
while ( fd >= 0 ) { for ( ; ; ) {
unsigned short len; ssize_t nRead = blocking_read( fdin, (unsigned char*)&len,
ssize_t nRead = blocking_read( fd, (unsigned char*)&len, sizeof(len) ); sizeof(len) );
if ( nRead != 2 ) { if ( nRead != sizeof(len) ) {
XP_LOGF( "%s: 1: unexpected nRead: %d", __func__, nRead );
break; break;
} }
len = ntohs( len ); len = ntohs( len );
if ( 0 == len ) {
break;
}
unsigned char buf[len]; unsigned char buf[len];
nRead = blocking_read( fd, buf, len ); nRead = blocking_read( fdin, buf, len );
if ( nRead != len ) { if ( nRead != len ) {
XP_LOGF( "%s: 2: unexpected nRead: %d", __func__, nRead );
break; break;
} }
stream = mem_stream_make( MPPARM(cGlobals->params->util->mpool) stream = mem_stream_make( MPPARM(cGlobals->params->util->mpool)
params->vtMgr, cGlobals, CHANNEL_NONE, NULL ); params->vtMgr, cGlobals, CHANNEL_NONE,
NULL );
stream_putBytes( stream, buf, len ); stream_putBytes( stream, buf, len );
if ( comms_checkIncomingStream( cGlobals->game.comms, if ( comms_checkIncomingStream( cGlobals->game.comms,
stream, NULL ) ) { stream, NULL ) ) {
handled = server_receiveMessage( cGlobals->game.server, ServerCtxt* server = cGlobals->game.server;
stream ) || handled; (void)server_do( server, NULL );
handled = server_receiveMessage( server, stream ) || handled;
XP_Bool notDone;
XP_U16 ii;
for ( ii = 0, notDone = XP_TRUE; notDone && ii < 5; ++ii ) {
(void)server_do( server, &notDone );
}
} }
stream_destroy( stream ); stream_destroy( stream );
} }
LOG_RETURNF( "%d", handled );
/* Write it out */ LOG_RETURN_VOID();
/* stream = mem_stream_make( MEMPOOLCG(cGlobals) params->vtMgr, */ } /* handle_messages_from */
/* cGlobals, 0, writeToFile ); */
/* stream_open( stream ); */ void
/* game_saveToStream( &cGlobals->game, &params->gi, stream ); */ read_pipe_then_close( CommonGlobals* cGlobals, const TransportProcs* procs )
/* stream_destroy( stream ); */ {
LOG_FUNC();
LaunchParams* params = cGlobals->params;
XWStreamCtxt* stream =
streamFromFile( cGlobals, params->fileName, cGlobals );
#ifdef DEBUG
XP_Bool opened =
#endif
game_makeFromStream( MPPARM(cGlobals->params->util->mpool)
stream, &cGlobals->game,
&params->gi, params->dict,
&params->dicts, params->util,
NULL /*draw*/,
&cGlobals->cp, procs );
XP_ASSERT( opened );
stream_destroy( stream );
XP_Bool handled = XP_FALSE;
int fd = open( params->pipe, O_RDWR );
XP_ASSERT( fd >= 0 );
if ( fd >= 0 ) {
unsigned short len;
for ( ; ; ) {
ssize_t nRead = blocking_read( fd, (unsigned char*)&len,
sizeof(len) );
if ( nRead != sizeof(len) ) {
XP_LOGF( "%s: 1: unexpected nRead: %d", __func__, nRead );
break;
}
len = ntohs( len );
if ( 0 == len ) {
break;
}
unsigned char buf[len];
nRead = blocking_read( fd, buf, len );
if ( nRead != len ) {
XP_LOGF( "%s: 2: unexpected nRead: %d", __func__, nRead );
break;
}
stream = mem_stream_make( MPPARM(cGlobals->params->util->mpool)
params->vtMgr, cGlobals, CHANNEL_NONE,
NULL );
stream_putBytes( stream, buf, len );
if ( comms_checkIncomingStream( cGlobals->game.comms,
stream, NULL ) ) {
ServerCtxt* server = cGlobals->game.server;
(void)server_do( server, NULL );
handled = server_receiveMessage( server, stream ) || handled;
XP_Bool notDone;
XP_U16 ii;
for ( ii = 0, notDone = XP_TRUE; notDone && ii < 5; ++ii ) {
(void)server_do( server, &notDone );
}
}
stream_destroy( stream );
}
/* 0-length packet closes it off */
XP_LOGF( "%s: writing 0-length packet", __func__ );
len = 0;
ssize_t nwritten = write( fd, &len, sizeof(len) );
XP_ASSERT( nwritten == sizeof(len) );
close( fd );
}
LOG_RETURN_VOID();
} /* read_pipe_then_close */ } /* read_pipe_then_close */
void
do_nbs_then_close( CommonGlobals* cGlobals, const TransportProcs* procs )
{
LOG_FUNC();
int sockfd = socket( AF_UNIX, SOCK_STREAM, 0 );
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy( addr.sun_path, cGlobals->params->nbs );
int err = bind( sockfd, (struct sockaddr*)&addr, sizeof(addr) );
if ( 0 != err ) {
XP_LOGF( "%s: bind=>%s", __func__, strerror( errno ) );
XP_ASSERT( 0 );
}
XP_LOGF( "calling listen" );
err = listen( sockfd, 1 );
assert( 0 == err );
struct sockaddr remote;
socklen_t addrlen = sizeof(remote);
XP_LOGF( "calling accept" );
int fd = accept( sockfd, &remote, &addrlen );
XP_LOGF( "%s: accept=>%d", __func__, fd );
assert( 0 <= fd );
/* do stuff here */
cGlobals->nbsFD = fd;
handle_messages_from( cGlobals, procs, fd );
cGlobals->nbsFD = -1;
/* Do I need this? Will reader get err if I close? */
unsigned short len = 0;
ssize_t nwritten = write( fd, &len, sizeof(len) );
XP_ASSERT( nwritten == sizeof(len) );
close( fd );
close( sockfd );
LOG_RETURN_VOID();
} /* do_nbs_then_close */
typedef enum { typedef enum {
CMD_SKIP_GAMEOVER CMD_SKIP_GAMEOVER
,CMD_SHOW_OTHERSCORES ,CMD_SHOW_OTHERSCORES
@ -280,6 +405,7 @@ typedef enum {
,CMD_VERTICALSCORE ,CMD_VERTICALSCORE
,CMD_NOPEEK ,CMD_NOPEEK
,CMD_ADDPIPE ,CMD_ADDPIPE
,CMD_ADDNBS
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
,CMD_HINTRECT ,CMD_HINTRECT
#endif #endif
@ -354,6 +480,8 @@ static CmdInfoRec CmdInfoRecs[] = {
,{ CMD_VERTICALSCORE, false, "vertical", "scoreboard is vertical" } ,{ CMD_VERTICALSCORE, false, "vertical", "scoreboard is vertical" }
,{ CMD_NOPEEK, false, "no-peek", "disallow scoreboard tap changing player" } ,{ CMD_NOPEEK, false, "no-peek", "disallow scoreboard tap changing player" }
,{ CMD_ADDPIPE, true, "with-pipe", "named pipe to listen on for relay msgs" } ,{ CMD_ADDPIPE, true, "with-pipe", "named pipe to listen on for relay msgs" }
,{ CMD_ADDNBS, true, "with-nbs",
"nbs socket to listen/reply on for relay msgs" }
#ifdef XWFEATURE_SEARCHLIMIT #ifdef XWFEATURE_SEARCHLIMIT
,{ CMD_HINTRECT, false, "hintrect", "enable draggable hint-limits rect" } ,{ CMD_HINTRECT, false, "hintrect", "enable draggable hint-limits rect" }
#endif #endif
@ -659,14 +787,15 @@ blocking_read( int fd, unsigned char* buf, int len )
{ {
int nRead = 0; int nRead = 0;
while ( nRead < len ) { while ( nRead < len ) {
ssize_t siz = read( fd, buf + nRead, len - nRead ); XP_LOGF( "%s: blocking for %d bytes", __func__, len );
if ( siz <= 0 ) { ssize_t siz = read( fd, buf + nRead, len - nRead );
XP_LOGF( "read => %d, errno=%d (\"%s\")", nRead, if ( siz <= 0 ) {
errno, strerror(errno) ); XP_LOGF( "read => %d, errno=%d (\"%s\")", nRead,
nRead = -1; errno, strerror(errno) );
break; nRead = -1;
} break;
nRead += siz; }
nRead += siz;
} }
return nRead; return nRead;
} }
@ -1186,6 +1315,9 @@ main( int argc, char** argv )
case CMD_ADDPIPE: case CMD_ADDPIPE:
mainParams.pipe = optarg; mainParams.pipe = optarg;
break; break;
case CMD_ADDNBS:
mainParams.nbs = optarg;
break;
#ifdef XWFEATURE_SLOW_ROBOT #ifdef XWFEATURE_SLOW_ROBOT
case CMD_SLOWROBOT: case CMD_SLOWROBOT:
if ( !parsePair( optarg, &mainParams.robotThinkMin, if ( !parsePair( optarg, &mainParams.robotThinkMin,
@ -1397,7 +1529,7 @@ main( int argc, char** argv )
free( mainParams.util ); free( mainParams.util );
XP_LOGF( "exiting main" ); XP_LOGF( "%s exiting main", argv[0] );
return 0; return 0;
} /* main */ } /* main */

View file

@ -1,6 +1,7 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make -k";-*- */ /* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
/* /*
* Copyright 1997-2008 by Eric House (xwords@eehouse.org). All rights reserved. * Copyright 1997-2011 by Eric House (xwords@eehouse.org). All rights
* reserved.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -74,6 +75,9 @@ XP_Bool linShiftFocus( CommonGlobals* cGlobals, XP_Key key,
BoardObjectType* nxtP ); BoardObjectType* nxtP );
#endif #endif
void read_pipe_then_close( CommonGlobals* cGlobals ); void read_pipe_then_close( CommonGlobals* cGlobals,
const TransportProcs* procs );
void do_nbs_then_close( CommonGlobals* cGlobals,
const TransportProcs* procs );
#endif #endif

View file

@ -50,6 +50,7 @@ typedef struct LaunchParams {
PlayerDicts dicts; PlayerDicts dicts;
char* fileName; char* fileName;
char* pipe; char* pipe;
char* nbs;
char* bonusFile; char* bonusFile;
VTableMgr* vtMgr; VTableMgr* vtMgr;
XP_U16 nLocalPlayers; XP_U16 nLocalPlayers;
@ -161,6 +162,7 @@ struct CommonGlobals {
* polling mechanism.*/ * polling mechanism.*/
AddAcceptorFunc addAcceptor; AddAcceptorFunc addAcceptor;
Acceptor acceptor; Acceptor acceptor;
int nbsFD;
#ifdef XWFEATURE_RELAY #ifdef XWFEATURE_RELAY
int socket; /* relay */ int socket; /* relay */