Compare commits
4 Commits
4df3742b37
...
6d179c3a25
Author | SHA1 | Date |
---|---|---|
Archilocos | 6d179c3a25 | |
Fufu Fang | 595c6d275e | |
chrysn | bd33966337 | |
liuchenghao | f361527459 |
53
src/link.c
53
src/link.c
|
@ -237,11 +237,13 @@ static void LinkTable_uninitialised_fill(LinkTable *linktbl)
|
|||
}
|
||||
/*
|
||||
* 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 j = 0;
|
||||
while ((i = curl_multi_perform_once())) {
|
||||
while ((i = curl_multi_perform_once(&result))) {
|
||||
if (CONFIG.log_type & debug) {
|
||||
if (j) {
|
||||
erase_string(stderr, STATUS_LEN, s);
|
||||
|
@ -406,20 +408,6 @@ static void HTML_to_LinkTable(const char *url, GumboNode *node,
|
|||
* This is to prevent duplicated link, if an Apache server has the
|
||||
* IconsAreLinks option.
|
||||
*/
|
||||
/* The following four lines of code have no effect so I've commented
|
||||
them out. I'm not removing them entirely because it's possible the
|
||||
original intent was to do a check of some sort here and it's an
|
||||
error that this check wasn't fully implemented, in which case this
|
||||
commented out code and the comment above it should serve as a
|
||||
reminder to whoever originally wrote it that there's something
|
||||
unfinished here that needs to be finished.
|
||||
*/
|
||||
/*
|
||||
size_t comp_len = strnlen(link_url, MAX_FILENAME_LEN);
|
||||
if (type == LINK_DIR) {
|
||||
comp_len--;
|
||||
}
|
||||
*/
|
||||
if (((type == LINK_DIR) || (type == LINK_UNINITIALISED_FILE)) &&
|
||||
!linknames_equal(linktbl->links[linktbl->num - 1]->linkname,
|
||||
link_url)) {
|
||||
|
@ -958,7 +946,7 @@ TransferStruct Link_download_full(Link *link)
|
|||
*/
|
||||
long http_resp = 0;
|
||||
do {
|
||||
transfer_blocking(curl);
|
||||
transfer_blocking(curl, ts.curr_size);
|
||||
ret = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp);
|
||||
if (ret) {
|
||||
lprintf(error, "%s", curl_easy_strerror(ret));
|
||||
|
@ -1077,7 +1065,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);
|
||||
|
||||
transfer_blocking(curl);
|
||||
transfer_blocking(curl, offset);
|
||||
|
||||
curl_off_t recv = Link_download_cleanup(curl, &header);
|
||||
|
||||
|
@ -1113,12 +1101,33 @@ long path_download(const char *path, char *output_buf, size_t req_size,
|
|||
static void make_link_relative(const char *page_url, char *link_url)
|
||||
{
|
||||
/*
|
||||
Some servers make the links to subdirectories absolute, but our code
|
||||
expects them to be relative, so change the contents of link_url as
|
||||
needed to accommodate that.
|
||||
Some servers make the links to subdirectories absolute (in URI terms:
|
||||
path-absolute), but our code expects them to be relative (in URI terms:
|
||||
path-noscheme), so change the contents of link_url as needed to
|
||||
accommodate that.
|
||||
|
||||
Also, some servers serve their links as `./name`. This is helpful to
|
||||
them because it is the only way to express relative references when the
|
||||
first new path segment of the target contains an unescaped colon (`:`),
|
||||
eg in `./6:1-balun.png`. While stripping the ./ strictly speaking
|
||||
reintroduces that ambiguity, it is of little practical concern in this
|
||||
implementation, as full URI link targets are filtered by their number of
|
||||
slashes anyway. In URI terms, this converts path-noscheme with a leading
|
||||
`.` segment into path-noscheme or path-rootless without that segment.
|
||||
*/
|
||||
|
||||
if (link_url[0] == '.' && link_url[1] == '/') {
|
||||
memmove(link_url, link_url + 2, strlen(link_url) - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (link_url[0] != '/') {
|
||||
/* Already relative, nothing to do here! */
|
||||
/* Already relative, nothing to do here!
|
||||
|
||||
(Full URIs, eg. `http://example.com/path`, pass through here
|
||||
unmodified, but those are classified in different LinkTypes later
|
||||
anyway).
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* ----------------- External variables ----------------------
|
||||
|
@ -110,9 +111,10 @@ curl_callback_unlock(CURL *handle, curl_lock_data data, void *userptr)
|
|||
* \details Adapted from:
|
||||
* 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)
|
||||
{
|
||||
int result = 0;
|
||||
(void) n_running_curl;
|
||||
(void) n_mesgs;
|
||||
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",
|
||||
curl_msg->data.result,
|
||||
curl_easy_strerror(curl_msg->data.result), url);
|
||||
result = curl_msg->data.result;
|
||||
}
|
||||
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 {
|
||||
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
|
||||
* 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,
|
||||
"thread %x: locking transfer_lock;\n", pthread_self());
|
||||
|
@ -207,7 +247,12 @@ int curl_multi_perform_once(void)
|
|||
int n_mesgs;
|
||||
CURLMsg *curl_msg;
|
||||
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,
|
||||
|
@ -272,7 +317,7 @@ void NetworkSystem_init(void)
|
|||
crypto_lock_init();
|
||||
}
|
||||
|
||||
void transfer_blocking(CURL *curl)
|
||||
void transfer_blocking(CURL *curl, size_t start)
|
||||
{
|
||||
TransferStruct *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());
|
||||
PTHREAD_MUTEX_UNLOCK(&transfer_lock);
|
||||
|
||||
while (ts->transferring) {
|
||||
curl_multi_perform_once();
|
||||
int result = 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,13 +26,13 @@ typedef enum {
|
|||
extern CURLSH *CURL_SHARE;
|
||||
|
||||
/** \brief perform one transfer cycle */
|
||||
int curl_multi_perform_once(void);
|
||||
int curl_multi_perform_once(int *result);
|
||||
|
||||
/** \brief initialise the network module */
|
||||
void NetworkSystem_init(void);
|
||||
|
||||
/** \brief blocking file transfer */
|
||||
void transfer_blocking(CURL *curl);
|
||||
void transfer_blocking(CURL *curl, size_t start);
|
||||
|
||||
/** \brief non blocking file transfer */
|
||||
void transfer_nonblocking(CURL *curl);
|
||||
|
|
Loading…
Reference in New Issue