http_avi_reader.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "main.h"
  2. #include "http_avi_reader.h"
  3. #include "../nu/AutoChar.h"
  4. #include "api__in_avi.h"
  5. #include <api/service/waservicefactory.h>
  6. #include "../nu/ns_wc.h"
  7. #include <strsafe.h>
  8. static const int http_buffer_size=128*1024;
  9. // {C0A565DC-0CFE-405a-A27C-468B0C8A3A5C}
  10. static const GUID internetConfigGroupGUID =
  11. {
  12. 0xc0a565dc, 0xcfe, 0x405a, { 0xa2, 0x7c, 0x46, 0x8b, 0xc, 0x8a, 0x3a, 0x5c }
  13. };
  14. AVIReaderHTTP::AVIReaderHTTP(HANDLE killswitch, HANDLE seek_event)
  15. {
  16. seekable = 0;
  17. http = 0;
  18. position = 0;
  19. handles[0]=killswitch;
  20. handles[1]=seek_event;
  21. }
  22. static void SetUserAgent(api_httpreceiver *http)
  23. {
  24. char agent[256] = {0};
  25. StringCchPrintfA(agent, 256, "User-Agent: %S/%S", WASABI_API_APP->main_getAppName(), WASABI_API_APP->main_getVersionNumString());
  26. http->addheader(agent);
  27. }
  28. void AVIReaderHTTP::GetFilename(wchar_t *fn, size_t len)
  29. {
  30. const char *url = http->get_url();
  31. MultiByteToWideCharSZ(CP_ACP, 0, url, -1, fn, (int)len);
  32. }
  33. int AVIReaderHTTP::Open(const wchar_t *url)
  34. {
  35. int use_proxy = 1;
  36. const wchar_t *proxy = AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0);
  37. bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
  38. if (proxy80 && wcsstr(url, L":") && (!wcsstr(url, L":80/") && wcsstr(url, L":80") != (url + wcslen(url) - 3)))
  39. use_proxy = 0;
  40. waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
  41. if (sf) http = (api_httpreceiver *)sf->getInterface();
  42. http->open(API_DNS_AUTODNS, http_buffer_size, (use_proxy && proxy && proxy[0]) ? (char *)AutoChar(proxy) : NULL);
  43. http->addheader("Accept:*/*");
  44. SetUserAgent(http);
  45. http->connect(AutoChar(url, CP_UTF8), 0);
  46. return nsavi::READ_OK;
  47. }
  48. int AVIReaderHTTP::Open(const char *url, uint64_t start_offset)
  49. {
  50. int use_proxy = 1;
  51. const wchar_t *proxy = AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0);
  52. bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
  53. if (proxy80 && strstr(url, ":") && (!strstr(url, ":80/") && strstr(url, ":80") != (url + strlen(url) - 3)))
  54. use_proxy = 0;
  55. waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
  56. if (sf) http = (api_httpreceiver *)sf->getInterface();
  57. http->open(API_DNS_AUTODNS, http_buffer_size, (use_proxy && proxy && proxy[0]) ? (char *)AutoChar(proxy) : NULL);
  58. http->addheader("Accept:*/*");
  59. SetUserAgent(http);
  60. if (start_offset)
  61. {
  62. char temp[128] = {0};
  63. StringCchPrintfA(temp, 128, "Range: bytes=%I64u-", start_offset);
  64. http->addheader(temp);
  65. position = start_offset;
  66. }
  67. http->connect(url, !!start_offset);
  68. return nsavi::READ_OK;
  69. }
  70. void AVIReaderHTTP::Close()
  71. {
  72. if (http)
  73. {
  74. waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
  75. if (sf) sf->releaseInterface(http);
  76. }
  77. http = 0;
  78. }
  79. int AVIReaderHTTP::Connect()
  80. {
  81. http->run();
  82. int status = http->get_status();
  83. while (status == HTTPRECEIVER_STATUS_CONNECTING || status == HTTPRECEIVER_STATUS_READING_HEADERS)
  84. {
  85. int ret = WaitForMultipleObjects(2, handles, FALSE, 50);
  86. if (ret == WAIT_OBJECT_0+1)
  87. return -2;
  88. else if (ret != WAIT_TIMEOUT)
  89. return -1;
  90. http->run();
  91. status = http->get_status();
  92. }
  93. if (status == HTTPRECEIVER_STATUS_ERROR)
  94. {
  95. return nsavi::READ_FAILED;
  96. }
  97. const char *headers = http->getallheaders();
  98. const char *ranges = http->getheader("accept-ranges");
  99. seekable = (ranges && _stricmp(ranges, "bytes"));
  100. return nsavi::READ_OK;
  101. }
  102. int AVIReaderHTTP::Buffer()
  103. {
  104. while (http->bytes_available() < http_buffer_size && http->run() == HTTPRECEIVER_RUN_OK)
  105. {
  106. int ret = WaitForMultipleObjects(2, handles, FALSE, 50);
  107. if (ret == WAIT_OBJECT_0+1)
  108. return -2;
  109. else if (ret != WAIT_TIMEOUT)
  110. return -1;
  111. }
  112. return nsavi::READ_OK;
  113. }
  114. uint64_t AVIReaderHTTP::GetContentLength()
  115. {
  116. const char *content_length = http->getheader("content-length");
  117. if (content_length)
  118. return _atoi64(content_length);
  119. else
  120. return 0;
  121. }
  122. int AVIReaderHTTP::Read(void *buffer, uint32_t read_length, uint32_t *bytes_read)
  123. {
  124. uint32_t total_bytes_read=0;
  125. for(;;)
  126. {
  127. int ret = http->run();
  128. int http_bytes_read = http->get_bytes(buffer, read_length);
  129. read_length -= http_bytes_read;
  130. buffer = (uint8_t *)buffer + http_bytes_read;
  131. total_bytes_read+=http_bytes_read;
  132. position += http_bytes_read;
  133. if (!read_length)
  134. {
  135. *bytes_read = total_bytes_read;
  136. return nsavi::READ_OK;
  137. }
  138. if (http->bytes_available() == 0)
  139. {
  140. if (ret == HTTPRECEIVER_RUN_CONNECTION_CLOSED)
  141. {
  142. if (position == http->content_length())
  143. return nsavi::READ_EOF;
  144. else
  145. return nsavi::READ_DISCONNECT;
  146. }
  147. else if (ret == HTTPRECEIVER_RUN_ERROR)
  148. {
  149. return nsavi::READ_DISCONNECT;
  150. }
  151. }
  152. ret = WaitForMultipleObjects(2, handles, FALSE, 50);
  153. if (ret == WAIT_OBJECT_0+1)
  154. return -2;
  155. else if (ret != WAIT_TIMEOUT)
  156. return -1;
  157. }
  158. return nsavi::READ_OK;
  159. }
  160. int AVIReaderHTTP::Peek(void *buffer, uint32_t read_length, uint32_t *bytes_read)
  161. {
  162. uint32_t total_bytes_read=0;
  163. while (http->bytes_available() < (int)read_length && http->run() == HTTPRECEIVER_RUN_OK)
  164. {
  165. int ret = WaitForMultipleObjects(2, handles, FALSE, 50);
  166. if (ret == WAIT_OBJECT_0+1)
  167. return -2;
  168. else if (ret != WAIT_TIMEOUT)
  169. return -1;
  170. }
  171. *bytes_read = http->peek_bytes(buffer, read_length);
  172. return nsavi::READ_OK;
  173. }
  174. int AVIReaderHTTP::Seek(uint64_t seek_position)
  175. {
  176. // if position is forward of our current position, see if we have enough in the buffer to just advance the buffer
  177. if (seek_position > position
  178. && seek_position - position <= http->bytes_available())
  179. {
  180. int bytes_read = http->get_bytes(0, (int)(seek_position - position));
  181. position += bytes_read;
  182. return nsavi::READ_OK;
  183. }
  184. else
  185. {
  186. // otherwise, close connection and re-open with a start position
  187. char *url = _strdup(http->get_url());
  188. Close();
  189. Open(url, seek_position);
  190. free(url);
  191. return Connect();
  192. }
  193. }
  194. uint64_t AVIReaderHTTP::Tell()
  195. {
  196. return position;
  197. }
  198. int AVIReaderHTTP::Skip(uint32_t skip_bytes)
  199. {
  200. // see if we have enough room in our buffer
  201. if (http->bytes_available() >= (int)skip_bytes)
  202. {
  203. int bytes_read = http->get_bytes(0, skip_bytes);
  204. position += bytes_read;
  205. return nsavi::READ_OK;
  206. }
  207. else
  208. {
  209. // close connection and re-open with a start position
  210. char *url = _strdup(http->get_url());
  211. Close();
  212. Open(url, position+skip_bytes);
  213. free(url);
  214. return Connect();
  215. }
  216. }