moved stream into synergy namespace (to prevent naming collision in win libs)

implemented ipc "hello" message (to identify client type)
integ tests working for hello message, but use of ipc in main program has problem with events.
This commit is contained in:
Nick Bolton 2012-07-05 18:05:35 +00:00
parent 4e268760b3
commit 3d6551f708
57 changed files with 367 additions and 173 deletions

View File

@ -41,6 +41,7 @@ set(inc
../../lib/client
../../lib/common
../../lib/io
../../lib/ipc
../../lib/mt
../../lib/net
../../lib/platform
@ -60,7 +61,7 @@ endif()
include_directories(${inc})
add_executable(synergyc ${src})
target_link_libraries(synergyc
arch base client common io mt net platform server synergy ${libs})
arch base client common io mt net ipc platform server synergy ${libs})
if (CONF_CPACK)
install(TARGETS

View File

@ -40,6 +40,7 @@ set(inc
../../lib/base
../../lib/common
../../lib/io
../../lib/ipc
../../lib/mt
../../lib/net
../../lib/platform
@ -60,7 +61,7 @@ endif()
include_directories(${inc})
add_executable(synergys ${src})
target_link_libraries(synergys
arch base client common io mt net platform server synergy ${libs})
arch base client common io mt net ipc platform server synergy ${libs})
if (CONF_CPACK)
install(TARGETS

View File

@ -25,6 +25,7 @@ IpcClient::IpcClient()
{
m_Socket = new QTcpSocket(this);
connect(m_Socket, SIGNAL(readyRead()), this, SLOT(read()));
connect(m_Socket, SIGNAL(connected()), this, SLOT(connected()));
connect(m_Socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError)));
}
@ -32,6 +33,15 @@ IpcClient::~IpcClient()
{
}
void IpcClient::connected()
{
infoMessage("connected to background service");
char typeBuf[1];
typeBuf[0] = kIpcClientGui;
write(kIpcHello, 1, typeBuf);
}
void IpcClient::connectToHost()
{
infoMessage("connecting to background service...");
@ -52,6 +62,7 @@ void IpcClient::read()
char lenBuf[2];
stream.readRawData(lenBuf, 2);
int len = bytesToInt(lenBuf, 2);
std::cout << "len: " << len << std::endl;
char* data = new char[len];
stream.readRawData(data, len);

View File

@ -42,6 +42,7 @@ private:
void intToBytes(int value, char* buffer, int size);
private slots:
void connected();
void read();
void error(QAbstractSocket::SocketError error);
@ -54,7 +55,15 @@ private:
QTcpSocket* m_Socket;
};
enum EIpcMessage {
enum IpcMessageType {
kIpcHello,
kIpcLogLine,
kIpcCommand
kIpcCommand,
kIpcShutdown,
};
enum IpcClientType {
kIpcClientUnknown,
kIpcClientGui,
kIpcClientNode,
};

View File

@ -369,6 +369,11 @@ void MainWindow::startSynergy()
{
setSynergyProcess(new QProcess(this));
}
else
{
// tell client/server to talk to daemon through ipc.
args << "--ipc";
}
if ((synergyType() == synergyClient && !clientArgs(args, app))
|| (synergyType() == synergyServer && !serverArgs(args, app)))

View File

@ -28,7 +28,7 @@ class CScreen;
class CServerProxy;
class IDataSocket;
class ISocketFactory;
class IStream;
namespace synergy { class IStream; }
class IStreamFilterFactory;
class IEventQueue;
@ -195,7 +195,7 @@ private:
ISocketFactory* m_socketFactory;
IStreamFilterFactory* m_streamFilterFactory;
CScreen* m_screen;
IStream* m_stream;
synergy::IStream* m_stream;
CEventQueueTimer* m_timer;
CServerProxy* m_server;
bool m_ready;

View File

@ -33,7 +33,7 @@
// CServerProxy
//
CServerProxy::CServerProxy(CClient* client, IStream* stream, IEventQueue& eventQueue) :
CServerProxy::CServerProxy(CClient* client, synergy::IStream* stream, IEventQueue& eventQueue) :
m_client(client),
m_stream(stream),
m_seqNum(0),

View File

@ -27,7 +27,7 @@ class CClient;
class CClientInfo;
class CEventQueueTimer;
class IClipboard;
class IStream;
namespace synergy { class IStream; }
class IEventQueue;
//! Proxy for server
@ -41,7 +41,7 @@ public:
Process messages from the server on \p stream and forward to
\p client.
*/
CServerProxy(CClient* client, IStream* stream, IEventQueue& eventQueue);
CServerProxy(CClient* client, synergy::IStream* stream, IEventQueue& eventQueue);
~CServerProxy();
//! @name manipulators
@ -104,7 +104,7 @@ private:
typedef EResult (CServerProxy::*MessageParser)(const UInt8*);
CClient* m_client;
IStream* m_stream;
synergy::IStream* m_stream;
UInt32 m_seqNum;

View File

@ -23,7 +23,7 @@
// CStreamFilter
//
CStreamFilter::CStreamFilter(IStream* stream, bool adoptStream) :
CStreamFilter::CStreamFilter(synergy::IStream* stream, bool adoptStream) :
m_stream(stream),
m_adopted(adoptStream)
{
@ -96,7 +96,7 @@ CStreamFilter::getSize() const
return getStream()->getSize();
}
IStream*
synergy::IStream*
CStreamFilter::getStream() const
{
return m_stream;

View File

@ -25,14 +25,14 @@
This class wraps a stream. Subclasses provide indirect access
to the wrapped stream, typically performing some filtering.
*/
class CStreamFilter : public IStream {
class CStreamFilter : public synergy::IStream {
public:
/*!
Create a wrapper around \c stream. Iff \c adoptStream is true then
this object takes ownership of the stream and will delete it in the
d'tor.
*/
CStreamFilter(IStream* stream, bool adoptStream = true);
CStreamFilter(synergy::IStream* stream, bool adoptStream = true);
~CStreamFilter();
// IStream overrides
@ -53,7 +53,7 @@ protected:
/*!
Returns the stream passed to the c'tor.
*/
IStream* getStream() const;
synergy::IStream* getStream() const;
//! Handle events from source stream
/*!
@ -66,7 +66,7 @@ private:
void handleUpstreamEvent(const CEvent&, void*);
private:
IStream* m_stream;
synergy::IStream* m_stream;
bool m_adopted;
};

View File

@ -18,6 +18,8 @@
#include "IStream.h"
#include "CEventQueue.h"
using namespace synergy;
//
// IStream
//

View File

@ -24,6 +24,8 @@
class IEventQueue;
namespace synergy {
//! Bidirectional stream interface
/*!
Defines the interface for all streams.
@ -165,4 +167,6 @@ private:
static CEvent::Type s_outputShutdownEvent;
};
}
#endif

View File

@ -20,7 +20,8 @@
#include "IInterface.h"
class IStream;
using namespace synergy;
namespace synergy { class IStream; }
//! Stream filter factory interface
/*!
@ -33,7 +34,7 @@ public:
Create and return a stream filter on \p stream. The caller must
delete the returned object.
*/
virtual IStream* create(IStream* stream, bool adoptStream) = 0;
virtual synergy::IStream* create(IStream* stream, bool adoptStream) = 0;
};
#endif

View File

@ -18,16 +18,26 @@
#include "CIpcClient.h"
#include "Ipc.h"
#include "CIpcServerProxy.h"
#include "TMethodEventJob.h"
#include "CIpcMessage.h"
CEvent::Type CIpcClient::s_connectedEvent = CEvent::kUnknown;
CIpcClient::CIpcClient() :
m_serverAddress(CNetworkAddress(IPC_HOST, IPC_PORT)),
m_server(nullptr)
{
m_serverAddress.resolve();
EVENTQUEUE->adoptHandler(
m_socket.getConnectedEvent(), &m_socket,
new TMethodEventJob<CIpcClient>(
this, &CIpcClient::handleConnected));
}
CIpcClient::~CIpcClient()
{
delete m_server;
}
void
@ -43,3 +53,21 @@ CIpcClient::send(const CIpcMessage& message)
assert(m_server != NULL);
m_server->send(message);
}
CEvent::Type
CIpcClient::getConnectedEvent()
{
return EVENTQUEUE->registerTypeOnce(
s_connectedEvent, "CIpcClient::connected");
}
void
CIpcClient::handleConnected(const CEvent&, void*)
{
EVENTQUEUE->addEvent(CEvent(getConnectedEvent(), this, m_server, CEvent::kDontFreeData));
CIpcMessage message;
message.m_type = kIpcHello;
message.m_data = new UInt8(kIpcClientNode);
send(message);
}

View File

@ -32,14 +32,31 @@ public:
CIpcClient();
virtual ~CIpcClient();
//! @name manipulators
//@{
//! Connects to the IPC server at localhost.
void connect();
//! Sends a message to the server.
void send(const CIpcMessage& message);
//@}
//! @name accessors
//@{
//! Raised when the socket is connected.
static CEvent::Type getConnectedEvent();
//@}
private:
CNetworkAddress m_serverAddress;
CTCPSocket m_socket;
CIpcServerProxy* m_server;
void handleConnected(const CEvent&, void*);
private:
CNetworkAddress m_serverAddress;
CTCPSocket m_socket;
CIpcServerProxy* m_server;
static CEvent::Type s_connectedEvent;
};

View File

@ -25,20 +25,23 @@
CEvent::Type CIpcClientProxy::s_messageReceivedEvent = CEvent::kUnknown;
CIpcClientProxy::CIpcClientProxy(IStream& stream) :
CIpcClientProxy::CIpcClientProxy(synergy::IStream& stream) :
m_stream(stream),
m_enableLog(false)
m_enableLog(false),
m_clientType(kIpcClientUnknown)
{
EVENTQUEUE->adoptHandler(m_stream.getInputReadyEvent(),
stream.getEventTarget(),
EVENTQUEUE->adoptHandler(
m_stream.getInputReadyEvent(), stream.getEventTarget(),
new TMethodEventJob<CIpcClientProxy>(
this, &CIpcClientProxy::handleData, nullptr));
}
CIpcClientProxy::~CIpcClientProxy()
{
EVENTQUEUE->removeHandler(m_stream.getInputReadyEvent(),
m_stream.getEventTarget());
EVENTQUEUE->removeHandler(
m_stream.getInputReadyEvent(), m_stream.getEventTarget());
m_stream.close();
}
void
@ -57,6 +60,10 @@ CIpcClientProxy::handleData(const CEvent&, void*)
}
switch (type) {
case kIpcHello:
parseHello();
break;
case kIpcCommand:
m->m_data = parseCommand();
break;
@ -87,14 +94,18 @@ CIpcClientProxy::send(const CIpcMessage& message)
switch (message.m_type) {
case kIpcLogLine: {
CString* s = (CString*)message.m_data;
const char* data = s->c_str();
int len = strlen(data);
CProtocolUtil::writef(&m_stream, "%2i", len);
CString* s = (CString*)message.m_data;
const char* data = s->c_str();
int len = strlen(data);
CProtocolUtil::writef(&m_stream, "%2i", len);
m_stream.write(data, len);
}
m_stream.write(data, len);
break;
}
case kIpcShutdown:
// no data.
break;
default:
@ -105,6 +116,14 @@ CIpcClientProxy::send(const CIpcMessage& message)
}
}
void
CIpcClientProxy::parseHello()
{
UInt8 buffer[1];
m_stream.read(buffer, 1);
m_clientType = static_cast<EIpcClientType>(buffer[0]);
}
void*
CIpcClientProxy::parseCommand()
{
@ -114,6 +133,7 @@ CIpcClientProxy::parseCommand()
UInt8* buffer = new UInt8[len];
m_stream.read(buffer, len);
// delete by event cleanup.
return new CString((const char*)buffer, len);
}

