Replace UDP-based messaging with TCP. Stream protocol says distinct

message is length plus data.  Use non-deprecated gtk select-like
function.  With these changes can play full games through the relay on
gtk.  Untested on ncurses but probably broken.
This commit is contained in:
ehouse 2005-03-06 18:07:00 +00:00
parent e2c2486f71
commit 1fba8494f3
6 changed files with 124 additions and 194 deletions

View file

@ -871,6 +871,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
globals.amServer = isServer;
globals.cGlobals.params = params;
globals.cGlobals.socket = -1;
globals.cp.showBoardArrow = XP_TRUE;
globals.cp.showRobotScores = params->showRobotScores;
@ -879,7 +880,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
setupCursesUtilCallbacks( &globals, params->util );
globals.cGlobals.defaultServerName = params->info.clientInfo.serverName;
globals.cGlobals.defaultServerName = params->relayName;
cursesListenOnSocket( &globals, 0, NULL ); /* stdin */
@ -888,8 +889,8 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
cursesListenOnSocket( &globals, globals.timepipe[0], NULL ); /* reader pipe */
sock = initListenerSocket( params->defaultListenPort );
cursesListenOnSocket( &globals, sock, NULL );
sock = linux_init_socket( &globals.cGlobals );
cursesListenOnSocket( &globals, sock, NULL );
signal( SIGWINCH, SIGWINCH_handler );
initCurses( &globals );
@ -899,7 +900,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
gameID = (XP_U16)util_getCurSeconds( globals.cGlobals.params->util );
game_makeNewGame( MEMPOOL &globals.cGlobals.game, &params->gi,
params->util, (DrawCtx*)globals.draw,
gameID, &globals.cp, linux_udp_send, &globals );
gameID, &globals.cp, linux_tcp_send, &globals );
addr.conType = COMMS_CONN_IP;
addr.u.ip.ipAddr = 0; /* ??? */

View file

