Re: Write stream proxy
Re: Write stream proxy
- Subject: Re: Write stream proxy
- From: Mark Pauley <email@hidden>
- Date: Fri, 12 Sep 2008 11:10:37 -0700
Jack, as I said: if you're writing code for Leopard and on, consider
switching your use of CFStreamCreatePairWithSocket to
CFStreamCreateBoundPair. This bypasses the socket subsystem and will
dramatically increase the efficiency of CFNetwork as the number of
simultaneous uploads increases.
On Sep 11, 2008, at 3:35 PM, Philip D. Wasson wrote:
On Sep 11, 2008, at 16:45, Jack Brindle wrote:
Mark's suggestions were also very interesting. I have just a few
comments.
Our application must run on Tiger, so the CFStreamCreateBoundPair
call
Is probably out. But this gets us back to the question as to
whether we
really need a socket pair and what is its purpose. I'm still
chewing on the
rest of his suggestions, they make a lot of sense, and are pretty
close to
what we are doing now. It does get me back to the question as to
why the
pipe breaks when we receive the proxy challenge on the write stream.
We do something similar in one of our applications, although we
don't have to deal with the proxy issues.
You need to use CFReadStreamCreateForStreamedHTTPRequest because you
can't simply give it a complete request since you're reading it or
generating it from multiple location and it can be huge. The result
of that call is a read stream from which you can read the reply. But
you also need to give it a read stream from which the system can
read the data you're sending. (It reads it from you, then writes it
to the server.) Unfortunately, you can't create a custom read
stream, but you can create read and write streams with sockets. If
you have a pair of sockets that form a pipe, you can write into one
end and the mechanism behind
CFReadStreamCreateForStreamedHTTPRequest can read that data out and
send it along.
What we do is use the posix socketpair function to create two
sockets that talk to each other. Then we call
CFStreamCreatePairWithSocket, twice, to create a read stream bound
to one of those sockets and a write stream bound to the other. Then
we can give that read stream to
CFReadStreamCreateForStreamedHTTPRequest and write into the other
end. And it works on Tiger.
Hastily condensed code sample:
int mySockets[2] = { 0, 0 };
CFReadStreamRef theFileReadStream; // CFHTTP reads our content
from this end
CFWriteStreamRef theFileWriteStream; // we write the encoded file
data into this end
socketpair(AF_UNIX, SOCK_STREAM, 0, mySockets);
CFStreamCreatePairWithSocket(NULL, mySockets[0], &theFileReadStream,
NULL);
CFStreamCreatePairWithSocket(NULL, mySockets[1], NULL,
&theFileWriteStream);
CFReadStreamSetProperty(theFileReadStream,
kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFWriteStreamSetProperty(theFileWriteStream,
kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
CFStreamClientContext myClientContext = {0, this, NULL, NULL, NULL};
CFWriteStreamSetClient(theFileWriteStream,
kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes |
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
(CFWriteStreamClientCallBack)MyWriteStreamClientCallBack,
&myClientContext);
CFWriteStreamScheduleWithRunLoop(theFileWriteStream,
CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFWriteStreamOpen(theFileWriteStream);
CFReadStreamOpen(theFileReadStream);
CFReadStreamRef theReplyStream =
CFReadStreamCreateForStreamedHTTPRequest(
kCFAllocatorDefault, myRequestCreatedElsewhere,
theFileReadStream);
// theReplyStream has Retained theFileReadStream so we can release
and forget about it.
CFRelease(theFileReadStream);
I would expect that if there is some problem with the upload, you'll
hear about it in the callback for the read stream created for the
request (theReplyStream in my example above). If that happens, it
probably closes early the read stream it's reading content from
(theFileReadStream above), which could cause an error in the write
stream that's attached to it (theFileWriteStream above). I would
think that if you get any fatal errors in theFileWriteStream's
callback, you can ignore them (after giving up trying to write) if
your reply stream is dealing with something more interesting.
I hope that helps some and didn't cause more confusion.
----------------------------------------
Philip D. Wasson
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
_Mark
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