2013-07-24 16:41:12 +00:00
|
|
|
/*
|
|
|
|
* synergy -- mouse and keyboard sharing utility
|
2014-11-02 12:12:05 +00:00
|
|
|
* Copyright (C) 2013 Synergy Si Ltd.
|
2013-07-24 16:41:12 +00:00
|
|
|
*
|
|
|
|
* This package is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
2015-05-03 02:33:52 +00:00
|
|
|
* found in the file LICENSE that should have accompanied this file.
|
2013-07-24 16:41:12 +00:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2015-05-18 17:17:22 +00:00
|
|
|
#include "synergy/StreamChunker.h"
|
2014-02-28 12:36:45 +00:00
|
|
|
|
|
|
|
#include "synergy/protocol_types.h"
|
|
|
|
#include "base/EventTypes.h"
|
|
|
|
#include "base/Event.h"
|
|
|
|
#include "base/IEventQueue.h"
|
|
|
|
#include "base/EventTypes.h"
|
|
|
|
#include "base/Log.h"
|
|
|
|
#include "base/Stopwatch.h"
|
2014-03-14 20:33:18 +00:00
|
|
|
#include "common/stdexcept.h"
|
2014-02-28 12:36:45 +00:00
|
|
|
|
2013-07-24 16:41:12 +00:00
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
|
2013-07-26 14:10:06 +00:00
|
|
|
#define PAUSE_TIME_HACK 0.1
|
|
|
|
|
2013-07-24 16:41:12 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2015-05-18 17:17:22 +00:00
|
|
|
const size_t StreamChunker::m_chunkSize = 512 * 1024; // 512kb
|
2013-07-24 16:41:12 +00:00
|
|
|
|
|
|
|
void
|
2015-05-18 17:17:22 +00:00
|
|
|
StreamChunker::sendFileChunks(char* filename, IEventQueue* events, void* eventTarget)
|
2013-07-24 16:41:12 +00:00
|
|
|
{
|
|
|
|
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)
|
2014-11-11 13:51:47 +00:00
|
|
|
String fileSize = intToString(size);
|
2013-08-02 13:21:06 +00:00
|
|
|
size_t sizeLength = fileSize.size();
|
2015-05-18 17:17:22 +00:00
|
|
|
Chunk* sizeMessage = new Chunk(sizeLength + 2);
|
2013-07-24 16:41:12 +00:00
|
|
|
char* chunkData = sizeMessage->m_chunk;
|
|
|
|
|
2015-05-15 21:26:57 +00:00
|
|
|
chunkData[0] = kDataStart;
|
2013-07-24 16:41:12 +00:00
|
|
|
memcpy(&chunkData[1], fileSize.c_str(), sizeLength);
|
|
|
|
chunkData[sizeLength + 1] = '\0';
|
2014-11-11 13:51:47 +00:00
|
|
|
events->addEvent(Event(events->forIScreen().fileChunkSending(), eventTarget, sizeMessage));
|
2013-07-24 16:41:12 +00:00
|
|
|
|
|
|
|
// send chunk messages with a fixed chunk size
|
|
|
|
size_t sentLength = 0;
|
|
|
|
size_t chunkSize = m_chunkSize;
|
2014-11-11 13:51:47 +00:00
|
|
|
Stopwatch stopwatch;
|
2013-07-26 14:10:06 +00:00
|
|
|
stopwatch.start();
|
2013-07-24 16:41:12 +00:00
|
|
|
file.seekg (0, std::ios::beg);
|
|
|
|
while (true) {
|
2013-07-26 14:10:06 +00:00
|
|
|
if (stopwatch.getTime() > PAUSE_TIME_HACK) {
|
|
|
|
// 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
|
2015-05-18 17:17:22 +00:00
|
|
|
Chunk* fileChunk = new Chunk(chunkSize + 2);
|
2013-07-26 14:10:06 +00:00
|
|
|
char* chunkData = fileChunk->m_chunk;
|
2013-07-24 16:41:12 +00:00
|
|
|
|
2015-05-15 21:26:57 +00:00
|
|
|
chunkData[0] = kDataChunk;
|
2013-07-26 14:10:06 +00:00
|
|
|
file.read(&chunkData[1], chunkSize);
|
|
|
|
chunkData[chunkSize + 1] = '\0';
|
2014-11-11 13:51:47 +00:00
|
|
|
events->addEvent(Event(events->forIScreen().fileChunkSending(), eventTarget, fileChunk));
|
2013-07-24 16:41:12 +00:00
|
|
|
|
2013-07-26 14:10:06 +00:00
|
|
|
sentLength += chunkSize;
|
|
|
|
file.seekg (sentLength, std::ios::beg);
|
2013-07-24 16:41:12 +00:00
|
|
|
|
2013-07-26 14:10:06 +00:00
|
|
|
if (sentLength == size) {
|
|
|
|
break;
|
|
|
|
}
|
2013-07-24 16:41:12 +00:00
|
|
|
|
2013-07-26 14:10:06 +00:00
|
|
|
stopwatch.reset();
|
2013-07-24 16:41:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// send last message
|
2015-05-18 17:17:22 +00:00
|
|
|
Chunk* transferFinished = new Chunk(2);
|
2013-07-24 16:41:12 +00:00
|
|
|
chunkData = transferFinished->m_chunk;
|
|
|
|
|
2015-05-15 21:26:57 +00:00
|
|
|
chunkData[0] = kDataEnd;
|
2013-07-24 16:41:12 +00:00
|
|
|
chunkData[1] = '\0';
|
2014-11-11 13:51:47 +00:00
|
|
|
events->addEvent(Event(events->forIScreen().fileChunkSending(), eventTarget, transferFinished));
|
2013-07-24 16:41:12 +00:00
|
|
|
|
|
|
|
file.close();
|
|
|
|
}
|
|
|
|
|
2014-11-11 13:51:47 +00:00
|
|
|
String
|
2015-05-18 17:17:22 +00:00
|
|
|
StreamChunker::intToString(size_t i)
|
2013-07-24 16:41:12 +00:00
|
|
|
{
|
2015-05-18 17:17:22 +00:00
|
|
|
//TODO: this should be in string
|
2013-07-24 16:41:12 +00:00
|
|
|
stringstream ss;
|
|
|
|
ss << i;
|
|
|
|
return ss.str();
|
|
|
|
}
|