cURL / Mailing Lists / curl-library / Single Mail

curl-library

RE: libcurl and Microsoft IIS FTP server

From: Jeff Vincent <Jeff_Vincent_at_symantec.com>
Date: Fri, 7 Dec 2007 08:53:02 -0700

My comments inline:

 

> -----Original Message-----

> From: curl-library-bounces_at_cool.haxx.se [mailto:curl-library-

> bounces_at_cool.haxx.se] On Behalf Of Daniel Stenberg

> Sent: Thursday, December 06, 2007 4:40 AM

> To: libcurl development

> Subject: RE: libcurl and Microsoft IIS FTP server

>

> On Thu, 6 Dec 2007, Jeff Vincent wrote:

>

> > We are now seeing a similar issue when uploading to IIS6/Win2K3.

>

> And this is still only libcurl that shows this behaviour? What libcurl

> version

> are you using now? Have you compared the ftp command sequence with a

> working

> ftp client with the particular sequence that libcurl uses?

>

 

We are using version 7.16.3 I believe.

 

I've thus far used the MS FTP Command-line client which works fine and
appears to do the same sequence as libcurl. I tried running a
precompiled version of the curl client for windows but I'm still working
through issues.

 

In our implementation, libcurl works great against FileZilla and vsftpd
on openSuse 10.3. IIS works fine for most other files. There is a
subset that causes this condition to manifest itself. If we add a delay
between completing the file transfer and cleaning up the curl handle,
the destination file is completely written.

 

However, the packet trace still doesn't show the complete 226/QUIT/221
sequence. If we remove the delay and certain files are encountered, we
see the connection being RST by the server before it sends any 226
responses and the file is truncated. If we introduce a delay, the trace
does show a 226 response from the server, but the server then
immediately resets the connection and no QUIT/221 sequence is seen.

 

> > At the end of *some* file transfers we do not see the typical

> 226/QUIT/221

> > message sequence, but a similar connection RST issue and the
resulting

> file

> > is truncated. It doesn't happen on all files, but it happens

> consistently

> > on files of certain sizes.

>

> libcurl waits for the 226 response when it still thinks everything is

> fine, it

> doesn't if it already has deemed the transfer to have failed. See

> Curl_ftp_done() in lib/ftp.c.

>

 

I don't believe that curl ever thinks the transfer has failed in any of
the failure cases. Curl always reports the correct byte count sent to
the server. What we need is some guidance in trying to determine why
curl reports success when there is no 226 in the packet trace or when we
do see the 226, there is no QUIT/221 sequence.

 

> > Rob Lievaart suggested a scenario where a command connection request
may

> be

> > getting to the server before the data connection upload/closure
sequence

> > completes.

>

> I don't see how this can happen, and if it does happen it is a major

> server

> bug that I can't see what a client can do to avoid.

>

 

I won't deny the server implementation may have issues, but when we
introduce a delay between transfer and cleanup and it works so it seems
there is a scenario we might be able to detect and work around.

 

Responding to Rob also, I can see that the issue he described was file
size related and how the CURLOPT_INFILESIZE* options were (mis)used. We
aren't using that option. However, the timing issue even now still
seems related.

 

> > Though we don't see cURL checking SIZE at the end of the transfer,
we

> felt

> > that there is a good chance that we are seeing a similar issue.

>

> No it doesn't check SIZE, why would it? libcurl knows how much data it

> sent

> and if it sent the entire file without problems, it just needs to wait
for

> the

> 226 (or 250) to know the file transfer was fine.

>

 

Makes sense.

 

> > In the case that seems to always work, we keep the curl handle
around to

> be

> > reused, thus the cleanup is delayed significantly after the transfer

> > completes. In the failure cases, if we introduce a hard-coded sleep

> after

> > the data connection is closed but before curl is cleaned up, all
file

> > transfers succeed!!

>

> This somehow implies that Curl_ftp_done() is buggy or that its 60
second

> timeout is too short?

>

 

I can only offer observation that something is wrong and what we did to
"work around" the issue did in fact help. The "work around" was only an
attempt at explaining why the connection is being reset as opposed to a
correct 226/QUIT/221 message sequence.

 

> > THE THEORY: It seems that if we close the data connection and clean
up

> curl

> > too quickly, the MS FTP server is still processing or flushing the
last

> bits

> > of the data stream to disk when the command connection is closed.
The

> > server thinks there was an error so it sends a RST and aborts,
causing

> the

> > file to be truncated, thought curl thinks everything is happy.

>

> I don't see how this theory matches how the code is written-

>

> First, the data connection is *OF COURSE* closed when the transfer is

> complete

> as that's how a client signals that the transfer is complete. There's
no

> other

> way to do this - it just can't be wrong. See RFC959.

>

> Then, libcurl _does_ wait for the server to tell that the operation is

> fine

> (or not) before it continues and if the server does tell it things are

> fine

> before it is then the server is buggy. If the server doesn't say that
and

> libcurl still continues (but the 226 comes after yet a while) then our

> hardcoded 60 second timeout in Curl_ftp_done() is too strict and
should be

> prolonged.

 

Again, I can only say that my observations suggest that there is a
scenario when either lib curl is not waiting for the 226 or we are not
cleaning up correctly whether due to a poor server implementation or to
an obscure bug or an error on our part.

 

The 60 second timeout is also not being invoked because the file
transfer for a 1.103 MB file is taking less than a second to complete,
even in the failure case.

 

In the packet traces for the files that fail, if we cleanup the curl
handle as soon as the file transfer is complete, we never see the 226 on
the wire, only a RST. If we wait before cleaning up, the 226 is seen.
Again, it was a theory. If there is a better theory then I'm up for
further enlightenment that can help us make file transfers to IIS
servers more reliable.

 

>

> > THE BIG QUESTION: What is the mechanism to watch and wait for the
226 -

> > Transfer Complete message from the server before initiating the
cleanup?

>

> libcurl always does that.

>

 

Again, curl reports success, we clean up, packet trace shows server
sending a RST but no 226 on the wire and curl is not waiting any
significant time at all, but file is short a few hundred bytes.

 

If we wait before we clean up, curl reports success, 226 is shown as
being sent from the server and the file is complete w/ no truncation.
However, I have noticed that there is still a RST and the client never
issues the QUIT.

 

> > I can not find any examples/docs of how this might be done as it
seems

> > that once initiated, curl handles everything internally and never

> > exposes the 226 or other server messages.

>

> libcurl exposes the 226 response the same way as all other respones,
in

> header

> callbacks. All this that you talk about are details that just should
work,

> with no particular treatment required from an application so I don't
see

> why

> any particular exposure of the 226 is necessary.

>

 

Again, my theories could be wrong and I agree we shouldn't have to worry
about it, but it isn't working in this case and we are trying to
determine why.

 

Where can we look, set breakpoints, what CURL options to set conditions
we can poll for? The initial thought was that if we can watch for the
226 ourselves, we can then know it's safe to clean up.

 

Does curl use separate threads to process responses from the server?
Would it be possible to

 

> > Any suggestions/helps/links are much appreciated!! Thanks.

>

> Oh, and please don't top-post, it makes it totally confusing to read

> quotes in

> mails in mixed (or just reversed) order.

>

> --

> Commercial curl and libcurl Technical Support:
http://haxx.se/curl.html
Received on 2007-12-07