Patch by Jerry for issue 46:
- Unit test for sending file data from server to client. - Removed singleton pattern from CSocketMultiplexer for easier unit testing. - Incremented protocol version from 1.4 to 1.5 (new file chunk message). - Storing pointer to CConfig instead of copying in CServer (so we can mock it). - Created a common event queue for testing (timeout, quit event, etc). - Fixed code style.
This commit is contained in:
parent
6f97f1d186
commit
c368013f13
|
@ -180,6 +180,8 @@ REGISTER_EVENT(IScreen, shapeChanged)
|
||||||
REGISTER_EVENT(IScreen, clipboardGrabbed)
|
REGISTER_EVENT(IScreen, clipboardGrabbed)
|
||||||
REGISTER_EVENT(IScreen, suspend)
|
REGISTER_EVENT(IScreen, suspend)
|
||||||
REGISTER_EVENT(IScreen, resume)
|
REGISTER_EVENT(IScreen, resume)
|
||||||
|
REGISTER_EVENT(IScreen, fileChunkSending)
|
||||||
|
REGISTER_EVENT(IScreen, fileRecieveComplete)
|
||||||
|
|
||||||
//
|
//
|
||||||
// ISecondaryScreen
|
// ISecondaryScreen
|
||||||
|
|
|
@ -647,7 +647,9 @@ public:
|
||||||
m_shapeChanged(CEvent::kUnknown),
|
m_shapeChanged(CEvent::kUnknown),
|
||||||
m_clipboardGrabbed(CEvent::kUnknown),
|
m_clipboardGrabbed(CEvent::kUnknown),
|
||||||
m_suspend(CEvent::kUnknown),
|
m_suspend(CEvent::kUnknown),
|
||||||
m_resume(CEvent::kUnknown) { }
|
m_resume(CEvent::kUnknown),
|
||||||
|
m_fileChunkSending(CEvent::kUnknown),
|
||||||
|
m_fileRecieveComplete(CEvent::kUnknown) { }
|
||||||
|
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -683,11 +685,17 @@ public:
|
||||||
|
|
||||||
//! Get resume event type
|
//! Get resume event type
|
||||||
/*!
|
/*!
|
||||||
Returns the suspend event type. This is sent whenever the system wakes
|
Returns the resume event type. This is sent whenever the system wakes
|
||||||
up or a user session is activated (fast user switching).
|
up or a user session is activated (fast user switching).
|
||||||
*/
|
*/
|
||||||
CEvent::Type resume();
|
CEvent::Type resume();
|
||||||
|
|
||||||
|
//! Sending a file chunk
|
||||||
|
CEvent::Type fileChunkSending();
|
||||||
|
|
||||||
|
//! Completed receiving a file
|
||||||
|
CEvent::Type fileRecieveComplete();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -696,6 +704,8 @@ private:
|
||||||
CEvent::Type m_clipboardGrabbed;
|
CEvent::Type m_clipboardGrabbed;
|
||||||
CEvent::Type m_suspend;
|
CEvent::Type m_suspend;
|
||||||
CEvent::Type m_resume;
|
CEvent::Type m_resume;
|
||||||
|
CEvent::Type m_fileChunkSending;
|
||||||
|
CEvent::Type m_fileRecieveComplete;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ISecondaryScreenEvents : public CEventTypes {
|
class ISecondaryScreenEvents : public CEventTypes {
|
||||||
|
|
|
@ -30,11 +30,12 @@
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include "IEventQueue.h"
|
#include "IEventQueue.h"
|
||||||
#include "TMethodEventJob.h"
|
#include "TMethodEventJob.h"
|
||||||
#include <cstring>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include "CArch.h"
|
#include "CArch.h"
|
||||||
#include "IPlatformScreen.h"
|
#include "IPlatformScreen.h"
|
||||||
#include "CCryptoStream.h"
|
#include "CCryptoStream.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CClient
|
// CClient
|
||||||
|
@ -83,6 +84,10 @@ CClient::CClient(IEventQueue* events,
|
||||||
getEventTarget(),
|
getEventTarget(),
|
||||||
new TMethodEventJob<CClient>(this,
|
new TMethodEventJob<CClient>(this,
|
||||||
&CClient::handleGameDeviceFeedback));
|
&CClient::handleGameDeviceFeedback));
|
||||||
|
m_events->adoptHandler(m_events->forIScreen().fileChunkSending(),
|
||||||
|
this,
|
||||||
|
new TMethodEventJob<CClient>(this,
|
||||||
|
&CClient::handleFileChunkSending));
|
||||||
}
|
}
|
||||||
|
|
||||||
CClient::~CClient()
|
CClient::~CClient()
|
||||||
|
@ -728,3 +733,33 @@ CClient::handleGameDeviceFeedback(const CEvent& event, void*)
|
||||||
|
|
||||||
m_server->onGameDeviceFeedback(info->m_id, info->m_m1, info->m_m2);
|
m_server->onGameDeviceFeedback(info->m_id, info->m_m1, info->m_m2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::handleFileChunkSending(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::clearReceivedFileData()
|
||||||
|
{
|
||||||
|
m_receivedFileData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::setExpectedFileSize(CString data)
|
||||||
|
{
|
||||||
|
std::istringstream iss(data);
|
||||||
|
iss >> m_expectedFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::fileChunkReceived(CString data)
|
||||||
|
{
|
||||||
|
m_receivedFileData += data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CClient::isReceivedFileSizeValid()
|
||||||
|
{
|
||||||
|
return m_expectedFileSize == m_receivedFileData.size();
|
||||||
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
~CClient();
|
~CClient();
|
||||||
|
|
||||||
#ifdef TEST_ENV
|
#ifdef TEST_ENV
|
||||||
CClient() : m_mock(true), m_events(NULL) { }
|
CClient() : m_mock(true) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
@ -92,6 +92,18 @@ public:
|
||||||
//! Set crypto IV for decryption
|
//! Set crypto IV for decryption
|
||||||
virtual void setDecryptIv(const UInt8* iv);
|
virtual void setDecryptIv(const UInt8* iv);
|
||||||
|
|
||||||
|
//! Clears the file buffer
|
||||||
|
void clearReceivedFileData();
|
||||||
|
|
||||||
|
//! Set the expected size of receiving file
|
||||||
|
void setExpectedFileSize(CString data);
|
||||||
|
|
||||||
|
//! Received a chunk of file data
|
||||||
|
void fileChunkReceived(CString data);
|
||||||
|
|
||||||
|
//! Return true if recieved file size is valid
|
||||||
|
bool isReceivedFileSizeValid();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -175,6 +187,7 @@ private:
|
||||||
void handleResume(const CEvent& event, void*);
|
void handleResume(const CEvent& event, void*);
|
||||||
void handleGameDeviceTimingResp(const CEvent& event, void*);
|
void handleGameDeviceTimingResp(const CEvent& event, void*);
|
||||||
void handleGameDeviceFeedback(const CEvent& event, void*);
|
void handleGameDeviceFeedback(const CEvent& event, void*);
|
||||||
|
void handleFileChunkSending(const CEvent&, void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
@ -199,6 +212,8 @@ private:
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
CCryptoStream* m_cryptoStream;
|
CCryptoStream* m_cryptoStream;
|
||||||
CCryptoOptions m_crypto;
|
CCryptoOptions m_crypto;
|
||||||
|
std::size_t m_expectedFileSize;
|
||||||
|
CString m_receivedFileData;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -309,6 +309,10 @@ CServerProxy::parseMessage(const UInt8* code)
|
||||||
cryptoIv();
|
cryptoIv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (memcmp(code, kMsgDFileTransfer, 4) == 0) {
|
||||||
|
fileChunkReceived();
|
||||||
|
}
|
||||||
|
|
||||||
else if (memcmp(code, kMsgCClose, 4) == 0) {
|
else if (memcmp(code, kMsgCClose, 4) == 0) {
|
||||||
// server wants us to hangup
|
// server wants us to hangup
|
||||||
LOG((CLOG_DEBUG1 "recv close"));
|
LOG((CLOG_DEBUG1 "recv close"));
|
||||||
|
@ -930,3 +934,29 @@ CServerProxy::infoAcknowledgment()
|
||||||
LOG((CLOG_DEBUG1 "recv info acknowledgment"));
|
LOG((CLOG_DEBUG1 "recv info acknowledgment"));
|
||||||
m_ignoreMouse = false;
|
m_ignoreMouse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CServerProxy::fileChunkReceived()
|
||||||
|
{
|
||||||
|
// parse
|
||||||
|
UInt8 mark;
|
||||||
|
CString content;
|
||||||
|
CProtocolUtil::readf(m_stream, kMsgDFileTransfer + 4, &mark, &content);
|
||||||
|
|
||||||
|
switch (mark) {
|
||||||
|
case '0':
|
||||||
|
LOG((CLOG_DEBUG2 "recv file data: file size = %s", content));
|
||||||
|
m_client->clearReceivedFileData();
|
||||||
|
m_client->setExpectedFileSize(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
LOG((CLOG_DEBUG2 "recv file data: chunck size = %i", content.size()));
|
||||||
|
m_client->fileChunkReceived(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '2':
|
||||||
|
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
||||||
|
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), m_client));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -105,6 +105,7 @@ private:
|
||||||
void setOptions();
|
void setOptions();
|
||||||
void queryInfo();
|
void queryInfo();
|
||||||
void infoAcknowledgment();
|
void infoAcknowledgment();
|
||||||
|
void fileChunkReceived();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef EResult (CServerProxy::*MessageParser)(const UInt8*);
|
typedef EResult (CServerProxy::*MessageParser)(const UInt8*);
|
||||||
|
|
|
@ -26,19 +26,19 @@
|
||||||
// CIpcClient
|
// CIpcClient
|
||||||
//
|
//
|
||||||
|
|
||||||
CIpcClient::CIpcClient(IEventQueue* events) :
|
CIpcClient::CIpcClient(IEventQueue* events, CSocketMultiplexer* socketMultiplexer) :
|
||||||
m_serverAddress(CNetworkAddress(IPC_HOST, IPC_PORT)),
|
m_serverAddress(CNetworkAddress(IPC_HOST, IPC_PORT)),
|
||||||
m_server(nullptr),
|
m_server(nullptr),
|
||||||
m_socket(events),
|
m_socket(events, socketMultiplexer),
|
||||||
m_events(events)
|
m_events(events)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CIpcClient::CIpcClient(IEventQueue* events, int port) :
|
CIpcClient::CIpcClient(IEventQueue* events, CSocketMultiplexer* socketMultiplexer, int port) :
|
||||||
m_serverAddress(CNetworkAddress(IPC_HOST, port)),
|
m_serverAddress(CNetworkAddress(IPC_HOST, port)),
|
||||||
m_server(nullptr),
|
m_server(nullptr),
|
||||||
m_socket(events),
|
m_socket(events, socketMultiplexer),
|
||||||
m_events(events)
|
m_events(events)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
class CIpcServerProxy;
|
class CIpcServerProxy;
|
||||||
class CIpcMessage;
|
class CIpcMessage;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
class CSocketMultiplexer;
|
||||||
|
|
||||||
//! IPC client for communication between daemon and GUI.
|
//! IPC client for communication between daemon and GUI.
|
||||||
/*!
|
/*!
|
||||||
|
@ -32,8 +33,8 @@ class IEventQueue;
|
||||||
*/
|
*/
|
||||||
class CIpcClient {
|
class CIpcClient {
|
||||||
public:
|
public:
|
||||||
CIpcClient(IEventQueue* events);
|
CIpcClient(IEventQueue* events, CSocketMultiplexer* socketMultiplexer);
|
||||||
CIpcClient(IEventQueue* events, int port);
|
CIpcClient(IEventQueue* events, CSocketMultiplexer* socketMultiplexer, int port);
|
||||||
virtual ~CIpcClient();
|
virtual ~CIpcClient();
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
|
|
@ -31,17 +31,17 @@
|
||||||
// CIpcServer
|
// CIpcServer
|
||||||
//
|
//
|
||||||
|
|
||||||
CIpcServer::CIpcServer(IEventQueue* events) :
|
CIpcServer::CIpcServer(IEventQueue* events, CSocketMultiplexer* socketMultiplexer) :
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_socket(events),
|
m_socket(events, socketMultiplexer),
|
||||||
m_address(CNetworkAddress(IPC_HOST, IPC_PORT))
|
m_address(CNetworkAddress(IPC_HOST, IPC_PORT))
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CIpcServer::CIpcServer(IEventQueue* events, int port) :
|
CIpcServer::CIpcServer(IEventQueue* events, CSocketMultiplexer* socketMultiplexer, int port) :
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_socket(events),
|
m_socket(events, socketMultiplexer),
|
||||||
m_address(CNetworkAddress(IPC_HOST, port))
|
m_address(CNetworkAddress(IPC_HOST, port))
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
|
@ -29,6 +29,7 @@ class CEvent;
|
||||||
class CIpcClientProxy;
|
class CIpcClientProxy;
|
||||||
class CIpcMessage;
|
class CIpcMessage;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
class CSocketMultiplexer;
|
||||||
|
|
||||||
//! IPC server for communication between daemon and GUI.
|
//! IPC server for communication between daemon and GUI.
|
||||||
/*!
|
/*!
|
||||||
|
@ -39,8 +40,8 @@ and allows the daemon and client/server to send log data to the GUI.
|
||||||
*/
|
*/
|
||||||
class CIpcServer {
|
class CIpcServer {
|
||||||
public:
|
public:
|
||||||
CIpcServer(IEventQueue* events);
|
CIpcServer(IEventQueue* events, CSocketMultiplexer* socketMultiplexer);
|
||||||
CIpcServer(IEventQueue* events, int port);
|
CIpcServer(IEventQueue* events, CSocketMultiplexer* socketMultiplexer, int port);
|
||||||
virtual ~CIpcServer();
|
virtual ~CIpcServer();
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
// CSocketMultiplexer
|
// CSocketMultiplexer
|
||||||
//
|
//
|
||||||
|
|
||||||
CSocketMultiplexer* CSocketMultiplexer::s_instance = NULL;
|
|
||||||
|
|
||||||
CSocketMultiplexer::CSocketMultiplexer() :
|
CSocketMultiplexer::CSocketMultiplexer() :
|
||||||
m_mutex(new CMutex),
|
m_mutex(new CMutex),
|
||||||
m_thread(NULL),
|
m_thread(NULL),
|
||||||
|
@ -44,8 +42,6 @@ CSocketMultiplexer::CSocketMultiplexer() :
|
||||||
m_jobListLocker(NULL),
|
m_jobListLocker(NULL),
|
||||||
m_jobListLockLocker(NULL)
|
m_jobListLockLocker(NULL)
|
||||||
{
|
{
|
||||||
assert(s_instance == NULL);
|
|
||||||
|
|
||||||
// this pointer just has to be unique and not NULL. it will
|
// this pointer just has to be unique and not NULL. it will
|
||||||
// never be dereferenced. it's used to identify cursor nodes
|
// never be dereferenced. it's used to identify cursor nodes
|
||||||
// in the jobs list.
|
// in the jobs list.
|
||||||
|
@ -54,8 +50,6 @@ CSocketMultiplexer::CSocketMultiplexer() :
|
||||||
// start thread
|
// start thread
|
||||||
m_thread = new CThread(new TMethodJob<CSocketMultiplexer>(
|
m_thread = new CThread(new TMethodJob<CSocketMultiplexer>(
|
||||||
this, &CSocketMultiplexer::serviceThread));
|
this, &CSocketMultiplexer::serviceThread));
|
||||||
|
|
||||||
s_instance = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSocketMultiplexer::~CSocketMultiplexer()
|
CSocketMultiplexer::~CSocketMultiplexer()
|
||||||
|
@ -76,15 +70,6 @@ CSocketMultiplexer::~CSocketMultiplexer()
|
||||||
i != m_socketJobMap.end(); ++i) {
|
i != m_socketJobMap.end(); ++i) {
|
||||||
delete *(i->second);
|
delete *(i->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_instance = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSocketMultiplexer*
|
|
||||||
CSocketMultiplexer::getInstance()
|
|
||||||
{
|
|
||||||
assert(s_instance != NULL);
|
|
||||||
return s_instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -108,8 +108,6 @@ private:
|
||||||
CSocketJobs m_socketJobs;
|
CSocketJobs m_socketJobs;
|
||||||
CSocketJobMap m_socketJobMap;
|
CSocketJobMap m_socketJobMap;
|
||||||
ISocketMultiplexerJob* m_cursorMark;
|
ISocketMultiplexerJob* m_cursorMark;
|
||||||
|
|
||||||
static CSocketMultiplexer* s_instance;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -33,8 +33,9 @@
|
||||||
// CTCPListenSocket
|
// CTCPListenSocket
|
||||||
//
|
//
|
||||||
|
|
||||||
CTCPListenSocket::CTCPListenSocket(IEventQueue* events) :
|
CTCPListenSocket::CTCPListenSocket(IEventQueue* events, CSocketMultiplexer* socketMultiplexer) :
|
||||||
m_events(events)
|
m_events(events),
|
||||||
|
m_socketMultiplexer(socketMultiplexer)
|
||||||
{
|
{
|
||||||
m_mutex = new CMutex;
|
m_mutex = new CMutex;
|
||||||
try {
|
try {
|
||||||
|
@ -49,7 +50,7 @@ CTCPListenSocket::~CTCPListenSocket()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (m_socket != NULL) {
|
if (m_socket != NULL) {
|
||||||
CSocketMultiplexer::getInstance()->removeSocket(this);
|
m_socketMultiplexer->removeSocket(this);
|
||||||
ARCH->closeSocket(m_socket);
|
ARCH->closeSocket(m_socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,7 @@ CTCPListenSocket::bind(const CNetworkAddress& addr)
|
||||||
ARCH->setReuseAddrOnSocket(m_socket, true);
|
ARCH->setReuseAddrOnSocket(m_socket, true);
|
||||||
ARCH->bindSocket(m_socket, addr.getAddress());
|
ARCH->bindSocket(m_socket, addr.getAddress());
|
||||||
ARCH->listenOnSocket(m_socket);
|
ARCH->listenOnSocket(m_socket);
|
||||||
CSocketMultiplexer::getInstance()->addSocket(this,
|
m_socketMultiplexer->addSocket(this,
|
||||||
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
||||||
this, &CTCPListenSocket::serviceListening,
|
this, &CTCPListenSocket::serviceListening,
|
||||||
m_socket, true, false));
|
m_socket, true, false));
|
||||||
|
@ -88,7 +89,7 @@ CTCPListenSocket::close()
|
||||||
throw XIOClosed();
|
throw XIOClosed();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
CSocketMultiplexer::getInstance()->removeSocket(this);
|
m_socketMultiplexer->removeSocket(this);
|
||||||
ARCH->closeSocket(m_socket);
|
ARCH->closeSocket(m_socket);
|
||||||
m_socket = NULL;
|
m_socket = NULL;
|
||||||
}
|
}
|
||||||
|
@ -108,9 +109,9 @@ CTCPListenSocket::accept()
|
||||||
{
|
{
|
||||||
IDataSocket* socket = NULL;
|
IDataSocket* socket = NULL;
|
||||||
try {
|
try {
|
||||||
socket = new CTCPSocket(m_events, ARCH->acceptSocket(m_socket, NULL));
|
socket = new CTCPSocket(m_events, m_socketMultiplexer, ARCH->acceptSocket(m_socket, NULL));
|
||||||
if (socket != NULL) {
|
if (socket != NULL) {
|
||||||
CSocketMultiplexer::getInstance()->addSocket(this,
|
m_socketMultiplexer->addSocket(this,
|
||||||
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
new TSocketMultiplexerMethodJob<CTCPListenSocket>(
|
||||||
this, &CTCPListenSocket::serviceListening,
|
this, &CTCPListenSocket::serviceListening,
|
||||||
m_socket, true, false));
|
m_socket, true, false));
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
class CMutex;
|
class CMutex;
|
||||||
class ISocketMultiplexerJob;
|
class ISocketMultiplexerJob;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
class CSocketMultiplexer;
|
||||||
|
|
||||||
//! TCP listen socket
|
//! TCP listen socket
|
||||||
/*!
|
/*!
|
||||||
|
@ -32,7 +33,7 @@ A listen socket using TCP.
|
||||||
*/
|
*/
|
||||||
class CTCPListenSocket : public IListenSocket {
|
class CTCPListenSocket : public IListenSocket {
|
||||||
public:
|
public:
|
||||||
CTCPListenSocket(IEventQueue* events);
|
CTCPListenSocket(IEventQueue* events, CSocketMultiplexer* socketMultiplexer);
|
||||||
~CTCPListenSocket();
|
~CTCPListenSocket();
|
||||||
|
|
||||||
// ISocket overrides
|
// ISocket overrides
|
||||||
|
@ -52,6 +53,7 @@ private:
|
||||||
CArchSocket m_socket;
|
CArchSocket m_socket;
|
||||||
CMutex* m_mutex;
|
CMutex* m_mutex;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
CSocketMultiplexer* m_socketMultiplexer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,11 +35,12 @@
|
||||||
// CTCPSocket
|
// CTCPSocket
|
||||||
//
|
//
|
||||||
|
|
||||||
CTCPSocket::CTCPSocket(IEventQueue* events) :
|
CTCPSocket::CTCPSocket(IEventQueue* events, CSocketMultiplexer* socketMultiplexer) :
|
||||||
IDataSocket(events),
|
IDataSocket(events),
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_mutex(),
|
m_mutex(),
|
||||||
m_flushed(&m_mutex, true)
|
m_flushed(&m_mutex, true),
|
||||||
|
m_socketMultiplexer(socketMultiplexer)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
m_socket = ARCH->newSocket(IArchNetwork::kINET, IArchNetwork::kSTREAM);
|
m_socket = ARCH->newSocket(IArchNetwork::kINET, IArchNetwork::kSTREAM);
|
||||||
|
@ -51,12 +52,13 @@ CTCPSocket::CTCPSocket(IEventQueue* events) :
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CTCPSocket::CTCPSocket(IEventQueue* events, CArchSocket socket) :
|
CTCPSocket::CTCPSocket(IEventQueue* events, CSocketMultiplexer* socketMultiplexer, CArchSocket socket) :
|
||||||
IDataSocket(events),
|
IDataSocket(events),
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_mutex(),
|
m_mutex(),
|
||||||
m_socket(socket),
|
m_socket(socket),
|
||||||
m_flushed(&m_mutex, true)
|
m_flushed(&m_mutex, true),
|
||||||
|
m_socketMultiplexer(socketMultiplexer)
|
||||||
{
|
{
|
||||||
assert(m_socket != NULL);
|
assert(m_socket != NULL);
|
||||||
|
|
||||||
|
@ -316,10 +318,10 @@ CTCPSocket::setJob(ISocketMultiplexerJob* job)
|
||||||
{
|
{
|
||||||
// multiplexer will delete the old job
|
// multiplexer will delete the old job
|
||||||
if (job == NULL) {
|
if (job == NULL) {
|
||||||
CSocketMultiplexer::getInstance()->removeSocket(this);
|
m_socketMultiplexer->removeSocket(this);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CSocketMultiplexer::getInstance()->addSocket(this, job);
|
m_socketMultiplexer->addSocket(this, job);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ class CMutex;
|
||||||
class CThread;
|
class CThread;
|
||||||
class ISocketMultiplexerJob;
|
class ISocketMultiplexerJob;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
class CSocketMultiplexer;
|
||||||
|
|
||||||
//! TCP data socket
|
//! TCP data socket
|
||||||
/*!
|
/*!
|
||||||
|
@ -36,8 +37,8 @@ A data socket using TCP.
|
||||||
*/
|
*/
|
||||||
class CTCPSocket : public IDataSocket {
|
class CTCPSocket : public IDataSocket {
|
||||||
public:
|
public:
|
||||||
CTCPSocket(IEventQueue* events);
|
CTCPSocket(IEventQueue* events, CSocketMultiplexer* socketMultiplexer);
|
||||||
CTCPSocket(IEventQueue* events, CArchSocket socket);
|
CTCPSocket(IEventQueue* events, CSocketMultiplexer* socketMultiplexer, CArchSocket socket);
|
||||||
~CTCPSocket();
|
~CTCPSocket();
|
||||||
|
|
||||||
// ISocket overrides
|
// ISocket overrides
|
||||||
|
@ -87,6 +88,7 @@ private:
|
||||||
bool m_readable;
|
bool m_readable;
|
||||||
bool m_writable;
|
bool m_writable;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
CSocketMultiplexer* m_socketMultiplexer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,8 +24,9 @@
|
||||||
// CTCPSocketFactory
|
// CTCPSocketFactory
|
||||||
//
|
//
|
||||||
|
|
||||||
CTCPSocketFactory::CTCPSocketFactory(IEventQueue* events) :
|
CTCPSocketFactory::CTCPSocketFactory(IEventQueue* events, CSocketMultiplexer* socketMultiplexer) :
|
||||||
m_events(events)
|
m_events(events),
|
||||||
|
m_socketMultiplexer(socketMultiplexer)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
@ -38,11 +39,11 @@ CTCPSocketFactory::~CTCPSocketFactory()
|
||||||
IDataSocket*
|
IDataSocket*
|
||||||
CTCPSocketFactory::create() const
|
CTCPSocketFactory::create() const
|
||||||
{
|
{
|
||||||
return new CTCPSocket(m_events);
|
return new CTCPSocket(m_events, m_socketMultiplexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
IListenSocket*
|
IListenSocket*
|
||||||
CTCPSocketFactory::createListen() const
|
CTCPSocketFactory::createListen() const
|
||||||
{
|
{
|
||||||
return new CTCPListenSocket(m_events);
|
return new CTCPListenSocket(m_events, m_socketMultiplexer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,12 @@
|
||||||
#include "ISocketFactory.h"
|
#include "ISocketFactory.h"
|
||||||
|
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
class CSocketMultiplexer;
|
||||||
|
|
||||||
//! Socket factory for TCP sockets
|
//! Socket factory for TCP sockets
|
||||||
class CTCPSocketFactory : public ISocketFactory {
|
class CTCPSocketFactory : public ISocketFactory {
|
||||||
public:
|
public:
|
||||||
CTCPSocketFactory(IEventQueue* events);
|
CTCPSocketFactory(IEventQueue* events, CSocketMultiplexer* socketMultiplexer);
|
||||||
virtual ~CTCPSocketFactory();
|
virtual ~CTCPSocketFactory();
|
||||||
|
|
||||||
// ISocketFactory overrides
|
// ISocketFactory overrides
|
||||||
|
@ -35,6 +36,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
CSocketMultiplexer* m_socketMultiplexer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -83,6 +83,7 @@ public:
|
||||||
virtual void screensaver(bool activate) = 0;
|
virtual void screensaver(bool activate) = 0;
|
||||||
virtual void resetOptions() = 0;
|
virtual void resetOptions() = 0;
|
||||||
virtual void setOptions(const COptionsList& options) = 0;
|
virtual void setOptions(const COptionsList& options) = 0;
|
||||||
|
virtual void fileChunkSending(UInt8 mark, const UInt8* data) = 0;
|
||||||
virtual CString getName() const;
|
virtual CString getName() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -63,6 +63,9 @@ public:
|
||||||
*/
|
*/
|
||||||
CClientProxy* getNextClient();
|
CClientProxy* getNextClient();
|
||||||
|
|
||||||
|
//! Get server which owns this listener
|
||||||
|
CServer* getServer() { return m_server; }
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -89,6 +89,7 @@ public:
|
||||||
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2) = 0;
|
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2) = 0;
|
||||||
virtual void gameDeviceTimingReq() = 0;
|
virtual void gameDeviceTimingReq() = 0;
|
||||||
virtual void cryptoIv(const UInt8* iv) = 0;
|
virtual void cryptoIv(const UInt8* iv) = 0;
|
||||||
|
virtual void fileChunkSending(UInt8 mark, const UInt8* data) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
synergy::IStream* m_stream;
|
synergy::IStream* m_stream;
|
||||||
|
|
|
@ -393,6 +393,13 @@ CClientProxy1_0::cryptoIv(const UInt8* iv)
|
||||||
LOG((CLOG_DEBUG "cryptoIv not supported"));
|
LOG((CLOG_DEBUG "cryptoIv not supported"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClientProxy1_0::fileChunkSending(UInt8 mark, const UInt8* iv)
|
||||||
|
{
|
||||||
|
// ignore -- not supported in protocol 1.0
|
||||||
|
LOG((CLOG_DEBUG "fileChunkSending not supported"));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_0::screensaver(bool on)
|
CClientProxy1_0::screensaver(bool on)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
||||||
virtual void gameDeviceTimingReq();
|
virtual void gameDeviceTimingReq();
|
||||||
virtual void cryptoIv(const UInt8* iv);
|
virtual void cryptoIv(const UInt8* iv);
|
||||||
|
virtual void fileChunkSending(UInt8 mark, const UInt8* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool parseHandshakeMessage(const UInt8* code);
|
virtual bool parseHandshakeMessage(const UInt8* code);
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CClientProxy1_5.h"
|
||||||
|
#include "CProtocolUtil.h"
|
||||||
|
#include "CLog.h"
|
||||||
|
#include "IStream.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// CClientProxy1_5
|
||||||
|
//
|
||||||
|
|
||||||
|
CClientProxy1_5::CClientProxy1_5(const CString& name, synergy::IStream* stream, CServer* server, IEventQueue* events) :
|
||||||
|
CClientProxy1_4(name, stream, server, events)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CClientProxy1_5::~CClientProxy1_5()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClientProxy1_5::fileChunkSending(UInt8 mark, const UInt8* data)
|
||||||
|
{
|
||||||
|
CString chunk(reinterpret_cast<const char*>(data));
|
||||||
|
|
||||||
|
switch (mark) {
|
||||||
|
case '0':
|
||||||
|
LOG((CLOG_DEBUG2 "file sending start: file size = %s", data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
LOG((CLOG_DEBUG2 "file chunk sending: %s", data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '2':
|
||||||
|
LOG((CLOG_DEBUG2 "file sending finished"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CProtocolUtil::writef(getStream(), kMsgDFileTransfer, mark, &chunk);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CClientProxy1_4.h"
|
||||||
|
|
||||||
|
class CServer;
|
||||||
|
class IEventQueue;
|
||||||
|
|
||||||
|
//! Proxy for client implementing protocol version 1.5
|
||||||
|
class CClientProxy1_5 : public CClientProxy1_4 {
|
||||||
|
public:
|
||||||
|
CClientProxy1_5(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
||||||
|
~CClientProxy1_5();
|
||||||
|
|
||||||
|
virtual void fileChunkSending(UInt8 mark, const UInt8* data);
|
||||||
|
};
|
|
@ -22,6 +22,7 @@
|
||||||
#include "CClientProxy1_2.h"
|
#include "CClientProxy1_2.h"
|
||||||
#include "CClientProxy1_3.h"
|
#include "CClientProxy1_3.h"
|
||||||
#include "CClientProxy1_4.h"
|
#include "CClientProxy1_4.h"
|
||||||
|
#include "CClientProxy1_5.h"
|
||||||
#include "ProtocolTypes.h"
|
#include "ProtocolTypes.h"
|
||||||
#include "CProtocolUtil.h"
|
#include "CProtocolUtil.h"
|
||||||
#include "XSynergy.h"
|
#include "XSynergy.h"
|
||||||
|
@ -221,6 +222,10 @@ CClientProxyUnknown::handleData(const CEvent&, void*)
|
||||||
case 4:
|
case 4:
|
||||||
m_proxy = new CClientProxy1_4(name, m_stream, m_server, m_events);
|
m_proxy = new CClientProxy1_4(name, m_stream, m_server, m_events);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
m_proxy = new CClientProxy1_5(name, m_stream, m_server, m_events);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,10 @@ public:
|
||||||
CConfig(IEventQueue* events);
|
CConfig(IEventQueue* events);
|
||||||
virtual ~CConfig();
|
virtual ~CConfig();
|
||||||
|
|
||||||
|
#ifdef TEST_ENV
|
||||||
|
CConfig() : m_inputFilter(NULL) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
@ -313,7 +317,8 @@ public:
|
||||||
Returns the hot key input filter. Clients can modify hotkeys using
|
Returns the hot key input filter. Clients can modify hotkeys using
|
||||||
that object.
|
that object.
|
||||||
*/
|
*/
|
||||||
CInputFilter* getInputFilter();
|
virtual CInputFilter*
|
||||||
|
getInputFilter();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
|
@ -339,7 +344,7 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Returns true iff \c name names a screen.
|
Returns true iff \c name names a screen.
|
||||||
*/
|
*/
|
||||||
bool isScreen(const CString& name) const;
|
virtual bool isScreen(const CString& name) const;
|
||||||
|
|
||||||
//! Test for canonical screen name
|
//! Test for canonical screen name
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -321,6 +321,10 @@ public:
|
||||||
CInputFilter(const CInputFilter&);
|
CInputFilter(const CInputFilter&);
|
||||||
virtual ~CInputFilter();
|
virtual ~CInputFilter();
|
||||||
|
|
||||||
|
#ifdef TEST_ENV
|
||||||
|
CInputFilter() : m_primaryClient(NULL) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
CInputFilter& operator=(const CInputFilter&);
|
CInputFilter& operator=(const CInputFilter&);
|
||||||
|
|
||||||
// add rule, adopting the condition and the actions
|
// add rule, adopting the condition and the actions
|
||||||
|
@ -334,7 +338,7 @@ public:
|
||||||
|
|
||||||
// enable event filtering using the given primary client. disable
|
// enable event filtering using the given primary client. disable
|
||||||
// if client is NULL.
|
// if client is NULL.
|
||||||
void setPrimaryClient(CPrimaryClient* client);
|
virtual void setPrimaryClient(CPrimaryClient* client);
|
||||||
|
|
||||||
// convert rules to a string
|
// convert rules to a string
|
||||||
CString format(const CString& linePrefix) const;
|
CString format(const CString& linePrefix) const;
|
||||||
|
|
|
@ -23,6 +23,7 @@ set(inc
|
||||||
CClientProxy1_2.h
|
CClientProxy1_2.h
|
||||||
CClientProxy1_3.h
|
CClientProxy1_3.h
|
||||||
CClientProxy1_4.h
|
CClientProxy1_4.h
|
||||||
|
CClientProxy1_5.h
|
||||||
CClientProxyUnknown.h
|
CClientProxyUnknown.h
|
||||||
CConfig.h
|
CConfig.h
|
||||||
CInputFilter.h
|
CInputFilter.h
|
||||||
|
@ -39,6 +40,7 @@ set(src
|
||||||
CClientProxy1_2.cpp
|
CClientProxy1_2.cpp
|
||||||
CClientProxy1_3.cpp
|
CClientProxy1_3.cpp
|
||||||
CClientProxy1_4.cpp
|
CClientProxy1_4.cpp
|
||||||
|
CClientProxy1_5.cpp
|
||||||
CClientProxyUnknown.cpp
|
CClientProxyUnknown.cpp
|
||||||
CConfig.cpp
|
CConfig.cpp
|
||||||
CInputFilter.cpp
|
CInputFilter.cpp
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
CPrimaryClient::CPrimaryClient(const CString& name, CScreen* screen) :
|
CPrimaryClient::CPrimaryClient(const CString& name, CScreen* screen) :
|
||||||
CBaseClientProxy(name),
|
CBaseClientProxy(name),
|
||||||
m_screen(screen),
|
m_screen(screen),
|
||||||
m_fakeInputCount(0)
|
m_fakeInputCount(0),
|
||||||
|
m_mock(false)
|
||||||
{
|
{
|
||||||
// all clipboards are clean
|
// all clipboards are clean
|
||||||
for (UInt32 i = 0; i < kClipboardEnd; ++i) {
|
for (UInt32 i = 0; i < kClipboardEnd; ++i) {
|
||||||
|
@ -272,6 +273,12 @@ CPrimaryClient::screensaver(bool)
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CPrimaryClient::fileChunkSending(UInt8 mark, const UInt8* data)
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CPrimaryClient::resetOptions()
|
CPrimaryClient::resetOptions()
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,10 @@ public:
|
||||||
CPrimaryClient(const CString& name, CScreen* screen);
|
CPrimaryClient(const CString& name, CScreen* screen);
|
||||||
~CPrimaryClient();
|
~CPrimaryClient();
|
||||||
|
|
||||||
|
#ifdef TEST_ENV
|
||||||
|
CPrimaryClient() : CBaseClientProxy(""), m_mock(true) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
@ -45,20 +49,20 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Handles reconfiguration of jump zones.
|
Handles reconfiguration of jump zones.
|
||||||
*/
|
*/
|
||||||
void reconfigure(UInt32 activeSides);
|
virtual void reconfigure(UInt32 activeSides);
|
||||||
|
|
||||||
//! Register a system hotkey
|
//! Register a system hotkey
|
||||||
/*!
|
/*!
|
||||||
Registers a system-wide hotkey for key \p key with modifiers \p mask.
|
Registers a system-wide hotkey for key \p key with modifiers \p mask.
|
||||||
Returns an id used to unregister the hotkey.
|
Returns an id used to unregister the hotkey.
|
||||||
*/
|
*/
|
||||||
UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
|
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
|
||||||
|
|
||||||
//! Unregister a system hotkey
|
//! Unregister a system hotkey
|
||||||
/*!
|
/*!
|
||||||
Unregisters a previously registered hot key.
|
Unregisters a previously registered hot key.
|
||||||
*/
|
*/
|
||||||
void unregisterHotKey(UInt32 id);
|
virtual void unregisterHotKey(UInt32 id);
|
||||||
|
|
||||||
//! Prepare to synthesize input on primary screen
|
//! Prepare to synthesize input on primary screen
|
||||||
/*!
|
/*!
|
||||||
|
@ -98,7 +102,8 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Returns the primary screen's current toggle modifier key state.
|
Returns the primary screen's current toggle modifier key state.
|
||||||
*/
|
*/
|
||||||
KeyModifierMask getToggleMask() const;
|
virtual KeyModifierMask
|
||||||
|
getToggleMask() const;
|
||||||
|
|
||||||
//! Get screen lock state
|
//! Get screen lock state
|
||||||
/*!
|
/*!
|
||||||
|
@ -143,11 +148,13 @@ public:
|
||||||
virtual void screensaver(bool activate);
|
virtual void screensaver(bool activate);
|
||||||
virtual void resetOptions();
|
virtual void resetOptions();
|
||||||
virtual void setOptions(const COptionsList& options);
|
virtual void setOptions(const COptionsList& options);
|
||||||
|
virtual void fileChunkSending(UInt8 mark, const UInt8* data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CScreen* m_screen;
|
CScreen* m_screen;
|
||||||
bool m_clipboardDirty[kClipboardEnd];
|
bool m_clipboardDirty[kClipboardEnd];
|
||||||
SInt32 m_fakeInputCount;
|
SInt32 m_fakeInputCount;
|
||||||
|
bool m_mock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
// CServer
|
// CServer
|
||||||
//
|
//
|
||||||
|
|
||||||
CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen* screen, IEventQueue* events) :
|
CServer::CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen, IEventQueue* events) :
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_mock(false),
|
m_mock(false),
|
||||||
m_primaryClient(primaryClient),
|
m_primaryClient(primaryClient),
|
||||||
|
@ -51,8 +51,8 @@ CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen*
|
||||||
m_yDelta(0),
|
m_yDelta(0),
|
||||||
m_xDelta2(0),
|
m_xDelta2(0),
|
||||||
m_yDelta2(0),
|
m_yDelta2(0),
|
||||||
m_config(events),
|
m_config(&config),
|
||||||
m_inputFilter(m_config.getInputFilter()),
|
m_inputFilter(config.getInputFilter()),
|
||||||
m_activeSaver(NULL),
|
m_activeSaver(NULL),
|
||||||
m_switchDir(kNoDirection),
|
m_switchDir(kNoDirection),
|
||||||
m_switchScreen(NULL),
|
m_switchScreen(NULL),
|
||||||
|
@ -173,6 +173,10 @@ CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen*
|
||||||
m_inputFilter,
|
m_inputFilter,
|
||||||
new TMethodEventJob<CServer>(this,
|
new TMethodEventJob<CServer>(this,
|
||||||
&CServer::handleFakeInputEndEvent));
|
&CServer::handleFakeInputEndEvent));
|
||||||
|
m_events->adoptHandler(m_events->forIScreen().fileChunkSending(),
|
||||||
|
this,
|
||||||
|
new TMethodEventJob<CServer>(this,
|
||||||
|
&CServer::handleFileChunkSendingEvent));
|
||||||
|
|
||||||
// add connection
|
// add connection
|
||||||
addClient(m_primaryClient);
|
addClient(m_primaryClient);
|
||||||
|
@ -185,8 +189,8 @@ CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen*
|
||||||
m_inputFilter->setPrimaryClient(m_primaryClient);
|
m_inputFilter->setPrimaryClient(m_primaryClient);
|
||||||
|
|
||||||
// Determine if scroll lock is already set. If so, lock the cursor to the primary screen
|
// Determine if scroll lock is already set. If so, lock the cursor to the primary screen
|
||||||
int keyValue = m_primaryClient->getToggleMask ();
|
int keyValue = m_primaryClient->getToggleMask();
|
||||||
if (m_primaryClient->getToggleMask () & KeyModifierScrollLock) {
|
if (m_primaryClient->getToggleMask() & KeyModifierScrollLock) {
|
||||||
LOG((CLOG_DEBUG "scroll lock on initially. locked to screen"));
|
LOG((CLOG_DEBUG "scroll lock on initially. locked to screen"));
|
||||||
m_lockedToScreen = true;
|
m_lockedToScreen = true;
|
||||||
}
|
}
|
||||||
|
@ -259,7 +263,6 @@ CServer::setConfig(const CConfig& config)
|
||||||
closeClients(config);
|
closeClients(config);
|
||||||
|
|
||||||
// cut over
|
// cut over
|
||||||
m_config = config;
|
|
||||||
processOptions();
|
processOptions();
|
||||||
|
|
||||||
// add ScrollLock as a hotkey to lock to the screen. this was a
|
// add ScrollLock as a hotkey to lock to the screen. this was a
|
||||||
|
@ -269,7 +272,7 @@ CServer::setConfig(const CConfig& config)
|
||||||
// we will unfortunately generate a warning. if the user has
|
// we will unfortunately generate a warning. if the user has
|
||||||
// configured a CLockCursorToScreenAction then we don't add
|
// configured a CLockCursorToScreenAction then we don't add
|
||||||
// ScrollLock as a hotkey.
|
// ScrollLock as a hotkey.
|
||||||
if (!m_config.hasLockToScreenAction()) {
|
if (!m_config->hasLockToScreenAction()) {
|
||||||
IPlatformScreen::CKeyInfo* key =
|
IPlatformScreen::CKeyInfo* key =
|
||||||
IPlatformScreen::CKeyInfo::alloc(kKeyScrollLock, 0, 0, 0);
|
IPlatformScreen::CKeyInfo::alloc(kKeyScrollLock, 0, 0, 0);
|
||||||
CInputFilter::CRule rule(new CInputFilter::CKeystrokeCondition(m_events, key));
|
CInputFilter::CRule rule(new CInputFilter::CKeystrokeCondition(m_events, key));
|
||||||
|
@ -301,7 +304,7 @@ CServer::adoptClient(CBaseClientProxy* client)
|
||||||
&CServer::handleClientDisconnected, client));
|
&CServer::handleClientDisconnected, client));
|
||||||
|
|
||||||
// name must be in our configuration
|
// name must be in our configuration
|
||||||
if (!m_config.isScreen(client->getName())) {
|
if (!m_config->isScreen(client->getName())) {
|
||||||
LOG((CLOG_WARN "unrecognised client name \"%s\", check server config", client->getName().c_str()));
|
LOG((CLOG_WARN "unrecognised client name \"%s\", check server config", client->getName().c_str()));
|
||||||
closeClient(client, kMsgEUnknown);
|
closeClient(client, kMsgEUnknown);
|
||||||
return;
|
return;
|
||||||
|
@ -375,7 +378,7 @@ CServer::getClients(std::vector<CString>& list) const
|
||||||
CString
|
CString
|
||||||
CServer::getName(const CBaseClientProxy* client) const
|
CServer::getName(const CBaseClientProxy* client) const
|
||||||
{
|
{
|
||||||
CString name = m_config.getCanonicalName(client->getName());
|
CString name = m_config->getCanonicalName(client->getName());
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
name = client->getName();
|
name = client->getName();
|
||||||
}
|
}
|
||||||
|
@ -579,7 +582,7 @@ CServer::hasAnyNeighbor(CBaseClientProxy* client, EDirection dir) const
|
||||||
{
|
{
|
||||||
assert(client != NULL);
|
assert(client != NULL);
|
||||||
|
|
||||||
return m_config.hasNeighbor(getName(client), dir);
|
return m_config->hasNeighbor(getName(client), dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBaseClientProxy*
|
CBaseClientProxy*
|
||||||
|
@ -601,7 +604,7 @@ CServer::getNeighbor(CBaseClientProxy* src,
|
||||||
// search for the closest neighbor that exists in direction dir
|
// search for the closest neighbor that exists in direction dir
|
||||||
float tTmp;
|
float tTmp;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
CString dstName(m_config.getNeighbor(srcName, dir, t, &tTmp));
|
CString dstName(m_config->getNeighbor(srcName, dir, t, &tTmp));
|
||||||
|
|
||||||
// if nothing in that direction then return NULL. if the
|
// if nothing in that direction then return NULL. if the
|
||||||
// destination is the source then we can make no more
|
// destination is the source then we can make no more
|
||||||
|
@ -757,25 +760,25 @@ CServer::avoidJumpZone(CBaseClientProxy* dst,
|
||||||
// don't need to move inwards because that side can't provoke a jump.
|
// don't need to move inwards because that side can't provoke a jump.
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case kLeft:
|
case kLeft:
|
||||||
if (!m_config.getNeighbor(dstName, kRight, t, NULL).empty() &&
|
if (!m_config->getNeighbor(dstName, kRight, t, NULL).empty() &&
|
||||||
x > dx + dw - 1 - z)
|
x > dx + dw - 1 - z)
|
||||||
x = dx + dw - 1 - z;
|
x = dx + dw - 1 - z;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kRight:
|
case kRight:
|
||||||
if (!m_config.getNeighbor(dstName, kLeft, t, NULL).empty() &&
|
if (!m_config->getNeighbor(dstName, kLeft, t, NULL).empty() &&
|
||||||
x < dx + z)
|
x < dx + z)
|
||||||
x = dx + z;
|
x = dx + z;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kTop:
|
case kTop:
|
||||||
if (!m_config.getNeighbor(dstName, kBottom, t, NULL).empty() &&
|
if (!m_config->getNeighbor(dstName, kBottom, t, NULL).empty() &&
|
||||||
y > dy + dh - 1 - z)
|
y > dy + dh - 1 - z)
|
||||||
y = dy + dh - 1 - z;
|
y = dy + dh - 1 - z;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kBottom:
|
case kBottom:
|
||||||
if (!m_config.getNeighbor(dstName, kTop, t, NULL).empty() &&
|
if (!m_config->getNeighbor(dstName, kTop, t, NULL).empty() &&
|
||||||
y < dy + z)
|
y < dy + z)
|
||||||
y = dy + z;
|
y = dy + z;
|
||||||
break;
|
break;
|
||||||
|
@ -839,9 +842,9 @@ CServer::isSwitchOkay(CBaseClientProxy* newScreen,
|
||||||
// are we in a locked corner? first check if screen has the option set
|
// are we in a locked corner? first check if screen has the option set
|
||||||
// and, if not, check the global options.
|
// and, if not, check the global options.
|
||||||
const CConfig::CScreenOptions* options =
|
const CConfig::CScreenOptions* options =
|
||||||
m_config.getOptions(getName(m_active));
|
m_config->getOptions(getName(m_active));
|
||||||
if (options == NULL || options->count(kOptionScreenSwitchCorners) == 0) {
|
if (options == NULL || options->count(kOptionScreenSwitchCorners) == 0) {
|
||||||
options = m_config.getOptions("");
|
options = m_config->getOptions("");
|
||||||
}
|
}
|
||||||
if (options != NULL && options->count(kOptionScreenSwitchCorners) > 0) {
|
if (options != NULL && options->count(kOptionScreenSwitchCorners) > 0) {
|
||||||
// get corner mask and size
|
// get corner mask and size
|
||||||
|
@ -1089,7 +1092,7 @@ CServer::sendOptions(CBaseClientProxy* client) const
|
||||||
|
|
||||||
// look up options for client
|
// look up options for client
|
||||||
const CConfig::CScreenOptions* options =
|
const CConfig::CScreenOptions* options =
|
||||||
m_config.getOptions(getName(client));
|
m_config->getOptions(getName(client));
|
||||||
if (options != NULL) {
|
if (options != NULL) {
|
||||||
// convert options to a more convenient form for sending
|
// convert options to a more convenient form for sending
|
||||||
optionsList.reserve(2 * options->size());
|
optionsList.reserve(2 * options->size());
|
||||||
|
@ -1101,7 +1104,7 @@ CServer::sendOptions(CBaseClientProxy* client) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// look up global options
|
// look up global options
|
||||||
options = m_config.getOptions("");
|
options = m_config->getOptions("");
|
||||||
if (options != NULL) {
|
if (options != NULL) {
|
||||||
// convert options to a more convenient form for sending
|
// convert options to a more convenient form for sending
|
||||||
optionsList.reserve(optionsList.size() + 2 * options->size());
|
optionsList.reserve(optionsList.size() + 2 * options->size());
|
||||||
|
@ -1120,7 +1123,7 @@ CServer::sendOptions(CBaseClientProxy* client) const
|
||||||
void
|
void
|
||||||
CServer::processOptions()
|
CServer::processOptions()
|
||||||
{
|
{
|
||||||
const CConfig::CScreenOptions* options = m_config.getOptions("");
|
const CConfig::CScreenOptions* options = m_config->getOptions("");
|
||||||
if (options == NULL) {
|
if (options == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1510,6 +1513,13 @@ CServer::handleFakeInputEndEvent(const CEvent&, void*)
|
||||||
m_primaryClient->fakeInputEnd();
|
m_primaryClient->fakeInputEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::handleFileChunkSendingEvent(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
UInt8* data = reinterpret_cast<UInt8*>(event.getData());
|
||||||
|
onFileChunkSending(data);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServer::onClipboardChanged(CBaseClientProxy* sender,
|
CServer::onClipboardChanged(CBaseClientProxy* sender,
|
||||||
ClipboardID id, UInt32 seqNum)
|
ClipboardID id, UInt32 seqNum)
|
||||||
|
@ -1970,6 +1980,16 @@ CServer::onGameDeviceTimingReq()
|
||||||
m_active->gameDeviceTimingReq();
|
m_active->gameDeviceTimingReq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::onFileChunkSending(const UInt8* data)
|
||||||
|
{
|
||||||
|
LOG((CLOG_DEBUG1 "onFileChunkSending"));
|
||||||
|
assert(m_active != NULL);
|
||||||
|
|
||||||
|
// relay
|
||||||
|
m_active->fileChunkSending(data[0], &data[1]);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CServer::addClient(CBaseClientProxy* client)
|
CServer::addClient(CBaseClientProxy* client)
|
||||||
{
|
{
|
||||||
|
|
|
@ -103,11 +103,12 @@ public:
|
||||||
client (local screen) \p primaryClient. The client retains
|
client (local screen) \p primaryClient. The client retains
|
||||||
ownership of \p primaryClient.
|
ownership of \p primaryClient.
|
||||||
*/
|
*/
|
||||||
CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen* screen, IEventQueue* events);
|
CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen, IEventQueue* events);
|
||||||
~CServer();
|
~CServer();
|
||||||
|
|
||||||
#ifdef TEST_ENV
|
#ifdef TEST_ENV
|
||||||
CServer() : m_mock(true), m_events(NULL), m_config(NULL) { }
|
CServer() : m_mock(true), m_config(NULL) { }
|
||||||
|
void setActive(CBaseClientProxy* active) { m_active = active; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
@ -297,6 +298,7 @@ private:
|
||||||
void handleLockCursorToScreenEvent(const CEvent&, void*);
|
void handleLockCursorToScreenEvent(const CEvent&, void*);
|
||||||
void handleFakeInputBeginEvent(const CEvent&, void*);
|
void handleFakeInputBeginEvent(const CEvent&, void*);
|
||||||
void handleFakeInputEndEvent(const CEvent&, void*);
|
void handleFakeInputEndEvent(const CEvent&, void*);
|
||||||
|
void handleFileChunkSendingEvent(const CEvent&, void*);
|
||||||
|
|
||||||
// event processing
|
// event processing
|
||||||
void onClipboardChanged(CBaseClientProxy* sender,
|
void onClipboardChanged(CBaseClientProxy* sender,
|
||||||
|
@ -316,6 +318,7 @@ private:
|
||||||
void onGameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
void onGameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
||||||
void onGameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
void onGameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
|
||||||
void onGameDeviceTimingReq();
|
void onGameDeviceTimingReq();
|
||||||
|
void onFileChunkSending(const UInt8* data);
|
||||||
|
|
||||||
// add client to list and attach event handlers for client
|
// add client to list and attach event handlers for client
|
||||||
bool addClient(CBaseClientProxy*);
|
bool addClient(CBaseClientProxy*);
|
||||||
|
@ -386,7 +389,7 @@ private:
|
||||||
SInt32 m_xDelta2, m_yDelta2;
|
SInt32 m_xDelta2, m_yDelta2;
|
||||||
|
|
||||||
// current configuration
|
// current configuration
|
||||||
CConfig m_config;
|
CConfig* m_config;
|
||||||
|
|
||||||
// input filter (from m_config);
|
// input filter (from m_config);
|
||||||
CInputFilter* m_inputFilter;
|
CInputFilter* m_inputFilter;
|
||||||
|
|
|
@ -357,7 +357,7 @@ CApp::initApp(int argc, const char** argv)
|
||||||
void
|
void
|
||||||
CApp::initIpcClient()
|
CApp::initIpcClient()
|
||||||
{
|
{
|
||||||
m_ipcClient = new CIpcClient(m_events);
|
m_ipcClient = new CIpcClient(m_events, m_socketMultiplexer);
|
||||||
m_ipcClient->connect();
|
m_ipcClient->connect();
|
||||||
|
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
|
|
|
@ -35,6 +35,7 @@ class ILogOutputter;
|
||||||
class CFileLogOutputter;
|
class CFileLogOutputter;
|
||||||
class CScreen;
|
class CScreen;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
class CSocketMultiplexer;
|
||||||
|
|
||||||
typedef IArchTaskBarReceiver* (*CreateTaskBarReceiverFunc)(const CBufferedLogOutputter*, IEventQueue* events);
|
typedef IArchTaskBarReceiver* (*CreateTaskBarReceiverFunc)(const CBufferedLogOutputter*, IEventQueue* events);
|
||||||
|
|
||||||
|
@ -97,6 +98,9 @@ public:
|
||||||
|
|
||||||
virtual IEventQueue* getEvents() const { return m_events; }
|
virtual IEventQueue* getEvents() const { return m_events; }
|
||||||
|
|
||||||
|
void setSocketMultiplexer(CSocketMultiplexer* sm) { m_socketMultiplexer = sm; }
|
||||||
|
CSocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleIpcMessage(const CEvent&, void*);
|
void handleIpcMessage(const CEvent&, void*);
|
||||||
|
|
||||||
|
@ -117,6 +121,7 @@ private:
|
||||||
ARCH_APP_UTIL m_appUtil;
|
ARCH_APP_UTIL m_appUtil;
|
||||||
CIpcClient* m_ipcClient;
|
CIpcClient* m_ipcClient;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
CSocketMultiplexer* m_socketMultiplexer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BYE "\nTry `%s --help' for more information."
|
#define BYE "\nTry `%s --help' for more information."
|
||||||
|
|
|
@ -391,7 +391,13 @@ CClient*
|
||||||
CClientApp::openClient(const CString& name, const CNetworkAddress& address, CScreen* screen, const CCryptoOptions& crypto)
|
CClientApp::openClient(const CString& name, const CNetworkAddress& address, CScreen* screen, const CCryptoOptions& crypto)
|
||||||
{
|
{
|
||||||
CClient* client = new CClient(
|
CClient* client = new CClient(
|
||||||
m_events, name, address, new CTCPSocketFactory(m_events), NULL, screen, crypto);
|
m_events,
|
||||||
|
name,
|
||||||
|
address,
|
||||||
|
new CTCPSocketFactory(m_events, getSocketMultiplexer()),
|
||||||
|
NULL,
|
||||||
|
screen,
|
||||||
|
crypto);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
|
@ -522,6 +528,7 @@ CClientApp::mainLoop()
|
||||||
// create socket multiplexer. this must happen after daemonization
|
// create socket multiplexer. this must happen after daemonization
|
||||||
// on unix because threads evaporate across a fork().
|
// on unix because threads evaporate across a fork().
|
||||||
CSocketMultiplexer multiplexer;
|
CSocketMultiplexer multiplexer;
|
||||||
|
setSocketMultiplexer(&multiplexer);
|
||||||
|
|
||||||
// start client, etc
|
// start client, etc
|
||||||
appUtil().startNode();
|
appUtil().startNode();
|
||||||
|
|
|
@ -203,7 +203,7 @@ CDaemonApp::mainLoop(bool logToFile)
|
||||||
CSocketMultiplexer multiplexer;
|
CSocketMultiplexer multiplexer;
|
||||||
|
|
||||||
// uses event queue, must be created here.
|
// uses event queue, must be created here.
|
||||||
m_ipcServer = new CIpcServer(m_events);
|
m_ipcServer = new CIpcServer(m_events, &multiplexer);
|
||||||
|
|
||||||
// send logging to gui via ipc, log system adopts outputter.
|
// send logging to gui via ipc, log system adopts outputter.
|
||||||
m_ipcLogOutputter = new CIpcLogOutputter(*m_ipcServer);
|
m_ipcLogOutputter = new CIpcLogOutputter(*m_ipcServer);
|
||||||
|
|
|
@ -35,7 +35,8 @@ CScreen::CScreen(IPlatformScreen* platformScreen, IEventQueue* events) :
|
||||||
m_enabled(false),
|
m_enabled(false),
|
||||||
m_entered(m_isPrimary),
|
m_entered(m_isPrimary),
|
||||||
m_screenSaverSync(true),
|
m_screenSaverSync(true),
|
||||||
m_fakeInput(false)
|
m_fakeInput(false),
|
||||||
|
m_mock(false)
|
||||||
{
|
{
|
||||||
assert(m_screen != NULL);
|
assert(m_screen != NULL);
|
||||||
|
|
||||||
|
@ -47,6 +48,10 @@ CScreen::CScreen(IPlatformScreen* platformScreen, IEventQueue* events) :
|
||||||
|
|
||||||
CScreen::~CScreen()
|
CScreen::~CScreen()
|
||||||
{
|
{
|
||||||
|
if (m_mock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_enabled) {
|
if (m_enabled) {
|
||||||
disable();
|
disable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ public:
|
||||||
CScreen(IPlatformScreen* platformScreen, IEventQueue* events);
|
CScreen(IPlatformScreen* platformScreen, IEventQueue* events);
|
||||||
virtual ~CScreen();
|
virtual ~CScreen();
|
||||||
|
|
||||||
|
#ifdef TEST_ENV
|
||||||
|
CScreen() : m_mock(true) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
@ -49,14 +53,14 @@ public:
|
||||||
For a secondary screen it also means disabling the screen saver if
|
For a secondary screen it also means disabling the screen saver if
|
||||||
synchronizing it and preparing to synthesize events.
|
synchronizing it and preparing to synthesize events.
|
||||||
*/
|
*/
|
||||||
void enable();
|
virtual void enable();
|
||||||
|
|
||||||
//! Deactivate screen
|
//! Deactivate screen
|
||||||
/*!
|
/*!
|
||||||
Undoes the operations in activate() and events are no longer
|
Undoes the operations in activate() and events are no longer
|
||||||
reported. It also releases keys that are logically pressed.
|
reported. It also releases keys that are logically pressed.
|
||||||
*/
|
*/
|
||||||
void disable();
|
virtual void disable();
|
||||||
|
|
||||||
//! Enter screen
|
//! Enter screen
|
||||||
/*!
|
/*!
|
||||||
|
@ -208,14 +212,14 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Resets all options to their default values.
|
Resets all options to their default values.
|
||||||
*/
|
*/
|
||||||
void resetOptions();
|
virtual void resetOptions();
|
||||||
|
|
||||||
//! Notify of options changes
|
//! Notify of options changes
|
||||||
/*!
|
/*!
|
||||||
Set options to given values. Ignores unknown options and doesn't
|
Set options to given values. Ignores unknown options and doesn't
|
||||||
modify options that aren't given in \c options.
|
modify options that aren't given in \c options.
|
||||||
*/
|
*/
|
||||||
void setOptions(const COptionsList& options);
|
virtual void setOptions(const COptionsList& options);
|
||||||
|
|
||||||
//! Set clipboard sequence number
|
//! Set clipboard sequence number
|
||||||
/*!
|
/*!
|
||||||
|
@ -343,6 +347,8 @@ private:
|
||||||
bool m_fakeInput;
|
bool m_fakeInput;
|
||||||
|
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
||||||
|
bool m_mock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -670,8 +670,11 @@ CClientListener*
|
||||||
CServerApp::openClientListener(const CNetworkAddress& address)
|
CServerApp::openClientListener(const CNetworkAddress& address)
|
||||||
{
|
{
|
||||||
CClientListener* listen = new CClientListener(
|
CClientListener* listen = new CClientListener(
|
||||||
address, new CTCPSocketFactory(m_events),
|
address,
|
||||||
NULL, args().m_crypto, m_events);
|
new CTCPSocketFactory(m_events, getSocketMultiplexer()),
|
||||||
|
NULL,
|
||||||
|
args().m_crypto,
|
||||||
|
m_events);
|
||||||
|
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
m_events->forCClientListener().connected(), listen,
|
m_events->forCClientListener().connected(), listen,
|
||||||
|
@ -682,7 +685,7 @@ CServerApp::openClientListener(const CNetworkAddress& address)
|
||||||
}
|
}
|
||||||
|
|
||||||
CServer*
|
CServer*
|
||||||
CServerApp::openServer(const CConfig& config, CPrimaryClient* primaryClient)
|
CServerApp::openServer(CConfig& config, CPrimaryClient* primaryClient)
|
||||||
{
|
{
|
||||||
CServer* server = new CServer(config, primaryClient, s_serverScreen, m_events);
|
CServer* server = new CServer(config, primaryClient, s_serverScreen, m_events);
|
||||||
|
|
||||||
|
@ -720,6 +723,7 @@ CServerApp::mainLoop()
|
||||||
// create socket multiplexer. this must happen after daemonization
|
// create socket multiplexer. this must happen after daemonization
|
||||||
// on unix because threads evaporate across a fork().
|
// on unix because threads evaporate across a fork().
|
||||||
CSocketMultiplexer multiplexer;
|
CSocketMultiplexer multiplexer;
|
||||||
|
setSocketMultiplexer(&multiplexer);
|
||||||
|
|
||||||
// if configuration has no screens then add this system
|
// if configuration has no screens then add this system
|
||||||
// as the default
|
// as the default
|
||||||
|
|
|
@ -100,7 +100,7 @@ public:
|
||||||
void handleSuspend(const CEvent&, void*);
|
void handleSuspend(const CEvent&, void*);
|
||||||
void handleResume(const CEvent&, void*);
|
void handleResume(const CEvent&, void*);
|
||||||
CClientListener* openClientListener(const CNetworkAddress& address);
|
CClientListener* openClientListener(const CNetworkAddress& address);
|
||||||
CServer* openServer(const CConfig& config, CPrimaryClient* primaryClient);
|
CServer* openServer(CConfig& config, CPrimaryClient* primaryClient);
|
||||||
void handleNoClients(const CEvent&, void*);
|
void handleNoClients(const CEvent&, void*);
|
||||||
bool startServer();
|
bool startServer();
|
||||||
int mainLoop();
|
int mainLoop();
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "IInterface.h"
|
#include "IInterface.h"
|
||||||
|
|
||||||
class INode : IInterface {
|
class INode : IInterface {
|
||||||
|
|
|
@ -51,6 +51,7 @@ const char* kMsgDGameSticks = "DGST%1i%2i%2i%2i%2i";
|
||||||
const char* kMsgDGameTriggers = "DGTR%1i%1i%1i";
|
const char* kMsgDGameTriggers = "DGTR%1i%1i%1i";
|
||||||
const char* kMsgDGameFeedback = "DGFB%1i%2i%2i";
|
const char* kMsgDGameFeedback = "DGFB%1i%2i%2i";
|
||||||
const char* kMsgDCryptoIv = "DCIV%s";
|
const char* kMsgDCryptoIv = "DCIV%s";
|
||||||
|
const char* kMsgDFileTransfer = "DFTR%1i%s";
|
||||||
const char* kMsgQInfo = "QINF";
|
const char* kMsgQInfo = "QINF";
|
||||||
const char* kMsgEIncompatible = "EICV%2i%2i";
|
const char* kMsgEIncompatible = "EICV%2i%2i";
|
||||||
const char* kMsgEBusy = "EBSY";
|
const char* kMsgEBusy = "EBSY";
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
// adds horizontal mouse scrolling
|
// adds horizontal mouse scrolling
|
||||||
// 1.4: adds game device support
|
// 1.4: adds game device support
|
||||||
static const SInt16 kProtocolMajorVersion = 1;
|
static const SInt16 kProtocolMajorVersion = 1;
|
||||||
static const SInt16 kProtocolMinorVersion = 4;
|
static const SInt16 kProtocolMinorVersion = 5;
|
||||||
|
|
||||||
// default contact port number
|
// default contact port number
|
||||||
static const UInt16 kDefaultPort = 24800;
|
static const UInt16 kDefaultPort = 24800;
|
||||||
|
@ -288,6 +288,13 @@ extern const char* kMsgDSetOptions;
|
||||||
// cryptography stream.
|
// cryptography stream.
|
||||||
extern const char* kMsgDCryptoIv;
|
extern const char* kMsgDCryptoIv;
|
||||||
|
|
||||||
|
// file data: primary <-> secondary
|
||||||
|
// transfer file data. A mark is used in the first byte.
|
||||||
|
// 0 means the content followed is the file size.
|
||||||
|
// 1 means the content followed is the chunk data.
|
||||||
|
// 2 means the file transfer is finished.
|
||||||
|
extern const char* kMsgDFileTransfer;
|
||||||
|
|
||||||
//
|
//
|
||||||
// query codes
|
// query codes
|
||||||
//
|
//
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
#include "CIpcServerProxy.h"
|
#include "CIpcServerProxy.h"
|
||||||
#include "CIpcMessage.h"
|
#include "CIpcMessage.h"
|
||||||
#include "CSimpleEventQueueBuffer.h"
|
#include "CTestEventQueue.h"
|
||||||
|
|
||||||
#define TEST_IPC_PORT 24802
|
#define TEST_IPC_PORT 24802
|
||||||
|
|
||||||
|
@ -49,18 +49,9 @@ public:
|
||||||
void sendMessageToServer_serverHandleMessageReceived(const CEvent&, void*);
|
void sendMessageToServer_serverHandleMessageReceived(const CEvent&, void*);
|
||||||
void sendMessageToClient_serverHandleClientConnected(const CEvent&, void*);
|
void sendMessageToClient_serverHandleClientConnected(const CEvent&, void*);
|
||||||
void sendMessageToClient_clientHandleMessageReceived(const CEvent&, void*);
|
void sendMessageToClient_clientHandleMessageReceived(const CEvent&, void*);
|
||||||
void handleQuitTimeout(const CEvent&, void* vclient);
|
|
||||||
void raiseQuitEvent();
|
|
||||||
void initQuitTimeout(double timeout);
|
|
||||||
void cleanupQuitTimeout();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void timeoutThread(void*);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSocketMultiplexer m_multiplexer;
|
CSocketMultiplexer m_multiplexer;
|
||||||
CEventQueue m_events;
|
|
||||||
CEventQueueTimer* m_quitTimeoutTimer;
|
|
||||||
bool m_connectToServer_helloMessageReceived;
|
bool m_connectToServer_helloMessageReceived;
|
||||||
bool m_connectToServer_hasClientNode;
|
bool m_connectToServer_hasClientNode;
|
||||||
CIpcServer* m_connectToServer_server;
|
CIpcServer* m_connectToServer_server;
|
||||||
|
@ -68,12 +59,14 @@ public:
|
||||||
CString m_sendMessageToClient_receivedString;
|
CString m_sendMessageToClient_receivedString;
|
||||||
CIpcClient* m_sendMessageToServer_client;
|
CIpcClient* m_sendMessageToServer_client;
|
||||||
CIpcServer* m_sendMessageToClient_server;
|
CIpcServer* m_sendMessageToClient_server;
|
||||||
|
CTestEventQueue m_events;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(CIpcTests, connectToServer)
|
TEST_F(CIpcTests, connectToServer)
|
||||||
{
|
{
|
||||||
CIpcServer server(&m_events, TEST_IPC_PORT);
|
CSocketMultiplexer socketMultiplexer;
|
||||||
|
CIpcServer server(&m_events, &socketMultiplexer, TEST_IPC_PORT);
|
||||||
server.listen();
|
server.listen();
|
||||||
m_connectToServer_server = &server;
|
m_connectToServer_server = &server;
|
||||||
|
|
||||||
|
@ -82,13 +75,13 @@ TEST_F(CIpcTests, connectToServer)
|
||||||
new TMethodEventJob<CIpcTests>(
|
new TMethodEventJob<CIpcTests>(
|
||||||
this, &CIpcTests::connectToServer_handleMessageReceived));
|
this, &CIpcTests::connectToServer_handleMessageReceived));
|
||||||
|
|
||||||
CIpcClient client(&m_events, TEST_IPC_PORT);
|
CIpcClient client(&m_events, &socketMultiplexer, TEST_IPC_PORT);
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
initQuitTimeout(5);
|
m_events.initQuitTimeout(5);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.removeHandler(m_events.forCIpcServer().messageReceived(), &server);
|
m_events.removeHandler(m_events.forCIpcServer().messageReceived(), &server);
|
||||||
cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
|
|
||||||
EXPECT_EQ(true, m_connectToServer_helloMessageReceived);
|
EXPECT_EQ(true, m_connectToServer_helloMessageReceived);
|
||||||
EXPECT_EQ(true, m_connectToServer_hasClientNode);
|
EXPECT_EQ(true, m_connectToServer_hasClientNode);
|
||||||
|
@ -96,7 +89,8 @@ TEST_F(CIpcTests, connectToServer)
|
||||||
|
|
||||||
TEST_F(CIpcTests, sendMessageToServer)
|
TEST_F(CIpcTests, sendMessageToServer)
|
||||||
{
|
{
|
||||||
CIpcServer server(&m_events, TEST_IPC_PORT);
|
CSocketMultiplexer socketMultiplexer;
|
||||||
|
CIpcServer server(&m_events, &socketMultiplexer, TEST_IPC_PORT);
|
||||||
server.listen();
|
server.listen();
|
||||||
|
|
||||||
// event handler sends "test" command to server.
|
// event handler sends "test" command to server.
|
||||||
|
@ -105,21 +99,22 @@ TEST_F(CIpcTests, sendMessageToServer)
|
||||||
new TMethodEventJob<CIpcTests>(
|
new TMethodEventJob<CIpcTests>(
|
||||||
this, &CIpcTests::sendMessageToServer_serverHandleMessageReceived));
|
this, &CIpcTests::sendMessageToServer_serverHandleMessageReceived));
|
||||||
|
|
||||||
CIpcClient client(&m_events, TEST_IPC_PORT);
|
CIpcClient client(&m_events, &socketMultiplexer, TEST_IPC_PORT);
|
||||||
client.connect();
|
client.connect();
|
||||||
m_sendMessageToServer_client = &client;
|
m_sendMessageToServer_client = &client;
|
||||||
|
|
||||||
initQuitTimeout(5);
|
m_events.initQuitTimeout(5);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.removeHandler(m_events.forCIpcServer().messageReceived(), &server);
|
m_events.removeHandler(m_events.forCIpcServer().messageReceived(), &server);
|
||||||
cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
|
|
||||||
EXPECT_EQ("test", m_sendMessageToServer_receivedString);
|
EXPECT_EQ("test", m_sendMessageToServer_receivedString);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CIpcTests, sendMessageToClient)
|
TEST_F(CIpcTests, sendMessageToClient)
|
||||||
{
|
{
|
||||||
CIpcServer server(&m_events, TEST_IPC_PORT);
|
CSocketMultiplexer socketMultiplexer;
|
||||||
|
CIpcServer server(&m_events, &socketMultiplexer, TEST_IPC_PORT);
|
||||||
server.listen();
|
server.listen();
|
||||||
m_sendMessageToClient_server = &server;
|
m_sendMessageToClient_server = &server;
|
||||||
|
|
||||||
|
@ -129,7 +124,7 @@ TEST_F(CIpcTests, sendMessageToClient)
|
||||||
new TMethodEventJob<CIpcTests>(
|
new TMethodEventJob<CIpcTests>(
|
||||||
this, &CIpcTests::sendMessageToClient_serverHandleClientConnected));
|
this, &CIpcTests::sendMessageToClient_serverHandleClientConnected));
|
||||||
|
|
||||||
CIpcClient client(&m_events, TEST_IPC_PORT);
|
CIpcClient client(&m_events, &socketMultiplexer, TEST_IPC_PORT);
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
|
@ -137,17 +132,16 @@ TEST_F(CIpcTests, sendMessageToClient)
|
||||||
new TMethodEventJob<CIpcTests>(
|
new TMethodEventJob<CIpcTests>(
|
||||||
this, &CIpcTests::sendMessageToClient_clientHandleMessageReceived));
|
this, &CIpcTests::sendMessageToClient_clientHandleMessageReceived));
|
||||||
|
|
||||||
initQuitTimeout(5);
|
m_events.initQuitTimeout(5);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.removeHandler(m_events.forCIpcServer().messageReceived(), &server);
|
m_events.removeHandler(m_events.forCIpcServer().messageReceived(), &server);
|
||||||
m_events.removeHandler(m_events.forCIpcClient().messageReceived(), &client);
|
m_events.removeHandler(m_events.forCIpcClient().messageReceived(), &client);
|
||||||
cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
|
|
||||||
EXPECT_EQ("test", m_sendMessageToClient_receivedString);
|
EXPECT_EQ("test", m_sendMessageToClient_receivedString);
|
||||||
}
|
}
|
||||||
|
|
||||||
CIpcTests::CIpcTests() :
|
CIpcTests::CIpcTests() :
|
||||||
m_quitTimeoutTimer(nullptr),
|
|
||||||
m_connectToServer_helloMessageReceived(false),
|
m_connectToServer_helloMessageReceived(false),
|
||||||
m_connectToServer_hasClientNode(false),
|
m_connectToServer_hasClientNode(false),
|
||||||
m_connectToServer_server(nullptr),
|
m_connectToServer_server(nullptr),
|
||||||
|
@ -168,7 +162,7 @@ CIpcTests::connectToServer_handleMessageReceived(const CEvent& e, void*)
|
||||||
m_connectToServer_hasClientNode =
|
m_connectToServer_hasClientNode =
|
||||||
m_connectToServer_server->hasClients(kIpcClientNode);
|
m_connectToServer_server->hasClients(kIpcClientNode);
|
||||||
m_connectToServer_helloMessageReceived = true;
|
m_connectToServer_helloMessageReceived = true;
|
||||||
raiseQuitEvent();
|
m_events.raiseQuitEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +179,7 @@ CIpcTests::sendMessageToServer_serverHandleMessageReceived(const CEvent& e, void
|
||||||
CIpcCommandMessage* cm = static_cast<CIpcCommandMessage*>(m);
|
CIpcCommandMessage* cm = static_cast<CIpcCommandMessage*>(m);
|
||||||
LOG((CLOG_DEBUG "got ipc command message, %d", cm->command().c_str()));
|
LOG((CLOG_DEBUG "got ipc command message, %d", cm->command().c_str()));
|
||||||
m_sendMessageToServer_receivedString = cm->command();
|
m_sendMessageToServer_receivedString = cm->command();
|
||||||
raiseQuitEvent();
|
m_events.raiseQuitEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,37 +202,6 @@ CIpcTests::sendMessageToClient_clientHandleMessageReceived(const CEvent& e, void
|
||||||
CIpcLogLineMessage* llm = static_cast<CIpcLogLineMessage*>(m);
|
CIpcLogLineMessage* llm = static_cast<CIpcLogLineMessage*>(m);
|
||||||
LOG((CLOG_DEBUG "got ipc log message, %d", llm->logLine().c_str()));
|
LOG((CLOG_DEBUG "got ipc log message, %d", llm->logLine().c_str()));
|
||||||
m_sendMessageToClient_receivedString = llm->logLine();
|
m_sendMessageToClient_receivedString = llm->logLine();
|
||||||
raiseQuitEvent();
|
m_events.raiseQuitEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CIpcTests::raiseQuitEvent()
|
|
||||||
{
|
|
||||||
m_events.addEvent(CEvent(CEvent::kQuit));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CIpcTests::initQuitTimeout(double timeout)
|
|
||||||
{
|
|
||||||
assert(m_quitTimeoutTimer == nullptr);
|
|
||||||
m_quitTimeoutTimer = m_events.newOneShotTimer(timeout, NULL);
|
|
||||||
m_events.adoptHandler(CEvent::kTimer, m_quitTimeoutTimer,
|
|
||||||
new TMethodEventJob<CIpcTests>(
|
|
||||||
this, &CIpcTests::handleQuitTimeout));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CIpcTests::cleanupQuitTimeout()
|
|
||||||
{
|
|
||||||
m_events.removeHandler(CEvent::kTimer, m_quitTimeoutTimer);
|
|
||||||
delete m_quitTimeoutTimer;
|
|
||||||
m_quitTimeoutTimer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CIpcTests::handleQuitTimeout(const CEvent&, void* vclient)
|
|
||||||
{
|
|
||||||
LOG((CLOG_ERR "timeout"));
|
|
||||||
raiseQuitEvent();
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,9 +14,16 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
set(h
|
||||||
|
CTestEventQueue.h
|
||||||
|
)
|
||||||
|
|
||||||
set(src
|
set(src
|
||||||
|
${h}
|
||||||
Main.cpp
|
Main.cpp
|
||||||
CIpcTests.cpp
|
CIpcTests.cpp
|
||||||
|
NetworkTests.cpp
|
||||||
|
CTestEventQueue.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
@ -50,11 +57,11 @@ set(inc
|
||||||
../../lib/mt
|
../../lib/mt
|
||||||
../../lib/net
|
../../lib/net
|
||||||
../../lib/platform
|
../../lib/platform
|
||||||
|
../../lib/server
|
||||||
../../lib/synergy
|
../../lib/synergy
|
||||||
../../../tools/gtest-1.6.0/include
|
../../../tools/gtest-1.6.0/include
|
||||||
../../../tools/gmock-1.6.0/include
|
../../../tools/gmock-1.6.0/include
|
||||||
../unittests
|
../unittests
|
||||||
../unittests/synergy
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
|
@ -72,4 +79,4 @@ endif()
|
||||||
include_directories(${inc})
|
include_directories(${inc})
|
||||||
add_executable(integtests ${src})
|
add_executable(integtests ${src})
|
||||||
target_link_libraries(integtests
|
target_link_libraries(integtests
|
||||||
arch base client common io ipc mt net platform server synergy gtest gmock ${libs})
|
arch base client common io ipc mt net platform server synergy gtest gmock cryptopp ${libs})
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CTestEventQueue.h"
|
||||||
|
#include "CLog.h"
|
||||||
|
#include "TMethodEventJob.h"
|
||||||
|
#include "CSimpleEventQueueBuffer.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
CTestEventQueue::raiseQuitEvent()
|
||||||
|
{
|
||||||
|
addEvent(CEvent(CEvent::kQuit));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CTestEventQueue::initQuitTimeout(double timeout)
|
||||||
|
{
|
||||||
|
assert(m_quitTimeoutTimer == nullptr);
|
||||||
|
m_quitTimeoutTimer = newOneShotTimer(timeout, NULL);
|
||||||
|
adoptHandler(CEvent::kTimer, m_quitTimeoutTimer,
|
||||||
|
new TMethodEventJob<CTestEventQueue>(
|
||||||
|
this, &CTestEventQueue::handleQuitTimeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CTestEventQueue::cleanupQuitTimeout()
|
||||||
|
{
|
||||||
|
removeHandler(CEvent::kTimer, m_quitTimeoutTimer);
|
||||||
|
delete m_quitTimeoutTimer;
|
||||||
|
m_quitTimeoutTimer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CTestEventQueue::handleQuitTimeout(const CEvent&, void* vclient)
|
||||||
|
{
|
||||||
|
LOG((CLOG_ERR "timeout"));
|
||||||
|
raiseQuitEvent();
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CEventQueue.h"
|
||||||
|
|
||||||
|
class CEventQueueTimer;
|
||||||
|
|
||||||
|
class CTestEventQueue : public CEventQueue {
|
||||||
|
public:
|
||||||
|
CTestEventQueue() : m_quitTimeoutTimer(nullptr) { }
|
||||||
|
|
||||||
|
void handleQuitTimeout(const CEvent&, void* vclient);
|
||||||
|
void raiseQuitEvent();
|
||||||
|
void initQuitTimeout(double timeout);
|
||||||
|
void cleanupQuitTimeout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void timeoutThread(void*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CEventQueueTimer* m_quitTimeoutTimer;
|
||||||
|
};
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#define TEST_ENV
|
||||||
|
|
||||||
|
#include "CLog.h"
|
||||||
|
#include "CServer.h"
|
||||||
|
#include "CClient.h"
|
||||||
|
#include "TMethodEventJob.h"
|
||||||
|
#include "server/CMockConfig.h"
|
||||||
|
#include "server/CMockPrimaryClient.h"
|
||||||
|
#include "synergy/CMockScreen.h"
|
||||||
|
#include "CClientListener.h"
|
||||||
|
#include "CNetworkAddress.h"
|
||||||
|
#include "CTCPSocketFactory.h"
|
||||||
|
#include "CCryptoOptions.h"
|
||||||
|
#include "CSocketMultiplexer.h"
|
||||||
|
#include "CMSWindowsScreen.h"
|
||||||
|
#include "CGameDevice.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "TMethodJob.h"
|
||||||
|
#include "CTestEventQueue.h"
|
||||||
|
#include "server/CMockInputFilter.h"
|
||||||
|
|
||||||
|
using ::testing::_;
|
||||||
|
using ::testing::NiceMock;
|
||||||
|
using ::testing::Return;
|
||||||
|
using ::testing::Invoke;
|
||||||
|
|
||||||
|
#define TEST_PORT 24803
|
||||||
|
#define TEST_HOST "localhost"
|
||||||
|
|
||||||
|
const int klargeDataSize = 512;
|
||||||
|
char g_largeData[klargeDataSize] = "large data:head.1221412312341244213123fdsfasdawdwadwadacwdd.12321412312341244213123fdsfasdawdwadwadacwdawddawdwacawdawd232141231awddawdwacawdawd2321412312341244213123fdsfasdawdwadacwdawddawdwacawdtrtetawdawdwaewe1213412321412312341244213123fdsfasdawdwadacwdawddawdwacawdawdawdwaewe121341awdwaewedacwdawddawdwacawdawd2321412312341244213123fdsfasdawdwadacwdawddawdwacawdtrtetawdawdwaewe1213412321412312341244213123fdsfasdawdwadacwdawddawdwacawdawdawdwaewe121341awdwaewe12134123njk1u31i2nm3e123hu23oi132213njk.tail";
|
||||||
|
|
||||||
|
void sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h);
|
||||||
|
void sendFileToClient_getCursorPos(SInt32& x, SInt32& y);
|
||||||
|
|
||||||
|
class NetworkTests : public ::testing::Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetworkTests() { }
|
||||||
|
|
||||||
|
void sendData(CServer* server);
|
||||||
|
|
||||||
|
void sendFileToClient_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendFileToClient_fileRecieveComplete(const CEvent&, void*);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CTestEventQueue m_events;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(NetworkTests, sendFileToClient)
|
||||||
|
{
|
||||||
|
// server and client
|
||||||
|
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
||||||
|
CCryptoOptions cryptoOptions;
|
||||||
|
|
||||||
|
serverAddress.resolve();
|
||||||
|
|
||||||
|
// server
|
||||||
|
CSocketMultiplexer serverSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* serverSocketFactory = new CTCPSocketFactory(&m_events, &serverSocketMultiplexer);
|
||||||
|
CClientListener listener(serverAddress, serverSocketFactory, NULL, cryptoOptions, &m_events);
|
||||||
|
NiceMock<CMockScreen> serverScreen;
|
||||||
|
NiceMock<CMockPrimaryClient> primaryClient;
|
||||||
|
NiceMock<CMockConfig> serverConfig;
|
||||||
|
NiceMock<CMockInputFilter> serverInputFilter;
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forCClientListener().connected(), &listener,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendFileToClient_handleClientConnected, &listener));
|
||||||
|
|
||||||
|
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
||||||
|
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
||||||
|
|
||||||
|
CServer server(serverConfig, &primaryClient, &serverScreen, &m_events);
|
||||||
|
server.m_mock = true;
|
||||||
|
listener.setServer(&server);
|
||||||
|
|
||||||
|
// client
|
||||||
|
NiceMock<CMockScreen> clientScreen;
|
||||||
|
CSocketMultiplexer clientSocketMultiplexer;
|
||||||
|
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
||||||
|
|
||||||
|
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(sendFileToClient_getShape));
|
||||||
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(sendFileToClient_getCursorPos));
|
||||||
|
|
||||||
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forIScreen().fileRecieveComplete(), &client,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendFileToClient_fileRecieveComplete));
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
m_events.initQuitTimeout(10);
|
||||||
|
m_events.loop();
|
||||||
|
m_events.cleanupQuitTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendFileToClient_handleClientConnected(const CEvent&, void* vlistener)
|
||||||
|
{
|
||||||
|
CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
|
||||||
|
CServer* server = listener->getServer();
|
||||||
|
|
||||||
|
CClientProxy* client = listener->getNextClient();
|
||||||
|
if (client == NULL) {
|
||||||
|
throw std::exception("client is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
CBaseClientProxy* bcp = reinterpret_cast<CBaseClientProxy*>(client);
|
||||||
|
server->adoptClient(bcp);
|
||||||
|
server->setActive(bcp);
|
||||||
|
|
||||||
|
sendData(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendFileToClient_fileRecieveComplete(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
||||||
|
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
||||||
|
|
||||||
|
m_events.raiseQuitEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendData(CServer* server)
|
||||||
|
{
|
||||||
|
UInt8* largeDataSize = new UInt8[5];
|
||||||
|
largeDataSize[0] = '0';
|
||||||
|
largeDataSize[1] = '5';
|
||||||
|
largeDataSize[2] = '1';
|
||||||
|
largeDataSize[3] = '1';
|
||||||
|
largeDataSize[4] = '\0';
|
||||||
|
|
||||||
|
// transfer data from server -> client
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, largeDataSize));
|
||||||
|
|
||||||
|
UInt8* largeData = new UInt8[klargeDataSize + 1];
|
||||||
|
largeData[0] = '1';
|
||||||
|
memcpy(&largeData[1], g_largeData, klargeDataSize);
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, (UInt8*)largeData));
|
||||||
|
|
||||||
|
UInt8* transferFinished = new UInt8[2];
|
||||||
|
transferFinished[0] = '2';
|
||||||
|
transferFinished[1] = '\0';
|
||||||
|
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, transferFinished));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
w = 1;
|
||||||
|
h = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sendFileToClient_getCursorPos(SInt32& x, SInt32& y)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
}
|
|
@ -27,8 +27,8 @@
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CMSWindowsScreen.h"
|
||||||
#include "CMSWindowsScreenSaver.h"
|
#include "CMSWindowsScreenSaver.h"
|
||||||
#include "TMethodJob.h"
|
#include "TMethodJob.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "synergy/CMockEventQueue.h"
|
||||||
#include "CMockKeyMap.h"
|
#include "synergy/CMockKeyMap.h"
|
||||||
|
|
||||||
// wParam = flags, HIBYTE(lParam) = virtual key, LOBYTE(lParam) = scan code
|
// wParam = flags, HIBYTE(lParam) = virtual key, LOBYTE(lParam) = scan code
|
||||||
#define SYNERGY_MSG_FAKE_KEY SYNERGY_HOOK_LAST_MSG + 4
|
#define SYNERGY_MSG_FAKE_KEY SYNERGY_HOOK_LAST_MSG + 4
|
||||||
|
|
|
@ -22,6 +22,10 @@ set(h
|
||||||
io/CMockStream.h
|
io/CMockStream.h
|
||||||
server/CMockServer.h
|
server/CMockServer.h
|
||||||
io/CMockCryptoStream.h
|
io/CMockCryptoStream.h
|
||||||
|
synergy/CMockScreen.h
|
||||||
|
server/CMockConfig.h
|
||||||
|
server/CMockPrimaryClient.h
|
||||||
|
server/CMockInputFilter.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(src
|
set(src
|
||||||
|
|
|
@ -26,7 +26,6 @@ class CMockCryptoStream : public CCryptoStream
|
||||||
public:
|
public:
|
||||||
CMockCryptoStream(IEventQueue* eventQueue, IStream* stream) :
|
CMockCryptoStream(IEventQueue* eventQueue, IStream* stream) :
|
||||||
CCryptoStream(eventQueue, stream, CCryptoOptions("gcm", "stub"), false) { }
|
CCryptoStream(eventQueue, stream, CCryptoOptions("gcm", "stub"), false) { }
|
||||||
|
|
||||||
MOCK_METHOD2(read, UInt32(void*, UInt32));
|
MOCK_METHOD2(read, UInt32(void*, UInt32));
|
||||||
MOCK_METHOD2(write, void(const void*, UInt32));
|
MOCK_METHOD2(write, void(const void*, UInt32));
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#define TEST_ENV
|
||||||
|
#include "CConfig.h"
|
||||||
|
|
||||||
|
class CMockConfig : public CConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMockConfig() : CConfig() { }
|
||||||
|
MOCK_METHOD0(getInputFilter, CInputFilter*());
|
||||||
|
MOCK_CONST_METHOD1(isScreen, bool(const CString&));
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#define TEST_ENV
|
||||||
|
#include "CInputFilter.h"
|
||||||
|
|
||||||
|
class CMockInputFilter : public CInputFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD1(setPrimaryClient, void(CPrimaryClient*));
|
||||||
|
};
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#define TEST_ENV
|
||||||
|
#include "CPrimaryClient.h"
|
||||||
|
#include "CString.h"
|
||||||
|
|
||||||
|
class CMockPrimaryClient : public CPrimaryClient
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_CONST_METHOD0(getEventTarget, void*());
|
||||||
|
MOCK_CONST_METHOD2(getCursorPos, void(SInt32&, SInt32&));
|
||||||
|
MOCK_CONST_METHOD2(setJumpCursorPos, void(SInt32, SInt32));
|
||||||
|
MOCK_METHOD1(reconfigure, void(UInt32));
|
||||||
|
MOCK_METHOD0(resetOptions, void());
|
||||||
|
MOCK_METHOD1(setOptions, void(const COptionsList&));
|
||||||
|
MOCK_METHOD0(enable, void());
|
||||||
|
MOCK_METHOD0(disable, void());
|
||||||
|
MOCK_METHOD2(registerHotKey, UInt32(KeyID, KeyModifierMask));
|
||||||
|
MOCK_CONST_METHOD0(getToggleMask, KeyModifierMask());
|
||||||
|
MOCK_METHOD1(unregisterHotKey, void(UInt32));
|
||||||
|
};
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2013 Bolton Software Ltd.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#define TEST_ENV
|
||||||
|
#include "CScreen.h"
|
||||||
|
|
||||||
|
class CMockScreen : public CScreen
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMockScreen() : CScreen() { }
|
||||||
|
MOCK_METHOD0(disable, void());
|
||||||
|
MOCK_CONST_METHOD4(getShape, void(SInt32&, SInt32&, SInt32&, SInt32&));
|
||||||
|
MOCK_CONST_METHOD2(getCursorPos, void(SInt32&, SInt32&));
|
||||||
|
MOCK_METHOD0(resetOptions, void());
|
||||||
|
MOCK_METHOD1(setOptions, void(const COptionsList&));
|
||||||
|
MOCK_METHOD0(enable, void());
|
||||||
|
};
|
Loading…
Reference in New Issue