diff options
Diffstat (limited to 'Swiften/FileTransfer')
-rw-r--r-- | Swiften/FileTransfer/ByteArrayWriteBytestream.h | 5 | ||||
-rw-r--r-- | Swiften/FileTransfer/FileTransferError.h | 3 | ||||
-rw-r--r-- | Swiften/FileTransfer/FileWriteBytestream.cpp | 17 | ||||
-rw-r--r-- | Swiften/FileTransfer/FileWriteBytestream.h | 2 | ||||
-rw-r--r-- | Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp | 3 | ||||
-rw-r--r-- | Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp | 40 | ||||
-rw-r--r-- | Swiften/FileTransfer/SOCKS5BytestreamServerSession.h | 9 | ||||
-rw-r--r-- | Swiften/FileTransfer/WriteBytestream.h | 12 |
8 files changed, 49 insertions, 42 deletions
diff --git a/Swiften/FileTransfer/ByteArrayWriteBytestream.h b/Swiften/FileTransfer/ByteArrayWriteBytestream.h index 938b1d4..08c4d4b 100644 --- a/Swiften/FileTransfer/ByteArrayWriteBytestream.h +++ b/Swiften/FileTransfer/ByteArrayWriteBytestream.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/WriteBytestream.h> namespace Swift { class SWIFTEN_API ByteArrayWriteBytestream : public WriteBytestream { public: ByteArrayWriteBytestream() { } - virtual void write(const std::vector<unsigned char>& bytes) { + virtual bool write(const std::vector<unsigned char>& bytes) { data.insert(data.end(), bytes.begin(), bytes.end()); onWrite(bytes); + return true; } const std::vector<unsigned char>& getData() const { return data; } private: std::vector<unsigned char> data; }; } diff --git a/Swiften/FileTransfer/FileTransferError.h b/Swiften/FileTransfer/FileTransferError.h index 67e32f2..eff8ca9 100644 --- a/Swiften/FileTransfer/FileTransferError.h +++ b/Swiften/FileTransfer/FileTransferError.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/API.h> namespace Swift { class SWIFTEN_API FileTransferError { public: enum Type { UnknownError, PeerError, ReadError, + WriteError, ClosedError }; FileTransferError(Type type = UnknownError) : type(type) {} Type getType() const { return type; } private: Type type; }; } diff --git a/Swiften/FileTransfer/FileWriteBytestream.cpp b/Swiften/FileTransfer/FileWriteBytestream.cpp index bbf3d51..c39d63a 100644 --- a/Swiften/FileTransfer/FileWriteBytestream.cpp +++ b/Swiften/FileTransfer/FileWriteBytestream.cpp @@ -1,47 +1,52 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/FileWriteBytestream.h> #include <cassert> #include <boost/filesystem/fstream.hpp> #include <boost/numeric/conversion/cast.hpp> namespace Swift { FileWriteBytestream::FileWriteBytestream(const boost::filesystem::path& file) : file(file), stream(NULL) { } FileWriteBytestream::~FileWriteBytestream() { if (stream) { stream->close(); delete stream; stream = NULL; } } -void FileWriteBytestream::write(const std::vector<unsigned char>& data) { +bool FileWriteBytestream::write(const std::vector<unsigned char>& data) { if (data.empty()) { - return; + return true; } if (!stream) { stream = new boost::filesystem::ofstream(file, std::ios_base::out|std::ios_base::binary); } - assert(stream->good()); - stream->write(reinterpret_cast<const char*>(&data[0]), boost::numeric_cast<std::streamsize>(data.size())); - onWrite(data); + if (stream->good()) { + stream->write(reinterpret_cast<const char*>(&data[0]), boost::numeric_cast<std::streamsize>(data.size())); + if (stream->good()) { + onWrite(data); + return true; + } + } + return false; } void FileWriteBytestream::close() { if (stream) { stream->close(); delete stream; stream = NULL; } } } diff --git a/Swiften/FileTransfer/FileWriteBytestream.h b/Swiften/FileTransfer/FileWriteBytestream.h index b2d3347..02e1b46 100644 --- a/Swiften/FileTransfer/FileWriteBytestream.h +++ b/Swiften/FileTransfer/FileWriteBytestream.h @@ -1,28 +1,28 @@ /* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <boost/filesystem/fstream.hpp> #include <boost/filesystem/path.hpp> #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/WriteBytestream.h> namespace Swift { class SWIFTEN_API FileWriteBytestream : public WriteBytestream { public: FileWriteBytestream(const boost::filesystem::path& file); virtual ~FileWriteBytestream(); - virtual void write(const std::vector<unsigned char>&); + virtual bool write(const std::vector<unsigned char>&); void close(); private: boost::filesystem::path file; boost::filesystem::ofstream* stream; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp index a38501b..4fc0246 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp @@ -1,38 +1,38 @@ /* * Copyright (c) 2011 Tobias Markmann * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include "SOCKS5BytestreamClientSession.h" #include <boost/bind.hpp> #include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/SafeByteArray.h> #include <Swiften/FileTransfer/BytestreamException.h> #include <Swiften/Network/TimerFactory.h> #include <Swiften/StringCodecs/Hexify.h> namespace Swift { SOCKS5BytestreamClientSession::SOCKS5BytestreamClientSession( boost::shared_ptr<Connection> connection, const HostAddressPort& addressPort, const std::string& destination, TimerFactory* timerFactory) : connection(connection), addressPort(addressPort), destination(destination), state(Initial), chunkSize(131072) { @@ -139,61 +139,60 @@ void SOCKS5BytestreamClientSession::process() { SWIFT_LOG(debug) << "Data: " << Hexify::hexify(unprocessedData) << std::endl; unprocessedData.clear(); //assert(false); } } void SOCKS5BytestreamClientSession::hello() { // Version 5, 1 auth method, No authentication const SafeByteArray hello = createSafeByteArray("\x05\x01\x00", 3); connection->write(hello); state = Hello; } void SOCKS5BytestreamClientSession::authenticate() { SWIFT_LOG(debug) << std::endl; SafeByteArray header = createSafeByteArray("\x05\x01\x00\x03", 4); SafeByteArray message = header; append(message, createSafeByteArray(boost::numeric_cast<char>(destination.size()))); authenticateAddress = createByteArray(destination); append(message, authenticateAddress); append(message, createSafeByteArray("\x00\x00", 2)); // 2 byte for port connection->write(message); state = Authenticating; } void SOCKS5BytestreamClientSession::startReceiving(boost::shared_ptr<WriteBytestream> writeStream) { if (state == Ready) { state = Reading; writeBytestream = writeStream; writeBytestream->write(unprocessedData); - //onBytesReceived(unprocessedData.size()); unprocessedData.clear(); } else { SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; } } void SOCKS5BytestreamClientSession::startSending(boost::shared_ptr<ReadBytestream> readStream) { if (state == Ready) { state = Writing; readBytestream = readStream; dataWrittenConnection = connection->onDataWritten.connect( boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); sendData(); } else { SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; } } HostAddressPort SOCKS5BytestreamClientSession::getAddressPort() const { return addressPort; } void SOCKS5BytestreamClientSession::sendData() { if (!readBytestream->isFinished()) { try { boost::shared_ptr<ByteArray> dataToSend = readBytestream->read(boost::numeric_cast<size_t>(chunkSize)); connection->write(createSafeByteArray(*dataToSend)); onBytesSent(dataToSend->size()); } catch (const BytestreamException&) { diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp index 7838dd1..0e1eb6b 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp @@ -1,199 +1,195 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <boost/bind.hpp> #include <boost/numeric/conversion/cast.hpp> -#include <iostream> -#include <Swiften/Base/ByteArray.h> -#include <Swiften/Base/SafeByteArray.h> #include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> #include <Swiften/Base/Log.h> -#include <Swiften/Network/HostAddressPort.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/Base/SafeByteArray.h> #include <Swiften/FileTransfer/BytestreamException.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/Network/HostAddressPort.h> namespace Swift { SOCKS5BytestreamServerSession::SOCKS5BytestreamServerSession( boost::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* bytestreams) : connection(connection), bytestreams(bytestreams), state(Initial), chunkSize(131072), waitingForData(false) { disconnectedConnection = connection->onDisconnected.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDisconnected, this, _1)); } SOCKS5BytestreamServerSession::~SOCKS5BytestreamServerSession() { if (state != Finished && state != Initial) { - std::cerr << "Warning: SOCKS5BytestreamServerSession unfinished" << std::endl; - finish(false); + SWIFT_LOG(warning) << "SOCKS5BytestreamServerSession unfinished" << std::endl; + finish(); } } void SOCKS5BytestreamServerSession::start() { SWIFT_LOG(debug) << std::endl; dataReadConnection = connection->onDataRead.connect( boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); state = WaitingForAuthentication; } void SOCKS5BytestreamServerSession::stop() { - finish(false); + finish(); } void SOCKS5BytestreamServerSession::startSending(boost::shared_ptr<ReadBytestream> stream) { if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } readBytestream = stream; state = WritingData; dataAvailableConnection = readBytestream->onDataAvailable.connect( boost::bind(&SOCKS5BytestreamServerSession::handleDataAvailable, this)); dataWrittenConnection = connection->onDataWritten.connect( boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); sendData(); } void SOCKS5BytestreamServerSession::startReceiving(boost::shared_ptr<WriteBytestream> stream) { if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } writeBytestream = stream; state = ReadingData; writeBytestream->write(unprocessedData); // onBytesReceived(unprocessedData.size()); unprocessedData.clear(); } HostAddressPort SOCKS5BytestreamServerSession::getAddressPort() const { return connection->getLocalAddress(); } void SOCKS5BytestreamServerSession::handleDataRead(boost::shared_ptr<SafeByteArray> data) { if (state != ReadingData) { append(unprocessedData, *data); process(); } else { - writeBytestream->write(createByteArray(vecptr(*data), data->size())); - // onBytesReceived(data->size()); + if (!writeBytestream->write(createByteArray(vecptr(*data), data->size()))) { + finish(boost::optional<FileTransferError>(FileTransferError::WriteError)); + } } } void SOCKS5BytestreamServerSession::handleDataAvailable() { if (waitingForData) { sendData(); } } void SOCKS5BytestreamServerSession::handleDisconnected(const boost::optional<Connection::Error>& error) { SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error") << std::endl; - finish(error ? true : false); + finish(error ? boost::optional<FileTransferError>(FileTransferError::PeerError) : boost::optional<FileTransferError>()); } void SOCKS5BytestreamServerSession::process() { if (state == WaitingForAuthentication) { if (unprocessedData.size() >= 2) { size_t authCount = unprocessedData[1]; size_t i = 2; while (i < 2 + authCount && i < unprocessedData.size()) { // Skip authentication mechanism ++i; } if (i == 2 + authCount) { // Authentication message is complete if (i != unprocessedData.size()) { SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; } unprocessedData.clear(); connection->write(createSafeByteArray("\x05\x00", 2)); state = WaitingForRequest; } } } else if (state == WaitingForRequest) { if (unprocessedData.size() >= 5) { ByteArray requestID; size_t i = 5; size_t hostnameSize = unprocessedData[4]; while (i < 5 + hostnameSize && i < unprocessedData.size()) { requestID.push_back(unprocessedData[i]); ++i; } // Skip the port: 2 byte large, one already skipped. Add one for comparison with size i += 2; if (i <= unprocessedData.size()) { if (i != unprocessedData.size()) { SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; } unprocessedData.clear(); streamID = byteArrayToString(requestID); bool hasBytestream = bytestreams->hasBytestream(streamID); SafeByteArray result = createSafeByteArray("\x05", 1); result.push_back(hasBytestream ? 0x0 : 0x4); append(result, createByteArray("\x00\x03", 2)); result.push_back(boost::numeric_cast<unsigned char>(requestID.size())); append(result, concat(requestID, createByteArray("\x00\x00", 2))); if (!hasBytestream) { SWIFT_LOG(debug) << "Readstream or Wrtiestream with ID " << streamID << " not found!" << std::endl; connection->write(result); - finish(true); + finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); } else { SWIFT_LOG(debug) << "Found stream. Sent OK." << std::endl; connection->write(result); state = ReadyForTransfer; } } } } } void SOCKS5BytestreamServerSession::sendData() { if (!readBytestream->isFinished()) { try { SafeByteArray dataToSend = createSafeByteArray(*readBytestream->read(boost::numeric_cast<size_t>(chunkSize))); if (!dataToSend.empty()) { connection->write(dataToSend); onBytesSent(dataToSend.size()); waitingForData = false; } else { waitingForData = true; } } catch (const BytestreamException&) { - finish(true); + finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); } } else { - finish(false); + finish(); } } -void SOCKS5BytestreamServerSession::finish(bool error) { - SWIFT_LOG(debug) << error << " " << state << std::endl; +void SOCKS5BytestreamServerSession::finish(const boost::optional<FileTransferError>& error) { + SWIFT_LOG(debug) << "state: " << state << std::endl; if (state == Finished) { return; } disconnectedConnection.disconnect(); dataReadConnection.disconnect(); dataWrittenConnection.disconnect(); dataAvailableConnection.disconnect(); readBytestream.reset(); state = Finished; - if (error) { - onFinished(boost::optional<FileTransferError>(FileTransferError::PeerError)); - } else { - onFinished(boost::optional<FileTransferError>()); - } + onFinished(error); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h index d8eea34..ed5272f 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h @@ -1,84 +1,83 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Network/Connection.h> +#include <Swiften/FileTransfer/FileTransferError.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/FileTransfer/WriteBytestream.h> -#include <Swiften/FileTransfer/FileTransferError.h> +#include <Swiften/Network/Connection.h> namespace Swift { class SOCKS5BytestreamRegistry; class SWIFTEN_API SOCKS5BytestreamServerSession { public: typedef boost::shared_ptr<SOCKS5BytestreamServerSession> ref; public: enum State { Initial, WaitingForAuthentication, WaitingForRequest, ReadyForTransfer, ReadingData, WritingData, Finished }; SOCKS5BytestreamServerSession(boost::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* registry); ~SOCKS5BytestreamServerSession(); void setChunkSize(int chunkSize) { this->chunkSize = chunkSize; } void start(); void stop(); void startSending(boost::shared_ptr<ReadBytestream>); void startReceiving(boost::shared_ptr<WriteBytestream>); HostAddressPort getAddressPort() const; boost::signal<void (boost::optional<FileTransferError>)> onFinished; boost::signal<void (unsigned long long)> onBytesSent; - // boost::signal<void (unsigned long long)> onBytesReceived; const std::string& getStreamID() const { return streamID; } private: - void finish(bool error); + void finish(const boost::optional<FileTransferError>& error = boost::optional<FileTransferError>()); void process(); void handleDataRead(boost::shared_ptr<SafeByteArray>); void handleDisconnected(const boost::optional<Connection::Error>&); void handleDataAvailable(); void sendData(); private: boost::shared_ptr<Connection> connection; SOCKS5BytestreamRegistry* bytestreams; ByteArray unprocessedData; State state; int chunkSize; std::string streamID; boost::shared_ptr<ReadBytestream> readBytestream; boost::shared_ptr<WriteBytestream> writeBytestream; bool waitingForData; boost::bsignals::connection disconnectedConnection; boost::bsignals::connection dataReadConnection; boost::bsignals::connection dataWrittenConnection; boost::bsignals::connection dataAvailableConnection; }; } diff --git a/Swiften/FileTransfer/WriteBytestream.h b/Swiften/FileTransfer/WriteBytestream.h index 3299620..76237c4 100644 --- a/Swiften/FileTransfer/WriteBytestream.h +++ b/Swiften/FileTransfer/WriteBytestream.h @@ -1,26 +1,32 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <vector> +#include <boost/shared_ptr.hpp> + #include <Swiften/Base/API.h> #include <Swiften/Base/boost_bsignals.h> namespace Swift { class SWIFTEN_API WriteBytestream { public: typedef boost::shared_ptr<WriteBytestream> ref; virtual ~WriteBytestream(); - virtual void write(const std::vector<unsigned char>&) = 0; + /** + * Write data from vector argument to bytestream. + * + * On success true is returned and \ref onWrite is called. On failure false is returned. + */ + virtual bool write(const std::vector<unsigned char>&) = 0; boost::signal<void (const std::vector<unsigned char>&)> onWrite; }; } |