curl-library
RE: known problem with write progress callback?
Date: Wed, 30 Jan 2008 06:29:53 -0700
From: curl-library-bounces_at_cool.haxx.se [mailto:curl-library-bounces_at_cool.haxx.se] On Behalf Of Daniel Stenberg
Sent: Wednesday, January 30, 2008 4:32 AM
To: libcurl development
Subject: Re: known problem with write progress callback?
On Tue, 29 Jan 2008, Max L. Eidswick wrote:
> I am testing the progress callback for an updated win32 app. The progress
> callback gets hit, but there is no write callback data until the last call.
> The last call values are not correct either.
>
> Are there known problems with the progress callback on a simple HTTP post
> for a file send?
No.
AFAIK, this works and the code for this really hasn't been modified in a
number of years so I'm suspecting you have these problems for some other
reasons.
Can you show us a full stand-alone source code that repeats this behaviour
when run?
----- snip
Here is an example of the test code ...
// ---------------------------------------------------------------------
// module to test progress callback during http file upload -- 25.01.08 //
// the symptom I am experiencing in this test that I don't understand
// is that the SendfileProgressCallback proc is called about 90 times
// in the 15 seconds it takes to upload the ~1.3mb test file. It then
// reports 1,075,576,832 bytes uploaded for a file that is
// 1,338,460 bytes big (the upload is successful, I can re-download it
// and test the RAR file's integrity).
//
// obviously, I am doing something wrong, either with the callback
// data or I need to use the CURLOPT_PROGRESSDATA pointer, but I
// am unclear as to what type of structure it is supposed to point to
// and the format of the data that gets pointed to by it. I have gone
// through the current examples and several others I have found on the
// web, but most seem to do with the multi-interface.
//
// I am confident this libcurl version works fine with this feature,
// so this must be a simple mis-implementation of this test code.
//
// Thanks for any direction. The last run output follows together
// with a directory listing of the source sendfile test file ...
//
/* ----- snip: output from command line stdout:
Uploading now:
Call count: 90, dltotal: 0, dlnow: 0, ultotal: 0,ulnow: 1075576832 curl sendfile time: 15281 msecs
----- End of test of libcurl sendfile ----- Press any key to exit.
----- end snip */
/* ----- snip: dir size of test file:
">"dir c:\sendfiletest.rar
01/24/2008 11:08 AM 1,338,460 SendfileTest.rar
1 File(s) 1,338,460 bytes
----- end snip */
// see SendfileProgressCallback for this test module.
// ---------------------------------------------------------------------
// standard c and windows includes
#include <conio.h>
// ---------------------------------------------------------------------
// cURL inclusions (winsock2.h is before windows.h) // ---------------------------------------------------------------------
#define _WIN32_WINNT 0x0500 // for icon notification size
#pragma warning( disable : 4996 ) // eliminate vs2005 security bs
// ---------------------------------------------------------------------
// libcurl includes in ..\RedPawComms\libcURL\curl-7.17.1\include
#include <curl/curl.h>
// ---------------------------------------------------------------------
// test module storage allocations and structures
struct curl_httppost *formPostSendfile = NULL ; // for formadd
struct curl_httppost *lastPtr = NULL ; // for libcurl curl_formadd
// ---------------------------------------------------------------------
UCHAR ucCURLErrorBuffer[CURL_ERROR_SIZE] ; // used by libcurl errors
ULONG ulStartClick = 0 ; // millisecond counter before easy perform
ULONG ulStopClick = 0 ; // millisecond counter after easy perform
UCHAR szTmpBuf[2048] ; // plenty of space for string output
BOOL bDone = FALSE ; // exit flag, when done
// ---------------------------------------------------------------------
CURL *curlhSendfile ; // libcurl sendfile test handle
CURLcode res ; // result code from libcurl
// =====================================================================
// libcurl file transfer callback -
//
// the docs say to look at the prototype in curl.h, but it doesn't say
// much about what the clientp pointer is for ... maybe testing will
// help clear this up ...
// =====================================================================
int SendfileProgressCallback (
void *clientp, // CURLOPT_PROGRESSDATA pointer
double dltotal, // download total bytes
double dlnow, // downloaded bytes so far
double ultotal, // uploaded total bytes
double ulnow // uploaded bytes so far
)
{
static BOOL bFirstTime = TRUE ;
static ULONG ulCallCount = 0 ;
// write a command line window header for the test, then display
// the callback data as called ..
if ( bFirstTime )
{
printf ( "\nUploading now:\n" ) ;
bFirstTime = FALSE ;
}
printf (
"\rCall count: %d, dltotal: %ld, dlnow: %ld, ultotal: %ld,"
"ulnow: %ld",
++ulCallCount, dltotal, dlnow, ultotal, ulnow ) ;
return 0 ;
}
// end of progress callback test
// =====================================================================
// =====================================================================
// start of main test win32 procedure
//
// Testing: libcurl call to send a test file using a callback // //
=====================================================================
int main ( int argc, char *argv[] ) // test for comms dvlmt {
// ----- local data definitions for main proc ---------------------
// -----------------------------------------------------------------
// verify the file exists on client workstation, exit with error msg
// if not
// -----------------------------------------------------------------
// setup libcurl global info for win32, global cleanup on exit
if ( curl_global_init ( CURL_GLOBAL_ALL | CURL_GLOBAL_WIN32 ) )
{
// report and ABEND!
MessageBox ( NULL, "libcurl global init error",
"libcurl global init error", MB_OK ) ;
} // end of call to curl global init failed
// -----------------------------------------------------------------
// initialize the easy interface
curlhSendfile = curl_easy_init ( ) ; // get curl handle
if ( !curlhSendfile ) // zero means no handle, failed
{
// failed to get easy handle, so global cleanup and ABEND
curl_global_cleanup ( ) ; // clean up environment
MessageBox ( NULL, "libcurl easy init failure",
"libcurl easy init failure", MB_OK ) ;
ExitProcess ( 101 ) ; // ABEND ABEND ABEND ABEND ABEND ABEND
} // end of if !curl call to curl init failed
// -------------------------------------------------------------
// curl fails on 400+ error codes from the server - it's unclear
// if this does anything useful for our ping example, but it is
// in the planned production design, so it is here too ...
// -------------------------------------------------------------
curl_easy_setopt ( curlhSendfile, CURLOPT_FAILONERROR, TRUE ) ;
// ------------------------------------------------------------
// if there are any errors, make sure we know what libcurl says
// is going on
// ------------------------------------------------------------
curl_easy_setopt (
curlhSendfile, // for our sendfile test handle
CURLOPT_ERRORBUFFER, // ask libcurl to keep us
ucCURLErrorBuffer // informed about errors
) ;
// -------------------------------------------------------------
// setup our test URL
// -------------------------------------------------------------
curl_easy_setopt ( // setup URL to touch
curlhSendfile,
CURLOPT_URL,
"http://redpawsys.com/RPV7CommServices/"
"RPV7SendfileViaHTTPPost.php"
) ;
// =================================================================
// -----------------------------------------------------------------
// THIS IS WHAT WE ARE TESTING IN THIS MODULE
// -----------------------------------------------------------------
// turn on progress callback
curl_easy_setopt(curlhSendfile, CURLOPT_NOPROGRESS, FALSE ) ;
// set progress callback
curl_easy_setopt (
curlhSendfile,
CURLOPT_PROGRESSFUNCTION,
SendfileProgressCallback
) ;
// =================================================================
// -----------------------------------------------------------------
// setup a simple sendfile form, the php script simply copies the
// uploaded file and creates an upload logfile entry for testing
// -----------------------------------------------------------------
curl_formadd ( // add field/value for sendfile/callback test
&formPostSendfile, // libcurl form for sendfile
&lastPtr, // managed by formadd
CURLFORM_COPYNAME, "sendfile", // field name
CURLFORM_FILE, "C:\\SendfileTest.rar", // HTTP upload
CURLFORM_END
) ; // per libcurl spec
// -------------------------------------------------------------
// Tells libcurl you want a multipart/formdata HTTP POST to be
// made and you instruct what data to pass on to the server.
// -------------------------------------------------------------
curl_easy_setopt (
curlhSendfile,
CURLOPT_HTTPPOST,
formPostSendfile
) ;
// -------------------------------------------------------------
// DO IT. This should trigger the progress callback under test
// check the msecs before and after the call to easy perform
// -------------------------------------------------------------
ulStartClick = GetTickCount ( ) ;
res = curl_easy_perform ( curlhSendfile ) ; // << --- send it!
ulStopClick = GetTickCount ( ) ;
if ( res ) // libcurl call failed for some reason, so let's see
{
sprintf ( szTmpBuf, "cURL error: %d, %s",
curlhSendfile, ucCURLErrorBuffer ) ;
printf ( "\n ----- %s ----- \n", szTmpBuf ) ;
} // end of if libcurl perform call failed
else // the libcurl call was successful, so let's just see the
{ // click count and some of the PHP script response ...
printf ( "\nlibcurl sendfile time: %d msecs",
ulStopClick - ulStartClick ) ;
} // end of else libcurl perform call was successful
// -----------------------------------------------------------------
// clean up allocations for the sendfile form
curl_formfree ( formPostSendfile ) ; // free the form
// -----------------------------------------------------------------
// standard libcurl cleanup
// -----------------------------------------------------------------
curl_easy_cleanup ( curlhSendfile ) ; // end of easy session
curl_global_cleanup ( ) ; // clean up environment
// -----------------------------------------------------------------
printf ( "\n\n ----- End of test of libcurl sendfile ----- "
"Press any key to exit." ) ;
res = _getch ( ) ;
// -----------------------------------------------------------------
// end of this test program
// -----------------------------------------------------------------
return TRUE ;
} // ~~~~~ end of main procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Received on 2008-01-30