1#include "DownloadQueue.hpp"
11#define MAX_PARALLEL_DOWNLOADS 4
14#define SOCU_ALIGN 0x1000
15#define SOCU_BUFFERSIZE 0x100000
18#define SO_TCPSACK 0x00200
22#define SO_WINSCALE 0x00400
26#define SO_RCVBUF 0x01002
32int sockopt_callback_chesto(
void*, curl_socket_t curlfd, curlsocktype)
34 int winscale = 1, rcvbuf = 0x20000, tcpsack = 1;
36 setsockopt(curlfd, SOL_SOCKET, SO_WINSCALE, &winscale,
sizeof(
int));
37 setsockopt(curlfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf,
sizeof(
int));
38 setsockopt(curlfd, SOL_SOCKET, SO_TCPSACK, &tcpsack,
sizeof(
int));
44DownloadQueue* DownloadQueue::downloadQueue = NULL;
46void DownloadQueue::init()
48 downloadQueue =
new DownloadQueue();
51void DownloadQueue::quit()
56static size_t WriteCallback(
char *data,
size_t n,
size_t l,
void *userp)
58 DownloadOperation *download = (DownloadOperation *)userp;
59 download->buffer.append(data, n * l);
63DownloadQueue::DownloadQueue()
66 cm = curl_multi_init();
67 curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, MAX_PARALLEL_DOWNLOADS);
71DownloadQueue::~DownloadQueue()
74 curl_multi_cleanup(cm);
82 download->status = DownloadStatus::QUEUED;
83 queue.push_back(download);
89 if (download->status == DownloadStatus::DOWNLOADING)
90 transferFinish(download);
91 else if (download->status == DownloadStatus::QUEUED && queue.size() > 0)
92 queue.remove(download);
96void DownloadQueue::setPlatformCurlFlags(CURL* c)
102 curl_easy_setopt(c, CURLOPT_CAINFO, RAMFS
"res/cacert.pem");
104 curl_easy_setopt(c, CURLOPT_SOCKOPTFUNCTION, sockopt_callback_chesto);
109void DownloadQueue::transferStart(DownloadOperation *download)
112 download->eh = curl_easy_init();
114 setPlatformCurlFlags(download->eh);
116 curl_easy_setopt(download->eh, CURLOPT_URL, download->url.c_str());
117 curl_easy_setopt(download->eh, CURLOPT_WRITEFUNCTION, WriteCallback);
118 curl_easy_setopt(download->eh, CURLOPT_WRITEDATA, download);
119 curl_easy_setopt(download->eh, CURLOPT_PRIVATE, download);
121 curl_easy_setopt(download->eh, CURLOPT_FOLLOWLOCATION, 1L);
123 curl_multi_add_handle(cm, download->eh);
129void DownloadQueue::transferFinish(DownloadOperation *download)
133 curl_multi_remove_handle(cm, download->eh);
135 curl_easy_cleanup(download->eh);
141void DownloadQueue::startTransfersFromQueue()
144 while ((transfers < MAX_PARALLEL_DOWNLOADS) && (queue.size() > 0))
147 DownloadOperation *download = queue.front();
151 download->status = DownloadStatus::DOWNLOADING;
152 transferStart(download);
167 curl_multi_perform(cm, &still_alive);
170 while((msg = curl_multi_info_read(cm, &msgs_left)))
172 long response_code = 404;
174 if (msg->msg != CURLMSG_DONE)
177 curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &download);
178 curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response_code);
180 transferFinish(download);
181 startTransfersFromQueue();
183 if (response_code == 200)
184 download->status = DownloadStatus::COMPLETE;
186 download->status = DownloadStatus::FAILED;
188 download->cb(download);
191 startTransfersFromQueue();
193 return ((still_alive) || (msgs_left > 0) || (queue.size() > 0));
void downloadCancel(DownloadOperation *download)
cancel a download operation
void downloadAdd(DownloadOperation *download)
add a new download operation
int process()
process finished and queued downloads