mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-10 02:08:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
181
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java
vendored
Normal file
181
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.conn.routing;
|
||||
|
||||
import ch.boye.httpclientandroidlib.annotation.Immutable;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
|
||||
/**
|
||||
* Basic {@link HttpRouteDirector} implementation.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@Immutable
|
||||
public class BasicRouteDirector implements HttpRouteDirector {
|
||||
|
||||
/**
|
||||
* 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(final RouteInfo plan, final RouteInfo fact) {
|
||||
Args.notNull(plan, "Planned route");
|
||||
|
||||
int step = UNREACHABLE;
|
||||
|
||||
if ((fact == null) || (fact.getHopCount() < 1)) {
|
||||
step = firstStep(plan);
|
||||
} else if (plan.getHopCount() > 1) {
|
||||
step = proxiedStep(plan, fact);
|
||||
} else {
|
||||
step = directStep(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(final RouteInfo plan) {
|
||||
|
||||
return (plan.getHopCount() > 1) ?
|
||||
CONNECT_PROXY : CONNECT_TARGET;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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(final RouteInfo plan, final RouteInfo fact) {
|
||||
|
||||
if (fact.getHopCount() > 1) {
|
||||
return UNREACHABLE;
|
||||
}
|
||||
if (!plan.getTargetHost().equals(fact.getTargetHost()))
|
||||
{
|
||||
return UNREACHABLE;
|
||||
// If the security is too low, 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.
|
||||
}
|
||||
|
||||
// Should we tolerate if security is better than planned?
|
||||
// (plan.isSecure() && !fact.isSecure())
|
||||
if (plan.isSecure() != fact.isSecure()) {
|
||||
return UNREACHABLE;
|
||||
}
|
||||
|
||||
// Local address has to match only if the plan specifies one.
|
||||
if ((plan.getLocalAddress() != null) &&
|
||||
!plan.getLocalAddress().equals(fact.getLocalAddress())
|
||||
) {
|
||||
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(final RouteInfo plan, final RouteInfo fact) {
|
||||
|
||||
if (fact.getHopCount() <= 1) {
|
||||
return UNREACHABLE;
|
||||
}
|
||||
if (!plan.getTargetHost().equals(fact.getTargetHost())) {
|
||||
return UNREACHABLE;
|
||||
}
|
||||
final int phc = plan.getHopCount();
|
||||
final int fhc = fact.getHopCount();
|
||||
if (phc < fhc) {
|
||||
return UNREACHABLE;
|
||||
}
|
||||
|
||||
for (int i=0; i<fhc-1; i++) {
|
||||
if (!plan.getHopTarget(i).equals(fact.getHopTarget(i))) {
|
||||
return UNREACHABLE;
|
||||
}
|
||||
}
|
||||
// now we know that the target matches and proxies so far are the same
|
||||
if (phc > fhc)
|
||||
{
|
||||
return TUNNEL_PROXY; // need to extend the proxy chain
|
||||
}
|
||||
|
||||
// proxy chain 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 TUNNEL_TARGET;
|
||||
}
|
||||
if (plan.isLayered() && !fact.isLayered()) {
|
||||
return LAYER_PROTOCOL;
|
||||
}
|
||||
|
||||
// tunnel and layering are the same, remains to check the security
|
||||
// Should we tolerate if security is better than planned?
|
||||
// (plan.isSecure() && !fact.isSecure())
|
||||
if (plan.isSecure() != fact.isSecure()) {
|
||||
return UNREACHABLE;
|
||||
}
|
||||
|
||||
return COMPLETE;
|
||||
}
|
||||
|
||||
}
|
||||
328
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java
vendored
Normal file
328
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java
vendored
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.conn.routing;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpHost;
|
||||
import ch.boye.httpclientandroidlib.annotation.Immutable;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
import ch.boye.httpclientandroidlib.util.LangUtils;
|
||||
|
||||
/**
|
||||
* The route for a request.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@Immutable
|
||||
public final class HttpRoute implements RouteInfo, Cloneable {
|
||||
|
||||
/** The target host to connect to. */
|
||||
private final HttpHost targetHost;
|
||||
|
||||
/**
|
||||
* The local address to connect from.
|
||||
* <code>null</code> indicates that the default should be used.
|
||||
*/
|
||||
private final InetAddress localAddress;
|
||||
|
||||
/** The proxy servers, if any. Never null. */
|
||||
private final List<HttpHost> proxyChain;
|
||||
|
||||
/** Whether the the route is tunnelled through the proxy. */
|
||||
private final TunnelType tunnelled;
|
||||
|
||||
/** Whether the route is layered. */
|
||||
private final LayerType layered;
|
||||
|
||||
/** Whether the route is (supposed to be) secure. */
|
||||
private final boolean secure;
|
||||
|
||||
private HttpRoute(final HttpHost target, final InetAddress local, final List<HttpHost> proxies,
|
||||
final boolean secure, final TunnelType tunnelled, final LayerType layered) {
|
||||
Args.notNull(target, "Target host");
|
||||
this.targetHost = target;
|
||||
this.localAddress = local;
|
||||
if (proxies != null && !proxies.isEmpty()) {
|
||||
this.proxyChain = new ArrayList<HttpHost>(proxies);
|
||||
} else {
|
||||
this.proxyChain = null;
|
||||
}
|
||||
if (tunnelled == TunnelType.TUNNELLED) {
|
||||
Args.check(this.proxyChain != null, "Proxy required if tunnelled");
|
||||
}
|
||||
this.secure = secure;
|
||||
this.tunnelled = tunnelled != null ? tunnelled : TunnelType.PLAIN;
|
||||
this.layered = layered != null ? layered : LayerType.PLAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route with all attributes specified explicitly.
|
||||
*
|
||||
* @param target the host to which to route
|
||||
* @param local the local address to route from, or
|
||||
* <code>null</code> for the default
|
||||
* @param proxies the proxy chain to use, or
|
||||
* <code>null</code> for a direct route
|
||||
* @param secure <code>true</code> if the route is (to be) secure,
|
||||
* <code>false</code> otherwise
|
||||
* @param tunnelled the tunnel type of this route
|
||||
* @param layered the layering type of this route
|
||||
*/
|
||||
public HttpRoute(final HttpHost target, final InetAddress local, final HttpHost[] proxies,
|
||||
final boolean secure, final TunnelType tunnelled, final LayerType layered) {
|
||||
this(target, local, proxies != null ? Arrays.asList(proxies) : null,
|
||||
secure, tunnelled, layered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route with at most one proxy.
|
||||
*
|
||||
* @param target the host to which to route
|
||||
* @param local the local address to route from, or
|
||||
* <code>null</code> for the default
|
||||
* @param proxy the proxy to use, or
|
||||
* <code>null</code> for a direct route
|
||||
* @param secure <code>true</code> if the route is (to be) secure,
|
||||
* <code>false</code> otherwise
|
||||
* @param tunnelled <code>true</code> if the route is (to be) tunnelled
|
||||
* via the proxy,
|
||||
* <code>false</code> otherwise
|
||||
* @param layered <code>true</code> if the route includes a
|
||||
* layered protocol,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public HttpRoute(final HttpHost target, final InetAddress local, final HttpHost proxy,
|
||||
final boolean secure, final TunnelType tunnelled, final LayerType layered) {
|
||||
this(target, local, proxy != null ? Collections.singletonList(proxy) : null,
|
||||
secure, tunnelled, layered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new direct route.
|
||||
* That is a route without a proxy.
|
||||
*
|
||||
* @param target the host to which to route
|
||||
* @param local the local address to route from, or
|
||||
* <code>null</code> for the default
|
||||
* @param secure <code>true</code> if the route is (to be) secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public HttpRoute(final HttpHost target, final InetAddress local, final boolean secure) {
|
||||
this(target, local, Collections.<HttpHost>emptyList(), secure,
|
||||
TunnelType.PLAIN, LayerType.PLAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new direct insecure route.
|
||||
*
|
||||
* @param target the host to which to route
|
||||
*/
|
||||
public HttpRoute(final HttpHost target) {
|
||||
this(target, null, Collections.<HttpHost>emptyList(), false,
|
||||
TunnelType.PLAIN, LayerType.PLAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route through a proxy.
|
||||
* When using this constructor, the <code>proxy</code> MUST be given.
|
||||
* For convenience, it is assumed that a secure connection will be
|
||||
* layered over a tunnel through the proxy.
|
||||
*
|
||||
* @param target the host to which to route
|
||||
* @param local the local address to route from, or
|
||||
* <code>null</code> for the default
|
||||
* @param proxy the proxy to use
|
||||
* @param secure <code>true</code> if the route is (to be) secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public HttpRoute(final HttpHost target, final InetAddress local, final HttpHost proxy,
|
||||
final boolean secure) {
|
||||
this(target, local, Collections.singletonList(Args.notNull(proxy, "Proxy host")), secure,
|
||||
secure ? TunnelType.TUNNELLED : TunnelType.PLAIN,
|
||||
secure ? LayerType.LAYERED : LayerType.PLAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new plain route through a proxy.
|
||||
*
|
||||
* @param target the host to which to route
|
||||
* @param proxy the proxy to use
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
public HttpRoute(final HttpHost target, final HttpHost proxy) {
|
||||
this(target, null, proxy, false);
|
||||
}
|
||||
|
||||
public final HttpHost getTargetHost() {
|
||||
return this.targetHost;
|
||||
}
|
||||
|
||||
public final InetAddress getLocalAddress() {
|
||||
return this.localAddress;
|
||||
}
|
||||
|
||||
public final InetSocketAddress getLocalSocketAddress() {
|
||||
return this.localAddress != null ? new InetSocketAddress(this.localAddress, 0) : null;
|
||||
}
|
||||
|
||||
public final int getHopCount() {
|
||||
return proxyChain != null ? proxyChain.size() + 1 : 1;
|
||||
}
|
||||
|
||||
public final HttpHost getHopTarget(final int hop) {
|
||||
Args.notNegative(hop, "Hop index");
|
||||
final int hopcount = getHopCount();
|
||||
Args.check(hop < hopcount, "Hop index exceeds tracked route length");
|
||||
if (hop < hopcount - 1) {
|
||||
return this.proxyChain.get(hop);
|
||||
} else {
|
||||
return this.targetHost;
|
||||
}
|
||||
}
|
||||
|
||||
public final HttpHost getProxyHost() {
|
||||
return proxyChain != null && !this.proxyChain.isEmpty() ? this.proxyChain.get(0) : null;
|
||||
}
|
||||
|
||||
public final TunnelType getTunnelType() {
|
||||
return this.tunnelled;
|
||||
}
|
||||
|
||||
public final boolean isTunnelled() {
|
||||
return (this.tunnelled == TunnelType.TUNNELLED);
|
||||
}
|
||||
|
||||
public final LayerType getLayerType() {
|
||||
return this.layered;
|
||||
}
|
||||
|
||||
public final boolean isLayered() {
|
||||
return (this.layered == LayerType.LAYERED);
|
||||
}
|
||||
|
||||
public final boolean isSecure() {
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this route to another.
|
||||
*
|
||||
* @param obj the object to compare with
|
||||
*
|
||||
* @return <code>true</code> if the argument is the same route,
|
||||
* <code>false</code>
|
||||
*/
|
||||
@Override
|
||||
public final boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof HttpRoute) {
|
||||
final HttpRoute that = (HttpRoute) obj;
|
||||
return
|
||||
// Do the cheapest tests first
|
||||
(this.secure == that.secure) &&
|
||||
(this.tunnelled == that.tunnelled) &&
|
||||
(this.layered == that.layered) &&
|
||||
LangUtils.equals(this.targetHost, that.targetHost) &&
|
||||
LangUtils.equals(this.localAddress, that.localAddress) &&
|
||||
LangUtils.equals(this.proxyChain, that.proxyChain);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a hash code for this route.
|
||||
*
|
||||
* @return the hash code
|
||||
*/
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
int hash = LangUtils.HASH_SEED;
|
||||
hash = LangUtils.hashCode(hash, this.targetHost);
|
||||
hash = LangUtils.hashCode(hash, this.localAddress);
|
||||
if (this.proxyChain != null) {
|
||||
for (final HttpHost element : this.proxyChain) {
|
||||
hash = LangUtils.hashCode(hash, element);
|
||||
}
|
||||
}
|
||||
hash = LangUtils.hashCode(hash, this.secure);
|
||||
hash = LangUtils.hashCode(hash, this.tunnelled);
|
||||
hash = LangUtils.hashCode(hash, this.layered);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a description of this route.
|
||||
*
|
||||
* @return a human-readable representation of this route
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
final StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
|
||||
if (this.localAddress != null) {
|
||||
cab.append(this.localAddress);
|
||||
cab.append("->");
|
||||
}
|
||||
cab.append('{');
|
||||
if (this.tunnelled == TunnelType.TUNNELLED) {
|
||||
cab.append('t');
|
||||
}
|
||||
if (this.layered == LayerType.LAYERED) {
|
||||
cab.append('l');
|
||||
}
|
||||
if (this.secure) {
|
||||
cab.append('s');
|
||||
}
|
||||
cab.append("}->");
|
||||
if (this.proxyChain != null) {
|
||||
for (final HttpHost aProxyChain : this.proxyChain) {
|
||||
cab.append(aProxyChain);
|
||||
cab.append("->");
|
||||
}
|
||||
}
|
||||
cab.append(this.targetHost);
|
||||
return cab.toString();
|
||||
}
|
||||
|
||||
// default implementation of clone() is sufficient
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
}
|
||||
74
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java
vendored
Normal file
74
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.conn.routing;
|
||||
|
||||
/**
|
||||
* Provides directions on establishing a route.
|
||||
* Implementations of this interface compare a planned route with
|
||||
* a tracked route and indicate the next step required.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface HttpRouteDirector {
|
||||
|
||||
/** 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 to target. */
|
||||
public final static int TUNNEL_TARGET = 3;
|
||||
|
||||
/** Step: tunnel through proxy to other proxy. */
|
||||
public final static int TUNNEL_PROXY = 4;
|
||||
|
||||
/** Step: layer protocol (over tunnel). */
|
||||
public final static int LAYER_PROTOCOL = 5;
|
||||
|
||||
|
||||
/**
|
||||
* 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 interface, indicating
|
||||
* either the next step to perform, or success, or failure.
|
||||
* 0 is for success, a negative value for failure.
|
||||
*/
|
||||
public int nextStep(RouteInfo plan, RouteInfo fact);
|
||||
|
||||
}
|
||||
67
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java
vendored
Normal file
67
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.conn.routing;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpException;
|
||||
import ch.boye.httpclientandroidlib.HttpHost;
|
||||
import ch.boye.httpclientandroidlib.HttpRequest;
|
||||
import ch.boye.httpclientandroidlib.protocol.HttpContext;
|
||||
|
||||
/**
|
||||
* Encapsulates logic to compute a {@link HttpRoute} to a target host.
|
||||
* Implementations may for example be based on parameters, or on the
|
||||
* standard Java system properties.
|
||||
* <p/>
|
||||
* Implementations of this interface must be thread-safe. Access to shared
|
||||
* data must be synchronized as methods of this interface may be executed
|
||||
* from multiple threads.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface HttpRoutePlanner {
|
||||
|
||||
/**
|
||||
* Determines the route for a request.
|
||||
*
|
||||
* @param target the target host for the request.
|
||||
* Implementations may accept <code>null</code>
|
||||
* if they can still determine a route, for example
|
||||
* to a default target or by inspecting the request.
|
||||
* @param request the request to execute
|
||||
* @param context the context to use for the subsequent execution.
|
||||
* Implementations may accept <code>null</code>.
|
||||
*
|
||||
* @return the route that the request should take
|
||||
*
|
||||
* @throws HttpException in case of a problem
|
||||
*/
|
||||
public HttpRoute determineRoute(HttpHost target,
|
||||
HttpRequest request,
|
||||
HttpContext context) throws HttpException;
|
||||
|
||||
}
|
||||
161
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java
vendored
Normal file
161
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java
vendored
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.conn.routing;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpHost;
|
||||
|
||||
/**
|
||||
* Read-only interface for route information.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public interface RouteInfo {
|
||||
|
||||
/**
|
||||
* The tunnelling type of a route.
|
||||
* Plain routes are established by connecting to the target or
|
||||
* the first proxy.
|
||||
* Tunnelled routes are established by connecting to the first proxy
|
||||
* and tunnelling through all proxies to the target.
|
||||
* Routes without a proxy cannot be tunnelled.
|
||||
*/
|
||||
public enum TunnelType { PLAIN, TUNNELLED }
|
||||
|
||||
/**
|
||||
* The layering type of a route.
|
||||
* Plain routes are established by connecting or tunnelling.
|
||||
* Layered routes are established by layering a protocol such as TLS/SSL
|
||||
* over an existing connection.
|
||||
* Protocols can only be layered over a tunnel to the target, or
|
||||
* or over a direct connection without proxies.
|
||||
* <br/>
|
||||
* Layering a protocol
|
||||
* over a direct connection makes little sense, since the connection
|
||||
* could be established with the new protocol in the first place.
|
||||
* But we don't want to exclude that use case.
|
||||
*/
|
||||
public enum LayerType { PLAIN, LAYERED }
|
||||
|
||||
/**
|
||||
* Obtains the target host.
|
||||
*
|
||||
* @return the target host
|
||||
*/
|
||||
HttpHost getTargetHost();
|
||||
|
||||
/**
|
||||
* Obtains the local address to connect from.
|
||||
*
|
||||
* @return the local address,
|
||||
* or <code>null</code>
|
||||
*/
|
||||
InetAddress getLocalAddress();
|
||||
|
||||
/**
|
||||
* Obtains the number of hops in this route.
|
||||
* A direct route has one hop. A route through a proxy has two hops.
|
||||
* A route through a chain of <i>n</i> proxies has <i>n+1</i> hops.
|
||||
*
|
||||
* @return the number of hops in this route
|
||||
*/
|
||||
int getHopCount();
|
||||
|
||||
/**
|
||||
* Obtains the target of a hop in this route.
|
||||
* The target of the last hop is the {@link #getTargetHost target host},
|
||||
* the target of previous hops is the respective proxy in the chain.
|
||||
* For a route through exactly one proxy, target of hop 0 is the proxy
|
||||
* and target of hop 1 is the target host.
|
||||
*
|
||||
* @param hop index of the hop for which to get the target,
|
||||
* 0 for first
|
||||
*
|
||||
* @return the target of the given hop
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the argument is negative or not less than
|
||||
* {@link #getHopCount getHopCount()}
|
||||
*/
|
||||
HttpHost getHopTarget(int hop);
|
||||
|
||||
/**
|
||||
* Obtains the first proxy host.
|
||||
*
|
||||
* @return the first proxy in the proxy chain, or
|
||||
* <code>null</code> if this route is direct
|
||||
*/
|
||||
HttpHost getProxyHost();
|
||||
|
||||
/**
|
||||
* Obtains the tunnel type of this route.
|
||||
* If there is a proxy chain, only end-to-end tunnels are considered.
|
||||
*
|
||||
* @return the tunnelling type
|
||||
*/
|
||||
TunnelType getTunnelType();
|
||||
|
||||
/**
|
||||
* Checks whether this route is tunnelled through a proxy.
|
||||
* If there is a proxy chain, only end-to-end tunnels are considered.
|
||||
*
|
||||
* @return <code>true</code> if tunnelled end-to-end through at least
|
||||
* one proxy,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean isTunnelled();
|
||||
|
||||
/**
|
||||
* Obtains the layering type of this route.
|
||||
* In the presence of proxies, only layering over an end-to-end tunnel
|
||||
* is considered.
|
||||
*
|
||||
* @return the layering type
|
||||
*/
|
||||
LayerType getLayerType();
|
||||
|
||||
/**
|
||||
* Checks whether this route includes a layered protocol.
|
||||
* In the presence of proxies, only layering over an end-to-end tunnel
|
||||
* is considered.
|
||||
*
|
||||
* @return <code>true</code> if layered,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean isLayered();
|
||||
|
||||
/**
|
||||
* Checks whether this route is secure.
|
||||
*
|
||||
* @return <code>true</code> if secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
boolean isSecure();
|
||||
|
||||
}
|
||||
366
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java
vendored
Normal file
366
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java
vendored
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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 ch.boye.httpclientandroidlib.conn.routing;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpHost;
|
||||
import ch.boye.httpclientandroidlib.annotation.NotThreadSafe;
|
||||
import ch.boye.httpclientandroidlib.util.Args;
|
||||
import ch.boye.httpclientandroidlib.util.Asserts;
|
||||
import ch.boye.httpclientandroidlib.util.LangUtils;
|
||||
|
||||
/**
|
||||
* Helps tracking the steps in establishing a route.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
@NotThreadSafe
|
||||
public final class RouteTracker implements RouteInfo, Cloneable {
|
||||
|
||||
/** The target host to connect to. */
|
||||
private final HttpHost targetHost;
|
||||
|
||||
/**
|
||||
* The local address to connect from.
|
||||
* <code>null</code> indicates that the default should be used.
|
||||
*/
|
||||
private final InetAddress localAddress;
|
||||
|
||||
// the attributes above are fixed at construction time
|
||||
// now follow attributes that indicate the established route
|
||||
|
||||
/** Whether the first hop of the route is established. */
|
||||
private boolean connected;
|
||||
|
||||
/** The proxy chain, if any. */
|
||||
private HttpHost[] proxyChain;
|
||||
|
||||
/** Whether the the route is tunnelled end-to-end through proxies. */
|
||||
private TunnelType tunnelled;
|
||||
|
||||
/** Whether the route is layered over a tunnel. */
|
||||
private LayerType layered;
|
||||
|
||||
/** Whether the route is secure. */
|
||||
private boolean secure;
|
||||
|
||||
/**
|
||||
* Creates a new route tracker.
|
||||
* The target and origin need to be specified at creation time.
|
||||
*
|
||||
* @param target the host to which to route
|
||||
* @param local the local address to route from, or
|
||||
* <code>null</code> for the default
|
||||
*/
|
||||
public RouteTracker(final HttpHost target, final InetAddress local) {
|
||||
Args.notNull(target, "Target host");
|
||||
this.targetHost = target;
|
||||
this.localAddress = local;
|
||||
this.tunnelled = TunnelType.PLAIN;
|
||||
this.layered = LayerType.PLAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
public void reset() {
|
||||
this.connected = false;
|
||||
this.proxyChain = null;
|
||||
this.tunnelled = TunnelType.PLAIN;
|
||||
this.layered = LayerType.PLAIN;
|
||||
this.secure = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new tracker for the given route.
|
||||
* Only target and origin are taken from the route,
|
||||
* everything else remains to be tracked.
|
||||
*
|
||||
* @param route the route to track
|
||||
*/
|
||||
public RouteTracker(final HttpRoute route) {
|
||||
this(route.getTargetHost(), route.getLocalAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks connecting to the target.
|
||||
*
|
||||
* @param secure <code>true</code> if the route is secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public final void connectTarget(final boolean secure) {
|
||||
Asserts.check(!this.connected, "Already connected");
|
||||
this.connected = true;
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks connecting to the first proxy.
|
||||
*
|
||||
* @param proxy the proxy connected to
|
||||
* @param secure <code>true</code> if the route is secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public final void connectProxy(final HttpHost proxy, final boolean secure) {
|
||||
Args.notNull(proxy, "Proxy host");
|
||||
Asserts.check(!this.connected, "Already connected");
|
||||
this.connected = true;
|
||||
this.proxyChain = new HttpHost[]{ proxy };
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks tunnelling to the target.
|
||||
*
|
||||
* @param secure <code>true</code> if the route is secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public final void tunnelTarget(final boolean secure) {
|
||||
Asserts.check(this.connected, "No tunnel unless connected");
|
||||
Asserts.notNull(this.proxyChain, "No tunnel without proxy");
|
||||
this.tunnelled = TunnelType.TUNNELLED;
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks tunnelling to a proxy in a proxy chain.
|
||||
* This will extend the tracked proxy chain, but it does not mark
|
||||
* the route as tunnelled. Only end-to-end tunnels are considered there.
|
||||
*
|
||||
* @param proxy the proxy tunnelled to
|
||||
* @param secure <code>true</code> if the route is secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public final void tunnelProxy(final HttpHost proxy, final boolean secure) {
|
||||
Args.notNull(proxy, "Proxy host");
|
||||
Asserts.check(this.connected, "No tunnel unless connected");
|
||||
Asserts.notNull(this.proxyChain, "No tunnel without proxy");
|
||||
// prepare an extended proxy chain
|
||||
final HttpHost[] proxies = new HttpHost[this.proxyChain.length+1];
|
||||
System.arraycopy(this.proxyChain, 0,
|
||||
proxies, 0, this.proxyChain.length);
|
||||
proxies[proxies.length-1] = proxy;
|
||||
|
||||
this.proxyChain = proxies;
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks layering a protocol.
|
||||
*
|
||||
* @param secure <code>true</code> if the route is secure,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public final void layerProtocol(final boolean secure) {
|
||||
// it is possible to layer a protocol over a direct connection,
|
||||
// although this case is probably not considered elsewhere
|
||||
Asserts.check(this.connected, "No layered protocol unless connected");
|
||||
this.layered = LayerType.LAYERED;
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
public final HttpHost getTargetHost() {
|
||||
return this.targetHost;
|
||||
}
|
||||
|
||||
public final InetAddress getLocalAddress() {
|
||||
return this.localAddress;
|
||||
}
|
||||
|
||||
public final int getHopCount() {
|
||||
int hops = 0;
|
||||
if (this.connected) {
|
||||
if (proxyChain == null) {
|
||||
hops = 1;
|
||||
} else {
|
||||
hops = proxyChain.length + 1;
|
||||
}
|
||||
}
|
||||
return hops;
|
||||
}
|
||||
|
||||
public final HttpHost getHopTarget(final int hop) {
|
||||
Args.notNegative(hop, "Hop index");
|
||||
final int hopcount = getHopCount();
|
||||
Args.check(hop < hopcount, "Hop index exceeds tracked route length");
|
||||
HttpHost result = null;
|
||||
if (hop < hopcount-1) {
|
||||
result = this.proxyChain[hop];
|
||||
} else {
|
||||
result = this.targetHost;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public final HttpHost getProxyHost() {
|
||||
return (this.proxyChain == null) ? null : this.proxyChain[0];
|
||||
}
|
||||
|
||||
public final boolean isConnected() {
|
||||
return this.connected;
|
||||
}
|
||||
|
||||
public final TunnelType getTunnelType() {
|
||||
return this.tunnelled;
|
||||
}
|
||||
|
||||
public final boolean isTunnelled() {
|
||||
return (this.tunnelled == TunnelType.TUNNELLED);
|
||||
}
|
||||
|
||||
public final LayerType getLayerType() {
|
||||
return this.layered;
|
||||
}
|
||||
|
||||
public final boolean isLayered() {
|
||||
return (this.layered == LayerType.LAYERED);
|
||||
}
|
||||
|
||||
public final boolean isSecure() {
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the tracked route.
|
||||
* If a route has been tracked, it is {@link #isConnected connected}.
|
||||
* If not connected, nothing has been tracked so far.
|
||||
*
|
||||
* @return the tracked route, or
|
||||
* <code>null</code> if nothing has been tracked so far
|
||||
*/
|
||||
public final HttpRoute toRoute() {
|
||||
return !this.connected ?
|
||||
null : new HttpRoute(this.targetHost, this.localAddress,
|
||||
this.proxyChain, this.secure,
|
||||
this.tunnelled, this.layered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this tracked route to another.
|
||||
*
|
||||
* @param o the object to compare with
|
||||
*
|
||||
* @return <code>true</code> if the argument is the same tracked route,
|
||||
* <code>false</code>
|
||||
*/
|
||||
@Override
|
||||
public final boolean equals(final Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof RouteTracker)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final RouteTracker that = (RouteTracker) o;
|
||||
return
|
||||
// Do the cheapest checks first
|
||||
(this.connected == that.connected) &&
|
||||
(this.secure == that.secure) &&
|
||||
(this.tunnelled == that.tunnelled) &&
|
||||
(this.layered == that.layered) &&
|
||||
LangUtils.equals(this.targetHost, that.targetHost) &&
|
||||
LangUtils.equals(this.localAddress, that.localAddress) &&
|
||||
LangUtils.equals(this.proxyChain, that.proxyChain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a hash code for this tracked route.
|
||||
* Route trackers are modifiable and should therefore not be used
|
||||
* as lookup keys. Use {@link #toRoute toRoute} to obtain an
|
||||
* unmodifiable representation of the tracked route.
|
||||
*
|
||||
* @return the hash code
|
||||
*/
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
int hash = LangUtils.HASH_SEED;
|
||||
hash = LangUtils.hashCode(hash, this.targetHost);
|
||||
hash = LangUtils.hashCode(hash, this.localAddress);
|
||||
if (this.proxyChain != null) {
|
||||
for (final HttpHost element : this.proxyChain) {
|
||||
hash = LangUtils.hashCode(hash, element);
|
||||
}
|
||||
}
|
||||
hash = LangUtils.hashCode(hash, this.connected);
|
||||
hash = LangUtils.hashCode(hash, this.secure);
|
||||
hash = LangUtils.hashCode(hash, this.tunnelled);
|
||||
hash = LangUtils.hashCode(hash, this.layered);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a description of the tracked route.
|
||||
*
|
||||
* @return a human-readable representation of the tracked route
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
final StringBuilder cab = new StringBuilder(50 + getHopCount()*30);
|
||||
|
||||
cab.append("RouteTracker[");
|
||||
if (this.localAddress != null) {
|
||||
cab.append(this.localAddress);
|
||||
cab.append("->");
|
||||
}
|
||||
cab.append('{');
|
||||
if (this.connected) {
|
||||
cab.append('c');
|
||||
}
|
||||
if (this.tunnelled == TunnelType.TUNNELLED) {
|
||||
cab.append('t');
|
||||
}
|
||||
if (this.layered == LayerType.LAYERED) {
|
||||
cab.append('l');
|
||||
}
|
||||
if (this.secure) {
|
||||
cab.append('s');
|
||||
}
|
||||
cab.append("}->");
|
||||
if (this.proxyChain != null) {
|
||||
for (final HttpHost element : this.proxyChain) {
|
||||
cab.append(element);
|
||||
cab.append("->");
|
||||
}
|
||||
}
|
||||
cab.append(this.targetHost);
|
||||
cab.append(']');
|
||||
|
||||
return cab.toString();
|
||||
}
|
||||
|
||||
|
||||
// default implementation of clone() is sufficient
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
}
|
||||
31
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java
vendored
Normal file
31
mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Client connection routing APIs.
|
||||
*/
|
||||
package ch.boye.httpclientandroidlib.conn.routing;
|
||||
Loading…
Add table
Add a link
Reference in a new issue