barrier/src/lib/ipc/IpcServer.cpp

175 lines
4.3 KiB
C++
Raw Normal View History

2012-06-28 07:29:06 +00:00
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012 Synergy Si Ltd.
2012-06-28 07:29:06 +00:00
* Copyright (C) 2012 Nick Bolton
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
2012-06-28 07:29:06 +00:00
*
* This package 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, see <http://www.gnu.org/licenses/>.
*/
#include "ipc/IpcServer.h"
#include "ipc/Ipc.h"
#include "ipc/IpcClientProxy.h"
#include "ipc/IpcMessage.h"
#include "net/IDataSocket.h"
#include "io/IStream.h"
#include "base/IEventQueue.h"
#include "base/TMethodEventJob.h"
#include "base/Event.h"
#include "base/Log.h"
2012-07-01 21:18:21 +00:00
//
2014-11-11 13:51:47 +00:00
// IpcServer
//
2014-11-11 13:51:47 +00:00
IpcServer::IpcServer(IEventQueue* events, SocketMultiplexer* socketMultiplexer) :
m_socket(events, socketMultiplexer),
2014-11-11 13:51:47 +00:00
m_address(NetworkAddress(IPC_HOST, IPC_PORT)),
2014-02-25 15:03:43 +00:00
m_events(events)
{
init();
}
2014-11-11 13:51:47 +00:00
IpcServer::IpcServer(IEventQueue* events, SocketMultiplexer* socketMultiplexer, int port) :
m_socket(events, socketMultiplexer),
2014-11-11 13:51:47 +00:00
m_address(NetworkAddress(IPC_HOST, port)),
2014-02-25 15:03:43 +00:00
m_events(events)
{
init();
}
void
2014-11-11 13:51:47 +00:00
IpcServer::init()
2012-06-28 07:29:06 +00:00
{
m_clientsMutex = ARCH->newMutex();
m_address.resolve();
2012-07-01 21:18:21 +00:00
m_events->adoptHandler(
m_events->forIListenSocket().connecting(), &m_socket,
2014-11-11 13:51:47 +00:00
new TMethodEventJob<IpcServer>(
this, &IpcServer::handleClientConnecting));
2012-06-28 07:29:06 +00:00
}
2014-11-11 13:51:47 +00:00
IpcServer::~IpcServer()
2012-06-28 07:29:06 +00:00
{
ARCH->lockMutex(m_clientsMutex);
2014-11-11 13:51:47 +00:00
ClientList::iterator it;
for (it = m_clients.begin(); it != m_clients.end(); it++) {
deleteClient(*it);
}
m_clients.empty();
ARCH->unlockMutex(m_clientsMutex);
ARCH->closeMutex(m_clientsMutex);
m_events->removeHandler(m_events->forIListenSocket().connecting(), &m_socket);
2012-06-28 07:29:06 +00:00
}
void
2014-11-11 13:51:47 +00:00
IpcServer::listen()
2012-06-28 07:29:06 +00:00
{
m_socket.bind(m_address);
2012-06-28 07:29:06 +00:00
}
2012-07-01 21:18:21 +00:00
void
2014-11-11 13:51:47 +00:00
IpcServer::handleClientConnecting(const Event&, void*)
2012-07-01 21:18:21 +00:00
{
synergy::IStream* stream = m_socket.accept();
2012-07-01 21:18:21 +00:00
if (stream == NULL) {
return;
}
LOG((CLOG_DEBUG "accepted ipc client connection"));
ARCH->lockMutex(m_clientsMutex);
2014-11-11 13:51:47 +00:00
IpcClientProxy* proxy = new IpcClientProxy(*stream, m_events);
m_clients.push_back(proxy);
ARCH->unlockMutex(m_clientsMutex);
2012-07-01 21:18:21 +00:00
m_events->adoptHandler(
2014-11-11 13:51:47 +00:00
m_events->forIpcClientProxy().disconnected(), proxy,
new TMethodEventJob<IpcServer>(
this, &IpcServer::handleClientDisconnected));
m_events->adoptHandler(
2014-11-11 13:51:47 +00:00
m_events->forIpcClientProxy().messageReceived(), proxy,
new TMethodEventJob<IpcServer>(
this, &IpcServer::handleMessageReceived));
2014-11-11 13:51:47 +00:00
m_events->addEvent(Event(
m_events->forIpcServer().clientConnected(), this, proxy, Event::kDontFreeData));
}
void
2014-11-11 13:51:47 +00:00
IpcServer::handleClientDisconnected(const Event& e, void*)
{
2014-11-11 13:51:47 +00:00
IpcClientProxy* proxy = static_cast<IpcClientProxy*>(e.getTarget());
2014-11-11 13:51:47 +00:00
ArchMutexLock lock(m_clientsMutex);
m_clients.remove(proxy);
deleteClient(proxy);
LOG((CLOG_DEBUG "ipc client proxy removed, connected=%d", m_clients.size()));
}
void
2014-11-11 13:51:47 +00:00
IpcServer::handleMessageReceived(const Event& e, void*)
{
2014-11-11 13:51:47 +00:00
Event event(m_events->forIpcServer().messageReceived(), this);
event.setDataObject(e.getDataObject());
m_events->addEvent(event);
}
void
2014-11-11 13:51:47 +00:00
IpcServer::deleteClient(IpcClientProxy* proxy)
{
2014-11-11 13:51:47 +00:00
m_events->removeHandler(m_events->forIpcClientProxy().messageReceived(), proxy);
m_events->removeHandler(m_events->forIpcClientProxy().disconnected(), proxy);
delete proxy;
}
bool
2014-11-11 13:51:47 +00:00
IpcServer::hasClients(EIpcClientType clientType) const
{
2014-11-11 13:51:47 +00:00
ArchMutexLock lock(m_clientsMutex);
if (m_clients.empty()) {
return false;
}
2014-11-11 13:51:47 +00:00
ClientList::const_iterator it;
for (it = m_clients.begin(); it != m_clients.end(); it++) {
// at least one client is alive and type matches, there are clients.
2014-11-11 13:51:47 +00:00
IpcClientProxy* p = *it;
if (!p->m_disconnecting && p->m_clientType == clientType) {
return true;
}
}
// all clients must be disconnecting, no active clients.
return false;
2012-07-01 21:18:21 +00:00
}
2012-07-02 15:28:23 +00:00
void
2014-11-11 13:51:47 +00:00
IpcServer::send(const IpcMessage& message, EIpcClientType filterType)
2012-07-02 15:28:23 +00:00
{
2014-11-11 13:51:47 +00:00
ArchMutexLock lock(m_clientsMutex);
2014-11-11 13:51:47 +00:00
ClientList::iterator it;
2012-07-02 15:28:23 +00:00
for (it = m_clients.begin(); it != m_clients.end(); it++) {
2014-11-11 13:51:47 +00:00
IpcClientProxy* proxy = *it;
if (proxy->m_clientType == filterType) {
proxy->send(message);
}
2012-07-02 15:28:23 +00:00
}
}