Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

curl_easy_setopt CURLOPT_MAX_RECV_SPEED_LARGE not work during curl_multi_perform #6162

Closed
Ymir1711 opened this issue Nov 3, 2020 · 2 comments

Comments

@Ymir1711
Copy link

Ymir1711 commented Nov 3, 2020

Version: curl-7_73_0
Action: curl_easy_setopt CURLOPT_MAX_RECV_SPEED_LARGE after curl_multi_perform for a while.
Expect: Download speed is limited.
Actually: CURLOPT_MAX_RECV_SPEED_LARGE not work.

Issue:
void Curl_pgrsStartNow(struct Curl_easy *data)
data->progress.dl_limit_start and data->progress.ul_limit_start is zero, not Curl_now();

@Ymir1711
Copy link
Author

Ymir1711 commented Nov 3, 2020

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

bool change_speed = false;

static int progress_callback(void *clientp,   double dltotal,   double dlnow,   double ultotal,   double ulnow)
{
    static time_t time_last = 0;
    static time_t time_start = 0;
    static double dlnow_last = 0;

    time_t now = time(NULL);
    if (time_last == 0) {
        time_last = now;
        time_start = now;
        dlnow_last = dlnow;
    }

    if (now > time_last + 1) {
        printf("Speed: %.2f KB/S\n", (dlnow - dlnow_last) / (now - time_last) / 1024);
        time_last = now;
        dlnow_last = dlnow;
    }

    if (dlnow / dltotal > 0.5 || now > time_start + 10) {
        change_speed = true;
    }

    return 0;
}

static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    return size * nmemb;
}

int main()
{
    CURL *easy_handle = curl_easy_init();
    if (!easy_handle) {
        return -1;
    }

    const char *url = "https://speed.hetzner.de/100MB.bin";
    curl_easy_setopt(easy_handle, CURLOPT_URL, url);
    curl_easy_setopt(easy_handle, CURLOPT_PROGRESSFUNCTION, progress_callback);
    curl_easy_setopt(easy_handle, CURLOPT_NOPROGRESS, 0L);
    curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_callback);
    curl_easy_setopt(easy_handle, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(easy_handle, CURLOPT_SSL_VERIFYPEER, 0L);

    CURLM *multi_handle = curl_multi_init();
    if (!multi_handle) {
        return -1;
    }

    bool done = false;
    CURLcode result = CURLE_OK;

    CURLMcode mcode = curl_multi_add_handle(multi_handle, easy_handle);

    while (!mcode) {
        int still_running = 0;
        int numfds = 0;

        mcode = curl_multi_perform(multi_handle, &still_running);

        if (!still_running && !mcode) {
            int rc;
            CURLMsg *msg = curl_multi_info_read(multi_handle, &rc);
            if (msg) {
                result = msg->data.result;
                printf("Curl result: %d\n", result);
                break;
            }
        }else {
            long timeout;
            curl_multi_timeout(multi_handle, &timeout);
            if (timeout < 0) {
                timeout = 100;
            }

            curl_multi_wait(multi_handle, NULL, 0, timeout, &numfds);
        }

        static bool speed_changed = false;
        if (change_speed && !speed_changed) {
            curl_easy_setopt(easy_handle, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)31415);

            speed_changed = true;
            printf("CURLOPT_MAX_RECV_SPEED_LARGE\n");
        }
    }

    curl_multi_remove_handle(multi_handle, easy_handle);
    curl_easy_cleanup(easy_handle);
    curl_multi_cleanup(multi_handle);

    return 0;
}

@bagder
Copy link
Member

bagder commented Nov 3, 2020

We actually don't promise that setting and changing this option at run-time works. I would of course still be cool if it does, but I think there's not enough caution in the code being made for that situation.

bagder added a commit that referenced this issue Nov 7, 2020
By setting the speed limit time stamps unconditionally at transfer
start, we can start off a transfer without speed limits and yet allow
them to get set during transfer and have an effect.

Reported-by: Kael1117 on github
Fixes #6162
Closes #
@Ymir1711 Ymir1711 closed this as completed Nov 9, 2020
bagder added a commit that referenced this issue Nov 9, 2020
By setting the speed limit time stamps unconditionally at transfer
start, we can start off a transfer without speed limits and yet allow
them to get set during transfer and have an effect.

Reported-by: Kael1117 on github
Fixes #6162
Closes #6184
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

2 participants