@ -244,7 +244,7 @@ createOrLoadObjects( GtkAppGlobals* globals, GtkWidget *widget )
params->dict, params->util,
(DrawCtx*)globals->draw,
&globals->cp,
linux_udp_send, globals );
linux_tcp_send, globals );
stream_destroy( stream );
@ -252,17 +252,15 @@ createOrLoadObjects( GtkAppGlobals* globals, GtkWidget *widget )
XP_U16 gameID = (XP_U16)util_getCurSeconds( globals->cGlobals.params->util );
CommsAddrRec addr;
if ( serverRole == SERVER_ISCLIENT ) {
globals->cGlobals.defaultServerName =
params->info.clientInfo.serverName;
}
XP_ASSERT( !!params->relayName );
globals->cGlobals.defaultServerName = params->relayName;
params->gi.gameID = util_getCurSeconds(globals->cGlobals.params->util);
XP_STATUSF( "grabbed gameID: %ld\n", params->gi.gameID );
game_makeNewGame( MEMPOOL &globals->cGlobals.game, &params->gi,
params->util, (DrawCtx*)globals->draw,
gameID, &globals->cp, linux_udp_send, globals );
gameID, &globals->cp, linux_tcp_send, globals );
addr.conType = COMMS_CONN_IP;
addr.u.ip.ipAddr = 0; /* ??? */
@ -307,13 +305,10 @@ configure_event( GtkWidget *widget, GdkEventConfigure *event,
firstTime = (globals->draw == NULL);
if ( firstTime ) {
int listenSocket =
initListenerSocket(globals->cGlobals.params->defaultListenPort);
int listenSocket = linux_init_socket( &globals->cGlobals );
gtkListenOnSocket( globals, listenSocket );
createOrLoadObjects( globals, widget );
} else {
/* gdk_pixmap_unref( ((GtkDrawCtx*)globals->draw)->pixmap ); */
}
width = widget->allocation.width - (RIGHT_MARGIN + BOARD_LEFT_MARGIN);
@ -544,7 +539,7 @@ new_game( GtkWidget* widget, GtkAppGlobals* globals )
XP_STATUSF( "grabbed gameID: %ld\n", gameID );
game_reset( MEMPOOL &globals->cGlobals.game, gi, gameID, &globals->cp,
linux_udp_send, globals );
linux_tcp_send, globals );
if ( isClient ) {
XWStreamCtxt* stream =
@ -1406,92 +1401,80 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
util->closure = globals;
} /* setupGtkUtilCallbacks */
static void
newConnectionInput( gpointer data, gint source,
GdkInputCondition condition )
static gboolean
newConnectionInput( GIOChannel *source,
GIOCondition condition,
gpointer data )
{
int sock = g_io_channel_unix_get_fd( source );
GtkAppGlobals* globals = (GtkAppGlobals*)data;
struct sockaddr_in addr_sock;
int flen, nBytes;
char buf[256];
char* bufPtr = buf;
XP_LOGF( "Incomming message!!!" );
XP_ASSERT( sock == globals->cGlobals.socket );
memset( buf, 0, sizeof(buf) );
flen = sizeof(struct sockaddr_in);
nBytes = recvfrom( source, buf, sizeof(buf), 0,
(struct sockaddr *)&addr_sock, &flen );
XP_ASSERT( nBytes != -1 );
if ( (condition & G_IO_HUP) != 0 ) {
if ( !globals->dropIncommingMsgs && nBytes != -1 ) {
XWStreamCtxt* inboundS;
XP_Bool redraw = XP_FALSE;
globals->cGlobals.socket = -1;
return FALSE; /* remove the event source */
/* somehow, we need to associate a return address with a client. This
is the address we'll be using from now on. So when a connection is
made, pass the return address to the comms module. It can decide
from the message if it's seen the message source before.*/
} else if ( (condition & G_IO_IN) != 0 ) {
ssize_t nRead;
unsigned short packetSize;
unsigned short tmp;
unsigned char buf[512];
/* inboundS = linux_make_inbound_socketStream( */
/* inboundSocket, &returnSockAddr, addrLen ); */
XP_LOGF( "activity on socket %d", sock );
nRead = recv( sock, &tmp, sizeof(tmp), 0 );
assert( nRead == 2 );
inboundS = stream_from_msgbuf( &globals->cGlobals, bufPtr, nBytes );
if ( !!inboundS ) {
CommsAddrRec addrRec;
packetSize = ntohs( tmp );
nRead = recv( sock, buf, packetSize, 0 );
XP_MEMSET( &addrRec, 0, sizeof(addrRec) );
addrRec.conType = COMMS_CONN_IP;
addrRec.u.ip.ipAddr = ntohl(addr_sock.sin_addr.s_addr);
XP_LOGF( "captured incomming ip address: 0x%lx",
addrRec.u.ip.ipAddr );
if ( comms_checkIncommingStream( globals->cGlobals.game.comms,
inboundS, &addrRec ) ) {
redraw = server_receiveMessage( globals->cGlobals.game.server,
inboundS );
if ( !globals->dropIncommingMsgs && nRead > 0 ) {
XWStreamCtxt* inboundS;
XP_Bool redraw = XP_FALSE;
inboundS = stream_from_msgbuf( &globals->cGlobals, buf, nRead );
if ( !!inboundS ) {
if ( comms_checkIncommingStream( globals->cGlobals.game.comms,
inboundS, NULL ) ) {
redraw = server_receiveMessage(globals->cGlobals.game.server
, inboundS );
}
stream_destroy( inboundS );
}
stream_destroy( inboundS );
}
/* 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 ( redraw ) {
gtk_util_requestTime( globals->cGlobals.params->util );
/* 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 ( redraw ) {
gtk_util_requestTime( globals->cGlobals.params->util );
} else {
redraw = server_do( globals->cGlobals.game.server );
}
if ( redraw ) {
board_draw( globals->cGlobals.game.board );
}
} else {
redraw = server_do( globals->cGlobals.game.server );
XP_LOGF( "errno from read: %d", errno );
}
if ( redraw ) {
board_draw( globals->cGlobals.game.board );
}
} else {
XP_LOGF( "errno from accept: %d", errno );
}
return TRUE; /* FALSE means to remove event source */
} /* newConnectionInput */
static void
newConnectionDestroy( gpointer data )
{
XP_LOGF( "newConnectionDestroy called" );
} /* newConnectionDestroy */
/* Make gtk listen for events on the socket that clients will use to
* connect to us.
*/
static void
gtkListenOnSocket( GtkAppGlobals* globals, int newSock )
{
guint result = gtk_input_add_full( newSock,
GDK_INPUT_READ,
newConnectionInput,
(GtkCallbackMarshal)0L,
globals,
newConnectionDestroy );
globals->listenSockKey = result;
GIOChannel* channel = g_io_channel_unix_new( newSock );
guint result = g_io_add_watch( channel,
G_IO_IN | G_IO_HUP,
newConnectionInput,
globals );
XP_LOGF( "g_io_add_watch => %d", result );
} /* gtkListenOnSocket */
static void
@ -1529,6 +1512,7 @@ gtkmain( XP_Bool isServer, LaunchParams* params, int argc, char *argv[] )
globals.cGlobals.params = params;
globals.cGlobals.lastNTilesToUse = MAX_TRAY_TILES;
globals.cGlobals.socket = -1;
globals.cp.showBoardArrow = XP_TRUE;
globals.cp.showRobotScores = params->showRobotScores;

View file

@ -70,7 +70,6 @@ typedef struct GtkAppGlobals {
GtkAdjustment* adjustment;
ClientStreamRec clientRecs[MAX_NUM_PLAYERS];
guint listenSockKey; /* save return from gtk_input_add_full */
CommonPrefs cp;

View file

@ -28,7 +28,6 @@
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <time.h>
#include "linuxmain.h"
@ -200,7 +199,6 @@ usage( char* appName, char* msg )
"\t [-c] # explain robot scores after each move\n"
"\t\t # (max of four players total, local and remote)\n"
"\t [-b boardSize] # number of columns and rows\n"
"\t [-l listen_port] # port for inet connection (4999 default)\n"
"\t [-e random_seed] \n"
"\t [-t initial_minutes_on_timer] \n"
"# --------------- choose client or server ----------\n"
@ -208,106 +206,83 @@ usage( char* appName, char* msg )
"\t -d xwd_file # provides tile counts & values\n"
"\t\t # list each player as local or remote\n"
"\t [-N]* # remote client (listen for connection)\n"
"# --------------- OR client-only ----------\n"
"\t [-a server_addr] # be a client (on port spec'd above)\n"
"\t [-p client_port] # must != server's port if on same device"
"\t [-a relay_addr] # use relay (via port spec'd above)\n"
"" " (default localhost)\n"
"\t [-p relay_port] # relay is at this port\n"
/* "# --------------- OR client-only ----------\n" */
/* "\t [-p client_port] # must != server's port if on same device" */
"\nexample: \n"
"\tserver: ./xwords -d dict.xwd -s -r Eric -N\n"
"\tclient: ./xwords -d dict.xwd -r Kati -p 4998 -l 6000\n"
"\tserver: ./xwords -d dict.xwd -s -a localhost -p 10999 -r Eric -N\n"
"\tclient: ./xwords -d dict.xwd -a localhost -p 10999 -r Kati\n"
, appName );
exit(1);
}
XP_S16
linux_udp_send( XP_U8* buf, XP_U16 buflen, CommsAddrRec* addrRec,
linux_tcp_send( XP_U8* buf, XP_U16 buflen, CommsAddrRec* addrRec,
void* closure )
{
CommonGlobals* globals = (CommonGlobals*)closure;
XP_S16 result = 0;
int socket = globals->socket;
if ( socket == -1 ) {
XP_STATUSF( "linux_tcp_send: socket uninitialized" );
} else {
XP_U16 netLen = htons( buflen );
errno = 0;
(void)send( socket, &netLen, sizeof(netLen), 0 );
result = send( socket, buf, buflen, 0 );
XP_STATUSF( "linux_tcp_send: send returned %d of %d (err=%d)",
result, buflen, errno );
}
return result;
} /* linux_tcp_send */
int
linux_init_socket( CommonGlobals* cGlobals )
{
struct sockaddr_in to_sock;
struct hostent* host;
XP_S16 result;
int sock;
/* XP_U8* msg; */
XP_LOGF( "linux_udp_send" );
/* make a local copy of the address to send to */
sock = socket( AF_INET, SOCK_DGRAM, 0 );
int sock = cGlobals->socket;
if ( sock == -1 ) {
XP_DEBUGF( "socket returned -1\n" );
return -1;
}
if ( !!addrRec ) {
/* make a local copy of the address to send to */
sock = socket( AF_INET, SOCK_STREAM, 0 );
if ( sock == -1 ) {
XP_DEBUGF( "socket returned -1\n" );
return -1;
}
XP_ASSERT( addrRec->conType == COMMS_CONN_IP );
XP_MEMSET( &to_sock, 0, sizeof(to_sock) );
XP_STATUSF( "target IP = 0x%lx", addrRec->u.ip.ipAddr );
to_sock.sin_addr.s_addr = htonl(addrRec->u.ip.ipAddr);
to_sock.sin_port = htons(addrRec->u.ip.port);
XP_STATUSF( "0: sending to port %d(0x%x)",
addrRec->u.ip.port, addrRec->u.ip.port );
} else {
to_sock.sin_port = htons(globals->params->defaultSendPort);
to_sock.sin_port = htons(cGlobals->params->defaultSendPort);
XP_STATUSF( "1: sending to port %d",
globals->params->defaultSendPort );
if (( host = gethostbyname(globals->defaultServerName) ) == NULL ) {
cGlobals->params->defaultSendPort );
if (( host = gethostbyname(cGlobals->params->relayName) ) == NULL ) {
XP_WARNF( "gethostbyname returned -1\n" );
return -1;
} else {
XP_WARNF( "gethostbyname for %s worked",
globals->defaultServerName );
cGlobals->defaultServerName );
}
memcpy( &(to_sock.sin_addr.s_addr), host->h_addr_list[0],
sizeof(struct in_addr));
to_sock.sin_family = AF_INET;
errno = 0;
if ( 0 == connect( sock, (const struct sockaddr*)&to_sock,
sizeof(to_sock) ) ) {
cGlobals->socket = sock;
} else {
close( sock );
XP_STATUSF( "connect failed: %d", errno );
}
}
to_sock.sin_family = AF_INET;
/* msg = malloc( buflen ); */
/* XP_MEMCPY( msg, buf, buflen ); */
errno = 0;
XP_STATUSF( "checking: errno=%d", (short)errno );
result = sendto( sock, buf, buflen, 0,
(struct sockaddr *)&to_sock, sizeof(to_sock) );
XP_STATUSF( "foo: sendto returned %d of %d (err=%d)",
result, buflen, errno );
close(sock);
/* free( msg ); */
return result;
} /* linux_udp_send */
int
initListenerSocket( int port )
{
int newSocket;
int result;
struct sockaddr_in sockAddr;
XP_DEBUGF( "opening socket to listen on port %d", port );
newSocket = socket( AF_INET, DGRAM_TYPE, 0 );
XP_DEBUGF( "socket returned %d", newSocket );
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockAddr.sin_port = htons(port);
result = bind( newSocket, (struct sockaddr*)&sockAddr, sizeof(sockAddr) );
XP_LOGF( "bind on port %d returned %d; errno=%d",
port, result, errno );
/* result = listen( newSocket, 5 ); */
/* XP_DEBUGF( "listen returned %d; errno=%d\n", result, errno ); */
return newSocket;
} /* initListenerSocket */
return sock;
} /* linux_init_socket */
/* Create a stream for the incomming message buffer, and read in any
information specific to our platform's comms layer (return address, say)
@ -485,9 +460,8 @@ main( int argc, char** argv )
int opt;
int totalPlayerCount = 0;
XP_Bool isServer = XP_FALSE;
char* listenPortNumString = NULL;
char* sendPortNumString = NULL;
char* serverName = "localhost";
char* relayName = "localhost";
unsigned int seed = defaultRandomSeed();
LaunchParams mainParams;
XP_U16 robotCount = 0;
@ -592,9 +566,6 @@ main( int argc, char** argv )
mainParams.gi.players[index].isLocal = XP_FALSE;
++mainParams.info.serverInfo.nRemotePlayers;
break;
case 'l':
listenPortNumString = optarg;
break;
case 'p':
sendPortNumString = optarg;
break;
@ -622,7 +593,7 @@ main( int argc, char** argv )
break;
case 'a':
/* mainParams.info.clientInfo.serverName = */
serverName = optarg;
relayName = optarg;
break;
case 'q':
mainParams.quitAfter = XP_TRUE;
@ -667,9 +638,6 @@ main( int argc, char** argv )
}
/* convert strings to whatever */
if ( listenPortNumString ) {
mainParams.defaultListenPort = atoi( listenPortNumString );
}
if ( sendPortNumString != NULL ) {
mainParams.defaultSendPort = atoi( sendPortNumString );
}
@ -706,31 +674,7 @@ main( int argc, char** argv )
}
}
/* setup sockets and any other stuff not specific to GTK or ncurses */
if ( isServer ) {
} else {
/* struct hostent* hostinfo; */
/* hostinfo = gethostbyname( serverName ); */
/* if ( !hostinfo ) { */
/* fprintf( stderr, "unable to get host info for %s\n", serverName ); */
/* exit( 0 ); */
/* } else { */
/* char* hostName = inet_ntoa( *(struct in_addr*)hostinfo->h_addr ); */
/* unsigned long int serverAddr; */
/* fprintf( stderr, "gethostbyname returned %s\n", hostName ); */
/* serverAddr = inet_addr(hostName); */
/* fprintf( stderr, "inet_addr returned %lu\n", serverAddr ); */
/* mainParams.info.clientInfo.stream = */
/* linux_make_outbound_socketStream( serverAddr, serverPort ); */
/* if ( !stream_open( mainParams.info.clientInfo.stream ) { */
/* fprintf( stderr, "ERROR: unable to connect to server\n" ); */
/* exit(0); */
/* } */
/* } */
mainParams.info.clientInfo.serverName = serverName;
}
mainParams.relayName = relayName;
/* mainParams.pipe = linuxCommPipeCtxtMake( isServer ); */

