• 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
More CF HTTP streams (Re: CFReadStreamGetBuffer doesn't work for HTTP streams?)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

More CF HTTP streams (Re: CFReadStreamGetBuffer doesn't work for HTTP streams?)


  • Subject: More CF HTTP streams (Re: CFReadStreamGetBuffer doesn't work for HTTP streams?)
  • From: Tommy Knowlton <email@hidden>
  • Date: Wed, 10 Jul 2002 00:34:31 -0600

Thanks, Becky. That makes good sense, and indeed, I have abandoned trying to use CFReadStreamGetBuffer for CFHTTPReadStreams.

Now for another CFNetwork question: how does CFHTTPMessageAddAuthentication() work? In my readStreamCallback function (asynchronous reading on the CFRunLoop), I have the following code:

// other cases above might 'goto END_OF_STREAM' under certain circumstances
END_OF_STREAM:
case kCFStreamEventEndEncountered:
// capture the response headers, close the stream (unregister from the runloop and release the stream).
// 'handle' is an 'ADURLHandle *', my personal HTTP handling subclass of 'NSURLHandle'
if ([handle tryLockStreamLock]) // sends '-tryLock' to '_streamLock', an 'NSLock *'
{
int statusCode = 0;
NSString *statusLine = nil;
CFHTTPMessageRef responseHeaders =
(CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);

if (responseHeaders != NULL)
{
if (CFHTTPMessageIsHeaderComplete(responseHeaders))
{
// store the properties obtained from the response header, into the ADURLHandle's dictionary
[handle writeProperty:[(NSDictionary *)CFHTTPMessageCopyAllHeaderFields(responseHeaders) autorelease]
forKey:kADURLHandleHTTPResponseHeadersKey];

statusCode = CFHTTPMessageGetResponseStatusCode(responseHeaders);
[handle writeProperty:[NSNumber numberWithInt:statusCode]
forKey:kADURLHandleHTTPResponseStatusCodeKey];

statusLine = [(NSString *)CFHTTPMessageCopyResponseStatusLine(responseHeaders) autorelease];
[handle writeProperty:statusLine
forKey:kADURLHandleHTTPResponseStatusLineKey];
}
// might not be done with 'responseHeaders', but ref count correctly.
[(id)responseHeaders autorelease];
}

[handle unlockStreamLock];

[handle closeStream]; // close, unregister, release, and nullify the CFReadStreamRef
// doing all that might not be the death of the current RunLoop,
// because we might attach another stream, created below.

if (//(statusCode >= 200) &&
(statusCode < 400)) // I know, I've got yet to deal with 3xx redirect.
{
[handle didLoadBytes:nil
loadComplete:YES];
}
else if ((statusCode == 401) ||
(statusCode == 407))
{
// retry the request...
// as CFNetwork documentation says, close the stream (done),
// followed by 'CFHTTPMessageAddAuthentication' with the original
// messageRef, followed by create and open a new stream with the same
// messageRef (that was modified by 'CFHTTPMessageAddAuthentication').
NSCAssert((CFHTTPMessageAddAuthentication([handle message],
responseHeaders,
CFSTR("me"),
CFSTR("myProxyPassword"),
NULL,
(statusCode == 407))),
@"Failed to add auth to my message.");

// THE ASSERTION ALWAYS FAILS. WHY?

[handle createAndOpenStream]; // 'CFReadStreamCreateForHTTPRequest', ask it to
// 'CFHTTPReadStreamSetRedirectsAutomatically',
// attach it to the RunLoop, open the stream. Uses _streamLock.
}
else
{
[handle backgroundLoadDidFailWithReason:statusLine];
}
}
break;

Hopefully that's not too hard to follow. The point is, I'm implementing an NSURLHandle subclass by using CFNetwork. The advantages that this gives me are 1) auto-proxy-auth behavior (if I can get the thing above to work) and 2) auto-redirect behavior. Which also I have not gotten to work for me. Keep reading, if you please.

My question, of course, is "why does the assertion fail?"

I believe that I'm using the 'CFHTTPMessageAddAuthentication' call correctly as explained in CFNetwork.pdf in my /Developer/Documentation/Networking/CFNetwork folder. It's dated October 2001, which is as recent as what's on Apple's website. (Respondent performs a quick double check to verify that assertion).

http://developer.apple.com/techpubs/macosx/Networking/CFNetwork/CFNetwork.
pdf is indeed dated October 2001.

Has anyone seen this API in action? Am I passing an incorrect second argument? What am I supposed to pass for the second argument?

Also, 'CFHTTPReadStreamSetRedirectsAutomatically(_stream, YES)' seems not to work for a stream that is read asynchronously (I haven't yet tried it while reading the stream in a poll-loop). I wonder if anyone out there has successfully used that API, who can offer me some advice how to see it win? I wonder if the fact I'm trying to POST instead of GET hurts my chances? Basically, the design of the web site is such that a well-formed POST results in a redirect response.

I'm grateful to anybody who's willing to offer me any suggestions. Especially if your suggestion works! :^)

On Monday, July 8, 2002, at 11:09 PM, macnetworkprog-
email@hidden wrote:

Message: 12
Date: Mon, 8 Jul 2002 17:07:08 -0700
Subject: Re: CFReadStreamGetBuffer doesn't work for HTTP streams?
Cc: email@hidden
To: Tommy Knowlton <email@hidden>
From: Becky Willrich <email@hidden>

CFReadStreamGetBuffer is an optional optimization a la
CFStringGetCStringPtr - it will only return non-NULL if the underlying
stream supports it and if a convenient buffer is on-hand. If you want
to use it, you should always have code that will fall-back to calling
CFReadStreamRead() (which every read stream must support):

// I'm glossing over the details for managing the length of the
buffer...
if (myBuf = CFReadStreamGetBuffer(stream)) {
handleBuffer(myBuf);
} else {
// GetBuffer not supported for this stream
UInt8 buf[BUFSIZE];
CFReadStreamRead(stream, buf, BUFSIZE);
handleBuffer(buf);
}

REW


On Friday, July 5, 2002, at 09:08 AM, Tommy Knowlton wrote:

On my 10.1.5 development system, I seem to be experiencing that
CFReadStreamGetBuffer always writes 0 into its out parameter,
numBytesRead. I've tried negative, zero, and positive values for the
maxBytesToRead in parameter, all with the same result. I am guarding
my callback's kCFStreamEventHasBytesAvailable case with a call to
CFReadStreamHasBytesAvailable (because I believe this is a low-cost
way to guard against other bugs in CFNetwork), so I "know" there are
bytes there before I call CFReadStreamGetBuffer.

Does anyone know any "tricks" to correctly using CFReadStreamGetBytes?

Kind regards,
--Tk!
_______________________________________________
macnetworkprog mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/macnetworkprog
Do not post admin requests to the list. They will be ignored.

--__--__--



Kind regards,
--
Tommy Knowlton
_______________________________________________
macnetworkprog mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/macnetworkprog
Do not post admin requests to the list. They will be ignored.

  • Prev by Date: Re: send on unconnected socket = crash (TCP sockets on X)
  • Next by Date: Re: OTIoctl Question
  • Previous by thread: Re: send on unconnected socket = crash (TCP sockets on X)
  • Next by thread: Debuging stack varialbe overwrite on MacOS9
  • Index(es):
    • Date
    • Thread