wac_downloadManager.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #ifndef NULLSOFT_WAC_DOWNLOAD_MANAGER_DOWNLOAD_MANAGER_H
  2. #define NULLSOFT_WAC_DOWNLOAD_MANAGER_DOWNLOAD_MANAGER_H
  3. #include <vector>
  4. #include <map>
  5. #include <string> // for string class
  6. #include <atomic>
  7. #include <QtCore>
  8. #include <QAuthenticator>
  9. #include <QNetworkAccessManager>
  10. #include <QNetworkRequest>
  11. #include <QNetworkReply>
  12. #include <QUrl>
  13. #include <QUrlQuery>
  14. #include "../nu/GrowBuf.h"
  15. //#include "main.h"
  16. //#include "wac_downloadManager_Headers.h"
  17. #include "wac_download_http_receiver.h"
  18. //#include "wac_download_http_receiver_api.h"
  19. #include "wac_downloadManager_api.h"
  20. //#include "../wac_network/wac_network_http_receiver_api.h"
  21. #define MAX_SIMULTANEOUS_DOWNLOADS 2
  22. static std::map<std::string, std::string> _CONTENT_TYPES_EXTENSIONS = {
  23. { "audio/aac", "aac" },
  24. { "audio/mp4", "mp4" },
  25. { "audio/MPA", "MPA" },
  26. { "audio/mpeg", "mp3" },
  27. { "audio/opus", "opus" },
  28. { "audio/ogg", "ogg" },
  29. { "audio/vorbis", "vorbis" },
  30. { "audio/wav", "wav" },
  31. { "video/mp2t", "ts" },
  32. { "video/mp4", "mp4" },
  33. { "video/mpeg", "mpeg" },
  34. { "video/ogg", "ogv" },
  35. { "video/x-matroska", "mkv" },
  36. { "video/x-msvideo", "avi" }
  37. };
  38. namespace wa
  39. {
  40. namespace Components
  41. {
  42. class WAC_DownloadData : public QObject
  43. {
  44. Q_OBJECT
  45. public:
  46. WAC_DownloadData( api_wac_download_manager_http_receiver *p_http, const char *p_url, int p_flags, ifc_downloadManagerCallback *p_callback );
  47. ~WAC_DownloadData();
  48. void Retain();
  49. void Release();
  50. void Close( ifc_downloadManagerCallback **callbackCopy );
  51. bool getExtention();
  52. api_wac_download_manager_http_receiver *_http = Q_NULLPTR;
  53. ifc_downloadManagerCallback *_callback = Q_NULLPTR;
  54. int _flags = 0;
  55. HANDLE _hFile; // handle to the open file where data is written to
  56. DWORD _lastDownloadTick; // last time we got data out of the connection. used for timeout
  57. DWORD _connectionStart; // used for when the connection starts, to help us calculate a k/s download rate
  58. wchar_t _filepath[ MAX_PATH ]; // where file is downloaded to. probably a temp path
  59. char *_fileext = 0;
  60. char _url[ 1024 ];
  61. wchar_t _source[ 1024 ];
  62. wchar_t _title[ 1024 ];
  63. int _replyCode = 0; // HTTP 200, 404, etc.
  64. uint64_t _bytesDownloaded = 0;
  65. int _last_status; // from http->get_status()
  66. bool _pending;
  67. GrowBuf _buffer;
  68. private:
  69. std::atomic<std::size_t> _refCount = 1;
  70. };
  71. class WAC_DownloadManager : public QNetworkAccessManager, public api_downloadManager
  72. {
  73. Q_OBJECT
  74. public:
  75. WAC_DownloadManager( QObject *parent = Q_NULLPTR );
  76. ~WAC_DownloadManager();
  77. static const char *getServiceName() { return "Download Manager Service"; }
  78. static GUID getServiceGuid() { return DownloadManagerGUID; }
  79. DownloadToken Download( const char *p_url, ifc_downloadManagerCallback *p_callback );
  80. DownloadToken DownloadEx( const char *p_url, ifc_downloadManagerCallback *p_callback, int p_flags );
  81. private:
  82. void init();
  83. QNetworkReply *createRequest( Operation p_operation, const QNetworkRequest &p_request, QIODevice *p_outgoing_data = Q_NULLPTR );
  84. QMetaObject::Connection _connection_authentication_required;
  85. std::map<std::string, wa::Components::WAC_Download_HTTP_Receiver *> _runing_downloads;
  86. std::map<std::string, wa::Components::WAC_Download_HTTP_Receiver *> _pending_downloads;
  87. private Q_SLOTS:
  88. void on_s_authentication_required( QNetworkReply *p_reply, QAuthenticator *p_authenticator );
  89. };
  90. }
  91. }
  92. #pragma region "DownloadData"
  93. struct DownloadData
  94. {
  95. DownloadData( api_httpreceiver *http, const char *url, int flags, ifc_downloadManagerCallback *callback );
  96. ~DownloadData();
  97. void Retain();
  98. void Release();
  99. void Close( ifc_downloadManagerCallback **callbackCopy );
  100. bool getExtention();
  101. api_httpreceiver *http = NULL;
  102. ifc_downloadManagerCallback *callback = NULL;
  103. wchar_t filepath[ MAX_PATH ]; // where file is downloaded to. probably a temp path
  104. char *fileext = 0;
  105. char url[ 1024 ];
  106. wchar_t source[ 1024 ];
  107. wchar_t title[ 1024 ];
  108. HANDLE hFile; // handle to the open file where data is written to
  109. DWORD lastDownloadTick; // last time we got data out of the connection. used for timeout
  110. DWORD connectionStart; // used for when the connection starts, to help us calculate a k/s download rate
  111. int replyCode = 0; // HTTP 200, 404, etc.
  112. uint64_t bytesDownloaded = 0;
  113. int last_status; // from http->get_status()
  114. bool pending;
  115. int flags;
  116. GrowBuf buffer;
  117. private:
  118. std::atomic<std::size_t> _refCount = 1;
  119. };
  120. #pragma endregion
  121. /* method ideas
  122. Download(url, owner_token, callback, user_data)
  123. Lock() - call before enumerating and doing anything
  124. Unlock()
  125. CancelDownload()
  126. Enum(owner_token)
  127. */
  128. class DownloadManager : public api_downloadManager
  129. {
  130. public:
  131. static const char *getServiceName() { return "Download Manager"; }
  132. static GUID getServiceGuid() { return DownloadManagerGUID; }
  133. DownloadManager();
  134. void Kill();
  135. DownloadToken Download( const char *url, ifc_downloadManagerCallback *callback );
  136. DownloadToken DownloadEx( const char *url, ifc_downloadManagerCallback *callback, int flags );
  137. void ResumePendingDownload( DownloadToken token );
  138. void CancelDownload( DownloadToken token );
  139. void RetainDownload( DownloadToken token );
  140. void ReleaseDownload( DownloadToken token );
  141. void RegisterStatusCallback( ifc_downloadManagerCallback *callback );
  142. void UnregisterStatusCallback( ifc_downloadManagerCallback *callback );
  143. bool IsPending( DownloadToken token );
  144. /*
  145. only call these during a callback!
  146. */
  147. api_httpreceiver *GetReceiver( DownloadToken token )
  148. {
  149. if ( token )
  150. return ( (DownloadData *)token )->http;
  151. else
  152. return 0;
  153. }
  154. const wchar_t *GetLocation( DownloadToken token )
  155. {
  156. if ( token )
  157. return ( (DownloadData *)token )->filepath;
  158. else
  159. return 0;
  160. }
  161. const wchar_t *GetSource( DownloadToken p_token )
  162. {
  163. if ( !p_token )
  164. return 0;
  165. DownloadData *data = (DownloadData *)p_token;
  166. if ( data )
  167. return data->source;
  168. else
  169. return 0;
  170. }
  171. const wchar_t *GetTitle( DownloadToken p_token )
  172. {
  173. if ( !p_token )
  174. return 0;
  175. DownloadData *data = (DownloadData *)p_token;
  176. if ( data )
  177. return data->title;
  178. else
  179. return 0;
  180. }
  181. void SetLocation( DownloadToken token, const wchar_t *p_location )
  182. {
  183. if ( token )
  184. wcscpy( ( (DownloadData *)token )->filepath, p_location );
  185. }
  186. const char *GetExtention( DownloadToken token )
  187. {
  188. if ( token )
  189. return ( (DownloadData *)token )->fileext;
  190. else
  191. return 0;
  192. }
  193. const char *GetUrl( DownloadToken token )
  194. {
  195. if ( token )
  196. return ( (DownloadData *)token )->url;
  197. else
  198. return 0;
  199. }
  200. int GetBuffer( DownloadToken token, void **buffer, size_t *bufferlen )
  201. {
  202. if ( token )
  203. {
  204. *buffer = ( (DownloadData *)token )->buffer.get();
  205. *bufferlen = ( (DownloadData *)token )->buffer.getlen();
  206. return 0;
  207. }
  208. else
  209. return 1;
  210. }
  211. uint64_t GetBytesDownloaded( DownloadToken token )
  212. {
  213. if ( token )
  214. return ( (DownloadData *)token )->bytesDownloaded;
  215. else
  216. return 0;
  217. }
  218. private:
  219. CRITICAL_SECTION downloadsCS;
  220. bool DownloadThreadTick();
  221. static int DownloadTickThreadPoolFunc( HANDLE handle, void *user_data, intptr_t id );
  222. bool InitDownloadThread();
  223. void FinishDownload( DownloadData *data, int code );
  224. int Tick( DownloadData *thisDownload, void *buffer, int bufferSize );
  225. HANDLE download_thread;
  226. HANDLE killswitch;
  227. std::vector<DownloadData *> downloads;
  228. typedef std::vector<ifc_downloadManagerCallback *> StatusList;
  229. StatusList status_callbacks;
  230. protected:
  231. RECVS_DISPATCH;
  232. };
  233. #endif // !NULLSOFT_WAC_DOWNLOAD_MANAGER_DOWNLOAD_MANAGER_H