Hi all
I have read this(http://curl.haxx.se/libcurl/c/multi-single.html) and 
carefully, 
but I still don't understand how to keep multi interface work again without 
recreate it when select call failed.


Attached is my code, I call CMultiCurl::Poll in an infinite loop. When I need 
to post something, I call CMultiCurl::Post.
This work first, but I don't know when and how, select call failed, then 
nothing goes right.
Please help me out, thanks very much.


___________________________________________________________________________________________
int CMultiCurl::Poll(int timeout/*msec*/)
{
struct timeval rTimeo;
rTimeo.tv_sec = timeout / 1000;
rTimeo.tv_usec = (timeout % 1000) * 1000;


long curlTimeo = -1;
curl_multi_timeout(m_mcurl, &curlTimeo);
if (curlTimeo >= 0 && curlTimeo < timeout)
{
rTimeo.tv_sec = curlTimeo / 1000;
rTimeo.tv_usec = (curlTimeo % 1000) * 1000;
}
//XA_TRACE("multi_curl select timeout: %d, %d", rTimeo.tv_sec, rTimeo.tv_usec);


fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);


int ret = curl_multi_fdset(m_mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
if (ret != 0)
{
XA_ERROR("%d", ret);
return -1;
}


ret = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &rTimeo);
if (ret == -1)
{
XA_ERROR("%d: %s", ret, strerror(errno));
return -1;
}


int stillR = 0;
while (CURLM_CALL_MULTI_PERFORM 
== (ret = curl_multi_perform(m_mcurl, &stillR))) {}
if (ret != 0)
{
XA_ERROR("%d", ret);
}


// check msg
int rest = 0;
CURLMsg *msg = NULL;
while (NULL != (msg = curl_multi_info_read(m_mcurl, &rest)))
{
if (msg->msg == CURLMSG_DONE)
{
MCB *mcb = (MCB *)GetFromMap(msg->easy_handle);
DelFromMap(msg->easy_handle);
XA_ASSERT(mcb != NULL);
if (mcb->ptr != NULL)
{
m_callback(msg->data.result, mcb->ptr, mcb->buf, mcb->used);
delete [] mcb->buf;
}


if (mcb->slist != NULL)
{
curl_slist_free_all(mcb->slist);
}
delete mcb;


curl_multi_remove_handle(m_mcurl, msg->easy_handle);
curl_easy_cleanup(msg->easy_handle);
}
}


return 0;
}
#include "MultiCurl.h"

typedef struct _MCB
{
        struct curl_slist *slist;
        void *ptr;

        char *buf;
        int total;
        int used;

}MCB;

static size_t CurlWriteCallback( char *ptr, size_t size, size_t nmemb, void 
*userdata)
{
        if (size * nmemb == 0) return 0;

        int len = (int)(size * nmemb);  

        // debug
        //char debug[1024*16];
        //snprintf(debug, 1024*16, ptr, len);
        //printf("\n###\n%s\n###\n", debug);

        MCB *mcb = (MCB *)userdata;
        if (mcb->ptr == NULL)
        {
                // do nothing
                return len;
        }

        if (len + mcb->used > mcb->total)
        {
                XA_ERROR("buffer is too small: curSize:%d, at least:%d", 
mcb->total, len + mcb->used);
                return 0; // This will abort the transfer and return 
CURLE_WRITE_ERROR.
        }

        memcpy(mcb->buf + mcb->used, ptr, len);
        mcb->used += len;
        return len;
}

int CMultiCurl::Init(MultiCurlCallback callback, int bufLen)
{
        m_callback = callback;
        m_mcurl = curl_multi_init();
        if (m_mcurl == NULL)
        {
                XA_ERROR("");
                return -1;
        }
        m_bufLen = bufLen;

        return 0;
}

