mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-18 22:26:30 +01:00
fix and cleanup linux client to move to using tcp. Add the ability to
deal with socket dying and (maybe) being replaced. Only connect on demand now, when first packet's ready to go.
This commit is contained in:
parent
820664d212
commit
3d54ec402a
5 changed files with 122 additions and 76 deletions
|
@ -83,16 +83,6 @@ cursesUserError( CursesAppGlobals* globals, char* format, ... )
|
|||
va_end(ap);
|
||||
} /* cursesUserError */
|
||||
|
||||
static void
|
||||
curses_util_listenPortChange( XW_UtilCtxt* uc, XP_U16 newPort )
|
||||
{
|
||||
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
|
||||
XP_LOGF( "listenPortChange called: not sure what to do" );
|
||||
|
||||
/* if this isn't true, need to tear down and rebind socket */
|
||||
XP_ASSERT( newPort == globals->cGlobals.params->defaultListenPort );
|
||||
} /* curses_util_listenPortChange */
|
||||
|
||||
static XP_S16
|
||||
curses_util_userPickTile( XW_UtilCtxt* uc, const PickInfo* pi, XP_U16 playerNum,
|
||||
const XP_UCHAR4* texts, XP_U16 nTiles )
|
||||
|
@ -598,13 +588,40 @@ cursesListenOnSocket( CursesAppGlobals* globals, int newSock,
|
|||
globals->fdArray[globals->fdCount].fd = newSock;
|
||||
globals->fdArray[globals->fdCount].events = POLLIN;
|
||||
|
||||
globals->streams[globals->fdCount] = stream;
|
||||
|
||||
++globals->fdCount;
|
||||
XP_LOGF( "listenOnSocket: there are now %d sources to poll",
|
||||
globals->fdCount );
|
||||
} /* cursesListenOnSocket */
|
||||
|
||||
static void
|
||||
curses_stop_listening( CursesAppGlobals* globals, int sock )
|
||||
{
|
||||
int count = globals->fdCount;
|
||||
int i, found = 0;
|
||||
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
if ( globals->fdArray[i].fd == sock ) {
|
||||
found = 1;
|
||||
} else if ( found ) {
|
||||
globals->fdArray[i-1].fd = globals->fdArray[i].fd;
|
||||
}
|
||||
}
|
||||
|
||||
assert( found );
|
||||
--globals->fdCount;
|
||||
} /* curses_stop_listening */
|
||||
|
||||
static void
|
||||
curses_socket_changed( void* closure, int oldSock, int newSock )
|
||||
{
|
||||
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
|
||||
if ( oldSock != -1 ) {
|
||||
curses_stop_listening( globals, oldSock );
|
||||
}
|
||||
if ( newSock != -1 ) {
|
||||
cursesListenOnSocket( globals, newSock, NULL );
|
||||
}
|
||||
} /* curses_socket_changed */
|
||||
|
||||
/*
|
||||
* Ok, so this doesn't block yet....
|
||||
|
@ -661,17 +678,18 @@ blocking_gotEvent( CursesAppGlobals* globals, int* ch )
|
|||
CommsAddrRec addrRec;
|
||||
|
||||
XP_MEMSET( &addrRec, 0, sizeof(addrRec) );
|
||||
addrRec.conType = COMMS_CONN_IP;
|
||||
addrRec.conType = COMMS_CONN_RELAY;
|
||||
|
||||
addrRec.u.ip.ipAddr = ntohl(addr_sock.sin_addr.s_addr);
|
||||
addrRec.u.ip_relay.ipAddr =
|
||||
ntohl(addr_sock.sin_addr.s_addr);
|
||||
XP_LOGF( "captured incomming ip address: 0x%lx",
|
||||
addrRec.u.ip.ipAddr );
|
||||
addrRec.u.ip_relay.ipAddr );
|
||||
|
||||
if ( comms_checkIncomingStream(globals->cGlobals.game.comms,
|
||||
inboundS,
|
||||
&addrRec ) ) {
|
||||
XP_LOGF( "comms read port: %d",
|
||||
addrRec.u.ip.port );
|
||||
addrRec.u.ip_relay.port );
|
||||
redraw =
|
||||
server_receiveMessage( globals->cGlobals.game.server,
|
||||
inboundS );
|
||||
|
@ -777,7 +795,7 @@ cursesSendOnClose( XWStreamCtxt* stream, void* closure )
|
|||
CursesAppGlobals* globals = (CursesAppGlobals*)closure;
|
||||
|
||||
XP_LOGF( "cursesSendOnClose called" );
|
||||
result = comms_send( globals->cGlobals.game.comms, COMMS_CONN_IP, stream );
|
||||
result = comms_send( globals->cGlobals.game.comms, stream );
|
||||
} /* cursesSendOnClose */
|
||||
|
||||
static XWStreamCtxt*
|
||||
|
@ -814,8 +832,6 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
|
|||
util->vtable->m_util_setTimer = curses_util_setTimer;
|
||||
util->vtable->m_util_requestTime = curses_util_requestTime;
|
||||
|
||||
util->vtable->m_util_listenPortChange = curses_util_listenPortChange;
|
||||
|
||||
util->closure = globals;
|
||||
} /* setupCursesUtilCallbacks */
|
||||
|
||||
|
@ -825,7 +841,7 @@ sendOnClose( XWStreamCtxt* stream, void* closure )
|
|||
CursesAppGlobals* globals = closure;
|
||||
XP_LOGF( "curses sendOnClose called" );
|
||||
XP_ASSERT( !!globals->cGlobals.game.comms );
|
||||
comms_send( globals->cGlobals.game.comms, COMMS_CONN_IP, stream );
|
||||
comms_send( globals->cGlobals.game.comms, stream );
|
||||
} /* sendOnClose */
|
||||
|
||||
static XP_Bool
|
||||
|
@ -858,7 +874,6 @@ void
|
|||
cursesmain( XP_Bool isServer, LaunchParams* params )
|
||||
{
|
||||
int piperesult;
|
||||
int sock;
|
||||
DictionaryCtxt* dict;
|
||||
CommsAddrRec addr;
|
||||
XP_U16 gameID;
|
||||
|
@ -869,6 +884,9 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
|||
globals.cGlobals.params = params;
|
||||
globals.cGlobals.socket = -1;
|
||||
|
||||
globals.cGlobals.socketChanged = curses_socket_changed;
|
||||
globals.cGlobals.socketChangedClosure = &globals;
|
||||
|
||||
globals.cp.showBoardArrow = XP_TRUE;
|
||||
globals.cp.showRobotScores = params->showRobotScores;
|
||||
|
||||
|
@ -883,11 +901,8 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
|||
piperesult = pipe( globals.timepipe );
|
||||
XP_ASSERT( piperesult == 0 );
|
||||
|
||||
cursesListenOnSocket( &globals, globals.timepipe[0], NULL ); /* reader pipe */
|
||||
|
||||
sock = linux_init_socket( &globals.cGlobals );
|
||||
cursesListenOnSocket( &globals, sock, NULL );
|
||||
|
||||
/* reader pipe */
|
||||
cursesListenOnSocket( &globals, globals.timepipe[0], NULL );
|
||||
signal( SIGWINCH, SIGWINCH_handler );
|
||||
initCurses( &globals );
|
||||
|
||||
|
@ -898,11 +913,14 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
|||
params->util, (DrawCtx*)globals.draw,
|
||||
gameID, &globals.cp, linux_tcp_send, &globals );
|
||||
|
||||
addr.conType = COMMS_CONN_IP;
|
||||
addr.u.ip.ipAddr = 0; /* ??? */
|
||||
addr.u.ip.port = params->defaultSendPort;
|
||||
comms_setAddr( globals.cGlobals.game.comms,
|
||||
&addr, params->defaultListenPort );
|
||||
addr.conType = COMMS_CONN_RELAY;
|
||||
addr.u.ip_relay.ipAddr = 0; /* ??? */
|
||||
addr.u.ip_relay.port = params->defaultSendPort;
|
||||
XP_STRNCPY( addr.u.ip_relay.hostName, params->relayName,
|
||||
sizeof(addr.u.ip_relay.hostName) - 1 );
|
||||
XP_STRNCPY( addr.u.ip_relay.cookie, params->cookie,
|
||||
sizeof(addr.u.ip_relay.cookie) - 1 );
|
||||
comms_setAddr( globals.cGlobals.game.comms, &addr );
|
||||
|
||||
model_setDictionary( globals.cGlobals.game.model, params->dict );
|
||||
|
||||
|
@ -926,12 +944,6 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
|||
&globals,
|
||||
(XP_PlayerAddr)0,
|
||||
sendOnClose ) );
|
||||
#if 0
|
||||
cursesListenOnSocket(
|
||||
&globals, NULL, /* replaces below */
|
||||
/* linux_getStreamSocket( params->info.clientInfo.stream ), */
|
||||
params->info.clientInfo.stream );
|
||||
#endif
|
||||
} else {
|
||||
cursesUserError( &globals, "Unable to open connection to server");
|
||||
exit( 0 );
|
||||
|
|
|
@ -95,7 +95,6 @@ struct CursesAppGlobals {
|
|||
struct sockaddr_in listenerSockAddr;
|
||||
short fdCount;
|
||||
struct pollfd fdArray[FD_MAX]; /* one for stdio, one for listening socket */
|
||||
XWStreamCtxt* streams[FD_MAX]; /* [0], for stdin, will be null.... */
|
||||
|
||||
int timepipe[2]; /* for reading/writing "user events" */
|
||||
};
|
||||
|
|
|
@ -249,9 +249,11 @@ createOrLoadObjects( GtkAppGlobals* globals, GtkWidget *widget )
|
|||
stream_destroy( stream );
|
||||
|
||||
} else { /* not reading from a saved file */
|
||||
XP_U16 gameID = (XP_U16)util_getCurSeconds( globals->cGlobals.params->util );
|
||||
XP_U16 gameID;
|
||||
CommsAddrRec addr;
|
||||
|
||||
gameID = (XP_U16)util_getCurSeconds( globals->cGlobals.params->util );
|
||||
|
||||
XP_ASSERT( !!params->relayName );
|
||||
globals->cGlobals.defaultServerName = params->relayName;
|
||||
|
||||
|
@ -262,11 +264,16 @@ createOrLoadObjects( GtkAppGlobals* globals, GtkWidget *widget )
|
|||
params->util, (DrawCtx*)globals->draw,
|
||||
gameID, &globals->cp, linux_tcp_send, globals );
|
||||
|
||||
addr.conType = COMMS_CONN_IP;
|
||||
addr.u.ip.ipAddr = 0; /* ??? */
|
||||
addr.u.ip.port = params->defaultSendPort;
|
||||
comms_setAddr( globals->cGlobals.game.comms,
|
||||
&addr, params->defaultListenPort );
|
||||
addr.conType = COMMS_CONN_RELAY;
|
||||
addr.u.ip_relay.ipAddr = 0;
|
||||
addr.u.ip_relay.port = params->defaultSendPort;
|
||||
XP_STRNCPY( addr.u.ip_relay.hostName, params->relayName,
|
||||
sizeof(addr.u.ip_relay.hostName) - 1 );
|
||||
XP_STRNCPY( addr.u.ip_relay.cookie, params->cookie,
|
||||
sizeof(addr.u.ip_relay.cookie) - 1 );
|
||||
|
||||
/* This may trigger network activity */
|
||||
comms_setAddr( globals->cGlobals.game.comms, &addr );
|
||||
|
||||
model_setDictionary( globals->cGlobals.game.model, params->dict );
|
||||
|
||||
|
@ -1141,18 +1148,6 @@ gtk_util_makeStreamFromAddr(XW_UtilCtxt* uc, XP_PlayerAddr channelNo )
|
|||
return stream;
|
||||
} /* gtk_util_makeStreamFromAddr */
|
||||
|
||||
static void
|
||||
gtk_util_listenPortChange( XW_UtilCtxt* uc, XP_U16 newPort )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)uc->closure;
|
||||
#endif
|
||||
XP_LOGF( "listenPortChange called: not sure what to do" );
|
||||
|
||||
/* if this isn't true, need to tear down and rebind socket */
|
||||
XP_ASSERT( newPort == globals->cGlobals.params->defaultListenPort );
|
||||
} /* gtk_util_listenPortChange */
|
||||
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
static XP_Bool
|
||||
gtk_util_getTraySearchLimits( XW_UtilCtxt* uc, XP_U16* min, XP_U16* max )
|
||||
|
@ -1394,10 +1389,6 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
|
|||
util->vtable->m_util_getTraySearchLimits = gtk_util_getTraySearchLimits;
|
||||
#endif
|
||||
|
||||
#ifdef BEYOND_IR
|
||||
util->vtable->m_util_listenPortChange = gtk_util_listenPortChange;
|
||||
#endif
|
||||
|
||||
util->closure = globals;
|
||||
} /* setupGtkUtilCallbacks */
|
||||
|
||||
|
@ -1470,6 +1461,19 @@ gtkListenOnSocket( GtkAppGlobals* globals, int newSock )
|
|||
XP_LOGF( "g_io_add_watch => %d", result );
|
||||
} /* gtkListenOnSocket */
|
||||
|
||||
static void
|
||||
gtk_socket_changed( void* closure, int oldSock, int newSock )
|
||||
{
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)closure;
|
||||
if ( oldSock != -1 ) {
|
||||
g_source_remove( oldSock );
|
||||
XP_LOGF( "Removed %d from gtk's list of listened-to sockets" );
|
||||
}
|
||||
if ( newSock != -1 ) {
|
||||
gtkListenOnSocket( globals, newSock );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sendOnClose( XWStreamCtxt* stream, void* closure )
|
||||
{
|
||||
|
@ -1477,7 +1481,7 @@ sendOnClose( XWStreamCtxt* stream, void* closure )
|
|||
GtkAppGlobals* globals = closure;
|
||||
|
||||
XP_LOGF( "sendOnClose called" );
|
||||
result = comms_send( globals->cGlobals.game.comms, COMMS_CONN_IP, stream );
|
||||
result = comms_send( globals->cGlobals.game.comms, stream );
|
||||
} /* sendOnClose */
|
||||
|
||||
static void
|
||||
|
@ -1507,6 +1511,9 @@ gtkmain( XP_Bool isServer, LaunchParams* params, int argc, char *argv[] )
|
|||
globals.cGlobals.lastNTilesToUse = MAX_TRAY_TILES;
|
||||
globals.cGlobals.socket = -1;
|
||||
|
||||
globals.cGlobals.socketChanged = gtk_socket_changed;
|
||||
globals.cGlobals.socketChangedClosure = &globals;
|
||||
|
||||
globals.cp.showBoardArrow = XP_TRUE;
|
||||
globals.cp.showRobotScores = params->showRobotScores;
|
||||
|
||||
|
|
|
@ -197,6 +197,7 @@ usage( char* appName, char* msg )
|
|||
"\t [-v] # put scoreboard in vertical mode\n"
|
||||
"\t [-m] # make the robot duMb (smart is default)\n"
|
||||
"\t [-c] # explain robot scores after each move\n"
|
||||
"\t [-C COOKIE] # cookie used to groups games on relay\n"
|
||||
"\t\t # (max of four players total, local and remote)\n"
|
||||
"\t [-b boardSize] # number of columns and rows\n"
|
||||
"\t [-e random_seed] \n"
|
||||
|
@ -228,12 +229,29 @@ linux_tcp_send( XP_U8* buf, XP_U16 buflen, CommsAddrRec* addrRec,
|
|||
|
||||
if ( socket == -1 ) {
|
||||
XP_STATUSF( "linux_tcp_send: socket uninitialized" );
|
||||
} else {
|
||||
socket = linux_init_socket( globals );
|
||||
if ( socket != -1 ) {
|
||||
assert( globals->socket == socket );
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
-1, socket );
|
||||
}
|
||||
}
|
||||
|
||||
if ( socket != -1 ) {
|
||||
XP_U16 netLen = htons( buflen );
|
||||
errno = 0;
|
||||
|
||||
(void)send( socket, &netLen, sizeof(netLen), 0 );
|
||||
result = send( socket, &netLen, sizeof(netLen), 0 );
|
||||
if ( result == sizeof(netLen) ) {
|
||||
result = send( socket, buf, buflen, 0 );
|
||||
}
|
||||
if ( result <= 0 ) {
|
||||
XP_STATUSF( "closing non-functional socket" );
|
||||
close( socket );
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
socket, -1 );
|
||||
globals->socket = -1;
|
||||
}
|
||||
|
||||
XP_STATUSF( "linux_tcp_send: send returned %d of %d (err=%d)",
|
||||
result, buflen, errno );
|
||||
|
@ -512,6 +530,7 @@ main( int argc, char** argv )
|
|||
mainParams.defaultListenPort = DEFAULT_LISTEN_PORT;
|
||||
mainParams.defaultSendPort = DEFAULT_SEND_PORT;
|
||||
mainParams.trayOverlaps = XP_FALSE;
|
||||
mainParams.cookie = "COOKIE";
|
||||
mainParams.gi.boardSize = 15;
|
||||
mainParams.quitAfter = XP_FALSE;
|
||||
mainParams.sleepOnAnchor = XP_FALSE;
|
||||
|
@ -519,6 +538,7 @@ main( int argc, char** argv )
|
|||
mainParams.undoWhenDone = XP_FALSE;
|
||||
mainParams.gi.timerEnabled = XP_FALSE;
|
||||
mainParams.gi.robotSmartness = SMART_ROBOT;
|
||||
|
||||
/* serverName = mainParams.info.clientInfo.serverName = "localhost"; */
|
||||
|
||||
#if defined PLATFORM_GTK
|
||||
|
@ -540,7 +560,7 @@ main( int argc, char** argv )
|
|||
#if defined PLATFORM_GTK
|
||||
"o"
|
||||
#endif
|
||||
"kKf:l:n:Nsd:a:p:e:r:b:qw:Sit:Umvc" );
|
||||
"kKf:l:n:Nsd:a:p:e:r:b:qw:Sit:UmvcC:" );
|
||||
switch( opt ) {
|
||||
case 'h':
|
||||
case '?':
|
||||
|
@ -549,6 +569,9 @@ main( int argc, char** argv )
|
|||
case 'c':
|
||||
mainParams.showRobotScores = XP_TRUE;
|
||||
break;
|
||||
case 'C':
|
||||
mainParams.cookie = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
mainParams.gi.dictName = copyString( MPPARM(mainParams.util->mpool)
|
||||
optarg );
|
||||
|
|
|
@ -43,6 +43,7 @@ typedef struct LaunchParams {
|
|||
DictionaryCtxt* dict;
|
||||
CurGameInfo gi;
|
||||
char* fileName;
|
||||
char* cookie;
|
||||
VTableMgr* vtMgr;
|
||||
XP_U16 nLocalPlayers;
|
||||
XP_Bool trayOverlaps; /* probably only interesting for GTK case */
|
||||
|
@ -69,6 +70,8 @@ typedef struct LaunchParams {
|
|||
|
||||
} LaunchParams;
|
||||
|
||||
typedef void (*SocketChangedFunc)(void* closure, int oldsock, int newsock );
|
||||
|
||||
typedef struct CommonGlobals {
|
||||
LaunchParams* params;
|
||||
|
||||
|
@ -77,6 +80,8 @@ typedef struct CommonGlobals {
|
|||
/* UDP comms stuff */
|
||||
char* defaultServerName;
|
||||
int socket;
|
||||
SocketChangedFunc socketChanged;
|
||||
void* socketChangedClosure;
|
||||
} CommonGlobals;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue