From 3d54ec402a6c7c57c28cc3efb78d68b37713edbb Mon Sep 17 00:00:00 2001 From: ehouse Date: Sat, 19 Mar 2005 22:07:53 +0000 Subject: [PATCH] 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. --- linux/cursesmain.c | 86 ++++++++++++++++++++++++++-------------------- linux/cursesmain.h | 1 - linux/gtkmain.c | 75 ++++++++++++++++++++++------------------ linux/linuxmain.c | 31 ++++++++++++++--- linux/main.h | 5 +++ 5 files changed, 122 insertions(+), 76 deletions(-) diff --git a/linux/cursesmain.c b/linux/cursesmain.c index 78e14ecbc..f0a4a1a90 100644 --- a/linux/cursesmain.c +++ b/linux/cursesmain.c @@ -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 ); diff --git a/linux/cursesmain.h b/linux/cursesmain.h index 9e640b5df..c76f5e883 100644 --- a/linux/cursesmain.h +++ b/linux/cursesmain.h @@ -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" */ }; diff --git a/linux/gtkmain.c b/linux/gtkmain.c index e41cc190d..19cc4a8ae 100644 --- a/linux/gtkmain.c +++ b/linux/gtkmain.c @@ -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 ) @@ -1244,24 +1239,24 @@ makeShowButtonFromBitmap( GtkAppGlobals* globals, GtkWidget* parent, GtkStyle *style; if ( file_exists( fileName ) ) { - button = gtk_button_new(); + button = gtk_button_new(); - style = gtk_widget_get_style(parent); + style = gtk_widget_get_style(parent); - pixmap = gdk_pixmap_create_from_xpm( parent->window, &mask, - &style->bg[GTK_STATE_NORMAL], - fileName ); - pixmapWid = gtk_pixmap_new( pixmap, mask ); - gtk_container_add( GTK_CONTAINER(button), pixmapWid ); + pixmap = gdk_pixmap_create_from_xpm( parent->window, &mask, + &style->bg[GTK_STATE_NORMAL], + fileName ); + pixmapWid = gtk_pixmap_new( pixmap, mask ); + gtk_container_add( GTK_CONTAINER(button), pixmapWid ); - gtk_widget_show( pixmapWid ); + gtk_widget_show( pixmapWid ); } else { - button = gtk_button_new_with_label( alt ); + button = gtk_button_new_with_label( alt ); } gtk_widget_show( button ); if ( func != NULL ) { - gtk_signal_connect( GTK_OBJECT(button), "clicked", func, globals ); + gtk_signal_connect( GTK_OBJECT(button), "clicked", func, globals ); } return button; @@ -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 */ @@ -1430,7 +1421,7 @@ newConnectionInput( GIOChannel *source, inboundS = stream_from_msgbuf( &globals->cGlobals, buf, nRead ); if ( !!inboundS ) { if ( comms_checkIncomingStream( globals->cGlobals.game.comms, - inboundS, NULL ) ) { + inboundS, NULL ) ) { redraw = server_receiveMessage(globals->cGlobals.game.server , inboundS ); } @@ -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; diff --git a/linux/linuxmain.c b/linux/linuxmain.c index 28c28b6b7..dbd98e857 100644 --- a/linux/linuxmain.c +++ b/linux/linuxmain.c @@ -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, buf, buflen, 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 ); diff --git a/linux/main.h b/linux/main.h index 96ebf6203..7a9f1805b 100644 --- a/linux/main.h +++ b/linux/main.h @@ -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