private bool TunnelThroughProxy(Uri proxy, HttpWebRequest originalRequest, bool async) {
GlobalLog.Enter("Connection#" + ValidationHelper.HashString(this) + "::TunnelThroughProxy", "proxy="+proxy+", async="+async+", originalRequest #"+ValidationHelper.HashString(originalRequest));
bool result = false;
HttpWebRequest connectRequest = null;
HttpWebResponse connectResponse = null;
try {
connectRequest = new HttpWebRequest(
proxy,
originalRequest.Address,
// new Uri("https://" + originalRequest.Address.GetParts(UriComponents.HostAndPort, UriFormat.UriEscaped)),
originalRequest
);
connectRequest.Credentials = originalRequest.InternalProxy == null ? null : originalRequest.InternalProxy.Credentials;
connectRequest.InternalProxy = null;
connectRequest.PreAuthenticate = true;
if(async){
TunnelStateObject o = new TunnelStateObject(originalRequest, this);
IAsyncResult asyncResult = connectRequest.BeginGetResponse(m_TunnelCallback, o);
if(!asyncResult.CompletedSynchronously){
GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::TunnelThroughProxy completed asynchronously", true);
return true;
}
connectResponse = (HttpWebResponse)connectRequest.EndGetResponse(asyncResult);
}
else{
connectResponse = (HttpWebResponse)connectRequest.GetResponse();
}
ConnectStream connectStream = (ConnectStream)connectResponse.GetResponseStream();
// this stream will be used as the real stream for TlsStream
NetworkStream = new NetworkStream(connectStream.Connection.NetworkStream, true);
// This will orphan the original connect stream now owned by tunnelStream
connectStream.Connection.NetworkStream.ConvertToNotSocketOwner();
result = true;
}
catch (Exception exception) {
if (m_InnerException == null)
m_InnerException = exception;
GlobalLog.Print("Connection#" + ValidationHelper.HashString(this) + "::TunnelThroughProxy() exception occurred: " + exception);
}
GlobalLog.Leave("Connection#" + ValidationHelper.HashString(this) + "::TunnelThroughProxy", result);
return result;
}