/
mythsingledownload.cpp
127 lines (106 loc) · 3.53 KB
/
mythsingledownload.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "mythsingledownload.h"
#include "mythversion.h"
#include "mythlogging.h"
/*
* For simple one-at-a-time downloads, this routine (found at
* http://www.insanefactory.com/2012/08/qt-http-request-in-a-single-function/
* ) works well.
*/
#define LOC QString("MythSingleDownload: ")
bool MythSingleDownload::DownloadURL(const QUrl &url, QByteArray *buffer,
uint timeout, uint redirs, qint64 maxsize)
{
m_lock.lock();
QEventLoop event_loop;
m_buffer = buffer;
// the HTTP request
QNetworkRequest req(url);
req.setRawHeader("User-Agent",
"MythTV v" MYTH_BINARY_VERSION " MythSingleDownload");
m_replylock.lock();
m_reply = m_mgr.get(req);
m_replylock.unlock();
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
QNetworkRequest::AlwaysNetwork);
// "quit()" the event-loop, when the network request "finished()"
connect(&m_timer, SIGNAL(timeout()), &event_loop, SLOT(quit()));
connect(m_reply, SIGNAL(finished()), &event_loop, SLOT(quit()));
connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(Progress(qint64,qint64)));
// Configure timeout and size limit
m_maxsize = maxsize;
m_timer.setSingleShot(true);
m_timer.start(timeout); // 30 secs. by default
bool ret = event_loop.exec() != 0; // blocks stack until quit() is called
disconnect(&m_timer, SIGNAL(timeout()), &event_loop, SLOT(quit()));
disconnect(m_reply, SIGNAL(finished()), &event_loop, SLOT(quit()));
disconnect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(Progress(qint64,qint64)));
if (ret)
{
LOG(VB_GENERAL, LOG_ERR, LOC + "evenloop failed");
}
m_replylock.lock();
if (!m_timer.isActive())
{
m_errorstring = "timed-out";
m_reply->abort();
ret = false;
}
else
{
m_timer.stop();
m_errorcode = m_reply->error();
QString redir = m_reply->attribute(
QNetworkRequest::RedirectionTargetAttribute).toUrl().toString();
if (redir.length())
{
if (redirs <= 3)
{
LOG(VB_GENERAL, LOG_INFO, QString("%1 -> %2").arg(url.toString()).arg(redir));
m_replylock.unlock();
m_lock.unlock();
return DownloadURL(redir, buffer, timeout, redirs + 1);
}
LOG(VB_GENERAL, LOG_ERR, QString("%1: too many redirects").arg(url.toString()));
ret = false;
}
else if (m_errorcode == QNetworkReply::NoError)
{
*m_buffer += m_reply->readAll();
m_errorstring.clear();
ret = true;
}
else
{
m_errorstring = m_reply->errorString();
ret = false;
}
}
m_replylock.unlock();
m_lock.unlock();
delete m_reply;
m_reply = nullptr;
m_buffer = nullptr;
return ret;
}
void MythSingleDownload::Cancel(void)
{
QMutexLocker replylock(&m_replylock);
if (m_reply)
{
LOG(VB_GENERAL, LOG_INFO, LOC + "Aborting download");
m_reply->abort();
}
}
void MythSingleDownload::Progress(qint64 bytesRead, qint64 /*totalBytes*/)
{
if (m_maxsize && bytesRead>=m_maxsize)
{
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Reached specified max file size (%1 bytes)").arg(m_maxsize));
{
QMutexLocker replylock(&m_replylock);
*m_buffer += m_reply->read(m_maxsize);
}
m_maxsize=0;
Cancel();
}
}