cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: CURLM Chain of events

From: surf via curl-library <curl-library_at_cool.haxx.se>
Date: Fri, 22 Jan 2016 13:26:12 +0000 (UTC)

>This said, are you even intending to use libcurlevent-based? Yes. >The event based API is curl_multi_socket_action() andfriends. Event-based >(just in case it isn't clear) means you use some sortof system that monitors >all sockets in use right now and as soon as there'san "event" on one of them, >you call the necessary function that acts on thatsocket.
OK. curl_multi_perform OUT, curl_multi_socket_action(curl_m_handle,CURL_SOCKET_TIMEOUT… IN I assume this just causes libcurl to attempttransfer for all added easy handles? So the general idea is that calling curl_multi_socket_action()for a particular socket will cause libcurl to attempt transfer on thatsocket -  if it can, and if it can’t itwill fire socket_callback() telling me to call curl_multi_socket_action() againonce I determine the socket is ready for read or write. This would goback and forth until socket_callback() fires with CURL_POLL_REMOVE in whichcase I would need to loop on curl_multi_info_read() to determine the outcomefor the transfer and optionally remove the easy handle from the collection. DidI get this right? >It may call the callback several times when it needsto uptime the timeout >value (even if it isn't really meant to do it manytimes, I think you may see >this because you're not usingcurl_multi_socket_action()). Still seeing those after changing to curl_multi_socket_action(curl_m_handle,CURL_SOCKET_TIMEOUT.. (25 calls), but I guess this is OK. I'm still a bit hesitated about how the non-repeatingtimer supplements the transfer process per easy handle. The way I figure, thenon-repeating timer callback says it's time's up for telling libcurl that"some socket" is ready; therefore, I assume I should stop the timer from firing as soonas I determine the socket is ready. The thing is that the api does not appear toexpose a one-to-one relationship between a socketfd and a non-repeating timerinstance. I mean sure it allows me to pass custom data via *userp but I don'tquite see how to construct this per socketfd to begin with. Alternatively, am Iexpected to just let timer callbacks fire anyway and callcurl_multi_socket_action(curl_m_handle, CURL_SOCKET_TIMEOUT regardless of what the socket ready state is? Will that cause libcurl to fire asocket_callback with CURL_POLL_REMOVE for a particular timed-out socket inwhich case I would need to also test for CURLE_OPERATION_TIMEDOUT when loopingon curl_multi_info_read? Obviously I would need to ensure that no call to curl_multi_socket_action()will take place for that socket after this point, but I wonder if I'm allowed to preventthe timeout callback from firing to begin with just to be more efficient, that is when socket readiness is determined before the timeout elapses.
 

    On Friday, January 22, 2016 12:41 AM, Daniel Stenberg <daniel_at_haxx.se> wrote:
 

 On Thu, 21 Jan 2016, surf via curl-library wrote:

> I'm a bit confused about the semantics and dealing with the various CURLM
> events. Here is a high-level description of my setup (Windows). I embedded
> my questions within.

Let me try to explain. But also, I'm not at all familar with event-based
programming on Windows so while I can tell you the libcurl side I don't know
the Windows implementation details.

This said, are you even intending to use libcurl event-based?

The event based API is curl_multi_socket_action() and friends. Event-based
(just in case it isn't clear) means you use some sort of system that monitors
all sockets in use right now and as soon as there's an "event" on one of them,
you call the necessary function that acts on that socket.

The "normal" multi API is not event based and uses the curl_multi_perform()
function to drive the transfers. It is design to have you extract the file
descriptors from libcurl, call select() and then call curl_multi_perform() as
soon as there's activity (or timeout).

>   curl_multi_add_handle(..;
>   curl_multi_perform(..

So this is the regular multi interface. Then I understand the confusion.

This makes me hesitate if I should go on and answer the rest of the questions
because they're all related to the multi_socket API that you don't seem to be
using. But maybe its just a mistake? OK, I'll try to answer them anyway.

Just keep the two different approaches in your mind when proceeding from here.

>   socket_callback(
>   {
>    // Here curl is telling me via CURL_POLL_IN/OUT that it wants me to tell it 
>    // when the socket is ready for read/write.
>   }

The socket callback is for the multi_socket API. You can ignore it otherwise.

>   timer_callback(

The timer callback is also for the multi_socket API. With the ordinary multi
API you typically either use curl_multi_wait() *or* you extract the file
descriptors and timeout value with curl_multi_fdset() and
curl_multi_timeout().

>   {
>    // Here curl tells me to give up waiting for socket readiness after Xms
>    
>    Q1: How does it figure X ?
>    Q2: When I start my program I noticed curl raises this event 3 times before
>     raising any other events.. Why is that?
>   }

It figures out X based on what it does and what needs it has for the moment,
based on what states the current running transfers are in.

It may call the callback several times when it needs to uptime the timeout
value (even if it isn't really meant to do it many times, I think you may see
this because you're not using curl_multi_socket_action()).

> "When the curl_multi_socket_action function runs, it informs the application
> about updates in the socket (file descriptor) status by doing none, one, or
> multiple calls to the socket_callback"

This is again describing the multi_socket functionality.

>  What exactly am I supposed to do in socket_callback for this case ?

The socket_callback is your code. libcurl calls it to inform about what
sockets you should monitor for its sake. It adds, removes or changes the
sockets you monitor.

When there's activity on one of those sockets, you call libcurl and tell it
about it.

That's basically how event-based socket handling works.

>  Since I'm only supposed to pass CURL_SOCKET_TIMEOUT and not sockfd,

You're supposed to pass CURL_SOCKET_TIMEOUT on timeouts and you're supposed to
pass a socket descriptor when there's socket activity.

-- 
  / daniel.haxx.se
  

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2016-01-22