cURL / Mailing Lists / curl-library / Single Mail

curl-library

curl_easy_perform does not return if the readfunc_callback returns

From: Dheeraj Sangamkar <dheerajrs_at_gmail.com>
Date: Thu, 14 Nov 2013 13:00:03 -0800

I am building a wrapper around curl that uploads data using HTTP PUT using
the chunked transfer encoding.

The code flow is

Constructor->
public:
    HttpFragmentSink(const std::string &uri)
        : m_uri(uri), m_curl(0), m_chunk(0), m_data(0, 0)
    {
        // Setup curl connection.
        std::cout << "Opening sink uri: " << m_uri << std::endl;
        if(0 == (m_curl = curl_easy_init())){
            throw std::bad_alloc();
        }
        curl_easy_setopt(m_curl, CURLOPT_UPLOAD, 1L);
        curl_easy_setopt(m_curl, CURLOPT_PUT, 1L);
        curl_easy_setopt(m_curl, CURLOPT_URL, m_uri.c_str());

        m_chunk = curl_slist_append(m_chunk, "Transfer-Encoding: chunked");
        m_chunk = curl_slist_append(m_chunk, "Expect:");
        curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_chunk);
        curl_easy_setopt(m_curl, libcurl verbose debug, 1L);

        curl_easy_setopt(m_curl, CURLOPT_READFUNCTION, read_callback);
        curl_easy_setopt(m_curl, CURLOPT_READDATA, &m_data);
    }

>>The constructor sets up the curl handle to upload data to the http server.

    std::streamsize write(char* data, const ssize_t len)
    {

        if(!m_data.finished()) {
            throw std::exception();
        }

        m_data = DataDesc(data, len);

        std::cout << "calling curl_easy_perform for " << data << std::endl;

        int ret = curl_easy_perform(m_curl);
        if(CURLE_OK != ret) {
            return -1;
        }

        if(!m_data.finished()) {
            return m_data.sent();
        }

        return len;
    }

>>The write function attempts to send one chunk.
>> The client of this class calls write and write calls curl_easy_perform.
>> curl_easy_perform calls the 'read_callback' function.
>> When read_callback returns CURL_READFUNC_PAUSE, I expect
curl_easy_perform to return. However that does not happen and write hangs.

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void
*userdata)
{
    std::cout << "read callback called. (" << ptr << ", " << size << ", "
<< nmemb << ", " << userdata << ")" << std::endl;
    HttpFragmentSink::DataDesc *pData =
reinterpret_cast<HttpFragmentSink::DataDesc*>(userdata);

    if(pData->endOfXfer()) {
        std::cout << "read callback returning 0." << std::endl;
        return 0;
    }

    if(pData->finished()) {
        std::cout << "read callback returning PAUSE." << std::endl;
        return CURL_READFUNC_PAUSE;
    }

    ssize_t data2Xfer = std::min(static_cast<ssize_t>(size * nmemb),
pData->getXferLen());

    memcpy(ptr, pData->getXferStart(), data2Xfer);
    pData->advance(data2Xfer);

    std::cout << "read callback returning " << data2Xfer << std::endl;
    return data2Xfer;
}

Is the curl_easy_perform supposed to return when the read callback function
returns CURL_READFUNC_PAUSE?
If yes, how to get around the problem?

-- 
Dheeraj
Protection of our environment is our responsibility.

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2013-11-14