add udp socket and protocol for use over it so that a device can

manage a single connection to the relay for all of its games.  Works
so far to the extent that the game's playable with all boards on the
same device (with checkins about to come) as long as all boards are
open.  (Client doesn't handle opening closed games yet.)
This commit is contained in:
Eric House 2013-01-15 18:41:17 -08:00
parent 5a51af489a
commit 7fec736947
16 changed files with 370 additions and 46 deletions

View file

@ -31,6 +31,7 @@ SRC = \
tpool.cpp \
cidlock.cpp \
addrinfo.cpp \
devmgr.cpp \
xwrelay.cpp \
# STATIC ?= -static

View file

@ -32,7 +32,10 @@ AddrInfo::equals( const AddrInfo& other ) const
if ( isTCP() ) {
equal = m_socket == other.m_socket;
} else {
assert(0); /* later.... */
assert( m_socket == other.m_socket ); /* both same UDP socket */
/* what does equal mean on udp addresses? Same host, or same host AND game */
equal = m_clientToken == other.m_clientToken
&& 0 == memcmp( &m_saddr, &other.m_saddr, sizeof(m_saddr) );
}
}
return equal;

View file

@ -24,6 +24,7 @@
#include <netinet/in.h>
#include <string.h>
#include <assert.h>
class AddrInfo {
public:
@ -32,31 +33,45 @@ class AddrInfo {
struct sockaddr_in addr_in;
} AddrUnion;
/* Those constructed without params are only valid after another copied on
top of it */
AddrInfo() {
memset( this, 0, sizeof(*this) );
m_socket = -1;
m_isValid = false;
}
AddrInfo( bool isTCP, int socket, const AddrUnion* saddr ) {
m_isValid = true;
m_isTCP = isTCP;
m_socket = socket;
memcpy( &m_saddr, saddr, sizeof(m_saddr) );
AddrInfo( int socket, const AddrUnion* saddr ) {
construct( socket, saddr, true );
}
AddrInfo( int socket, uint32_t clientToken, const AddrUnion* saddr ) {
construct( socket, saddr, false );
m_clientToken = clientToken;
}
void setIsTCP( bool val ) { m_isTCP = val; }
bool isTCP() const { return m_isTCP; } /* later UDP will be here too */
int socket() const { assert(m_isValid); return m_socket; }
uint32_t clientToken() const { assert(m_isValid); return m_clientToken; }
struct in_addr sin_addr() const { return m_saddr.addr_in.sin_addr; }
const struct sockaddr* sockaddr() const { assert(m_isValid); return &m_saddr.addr; }
bool equals( const AddrInfo& other ) const;
private:
void construct( int socket, const AddrUnion* saddr, bool isTCP ) {
memset( this, 0, sizeof(*this) );
m_socket = socket;
m_isTCP = isTCP;
memcpy( &m_saddr, saddr, sizeof(m_saddr) );
m_isValid = true;
}
// AddrInfo& operator=(const AddrInfo&); // Prevent assignment
int m_socket;
bool m_isTCP;
bool m_isValid;
uint32_t m_clientToken; /* must be 32 bit */
AddrUnion m_saddr;
};

View file

@ -276,7 +276,7 @@ CookieRef::_PutMsg( HostID srcID, const AddrInfo* addr, HostID destID,
void
CookieRef::_Disconnect( const AddrInfo* addr, HostID hostID )
{
logf( XW_LOGINFO, "%s(socket=%d, hostID=%d)", __func__, socket, hostID );
logf( XW_LOGINFO, "%s(hostID=%d)", __func__, hostID );
CRefEvent evt( XWE_DISCONN, addr );
evt.u.discon.srcID = hostID;
@ -636,7 +636,7 @@ CookieRef::handleEvents()
/* Assumption: has mutex!!!! */
while ( m_eventQueue.size () > 0 ) {
XW_RELAY_STATE nextState;
DBMgr::DevIDRelay devID;
DevIDRelay devID;
CRefEvent evt = m_eventQueue.front();
m_eventQueue.pop_front();
@ -848,7 +848,6 @@ CookieRef::send_stored_messages( HostID dest, const AddrInfo* addr )
assert( dest > 0 && dest <= 4 );
assert( -1 != addr->socket() );
assert( addr->isTCP() );
for ( ; ; ) {
unsigned char buf[MAX_MSG_LEN];
@ -867,9 +866,9 @@ CookieRef::send_stored_messages( HostID dest, const AddrInfo* addr )
bool
CookieRef::increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp,
DBMgr::DevIDRelay* devIDp )
DevIDRelay* devIDp )
{
DBMgr::DevIDRelay devID = DBMgr::DEVID_NONE;
DevIDRelay devID = DBMgr::DEVID_NONE;
int nPlayersH = evt->u.con.nPlayersH;
int seed = evt->u.con.seed;
@ -1038,7 +1037,7 @@ CookieRef::cancelAllConnectedTimer()
void
CookieRef::sendResponse( const CRefEvent* evt, bool initial,
const DBMgr::DevIDRelay* devID )
const DevIDRelay* devID )
{
/* Now send the response */
unsigned char buf[1 /* cmd */
@ -1191,7 +1190,6 @@ void
CookieRef::notifyOthers( const AddrInfo* addr, XWRelayMsg msg, XWREASON why )
{
assert( addr->socket() != 0 );
assert( addr->isTCP() );
ASSERT_LOCKED();
RWReadLock rrl( &m_socketsRWLock );

View file

@ -219,11 +219,11 @@ class CookieRef {
void handleEvents();
void sendResponse( const CRefEvent* evt, bool initial,
const DBMgr::DevIDRelay* devID );
const DevIDRelay* devID );
void sendAnyStored( const CRefEvent* evt );
void initPlayerCounts( const CRefEvent* evt );
bool increasePlayerCounts( CRefEvent* evt, bool reconn, HostID* hidp,
DBMgr::DevIDRelay* devID );
DevIDRelay* devID );
void updateAck( HostID hostID, bool keep );
void dropPending( int seed );

View file

@ -249,10 +249,10 @@ DBMgr::AllDevsAckd( const char* const connName )
// Return DevIDRelay for device, adding it to devices table IFF it's not
// already there.
DBMgr::DevIDRelay
DevIDRelay
DBMgr::RegisterDevice( const DevID* host )
{
DBMgr::DevIDRelay devID;
DevIDRelay devID;
assert( host->m_devIDType != ID_TYPE_NONE );
int ii;
bool success;
@ -261,7 +261,7 @@ DBMgr::RegisterDevice( const DevID* host )
devID = getDevID( host );
// If it's not present *and* of type ID_TYPE_RELAY, we can do nothing.
// Fail.
// Otherwise proceed.
if ( DEVID_NONE == devID && ID_TYPE_RELAY < host->m_devIDType ) {
// loop until we're successful inserting the unique key. Ship with this
// coming from random, but test with increasing values initially to make
@ -269,7 +269,7 @@ DBMgr::RegisterDevice( const DevID* host )
for ( success = false, ii = 0; !success; ++ii ) {
assert( 10 > ii ); // better to check that we're looping BECAUSE
// of uniqueness problem.
devID = (DBMgr::DevIDRelay)random();
devID = (DevIDRelay)random();
if ( DEVID_NONE == devID ) {
continue;
}
@ -327,13 +327,14 @@ DBMgr::AddDevice( const char* connName, HostID curID, int clientVersion,
const char* fmt = "UPDATE " GAMES_TABLE " SET nPerDevice[%d] = %d,"
" clntVers[%d] = %d,"
" seeds[%d] = %d, addrs[%d] = \'%s\', %s"
" mtimes[%d]='now', ack[%d]=\'%c\'"
" tokens[%d] = %d, mtimes[%d]='now', ack[%d]=\'%c\'"
" WHERE connName = '%s'";
string query;
char* ntoa = inet_ntoa( addr->sin_addr() );
string_printf( query, fmt, newID, nToAdd, newID, clientVersion,
newID, seed, newID, ntoa, devIDBuf.c_str(), newID,
newID, ackd?'A':'a', connName );
newID, seed, newID, ntoa, devIDBuf.c_str(),
newID, addr->clientToken(), newID, newID, ackd?'A':'a',
connName );
logf( XW_LOGINFO, "%s: query: %s", __func__, query.c_str() );
execSql( query );
@ -632,10 +633,10 @@ DBMgr::readArray( const char* const connName, int arr[] ) /* len 4 */
PQclear( result );
}
DBMgr::DevIDRelay
DevIDRelay
DBMgr::getDevID( const char* connName, int hid )
{
DBMgr::DevIDRelay devID;
DevIDRelay devID;
const char* fmt = "SELECT devids[%d] FROM " GAMES_TABLE " WHERE connName='%s'";
string query;
string_printf( query, fmt, hid, connName );
@ -643,29 +644,28 @@ DBMgr::getDevID( const char* connName, int hid )
PGresult* result = PQexec( getThreadConn(), query.c_str() );
assert( 1 == PQntuples( result ) );
devID = (DBMgr::DevIDRelay)strtoul( PQgetvalue( result, 0, 0 ), NULL, 10 );
devID = (DevIDRelay)strtoul( PQgetvalue( result, 0, 0 ), NULL, 10 );
PQclear( result );
return devID;
}
DBMgr::DevIDRelay
DevIDRelay
DBMgr::getDevID( const DevID* devID )
{
DBMgr::DevIDRelay rDevID = DEVID_NONE;
DevIDRelay rDevID = DEVID_NONE;
DevIDType devIDType = devID->m_devIDType;
string query;
assert( ID_TYPE_NONE < devIDType );
const char* asStr = devID->m_devIDString.c_str();
if ( ID_TYPE_RELAY == devIDType ) {
// confirm it's there
DBMgr::DevIDRelay cur = strtoul( asStr, NULL, 16 );
DevIDRelay cur = devID->asRelayID();
if ( DEVID_NONE != cur ) {
const char* fmt = "SELECT id FROM " DEVICES_TABLE " WHERE id=%d";
string_printf( query, fmt, cur );
}
} else {
const char* fmt = "SELECT id FROM " DEVICES_TABLE " WHERE devtype=%d and devid = '%s'";
string_printf( query, fmt, devIDType, asStr );
string_printf( query, fmt, devIDType, devID->m_devIDString.c_str() );
}
if ( 0 < query.size() ) {
@ -673,7 +673,7 @@ DBMgr::getDevID( const DevID* devID )
PGresult* result = PQexec( getThreadConn(), query.c_str() );
assert( 1 >= PQntuples( result ) );
if ( 1 == PQntuples( result ) ) {
rDevID = (DBMgr::DevIDRelay)strtoul( PQgetvalue( result, 0, 0 ), NULL, 10 );
rDevID = (DevIDRelay)strtoul( PQgetvalue( result, 0, 0 ), NULL, 10 );
}
PQclear( result );
}

View file

@ -36,7 +36,6 @@ class DBMgr {
/* DevIDs on various platforms are stored in devices table. This is the
key, and used in msgs and games tables as a shorter way to refer to
them. */
typedef unsigned int DevIDRelay;
static const DevIDRelay DEVID_NONE = 0;
static DBMgr* Get();
@ -62,7 +61,7 @@ class DBMgr {
char* connNameBuf, int bufLen, int* nPlayersHP );
bool AllDevsAckd( const char* const connName );
DevIDRelay RegisterDevice( const DevID* hosts );
DevIDRelay RegisterDevice( const DevID* host );
HostID AddDevice( const char* const connName, HostID curID, int clientVersion,
int nToAdd, unsigned short seed, const AddrInfo* addr,

View file

@ -22,6 +22,8 @@
#define _DEVID_H_
#include <string>
#include <stdlib.h>
#include "xwrelay.h"
/* DevID protocol.
@ -52,11 +54,18 @@
*
*/
#include <assert.h>
using namespace std;
class DevID {
public:
DevID() { m_devIDType = ID_TYPE_NONE; }
DevID(DevIDType typ) { m_devIDType = typ; }
DevIDRelay asRelayID() const {
assert( ID_TYPE_RELAY == m_devIDType );
return strtoul( m_devIDString.c_str(), NULL, 16 );
}
string m_devIDString;
DevIDType m_devIDType;
};

61
xwords4/relay/devmgr.cpp Normal file
View file

@ -0,0 +1,61 @@
/* -*- compile-command: "make -k -j3"; -*- */
/*
* Copyright 2013 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.
*/
#include "devmgr.h"
#include "mlock.h"
static DevMgr* s_instance = NULL;
/* static */ DevMgr*
DevMgr::Get()
{
if ( s_instance == NULL ) {
s_instance = new DevMgr();
}
return s_instance;
} /* Get */
void
DevMgr::Remember( DevIDRelay devid, const AddrInfo::AddrUnion* saddr )
{
time_t now = time( NULL );
MutexLock ml( &m_mapLock );
UDPAddrRec rec( saddr, now );
m_devAddrMap.insert( pair<DevIDRelay,UDPAddrRec>( devid, rec ) );
logf( XW_LOGINFO, "dev->addr map now contains %d entries", m_devAddrMap.size() );
}
#if 0 // not used yet
const AddrInfo::AddrUnion*
DevMgr::get( DevIDRelay devid )
{
const AddrInfo::AddrUnion* result = NULL;
MutexLock ml( &m_mapLock );
map<DevIDRelay,UDPAddrRec>::iterator iter;
iter = m_devAddrMap.find( devid );
if ( m_devAddrMap.end() != iter ) {
result = &iter->second.m_addr;
logf( XW_LOGINFO, "%s: found addr for %.8x; is %d seconds old", __func__,
devid, time(NULL) - iter->second.m_added );
}
return result;
}
#endif

54
xwords4/relay/devmgr.h Normal file
View file

@ -0,0 +1,54 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 2013 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.
*
* 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 _DEVMGR_H_
#define _DEVMGR_H_
#include <pthread.h>
#include "xwrelay_priv.h"
#include "addrinfo.h"
using namespace std;
class DevMgr {
public:
static DevMgr* Get();
void Remember( DevIDRelay devid, const AddrInfo::AddrUnion* saddr );
const AddrInfo::AddrUnion* get( DevIDRelay devid );
private:
DevMgr() { pthread_mutex_init( &m_mapLock, NULL ); }
~DevMgr() { pthread_mutex_destroy( &m_mapLock ); }
class UDPAddrRec {
public:
UDPAddrRec( const AddrInfo::AddrUnion* addr, time_t tim ) {
m_addr = *addr; m_added = tim;
}
AddrInfo::AddrUnion m_addr;
time_t m_added;
};
map<DevIDRelay,UDPAddrRec> m_devAddrMap;
pthread_mutex_t m_mapLock;
};
#endif

View file

@ -26,7 +26,7 @@ QUERY="WHERE NOT -NTOTAL = sum_array(nperdevice)"
echo "Device (pid) count: $(pidof xwords | wc | awk '{print $2}')"
echo "Row count:" $(psql -t xwgames -c "select count(*) FROM games $QUERY;")
echo "SELECT dead,connname,cid,room,lang,clntVers,ntotal,nperdevice,seeds,devids,ack,nsent "\
echo "SELECT dead,connname,cid,room,lang,clntVers,ntotal,nperdevice,seeds,addrs,tokens,ack,nsent "\
"FROM games $QUERY ORDER BY NOT dead, connname LIMIT $LIMIT;" \
| psql xwgames

View file

@ -26,12 +26,16 @@ GAME_PORTS=10997
# What ports do we listen on for per-device incoming connections?
DEVICE_PORTS=10998
# Port for per-device UDP interface (experimental)
UDPPORT=10997
# default 5
SOCK_TIMEOUT_SECONDS=5
# And the control port is?
CTLPORT=11000
# port for web interface
WWW_PORT=11001
#--- INADDR_ANY: 0x00000000

View file

@ -76,9 +76,11 @@
#include "lstnrmgr.h"
#include "dbmgr.h"
#include "addrinfo.h"
#include "devmgr.h"
static int s_nSpawns = 0;
static int g_maxsocks = -1;
static int g_udpsock = -1;
void
logf( XW_LogLevel level, const char* format, ... )
@ -334,6 +336,15 @@ denyConnection( const AddrInfo* addr, XWREASON err )
send_with_length_unsafe( addr, buf, sizeof(buf) );
}
static ssize_t
send_via_udp( int socket, const struct sockaddr *dest_addr,
const unsigned char* buf, int buflen )
{
ssize_t nSent = sendto( socket, buf, buflen,
0, /* flags */ dest_addr, sizeof(*dest_addr) );
return nSent;
}
/* No mutex here. Caller better be ensuring no other thread can access this
* socket. */
bool
@ -343,15 +354,29 @@ send_with_length_unsafe( const AddrInfo* addr, unsigned char* buf,
assert( !!addr );
bool ok = false;
int socket = addr->socket();
assert ( addr->isTCP() );
unsigned short len = htons( bufLen );
ssize_t nSent = send( socket, &len, 2, 0 );
if ( nSent == 2 ) {
nSent = send( socket, buf, bufLen, 0 );
if ( nSent == ssize_t(bufLen) ) {
logf( XW_LOGINFO, "sent %d bytes on socket %d", nSent, socket );
ok = true;
if ( addr->isTCP() ) {
unsigned short len = htons( bufLen );
ssize_t nSent = send( socket, &len, 2, 0 );
if ( nSent == 2 ) {
nSent = send( socket, buf, bufLen, 0 );
if ( nSent == ssize_t(bufLen) ) {
logf( XW_LOGINFO, "sent %d bytes on socket %d", nSent, socket );
ok = true;
}
}
} else {
uint32_t clientToken = addr->clientToken();
assert( 0 != clientToken );
unsigned char tmpbuf[1 + 1 + sizeof(clientToken) + bufLen];
tmpbuf[0] = XWREG_PROTO_VERSION;
tmpbuf[1] = XWRREG_MSG;
clientToken = htonl(clientToken);
memcpy( &tmpbuf[2], &clientToken, sizeof(clientToken) );
memcpy( &tmpbuf[2 + sizeof(clientToken)], buf, bufLen );
const struct sockaddr* saddr = addr->sockaddr();
send_via_udp( g_udpsock, saddr, tmpbuf, sizeof(tmpbuf) );
logf( XW_LOGINFO, "sent %d bytes on UDP socket %d", bufLen, socket );
ok = true;
}
if ( !ok ) {
@ -1046,6 +1071,94 @@ handle_proxy_packet( unsigned char* buf, int len, const AddrInfo* addr )
}
} /* handle_proxy_packet */
static void
registerDevice( const DevID* devID, const AddrInfo::AddrUnion* saddr )
{
DevIDRelay relayID;
if ( ID_TYPE_RELAY != devID->m_devIDType ) { // known to us; just update the time
relayID = DBMgr::Get()->RegisterDevice( devID );
if ( ID_TYPE_NONE != relayID ) {
// send it back to the device
char idbuf[9];
int len = snprintf( idbuf, sizeof(idbuf), "%.8X", relayID );
logf( XW_LOGERROR, "%s: len(%s) => %d", __func__, idbuf, len );
unsigned char buf[1 + 1 + 2 + len];
buf[0] = XWREG_PROTO_VERSION;
buf[1] = XWRREG_REGRSP;
short lenNBO = htons(len);
memcpy( &buf[2], &lenNBO, sizeof(lenNBO));
memcpy( &buf[4], idbuf, len );
send_via_udp( g_udpsock, &saddr->addr, buf, sizeof(buf) );
}
} else {
relayID = devID->asRelayID();
}
// Now let's map the address to the devid for future sending purposes.
DevMgr::Get()->Remember( relayID, saddr );
}
// This will need to be done in a thread before there can be simulaneous
// connections.
static void
handle_udp_packet( int udpsock )
{
bool success = false;
logf( XW_LOGINFO, "%s()", __func__ );
unsigned char buf[512];
AddrInfo::AddrUnion saddr;
memset( &saddr, 0, sizeof(saddr) );
socklen_t fromlen = sizeof(saddr.addr_in);
ssize_t nRead = recvfrom( udpsock, buf, sizeof(buf), 0 /*flags*/,
&saddr.addr, &fromlen );
if ( 2 <= nRead ) {
unsigned char* ptr = buf;
unsigned char* end = buf + nRead;
logf( XW_LOGINFO, "%s: recvfrom=>%d", __func__, nRead );
unsigned char proto = *ptr++;
if ( XWREG_PROTO_VERSION != 0 ) {
logf( XW_LOGERROR, "unexpected proto %d", __func__, (int) proto );
} else {
int msg = *ptr++;
switch( msg ) {
case XWRREG_REG: {
DevIDType typ = (DevIDType)*ptr++;
unsigned short idLen;
if ( !getNetShort( &ptr, end, &idLen ) ) {
break;
}
if ( end - ptr > idLen ) {
logf( XW_LOGERROR, "full devID not received" );
break;
}
DevID devID( typ );
devID.m_devIDString.append( (const char*)ptr, idLen );
ptr += idLen;
registerDevice( &devID, &saddr );
}
break;
case XWRREG_MSG: {
uint32_t clientToken;
memcpy( &clientToken, ptr, sizeof(clientToken) );
ptr += sizeof(clientToken);
clientToken = ntohl( clientToken );
if ( 0 != clientToken ) {
AddrInfo addr( udpsock, clientToken, &saddr );
success = processMessage( ptr, end - ptr, &addr );
} else {
logf( XW_LOGERROR, "%s: dropping packet with token of 0" );
}
}
break;
default:
logf( XW_LOGERROR, "%s: unexpected msg %d", __func__, msg );
}
}
}
logf( XW_LOGINFO, "%s()=>%d", __func__, success );
}
/* From stack overflow, toward a snprintf with an expanding buffer.
*/
void
@ -1134,6 +1247,7 @@ main( int argc, char** argv )
{
int port = 0;
int ctrlport = 0;
int udpport = 0;
#ifdef DO_HTTP
int httpport = 0;
const char* cssFile = NULL;
@ -1156,7 +1270,7 @@ main( int argc, char** argv )
first. */
for ( ; ; ) {
int opt = getopt(argc, argv, "h?c:p:m:n:f:l:t:s:w:"
int opt = getopt(argc, argv, "h?c:p:m:n:f:l:t:s:u:w:"
"DF" );
if ( opt == -1 ) {
@ -1210,6 +1324,9 @@ main( int argc, char** argv )
case 't':
nWorkerThreads = atoi( optarg );
break;
case 'u':
udpport = atoi( optarg );
break;
default:
usage( argv[0] );
exit( 1 );
@ -1232,6 +1349,9 @@ main( int argc, char** argv )
if ( ctrlport == 0 ) {
(void)cfg->GetValueFor( "CTLPORT", &ctrlport );
}
if ( 0 == udpport ) {
(void)cfg->GetValueFor( "UDPPORT", &udpport );
}
#ifdef DO_HTTP
if ( httpport == 0 ) {
(void)cfg->GetValueFor( "WWW_PORT", &httpport );
@ -1371,6 +1491,19 @@ main( int argc, char** argv )
exit( 1 );
}
if ( 0 != udpport ) {
struct sockaddr_in saddr;
g_udpsock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
saddr.sin_family = PF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(udpport);
int err = bind( g_udpsock, (struct sockaddr*)&saddr, sizeof(saddr) );
if ( 0 != err ) {
logf( XW_LOGERROR, "bind()=>%s", strerror(errno) );
g_udpsock = -1;
}
}
#ifdef DO_HTTP
HttpState http_state;
int addr;
@ -1404,6 +1537,9 @@ main( int argc, char** argv )
FD_ZERO(&rfds);
g_listeners.AddToFDSet( &rfds );
FD_SET( g_control, &rfds );
if ( -1 != g_udpsock ) {
FD_SET( g_udpsock, &rfds );
}
#ifdef DO_HTTP
if ( -1 != g_http ) {
FD_SET( g_http, &rfds );
@ -1413,6 +1549,9 @@ main( int argc, char** argv )
if ( g_control > highest ) {
highest = g_control;
}
if ( g_udpsock > highest ) {
highest = g_udpsock;
}
#ifdef DO_HTTP
if ( g_http > highest ) {
highest = g_http;
@ -1458,7 +1597,7 @@ main( int argc, char** argv )
"%s: accepting connection from %s on socket %d",
__func__, inet_ntoa(saddr.addr_in.sin_addr), newSock );
AddrInfo addr( true, newSock, &saddr );
AddrInfo addr( newSock, &saddr );
tPool->AddSocket( perGame ? XWThreadPool::STYPE_GAME
: XWThreadPool::STYPE_PROXY,
&addr );
@ -1471,6 +1610,12 @@ main( int argc, char** argv )
// run_ctrl_thread( g_control );
--retval;
}
if ( FD_ISSET( g_udpsock, &rfds ) ) {
// This will need to be done in a separate thread, or pushed
// to the existing thread pool
handle_udp_packet( g_udpsock );
--retval;
}
#ifdef DO_HTTP
if ( FD_ISSET( g_http, &rfds ) ) {
FD_CLR( g_http, &rfds );

View file

@ -27,6 +27,37 @@
/* Set if device is acting a server; cleared if as client */
#define FLAGS_SERVER_BIT 0x01
/* message types for the udp-based per-device (not per-game) protocol */
#define XWREG_PROTO_VERSION 0
#ifndef CANT_DO_TYPEDEF
typedef
#endif
enum { XWRREG_NONE /* 0 is an illegal value */
,XWRREG_REG /* dev->relay: device registers self and
self-selected (e.g. gcm) or assigned devid
format: proto: 1; this enum: 1; idType: 1,
idLen: 2, id: <idLen> */
,XWRREG_REGRSP /* relay->device: if non-relay-assigned devid
type was given, this gives the
relay-assigned one to be used from now on.
format: proto: 1, this enum: 1, idLen: 2, id: <idLen>
*/
,XWRREG_PING /* device->relay: keep the UDP connection
open. format: proto: 1, this enum: 1. */
,XWRREG_MSG /* dev->relay and relay->dev: norm: a message from a game to
the relay format: proto: 1, this enum: 1,
clientToken: 4, message<varies>*/
,XWRREG_MSGRSP /* relay->dev: conveys error on receipt of XWRREG_MSG */
}
#ifndef CANT_DO_TYPEDEF
XWRelayReg
#endif
;
#ifndef CANT_DO_TYPEDEF
typedef
#endif

View file

@ -58,6 +58,7 @@ cid integer
,mtimes TIMESTAMP(0)[]
,addrs INET[]
,devids INTEGER[]
,tokens INTEGER[]
);
EOF

View file

@ -25,11 +25,14 @@
#include <string>
#include <time.h>
#include <netinet/in.h>
#include <stdint.h>
#include "lstnrmgr.h"
#include "xwrelay.h"
#include "addrinfo.h"
typedef unsigned char HostID; /* see HOST_ID_SERVER */
typedef uint32_t DevIDRelay;
typedef enum {
XW_LOGERROR