/* * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/bind.hpp> #include <boost/filesystem.hpp> #include <iostream> #include <Swiften/Client/Client.h> #include <Swiften/Elements/Presence.h> #include <Swiften/Base/Log.h> #include <Swiften/Network/BoostTimer.h> #include <Swiften/Network/TimerFactory.h> #include <Swiften/Network/BoostNetworkFactories.h> #include <Swiften/EventLoop/EventLoop.h> #include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/FileTransfer/OutgoingSIFileTransfer.h> #include <Swiften/FileTransfer/FileReadBytestream.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> #include <Swiften/Network/BoostConnectionServer.h> #include <Swiften/FileTransfer/OutgoingFileTransferManager.h> #include <Swiften/FileTransfer/OutgoingFileTransfer.h> #include <Swiften/Jingle/JingleSessionManager.h> #include <Swiften/Disco/EntityCapsManager.h> #include <Swiften/FileTransfer/DefaultLocalJingleTransportCandidateGeneratorFactory.h> #include <Swiften/FileTransfer/DefaultRemoteJingleTransportCandidateSelectorFactory.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/StringCodecs/MD5.h> #include <Swiften/StringCodecs/SHA1.h> #include <Swiften/StringCodecs/Hexify.h> #include <Swiften/FileTransfer/FileTransferManager.h> using namespace Swift; static SimpleEventLoop eventLoop; static BoostNetworkFactories networkFactories(&eventLoop); static int exitCode = 2; class FileSender { public: FileSender(const JID& jid, const std::string& password, const JID& recipient, const boost::filesystem::path& file) : jid(jid), password(password), recipient(recipient), file(file) { client = new Swift::Client(jid, password, &networkFactories); client->onConnected.connect(boost::bind(&FileSender::handleConnected, this)); client->onDisconnected.connect(boost::bind(&FileSender::handleDisconnected, this, _1)); tracer = new ClientXMLTracer(client); client->getEntityCapsProvider()->onCapsChanged.connect(boost::bind(&FileSender::handleCapsChanged, this, _1)); } ~FileSender() { delete tracer; client->onDisconnected.disconnect(boost::bind(&FileSender::handleDisconnected, this, _1)); client->onConnected.disconnect(boost::bind(&FileSender::handleConnected, this)); delete client; } void start() { client->connect(); } private: void handleConnected() { client->sendPresence(Presence::create()); client->getFileTransferManager()->startListeningOnPort(19999); //ByteArray fileData; //readByteArrayFromFile(fileData, file.string()); // gather file information /*StreamInitiationFileInfo fileInfo; fileInfo.setName(file.filename()); fileInfo.setSize(boost::filesystem::file_size(file)); fileInfo.setDescription("Some file!"); fileInfo.setDate(boost::posix_time::from_time_t(boost::filesystem::last_write_time(file)));*/ //fileInfo.setHash(Hexify::hexify(MD5::getHash(fileData))); /* transfer = new OutgoingSIFileTransfer("myid", client->getJID(), recipient, file.filename(), boost::filesystem::file_size(file), "A file", boost::make_shared<FileReadBytestream>(file)), client->getIQRouter(), socksBytestreamServer); transfer->onFinished.connect(boost::bind(&FileSender::handleFileTransferFinished, this, _1)); transfer->start(); */ } void handleCapsChanged(JID jid) { if (jid.toBare() == recipient) { // create ReadBytestream from file boost::shared_ptr<FileReadBytestream> fileStream = boost::make_shared<FileReadBytestream>(file); outgoingFileTransfer = client->getFileTransferManager()->createOutgoingFileTransfer(recipient, file, "Some File!", fileStream); if (outgoingFileTransfer) { std::cout << "started FT" << std::endl; outgoingFileTransfer->start(); // TODO: getting notified about FT status and end } else { std::cout << "[ ERROR ] " << recipient << " doesn't support any kind of file transfer!" << std::endl; //client->disconnect(); } } } void handleDisconnected(const boost::optional<ClientError>&) { std::cerr << "Error!" << std::endl; exit(-1); } void handleFileTransferFinished(const boost::optional<FileTransferError>& error) { std::cout << "File transfer finished" << std::endl; if (error) { exit(-1); } else { exit(0); } } void exit(int code) { exitCode = code; eventLoop.stop(); } private: BoostConnectionServer::ref connectionServer; OutgoingFileTransfer::ref outgoingFileTransfer; JID jid; std::string password; JID recipient; boost::filesystem::path file; Client* client; ClientXMLTracer* tracer; }; int main(int argc, char* argv[]) { if (argc != 5) { std::cerr << "Usage: " << argv[0] << " <jid> <password> <recipient> <file>" << std::endl; return -1; } JID sender(argv[1]); JID recipient(argv[3]); Log::setLogLevel(Log::debug); FileSender fileSender(sender, std::string(argv[2]), recipient, boost::filesystem::path(argv[4])); fileSender.start(); { /*BoostTimer::ref timer(BoostTimer::create(30000, &MainBoostIOServiceThread::getInstance().getIOService())); timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); timer->start();*/ eventLoop.run(); } return exitCode; }