sending IV to client before DKDN, DKUP and DKRP (the most sensitive messages). unit tests to support changes. made crypto stream tests a bit less spammy by using NiceMock.

This commit is contained in:
Nick Bolton 2013-04-09 18:56:19 +00:00
parent 23998fc06c
commit 7010de9cc4
37 changed files with 490 additions and 227 deletions

View File

@ -48,16 +48,12 @@ CEvent::Type CClient::s_connectedEvent = CEvent::kUnknown;
CEvent::Type CClient::s_connectionFailedEvent = CEvent::kUnknown;
CEvent::Type CClient::s_disconnectedEvent = CEvent::kUnknown;
CClient::CClient(IEventQueue& eventQueue) :
m_eventQueue(eventQueue)
{
}
CClient::CClient(IEventQueue& eventQueue,
CClient::CClient(IEventQueue* eventQueue,
const CString& name, const CNetworkAddress& address,
ISocketFactory* socketFactory,
IStreamFilterFactory* streamFilterFactory,
CScreen* screen) :
m_mock(false),
m_name(name),
m_serverAddress(address),
m_socketFactory(socketFactory),
@ -71,25 +67,25 @@ CClient::CClient(IEventQueue& eventQueue,
m_suspended(false),
m_connectOnResume(false),
m_eventQueue(eventQueue),
m_mock(false)
m_cryptoStream(NULL)
{
assert(m_socketFactory != NULL);
assert(m_screen != NULL);
// register suspend/resume event handlers
m_eventQueue.adoptHandler(IScreen::getSuspendEvent(),
m_eventQueue->adoptHandler(IScreen::getSuspendEvent(),
getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleSuspend));
m_eventQueue.adoptHandler(IScreen::getResumeEvent(),
m_eventQueue->adoptHandler(IScreen::getResumeEvent(),
getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleResume));
EVENTQUEUE->adoptHandler(IPlatformScreen::getGameDeviceTimingRespEvent(),
m_eventQueue->adoptHandler(IPlatformScreen::getGameDeviceTimingRespEvent(),
getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleGameDeviceTimingResp));
EVENTQUEUE->adoptHandler(IPlatformScreen::getGameDeviceFeedbackEvent(),
m_eventQueue->adoptHandler(IPlatformScreen::getGameDeviceFeedbackEvent(),
getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleGameDeviceFeedback));
@ -97,13 +93,13 @@ CClient::CClient(IEventQueue& eventQueue,
CClient::~CClient()
{
// HACK: can't disable dtor with mocks
if (m_mock)
if (m_mock) {
return;
}
m_eventQueue.removeHandler(IScreen::getSuspendEvent(),
m_eventQueue->removeHandler(IScreen::getSuspendEvent(),
getEventTarget());
m_eventQueue.removeHandler(IScreen::getResumeEvent(),
m_eventQueue->removeHandler(IScreen::getResumeEvent(),
getEventTarget());
cleanupTimer();
@ -153,9 +149,9 @@ CClient::connect()
m_stream = new CPacketStreamFilter(m_stream, true);
if (s_cryptoEnabled) {
CCryptoStream* cryptoStream = new CCryptoStream(*EVENTQUEUE, m_stream, true);
cryptoStream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
m_stream = cryptoStream;
m_cryptoStream = new CCryptoStream(m_eventQueue, m_stream, true);
m_cryptoStream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
m_stream = m_cryptoStream;
}
// connect
@ -199,6 +195,14 @@ CClient::handshakeComplete()
sendEvent(getConnectedEvent(), NULL);
}
void
CClient::setCryptoIv(const UInt8* iv)
{
if (m_cryptoStream != NULL) {
m_cryptoStream->setIv(iv);
}
}
bool
CClient::isConnected() const
{
@ -444,7 +448,7 @@ CClient::sendClipboard(ClipboardID id)
void
CClient::sendEvent(CEvent::Type type, void* data)
{
m_eventQueue.addEvent(CEvent(type, getEventTarget(), data));
m_eventQueue->addEvent(CEvent(type, getEventTarget(), data));
}
void
@ -453,7 +457,7 @@ CClient::sendConnectionFailedEvent(const char* msg)
CFailInfo* info = new CFailInfo(msg);
info->m_retry = true;
CEvent event(getConnectionFailedEvent(), getEventTarget(), info, CEvent::kDontFreeData);
EVENTQUEUE->addEvent(event);
m_eventQueue->addEvent(event);
}
void
@ -461,11 +465,11 @@ CClient::setupConnecting()
{
assert(m_stream != NULL);
m_eventQueue.adoptHandler(IDataSocket::getConnectedEvent(),
m_eventQueue->adoptHandler(IDataSocket::getConnectedEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleConnected));
m_eventQueue.adoptHandler(IDataSocket::getConnectionFailedEvent(),
m_eventQueue->adoptHandler(IDataSocket::getConnectionFailedEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleConnectionFailed));
@ -476,23 +480,23 @@ CClient::setupConnection()
{
assert(m_stream != NULL);
m_eventQueue.adoptHandler(ISocket::getDisconnectedEvent(),
m_eventQueue->adoptHandler(ISocket::getDisconnectedEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleDisconnected));
m_eventQueue.adoptHandler(m_stream->getInputReadyEvent(),
m_eventQueue->adoptHandler(m_stream->getInputReadyEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleHello));
m_eventQueue.adoptHandler(m_stream->getOutputErrorEvent(),
m_eventQueue->adoptHandler(m_stream->getOutputErrorEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleOutputError));
m_eventQueue.adoptHandler(m_stream->getInputShutdownEvent(),
m_eventQueue->adoptHandler(m_stream->getInputShutdownEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleDisconnected));
m_eventQueue.adoptHandler(m_stream->getOutputShutdownEvent(),
m_eventQueue->adoptHandler(m_stream->getOutputShutdownEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleDisconnected));
@ -504,12 +508,12 @@ CClient::setupScreen()
assert(m_server == NULL);
m_ready = false;
m_server = new CServerProxy(this, m_stream, *EVENTQUEUE);
m_eventQueue.adoptHandler(IScreen::getShapeChangedEvent(),
m_server = new CServerProxy(this, m_stream, m_eventQueue);
m_eventQueue->adoptHandler(IScreen::getShapeChangedEvent(),
getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleShapeChanged));
m_eventQueue.adoptHandler(IScreen::getClipboardGrabbedEvent(),
m_eventQueue->adoptHandler(IScreen::getClipboardGrabbedEvent(),
getEventTarget(),
new TMethodEventJob<CClient>(this,
&CClient::handleClipboardGrabbed));
@ -520,8 +524,8 @@ CClient::setupTimer()
{
assert(m_timer == NULL);
m_timer = m_eventQueue.newOneShotTimer(15.0, NULL);
m_eventQueue.adoptHandler(CEvent::kTimer, m_timer,
m_timer = m_eventQueue->newOneShotTimer(15.0, NULL);
m_eventQueue->adoptHandler(CEvent::kTimer, m_timer,
new TMethodEventJob<CClient>(this,
&CClient::handleConnectTimeout));
}
@ -530,9 +534,9 @@ void
CClient::cleanupConnecting()
{
if (m_stream != NULL) {
m_eventQueue.removeHandler(IDataSocket::getConnectedEvent(),
m_eventQueue->removeHandler(IDataSocket::getConnectedEvent(),
m_stream->getEventTarget());
m_eventQueue.removeHandler(IDataSocket::getConnectionFailedEvent(),
m_eventQueue->removeHandler(IDataSocket::getConnectionFailedEvent(),
m_stream->getEventTarget());
}
}
@ -541,15 +545,15 @@ void
CClient::cleanupConnection()
{
if (m_stream != NULL) {
m_eventQueue.removeHandler(m_stream->getInputReadyEvent(),
m_eventQueue->removeHandler(m_stream->getInputReadyEvent(),
m_stream->getEventTarget());
m_eventQueue.removeHandler(m_stream->getOutputErrorEvent(),
m_eventQueue->removeHandler(m_stream->getOutputErrorEvent(),
m_stream->getEventTarget());
m_eventQueue.removeHandler(m_stream->getInputShutdownEvent(),
m_eventQueue->removeHandler(m_stream->getInputShutdownEvent(),
m_stream->getEventTarget());
m_eventQueue.removeHandler(m_stream->getOutputShutdownEvent(),
m_eventQueue->removeHandler(m_stream->getOutputShutdownEvent(),
m_stream->getEventTarget());
m_eventQueue.removeHandler(ISocket::getDisconnectedEvent(),
m_eventQueue->removeHandler(ISocket::getDisconnectedEvent(),
m_stream->getEventTarget());
delete m_stream;
m_stream = NULL;
@ -564,9 +568,9 @@ CClient::cleanupScreen()
m_screen->disable();
m_ready = false;
}
m_eventQueue.removeHandler(IScreen::getShapeChangedEvent(),
m_eventQueue->removeHandler(IScreen::getShapeChangedEvent(),
getEventTarget());
m_eventQueue.removeHandler(IScreen::getClipboardGrabbedEvent(),
m_eventQueue->removeHandler(IScreen::getClipboardGrabbedEvent(),
getEventTarget());
delete m_server;
m_server = NULL;
@ -577,8 +581,8 @@ void
CClient::cleanupTimer()
{
if (m_timer != NULL) {
m_eventQueue.removeHandler(CEvent::kTimer, m_timer);
m_eventQueue.deleteTimer(m_timer);
m_eventQueue->removeHandler(CEvent::kTimer, m_timer);
m_eventQueue->deleteTimer(m_timer);
m_timer = NULL;
}
}
@ -708,7 +712,7 @@ CClient::handleHello(const CEvent&, void*)
// receive another event for already pending messages so we fake
// one.
if (m_stream->isReady()) {
m_eventQueue.addEvent(CEvent(m_stream->getInputReadyEvent(),
m_eventQueue->addEvent(CEvent(m_stream->getInputReadyEvent(),
m_stream->getEventTarget()));
}
}

View File

@ -32,6 +32,7 @@ class ISocketFactory;
namespace synergy { class IStream; }
class IStreamFilterFactory;
class IEventQueue;
class CCryptoStream;
//! Synergy client
/*!
@ -46,21 +47,22 @@ public:
CString m_what;
};
protected:
CClient(IEventQueue& eventQueue);
public:
/*!
This client will attempt to connect to the server using \p name
as its name and \p address as the server's address and \p factory
to create the socket. \p screen is the local screen.
*/
CClient(IEventQueue& eventQueue,
CClient(IEventQueue* eventQueue,
const CString& name, const CNetworkAddress& address,
ISocketFactory* socketFactory,
IStreamFilterFactory* streamFilterFactory,
CScreen* screen);
~CClient();
#ifdef TEST_ENV
CClient() { }
#endif
//! @name manipulators
//@{
@ -82,7 +84,10 @@ public:
/*!
Notifies the client that the connection handshake has completed.
*/
void handshakeComplete();
virtual void handshakeComplete();
//! Set crypto IV
virtual void setCryptoIv(const UInt8* iv);
//@}
//! @name accessors
@ -190,6 +195,9 @@ private:
void handleGameDeviceTimingResp(const CEvent& event, void*);
void handleGameDeviceFeedback(const CEvent& event, void*);
public:
bool m_mock;
private:
CString m_name;
CNetworkAddress m_serverAddress;
@ -207,8 +215,8 @@ private:
bool m_sentClipboard[kClipboardEnd];
IClipboard::Time m_timeClipboard[kClipboardEnd];
CString m_dataClipboard[kClipboardEnd];
IEventQueue& m_eventQueue;
bool m_mock;
IEventQueue* m_eventQueue;
CCryptoStream* m_cryptoStream;
static CEvent::Type s_connectedEvent;
static CEvent::Type s_connectionFailedEvent;

View File

@ -35,10 +35,9 @@
// CServerProxy
//
CServerProxy::CServerProxy(CClient* client, synergy::IStream* stream, IEventQueue& eventQueue) :
CServerProxy::CServerProxy(CClient* client, synergy::IStream* stream, IEventQueue* eventQueue) :
m_client(client),
m_stream(stream),
m_cryptoStream(NULL),
m_seqNum(0),
m_compressMouse(false),
m_compressMouseRelative(false),
@ -60,7 +59,7 @@ CServerProxy::CServerProxy(CClient* client, synergy::IStream* stream, IEventQueu
m_modifierTranslationTable[id] = id;
// handle data on stream
m_eventQueue.adoptHandler(m_stream->getInputReadyEvent(),
m_eventQueue->adoptHandler(m_stream->getInputReadyEvent(),
m_stream->getEventTarget(),
new TMethodEventJob<CServerProxy>(this,
&CServerProxy::handleData));
@ -72,7 +71,7 @@ CServerProxy::CServerProxy(CClient* client, synergy::IStream* stream, IEventQueu
CServerProxy::~CServerProxy()
{
setKeepAliveRate(-1.0);
m_eventQueue.removeHandler(m_stream->getInputReadyEvent(),
m_eventQueue->removeHandler(m_stream->getInputReadyEvent(),
m_stream->getEventTarget());
}
@ -80,14 +79,14 @@ void
CServerProxy::resetKeepAliveAlarm()
{
if (m_keepAliveAlarmTimer != NULL) {
m_eventQueue.removeHandler(CEvent::kTimer, m_keepAliveAlarmTimer);
m_eventQueue.deleteTimer(m_keepAliveAlarmTimer);
m_eventQueue->removeHandler(CEvent::kTimer, m_keepAliveAlarmTimer);
m_eventQueue->deleteTimer(m_keepAliveAlarmTimer);
m_keepAliveAlarmTimer = NULL;
}
if (m_keepAliveAlarm > 0.0) {
m_keepAliveAlarmTimer =
m_eventQueue.newOneShotTimer(m_keepAliveAlarm, NULL);
m_eventQueue.adoptHandler(CEvent::kTimer, m_keepAliveAlarmTimer,
m_eventQueue->newOneShotTimer(m_keepAliveAlarm, NULL);
m_eventQueue->adoptHandler(CEvent::kTimer, m_keepAliveAlarmTimer,
new TMethodEventJob<CServerProxy>(this,
&CServerProxy::handleKeepAliveAlarm));
}
@ -306,6 +305,10 @@ CServerProxy::parseMessage(const UInt8* code)
gameDeviceTimingReq();
}
else if (memcmp(code, kMsgDCryptoIv, 4) == 0) {
cryptoIv();
}
else if (memcmp(code, kMsgCClose, 4) == 0) {
// server wants us to hangup
LOG((CLOG_DEBUG1 "recv close"));
@ -826,6 +829,18 @@ CServerProxy::gameDeviceTimingReq()
m_client->gameDeviceTimingReq();
}
void
CServerProxy::cryptoIv()
{
// parse
CString s;
CProtocolUtil::readf(m_stream, kMsgDCryptoIv + 4, &s);
LOG((CLOG_DEBUG2 "recv crypto iv size=%i", s.size()));
// forward
m_client->setCryptoIv(reinterpret_cast<const UInt8*>(s.c_str()));
}
void
CServerProxy::screensaver()
{

View File

@ -30,7 +30,6 @@ class CEventQueueTimer;
class IClipboard;
namespace synergy { class IStream; }
class IEventQueue;
class CCryptoStream;
//! Proxy for server
/*!
@ -43,7 +42,7 @@ public:
Process messages from the server on \p stream and forward to
\p client.
*/
CServerProxy(CClient* client, synergy::IStream* stream, IEventQueue& eventQueue);
CServerProxy(CClient* client, synergy::IStream* stream, IEventQueue* eventQueue);
~CServerProxy();
//! @name manipulators
@ -57,6 +56,10 @@ public:
//@}
#ifdef TEST_ENV
void handleDataForTest() { handleData(NULL, NULL); }
#endif
protected:
enum EResult { kOkay, kUnknown, kDisconnect };
EResult parseHandshakeMessage(const UInt8* code);
@ -96,6 +99,7 @@ private:
void gameDeviceSticks();
void gameDeviceTriggers();
void gameDeviceTimingReq();
void cryptoIv();
void screensaver();
void resetOptions();
void setOptions();
@ -107,7 +111,6 @@ private:
CClient* m_client;
synergy::IStream* m_stream;
CCryptoStream* m_cryptoStream;
UInt32 m_seqNum;
@ -124,7 +127,7 @@ private:
CEventQueueTimer* m_keepAliveAlarmTimer;
MessageParser m_parser;
IEventQueue& m_eventQueue;
IEventQueue* m_eventQueue;
};
#endif

View File

@ -24,21 +24,21 @@
// CStreamFilter
//
CStreamFilter::CStreamFilter(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream) :
CStreamFilter::CStreamFilter(IEventQueue* eventQueue, synergy::IStream* stream, bool adoptStream) :
IStream(eventQueue),
m_stream(stream),
m_adopted(adoptStream)
{
// replace handlers for m_stream
m_eventQueue.removeHandlers(m_stream->getEventTarget());
m_eventQueue.adoptHandler(CEvent::kUnknown, m_stream->getEventTarget(),
getEventQueue().removeHandlers(m_stream->getEventTarget());
getEventQueue().adoptHandler(CEvent::kUnknown, m_stream->getEventTarget(),
new TMethodEventJob<CStreamFilter>(this,
&CStreamFilter::handleUpstreamEvent));
}
CStreamFilter::~CStreamFilter()
{
m_eventQueue.removeHandler(CEvent::kUnknown, m_stream->getEventTarget());
getEventQueue().removeHandler(CEvent::kUnknown, m_stream->getEventTarget());
if (m_adopted) {
delete m_stream;
}
@ -107,7 +107,7 @@ CStreamFilter::getStream() const
void
CStreamFilter::filterEvent(const CEvent& event)
{
m_eventQueue.dispatchEvent(CEvent(event.getType(),
getEventQueue().dispatchEvent(CEvent(event.getType(),
getEventTarget(), event.getData()));
}

View File

@ -34,7 +34,7 @@ public:
this object takes ownership of the stream and will delete it in the
d'tor.
*/
CStreamFilter(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream = true);
CStreamFilter(IEventQueue* eventQueue, synergy::IStream* stream, bool adoptStream = true);
virtual ~CStreamFilter();
// IStream overrides

View File

@ -34,34 +34,41 @@ CEvent::Type IStream::s_outputShutdownEvent = CEvent::kUnknown;
CEvent::Type
IStream::getInputReadyEvent()
{
return m_eventQueue.registerTypeOnce(s_inputReadyEvent,
return m_eventQueue->registerTypeOnce(s_inputReadyEvent,
"IStream::inputReady");
}
CEvent::Type
IStream::getOutputFlushedEvent()
{
return m_eventQueue.registerTypeOnce(s_outputFlushedEvent,
return m_eventQueue->registerTypeOnce(s_outputFlushedEvent,
"IStream::outputFlushed");
}
CEvent::Type
IStream::getOutputErrorEvent()
{
return m_eventQueue.registerTypeOnce(s_outputErrorEvent,
return m_eventQueue->registerTypeOnce(s_outputErrorEvent,
"IStream::outputError");
}
CEvent::Type
IStream::getInputShutdownEvent()
{
return m_eventQueue.registerTypeOnce(s_inputShutdownEvent,
return m_eventQueue->registerTypeOnce(s_inputShutdownEvent,
"IStream::inputShutdown");
}
CEvent::Type
IStream::getOutputShutdownEvent()
{
return m_eventQueue.registerTypeOnce(s_outputShutdownEvent,
return m_eventQueue->registerTypeOnce(s_outputShutdownEvent,
"IStream::outputShutdown");
}
IEventQueue&
IStream::getEventQueue() const
{
assert(m_eventQueue != NULL);
return *m_eventQueue;
}

View File

@ -33,8 +33,8 @@ Defines the interface for all streams.
*/
class IStream : public IInterface {
public:
IStream() : m_eventQueue(*EVENTQUEUE) { }
IStream(IEventQueue& eventQueue) : m_eventQueue(eventQueue) { }
IStream() : m_eventQueue(EVENTQUEUE) { }
IStream(IEventQueue* eventQueue) : m_eventQueue(eventQueue) { }
//! @name manipulators
//@{
@ -156,9 +156,10 @@ public:
*/
virtual CEvent::Type getOutputShutdownEvent();
//@}
//! Get the event queue
IEventQueue& getEventQueue() const;
IEventQueue& m_eventQueue;
//@}
private:
static CEvent::Type s_inputReadyEvent;
@ -166,6 +167,8 @@ private:
static CEvent::Type s_outputErrorEvent;
static CEvent::Type s_inputShutdownEvent;
static CEvent::Type s_outputShutdownEvent;
IEventQueue* m_eventQueue;
};
}

View File

@ -150,7 +150,7 @@ CClientListener::handleClientConnecting(const CEvent&, void*)
stream = new CPacketStreamFilter(stream, true);
if (s_cryptoEnabled) {
CCryptoStream* cryptoStream = new CCryptoStream(*EVENTQUEUE, stream, true);
CCryptoStream* cryptoStream = new CCryptoStream(EVENTQUEUE, stream, true);
cryptoStream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
stream = cryptoStream;
}

View File

@ -25,8 +25,6 @@
namespace synergy { class IStream; }
const int g_encryptionEnabled = true;
//! Generic proxy for client
class CClientProxy : public CBaseClientProxy {
public:
@ -49,12 +47,6 @@ public:
//! @name accessors
//@{
//! Get stream (unmodified)
/*!
Returns the original stream passed to the c'tor.
*/
synergy::IStream* getStreamUnmodified() const;
//! Get stream
/*!
Returns a crypto stream if the user has this enabled,
@ -125,6 +117,7 @@ public:
virtual void gameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2) = 0;
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2) = 0;
virtual void gameDeviceTimingReq() = 0;
virtual void cryptoIv(const UInt8* iv) = 0;
private:
synergy::IStream* m_stream;

View File

@ -29,29 +29,30 @@
// CClientProxy1_0
//
CClientProxy1_0::CClientProxy1_0(const CString& name, synergy::IStream* stream) :
CClientProxy1_0::CClientProxy1_0(const CString& name, synergy::IStream* stream, IEventQueue* eventQueue) :
CClientProxy(name, stream),
m_heartbeatTimer(NULL),
m_parser(&CClientProxy1_0::parseHandshakeMessage)
m_parser(&CClientProxy1_0::parseHandshakeMessage),
m_eventQueue(eventQueue)
{
// install event handlers
EVENTQUEUE->adoptHandler(stream->getInputReadyEvent(),
m_eventQueue->adoptHandler(stream->getInputReadyEvent(),
stream->getEventTarget(),
new TMethodEventJob<CClientProxy1_0>(this,
&CClientProxy1_0::handleData, NULL));
EVENTQUEUE->adoptHandler(stream->getOutputErrorEvent(),
m_eventQueue->adoptHandler(stream->getOutputErrorEvent(),
stream->getEventTarget(),
new TMethodEventJob<CClientProxy1_0>(this,
&CClientProxy1_0::handleWriteError, NULL));
EVENTQUEUE->adoptHandler(stream->getInputShutdownEvent(),
m_eventQueue->adoptHandler(stream->getInputShutdownEvent(),
stream->getEventTarget(),
new TMethodEventJob<CClientProxy1_0>(this,
&CClientProxy1_0::handleDisconnect, NULL));
EVENTQUEUE->adoptHandler(stream->getOutputShutdownEvent(),
m_eventQueue->adoptHandler(stream->getOutputShutdownEvent(),
stream->getEventTarget(),
new TMethodEventJob<CClientProxy1_0>(this,
&CClientProxy1_0::handleWriteError, NULL));
EVENTQUEUE->adoptHandler(CEvent::kTimer, this,
m_eventQueue->adoptHandler(CEvent::kTimer, this,
new TMethodEventJob<CClientProxy1_0>(this,
&CClientProxy1_0::handleFlatline, NULL));
@ -71,22 +72,22 @@ CClientProxy1_0::disconnect()
{
removeHandlers();
getStream()->close();
EVENTQUEUE->addEvent(CEvent(getDisconnectedEvent(), getEventTarget()));
m_eventQueue->addEvent(CEvent(getDisconnectedEvent(), getEventTarget()));
}
void
CClientProxy1_0::removeHandlers()
{
// uninstall event handlers
EVENTQUEUE->removeHandler(getStream()->getInputReadyEvent(),
m_eventQueue->removeHandler(getStream()->getInputReadyEvent(),
getStream()->getEventTarget());
EVENTQUEUE->removeHandler(getStream()->getOutputErrorEvent(),
m_eventQueue->removeHandler(getStream()->getOutputErrorEvent(),
getStream()->getEventTarget());
EVENTQUEUE->removeHandler(getStream()->getInputShutdownEvent(),
m_eventQueue->removeHandler(getStream()->getInputShutdownEvent(),
getStream()->getEventTarget());
EVENTQUEUE->removeHandler(getStream()->getOutputShutdownEvent(),
m_eventQueue->removeHandler(getStream()->getOutputShutdownEvent(),
getStream()->getEventTarget());
EVENTQUEUE->removeHandler(CEvent::kTimer, this);
m_eventQueue->removeHandler(CEvent::kTimer, this);
// remove timer
removeHeartbeatTimer();
@ -96,7 +97,7 @@ void
CClientProxy1_0::addHeartbeatTimer()
{
if (m_heartbeatAlarm > 0.0) {
m_heartbeatTimer = EVENTQUEUE->newOneShotTimer(m_heartbeatAlarm, this);
m_heartbeatTimer = m_eventQueue->newOneShotTimer(m_heartbeatAlarm, this);
}
}
@ -104,7 +105,7 @@ void
CClientProxy1_0::removeHeartbeatTimer()
{
if (m_heartbeatTimer != NULL) {
EVENTQUEUE->deleteTimer(m_heartbeatTimer);
m_eventQueue->deleteTimer(m_heartbeatTimer);
m_heartbeatTimer = NULL;
}
}
@ -171,7 +172,7 @@ CClientProxy1_0::parseHandshakeMessage(const UInt8* code)
// future messages get parsed by parseMessage
m_parser = &CClientProxy1_0::parseMessage;
if (recvInfo()) {
EVENTQUEUE->addEvent(CEvent(getReadyEvent(), getEventTarget()));
m_eventQueue->addEvent(CEvent(getReadyEvent(), getEventTarget()));
addHeartbeatTimer();
return true;
}
@ -184,7 +185,7 @@ CClientProxy1_0::parseMessage(const UInt8* code)
{
if (memcmp(code, kMsgDInfo, 4) == 0) {
if (recvInfo()) {
EVENTQUEUE->addEvent(
m_eventQueue->addEvent(
CEvent(getShapeChangedEvent(), getEventTarget()));
return true;
}
@ -385,6 +386,13 @@ CClientProxy1_0::gameDeviceTimingReq()
LOG((CLOG_DEBUG "gameDeviceTimingReq not supported"));
}
void
CClientProxy1_0::cryptoIv(const UInt8* iv)
{
// ignore -- not supported in protocol 1.0
LOG((CLOG_DEBUG "cryptoIv not supported"));
}
void
CClientProxy1_0::screensaver(bool on)
{
@ -484,7 +492,7 @@ CClientProxy1_0::recvClipboard()
CClipboardInfo* info = new CClipboardInfo;
info->m_id = id;
info->m_sequenceNumber = seqNum;
EVENTQUEUE->addEvent(CEvent(getClipboardChangedEvent(),
m_eventQueue->addEvent(CEvent(getClipboardChangedEvent(),
getEventTarget(), info));
return true;
@ -510,7 +518,7 @@ CClientProxy1_0::recvGrabClipboard()
CClipboardInfo* info = new CClipboardInfo;
info->m_id = id;
info->m_sequenceNumber = seqNum;
EVENTQUEUE->addEvent(CEvent(getClipboardGrabbedEvent(),
m_eventQueue->addEvent(CEvent(getClipboardGrabbedEvent(),
getEventTarget(), info));
return true;

View File

@ -25,11 +25,12 @@
class CEvent;
class CEventQueueTimer;
class IEventQueue;
//! Proxy for client implementing protocol version 1.0
class CClientProxy1_0 : public CClientProxy {
public:
CClientProxy1_0(const CString& name, synergy::IStream* adoptedStream);
CClientProxy1_0(const CString& name, synergy::IStream* adoptedStream, IEventQueue* eventQueue);
~CClientProxy1_0();
// IScreen
@ -62,6 +63,7 @@ public:
virtual void gameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
virtual void gameDeviceTimingReq();
virtual void cryptoIv(const UInt8* iv);
protected:
virtual bool parseHandshakeMessage(const UInt8* code);
@ -103,6 +105,7 @@ private:
double m_heartbeatAlarm;
CEventQueueTimer* m_heartbeatTimer;
MessageParser m_parser;
IEventQueue* m_eventQueue;
};
#endif

View File

@ -25,8 +25,8 @@
// CClientProxy1_1
//
CClientProxy1_1::CClientProxy1_1(const CString& name, synergy::IStream* stream) :
CClientProxy1_0(name, stream)
CClientProxy1_1::CClientProxy1_1(const CString& name, synergy::IStream* stream, IEventQueue* eventQueue) :
CClientProxy1_0(name, stream, eventQueue)
{
// do nothing
}

View File

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

View File

@ -24,8 +24,8 @@
// CClientProxy1_1
//
CClientProxy1_2::CClientProxy1_2(const CString& name, synergy::IStream* stream) :
CClientProxy1_1(name, stream)
CClientProxy1_2::CClientProxy1_2(const CString& name, synergy::IStream* stream, IEventQueue* eventQueue) :
CClientProxy1_1(name, stream, eventQueue)
{
// do nothing
}

View File

@ -21,10 +21,12 @@
#include "CClientProxy1_1.h"
class IEventQueue;
//! Proxy for client implementing protocol version 1.2
class CClientProxy1_2 : public CClientProxy1_1 {
public:
CClientProxy1_2(const CString& name, synergy::IStream* adoptedStream);
CClientProxy1_2(const CString& name, synergy::IStream* adoptedStream, IEventQueue* eventQueue);
~CClientProxy1_2();
// IClient overrides

View File

@ -28,8 +28,8 @@
// CClientProxy1_3
//
CClientProxy1_3::CClientProxy1_3(const CString& name, synergy::IStream* stream) :
CClientProxy1_2(name, stream),
CClientProxy1_3::CClientProxy1_3(const CString& name, synergy::IStream* stream, IEventQueue* eventQueue) :
CClientProxy1_2(name, stream, eventQueue),
m_keepAliveRate(kKeepAliveRate),
m_keepAliveTimer(NULL)
{

View File

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

View File

@ -24,13 +24,14 @@
#include <cstring>
#include <memory>
#include "CServer.h"
#include "CCryptoStream.h"
//
// CClientProxy1_4
//
CClientProxy1_4::CClientProxy1_4(const CString& name, synergy::IStream* stream, CServer* server) :
CClientProxy1_3(name, stream), m_server(server)
CClientProxy1_4::CClientProxy1_4(const CString& name, synergy::IStream* stream, CServer* server, IEventQueue* eventQueue) :
CClientProxy1_3(name, stream, eventQueue), m_server(server)
{
assert(m_server != NULL);
}
@ -67,6 +68,43 @@ CClientProxy1_4::gameDeviceTimingReq()
CProtocolUtil::writef(getStream(), kMsgCGameTimingReq);
}
void
CClientProxy1_4::keyDown(KeyID key, KeyModifierMask mask, KeyButton button)
{
cryptoIv();
CClientProxy1_3::keyDown(key, mask, button);
}
void
CClientProxy1_4::keyRepeat(KeyID key, KeyModifierMask mask, SInt32 count, KeyButton button)
{
cryptoIv();
CClientProxy1_3::keyRepeat(key, mask, count, button);
}
void
CClientProxy1_4::keyUp(KeyID key, KeyModifierMask mask, KeyButton button)
{
cryptoIv();
CClientProxy1_3::keyUp(key, mask, button);
}
void
CClientProxy1_4::cryptoIv()
{
CCryptoStream* cryptoStream = dynamic_cast<CCryptoStream*>(getStream());
if (cryptoStream == NULL) {
return;
}
byte iv[CRYPTO_IV_SIZE];
cryptoStream->newIv(iv);
CString data(reinterpret_cast<const char*>(iv), CRYPTO_IV_SIZE);
LOG((CLOG_DEBUG2 "send crypto iv change to \"%s\"", getName().c_str()));
CProtocolUtil::writef(getStream(), kMsgDCryptoIv, &data);
}
bool
CClientProxy1_4::parseMessage(const UInt8* code)
{

View File

@ -26,7 +26,7 @@ class CServer;
//! Proxy for client implementing protocol version 1.4
class CClientProxy1_4 : public CClientProxy1_3 {
public:
CClientProxy1_4(const CString& name, synergy::IStream* adoptedStream, CServer* server);
CClientProxy1_4(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* eventQueue);
~CClientProxy1_4();
// IClient overrides
@ -34,6 +34,12 @@ public:
virtual void gameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
virtual void gameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2);
virtual void gameDeviceTimingReq();
virtual void keyDown(KeyID key, KeyModifierMask mask, KeyButton button);
virtual void keyRepeat(KeyID key, KeyModifierMask mask, SInt32 count, KeyButton button);
virtual void keyUp(KeyID key, KeyModifierMask mask, KeyButton button);
//! Send IV to make
void cryptoIv();
protected:
// CClientProxy overrides

View File

@ -219,23 +219,23 @@ CClientProxyUnknown::handleData(const CEvent&, void*)
if (major == 1) {
switch (minor) {
case 0:
m_proxy = new CClientProxy1_0(name, m_stream);
m_proxy = new CClientProxy1_0(name, m_stream, EVENTQUEUE);
break;
case 1:
m_proxy = new CClientProxy1_1(name, m_stream);
m_proxy = new CClientProxy1_1(name, m_stream, EVENTQUEUE);
break;
case 2:
m_proxy = new CClientProxy1_2(name, m_stream);
m_proxy = new CClientProxy1_2(name, m_stream, EVENTQUEUE);
break;
case 3:
m_proxy = new CClientProxy1_3(name, m_stream);
m_proxy = new CClientProxy1_3(name, m_stream, EVENTQUEUE);
break;
case 4:
m_proxy = new CClientProxy1_4(name, m_stream, m_server);
m_proxy = new CClientProxy1_4(name, m_stream, m_server, EVENTQUEUE);
break;
}
}

View File

@ -51,6 +51,7 @@ CEvent::Type CServer::s_lockCursorToScreen = CEvent::kUnknown;
CEvent::Type CServer::s_screenSwitched = CEvent::kUnknown;
CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen* screen) :
m_mock(false),
m_primaryClient(primaryClient),
m_active(primaryClient),
m_seqNum(0),
@ -202,6 +203,10 @@ CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen*
CServer::~CServer()
{
if (m_mock) {
return;
}
// remove event handlers and timers
EVENTQUEUE->removeHandler(IPlatformScreen::getKeyDownEvent(*EVENTQUEUE),
m_inputFilter);

View File

@ -103,6 +103,10 @@ public:
*/
CServer(const CConfig& config, CPrimaryClient* primaryClient, CScreen* screen);
~CServer();
#ifdef TEST_ENV
CServer() { }
#endif
//! @name manipulators
//@{
@ -394,6 +398,9 @@ private:
// force the cursor off of \p client
void forceLeaveClient(CBaseClientProxy* client);
public:
bool m_mock;
private:
class CClipboardInfo {

View File

@ -396,7 +396,7 @@ CClient*
CClientApp::openClient(const CString& name, const CNetworkAddress& address, CScreen* screen)
{
CClient* client = new CClient(
*EVENTQUEUE, name, address, new CTCPSocketFactory, NULL, screen);
EVENTQUEUE, name, address, new CTCPSocketFactory, NULL, screen);
try {
EVENTQUEUE->adoptHandler(

View File

@ -22,7 +22,7 @@
using namespace CryptoPP;
CCryptoStream::CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream) :
CCryptoStream::CCryptoStream(IEventQueue* eventQueue, synergy::IStream* stream, bool adoptStream) :
CStreamFilter(eventQueue, stream, adoptStream),
m_key(NULL),
m_keyLength(0)

View File

@ -32,7 +32,7 @@ Encrypts (on write) and decrypts (on read) to and from an underlying stream.
*/
class CCryptoStream : public CStreamFilter {
public:
CCryptoStream(IEventQueue& eventQueue, synergy::IStream* stream, bool adoptStream = true);
CCryptoStream(IEventQueue* eventQueue, synergy::IStream* stream, bool adoptStream = true);
virtual ~CCryptoStream();
//! @name manipulators

View File

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

View File

@ -50,6 +50,7 @@ const char* kMsgDGameButtons = "DGBT%1i%2i";
const char* kMsgDGameSticks = "DGST%1i%2i%2i%2i%2i";
const char* kMsgDGameTriggers = "DGTR%1i%1i%1i";
const char* kMsgDGameFeedback = "DGFB%1i%2i%2i";
const char* kMsgDCryptoIv = "DCIV%s";
const char* kMsgQInfo = "QINF";
const char* kMsgEIncompatible = "EICV%2i%2i";
const char* kMsgEBusy = "EBSY";

View File

@ -283,6 +283,11 @@ extern const char* kMsgDInfo;
// pairs.
extern const char* kMsgDSetOptions;
// crypto iv: primary -> secondary
// sends a new iv (initialization vector) to the client for the
// cryptography stream.
extern const char* kMsgDCryptoIv;
//
// query codes
//

View File

@ -20,6 +20,8 @@ set(h
synergy/CMockKeyMap.h
client/CMockClient.h
io/CMockStream.h
server/CMockServer.h
io/CMockCryptoStream.h
)
set(src
@ -29,12 +31,14 @@ set(src
synergy/CKeyStateTests.cpp
client/CServerProxyTests.cpp
synergy/CCryptoStreamTests.cpp
server/CClientProxyTests.cpp
)
set(inc
../../lib/arch
../../lib/base
../../lib/client
../../lib/server
../../lib/common
../../lib/io
../../lib/mt
@ -63,4 +67,4 @@ endif()
include_directories(${inc})
add_executable(unittests ${src})
target_link_libraries(unittests
arch base client common io net platform server synergy mt gtest gmock cryptopp ${libs})
arch base client server common io net platform server synergy mt gtest gmock cryptopp ${libs})

View File

@ -19,6 +19,8 @@
#pragma once
#include <gmock/gmock.h>
#define TEST_ENV
#include "CClient.h"
class IEventQueue;
@ -26,6 +28,9 @@ class IEventQueue;
class CMockClient : public CClient
{
public:
CMockClient(IEventQueue& eventQueue) : CClient(eventQueue) { m_mock = true; }
CMockClient() { m_mock = true; }
MOCK_METHOD2(mouseMove, void(SInt32, SInt32));
MOCK_METHOD1(setOptions, void(const COptionsList&));
MOCK_METHOD0(handshakeComplete, void());
MOCK_METHOD1(setCryptoIv, void(const UInt8*));
};

View File

@ -16,11 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
#define TEST_ENV
#include "Global.h"
#include <gtest/gtest.h>
#include "CServerProxy.h"
#include "CMockClient.h"
#include "CMockStream.h"
@ -32,60 +30,77 @@ using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::AnyNumber;
int streamReads = 0;
const UInt8 mouseMove_bufferLen = 16;
UInt8 mouseMove_buffer[mouseMove_bufferLen];
UInt32 mouseMove_bufferIndex = 0;
UInt32 mouseMove_mockRead(void* buffer, UInt32 n);
UInt32
streamRead(void* buffer, UInt32 n);
const UInt8 cryptoIv_bufferLen = 20;
UInt8 cryptoIv_buffer[cryptoIv_bufferLen];
UInt32 cryptoIv_bufferIndex = 0;
CString cryptoIv_result;
UInt32 cryptoIv_mockRead(void* buffer, UInt32 n);
void cryptoIv_setCryptoIv(const UInt8*);
// TODO: fix linking in windows (works in unix for some reason).
#if 0
TEST(CServerProxyTests, parseMessage_mouseMove_valuesCorrect)
TEST(CServerProxyTests, mouseMove)
{
NiceMock<CMockEventQueue> eventQueue;
CMockClient client(eventQueue);
CMockStream stream(eventQueue);
NiceMock<CMockClient> client;
NiceMock<CMockStream> stream;
ON_CALL(stream, read(_, _)).WillByDefault(Invoke(streamRead));
EXPECT_CALL(stream, read(_, _)).Times(4);
EXPECT_CALL(stream, write(_, _)).Times(1);
EXPECT_CALL(stream, isReady()).Times(1);
EXPECT_CALL(stream, getEventTarget()).Times(AnyNumber());
ON_CALL(stream, read(_, _)).WillByDefault(Invoke(mouseMove_mockRead));
EXPECT_CALL(client, mouseMove(1, 2)).Times(1);
const char data[] = "DSOP\0\0\0\0DMMV\0\1\0\2";
memcpy(mouseMove_buffer, data, sizeof(data));
CServerProxy serverProxy(&client, &stream, eventQueue);
// skip handshake, go straight to normal parser.
serverProxy.m_parser = &CServerProxy::parseMessage;
// assert
EXPECT_CALL(client, mouseMove(10, 20));
serverProxy.handleData(NULL, NULL);
CServerProxy serverProxy(&client, &stream, &eventQueue);
serverProxy.handleDataForTest();
}
TEST(CServerProxyTests, cryptoIv)
{
NiceMock<CMockEventQueue> eventQueue;
NiceMock<CMockClient> client;
NiceMock<CMockStream> stream;
ON_CALL(stream, read(_, _)).WillByDefault(Invoke(cryptoIv_mockRead));
ON_CALL(client, setCryptoIv(_)).WillByDefault(Invoke(cryptoIv_setCryptoIv));
const char data[] = "DSOP\0\0\0\0DCIV\0\0\0\4mock";
memcpy(cryptoIv_buffer, data, sizeof(data));
CServerProxy serverProxy(&client, &stream, &eventQueue);
serverProxy.handleDataForTest();
EXPECT_EQ("mock", cryptoIv_result);
}
#endif
UInt32
streamRead(void* buffer, UInt32 n)
mouseMove_mockRead(void* buffer, UInt32 n)
{
streamReads++;
UInt8* code = (UInt8*)buffer;
if (streamReads == 1) {
code[0] = 'D';
code[1] = 'M';
code[2] = 'M';
code[3] = 'V';
return 4;
if (mouseMove_bufferIndex >= mouseMove_bufferLen) {
return 0;
}
else if (streamReads == 2) {
code[0] = 0;
code[1] = 10;
return 2;
}
else if (streamReads == 3) {
code[0] = 0;
code[1] = 20;
return 2;
}
return 0;
memcpy(buffer, &mouseMove_buffer[mouseMove_bufferIndex], n);
mouseMove_bufferIndex += n;
return n;
}
UInt32
cryptoIv_mockRead(void* buffer, UInt32 n)
{
if (cryptoIv_bufferIndex >= cryptoIv_bufferLen) {
return 0;
}
memcpy(buffer, &cryptoIv_buffer[cryptoIv_bufferIndex], n);
cryptoIv_bufferIndex += n;
return n;
}
void
cryptoIv_setCryptoIv(const UInt8* data)
{
cryptoIv_result = reinterpret_cast<const char*>(data);
}

View File

@ -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>
#include "CCryptoStream.h"
class CMockCryptoStream : public CCryptoStream
{
public:
CMockCryptoStream(IEventQueue* eventQueue, IStream* stream) : CCryptoStream(eventQueue, stream, false) { }
MOCK_METHOD2(read, UInt32(void*, UInt32));
MOCK_METHOD2(write, void(const void*, UInt32));
};

View File

@ -26,13 +26,17 @@ class IEventQueue;
class CMockStream : public synergy::IStream
{
public:
CMockStream(IEventQueue& eventQueue) : IStream(eventQueue) { }
CMockStream() : synergy::IStream(NULL) { }
MOCK_METHOD0(close, void());
MOCK_METHOD2(read, UInt32(void*, UInt32));
MOCK_METHOD2(write, void(const void*, UInt32));
MOCK_METHOD0(flush, void());
MOCK_METHOD0(shutdownInput, void());
MOCK_METHOD0(shutdownOutput, void());
MOCK_METHOD0(getInputReadyEvent, CEvent::Type());
MOCK_METHOD0(getOutputErrorEvent, CEvent::Type());
MOCK_METHOD0(getInputShutdownEvent, CEvent::Type());
MOCK_METHOD0(getOutputShutdownEvent, CEvent::Type());
MOCK_CONST_METHOD0(getEventTarget, void*());
MOCK_CONST_METHOD0(isReady, bool());
MOCK_CONST_METHOD0(getSize, UInt32());

View File

@ -0,0 +1,96 @@
/*
* 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 "CClientProxy1_4.h"
#include "CMockServer.h"
#include "CMockStream.h"
#include "CMockCryptoStream.h"
#include "CMockEventQueue.h"
using ::testing::_;
using ::testing::NiceMock;
using ::testing::Invoke;
const byte g_key[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; // +\0, 32-byte/256-bit key.
const byte g_iv[] = "bbbbbbbbbbbbbb"; // +\0, AES block size = 16
const UInt8 cryptoIvWrite_bufferLen = 200;
UInt8 cryptoIvWrite_buffer[cryptoIvWrite_bufferLen];
UInt32 cryptoIvWrite_bufferIndex = 0;
void
cryptoIv_mockWrite(const void* in, UInt32 n);
TEST(CClientProxyTests, cryptoIvWrite)
{
NiceMock<CMockEventQueue> eventQueue;
NiceMock<CMockStream> innerStream;
NiceMock<CMockServer> server;
NiceMock<CMockCryptoStream>* stream = new NiceMock<CMockCryptoStream>(&eventQueue, &innerStream);
stream->setKeyWithIv(g_key, sizeof(g_key), g_iv);
ON_CALL(*stream, write(_, _)).WillByDefault(Invoke(cryptoIv_mockWrite));
CClientProxy1_4 clientProxy("stub", stream, &server, &eventQueue);
// DCIV, then DKDN.
cryptoIvWrite_bufferIndex = 0;
clientProxy.keyDown(1, 2, 3);
EXPECT_EQ('D', cryptoIvWrite_buffer[0]);
EXPECT_EQ('C', cryptoIvWrite_buffer[1]);
EXPECT_EQ('I', cryptoIvWrite_buffer[2]);
EXPECT_EQ('V', cryptoIvWrite_buffer[3]);
EXPECT_EQ('D', cryptoIvWrite_buffer[24]);
EXPECT_EQ('K', cryptoIvWrite_buffer[25]);
EXPECT_EQ('D', cryptoIvWrite_buffer[26]);
EXPECT_EQ('N', cryptoIvWrite_buffer[27]);
// DCIV, then DKUP.
cryptoIvWrite_bufferIndex = 0;
clientProxy.keyUp(1, 2, 3);
EXPECT_EQ('D', cryptoIvWrite_buffer[0]);
EXPECT_EQ('C', cryptoIvWrite_buffer[1]);
EXPECT_EQ('I', cryptoIvWrite_buffer[2]);
EXPECT_EQ('V', cryptoIvWrite_buffer[3]);
EXPECT_EQ('D', cryptoIvWrite_buffer[24]);
EXPECT_EQ('K', cryptoIvWrite_buffer[25]);
EXPECT_EQ('U', cryptoIvWrite_buffer[26]);
EXPECT_EQ('P', cryptoIvWrite_buffer[27]);
// DCIV, then DKRP.
cryptoIvWrite_bufferIndex = 0;
clientProxy.keyRepeat(1, 2, 4, 4);
EXPECT_EQ('D', cryptoIvWrite_buffer[0]);
EXPECT_EQ('C', cryptoIvWrite_buffer[1]);
EXPECT_EQ('I', cryptoIvWrite_buffer[2]);
EXPECT_EQ('V', cryptoIvWrite_buffer[3]);
EXPECT_EQ('D', cryptoIvWrite_buffer[24]);
EXPECT_EQ('K', cryptoIvWrite_buffer[25]);
EXPECT_EQ('R', cryptoIvWrite_buffer[26]);
EXPECT_EQ('P', cryptoIvWrite_buffer[27]);
}
void
cryptoIv_mockWrite(const void* in, UInt32 n)
{
if (cryptoIvWrite_bufferIndex >= cryptoIvWrite_bufferLen) {
return;
}
memcpy(&cryptoIvWrite_buffer[cryptoIvWrite_bufferIndex], in, n);
cryptoIvWrite_bufferIndex += n;
}

View File

@ -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 "CServer.h"
class IEventQueue;
class CMockServer : public CServer
{
public:
CMockServer() : CServer() { }
};

View File

@ -23,6 +23,7 @@
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
using namespace std;
@ -64,17 +65,12 @@ TEST(CCryptoTests, write)
buffer[2] = 'D';
buffer[3] = 'N';
CMockEventQueue eventQueue;
CMockStream innerStream(eventQueue);
NiceMock<CMockEventQueue> eventQueue;
NiceMock<CMockStream> innerStream;
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write_mockWrite));
EXPECT_CALL(innerStream, write(_, _)).Times(1);
EXPECT_CALL(innerStream, getEventTarget()).Times(3);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(1);
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
CCryptoStream cs(eventQueue, &innerStream, false);
CCryptoStream cs(&eventQueue, &innerStream, false);
cs.setKeyWithIv(g_key, sizeof(g_key), g_iv);
cs.write(buffer, size);
@ -86,17 +82,12 @@ TEST(CCryptoTests, write)
TEST(CCryptoTests, read)
{
CMockEventQueue eventQueue;
CMockStream innerStream(eventQueue);
NiceMock<CMockEventQueue> eventQueue;
NiceMock<CMockStream> innerStream;
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(read_mockRead));
EXPECT_CALL(innerStream, read(_, _)).Times(1);
EXPECT_CALL(innerStream, getEventTarget()).Times(3);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(1);
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(1);
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(1);
CCryptoStream cs(eventQueue, &innerStream, false);
CCryptoStream cs(&eventQueue, &innerStream, false);
cs.setKeyWithIv(g_key, sizeof(g_key), g_iv);
g_read_buffer[0] = 254;
@ -116,19 +107,13 @@ TEST(CCryptoTests, read)
TEST(CCryptoTests, write4Read1)
{
CMockEventQueue eventQueue;
CMockStream innerStream(eventQueue);
NiceMock<CMockEventQueue> eventQueue;
NiceMock<CMockStream> innerStream;
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write4Read1_mockWrite));
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(write4Read1_mockRead));
EXPECT_CALL(innerStream, write(_, _)).Times(4);
EXPECT_CALL(innerStream, read(_, _)).Times(1);
EXPECT_CALL(innerStream, getEventTarget()).Times(6);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(2);
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(2);
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
CCryptoStream cs1(eventQueue, &innerStream, false);
CCryptoStream cs1(&eventQueue, &innerStream, false);
cs1.setKeyWithIv(g_key, sizeof(g_key), g_iv);
cs1.write("a", 1);
@ -136,7 +121,7 @@ TEST(CCryptoTests, write4Read1)
cs1.write("c", 1);
cs1.write("d", 1);
CCryptoStream cs2(eventQueue, &innerStream, false);
CCryptoStream cs2(&eventQueue, &innerStream, false);
cs2.setKeyWithIv(g_key, sizeof(g_key), g_iv);
UInt8 buffer[4];
@ -150,19 +135,13 @@ TEST(CCryptoTests, write4Read1)
TEST(CCryptoTests, write1Read4)
{
CMockEventQueue eventQueue;
CMockStream innerStream(eventQueue);
NiceMock<CMockEventQueue> eventQueue;
NiceMock<CMockStream> innerStream;
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(write1Read4_mockWrite));
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(write1Read4_mockRead));
EXPECT_CALL(innerStream, write(_, _)).Times(1);
EXPECT_CALL(innerStream, read(_, _)).Times(4);
EXPECT_CALL(innerStream, getEventTarget()).Times(6);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(2);
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(2);
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
CCryptoStream cs1(eventQueue, &innerStream, false);
CCryptoStream cs1(&eventQueue, &innerStream, false);
cs1.setKeyWithIv(g_key, sizeof(g_key), g_iv);
UInt8 bufferIn[4];
@ -172,7 +151,7 @@ TEST(CCryptoTests, write1Read4)
bufferIn[3] = 'd';
cs1.write(bufferIn, 4);
CCryptoStream cs2(eventQueue, &innerStream, false);
CCryptoStream cs2(&eventQueue, &innerStream, false);
cs2.setKeyWithIv(g_key, sizeof(g_key), g_iv);
UInt8 bufferOut[4];
@ -189,22 +168,16 @@ TEST(CCryptoTests, write1Read4)
TEST(CCryptoTests, readWriteIvChanged)
{
CMockEventQueue eventQueue;
CMockStream innerStream(eventQueue);
NiceMock<CMockEventQueue> eventQueue;
NiceMock<CMockStream> innerStream;
ON_CALL(innerStream, write(_, _)).WillByDefault(Invoke(readWriteIvChanged_mockWrite));
ON_CALL(innerStream, read(_, _)).WillByDefault(Invoke(readWriteIvChanged_mockRead));
EXPECT_CALL(innerStream, write(_, _)).Times(2);
EXPECT_CALL(innerStream, read(_, _)).Times(2);
EXPECT_CALL(innerStream, getEventTarget()).Times(6);
EXPECT_CALL(eventQueue, removeHandlers(_)).Times(2);
EXPECT_CALL(eventQueue, adoptHandler(_, _, _)).Times(2);
EXPECT_CALL(eventQueue, removeHandler(_, _)).Times(2);
const byte iv1[] = "bbbbbbbbbbbbbbb";
const byte iv2[] = "ccccccccccccccc";
CCryptoStream cs1(eventQueue, &innerStream, false);
CCryptoStream cs1(&eventQueue, &innerStream, false);
cs1.setKeyWithIv(g_key, sizeof(g_key), iv1);
UInt8 bufferIn[4];
@ -214,7 +187,7 @@ TEST(CCryptoTests, readWriteIvChanged)
bufferIn[3] = 'd';
cs1.write(bufferIn, 4);
CCryptoStream cs2(eventQueue, &innerStream, false);
CCryptoStream cs2(&eventQueue, &innerStream, false);
cs2.setKeyWithIv(g_key, sizeof(g_key), iv2);
UInt8 bufferOut[4];
@ -296,8 +269,6 @@ readWriteIvChanged_mockRead(void* out, UInt32 n)
return n;
}
// TODO: macro?
void
readWriteIvChangeTrigger_mockWrite(const void* in, UInt32 n)
{