1 /*
2  * s5b.h - direct connection protocol via tcp
3  * Copyright (C) 2003  Justin Karneges
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * either version 2
9    of the License, or (at your option) any later version.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21 
22 #ifndef XMPP_S5B_H
23 #define XMPP_S5B_H
24 
25 #include <QObject>
26 #include <QList>
27 #include <QHostAddress>
28 
29 #include "iris_export.h"
30 #include "bytestream.h"
31 #include "xmpp/jid/jid.h"
32 #include "xmpp_task.h"
33 
34 class SocksClient;
35 class SocksUDP;
36 
37 namespace XMPP
38 {
39 	class StreamHost;
40 	class Client;
41 	class S5BConnection;
42 	class S5BManager;
43 	class S5BServer;
44 	struct S5BRequest;
45 	typedef QList<StreamHost> StreamHostList;
46 	typedef QList<S5BConnection*> S5BConnectionList;
47 
48 	class IRIS_EXPORT S5BDatagram
49 	{
50 	public:
51 		S5BDatagram();
52 		S5BDatagram(int source, int dest, const QByteArray &data);
53 
54 		int sourcePort() const;
55 		int destPort() const;
56 		QByteArray data() const;
57 
58 	private:
59 		int _source, _dest;
60 		QByteArray _buf;
61 	};
62 
63 	class IRIS_EXPORT S5BConnection : public ByteStream
64 	{
65 		Q_OBJECT
66 	public:
67 		enum Mode { Stream, Datagram };
68 		enum Error { ErrRefused, ErrConnect, ErrProxy, ErrSocket };
69 		enum State { Idle, Requesting, Connecting, WaitingForAccept, Active };
70 		~S5BConnection() override;
71 
72 		Jid proxy() const;
73 		void setProxy(const Jid &proxy);
74 
75 		void connectToJid(const Jid &peer, const QString &sid, Mode m = Stream);
76 		void accept();
77 		void close() override;
78 
79 		Jid peer() const;
80 		QString sid() const;
81 		bool isRemote() const;
82 		Mode mode() const;
83 		int state() const;
84 
85 		bool isOpen() const override;
86 		void write(const QByteArray &) override;
87 		QByteArray read(int bytes=0) override;
88 		int bytesAvailable() const override;
89 		int bytesToWrite() const override;
90 
91 		void writeDatagram(const S5BDatagram &);
92 		S5BDatagram readDatagram();
93 		int datagramsAvailable() const;
94 
95 	signals:
96 		void proxyQuery();                             // querying proxy for streamhost information
97 		void proxyResult(bool b);                      // query success / fail
98 		void requesting();                             // sent actual S5B request (initiator only)
99 		void accepted();                               // target accepted (initiator only
100 		void tryingHosts(const StreamHostList &hosts); // currently connecting to these hosts
101 		void proxyConnect();                           // connecting to proxy
102 		void waitingForActivation();                   // waiting for activation (target only)
103 		void connected();                              // connection active
104 		void datagramReady();
105 
106 	private slots:
107 		void doPending();
108 
109 		void sc_connectionClosed();
110 		void sc_delayedCloseFinished();
111 		void sc_readyRead();
112 		void sc_bytesWritten(int);
113 		void sc_error(int);
114 
115 		void su_packetReady(const QByteArray &buf);
116 
117 	private:
118 		class Private;
119 		Private *d;
120 
121 		void reset(bool clear=false);
122 		void handleUDP(const QByteArray &buf);
123 		void sendUDP(const QByteArray &buf);
124 
125 		friend class S5BManager;
126 		void man_waitForAccept(const S5BRequest &r);
127 		void man_clientReady(SocksClient *, SocksUDP *);
128 		void man_udpReady(const QByteArray &buf);
129 		void man_failed(int);
130 		S5BConnection(S5BManager *, QObject *parent=0);
131 	};
132 
133 	class IRIS_EXPORT S5BManager : public QObject
134 	{
135 		Q_OBJECT
136 	public:
137 		S5BManager(Client *);
138 		~S5BManager() override;
139 
140 		Client *client() const;
141 		S5BServer *server() const;
142 		void setServer(S5BServer *s);
143 
144 		bool isAcceptableSID(const Jid &peer, const QString &sid) const;
145 		QString genUniqueSID(const Jid &peer) const;
146 
147 		S5BConnection *createConnection();
148 		S5BConnection *takeIncoming();
149 
150 		class Item;
151 		class Entry;
152 
153 	signals:
154 		void incomingReady();
155 
156 	private slots:
157 		void ps_incoming(const S5BRequest &req);
158 		void ps_incomingUDPSuccess(const Jid &from, const QString &dstaddr);
159 		void ps_incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost);
160 		void item_accepted();
161 		void item_tryingHosts(const StreamHostList &list);
162 		void item_proxyConnect();
163 		void item_waitingForActivation();
164 		void item_connected();
165 		void item_error(int);
166 		void query_finished();
167 
168 	private:
169 		class Private;
170 		Private *d;
171 
172 		S5BConnection *findIncoming(const Jid &from, const QString &sid) const;
173 		Entry *findEntry(S5BConnection *) const;
174 		Entry *findEntry(Item *) const;
175 		Entry *findEntryByHash(const QString &key) const;
176 		Entry *findEntryBySID(const Jid &peer, const QString &sid) const;
177 		Entry *findServerEntryByHash(const QString &key) const;
178 
179 		void entryContinue(Entry *e);
180 		void queryProxy(Entry *e);
181 		bool targetShouldOfferProxy(Entry *e);
182 
183 		friend class S5BConnection;
184 		void con_connect(S5BConnection *);
185 		void con_accept(S5BConnection *);
186 		void con_reject(S5BConnection *);
187 		void con_unlink(S5BConnection *);
188 		void con_sendUDP(S5BConnection *, const QByteArray &buf);
189 
190 		friend class S5BServer;
191 		bool srv_ownsHash(const QString &key) const;
192 		void srv_incomingReady(SocksClient *sc, const QString &key);
193 		void srv_incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data);
194 		void srv_unlink();
195 
196 		friend class Item;
197 		void doSuccess(const Jid &peer, const QString &id, const Jid &streamHost);
198 		void doError(const Jid &peer, const QString &id, int, const QString &);
199 		void doActivate(const Jid &peer, const QString &sid, const Jid &streamHost);
200 	};
201 
202 	class IRIS_EXPORT S5BConnector : public QObject
203 	{
204 		Q_OBJECT
205 	public:
206 		S5BConnector(QObject *parent=0);
207 		~S5BConnector() override;
208 
209 		void reset();
210 		void start(const Jid &self, const StreamHostList &hosts, const QString &key, bool udp, int timeout);
211 		SocksClient *takeClient();
212 		SocksUDP *takeUDP();
213 		StreamHost streamHostUsed() const;
214 
215 		class Item;
216 
217 	signals:
218 		void result(bool);
219 
220 	private slots:
221 		void item_result(bool);
222 		void t_timeout();
223 
224 	private:
225 		class Private;
226 		Private *d;
227 
228 		friend class S5BManager;
229 		void man_udpSuccess(const Jid &streamHost);
230 	};
231 
232 	// listens on a port for serving
233 	class IRIS_EXPORT S5BServer : public QObject
234 	{
235 		Q_OBJECT
236 	public:
237 		S5BServer(QObject *par=0);
238 		~S5BServer() override;
239 
240 		bool isActive() const;
241 		bool start(int port);
242 		void stop();
243 		int port() const;
244 		void setHostList(const QStringList &);
245 		QStringList hostList() const;
246 
247 		class Item;
248 
249 	private slots:
250 		void ss_incomingReady();
251 		void ss_incomingUDP(const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data);
252 		void item_result(bool);
253 
254 	private:
255 		class Private;
256 		Private *d;
257 
258 		friend class S5BManager;
259 		void link(S5BManager *);
260 		void unlink(S5BManager *);
261 		void unlinkAll();
262 		const QList<S5BManager*> & managerList() const;
263 		void writeUDP(const QHostAddress &addr, int port, const QByteArray &data);
264 	};
265 
266 	class IRIS_EXPORT JT_S5B : public Task
267 	{
268 		Q_OBJECT
269 	public:
270 		JT_S5B(Task *);
271 		~JT_S5B() override;
272 
273 		void request(const Jid &to, const QString &sid, const StreamHostList &hosts, bool fast, bool udp=false);
274 		void requestProxyInfo(const Jid &to);
275 		void requestActivation(const Jid &to, const QString &sid, const Jid &target);
276 
277 		void onGo() override;
278 		void onDisconnect() override;
279 		bool take(const QDomElement &) override;
280 
281 		Jid streamHostUsed() const;
282 		StreamHost proxyInfo() const;
283 
284 	private slots:
285 		void t_timeout();
286 
287 	private:
288 		class Private;
289 		Private *d;
290 	};
291 
292 	struct IRIS_EXPORT S5BRequest
293 	{
294 		Jid from;
295 		QString id, sid;
296 		StreamHostList hosts;
297 		bool fast;
298 		bool udp;
299 	};
300 	class IRIS_EXPORT JT_PushS5B : public Task
301 	{
302 		Q_OBJECT
303 	public:
304 		JT_PushS5B(Task *);
305 		~JT_PushS5B() override;
306 
307 		int priority() const;
308 
309 		void respondSuccess(const Jid &to, const QString &id, const Jid &streamHost);
310 		void respondError(const Jid &to, const QString &id, int code, const QString &str);
311 		void sendUDPSuccess(const Jid &to, const QString &dstaddr);
312 		void sendActivate(const Jid &to, const QString &sid, const Jid &streamHost);
313 
314 		bool take(const QDomElement &) override;
315 
316 	signals:
317 		void incoming(const S5BRequest &req);
318 		void incomingUDPSuccess(const Jid &from, const QString &dstaddr);
319 		void incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost);
320 	};
321 
322 	class IRIS_EXPORT StreamHost
323 	{
324 	public:
325 		StreamHost();
326 
327 		const Jid & jid() const;
328 		const QString & host() const;
329 		int port() const;
330 		bool isProxy() const;
331 		void setJid(const Jid &);
332 		void setHost(const QString &);
333 		void setPort(int);
334 		void setIsProxy(bool);
335 
336 	private:
337 		Jid j;
338 		QString v_host;
339 		int v_port;
340 		bool proxy;
341 	};
342 }
343 
344 #endif
345