xwords/xwords4/relay/lstnrmgr.cpp
ehouse 25c4368231 Start adding ability to listen on multiple sockets and to dynamically
change the set listened on.  There's still some debugging to do but
nothing that worked before is broken.  Also begin to accept unique
prefixes (e.g. g for get) for commands and attributes on the control
port.  Note that relay-related code in comms seems broken now, but is
without this checkin.
2007-12-01 15:00:30 +00:00

203 lines
5.2 KiB
C++

/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
/*
* Copyright 2007 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 <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h>
#include "lstnrmgr.h"
#include "mlock.h"
bool
ListenerMgr::AddListener( int port )
{
logf( XW_LOGINFO, "%s(%d)", __func__, port );
MutexLock ml( &m_mutex );
return addOne( port );
}
void
ListenerMgr::SetAll( const vector<int>* ivp )
{
logf( XW_LOGINFO, "%s", __func__ );
MutexLock ml( &m_mutex );
vector<int> have;
map<int,int>::iterator iter2 = m_socks_to_ports.begin();
while ( iter2 != m_socks_to_ports.end() ) {
have.push_back(iter2->second);
++iter2;
}
std::sort(have.begin(), have.end());
vector<int> want = *ivp;
std::sort(want.begin(), want.end());
/* Now go through both lists in order, removing and adding as
appropriate. */
size_t iWant = 0;
size_t iHave = 0;
while ( (iHave < have.size()) || (iWant < want.size()) ) {
assert( iHave <= have.size() && iWant <= want.size() );
while( (iWant < want.size())
&& ((iHave == have.size() || want[iWant] < have[iHave])) ) {
addOne( want[iWant] );
++iWant;
}
while ( (iHave < have.size())
&& (iWant == want.size() || (have[iHave] < want[iWant])) ) {
removePort( have[iHave] );
++iHave;
}
while ( (iHave < have.size()) && (iWant < want.size())
&& (have[iHave] == want[iWant]) ) {
/* keep both */
++iWant; ++iHave;
}
}
} /* SetAll */
/* void */
/* ListenerMgr::RemoveListener( int listener ) */
/* { */
/* MutexLock ml( &m_mutex ); */
/* removeFD( listener ); */
/* } */
void
ListenerMgr::RemoveAll()
{
MutexLock ml( &m_mutex );
for ( ; ; ) {
map<int,int>::const_iterator iter = m_socks_to_ports.begin();
if ( iter == m_socks_to_ports.end() ) {
break;
}
removeSocket( iter->first );
}
}
void
ListenerMgr::AddToFDSet( fd_set* rfds )
{
MutexLock ml( &m_mutex );
map<int,int>::const_iterator iter = m_socks_to_ports.begin();
while ( iter != m_socks_to_ports.end() ) {
FD_SET( iter->first, rfds );
++iter;
}
}
int
ListenerMgr::GetHighest()
{
int highest = 0;
MutexLock ml( &m_mutex );
map<int,int>::const_iterator iter = m_socks_to_ports.begin();
while ( iter != m_socks_to_ports.end() ) {
if ( iter->first > highest ) {
highest = iter->first;
}
++iter;
}
return highest;
}
bool
ListenerMgr::PortInUse( int port )
{
MutexLock ml( &m_mutex );
return portInUse( port );
}
void
ListenerMgr::removeSocket( int sock )
{
/* Assumption: we have the mutex! */
logf( XW_LOGINFO, "%s(%d)", __func__, sock );
map<int,int>::iterator iter = m_socks_to_ports.find( sock );
assert( iter != m_socks_to_ports.end() );
m_socks_to_ports.erase(iter);
close(sock);
}
void
ListenerMgr::removePort( int port )
{
/* Assumption: we have the mutex! */
logf( XW_LOGINFO, "%s(%d)", __func__, port );
map<int,int>::iterator iter = m_socks_to_ports.begin();
while ( iter != m_socks_to_ports.end() ) {
if ( iter->second == port ) {
int sock = iter->first;
close(sock);
m_socks_to_ports.erase(iter);
break;
}
++iter;
}
assert( iter != m_socks_to_ports.end() ); /* we must have found it! */
}
bool
ListenerMgr::addOne( int port )
{
logf( XW_LOGINFO, "%s(%d)", __func__, port );
/* Assumption: we have the mutex! */
assert( !portInUse(port) );
bool success = false;
int sock = make_socket( INADDR_ANY, port );
success = sock != -1;
if ( success ) {
m_socks_to_ports.insert( pair<int,int>(sock, port) );
}
return success;
}
bool
ListenerMgr::portInUse( int port )
{
/* Assumption: we have the mutex! */
bool found = false;
map<int,int>::const_iterator iter = m_socks_to_ports.begin();
while ( iter != m_socks_to_ports.end() ) {
if ( iter->second == port ) {
found = true;
break;
}
++iter;
}
return found;
}
int
ListenersIter::next()
{
int result = -1;
if ( m_iter != m_lm->m_socks_to_ports.end() ) {
result = m_fds? m_iter->first : m_iter->second;
++m_iter;
}
/* logf( XW_LOGINFO, "%s=>%d", __func__, result ); */
return result;
}