View File

@ -18,29 +18,32 @@
#pragma once
#include "CEvent.h"
#include "Ipc.h"
class IStream;
namespace synergy { class IStream; }
class CIpcMessage;
class CIpcClientProxy {
public:
CIpcClientProxy(IStream& stream);
CIpcClientProxy(synergy::IStream& stream);
virtual ~CIpcClientProxy();
//! Send a message to the client.
void send(const CIpcMessage& message);
void send(const CIpcMessage& message);
//! Raised when the server receives a message from a client.
static CEvent::Type getMessageReceivedEvent();
static CEvent::Type getMessageReceivedEvent();
private:
void handleData(const CEvent&, void*);
void parseHello();
void* parseCommand();
void disconnect();
public:
IStream& m_stream;
synergy::IStream& m_stream;
bool m_enableLog;
EIpcClientType m_clientType;
private:
static CEvent::Type s_messageReceivedEvent;

View File

@ -50,6 +50,6 @@ CIpcLogOutputter::write(ELevel level, const char* msg)
CIpcMessage message;
message.m_type = kIpcLogLine;
message.m_data = new CString(msg);
m_ipcServer.send(message);
m_ipcServer.send(message, kIpcClientGui);
return true;
}

View File

@ -34,14 +34,19 @@ m_address(CNetworkAddress(IPC_HOST, IPC_PORT))
m_address.resolve();
EVENTQUEUE->adoptHandler(
IListenSocket::getConnectingEvent(), &m_socket,
m_socket.getConnectingEvent(), &m_socket,
new TMethodEventJob<CIpcServer>(
this, &CIpcServer::handleClientConnecting));
}
CIpcServer::~CIpcServer()
{
EVENTQUEUE->removeHandler(IListenSocket::getConnectingEvent(), &m_socket);
CClientSet::iterator it;
for (it = m_clients.begin(); it != m_clients.end(); it++) {
delete *it;
}
EVENTQUEUE->removeHandler(m_socket.getConnectingEvent(), &m_socket);
}
void
@ -53,12 +58,11 @@ CIpcServer::listen()
void
CIpcServer::handleClientConnecting(const CEvent&, void*)
{
IStream* stream = m_socket.accept();
synergy::IStream* stream = m_socket.accept();
if (stream == NULL) {
return;
}
// when there is already a client connected, this causes stack overflow,
//
LOG((CLOG_NOTE "accepted ipc client connection"));
// TODO: delete on disconnect
@ -76,10 +80,13 @@ CIpcServer::getClientConnectedEvent()
}
void
CIpcServer::send(const CIpcMessage& message)
CIpcServer::send(const CIpcMessage& message, EIpcClientType filterType)
{
CClientSet::iterator it;
for (it = m_clients.begin(); it != m_clients.end(); it++) {
(*it)->send(message);
CIpcClientProxy* proxy = *it;
if (proxy->m_clientType == filterType) {
proxy->send(message);
}
}
}

