• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: URLAccess Stalls
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: URLAccess Stalls


  • Subject: Re: URLAccess Stalls
  • From: Jim Luther <email@hidden>
  • Date: Thu, 5 Jan 2006 14:21:12 -0800

Zack,

I don't think this is a bug.

First, it looks like you are using tcpflow to look at the packets. tcpflow throws an extra blank line into it's output between packets. That's the extra "\r\n between the header and body of a POST request" you are seeing.

Second, an HTTP message can be split into multiple tcp packets and it will not make any difference to the contents of the data stream. It's just slightly more overhead for short messages (messages that would fit into one tcp packet) because the message is sent in two packets instead of one.

CFNetwork's HTTP code sends the message headers and message body to socket as two separate writes -- that's why you end up with two tcp packets. Before Tiger, this could cause performance problems because "Nagel's Algorithm" was enabled by default on the sockets CFNetwork used for HTTP transactions (see TCP/IP Illustrated, Volume 1, section 19.4 for a full description of Nagel's Algorithm) -- That could cause a delay between the packet with the message headers and the packet with the message body. In Tiger, we disabled "Nagel's Algorithm" on the sockets used for HTTP (and FTP) by setting the TCP_NODELAY socket option on sockets, so the packets are now sent back to back with no delays. We've got a Radar performance bug open <rdar://problem/3864399> "CFHTTP should write small bodies and headers in one write call" to improve that behavior in the future.

- Jim Luther

On Jan 5, 2006, at 1:34 PM, email@hidden wrote:

On Dec 16, 2005, at 7:24 AM, Peter Sichel wrote:

On 12/14/05, Marc Krochmal wrote:

There were other reasons to deprecate URL Access besides the three I
listed.  Those were just some examples.

Did anyone at Apple ever resolve why URL Access broke in 10.4 ???

It's all very nice to deprecate older technology, but you still have to
figure out what broke in case there's a more serious underlying bug in
10.4 . Some of my customers are reporting seemingly random stalls under
10.4 in Distributed Objects messaging that has worked for ages.

Hi all, I finally bit the bullet and added code in my http wrapper class to use CFNetwork, CFHTTPMessage and CFReadStream. It took half a day of research to learn how it all works, and then half a day to import the CoreFoundation and CoreServices bundles for the constants and functions needed, since I am using CodeWarrior and Carbon. It took another full day, noon to 2 am, to fill in all of the OS X sections of my class. It's taken another day of testing so far to get it working, but I am not quite there yet because I have uncovered a bug in CFNetwork that I am not sure Apple is aware of. So anyway, figure on at least 3 full days to convert your URLAccess code to CFNetwork, which is not too bad I guess, and CFNetwork is MUCH faster than URLAccess. BTW https is working fine, it's all working quite well actually, except:


***CFNetwork either inserts an extra \r\n between the header and body of a POST request, or is sending the header and body in 2 steps***

So I am at the end of the line because none of the forms on my site work, and I dunno where to go from here unless someone can help me solve this bug. Here are all of the gory details:

-------------------------------------------------------------

I build the request by calling these lines:

////////////////////
CFHTTPMessageRef	messageRef
char			requestBody = "user=test&pass=test";
CFDataRef		dataRef;

messageRef = CFHTTPMessageCreateRequest( kCFAllocatorDefault, CFSTR ("POST"), CFSTR("http://mysite.com";), kCFHTTPVersion1_1 );
dataRef = CFDataCreateWithBytesNoCopy( nil, (unsigned char*) requestBody , strlen( requestBody ), kCFAllocatorNull );
CFHTTPMessageSetBody( messageRef, dataRef );
readStreamRef = CFReadStreamCreateForHTTPRequest ( kCFAllocatorDefault, messageRef );
CFReadStreamOpen( readStreamRef );


// then later:

header = nil;
while( !header )
{
CFReadStreamHasBytesAvailable( readStreamRef ); // tickle the download to give it time to load header

messageRef = CFReadStreamCopyProperty( readStreamRef, kCFStreamPropertyHTTPResponseHeader );
if( messageRef )
{
dataRef = CFHTTPMessageCopySerializedMessage( messageRef ); // messageRef only contains the header here

if( dataRef )
{
size = CFDataGetLength( dataRef );
header = CFDataGetBytePtr( dataRef ); // header is received
}
}
}
////////////////////


I receive the header from the server just fine, but my authentication failed because the POST was not sent correctly. Here is a packet trace to my website, using:

sudo /usr/local/bin/tcpflow -i en0 -c port 80

I have cleaned it up a bit and replaced the site name and IP address of the site with mysite.com and 1.2.3.4. I am sending a POST request with a body of:

user=test&pass=test

Which emulates the form I use on the website. Here is the complete transaction:

////////////////////
POST /index.php HTTP/1.1
User-Agent: CFNetwork/4.0
Content-Length: 19
Connection: close
Host: mysite.com


192.168.000.002.55331-001.002.003.004.00080: user=test&pass=test
001.002.003.004.00080-192.168.000.002.55331: HTTP/1.1 200 OK
Date: Thu, 05 Jan 2006 20:49:49 GMT
Server: Apache/2.0.54 (Debian GNU/Linux) PHP/4.3.10-16 mod_ssl/ 2.0.54 OpenSSL/0.9.7e
X-Powered-By: PHP/4.3.10-16
Content-Length: 3
Connection: close
Content-Type: text/html


***
////////////////////

The "***" at the end is a place where I call this in php on the server:

<?php echo '*'.$_POST['user'].'*'.$_POST['pass'].'*'."\n" ?>

In this case, php is not getting the username or password. The reason this fails is because the lines that say:

////////////////////
Host: mysite.com


192.168.000.002.55331-001.002.003.004.00080: user=test&pass=test 001.002.003.004.00080-192.168.000.002.55331: HTTP/1.1 200 OK ...

***
////////////////////

Are wrong. For some reason CFReadStream has either sent the request in 2 parts, or has added an extra \r\n to the request between mysite.com and user=test&pass=test (the header and body, respectively) in the first trace. It should read:

////////////////////
Host: mysite.com

user=test&pass=test
001.002.003.004.00080-192.168.000.002.55331: HTTP/1.1 200 OK
...

*test*test*
////////////////////

Notice there is one less \r\n in the second trace, which is correct. This is a pretty catastrophic error, and I am either doing something completely wrong, or I have no idea how CFNetwork can use web forms with POST. Sorry for such a verbose letter. Does anyone know what is going on, or how to fix this? Thanx,

---------------------------------------------------------------------- --
Zack Morris Z Sculpt Entertainment This Space
email@hidden http://www.zsculpt.com For Rent
---------------------------------------------------------------------- --
If the doors of perception were cleansed, everything would appear to man
as it is, infinite. -William Blake, The Marriage of Heaven and Hell


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40apple.com


This email sent to email@hidden

_______________________________________________ Do not post admin requests to the list. They will be ignored. Macnetworkprog mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
References: 
 >Re: URLAccess Stalls (From: email@hidden)

  • Prev by Date: Re: URLAccess Stalls
  • Next by Date: Re: URLAccess Stalls
  • Previous by thread: Re: URLAccess Stalls
  • Next by thread: Re: URLAccess Stalls
  • Index(es):
    • Date
    • Thread