mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-28 09:58:30 +01:00
Attempt to listen for connections on a separate thread so connected
game could disconnect and reconnect, but still need work on adding a socket to the main thread's io queue from a different thread.
This commit is contained in:
parent
2c5d15a8dd
commit
c27abcd486
5 changed files with 232 additions and 81 deletions
|
@ -92,7 +92,7 @@ OBJ = $(PLATFORM)/linuxmain.o \
|
|||
|
||||
# $(PLATFORM)/linuxcommpipe.o \
|
||||
|
||||
LIBS = -lm -lbluetooth -L $(HOME)/usr/local/pilot/lib $(GPROFFLAG)
|
||||
LIBS = -pthread -lm -lbluetooth -L $(HOME)/usr/local/pilot/lib $(GPROFFLAG)
|
||||
|
||||
ifneq (,$(findstring DPLATFORM_GTK,$(DEFINES)))
|
||||
LIBS += `pkg-config --libs gtk+-2.0`
|
||||
|
|
|
@ -1467,21 +1467,29 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
|
|||
util->closure = globals;
|
||||
} /* setupGtkUtilCallbacks */
|
||||
|
||||
|
||||
static gboolean
|
||||
newConnectionInput( GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
gpointer data )
|
||||
{
|
||||
gboolean keepSource;
|
||||
int sock = g_io_channel_unix_get_fd( source );
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)data;
|
||||
|
||||
XP_ASSERT( sock == globals->cGlobals.socket );
|
||||
XP_LOGF( "%s:condition = 0x%x", __FUNCTION__, (int)condition );
|
||||
|
||||
if ( (condition & G_IO_HUP) != 0 ) {
|
||||
/* XP_ASSERT( sock == globals->cGlobals.socket ); */
|
||||
|
||||
if ( (condition & (G_IO_HUP | G_IO_ERR)) != 0 ) {
|
||||
XP_LOGF( "dropping socket %d", sock );
|
||||
close( sock );
|
||||
globals->cGlobals.socket = -1;
|
||||
return FALSE; /* remove the event source */
|
||||
#ifdef XWFEATURE_BLUETOOTH
|
||||
if ( COMMS_CONN_BT == globals->cGlobals.params->conType ) {
|
||||
linux_bt_socketclosed( &globals->cGlobals, sock );
|
||||
}
|
||||
#endif
|
||||
keepSource = FALSE; /* remove the event source */
|
||||
|
||||
} else if ( (condition & G_IO_IN) != 0 ) {
|
||||
ssize_t nRead;
|
||||
|
@ -1491,7 +1499,7 @@ newConnectionInput( GIOChannel *source,
|
|||
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) );
|
||||
nRead = linux_bt_receive( sock, buf, sizeof(buf) );
|
||||
} else {
|
||||
XP_ASSERT( 0 );
|
||||
}
|
||||
|
@ -1526,8 +1534,9 @@ newConnectionInput( GIOChannel *source,
|
|||
} else {
|
||||
XP_LOGF( "errno from read: %d", errno );
|
||||
}
|
||||
keepSource = TRUE;
|
||||
}
|
||||
return TRUE; /* FALSE means to remove event source */
|
||||
return keepSource; /* FALSE means to remove event source */
|
||||
} /* newConnectionInput */
|
||||
|
||||
/* Make gtk listen for events on the socket that clients will use to
|
||||
|
@ -1536,19 +1545,20 @@ newConnectionInput( GIOChannel *source,
|
|||
static void
|
||||
gtkListenOnSocket( GtkAppGlobals* globals, int newSock )
|
||||
{
|
||||
|
||||
GIOChannel* channel = g_io_channel_unix_new( newSock );
|
||||
guint result = g_io_add_watch( channel,
|
||||
G_IO_IN | G_IO_HUP,
|
||||
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI,
|
||||
newConnectionInput,
|
||||
globals );
|
||||
XP_LOGF( "g_io_add_watch => %d", result );
|
||||
XP_LOGF( "g_io_add_watch(%d) => %d", newSock, result );
|
||||
} /* gtkListenOnSocket */
|
||||
|
||||
static void
|
||||
gtk_socket_changed( void* closure, int oldSock, int newSock )
|
||||
{
|
||||
GtkAppGlobals* globals = (GtkAppGlobals*)closure;
|
||||
XP_ASSERT( oldSock == globals->cGlobals.socket );
|
||||
|
||||
if ( oldSock != -1 ) {
|
||||
g_source_remove( oldSock );
|
||||
XP_LOGF( "Removed %d from gtk's list of listened-to sockets" );
|
||||
|
|
|
@ -26,28 +26,99 @@
|
|||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
|
||||
/* #define XW_USE_THREADS */
|
||||
#ifdef XW_USE_THREADS
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "linuxbt.h"
|
||||
#include "comms.h"
|
||||
|
||||
|
||||
#define MAX_CLIENTS 3
|
||||
|
||||
typedef struct BtaddrSockMap {
|
||||
bdaddr_t btaddr;
|
||||
int sock;
|
||||
} BtaddrSockMap;
|
||||
|
||||
typedef struct LinBtStuff {
|
||||
CommonGlobals* globals;
|
||||
int listener; /* socket */
|
||||
|
||||
union {
|
||||
struct {
|
||||
#ifdef XW_USE_THREADS
|
||||
pthread_t acceptThread;
|
||||
#endif
|
||||
BtaddrSockMap socks[MAX_CLIENTS];
|
||||
XP_U16 nSocks;
|
||||
XP_Bool threadDie;
|
||||
} master;
|
||||
} u;
|
||||
|
||||
XP_Bool amMaster;
|
||||
} LinBtStuff;
|
||||
|
||||
static void
|
||||
lbt_addSock( LinBtStuff* btStuff, const bdaddr_t* btaddr, int sock )
|
||||
{
|
||||
XP_U16 i;
|
||||
|
||||
XP_ASSERT( btStuff->amMaster );
|
||||
XP_ASSERT( btStuff->u.master.nSocks < MAX_CLIENTS - 1 );
|
||||
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||
if ( mp->sock == -1 ) {
|
||||
XP_MEMCPY( &mp->btaddr, btaddr, sizeof(mp->btaddr) );
|
||||
mp->sock = sock;
|
||||
++btStuff->u.master.nSocks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XP_ASSERT( i < MAX_CLIENTS );
|
||||
} /* lbt_addSock */
|
||||
|
||||
static void
|
||||
lbt_removeSock( LinBtStuff* btStuff, int sock )
|
||||
{
|
||||
XP_U16 i;
|
||||
|
||||
XP_ASSERT( btStuff->amMaster );
|
||||
XP_ASSERT( btStuff->u.master.nSocks > 0 );
|
||||
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
BtaddrSockMap* mp = &btStuff->u.master.socks[i];
|
||||
if ( mp->sock == sock ) {
|
||||
mp->sock = -1;
|
||||
--btStuff->u.master.nSocks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XP_ASSERT( i < MAX_CLIENTS );
|
||||
} /* lbt_addSock */
|
||||
|
||||
static LinBtStuff*
|
||||
linBtMake( MPFORMAL XP_Bool amMaster )
|
||||
lbt_make( MPFORMAL XP_Bool amMaster )
|
||||
{
|
||||
LinBtStuff* btStuff = (LinBtStuff*)XP_MALLOC( mpool, sizeof(*btStuff) );
|
||||
XP_MEMSET( btStuff, 0, sizeof(*btStuff) );
|
||||
|
||||
btStuff->amMaster = amMaster;
|
||||
|
||||
if ( amMaster ) {
|
||||
XP_U16 i;
|
||||
for ( i = 0; i < MAX_CLIENTS; ++i ) {
|
||||
btStuff->u.master.socks[i].sock = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return btStuff;
|
||||
}
|
||||
} /* lbt_make */
|
||||
|
||||
static void
|
||||
btConnectSocket( LinBtStuff* btStuff, const CommsAddrRec* addrP )
|
||||
lbt_connectSocket( LinBtStuff* btStuff, const CommsAddrRec* addrP )
|
||||
{
|
||||
struct sockaddr_l2 saddr;
|
||||
int sock;
|
||||
|
@ -74,37 +145,80 @@ btConnectSocket( LinBtStuff* btStuff, const CommsAddrRec* addrP )
|
|||
XP_LOGF( "%s: connect->%s", __FUNCTION__, strerror(errno) );
|
||||
}
|
||||
}
|
||||
} /* btConnectSocket */
|
||||
} /* lbt_connectSocket */
|
||||
|
||||
static void
|
||||
btWaitConnection( CommonGlobals* globals )
|
||||
waitForOne( LinBtStuff* btStuff )
|
||||
{
|
||||
struct sockaddr_l2 saddr;
|
||||
int sock;
|
||||
struct sockaddr_l2 inaddr;
|
||||
int listener, sock;
|
||||
socklen_t slen;
|
||||
|
||||
listener = socket( AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP );
|
||||
// accept one connection
|
||||
XP_LOGF( "%s: blocking on accept", __FUNCTION__ );
|
||||
slen = sizeof( inaddr );
|
||||
sock = accept( btStuff->listener, (struct sockaddr *)&inaddr, &slen );
|
||||
XP_LOGF( "%s: accept returned; sock = %d", __FUNCTION__, sock );
|
||||
|
||||
{
|
||||
char buf[18];
|
||||
(void)ba2str( &inaddr.l2_bdaddr, buf );
|
||||
XP_LOGF( "got connection from %s", buf );
|
||||
}
|
||||
|
||||
if ( sock >= 0 ) {
|
||||
CommonGlobals* globals = btStuff->globals;
|
||||
lbt_addSock( btStuff, &inaddr.l2_bdaddr, sock );
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
-1, sock );
|
||||
} else {
|
||||
XP_LOGF( "%s: accept failed with %s", __FUNCTION__,
|
||||
strerror(errno) );
|
||||
}
|
||||
} /* waitForOne */
|
||||
|
||||
#ifdef XW_USE_THREADS
|
||||
static void*
|
||||
lbt_acceptThreadProc( void* arg )
|
||||
{
|
||||
CommonGlobals* globals = (CommonGlobals*)arg;
|
||||
LinBtStuff* btStuff = globals->u.bt.btStuff;
|
||||
|
||||
while ( !btStuff->u.master.threadDie ) {
|
||||
waitForOne( btStuff );
|
||||
}
|
||||
|
||||
LOG_RETURN_VOID();
|
||||
return NULL;
|
||||
} /* acceptThreadProc */
|
||||
#endif
|
||||
|
||||
static void
|
||||
lbt_waitConnection( CommonGlobals* globals )
|
||||
{
|
||||
LinBtStuff* btStuff = globals->u.bt.btStuff;
|
||||
struct sockaddr_l2 saddr;
|
||||
|
||||
btStuff->listener = socket( AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP );
|
||||
|
||||
XP_MEMSET( &saddr, 0, sizeof(saddr) );
|
||||
saddr.l2_family = AF_BLUETOOTH;
|
||||
saddr.l2_bdaddr = *BDADDR_ANY;
|
||||
saddr.l2_psm = htobs( XW_PSM );
|
||||
bind( btStuff->listener, (struct sockaddr *)&saddr, sizeof(saddr) );
|
||||
|
||||
bind( listener, (struct sockaddr *)&saddr, sizeof(saddr) );
|
||||
listen( btStuff->listener, MAX_CLIENTS );
|
||||
|
||||
listen( listener, 3 ); /* eventually can accept up to 3 -- piconet */
|
||||
|
||||
// accept one connection
|
||||
XP_LOGF( "%s: blocking on accept", __FUNCTION__ );
|
||||
slen = sizeof( inaddr );
|
||||
sock = accept( listener, (struct sockaddr *)&inaddr, &slen );
|
||||
XP_LOGF( "%s: accept returned", __FUNCTION__ );
|
||||
|
||||
close( listener );
|
||||
|
||||
(*globals->socketChanged)( globals->socketChangedClosure,
|
||||
-1, sock );
|
||||
#ifdef XW_USE_THREADS
|
||||
int pthread_err;
|
||||
btStuff->u.master.threadDie = XP_FALSE;
|
||||
pthread_err = pthread_create( &btStuff->u.master.acceptThread,
|
||||
NULL, lbt_acceptThreadProc, globals );
|
||||
XP_ASSERT( 0 == pthread_err );
|
||||
pthread_detach( btStuff->u.master.acceptThread );
|
||||
#else
|
||||
waitForOne( btStuff );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -113,69 +227,81 @@ 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 );
|
||||
= lbt_make( MPPARM(globals->params->util->mpool) amMaster );
|
||||
btStuff->globals = globals;
|
||||
globals->u.bt.btStuff = btStuff;
|
||||
|
||||
}
|
||||
|
||||
if ( amMaster ) {
|
||||
btWaitConnection( globals );
|
||||
if ( amMaster ) {
|
||||
lbt_waitConnection( globals );
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* linux_bt_open */
|
||||
|
||||
void
|
||||
linux_bt_close( CommonGlobals* globals )
|
||||
{
|
||||
LinBtStuff* btStuff = globals->u.bt.btStuff;
|
||||
|
||||
if ( !!btStuff ) {
|
||||
if ( btStuff->amMaster ) {
|
||||
#ifdef XW_USE_THREADS
|
||||
int ret;
|
||||
btStuff->u.master.threadDie = XP_TRUE;
|
||||
ret = pthread_join( btStuff->u.master.acceptThread, NULL );
|
||||
if ( 0 != ret ) {
|
||||
XP_LOGF( "pthread_join=>%s", strerror(errno) );
|
||||
}
|
||||
#endif
|
||||
close( btStuff->listener );
|
||||
}
|
||||
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;
|
||||
}
|
||||
} /* linux_bt_close */
|
||||
|
||||
XP_S16
|
||||
linux_bt_receive( CommonGlobals* globals, XP_U8* buf, XP_U16 buflen )
|
||||
linux_bt_send( const XP_U8* buf, XP_U16 buflen,
|
||||
const CommsAddrRec* addrP,
|
||||
CommonGlobals* globals )
|
||||
{
|
||||
XP_S16 nSent = -1;
|
||||
LinBtStuff* btStuff = globals->u.bt.btStuff;
|
||||
if ( !!btStuff ) {
|
||||
CommsAddrRec addr;
|
||||
|
||||
LOG_FUNC();
|
||||
|
||||
XP_ASSERT( !!btStuff );
|
||||
if ( !addrP ) {
|
||||
comms_getAddr( globals->game.comms, &addr );
|
||||
addrP = &addr;
|
||||
}
|
||||
|
||||
if ( globals->socket < 0 ) {
|
||||
lbt_connectSocket( 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;
|
||||
} /* linux_bt_send */
|
||||
|
||||
XP_S16
|
||||
linux_bt_receive( int sock, XP_U8* buf, XP_U16 buflen )
|
||||
{
|
||||
XP_S16 nRead = 0;
|
||||
int sock = globals->socket;
|
||||
LOG_FUNC();
|
||||
XP_ASSERT( sock >= 0 );
|
||||
|
||||
|
@ -188,5 +314,12 @@ linux_bt_receive( CommonGlobals* globals, XP_U8* buf, XP_U16 buflen )
|
|||
return nRead;
|
||||
}
|
||||
|
||||
void
|
||||
linux_bt_socketclosed( CommonGlobals* globals, int sock )
|
||||
{
|
||||
LinBtStuff* btStuff = globals->u.bt.btStuff;
|
||||
lbt_removeSock( btStuff, sock );
|
||||
}
|
||||
|
||||
#endif /* XWFEATURE_BLUETOOTH */
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ 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 );
|
||||
XP_S16 linux_bt_receive( int sock, XP_U8* buf, XP_U16 buflen );
|
||||
|
||||
void linux_bt_socketclosed( CommonGlobals* globals, int sock );
|
||||
|
||||
#endif /* XWFEATURE_BLUETOOTH */
|
||||
#endif /* #ifndef _LINUXBT_H_ */
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_lib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "linuxmain.h"
|
||||
#include "linuxbt.h"
|
||||
#include "main.h"
|
||||
|
@ -64,11 +66,13 @@ linux_debugf( char* format, ... )
|
|||
struct tm* timp;
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
pthread_t me = pthread_self();
|
||||
|
||||
gettimeofday( &tv, &tz );
|
||||
timp = localtime( &tv.tv_sec );
|
||||
|
||||
sprintf( buf, "%d:%d:%d: ", timp->tm_hour, timp->tm_min, timp->tm_sec );
|
||||
sprintf( buf, "<%p>%d:%d:%d: ", (void*)me,
|
||||
timp->tm_hour, timp->tm_min, timp->tm_sec );
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
|
@ -321,6 +325,8 @@ linux_send( const XP_U8* buf, XP_U16 buflen,
|
|||
if ( conType == COMMS_CONN_RELAY ) {
|
||||
nSent = linux_tcp_send( buf, buflen, addrRec, globals );
|
||||
} else if ( conType == COMMS_CONN_BT ) {
|
||||
XP_Bool isServer = comms_getIsServer( globals->game.comms );
|
||||
linux_bt_open( globals, isServer );
|
||||
nSent = linux_bt_send( buf, buflen, addrRec, globals );
|
||||
} else {
|
||||
XP_ASSERT(0);
|
||||
|
@ -589,11 +595,11 @@ linux_util_getUserString( XW_UtilCtxt* XP_UNUSED(uc), XP_U16 code )
|
|||
static void
|
||||
linux_util_addrChange( XW_UtilCtxt* uc,
|
||||
const CommsAddrRec* XP_UNUSED(oldAddr),
|
||||
const CommsAddrRec* newAddr,
|
||||
XP_Bool isServer )
|
||||
const CommsAddrRec* newAddr )
|
||||
{
|
||||
if ( newAddr->conType == COMMS_CONN_BT ) {
|
||||
CommonGlobals* cGlobals = (CommonGlobals*)uc->closure;
|
||||
XP_Bool isServer = comms_getIsServer( cGlobals->game.comms );
|
||||
linux_bt_open( cGlobals, isServer );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue