Patch by Jerry:
- Fixed line endings - Integ test for file transfer - Fixed crashed problem when log info is larger than 2048 bytes - Fixed compile error caused by std exception (by Feng ye) - Fixed include path on Mac and linux (by Feng ye)
This commit is contained in:
parent
c368013f13
commit
394ece004a
|
@ -178,7 +178,7 @@ CLog::print(const char* file, int line, const char* fmt, ...)
|
||||||
// do not prefix time and file for kPRINT (CLOG_PRINT)
|
// do not prefix time and file for kPRINT (CLOG_PRINT)
|
||||||
if (priority != kPRINT) {
|
if (priority != kPRINT) {
|
||||||
|
|
||||||
char message[2048];
|
char message[kLogMessageLength];
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
|
|
@ -137,6 +137,8 @@ private:
|
||||||
int m_maxPriority;
|
int m_maxPriority;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const UInt16 kLogMessageLength = 2048;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\def LOG(arg)
|
\def LOG(arg)
|
||||||
Write to the log. Because macros cannot accept variable arguments, this
|
Write to the log. Because macros cannot accept variable arguments, this
|
||||||
|
|
|
@ -33,14 +33,20 @@
|
||||||
#include "CArch.h"
|
#include "CArch.h"
|
||||||
#include "IPlatformScreen.h"
|
#include "IPlatformScreen.h"
|
||||||
#include "CCryptoStream.h"
|
#include "CCryptoStream.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "TMethodJob.h"
|
||||||
|
#include "CFileChunker.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CClient
|
// CClient
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const size_t CClient::m_chunkSize = 1024 * 512; // 512kb
|
||||||
|
|
||||||
CClient::CClient(IEventQueue* events,
|
CClient::CClient(IEventQueue* events,
|
||||||
const CString& name, const CNetworkAddress& address,
|
const CString& name, const CNetworkAddress& address,
|
||||||
ISocketFactory* socketFactory,
|
ISocketFactory* socketFactory,
|
||||||
|
@ -438,6 +444,17 @@ CClient::sendConnectionFailedEvent(const char* msg)
|
||||||
m_events->addEvent(event);
|
m_events->addEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::sendFileChunk(const void* data)
|
||||||
|
{
|
||||||
|
CFileChunker::CFileChunk* fileChunk = reinterpret_cast<CFileChunker::CFileChunk*>(const_cast<void*>(data));
|
||||||
|
LOG((CLOG_DEBUG1 "sendFileChunk"));
|
||||||
|
assert(m_server != NULL);
|
||||||
|
|
||||||
|
// relay
|
||||||
|
m_server->fileChunkSending(fileChunk->m_chunk[0], &(fileChunk->m_chunk[1]), fileChunk->m_dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClient::setupConnecting()
|
CClient::setupConnecting()
|
||||||
{
|
{
|
||||||
|
@ -737,6 +754,7 @@ CClient::handleGameDeviceFeedback(const CEvent& event, void*)
|
||||||
void
|
void
|
||||||
CClient::handleFileChunkSending(const CEvent& event, void*)
|
CClient::handleFileChunkSending(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
|
sendFileChunk(event.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -763,3 +781,24 @@ CClient::isReceivedFileSizeValid()
|
||||||
{
|
{
|
||||||
return m_expectedFileSize == m_receivedFileData.size();
|
return m_expectedFileSize == m_receivedFileData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::sendFileToServer(const char* filename)
|
||||||
|
{
|
||||||
|
CThread* thread = new CThread(
|
||||||
|
new TMethodJob<CClient>(
|
||||||
|
this, &CClient::sendFileThread,
|
||||||
|
reinterpret_cast<void*>(const_cast<char*>(filename))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClient::sendFileThread(void* filename)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
char* name = reinterpret_cast<char*>(filename);
|
||||||
|
CFileChunker::sendFileChunks(name, m_events, this);
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
LOG((CLOG_ERR "failed sending file chunks: %s", error.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -101,8 +101,8 @@ public:
|
||||||
//! Received a chunk of file data
|
//! Received a chunk of file data
|
||||||
void fileChunkReceived(CString data);
|
void fileChunkReceived(CString data);
|
||||||
|
|
||||||
//! Return true if recieved file size is valid
|
//! Create a new thread and use it to send file to Server
|
||||||
bool isReceivedFileSizeValid();
|
void sendFileToServer(const char* filename);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
|
@ -128,6 +128,9 @@ public:
|
||||||
*/
|
*/
|
||||||
CNetworkAddress getServerAddress() const;
|
CNetworkAddress getServerAddress() const;
|
||||||
|
|
||||||
|
//! Return true if recieved file size is valid
|
||||||
|
bool isReceivedFileSizeValid();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
// IScreen overrides
|
// IScreen overrides
|
||||||
|
@ -167,6 +170,8 @@ private:
|
||||||
void sendClipboard(ClipboardID);
|
void sendClipboard(ClipboardID);
|
||||||
void sendEvent(CEvent::Type, void*);
|
void sendEvent(CEvent::Type, void*);
|
||||||
void sendConnectionFailedEvent(const char* msg);
|
void sendConnectionFailedEvent(const char* msg);
|
||||||
|
void sendFileChunk(const void* data);
|
||||||
|
void sendFileThread(void*);
|
||||||
void setupConnecting();
|
void setupConnecting();
|
||||||
void setupConnection();
|
void setupConnection();
|
||||||
void setupScreen();
|
void setupScreen();
|
||||||
|
@ -214,6 +219,7 @@ private:
|
||||||
CCryptoOptions m_crypto;
|
CCryptoOptions m_crypto;
|
||||||
std::size_t m_expectedFileSize;
|
std::size_t m_expectedFileSize;
|
||||||
CString m_receivedFileData;
|
CString m_receivedFileData;
|
||||||
|
static const size_t m_chunkSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -935,7 +935,8 @@ CServerProxy::infoAcknowledgment()
|
||||||
m_ignoreMouse = false;
|
m_ignoreMouse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerProxy::fileChunkReceived()
|
void
|
||||||
|
CServerProxy::fileChunkReceived()
|
||||||
{
|
{
|
||||||
// parse
|
// parse
|
||||||
UInt8 mark;
|
UInt8 mark;
|
||||||
|
@ -943,20 +944,42 @@ void CServerProxy::fileChunkReceived()
|
||||||
CProtocolUtil::readf(m_stream, kMsgDFileTransfer + 4, &mark, &content);
|
CProtocolUtil::readf(m_stream, kMsgDFileTransfer + 4, &mark, &content);
|
||||||
|
|
||||||
switch (mark) {
|
switch (mark) {
|
||||||
case '0':
|
case kFileStart:
|
||||||
LOG((CLOG_DEBUG2 "recv file data: file size = %s", content));
|
LOG((CLOG_DEBUG2 "recv file data from server: size=%s", content.c_str()));
|
||||||
m_client->clearReceivedFileData();
|
m_client->clearReceivedFileData();
|
||||||
m_client->setExpectedFileSize(content);
|
m_client->setExpectedFileSize(content);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case kFileChunk:
|
||||||
LOG((CLOG_DEBUG2 "recv file data: chunck size = %i", content.size()));
|
LOG((CLOG_DEBUG2 "recv file data from server: size=%i", content.size()));
|
||||||
m_client->fileChunkReceived(content);
|
m_client->fileChunkReceived(content);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '2':
|
case kFileEnd:
|
||||||
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
||||||
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), m_client));
|
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), m_client));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServerProxy::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
|
{
|
||||||
|
CString chunk(data, dataSize);
|
||||||
|
|
||||||
|
switch (mark) {
|
||||||
|
case kFileStart:
|
||||||
|
LOG((CLOG_DEBUG2 "file sending start: size=%s", data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileChunk:
|
||||||
|
LOG((CLOG_DEBUG2 "file chunk sending: size=%i", chunk.size()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileEnd:
|
||||||
|
LOG((CLOG_DEBUG2 "file sending finished"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CProtocolUtil::writef(m_stream, kMsgDFileTransfer, mark, &chunk);
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,14 @@ public:
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
//! @file transfer
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! sending file chunk to server
|
||||||
|
void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
#ifdef TEST_ENV
|
#ifdef TEST_ENV
|
||||||
void handleDataForTest() { handleData(CEvent(), NULL); }
|
void handleDataForTest() { handleData(CEvent(), NULL); }
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -83,7 +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 void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
||||||
virtual CString getName() const;
|
virtual CString getName() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -89,7 +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;
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
synergy::IStream* m_stream;
|
synergy::IStream* m_stream;
|
||||||
|
|
|
@ -394,7 +394,7 @@ CClientProxy1_0::cryptoIv(const UInt8* iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_0::fileChunkSending(UInt8 mark, const UInt8* iv)
|
CClientProxy1_0::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
// ignore -- not supported in protocol 1.0
|
// ignore -- not supported in protocol 1.0
|
||||||
LOG((CLOG_DEBUG "fileChunkSending not supported"));
|
LOG((CLOG_DEBUG "fileChunkSending not supported"));
|
||||||
|
|
|
@ -64,7 +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);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool parseHandshakeMessage(const UInt8* code);
|
virtual bool parseHandshakeMessage(const UInt8* code);
|
||||||
|
|
|
@ -42,7 +42,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
void handleKeepAlive(const CEvent&, void*);
|
void handleKeepAlive(const CEvent&, void*);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double m_keepAliveRate;
|
double m_keepAliveRate;
|
||||||
CEventQueueTimer* m_keepAliveTimer;
|
CEventQueueTimer* m_keepAliveTimer;
|
||||||
|
|
|
@ -29,6 +29,14 @@ public:
|
||||||
CClientProxy1_4(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
CClientProxy1_4(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
||||||
~CClientProxy1_4();
|
~CClientProxy1_4();
|
||||||
|
|
||||||
|
//! @name accessors
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! get server pointer
|
||||||
|
CServer* getServer() { return m_server; }
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
// IClient overrides
|
// IClient overrides
|
||||||
virtual void gameDeviceButtons(GameDeviceID id, GameDeviceButton buttons);
|
virtual void gameDeviceButtons(GameDeviceID id, GameDeviceButton buttons);
|
||||||
virtual void gameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
virtual void gameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2);
|
||||||
|
|
|
@ -19,13 +19,15 @@
|
||||||
#include "CProtocolUtil.h"
|
#include "CProtocolUtil.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include "IStream.h"
|
#include "IStream.h"
|
||||||
|
#include "CServer.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// CClientProxy1_5
|
// CClientProxy1_5
|
||||||
//
|
//
|
||||||
|
|
||||||
CClientProxy1_5::CClientProxy1_5(const CString& name, synergy::IStream* stream, CServer* server, IEventQueue* events) :
|
CClientProxy1_5::CClientProxy1_5(const CString& name, synergy::IStream* stream, CServer* server, IEventQueue* events) :
|
||||||
CClientProxy1_4(name, stream, server, events)
|
CClientProxy1_4(name, stream, server, events),
|
||||||
|
m_events(events)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,23 +36,64 @@ CClientProxy1_5::~CClientProxy1_5()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_5::fileChunkSending(UInt8 mark, const UInt8* data)
|
CClientProxy1_5::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
CString chunk(reinterpret_cast<const char*>(data));
|
CString chunk(data, dataSize);
|
||||||
|
|
||||||
switch (mark) {
|
switch (mark) {
|
||||||
case '0':
|
case kFileStart:
|
||||||
LOG((CLOG_DEBUG2 "file sending start: file size = %s", data));
|
LOG((CLOG_DEBUG2 "file sending start: size=%s", data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case kFileChunk:
|
||||||
LOG((CLOG_DEBUG2 "file chunk sending: %s", data));
|
LOG((CLOG_DEBUG2 "file chunk sending: size=%i", chunk.size()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '2':
|
case kFileEnd:
|
||||||
LOG((CLOG_DEBUG2 "file sending finished"));
|
LOG((CLOG_DEBUG2 "file sending finished"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CProtocolUtil::writef(getStream(), kMsgDFileTransfer, mark, &chunk);
|
CProtocolUtil::writef(getStream(), kMsgDFileTransfer, mark, &chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CClientProxy1_5::parseMessage(const UInt8* code)
|
||||||
|
{
|
||||||
|
if (memcmp(code, kMsgDFileTransfer, 4) == 0) {
|
||||||
|
fileChunkReceived();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return CClientProxy1_4::parseMessage(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CClientProxy1_5::fileChunkReceived()
|
||||||
|
{
|
||||||
|
// parse
|
||||||
|
UInt8 mark;
|
||||||
|
CString content;
|
||||||
|
CProtocolUtil::readf(getStream(), kMsgDFileTransfer + 4, &mark, &content);
|
||||||
|
|
||||||
|
CServer* server = getServer();
|
||||||
|
switch (mark) {
|
||||||
|
case kFileStart:
|
||||||
|
LOG((CLOG_DEBUG2 "recv file data from client: file size=%s", content.c_str()));
|
||||||
|
server->clearReceivedFileData();
|
||||||
|
server->setExpectedFileSize(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileChunk:
|
||||||
|
LOG((CLOG_DEBUG2 "recv file data from client: chunck size=%i", content.size()));
|
||||||
|
server->fileChunkReceived(content);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kFileEnd:
|
||||||
|
LOG((CLOG_DEBUG2 "file data transfer finished"));
|
||||||
|
m_events->addEvent(CEvent(m_events->forIScreen().fileRecieveComplete(), server));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,5 +28,10 @@ public:
|
||||||
CClientProxy1_5(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
CClientProxy1_5(const CString& name, synergy::IStream* adoptedStream, CServer* server, IEventQueue* events);
|
||||||
~CClientProxy1_5();
|
~CClientProxy1_5();
|
||||||
|
|
||||||
virtual void fileChunkSending(UInt8 mark, const UInt8* data);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
virtual bool parseMessage(const UInt8* code);
|
||||||
|
void fileChunkReceived();
|
||||||
|
|
||||||
|
private:
|
||||||
|
IEventQueue* m_events;
|
||||||
};
|
};
|
||||||
|
|
|
@ -274,7 +274,7 @@ CPrimaryClient::screensaver(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CPrimaryClient::fileChunkSending(UInt8 mark, const UInt8* data)
|
CPrimaryClient::fileChunkSending(UInt8 mark, char* data, size_t dataSize)
|
||||||
{
|
{
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ 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);
|
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CScreen* m_screen;
|
CScreen* m_screen;
|
||||||
|
|
|
@ -33,14 +33,22 @@
|
||||||
#include "TMethodEventJob.h"
|
#include "TMethodEventJob.h"
|
||||||
#include "CArch.h"
|
#include "CArch.h"
|
||||||
#include "CKeyState.h"
|
#include "CKeyState.h"
|
||||||
|
#include "CScreen.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "TMethodJob.h"
|
||||||
|
#include "CFileChunker.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "CScreen.h"
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CServer
|
// CServer
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const size_t CServer::m_chunkSize = 1024 * 512; // 512kb
|
||||||
|
|
||||||
CServer::CServer(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),
|
||||||
|
@ -177,6 +185,10 @@ CServer::CServer(CConfig& config, CPrimaryClient* primaryClient, CScreen* screen
|
||||||
this,
|
this,
|
||||||
new TMethodEventJob<CServer>(this,
|
new TMethodEventJob<CServer>(this,
|
||||||
&CServer::handleFileChunkSendingEvent));
|
&CServer::handleFileChunkSendingEvent));
|
||||||
|
m_events->adoptHandler(m_events->forIScreen().fileRecieveComplete(),
|
||||||
|
this,
|
||||||
|
new TMethodEventJob<CServer>(this,
|
||||||
|
&CServer::handleFileRecieveCompleteEvent));
|
||||||
|
|
||||||
// add connection
|
// add connection
|
||||||
addClient(m_primaryClient);
|
addClient(m_primaryClient);
|
||||||
|
@ -1516,8 +1528,13 @@ CServer::handleFakeInputEndEvent(const CEvent&, void*)
|
||||||
void
|
void
|
||||||
CServer::handleFileChunkSendingEvent(const CEvent& event, void*)
|
CServer::handleFileChunkSendingEvent(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
UInt8* data = reinterpret_cast<UInt8*>(event.getData());
|
onFileChunkSending(event.getData());
|
||||||
onFileChunkSending(data);
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::handleFileRecieveCompleteEvent(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
onFileRecieveComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1981,13 +1998,32 @@ CServer::onGameDeviceTimingReq()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CServer::onFileChunkSending(const UInt8* data)
|
CServer::onFileChunkSending(const void* data)
|
||||||
{
|
{
|
||||||
|
CFileChunker::CFileChunk* fileChunk = reinterpret_cast<CFileChunker::CFileChunk*>(const_cast<void*>(data));
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "onFileChunkSending"));
|
LOG((CLOG_DEBUG1 "onFileChunkSending"));
|
||||||
assert(m_active != NULL);
|
assert(m_active != NULL);
|
||||||
|
|
||||||
// relay
|
// relay
|
||||||
m_active->fileChunkSending(data[0], &data[1]);
|
m_active->fileChunkSending(fileChunk->m_chunk[0], &(fileChunk->m_chunk[1]), fileChunk->m_dataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::onFileRecieveComplete()
|
||||||
|
{
|
||||||
|
if (isReceivedFileSizeValid()) {
|
||||||
|
if (!m_fileTransferDes.empty()) {
|
||||||
|
std::fstream file;
|
||||||
|
file.open(m_fileTransferDes.c_str(), std::ios::out | std::ios::binary);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
// TODO: file open failed
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(m_receivedFileData.c_str(), m_receivedFileData.size());
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -2260,3 +2296,49 @@ CServer::CKeyboardBroadcastInfo::alloc(State state, const CString& screens)
|
||||||
strcpy(info->m_screens, screens.c_str());
|
strcpy(info->m_screens, screens.c_str());
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::clearReceivedFileData()
|
||||||
|
{
|
||||||
|
m_receivedFileData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::setExpectedFileSize(CString data)
|
||||||
|
{
|
||||||
|
std::istringstream iss(data);
|
||||||
|
iss >> m_expectedFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::fileChunkReceived(CString data)
|
||||||
|
{
|
||||||
|
m_receivedFileData += data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CServer::isReceivedFileSizeValid()
|
||||||
|
{
|
||||||
|
return m_expectedFileSize == m_receivedFileData.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::sendFileToClient(const char* filename)
|
||||||
|
{
|
||||||
|
CThread* thread = new CThread(
|
||||||
|
new TMethodJob<CServer>(
|
||||||
|
this, &CServer::sendFileThread,
|
||||||
|
reinterpret_cast<void*>(const_cast<char*>(filename))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CServer::sendFileThread(void* filename)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
char* name = reinterpret_cast<char*>(filename);
|
||||||
|
CFileChunker::sendFileChunks(name, m_events, this);
|
||||||
|
}
|
||||||
|
catch (std::runtime_error error) {
|
||||||
|
LOG((CLOG_ERR "failed sending file chunks: %s", error.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -144,6 +144,21 @@ public:
|
||||||
//! Notify of game device feedback
|
//! Notify of game device feedback
|
||||||
void gameDeviceFeedback(GameDeviceID id, UInt16 m1, UInt16 m2);
|
void gameDeviceFeedback(GameDeviceID id, UInt16 m1, UInt16 m2);
|
||||||
|
|
||||||
|
//! Clears the file buffer
|
||||||
|
void clearReceivedFileData();
|
||||||
|
|
||||||
|
//! Set the expected size of receiving file
|
||||||
|
void setExpectedFileSize(CString data);
|
||||||
|
|
||||||
|
//! Set
|
||||||
|
void setFileTransferDes(CString& des) { m_fileTransferDes = des; }
|
||||||
|
|
||||||
|
//! Received a chunk of file data
|
||||||
|
void fileChunkReceived(CString data);
|
||||||
|
|
||||||
|
//! Create a new thread and use it to send file to client
|
||||||
|
void sendFileToClient(const char* filename);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -160,6 +175,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void getClients(std::vector<CString>& list) const;
|
void getClients(std::vector<CString>& list) const;
|
||||||
|
|
||||||
|
//! Return true if recieved file size is valid
|
||||||
|
bool isReceivedFileSizeValid();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -299,6 +317,7 @@ private:
|
||||||
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*);
|
void handleFileChunkSendingEvent(const CEvent&, void*);
|
||||||
|
void handleFileRecieveCompleteEvent(const CEvent&, void*);
|
||||||
|
|
||||||
// event processing
|
// event processing
|
||||||
void onClipboardChanged(CBaseClientProxy* sender,
|
void onClipboardChanged(CBaseClientProxy* sender,
|
||||||
|
@ -318,7 +337,8 @@ 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);
|
void onFileChunkSending(const void* data);
|
||||||
|
void onFileRecieveComplete();
|
||||||
|
|
||||||
// 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*);
|
||||||
|
@ -343,6 +363,9 @@ private:
|
||||||
// force the cursor off of \p client
|
// force the cursor off of \p client
|
||||||
void forceLeaveClient(CBaseClientProxy* client);
|
void forceLeaveClient(CBaseClientProxy* client);
|
||||||
|
|
||||||
|
// thread funciton for sending file
|
||||||
|
void sendFileThread(void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_mock;
|
bool m_mock;
|
||||||
|
|
||||||
|
@ -438,6 +461,13 @@ private:
|
||||||
CScreen* m_screen;
|
CScreen* m_screen;
|
||||||
|
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
|
|
||||||
|
// file transfer
|
||||||
|
size_t m_expectedFileSize;
|
||||||
|
CString m_receivedFileData;
|
||||||
|
static const size_t m_chunkSize;
|
||||||
|
CString m_fileTransferSrc;
|
||||||
|
CString m_fileTransferDes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -171,6 +171,14 @@ CApp::parseArg(const int& argc, const char* const* argv, int& i)
|
||||||
argsBase().m_crypto.setMode(argv[++i]);
|
argsBase().m_crypto.setMode(argv[++i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (isArg(i, argc, argv, NULL, "--filetransfer-src")) {
|
||||||
|
m_fileTransferSrc = argv[++i];
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (isArg(i, argc, argv, NULL, "--filetransfer-des")) {
|
||||||
|
m_fileTransferDes = argv[++i];
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
// option not supported here
|
// option not supported here
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -101,6 +101,9 @@ public:
|
||||||
void setSocketMultiplexer(CSocketMultiplexer* sm) { m_socketMultiplexer = sm; }
|
void setSocketMultiplexer(CSocketMultiplexer* sm) { m_socketMultiplexer = sm; }
|
||||||
CSocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
|
CSocketMultiplexer* getSocketMultiplexer() const { return m_socketMultiplexer; }
|
||||||
|
|
||||||
|
CString& getFileTransferSrc() { return m_fileTransferSrc; }
|
||||||
|
CString& getFileTransferDes() { return m_fileTransferDes; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleIpcMessage(const CEvent&, void*);
|
void handleIpcMessage(const CEvent&, void*);
|
||||||
|
|
||||||
|
@ -122,6 +125,8 @@ private:
|
||||||
CIpcClient* m_ipcClient;
|
CIpcClient* m_ipcClient;
|
||||||
IEventQueue* m_events;
|
IEventQueue* m_events;
|
||||||
CSocketMultiplexer* m_socketMultiplexer;
|
CSocketMultiplexer* m_socketMultiplexer;
|
||||||
|
CString m_fileTransferSrc;
|
||||||
|
CString m_fileTransferDes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BYE "\nTry `%s --help' for more information."
|
#define BYE "\nTry `%s --help' for more information."
|
||||||
|
|
|
@ -349,6 +349,14 @@ CClientApp::handleClientConnected(const CEvent&, void*)
|
||||||
LOG((CLOG_NOTE "connected to server"));
|
LOG((CLOG_NOTE "connected to server"));
|
||||||
resetRestartTimeout();
|
resetRestartTimeout();
|
||||||
updateStatus();
|
updateStatus();
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO: remove testing code for relase
|
||||||
|
CString fileFullDir = getFileTransferSrc();
|
||||||
|
if (!fileFullDir.empty()) {
|
||||||
|
s_client->sendFileToServer(getFileTransferSrc().c_str());
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -473,6 +481,7 @@ CClientApp::startClient()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s_client->connect();
|
s_client->connect();
|
||||||
|
|
||||||
updateStatus();
|
updateStatus();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* 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 "CFileChunker.h"
|
||||||
|
#include "BasicTypes.h"
|
||||||
|
#include "ProtocolTypes.h"
|
||||||
|
#include "CEvent.h"
|
||||||
|
#include "IEventQueue.h"
|
||||||
|
#include "CEventTypes.h"
|
||||||
|
#include "CLOG.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
const size_t CFileChunker::m_chunkSize = 512 * 1024; // 512kb
|
||||||
|
|
||||||
|
void
|
||||||
|
CFileChunker::sendFileChunks(char* filename, IEventQueue* events, void* eventTarget)
|
||||||
|
{
|
||||||
|
std::fstream file(reinterpret_cast<char*>(filename), std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!file.is_open()) {
|
||||||
|
throw runtime_error("failed to open file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check file size
|
||||||
|
file.seekg (0, std::ios::end);
|
||||||
|
size_t size = (size_t)file.tellg();
|
||||||
|
|
||||||
|
// send first message (file size)
|
||||||
|
CString fileSize = intToString(size);
|
||||||
|
UInt32 sizeLength = fileSize.size();
|
||||||
|
CFileChunk* sizeMessage = new CFileChunk(sizeLength + 2);
|
||||||
|
char* chunkData = sizeMessage->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileStart;
|
||||||
|
memcpy(&chunkData[1], fileSize.c_str(), sizeLength);
|
||||||
|
chunkData[sizeLength + 1] = '\0';
|
||||||
|
events->addEvent(CEvent(events->forIScreen().fileChunkSending(), eventTarget, sizeMessage));
|
||||||
|
|
||||||
|
// send chunk messages with a fixed chunk size
|
||||||
|
size_t sentLength = 0;
|
||||||
|
size_t chunkSize = m_chunkSize;
|
||||||
|
file.seekg (0, std::ios::beg);
|
||||||
|
while (true) {
|
||||||
|
// make sure we don't read too much from the mock data.
|
||||||
|
if (sentLength + chunkSize > size) {
|
||||||
|
chunkSize = size - sentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for fileChunk->m_chunk, the first byte is the chunk mark, last is \0
|
||||||
|
CFileChunk* fileChunk = new CFileChunk(chunkSize + 2);
|
||||||
|
char* chunkData = fileChunk->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileChunk;
|
||||||
|
file.read(&chunkData[1], chunkSize);
|
||||||
|
chunkData[chunkSize + 1] = '\0';
|
||||||
|
events->addEvent(CEvent(events->forIScreen().fileChunkSending(), eventTarget, fileChunk));
|
||||||
|
|
||||||
|
sentLength += chunkSize;
|
||||||
|
file.seekg (sentLength, std::ios::beg);
|
||||||
|
|
||||||
|
if (sentLength == size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send last message
|
||||||
|
CFileChunk* transferFinished = new CFileChunk(2);
|
||||||
|
chunkData = transferFinished->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileEnd;
|
||||||
|
chunkData[1] = '\0';
|
||||||
|
events->addEvent(CEvent(events->forIScreen().fileChunkSending(), eventTarget, transferFinished));
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
CFileChunker::intToString(size_t i)
|
||||||
|
{
|
||||||
|
stringstream ss;
|
||||||
|
ss << i;
|
||||||
|
return ss.str();
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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 "CString.h"
|
||||||
|
|
||||||
|
class IEventQueue;
|
||||||
|
|
||||||
|
class CFileChunker {
|
||||||
|
public:
|
||||||
|
//! FileChunk data
|
||||||
|
class CFileChunk {
|
||||||
|
public:
|
||||||
|
CFileChunk(size_t chunkSize) : m_dataSize(chunkSize - 2)
|
||||||
|
{
|
||||||
|
m_chunk = new char[chunkSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
~CFileChunk() { delete[] m_chunk; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
const size_t m_dataSize;
|
||||||
|
char* m_chunk;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void sendFileChunks(char* filename, IEventQueue* events, void* eventTarget);
|
||||||
|
static CString intToString(size_t i);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const size_t m_chunkSize;
|
||||||
|
};
|
|
@ -49,6 +49,7 @@ set(inc
|
||||||
CArgsBase.h
|
CArgsBase.h
|
||||||
IAppUtil.h
|
IAppUtil.h
|
||||||
CEventGameDevice.h
|
CEventGameDevice.h
|
||||||
|
CFileChunker.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(src
|
set(src
|
||||||
|
@ -77,6 +78,7 @@ set(src
|
||||||
CArgsBase.cpp
|
CArgsBase.cpp
|
||||||
CEventGameDevice.cpp
|
CEventGameDevice.cpp
|
||||||
CGameDevice.cpp
|
CGameDevice.cpp
|
||||||
|
CFileChunker.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -228,7 +228,12 @@ CProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args)
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't cause buffer overrun, using +100 chars in case
|
||||||
|
// someone modifies this log message in future.
|
||||||
|
if (len + 100 < kLogMessageLength) {
|
||||||
LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
|
LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer));
|
||||||
|
}
|
||||||
|
|
||||||
// save the data
|
// save the data
|
||||||
CString* dst = va_arg(args, CString*);
|
CString* dst = va_arg(args, CString*);
|
||||||
|
|
|
@ -688,7 +688,7 @@ CServer*
|
||||||
CServerApp::openServer(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);
|
||||||
|
server->setFileTransferDes(getFileTransferDes());
|
||||||
try {
|
try {
|
||||||
m_events->adoptHandler(
|
m_events->adoptHandler(
|
||||||
m_events->forCServer().disconnected(), server,
|
m_events->forCServer().disconnected(), server,
|
||||||
|
|
|
@ -68,6 +68,13 @@ enum EDirectionMask {
|
||||||
kBottomMask = 1 << kBottom
|
kBottomMask = 1 << kBottom
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// file transfer constants
|
||||||
|
enum EFileTransfer {
|
||||||
|
kFileStart = 1,
|
||||||
|
kFileChunk = 2,
|
||||||
|
kFileEnd = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// message codes (trailing NUL is not part of code). in comments, $n
|
// message codes (trailing NUL is not part of code). in comments, $n
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include "TMethodEventJob.h"
|
#include "TMethodEventJob.h"
|
||||||
#include "CSimpleEventQueueBuffer.h"
|
#include "CSimpleEventQueueBuffer.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
void
|
void
|
||||||
CTestEventQueue::raiseQuitEvent()
|
CTestEventQueue::raiseQuitEvent()
|
||||||
|
@ -47,6 +48,5 @@ CTestEventQueue::cleanupQuitTimeout()
|
||||||
void
|
void
|
||||||
CTestEventQueue::handleQuitTimeout(const CEvent&, void* vclient)
|
CTestEventQueue::handleQuitTimeout(const CEvent&, void* vclient)
|
||||||
{
|
{
|
||||||
LOG((CLOG_ERR "timeout"));
|
throw std::runtime_error("test event queue timeout");
|
||||||
raiseQuitEvent();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <iostream>
|
#include <stdexcept>
|
||||||
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define TEST_ENV
|
#define TEST_ENV
|
||||||
|
|
||||||
|
@ -33,13 +36,14 @@
|
||||||
#include "CTCPSocketFactory.h"
|
#include "CTCPSocketFactory.h"
|
||||||
#include "CCryptoOptions.h"
|
#include "CCryptoOptions.h"
|
||||||
#include "CSocketMultiplexer.h"
|
#include "CSocketMultiplexer.h"
|
||||||
#include "CMSWindowsScreen.h"
|
|
||||||
#include "CGameDevice.h"
|
|
||||||
#include "CThread.h"
|
|
||||||
#include "TMethodJob.h"
|
|
||||||
#include "CTestEventQueue.h"
|
#include "CTestEventQueue.h"
|
||||||
#include "server/CMockInputFilter.h"
|
#include "server/CMockInputFilter.h"
|
||||||
|
#include "TMethodJob.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "CFileChunker.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
using ::testing::NiceMock;
|
using ::testing::NiceMock;
|
||||||
using ::testing::Return;
|
using ::testing::Return;
|
||||||
|
@ -48,27 +52,58 @@ using ::testing::Invoke;
|
||||||
#define TEST_PORT 24803
|
#define TEST_PORT 24803
|
||||||
#define TEST_HOST "localhost"
|
#define TEST_HOST "localhost"
|
||||||
|
|
||||||
const int klargeDataSize = 512;
|
const size_t kMockDataSize = 1024 * 1024 * 10; // 10MB
|
||||||
char g_largeData[klargeDataSize] = "large data:head.1221412312341244213123fdsfasdawdwadwadacwdd.12321412312341244213123fdsfasdawdwadwadacwdawddawdwacawdawd232141231awddawdwacawdawd2321412312341244213123fdsfasdawdwadacwdawddawdwacawdtrtetawdawdwaewe1213412321412312341244213123fdsfasdawdwadacwdawddawdwacawdawdawdwaewe121341awdwaewedacwdawddawdwacawdawd2321412312341244213123fdsfasdawdwadacwdawddawdwacawdtrtetawdawdwaewe1213412321412312341244213123fdsfasdawdwadacwdawddawdwacawdawdawdwaewe121341awdwaewe12134123njk1u31i2nm3e123hu23oi132213njk.tail";
|
const UInt16 kMockDataChunkIncrement = 1024; // 1KB
|
||||||
|
const char* kMockFilename = "NetworkTests.mock";
|
||||||
|
const size_t kMockFileSize = 1024 * 1024 * 10; // 10MB
|
||||||
|
|
||||||
void sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h);
|
void getScreenShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h);
|
||||||
void sendFileToClient_getCursorPos(SInt32& x, SInt32& y);
|
void getCursorPos(SInt32& x, SInt32& y);
|
||||||
|
CString intToString(size_t i);
|
||||||
|
UInt8* newMockData(size_t size);
|
||||||
|
void createFile(fstream& file, const char* filename, size_t size);
|
||||||
|
|
||||||
class NetworkTests : public ::testing::Test
|
class NetworkTests : public ::testing::Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NetworkTests() { }
|
NetworkTests() :
|
||||||
|
m_mockData(NULL),
|
||||||
|
m_mockDataSize(0),
|
||||||
|
m_mockFileSize(0)
|
||||||
|
{
|
||||||
|
m_mockData = newMockData(kMockDataSize);
|
||||||
|
createFile(m_mockFile, kMockFilename, kMockFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
void sendData(CServer* server);
|
~NetworkTests()
|
||||||
|
{
|
||||||
|
remove(kMockFilename);
|
||||||
|
delete[] m_mockData;
|
||||||
|
}
|
||||||
|
|
||||||
void sendFileToClient_handleClientConnected(const CEvent&, void* vlistener);
|
void sendMockData(void* eventTarget);
|
||||||
void sendFileToClient_fileRecieveComplete(const CEvent&, void*);
|
|
||||||
|
void sendToClient_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendToClient_mockData_fileRecieveComplete(const CEvent&, void*);
|
||||||
|
|
||||||
|
void sendToClient_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendToClient_mockFile_fileRecieveComplete(const CEvent& event, void*);
|
||||||
|
|
||||||
|
void sendToServer_mockData_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendToServer_mockData_fileRecieveComplete(const CEvent& event, void*);
|
||||||
|
|
||||||
|
void sendToServer_mockFile_handleClientConnected(const CEvent&, void* vlistener);
|
||||||
|
void sendToServer_mockFile_fileRecieveComplete(const CEvent& event, void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTestEventQueue m_events;
|
CTestEventQueue m_events;
|
||||||
|
UInt8* m_mockData;
|
||||||
|
size_t m_mockDataSize;
|
||||||
|
fstream m_mockFile;
|
||||||
|
size_t m_mockFileSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(NetworkTests, sendFileToClient)
|
TEST_F(NetworkTests, sendToClient_mockData)
|
||||||
{
|
{
|
||||||
// server and client
|
// server and client
|
||||||
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
CNetworkAddress serverAddress(TEST_HOST, TEST_PORT);
|
||||||
|
@ -88,7 +123,7 @@ TEST_F(NetworkTests, sendFileToClient)
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forCClientListener().connected(), &listener,
|
m_events.forCClientListener().connected(), &listener,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendFileToClient_handleClientConnected, &listener));
|
this, &NetworkTests::sendToClient_mockData_handleClientConnected, &listener));
|
||||||
|
|
||||||
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
|
||||||
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
|
||||||
|
@ -102,43 +137,196 @@ TEST_F(NetworkTests, sendFileToClient)
|
||||||
CSocketMultiplexer clientSocketMultiplexer;
|
CSocketMultiplexer clientSocketMultiplexer;
|
||||||
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
CTCPSocketFactory* clientSocketFactory = new CTCPSocketFactory(&m_events, &clientSocketMultiplexer);
|
||||||
|
|
||||||
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(sendFileToClient_getShape));
|
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
|
||||||
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(sendFileToClient_getCursorPos));
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
m_events.forIScreen().fileRecieveComplete(), &client,
|
m_events.forIScreen().fileRecieveComplete(), &client,
|
||||||
new TMethodEventJob<NetworkTests>(
|
new TMethodEventJob<NetworkTests>(
|
||||||
this, &NetworkTests::sendFileToClient_fileRecieveComplete));
|
this, &NetworkTests::sendToClient_mockData_fileRecieveComplete));
|
||||||
|
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
m_events.initQuitTimeout(10);
|
m_events.initQuitTimeout(5);
|
||||||
|
m_events.loop();
|
||||||
|
m_events.cleanupQuitTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NetworkTests, sendToClient_mockFile)
|
||||||
|
{
|
||||||
|
// 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::sendToClient_mockFile_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(getScreenShape));
|
||||||
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forIScreen().fileRecieveComplete(), &client,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToClient_mockFile_fileRecieveComplete));
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
m_events.initQuitTimeout(5);
|
||||||
|
m_events.loop();
|
||||||
|
m_events.cleanupQuitTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NetworkTests, sendToServer_mockData)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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(getScreenShape));
|
||||||
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forCClientListener().connected(), &listener,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockData_handleClientConnected, &client));
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forIScreen().fileRecieveComplete(), &server,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockData_fileRecieveComplete));
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
m_events.initQuitTimeout(5);
|
||||||
|
m_events.loop();
|
||||||
|
m_events.cleanupQuitTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(NetworkTests, sendToServer_mockFile)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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(getScreenShape));
|
||||||
|
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
|
||||||
|
|
||||||
|
CClient client(&m_events, "stub", serverAddress, clientSocketFactory, NULL, &clientScreen, cryptoOptions);
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forCClientListener().connected(), &listener,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockFile_handleClientConnected, &client));
|
||||||
|
|
||||||
|
m_events.adoptHandler(
|
||||||
|
m_events.forIScreen().fileRecieveComplete(), &server,
|
||||||
|
new TMethodEventJob<NetworkTests>(
|
||||||
|
this, &NetworkTests::sendToServer_mockFile_fileRecieveComplete));
|
||||||
|
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
m_events.initQuitTimeout(5);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
m_events.cleanupQuitTimeout();
|
m_events.cleanupQuitTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendFileToClient_handleClientConnected(const CEvent&, void* vlistener)
|
NetworkTests::sendToClient_mockData_handleClientConnected(const CEvent&, void* vlistener)
|
||||||
{
|
{
|
||||||
CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
|
CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
|
||||||
CServer* server = listener->getServer();
|
CServer* server = listener->getServer();
|
||||||
|
|
||||||
CClientProxy* client = listener->getNextClient();
|
CClientProxy* client = listener->getNextClient();
|
||||||
if (client == NULL) {
|
if (client == NULL) {
|
||||||
throw std::exception("client is null");
|
throw runtime_error("client is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
CBaseClientProxy* bcp = reinterpret_cast<CBaseClientProxy*>(client);
|
CBaseClientProxy* bcp = reinterpret_cast<CBaseClientProxy*>(client);
|
||||||
server->adoptClient(bcp);
|
server->adoptClient(bcp);
|
||||||
server->setActive(bcp);
|
server->setActive(bcp);
|
||||||
|
|
||||||
sendData(server);
|
sendMockData(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendFileToClient_fileRecieveComplete(const CEvent& event, void*)
|
NetworkTests::sendToClient_mockData_fileRecieveComplete(const CEvent& event, void*)
|
||||||
{
|
{
|
||||||
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
||||||
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
||||||
|
@ -147,32 +335,166 @@ NetworkTests::sendFileToClient_fileRecieveComplete(const CEvent& event, void*)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NetworkTests::sendData(CServer* server)
|
NetworkTests::sendToClient_mockFile_handleClientConnected(const CEvent&, void* vlistener)
|
||||||
{
|
{
|
||||||
UInt8* largeDataSize = new UInt8[5];
|
CClientListener* listener = reinterpret_cast<CClientListener*>(vlistener);
|
||||||
largeDataSize[0] = '0';
|
CServer* server = listener->getServer();
|
||||||
largeDataSize[1] = '5';
|
|
||||||
largeDataSize[2] = '1';
|
|
||||||
largeDataSize[3] = '1';
|
|
||||||
largeDataSize[4] = '\0';
|
|
||||||
|
|
||||||
// transfer data from server -> client
|
CClientProxy* client = listener->getNextClient();
|
||||||
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, largeDataSize));
|
if (client == NULL) {
|
||||||
|
throw runtime_error("client is null");
|
||||||
|
}
|
||||||
|
|
||||||
UInt8* largeData = new UInt8[klargeDataSize + 1];
|
CBaseClientProxy* bcp = reinterpret_cast<CBaseClientProxy*>(client);
|
||||||
largeData[0] = '1';
|
server->adoptClient(bcp);
|
||||||
memcpy(&largeData[1], g_largeData, klargeDataSize);
|
server->setActive(bcp);
|
||||||
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, (UInt8*)largeData));
|
|
||||||
|
|
||||||
UInt8* transferFinished = new UInt8[2];
|
server->sendFileToClient(kMockFilename);
|
||||||
transferFinished[0] = '2';
|
|
||||||
transferFinished[1] = '\0';
|
|
||||||
|
|
||||||
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), server, transferFinished));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h)
|
NetworkTests::sendToClient_mockFile_fileRecieveComplete(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
CClient* client = reinterpret_cast<CClient*>(event.getTarget());
|
||||||
|
EXPECT_TRUE(client->isReceivedFileSizeValid());
|
||||||
|
|
||||||
|
m_events.raiseQuitEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockData_handleClientConnected(const CEvent&, void* vclient)
|
||||||
|
{
|
||||||
|
CClient* client = reinterpret_cast<CClient*>(vclient);
|
||||||
|
sendMockData(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockData_fileRecieveComplete(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
||||||
|
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
||||||
|
|
||||||
|
m_events.raiseQuitEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockFile_handleClientConnected(const CEvent&, void* vclient)
|
||||||
|
{
|
||||||
|
CClient* client = reinterpret_cast<CClient*>(vclient);
|
||||||
|
client->sendFileToServer(kMockFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendToServer_mockFile_fileRecieveComplete(const CEvent& event, void*)
|
||||||
|
{
|
||||||
|
CServer* server = reinterpret_cast<CServer*>(event.getTarget());
|
||||||
|
EXPECT_TRUE(server->isReceivedFileSizeValid());
|
||||||
|
|
||||||
|
m_events.raiseQuitEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkTests::sendMockData(void* eventTarget)
|
||||||
|
{
|
||||||
|
// send first message (file size)
|
||||||
|
CString size = intToString(kMockDataSize);
|
||||||
|
UInt32 sizeLength = size.size();
|
||||||
|
CFileChunker::CFileChunk* sizeMessage = new CFileChunker::CFileChunk(sizeLength + 2);
|
||||||
|
char* chunkData = sizeMessage->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileStart;
|
||||||
|
memcpy(&chunkData[1], size.c_str(), sizeLength);
|
||||||
|
chunkData[sizeLength + 1] = '\0';
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), eventTarget, sizeMessage));
|
||||||
|
|
||||||
|
// send chunk messages with incrementing chunk size
|
||||||
|
size_t lastSize = 0;
|
||||||
|
size_t sentLength = 0;
|
||||||
|
while (true) {
|
||||||
|
size_t chunkSize = lastSize + kMockDataChunkIncrement;
|
||||||
|
|
||||||
|
// make sure we don't read too much from the mock data.
|
||||||
|
if (sentLength + chunkSize > kMockDataSize) {
|
||||||
|
chunkSize = kMockDataSize - sentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first byte is the chunk mark, last is \0
|
||||||
|
CFileChunker::CFileChunk* fileChunk = new CFileChunker::CFileChunk(chunkSize + 2);
|
||||||
|
char* chunkData = fileChunk->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileChunk;
|
||||||
|
memcpy(&chunkData[1], &m_mockData[sentLength], chunkSize);
|
||||||
|
chunkData[chunkSize + 1] = '\0';
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), eventTarget, fileChunk));
|
||||||
|
|
||||||
|
sentLength += chunkSize;
|
||||||
|
lastSize = chunkSize;
|
||||||
|
|
||||||
|
if (sentLength == kMockDataSize) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// send last message
|
||||||
|
CFileChunker::CFileChunk* transferFinished = new CFileChunker::CFileChunk(2);
|
||||||
|
chunkData = transferFinished->m_chunk;
|
||||||
|
|
||||||
|
chunkData[0] = kFileEnd;
|
||||||
|
chunkData[1] = '\0';
|
||||||
|
m_events.addEvent(CEvent(m_events.forIScreen().fileChunkSending(), eventTarget, transferFinished));
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt8*
|
||||||
|
newMockData(size_t size)
|
||||||
|
{
|
||||||
|
UInt8* buffer = new UInt8[size];
|
||||||
|
|
||||||
|
UInt8* data = buffer;
|
||||||
|
const UInt8 head[] = "mock head... ";
|
||||||
|
size_t headSize = sizeof(head) - 1;
|
||||||
|
const UInt8 tail[] = "... mock tail";
|
||||||
|
size_t tailSize = sizeof(tail) - 1;
|
||||||
|
const UInt8 synergyRocks[] = "synergy\0 rocks! ";
|
||||||
|
size_t synergyRocksSize = sizeof(synergyRocks) - 1;
|
||||||
|
|
||||||
|
memcpy(data, head, headSize);
|
||||||
|
data += headSize;
|
||||||
|
|
||||||
|
SInt32 times = (size - headSize - tailSize) / synergyRocksSize;
|
||||||
|
for (SInt32 i = 0; i < times; ++i) {
|
||||||
|
memcpy(data, synergyRocks, synergyRocksSize);
|
||||||
|
data += synergyRocksSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
SInt32 remainder = (size - headSize - tailSize) % synergyRocksSize;
|
||||||
|
if (remainder != 0) {
|
||||||
|
memset(data, '.', remainder);
|
||||||
|
data += remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data, tail, tailSize);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
createFile(fstream& file, const char* filename, size_t size)
|
||||||
|
{
|
||||||
|
UInt8* buffer = newMockData(size);
|
||||||
|
|
||||||
|
file.open(filename, ios::out | ios::binary);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
throw runtime_error("file not open");
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(reinterpret_cast<char*>(buffer), size);
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getScreenShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h)
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
@ -181,8 +503,16 @@ sendFileToClient_getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sendFileToClient_getCursorPos(SInt32& x, SInt32& y)
|
getCursorPos(SInt32& x, SInt32& y)
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CString
|
||||||
|
intToString(size_t i)
|
||||||
|
{
|
||||||
|
stringstream ss;
|
||||||
|
ss << i;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
#include "COSXKeyState.h"
|
#include "COSXKeyState.h"
|
||||||
#include "CMockKeyMap.h"
|
#include "synergy/CMockKeyMap.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "synergy/CMockEventQueue.h"
|
||||||
|
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
#define TEST_ENV
|
#define TEST_ENV
|
||||||
#include "Global.h"
|
#include "Global.h"
|
||||||
|
|
||||||
#include "CMockKeyMap.h"
|
#include "synergy/CMockKeyMap.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "synergy/CMockEventQueue.h"
|
||||||
#include "CXWindowsKeyState.h"
|
#include "CXWindowsKeyState.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include "CXWindowsScreen.h"
|
#include "CXWindowsScreen.h"
|
||||||
#include "CMockEventQueue.h"
|
#include "synergy/CMockEventQueue.h"
|
||||||
|
|
||||||
using ::testing::_;
|
using ::testing::_;
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,8 @@ TEST(CServerProxyTests, mouseMove)
|
||||||
g_mouseMove_bufferIndex = 0;
|
g_mouseMove_bufferIndex = 0;
|
||||||
|
|
||||||
NiceMock<CMockEventQueue> eventQueue;
|
NiceMock<CMockEventQueue> eventQueue;
|
||||||
NiceMock<CMockClient> client;
|
|
||||||
NiceMock<CMockStream> stream;
|
NiceMock<CMockStream> stream;
|
||||||
|
NiceMock<CMockClient> client;
|
||||||
IStreamEvents streamEvents;
|
IStreamEvents streamEvents;
|
||||||
streamEvents.setEvents(&eventQueue);
|
streamEvents.setEvents(&eventQueue);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue