2012-06-28 07:29:06 +00:00
|
|
|
/*
|
|
|
|
* synergy -- mouse and keyboard sharing utility
|
2012-09-04 02:09:56 +00:00
|
|
|
* Copyright (C) 2012 Bolton Software 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 COPYING that should have accompanied this file.
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2014-02-28 12:36:45 +00:00
|
|
|
#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
|
|
|
|
2013-06-29 14:17:49 +00:00
|
|
|
//
|
|
|
|
// CIpcServer
|
|
|
|
//
|
|
|
|
|
2013-07-16 19:02:30 +00:00
|
|
|
CIpcServer::CIpcServer(IEventQueue* events, CSocketMultiplexer* socketMultiplexer) :
|
|
|
|
m_socket(events, socketMultiplexer),
|
2014-02-25 15:03:43 +00:00
|
|
|
m_address(CNetworkAddress(IPC_HOST, IPC_PORT)),
|
|
|
|
m_events(events)
|
2012-07-11 12:07:13 +00:00
|
|
|
{
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
2013-07-16 19:02:30 +00:00
|
|
|
CIpcServer::CIpcServer(IEventQueue* events, CSocketMultiplexer* socketMultiplexer, int port) :
|
|
|
|
m_socket(events, socketMultiplexer),
|
2014-02-25 15:03:43 +00:00
|
|
|
m_address(CNetworkAddress(IPC_HOST, port)),
|
|
|
|
m_events(events)
|
2012-07-11 12:07:13 +00:00
|
|
|
{
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CIpcServer::init()
|
2012-06-28 07:29:06 +00:00
|
|
|
{
|
2012-07-08 17:49:45 +00:00
|
|
|
m_clientsMutex = ARCH->newMutex();
|
2012-06-29 11:33:21 +00:00
|
|
|
m_address.resolve();
|
2012-07-01 21:18:21 +00:00
|
|
|
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->adoptHandler(
|
|
|
|
m_events->forIListenSocket().connecting(), &m_socket,
|
2012-07-01 21:18:21 +00:00
|
|
|
new TMethodEventJob<CIpcServer>(
|
2012-07-02 13:45:52 +00:00
|
|
|
this, &CIpcServer::handleClientConnecting));
|
2012-06-28 07:29:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CIpcServer::~CIpcServer()
|
|
|
|
{
|
2012-07-08 17:49:45 +00:00
|
|
|
ARCH->lockMutex(m_clientsMutex);
|
|
|
|
CClientList::iterator it;
|
2012-07-05 18:05:35 +00:00
|
|
|
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
2012-07-10 01:51:51 +00:00
|
|
|
deleteClient(*it);
|
2012-07-05 18:05:35 +00:00
|
|
|
}
|
2012-07-05 19:10:04 +00:00
|
|
|
m_clients.empty();
|
2012-07-08 17:49:45 +00:00
|
|
|
ARCH->unlockMutex(m_clientsMutex);
|
|
|
|
ARCH->closeMutex(m_clientsMutex);
|
2012-07-10 01:51:51 +00:00
|
|
|
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->removeHandler(m_events->forIListenSocket().connecting(), &m_socket);
|
2012-06-28 07:29:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CIpcServer::listen()
|
|
|
|
{
|
2012-06-29 11:33:21 +00:00
|
|
|
m_socket.bind(m_address);
|
2012-06-28 07:29:06 +00:00
|
|
|
}
|
2012-07-01 21:18:21 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
CIpcServer::handleClientConnecting(const CEvent&, void*)
|
|
|
|
{
|
2012-07-05 18:05:35 +00:00
|
|
|
synergy::IStream* stream = m_socket.accept();
|
2012-07-01 21:18:21 +00:00
|
|
|
if (stream == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2012-07-05 18:05:35 +00:00
|
|
|
|
2012-07-05 21:26:41 +00:00
|
|
|
LOG((CLOG_DEBUG "accepted ipc client connection"));
|
2012-07-08 17:49:45 +00:00
|
|
|
|
|
|
|
ARCH->lockMutex(m_clientsMutex);
|
2013-06-29 14:17:49 +00:00
|
|
|
CIpcClientProxy* proxy = new CIpcClientProxy(*stream, m_events);
|
2012-07-08 17:49:45 +00:00
|
|
|
m_clients.push_back(proxy);
|
|
|
|
ARCH->unlockMutex(m_clientsMutex);
|
2012-07-01 21:18:21 +00:00
|
|
|
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->adoptHandler(
|
|
|
|
m_events->forCIpcClientProxy().disconnected(), proxy,
|
2012-07-06 12:27:22 +00:00
|
|
|
new TMethodEventJob<CIpcServer>(
|
|
|
|
this, &CIpcServer::handleClientDisconnected));
|
|
|
|
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->adoptHandler(
|
|
|
|
m_events->forCIpcClientProxy().messageReceived(), proxy,
|
2012-07-10 01:51:51 +00:00
|
|
|
new TMethodEventJob<CIpcServer>(
|
|
|
|
this, &CIpcServer::handleMessageReceived));
|
|
|
|
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->addEvent(CEvent(
|
|
|
|
m_events->forCIpcServer().clientConnected(), this, proxy, CEvent::kDontFreeData));
|
2012-07-06 12:27:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CIpcServer::handleClientDisconnected(const CEvent& e, void*)
|
|
|
|
{
|
|
|
|
CIpcClientProxy* proxy = static_cast<CIpcClientProxy*>(e.getTarget());
|
|
|
|
|
2012-07-08 17:49:45 +00:00
|
|
|
CArchMutexLock lock(m_clientsMutex);
|
|
|
|
m_clients.remove(proxy);
|
2012-07-10 01:51:51 +00:00
|
|
|
deleteClient(proxy);
|
|
|
|
|
2012-07-06 12:27:22 +00:00
|
|
|
LOG((CLOG_DEBUG "ipc client proxy removed, connected=%d", m_clients.size()));
|
|
|
|
}
|
|
|
|
|
2012-07-10 01:51:51 +00:00
|
|
|
void
|
|
|
|
CIpcServer::handleMessageReceived(const CEvent& e, void*)
|
|
|
|
{
|
2013-06-29 14:17:49 +00:00
|
|
|
CEvent event(m_events->forCIpcServer().messageReceived(), this);
|
2012-07-10 01:51:51 +00:00
|
|
|
event.setDataObject(e.getDataObject());
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->addEvent(event);
|
2012-07-10 01:51:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CIpcServer::deleteClient(CIpcClientProxy* proxy)
|
|
|
|
{
|
2013-06-29 14:17:49 +00:00
|
|
|
m_events->removeHandler(m_events->forCIpcClientProxy().messageReceived(), proxy);
|
|
|
|
m_events->removeHandler(m_events->forCIpcClientProxy().disconnected(), proxy);
|
2012-07-10 01:51:51 +00:00
|
|
|
delete proxy;
|
|
|
|
}
|
|
|
|
|
2012-07-06 12:27:22 +00:00
|
|
|
bool
|
|
|
|
CIpcServer::hasClients(EIpcClientType clientType) const
|
|
|
|
{
|
2012-07-08 17:49:45 +00:00
|
|
|
CArchMutexLock lock(m_clientsMutex);
|
|
|
|
|
|
|
|
if (m_clients.empty()) {
|
2012-07-06 12:27:22 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-07-08 17:49:45 +00:00
|
|
|
CClientList::const_iterator it;
|
2012-07-06 12:27:22 +00:00
|
|
|
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
|
|
|
// at least one client is alive and type matches, there are clients.
|
|
|
|
CIpcClientProxy* 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
|
2012-07-05 18:05:35 +00:00
|
|
|
CIpcServer::send(const CIpcMessage& message, EIpcClientType filterType)
|
2012-07-02 15:28:23 +00:00
|
|
|
{
|
2012-07-08 17:49:45 +00:00
|
|
|
CArchMutexLock lock(m_clientsMutex);
|
|
|
|
|
|
|
|
CClientList::iterator it;
|
2012-07-02 15:28:23 +00:00
|
|
|
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
2012-07-05 18:05:35 +00:00
|
|
|
CIpcClientProxy* proxy = *it;
|
|
|
|
if (proxy->m_clientType == filterType) {
|
|
|
|
proxy->send(message);
|
|
|
|
}
|
2012-07-02 15:28:23 +00:00
|
|
|
}
|
|
|
|
}
|