mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-29 08:34:37 +01:00
make transmitted vars smaller where possible; new relay identifying
scheme where cookie is used only to connect, and is replaced for reconnects by a relay-generated name that's supposed to be unique across all games on all relays and includes a hostname read in from config file; relay assign non-servers' hostIDs.
This commit is contained in:
parent
c954361d3b
commit
e098e6f7b2
14 changed files with 407 additions and 233 deletions
|
@ -24,6 +24,7 @@ SRC = xwrelay.cpp \
|
|||
timermgr.cpp \
|
||||
configs.cpp \
|
||||
crefmgr.cpp \
|
||||
permid.cpp \
|
||||
|
||||
OBJ = $(patsubst %.cpp,%.o,$(SRC))
|
||||
LDFLAGS += -lpthread -g
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
pthread_mutex_t g_IdsMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
CookieID CookieRef::ms_nextConnectionID = 1000;
|
||||
|
||||
/*****************************************************************************
|
||||
* SocketsIterator class
|
||||
*****************************************************************************/
|
||||
|
@ -71,21 +68,17 @@ SocketsIterator::Next()
|
|||
* CookieRef class
|
||||
*****************************************************************************/
|
||||
|
||||
CookieRef::CookieRef( const char* s, CookieID id )
|
||||
CookieRef::CookieRef( const char* cookie, const char* connName, CookieID id )
|
||||
: m_heatbeat(RelayConfigs::GetConfigs()->GetHeartbeatInterval())
|
||||
, m_name(s)
|
||||
, m_name(cookie==NULL?"":cookie)
|
||||
, m_connName(connName)
|
||||
, m_cookieID(id)
|
||||
, m_totalSent(0)
|
||||
, m_curState(XW_ST_INITED)
|
||||
, m_nextState(XW_ST_INITED)
|
||||
, m_eventQueue()
|
||||
, m_nextHostID(HOST_ID_SERVER)
|
||||
{
|
||||
/* pthread_rwlock_init( &m_sockets_rwlock, NULL ); */
|
||||
/* pthread_mutex_init( &m_EventsMutex, NULL ); */
|
||||
|
||||
if ( id == 0 ) {
|
||||
MutexLock ml( &g_IdsMutex );
|
||||
m_connectionID = ms_nextConnectionID++; /* needs a mutex!!! */
|
||||
} else {
|
||||
m_connectionID = id;
|
||||
}
|
||||
}
|
||||
|
||||
CookieRef::~CookieRef()
|
||||
|
@ -96,7 +89,6 @@ CookieRef::~CookieRef()
|
|||
XWThreadPool* tPool = XWThreadPool::GetTPool();
|
||||
|
||||
for ( ; ; ) {
|
||||
/* RWWriteLock rwl( &m_sockets_rwlock ); */
|
||||
map<HostID,HostRec>::iterator iter = m_sockets.begin();
|
||||
|
||||
if ( iter == m_sockets.end() ) {
|
||||
|
@ -108,18 +100,18 @@ CookieRef::~CookieRef()
|
|||
m_sockets.erase( iter );
|
||||
}
|
||||
|
||||
/* pthread_rwlock_destroy( &m_sockets_rwlock ); */
|
||||
logf( "CookieRef for %d being deleted", m_connectionID );
|
||||
|
||||
/* pthread_mutex_destroy( &m_EventsMutex ); */
|
||||
/* pthread_rwlock_destroy( &m_sockets_rwlock ); */
|
||||
logf( "CookieRef for %d being deleted; sent %d bytes",
|
||||
m_cookieID, m_totalSent );
|
||||
} /* ~CookieRef */
|
||||
|
||||
void
|
||||
CookieRef::_Connect( int socket, HostID srcID )
|
||||
{
|
||||
CRefMgr::Get()->Associate( socket, this );
|
||||
/* MutexLock ml( &m_EventsMutex ); */
|
||||
if ( srcID == HOST_ID_NONE ) {
|
||||
srcID = nextHostID();
|
||||
logf( "assigned host id: %x", srcID );
|
||||
}
|
||||
pushConnectEvent( socket, srcID );
|
||||
handleEvents();
|
||||
}
|
||||
|
@ -176,6 +168,14 @@ CookieRef::NeverFullyConnected()
|
|||
&& m_curState != XW_ST_MISSING;
|
||||
}
|
||||
|
||||
int
|
||||
CookieRef::AcceptingConnections()
|
||||
{
|
||||
return m_curState == XW_ST_INITED
|
||||
|| m_curState == XW_ST_CONNECTING
|
||||
|| m_curState == XW_ST_MISSING;
|
||||
}
|
||||
|
||||
void
|
||||
CookieRef::notifyDisconn( const CRefEvent* evt )
|
||||
{
|
||||
|
@ -400,19 +400,21 @@ CookieRef::handleEvents()
|
|||
if ( getFromTable( m_curState, evt.type, &takeAction, &m_nextState ) ) {
|
||||
|
||||
logf( "cid %d: moving from state %s to state %s for event %s",
|
||||
m_connectionID, stateString(m_curState),
|
||||
m_cookieID, stateString(m_curState),
|
||||
stateString(m_nextState), eventString(evt.type) );
|
||||
|
||||
switch( takeAction ) {
|
||||
case XW_ACT_SEND_1ST_RSP:
|
||||
case XW_ACT_SEND_1ST_RERSP:
|
||||
setAllConnectedTimer();
|
||||
sendResponse( &evt );
|
||||
sendResponse( &evt, takeAction == XW_ACT_SEND_1ST_RSP );
|
||||
break;
|
||||
|
||||
case XW_ACT_SENDRSP:
|
||||
case XW_ACT_SEND_RSP:
|
||||
case XW_ACT_SEND_RERSP:
|
||||
notifyOthers( evt.u.con.socket, XWRELAY_OTHERCONNECT,
|
||||
XWRELAY_ERROR_NONE );
|
||||
sendResponse( &evt );
|
||||
sendResponse( &evt, takeAction == XW_ACT_SEND_RSP );
|
||||
break;
|
||||
|
||||
case XW_ACT_FWD:
|
||||
|
@ -493,15 +495,6 @@ putNetShort( unsigned char** bufpp, unsigned short s )
|
|||
*bufpp += sizeof(s);
|
||||
}
|
||||
|
||||
static void
|
||||
putNetLong( unsigned char** bufpp, unsigned long s )
|
||||
{
|
||||
s = htonl( s );
|
||||
memcpy( *bufpp, &s, sizeof(s) );
|
||||
*bufpp += sizeof(s);
|
||||
assert( sizeof(s) == 4 ); /* otherwise need to hardcode */
|
||||
}
|
||||
|
||||
void
|
||||
CookieRef::setAllConnectedTimer()
|
||||
{
|
||||
|
@ -518,26 +511,39 @@ CookieRef::cancelAllConnectedTimer()
|
|||
}
|
||||
|
||||
void
|
||||
CookieRef::sendResponse( const CRefEvent* evt )
|
||||
CookieRef::sendResponse( const CRefEvent* evt, int initial )
|
||||
{
|
||||
int socket = evt->u.con.socket;
|
||||
HostID id = evt->u.con.srcID;
|
||||
|
||||
assert( id != HOST_ID_NONE );
|
||||
logf( "remembering pair: hostid=%x, socket=%d", id, socket );
|
||||
/* RWWriteLock ml( &m_sockets_rwlock ); */
|
||||
HostRec hr(socket);
|
||||
m_sockets.insert( pair<HostID,HostRec>(id,hr) );
|
||||
|
||||
/* Now send the response */
|
||||
unsigned char buf[7];
|
||||
unsigned char buf[1 + /* cmd */
|
||||
sizeof(short) + /* heartbeat */
|
||||
sizeof(CookieID) +
|
||||
1 + /* hostID */
|
||||
MAX_CONNNAME_LEN+1];
|
||||
unsigned char* bufp = buf;
|
||||
|
||||
*bufp++ = XWRELAY_CONNECTRESP;
|
||||
*bufp++ = initial ? XWRELAY_CONNECT_RESP : XWRELAY_RECONNECT_RESP;
|
||||
putNetShort( &bufp, GetHeartbeat() );
|
||||
putNetLong( &bufp, GetCookieID() );
|
||||
putNetShort( &bufp, GetCookieID() );
|
||||
logf( "writing hostID of %d into mgs", id );
|
||||
*bufp++ = (char)id;
|
||||
if ( initial ) {
|
||||
const char* connName = ConnName();
|
||||
int len = strlen( connName );
|
||||
assert( len < MAX_CONNNAME_LEN );
|
||||
*bufp++ = (char)len;
|
||||
memcpy( bufp, connName, len );
|
||||
bufp += len;
|
||||
}
|
||||
|
||||
send_with_length( socket, buf, sizeof(buf) );
|
||||
send_with_length( socket, buf, bufp - buf );
|
||||
logf( "sent XWRELAY_CONNECTRESP" );
|
||||
} /* sendResponse */
|
||||
|
||||
|
@ -655,7 +661,7 @@ CookieRef::noteHeartbeat( const CRefEvent* evt )
|
|||
|
||||
map<HostID,HostRec>::iterator iter = m_sockets.find(id);
|
||||
if ( iter == m_sockets.end() ) {
|
||||
logf( "no socket for HostID %d", id );
|
||||
logf( "no socket for HostID %x", id );
|
||||
} else {
|
||||
|
||||
/* PENDING If the message came on an unexpected socket, kill the
|
||||
|
@ -675,9 +681,7 @@ CookieRef::s_checkAllConnected( void* closure )
|
|||
/* Need to ensure */
|
||||
CookieRef* self = (CookieRef*)closure;
|
||||
SafeCref scr(self);
|
||||
if ( scr.IsValid() ) {
|
||||
scr.CheckAllConnected();
|
||||
}
|
||||
scr.CheckAllConnected();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -698,9 +702,12 @@ CookieRef::_PrintCookieInfo( string& out )
|
|||
out += Name();
|
||||
out += "\n";
|
||||
out += "ID: ";
|
||||
char buf[64];
|
||||
char buf[MAX_CONNNAME_LEN+MAX_COOKIE_LEN];
|
||||
|
||||
snprintf( buf, sizeof(buf), "%d\n", GetCookieID() );
|
||||
snprintf( buf, sizeof(buf), "%s\n", Name() );
|
||||
out += buf;
|
||||
|
||||
snprintf( buf, sizeof(buf), "%s\n", ConnName() );
|
||||
out += buf;
|
||||
|
||||
snprintf( buf, sizeof(buf), "Bytes sent: %d\n", m_totalSent );
|
||||
|
|
20
relay/cref.h
20
relay/cref.h
|
@ -52,21 +52,24 @@ class CookieRef {
|
|||
friend class SafeCref;
|
||||
friend class CookieMapIterator;
|
||||
|
||||
CookieRef( const char* s, CookieID id );
|
||||
CookieRef( const char* cookie, const char* connName, CookieID id );
|
||||
~CookieRef();
|
||||
|
||||
/* Within this cookie, remember that this hostID and socket go together.
|
||||
If the hostID is HOST_ID_SERVER, it's the server. */
|
||||
CookieID GetCookieID() { return m_connectionID; }
|
||||
CookieID GetCookieID() { return m_cookieID; }
|
||||
|
||||
int HostKnown( HostID host ) { return -1 != SocketForHost( host ); }
|
||||
int CountSockets() { return m_sockets.size(); }
|
||||
int HasSocket( int socket );
|
||||
string Name() { return m_name; }
|
||||
const char* Name() { return m_name.c_str(); }
|
||||
const char* ConnName() { return m_connName.c_str(); }
|
||||
|
||||
short GetHeartbeat() { return m_heatbeat; }
|
||||
int SocketForHost( HostID dest );
|
||||
|
||||
int NeverFullyConnected();
|
||||
int AcceptingConnections();
|
||||
|
||||
/* for console */
|
||||
void _PrintCookieInfo( string& out );
|
||||
|
@ -149,7 +152,7 @@ class CookieRef {
|
|||
|
||||
void handleEvents();
|
||||
|
||||
void sendResponse( const CRefEvent* evt );
|
||||
void sendResponse( const CRefEvent* evt, int initial );
|
||||
void setAllConnectedTimer();
|
||||
void cancelAllConnectedTimer();
|
||||
|
||||
|
@ -163,16 +166,17 @@ class CookieRef {
|
|||
void notifyDisconn(const CRefEvent* evt);
|
||||
void removeSocket( int socket );
|
||||
|
||||
|
||||
HostID nextHostID() { return ++m_nextHostID; }
|
||||
/* timer callback */
|
||||
static void s_checkAllConnected( void* closure );
|
||||
|
||||
map<HostID,HostRec> m_sockets;
|
||||
/* pthread_rwlock_t m_sockets_rwlock; */
|
||||
|
||||
CookieID m_connectionID;
|
||||
short m_heatbeat; /* might change per carrier or something. */
|
||||
string m_name;
|
||||
string m_name; /* cookie used for initial connections */
|
||||
string m_connName; /* globally unique name */
|
||||
CookieID m_cookieID; /* Unique among current games on this server */
|
||||
int m_totalSent;
|
||||
|
||||
/* Guard the event queue. Only one thread at a time can post to the
|
||||
|
@ -185,7 +189,7 @@ class CookieRef {
|
|||
XW_RELAY_STATE m_nextState;
|
||||
deque<CRefEvent> m_eventQueue;
|
||||
|
||||
static CookieID ms_nextConnectionID;
|
||||
HostID m_nextHostID;
|
||||
}; /* CookieRef */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "crefmgr.h"
|
||||
#include "cref.h"
|
||||
#include "mlock.h"
|
||||
#include "permid.h"
|
||||
|
||||
class SocketStuff {
|
||||
public:
|
||||
|
@ -48,6 +49,7 @@ CRefMgr::Get()
|
|||
} /* Get */
|
||||
|
||||
CRefMgr::CRefMgr()
|
||||
: m_nextCID(0)
|
||||
{
|
||||
/* should be using pthread_once() here */
|
||||
pthread_mutex_init( &m_guard, NULL );
|
||||
|
@ -59,21 +61,93 @@ CRefMgr::~CRefMgr()
|
|||
}
|
||||
|
||||
CookieRef*
|
||||
CRefMgr::getMakeCookieRef_locked( const char* cookie, CookieID connID )
|
||||
CRefMgr::FindOpenGameFor( const char* cORn, int isCookie )
|
||||
{
|
||||
CookieRef* cref = NULL;
|
||||
RWReadLock rwl( &m_cookieMapRWLock );
|
||||
|
||||
CookieMap::iterator iter = m_cookieMap.begin();
|
||||
while ( iter != m_cookieMap.end() ) {
|
||||
cref = iter->second;
|
||||
if ( isCookie ) {
|
||||
if ( cref->NeverFullyConnected() ) {
|
||||
if ( 0 == strcmp( cref->Name(), cORn ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( cref->AcceptingConnections() ) {
|
||||
if ( 0 == strcmp( cref->ConnName(), cORn ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
return (iter == m_cookieMap.end()) ? NULL : cref;
|
||||
} /* FindOpenGameFor */
|
||||
|
||||
CookieID
|
||||
CRefMgr::nextCID( const char* connName )
|
||||
{
|
||||
/* Later may want to guarantee that wrap-around doesn't cause an overlap.
|
||||
But that's really only a theoretical possibility. */
|
||||
return ++m_nextCID;
|
||||
} /* nextCID */
|
||||
|
||||
CookieID
|
||||
CRefMgr::cookieIDForConnName( const char* connName )
|
||||
{
|
||||
CookieID cid = 0;
|
||||
/* for now, just walk the existing data structure and see if the thing's
|
||||
in use. If it isn't, return a new id. */
|
||||
|
||||
RWReadLock rwl( &m_cookieMapRWLock );
|
||||
|
||||
CookieMap::iterator iter = m_cookieMap.begin();
|
||||
while ( iter != m_cookieMap.end() ) {
|
||||
CookieRef* cref = iter->second;
|
||||
if ( 0 == strcmp( cref->ConnName(), connName ) ) {
|
||||
cid = iter->first;
|
||||
break;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
return cid;
|
||||
} /* cookieIDForConnName */
|
||||
|
||||
CookieRef*
|
||||
CRefMgr::getMakeCookieRef_locked( const char* cORn, int isCookie, HostID hid )
|
||||
{
|
||||
CookieRef* cref;
|
||||
|
||||
pthread_mutex_lock( &m_guard );
|
||||
|
||||
CookieRef* cref = connID == 0 ? NULL: getCookieRef_impl( connID );
|
||||
/* We have a cookie from a new connection. This may be the first time
|
||||
it's been seen, or there may be a game currently in the
|
||||
XW_ST_CONNECTING state. So we need to look up the cookie first, then
|
||||
generate new connName and cookieIDs if it's not found. */
|
||||
|
||||
if ( cref == NULL ) { /* need to keep looking? */
|
||||
|
||||
CookieID newId = CookieIdForName( cookie );
|
||||
|
||||
if ( newId == 0 ) { /* not in the system */
|
||||
cref = AddNew( cookie, connID );
|
||||
cref = FindOpenGameFor( cORn, isCookie );
|
||||
if ( cref == NULL ) {
|
||||
const char* connName;
|
||||
const char* cookie = NULL;
|
||||
if ( isCookie ) {
|
||||
cookie = cORn;
|
||||
string s = PermID::GetNextUniqueID();
|
||||
connName = s.c_str();
|
||||
} else {
|
||||
cref = getCookieRef_impl( newId );
|
||||
connName = cORn;
|
||||
}
|
||||
|
||||
CookieID cid = cookieIDForConnName( connName );
|
||||
if ( cid == 0 ) {
|
||||
cid = nextCID( connName );
|
||||
}
|
||||
|
||||
cref = AddNew( cookie, connName, cid );
|
||||
}
|
||||
|
||||
if ( cref == NULL ) {
|
||||
|
@ -83,25 +157,6 @@ CRefMgr::getMakeCookieRef_locked( const char* cookie, CookieID connID )
|
|||
return cref;
|
||||
} /* getMakeCookieRef_locked */
|
||||
|
||||
CookieID
|
||||
CRefMgr::CookieIdForName( const char* name )
|
||||
{
|
||||
CookieRef* cref = NULL;
|
||||
string s(name);
|
||||
|
||||
RWReadLock rwl( &m_cookieMapRWLock );
|
||||
|
||||
CookieMap::iterator iter = m_cookieMap.begin();
|
||||
while ( iter != m_cookieMap.end() ) {
|
||||
cref = iter->second;
|
||||
if ( cref->Name() == s && cref->NeverFullyConnected() ) {
|
||||
return cref->GetCookieID();
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
return 0;
|
||||
} /* CookieIdForName */
|
||||
|
||||
void
|
||||
CRefMgr::Associate( int socket, CookieRef* cref )
|
||||
{
|
||||
|
@ -147,22 +202,21 @@ void
|
|||
CRefMgr::RemoveSocketRefs( int socket )
|
||||
{
|
||||
SafeCref scr( socket );
|
||||
if ( scr.IsValid() ) {
|
||||
scr.Remove( socket );
|
||||
}
|
||||
scr.Remove( socket );
|
||||
}
|
||||
|
||||
void
|
||||
CRefMgr::PrintSocketInfo( int socket, string& out )
|
||||
{
|
||||
SafeCref scr( socket );
|
||||
if ( scr.IsValid() ) {
|
||||
const char* name = scr.Name();
|
||||
if ( name != NULL && name[0] != '\0' ) {
|
||||
char buf[64];
|
||||
|
||||
snprintf( buf, sizeof(buf), "* socket: %d\n", socket );
|
||||
out += buf;
|
||||
|
||||
snprintf( buf, sizeof(buf), " in cookie: %s\n", scr.Name().c_str() );
|
||||
snprintf( buf, sizeof(buf), " in cookie: %s\n", name );
|
||||
out += buf;
|
||||
}
|
||||
}
|
||||
|
@ -256,13 +310,14 @@ CRefMgr::UnlockCref( CookieRef* cref )
|
|||
}
|
||||
|
||||
CookieRef*
|
||||
CRefMgr::AddNew( const char* s, CookieID id )
|
||||
CRefMgr::AddNew( const char* cookie, const char* connName, CookieID id )
|
||||
{
|
||||
RWWriteLock rwl( &m_cookieMapRWLock );
|
||||
logf( "making new cref" );
|
||||
CookieRef* ref = new CookieRef( s, id );
|
||||
logf( "making new cref: %d", id );
|
||||
CookieRef* ref = new CookieRef( cookie, connName, id );
|
||||
m_cookieMap.insert( pair<CookieID, CookieRef*>(ref->GetCookieID(), ref ) );
|
||||
logf( "paired cookie %s with id %d", s, ref->GetCookieID() );
|
||||
logf( "paired cookie %s/connName %s with id %d",
|
||||
(cookie?cookie:"NULL"), connName, ref->GetCookieID() );
|
||||
return ref;
|
||||
} /* AddNew */
|
||||
|
||||
|
@ -304,9 +359,9 @@ CRefMgr::Delete( CookieID id )
|
|||
} /* Delete */
|
||||
|
||||
void
|
||||
CRefMgr::Delete( const char* name )
|
||||
CRefMgr::Delete( const char* connName )
|
||||
{
|
||||
CookieID id = CookieIdForName( name );
|
||||
CookieID id = cookieIDForConnName( connName );
|
||||
Delete( id );
|
||||
} /* Delete */
|
||||
|
||||
|
@ -345,9 +400,7 @@ CRefMgr::CheckHeartbeats( time_t now )
|
|||
unsigned int i;
|
||||
for ( i = 0; i < crefs.size(); ++i ) {
|
||||
SafeCref scr( crefs[i] );
|
||||
if ( scr.IsValid() ) {
|
||||
scr.CheckHeartbeats( now );
|
||||
}
|
||||
scr.CheckHeartbeats( now );
|
||||
}
|
||||
} /* CheckHeartbeats */
|
||||
|
||||
|
@ -380,11 +433,13 @@ CookieMapIterator::Next()
|
|||
// SafeCref
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SafeCref::SafeCref( const char* cookie, CookieID connID )
|
||||
SafeCref::SafeCref( const char* cORn, int isCookie, HostID hid )
|
||||
: m_cref( NULL )
|
||||
, m_mgr( CRefMgr::Get() )
|
||||
{
|
||||
CookieRef* cref = m_mgr->getMakeCookieRef_locked( cookie, connID );
|
||||
CookieRef* cref;
|
||||
|
||||
cref = m_mgr->getMakeCookieRef_locked( cORn, isCookie, hid );
|
||||
if ( cref != NULL ) {
|
||||
if ( m_mgr->LockCref( cref ) ) {
|
||||
m_cref = cref;
|
||||
|
|
|
@ -60,7 +60,7 @@ class CRefMgr {
|
|||
void CheckHeartbeats( time_t now );
|
||||
void Delete( CookieID id );
|
||||
void Delete( CookieRef* cref );
|
||||
void Delete( const char* name );
|
||||
void Delete( const char* connName );
|
||||
CookieID CookieIdForName( const char* name );
|
||||
|
||||
/* For use from ctrl only!!!! */
|
||||
|
@ -77,12 +77,18 @@ class CRefMgr {
|
|||
|
||||
private:
|
||||
friend class SafeCref;
|
||||
CookieRef* getMakeCookieRef_locked( const char* cookie, CookieID cid );
|
||||
CookieRef* getMakeCookieRef_locked( const char* cORn, int isCookie, HostID hid );
|
||||
CookieRef* getCookieRef_locked( CookieID cookieID );
|
||||
CookieRef* getCookieRef_locked( int socket );
|
||||
int checkCookieRef_locked( CookieRef* cref );
|
||||
CookieRef* getCookieRef_impl( CookieID cookieID );
|
||||
CookieRef* AddNew( const char* s, CookieID id );
|
||||
CookieRef* AddNew( const char* cookie, const char* connName, CookieID id );
|
||||
CookieRef* FindOpenGameFor( const char* cORn, int isCookie );
|
||||
|
||||
CookieID cookieIDForConnName( const char* connName );
|
||||
CookieID nextCID( const char* connName );
|
||||
|
||||
CookieID m_nextCID;
|
||||
|
||||
int LockCref( CookieRef* cref );
|
||||
void UnlockCref( CookieRef* cref );
|
||||
|
@ -106,45 +112,81 @@ class SafeCref {
|
|||
CookieRef instance at a time. */
|
||||
|
||||
public:
|
||||
SafeCref( const char* cookie, CookieID cid );
|
||||
SafeCref( const char* cookieOrConnName, int cookie, HostID hid );
|
||||
SafeCref( CookieID cid );
|
||||
SafeCref( int socket );
|
||||
SafeCref( CookieRef* cref );
|
||||
~SafeCref();
|
||||
|
||||
int IsValid() { return m_cref != NULL; }
|
||||
|
||||
void Forward( HostID src, HostID dest, unsigned char* buf, int buflen ) {
|
||||
m_cref->_Forward( src, dest, buf, buflen );
|
||||
int Forward( HostID src, HostID dest, unsigned char* buf, int buflen ) {
|
||||
if ( IsValid() ) {
|
||||
m_cref->_Forward( src, dest, buf, buflen );
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void Connect( int socket, HostID srcID ) {
|
||||
m_cref->_Connect( socket, srcID );
|
||||
int Connect( int socket, HostID srcID ) {
|
||||
if ( IsValid() ) {
|
||||
m_cref->_Connect( socket, srcID );
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void Reconnect( int socket, HostID srcID ) {
|
||||
m_cref->_Reconnect( socket, srcID );
|
||||
int Reconnect( int socket, HostID srcID ) {
|
||||
if ( IsValid() ) {
|
||||
m_cref->_Reconnect( socket, srcID );
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void Disconnect(int socket, HostID hostID ) {
|
||||
m_cref->_Disconnect( socket, hostID );
|
||||
if ( IsValid() ) {
|
||||
m_cref->_Disconnect( socket, hostID );
|
||||
}
|
||||
}
|
||||
void Remove( int socket ) {
|
||||
m_cref->_Remove( socket );
|
||||
if ( IsValid() ) {
|
||||
m_cref->_Remove( socket );
|
||||
}
|
||||
}
|
||||
void HandleHeartbeat( HostID id, int socket ) {
|
||||
m_cref->_HandleHeartbeat( id, socket );
|
||||
int HandleHeartbeat( HostID id, int socket ) {
|
||||
if ( IsValid() ) {
|
||||
m_cref->_HandleHeartbeat( id, socket );
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void CheckHeartbeats( time_t now ) {
|
||||
m_cref->_CheckHeartbeats( now );
|
||||
if ( IsValid() ) {
|
||||
m_cref->_CheckHeartbeats( now );
|
||||
}
|
||||
}
|
||||
void PrintCookieInfo( string& out ) {
|
||||
m_cref->_PrintCookieInfo( out );
|
||||
if ( IsValid() ) {
|
||||
m_cref->_PrintCookieInfo( out );
|
||||
}
|
||||
}
|
||||
void CheckAllConnected() {
|
||||
m_cref->_CheckAllConnected();
|
||||
if ( IsValid() ) {
|
||||
m_cref->_CheckAllConnected();
|
||||
}
|
||||
}
|
||||
const char* Name() {
|
||||
if ( IsValid() ) {
|
||||
return m_cref->Name();
|
||||
} else {
|
||||
return ""; /* so don't crash.... */
|
||||
}
|
||||
}
|
||||
string Name() { return m_cref->Name(); }
|
||||
|
||||
|
||||
private:
|
||||
int IsValid() { return m_cref != NULL; }
|
||||
|
||||
CookieRef* m_cref;
|
||||
CRefMgr* m_mgr;
|
||||
};
|
||||
|
|
|
@ -123,12 +123,10 @@ print_cookies( int socket, CookieID theID )
|
|||
for ( id = iter.Next(); id != 0; id = iter.Next() ) {
|
||||
if ( theID == 0 || theID == id ) {
|
||||
SafeCref scr( id );
|
||||
if ( scr.IsValid() ) {
|
||||
string s;
|
||||
scr.PrintCookieInfo( s );
|
||||
string s;
|
||||
scr.PrintCookieInfo( s );
|
||||
|
||||
print_to_sock( socket, s.c_str() );
|
||||
}
|
||||
print_to_sock( socket, s.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +171,7 @@ cmd_kill( int socket, const char** args )
|
|||
if ( !found ) {
|
||||
char* msg =
|
||||
"%s socket <num>\n"
|
||||
"%s cookie name <name>\n"
|
||||
"%s cookie name <connName>\n"
|
||||
"%s cookie id <id>\n"
|
||||
;
|
||||
print_to_sock( socket, msg, args[0], args[0], args[0] );
|
||||
|
@ -207,7 +205,7 @@ print_cookies( int socket, const char* name )
|
|||
|
||||
for ( id = iter.Next(); id != 0; id = iter.Next() ) {
|
||||
SafeCref scr( id );
|
||||
if ( scr.IsValid() && scr.Name() == name ) {
|
||||
if ( scr.Name() == name ) {
|
||||
string s;
|
||||
scr.PrintCookieInfo( s );
|
||||
|
||||
|
|
|
@ -26,11 +26,15 @@
|
|||
using namespace std;
|
||||
|
||||
pthread_mutex_t PermID::s_guard = PTHREAD_MUTEX_INITIALIZER;
|
||||
string PermID::s_serverName;
|
||||
|
||||
string
|
||||
PermID::GetNextUniqueID()
|
||||
{
|
||||
MutexLock ml( &s_guard );
|
||||
|
||||
string s = s_serverName;
|
||||
s += ":";
|
||||
|
||||
char buf[32]; /* should last for a while :-) */
|
||||
|
||||
|
@ -40,6 +44,7 @@ PermID::GetNextUniqueID()
|
|||
rewind( f );
|
||||
} else {
|
||||
f = fopen( "/etc/xwrelay/xwrelay_id.txt", "w" );
|
||||
assert ( f != NULL );
|
||||
buf[0] = '0';
|
||||
buf[1] = '\0';
|
||||
}
|
||||
|
@ -50,8 +55,13 @@ PermID::GetNextUniqueID()
|
|||
fprintf( f, "%s\n", buf );
|
||||
fclose( f );
|
||||
|
||||
string s(buf);
|
||||
logf( "new id will be %s", s.c_str() );
|
||||
s += buf;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PermID::SetServerName( const char* name )
|
||||
{
|
||||
s_serverName = name;
|
||||
}
|
||||
|
|
|
@ -32,9 +32,15 @@
|
|||
*/
|
||||
class PermID {
|
||||
public:
|
||||
static std::string GetNextUniqueID();
|
||||
static void SetServerName( const char* name );
|
||||
static std::string GetNextUniqueID();
|
||||
|
||||
private:
|
||||
static pthread_mutex_t s_guard; /* guard access to the whole process */
|
||||
static pthread_mutex_t s_guard; /* guard access to the whole
|
||||
process */
|
||||
static std::string s_serverName; /* All ID's generated start with
|
||||
this, which is supposed to be
|
||||
unique to this relay
|
||||
instance. */
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -40,31 +40,31 @@ typedef struct StateTable {
|
|||
window where new devices can sign in using a given cookie is fairly small.
|
||||
|
||||
Perhaps a better algorithm is needed for determining when the game is
|
||||
closed. It's not when the first XW_EVT_FORWARDMSG comes along, since
|
||||
that can happen before all hosts have arrived (e.g. if a client signs up
|
||||
before the server.) The goal has been to avoid having the relay know about
|
||||
the xwords protocol. But it already knows about hostID 0 (I think). So
|
||||
maybe when that host sends a message for forwarding we know we're set? Or
|
||||
maybe we add a message the server can send saying "All are present now;
|
||||
lock the game!" It'd suck if that were spoofed though.
|
||||
closed. It's not when the first XW_EVT_FORWARDMSG comes along, since that
|
||||
can happen before all hosts have arrived (e.g. if a client signs up before
|
||||
the server.) The goal has been to avoid having the relay know about the
|
||||
xwords protocol. But it already knows about hostID 1. So maybe when that
|
||||
host sends a message for forwarding we know we're set? Yes: the server
|
||||
sends only after all clients have reported in, at least now.
|
||||
|
||||
The problem we want to avoid is bogus connections. Two are playing using
|
||||
cookie FOO. Somebody looks over a shoulder and sees FOO, and tries to
|
||||
connect. The relay must not start forwarding packets from the interloper
|
||||
into the game associated with FOO.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
StateTable g_stateTable[] = {
|
||||
|
||||
/* Initial msg comes in. Managing object created in init state, sends response */
|
||||
{ XW_ST_INITED, XW_EVT_CONNECTMSG, XW_ACT_SEND_1ST_RSP, XW_ST_CONNECTING },
|
||||
{ XW_ST_INITED, XW_EVT_RECONNECTMSG, XW_ACT_SENDRSP, XW_ST_CONNECTING },
|
||||
{ XW_ST_INITED, XW_EVT_RECONNECTMSG, XW_ACT_SEND_1ST_RERSP,XW_ST_CONNECTING },
|
||||
|
||||
/* Another connect msg comes in */
|
||||
{ XW_ST_CONNECTING, XW_EVT_CONNECTMSG, XW_ACT_SENDRSP, XW_ST_CONNECTING },
|
||||
{ XW_ST_CONNECTING, XW_EVT_RECONNECTMSG, XW_ACT_SENDRSP, XW_ST_CONNECTING },
|
||||
{ XW_ST_CONNECTING, XW_EVT_CONNECTMSG, XW_ACT_SEND_RSP, XW_ST_CONNECTING },
|
||||
{ XW_ST_CONNECTING, XW_EVT_RECONNECTMSG, XW_ACT_SEND_RERSP, XW_ST_CONNECTING },
|
||||
|
||||
{ XW_ST_MISSING, XW_EVT_CONNECTMSG, XW_ACT_SEND_RSP, XW_ST_CONNECTING },
|
||||
{ XW_ST_MISSING, XW_EVT_RECONNECTMSG, XW_ACT_SEND_RERSP, XW_ST_CONNECTING },
|
||||
|
||||
/* Disconnect. */
|
||||
{ XW_ST_ALLCONNECTED, XW_EVT_DISCONNECTMSG, XW_ACT_DISCONNECT, XW_ST_MISSING },
|
||||
|
|
|
@ -105,8 +105,10 @@ typedef enum {
|
|||
XW_ACT_NONE
|
||||
|
||||
,XW_ACT_SEND_1ST_RSP
|
||||
,XW_ACT_SEND_1ST_RERSP
|
||||
|
||||
,XW_ACT_SENDRSP /* Send a connection response */
|
||||
,XW_ACT_SEND_RSP /* Send a connection response */
|
||||
,XW_ACT_SEND_RERSP
|
||||
|
||||
,XW_ACT_FWD /* Forward a message */
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
# Format: var=value. No spaces between var and value at this point.
|
||||
|
||||
# Heartbeat timer. Sent to clients.
|
||||
HEARTBEAT=60
|
||||
HEARTBEAT=6000
|
||||
|
||||
# How long after the first connection on a cookie until we need to
|
||||
# have heard from all players in the game? After this long passes we
|
||||
# kill the connection after notifying all that have connected.
|
||||
ALLCONN=120
|
||||
ALLCONN=12000
|
||||
|
||||
# How many worker threads in the thread pool? Default is five.
|
||||
NTHREADS=5
|
||||
|
@ -20,3 +20,6 @@ PORT=10999
|
|||
# And the control port is?
|
||||
CTLPORT=11000
|
||||
|
||||
# Need a unique name for every instance of the relay so they can
|
||||
# create game ids guaranteed to be unique
|
||||
#SERVERNAME=eehouse.org
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "tpool.h"
|
||||
#include "configs.h"
|
||||
#include "timermgr.h"
|
||||
#include "permid.h"
|
||||
|
||||
#define N_WORKER_THREADS 5
|
||||
#define MILLIS 1000
|
||||
|
@ -83,54 +84,63 @@ logf( const char* format, ... )
|
|||
fprintf( where, "\n" );
|
||||
} /* logf */
|
||||
|
||||
static unsigned short
|
||||
getNetShort( unsigned char** bufpp )
|
||||
static int
|
||||
getNetShort( unsigned char** bufpp, unsigned char* end, unsigned short* out )
|
||||
{
|
||||
unsigned short tmp;
|
||||
memcpy( &tmp, *bufpp, 2 );
|
||||
*bufpp += 2;
|
||||
return ntohs( tmp );
|
||||
int ok = *bufpp + 2 <= end;
|
||||
if ( ok ) {
|
||||
unsigned short tmp;
|
||||
memcpy( &tmp, *bufpp, 2 );
|
||||
*bufpp += 2;
|
||||
*out = ntohs( tmp );
|
||||
}
|
||||
return ok;
|
||||
} /* getNetShort */
|
||||
|
||||
static unsigned short
|
||||
getNetLong( unsigned char** bufpp )
|
||||
static int
|
||||
getNetByte( unsigned char** bufpp, unsigned char* end, unsigned char* out )
|
||||
{
|
||||
unsigned long tmp;
|
||||
memcpy( &tmp, *bufpp, sizeof(tmp) );
|
||||
*bufpp += sizeof(tmp);
|
||||
assert( sizeof(tmp) == 4 );
|
||||
return ntohl( tmp );
|
||||
} /* getNetLong */
|
||||
int ok = *bufpp < end;
|
||||
if ( ok ) {
|
||||
*out = **bufpp;
|
||||
++*bufpp;
|
||||
}
|
||||
return ok;
|
||||
} /* getNetByte */
|
||||
|
||||
static void
|
||||
processHeartbeat( unsigned char* buf, int bufLen, int socket )
|
||||
{
|
||||
CookieID cookieID = getNetLong( &buf );
|
||||
HostID hostID = getNetShort( &buf );
|
||||
logf( "processHeartbeat: cookieID 0x%lx, hostID 0x%x", cookieID, hostID );
|
||||
unsigned char* end = buf + bufLen;
|
||||
CookieID cookieID;
|
||||
HostID hostID;
|
||||
|
||||
SafeCref scr( cookieID );
|
||||
if ( scr.IsValid() ) {
|
||||
scr.HandleHeartbeat( hostID, socket );
|
||||
} else {
|
||||
killSocket( socket, "no cref for socket" );
|
||||
if ( getNetShort( &buf, end, &cookieID )
|
||||
&& getNetByte( &buf, end, &hostID ) ) {
|
||||
logf( "processHeartbeat: cookieID 0x%lx, hostID 0x%x",
|
||||
cookieID, hostID );
|
||||
|
||||
SafeCref scr( cookieID );
|
||||
if ( !scr.HandleHeartbeat( hostID, socket ) ) {
|
||||
killSocket( socket, "no cref for socket" );
|
||||
}
|
||||
}
|
||||
} /* processHeartbeat */
|
||||
|
||||
static int
|
||||
readCookie( unsigned char** bufp, const unsigned char* end,
|
||||
char* outBuf )
|
||||
readStr( unsigned char** bufp, const unsigned char* end,
|
||||
char* outBuf, int bufLen )
|
||||
{
|
||||
unsigned char clen = **bufp;
|
||||
++*bufp;
|
||||
if ( *bufp < end && clen > 0 && clen < MAX_COOKIE_LEN ) {
|
||||
if ( ((*bufp + clen) <= end) && (clen < bufLen) ) {
|
||||
memcpy( outBuf, *bufp, clen );
|
||||
outBuf[clen] = '\0';
|
||||
*bufp += clen;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} /* readCookie */
|
||||
} /* readStr */
|
||||
|
||||
static int
|
||||
flagsOK( unsigned char flags )
|
||||
|
@ -180,10 +190,11 @@ send_with_length_unsafe( int socket, unsigned char* buf, int bufLen )
|
|||
* game?
|
||||
*/
|
||||
static void
|
||||
processConnect( unsigned char* bufp, int bufLen, int socket, int recon )
|
||||
processConnect( unsigned char* bufp, int bufLen, int socket )
|
||||
{
|
||||
char cookie[MAX_COOKIE_LEN+1];
|
||||
unsigned char* end = bufp + bufLen;
|
||||
int success = 0;
|
||||
|
||||
logf( "processConnect" );
|
||||
|
||||
|
@ -191,45 +202,63 @@ processConnect( unsigned char* bufp, int bufLen, int socket, int recon )
|
|||
|
||||
unsigned char flags = *bufp++;
|
||||
if ( flagsOK( flags ) ) {
|
||||
if ( recon || readCookie( &bufp, end, cookie ) ) {
|
||||
HostID srcID;
|
||||
if ( readStr( &bufp, end, cookie, sizeof(cookie) )
|
||||
&& getNetByte( &bufp, end, &srcID ) ) {
|
||||
|
||||
HostID srcID;
|
||||
CookieID cookieID;
|
||||
|
||||
if ( bufp + sizeof(srcID) + sizeof(cookieID) == end ) {
|
||||
srcID = getNetShort( &bufp );
|
||||
cookieID = getNetLong( &bufp );
|
||||
|
||||
SafeCref scr( cookie, cookieID );
|
||||
if ( scr.IsValid() ) {
|
||||
if ( recon ) {
|
||||
scr.Reconnect( socket, srcID );
|
||||
} else {
|
||||
scr.Connect( socket, srcID );
|
||||
}
|
||||
}
|
||||
}
|
||||
SafeCref scr( cookie, 1, srcID );
|
||||
success = scr.Connect( socket, srcID );
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if ( !success ) {
|
||||
denyConnection( socket );
|
||||
}
|
||||
} /* processConnect */
|
||||
|
||||
static void
|
||||
processReconnect( unsigned char* bufp, int bufLen, int socket )
|
||||
{
|
||||
char connName[MAX_CONNNAME_LEN+1];
|
||||
unsigned char* end = bufp + bufLen;
|
||||
int success = 0;
|
||||
|
||||
logf( "processReconnect" );
|
||||
|
||||
connName[0] = '\0';
|
||||
|
||||
unsigned char flags = *bufp++;
|
||||
if ( flagsOK( flags ) ) {
|
||||
HostID srcID;
|
||||
if ( getNetByte( &bufp, end, &srcID )
|
||||
&& readStr( &bufp, end, connName, sizeof(connName) ) ) {
|
||||
|
||||
SafeCref scr( connName, 0, srcID );
|
||||
success = scr.Connect( socket, srcID );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !success ) {
|
||||
denyConnection( socket );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
processDisconnect( unsigned char* bufp, int bufLen, int socket )
|
||||
{
|
||||
if ( bufLen == 6 ) {
|
||||
CookieID cookieID = getNetLong( &bufp );
|
||||
HostID hostID = getNetShort( &bufp );
|
||||
unsigned char* end = bufp + bufLen;
|
||||
CookieID cookieID;
|
||||
HostID hostID;
|
||||
|
||||
if ( getNetShort( &bufp, end, &cookieID )
|
||||
&& getNetByte( &bufp, end, &hostID ) ) {
|
||||
|
||||
SafeCref scr( cookieID );
|
||||
if ( scr.IsValid() ) {
|
||||
scr.Disconnect( socket, hostID );
|
||||
}
|
||||
scr.Disconnect( socket, hostID );
|
||||
} else {
|
||||
logf( "dropping XWRELAY_GAME_DISCONNECT; wrong length" );
|
||||
}
|
||||
}
|
||||
} /* processDisconnect */
|
||||
|
||||
void
|
||||
killSocket( int socket, char* why )
|
||||
|
@ -255,17 +284,18 @@ forwardMessage( unsigned char* buf, int buflen, int srcSocket )
|
|||
{
|
||||
int success = 0;
|
||||
unsigned char* bufp = buf + 1; /* skip cmd */
|
||||
CookieID cookieID = getNetLong( &bufp );
|
||||
logf( "cookieID = %d", cookieID );
|
||||
unsigned char* end = buf + buflen;
|
||||
CookieID cookieID;
|
||||
HostID src;
|
||||
HostID dest;
|
||||
|
||||
if ( getNetShort( &bufp, end, &cookieID )
|
||||
&& getNetByte( &bufp, end, &src )
|
||||
&& getNetByte( &bufp, end, &dest ) ) {
|
||||
logf( "cookieID = %d", cookieID );
|
||||
|
||||
SafeCref scr( cookieID );
|
||||
if ( scr.IsValid() ) {
|
||||
HostID src = getNetShort( &bufp );
|
||||
HostID dest = getNetShort( &bufp );
|
||||
|
||||
scr.Forward( src, dest, buf, buflen );
|
||||
success = 1;
|
||||
SafeCref scr( cookieID );
|
||||
success = scr.Forward( src, dest, buf, buflen );
|
||||
}
|
||||
return success;
|
||||
} /* forwardMessage */
|
||||
|
@ -277,21 +307,15 @@ processMessage( unsigned char* buf, int bufLen, int socket )
|
|||
switch( cmd ) {
|
||||
case XWRELAY_GAME_CONNECT:
|
||||
logf( "processMessage got XWRELAY_CONNECT" );
|
||||
processConnect( buf+1, bufLen-1, socket, 0 );
|
||||
processConnect( buf+1, bufLen-1, socket );
|
||||
break;
|
||||
case XWRELAY_GAME_RECONNECT:
|
||||
logf( "processMessage got XWRELAY_RECONNECT" );
|
||||
processConnect( buf+1, bufLen-1, socket, 1 );
|
||||
processReconnect( buf+1, bufLen-1, socket );
|
||||
break;
|
||||
case XWRELAY_GAME_DISCONNECT:
|
||||
processDisconnect( buf+1, bufLen-1, socket );
|
||||
break;
|
||||
case XWRELAY_CONNECTRESP:
|
||||
logf( "bad: processMessage got XWRELAY_CONNECTRESP" );
|
||||
break;
|
||||
case XWRELAY_MSG_FROMRELAY:
|
||||
logf( "bad: processMessage got XWRELAY_MSG_FROMRELAY" );
|
||||
break;
|
||||
case XWRELAY_HEARTBEAT:
|
||||
logf( "processMessage got XWRELAY_HEARTBEAT" );
|
||||
processHeartbeat( buf + 1, bufLen - 1, socket );
|
||||
|
@ -303,7 +327,9 @@ processMessage( unsigned char* buf, int bufLen, int socket )
|
|||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
logf( "processMessage bad: %d", cmd );
|
||||
break;
|
||||
/* just drop it */
|
||||
}
|
||||
} /* processMessage */
|
||||
|
||||
|
@ -344,6 +370,7 @@ enum { FLAG_HELP
|
|||
,FLAG_PORT
|
||||
,FLAG_CPORT
|
||||
,FLAG_NTHREADS
|
||||
,FLAG_NAME
|
||||
};
|
||||
|
||||
struct option longopts[] = {
|
||||
|
@ -365,6 +392,12 @@ struct option longopts[] = {
|
|||
NULL,
|
||||
FLAG_PORT
|
||||
}
|
||||
,{
|
||||
"name",
|
||||
1,
|
||||
NULL,
|
||||
FLAG_NAME
|
||||
}
|
||||
,{
|
||||
"ctrlport",
|
||||
1,
|
||||
|
@ -401,9 +434,10 @@ int main( int argc, char** argv )
|
|||
int ctrlport = 0;
|
||||
int nWorkerThreads = 0;
|
||||
char* conffile = NULL;
|
||||
const char* serverName = NULL;
|
||||
|
||||
/* Verify sizes here... */
|
||||
assert( sizeof(CookieID) == 4 );
|
||||
assert( sizeof(CookieID) == 2 );
|
||||
|
||||
|
||||
/* Read options. Options trump config file values when they conflict, but
|
||||
|
@ -411,7 +445,7 @@ int main( int argc, char** argv )
|
|||
first. */
|
||||
|
||||
for ( ; ; ) {
|
||||
int opt = getopt_long(argc, argv, "hc:p:l:",longopts, NULL);
|
||||
int opt = getopt_long(argc, argv, "hc:p:l:n:",longopts, NULL);
|
||||
|
||||
if ( opt == -1 ) {
|
||||
break;
|
||||
|
@ -427,6 +461,9 @@ int main( int argc, char** argv )
|
|||
case FLAG_PORT:
|
||||
port = atoi( optarg );
|
||||
break;
|
||||
case FLAG_NAME:
|
||||
serverName = optarg;
|
||||
break;
|
||||
case FLAG_CPORT:
|
||||
ctrlport = atoi( optarg );
|
||||
break;
|
||||
|
@ -451,7 +488,11 @@ int main( int argc, char** argv )
|
|||
if ( nWorkerThreads == 0 ) {
|
||||
nWorkerThreads = cfg->GetNWorkerThreads();
|
||||
}
|
||||
if ( serverName == NULL ) {
|
||||
serverName = cfg->GetServerName();
|
||||
}
|
||||
|
||||
PermID::SetServerName( serverName );
|
||||
|
||||
int listener = make_socket( INADDR_ANY, port );
|
||||
if ( listener == -1 ) {
|
||||
|
|
|
@ -31,23 +31,27 @@ enum { XWRELAY_NONE /* 0 is an illegal value */
|
|||
|
||||
, XWRELAY_GAME_CONNECT
|
||||
/* Sent from device to relay to establish connection to relay. Format:
|
||||
flags: 1; cookieLen: 1; cookie: <cookieLen>; hostID:
|
||||
2. connectionID: 2. */
|
||||
flags: 1; cookieLen: 1; cookie: <cookieLen>; hostID: 1. */
|
||||
|
||||
, XWRELAY_GAME_RECONNECT
|
||||
/* Connect using ID rather than cookie. Used by a device that's lost
|
||||
its connection to a game in progress. Once a game is locked this is
|
||||
the only way a host can get (back) in. */
|
||||
/* Connect using connName rather than cookie. Used by a device that's
|
||||
lost its connection to a game in progress. Once a game is locked
|
||||
this is the only way a host can get (back) in. Format: flags: 1;
|
||||
hostID: 1; connNameLen: 1; connName<connNameLen>*/
|
||||
|
||||
, XWRELAY_GAME_DISCONNECT
|
||||
/* Tell the relay that we're gone for this game. After this message is
|
||||
sent, the host can reconnect on the same socket for a new game.
|
||||
Format: cookieID: 4; srcID: 2 */
|
||||
Format: cookieID: 2; srcID: 1 */
|
||||
|
||||
, XWRELAY_CONNECTRESP
|
||||
/* Sent from relay to device in response to XWRELAY_CONNECT or
|
||||
XWRELAY_RECONNECT. Format: heartbeat_seconds: 2; connectionID:
|
||||
2; */
|
||||
, XWRELAY_CONNECT_RESP
|
||||
/* Sent from relay to device in response to XWRELAY_CONNECT. Format:
|
||||
heartbeat_seconds: 2; connectionID: 2; assignedHostID: 1;
|
||||
connNameLen: 1; connName: <connNameLen>; */
|
||||
|
||||
, XWRELAY_RECONNECT_RESP
|
||||
/* Sent from relay to device in response to XWRELAY_RECONNECT. Format:
|
||||
heartbeat_seconds: 2; connectionID: 2; */
|
||||
|
||||
, XWRELAY_OTHERCONNECT /* Another device has [re]joined your game.
|
||||
Format: ??? */
|
||||
|
@ -58,21 +62,21 @@ enum { XWRELAY_NONE /* 0 is an illegal value */
|
|||
|
||||
, XWRELAY_DISCONNECT_OTHER
|
||||
/* Another device has left the game.
|
||||
Format: errorCode: 1; lostHostId: 2 */
|
||||
Format: errorCode: 1; lostHostId: 1 */
|
||||
|
||||
, XWRELAY_CONNECTDENIED
|
||||
/* The relay says go away. Format: reason code: 1 */
|
||||
|
||||
, XWRELAY_HEARTBEAT
|
||||
/* Sent in either direction. Format: cookieID: 4; srcID: 2 */
|
||||
/* Sent in either direction. Format: cookieID: 2; srcID: 1 */
|
||||
|
||||
, XWRELAY_MSG_FROMRELAY
|
||||
/* Sent from relay to device. Format: cookieID: 4; src_hostID: 2;
|
||||
dest_hostID: 2; data <len-headerLen> */
|
||||
/* Sent from relay to device. Format: cookieID: 2; src_hostID: 1;
|
||||
dest_hostID: 1; data <len-headerLen> */
|
||||
|
||||
, XWRELAY_MSG_TORELAY
|
||||
/* Sent from device to relay. Format: connectionID: 2; src_hostID:
|
||||
2; dest_hostID: 2 */
|
||||
1; dest_hostID: 1 */
|
||||
} XWRelayMsg;
|
||||
|
||||
#ifndef CANT_DO_TYPEDEF
|
||||
|
@ -84,6 +88,7 @@ typedef unsigned char XWRELAY_Cmd;
|
|||
|
||||
#define MAX_COOKIE_LEN 15
|
||||
#define MAX_MSG_LEN 256 /* 100 is more like it */
|
||||
#define MAX_CONNNAME_LEN 35 /* host id plus a small integer, typically */
|
||||
|
||||
#define XWRELAY_PROTO_VERSION 0x01
|
||||
|
||||
|
@ -102,7 +107,7 @@ typedef enum {
|
|||
} XWREASON;
|
||||
|
||||
|
||||
typedef unsigned int CookieID;
|
||||
typedef unsigned short CookieID;
|
||||
#define COOKIE_ID_NONE 0L
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
typedef unsigned short HostID;
|
||||
typedef unsigned char HostID;
|
||||
|
||||
void logf( const char* format, ... );
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue