Exemplo n.º 1
0
int main()
{
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  attr.attributes = EMSCRIPTEN_FETCH_REPLACE | EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_WAITABLE;
  emscripten_fetch_t *fetch = emscripten_fetch(&attr, "gears.png");
  assert(fetch != 0);
  memset(&attr, 0, sizeof(attr)); // emscripten_fetch() must be able to operate without referencing to this structure after the call.
  printf("Main thread waiting for fetch to finish...\n");
  emscripten_fetch_wait(fetch, INFINITY);
  printf("Main thread waiting for fetch to finish done...\n");
  assert(fetch->data != 0);
  assert(fetch->numBytes > 0);
  assert(fetch->totalBytes == fetch->numBytes);
  assert(fetch->readyState == 4/*DONE*/);
  assert(fetch->status == 200);

  uint8_t checksum = 0;
  for(int i = 0; i < fetch->numBytes; ++i)
    checksum ^= fetch->data[i];
  printf("Data checksum: %02X\n", checksum);
  assert(checksum == 0x08);
  emscripten_fetch_close(fetch);

#ifdef REPORT_RESULT
  REPORT_RESULT(0);
#endif
}
emscripten_fetch_t *emscripten_fetch(emscripten_fetch_attr_t *fetch_attr, const char *url)
{
	if (!fetch_attr) return 0;
	if (!url) return 0;

	const bool waitable = (fetch_attr->attributes & EMSCRIPTEN_FETCH_WAITABLE) != 0;
	const bool synchronous = (fetch_attr->attributes & EMSCRIPTEN_FETCH_SYNCHRONOUS) != 0;
	const bool readFromIndexedDB = (fetch_attr->attributes & (EMSCRIPTEN_FETCH_APPEND | EMSCRIPTEN_FETCH_NO_DOWNLOAD)) != 0;
	const bool writeToIndexedDB = (fetch_attr->attributes & EMSCRIPTEN_FETCH_PERSIST_FILE) != 0 || !strncmp(fetch_attr->requestMethod, "EM_IDB_", strlen("EM_IDB_"));
	const bool performXhr = (fetch_attr->attributes & EMSCRIPTEN_FETCH_NO_DOWNLOAD) == 0;
	const bool isMainBrowserThread = emscripten_is_main_browser_thread() != 0;
	if (isMainBrowserThread && synchronous && (performXhr || readFromIndexedDB || writeToIndexedDB))
	{
		EM_ASM_INT( { Module['printErr']('emscripten_fetch("' + Pointer_stringify($0) + '") failed! Synchronous blocking XHRs and IndexedDB operations are not supported on the main browser thread. Try dropping the EMSCRIPTEN_FETCH_SYNCHRONOUS flag, or run with the linker flag --proxy-to-worker to decouple main C runtime thread from the main browser thread.') }, 
			url);
		return 0;
	}

	emscripten_fetch_t *fetch = (emscripten_fetch_t *)malloc(sizeof(emscripten_fetch_t));
	memset(fetch, 0, sizeof(emscripten_fetch_t));
	fetch->id = globalFetchIdCounter++; // TODO: make this thread-safe!
	fetch->userData = fetch_attr->userData;
	fetch->url = strdup(url); // TODO: free
	fetch->__attributes = *fetch_attr;
	fetch->__attributes.destinationPath = fetch->__attributes.destinationPath ? strdup(fetch->__attributes.destinationPath) : 0; // TODO: free
	fetch->__attributes.userName = fetch->__attributes.userName ? strdup(fetch->__attributes.userName) : 0; // TODO: free
	fetch->__attributes.password = fetch->__attributes.password ? strdup(fetch->__attributes.password) : 0; // TODO: free
	fetch->__attributes.requestHeaders = 0;// TODO:strdup(fetch->__attributes.requestHeaders);
	fetch->__attributes.overriddenMimeType = fetch->__attributes.overriddenMimeType ? strdup(fetch->__attributes.overriddenMimeType) : 0; // TODO: free

#if __EMSCRIPTEN_PTHREADS__
	// Depending on the type of fetch, we can either perform it in the same Worker/thread than the caller, or we might need
	// to run it in a separate Worker. There is a dedicated fetch worker that is available for the fetch, but in some scenarios
	// it might be desirable to run in the same Worker as the caller, so deduce here whether to run the fetch in this thread,
	// or if we need to use the fetch-worker instead.
	if (waitable // Waitable fetches can be synchronously waited on, so must always be proxied
		|| (synchronous && (readFromIndexedDB || writeToIndexedDB))) // Synchronous IndexedDB access needs proxying
	{
		emscripten_atomic_store_u32(&fetch->__proxyState, 1); // sent to proxy worker.
		emscripten_proxy_fetch(fetch);

		if (synchronous) emscripten_fetch_wait(fetch, INFINITY);
	}
	else
#endif
		emscripten_start_fetch(fetch);
	return fetch;
}