View file

@ -37,9 +37,10 @@ typedef struct LinuxBMStruct {
DictionaryCtxt* linux_dictionary_make( MPFORMAL char* dictFileName );
int initListenerSocket( int port );
XP_S16 linux_udp_send( XP_U8* buf, XP_U16 buflen, CommsAddrRec* addrRec,
XP_S16 linux_tcp_send( XP_U8* buf, XP_U16 buflen, CommsAddrRec* addrRec,
void* closure );
XWStreamCtxt* stream_from_msgbuf( CommonGlobals* globals, char* bufPtr,
int linux_init_socket( CommonGlobals* cGlobals );
XWStreamCtxt* stream_from_msgbuf( CommonGlobals* cGlobals, char* bufPtr,
XP_U16 nBytes );
XP_UCHAR* linux_getErrString( UtilErrID id );
XP_UCHAR* strFromStream( XWStreamCtxt* stream );

View file

@ -31,7 +31,6 @@ typedef struct ServerInfo {
} ServerInfo;
typedef struct ClientInfo {
char* serverName; /* still need this? */
} ClientInfo;
typedef struct LinuxUtilCtxt {
@ -59,6 +58,7 @@ typedef struct LaunchParams {
Connectedness serverRole;
char* relayName;
union {
ServerInfo serverInfo;
ClientInfo clientInfo;
@ -76,6 +76,7 @@ typedef struct CommonGlobals {
XP_U16 lastNTilesToUse;
/* UDP comms stuff */
char* defaultServerName;
int socket;
} CommonGlobals;
#endif