QXmppStun.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /*
  2. * Copyright (C) 2008-2012 The QXmpp developers
  3. *
  4. * Author:
  5. * Jeremy Lainé
  6. *
  7. * Source:
  8. * http://code.google.com/p/qxmpp
  9. *
  10. * This file is a part of QXmpp library.
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation; either
  15. * version 2.1 of the License, or (at your option) any later version.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. */
  23. #ifndef QXMPPSTUN_H
  24. #define QXMPPSTUN_H
  25. #include <QObject>
  26. #include "QXmppLogger.h"
  27. #include "QXmppJingleIq.h"
  28. class QDataStream;
  29. class QUdpSocket;
  30. class QTimer;
  31. /// \internal
  32. ///
  33. /// The QXmppStunMessage class represents a STUN message.
  34. ///
  35. class QXMPP_EXPORT QXmppStunMessage
  36. {
  37. public:
  38. enum MethodType {
  39. Binding = 0x1,
  40. SharedSecret = 0x2,
  41. Allocate = 0x3,
  42. Refresh = 0x4,
  43. Send = 0x6,
  44. Data = 0x7,
  45. CreatePermission = 0x8,
  46. ChannelBind = 0x9,
  47. };
  48. enum ClassType {
  49. Request = 0x000,
  50. Indication = 0x010,
  51. Response = 0x100,
  52. Error = 0x110,
  53. };
  54. QXmppStunMessage();
  55. quint32 cookie() const;
  56. void setCookie(quint32 cookie);
  57. QByteArray id() const;
  58. void setId(const QByteArray &id);
  59. quint16 messageClass() const;
  60. quint16 messageMethod() const;
  61. quint16 type() const;
  62. void setType(quint16 type);
  63. // attributes
  64. quint32 changeRequest() const;
  65. void setChangeRequest(quint32 changeRequest);
  66. quint16 channelNumber() const;
  67. void setChannelNumber(quint16 channelNumber);
  68. QByteArray data() const;
  69. void setData(const QByteArray &data);
  70. quint32 lifetime() const;
  71. void setLifetime(quint32 changeRequest);
  72. QByteArray nonce() const;
  73. void setNonce(const QByteArray &nonce);
  74. quint32 priority() const;
  75. void setPriority(quint32 priority);
  76. QString realm() const;
  77. void setRealm(const QString &realm);
  78. QByteArray reservationToken() const;
  79. void setReservationToken(const QByteArray &reservationToken);
  80. quint8 requestedTransport() const;
  81. void setRequestedTransport(quint8 requestedTransport);
  82. QString software() const;
  83. void setSoftware(const QString &software);
  84. QString username() const;
  85. void setUsername(const QString &username);
  86. QByteArray encode(const QByteArray &key = QByteArray(), bool addFingerprint = true) const;
  87. bool decode(const QByteArray &buffer, const QByteArray &key = QByteArray(), QStringList *errors = 0);
  88. QString toString() const;
  89. static quint16 peekType(const QByteArray &buffer, quint32 &cookie, QByteArray &id);
  90. // attributes
  91. int errorCode;
  92. QString errorPhrase;
  93. QByteArray iceControlling;
  94. QByteArray iceControlled;
  95. QHostAddress changedHost;
  96. quint16 changedPort;
  97. QHostAddress mappedHost;
  98. quint16 mappedPort;
  99. QHostAddress otherHost;
  100. quint16 otherPort;
  101. QHostAddress sourceHost;
  102. quint16 sourcePort;
  103. QHostAddress xorMappedHost;
  104. quint16 xorMappedPort;
  105. QHostAddress xorPeerHost;
  106. quint16 xorPeerPort;
  107. QHostAddress xorRelayedHost;
  108. quint16 xorRelayedPort;
  109. bool useCandidate;
  110. private:
  111. quint32 m_cookie;
  112. QByteArray m_id;
  113. quint16 m_type;
  114. // attributes
  115. QSet<quint16> m_attributes;
  116. quint32 m_changeRequest;
  117. quint16 m_channelNumber;
  118. QByteArray m_data;
  119. quint32 m_lifetime;
  120. QByteArray m_nonce;
  121. quint32 m_priority;
  122. QString m_realm;
  123. quint8 m_requestedTransport;
  124. QByteArray m_reservationToken;
  125. QString m_software;
  126. QString m_username;
  127. };
  128. /// \internal
  129. ///
  130. /// The QXmppStunTransaction class represents a STUN transaction.
  131. ///
  132. class QXMPP_EXPORT QXmppStunTransaction : public QXmppLoggable
  133. {
  134. Q_OBJECT
  135. public:
  136. QXmppStunTransaction(const QXmppStunMessage &request, QObject *parent);
  137. QXmppStunMessage request() const;
  138. QXmppStunMessage response() const;
  139. signals:
  140. void finished();
  141. void writeStun(const QXmppStunMessage &request);
  142. public slots:
  143. void readStun(const QXmppStunMessage &response);
  144. private slots:
  145. void retry();
  146. private:
  147. QXmppStunMessage m_request;
  148. QXmppStunMessage m_response;
  149. QTimer *m_retryTimer;
  150. int m_tries;
  151. };
  152. /// \internal
  153. ///
  154. /// The QXmppTurnAllocation class represents a TURN allocation as defined
  155. /// by RFC 5766 Traversal Using Relays around NAT (TURN).
  156. ///
  157. class QXMPP_EXPORT QXmppTurnAllocation : public QXmppLoggable
  158. {
  159. Q_OBJECT
  160. public:
  161. enum AllocationState
  162. {
  163. UnconnectedState,
  164. ConnectingState,
  165. ConnectedState,
  166. ClosingState,
  167. };
  168. QXmppTurnAllocation(QObject *parent = 0);
  169. ~QXmppTurnAllocation();
  170. QHostAddress relayedHost() const;
  171. quint16 relayedPort() const;
  172. AllocationState state() const;
  173. void setServer(const QHostAddress &host, quint16 port = 3478);
  174. void setUser(const QString &user);
  175. void setPassword(const QString &password);
  176. qint64 writeDatagram(const QByteArray &data, const QHostAddress &host, quint16 port);
  177. signals:
  178. /// \brief This signal is emitted once TURN allocation succeeds.
  179. void connected();
  180. /// \brief This signal is emitted when a data packet is received.
  181. void datagramReceived(const QByteArray &data, const QHostAddress &host, quint16 port);
  182. /// \brief This signal is emitted when TURN allocation fails.
  183. void disconnected();
  184. public slots:
  185. void connectToHost();
  186. void disconnectFromHost();
  187. private slots:
  188. void readyRead();
  189. void refresh();
  190. void refreshChannels();
  191. void transactionFinished();
  192. void writeStun(const QXmppStunMessage &message);
  193. private:
  194. void handleDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port);
  195. void setState(AllocationState state);
  196. QUdpSocket *socket;
  197. QTimer *m_timer;
  198. QTimer *m_channelTimer;
  199. QString m_password;
  200. QString m_username;
  201. QHostAddress m_relayedHost;
  202. quint16 m_relayedPort;
  203. QHostAddress m_turnHost;
  204. quint16 m_turnPort;
  205. // channels
  206. typedef QPair<QHostAddress, quint16> Address;
  207. quint16 m_channelNumber;
  208. QMap<quint16, Address> m_channels;
  209. // state
  210. quint32 m_lifetime;
  211. QByteArray m_key;
  212. QString m_realm;
  213. QByteArray m_nonce;
  214. AllocationState m_state;
  215. QList<QXmppStunTransaction*> m_transactions;
  216. };
  217. /// \brief The QXmppIceComponent class represents a piece of a media stream
  218. /// requiring a single transport address, as defined by RFC 5245
  219. /// (Interactive Connectivity Establishment).
  220. class QXMPP_EXPORT QXmppIceComponent : public QXmppLoggable
  221. {
  222. Q_OBJECT
  223. public:
  224. QXmppIceComponent(QObject *parent=0);
  225. ~QXmppIceComponent();
  226. void setIceControlling(bool controlling);
  227. void setStunServer(const QHostAddress &host, quint16 port);
  228. void setTurnServer(const QHostAddress &host, quint16 port);
  229. void setTurnUser(const QString &user);
  230. void setTurnPassword(const QString &password);
  231. QList<QXmppJingleCandidate> localCandidates() const;
  232. void setLocalUser(const QString &user);
  233. void setLocalPassword(const QString &password);
  234. int component() const;
  235. void setComponent(int component);
  236. bool addRemoteCandidate(const QXmppJingleCandidate &candidate);
  237. void setRemoteUser(const QString &user);
  238. void setRemotePassword(const QString &password);
  239. bool isConnected() const;
  240. void setSockets(QList<QUdpSocket*> sockets);
  241. static QList<QHostAddress> discoverAddresses();
  242. static QList<QUdpSocket*> reservePorts(const QList<QHostAddress> &addresses, int count, QObject *parent = 0);
  243. public slots:
  244. void close();
  245. void connectToHost();
  246. qint64 sendDatagram(const QByteArray &datagram);
  247. private slots:
  248. void checkCandidates();
  249. void checkStun();
  250. void handleDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port, QUdpSocket *socket = 0);
  251. void readyRead();
  252. void turnConnected();
  253. signals:
  254. /// \brief This signal is emitted once ICE negotiation succeeds.
  255. void connected();
  256. /// \brief This signal is emitted when a data packet is received.
  257. void datagramReceived(const QByteArray &datagram);
  258. /// \brief This signal is emitted when the list of local candidates changes.
  259. void localCandidatesChanged();
  260. private:
  261. class Pair {
  262. public:
  263. Pair(int component, bool controlling);
  264. quint64 priority() const;
  265. QString toString() const;
  266. QIODevice::OpenMode checked;
  267. QXmppJingleCandidate remote;
  268. QXmppJingleCandidate reflexive;
  269. QByteArray transaction;
  270. QUdpSocket *socket;
  271. private:
  272. int m_component;
  273. bool m_controlling;
  274. };
  275. Pair *addRemoteCandidate(QUdpSocket *socket, const QHostAddress &host, quint16 port, quint32 priority);
  276. qint64 writeStun(const QXmppStunMessage &message, QXmppIceComponent::Pair *pair);
  277. int m_component;
  278. QList<QXmppJingleCandidate> m_localCandidates;
  279. QString m_localUser;
  280. QString m_localPassword;
  281. Pair *m_activePair;
  282. Pair *m_fallbackPair;
  283. bool m_iceControlling;
  284. QList<Pair*> m_pairs;
  285. quint32 m_peerReflexivePriority;
  286. QString m_remoteUser;
  287. QString m_remotePassword;
  288. QList<QUdpSocket*> m_sockets;
  289. QTimer *m_timer;
  290. // STUN server
  291. QByteArray m_stunId;
  292. QHostAddress m_stunHost;
  293. quint16 m_stunPort;
  294. QTimer *m_stunTimer;
  295. int m_stunTries;
  296. // TURN server
  297. QXmppTurnAllocation *m_turnAllocation;
  298. bool m_turnConfigured;
  299. };
  300. /// \brief The QXmppIceConnection class represents a set of UDP sockets
  301. /// capable of performing Interactive Connectivity Establishment (RFC 5245).
  302. ///
  303. class QXMPP_EXPORT QXmppIceConnection : public QXmppLoggable
  304. {
  305. Q_OBJECT
  306. public:
  307. QXmppIceConnection(QObject *parent = 0);
  308. QXmppIceComponent *component(int component);
  309. void addComponent(int component);
  310. void setIceControlling(bool controlling);
  311. QList<QXmppJingleCandidate> localCandidates() const;
  312. QString localUser() const;
  313. void setLocalUser(const QString &user);
  314. QString localPassword() const;
  315. void setLocalPassword(const QString &password);
  316. void addRemoteCandidate(const QXmppJingleCandidate &candidate);
  317. void setRemoteUser(const QString &user);
  318. void setRemotePassword(const QString &password);
  319. void setStunServer(const QHostAddress &host, quint16 port = 3478);
  320. void setTurnServer(const QHostAddress &host, quint16 port = 3478);
  321. void setTurnUser(const QString &user);
  322. void setTurnPassword(const QString &password);
  323. bool bind(const QList<QHostAddress> &addresses);
  324. bool isConnected() const;
  325. signals:
  326. /// \brief This signal is emitted once ICE negotiation succeeds.
  327. void connected();
  328. /// \brief This signal is emitted when ICE negotiation fails.
  329. void disconnected();
  330. /// \brief This signal is emitted when the list of local candidates changes.
  331. void localCandidatesChanged();
  332. public slots:
  333. void close();
  334. void connectToHost();
  335. private slots:
  336. void slotConnected();
  337. void slotTimeout();
  338. private:
  339. QTimer *m_connectTimer;
  340. bool m_iceControlling;
  341. QMap<int, QXmppIceComponent*> m_components;
  342. QString m_localUser;
  343. QString m_localPassword;
  344. QHostAddress m_stunHost;
  345. quint16 m_stunPort;
  346. QHostAddress m_turnHost;
  347. quint16 m_turnPort;
  348. QString m_turnUser;
  349. QString m_turnPassword;
  350. };
  351. #endif