Ejemplo n.º 1
0
void
curlMulti_addHandle(xmlrpc_env *       const envP,
                    curlMulti *        const curlMultiP,
                    CURL *             const curlSessionP) {

    CURLMcode rc;

    curlMultiP->lockP->acquire(curlMultiP->lockP);

    rc = curl_multi_add_handle(curlMultiP->curlMultiP, curlSessionP);
    
    curlMultiP->lockP->release(curlMultiP->lockP);

    /* Old libcurl (e.g. 7.12) actually returns CURLM_CALL_MULTI_PERFORM
       (by design) when it succeeds.  Current libcurl returns CURLM_OK.
    */

    if (rc != CURLM_OK && rc != CURLM_CALL_MULTI_PERFORM) {
        const char * reason;
        interpretCurlMultiError(&reason, rc);
        xmlrpc_faultf(envP, "Could not add Curl session to the "
                      "curl multi manager.  curl_multi_add_handle() "
                      "failed: %s", reason);
        xmlrpc_strfree(reason);
    }
}
Ejemplo n.º 2
0
void
curlMulti_perform(xmlrpc_env * const envP,
                  curlMulti *  const curlMultiP,
                  bool *       const immediateWorkToDoP,
                  int *        const runningHandleCtP) {
/*----------------------------------------------------------------------------
   Do whatever work is ready to be done under the control of multi
   manager 'curlMultiP'.  E.g. if HTTP response data has recently arrived
   from the network, process it as an HTTP response.

   Iff this results in some work being finished from our point of view,
   return *immediateWorkToDoP true.  (Caller can query the multi manager for
   messages and find out what it is).

   Return as *runningHandleCtP the number of Curl easy handles under the
   multi manager's control that are still running -- yet to finish.
-----------------------------------------------------------------------------*/
    CURLMcode rc;

    curlMultiP->lockP->acquire(curlMultiP->lockP);

    rc = curl_multi_perform(curlMultiP->curlMultiP, runningHandleCtP);

    curlMultiP->lockP->release(curlMultiP->lockP);

    if (rc == CURLM_CALL_MULTI_PERFORM) {
        *immediateWorkToDoP = true;
    } else {
        *immediateWorkToDoP = false;

        if (rc != CURLM_OK) {
            const char * reason;
            interpretCurlMultiError(&reason, rc);
            xmlrpc_faultf(envP, "Impossible failure of curl_multi_perform(): "
                          "%s", reason);
            xmlrpc_strfree(reason);
        }
    }
}        
Ejemplo n.º 3
0
void
curlMulti_addHandle(xmlrpc_env *       const envP,
                    curlMulti *        const curlMultiP,
                    CURL *             const curlSessionP) {

    CURLMcode rc;

    curlMultiP->lockP->acquire(curlMultiP->lockP);

    rc = curl_multi_add_handle(curlMultiP->curlMultiP, curlSessionP);
    
    curlMultiP->lockP->release(curlMultiP->lockP);

    if (rc != CURLM_OK) {
        const char * reason;
        interpretCurlMultiError(&reason, rc);
        xmlrpc_faultf(envP, "Could not add Curl session to the "
                      "curl multi manager.  curl_multi_add_handle() "
                      "failed: %s", reason);
        xmlrpc_strfree(reason);
    }
}
Ejemplo n.º 4
0
void
curlMulti_fdset(xmlrpc_env * const envP,
                curlMulti *  const curlMultiP,
                fd_set *     const readFdSetP,
                fd_set *     const writeFdSetP,
                fd_set *     const exceptFdSetP,
                int *        const maxFdP) {
/*----------------------------------------------------------------------------
   Set the CURLM object's file descriptor sets to those in the
   curlMulti object, update those file descriptor sets with the
   current needs of the multi manager, and return the resulting values
   of the file descriptor sets.

   This is a bizarre operation, but is necessary because of the nonmodular
   way in which the Curl multi interface works with respect to waiting
   for work with select().
-----------------------------------------------------------------------------*/
    CURLMcode rc;
    
    curlMultiP->lockP->acquire(curlMultiP->lockP);

    /* curl_multi_fdset() doesn't _set_ the fdsets.  It adds to existing
       ones (so you can easily do a select() on other fds and Curl
       fds at the same time).  So we have to clear first:
    */
    FD_ZERO(&curlMultiP->readFdSet);
    FD_ZERO(&curlMultiP->writeFdSet);
    FD_ZERO(&curlMultiP->exceptFdSet);

    /* WARNING: curl_multi_fdset() doesn't just update the fdsets pointed
       to by its arguments.  It makes the CURLM object remember those
       pointers and refer back to them later!  In fact, curl_multi_perform
       expects its caller to have done a select() on those masks.  No,
       really.  The man page even admits it.

       Inspection of the Libcurl code in March 2007 indicates that
       this isn't actually true -- curl_multi_fdset() updates your
       fdset and doesn't remember the pointer at all.  I.e. it's just
       what you would expect.  The man pages still says it's as
       described above.  My guess is that Libcurl was fixed at some
       time and the man page not updated.  In any case, we have to
       work with old Libcurl if at all possible, so we still maintain
       these fdsets as if they belong to the CURLM object.
    */

    rc = curl_multi_fdset(curlMultiP->curlMultiP,
                          &curlMultiP->readFdSet,
                          &curlMultiP->writeFdSet,
                          &curlMultiP->exceptFdSet,
                          maxFdP);

    *readFdSetP   = curlMultiP->readFdSet;
    *writeFdSetP  = curlMultiP->writeFdSet;
    *exceptFdSetP = curlMultiP->exceptFdSet;

    curlMultiP->lockP->release(curlMultiP->lockP);

    if (rc != CURLM_OK) {
        const char * reason;
        interpretCurlMultiError(&reason, rc);
        xmlrpc_faultf(envP, "Impossible failure of curl_multi_fdset(): %s",
                      reason);
        xmlrpc_strfree(reason);
    }
}