Compare commits

...

5 Commits

Author SHA1 Message Date
Archilocos 0ec3cd562e
Merge f361527459 into 03ce864e70 2024-02-01 03:45:55 +00:00
Fufu Fang 03ce864e70
updated README 2024-02-01 03:18:58 +00:00
Fufu Fang 6775564354
added badges in README 2024-02-01 03:00:42 +00:00
Fufu Fang 707d9b9253
Configure online code scanning tools
- Added .deepsource.toml for Deep Source
- Added configuration for GitHub CodeQL
2024-02-01 02:53:26 +00:00
liuchenghao f361527459 fix: When the network is abnormal during the file download, start to resume the transfer 2021-09-22 09:59:57 +08:00
7 changed files with 181 additions and 21 deletions

4
.deepsource.toml Normal file
View File

@ -0,0 +1,4 @@
version = 1
[[analyzers]]
name = "cxx"

89
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,89 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '18 19 * * 1'
jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: 'ubuntu-latest'
timeout-minutes: 360
permissions:
# required for all workflows
security-events: write
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
language: [ 'c-cpp' ]
# CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
# Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install libgumbo-dev libfuse-dev libssl-dev libcurl4-openssl-dev uuid-dev help2man
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@ -1,3 +1,7 @@
[![CodeQL](https://github.com/fangfufu/httpdirfs/actions/workflows/codeql.yml/badge.svg)](https://github.com/fangfufu/httpdirfs/actions/workflows/codeql.yml)
[![CodeFactor](https://www.codefactor.io/repository/github/fangfufu/httpdirfs/badge)](https://www.codefactor.io/repository/github/fangfufu/httpdirfs)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/30af0a5b4d6f4a4d83ddb68f5193ad23)](https://app.codacy.com/gh/fangfufu/httpdirfs/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
# HTTPDirFS - HTTP Directory Filesystem with a permanent cache, and Airsonic / Subsonic server support! # HTTPDirFS - HTTP Directory Filesystem with a permanent cache, and Airsonic / Subsonic server support!
Have you ever wanted to mount those HTTP directory listings as if it was a Have you ever wanted to mount those HTTP directory listings as if it was a
@ -22,9 +26,9 @@ present a HTTP directory listing.
## Installation ## Installation
Please note if you install HTTDirFS from a repository, it can be outdated. Please note if you install HTTDirFS from a repository, it can be outdated.
### Debian 11 "Bullseye" ### Debian 12 "Bookworm"
HTTPDirFS is available as a package in Debian 11 "Bullseye", If you are on HTTPDirFS is available as a package in Debian 12 "Bookworm", If you are on
Debian Bullseye, you can simply run the following Debian Bookworm, you can simply run the following
command as ``root``: command as ``root``:
apt install httpdirfs apt install httpdirfs
@ -42,14 +46,14 @@ HTTPDirFS is available in the
## Compilation ## Compilation
### Ubuntu ### Ubuntu
Under Ubuntu 18.04.4 LTS, you need the following packages: Under Ubuntu 22.04 LTS, you need the following packages:
libgumbo-dev libfuse-dev libssl-dev libcurl4-openssl-dev uuid-dev libgumbo-dev libfuse-dev libssl-dev libcurl4-openssl-dev uuid-dev help2man
### Debian 11 "Bullseye" and Debian 10 "Buster" ### Debian 12 "Bookworm"
Under Debian 10 "Buster" and newer versions, you need the following packages: Under Debian 12 "Bookworm" and newer versions, you need the following packages:
libgumbo-dev libfuse-dev libssl-dev libcurl4-openssl-dev uuid-dev libgumbo-dev libfuse-dev libssl-dev libcurl4-openssl-dev uuid-dev help2man
### FreeBSD ### FreeBSD
The following dependencies are required from either pkg or ports: The following dependencies are required from either pkg or ports:
@ -300,6 +304,8 @@ for the technical and moral support. Your wisdom is much appreciated!
compatibility patches. compatibility patches.
- I would like to thank [hiliev](https://github.com/hiliev) for providing macOS - I would like to thank [hiliev](https://github.com/hiliev) for providing macOS
compatibility patches. compatibility patches.
- I would like to thank [Jonathan Kamens](https://github.com/jikamens) for providing
a whole bunch of code improvements and the improved build system.
- I would like to thank [-Archivist](https://www.reddit.com/user/-Archivist/) - I would like to thank [-Archivist](https://www.reddit.com/user/-Archivist/)
for not providing FTP or WebDAV access to his server. This piece of software was for not providing FTP or WebDAV access to his server. This piece of software was
written in direct response to his appalling behaviour. written in direct response to his appalling behaviour.

View File

@ -5,7 +5,7 @@ AC_PROG_CC
AC_SEARCH_LIBS([backtrace],[execinfo]) AC_SEARCH_LIBS([backtrace],[execinfo])
# Because we use $(fuse_LIBS) in $(CFLAGS); see comment in Makefile.in # Because we use $(fuse_LIBS) in $(CFLAGS); see comment in Makefile.in
AX_CHECK_COMPILE_FLAG([-Wunused-command-line-argument],[NUCLA=-Wno-unused-command-line-argument],,[-Werror]) AX_CHECK_COMPILE_FLAG([-Wunused-command-line-argument],[NUCLA=-Wno-unused-command-line-argument],[-Werror])
AC_SUBST([NUCLA]) AC_SUBST([NUCLA])
AM_INIT_AUTOMAKE([foreign subdir-objects]) AM_INIT_AUTOMAKE([foreign subdir-objects])
PKG_CHECK_MODULES([pkgconf],[gumbo libcurl uuid expat openssl]) PKG_CHECK_MODULES([pkgconf],[gumbo libcurl uuid expat openssl])

View File

@ -237,11 +237,13 @@ static void LinkTable_uninitialised_fill(LinkTable *linktbl)
} }
/* /*
* Block until the gaps are filled * Block until the gaps are filled
* result is an invalid variable
*/ */
int n = curl_multi_perform_once(); int result = 0;
int n = curl_multi_perform_once(&result);
int i = 0; int i = 0;
int j = 0; int j = 0;
while ((i = curl_multi_perform_once())) { while ((i = curl_multi_perform_once(&result))) {
if (CONFIG.log_type & debug) { if (CONFIG.log_type & debug) {
if (j) { if (j) {
erase_string(stderr, STATUS_LEN, s); erase_string(stderr, STATUS_LEN, s);
@ -949,7 +951,7 @@ TransferStruct Link_download_full(Link *link)
*/ */
long http_resp = 0; long http_resp = 0;
do { do {
transfer_blocking(curl); transfer_blocking(curl, ts.curr_size);
ret = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp); ret = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp);
if (ret) { if (ret) {
lprintf(error, "%s", curl_easy_strerror(ret)); lprintf(error, "%s", curl_easy_strerror(ret));
@ -1075,7 +1077,7 @@ long Link_download(Link *link, char *output_buf, size_t req_size, off_t offset)
CURL *curl = Link_download_curl_setup(link, req_size, offset, &header, &ts); CURL *curl = Link_download_curl_setup(link, req_size, offset, &header, &ts);
transfer_blocking(curl); transfer_blocking(curl, offset);
curl_off_t recv = Link_download_cleanup(curl, &header); curl_off_t recv = Link_download_cleanup(curl, &header);

View File

@ -10,6 +10,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdbool.h>
/* /*
* ----------------- External variables ---------------------- * ----------------- External variables ----------------------
@ -110,9 +111,10 @@ curl_callback_unlock(CURL *handle, curl_lock_data data, void *userptr)
* \details Adapted from: * \details Adapted from:
* https://curl.haxx.se/libcurl/c/10-at-a-time.html * https://curl.haxx.se/libcurl/c/10-at-a-time.html
*/ */
static void static int
curl_process_msgs(CURLMsg *curl_msg, int n_running_curl, int n_mesgs) curl_process_msgs(CURLMsg *curl_msg, int n_running_curl, int n_mesgs)
{ {
int result = 0;
(void) n_running_curl; (void) n_running_curl;
(void) n_mesgs; (void) n_mesgs;
static volatile int slept = 0; static volatile int slept = 0;
@ -163,6 +165,7 @@ curl_process_msgs(CURLMsg *curl_msg, int n_running_curl, int n_mesgs)
lprintf(error, "%d - %s <%s>\n", lprintf(error, "%d - %s <%s>\n",
curl_msg->data.result, curl_msg->data.result,
curl_easy_strerror(curl_msg->data.result), url); curl_easy_strerror(curl_msg->data.result), url);
result = curl_msg->data.result;
} }
curl_multi_remove_handle(curl_multi, curl); curl_multi_remove_handle(curl_multi, curl);
/* /*
@ -175,13 +178,50 @@ curl_process_msgs(CURLMsg *curl_msg, int n_running_curl, int n_mesgs)
} else { } else {
lprintf(warning, "curl_msg->msg: %d\n", curl_msg->msg); lprintf(warning, "curl_msg->msg: %d\n", curl_msg->msg);
} }
return result;
} }
static int http_error_result(int http_response)
{
switch(http_response)
{
case 0: //eg connection down from kick-off ~suggest retrying till some max limit
case 200: //yay we at least got to our url
case 206: //Partial Content
break;
case 416:
//cannot d/l range ~ either cos no server support
//or cos we're asking for an invalid range ~ie: we already d/ld the file
printf("HTTP416: either the d/l is already complete or the http server cannot d/l a range\n");
default:
return 0;//suggest quitting on an unhandled error
}
return 1;
}
static int curl_error_result(int curl_result)
{
switch (curl_result)
{
case CURLE_OK:
case CURLE_COULDNT_CONNECT: //no network connectivity ?
case CURLE_OPERATION_TIMEDOUT: //cos of CURLOPT_LOW_SPEED_TIME
case CURLE_COULDNT_RESOLVE_HOST: //host/DNS down ?
break; //we'll keep trying
default://see: http://curl.haxx.se/libcurl/c/libcurl-errors.html
return 0;
}
return 1;
}
/** /**
* \details effectively based on * \details effectively based on
* https://curl.haxx.se/libcurl/c/multi-double.html * https://curl.haxx.se/libcurl/c/multi-double.html
*/ */
int curl_multi_perform_once(void) int curl_multi_perform_once(int *result)
{ {
lprintf(network_lock_debug, lprintf(network_lock_debug,
"thread %x: locking transfer_lock;\n", pthread_self()); "thread %x: locking transfer_lock;\n", pthread_self());
@ -207,7 +247,12 @@ int curl_multi_perform_once(void)
int n_mesgs; int n_mesgs;
CURLMsg *curl_msg; CURLMsg *curl_msg;
while ((curl_msg = curl_multi_info_read(curl_multi, &n_mesgs))) { while ((curl_msg = curl_multi_info_read(curl_multi, &n_mesgs))) {
curl_process_msgs(curl_msg, n_running_curl, n_mesgs); int nResult = curl_process_msgs(curl_msg, n_running_curl, n_mesgs);
if (!http_error_result(n_mesgs) || !curl_error_result(nResult)) {
*result = 1;
}else{
*result = 0;
}
} }
lprintf(network_lock_debug, lprintf(network_lock_debug,
@ -272,7 +317,7 @@ void NetworkSystem_init(void)
crypto_lock_init(); crypto_lock_init();
} }
void transfer_blocking(CURL *curl) void transfer_blocking(CURL *curl, size_t start)
{ {
TransferStruct *ts; TransferStruct *ts;
CURLcode ret = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &ts); CURLcode ret = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &ts);
@ -293,8 +338,22 @@ void transfer_blocking(CURL *curl)
"thread %x: unlocking transfer_lock;\n", pthread_self()); "thread %x: unlocking transfer_lock;\n", pthread_self());
PTHREAD_MUTEX_UNLOCK(&transfer_lock); PTHREAD_MUTEX_UNLOCK(&transfer_lock);
while (ts->transferring) { int result = 0;
curl_multi_perform_once(); bool restartDown = false;
while (ts->transferring && !restartDown) {
/*
* When the network is abnormal during the file download, start to resume the transfer
*/
if (0 != result) {
curl_multi_remove_handle(curl_multi,curl);
curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, start);
res = curl_multi_add_handle(curl_multi, curl);
if (res > 0) {
lprintf(error, "%d, %s\n", res, curl_multi_strerror(res));
}
}
curl_multi_perform_once(&result);
} }
} }

View File

@ -26,13 +26,13 @@ typedef enum {
extern CURLSH *CURL_SHARE; extern CURLSH *CURL_SHARE;
/** \brief perform one transfer cycle */ /** \brief perform one transfer cycle */
int curl_multi_perform_once(void); int curl_multi_perform_once(int *result);
/** \brief initialise the network module */ /** \brief initialise the network module */
void NetworkSystem_init(void); void NetworkSystem_init(void);
/** \brief blocking file transfer */ /** \brief blocking file transfer */
void transfer_blocking(CURL *curl); void transfer_blocking(CURL *curl, size_t start);
/** \brief non blocking file transfer */ /** \brief non blocking file transfer */
void transfer_nonblocking(CURL *curl); void transfer_nonblocking(CURL *curl);