cURL / Mailing Lists / curl-users / Single Mail

curl-users

socket error with NTLM auth proxy and multi interface

From: Pingzhong Li <PLi_at_fiberlink.com>
Date: Mon, 3 Oct 2011 18:11:37 -0400

Hi, expert,

We are using the libcurl for the http communication. We are using the multi interface and there is only 1 easy interface wrapped inside the multi interface. Here are steps we did:

1. We first do a connect with easy interface to make sure we could connect with server

2. we then put the easy interface inside a multi interface

3. Then we would send out the request and we do make sure all the data is send out before we start checking if we received any data or not

4. On the receive side, we would use a function to check if there is any data or not to receive by using select on socket and then we could call the curl_multi_perform.

The code works fine on direct connection, proxy without authentication and basic and digest proxy. However it doesn't work for NTLM proxy. We are keeping get the socket error on select call.

Here is the code that we are checking for data available. It is used for both send and receive to make sure that socket is available for read or write:
      Int dataAvailable(int iTimeout = -1)
      {

            struct timeval timeout;
            timeout.tv_sec = 1;
            timeout.tv_usec = 0;
            int maxfd = -1;
            long curl_timeo = -1;
            CURLMcode mres;

            fd_set fdread;
            fd_set fdwrite;
            fd_set fdexcep;

            FD_ZERO(&fdread);
            FD_ZERO(&fdwrite);
            FD_ZERO(&fdexcep);
            if(iTimeout > 0)
            {
            timeout.tv_sec = iTimeout / 1000000;
            timeout.tv_usec = iTimeout % 1000000;
            }
            mres = curl_multi_timeout(m_curlMultiHandle, &curl_timeo);
            if(mres != CURLM_OK)
            {
                  //some error logging here
                  return -1;
            }
            if(curl_timeo >= 0)
            {
              timeout.tv_sec = curl_timeo / 1000;
              if(timeout.tv_sec > 1)
                  timeout.tv_sec = 1;
              else
                  timeout.tv_usec = (curl_timeo % 1000) * 1000;
            }
            mres = curl_multi_fdset(m_curlMultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd);
            if(mres != CURLM_OK)
            {
                  //some error logging here
                  return -1;
            }

           int nRet = 0;

            nRet = (select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout) );
            if(nRet == SOCKET_ERROR)
            {

//log the socket last error ::WSAGetLastError() );
//it could be 10038 or 10022.

            }

            return nRet;
      }

This method is called by both send and recv. The problem for us is that we would get the SOCKET_ERROR on select method for receiving. The last socket error could either 10038 (not a socket) or 10022 (invalid arguments).

Here is what send looks like:
      bool send( const std::string& data )
      {

            CURLMcode mres;
            m_debugFileStruct.m_uploadSize = 0;
            m_iStillRunning = -1;

            //setup libcurl easy interface and mulit interface and call back for receiving the http resonse
            mres = curl_multi_perform(m_curlMultiHandle, &m_iStillRunning);
            if(mres != CURLM_OK)
            {
                  return false;
            }
            while(m_iStillRunning)
            {

                  //here we are checking if all the data is send out or not
                  if( (int)m_debugFileStruct.m_uploadSize == (int)data.length())
                  {
                        break;
                  }

                  if(dataAvailable(-1, szLogHeader) >= 0)
                  {
                        mres = curl_multi_perform(m_curlMultiHandle, &m_iStillRunning);
                  }
                  else
                  {
                        return false;
                  }
            }
            return true;
      }

Here is recv side:

int recv( int timeout )
      {
            CURLMcode mres ;
            CURLMsg *msg; /* for picking up messages with the transfer status */
            int msgs_left; /* how many messages are left */

            //here mres is CURLM_OK from logs
            mres = curl_multi_perform(m_curlMultiHandle, &m_iStillRunning);

            int nDataAvail = dataAvailable(timeout);
            if(nDataAvail == 0)
            {

                  return NO_DATA;
            }
            else if(nDataAvail < 0)
            {
                  return ERROR;
            }
            mres = curl_multi_perform(m_curlMultiHandle, &m_iStillRunning);
            if(mres != CURLM_OK)
            {
                  Return ERROR
            }
            i = 0;
            while(m_iStillRunning && i < 2 )
            {
                  i++;
                  nDataAvail = dataAvailable(timeout);
                  if(nDataAvail > 0 )
                  {
                              mres = curl_multi_perform(m_curlMultiHandle, &m_iStillRunning);
                              if(mres != CURLM_OK)
                              {
                                    Return ERROR; }
                  }
                  else if (nDataAvail == 0)
                  {
                        break;
                  }
                  else
                  {
                        //error here
                        Return ERROR;
                  }
            }

      }

I originally thought I could ignore the socket error, however the iStillRunning got from curl_multi_perform is still 1 and from logging, our call back buffer already has all the bytes of response (which mean 750 bytes), here is from libcurl verbose logging:
[0111-09-03 17:35:49] } [data not shown]
[0111-09-03 17:35:51] < HTTP/1.1 200 OK
[0111-09-03 17:35:51] < Date: Mon, 03 Oct 2011 21:35:50 GMT
[0111-09-03 17:35:51] < Content-Length: 750
[0111-09-03 17:35:51] < Content-Type: text/xml; charset=utf-8
[0111-09-03 17:35:51] < Access-Control-Allow-Origin: *
[0111-09-03 17:35:51] < Access-Control-Allow-Headers: Content-Type
[0111-09-03 17:35:51] * Keep sending data to get tossed away!

There is 200 http status code response, however there is one line said:
* Keep sending data to get tossed away!.

From the source code, looks like that logging will only appear for NTLM auth proxy.

Any idea what's wrong here? Could anyone shed some lights on this?

Thanks,
Pingzhong

________________________________
Fiberlink Disclaimer: The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-users
FAQ: http://curl.haxx.se/docs/faq.html
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2011-10-04