Re: Write stream proxy
Re: Write stream proxy
- Subject: Re: Write stream proxy
- From: Jack Brindle <email@hidden>
- Date: Fri, 12 Sep 2008 14:31:39 -0700
- Thread-topic: Write stream proxy
Now I can be more specific about the problems I have been having with proxy
support in the transfer application I am working on. The code is very
similar to the stub Philip showed (below). It seems important to remember
that the reply stream points at one server while the write stream points at
another. The reply stream authorizes with talks through the proxy just fine,
then the write stream is handed the task to send the file. I see the first
block of data being written to the write stream, then get a
kCFStreamEventCanAcceptBytes event, then very quickly an error through the
kCFStreamEventErrorOccurred event. The error is domain: 1, error 32, which
is a broken pipe. After that I see a kCFStreamEventHasBytesAvailable event
on the reply stream. I believe that the proxy is communicating its challenge
back to the Mac on the write stream but finds that no one is actually
listening, or set up to listen, thus the broken pipe. It is rather
interesting that the data coming in the reply stream is a challenge, and may
indeed be the challenge from the proxy that we need to handle. But by the
time we get it the error has already occurred.
Could it be that the write stream is not picking up on the initial
authentication that was set up for the reply stream? Does the different URL
matter here? Suggestions?
Jack Brindle
YouSendIt, Inc.
> On Sep 11, 2008, at 3:35 PM, Philip D. Wasson wrote:
>> 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