________________________________________
From: [email protected] [[email protected]] on
behalf of Dan Fandrich [[email protected]]
Sent: Wednesday, January 25, 2012 7:26 PM
To: [email protected]
Subject: Re: libcurl PUT retry and READFUNCTION
On Wed, Jan 25, 2012 at 08:09:19PM +0000, Wenjun Chen wrote:
> This is the actual code. It uses local variable, not on stack.
>It may be an issue elsewhere in your code (and your previous messages
>imply that), but you didn't show us that code. You'll have to be more
>specific about what the problem is including code if you'd like more
>specific help.
Thanks Dan for your help, the problem is as described in the first e-mail, I
copied below again.
I then use SEEK_FUNC call back to get more info. See code after
put_data_callback.
The normal sequences are
(1) put_data_callback is called and data is sent to server.
In case when TCP is terminated.
(1) put_data_callback is called, data is copied and sent (the first try)
(TCP terminated by server)
(2) seek_data_callback is called, but the dataPtr passed in is not correct.
The seek_data_callback is called when server terminated the TCP, but the
m_data->data_len is 0, Origin is also 0 (SEEK_SET), offset is also 0. I know
the seek_data_call back does not handle SEEK_CUR and SEEK_END correctly. The
handle of SEEK_SET should be ok.
(3) libcurl send 0 bytes to server
I try to debug.
(1) Why the m_data->data_len is 0 when seek_data_callback is called. While
m_data->data_len is correct.
(2) Why the read_data_callback is not called after seek_data_callback is
called. I assume this is the root cause of sending 0 bytes to server.
Thanks again,
Wenjun
### Original Problem description and all related function implementation ####
I use libcurl to put a file to a HTTP server. When HTTP server FIN TCP
connection, the curl retried and resend the http header. However, the data in
retry packet has 0 length.
The sequence of the packet is as follows. The 1.1.1.1 is client IP address, the
2.2.2.2 is server IP address
1 0.000000 1.1.1.1 -> 2.2.2.2 HTTP PUT
/webdav/arxce/1327331782-01XFR48JF-17.metadata HTTP/1.1 #### Initial PUT
request, send HTTP header
2 0.000105 2.2.2.2 -> 1.1.1.1 TCP www > 55199 [FIN, ACK] Seq=0 Ack=0
Win=27 Len=0 #### Server FIN the connection
3 0.000124 1.1.1.1 -> 2.2.2.2 HTTP Continuation or non-HTTP traffic
#### client send DATA 373 bytes. (Probably send before
process the TCP FIN packet).
4 0.000177 1.1.1.1 -> 2.2.2.2 TCP 55199 > www [FIN, ACK] Seq=533 Ack=1
Win=254 [TCP CHECKSUM INCORRECT] Len=0 ### Client FIN above TCP connection
5 0.000294 1.1.1.1 -> 2.2.2.2 TCP 55200 > www [SYN] Seq=0 [TCP CHECKSUM
INCORRECT] Len=0 MSS=1460 WS=8 #### Client started a new TCP connection
6 0.000496 2.2.2.2 -> 1.1.1.1 TCP www > 55199 [ACK] Seq=1 Ack=534 Win=36
Len=0
7 0.000498 2.2.2.2 -> 1.1.1.1 TCP www > 55200 [SYN, ACK] Seq=0 Ack=1
Win=5840 Len=0 MSS=1460 WS=8
8 0.000532 1.1.1.1 -> 2.2.2.2 TCP 55200 > www [ACK] Seq=1 Ack=1 Win=65536
[TCP CHECKSUM INCORRECT] Len=0
9 0.000600 1.1.1.1 -> 2.2.2.2 HTTP PUT
/webdav/arxce/1327331782-01XFR48JF-17.metadata HTTP/1.1 ### Retry PUT
request, send HTTP header
10 0.000785 2.2.2.2 -> 1.1.1.1 TCP www > 55200 [ACK] Seq=1 Ack=161 Win=6912
Len=0 #### Server ACK
11 0.000802 1.1.1.1 -> 2.2.2.2 HTTP Continuation or non-HTTP traffic
#### client resend the data (only 5 bytes
300d0a0d0a), it should send 373 bytes as initial data send.
12 0.000933 2.2.2.2 -> 1.1.1.1 TCP www > 55200 [ACK] Seq=1 Ack=166 Win=6912
Len=0 #### Server ACK
13 0.001284 2.2.2.2 -> 1.1.1.1 HTTP HTTP/1.1 201 Created (text/html)I saw a
similar issue reported here ### Server response with created (but only the file
is only 0 byte).
I read the e-mail trace and look like this is the similar problem and
SEEKFUNCTION is suggested here.
http://curl.haxx.se/mail/lib-2009-08/0401.html
What is the final solution to the issue described above? If SEEKFUNCTION is
used, does anyone have an example of how to use it.
Thank you very much for your help in advance.
Wenjun Chen
PS.
I use READFUNCTION call back to put data to the libcurl buff.
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// set the put_data_callback function
curl_easy_setopt(curl, CURLOPT_PUT, true);
curl_easy_setopt(curl, CURLOPT_READDATA, &m_data);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, put_data_callback);
curl_easy_perform(curl);
Here is my callback function.
struct put_data_t {
const char * data_start;
unsigned read_pos;
unsigned data_len;
};
size_t put_data_callback(void *buff, size_t size, size_t nmem, void* userp)
{
if (!userp)
return 0;
put_data_t *userdata = (put_data_t *)userp;
if (userdata->data_len <= 0)
return 0;
size_t curl_size = nmem*size;
std::ostringstream ss;
ss << "put_data_callback get " << curl_size << " data passed in
" << userdata->data_len;
DCAL_logCritical(ss.str().c_str());
size_t to_copy = (userdata->data_len < curl_size) ?
userdata->data_len : curl_size;
memcpy(buff, userdata->data_start + userdata->read_pos,
to_copy);
userdata->data_len -= to_copy;
userdata->read_pos += to_copy;
return to_copy;
}
#### The code is changed to add seek_data_callback ####
> // set the put_data_callback function
> curl_easy_setopt(curl, CURLOPT_PUT, true);
> curl_easy_setopt(curl, CURLOPT_READDATA, &m_data);
> curl_easy_setopt(curl, CURLOPT_READFUNCTION,
> put_data_callback);
>
> curl_easy_setopt(curl, CURLOPT_SEEKDATA, &m_data);
> curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION,
> seek_data_callback);
> curl_easy_perform(curl);
> struct put_data_t {
> const char * data_start;
> unsigned read_pos;
> unsigned data_len;
>};
>int seek_data_callback(void *userp, curl_off_t offset, int origin)
>{
> if (!userp)
> return 0;
> put_data_t *userdata = (put_data_t *)userp;
> if (offset > userdata->data_len)
> return CURL_SEEKFUNC_FAIL;
> if (origin == SEEK_SET || origin == SEEK_CUR)
> {
> userdata->read_pos = offset;
> return CURL_SEEKFUNC_OK;
> }
> if (origin == SEEK_END)
> {
> userdata->read_pos = userdata->data_len;
> return CURL_SEEKFUNC_OK;
> }
> return CURL_SEEKFUNC_FAIL;
> }
>>> Dan
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html