Start adding bt support to linux port. Required removing assumptions

that all connectivity was with relay and over streaming sockets (since
BT is using l2cap's datagram-style sockets.)  With this checkin, a full
robot-vs-robot game is possible with palm as host and linux as client.
Linux as host isn't started yet.
This commit is contained in:
ehouse 2006-08-26 21:15:20 +00:00
parent 7d48f2e430
commit a605fd4d49
8 changed files with 424 additions and 61 deletions

View file

@ -59,6 +59,9 @@ DEFINES += -DFEATURE_TRAY_EDIT
#DEFINES += -DDRAW_WITH_PRIMITIVES #DEFINES += -DDRAW_WITH_PRIMITIVES
DEFINES += -DBEYOND_IR DEFINES += -DBEYOND_IR
# Bluetooth support
DEFINES += -DXWFEATURE_BLUETOOTH
# Let users pick the tiles going into their trays # Let users pick the tiles going into their trays
#DEFINES += -DFEATURE_TRAY_EDIT #DEFINES += -DFEATURE_TRAY_EDIT
DEFINES += -DDONT_ABORT_ENGINE DEFINES += -DDONT_ABORT_ENGINE
@ -85,10 +88,11 @@ OBJ = $(PLATFORM)/linuxmain.o \
$(PLATFORM)/cursesdlgutil.o \ $(PLATFORM)/cursesdlgutil.o \
$(PLATFORM)/cursesletterask.o \ $(PLATFORM)/cursesletterask.o \
$(PLATFORM)/filestream.o \ $(PLATFORM)/filestream.o \
$(PLATFORM)/linuxbt.o \
# $(PLATFORM)/linuxcommpipe.o \ # $(PLATFORM)/linuxcommpipe.o \
LIBS = -lm -L $(HOME)/usr/local/pilot/lib $(GPROFFLAG) LIBS = -lm -lbluetooth -L $(HOME)/usr/local/pilot/lib $(GPROFFLAG)
ifneq (,$(findstring DPLATFORM_GTK,$(DEFINES))) ifneq (,$(findstring DPLATFORM_GTK,$(DEFINES)))
LIBS += `pkg-config --libs gtk+-2.0` LIBS += `pkg-config --libs gtk+-2.0`

View file

@ -704,7 +704,8 @@ blocking_gotEvent( CursesAppGlobals* globals, int* ch )
--numEvents; --numEvents;
nBytes = linux_receive( &globals->cGlobals, buf, sizeof(buf) ); nBytes = linux_relay_receive( &globals->cGlobals, buf,
sizeof(buf) );
if ( nBytes != -1 ) { if ( nBytes != -1 ) {
XWStreamCtxt* inboundS; XWStreamCtxt* inboundS;
@ -935,7 +936,10 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
setupCursesUtilCallbacks( &globals, params->util ); setupCursesUtilCallbacks( &globals, params->util );
globals.cGlobals.defaultServerName = params->relayName; if ( params->conType == COMMS_CONN_RELAY ) {
globals.cGlobals.u.relay.defaultServerName
= params->connInfo.relay.relayName;
}
cursesListenOnSocket( &globals, 0, NULL ); /* stdin */ cursesListenOnSocket( &globals, 0, NULL ); /* stdin */
@ -952,16 +956,16 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
gameID = (XP_U16)util_getCurSeconds( globals.cGlobals.params->util ); gameID = (XP_U16)util_getCurSeconds( globals.cGlobals.params->util );
game_makeNewGame( MEMPOOL &globals.cGlobals.game, &params->gi, game_makeNewGame( MEMPOOL &globals.cGlobals.game, &params->gi,
params->util, (DrawCtx*)globals.draw, params->util, (DrawCtx*)globals.draw,
gameID, &globals.cp, linux_tcp_send, &globals ); gameID, &globals.cp, linux_send, &globals );
if ( globals.cGlobals.game.comms ) { if ( globals.cGlobals.game.comms ) {
CommsAddrRec addr; CommsAddrRec addr;
addr.conType = COMMS_CONN_RELAY; addr.conType = COMMS_CONN_RELAY;
addr.u.ip_relay.ipAddr = 0; /* ??? */ addr.u.ip_relay.ipAddr = 0; /* ??? */
addr.u.ip_relay.port = params->defaultSendPort; addr.u.ip_relay.port = params->connInfo.relay.defaultSendPort;
XP_STRNCPY( addr.u.ip_relay.hostName, params->relayName, XP_STRNCPY( addr.u.ip_relay.hostName, params->connInfo.relay.relayName,
sizeof(addr.u.ip_relay.hostName) - 1 ); sizeof(addr.u.ip_relay.hostName) - 1 );
XP_STRNCPY( addr.u.ip_relay.cookie, params->cookie, XP_STRNCPY( addr.u.ip_relay.cookie, params->connInfo.relay.cookie,
sizeof(addr.u.ip_relay.cookie) - 1 ); sizeof(addr.u.ip_relay.cookie) - 1 );
comms_setAddr( globals.cGlobals.game.comms, &addr ); comms_setAddr( globals.cGlobals.game.comms, &addr );
} }

View file

@ -41,6 +41,7 @@
#include "main.h" #include "main.h"
#include "linuxmain.h" #include "linuxmain.h"
#include "linuxbt.h"
/* #include "gtkmain.h" */ /* #include "gtkmain.h" */
#include "draw.h" #include "draw.h"
@ -247,7 +248,7 @@ createOrLoadObjects( GtkAppGlobals* globals )
params->dict, params->util, params->dict, params->util,
(DrawCtx*)globals->draw, (DrawCtx*)globals->draw,
&globals->cp, &globals->cp,
linux_tcp_send, globals ); linux_send, globals );
stream_destroy( stream ); stream_destroy( stream );
@ -255,25 +256,37 @@ createOrLoadObjects( GtkAppGlobals* globals )
XP_U16 gameID; XP_U16 gameID;
CommsAddrRec addr; CommsAddrRec addr;
addr.conType = params->conType;
gameID = (XP_U16)util_getCurSeconds( globals->cGlobals.params->util ); gameID = (XP_U16)util_getCurSeconds( globals->cGlobals.params->util );
XP_ASSERT( !!params->relayName ); if ( addr.conType == COMMS_CONN_RELAY ) {
globals->cGlobals.defaultServerName = params->relayName; XP_ASSERT( !!params->connInfo.relay.relayName );
globals->cGlobals.u.relay.defaultServerName
= params->connInfo.relay.relayName;
}
params->gi.gameID = util_getCurSeconds(globals->cGlobals.params->util); params->gi.gameID = util_getCurSeconds(globals->cGlobals.params->util);
XP_STATUSF( "grabbed gameID: %ld\n", params->gi.gameID ); XP_STATUSF( "grabbed gameID: %ld\n", params->gi.gameID );
game_makeNewGame( MEMPOOL &globals->cGlobals.game, &params->gi, game_makeNewGame( MEMPOOL &globals->cGlobals.game, &params->gi,
params->util, (DrawCtx*)globals->draw, params->util, (DrawCtx*)globals->draw,
gameID, &globals->cp, linux_tcp_send, globals ); gameID, &globals->cp, linux_send, globals );
addr.conType = COMMS_CONN_RELAY; addr.conType = params->conType;
addr.u.ip_relay.ipAddr = 0; if ( addr.conType == COMMS_CONN_RELAY ) {
addr.u.ip_relay.port = params->defaultSendPort; addr.u.ip_relay.ipAddr = 0;
XP_STRNCPY( addr.u.ip_relay.hostName, params->relayName, addr.u.ip_relay.port = params->connInfo.relay.defaultSendPort;
sizeof(addr.u.ip_relay.hostName) - 1 ); XP_STRNCPY( addr.u.ip_relay.hostName, params->connInfo.relay.relayName,
XP_STRNCPY( addr.u.ip_relay.cookie, params->cookie, sizeof(addr.u.ip_relay.hostName) - 1 );
sizeof(addr.u.ip_relay.cookie) - 1 ); XP_STRNCPY( addr.u.ip_relay.cookie, params->connInfo.relay.cookie,
sizeof(addr.u.ip_relay.cookie) - 1 );
} else if ( addr.conType == COMMS_CONN_BT ) {
XP_ASSERT( sizeof(addr.u.bt.btAddr)
>= sizeof(params->connInfo.bt.hostAddr));
XP_MEMCPY( &addr.u.bt.btAddr, &params->connInfo.bt.hostAddr,
sizeof(params->connInfo.bt.hostAddr) );
}
/* This may trigger network activity */ /* This may trigger network activity */
if ( !!globals->cGlobals.game.comms ) { if ( !!globals->cGlobals.game.comms ) {
@ -464,6 +477,8 @@ quit( void* XP_UNUSED(dunno), GtkAppGlobals* globals )
game_dispose( &globals->cGlobals.game ); /* takes care of the dict */ game_dispose( &globals->cGlobals.game ); /* takes care of the dict */
gi_disposePlayerInfo( MEMPOOL &globals->cGlobals.params->gi ); gi_disposePlayerInfo( MEMPOOL &globals->cGlobals.params->gi );
linux_bt_close( &globals->cGlobals );
vtmgr_destroy( MEMPOOL globals->cGlobals.params->vtMgr ); vtmgr_destroy( MEMPOOL globals->cGlobals.params->vtMgr );
mpool_destroy( globals->cGlobals.params->util->mpool ); mpool_destroy( globals->cGlobals.params->util->mpool );
@ -547,7 +562,7 @@ new_game( GtkWidget* XP_UNUSED(widget), GtkAppGlobals* globals )
XP_STATUSF( "grabbed gameID: %ld\n", gameID ); XP_STATUSF( "grabbed gameID: %ld\n", gameID );
game_reset( MEMPOOL &globals->cGlobals.game, gi, game_reset( MEMPOOL &globals->cGlobals.game, gi,
globals->cGlobals.params->util, globals->cGlobals.params->util,
gameID, &globals->cp, linux_tcp_send, globals ); gameID, &globals->cp, linux_send, globals );
if ( isClient ) { if ( isClient ) {
XWStreamCtxt* stream = XWStreamCtxt* stream =
@ -1472,7 +1487,14 @@ newConnectionInput( GIOChannel *source,
ssize_t nRead; ssize_t nRead;
unsigned char buf[512]; unsigned char buf[512];
nRead = linux_receive( &globals->cGlobals, buf, sizeof(buf) ); if ( globals->cGlobals.params->conType == COMMS_CONN_RELAY ) {
nRead = linux_relay_receive( &globals->cGlobals,
buf, sizeof(buf) );
} else if ( globals->cGlobals.params->conType == COMMS_CONN_BT ) {
nRead = linux_bt_receive( &globals->cGlobals, buf, sizeof(buf) );
} else {
XP_ASSERT( 0 );
}
if ( !globals->dropIncommingMsgs && nRead > 0 ) { if ( !globals->dropIncommingMsgs && nRead > 0 ) {
XWStreamCtxt* inboundS; XWStreamCtxt* inboundS;
@ -1482,8 +1504,9 @@ newConnectionInput( GIOChannel *source,
if ( !!inboundS ) { if ( !!inboundS ) {
if ( comms_checkIncomingStream( globals->cGlobals.game.comms, if ( comms_checkIncomingStream( globals->cGlobals.game.comms,
inboundS, NULL ) ) { inboundS, NULL ) ) {
redraw = server_receiveMessage(globals->cGlobals.game.server redraw =
, inboundS ); server_receiveMessage(globals->cGlobals.game.server,
inboundS );
} }
stream_destroy( inboundS ); stream_destroy( inboundS );
} }
@ -1525,6 +1548,7 @@ static void
gtk_socket_changed( void* closure, int oldSock, int newSock ) gtk_socket_changed( void* closure, int oldSock, int newSock )
{ {
GtkAppGlobals* globals = (GtkAppGlobals*)closure; GtkAppGlobals* globals = (GtkAppGlobals*)closure;
XP_ASSERT( oldSock == globals->cGlobals.socket );
if ( oldSock != -1 ) { if ( oldSock != -1 ) {
g_source_remove( oldSock ); g_source_remove( oldSock );
XP_LOGF( "Removed %d from gtk's list of listened-to sockets" ); XP_LOGF( "Removed %d from gtk's list of listened-to sockets" );
@ -1532,6 +1556,7 @@ gtk_socket_changed( void* closure, int oldSock, int newSock )
if ( newSock != -1 ) { if ( newSock != -1 ) {
gtkListenOnSocket( globals, newSock ); gtkListenOnSocket( globals, newSock );
} }
globals->cGlobals.socket = newSock;
} }
static void static void

157
linux/linuxbt.c Normal file
View file

@ -0,0 +1,157 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE";-*- */
/*
* Copyright 2006 by Eric House (xwords@eehouse.org). All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef XWFEATURE_BLUETOOTH
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include "linuxbt.h"
#include "comms.h"
typedef struct LinBtStuff {
CommonGlobals* globals;
XP_Bool amMaster;
} LinBtStuff;
static LinBtStuff*
linBtMake( MPFORMAL XP_Bool amMaster )
{
LinBtStuff* btStuff = (LinBtStuff*)XP_MALLOC( mpool, sizeof(*btStuff) );
XP_MEMSET( btStuff, 0, sizeof(*btStuff) );
btStuff->amMaster = amMaster;
return btStuff;
}
static void
btConnectSocket( LinBtStuff* btStuff, const CommsAddrRec* addrP )
{
struct sockaddr_l2 saddr;
int sock;
XP_MEMSET( &saddr, 0, sizeof(saddr) );
// allocate a socket
sock = socket( AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP );
if ( sock < 0 ) {
XP_LOGF( "%s: socket->%s", __FUNCTION__, strerror(errno) );
} else {
// set the connection parameters (who to connect to)
saddr.l2_family = AF_BLUETOOTH;
saddr.l2_psm = htobs( XW_PSM );
XP_MEMCPY( &saddr.l2_bdaddr, &addrP->u.bt.btAddr,
sizeof(saddr.l2_bdaddr) );
// connect to server
if ( 0 == connect( sock, (struct sockaddr *)&saddr, sizeof(saddr) ) ) {
CommonGlobals* globals = btStuff->globals;
(*globals->socketChanged)( globals->socketChangedClosure,
-1, sock );
} else {
XP_LOGF( "%s: connect->%s", __FUNCTION__, strerror(errno) );
}
}
}
void
linux_bt_open( CommonGlobals* globals, XP_Bool amMaster )
{
LinBtStuff* btStuff = globals->u.bt.btStuff;
if ( !btStuff ) {
btStuff = globals->u.bt.btStuff
= linBtMake( MPPARM(globals->params->util->mpool)
amMaster );
btStuff->globals = globals;
globals->u.bt.btStuff = btStuff;
}
}
void
linux_bt_close( CommonGlobals* globals )
{
LinBtStuff* btStuff = globals->u.bt.btStuff;
if ( !!btStuff ) {
XP_FREE( globals->params->util->mpool, btStuff );
globals->u.bt.btStuff = NULL;
}
}
XP_S16 linux_bt_send( const XP_U8* buf, XP_U16 buflen,
const CommsAddrRec* addrP,
CommonGlobals* globals )
{
LinBtStuff* btStuff = globals->u.bt.btStuff;
CommsAddrRec addr;
XP_S16 nSent = -1;
LOG_FUNC();
XP_ASSERT( !!btStuff );
if ( !addrP ) {
comms_getAddr( globals->game.comms, &addr );
addrP = &addr;
}
if ( globals->socket < 0 ) {
btConnectSocket( btStuff, addrP );
}
if ( globals->socket >= 0 ) {
nSent = write( globals->socket, buf, buflen );
if ( nSent < 0 ) {
XP_LOGF( "%s: send->%s", __FUNCTION__, strerror(errno) );
} else if ( nSent < buflen ) {
XP_LOGF( "%s: send only %d bytes of %d", __FUNCTION__, nSent,
buflen );
}
} else {
XP_LOGF( "%s: socket still not set", __FUNCTION__ );
}
LOG_RETURNF( "%d", nSent );
return nSent;
}
XP_S16
linux_bt_receive( CommonGlobals* globals, XP_U8* buf, XP_U16 buflen )
{
XP_S16 nRead = 0;
int sock = globals->socket;
LOG_FUNC();
XP_ASSERT( sock >= 0 );
nRead = read( sock, buf, buflen );
if ( nRead < 0 ) {
XP_LOGF( "%s: read->%s", __FUNCTION__, strerror(errno) );
}
LOG_RETURNF( "%d", nRead );
return nRead;
}
#endif /* XWFEATURE_BLUETOOTH */

36
linux/linuxbt.h Normal file
View file

@ -0,0 +1,36 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE";-*- */
/*
* Copyright 2006 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _LINUXBT_H_
#define _LINUXBT_H_
#ifdef XWFEATURE_BLUETOOTH
#include "main.h"
void linux_bt_open( CommonGlobals* globals, XP_Bool amMaster );
void linux_bt_close( CommonGlobals* globals );
XP_S16 linux_bt_send( const XP_U8* buf, XP_U16 buflen,
const CommsAddrRec* addrRec,
CommonGlobals* globals );
XP_S16 linux_bt_receive( CommonGlobals* globals, XP_U8* buf, XP_U16 buflen );
#endif /* XWFEATURE_BLUETOOTH */
#endif /* #ifndef _LINUXBT_H_ */

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */ /* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
/* /*
* Copyright 2000 by Eric House (xwords@eehouse.org). All rights reserved. * Copyright 2000 by Eric House (xwords@eehouse.org). All rights reserved.
* *
@ -30,7 +30,12 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <time.h> #include <time.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include "linuxmain.h" #include "linuxmain.h"
#include "linuxbt.h"
#include "main.h" #include "main.h"
#ifdef PLATFORM_NCURSES #ifdef PLATFORM_NCURSES
# include "cursesmain.h" # include "cursesmain.h"
@ -245,6 +250,8 @@ usage( char* appName, char* msg )
"\t [-p relay_port] # relay is at this port\n" "\t [-p relay_port] # relay is at this port\n"
"\t [-a relay_addr] # use relay (via port spec'd above)\n" "\t [-a relay_addr] # use relay (via port spec'd above)\n"
"" " (default localhost)\n" "" " (default localhost)\n"
"\t [-B n:name|a:00:11:22:33:44:55]\n"
"\t\t\t# connect via bluetooth [param ignored if -s]\n"
/* "# --------------- OR client-only ----------\n" */ /* "# --------------- OR client-only ----------\n" */
/* "\t [-p client_port] # must != server's port if on same device" */ /* "\t [-p client_port] # must != server's port if on same device" */
"\nexample: \n" "\nexample: \n"
@ -255,18 +262,17 @@ usage( char* appName, char* msg )
exit(1); exit(1);
} }
XP_S16 static XP_S16
linux_tcp_send( XP_U8* buf, XP_U16 buflen, linux_tcp_send( const XP_U8* buf, XP_U16 buflen,
const CommsAddrRec* XP_UNUSED(addrRec), const CommsAddrRec* XP_UNUSED(addrRec),
void* closure ) CommonGlobals* globals )
{ {
CommonGlobals* globals = (CommonGlobals*)closure;
XP_S16 result = 0; XP_S16 result = 0;
int socket = globals->socket; int socket = globals->socket;
if ( socket == -1 ) { if ( socket == -1 ) {
XP_STATUSF( "linux_tcp_send: socket uninitialized" ); XP_STATUSF( "linux_tcp_send: socket uninitialized" );
socket = linux_init_socket( globals ); socket = linux_init_relay_socket( globals );
if ( socket != -1 ) { if ( socket != -1 ) {
assert( globals->socket == socket ); assert( globals->socket == socket );
(*globals->socketChanged)( globals->socketChangedClosure, (*globals->socketChanged)( globals->socketChangedClosure,
@ -297,8 +303,33 @@ linux_tcp_send( XP_U8* buf, XP_U16 buflen,
return result; return result;
} /* linux_tcp_send */ } /* linux_tcp_send */
XP_S16
linux_send( const XP_U8* buf, XP_U16 buflen,
const CommsAddrRec* addrRec,
void* closure )
{
XP_S16 nSent = -1;
CommonGlobals* globals = (CommonGlobals*)closure;
CommsConnType conType;
if ( !!addrRec ) {
conType = addrRec->conType;
} else {
conType = globals->params->conType;
}
if ( conType == COMMS_CONN_RELAY ) {
nSent = linux_tcp_send( buf, buflen, addrRec, globals );
} else if ( conType == COMMS_CONN_BT ) {
nSent = linux_bt_send( buf, buflen, addrRec, globals );
} else {
XP_ASSERT(0);
}
return nSent;
} /* linux_send */
int int
linux_init_socket( CommonGlobals* cGlobals ) linux_init_relay_socket( CommonGlobals* cGlobals )
{ {
struct sockaddr_in to_sock; struct sockaddr_in to_sock;
struct hostent* host; struct hostent* host;
@ -312,15 +343,17 @@ linux_init_socket( CommonGlobals* cGlobals )
return -1; return -1;
} }
to_sock.sin_port = htons(cGlobals->params->defaultSendPort); to_sock.sin_port = htons(cGlobals->params->
connInfo.relay.defaultSendPort );
XP_STATUSF( "1: sending to port %d", XP_STATUSF( "1: sending to port %d",
cGlobals->params->defaultSendPort ); cGlobals->params->connInfo.relay.defaultSendPort );
if (( host = gethostbyname(cGlobals->params->relayName) ) == NULL ) { host = gethostbyname( cGlobals->params->connInfo.relay.relayName );
if ( NULL == host ) {
XP_WARNF( "gethostbyname returned -1\n" ); XP_WARNF( "gethostbyname returned -1\n" );
return -1; return -1;
} else { } else {
XP_WARNF( "gethostbyname for %s worked", XP_WARNF( "gethostbyname for %s worked",
cGlobals->defaultServerName ); cGlobals->u.relay.defaultServerName );
} }
memcpy( &(to_sock.sin_addr.s_addr), host->h_addr_list[0], memcpy( &(to_sock.sin_addr.s_addr), host->h_addr_list[0],
sizeof(struct in_addr)); sizeof(struct in_addr));
@ -338,7 +371,7 @@ linux_init_socket( CommonGlobals* cGlobals )
} }
return sock; return sock;
} /* linux_init_socket */ } /* linux_init_relay_socket */
static void static void
linux_close_socket( CommonGlobals* cGlobals ) linux_close_socket( CommonGlobals* cGlobals )
@ -351,7 +384,7 @@ linux_close_socket( CommonGlobals* cGlobals )
} }
int int
linux_receive( CommonGlobals* cGlobals, unsigned char* buf, int bufSize ) linux_relay_receive( CommonGlobals* cGlobals, unsigned char* buf, int bufSize )
{ {
int sock = cGlobals->socket; int sock = cGlobals->socket;
unsigned short tmp; unsigned short tmp;
@ -554,11 +587,15 @@ linux_util_getUserString( XW_UtilCtxt* XP_UNUSED(uc), XP_U16 code )
#ifdef BEYOND_IR #ifdef BEYOND_IR
static void static void
linux_util_addrChange( XW_UtilCtxt* XP_UNUSED(uc), linux_util_addrChange( XW_UtilCtxt* uc,
const CommsAddrRec* XP_UNUSED(oldAddr), const CommsAddrRec* XP_UNUSED(oldAddr),
const CommsAddrRec* XP_UNUSED(newAddr) ) const CommsAddrRec* newAddr,
XP_Bool isServer )
{ {
XP_LOGF( "linux_util_addrChange called; what to do?" ); if ( newAddr->conType == COMMS_CONN_BT ) {
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
linux_bt_open( cGlobals, isServer );
}
} }
#endif #endif
@ -574,6 +611,40 @@ defaultRandomSeed()
return rs; return rs;
} /* defaultRandomSeed */ } /* defaultRandomSeed */
/* This belongs in linuxbt.c */
static XP_Bool
nameToBtAddr( const char* name, bdaddr_t* ba )
{
XP_Bool success = XP_FALSE;
int id, socket;
LOG_FUNC();
# define RESPMAX 5
id = hci_get_route( NULL );
socket = hci_open_dev( id );
if ( id >= 0 && socket >= 0 ) {
long flags = 0L;
inquiry_info inqInfo[RESPMAX];
inquiry_info* inqInfoP = inqInfo;
int count = hci_inquiry( id, 10, RESPMAX, NULL, &inqInfoP, flags );
int i;
for ( i = 0; i < count; ++i ) {
char buf[64];
if ( 0 >= hci_read_remote_name( socket, &inqInfo[i].bdaddr,
sizeof(buf), buf, 0)) {
if ( 0 == strcmp( buf, name ) ) {
XP_MEMCPY( ba, &inqInfo[i].bdaddr, sizeof(*ba) );
success = XP_TRUE;
XP_LOGF( "%s: matched %s", __FUNCTION__, name );
break;
}
}
}
}
return success;
} /* nameToBtAddr */
int int
main( int argc, char** argv ) main( int argc, char** argv )
{ {
@ -587,6 +658,9 @@ main( int argc, char** argv )
LaunchParams mainParams; LaunchParams mainParams;
XP_U16 robotCount = 0; XP_U16 robotCount = 0;
CommsConnType conType = COMMS_CONN_UNUSED;
const char* btaddr = NULL;
#ifdef DEBUG #ifdef DEBUG
{ {
int i; int i;
@ -611,9 +685,9 @@ main( int argc, char** argv )
/* (void)fgetc( stdin ); */ /* (void)fgetc( stdin ); */
/* defaults */ /* defaults */
mainParams.defaultListenPort = DEFAULT_LISTEN_PORT; mainParams.connInfo.relay.defaultListenPort = DEFAULT_LISTEN_PORT;
mainParams.defaultSendPort = DEFAULT_SEND_PORT; mainParams.connInfo.relay.defaultSendPort = DEFAULT_SEND_PORT;
mainParams.cookie = "COOKIE"; mainParams.connInfo.relay.cookie = "COOKIE";
mainParams.gi.boardSize = 15; mainParams.gi.boardSize = 15;
mainParams.quitAfter = XP_FALSE; mainParams.quitAfter = XP_FALSE;
mainParams.sleepOnAnchor = XP_FALSE; mainParams.sleepOnAnchor = XP_FALSE;
@ -645,7 +719,7 @@ main( int argc, char** argv )
#if defined PLATFORM_GTK #if defined PLATFORM_GTK
"h:" "h:"
#endif #endif
"kKf:l:n:Nsd:a:p:e:r:b:qw:Sit:HUmvcC:" ); "kKf:l:n:Nsd:a:p:e:r:b:qw:Sit:HUmvcC:B:" );
switch( opt ) { switch( opt ) {
case '?': case '?':
usage(argv[0], NULL); usage(argv[0], NULL);
@ -654,7 +728,10 @@ main( int argc, char** argv )
mainParams.showRobotScores = XP_TRUE; mainParams.showRobotScores = XP_TRUE;
break; break;
case 'C': case 'C':
mainParams.cookie = optarg; XP_ASSERT( conType == COMMS_CONN_UNUSED ||
conType == COMMS_CONN_RELAY );
mainParams.connInfo.relay.cookie = optarg;
conType = COMMS_CONN_RELAY;
break; break;
case 'd': case 'd':
mainParams.gi.dictName = copyString( MPPARM(mainParams.util->mpool) mainParams.gi.dictName = copyString( MPPARM(mainParams.util->mpool)
@ -694,6 +771,9 @@ main( int argc, char** argv )
break; break;
case 'p': case 'p':
sendPortNumString = optarg; sendPortNumString = optarg;
XP_ASSERT( conType == COMMS_CONN_UNUSED ||
conType == COMMS_CONN_RELAY );
conType = COMMS_CONN_RELAY;
break; break;
case 'r': case 'r':
++robotCount; ++robotCount;
@ -722,6 +802,9 @@ main( int argc, char** argv )
break; break;
case 'a': case 'a':
/* mainParams.info.clientInfo.serverName = */ /* mainParams.info.clientInfo.serverName = */
XP_ASSERT( conType == COMMS_CONN_UNUSED ||
conType == COMMS_CONN_RELAY );
conType = COMMS_CONN_RELAY;
relayName = optarg; relayName = optarg;
break; break;
case 'q': case 'q':
@ -730,6 +813,12 @@ main( int argc, char** argv )
case 'b': case 'b':
mainParams.gi.boardSize = atoi(optarg); mainParams.gi.boardSize = atoi(optarg);
break; break;
case 'B':
XP_ASSERT( conType == COMMS_CONN_UNUSED ||
conType == COMMS_CONN_BT );
conType = COMMS_CONN_BT;
btaddr = optarg;
break;
case 'v': case 'v':
mainParams.verticalScore = XP_TRUE; mainParams.verticalScore = XP_TRUE;
break; break;
@ -766,11 +855,6 @@ main( int argc, char** argv )
mainParams.gi.serverRole = SERVER_ISCLIENT; mainParams.gi.serverRole = SERVER_ISCLIENT;
} }
/* convert strings to whatever */
if ( sendPortNumString != NULL ) {
mainParams.defaultSendPort = atoi( sendPortNumString );
}
/* sanity checks */ /* sanity checks */
totalPlayerCount = mainParams.nLocalPlayers totalPlayerCount = mainParams.nLocalPlayers
+ mainParams.info.serverInfo.nRemotePlayers; + mainParams.info.serverInfo.nRemotePlayers;
@ -803,7 +887,38 @@ main( int argc, char** argv )
} }
} }
mainParams.relayName = relayName; if ( conType == COMMS_CONN_RELAY ) {
mainParams.connInfo.relay.relayName = relayName;
/* convert strings to whatever */
if ( sendPortNumString != NULL ) {
mainParams.connInfo.relay.defaultSendPort =
atoi( sendPortNumString );
}
} else if ( conType == COMMS_CONN_BT ) {
bdaddr_t ba;
XP_Bool success = XP_FALSE;
XP_ASSERT( btaddr );
if ( btaddr[1] == ':' ) {
if ( btaddr[0] == 'n' ) {
if ( !nameToBtAddr( btaddr+2, &ba ) ) {
fprintf( stderr, "fatal error: unable to find device %s\n",
btaddr + 2 );
exit(0);
}
success = XP_TRUE;
} else if ( btaddr[0] == 'a' ) {
success = 0 == str2ba( &btaddr[2], &ba );
XP_ASSERT( success );
}
}
if ( !success ) {
usage( argv[0], "bad format for -B param" );
}
XP_MEMCPY( &mainParams.connInfo.bt.hostAddr, &ba,
sizeof(mainParams.connInfo.bt.hostAddr) );
}
mainParams.conType = conType;
/* mainParams.pipe = linuxCommPipeCtxtMake( isServer ); */ /* mainParams.pipe = linuxCommPipeCtxtMake( isServer ); */

View file

@ -37,10 +37,11 @@ typedef struct LinuxBMStruct {
DictionaryCtxt* linux_dictionary_make( MPFORMAL const char* dictFileName ); DictionaryCtxt* linux_dictionary_make( MPFORMAL const char* dictFileName );
int initListenerSocket( int port ); int initListenerSocket( int port );
XP_S16 linux_tcp_send( XP_U8* buf, XP_U16 buflen, const CommsAddrRec* addrRec, XP_S16 linux_send( const XP_U8* buf, XP_U16 buflen,
void* closure ); const CommsAddrRec* addrRec, void* closure );
int linux_init_socket( CommonGlobals* cGlobals ); int linux_init_relay_socket( CommonGlobals* cGlobals );
int linux_receive( CommonGlobals* cGlobals, unsigned char* buf, int bufSize ); int linux_relay_receive( CommonGlobals* cGlobals, unsigned char* buf,
int bufSize );
void linuxFireTimer( CommonGlobals* cGlobals, XWTimerReason why ); void linuxFireTimer( CommonGlobals* cGlobals, XWTimerReason why );

View file

@ -20,6 +20,8 @@
#ifndef _MAIN_H_ #ifndef _MAIN_H_
#define _MAIN_H_ #define _MAIN_H_
#include <bluetooth/bluetooth.h> /* for bdaddr_t, which should move */
#include "comtypes.h" #include "comtypes.h"
#include "util.h" #include "util.h"
#include "game.h" #include "game.h"
@ -43,7 +45,6 @@ typedef struct LaunchParams {
DictionaryCtxt* dict; DictionaryCtxt* dict;
CurGameInfo gi; CurGameInfo gi;
char* fileName; char* fileName;
char* cookie;
VTableMgr* vtMgr; VTableMgr* vtMgr;
XP_U16 nLocalPlayers; XP_U16 nLocalPlayers;
XP_U16 nHidden; XP_U16 nHidden;
@ -60,15 +61,24 @@ typedef struct LaunchParams {
Connectedness serverRole; Connectedness serverRole;
char* relayName; CommsConnType conType;
union {
struct {
char* relayName;
char* cookie;
short defaultSendPort;
short defaultListenPort;
} relay;
struct {
bdaddr_t hostAddr; /* unused if a host */
} bt;
} connInfo;
union { union {
ServerInfo serverInfo; ServerInfo serverInfo;
ClientInfo clientInfo; ClientInfo clientInfo;
} info; } info;
short defaultSendPort;
short defaultListenPort;
} LaunchParams; } LaunchParams;
typedef void (*SocketChangedFunc)(void* closure, int oldsock, int newsock ); typedef void (*SocketChangedFunc)(void* closure, int oldsock, int newsock );
@ -78,14 +88,25 @@ typedef struct CommonGlobals {
XWGame game; XWGame game;
XP_U16 lastNTilesToUse; XP_U16 lastNTilesToUse;
/* UDP comms stuff */
char* defaultServerName;
int socket;
SocketChangedFunc socketChanged; SocketChangedFunc socketChanged;
void* socketChangedClosure; void* socketChangedClosure;
int socket; /* either relay or bt */
union {
struct {
char* defaultServerName;
} relay;
struct {
struct LinBtStuff* btStuff;
} bt;
} u;
TimerProc timerProcs[NUM_TIMERS_PLUS_ONE]; TimerProc timerProcs[NUM_TIMERS_PLUS_ONE];
void* timerClosures[NUM_TIMERS_PLUS_ONE]; void* timerClosures[NUM_TIMERS_PLUS_ONE];
MPSLOT
} CommonGlobals; } CommonGlobals;
#endif #endif