cURL / Mailing Lists / curl-library / Single Mail

curl-library

RE: Known Bug #37 - FIXED

From: Joe Mason <jmason_at_rim.com>
Date: Fri, 24 Aug 2012 16:05:52 +0000

> From: curl-library [curl-library-bounces_at_cool.haxx.se] on behalf of Daniel
> Stenberg [daniel_at_haxx.se]
>
> > Thanks. Unfortunately, test case 2032 always fails for me. I suspect it is
> > a
> > timing issue or something. It actually never reaches ConnectionExists()
> > ...
> > I'll try and see if I can figure out what's going on.
>
> I think the test program simply makes too many assumptions about the
> implementation so it decides it has failed before the application has
> completed. I'm not sure I understand the intension of it exactly so I haven't
> been able to fix it

Well, the intent of the test is to make several requests, forcing each to a different connection, with the final one being an NTLM request. Then see what connection the second message of the NTLM request is assigned to. The important options for each request are:

Request 0 - basic auth
easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
easy_setopt(handle, CURLOPT_URL, "http://host:port/20320100");
easy_setopt(handle, CURLOPT_USERPWD, "testuser:testpass");
easy_setopt(handle, CURLOPT_FRESH_CONNECT, 1L);

Request 1 - basic auth
easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
easy_setopt(handle, CURLOPT_URL, "http://host:port/20320100");
easy_setopt(handle, CURLOPT_USERPWD, "testuser:testpass");
easy_setopt(handle, CURLOPT_FRESH_CONNECT, 1L);

Request 2- NTLM auth
easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
easy_setopt(handle, CURLOPT_URL, "http://host:port/20320200");
easy_setopt(handle, CURLOPT_USERPWD, "testuser:testpass");
easy_setopt(handle, CURLOPT_FRESH_CONNECT, 1L);

Since these each have FRESH_CONNECT, they must be assigned to separate connections. We need to find the socket number of the connection they're assigned to. The obvious way to do this is to use curl_easy_getinfo(CURLINFO_LASTSOCKET). But in my testing, this always returns -1 except for NTLM requests, so it's pretty useless.

So what I do is I create request 0 (handle is stored in easy[0]) and then pass it to multi_fdset, which will write a set of sockets to select on in fdread. Since there's only one request, there should only by one socket and it must be the one request 0 is assigned to, so it's stored in sockets[0].

The next time through the select loop, create request 1 (handle stored in easy[1]) and call multi_fdset again. For every socket returned in fdread, look to see if it's in the sockets array - if it's already recorded, it's the socket for request 0 again. If it's not recorded yet, it must be the socket for request 1 since this is a new request.

Then repeat for request 2.

Here's my first simplifying assumption: if the first call to multi_fdset after making a new request doesn't return the socket for that request, I abort immediately with the error "Socket did not open immediately for new handle". This is just because it was easier to code that way - I figure if anyone runs into that error in practice I can add code to keep running the select loop until the new socket is found, before continuing to add more sockets.

Ok, so now we know which socket the first message of each request was assigned to. Now we need to make sure the NTLM type 3 message is sent on the same socket, and not the request 0 or request 1 sockets. Or, more generally, check that all data sent for the NTLM request uses the same socket that was found above for request 2. Since this is an NTLM message, CURLINFO_LASTSOCKET seems to return the right value. So in the write callback for request N, I check the return value of CURLINFO_LASTSOCKET against sockets[N] - if CURLINFO_LASTSOCKET returns -1, this is request 0 or request 1 so there's no need to test. Otherwise, if it does not equal sockets[N], this is request 2 and it's writing on the wrong socket, so fail. (I could just check whether N == 2 instead of CURLINFO_LASTSOCKET != -1, but this code seemed equivalent and simpler to me.)

Aha, I think I see a timing assumption here: if request 2 starts to be written, with CURLINFO_LASTSOCKET returning a value, in multi_perform before multi_fdset is called, then sockets[N] will still be -1 and you'll get the error "Handle 2 started on socket -1 and moved to N". Is that what you're seeing?

Joe

---------------------------------------------------------------------
This transmission (including any attachments) may contain confidential information, privileged material (including material protected by the solicitor-client or other applicable privileges), or constitute non-public information. Any use of this information by anyone other than the intended recipient is prohibited. If you have received this transmission in error, please immediately reply to the sender and delete this information from your system. Use, dissemination, distribution, or reproduction of this transmission by unintended recipients is not authorized and may be unlawful.

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2012-08-24