1#include "DownloadQueue.hpp" 
    9#define MAX_PARALLEL_DOWNLOADS  4 
   12#define SOCU_ALIGN 0x1000 
   13#define SOCU_BUFFERSIZE 0x100000 
   16#define SO_TCPSACK 0x00200  
   20#define SO_WINSCALE 0x00400   
   24#define SO_RCVBUF 0x01002  
   30int sockopt_callback_chesto(
void *clientp, curl_socket_t curlfd, curlsocktype purpose)
 
   32    int winscale = 1, rcvbuf = 0x20000, tcpsack = 1;
 
   34    setsockopt(curlfd, SOL_SOCKET, SO_WINSCALE, &winscale, 
sizeof(
int));
 
   35    setsockopt(curlfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, 
sizeof(
int));
 
   36    setsockopt(curlfd, SOL_SOCKET, SO_TCPSACK, &tcpsack, 
sizeof(
int));
 
   44void DownloadQueue::init()
 
   49void DownloadQueue::quit()
 
   54static size_t WriteCallback(
char *data, 
size_t n, 
size_t l, 
void *userp)
 
   57    download->buffer.append(data, n * l);
 
   61DownloadQueue::DownloadQueue()
 
   64    cm = curl_multi_init();
 
   65    curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, MAX_PARALLEL_DOWNLOADS);
 
   69DownloadQueue::~DownloadQueue()
 
   72    curl_multi_cleanup(cm);
 
   80    download->status = DownloadStatus::QUEUED;
 
   81    queue.push_back(download);
 
   87    if (download->status == DownloadStatus::DOWNLOADING)
 
   88        transferFinish(download);
 
   89    else if (download->status == DownloadStatus::QUEUED && queue.size() > 0)
 
   90        queue.remove(download);
 
   94void DownloadQueue::setPlatformCurlFlags(CURL* c)
 
   97    curl_easy_setopt(c, CURLOPT_CAINFO, RAMFS 
"res/cacert.pem");
 
   99    curl_easy_setopt(c, CURLOPT_SOCKOPTFUNCTION, sockopt_callback_chesto);
 
  107    download->eh = curl_easy_init();
 
  109    setPlatformCurlFlags(download->eh);
 
  111    curl_easy_setopt(download->eh, CURLOPT_URL, download->url.c_str());
 
  112    curl_easy_setopt(download->eh, CURLOPT_WRITEFUNCTION, WriteCallback);
 
  113    curl_easy_setopt(download->eh, CURLOPT_WRITEDATA, download);
 
  114    curl_easy_setopt(download->eh, CURLOPT_PRIVATE, download);
 
  116    curl_easy_setopt(download->eh, CURLOPT_FOLLOWLOCATION, 1L);
 
  118    curl_multi_add_handle(cm, download->eh);
 
  128        curl_multi_remove_handle(cm, download->eh);
 
  130    curl_easy_cleanup(download->eh);
 
  136void DownloadQueue::startTransfersFromQueue()
 
  139    while ((transfers < MAX_PARALLEL_DOWNLOADS) && (queue.size() > 0))
 
  146        download->status = DownloadStatus::DOWNLOADING;
 
  147        transferStart(download);
 
  162    curl_multi_perform(cm, &still_alive);
 
  165    while(msg = curl_multi_info_read(cm, &msgs_left))
 
  167        long response_code = 404;
 
  169        if (msg->msg != CURLMSG_DONE)
 
  172        curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &download);
 
  173        curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &response_code);
 
  175        transferFinish(download);
 
  176        startTransfersFromQueue();
 
  178        if (response_code == 200)
 
  179            download->status = DownloadStatus::COMPLETE;
 
  181            download->status = DownloadStatus::FAILED;
 
  183        download->cb(download);
 
  186    startTransfersFromQueue();
 
  188    return ((still_alive) || (msgs_left > 0) || (queue.size() > 0));
 
int process()
process finished and queued downloads
 
void downloadAdd(DownloadOperation *download)
add a new download operation
 
void downloadCancel(DownloadOperation *download)
cancel a download operation