summaryrefslogtreecommitdiffstats
blob: 6f72480e5ad6b1b1ac1a9bf910df62c6ffd08c06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * Copyright (c) 2010 Remko Tronçon
 * Licensed under the GNU General Public License v3.
 * See Documentation/Licenses/GPLv3.txt for more information.
 */

#include <boost/bind.hpp>
#include <boost/filesystem.hpp>

#include "Swiften/Client/Client.h"
#include "Swiften/Network/BoostTimer.h"
#include "Swiften/EventLoop/EventLoop.h"
#include "Swiften/Client/ClientXMLTracer.h"
#include "Swiften/EventLoop/SimpleEventLoop.h"
#include "Swiften/Network/MainBoostIOServiceThread.h"
#include "Swiften/FileTransfer/OutgoingFileTransfer.h"
#include "Swiften/FileTransfer/FileReadBytestream.h"
#include "Swiften/FileTransfer/SOCKS5BytestreamServer.h"
#include "Swiften/Network/BoostConnectionServer.h"
#include "Swiften/Network/BoostIOServiceThread.h"

using namespace Swift;

SimpleEventLoop eventLoop;
int exitCode = 2;

class FileSender {
	public:
		FileSender(const JID& jid, const String& password, const JID& recipient, const boost::filesystem::path& file, int port) : jid(jid), password(password), recipient(recipient), file(file), transfer(NULL) {
			connectionServer = BoostConnectionServer::create(port, &MainBoostIOServiceThread::getInstance().getIOService(), &eventLoop);
			socksBytestreamServer = new SOCKS5BytestreamServer(connectionServer);

			client = new Swift::Client(&eventLoop, jid, password);
			client->onConnected.connect(boost::bind(&FileSender::handleConnected, this));
			client->onError.connect(boost::bind(&FileSender::handleError, this, _1));
			//tracer = new ClientXMLTracer(client);
		}

		~FileSender() {
			//delete tracer;
			client->onError.disconnect(boost::bind(&FileSender::handleError, this, _1));
			client->onConnected.disconnect(boost::bind(&FileSender::handleConnected, this));
			delete client;
			delete socksBytestreamServer;
		}

		void start() {
			connectionServer->start();
			socksBytestreamServer->start();
			client->connect();
		}

		void stop() {
			if (transfer) {
				transfer->stop();
			}
			client->disconnect();
			socksBytestreamServer->stop();
			connectionServer->stop();
		}

	private:
		void handleConnected() {
			client->sendPresence(Presence::create());
			transfer = new OutgoingFileTransfer("myid",	client->getJID(), recipient, file.filename(), boost::filesystem::file_size(file), "A file", boost::shared_ptr<FileReadBytestream>(new FileReadBytestream(file)), client->getIQRouter(), socksBytestreamServer);
			transfer->onFinished.connect(boost::bind(&FileSender::handleFileTransferFinished, this, _1));
			transfer->start();
		}

		void handleError(const 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;
			stop();
			eventLoop.stop();
		}
	
	private:
		BoostConnectionServer::ref connectionServer;
		SOCKS5BytestreamServer* socksBytestreamServer;
		JID jid;
		String password;
		JID recipient;
		boost::filesystem::path file;
		Client* client;
		ClientXMLTracer* tracer;
		OutgoingFileTransfer* transfer;
};


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]);
	FileSender fileSender(sender, String(argv[2]), recipient, boost::filesystem::path(argv[4]), 8888);
	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;
}