You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ro...@apache.org on 2007/02/09 21:52:28 UTC
svn commit: r505491 - in
/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http:
conn/RouteDirector.java conn/RouteTracker.java
impl/client/DefaultClientRequestDirector.java
impl/conn/ThreadSafeClientConnManager.java
Author: rolandw
Date: Fri Feb 9 12:52:27 2007
New Revision: 505491
URL: http://svn.apache.org/viewvc?view=rev&rev=505491
Log:
request director uses route director; still missing tunnelling
Added:
jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java (with props)
Modified:
jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteTracker.java
jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java
Added: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java?view=auto&rev=505491
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java (added)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java Fri Feb 9 12:52:27 2007
@@ -0,0 +1,181 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn;
+
+
+
+/**
+ * Provides directions on establishing a route.
+ * Instances of this class compare a planned route with a tracked route
+ * and indicate the next step required.
+ *
+ * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
+ *
+ *
+ * <!-- empty lines to avoid svn diff problems -->
+ * @version $Revision$
+ *
+ * @since 4.0
+ */
+public class RouteDirector {
+
+ /** Indicates that the route can not be established at all. */
+ public final static int UNREACHABLE = -1;
+
+ /** Indicates that the route is complete. */
+ public final static int COMPLETE = 0;
+
+ /** Step: open connection to target. */
+ public final static int CONNECT_TARGET = 1;
+
+ /** Step: open connection to proxy. */
+ public final static int CONNECT_PROXY = 2;
+
+ /** Step: tunnel through proxy. */
+ public final static int CREATE_TUNNEL = 3;
+
+ /** Step: layer protocol (over tunnel). */
+ public final static int LAYER_PROTOCOL = 4;
+
+
+ // public default constructor
+
+
+ /**
+ * Provides the next step.
+ *
+ * @param plan the planned route
+ * @param fact the currently established route, or
+ * <code>null</code> if nothing is established
+ *
+ * @return one of the constants defined in this class, indicating
+ * either the next step to perform, or success, or failure.
+ * 0 is for success, a negative value for failure.
+ */
+ public int nextStep(HttpRoute plan, HttpRoute fact) {
+ if (plan == null) {
+ throw new IllegalArgumentException
+ ("Planned route may not be null.");
+ }
+
+ int step = UNREACHABLE;
+
+ if (fact == null)
+ step = firstStep(plan);
+ else if (plan.getProxyHost() == null)
+ step = directStep(plan, fact);
+ else
+ step = proxiedStep(plan, fact);
+
+ return step;
+
+ } // nextStep
+
+
+ /**
+ * Determines the first step to establish a route.
+ *
+ * @param plan the planned route
+ *
+ * @return the first step
+ */
+ protected int firstStep(HttpRoute plan) {
+
+ return (plan.getProxyHost() == null) ?
+ CONNECT_TARGET : CONNECT_PROXY;
+ }
+
+
+ /**
+ * Determines the next step to establish a direct connection.
+ *
+ * @param plan the planned route
+ * @param fact the currently established route
+ *
+ * @return one of the constants defined in this class, indicating
+ * either the next step to perform, or success, or failure
+ */
+ protected int directStep(HttpRoute plan, HttpRoute fact) {
+
+ if (fact.getProxyHost() != null)
+ return UNREACHABLE;
+ if (!plan.getTargetHost().equals(fact.getTargetHost()))
+ return UNREACHABLE;
+ // If the security values differ, we could now suggest to layer
+ // a secure protocol on the direct connection. Layering on direct
+ // connections has not been supported in HttpClient 3.x, we don't
+ // consider it here until there is a real-life use case for it.
+
+ // yes, this would cover the two checks above as well...
+ if (!plan.equals(fact))
+ return UNREACHABLE;
+
+ return COMPLETE;
+ }
+
+
+ /**
+ * Determines the next step to establish a connection via proxy.
+ *
+ * @param plan the planned route
+ * @param fact the currently established route
+ *
+ * @return one of the constants defined in this class, indicating
+ * either the next step to perform, or success, or failure
+ */
+ protected int proxiedStep(HttpRoute plan, HttpRoute fact) {
+
+ if (fact.getProxyHost() == null)
+ return UNREACHABLE;
+ if (!plan.getProxyHost().equals(fact.getProxyHost()) ||
+ !plan.getTargetHost().equals(fact.getTargetHost()))
+ return UNREACHABLE;
+
+ // proxy and target are the same, check tunnelling and layering
+ if ((fact.isTunnelled() && !plan.isTunnelled()) ||
+ (fact.isLayered() && !plan.isLayered()))
+ return UNREACHABLE;
+
+ if (plan.isTunnelled() && !fact.isTunnelled())
+ return CREATE_TUNNEL;
+ if (plan.isLayered() && !fact.isLayered())
+ return LAYER_PROTOCOL;
+
+ // tunnel and layering are the same, remains to check the security
+ if (plan.isSecure() != fact.isSecure())
+ return UNREACHABLE;
+
+ return COMPLETE;
+ }
+
+
+} // class RouteDirector
Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteDirector.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteTracker.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteTracker.java?view=diff&rev=505491&r1=505490&r2=505491
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteTracker.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/RouteTracker.java Fri Feb 9 12:52:27 2007
@@ -142,7 +142,7 @@
* @param secure <code>true</code> if the route is secure,
* <code>false</code> otherwise
*/
- public final void establishTunnel(boolean secure) {
+ public final void createTunnel(boolean secure) {
if (this.proxyHost == null) {
throw new IllegalStateException("No tunnel without proxy.");
}
Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java?view=diff&rev=505491&r1=505490&r2=505491
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java Fri Feb 9 12:52:27 2007
@@ -39,6 +39,8 @@
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestExecutor;
+import org.apache.http.conn.HttpRoute;
+import org.apache.http.conn.RouteDirector;
import org.apache.http.conn.HostConfiguration;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ManagedClientConnection;
@@ -166,40 +168,117 @@
/**
* Establishes the target route.
*
- * @param route the route to establish
+ * @param hostconf the route to establish
* @param context the context for the request execution
*
* @throws HttpException in case of a problem
* @throws IOException in case of an IO problem
*/
- protected void establishRoute(HostConfiguration route,
+ protected void establishRoute(HostConfiguration hostconf,
HttpContext context)
throws HttpException, IOException {
- //@@@ where do we get the currently established route?
//@@@ how to handle CONNECT requests for tunnelling?
+ //@@@ refuse to send external CONNECT via director? special handling?
- //@@@ for now, let's just deal with connected and not connected
- if ((route.getProxyHost() != null) &&
- !"http".equals(route.getHost().getSchemeName())) {
- //@@@ the actual check should be whether the socket factory
- //@@@ for the target host scheme is a SecureSocketFactory
- throw new UnsupportedOperationException
- ("Currently only plain http via proxy is supported.");
- }
- if (managedConn.isOpen())
- return; // already established
+ //@@@ this check for secure connections is an ugly hack until the
+ //@@@ director is changed to expect HttpRoute instead of HostConfig
+ //@@@ the actual check should be whether the socket factory
+ //@@@ for the target host scheme is a SecureSocketFactory
+ HttpRoute route = null;
+ {
+ final boolean secure =
+ !"http".equals(hostconf.getHost().getSchemeName());
+ if (hostconf.getProxyHost() == null)
+ route = new HttpRoute(hostconf.getHost(),
+ hostconf.getLocalAddress(),
+ secure);
+ else
+ route = new HttpRoute(hostconf.getHost(),
+ hostconf.getLocalAddress(),
+ hostconf.getProxyHost(),
+ secure);
+ System.out.println("@@@ planned: " + route);
+ } //@@@ end of ugly HostConfiguration -> HttpRoute conversion
- //@@@ should the request parameters already be used here?
+
+ //@@@ should the request parameters already be used below?
//@@@ probably yes, but they're not linked yet
- //@@@ will linking above cause problems with linking in reqExec?
+ //@@@ will linking here/above cause problems with linking in reqExec?
//@@@ probably not, because the parent is replaced
//@@@ just make sure we don't link parameters to themselves
- managedConn.open(route, context, defaultParams);
+
+ RouteDirector rowdy = new RouteDirector();
+ int step;
+ do {
+ HttpRoute fact = managedConn.getRoute();
+ System.out.println("@@@ current: " + fact);
+ step = rowdy.nextStep(route, fact);
+ System.out.println("@@@ action => " + step);
+
+ switch (step) {
+
+ case RouteDirector.CONNECT_TARGET:
+ case RouteDirector.CONNECT_PROXY:
+ managedConn.open(hostconf, context, defaultParams);
+ break;
+
+ case RouteDirector.CREATE_TUNNEL:
+ boolean secure = createTunnel(route, context);
+ managedConn.tunnelCreated(secure, defaultParams);
+ break;
+
+ case RouteDirector.LAYER_PROTOCOL:
+ managedConn.layerProtocol(context, defaultParams);
+ break;
+
+ case RouteDirector.UNREACHABLE:
+ throw new IllegalStateException
+ ("Unable to establish route." +
+ "\nplanned = " + route +
+ "\ncurrent = " + fact);
+
+ case RouteDirector.COMPLETE:
+ // do nothing
+ break;
+
+ default:
+ throw new IllegalStateException
+ ("Unknown step indicator "+step+" from RouteDirector.");
+ } // switch
+
+ } while (step > RouteDirector.COMPLETE);
} // establishConnection
+
+ /**
+ * Creates a tunnel.
+ * The connection must be established to the proxy.
+ * A CONNECT request for tunnelling through the proxy
+ * will be created and sent.
+ *
+ * @param route the route to establish
+ * @param context the context for request execution
+ *
+ * @return <code>true</code> if the tunnelled route is secure,
+ * <code>false</code> otherwise.
+ * The implementation here always returns <code>false</code>,
+ * but derived classes may override.
+ *
+ * @throws HttpException in case of a problem
+ * @throws IOException in case of an IO problem
+ */
+ protected boolean createTunnel(HttpRoute route, HttpContext context) {
+ if (true) throw new UnsupportedOperationException("@@@ don't know how to establish a tunnel yet");
+
+ // How to decide on security of the tunnelled connection?
+ // The socket factory knows only about the segment to the proxy.
+ // Even if that is secure, the hop to the target may be insecure.
+ // Leave it to derived classes, consider everything insecure here.
+ return false;
+ }
/**
* Prepares a request for execution.
Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java?view=diff&rev=505491&r1=505490&r2=505491
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java Fri Feb 9 12:52:27 2007
@@ -1211,7 +1211,7 @@
this.connection.update(null, tracker.getTargetHost(),
secure, params);
- this.tracker.establishTunnel(secure);
+ this.tracker.createTunnel(secure);
} // tunnelCreated