cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: easy API: curl_easy_perform() doesn't return after receiving all data

From: James Buchanan <software.au_at_gmail.com>
Date: Mon, 13 Nov 2006 00:01:50 +1100

On 11/8/06, Daniel Stenberg <daniel_at_haxx.se> wrote:
> On Mon, 6 Nov 2006, James Buchanan wrote:
>
> > Attached is a little test program and the output it gives. Am I doing
> > something wrong?
>
> Well, I don't see why you pollute it with C++, it is grossly ineffective (like
> new, strncpy(), append with string operator + and then delete - in every
> callback) and you add a custom Content-Length: where you shouldn't need to,
> but apart from that I couldn't spot any major flaw.

:-) The C++ is because I'm lazy and I'm just trying to get it working.
It will be properly designed when it's working. I'm only doing the
(eventual) GUI in C++, and maybe a thin wrapper class around libcurl's
functions, but inside it will be all C.

Are you saying that after libcurl has called its CURLOPT_xxxFUNCTION
and gets the data it POSTs to the server, it will correctly set
Content-Length by itself? If yes, in what order should I set things
with curl_easy_setopt()?

> > CURL info: Connected to api.google.com (216.239.37.104) port 80 (#0)
> >
> > CURL HTTP Header Out: POST /search/beta2 HTTP/1.1
> > Host: api.google.com
> > Accept: */*
> > Content-Type: text/xml; charset=utf-8
> > Content-Length: 829
> > SOAPAction: urn:GoogleSearchAction
>
> As you can see, this is only the request-heders being sent. It should also
> send 829 of request-body...

But it has, as you can see above, or am I misunderstanding something?

> > CURL HTTP Header In: HTTP/1.1 200 OK
> > CURL HTTP Header In: Content-Type: text/xml; charset=utf-8
> > CURL HTTP Header In: Cache-control: private
> > CURL HTTP Header In: Transfer-Encoding: chunked
> > CURL HTTP Header In: Date: Mon, 06 Nov 2006 07:00:50 GMT
> > CURL HTTP Header In: Server: GFE/1.3
> >
> > CURL info: select/poll returned error
>
> Wow. This happens when Curl_select() returns only CSELECT_ERR and I've
> actually never seen anyone experience this before.
>
> I would suggest you run this with a debugger to investigate this deeper.

No worries. I'll get onto it.

By the way, everything seems to have gone completely awry. I have been
writing the shortest and simplest C programs using libcurl as I
possibly can, using CURLOPT_READFUNCTION and CURLOPT_WRITEFUNCTION. Is
it possible I am mixing them up?

The read function is actually what is called when data is sent from
the server to the application, is that correct? And the write function
is what is called when libcurl needs the POST data to send to the
server (and presumably somewhere sets content-length if I return the
correct content length in the write function callback? But then it
could get called several times, so will it accumulate the return
values or is only the last return value used, ending up with
Content-Length: 0 when I don't explicitly set Content-Length?)

Also, with the CURLOPT_READFUNCTION and CURLOPT_WRITEFUNCTION:

size_t curl_readfcn(void *ptr, size_t size, size_t nmemb, void *v)
{
   /* Assume this is how CURL gets our data to POST */

   if ( our_data_length > size * nmemb)
      return 0; /* Too long */

   /* Is this the way to do it? Can't NUL terminate, in case called
multiple times */
   size_t rc = fwrite(ptr, 1, our_data_length, our_data_buffer_FILEptr);

   while (fwrite() hasn't written our_data_length and no other errors)
      keep frwrite()'ing

   /* Handle possible error/s */

   return our_data_length;
}

size_t curl_readfcn(void *ptr, size_t size, size_t nmemb, void *v)
{
   /* Assume this is where CURL gets the data send back from the server */

   if (size * nmemb == 0)
      return 0; /* No more data from server? Check for Curl error? */

   /*
      Does this get called multiple times or can it be called multiple times
      so I will possibly need to realloc() my buffer to receive the data?

      Probably better a simple strncpy(our_buffer, ptr, size * nmemb);
      or memcpy(our_buffer, ptr, size * nmemb);
   */
   size_t rc = fwrite(our_buffer, size, size * nmemb, [v as FILE* ?]);

   /* if rc accumulated != size * nmemb, realloc buffer and keep
fwrite()'ing? */

   return size * nmemb;
}

I'm getting some very odd results with data in and data out and
headers in and headers out being mixed up when I dump it all to log
files, so I just want to be sure I understand what I'm doing here.

A couple of further questions: on Win32,
curl_global_init(CURL_GLOBAL_WIN32) or
curl_global_init(CURL_GLOBAL_ALL)? And could there be potential issues
with the order in which things are set with curl_easy_setopt()?

Thanks for your help. If I keep having further problems could I send
you a simple C app that uses libcurl to make sure everything's done
properly?

Thanks very much. I think I'm muddled a bit here...

-J
Received on 2006-11-12