1 /* 2 SPDX-FileCopyrightText: 2008 Joris Guisson <joris.guisson@gmail.com> 3 SPDX-FileCopyrightText: 2008 Ivan Vasic <ivasic@gmail.com> 4 5 SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 #ifndef BTHTTPCONNECTION_H 8 #define BTHTTPCONNECTION_H 9 10 #include <QMutex> 11 #include <QTimer> 12 #include <QUrl> 13 #include <net/addressresolver.h> 14 #include <net/streamsocket.h> 15 16 class QUrl; 17 18 namespace bt 19 { 20 /** 21 @author Joris Guisson 22 23 HTTP connection for webseeding. We do not use KIO here, because we want to be able to apply 24 the maximum upload and download rate to webseeds; 25 */ 26 class HttpConnection : public QObject, public net::SocketReader, public net::StreamSocketListener 27 { 28 Q_OBJECT 29 public: 30 HttpConnection(); 31 ~HttpConnection() override; 32 33 /// Get the last http response code responseCode()34 int responseCode() const 35 { 36 return response_code; 37 } 38 39 /// Is this connection redirected isRedirected()40 bool isRedirected() const 41 { 42 return redirected; 43 } 44 45 /// Get the redirected url redirectedUrl()46 QUrl redirectedUrl() const 47 { 48 return redirected_url; 49 } 50 51 /** 52 * Set the group ID's of the socket 53 * @param up Upload group id 54 * @param down Download group id 55 */ 56 void setGroupIDs(Uint32 up, Uint32 down); 57 58 /** 59 * Connect to a webseed 60 * @param url Url of the webseeder 61 */ 62 void connectTo(const QUrl &url); 63 64 /** 65 * Connect to a proxy. 66 * @param proxy The HTTP proxy to use (null means don't use any) 67 * @param proxy_port The port of the HTTP proxy 68 */ 69 void connectToProxy(const QString &proxy, Uint16 proxy_port); 70 71 /// Check if the connection is OK 72 bool ok() const; 73 74 /// See if we are connected 75 bool connected() const; 76 77 /// Has the connection been closed 78 bool closed() const; 79 80 /// Ready to do another request 81 bool ready() const; 82 83 /** 84 * Do a HTTP GET request 85 * @param path The path of the file 86 * @param query The query string for the url 87 * @param start Offset into file 88 * @param len Length of data to download 89 */ 90 bool get(const QString &host, const QString &path, const QString &query, bt::Uint64 start, bt::Uint64 len); 91 92 void onDataReady(Uint8 *buf, Uint32 size) override; 93 void connectFinished(bool succeeded) override; 94 void dataSent() override; 95 96 /** 97 * Get some part of the 98 * @param data Bytearray to copy the data into 99 * @return true if data was filled in 100 */ 101 bool getData(QByteArray &data); 102 103 /// Get the current download rate 104 int getDownloadRate() const; 105 106 /// Get the status string 107 const QString getStatusString() const; 108 109 private: 110 void hostResolved(net::AddressResolver *ar); 111 void connectTimeout(); 112 void replyTimeout(); 113 114 Q_SIGNALS: 115 void startReplyTimer(int timeout); 116 void stopReplyTimer(); 117 void stopConnectTimer(); 118 119 private: 120 enum State { 121 IDLE, 122 RESOLVING, 123 CONNECTING, 124 ACTIVE, 125 ERROR, 126 CLOSED, 127 }; 128 129 struct HttpGet { 130 QString host; 131 QString path; 132 QString query; 133 bt::Uint64 start; 134 bt::Uint64 len; 135 bt::Uint64 data_received; 136 QByteArray buffer; 137 QByteArray piece_data; 138 bool response_header_received; 139 bool request_sent; 140 QString failure_reason; 141 bool redirected; 142 QUrl redirected_to; 143 bt::Uint64 content_length; 144 int response_code; 145 146 HttpGet(const QString &host, const QString &path, const QString &query, bt::Uint64 start, bt::Uint64 len, bool using_proxy); 147 virtual ~HttpGet(); 148 149 bool onDataReady(Uint8 *buf, Uint32 size); finishedHttpGet150 bool finished() const 151 { 152 return data_received >= len; 153 } 154 }; 155 156 net::StreamSocket *sock; 157 State state; 158 mutable QMutex mutex; 159 HttpGet *request; 160 bool using_proxy; 161 QString status; 162 QTimer connect_timer; 163 QTimer reply_timer; 164 Uint32 up_gid, down_gid; 165 bool close_when_finished; 166 bool redirected; 167 QUrl redirected_url; 168 int response_code; 169 }; 170 } 171 172 #endif 173