cURL / Mailing Lists / curl-library / Single Mail

curl-library

curl_multi question

From: Surya Kiran Gullapalli <suryakiran.gullapalli_at_gmail.com>
Date: Fri, 10 Aug 2007 10:00:22 +0530

Hello,
I'm using curl_multi to transfer multiple files from a particular web page.

When i use CURLOPT_WRITEDATA and CURLOPT_WRITEFUNCTION, I'm getting a
segmentation violation at curl_multi_perform. If i do not use them,
I'm able to transfer the files, but the output is written to stdout.

Two Questions:

1. How can i write the data to files when i use curl_multi
2. If this is the way to write data to files, then why the
segmentation violation?

Find the code attached below.

Thanks in advance,
Surya

================================
#include <sys/select.h>
#include <curl/curl.h>

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <sstream>
using namespace std ;

typedef struct
{
        string filename ;
        FILE *fp ;
}OutFile;

map <int, OutFile> files;

static size_t write_function (void* buffer, size_t size, size_t nmemb,
void *stream)
{
    OutFile *out = (OutFile*)stream ;
    if (out && !out->fp)
    {
        out->fp = fopen (out->filename.c_str(), "wb") ;
        if (!out->fp) return (-1) ;
    }
    return fwrite (buffer, size, nmemb, out->fp) ;
}

CURL* set_handle (const string& site, const string& code, int idx)
{
    OutFile outfile ;
    outfile.filename = ("out-") ;
    outfile.filename += code ;
    outfile.fp = NULL ;

        files [idx] = outfile ;

    CURL *handle = curl_easy_init() ;
    curl_easy_setopt(handle, CURLOPT_URL, site.c_str()) ;
    curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1) ;
        /*
    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_function) ;
    curl_easy_setopt(handle, CURLOPT_WRITEDATA, &outfile) ;
        */
    return handle ;
}

int main (void)
{
    vector<CURL *> handles;
    CURLM *multi_handle;
    int still_running ;
    int msgs_left ;

    int num_handles (3) ;
    handles.reserve(num_handles) ;
    CURLMsg *msg ;
    string site
("http://getquote.icicidirect.com/trading/equity/trading_stock_quote.asp")
;
    vector<string> codes ;
        vector<string> sites ;

    codes.push_back ("ICIBAN") ;
    codes.push_back ("HINFC") ;
    codes.push_back ("DLFLIM") ;
    char error_buffer[CURL_ERROR_SIZE] ;

    for (int i = 0; i < num_handles; ++i)
    {
        ostringstream os ;
        os << "http://getquote.icicidirect.com/trading/equity/trading_stock_quote.asp"
           << "?Symbol=" << codes[i] << ends ;
                sites.push_back (os.str()) ;
        handles.push_back (set_handle(sites[i], codes[i], i)) ;
    }

        for (int i = 0; i < num_handles; ++i)

    multi_handle = curl_multi_init();

    for (int i=0; i<num_handles; i++)
        curl_multi_add_handle(multi_handle, handles[i]);

    while(CURLM_CALL_MULTI_PERFORM ==
            curl_multi_perform(multi_handle, &still_running));

    while(still_running) {
        struct timeval timeout;
        int rc; /* select() return code */

        fd_set fdread;
        fd_set fdwrite;
        fd_set fdexcep;
        int maxfd;

        FD_ZERO(&fdread);
        FD_ZERO(&fdwrite);
        FD_ZERO(&fdexcep);

        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

        switch(rc)
                {
            case -1:
                cout << "SELECT ERROR" << endl ;
                break;
            case 0:
                cout << "TIME OUT" << endl ;
                break;
            default:
                                cout << "IN DEFAULT" << endl ;
                while(CURLM_CALL_MULTI_PERFORM ==
                        curl_multi_perform(multi_handle, &still_running)) ;
                break;
        }
    }

    while ((msg = curl_multi_info_read(multi_handle, &msgs_left)))
    {
        if (msg->msg == CURLMSG_DONE)
        {
            int idx, found = 0;

            /* Find out which handle this message is about */
            for (idx=0; (!found && (idx<num_handles)); ++idx)
            {
                found = (msg->easy_handle == handles[idx]);

                cout << codes[idx] << " transfer completed with status "
                    << msg->data.result << endl ;

                                if (files[idx].fp) fclose (files[idx].fp) ;
            }

        }
    }

    curl_multi_cleanup(multi_handle);

    /* Free the CURL handles */
    for (int i=0; i<num_handles; i++)
        curl_easy_cleanup(handles[i]);

    handles.clear() ;
}
===========================
Received on 2007-08-10