/* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2013 Synergy Si 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 LICENSE 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 . */ #include "synergy/StreamChunker.h" #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" #include "common/stdexcept.h" #include #include #define PAUSE_TIME_HACK 0.1 using namespace std; const size_t StreamChunker::m_chunkSize = 512 * 1024; // 512kb void StreamChunker::sendFileChunks(char* filename, IEventQueue* events, void* eventTarget) { std::fstream file(reinterpret_cast(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) String fileSize = intToString(size); size_t sizeLength = fileSize.size(); Chunk* sizeMessage = new Chunk(sizeLength + 2); char* chunkData = sizeMessage->m_chunk; chunkData[0] = kDataStart; memcpy(&chunkData[1], fileSize.c_str(), sizeLength); chunkData[sizeLength + 1] = '\0'; events->addEvent(Event(events->forIScreen().fileChunkSending(), eventTarget, sizeMessage)); // send chunk messages with a fixed chunk size size_t sentLength = 0; size_t chunkSize = m_chunkSize; Stopwatch stopwatch; stopwatch.start(); file.seekg (0, std::ios::beg); while (true) { 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 Chunk* fileChunk = new Chunk(chunkSize + 2); char* chunkData = fileChunk->m_chunk; chunkData[0] = kDataChunk; file.read(&chunkData[1], chunkSize); chunkData[chunkSize + 1] = '\0'; events->addEvent(Event(events->forIScreen().fileChunkSending(), eventTarget, fileChunk)); sentLength += chunkSize; file.seekg (sentLength, std::ios::beg); if (sentLength == size) { break; } stopwatch.reset(); } } // send last message Chunk* transferFinished = new Chunk(2); chunkData = transferFinished->m_chunk; chunkData[0] = kDataEnd; chunkData[1] = '\0'; events->addEvent(Event(events->forIScreen().fileChunkSending(), eventTarget, transferFinished)); file.close(); } String StreamChunker::intToString(size_t i) { //TODO: this should be in string stringstream ss; ss << i; return ss.str(); }