/// <summary>Establishes the target route.</summary> /// <remarks>Establishes the target route.</remarks> /// <exception cref="Apache.Http.HttpException"></exception> /// <exception cref="System.IO.IOException"></exception> internal virtual void EstablishRoute(AuthState proxyAuthState, HttpClientConnection managedConn, HttpRoute route, IHttpRequest request, HttpClientContext context) { RequestConfig config = context.GetRequestConfig(); int timeout = config.GetConnectTimeout(); RouteTracker tracker = new RouteTracker(route); int step; do { HttpRoute fact = tracker.ToRoute(); step = this.routeDirector.NextStep(route, fact); switch (step) { case HttpRouteDirector.ConnectTarget: { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); tracker.ConnectTarget(route.IsSecure()); break; } case HttpRouteDirector.ConnectProxy: { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); HttpHost proxy = route.GetProxyHost(); tracker.ConnectProxy(proxy, false); break; } case HttpRouteDirector.TunnelTarget: { bool secure = CreateTunnelToTarget(proxyAuthState, managedConn, route, request, context ); this.log.Debug("Tunnel to target created."); tracker.TunnelTarget(secure); break; } case HttpRouteDirector.TunnelProxy: { // The most simple example for this case is a proxy chain // of two proxies, where P1 must be tunnelled to P2. // route: Source -> P1 -> P2 -> Target (3 hops) // fact: Source -> P1 -> Target (2 hops) int hop = fact.GetHopCount() - 1; // the hop to establish bool secure = CreateTunnelToProxy(route, hop, context); this.log.Debug("Tunnel to proxy created."); tracker.TunnelProxy(route.GetHopTarget(hop), secure); break; } case HttpRouteDirector.LayerProtocol: { this.connManager.Upgrade(managedConn, route, context); tracker.LayerProtocol(route.IsSecure()); break; } case HttpRouteDirector.Unreachable: { throw new HttpException("Unable to establish route: " + "planned = " + route + "; current = " + fact); } case HttpRouteDirector.Complete: { this.connManager.RouteComplete(managedConn, route, context); break; } default: { throw new InvalidOperationException("Unknown step indicator " + step + " from RouteDirector." ); } } }while (step > HttpRouteDirector.Complete); }