int CMultiCurl::Poll(int timeout/*msec*/)
{
        struct timeval rTimeo;
        rTimeo.tv_sec = timeout / 1000;
        rTimeo.tv_usec = (timeout % 1000) * 1000;

        long curlTimeo = -1;
        curl_multi_timeout(m_mcurl, &curlTimeo);
        if (curlTimeo >= 0 && curlTimeo < timeout)
        {
                rTimeo.tv_sec = curlTimeo / 1000;
                rTimeo.tv_usec = (curlTimeo % 1000) * 1000;
        }
        //XA_TRACE("multi_curl select timeout: %d, %d", rTimeo.tv_sec, 
rTimeo.tv_usec);

        fd_set fdread;
        fd_set fdwrite;
        fd_set fdexcep;
        int maxfd = -1;
        FD_ZERO(&fdread);
        FD_ZERO(&fdwrite);
        FD_ZERO(&fdexcep);

        int ret = curl_multi_fdset(m_mcurl, &fdread, &fdwrite, &fdexcep, 
&maxfd);
        if (ret != 0)
        {
                XA_ERROR("%d", ret);
                return -1;
        }

        ret = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &rTimeo);
        if (ret == -1)
        {
                XA_ERROR("%d: %s", ret, strerror(errno));
                return -1;
        }

        int stillR = 0;
        while (CURLM_CALL_MULTI_PERFORM 
                                == (ret = curl_multi_perform(m_mcurl, 
&stillR))) {}
        if (ret != 0)
        {
                XA_ERROR("%d", ret);
        }

        // check msg
        int rest = 0;
        CURLMsg *msg = NULL;
        while (NULL != (msg = curl_multi_info_read(m_mcurl, &rest)))
        {
                if (msg->msg == CURLMSG_DONE)
                {
                        MCB *mcb = (MCB *)GetFromMap(msg->easy_handle);         
                                
                        DelFromMap(msg->easy_handle);
                        XA_ASSERT(mcb != NULL);
                        if (mcb->ptr != NULL)
                        {
                                m_callback(msg->data.result, mcb->ptr, 
mcb->buf, mcb->used);
                                delete [] mcb->buf;
                        }

                        if (mcb->slist != NULL)
                        {
                                curl_slist_free_all(mcb->slist);
                        }
                        delete mcb;

                        curl_multi_remove_handle(m_mcurl, msg->easy_handle);
                        curl_easy_cleanup(msg->easy_handle);
                }
        }

        
        return 0;
}

int CMultiCurl::Exit()
{
        return 0;
}

int CMultiCurl::Post(const char *url, const char *param, void *ptr,
                        const char *host, int timeout/*msec*/,
                        const char *encoding)
{
        CURL *curl = curl_easy_init();  
        XA_ASSERT(curl != NULL);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
        //curl_easy_setopt(curl, CURLOPT_HEADER, 1); 
        curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

        curl_easy_setopt(curl, CURLOPT_POST, 1);
        //curl_easy_setopt(curl, CURLOPT_POSTFIELDS, param); 
        curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, param); 
        curl_easy_setopt(curl, CURLOPT_URL, url);
        struct curl_slist *slist = NULL;
        if (host != NULL)
        {
                char buf[256];
                snprintf(buf, 256, "Host:%s", host);

                slist = curl_slist_append(slist, buf);
                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
        }

        curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout);
        curl_easy_setopt(curl, CURLOPT_ENCODING , encoding);

        MCB *mcb = new MCB();
        mcb->slist = slist;
        mcb->ptr = ptr;
        mcb->buf = NULL;
        mcb->total = 0;
        mcb->used = 0;

        if (ptr != NULL)// otherwise no callback
        {
                mcb->buf = new char[m_bufLen];
                mcb->total = m_bufLen;
        }
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)mcb); 


        // debug
        //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        //printf("\n##post\n%s\n##\n", param);

        int ret = curl_multi_add_handle(m_mcurl, curl);
        XA_ASSERT(ret == 0);
        
        AddToMap(curl, (void *)mcb);
        return 0;
}

void CMultiCurl::AddToMap(CURL* key, void *value)
{
        unsigned long k = (unsigned long)key;
        int c = m_mcbMap.count(k);
        XA_ASSERT(c == 0);
        m_mcbMap[k] = value;
        return;
}

void CMultiCurl::DelFromMap(CURL *key)
{
        unsigned long k = (unsigned long)key;
        int c = m_mcbMap.count(k);
        XA_ASSERT(c == 1);
        m_mcbMap.erase(k);
        return;
}

void *CMultiCurl::GetFromMap(CURL *key)
{
        unsigned long k = (unsigned long)key;
        int c = m_mcbMap.count(k);
        XA_ASSERT(c == 1);
        return m_mcbMap[k];
}

Attachment: MultiCurl.h
Description: Binary data

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to