View File

@ -19,6 +19,7 @@
#include "CTCPListenSocket.h"
#include "CNetworkAddress.h"
#include "Ipc.h"
#include <set>
class CEvent;
@ -43,15 +44,15 @@ public:
//! Opens a TCP socket only allowing local connections.
void listen();
//! Send a message to all clients.
void send(const CIpcMessage& message);
//! Send a message to all clients matching the filter type.
void send(const CIpcMessage& message, EIpcClientType filterType);
//@}
//! @name accessors
//@{
//! Raised when we have created the client proxy.
static CEvent::Type getClientConnectedEvent();
static CEvent::Type getClientConnectedEvent();
//@}

View File

@ -25,19 +25,21 @@
CEvent::Type CIpcServerProxy::s_messageReceivedEvent = CEvent::kUnknown;
CIpcServerProxy::CIpcServerProxy(IStream& stream) :
CIpcServerProxy::CIpcServerProxy(synergy::IStream& stream) :
m_stream(stream)
{
EVENTQUEUE->adoptHandler(m_stream.getInputReadyEvent(),
stream.getEventTarget(),
new TMethodEventJob<CIpcServerProxy>(
this, &CIpcServerProxy::handleData, nullptr));
this, &CIpcServerProxy::handleData));
}
CIpcServerProxy::~CIpcServerProxy()
{
EVENTQUEUE->removeHandler(m_stream.getInputReadyEvent(),
m_stream.getEventTarget());
m_stream.close();
}
void
@ -48,13 +50,17 @@ CIpcServerProxy::handleData(const CEvent&, void*)
while (n != 0) {
CIpcMessage* m = new CIpcMessage();
m->m_type = code[1];
m->m_type = code[0];
LOG((CLOG_DEBUG "ipc server proxy read: %d", code[0]));
switch (code[0]) {
LOG((CLOG_DEBUG "ipc server proxy read: %d", m->m_type));
switch (m->m_type) {
case kIpcLogLine:
m->m_data = parseLogLine();
break;
case kIpcShutdown:
// no data.
break;
default:
delete m;
@ -79,17 +85,21 @@ CIpcServerProxy::send(const CIpcMessage& message)
m_stream.write(code, 1);
switch (message.m_type) {
case kIpcCommand: {
CString* s = (CString*)message.m_data;
const char* data = s->c_str();
int len = strlen(data);
CProtocolUtil::writef(&m_stream, "%2i", len);
m_stream.write(data, len);
}
case kIpcHello:
m_stream.write(message.m_data, 1);
break;
case kIpcCommand: {
CString* s = (CString*)message.m_data;
const char* data = s->c_str();
int len = strlen(data);
CProtocolUtil::writef(&m_stream, "%2i", len);
m_stream.write(data, len);
break;
}
default:
LOG((CLOG_ERR "message not supported: %d", message.m_type));
break;

View File

@ -19,12 +19,12 @@
#include "CEvent.h"
class IStream;
namespace synergy { class IStream; }
class CIpcMessage;
class CIpcServerProxy {
public:
CIpcServerProxy(IStream& stream);
CIpcServerProxy(synergy::IStream& stream);
virtual ~CIpcServerProxy();
void send(const CIpcMessage& message);
@ -38,7 +38,7 @@ private:
void disconnect();
private:
IStream& m_stream;
synergy::IStream& m_stream;
static CEvent::Type s_messageReceivedEvent;
};

View File

@ -21,6 +21,14 @@
#define IPC_PORT 24801
enum EIpcMessage {
kIpcHello,
kIpcLogLine,
kIpcCommand
kIpcCommand,
kIpcShutdown,
};
enum EIpcClientType {
kIpcClientUnknown,
kIpcClientGui,
kIpcClientNode,
};

View File

@ -27,7 +27,7 @@
This interface defines the methods common to all network sockets that
represent a full-duplex data stream.
*/
class IDataSocket : public ISocket, public IStream {
class IDataSocket : public ISocket, public synergy::IStream {
public:
class CConnectionFailedInfo {
public:

View File

@ -26,6 +26,9 @@
#include "CApp.h"
#include "CArgsBase.h"
#include "CIpcLogOutputter.h"
#include "CIpcServer.h"
#include "CIpcMessage.h"
#include "Ipc.h"
#include <Tlhelp32.h>
#include <UserEnv.h>
@ -37,14 +40,18 @@ enum {
typedef VOID (WINAPI *SendSas)(BOOL asUser);
CMSWindowsRelauncher::CMSWindowsRelauncher(bool autoDetectCommand) :
CMSWindowsRelauncher::CMSWindowsRelauncher(
bool autoDetectCommand,
CIpcServer& ipcServer,
CIpcLogOutputter& ipcLogOutputter) :
m_thread(NULL),
m_autoDetectCommand(autoDetectCommand),
m_running(true),
m_commandChanged(false),
m_stdOutWrite(NULL),
m_stdOutRead(NULL),
m_ipcLogOutputter(nullptr)
m_ipcServer(ipcServer),
m_ipcLogOutputter(ipcLogOutputter)
{
}
@ -374,7 +381,7 @@ CMSWindowsRelauncher::command() const
// build up a full command line
std::stringstream cmdTemp;
cmdTemp << launchName << /*" --debug-data session-" << sessionId <<*/ args;
cmdTemp << launchName << args;
std::string cmd = cmdTemp.str();
@ -390,7 +397,8 @@ CMSWindowsRelauncher::command() const
void
CMSWindowsRelauncher::outputLoop(void*)
{
CHAR buffer[kOutputBufferSize];
// +1 char for \0
CHAR buffer[kOutputBufferSize + 1];
while (true) {
@ -405,7 +413,7 @@ CMSWindowsRelauncher::outputLoop(void*)
else {
// send process output over IPC to GUI.
buffer[bytesRead] = '\0';
m_ipcLogOutputter->write(kINFO, buffer);
m_ipcLogOutputter.write(kINFO, buffer);
}
}
@ -419,6 +427,10 @@ CMSWindowsRelauncher::shutdownProcess(const PROCESS_INFORMATION& pi, int timeout
if (exitCode != STILL_ACTIVE)
return;
CIpcMessage shutdown;
shutdown.m_type = kIpcShutdown;
m_ipcServer.send(shutdown, kIpcClientNode);
// wait for process to exit gracefully.
double start = ARCH->time();
while (true)
@ -430,12 +442,13 @@ CMSWindowsRelauncher::shutdownProcess(const PROCESS_INFORMATION& pi, int timeout
}
else {
if ((ARCH->time() - start) > timeout) {
double elapsed = (ARCH->time() - start);
if (elapsed > timeout) {
// if timeout reached, kill forcefully.
// calling TerminateProcess on synergy is very bad!
// it causes the hook DLL to stay loaded in some apps,
// making it impossible to start synergy again.
LOG((CLOG_WARN "shutdown timed out after %d secs, forcefully terminating", pi.dwProcessId));
LOG((CLOG_WARN "shutdown timed out after %d secs, forcefully terminating", (int)elapsed));
TerminateProcess(pi.hProcess, kExitSuccess);
break;
}

View File

@ -24,10 +24,14 @@
class CThread;
class CIpcLogOutputter;
class CIpcServer;
class CMSWindowsRelauncher {
public:
CMSWindowsRelauncher(bool autoDetectCommand);
CMSWindowsRelauncher(
bool autoDetectCommand,
CIpcServer& ipcServer,
CIpcLogOutputter& ipcLogOutputter);
virtual ~CMSWindowsRelauncher();
void startAsync();
std::string command() const;
@ -42,9 +46,6 @@ private:
void outputLoop(void*);
void shutdownProcess(const PROCESS_INFORMATION& pi, int timeout);
public:
CIpcLogOutputter* m_ipcLogOutputter;
private:
CThread* m_thread;
bool m_autoDetectCommand;
@ -54,4 +55,6 @@ private:
HANDLE m_stdOutWrite;
HANDLE m_stdOutRead;
CThread* m_outputThread;
CIpcServer& m_ipcServer;
CIpcLogOutputter& m_ipcLogOutputter;
};

View File

@ -138,6 +138,8 @@ set(inc
../mt
../synergy
../ipc
../net
../io
)
if (UNIX)
@ -192,5 +194,5 @@ if (WIN32)
endif()
if (UNIX)
target_link_libraries(platform ipc synergy ${libs})
target_link_libraries(platform io net ipc synergy ${libs})
endif()

View File

@ -66,7 +66,7 @@ CClientListener::CClientListener(const CNetworkAddress& address,
LOG((CLOG_DEBUG1 "listening for clients"));
// setup event handler
EVENTQUEUE->adoptHandler(IListenSocket::getConnectingEvent(), m_listen,
EVENTQUEUE->adoptHandler(m_listen->getConnectingEvent(), m_listen,
new TMethodEventJob<CClientListener>(this,
&CClientListener::handleClientConnecting));
}
@ -95,7 +95,7 @@ CClientListener::~CClientListener()
client = getNextClient();
}
EVENTQUEUE->removeHandler(IListenSocket::getConnectingEvent(), m_listen);
EVENTQUEUE->removeHandler(m_listen->getConnectingEvent(), m_listen);
delete m_listen;
delete m_socketFactory;
delete m_streamFilterFactory;
@ -131,7 +131,7 @@ void
CClientListener::handleClientConnecting(const CEvent&, void*)
{
// accept client connection
IStream* stream = m_listen->accept();
synergy::IStream* stream = m_listen->accept();
if (stream == NULL) {
return;
}

View File

@ -30,7 +30,7 @@ CEvent::Type CClientProxy::s_disconnectedEvent = CEvent::kUnknown;
CEvent::Type CClientProxy::s_clipboardChangedEvent= CEvent::kUnknown;
CEvent::Type CClientProxy::s_gameDeviceTimingRecvEvent= CEvent::kUnknown;
CClientProxy::CClientProxy(const CString& name, IStream* stream) :
CClientProxy::CClientProxy(const CString& name, synergy::IStream* stream) :
CBaseClientProxy(name),
m_stream(stream)
{
@ -52,7 +52,7 @@ CClientProxy::close(const char* msg)
getStream()->flush();
}
IStream*
synergy::IStream*
CClientProxy::getStream() const
{
return m_stream;

View File

@ -22,7 +22,7 @@
#include "CEvent.h"
#include "CString.h"
class IStream;
namespace synergy { class IStream; }
//! Generic proxy for client
class CClientProxy : public CBaseClientProxy {
@ -30,7 +30,7 @@ public:
/*!
\c name is the name of the client.
*/
CClientProxy(const CString& name, IStream* adoptedStream);
CClientProxy(const CString& name, synergy::IStream* adoptedStream);
~CClientProxy();
//! @name manipulators
@ -50,7 +50,7 @@ public:
/*!
Returns the stream passed to the c'tor.
*/
IStream* getStream() const;
synergy::IStream* getStream() const;
//! Get ready event type
/*!
@ -117,7 +117,7 @@ public:
virtual void gameDeviceTimingReq() = 0;
private:
IStream* m_stream;
synergy::IStream* m_stream;
static CEvent::Type s_readyEvent;
static CEvent::Type s_disconnectedEvent;

View File

@ -28,7 +28,7 @@
// CClientProxy1_0
//
CClientProxy1_0::CClientProxy1_0(const CString& name, IStream* stream) :
CClientProxy1_0::CClientProxy1_0(const CString& name, synergy::IStream* stream) :
CClientProxy(name, stream),
m_heartbeatTimer(NULL),
m_parser(&CClientProxy1_0::parseHandshakeMessage)

View File

@ -28,7 +28,7 @@ class CEventQueueTimer;
//! Proxy for client implementing protocol version 1.0
class CClientProxy1_0 : public CClientProxy {
public:
CClientProxy1_0(const CString& name, IStream* adoptedStream);
CClientProxy1_0(const CString& name, synergy::IStream* adoptedStream);
~CClientProxy1_0();
// IScreen

View File

@ -24,7 +24,7 @@
// CClientProxy1_1
//
CClientProxy1_1::CClientProxy1_1(const CString& name, IStream* stream) :
CClientProxy1_1::CClientProxy1_1(const CString& name, synergy::IStream* stream) :
CClientProxy1_0(name, stream)
{
// do nothing

View File

@ -23,7 +23,7 @@
//! Proxy for client implementing protocol version 1.1
class CClientProxy1_1 : public CClientProxy1_0 {
public:
CClientProxy1_1(const CString& name, IStream* adoptedStream);
CClientProxy1_1(const CString& name, synergy::IStream* adoptedStream);
~CClientProxy1_1();
// IClient overrides

View File

@ -23,7 +23,7 @@
// CClientProxy1_1
//
CClientProxy1_2::CClientProxy1_2(const CString& name, IStream* stream) :
CClientProxy1_2::CClientProxy1_2(const CString& name, synergy::IStream* stream) :
CClientProxy1_1(name, stream)
{
// do nothing

View File

@ -23,7 +23,7 @@
//! Proxy for client implementing protocol version 1.2
class CClientProxy1_2 : public CClientProxy1_1 {
public:
CClientProxy1_2(const CString& name, IStream* adoptedStream);
CClientProxy1_2(const CString& name, synergy::IStream* adoptedStream);
~CClientProxy1_2();
// IClient overrides

View File

@ -27,7 +27,7 @@
// CClientProxy1_3
//
CClientProxy1_3::CClientProxy1_3(const CString& name, IStream* stream) :
CClientProxy1_3::CClientProxy1_3(const CString& name, synergy::IStream* stream) :
CClientProxy1_2(name, stream),
m_keepAliveRate(kKeepAliveRate),
m_keepAliveTimer(NULL)

View File

@ -23,7 +23,7 @@
//! Proxy for client implementing protocol version 1.3
class CClientProxy1_3 : public CClientProxy1_2 {
public:
CClientProxy1_3(const CString& name, IStream* adoptedStream);
CClientProxy1_3(const CString& name, synergy::IStream* adoptedStream);
~CClientProxy1_3();
// IClient overrides

View File

@ -28,7 +28,7 @@
// CClientProxy1_4
//
CClientProxy1_4::CClientProxy1_4(const CString& name, IStream* stream, CServer* server) :
CClientProxy1_4::CClientProxy1_4(const CString& name, synergy::IStream* stream, CServer* server) :
CClientProxy1_3(name, stream), m_server(server)
{
assert(m_server != NULL);

View File

@ -25,7 +25,7 @@ class CServer;
//! Proxy for client implementing protocol version 1.4
class CClientProxy1_4 : public CClientProxy1_3 {
public:
CClientProxy1_4(const CString& name, IStream* adoptedStream, CServer* server);
CClientProxy1_4(const CString& name, synergy::IStream* adoptedStream, CServer* server);
~CClientProxy1_4();
// IClient overrides

View File

@ -39,7 +39,7 @@
CEvent::Type CClientProxyUnknown::s_successEvent = CEvent::kUnknown;
CEvent::Type CClientProxyUnknown::s_failureEvent = CEvent::kUnknown;
CClientProxyUnknown::CClientProxyUnknown(IStream* stream, double timeout, CServer* server) :
CClientProxyUnknown::CClientProxyUnknown(synergy::IStream* stream, double timeout, CServer* server) :
m_stream(stream),
m_proxy(NULL),
m_ready(false),

View File

@ -22,12 +22,12 @@
class CClientProxy;
class CEventQueueTimer;
class IStream;
namespace synergy { class IStream; }
class CServer;
class CClientProxyUnknown {
public:
CClientProxyUnknown(IStream* stream, double timeout, CServer* server);
CClientProxyUnknown(synergy::IStream* stream, double timeout, CServer* server);
~CClientProxyUnknown();
//! @name manipulators
@ -75,7 +75,7 @@ private:
void handleReady(const CEvent&, void*);
private:
IStream* m_stream;
synergy::IStream* m_stream;
CEventQueueTimer* m_timer;
CClientProxy* m_proxy;
bool m_ready;

View File

@ -25,6 +25,10 @@
#include "LogOutputters.h"
#include "XSynergy.h"
#include "CArgsBase.h"
#include "CIpcServerProxy.h"
#include "TMethodEventJob.h"
#include "CIpcMessage.h"
#include "Ipc.h"
#if SYSAPI_WIN32
#include "CArchMiscWindows.h"
@ -46,7 +50,8 @@ m_createTaskBarReceiver(createTaskBarReceiver),
m_args(args),
m_bye(&exit),
m_taskBarReceiver(NULL),
m_suspended(false)
m_suspended(false),
m_ipcClient(nullptr)
{
assert(s_instance == nullptr);
s_instance = this;
@ -142,6 +147,10 @@ CApp::parseArg(const int& argc, const char* const* argv, int& i)
argsBase().m_disableTray = true;
}
else if (isArg(i, argc, argv, NULL, "--ipc")) {
argsBase().m_enableIpc = true;
}
#if VNC_SUPPORT
else if (isArg(i, argc, argv, NULL, "--vnc")) {
argsBase().m_enableVnc = true;
@ -335,3 +344,33 @@ CApp::initApp(int argc, const char** argv)
m_taskBarReceiver = m_createTaskBarReceiver(logBuffer);
}
}
void
CApp::initIpcClient()
{
// TODO: delete ipc client on shutdown and the 2 event handlers.
m_ipcClient = new CIpcClient();
m_ipcClient->connect();
EVENTQUEUE->adoptHandler(
CIpcClient::getConnectedEvent(), m_ipcClient,
new TMethodEventJob<CApp>(this, &CApp::handleIpcConnected));
}
void
CApp::handleIpcConnected(const CEvent& e, void*)
{
EVENTQUEUE->adoptHandler(
CIpcServerProxy::getMessageReceivedEvent(), e.getData(),
new TMethodEventJob<CApp>(this, &CApp::handleIpcMessage));
}
void
CApp::handleIpcMessage(const CEvent& e, void*)
{
CIpcMessage* m = static_cast<CIpcMessage*>(e.getData());
if (m->m_type == kIpcShutdown) {
LOG((CLOG_INFO "got ipc shutdown message"));
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
}

View File

@ -20,6 +20,7 @@
#include "common.h"
#include "CString.h"
#include "IApp.h"
#include "CIpcClient.h"
#if SYSAPI_WIN32
#include "CAppUtilWindows.h"
@ -92,9 +93,14 @@ public:
virtual void setByeFunc(void(*bye)(int)) { m_bye = bye; }
virtual void bye(int error) { m_bye(error); }
private:
void handleIpcConnected(const CEvent&, void*);
void handleIpcMessage(const CEvent&, void*);
protected:
virtual void parseArgs(int argc, const char* const* argv, int &i);
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
void initIpcClient();
IArchTaskBarReceiver* m_taskBarReceiver;
bool m_suspended;
@ -105,6 +111,7 @@ private:
CFileLogOutputter* m_fileLog;
CreateTaskBarReceiverFunc m_createTaskBarReceiver;
ARCH_APP_UTIL m_appUtil;
CIpcClient* m_ipcClient;
};
#define BYE "\nTry `%s --help' for more information."

View File

@ -25,7 +25,6 @@
#include "CMSWindowsScreen.h"
#include "XSynergy.h"
#include "IArchTaskBarReceiver.h"
#include "CMSWindowsRelauncher.h"
#include "CScreen.h"
#include "CArgsBase.h"
#include "IEventQueue.h"
@ -214,17 +213,5 @@ CAppUtilWindows::debugServiceWait()
void
CAppUtilWindows::startNode()
{
if (app().argsBase().m_relaunchMode) {
LOG((CLOG_DEBUG1 "entering relaunch mode"));
CMSWindowsRelauncher relauncher(true);
relauncher.startAsync();
// HACK: create a dummy screen, which can handle system events
// (such as a stop request from the service controller).
CScreen* dummyScreen = app().createScreen();
}
else {
app().startNode();
}
app().startNode();
}

View File

@ -21,7 +21,6 @@ CArgsBase::CArgsBase() :
#if SYSAPI_WIN32
m_daemon(false), // daemon mode not supported on windows (use --service)
m_debugServiceWait(false),
m_relaunchMode(false),
m_pauseOnExit(false),
#else
m_daemon(true), // backward compatibility for unix (daemon by default)

View File

@ -35,8 +35,8 @@ public:
CString m_name;
bool m_disableTray;
bool m_enableVnc;
bool m_enableIpc;
#if SYSAPI_WIN32
bool m_relaunchMode;
bool m_debugServiceWait;
bool m_pauseOnExit;
CGameDeviceInfo m_gameDevice;

View File

@ -528,6 +528,10 @@ CClientApp::mainLoop()
// create the event queue
CEventQueue eventQueue;
if (argsBase().m_enableIpc) {
initIpcClient();
}
// start client, etc
appUtil().startNode();

View File

@ -78,7 +78,7 @@ CDaemonApp::CDaemonApp() :
m_ipcServer(nullptr),
m_ipcLogOutputter(nullptr)
#if SYSAPI_WIN32
,m_relauncher(false)
,m_relauncher(nullptr)
#endif
{
s_instance = this;
@ -182,16 +182,20 @@ CDaemonApp::mainLoop(bool logToFile)
// uses event queue, must be created here.
m_ipcServer = new CIpcServer();
// send logging to gui via ipc, log system adopts outputter.
m_ipcLogOutputter = new CIpcLogOutputter(*m_ipcServer);
CLOG->insert(m_ipcLogOutputter);
#if SYSAPI_WIN32
m_relauncher = new CMSWindowsRelauncher(false, *m_ipcServer, *m_ipcLogOutputter);
#endif
eventQueue.adoptHandler(
CIpcServer::getClientConnectedEvent(), m_ipcServer,
new TMethodEventJob<CDaemonApp>(this, &CDaemonApp::handleIpcConnected));
m_ipcServer->listen();
// send logging to gui via ipc, log system adopts outputter.
m_ipcLogOutputter = new CIpcLogOutputter(*m_ipcServer);
CLOG->insert(m_ipcLogOutputter);
#if SYSAPI_WIN32
// HACK: create a dummy screen, which can handle system events
// (such as a stop request from the service controller).
@ -199,21 +203,19 @@ CDaemonApp::mainLoop(bool logToFile)
CGameDeviceInfo gameDevice;
CScreen dummyScreen(new CMSWindowsScreen(false, true, gameDevice));
m_relauncher.m_ipcLogOutputter = m_ipcLogOutputter;
string command = ARCH->setting("Command");
if (command != "") {
LOG((CLOG_INFO "using last known command: %s", command.c_str()));
m_relauncher.command(command);
m_relauncher->command(command);
}
m_relauncher.startAsync();
m_relauncher->startAsync();
#endif
eventQueue.loop();
#if SYSAPI_WIN32
m_relauncher.stop();
m_relauncher->stop();
#endif
eventQueue.removeHandler(
@ -275,13 +277,12 @@ CDaemonApp::handleIpcConnected(const CEvent& e, void*)
void
CDaemonApp::handleIpcMessage(const CEvent& e, void*)
{
CIpcMessage& m = *reinterpret_cast<CIpcMessage*>(e.getData());
CIpcMessage& m = *static_cast<CIpcMessage*>(e.getData());
LOG((CLOG_DEBUG "ipc message, type=%d", m.m_type));
switch (m.m_type) {
case kIpcCommand: {
CString& command = *reinterpret_cast<CString*>(m.m_data);
CString& command = *static_cast<CString*>(m.m_data);
LOG((CLOG_DEBUG "got new command: %s", command.c_str()));
try {
@ -296,7 +297,7 @@ CDaemonApp::handleIpcMessage(const CEvent& e, void*)
// tell the relauncher about the new command. this causes the
// relauncher to stop the existing command and start the new
// command.
m_relauncher.command(command);
m_relauncher->command(command);
}
break;

View File

@ -48,7 +48,8 @@ public:
static CDaemonApp* s_instance;
#if SYSAPI_WIN32
CMSWindowsRelauncher m_relauncher;
CMSWindowsRelauncher*
m_relauncher;
#endif
private:
@ -57,7 +58,3 @@ private:
};
#define LOG_FILENAME "synergyd.log"
enum {
kIpcCommand = 1
};

View File

@ -26,7 +26,7 @@
// CPacketStreamFilter
//
CPacketStreamFilter::CPacketStreamFilter(IStream* stream, bool adoptStream) :
CPacketStreamFilter::CPacketStreamFilter(synergy::IStream* stream, bool adoptStream) :
CStreamFilter(stream, adoptStream),
m_size(0),
m_inputShutdown(false)

View File

@ -28,7 +28,7 @@ Filters a stream to read and write packets.
*/
class CPacketStreamFilter : public CStreamFilter {
public:
CPacketStreamFilter(IStream* stream, bool adoptStream = true);
CPacketStreamFilter(synergy::IStream* stream, bool adoptStream = true);
~CPacketStreamFilter();
// IStream overrides

View File

@ -27,7 +27,7 @@
//
void
CProtocolUtil::writef(IStream* stream, const char* fmt, ...)
CProtocolUtil::writef(synergy::IStream* stream, const char* fmt, ...)
{
assert(stream != NULL);
assert(fmt != NULL);
@ -43,7 +43,7 @@ CProtocolUtil::writef(IStream* stream, const char* fmt, ...)
}
bool
CProtocolUtil::readf(IStream* stream, const char* fmt, ...)
CProtocolUtil::readf(synergy::IStream* stream, const char* fmt, ...)
{
assert(stream != NULL);
assert(fmt != NULL);
@ -64,7 +64,7 @@ CProtocolUtil::readf(IStream* stream, const char* fmt, ...)
}
void
CProtocolUtil::vwritef(IStream* stream,
CProtocolUtil::vwritef(synergy::IStream* stream,
const char* fmt, UInt32 size, va_list args)
{
assert(stream != NULL);
@ -93,7 +93,7 @@ CProtocolUtil::vwritef(IStream* stream,
}
void
CProtocolUtil::vreadf(IStream* stream, const char* fmt, va_list args)
CProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args)
{
assert(stream != NULL);
assert(fmt != NULL);
@ -507,7 +507,7 @@ CProtocolUtil::eatLength(const char** pfmt)
}
void
CProtocolUtil::read(IStream* stream, void* vbuffer, UInt32 count)
CProtocolUtil::read(synergy::IStream* stream, void* vbuffer, UInt32 count)
{
assert(stream != NULL);
assert(vbuffer != NULL);

View File

@ -22,7 +22,7 @@
#include "XIO.h"
#include <stdarg.h>
class IStream;
namespace synergy { class IStream; }
//! Synergy protocol utilities
/*!
@ -49,7 +49,7 @@ public:
- \%s -- converts CString* to stream of bytes
- \%S -- converts integer N and const UInt8* to stream of N bytes
*/
static void writef(IStream*,
static void writef(synergy::IStream*,
const char* fmt, ...);
//! Read formatted data
@ -68,19 +68,19 @@ public:
- \%4I -- reads NBO 4 byte integers; arg is std::vector<UInt32>*
- \%s -- reads bytes; argument must be a CString*, \b not a char*
*/
static bool readf(IStream*,
static bool readf(synergy::IStream*,
const char* fmt, ...);
private:
static void vwritef(IStream*,
static void vwritef(synergy::IStream*,
const char* fmt, UInt32 size, va_list);
static void vreadf(IStream*,
static void vreadf(synergy::IStream*,
const char* fmt, va_list);
static UInt32 getLength(const char* fmt, va_list);
static void writef(void*, const char* fmt, va_list);
static UInt32 eatLength(const char** fmt);
static void read(IStream*, void*, UInt32);
static void read(synergy::IStream*, void*, UInt32);
};
//! Mismatched read exception

View File

@ -760,6 +760,15 @@ CServerApp::mainLoop()
// create the event queue
CEventQueue eventQueue;
/*
bool a = true;
while (a) {
ARCH->sleep(1);
}*/
if (argsBase().m_enableIpc) {
initIpcClient();
}
// if configuration has no screens then add this system
// as the default

View File

@ -59,8 +59,8 @@ public:
bool m_connectToServer_clientConnected;
CString m_sendMessageToServer_receivedString;
CString m_sendMessageToClient_receivedString;
CIpcClient* m_sendMessageToServer_client;
CIpcServer* m_sendMessageToClient_server;
CIpcServerProxy* m_sendMessageToClient_serverProxy;
};
TEST_F(CIpcTests, connectToServer)
@ -89,16 +89,13 @@ TEST_F(CIpcTests, sendMessageToServer)
CIpcClient client;
client.connect();
m_sendMessageToServer_client = &client;
// event handler sends "test" log line to client.
m_events.adoptHandler(
CIpcServer::getClientConnectedEvent(), &server,
new TMethodEventJob<CIpcTests>(
this, &CIpcTests::sendMessageToServer_handleClientConnected));
CIpcMessage m;
m.m_type = kIpcCommand;
m.m_data = (void*)(new CString("test"));
client.send(m);
quitTimeout(2);
m_events.loop();
@ -114,11 +111,10 @@ TEST_F(CIpcTests, sendMessageToClient)
CIpcClient client;
client.connect();
m_sendMessageToClient_serverProxy = client.m_server;
// event handler sends "test" log line to client.
// event handler sends "test" log line to server.
m_events.adoptHandler(
CIpcServer::getClientConnectedEvent(), &server,
CIpcClient::getConnectedEvent(), &client,
new TMethodEventJob<CIpcTests>(
this, &CIpcTests::sendMessageToClient_handleConnected));
@ -131,7 +127,7 @@ TEST_F(CIpcTests, sendMessageToClient)
CIpcTests::CIpcTests() :
m_connectToServer_clientConnected(false),
m_sendMessageToClient_server(nullptr),
m_sendMessageToClient_serverProxy(nullptr)
m_sendMessageToServer_client(nullptr)
{
}
@ -153,36 +149,45 @@ CIpcTests::sendMessageToServer_handleClientConnected(const CEvent& e, void*)
CIpcClientProxy::getMessageReceivedEvent(), e.getData(),
new TMethodEventJob<CIpcTests>(
this, &CIpcTests::sendMessageToServer_handleMessageReceived));
CIpcMessage m;
m.m_type = kIpcCommand;
m.m_data = new CString("test");
m_sendMessageToServer_client->send(m);
}
void
CIpcTests::sendMessageToServer_handleMessageReceived(const CEvent& e, void*)
{
CIpcMessage* m = (CIpcMessage*)e.getData();
m_sendMessageToServer_receivedString = *((CString*)m->m_data);
raiseQuitEvent();
CIpcMessage* m = static_cast<CIpcMessage*>(e.getData());
if (m->m_type == kIpcCommand) {
m_sendMessageToServer_receivedString = *static_cast<CString*>(m->m_data);
raiseQuitEvent();
}
}
void
CIpcTests::sendMessageToClient_handleConnected(const CEvent& e, void*)
{
m_events.adoptHandler(
CIpcServerProxy::getMessageReceivedEvent(), m_sendMessageToClient_serverProxy,
CIpcServerProxy::getMessageReceivedEvent(), e.getData(),
new TMethodEventJob<CIpcTests>(
this, &CIpcTests::sendMessageToClient_handleMessageReceived));
CIpcMessage m;
m.m_type = kIpcLogLine;
m.m_data = (void*)(new CString("test"));
m_sendMessageToClient_server->send(m);
m.m_data = new CString("test");
m_sendMessageToClient_server->send(m, kIpcClientUnknown);
}
void
CIpcTests::sendMessageToClient_handleMessageReceived(const CEvent& e, void*)
{
CIpcMessage* m = reinterpret_cast<CIpcMessage*>(e.getData());
m_sendMessageToClient_receivedString = *((CString*)m->m_data);
raiseQuitEvent();
CIpcMessage* m = static_cast<CIpcMessage*>(e.getData());
if (m->m_type == kIpcLogLine) {
m_sendMessageToClient_receivedString = *static_cast<CString*>(m->m_data);
raiseQuitEvent();
}
}
void

View File

@ -22,7 +22,7 @@
class IEventQueue;
class CMockStream : public IStream
class CMockStream : public synergy::IStream
{
public:
CMockStream(IEventQueue& eventQueue) : IStream(eventQueue) { }