File indexing completed on 2024-06-23 04:03:39

0001 /*
0002  * s5b.h - direct connection protocol via tcp
0003  * Copyright (C) 2003  Justin Karneges
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * either version 2
0009    of the License, or (at your option) any later version.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library; if not, write to the Free Software
0018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0019  *
0020  */
0021 
0022 #ifndef XMPP_S5B_H
0023 #define XMPP_S5B_H
0024 
0025 #include <QObject>
0026 #include <QList>
0027 #include <QHostAddress>
0028 
0029 #include "iris_export.h"
0030 #include "bytestream.h"
0031 #include "xmpp/jid/jid.h"
0032 #include "xmpp_task.h"
0033 
0034 class SocksClient;
0035 class SocksUDP;
0036 
0037 namespace XMPP
0038 {
0039     class StreamHost;
0040     class Client;
0041     class S5BConnection;
0042     class S5BManager;
0043     class S5BServer;
0044     struct S5BRequest;
0045     typedef QList<StreamHost> StreamHostList;
0046     typedef QList<S5BConnection*> S5BConnectionList;
0047 
0048     class IRIS_EXPORT S5BDatagram
0049     {
0050     public:
0051         S5BDatagram();
0052         S5BDatagram(int source, int dest, const QByteArray &data);
0053 
0054         int sourcePort() const;
0055         int destPort() const;
0056         QByteArray data() const;
0057 
0058     private:
0059         int _source, _dest;
0060         QByteArray _buf;
0061     };
0062 
0063     class IRIS_EXPORT S5BConnection : public ByteStream
0064     {
0065         Q_OBJECT
0066     public:
0067         enum Mode { Stream, Datagram };
0068         enum Error { ErrRefused, ErrConnect, ErrProxy, ErrSocket };
0069         enum State { Idle, Requesting, Connecting, WaitingForAccept, Active };
0070         ~S5BConnection() override;
0071 
0072         Jid proxy() const;
0073         void setProxy(const Jid &proxy);
0074 
0075         void connectToJid(const Jid &peer, const QString &sid, Mode m = Stream);
0076         void accept();
0077         void close() override;
0078 
0079         Jid peer() const;
0080         QString sid() const;
0081         bool isRemote() const;
0082         Mode mode() const;
0083         int state() const;
0084 
0085         bool isOpen() const override;
0086         void write(const QByteArray &) override;
0087         QByteArray read(int bytes=0) override;
0088         int bytesAvailable() const override;
0089         int bytesToWrite() const override;
0090 
0091         void writeDatagram(const S5BDatagram &);
0092         S5BDatagram readDatagram();
0093         int datagramsAvailable() const;
0094 
0095     signals:
0096         void proxyQuery();                             // querying proxy for streamhost information
0097         void proxyResult(bool b);                      // query success / fail
0098         void requesting();                             // sent actual S5B request (initiator only)
0099         void accepted();                               // target accepted (initiator only
0100         void tryingHosts(const StreamHostList &hosts); // currently connecting to these hosts
0101         void proxyConnect();                           // connecting to proxy
0102         void waitingForActivation();                   // waiting for activation (target only)
0103         void connected();                              // connection active
0104         void datagramReady();
0105 
0106     private slots:
0107         void doPending();
0108 
0109         void sc_connectionClosed();
0110         void sc_delayedCloseFinished();
0111         void sc_readyRead();
0112         void sc_bytesWritten(int);
0113         void sc_error(int);
0114 
0115         void su_packetReady(const QByteArray &buf);
0116 
0117     private:
0118         class Private;
0119         Private *d;
0120 
0121         void reset(bool clear=false);
0122         void handleUDP(const QByteArray &buf);
0123         void sendUDP(const QByteArray &buf);
0124 
0125         friend class S5BManager;
0126         void man_waitForAccept(const S5BRequest &r);
0127         void man_clientReady(SocksClient *, SocksUDP *);
0128         void man_udpReady(const QByteArray &buf);
0129         void man_failed(int);
0130         S5BConnection(S5BManager *, QObject *parent=0);
0131     };
0132 
0133     class IRIS_EXPORT S5BManager : public QObject
0134     {
0135         Q_OBJECT
0136     public:
0137         S5BManager(Client *);
0138         ~S5BManager() override;
0139 
0140         Client *client() const;
0141         S5BServer *server() const;
0142         void setServer(S5BServer *s);
0143 
0144         bool isAcceptableSID(const Jid &peer, const QString &sid) const;
0145         QString genUniqueSID(const Jid &peer) const;
0146 
0147         S5BConnection *createConnection();
0148         S5BConnection *takeIncoming();
0149 
0150         class Item;
0151         class Entry;
0152 
0153     signals:
0154         void incomingReady();
0155 
0156     private slots:
0157         void ps_incoming(const S5BRequest &req);
0158         void ps_incomingUDPSuccess(const Jid &from, const QString &dstaddr);
0159         void ps_incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost);
0160         void item_accepted();
0161         void item_tryingHosts(const StreamHostList &list);
0162         void item_proxyConnect();
0163         void item_waitingForActivation();
0164         void item_connected();
0165         void item_error(int);
0166         void query_finished();
0167 
0168     private:
0169         class Private;
0170         Private *d;
0171 
0172         S5BConnection *findIncoming(const Jid &from, const QString &sid) const;
0173         Entry *findEntry(S5BConnection *) const;
0174         Entry *findEntry(Item *) const;
0175         Entry *findEntryByHash(const QString &key) const;
0176         Entry *findEntryBySID(const Jid &peer, const QString &sid) const;
0177         Entry *findServerEntryByHash(const QString &key) const;
0178 
0179         void entryContinue(Entry *e);
0180         void queryProxy(Entry *e);
0181         bool targetShouldOfferProxy(Entry *e);
0182 
0183         friend class S5BConnection;
0184         void con_connect(S5BConnection *);
0185         void con_accept(S5BConnection *);
0186         void con_reject(S5BConnection *);
0187         void con_unlink(S5BConnection *);
0188         void con_sendUDP(S5BConnection *, const QByteArray &buf);
0189 
0190         friend class S5BServer;
0191         bool srv_ownsHash(const QString &key) const;
0192         void srv_incomingReady(SocksClient *sc, const QString &key);
0193         void srv_incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data);
0194         void srv_unlink();
0195 
0196         friend class Item;
0197         void doSuccess(const Jid &peer, const QString &id, const Jid &streamHost);
0198         void doError(const Jid &peer, const QString &id, int, const QString &);
0199         void doActivate(const Jid &peer, const QString &sid, const Jid &streamHost);
0200     };
0201 
0202     class IRIS_EXPORT S5BConnector : public QObject
0203     {
0204         Q_OBJECT
0205     public:
0206         S5BConnector(QObject *parent=0);
0207         ~S5BConnector() override;
0208 
0209         void reset();
0210         void start(const Jid &self, const StreamHostList &hosts, const QString &key, bool udp, int timeout);
0211         SocksClient *takeClient();
0212         SocksUDP *takeUDP();
0213         StreamHost streamHostUsed() const;
0214 
0215         class Item;
0216 
0217     signals:
0218         void result(bool);
0219 
0220     private slots:
0221         void item_result(bool);
0222         void t_timeout();
0223 
0224     private:
0225         class Private;
0226         Private *d;
0227 
0228         friend class S5BManager;
0229         void man_udpSuccess(const Jid &streamHost);
0230     };
0231 
0232     // listens on a port for serving
0233     class IRIS_EXPORT S5BServer : public QObject
0234     {
0235         Q_OBJECT
0236     public:
0237         S5BServer(QObject *par=0);
0238         ~S5BServer() override;
0239 
0240         bool isActive() const;
0241         bool start(int port);
0242         void stop();
0243         int port() const;
0244         void setHostList(const QStringList &);
0245         QStringList hostList() const;
0246 
0247         class Item;
0248 
0249     private slots:
0250         void ss_incomingReady();
0251         void ss_incomingUDP(const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data);
0252         void item_result(bool);
0253 
0254     private:
0255         class Private;
0256         Private *d;
0257 
0258         friend class S5BManager;
0259         void link(S5BManager *);
0260         void unlink(S5BManager *);
0261         void unlinkAll();
0262         const QList<S5BManager*> & managerList() const;
0263         void writeUDP(const QHostAddress &addr, int port, const QByteArray &data);
0264     };
0265 
0266     class IRIS_EXPORT JT_S5B : public Task
0267     {
0268         Q_OBJECT
0269     public:
0270         JT_S5B(Task *);
0271         ~JT_S5B() override;
0272 
0273         void request(const Jid &to, const QString &sid, const StreamHostList &hosts, bool fast, bool udp=false);
0274         void requestProxyInfo(const Jid &to);
0275         void requestActivation(const Jid &to, const QString &sid, const Jid &target);
0276 
0277         void onGo() override;
0278         void onDisconnect() override;
0279         bool take(const QDomElement &) override;
0280 
0281         Jid streamHostUsed() const;
0282         StreamHost proxyInfo() const;
0283 
0284     private slots:
0285         void t_timeout();
0286 
0287     private:
0288         class Private;
0289         Private *d;
0290     };
0291 
0292     struct IRIS_EXPORT S5BRequest
0293     {
0294         Jid from;
0295         QString id, sid;
0296         StreamHostList hosts;
0297         bool fast;
0298         bool udp;
0299     };
0300     class IRIS_EXPORT JT_PushS5B : public Task
0301     {
0302         Q_OBJECT
0303     public:
0304         JT_PushS5B(Task *);
0305         ~JT_PushS5B() override;
0306 
0307         int priority() const;
0308 
0309         void respondSuccess(const Jid &to, const QString &id, const Jid &streamHost);
0310         void respondError(const Jid &to, const QString &id, int code, const QString &str);
0311         void sendUDPSuccess(const Jid &to, const QString &dstaddr);
0312         void sendActivate(const Jid &to, const QString &sid, const Jid &streamHost);
0313 
0314         bool take(const QDomElement &) override;
0315 
0316     signals:
0317         void incoming(const S5BRequest &req);
0318         void incomingUDPSuccess(const Jid &from, const QString &dstaddr);
0319         void incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost);
0320     };
0321 
0322     class IRIS_EXPORT StreamHost
0323     {
0324     public:
0325         StreamHost();
0326 
0327         const Jid & jid() const;
0328         const QString & host() const;
0329         int port() const;
0330         bool isProxy() const;
0331         void setJid(const Jid &);
0332         void setHost(const QString &);
0333         void setPort(int);
0334         void setIsProxy(bool);
0335 
0336     private:
0337         Jid j;
0338         QString v_host;
0339         int v_port;
0340         bool proxy;
0341     };
0342 }
0343 
0344 #endif