DTerr FileHandleCompressedFD::open_file (const FilePath &pathname, DTsize start, DTsize length, DTsize uncompressed_length) { DTint fd; fd = ::open(pathname.full_path().c_str(), O_RDONLY); if (fd < 0) { return DT3_ERR_FILE_OPEN_FAILED; } _eof = false; _file_g = 0; set_fd(fd,start,length,uncompressed_length); return DT3_ERR_NONE; }
void AssetDownloader::downloader_task ( const URL url, const FilePath save_path, DTfloat timeout) { std::shared_ptr<DeviceNetwork> network = System::network_manager(); // // Connecting Phase // // Update status update_status (STATUS_CONNECTING, 0,0); // Resolve the host NetworkSocket socket; NetworkAddress ip; DTerr err = network->resolve_host( ip, url.hostname(), url.port() ); if (err != DT3_ERR_NONE) { LOG_MESSAGE << "HTTPRequest: Unable to resolve host."; update_status (STATUS_ERROR, 0,0); return; } err = network->tcp_open(socket,ip); if (err != DT3_ERR_NONE) { LOG_MESSAGE << "HTTPRequest: Unable to resolve host."; update_status (STATUS_ERROR, 0,0); return; } // Send http request std::string server = url.hostname(); std::string path = url.path(); // Note: // HTTP/1.1 defines the "close" connection option for the sender to signal that the connection // will be closed after completion of the response. For example, // Connection: close // in either the request or the response header fields indicates that the connection SHOULD NOT // be considered `persistent' (section 8.1) after the current request/response is complete. // HTTP/1.1 applications that do not support persistent connections MUST include the "close" // connection option in every message. std::string request = "GET " + path + " HTTP/1.1\r\n" + "Host: " + server + "\r\n" + "User-Agent: DT3\r\n" + "Accept: */*\r\n" + "Cache-Control: max-age=0\r\n" + "Connection: close\r\n" + "\r\n"; LOG_MESSAGE << "Sending..."; LOG_MESSAGE << request; NetworkPacket packet_request; packet_request.set_data(request); err = network->tcp_send(packet_request, socket); if (err != DT3_ERR_NONE) { network->tcp_close(socket); LOG_MESSAGE << "HTTPRequest: Unable to send packet."; update_status (STATUS_ERROR, 0,0); return; } // // Downloading Phase // update_status (STATUS_DOWNLOADING, 0,0); // Hash the URL FilePath temp_file_path = FilePath(HAL::save_dir().full_path() + "/" + MoreStrings::cast_to_string(MoreStrings::hash(url.full_url()))); // Create a temporary file BinaryFileStream temp_file; err = FileManager::open(temp_file, temp_file_path, false); if (err != DT3_ERR_NONE) { network->tcp_close(socket); LOG_MESSAGE << "HTTPRequest: Unable to open file for writing."; update_status (STATUS_ERROR, 0,0); return; } LOG_MESSAGE << "HTTPRequest: Opened temp file at " << temp_file_path.full_path(); // Temporary storage for buffer std::string data; // Timer for timeout TimerHires timeout_timer; do { // Get the results NetworkPacket packet; packet.set_data_size(1024*16); err = network->tcp_recv(packet,socket); // If we recieved some data, append it to the buffer if (packet.data_size() > 0) { data += packet.data_as_string(); append_data(data, temp_file); timeout_timer.reset_abs_time(); } // Check complete if ( (_current_size == _total_size) && (_total_size > 0) ) { break; } // If we hit our timeout, then we abort if (timeout_timer.abs_time() > timeout) { network->tcp_close(socket); LOG_MESSAGE << "Http request timed out!"; update_status (STATUS_ERROR, 0,0); // Remove the temporary file temp_file_path.del(); return; } // Check for cancel if (_cancelled) { network->tcp_close(socket); LOG_MESSAGE << "Http request cancelled!"; update_status (STATUS_CANCELLED, 0,0); // Remove the temporary file temp_file_path.del(); return; } } while (err == DT3_ERR_NET_WOULD_BLOCK || err == DT3_ERR_NONE); // Close the connection, we're done network->tcp_close(socket); // Close off the stream finalize_data(data, temp_file); // // Finalizing phase // // Move the file save_path.del(); temp_file_path.move(save_path); LOG_MESSAGE << "Saving file to " << save_path.full_path(); // Final update of status update_status (STATUS_COMPLETE, _current_size, _total_size); }
static void fileOpenCB (const FilePath &path, std::shared_ptr<FileHandle> &file_handle, DTsize &start, DTsize &length, void *data) { // Check if it's an asset if (path.full_path().substr(0,6) != "Asset@") { file_handle = NULL; return; } // State struct android_app* state = (struct android_app*) data; // Get the asset manager AAssetManager* mgr = state->activity->assetManager; // Open Files if (path.in_package()) { // In package std::string full_path = path.package_path(); full_path = full_path.substr(6); // Strip off "Asset@" LOG_MESSAGE << "Opening Asset from Package: " << full_path; // Get the asset from the asset manager AAsset* asset = AAssetManager_open(mgr, full_path.c_str(), AASSET_MODE_UNKNOWN); // Get a file descriptor for the asset off_t outStart, outLength; int fd = AAsset_openFileDescriptor(asset, &outStart, &outLength); // Close the asset AAsset_close(asset); // Error check if (fd < 0) { file_handle = NULL; return; } // Find file in package FilePath packagename; DTsize file_start, file_length, file_uncompressed_length; FileManager::start_and_length(path, packagename, file_start, file_length, file_uncompressed_length); LOG_MESSAGE << " Asset: " << path.full_path(); LOG_MESSAGE << " Start: " << file_start; LOG_MESSAGE << " Length: " << file_length; LOG_MESSAGE << " Uncompressed Length: " << file_uncompressed_length; if (file_length == file_uncompressed_length) { auto fh = FileHandleUncompressedFD::create(); fh->set_fd(fd); file_handle = fh; start = file_start; length = file_length; } else { auto fh = FileHandleCompressedFD::create(); fh->set_fd(fd,file_start,file_length,file_uncompressed_length); file_handle = fh; start = 0; length = file_uncompressed_length; } } else { // Not in Package std::string full_path = path.full_path(); full_path = full_path.substr(6); // Strip off "Asset@" LOG_MESSAGE << "Opening Asset: " << full_path; // Get the asset from the asset manager AAsset* asset = AAssetManager_open(mgr, full_path.c_str(), AASSET_MODE_UNKNOWN); // Get a file descriptor for the asset off_t outStart, outLength; int fd = AAsset_openFileDescriptor(asset, &outStart, &outLength); // Close the asset AAsset_close(asset); // Error check if (fd < 0) { file_handle = NULL; return; } auto fh = FileHandleUncompressedFD::create(); fh->set_fd(fd); file_handle = fh; start = outStart; length = outLength; } }