2005-09-02 08:35:25 +02:00
|
|
|
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright 2005 by Eric House (fixin@peak.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 _CREFMGR_H_
|
|
|
|
#define _CREFMGR_H_
|
|
|
|
|
|
|
|
#include "cref.h"
|
|
|
|
|
|
|
|
typedef map<CookieID,CookieRef*> CookieMap;
|
|
|
|
class CookieMapIterator;
|
|
|
|
class SocketStuff;
|
|
|
|
typedef map< int, SocketStuff* > SocketMap;
|
|
|
|
|
|
|
|
class SocketsIterator {
|
|
|
|
public:
|
|
|
|
SocketsIterator( SocketMap::iterator iter, SocketMap::iterator end,
|
|
|
|
pthread_mutex_t* mutex );
|
|
|
|
~SocketsIterator();
|
|
|
|
int Next();
|
|
|
|
private:
|
|
|
|
SocketMap::iterator m_iter;
|
|
|
|
SocketMap::iterator m_end;
|
|
|
|
pthread_mutex_t* m_mutex; /* locked */
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CRefMgr {
|
|
|
|
/* Maintain access to CookieRef instances, ultimately to ensure that no
|
|
|
|
single instance is being acted on by more than one thread at a time,
|
|
|
|
and that once one is destroyed no additional threads attempt to access
|
|
|
|
it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public:
|
|
|
|
static CRefMgr* Get();
|
|
|
|
|
|
|
|
CRefMgr();
|
|
|
|
~CRefMgr();
|
|
|
|
|
|
|
|
CookieMapIterator GetCookieIterator();
|
|
|
|
|
|
|
|
/* PENDING. These need to go through SafeCref */
|
2005-09-03 08:55:08 +02:00
|
|
|
void CheckHeartbeats( time_t now );
|
2005-09-02 08:35:25 +02:00
|
|
|
void Delete( CookieID id );
|
|
|
|
void Delete( CookieRef* cref );
|
2005-10-01 18:33:45 +02:00
|
|
|
void Delete( const char* connName );
|
2005-09-02 08:35:25 +02:00
|
|
|
CookieID CookieIdForName( const char* name );
|
|
|
|
|
|
|
|
/* For use from ctrl only!!!! */
|
|
|
|
void LockAll() { pthread_rwlock_wrlock( &m_cookieMapRWLock ); }
|
|
|
|
void UnlockAll() { pthread_rwlock_unlock( &m_cookieMapRWLock ); }
|
|
|
|
|
|
|
|
/* Track sockets independent of cookie refs */
|
|
|
|
void Associate( int socket, CookieRef* cref );
|
2005-09-05 17:50:49 +02:00
|
|
|
void Disassociate( int socket, CookieRef* cref );
|
2005-09-02 08:35:25 +02:00
|
|
|
pthread_mutex_t* GetWriteMutexForSocket( int socket );
|
|
|
|
void RemoveSocketRefs( int socket );
|
|
|
|
void PrintSocketInfo( int socket, string& out );
|
|
|
|
SocketsIterator MakeSocketsIterator();
|
|
|
|
|
|
|
|
private:
|
|
|
|
friend class SafeCref;
|
2005-10-02 17:39:38 +02:00
|
|
|
CookieRef* getMakeCookieRef_locked( const char* cORn, int isCookie,
|
|
|
|
HostID hid,
|
|
|
|
int nPlayersH, int nPlayersT );
|
2005-09-02 08:35:25 +02:00
|
|
|
CookieRef* getCookieRef_locked( CookieID cookieID );
|
|
|
|
CookieRef* getCookieRef_locked( int socket );
|
|
|
|
int checkCookieRef_locked( CookieRef* cref );
|
|
|
|
CookieRef* getCookieRef_impl( CookieID cookieID );
|
2005-10-01 18:33:45 +02:00
|
|
|
CookieRef* AddNew( const char* cookie, const char* connName, CookieID id );
|
2005-10-02 17:39:38 +02:00
|
|
|
CookieRef* FindOpenGameFor( const char* cORn, int isCookie,
|
|
|
|
HostID hid, int nPlayersH, int nPlayersT );
|
2005-10-01 18:33:45 +02:00
|
|
|
|
|
|
|
CookieID cookieIDForConnName( const char* connName );
|
|
|
|
CookieID nextCID( const char* connName );
|
|
|
|
|
|
|
|
CookieID m_nextCID;
|
2005-09-02 08:35:25 +02:00
|
|
|
|
|
|
|
int LockCref( CookieRef* cref );
|
|
|
|
void UnlockCref( CookieRef* cref );
|
|
|
|
|
|
|
|
pthread_mutex_t m_guard;
|
|
|
|
map<CookieRef*,pthread_mutex_t*> m_crefMutexes;
|
|
|
|
|
|
|
|
pthread_rwlock_t m_cookieMapRWLock;
|
|
|
|
CookieMap m_cookieMap;
|
|
|
|
|
|
|
|
pthread_mutex_t m_SocketStuffMutex;
|
|
|
|
SocketMap m_SocketStuff;
|
|
|
|
|
|
|
|
friend class CookieMapIterator;
|
|
|
|
}; /* CRefMgr */
|
|
|
|
|
|
|
|
|
|
|
|
class SafeCref {
|
|
|
|
|
|
|
|
/* Stack-based class that keeps more than one thread from accessing a
|
|
|
|
CookieRef instance at a time. */
|
|
|
|
|
|
|
|
public:
|
2005-10-02 17:39:38 +02:00
|
|
|
SafeCref( const char* cookieOrConnName, int cookie, HostID hid,
|
|
|
|
int nPlayersH, int nPlayersT );
|
2005-09-05 17:50:49 +02:00
|
|
|
SafeCref( CookieID cid );
|
2005-09-02 08:35:25 +02:00
|
|
|
SafeCref( int socket );
|
|
|
|
SafeCref( CookieRef* cref );
|
|
|
|
~SafeCref();
|
|
|
|
|
2005-10-01 18:33:45 +02:00
|
|
|
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;
|
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
}
|
2005-10-02 17:39:38 +02:00
|
|
|
int Connect( int socket, HostID srcID, int nPlayersH, int nPlayersT ) {
|
2005-10-01 18:33:45 +02:00
|
|
|
if ( IsValid() ) {
|
2005-10-02 17:39:38 +02:00
|
|
|
m_cref->_Connect( socket, srcID, nPlayersH, nPlayersT );
|
2005-10-01 18:33:45 +02:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
}
|
2005-10-02 17:39:38 +02:00
|
|
|
int Reconnect( int socket, HostID srcID, int nPlayersH, int nPlayersT ) {
|
2005-10-01 18:33:45 +02:00
|
|
|
if ( IsValid() ) {
|
2005-10-02 17:39:38 +02:00
|
|
|
m_cref->_Reconnect( socket, srcID, nPlayersH, nPlayersT );
|
2005-10-01 18:33:45 +02:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
}
|
2005-09-05 17:50:49 +02:00
|
|
|
void Disconnect(int socket, HostID hostID ) {
|
2005-10-01 18:33:45 +02:00
|
|
|
if ( IsValid() ) {
|
|
|
|
m_cref->_Disconnect( socket, hostID );
|
|
|
|
}
|
2005-09-05 17:50:49 +02:00
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
void Remove( int socket ) {
|
2005-10-01 18:33:45 +02:00
|
|
|
if ( IsValid() ) {
|
|
|
|
m_cref->_Remove( socket );
|
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
}
|
2005-10-01 18:33:45 +02:00
|
|
|
int HandleHeartbeat( HostID id, int socket ) {
|
|
|
|
if ( IsValid() ) {
|
|
|
|
m_cref->_HandleHeartbeat( id, socket );
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
}
|
2005-09-03 08:55:08 +02:00
|
|
|
void CheckHeartbeats( time_t now ) {
|
2005-10-01 18:33:45 +02:00
|
|
|
if ( IsValid() ) {
|
|
|
|
m_cref->_CheckHeartbeats( now );
|
|
|
|
}
|
2005-09-03 08:55:08 +02:00
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
void PrintCookieInfo( string& out ) {
|
2005-10-01 18:33:45 +02:00
|
|
|
if ( IsValid() ) {
|
|
|
|
m_cref->_PrintCookieInfo( out );
|
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
}
|
|
|
|
void CheckAllConnected() {
|
2005-10-01 18:33:45 +02:00
|
|
|
if ( IsValid() ) {
|
|
|
|
m_cref->_CheckAllConnected();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const char* Name() {
|
|
|
|
if ( IsValid() ) {
|
|
|
|
return m_cref->Name();
|
|
|
|
} else {
|
|
|
|
return ""; /* so don't crash.... */
|
|
|
|
}
|
2005-09-02 08:35:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
2005-10-01 18:33:45 +02:00
|
|
|
int IsValid() { return m_cref != NULL; }
|
|
|
|
|
2005-09-02 08:35:25 +02:00
|
|
|
CookieRef* m_cref;
|
|
|
|
CRefMgr* m_mgr;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class CookieMapIterator {
|
|
|
|
public:
|
|
|
|
CookieMapIterator();
|
|
|
|
~CookieMapIterator() {}
|
|
|
|
CookieID Next();
|
|
|
|
private:
|
|
|
|
CookieMap::const_iterator _iter;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|