prog_stream.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // Copyright (C) 2004-2021 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include <errno.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <assert.h>
  27. #include "curl_stream.h"
  28. #ifdef _WIN32
  29. #include <windows.h>
  30. #else
  31. #include <sys/time.h>
  32. #include <unistd.h>
  33. #include <pthread.h>
  34. #endif
  35. /* File stream - progressive reading to simulate http download */
  36. typedef struct prog_state
  37. {
  38. FILE *file;
  39. int64_t length;
  40. int64_t available; /* guarded by lock below */
  41. int kbps;
  42. int64_t start_time; /* in milliseconds since epoch */
  43. unsigned char buffer[4096];
  44. void (*on_data)(void*,int);
  45. void *on_data_arg;
  46. /* We assume either Windows threads or pthreads here. */
  47. #ifdef _WIN32
  48. void *thread;
  49. DWORD thread_id;
  50. HANDLE mutex;
  51. #else
  52. pthread_t thread;
  53. pthread_mutex_t mutex;
  54. #endif
  55. } prog_state;
  56. static int64_t get_current_time(void)
  57. {
  58. #ifdef _WIN32
  59. return (int)GetTickCount();
  60. #else
  61. struct timeval now;
  62. gettimeofday(&now, NULL);
  63. return (int64_t)now.tv_sec*1000 + now.tv_usec/1000;
  64. #endif
  65. }
  66. #ifdef _WIN32
  67. static int locked;
  68. static void
  69. lock(prog_state *state)
  70. {
  71. WaitForSingleObject(state->mutex, INFINITE);
  72. assert(locked == 0);
  73. locked = 1;
  74. }
  75. static void
  76. unlock(prog_state *state)
  77. {
  78. assert(locked == 1);
  79. locked = 0;
  80. ReleaseMutex(state->mutex);
  81. }
  82. #else
  83. static void
  84. lock(prog_state *state)
  85. {
  86. pthread_mutex_lock(&state->mutex);
  87. }
  88. static void
  89. unlock(prog_state *state)
  90. {
  91. pthread_mutex_unlock(&state->mutex);
  92. }
  93. #endif
  94. static int next_prog(fz_context *ctx, fz_stream *stm, size_t len)
  95. {
  96. prog_state *ps = (prog_state *)stm->state;
  97. size_t n;
  98. if (len > sizeof(ps->buffer))
  99. len = sizeof(ps->buffer);
  100. /* Simulate not all data available yet. */
  101. lock(ps);
  102. if (ps->available < ps->length)
  103. {
  104. if (stm->pos > ps->available || ps->available - stm->pos <= 0)
  105. {
  106. unlock(ps);
  107. fz_throw(ctx, FZ_ERROR_TRYLATER, "Not enough data yet");
  108. }
  109. len = fz_mini(len, ps->available - stm->pos);
  110. }
  111. unlock(ps);
  112. n = fread(ps->buffer, 1, len, ps->file);
  113. stm->rp = ps->buffer;
  114. stm->wp = ps->buffer + n;
  115. stm->pos += (int64_t)n;
  116. if (n < len)
  117. {
  118. if (ferror(ps->file))
  119. fz_throw(ctx, FZ_ERROR_GENERIC, "prog read error: %s", strerror(errno));
  120. if (n == 0)
  121. return EOF;
  122. }
  123. return *stm->rp++;
  124. }
  125. static void seek_prog(fz_context *ctx, fz_stream *stm, int64_t offset, int whence)
  126. {
  127. prog_state *ps = (prog_state *)stm->state;
  128. if (whence == SEEK_END)
  129. {
  130. whence = SEEK_SET;
  131. offset += ps->length;
  132. }
  133. else if (whence == SEEK_CUR)
  134. {
  135. whence = SEEK_SET;
  136. offset += stm->pos;
  137. }
  138. if (fseek(ps->file, offset, whence) != 0)
  139. fz_throw(ctx, FZ_ERROR_GENERIC, "cannot seek: %s", strerror(errno));
  140. stm->pos = offset;
  141. stm->wp = stm->rp;
  142. }
  143. static void close_prog(fz_context *ctx, void *state)
  144. {
  145. prog_state *ps = (prog_state *)state;
  146. int n = fclose(ps->file);
  147. if (n < 0)
  148. fz_warn(ctx, "cannot fclose: %s", strerror(errno));
  149. fz_free(ctx, state);
  150. }
  151. static void fetcher_thread(prog_state *ps)
  152. {
  153. int complete = 0;
  154. ps->start_time = get_current_time();
  155. while (!complete)
  156. {
  157. /* Wait a while. */
  158. #ifdef _WIN32
  159. Sleep(200);
  160. #else
  161. usleep(200000);
  162. #endif
  163. lock(ps);
  164. /* Simulate more data having arrived. */
  165. if (ps->available < ps->length)
  166. {
  167. int64_t av = (get_current_time() - ps->start_time) * ps->kbps;
  168. if (av > ps->length)
  169. av = ps->length;
  170. ps->available = av;
  171. }
  172. else
  173. {
  174. complete = 1;
  175. }
  176. unlock(ps);
  177. /* Ping callback with new data. */
  178. if (ps->on_data)
  179. ps->on_data(ps->on_data_arg, complete);
  180. }
  181. }
  182. #ifdef _WIN32
  183. static DWORD WINAPI win_thread(void *lparam)
  184. {
  185. fetcher_thread((prog_state *)lparam);
  186. return 0;
  187. }
  188. #else
  189. static void *pthread_thread(void *arg)
  190. {
  191. fetcher_thread((prog_state *)arg);
  192. return NULL;
  193. }
  194. #endif
  195. static fz_stream *
  196. fz_open_file_ptr_progressive(fz_context *ctx, FILE *file, int kbps, void (*on_data)(void*,int), void *opaque)
  197. {
  198. fz_stream *stm;
  199. prog_state *state;
  200. state = fz_malloc_struct(ctx, prog_state);
  201. state->file = file;
  202. state->kbps = kbps;
  203. state->available = 0;
  204. state->on_data = on_data;
  205. state->on_data_arg = opaque;
  206. fseek(state->file, 0, SEEK_END);
  207. state->length = ftell(state->file);
  208. fseek(state->file, 0, SEEK_SET);
  209. #ifdef _WIN32
  210. state->mutex = CreateMutex(NULL, FALSE, NULL);
  211. if (state->mutex == NULL)
  212. fz_throw(ctx, FZ_ERROR_GENERIC, "mutex creation failed");
  213. state->thread = CreateThread(NULL, 0, win_thread, state, 0, &state->thread_id);
  214. if (state->thread == NULL)
  215. fz_throw(ctx, FZ_ERROR_GENERIC, "thread creation failed");
  216. #else
  217. if (pthread_mutex_init(&state->mutex, NULL))
  218. fz_throw(ctx, FZ_ERROR_GENERIC, "mutex creation failed");
  219. if (pthread_create(&state->thread, NULL, pthread_thread, state))
  220. fz_throw(ctx, FZ_ERROR_GENERIC, "thread creation failed");
  221. #endif
  222. stm = fz_new_stream(ctx, state, next_prog, close_prog);
  223. stm->progressive = 1;
  224. stm->seek = seek_prog;
  225. return stm;
  226. }
  227. fz_stream *
  228. fz_open_file_progressive(fz_context *ctx, const char *name, int kbps, void (*on_data)(void*,int), void *opaque)
  229. {
  230. FILE *f;
  231. #ifdef _WIN32
  232. f = fz_fopen_utf8(name, "rb");
  233. #else
  234. f = fopen(name, "rb");
  235. #endif
  236. if (f == NULL)
  237. fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open %s", name);
  238. return fz_open_file_ptr_progressive(ctx, f, kbps, on_data, opaque);
  239. }