1 /*
2  * Copyright (C) 2010  Barracuda Networks, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301  USA
18  *
19  */
20 
21 #ifndef TURNCLIENT_H
22 #define TURNCLIENT_H
23 
24 #include <QObject>
25 #include <QByteArray>
26 #include <QString>
27 #include <QHostAddress>
28 
29 namespace QCA {
30 	class SecureArray;
31 }
32 
33 namespace XMPP {
34 
35 class StunTransactionPool;
36 class StunAllocate;
37 
38 class TurnClient : public QObject
39 {
40 	Q_OBJECT
41 
42 public:
43 	enum Error
44 	{
45 		ErrorGeneric,
46 		ErrorHostNotFound,
47 		ErrorConnect,
48 
49 		// stream error or stream unexpectedly disconnected by peer
50 		ErrorStream,
51 
52 		ErrorProxyConnect,
53 		ErrorProxyNeg,
54 		ErrorProxyAuth,
55 		ErrorTls,
56 		ErrorAuth,
57 		ErrorRejected,
58 		ErrorProtocol,
59 		ErrorCapacity,
60 
61 		// according to the TURN spec, a client should try three times
62 		//   to correct a mismatch error before giving up.  this class
63 		//   will perform the retries internally, and ErrorMismatch is
64 		//   only emitted when it has given up.  note that if this
65 		//   happens, the TURN spec says you should not connect to the
66 		//   TURN server again for at least 2 minutes.
67 		// note: in UDP mode, this class does not perform retries and
68 		//   will emit this error immediately.
69 		ErrorMismatch
70 	};
71 
72 	enum Mode
73 	{
74 		PlainMode,
75 		TlsMode
76 	};
77 
78 	enum DebugLevel
79 	{
80 		DL_None,
81 		DL_Info,
82 		DL_Packet
83 	};
84 
85 	// adapted from XMPP::AdvancedConnector
86 	class Proxy
87 	{
88 	public:
89 		enum
90 		{
91 			None,
92 			HttpConnect,
93 			Socks
94 		};
95 
96 		Proxy();
97 		~Proxy();
98 
99 		int type() const;
100 		QString host() const;
101 		quint16 port() const;
102 		QString user() const;
103 		QString pass() const;
104 
105 		void setHttpConnect(const QString &host, quint16 port);
106 		void setSocks(const QString &host, quint16 port);
107 		void setUserPass(const QString &user, const QString &pass);
108 
109 	private:
110 		int t;
111 		QString v_host;
112 		quint16 v_port;
113 		QString v_user, v_pass;
114 	};
115 
116 	TurnClient(QObject *parent = 0);
117 	~TurnClient();
118 
119 	void setProxy(const Proxy &proxy);
120 	void setClientSoftwareNameAndVersion(const QString &str);
121 
122 	// for UDP.  does not take ownership of the pool.  stun transaction
123 	//   I/O occurs through the pool.  transfer of data packets occurs
124 	//   via processIncomingDatagram(), outgoingDatagram(), and
125 	//   outgoingDatagramsWritten().  authentication happens through the
126 	//   pool and not through this class.  the turn addr/port is optional,
127 	//   and used only for addr association with the pool
128 	void connectToHost(StunTransactionPool *pool, const QHostAddress &addr = QHostAddress(), int port = -1);
129 
130 	// for TCP and TCP-TLS
131 	void connectToHost(const QHostAddress &addr, int port, Mode mode = PlainMode);
132 
133 	// for UDP, use this function to process incoming packets instead of
134 	//   read().
135 	QByteArray processIncomingDatagram(const QByteArray &buf, bool notStun, QHostAddress *addr, int *port);
136 
137 	// call after writing datagrams from outgoingDatagram.  not DOR-DS safe
138 	void outgoingDatagramsWritten(int count);
139 
140 	QString realm() const;
141 	void setUsername(const QString &username);
142 	void setPassword(const QCA::SecureArray &password);
143 	void setRealm(const QString &realm);
144 	void continueAfterParams();
145 
146 	void close();
147 
148 	StunAllocate *stunAllocate();
149 
150 	void addChannelPeer(const QHostAddress &addr, int port);
151 
152 	int packetsToRead() const;
153 	int packetsToWrite() const;
154 
155 	// TCP mode only
156 	QByteArray read(QHostAddress *addr, int *port);
157 
158 	// for UDP, this call may emit outgoingDatagram() immediately (not
159 	//   DOR-DS safe)
160 	void write(const QByteArray &buf, const QHostAddress &addr, int port);
161 
162 	QString errorString() const;
163 
164 	void setDebugLevel(DebugLevel level); // default DL_None
165 
166 signals:
167 	void connected(); // tcp connected
168 	void tlsHandshaken();
169 	void closed();
170 	void needAuthParams();
171 	void retrying(); // mismatch error received, starting all over
172 	void activated(); // ready for read/write
173 
174 	// TCP mode only
175 	void readyRead();
176 
177 	void packetsWritten(int count, const QHostAddress &addr, int port);
178 	void error(XMPP::TurnClient::Error e);
179 
180 	// data packets to be sent to the TURN server, UDP mode only
181 	void outgoingDatagram(const QByteArray &buf);
182 
183 	// not DOR-SS/DS safe
184 	void debugLine(const QString &line);
185 
186 private:
187 	class Private;
188 	friend class Private;
189 	Private *d;
190 };
191 
192 }
193 
194 #endif
195