• 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: Write stream proxy
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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
  • Follow-Ups:
    • Re: Write stream proxy
      • From: Jack Brindle <email@hidden>
References: 
 >Re: Write stream proxy (From: Jack Brindle <email@hidden>)
 >Re: Write stream proxy (From: "Philip D. Wasson" <email@hidden>)

  • Prev by Date: Re: Data sending problem
  • Next by Date: Re: Write stream proxy
  • Previous by thread: Re: Write stream proxy
  • Next by thread: Re: Write stream proxy
  • Index(es):
    • Date
    • Thread