diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn')
82 files changed, 9262 insertions, 0 deletions
diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicEofSensorWatcher.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicEofSensorWatcher.java new file mode 100644 index 000000000..0273224ad --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicEofSensorWatcher.java @@ -0,0 +1,105 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.io.InputStream; + +import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * Basic implementation of {@link EofSensorWatcher}. The underlying connection + * is released on close or EOF. + * + * @since 4.0 + * + * @deprecated (4.3) do not use. + */ +@Deprecated +@NotThreadSafe +public class BasicEofSensorWatcher implements EofSensorWatcher { + + /** The connection to auto-release. */ + protected final ManagedClientConnection managedConn; + + /** Whether to keep the connection alive. */ + protected final boolean attemptReuse; + + /** + * Creates a new watcher for auto-releasing a connection. + * + * @param conn the connection to auto-release + * @param reuse whether the connection should be re-used + */ + public BasicEofSensorWatcher(final ManagedClientConnection conn, + final boolean reuse) { + Args.notNull(conn, "Connection"); + managedConn = conn; + attemptReuse = reuse; + } + + public boolean eofDetected(final InputStream wrapped) + throws IOException { + + try { + if (attemptReuse) { + // there may be some cleanup required, such as + // reading trailers after the response body: + wrapped.close(); + managedConn.markReusable(); + } + } finally { + managedConn.releaseConnection(); + } + return false; + } + + public boolean streamClosed(final InputStream wrapped) + throws IOException { + + try { + if (attemptReuse) { + // this assumes that closing the stream will + // consume the remainder of the response body: + wrapped.close(); + managedConn.markReusable(); + } + } finally { + managedConn.releaseConnection(); + } + return false; + } + + public boolean streamAbort(final InputStream wrapped) + throws IOException { + + managedConn.abortConnection(); + return false; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicManagedEntity.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicManagedEntity.java new file mode 100644 index 000000000..59556b5e9 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/BasicManagedEntity.java @@ -0,0 +1,208 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.SocketException; + +import ch.boye.httpclientandroidlib.HttpEntity; +import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; +import ch.boye.httpclientandroidlib.entity.HttpEntityWrapper; +import ch.boye.httpclientandroidlib.util.Args; +import ch.boye.httpclientandroidlib.util.EntityUtils; + +/** + * An entity that releases a {@link ManagedClientConnection connection}. + * A {@link ManagedClientConnection} will + * typically <i>not</i> return a managed entity, but you can replace + * the unmanaged entity in the response with a managed one. + * + * @since 4.0 + * + * @deprecated (4.3) do not use. + */ +@Deprecated +@NotThreadSafe +public class BasicManagedEntity extends HttpEntityWrapper + implements ConnectionReleaseTrigger, EofSensorWatcher { + + /** The connection to release. */ + protected ManagedClientConnection managedConn; + + /** Whether to keep the connection alive. */ + protected final boolean attemptReuse; + + /** + * Creates a new managed entity that can release a connection. + * + * @param entity the entity of which to wrap the content. + * Note that the argument entity can no longer be used + * afterwards, since the content will be taken by this + * managed entity. + * @param conn the connection to release + * @param reuse whether the connection should be re-used + */ + public BasicManagedEntity(final HttpEntity entity, + final ManagedClientConnection conn, + final boolean reuse) { + super(entity); + Args.notNull(conn, "Connection"); + this.managedConn = conn; + this.attemptReuse = reuse; + } + + @Override + public boolean isRepeatable() { + return false; + } + + @Override + public InputStream getContent() throws IOException { + return new EofSensorInputStream(wrappedEntity.getContent(), this); + } + + private void ensureConsumed() throws IOException { + if (managedConn == null) { + return; + } + + try { + if (attemptReuse) { + // this will not trigger a callback from EofSensorInputStream + EntityUtils.consume(wrappedEntity); + managedConn.markReusable(); + } else { + managedConn.unmarkReusable(); + } + } finally { + releaseManagedConnection(); + } + } + + /** + * @deprecated (4.1) Use {@link EntityUtils#consume(HttpEntity)} + */ + @Deprecated + @Override + public void consumeContent() throws IOException { + ensureConsumed(); + } + + @Override + public void writeTo(final OutputStream outstream) throws IOException { + super.writeTo(outstream); + ensureConsumed(); + } + + public void releaseConnection() throws IOException { + ensureConsumed(); + } + + public void abortConnection() throws IOException { + + if (managedConn != null) { + try { + managedConn.abortConnection(); + } finally { + managedConn = null; + } + } + } + + public boolean eofDetected(final InputStream wrapped) throws IOException { + try { + if (managedConn != null) { + if (attemptReuse) { + // there may be some cleanup required, such as + // reading trailers after the response body: + wrapped.close(); + managedConn.markReusable(); + } else { + managedConn.unmarkReusable(); + } + } + } finally { + releaseManagedConnection(); + } + return false; + } + + public boolean streamClosed(final InputStream wrapped) throws IOException { + try { + if (managedConn != null) { + if (attemptReuse) { + final boolean valid = managedConn.isOpen(); + // this assumes that closing the stream will + // consume the remainder of the response body: + try { + wrapped.close(); + managedConn.markReusable(); + } catch (final SocketException ex) { + if (valid) { + throw ex; + } + } + } else { + managedConn.unmarkReusable(); + } + } + } finally { + releaseManagedConnection(); + } + return false; + } + + public boolean streamAbort(final InputStream wrapped) throws IOException { + if (managedConn != null) { + managedConn.abortConnection(); + } + return false; + } + + /** + * Releases the connection gracefully. + * The connection attribute will be nullified. + * Subsequent invocations are no-ops. + * + * @throws IOException in case of an IO problem. + * The connection attribute will be nullified anyway. + */ + protected void releaseManagedConnection() + throws IOException { + + if (managedConn != null) { + try { + managedConn.releaseConnection(); + } finally { + managedConn = null; + } + } + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManager.java new file mode 100644 index 000000000..dcdbb4ce5 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManager.java @@ -0,0 +1,117 @@ +/* + * ==================================================================== + * 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; + +import java.util.concurrent.TimeUnit; + +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; +import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry; + +/** + * Management interface for {@link ManagedClientConnection client connections}. + * The purpose of an HTTP connection manager is to serve as a factory for new + * HTTP connections, manage persistent connections and synchronize access to + * persistent connections making sure that only one thread of execution can + * have access to a connection at a time. + * <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 + * + * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}. + */ +@Deprecated +public interface ClientConnectionManager { + + /** + * Obtains the scheme registry used by this manager. + * + * @return the scheme registry, never <code>null</code> + */ + SchemeRegistry getSchemeRegistry(); + + /** + * Returns a new {@link ClientConnectionRequest}, from which a + * {@link ManagedClientConnection} can be obtained or the request can be + * aborted. + */ + ClientConnectionRequest requestConnection(HttpRoute route, Object state); + + /** + * Releases a connection for use by others. + * You may optionally specify how long the connection is valid + * to be reused. Values <= 0 are considered to be valid forever. + * If the connection is not marked as reusable, the connection will + * not be reused regardless of the valid duration. + * + * If the connection has been released before, + * the call will be ignored. + * + * @param conn the connection to release + * @param validDuration the duration of time this connection is valid for reuse + * @param timeUnit the unit of time validDuration is measured in + * + * @see #closeExpiredConnections() + */ + void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit); + + /** + * Closes idle connections in the pool. + * Open connections in the pool that have not been used for the + * timespan given by the argument will be closed. + * Currently allocated connections are not subject to this method. + * Times will be checked with milliseconds precision + * + * All expired connections will also be closed. + * + * @param idletime the idle time of connections to be closed + * @param tunit the unit for the <code>idletime</code> + * + * @see #closeExpiredConnections() + */ + void closeIdleConnections(long idletime, TimeUnit tunit); + + /** + * Closes all expired connections in the pool. + * Open connections in the pool that have not been used for + * the timespan defined when the connection was released will be closed. + * Currently allocated connections are not subject to this method. + * Times will be checked with milliseconds precision. + */ + void closeExpiredConnections(); + + /** + * Shuts down this connection manager and releases allocated resources. + * This includes closing all connections, whether they are currently + * used or not. + */ + void shutdown(); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManagerFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManagerFactory.java new file mode 100644 index 000000000..895690e95 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionManagerFactory.java @@ -0,0 +1,47 @@ +/* + * ==================================================================== + * 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; + +import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * A factory for creating new {@link ClientConnectionManager} instances. + * + * @since 4.0 + * + * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}. + */ +@Deprecated +public interface ClientConnectionManagerFactory { + + ClientConnectionManager newInstance( + HttpParams params, + SchemeRegistry schemeRegistry); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionOperator.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionOperator.java new file mode 100644 index 000000000..333975b2c --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionOperator.java @@ -0,0 +1,107 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.net.InetAddress; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.params.HttpParams; +import ch.boye.httpclientandroidlib.protocol.HttpContext; + +/** + * ClientConnectionOperator represents a strategy for creating + * {@link OperatedClientConnection} instances and updating the underlying + * {@link java.net.Socket} of those objects. Implementations will most + * likely make use of {@link ch.boye.httpclientandroidlib.conn.scheme.SchemeSocketFactory}s + * to create {@link java.net.Socket} instances. + * <p> + * The methods in this interface allow the creation of plain and layered + * sockets. Creating a tunnelled connection through a proxy, however, + * is not within the scope of the operator. + * <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 + * + * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}. + */ +@Deprecated +public interface ClientConnectionOperator { + + /** + * Creates a new connection that can be operated. + * + * @return a new, unopened connection for use with this operator + */ + OperatedClientConnection createConnection(); + + /** + * Opens a connection to the given target host. + * + * @param conn the connection to open + * @param target the target host to connect to + * @param local the local address to route from, or + * <code>null</code> for the default + * @param context the context for the connection + * @param params the parameters for the connection + * + * @throws IOException in case of a problem + */ + void openConnection(OperatedClientConnection conn, + HttpHost target, + InetAddress local, + HttpContext context, + HttpParams params) + throws IOException; + + /** + * Updates a connection with a layered secure connection. + * The typical use of this method is to update a tunnelled plain + * connection (HTTP) to a secure TLS/SSL connection (HTTPS). + * + * @param conn the open connection to update + * @param target the target host for the updated connection. + * The connection must already be open or tunnelled + * to the host and port, but the scheme of the target + * will be used to create a layered connection. + * @param context the context for the connection + * @param params the parameters for the updated connection + * + * @throws IOException in case of a problem + */ + void updateSecureConnection(OperatedClientConnection conn, + HttpHost target, + HttpContext context, + HttpParams params) + throws IOException; + +} + diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionRequest.java new file mode 100644 index 000000000..656284081 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ClientConnectionRequest.java @@ -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; + +import java.util.concurrent.TimeUnit; + +/** + * Encapsulates a request for a {@link ManagedClientConnection}. + * + * @since 4.0 + * + * @deprecated (4.3) replaced by {@link ConnectionRequest}. + */ +@Deprecated +public interface ClientConnectionRequest { + + /** + * Obtains a connection within a given time. + * This method will block until a connection becomes available, + * the timeout expires, or the connection manager is + * {@link ClientConnectionManager#shutdown() shut down}. + * Timeouts are handled with millisecond precision. + * + * If {@link #abortRequest()} is called while this is blocking or + * before this began, an {@link InterruptedException} will + * be thrown. + * + * @param timeout the timeout, 0 or negative for no timeout + * @param tunit the unit for the <code>timeout</code>, + * may be <code>null</code> only if there is no timeout + * + * @return a connection that can be used to communicate + * along the given route + * + * @throws ConnectionPoolTimeoutException + * in case of a timeout + * @throws InterruptedException + * if the calling thread is interrupted while waiting + */ + ManagedClientConnection getConnection(long timeout, TimeUnit tunit) + throws InterruptedException, ConnectionPoolTimeoutException; + + /** + * Aborts the call to {@link #getConnection(long, TimeUnit)}, + * causing it to throw an {@link InterruptedException}. + */ + void abortRequest(); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectTimeoutException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectTimeoutException.java new file mode 100644 index 000000000..f98bd1941 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectTimeoutException.java @@ -0,0 +1,94 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.InetAddress; +import java.util.Arrays; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * A timeout while connecting to an HTTP server or waiting for an + * available connection from an HttpConnectionManager. + * + * + * @since 4.0 + */ +@Immutable +public class ConnectTimeoutException extends InterruptedIOException { + + private static final long serialVersionUID = -4816682903149535989L; + + private final HttpHost host; + + /** + * Creates a ConnectTimeoutException with a <tt>null</tt> detail message. + */ + public ConnectTimeoutException() { + super(); + this.host = null; + } + + /** + * Creates a ConnectTimeoutException with the specified detail message. + */ + public ConnectTimeoutException(final String message) { + super(message); + this.host = null; + } + + /** + * Creates a ConnectTimeoutException based on original {@link IOException}. + * + * @since 4.3 + */ + public ConnectTimeoutException( + final IOException cause, + final HttpHost host, + final InetAddress... remoteAddresses) { + super("Connect to " + + (host != null ? host.toHostString() : "remote host") + + (remoteAddresses != null && remoteAddresses.length > 0 ? + " " + Arrays.asList(remoteAddresses) : "") + + ((cause != null && cause.getMessage() != null) ? + " failed: " + cause.getMessage() : " timed out")); + this.host = host; + initCause(cause); + } + + /** + * @since 4.3 + */ + public HttpHost getHost() { + return host; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java new file mode 100644 index 000000000..3f06e4873 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java @@ -0,0 +1,66 @@ +/* + * ==================================================================== + * 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; + +import ch.boye.httpclientandroidlib.HttpResponse; +import ch.boye.httpclientandroidlib.protocol.HttpContext; + +/** + * Interface for deciding how long a connection can remain + * idle before being reused. + * <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 ConnectionKeepAliveStrategy { + + /** + * Returns the duration of time which this connection can be safely kept + * idle. If the connection is left idle for longer than this period of time, + * it MUST not reused. A value of 0 or less may be returned to indicate that + * there is no suitable suggestion. + * + * When coupled with a {@link ch.boye.httpclientandroidlib.ConnectionReuseStrategy}, if + * {@link ch.boye.httpclientandroidlib.ConnectionReuseStrategy#keepAlive( + * HttpResponse, HttpContext)} returns true, this allows you to control + * how long the reuse will last. If keepAlive returns false, this should + * have no meaningful impact + * + * @param response + * The last response received over the connection. + * @param context + * the context in which the connection is being used. + * + * @return the duration in ms for which it is safe to keep the connection + * idle, or <=0 if no suggested duration. + */ + long getKeepAliveDuration(HttpResponse response, HttpContext context); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java new file mode 100644 index 000000000..d4066b2a3 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionPoolTimeoutException.java @@ -0,0 +1,60 @@ +/* + * ==================================================================== + * 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; + +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * A timeout while waiting for an available connection + * from a connection manager. + * + * + * @since 4.0 + */ +@Immutable +public class ConnectionPoolTimeoutException extends ConnectTimeoutException { + + private static final long serialVersionUID = -7898874842020245128L; + + /** + * Creates a ConnectTimeoutException with a <tt>null</tt> detail message. + */ + public ConnectionPoolTimeoutException() { + super(); + } + + /** + * Creates a ConnectTimeoutException with the specified detail message. + * + * @param message The exception detail message + */ + public ConnectionPoolTimeoutException(final String message) { + super(message); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionReleaseTrigger.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionReleaseTrigger.java new file mode 100644 index 000000000..97269268b --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionReleaseTrigger.java @@ -0,0 +1,70 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; + +/** + * Interface for releasing a connection. This can be implemented by various + * "trigger" objects which are associated with a connection, for example + * a {@link EofSensorInputStream stream} or an {@link BasicManagedEntity entity} + * or the {@link ManagedClientConnection connection} itself. + * <p> + * The methods in this interface can safely be called multiple times. + * The first invocation releases the connection, subsequent calls + * are ignored. + * + * @since 4.0 + */ +public interface ConnectionReleaseTrigger { + + /** + * Releases the connection with the option of keep-alive. This is a + * "graceful" release and may cause IO operations for consuming the + * remainder of a response entity. Use + * {@link #abortConnection abortConnection} for a hard release. The + * connection may be reused as specified by the duration. + * + * @throws IOException + * in case of an IO problem. The connection will be released + * anyway. + */ + void releaseConnection() + throws IOException; + + /** + * Releases the connection without the option of keep-alive. + * This is a "hard" release that implies a shutdown of the connection. + * Use {@link #releaseConnection()} for a graceful release. + * + * @throws IOException in case of an IO problem. + * The connection will be released anyway. + */ + void abortConnection() + throws IOException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionRequest.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionRequest.java new file mode 100644 index 000000000..838c35567 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ConnectionRequest.java @@ -0,0 +1,69 @@ +/* + * ==================================================================== + * 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; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import ch.boye.httpclientandroidlib.HttpClientConnection; +import ch.boye.httpclientandroidlib.concurrent.Cancellable; + +/** + * Represents a request for a {@link HttpClientConnection} whose life cycle + * is managed by a connection manager. + * + * @since 4.3 + */ +public interface ConnectionRequest extends Cancellable { + + /** + * Obtains a connection within a given time. + * This method will block until a connection becomes available, + * the timeout expires, or the connection manager is shut down. + * Timeouts are handled with millisecond precision. + * + * If {@link #cancel()} is called while this is blocking or + * before this began, an {@link InterruptedException} will + * be thrown. + * + * @param timeout the timeout, 0 or negative for no timeout + * @param tunit the unit for the <code>timeout</code>, + * may be <code>null</code> only if there is no timeout + * + * @return a connection that can be used to communicate + * along the given route + * + * @throws ConnectionPoolTimeoutException + * in case of a timeout + * @throws InterruptedException + * if the calling thread is interrupted while waiting + */ + HttpClientConnection get(long timeout, TimeUnit tunit) + throws InterruptedException, ExecutionException, ConnectionPoolTimeoutException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/DnsResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/DnsResolver.java new file mode 100644 index 000000000..78ce8709b --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/DnsResolver.java @@ -0,0 +1,54 @@ +/* + * ==================================================================== + * 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; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Users may implement this interface to override the normal DNS lookup offered + * by the OS. + * + * @since 4.2 + */ +public interface DnsResolver { + + /** + * Returns the IP address for the specified host name, or null if the given + * host is not recognized or the associated IP address cannot be used to + * build an InetAddress instance. + * + * @see InetAddress + * + * @param host + * The host name to be resolved by this resolver. + * @return The IP address associated to the given host name, or null if the + * host name is not known by the implementation class. + */ + InetAddress[] resolve(String host) throws UnknownHostException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorInputStream.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorInputStream.java new file mode 100644 index 000000000..7db23eed4 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorInputStream.java @@ -0,0 +1,289 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.io.InputStream; + +import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * A stream wrapper that triggers actions on {@link #close close()} and EOF. + * Primarily used to auto-release an underlying managed connection when the response + * body is consumed or no longer needed. + * + * @see EofSensorWatcher + * + * @since 4.0 + */ +// don't use FilterInputStream as the base class, we'd have to +// override markSupported(), mark(), and reset() to disable them +@NotThreadSafe +public class EofSensorInputStream extends InputStream implements ConnectionReleaseTrigger { + + /** + * The wrapped input stream, while accessible. + * The value changes to <code>null</code> when the wrapped stream + * becomes inaccessible. + */ + protected InputStream wrappedStream; + + /** + * Indicates whether this stream itself is closed. + * If it isn't, but {@link #wrappedStream wrappedStream} + * is <code>null</code>, we're running in EOF mode. + * All read operations will indicate EOF without accessing + * the underlying stream. After closing this stream, read + * operations will trigger an {@link IOException IOException}. + * + * @see #isReadAllowed isReadAllowed + */ + private boolean selfClosed; + + /** The watcher to be notified, if any. */ + private final EofSensorWatcher eofWatcher; + + /** + * Creates a new EOF sensor. + * If no watcher is passed, the underlying stream will simply be + * closed when EOF is detected or {@link #close close} is called. + * Otherwise, the watcher decides whether the underlying stream + * should be closed before detaching from it. + * + * @param in the wrapped stream + * @param watcher the watcher for events, or <code>null</code> for + * auto-close behavior without notification + */ + public EofSensorInputStream(final InputStream in, + final EofSensorWatcher watcher) { + Args.notNull(in, "Wrapped stream"); + wrappedStream = in; + selfClosed = false; + eofWatcher = watcher; + } + + boolean isSelfClosed() { + return selfClosed; + } + + InputStream getWrappedStream() { + return wrappedStream; + } + + /** + * Checks whether the underlying stream can be read from. + * + * @return <code>true</code> if the underlying stream is accessible, + * <code>false</code> if this stream is in EOF mode and + * detached from the underlying stream + * + * @throws IOException if this stream is already closed + */ + protected boolean isReadAllowed() throws IOException { + if (selfClosed) { + throw new IOException("Attempted read on closed stream."); + } + return (wrappedStream != null); + } + + @Override + public int read() throws IOException { + int l = -1; + + if (isReadAllowed()) { + try { + l = wrappedStream.read(); + checkEOF(l); + } catch (final IOException ex) { + checkAbort(); + throw ex; + } + } + + return l; + } + + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + int l = -1; + + if (isReadAllowed()) { + try { + l = wrappedStream.read(b, off, len); + checkEOF(l); + } catch (final IOException ex) { + checkAbort(); + throw ex; + } + } + + return l; + } + + @Override + public int read(final byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public int available() throws IOException { + int a = 0; // not -1 + + if (isReadAllowed()) { + try { + a = wrappedStream.available(); + // no checkEOF() here, available() can't trigger EOF + } catch (final IOException ex) { + checkAbort(); + throw ex; + } + } + + return a; + } + + @Override + public void close() throws IOException { + // tolerate multiple calls to close() + selfClosed = true; + checkClose(); + } + + /** + * Detects EOF and notifies the watcher. + * This method should only be called while the underlying stream is + * still accessible. Use {@link #isReadAllowed isReadAllowed} to + * check that condition. + * <br/> + * If EOF is detected, the watcher will be notified and this stream + * is detached from the underlying stream. This prevents multiple + * notifications from this stream. + * + * @param eof the result of the calling read operation. + * A negative value indicates that EOF is reached. + * + * @throws IOException + * in case of an IO problem on closing the underlying stream + */ + protected void checkEOF(final int eof) throws IOException { + + if ((wrappedStream != null) && (eof < 0)) { + try { + boolean scws = true; // should close wrapped stream? + if (eofWatcher != null) { + scws = eofWatcher.eofDetected(wrappedStream); + } + if (scws) { + wrappedStream.close(); + } + } finally { + wrappedStream = null; + } + } + } + + /** + * Detects stream close and notifies the watcher. + * There's not much to detect since this is called by {@link #close close}. + * The watcher will only be notified if this stream is closed + * for the first time and before EOF has been detected. + * This stream will be detached from the underlying stream to prevent + * multiple notifications to the watcher. + * + * @throws IOException + * in case of an IO problem on closing the underlying stream + */ + protected void checkClose() throws IOException { + + if (wrappedStream != null) { + try { + boolean scws = true; // should close wrapped stream? + if (eofWatcher != null) { + scws = eofWatcher.streamClosed(wrappedStream); + } + if (scws) { + wrappedStream.close(); + } + } finally { + wrappedStream = null; + } + } + } + + /** + * Detects stream abort and notifies the watcher. + * There's not much to detect since this is called by + * {@link #abortConnection abortConnection}. + * The watcher will only be notified if this stream is aborted + * for the first time and before EOF has been detected or the + * stream has been {@link #close closed} gracefully. + * This stream will be detached from the underlying stream to prevent + * multiple notifications to the watcher. + * + * @throws IOException + * in case of an IO problem on closing the underlying stream + */ + protected void checkAbort() throws IOException { + + if (wrappedStream != null) { + try { + boolean scws = true; // should close wrapped stream? + if (eofWatcher != null) { + scws = eofWatcher.streamAbort(wrappedStream); + } + if (scws) { + wrappedStream.close(); + } + } finally { + wrappedStream = null; + } + } + } + + /** + * Same as {@link #close close()}. + */ + public void releaseConnection() throws IOException { + close(); + } + + /** + * Aborts this stream. + * This is a special version of {@link #close close()} which prevents + * re-use of the underlying connection, if any. Calling this method + * indicates that there should be no attempt to read until the end of + * the stream. + */ + public void abortConnection() throws IOException { + // tolerate multiple calls + selfClosed = true; + checkAbort(); + } + +} + diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorWatcher.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorWatcher.java new file mode 100644 index 000000000..c57772fb8 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/EofSensorWatcher.java @@ -0,0 +1,95 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.io.InputStream; + +/** + * A watcher for {@link EofSensorInputStream}. Each stream will notify its + * watcher at most once. + * + * @since 4.0 + */ +public interface EofSensorWatcher { + + /** + * Indicates that EOF is detected. + * + * @param wrapped the underlying stream which has reached EOF + * + * @return <code>true</code> if <code>wrapped</code> should be closed, + * <code>false</code> if it should be left alone + * + * @throws IOException + * in case of an IO problem, for example if the watcher itself + * closes the underlying stream. The caller will leave the + * wrapped stream alone, as if <code>false</code> was returned. + */ + boolean eofDetected(InputStream wrapped) + throws IOException; + + /** + * Indicates that the {@link EofSensorInputStream stream} is closed. + * This method will be called only if EOF was <i>not</i> detected + * before closing. Otherwise, {@link #eofDetected eofDetected} is called. + * + * @param wrapped the underlying stream which has not reached EOF + * + * @return <code>true</code> if <code>wrapped</code> should be closed, + * <code>false</code> if it should be left alone + * + * @throws IOException + * in case of an IO problem, for example if the watcher itself + * closes the underlying stream. The caller will leave the + * wrapped stream alone, as if <code>false</code> was returned. + */ + boolean streamClosed(InputStream wrapped) + throws IOException; + + /** + * Indicates that the {@link EofSensorInputStream stream} is aborted. + * This method will be called only if EOF was <i>not</i> detected + * before aborting. Otherwise, {@link #eofDetected eofDetected} is called. + * <p/> + * This method will also be invoked when an input operation causes an + * IOException to be thrown to make sure the input stream gets shut down. + * + * @param wrapped the underlying stream which has not reached EOF + * + * @return <code>true</code> if <code>wrapped</code> should be closed, + * <code>false</code> if it should be left alone + * + * @throws IOException + * in case of an IO problem, for example if the watcher itself + * closes the underlying stream. The caller will leave the + * wrapped stream alone, as if <code>false</code> was returned. + */ + boolean streamAbort(InputStream wrapped) + throws IOException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpClientConnectionManager.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpClientConnectionManager.java new file mode 100644 index 000000000..0381a803f --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpClientConnectionManager.java @@ -0,0 +1,176 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import ch.boye.httpclientandroidlib.HttpClientConnection; +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; +import ch.boye.httpclientandroidlib.protocol.HttpContext; + +/** + * Represents a manager of persistent client connections. + * <p/> + * The purpose of an HTTP connection manager is to serve as a factory for new + * HTTP connections, manage persistent connections and synchronize access to + * persistent connections making sure that only one thread of execution can + * have access to a connection at a time. + * <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.3 + */ +public interface HttpClientConnectionManager { + + /** + * Returns a new {@link ConnectionRequest}, from which a + * {@link HttpClientConnection} can be obtained or the request can be + * aborted. + * <p/> + * Please note that newly allocated connections can be returned + * in the closed state. The consumer of that connection is responsible + * for fully establishing the route the to the connection target + * by calling {@link #connect(ch.boye.httpclientandroidlib.HttpClientConnection, + * ch.boye.httpclientandroidlib.conn.routing.HttpRoute, int, + * ch.boye.httpclientandroidlib.protocol.HttpContext) connect} in order to connect + * directly to the target or to the first proxy hop, optionally calling + * {@link #upgrade(ch.boye.httpclientandroidlib.HttpClientConnection, + * ch.boye.httpclientandroidlib.conn.routing.HttpRoute, + * ch.boye.httpclientandroidlib.protocol.HttpContext) upgrade} method to upgrade + * the connection after having executed <code>CONNECT</code> method to + * all intermediate proxy hops and and finally calling {@link #routeComplete( + * ch.boye.httpclientandroidlib.HttpClientConnection, + * ch.boye.httpclientandroidlib.conn.routing.HttpRoute, + * ch.boye.httpclientandroidlib.protocol.HttpContext) routeComplete} to mark the route + * as fully completed. + * + * @param route HTTP route of the requested connection. + * @param state expected state of the connection or <code>null</code> + * if the connection is not expected to carry any state. + */ + ConnectionRequest requestConnection(HttpRoute route, Object state); + + /** + * Releases the connection back to the manager making it potentially + * re-usable by other consumers. Optionally, the maximum period + * of how long the manager should keep the connection alive can be + * defined using <code>validDuration</code> and <code>timeUnit</code> + * parameters. + * + * @param conn the managed connection to release. + * @param validDuration the duration of time this connection is valid for reuse. + * @param timeUnit the time unit. + * + * @see #closeExpiredConnections() + */ + void releaseConnection( + HttpClientConnection conn, Object newState, long validDuration, TimeUnit timeUnit); + + /** + * Connects the underlying connection socket to the connection target in case + * of a direct route or to the first proxy hop in case of a route via a proxy + * (or multiple proxies). + * + * @param conn the managed connection. + * @param route the route of the connection. + * @param connectTimeout connect timeout in milliseconds. + * @param context the actual HTTP context. + * @throws IOException + */ + void connect( + HttpClientConnection conn, + HttpRoute route, + int connectTimeout, + HttpContext context) throws IOException; + + /** + * Upgrades the underlying connection socket to TLS/SSL (or another layering + * protocol) after having executed <code>CONNECT</code> method to all + * intermediate proxy hops + * + * @param conn the managed connection. + * @param route the route of the connection. + * @param context the actual HTTP context. + * @throws IOException + */ + void upgrade( + HttpClientConnection conn, + HttpRoute route, + HttpContext context) throws IOException; + + /** + * Marks the connection as fully established with all its intermediate + * hops completed. + * + * @param conn the managed connection. + * @param route the route of the connection. + * @param context the actual HTTP context. + * @throws IOException + */ + void routeComplete( + HttpClientConnection conn, + HttpRoute route, + HttpContext context) throws IOException; + + /** + * Closes idle connections in the pool. + * <p/> + * Open connections in the pool that have not been used for the + * timespan given by the argument will be closed. + * Currently allocated connections are not subject to this method. + * Times will be checked with milliseconds precision + * + * All expired connections will also be closed. + * + * @param idletime the idle time of connections to be closed + * @param tunit the unit for the <code>idletime</code> + * + * @see #closeExpiredConnections() + */ + void closeIdleConnections(long idletime, TimeUnit tunit); + + /** + * Closes all expired connections in the pool. + * <p/> + * Open connections in the pool that have not been used for + * the timespan defined when the connection was released will be closed. + * Currently allocated connections are not subject to this method. + * Times will be checked with milliseconds precision. + */ + void closeExpiredConnections(); + + /** + * Shuts down this connection manager and releases allocated resources. + * This includes closing all connections, whether they are currently + * used or not. + */ + void shutdown(); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpConnectionFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpConnectionFactory.java new file mode 100644 index 000000000..be910921f --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpConnectionFactory.java @@ -0,0 +1,41 @@ +/* + * ==================================================================== + * 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; + +import ch.boye.httpclientandroidlib.HttpConnection; +import ch.boye.httpclientandroidlib.config.ConnectionConfig; + +/** + * Generic {@link HttpConnection} factory. + * + * @since 4.3 + */ +public interface HttpConnectionFactory<T, C extends HttpConnection> { + + C create(T route, ConnectionConfig config); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpHostConnectException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpHostConnectException.java new file mode 100644 index 000000000..9b1a1c57a --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpHostConnectException.java @@ -0,0 +1,82 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.net.ConnectException; +import java.net.InetAddress; +import java.util.Arrays; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * A {@link ConnectException} that specifies the {@link HttpHost} that was + * being connected to. + * + * @since 4.0 + */ +@Immutable +public class HttpHostConnectException extends ConnectException { + + private static final long serialVersionUID = -3194482710275220224L; + + private final HttpHost host; + + /** + * @deprecated (4.3) use {@link #HttpHostConnectException(java.io.IOException, ch.boye.httpclientandroidlib.HttpHost, + * java.net.InetAddress...)} + */ + @Deprecated + public HttpHostConnectException(final HttpHost host, final ConnectException cause) { + this(cause, host, null); + } + + /** + * Creates a HttpHostConnectException based on original {@link java.io.IOException}. + * + * @since 4.3 + */ + public HttpHostConnectException( + final IOException cause, + final HttpHost host, + final InetAddress... remoteAddresses) { + super("Connect to " + + (host != null ? host.toHostString() : "remote host") + + (remoteAddresses != null && remoteAddresses .length > 0 ? + " " + Arrays.asList(remoteAddresses) : "") + + ((cause != null && cause.getMessage() != null) ? + " failed: " + cause.getMessage() : " refused")); + this.host = host; + initCause(cause); + } + + public HttpHost getHost() { + return this.host; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpInetSocketAddress.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpInetSocketAddress.java new file mode 100644 index 000000000..3bd878d21 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpInetSocketAddress.java @@ -0,0 +1,65 @@ +/* + * ==================================================================== + * 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; + +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * Extended {@link InetSocketAddress} implementation that also provides access to the original + * {@link HttpHost} used to resolve the address. + * + * @since 4.2 no longer used. + * + * @deprecated (4.3) + */ +@Deprecated +public class HttpInetSocketAddress extends InetSocketAddress { + + private static final long serialVersionUID = -6650701828361907957L; + + private final HttpHost httphost; + + public HttpInetSocketAddress(final HttpHost httphost, final InetAddress addr, final int port) { + super(addr, port); + Args.notNull(httphost, "HTTP host"); + this.httphost = httphost; + } + + public HttpHost getHttpHost() { + return this.httphost; + } + + @Override + public String toString() { + return this.httphost.getHostName() + ":" + getPort(); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpRoutedConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpRoutedConnection.java new file mode 100644 index 000000000..956e61208 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/HttpRoutedConnection.java @@ -0,0 +1,81 @@ +/* + * ==================================================================== + * 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; + +import javax.net.ssl.SSLSession; + +import ch.boye.httpclientandroidlib.HttpInetConnection; +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; + +/** + * Interface to access routing information of a client side connection. + * + * @since 4.1 + * + * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}. + */ +@Deprecated +public interface HttpRoutedConnection extends HttpInetConnection { + + /** + * Indicates whether this connection is secure. + * The return value is well-defined only while the connection is open. + * It may change even while the connection is open. + * + * @return <code>true</code> if this connection is secure, + * <code>false</code> otherwise + */ + boolean isSecure(); + + /** + * Obtains the current route of this connection. + * + * @return the route established so far, or + * <code>null</code> if not connected + */ + HttpRoute getRoute(); + + /** + * Obtains the SSL session of the underlying connection, if any. + * If this connection is open, and the underlying socket is an + * {@link javax.net.ssl.SSLSocket SSLSocket}, the SSL session of + * that socket is obtained. This is a potentially blocking operation. + * <br/> + * <b>Note:</b> Whether the underlying socket is an SSL socket + * can not necessarily be determined via {@link #isSecure}. + * Plain sockets may be considered secure, for example if they are + * connected to a known host in the same network segment. + * On the other hand, SSL sockets may be considered insecure, + * for example depending on the chosen cipher suite. + * + * @return the underlying SSL session if available, + * <code>null</code> otherwise + */ + SSLSession getSSLSession(); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedClientConnection.java new file mode 100644 index 000000000..a54567b4f --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedClientConnection.java @@ -0,0 +1,228 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLSession; + +import ch.boye.httpclientandroidlib.HttpClientConnection; +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; +import ch.boye.httpclientandroidlib.params.HttpParams; +import ch.boye.httpclientandroidlib.protocol.HttpContext; + +/** + * A client-side connection with advanced connection logic. + * Instances are typically obtained from a connection manager. + * + * @since 4.0 + * + * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}. + */ +@Deprecated +public interface ManagedClientConnection extends + HttpClientConnection, HttpRoutedConnection, ManagedHttpClientConnection, ConnectionReleaseTrigger { + + /** + * Indicates whether this connection is secure. + * The return value is well-defined only while the connection is open. + * It may change even while the connection is open. + * + * @return <code>true</code> if this connection is secure, + * <code>false</code> otherwise + */ + boolean isSecure(); + + /** + * Obtains the current route of this connection. + * + * @return the route established so far, or + * <code>null</code> if not connected + */ + HttpRoute getRoute(); + + /** + * Obtains the SSL session of the underlying connection, if any. + * If this connection is open, and the underlying socket is an + * {@link javax.net.ssl.SSLSocket SSLSocket}, the SSL session of + * that socket is obtained. This is a potentially blocking operation. + * <br/> + * <b>Note:</b> Whether the underlying socket is an SSL socket + * can not necessarily be determined via {@link #isSecure}. + * Plain sockets may be considered secure, for example if they are + * connected to a known host in the same network segment. + * On the other hand, SSL sockets may be considered insecure, + * for example depending on the chosen cipher suite. + * + * @return the underlying SSL session if available, + * <code>null</code> otherwise + */ + SSLSession getSSLSession(); + + /** + * Opens this connection according to the given route. + * + * @param route the route along which to open. It will be opened to + * the first proxy if present, or directly to the target. + * @param context the context for opening this connection + * @param params the parameters for opening this connection + * + * @throws IOException in case of a problem + */ + void open(HttpRoute route, HttpContext context, HttpParams params) + throws IOException; + + /** + * Indicates that a tunnel to the target has been established. + * The route is the one previously passed to {@link #open open}. + * Subsequently, {@link #layerProtocol layerProtocol} can be called + * to layer the TLS/SSL protocol on top of the tunnelled connection. + * <br/> + * <b>Note:</b> In HttpClient 3, a call to the corresponding method + * would automatically trigger the layering of the TLS/SSL protocol. + * This is not the case anymore, you can establish a tunnel without + * layering a new protocol over the connection. + * + * @param secure <code>true</code> if the tunnel should be considered + * secure, <code>false</code> otherwise + * @param params the parameters for tunnelling this connection + * + * @throws IOException in case of a problem + */ + void tunnelTarget(boolean secure, HttpParams params) + throws IOException; + + /** + * Indicates that a tunnel to an intermediate proxy has been established. + * This is used exclusively for so-called <i>proxy chains</i>, where + * a request has to pass through multiple proxies before reaching the + * target. In that case, all proxies but the last need to be tunnelled + * when establishing the connection. Tunnelling of the last proxy to the + * target is optional and would be indicated via {@link #tunnelTarget}. + * + * @param next the proxy to which the tunnel was established. + * This is <i>not</i> the proxy <i>through</i> which + * the tunnel was established, but the new end point + * of the tunnel. The tunnel does <i>not</i> yet + * reach to the target, use {@link #tunnelTarget} + * to indicate an end-to-end tunnel. + * @param secure <code>true</code> if the connection should be + * considered secure, <code>false</code> otherwise + * @param params the parameters for tunnelling this connection + * + * @throws IOException in case of a problem + */ + void tunnelProxy(HttpHost next, boolean secure, HttpParams params) + throws IOException; + + /** + * Layers a new protocol on top of a {@link #tunnelTarget tunnelled} + * connection. This is typically used to create a TLS/SSL connection + * through a proxy. + * The route is the one previously passed to {@link #open open}. + * It is not guaranteed that the layered connection is + * {@link #isSecure secure}. + * + * @param context the context for layering on top of this connection + * @param params the parameters for layering on top of this connection + * + * @throws IOException in case of a problem + */ + void layerProtocol(HttpContext context, HttpParams params) + throws IOException; + + /** + * Marks this connection as being in a reusable communication state. + * The checkpoints for reuseable communication states (in the absence + * of pipelining) are before sending a request and after receiving + * the response in its entirety. + * The connection will automatically clear the checkpoint when + * used for communication. A call to this method indicates that + * the next checkpoint has been reached. + * <br/> + * A reusable communication state is necessary but not sufficient + * for the connection to be reused. + * A {@link #getRoute route} mismatch, the connection being closed, + * or other circumstances might prevent reuse. + */ + void markReusable(); + + /** + * Marks this connection as not being in a reusable state. + * This can be used immediately before releasing this connection + * to prevent its reuse. Reasons for preventing reuse include + * error conditions and the evaluation of a + * {@link ch.boye.httpclientandroidlib.ConnectionReuseStrategy reuse strategy}. + * <br/> + * <b>Note:</b> + * It is <i>not</i> necessary to call here before writing to + * or reading from this connection. Communication attempts will + * automatically unmark the state as non-reusable. It can then + * be switched back using {@link #markReusable markReusable}. + */ + void unmarkReusable(); + + /** + * Indicates whether this connection is in a reusable communication state. + * See {@link #markReusable markReusable} and + * {@link #unmarkReusable unmarkReusable} for details. + * + * @return <code>true</code> if this connection is marked as being in + * a reusable communication state, + * <code>false</code> otherwise + */ + boolean isMarkedReusable(); + + /** + * Assigns a state object to this connection. Connection managers may make + * use of the connection state when allocating persistent connections. + * + * @param state The state object + */ + void setState(Object state); + + /** + * Returns the state object associated with this connection. + * + * @return The state object + */ + Object getState(); + + /** + * Sets the duration that this connection can remain idle before it is + * reused. The connection should not be used again if this time elapses. The + * idle duration must be reset after each request sent over this connection. + * The elapsed time starts counting when the connection is released, which + * is typically after the headers (and any response body, if present) is + * fully consumed. + */ + void setIdleDuration(long duration, TimeUnit unit); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedHttpClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedHttpClientConnection.java new file mode 100644 index 000000000..4195d59b7 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ManagedHttpClientConnection.java @@ -0,0 +1,80 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.net.Socket; + +import javax.net.ssl.SSLSession; + +import ch.boye.httpclientandroidlib.HttpClientConnection; +import ch.boye.httpclientandroidlib.HttpInetConnection; + +/** + * Represents a managed connection whose state and life cycle is managed by + * a connection manager. This interface extends {@link HttpClientConnection} + * with methods to bind the connection to an arbitrary socket and + * to obtain SSL session details. + * + * @since 4.3 + */ +public interface ManagedHttpClientConnection extends HttpClientConnection, HttpInetConnection { + + /** + * Returns connection ID which is expected to be unique + * for the life span of the connection manager. + */ + String getId(); + + /** + * Binds this connection to the given socket. The connection + * is considered open if it is bound and the underlying socket + * is connection to a remote host. + * + * @param socket the socket to bind the connection to. + * @throws IOException + */ + void bind(Socket socket) throws IOException; + + /** + * Returns the underlying socket. + */ + Socket getSocket(); + + /** + * Obtains the SSL session of the underlying connection, if any. + * If this connection is open, and the underlying socket is an + * {@link javax.net.ssl.SSLSocket SSLSocket}, the SSL session of + * that socket is obtained. This is a potentially blocking operation. + * + * @return the underlying SSL session if available, + * <code>null</code> otherwise + */ + SSLSession getSSLSession(); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/MultihomePlainSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/MultihomePlainSocketFactory.java new file mode 100644 index 000000000..c4c34f769 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/MultihomePlainSocketFactory.java @@ -0,0 +1,173 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.conn.scheme.SocketFactory; +import ch.boye.httpclientandroidlib.params.HttpConnectionParams; +import ch.boye.httpclientandroidlib.params.HttpParams; +import ch.boye.httpclientandroidlib.util.Args; +import ch.boye.httpclientandroidlib.util.Asserts; + +/** + * Socket factory that implements a simple multi-home fail-over on connect failure, + * provided the same hostname resolves to multiple {@link InetAddress}es. Please note + * the {@link #connectSocket(Socket, String, int, InetAddress, int, HttpParams)} + * method cannot be reliably interrupted by closing the socket returned by the + * {@link #createSocket()} method. + * + * @since 4.0 + * + * @deprecated (4.1) Do not use. For multihome support socket factories must implement + * {@link ch.boye.httpclientandroidlib.conn.scheme.SchemeSocketFactory} interface. + */ +@Deprecated +@Immutable +public final class MultihomePlainSocketFactory implements SocketFactory { + + /** + * The factory singleton. + */ + private static final + MultihomePlainSocketFactory DEFAULT_FACTORY = new MultihomePlainSocketFactory(); + + /** + * Gets the singleton instance of this class. + * @return the one and only plain socket factory + */ + public static MultihomePlainSocketFactory getSocketFactory() { + return DEFAULT_FACTORY; + } + + /** + * Restricted default constructor. + */ + private MultihomePlainSocketFactory() { + super(); + } + + + // non-javadoc, see interface ch.boye.httpclientandroidlib.conn.SocketFactory + public Socket createSocket() { + return new Socket(); + } + + /** + * Attempts to connects the socket to any of the {@link InetAddress}es the + * given host name resolves to. If connection to all addresses fail, the + * last I/O exception is propagated to the caller. + * + * @param socket socket to connect to any of the given addresses + * @param host Host name to connect to + * @param port the port to connect to + * @param localAddress local address + * @param localPort local port + * @param params HTTP parameters + * + * @throws IOException if an error occurs during the connection + * @throws SocketTimeoutException if timeout expires before connecting + */ + public Socket connectSocket(final Socket socket, final String host, final int port, + final InetAddress localAddress, final int localPort, + final HttpParams params) + throws IOException { + Args.notNull(host, "Target host"); + Args.notNull(params, "HTTP parameters"); + + Socket sock = socket; + if (sock == null) { + sock = createSocket(); + } + + if ((localAddress != null) || (localPort > 0)) { + final InetSocketAddress isa = new InetSocketAddress(localAddress, + localPort > 0 ? localPort : 0); + sock.bind(isa); + } + + final int timeout = HttpConnectionParams.getConnectionTimeout(params); + + final InetAddress[] inetadrs = InetAddress.getAllByName(host); + final List<InetAddress> addresses = new ArrayList<InetAddress>(inetadrs.length); + addresses.addAll(Arrays.asList(inetadrs)); + Collections.shuffle(addresses); + + IOException lastEx = null; + for (final InetAddress remoteAddress: addresses) { + try { + sock.connect(new InetSocketAddress(remoteAddress, port), timeout); + break; + } catch (final SocketTimeoutException ex) { + throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out"); + } catch (final IOException ex) { + // create new socket + sock = new Socket(); + // keep the last exception and retry + lastEx = ex; + } + } + if (lastEx != null) { + throw lastEx; + } + return sock; + } // connectSocket + + + /** + * Checks whether a socket connection is secure. + * This factory creates plain socket connections + * which are not considered secure. + * + * @param sock the connected socket + * + * @return <code>false</code> + * + * @throws IllegalArgumentException if the argument is invalid + */ + public final boolean isSecure(final Socket sock) + throws IllegalArgumentException { + + Args.notNull(sock, "Socket"); + // This check is performed last since it calls a method implemented + // by the argument object. getClass() is final in java.lang.Object. + Asserts.check(!sock.isClosed(), "Socket is closed"); + return false; + + } // isSecure + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/OperatedClientConnection.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/OperatedClientConnection.java new file mode 100644 index 000000000..3f8df0591 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/OperatedClientConnection.java @@ -0,0 +1,155 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; +import java.net.Socket; + +import ch.boye.httpclientandroidlib.HttpClientConnection; +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.HttpInetConnection; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * A client-side connection that relies on outside logic to connect sockets to the + * appropriate hosts. It can be operated directly by an application, or through an + * {@link ClientConnectionOperator operator}. + * + * @since 4.0 + * + * @deprecated (4.3) replaced by {@link HttpClientConnectionManager}. + */ +@Deprecated +public interface OperatedClientConnection extends HttpClientConnection, HttpInetConnection { + + /** + * Obtains the target host for this connection. + * If the connection is to a proxy but not tunnelled, this is + * the proxy. If the connection is tunnelled through a proxy, + * this is the target of the tunnel. + * <br/> + * The return value is well-defined only while the connection is open. + * It may change even while the connection is open, + * because of an {@link #update update}. + * + * @return the host to which this connection is opened + */ + HttpHost getTargetHost(); + + /** + * Indicates whether this connection is secure. + * The return value is well-defined only while the connection is open. + * It may change even while the connection is open, + * because of an {@link #update update}. + * + * @return <code>true</code> if this connection is secure, + * <code>false</code> otherwise + */ + boolean isSecure(); + + /** + * Obtains the socket for this connection. + * The return value is well-defined only while the connection is open. + * It may change even while the connection is open, + * because of an {@link #update update}. + * + * @return the socket for communicating with the + * {@link #getTargetHost target host} + */ + Socket getSocket(); + + /** + * Signals that this connection is in the process of being open. + * <p> + * By calling this method, the connection can be re-initialized + * with a new Socket instance before {@link #openCompleted} is called. + * This enabled the connection to close that socket if + * {@link ch.boye.httpclientandroidlib.HttpConnection#shutdown shutdown} + * is called before it is fully open. Closing an unconnected socket + * will interrupt a thread that is blocked on the connect. + * Otherwise, that thread will either time out on the connect, + * or it returns successfully and then opens this connection + * which was just shut down. + * <p> + * This method can be called multiple times if the connection + * is layered over another protocol. <b>Note:</b> This method + * will <i>not</i> close the previously used socket. It is + * the caller's responsibility to close that socket if it is + * no longer required. + * <p> + * The caller must invoke {@link #openCompleted} in order to complete + * the process. + * + * @param sock the unconnected socket which is about to + * be connected. + * @param target the target host of this connection + */ + void opening(Socket sock, HttpHost target) + throws IOException; + + /** + * Signals that the connection has been successfully open. + * An attempt to call this method on an open connection will cause + * an exception. + * + * @param secure <code>true</code> if this connection is secure, for + * example if an <code>SSLSocket</code> is used, or + * <code>false</code> if it is not secure + * @param params parameters for this connection. The parameters will + * be used when creating dependent objects, for example + * to determine buffer sizes. + */ + void openCompleted(boolean secure, HttpParams params) + throws IOException; + + /** + * Updates this connection. + * A connection can be updated only while it is open. + * Updates are used for example when a tunnel has been established, + * or when a TLS/SSL connection has been layered on top of a plain + * socket connection. + * <br/> + * <b>Note:</b> Updating the connection will <i>not</i> close the + * previously used socket. It is the caller's responsibility to close + * that socket if it is no longer required. + * + * @param sock the new socket for communicating with the target host, + * or <code>null</code> to continue using the old socket. + * If <code>null</code> is passed, helper objects that + * depend on the socket should be re-used. In that case, + * some changes in the parameters will not take effect. + * @param target the new target host of this connection + * @param secure <code>true</code> if this connection is now secure, + * <code>false</code> if it is not secure + * @param params new parameters for this connection + */ + void update(Socket sock, HttpHost target, + boolean secure, HttpParams params) + throws IOException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/SchemePortResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/SchemePortResolver.java new file mode 100644 index 000000000..10df60f04 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/SchemePortResolver.java @@ -0,0 +1,43 @@ +/* + * ==================================================================== + * 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; + +import ch.boye.httpclientandroidlib.HttpHost; + +/** + * Strategy for default port resolution for protocol schemes. + * + * @since 4.3 + */ +public interface SchemePortResolver { + + /** + * Returns the actual port for the host based on the protocol scheme. + */ + int resolve(HttpHost host) throws UnsupportedSchemeException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/UnsupportedSchemeException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/UnsupportedSchemeException.java new file mode 100644 index 000000000..c8034191e --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/UnsupportedSchemeException.java @@ -0,0 +1,51 @@ +/* + * ==================================================================== + * 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; + +import java.io.IOException; + +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * Signals failure to establish connection using an unknown protocol scheme. + * + * @since 4.3 + */ +@Immutable +public class UnsupportedSchemeException extends IOException { + + private static final long serialVersionUID = 3597127619218687636L; + + /** + * Creates a UnsupportedSchemeException with the specified detail message. + */ + public UnsupportedSchemeException(final String message) { + super(message); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/package-info.java new file mode 100644 index 000000000..6d83f5a8b --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/package-info.java @@ -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 management APIs. + */ +package ch.boye.httpclientandroidlib.conn; diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionPNames.java new file mode 100644 index 000000000..59246459f --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionPNames.java @@ -0,0 +1,64 @@ +/* + * ==================================================================== + * 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.params; + +/** + * Parameter names for HTTP client connections. + * + * @since 4.0 + * + * @deprecated (4.1) use custom {@link + * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation. + */ +@Deprecated +public interface ConnConnectionPNames { + + /** + * Defines the maximum number of ignorable lines before we expect + * a HTTP response's status line. + * <p> + * With HTTP/1.1 persistent connections, the problem arises that + * broken scripts could return a wrong Content-Length + * (there are more bytes sent than specified). + * Unfortunately, in some cases, this cannot be detected after the + * bad response, but only before the next one. + * So HttpClient must be able to skip those surplus lines this way. + * </p> + * <p> + * This parameter expects a value of type {@link Integer}. + * 0 disallows all garbage/empty lines before the status line. + * Use {@link java.lang.Integer#MAX_VALUE} for unlimited number. + * </p> + * + * @deprecated (4.1) Use custom {@link + * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation + */ + @Deprecated + public static final String MAX_STATUS_LINE_GARBAGE = "http.connection.max-status-line-garbage"; + + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionParamBean.java new file mode 100644 index 000000000..8c8b1b2dc --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnConnectionParamBean.java @@ -0,0 +1,59 @@ +/* + * ==================================================================== + * 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.params; + +import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * This is a Java Bean class that can be used to wrap an instance of + * {@link HttpParams} and manipulate HTTP client connection parameters + * using Java Beans conventions. + * + * @since 4.0 + * + * @deprecated (4.1) use custom {@link + * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation. + */ +@Deprecated +public class ConnConnectionParamBean extends HttpAbstractParamBean { + + public ConnConnectionParamBean (final HttpParams params) { + super(params); + } + + /** + * @deprecated (4.2) Use custom {@link + * ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser} implementation + */ + @Deprecated + public void setMaxStatusLineGarbage (final int maxStatusLineGarbage) { + params.setIntParameter(ConnConnectionPNames.MAX_STATUS_LINE_GARBAGE, maxStatusLineGarbage); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerPNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerPNames.java new file mode 100644 index 000000000..16a79ca18 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerPNames.java @@ -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.params; + +/** + * Parameter names for connection managers in HttpConn. + * + * @since 4.0 + * + * @deprecated (4.1) use configuration methods of the specific connection manager implementation. +*/ +@Deprecated +public interface ConnManagerPNames { + + /** + * Defines the timeout in milliseconds used when retrieving an instance of + * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the + * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}. + * <p> + * This parameter expects a value of type {@link Long}. + */ + public static final String TIMEOUT = "http.conn-manager.timeout"; + + /** + * Defines the maximum number of connections per route. + * This limit is interpreted by client connection managers + * and applies to individual manager instances. + * <p> + * This parameter expects a value of type {@link ConnPerRoute}. + * <p> + */ + public static final String MAX_CONNECTIONS_PER_ROUTE = "http.conn-manager.max-per-route"; + + /** + * Defines the maximum number of connections in total. + * This limit is interpreted by client connection managers + * and applies to individual manager instances. + * <p> + * This parameter expects a value of type {@link Integer}. + */ + public static final String MAX_TOTAL_CONNECTIONS = "http.conn-manager.max-total"; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParamBean.java new file mode 100644 index 000000000..735a25360 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParamBean.java @@ -0,0 +1,63 @@ +/* + * ==================================================================== + * 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.params; + +import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; +import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * This is a Java Bean class that can be used to wrap an instance of + * {@link HttpParams} and manipulate connection manager parameters + * using Java Beans conventions. + * + * @since 4.0 + * + * @deprecated (4.1) use configuration methods of the specific connection manager implementation. + */ +@NotThreadSafe +@Deprecated +public class ConnManagerParamBean extends HttpAbstractParamBean { + + public ConnManagerParamBean (final HttpParams params) { + super(params); + } + + public void setTimeout (final long timeout) { + params.setLongParameter(ConnManagerPNames.TIMEOUT, timeout); + } + + public void setMaxTotalConnections (final int maxConnections) { + params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, maxConnections); + } + + public void setConnectionsPerRoute(final ConnPerRouteBean connPerRoute) { + params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, connPerRoute); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParams.java new file mode 100644 index 000000000..e6521134a --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnManagerParams.java @@ -0,0 +1,147 @@ +/* + * ==================================================================== + * 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.params; + +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; +import ch.boye.httpclientandroidlib.params.HttpParams; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * An adaptor for manipulating HTTP connection management + * parameters in {@link HttpParams}. + * + * @since 4.0 + * + * @see ConnManagerPNames + * + * @deprecated (4.1) use configuration methods of the specific connection manager implementation. + */ +@Deprecated +@Immutable +public final class ConnManagerParams implements ConnManagerPNames { + + /** The default maximum number of connections allowed overall */ + public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; + + /** + * Returns the timeout in milliseconds used when retrieving a + * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the + * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}. + * + * @return timeout in milliseconds. + * + * @deprecated (4.1) use {@link + * ch.boye.httpclientandroidlib.params.HttpConnectionParams#getConnectionTimeout(HttpParams)} + */ + @Deprecated + public static long getTimeout(final HttpParams params) { + Args.notNull(params, "HTTP parameters"); + return params.getLongParameter(TIMEOUT, 0); + } + + /** + * Sets the timeout in milliseconds used when retrieving a + * {@link ch.boye.httpclientandroidlib.conn.ManagedClientConnection} from the + * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager}. + * + * @param timeout the timeout in milliseconds + * + * @deprecated (4.1) use {@link + * ch.boye.httpclientandroidlib.params.HttpConnectionParams#setConnectionTimeout(HttpParams, int)} + */ + @Deprecated + public static void setTimeout(final HttpParams params, final long timeout) { + Args.notNull(params, "HTTP parameters"); + params.setLongParameter(TIMEOUT, timeout); + } + + /** The default maximum number of connections allowed per host */ + private static final ConnPerRoute DEFAULT_CONN_PER_ROUTE = new ConnPerRoute() { + + public int getMaxForRoute(final HttpRoute route) { + return ConnPerRouteBean.DEFAULT_MAX_CONNECTIONS_PER_ROUTE; + } + + }; + + /** + * Sets lookup interface for maximum number of connections allowed per route. + * + * @param params HTTP parameters + * @param connPerRoute lookup interface for maximum number of connections allowed + * per route + */ + public static void setMaxConnectionsPerRoute(final HttpParams params, + final ConnPerRoute connPerRoute) { + Args.notNull(params, "HTTP parameters"); + params.setParameter(MAX_CONNECTIONS_PER_ROUTE, connPerRoute); + } + + /** + * Returns lookup interface for maximum number of connections allowed per route. + * + * @param params HTTP parameters + * + * @return lookup interface for maximum number of connections allowed per route. + */ + public static ConnPerRoute getMaxConnectionsPerRoute(final HttpParams params) { + Args.notNull(params, "HTTP parameters"); + ConnPerRoute connPerRoute = (ConnPerRoute) params.getParameter(MAX_CONNECTIONS_PER_ROUTE); + if (connPerRoute == null) { + connPerRoute = DEFAULT_CONN_PER_ROUTE; + } + return connPerRoute; + } + + /** + * Sets the maximum number of connections allowed. + * + * @param params HTTP parameters + * @param maxTotalConnections The maximum number of connections allowed. + */ + public static void setMaxTotalConnections( + final HttpParams params, + final int maxTotalConnections) { + Args.notNull(params, "HTTP parameters"); + params.setIntParameter(MAX_TOTAL_CONNECTIONS, maxTotalConnections); + } + + /** + * Gets the maximum number of connections allowed. + * + * @param params HTTP parameters + * + * @return The maximum number of connections allowed. + */ + public static int getMaxTotalConnections( + final HttpParams params) { + Args.notNull(params, "HTTP parameters"); + return params.getIntParameter(MAX_TOTAL_CONNECTIONS, DEFAULT_MAX_TOTAL_CONNECTIONS); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRoute.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRoute.java new file mode 100644 index 000000000..ebaad93cb --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRoute.java @@ -0,0 +1,46 @@ +/* + * ==================================================================== + * 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.params; + +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; + +/** + * This interface is intended for looking up maximum number of connections + * allowed for a given route. This class can be used by pooling + * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager connection managers} for + * a fine-grained control of connections on a per route basis. + * + * @since 4.0 + * + * @deprecated (4.3) no longer used. + */ +@Deprecated +public interface ConnPerRoute { + + int getMaxForRoute(HttpRoute route); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRouteBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRouteBean.java new file mode 100644 index 000000000..6cc6da8ab --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnPerRouteBean.java @@ -0,0 +1,112 @@ +/* + * ==================================================================== + * 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.params; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import ch.boye.httpclientandroidlib.annotation.ThreadSafe; +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * This class maintains a map of HTTP routes to maximum number of connections allowed + * for those routes. This class can be used by pooling + * {@link ch.boye.httpclientandroidlib.conn.ClientConnectionManager connection managers} for + * a fine-grained control of connections on a per route basis. + * + * @since 4.0 + * + * @deprecated (4.2) use {@link ch.boye.httpclientandroidlib.pool.ConnPoolControl} + */ +@Deprecated +@ThreadSafe +public final class ConnPerRouteBean implements ConnPerRoute { + + /** The default maximum number of connections allowed per host */ + public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; // Per RFC 2616 sec 8.1.4 + + private final ConcurrentHashMap<HttpRoute, Integer> maxPerHostMap; + + private volatile int defaultMax; + + public ConnPerRouteBean(final int defaultMax) { + super(); + this.maxPerHostMap = new ConcurrentHashMap<HttpRoute, Integer>(); + setDefaultMaxPerRoute(defaultMax); + } + + public ConnPerRouteBean() { + this(DEFAULT_MAX_CONNECTIONS_PER_ROUTE); + } + + public int getDefaultMax() { + return this.defaultMax; + } + + /** + * @since 4.1 + */ + public int getDefaultMaxPerRoute() { + return this.defaultMax; + } + + public void setDefaultMaxPerRoute(final int max) { + Args.positive(max, "Defautl max per route"); + this.defaultMax = max; + } + + public void setMaxForRoute(final HttpRoute route, final int max) { + Args.notNull(route, "HTTP route"); + Args.positive(max, "Max per route"); + this.maxPerHostMap.put(route, Integer.valueOf(max)); + } + + public int getMaxForRoute(final HttpRoute route) { + Args.notNull(route, "HTTP route"); + final Integer max = this.maxPerHostMap.get(route); + if (max != null) { + return max.intValue(); + } else { + return this.defaultMax; + } + } + + public void setMaxForRoutes(final Map<HttpRoute, Integer> map) { + if (map == null) { + return; + } + this.maxPerHostMap.clear(); + this.maxPerHostMap.putAll(map); + } + + @Override + public String toString() { + return this.maxPerHostMap.toString(); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRoutePNames.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRoutePNames.java new file mode 100644 index 000000000..083216b14 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRoutePNames.java @@ -0,0 +1,79 @@ +/* + * ==================================================================== + * 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.params; + +/** + * Parameter names for connection routing. + * + * @since 4.0 + * + * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}. + */ +@Deprecated +public interface ConnRoutePNames { + + /** + * Parameter for the default proxy. + * The default value will be used by some + * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner HttpRoutePlanner} + * implementations, in particular the default implementation. + * <p> + * This parameter expects a value of type {@link ch.boye.httpclientandroidlib.HttpHost}. + * </p> + */ + public static final String DEFAULT_PROXY = "http.route.default-proxy"; + + /** + * Parameter for the local address. + * On machines with multiple network interfaces, this parameter + * can be used to select the network interface from which the + * connection originates. + * It will be interpreted by the standard + * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner HttpRoutePlanner} + * implementations, in particular the default implementation. + * <p> + * This parameter expects a value of type {@link java.net.InetAddress}. + * </p> + */ + public static final String LOCAL_ADDRESS = "http.route.local-address"; + + /** + * Parameter for an forced route. + * The forced route will be interpreted by the standard + * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoutePlanner HttpRoutePlanner} + * implementations. + * Instead of computing a route, the given forced route will be + * returned, even if it points to the wrong target host. + * <p> + * This parameter expects a value of type + * {@link ch.boye.httpclientandroidlib.conn.routing.HttpRoute HttpRoute}. + * </p> + */ + public static final String FORCED_ROUTE = "http.route.forced-route"; + +} + diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParamBean.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParamBean.java new file mode 100644 index 000000000..d3018ad0b --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParamBean.java @@ -0,0 +1,70 @@ +/* + * ==================================================================== + * 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.params; + +import java.net.InetAddress; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; +import ch.boye.httpclientandroidlib.params.HttpAbstractParamBean; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * This is a Java Bean class that can be used to wrap an instance of + * {@link HttpParams} and manipulate connection routing parameters + * using Java Beans conventions. + * + * @since 4.0 + * + * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}. + */ +@Deprecated +@NotThreadSafe +public class ConnRouteParamBean extends HttpAbstractParamBean { + + public ConnRouteParamBean (final HttpParams params) { + super(params); + } + + /** @see ConnRoutePNames#DEFAULT_PROXY */ + public void setDefaultProxy (final HttpHost defaultProxy) { + params.setParameter(ConnRoutePNames.DEFAULT_PROXY, defaultProxy); + } + + /** @see ConnRoutePNames#LOCAL_ADDRESS */ + public void setLocalAddress (final InetAddress address) { + params.setParameter(ConnRoutePNames.LOCAL_ADDRESS, address); + } + + /** @see ConnRoutePNames#FORCED_ROUTE */ + public void setForcedRoute (final HttpRoute route) { + params.setParameter(ConnRoutePNames.FORCED_ROUTE, route); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParams.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParams.java new file mode 100644 index 000000000..241953dbd --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/ConnRouteParams.java @@ -0,0 +1,178 @@ +/* + * ==================================================================== + * 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.params; + +import java.net.InetAddress; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.conn.routing.HttpRoute; +import ch.boye.httpclientandroidlib.params.HttpParams; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * An adaptor for manipulating HTTP routing parameters + * in {@link HttpParams}. + * + * @since 4.0 + * + * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.client.config.RequestConfig}. + */ +@Deprecated +@Immutable +public class ConnRouteParams implements ConnRoutePNames { + + /** + * A special value indicating "no host". + * This relies on a nonsense scheme name to avoid conflicts + * with actual hosts. Note that this is a <i>valid</i> host. + */ + public static final HttpHost NO_HOST = + new HttpHost("127.0.0.255", 0, "no-host"); // Immutable + + /** + * A special value indicating "no route". + * This is a route with {@link #NO_HOST} as the target. + */ + public static final HttpRoute NO_ROUTE = new HttpRoute(NO_HOST); // Immutable + + /** Disabled default constructor. */ + private ConnRouteParams() { + // no body + } + + /** + * Obtains the {@link ConnRoutePNames#DEFAULT_PROXY DEFAULT_PROXY} + * parameter value. + * {@link #NO_HOST} will be mapped to <code>null</code>, + * to allow unsetting in a hierarchy. + * + * @param params the parameters in which to look up + * + * @return the default proxy set in the argument parameters, or + * <code>null</code> if not set + */ + public static HttpHost getDefaultProxy(final HttpParams params) { + Args.notNull(params, "Parameters"); + HttpHost proxy = (HttpHost) + params.getParameter(DEFAULT_PROXY); + if ((proxy != null) && NO_HOST.equals(proxy)) { + // value is explicitly unset + proxy = null; + } + return proxy; + } + + /** + * Sets the {@link ConnRoutePNames#DEFAULT_PROXY DEFAULT_PROXY} + * parameter value. + * + * @param params the parameters in which to set the value + * @param proxy the value to set, may be <code>null</code>. + * Note that {@link #NO_HOST} will be mapped to + * <code>null</code> by {@link #getDefaultProxy}, + * to allow for explicit unsetting in hierarchies. + */ + public static void setDefaultProxy(final HttpParams params, + final HttpHost proxy) { + Args.notNull(params, "Parameters"); + params.setParameter(DEFAULT_PROXY, proxy); + } + + /** + * Obtains the {@link ConnRoutePNames#FORCED_ROUTE FORCED_ROUTE} + * parameter value. + * {@link #NO_ROUTE} will be mapped to <code>null</code>, + * to allow unsetting in a hierarchy. + * + * @param params the parameters in which to look up + * + * @return the forced route set in the argument parameters, or + * <code>null</code> if not set + */ + public static HttpRoute getForcedRoute(final HttpParams params) { + Args.notNull(params, "Parameters"); + HttpRoute route = (HttpRoute) + params.getParameter(FORCED_ROUTE); + if ((route != null) && NO_ROUTE.equals(route)) { + // value is explicitly unset + route = null; + } + return route; + } + + /** + * Sets the {@link ConnRoutePNames#FORCED_ROUTE FORCED_ROUTE} + * parameter value. + * + * @param params the parameters in which to set the value + * @param route the value to set, may be <code>null</code>. + * Note that {@link #NO_ROUTE} will be mapped to + * <code>null</code> by {@link #getForcedRoute}, + * to allow for explicit unsetting in hierarchies. + */ + public static void setForcedRoute(final HttpParams params, + final HttpRoute route) { + Args.notNull(params, "Parameters"); + params.setParameter(FORCED_ROUTE, route); + } + + /** + * Obtains the {@link ConnRoutePNames#LOCAL_ADDRESS LOCAL_ADDRESS} + * parameter value. + * There is no special value that would automatically be mapped to + * <code>null</code>. You can use the wildcard address (0.0.0.0 for IPv4, + * :: for IPv6) to override a specific local address in a hierarchy. + * + * @param params the parameters in which to look up + * + * @return the local address set in the argument parameters, or + * <code>null</code> if not set + */ + public static InetAddress getLocalAddress(final HttpParams params) { + Args.notNull(params, "Parameters"); + final InetAddress local = (InetAddress) + params.getParameter(LOCAL_ADDRESS); + // no explicit unsetting + return local; + } + + /** + * Sets the {@link ConnRoutePNames#LOCAL_ADDRESS LOCAL_ADDRESS} + * parameter value. + * + * @param params the parameters in which to set the value + * @param local the value to set, may be <code>null</code> + */ + public static void setLocalAddress(final HttpParams params, + final InetAddress local) { + Args.notNull(params, "Parameters"); + params.setParameter(LOCAL_ADDRESS, local); + } + +} + diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/package-info.java new file mode 100644 index 000000000..32b359e3e --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/params/package-info.java @@ -0,0 +1,32 @@ +/* + * ==================================================================== + * 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/>. + * + */ + +/** + * Deprecated. + * @deprecated (4.3). + */ +package ch.boye.httpclientandroidlib.conn.params; diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java new file mode 100644 index 000000000..9c653eb3c --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/BasicRouteDirector.java @@ -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; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java new file mode 100644 index 000000000..7bf02d14c --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoute.java @@ -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(); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java new file mode 100644 index 000000000..f8b774603 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRouteDirector.java @@ -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); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java new file mode 100644 index 000000000..9e8ba19d3 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/HttpRoutePlanner.java @@ -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; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java new file mode 100644 index 000000000..0784b7894 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteInfo.java @@ -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(); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java new file mode 100644 index 000000000..9a900319c --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/RouteTracker.java @@ -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(); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java new file mode 100644 index 000000000..ddd6b8ae8 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/routing/package-info.java @@ -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; diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/HostNameResolver.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/HostNameResolver.java new file mode 100644 index 000000000..8dcca6902 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/HostNameResolver.java @@ -0,0 +1,52 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.InetAddress; + +/** + * Hostname to IP address resolver. + * + * @since 4.0 + * + * @deprecated (4.1) Do not use + */ +@Deprecated +public interface HostNameResolver { + + /** + * Resolves given hostname to its IP address + * + * @param hostname the hostname. + * @return IP address. + * @throws IOException + */ + InetAddress resolve (String hostname) throws IOException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java new file mode 100644 index 000000000..3833b2360 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java @@ -0,0 +1,68 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * Extended {@link SchemeSocketFactory} interface for layered sockets such as SSL/TLS. + * + * @since 4.1 + * + * @deprecated (4.2) use {@link SchemeLayeredSocketFactory} + */ +@Deprecated +public interface LayeredSchemeSocketFactory extends SchemeSocketFactory { + + /** + * Returns a socket connected to the given host that is layered over an + * existing socket. Used primarily for creating secure sockets through + * proxies. + * + * @param socket the existing socket + * @param target the name of the target host. + * @param port the port to connect to on the target host + * @param autoClose a flag for closing the underling socket when the created + * socket is closed + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + Socket createLayeredSocket( + Socket socket, + String target, + int port, + boolean autoClose + ) throws IOException, UnknownHostException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java new file mode 100644 index 000000000..318e35f9c --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactory.java @@ -0,0 +1,69 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * A {@link SocketFactory SocketFactory} for layered sockets (SSL/TLS). + * See there for things to consider when implementing a socket factory. + * + * @since 4.0 + * + * @deprecated (4.1) use {@link SchemeSocketFactory} + */ +@Deprecated +public interface LayeredSocketFactory extends SocketFactory { + + /** + * Returns a socket connected to the given host that is layered over an + * existing socket. Used primarily for creating secure sockets through + * proxies. + * + * @param socket the existing socket + * @param host the host name/IP + * @param port the port on the host + * @param autoClose a flag for closing the underling socket when the created + * socket is closed + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + Socket createSocket( + Socket socket, + String host, + int port, + boolean autoClose + ) throws IOException, UnknownHostException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java new file mode 100644 index 000000000..11ebd10cb --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java @@ -0,0 +1,53 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @deprecated (4.1) do not use + */ +@Deprecated +class LayeredSocketFactoryAdaptor extends SocketFactoryAdaptor implements LayeredSocketFactory { + + private final LayeredSchemeSocketFactory factory; + + LayeredSocketFactoryAdaptor(final LayeredSchemeSocketFactory factory) { + super(factory); + this.factory = factory; + } + + public Socket createSocket( + final Socket socket, + final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException { + return this.factory.createLayeredSocket(socket, host, port, autoClose); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/PlainSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/PlainSocketFactory.java new file mode 100644 index 000000000..efa8f281b --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/PlainSocketFactory.java @@ -0,0 +1,160 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException; +import ch.boye.httpclientandroidlib.params.HttpConnectionParams; +import ch.boye.httpclientandroidlib.params.HttpParams; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * The default class for creating plain (unencrypted) sockets. + * + * @since 4.0 + * + * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.conn.socket.PlainConnectionSocketFactory} + */ +@Immutable +@Deprecated +public class PlainSocketFactory implements SocketFactory, SchemeSocketFactory { + + private final HostNameResolver nameResolver; + + /** + * Gets the default factory. + * + * @return the default factory + */ + public static PlainSocketFactory getSocketFactory() { + return new PlainSocketFactory(); + } + + /** + * @deprecated (4.1) use {@link ch.boye.httpclientandroidlib.conn.DnsResolver} + */ + @Deprecated + public PlainSocketFactory(final HostNameResolver nameResolver) { + super(); + this.nameResolver = nameResolver; + } + + public PlainSocketFactory() { + super(); + this.nameResolver = null; + } + + /** + * @param params Optional parameters. Parameters passed to this method will have no effect. + * This method will create a unconnected instance of {@link Socket} class + * using default constructor. + * + * @since 4.1 + */ + public Socket createSocket(final HttpParams params) { + return new Socket(); + } + + public Socket createSocket() { + return new Socket(); + } + + /** + * @since 4.1 + */ + public Socket connectSocket( + final Socket socket, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpParams params) throws IOException, ConnectTimeoutException { + Args.notNull(remoteAddress, "Remote address"); + Args.notNull(params, "HTTP parameters"); + Socket sock = socket; + if (sock == null) { + sock = createSocket(); + } + if (localAddress != null) { + sock.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params)); + sock.bind(localAddress); + } + final int connTimeout = HttpConnectionParams.getConnectionTimeout(params); + final int soTimeout = HttpConnectionParams.getSoTimeout(params); + + try { + sock.setSoTimeout(soTimeout); + sock.connect(remoteAddress, connTimeout); + } catch (final SocketTimeoutException ex) { + throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out"); + } + return sock; + } + + /** + * Checks whether a socket connection is secure. + * This factory creates plain socket connections + * which are not considered secure. + * + * @param sock the connected socket + * + * @return <code>false</code> + */ + public final boolean isSecure(final Socket sock) { + return false; + } + + /** + * @deprecated (4.1) Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)} + */ + @Deprecated + public Socket connectSocket( + final Socket socket, + final String host, final int port, + final InetAddress localAddress, final int localPort, + final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { + InetSocketAddress local = null; + if (localAddress != null || localPort > 0) { + local = new InetSocketAddress(localAddress, localPort > 0 ? localPort : 0); + } + final InetAddress remoteAddress; + if (this.nameResolver != null) { + remoteAddress = this.nameResolver.resolve(host); + } else { + remoteAddress = InetAddress.getByName(host); + } + final InetSocketAddress remote = new InetSocketAddress(remoteAddress, port); + return connectSocket(socket, remote, local, params); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/Scheme.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/Scheme.java new file mode 100644 index 000000000..93a44de35 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/Scheme.java @@ -0,0 +1,260 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.util.Locale; + +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.util.Args; +import ch.boye.httpclientandroidlib.util.LangUtils; + +/** + * Encapsulates specifics of a protocol scheme such as "http" or "https". Schemes are identified + * by lowercase names. Supported schemes are typically collected in a {@link SchemeRegistry + * SchemeRegistry}. + * <p/> + * For example, to configure support for "https://" URLs, you could write code like the following: + * <pre> + * Scheme https = new Scheme("https", 443, new MySecureSocketFactory()); + * SchemeRegistry registry = new SchemeRegistry(); + * registry.register(https); + * </pre> + * + * @since 4.0 + * + * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.conn.SchemePortResolver} for default port + * resolution and {@link ch.boye.httpclientandroidlib.config.Registry} for socket factory lookups. + */ +@Immutable +@Deprecated +public final class Scheme { + + /** The name of this scheme, in lowercase. (e.g. http, https) */ + private final String name; + + /** The socket factory for this scheme */ + private final SchemeSocketFactory socketFactory; + + /** The default port for this scheme */ + private final int defaultPort; + + /** Indicates whether this scheme allows for layered connections */ + private final boolean layered; + + /** A string representation, for {@link #toString toString}. */ + private String stringRep; + /* + * This is used to cache the result of the toString() method + * Since the method always generates the same value, there's no + * need to synchronize, and it does not affect immutability. + */ + + /** + * Creates a new scheme. + * Whether the created scheme allows for layered connections + * depends on the class of <code>factory</code>. + * + * @param name the scheme name, for example "http". + * The name will be converted to lowercase. + * @param port the default port for this scheme + * @param factory the factory for creating sockets for communication + * with this scheme + * + * @since 4.1 + */ + public Scheme(final String name, final int port, final SchemeSocketFactory factory) { + Args.notNull(name, "Scheme name"); + Args.check(port > 0 && port <= 0xffff, "Port is invalid"); + Args.notNull(factory, "Socket factory"); + this.name = name.toLowerCase(Locale.ENGLISH); + this.defaultPort = port; + if (factory instanceof SchemeLayeredSocketFactory) { + this.layered = true; + this.socketFactory = factory; + } else if (factory instanceof LayeredSchemeSocketFactory) { + this.layered = true; + this.socketFactory = new SchemeLayeredSocketFactoryAdaptor2((LayeredSchemeSocketFactory) factory); + } else { + this.layered = false; + this.socketFactory = factory; + } + } + + /** + * Creates a new scheme. + * Whether the created scheme allows for layered connections + * depends on the class of <code>factory</code>. + * + * @param name the scheme name, for example "http". + * The name will be converted to lowercase. + * @param factory the factory for creating sockets for communication + * with this scheme + * @param port the default port for this scheme + * + * @deprecated (4.1) Use {@link #Scheme(String, int, SchemeSocketFactory)} + */ + @Deprecated + public Scheme(final String name, + final SocketFactory factory, + final int port) { + + Args.notNull(name, "Scheme name"); + Args.notNull(factory, "Socket factory"); + Args.check(port > 0 && port <= 0xffff, "Port is invalid"); + + this.name = name.toLowerCase(Locale.ENGLISH); + if (factory instanceof LayeredSocketFactory) { + this.socketFactory = new SchemeLayeredSocketFactoryAdaptor( + (LayeredSocketFactory) factory); + this.layered = true; + } else { + this.socketFactory = new SchemeSocketFactoryAdaptor(factory); + this.layered = false; + } + this.defaultPort = port; + } + + /** + * Obtains the default port. + * + * @return the default port for this scheme + */ + public final int getDefaultPort() { + return defaultPort; + } + + + /** + * Obtains the socket factory. + * If this scheme is {@link #isLayered layered}, the factory implements + * {@link LayeredSocketFactory LayeredSocketFactory}. + * + * @return the socket factory for this scheme + * + * @deprecated (4.1) Use {@link #getSchemeSocketFactory()} + */ + @Deprecated + public final SocketFactory getSocketFactory() { + if (this.socketFactory instanceof SchemeSocketFactoryAdaptor) { + return ((SchemeSocketFactoryAdaptor) this.socketFactory).getFactory(); + } else { + if (this.layered) { + return new LayeredSocketFactoryAdaptor( + (LayeredSchemeSocketFactory) this.socketFactory); + } else { + return new SocketFactoryAdaptor(this.socketFactory); + } + } + } + + /** + * Obtains the socket factory. + * If this scheme is {@link #isLayered layered}, the factory implements + * {@link LayeredSocketFactory LayeredSchemeSocketFactory}. + * + * @return the socket factory for this scheme + * + * @since 4.1 + */ + public final SchemeSocketFactory getSchemeSocketFactory() { + return this.socketFactory; + } + + /** + * Obtains the scheme name. + * + * @return the name of this scheme, in lowercase + */ + public final String getName() { + return name; + } + + /** + * Indicates whether this scheme allows for layered connections. + * + * @return <code>true</code> if layered connections are possible, + * <code>false</code> otherwise + */ + public final boolean isLayered() { + return layered; + } + + /** + * Resolves the correct port for this scheme. + * Returns the given port if it is valid, the default port otherwise. + * + * @param port the port to be resolved, + * a negative number to obtain the default port + * + * @return the given port or the defaultPort + */ + public final int resolvePort(final int port) { + return port <= 0 ? defaultPort : port; + } + + /** + * Return a string representation of this object. + * + * @return a human-readable string description of this scheme + */ + @Override + public final String toString() { + if (stringRep == null) { + final StringBuilder buffer = new StringBuilder(); + buffer.append(this.name); + buffer.append(':'); + buffer.append(Integer.toString(this.defaultPort)); + stringRep = buffer.toString(); + } + return stringRep; + } + + @Override + public final boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof Scheme) { + final Scheme that = (Scheme) obj; + return this.name.equals(that.name) + && this.defaultPort == that.defaultPort + && this.layered == that.layered; + } else { + return false; + } + } + + @Override + public int hashCode() { + int hash = LangUtils.HASH_SEED; + hash = LangUtils.hashCode(hash, this.defaultPort); + hash = LangUtils.hashCode(hash, this.name); + hash = LangUtils.hashCode(hash, this.layered); + return hash; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactory.java new file mode 100644 index 000000000..b20ada328 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactory.java @@ -0,0 +1,69 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * Extended {@link SchemeSocketFactory} interface for layered sockets such as SSL/TLS. + * + * @since 4.2 + * + * @deprecated (4.3) use {@link + * ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory} + */ +@Deprecated +public interface SchemeLayeredSocketFactory extends SchemeSocketFactory { + + /** + * Returns a socket connected to the given host that is layered over an + * existing socket. Used primarily for creating secure sockets through + * proxies. + * + * @param socket the existing socket + * @param target the name of the target host. + * @param port the port to connect to on the target host + * @param params HTTP parameters + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + Socket createLayeredSocket( + Socket socket, + String target, + int port, + HttpParams params) throws IOException, UnknownHostException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor.java new file mode 100644 index 000000000..098f55d9a --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor.java @@ -0,0 +1,57 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * @deprecated (4.2) do not use + */ +@Deprecated +class SchemeLayeredSocketFactoryAdaptor extends SchemeSocketFactoryAdaptor + implements SchemeLayeredSocketFactory { + + private final LayeredSocketFactory factory; + + SchemeLayeredSocketFactoryAdaptor(final LayeredSocketFactory factory) { + super(factory); + this.factory = factory; + } + + public Socket createLayeredSocket( + final Socket socket, + final String target, final int port, + final HttpParams params) throws IOException, UnknownHostException { + return this.factory.createSocket(socket, target, port, true); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor2.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor2.java new file mode 100644 index 000000000..97f0442d7 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeLayeredSocketFactoryAdaptor2.java @@ -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.scheme; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * @deprecated (4.2) do not use + */ +@Deprecated +class SchemeLayeredSocketFactoryAdaptor2 implements SchemeLayeredSocketFactory { + + private final LayeredSchemeSocketFactory factory; + + SchemeLayeredSocketFactoryAdaptor2(final LayeredSchemeSocketFactory factory) { + super(); + this.factory = factory; + } + + public Socket createSocket(final HttpParams params) throws IOException { + return this.factory.createSocket(params); + } + + public Socket connectSocket( + final Socket sock, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { + return this.factory.connectSocket(sock, remoteAddress, localAddress, params); + } + + public boolean isSecure(final Socket sock) throws IllegalArgumentException { + return this.factory.isSecure(sock); + } + + public Socket createLayeredSocket( + final Socket socket, + final String target, final int port, + final HttpParams params) throws IOException, UnknownHostException { + return this.factory.createLayeredSocket(socket, target, port, true); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeRegistry.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeRegistry.java new file mode 100644 index 000000000..ef87c809d --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeRegistry.java @@ -0,0 +1,168 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.ThreadSafe; +import ch.boye.httpclientandroidlib.util.Args; + +/** + * A set of supported protocol {@link Scheme}s. + * Schemes are identified by lowercase names. + * + * @since 4.0 + * + * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.config.Registry} + */ +@ThreadSafe +@Deprecated +public final class SchemeRegistry { + + /** The available schemes in this registry. */ + private final ConcurrentHashMap<String,Scheme> registeredSchemes; + + /** + * Creates a new, empty scheme registry. + */ + public SchemeRegistry() { + super(); + registeredSchemes = new ConcurrentHashMap<String,Scheme>(); + } + + /** + * Obtains a scheme by name. + * + * @param name the name of the scheme to look up (in lowercase) + * + * @return the scheme, never <code>null</code> + * + * @throws IllegalStateException + * if the scheme with the given name is not registered + */ + public final Scheme getScheme(final String name) { + final Scheme found = get(name); + if (found == null) { + throw new IllegalStateException + ("Scheme '"+name+"' not registered."); + } + return found; + } + + /** + * Obtains the scheme for a host. + * Convenience method for <code>getScheme(host.getSchemeName())</pre> + * + * @param host the host for which to obtain the scheme + * + * @return the scheme for the given host, never <code>null</code> + * + * @throws IllegalStateException + * if a scheme with the respective name is not registered + */ + public final Scheme getScheme(final HttpHost host) { + Args.notNull(host, "Host"); + return getScheme(host.getSchemeName()); + } + + /** + * Obtains a scheme by name, if registered. + * + * @param name the name of the scheme to look up (in lowercase) + * + * @return the scheme, or + * <code>null</code> if there is none by this name + */ + public final Scheme get(final String name) { + Args.notNull(name, "Scheme name"); + // leave it to the caller to use the correct name - all lowercase + //name = name.toLowerCase(Locale.ENGLISH); + final Scheme found = registeredSchemes.get(name); + return found; + } + + /** + * Registers a scheme. + * The scheme can later be retrieved by its name + * using {@link #getScheme(String) getScheme} or {@link #get get}. + * + * @param sch the scheme to register + * + * @return the scheme previously registered with that name, or + * <code>null</code> if none was registered + */ + public final Scheme register(final Scheme sch) { + Args.notNull(sch, "Scheme"); + final Scheme old = registeredSchemes.put(sch.getName(), sch); + return old; + } + + /** + * Unregisters a scheme. + * + * @param name the name of the scheme to unregister (in lowercase) + * + * @return the unregistered scheme, or + * <code>null</code> if there was none + */ + public final Scheme unregister(final String name) { + Args.notNull(name, "Scheme name"); + // leave it to the caller to use the correct name - all lowercase + //name = name.toLowerCase(Locale.ENGLISH); + final Scheme gone = registeredSchemes.remove(name); + return gone; + } + + /** + * Obtains the names of the registered schemes. + * + * @return List containing registered scheme names. + */ + public final List<String> getSchemeNames() { + return new ArrayList<String>(registeredSchemes.keySet()); + } + + /** + * Populates the internal collection of registered {@link Scheme protocol schemes} + * with the content of the map passed as a parameter. + * + * @param map protocol schemes + */ + public void setItems(final Map<String, Scheme> map) { + if (map == null) { + return; + } + registeredSchemes.clear(); + registeredSchemes.putAll(map); + } + +} + diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java new file mode 100644 index 000000000..81cac0ed1 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactory.java @@ -0,0 +1,130 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * A factory for creating, initializing and connecting sockets. The factory encapsulates the logic + * for establishing a socket connection. + * + * @since 4.1 + * + * @deprecated (4.3) use {@link ch.boye.httpclientandroidlib.conn.socket.ConnectionSocketFactory} + */ +@Deprecated +public interface SchemeSocketFactory { + + /** + * Creates a new, unconnected socket. The socket should subsequently be passed to + * {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}. + * + * @param params Optional {@link HttpParams parameters}. In most cases these parameters + * will not be required and will have no effect, as usually socket + * initialization should take place in the + * {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)} + * method. However, in rare cases one may want to pass additional parameters + * to this method in order to create a customized {@link Socket} instance, + * for instance bound to a SOCKS proxy server. + * + * @return a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + */ + Socket createSocket(HttpParams params) throws IOException; + + /** + * Connects a socket to the target host with the given remote address. + * <p/> + * Please note that {@link ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress} class should + * be used in order to pass the target remote address along with the original + * {@link ch.boye.httpclientandroidlib.HttpHost} value used to resolve the address. The use of + * {@link ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress} can also ensure that no reverse + * DNS lookup will be performed if the target remote address was specified + * as an IP address. + * + * @param sock the socket to connect, as obtained from + * {@link #createSocket(HttpParams) createSocket}. + * <code>null</code> indicates that a new socket + * should be created and connected. + * @param remoteAddress the remote address to connect to. + * @param localAddress the local address to bind the socket to, or + * <code>null</code> for any + * @param params additional {@link HttpParams parameters} for connecting + * + * @return the connected socket. The returned object may be different + * from the <code>sock</code> argument if this factory supports + * a layered protocol. + * + * @throws IOException if an I/O error occurs + * @throws UnknownHostException if the IP address of the target host + * can not be determined + * @throws ConnectTimeoutException if the socket cannot be connected + * within the time limit defined in the <code>params</code> + * + * @see ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress + */ + Socket connectSocket( + Socket sock, + InetSocketAddress remoteAddress, + InetSocketAddress localAddress, + HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException; + + /** + * Checks whether a socket provides a secure connection. The socket must be + * {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams) connected} + * by this factory. The factory will <i>not</i> perform I/O operations in this method. + * <p> + * As a rule of thumb, plain sockets are not secure and TLS/SSL sockets are secure. However, + * there may be application specific deviations. For example, a plain socket to a host in the + * same intranet ("trusted zone") could be considered secure. On the other hand, a TLS/SSL + * socket could be considered insecure based on the cipher suite chosen for the connection. + * + * @param sock the connected socket to check + * + * @return <code>true</code> if the connection of the socket + * should be considered secure, or + * <code>false</code> if it should not + * + * @throws IllegalArgumentException + * if the argument is invalid, for example because it is + * not a connected socket or was created by a different + * socket factory. + * Note that socket factories are <i>not</i> required to + * check these conditions, they may simply return a default + * value when called with an invalid socket argument. + */ + boolean isSecure(Socket sock) throws IllegalArgumentException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java new file mode 100644 index 000000000..85ff5e6b2 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java @@ -0,0 +1,100 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * @deprecated (4.1) do not use + */ +@Deprecated +class SchemeSocketFactoryAdaptor implements SchemeSocketFactory { + + private final SocketFactory factory; + + SchemeSocketFactoryAdaptor(final SocketFactory factory) { + super(); + this.factory = factory; + } + + public Socket connectSocket( + final Socket sock, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { + final String host = remoteAddress.getHostName(); + final int port = remoteAddress.getPort(); + InetAddress local = null; + int localPort = 0; + if (localAddress != null) { + local = localAddress.getAddress(); + localPort = localAddress.getPort(); + } + return this.factory.connectSocket(sock, host, port, local, localPort, params); + } + + public Socket createSocket(final HttpParams params) throws IOException { + return this.factory.createSocket(); + } + + public boolean isSecure(final Socket sock) throws IllegalArgumentException { + return this.factory.isSecure(sock); + } + + public SocketFactory getFactory() { + return this.factory; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (obj instanceof SchemeSocketFactoryAdaptor) { + return this.factory.equals(((SchemeSocketFactoryAdaptor)obj).factory); + } else { + return this.factory.equals(obj); + } + } + + @Override + public int hashCode() { + return this.factory.hashCode(); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactory.java new file mode 100644 index 000000000..71960194b --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactory.java @@ -0,0 +1,127 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException; +import ch.boye.httpclientandroidlib.params.HttpParams; + +/** + * A factory for creating, initializing and connecting sockets. + * The factory encapsulates the logic for establishing a socket connection. + * + * @since 4.0 + * + * @deprecated (4.1) use {@link SchemeSocketFactory} + */ +@Deprecated +public interface SocketFactory { + + /** + * Creates a new, unconnected socket. + * The socket should subsequently be passed to + * {@link #connectSocket connectSocket}. + * + * @return a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + */ + Socket createSocket() + throws IOException; + + /** + * Connects a socket to the given host. + * + * @param sock the socket to connect, as obtained from + * {@link #createSocket createSocket}. + * <code>null</code> indicates that a new socket + * should be created and connected. + * @param host the host to connect to + * @param port the port to connect to on the host + * @param localAddress the local address to bind the socket to, or + * <code>null</code> for any + * @param localPort the port on the local machine, + * 0 or a negative number for any + * @param params additional {@link HttpParams parameters} for connecting + * + * @return the connected socket. The returned object may be different + * from the <code>sock</code> argument if this factory supports + * a layered protocol. + * + * @throws IOException if an I/O error occurs + * @throws UnknownHostException if the IP address of the target host + * can not be determined + * @throws ConnectTimeoutException if the socket cannot be connected + * within the time limit defined in the <code>params</code> + */ + Socket connectSocket( + Socket sock, + String host, + int port, + InetAddress localAddress, + int localPort, + HttpParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException; + + /** + * Checks whether a socket provides a secure connection. + * The socket must be {@link #connectSocket connected} + * by this factory. + * The factory will <i>not</i> perform I/O operations + * in this method. + * <br/> + * As a rule of thumb, plain sockets are not secure and + * TLS/SSL sockets are secure. However, there may be + * application specific deviations. For example, a plain + * socket to a host in the same intranet ("trusted zone") + * could be considered secure. On the other hand, a + * TLS/SSL socket could be considered insecure based on + * the cipher suite chosen for the connection. + * + * @param sock the connected socket to check + * + * @return <code>true</code> if the connection of the socket + * should be considered secure, or + * <code>false</code> if it should not + * + * @throws IllegalArgumentException + * if the argument is invalid, for example because it is + * not a connected socket or was created by a different + * socket factory. + * Note that socket factories are <i>not</i> required to + * check these conditions, they may simply return a default + * value when called with an invalid socket argument. + */ + boolean isSecure(Socket sock) + throws IllegalArgumentException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java new file mode 100644 index 000000000..0e9aab355 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java @@ -0,0 +1,97 @@ +/* + * ==================================================================== + * 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.scheme; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException; +import ch.boye.httpclientandroidlib.params.BasicHttpParams; +import ch.boye.httpclientandroidlib.params.HttpParams; + +@Deprecated +class SocketFactoryAdaptor implements SocketFactory { + + private final SchemeSocketFactory factory; + + SocketFactoryAdaptor(final SchemeSocketFactory factory) { + super(); + this.factory = factory; + } + + public Socket createSocket() throws IOException { + final HttpParams params = new BasicHttpParams(); + return this.factory.createSocket(params); + } + + public Socket connectSocket( + final Socket socket, + final String host, final int port, + final InetAddress localAddress, final int localPort, + final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { + InetSocketAddress local = null; + if (localAddress != null || localPort > 0) { + local = new InetSocketAddress(localAddress, localPort > 0 ? localPort : 0); + } + final InetAddress remoteAddress = InetAddress.getByName(host); + final InetSocketAddress remote = new InetSocketAddress(remoteAddress, port); + return this.factory.connectSocket(socket, remote, local, params); + } + + public boolean isSecure(final Socket socket) throws IllegalArgumentException { + return this.factory.isSecure(socket); + } + + public SchemeSocketFactory getFactory() { + return this.factory; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (this == obj) { + return true; + } + if (obj instanceof SocketFactoryAdaptor) { + return this.factory.equals(((SocketFactoryAdaptor)obj).factory); + } else { + return this.factory.equals(obj); + } + } + + @Override + public int hashCode() { + return this.factory.hashCode(); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/package-info.java new file mode 100644 index 000000000..2e6409084 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/scheme/package-info.java @@ -0,0 +1,32 @@ +/* + * ==================================================================== + * 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/>. + * + */ + +/** + * Deprecated. + * @deprecated (4.3). + */ +package ch.boye.httpclientandroidlib.conn.scheme; diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/ConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/ConnectionSocketFactory.java new file mode 100644 index 000000000..98274f213 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/ConnectionSocketFactory.java @@ -0,0 +1,80 @@ +/* + * ==================================================================== + * 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.socket; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.protocol.HttpContext; + +/** + * A factory for creating and connecting connection sockets. + * + * @since 4.3 + */ +public interface ConnectionSocketFactory { + + /** + * Creates new, unconnected socket. The socket should subsequently be passed to + * {@link #connectSocket(int, Socket, HttpHost, InetSocketAddress, InetSocketAddress, + * HttpContext) connectSocket} method. + * + * @return a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + */ + Socket createSocket(HttpContext context) throws IOException; + + /** + * Connects the socket to the target host with the given resolved remote address. + * + * @param connectTimeout connect timeout. + * @param sock the socket to connect, as obtained from {@link #createSocket(HttpContext)}. + * <code>null</code> indicates that a new socket should be created and connected. + * @param host target host as specified by the caller (end user). + * @param remoteAddress the resolved remote address to connect to. + * @param localAddress the local address to bind the socket to, or <code>null</code> for any. + * @param context the actual HTTP context. + * + * @return the connected socket. The returned object may be different + * from the <code>sock</code> argument if this factory supports + * a layered protocol. + * + * @throws IOException if an I/O error occurs + */ + Socket connectSocket( + int connectTimeout, + Socket sock, + HttpHost host, + InetSocketAddress remoteAddress, + InetSocketAddress localAddress, + HttpContext context) throws IOException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/LayeredConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/LayeredConnectionSocketFactory.java new file mode 100644 index 000000000..40c54f8fa --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/LayeredConnectionSocketFactory.java @@ -0,0 +1,63 @@ +/* + * ==================================================================== + * 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.socket; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +import ch.boye.httpclientandroidlib.protocol.HttpContext; + +/** + * Extended {@link ConnectionSocketFactory} interface for layered sockets such as SSL/TLS. + * + * @since 4.3 + */ +public interface LayeredConnectionSocketFactory extends ConnectionSocketFactory { + + /** + * Returns a socket connected to the given host that is layered over an + * existing socket. Used primarily for creating secure sockets through + * proxies. + * + * @param socket the existing socket + * @param target the name of the target host. + * @param port the port to connect to on the target host. + * @param context the actual HTTP context. + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + */ + Socket createLayeredSocket( + Socket socket, + String target, + int port, + HttpContext context) throws IOException, UnknownHostException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/PlainConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/PlainConnectionSocketFactory.java new file mode 100644 index 000000000..d8fa807c5 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/PlainConnectionSocketFactory.java @@ -0,0 +1,83 @@ +/* + * ==================================================================== + * 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.socket; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.protocol.HttpContext; + +/** + * The default class for creating plain (unencrypted) sockets. + * + * @since 4.3 + */ +@Immutable +public class PlainConnectionSocketFactory implements ConnectionSocketFactory { + + public static final PlainConnectionSocketFactory INSTANCE = new PlainConnectionSocketFactory(); + + public static PlainConnectionSocketFactory getSocketFactory() { + return INSTANCE; + } + + public PlainConnectionSocketFactory() { + super(); + } + + public Socket createSocket(final HttpContext context) throws IOException { + return new Socket(); + } + + public Socket connectSocket( + final int connectTimeout, + final Socket socket, + final HttpHost host, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpContext context) throws IOException { + final Socket sock = socket != null ? socket : createSocket(context); + if (localAddress != null) { + sock.bind(localAddress); + } + try { + sock.connect(remoteAddress, connectTimeout); + } catch (final IOException ex) { + try { + sock.close(); + } catch (final IOException ignore) { + } + throw ex; + } + return sock; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/package-info.java new file mode 100644 index 000000000..fb73d60de --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/socket/package-info.java @@ -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 socket APIs. + */ +package ch.boye.httpclientandroidlib.conn.socket; diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AbstractVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AbstractVerifier.java new file mode 100644 index 000000000..24a7b40a8 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AbstractVerifier.java @@ -0,0 +1,386 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.cert.Certificate; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.NoSuchElementException; + +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; + +import ch.boye.httpclientandroidlib.androidextra.HttpClientAndroidLog; +/* LogFactory removed by HttpClient for Android script. */ +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.conn.util.InetAddressUtils; +import ch.boye.httpclientandroidlib.util.TextUtils; + +import ch.boye.httpclientandroidlib.NameValuePair; + + +/** + * Abstract base class for all standard {@link X509HostnameVerifier} + * implementations. + * + * @since 4.0 + */ +@Immutable +public abstract class AbstractVerifier implements X509HostnameVerifier { + + /** + * This contains a list of 2nd-level domains that aren't allowed to + * have wildcards when combined with country-codes. + * For example: [*.co.uk]. + * <p/> + * The [*.co.uk] problem is an interesting one. Should we just hope + * that CA's would never foolishly allow such a certificate to happen? + * Looks like we're the only implementation guarding against this. + * Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check. + */ + private final static String[] BAD_COUNTRY_2LDS = + { "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info", + "lg", "ne", "net", "or", "org" }; + + static { + // Just in case developer forgot to manually sort the array. :-) + Arrays.sort(BAD_COUNTRY_2LDS); + } + + public HttpClientAndroidLog log = new HttpClientAndroidLog(getClass()); + + public AbstractVerifier() { + super(); + } + + public final void verify(final String host, final SSLSocket ssl) + throws IOException { + if(host == null) { + throw new NullPointerException("host to verify is null"); + } + + SSLSession session = ssl.getSession(); + if(session == null) { + // In our experience this only happens under IBM 1.4.x when + // spurious (unrelated) certificates show up in the server' + // chain. Hopefully this will unearth the real problem: + final InputStream in = ssl.getInputStream(); + in.available(); + /* + If you're looking at the 2 lines of code above because + you're running into a problem, you probably have two + options: + + #1. Clean up the certificate chain that your server + is presenting (e.g. edit "/etc/apache2/server.crt" + or wherever it is your server's certificate chain + is defined). + + OR + + #2. Upgrade to an IBM 1.5.x or greater JVM, or switch + to a non-IBM JVM. + */ + + // If ssl.getInputStream().available() didn't cause an + // exception, maybe at least now the session is available? + session = ssl.getSession(); + if(session == null) { + // If it's still null, probably a startHandshake() will + // unearth the real problem. + ssl.startHandshake(); + + // Okay, if we still haven't managed to cause an exception, + // might as well go for the NPE. Or maybe we're okay now? + session = ssl.getSession(); + } + } + + final Certificate[] certs = session.getPeerCertificates(); + final X509Certificate x509 = (X509Certificate) certs[0]; + verify(host, x509); + } + + public final boolean verify(final String host, final SSLSession session) { + try { + final Certificate[] certs = session.getPeerCertificates(); + final X509Certificate x509 = (X509Certificate) certs[0]; + verify(host, x509); + return true; + } + catch(final SSLException e) { + return false; + } + } + + public final void verify(final String host, final X509Certificate cert) + throws SSLException { + final String[] cns = getCNs(cert); + final String[] subjectAlts = getSubjectAlts(cert, host); + verify(host, cns, subjectAlts); + } + + public final void verify(final String host, final String[] cns, + final String[] subjectAlts, + final boolean strictWithSubDomains) + throws SSLException { + + // Build the list of names we're going to check. Our DEFAULT and + // STRICT implementations of the HostnameVerifier only use the + // first CN provided. All other CNs are ignored. + // (Firefox, wget, curl, Sun Java 1.4, 5, 6 all work this way). + final LinkedList<String> names = new LinkedList<String>(); + if(cns != null && cns.length > 0 && cns[0] != null) { + names.add(cns[0]); + } + if(subjectAlts != null) { + for (final String subjectAlt : subjectAlts) { + if (subjectAlt != null) { + names.add(subjectAlt); + } + } + } + + if(names.isEmpty()) { + final String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt"; + throw new SSLException(msg); + } + + // StringBuilder for building the error message. + final StringBuilder buf = new StringBuilder(); + + // We're can be case-insensitive when comparing the host we used to + // establish the socket to the hostname in the certificate. + final String hostName = normaliseIPv6Address(host.trim().toLowerCase(Locale.ENGLISH)); + boolean match = false; + for(final Iterator<String> it = names.iterator(); it.hasNext();) { + // Don't trim the CN, though! + String cn = it.next(); + cn = cn.toLowerCase(Locale.ENGLISH); + // Store CN in StringBuilder in case we need to report an error. + buf.append(" <"); + buf.append(cn); + buf.append('>'); + if(it.hasNext()) { + buf.append(" OR"); + } + + // The CN better have at least two dots if it wants wildcard + // action. It also can't be [*.co.uk] or [*.co.jp] or + // [*.org.uk], etc... + final String parts[] = cn.split("\\."); + final boolean doWildcard = + parts.length >= 3 && parts[0].endsWith("*") && + validCountryWildcard(cn) && !isIPAddress(host); + + if(doWildcard) { + final String firstpart = parts[0]; + if (firstpart.length() > 1) { // e.g. server* + final String prefix = firstpart.substring(0, firstpart.length() - 1); // e.g. server + final String suffix = cn.substring(firstpart.length()); // skip wildcard part from cn + final String hostSuffix = hostName.substring(prefix.length()); // skip wildcard part from host + match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix); + } else { + match = hostName.endsWith(cn.substring(1)); + } + if(match && strictWithSubDomains) { + // If we're in strict mode, then [*.foo.com] is not + // allowed to match [a.b.foo.com] + match = countDots(hostName) == countDots(cn); + } + } else { + match = hostName.equals(normaliseIPv6Address(cn)); + } + if(match) { + break; + } + } + if(!match) { + throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf); + } + } + + /** + * @deprecated (4.3.1) should not be a part of public APIs. + */ + @Deprecated + public static boolean acceptableCountryWildcard(final String cn) { + final String parts[] = cn.split("\\."); + if (parts.length != 3 || parts[2].length() != 2) { + return true; // it's not an attempt to wildcard a 2TLD within a country code + } + return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0; + } + + boolean validCountryWildcard(final String cn) { + final String parts[] = cn.split("\\."); + if (parts.length != 3 || parts[2].length() != 2) { + return true; // it's not an attempt to wildcard a 2TLD within a country code + } + return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0; + } + + public static String[] getCNs(final X509Certificate cert) { + final String subjectPrincipal = cert.getSubjectX500Principal().toString(); + try { + return extractCNs(subjectPrincipal); + } catch (SSLException ex) { + return null; + } + } + + static String[] extractCNs(final String subjectPrincipal) throws SSLException { + if (subjectPrincipal == null) { + return null; + } + final List<String> cns = new ArrayList<String>(); + final List<NameValuePair> nvps = DistinguishedNameParser.INSTANCE.parse(subjectPrincipal); + for (int i = 0; i < nvps.size(); i++) { + final NameValuePair nvp = nvps.get(i); + final String attribName = nvp.getName(); + final String attribValue = nvp.getValue(); + if (TextUtils.isBlank(attribValue)) { + throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name"); + } + if (attribName.equalsIgnoreCase("cn")) { + cns.add(attribValue); + } + } + return cns.isEmpty() ? null : cns.toArray(new String[ cns.size() ]); + } + + /** + * Extracts the array of SubjectAlt DNS or IP names from an X509Certificate. + * Returns null if there aren't any. + * + * @param cert X509Certificate + * @param hostname + * @return Array of SubjectALT DNS or IP names stored in the certificate. + */ + private static String[] getSubjectAlts( + final X509Certificate cert, final String hostname) { + final int subjectType; + if (isIPAddress(hostname)) { + subjectType = 7; + } else { + subjectType = 2; + } + + final LinkedList<String> subjectAltList = new LinkedList<String>(); + Collection<List<?>> c = null; + try { + c = cert.getSubjectAlternativeNames(); + } + catch(final CertificateParsingException cpe) { + } + if(c != null) { + for (final List<?> aC : c) { + final List<?> list = aC; + final int type = ((Integer) list.get(0)).intValue(); + if (type == subjectType) { + final String s = (String) list.get(1); + subjectAltList.add(s); + } + } + } + if(!subjectAltList.isEmpty()) { + final String[] subjectAlts = new String[subjectAltList.size()]; + subjectAltList.toArray(subjectAlts); + return subjectAlts; + } else { + return null; + } + } + + /** + * Extracts the array of SubjectAlt DNS names from an X509Certificate. + * Returns null if there aren't any. + * <p/> + * Note: Java doesn't appear able to extract international characters + * from the SubjectAlts. It can only extract international characters + * from the CN field. + * <p/> + * (Or maybe the version of OpenSSL I'm using to test isn't storing the + * international characters correctly in the SubjectAlts?). + * + * @param cert X509Certificate + * @return Array of SubjectALT DNS names stored in the certificate. + */ + public static String[] getDNSSubjectAlts(final X509Certificate cert) { + return getSubjectAlts(cert, null); + } + + /** + * Counts the number of dots "." in a string. + * @param s string to count dots from + * @return number of dots + */ + public static int countDots(final String s) { + int count = 0; + for(int i = 0; i < s.length(); i++) { + if(s.charAt(i) == '.') { + count++; + } + } + return count; + } + + private static boolean isIPAddress(final String hostname) { + return hostname != null && + (InetAddressUtils.isIPv4Address(hostname) || + InetAddressUtils.isIPv6Address(hostname)); + } + + /* + * Check if hostname is IPv6, and if so, convert to standard format. + */ + private String normaliseIPv6Address(final String hostname) { + if (hostname == null || !InetAddressUtils.isIPv6Address(hostname)) { + return hostname; + } + try { + final InetAddress inetAddress = InetAddress.getByName(hostname); + return inetAddress.getHostAddress(); + } catch (final UnknownHostException uhe) { // Should not happen, because we check for IPv6 address above + log.error("Unexpected error converting "+hostname, uhe); + return hostname; + } + } +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java new file mode 100644 index 000000000..8ca1fad5a --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java @@ -0,0 +1,54 @@ +/* + * ==================================================================== + * 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.ssl; + +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * The ALLOW_ALL HostnameVerifier essentially turns hostname verification + * off. This implementation is a no-op, and never throws the SSLException. + * + * + * @since 4.0 + */ +@Immutable +public class AllowAllHostnameVerifier extends AbstractVerifier { + + public final void verify( + final String host, + final String[] cns, + final String[] subjectAlts) { + // Allow everything - so never blowup. + } + + @Override + public final String toString() { + return "ALLOW_ALL"; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java new file mode 100644 index 000000000..05f7d8c8c --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java @@ -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.ssl; + +import javax.net.ssl.SSLException; + +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * The HostnameVerifier that works the same way as Curl and Firefox. + * <p/> + * The hostname must match either the first CN, or any of the subject-alts. + * A wildcard can occur in the CN, and in any of the subject-alts. + * <p/> + * The only difference between BROWSER_COMPATIBLE and STRICT is that a wildcard + * (such as "*.foo.com") with BROWSER_COMPATIBLE matches all subdomains, + * including "a.b.foo.com". + * + * + * @since 4.0 + */ +@Immutable +public class BrowserCompatHostnameVerifier extends AbstractVerifier { + + public final void verify( + final String host, + final String[] cns, + final String[] subjectAlts) throws SSLException { + verify(host, cns, subjectAlts, false); + } + + @Override + boolean validCountryWildcard(final String cn) { + return true; + } + + @Override + public final String toString() { + return "BROWSER_COMPATIBLE"; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/DistinguishedNameParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/DistinguishedNameParser.java new file mode 100644 index 000000000..98b2ec3a9 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/DistinguishedNameParser.java @@ -0,0 +1,131 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.List; + +import ch.boye.httpclientandroidlib.NameValuePair; +import ch.boye.httpclientandroidlib.annotation.Immutable; +import ch.boye.httpclientandroidlib.message.BasicNameValuePair; +import ch.boye.httpclientandroidlib.message.ParserCursor; +import ch.boye.httpclientandroidlib.util.CharArrayBuffer; + +@Immutable +final class DistinguishedNameParser { + + public final static DistinguishedNameParser INSTANCE = new DistinguishedNameParser(); + + private static final BitSet EQUAL_OR_COMMA_OR_PLUS = TokenParser.INIT_BITSET('=', ',', '+'); + private static final BitSet COMMA_OR_PLUS = TokenParser.INIT_BITSET(',', '+'); + + private final TokenParser tokenParser; + + DistinguishedNameParser() { + this.tokenParser = new InternalTokenParser(); + } + + String parseToken(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) { + return tokenParser.parseToken(buf, cursor, delimiters); + } + + String parseValue(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) { + return tokenParser.parseValue(buf, cursor, delimiters); + } + + NameValuePair parseParameter(final CharArrayBuffer buf, final ParserCursor cursor) { + final String name = parseToken(buf, cursor, EQUAL_OR_COMMA_OR_PLUS); + if (cursor.atEnd()) { + return new BasicNameValuePair(name, null); + } + final int delim = buf.charAt(cursor.getPos()); + cursor.updatePos(cursor.getPos() + 1); + if (delim == ',') { + return new BasicNameValuePair(name, null); + } + final String value = parseValue(buf, cursor, COMMA_OR_PLUS); + if (!cursor.atEnd()) { + cursor.updatePos(cursor.getPos() + 1); + } + return new BasicNameValuePair(name, value); + } + + public List<NameValuePair> parse(final CharArrayBuffer buf, final ParserCursor cursor) { + final List<NameValuePair> params = new ArrayList<NameValuePair>(); + tokenParser.skipWhiteSpace(buf, cursor); + while (!cursor.atEnd()) { + final NameValuePair param = parseParameter(buf, cursor); + params.add(param); + } + return params; + } + + public List<NameValuePair> parse(final String s) { + if (s == null) { + return null; + } + final CharArrayBuffer buffer = new CharArrayBuffer(s.length()); + buffer.append(s); + final ParserCursor cursor = new ParserCursor(0, s.length()); + return parse(buffer, cursor); + } + + static class InternalTokenParser extends TokenParser { + + @Override + public void copyUnquotedContent( + final CharArrayBuffer buf, + final ParserCursor cursor, + final BitSet delimiters, + final StringBuilder dst) { + int pos = cursor.getPos(); + final int indexFrom = cursor.getPos(); + final int indexTo = cursor.getUpperBound(); + boolean escaped = false; + for (int i = indexFrom; i < indexTo; i++, pos++) { + final char current = buf.charAt(i); + if (escaped) { + dst.append(current); + escaped = false; + } else { + if ((delimiters != null && delimiters.get(current)) + || TokenParser.isWhitespace(current) || current == '\"') { + break; + } else if (current == '\\') { + escaped = true; + } else { + dst.append(current); + } + } + } + cursor.updatePos(pos); + } + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyDetails.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyDetails.java new file mode 100644 index 000000000..c85978550 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyDetails.java @@ -0,0 +1,63 @@ +/* + * ==================================================================== + * 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.ssl; + +import ch.boye.httpclientandroidlib.util.Args; + +import java.security.cert.X509Certificate; +import java.util.Arrays; + +/** + * Private key details. + * + * @since 4.3 + */ +public final class PrivateKeyDetails { + + private final String type; + private final X509Certificate[] certChain; + + public PrivateKeyDetails(final String type, final X509Certificate[] certChain) { + super(); + this.type = Args.notNull(type, "Private key type"); + this.certChain = certChain; + } + + public String getType() { + return type; + } + + public X509Certificate[] getCertChain() { + return certChain; + } + + @Override + public String toString() { + return type + ':' + Arrays.toString(certChain); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyStrategy.java new file mode 100644 index 000000000..ba3ba40c5 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/PrivateKeyStrategy.java @@ -0,0 +1,44 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.net.Socket; +import java.util.Map; + +/** + * A strategy allowing for a choice of an alias during SSL authentication. + * + * @since 4.3 + */ +public interface PrivateKeyStrategy { + + /** + * Determines what key material to use for SSL authentication. + */ + String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket); + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLConnectionSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLConnectionSocketFactory.java new file mode 100644 index 000000000..341fbe385 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLConnectionSocketFactory.java @@ -0,0 +1,295 @@ +/* + * ==================================================================== + * 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.ssl; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.ThreadSafe; +import ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory; +import ch.boye.httpclientandroidlib.protocol.HttpContext; +import ch.boye.httpclientandroidlib.util.Args; +import ch.boye.httpclientandroidlib.util.TextUtils; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +/** + * Layered socket factory for TLS/SSL connections. + * <p> + * SSLSocketFactory can be used to validate the identity of the HTTPS server against a list of + * trusted certificates and to authenticate to the HTTPS server using a private key. + * <p> + * SSLSocketFactory will enable server authentication when supplied with + * a {@link java.security.KeyStore trust-store} file containing one or several trusted certificates. The client + * secure socket will reject the connection during the SSL session handshake if the target HTTPS + * server attempts to authenticate itself with a non-trusted certificate. + * <p> + * Use JDK keytool utility to import a trusted certificate and generate a trust-store file: + * <pre> + * keytool -import -alias "my server cert" -file server.crt -keystore my.truststore + * </pre> + * <p> + * In special cases the standard trust verification process can be bypassed by using a custom + * {@link ch.boye.httpclientandroidlib.conn.ssl.TrustStrategy}. This interface is primarily intended for allowing self-signed + * certificates to be accepted as trusted without having to add them to the trust-store file. + * <p> + * SSLSocketFactory will enable client authentication when supplied with + * a {@link java.security.KeyStore key-store} file containing a private key/public certificate + * pair. The client secure socket will use the private key to authenticate + * itself to the target HTTPS server during the SSL session handshake if + * requested to do so by the server. + * The target HTTPS server will in its turn verify the certificate presented + * by the client in order to establish client's authenticity. + * <p> + * Use the following sequence of actions to generate a key-store file + * </p> + * <ul> + * <li> + * <p> + * Use JDK keytool utility to generate a new key + * <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre> + * For simplicity use the same password for the key as that of the key-store + * </p> + * </li> + * <li> + * <p> + * Issue a certificate signing request (CSR) + * <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre> + * </p> + * </li> + * <li> + * <p> + * Send the certificate request to the trusted Certificate Authority for signature. + * One may choose to act as her own CA and sign the certificate request using a PKI + * tool, such as OpenSSL. + * </p> + * </li> + * <li> + * <p> + * Import the trusted CA root certificate + * <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre> + * </p> + * </li> + * <li> + * <p> + * Import the PKCS#7 file containg the complete certificate chain + * <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre> + * </p> + * </li> + * <li> + * <p> + * Verify the content the resultant keystore file + * <pre>keytool -list -v -keystore my.keystore</pre> + * </p> + * </li> + * </ul> + * + * @since 4.0 + */ +@ThreadSafe +public class SSLConnectionSocketFactory implements LayeredConnectionSocketFactory { + + public static final String TLS = "TLS"; + public static final String SSL = "SSL"; + public static final String SSLV2 = "SSLv2"; + + public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER + = new AllowAllHostnameVerifier(); + + public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER + = new BrowserCompatHostnameVerifier(); + + public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER + = new StrictHostnameVerifier(); + + /** + * Obtains default SSL socket factory with an SSL context based on the standard JSSE + * trust material (<code>cacerts</code> file in the security properties directory). + * System properties are not taken into consideration. + * + * @return default SSL socket factory + */ + public static SSLConnectionSocketFactory getSocketFactory() throws SSLInitializationException { + return new SSLConnectionSocketFactory( + SSLContexts.createDefault(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + private static String[] split(final String s) { + if (TextUtils.isBlank(s)) { + return null; + } + return s.split(" *, *"); + } + + /** + * Obtains default SSL socket factory with an SSL context based on system properties + * as described in + * <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html"> + * "JavaTM Secure Socket Extension (JSSE) Reference Guide for the JavaTM 2 Platform + * Standard Edition 5</a> + * + * @return default system SSL socket factory + */ + public static SSLConnectionSocketFactory getSystemSocketFactory() throws SSLInitializationException { + return new SSLConnectionSocketFactory( + (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault(), + split(System.getProperty("https.protocols")), + split(System.getProperty("https.cipherSuites")), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + private final javax.net.ssl.SSLSocketFactory socketfactory; + private final X509HostnameVerifier hostnameVerifier; + private final String[] supportedProtocols; + private final String[] supportedCipherSuites; + + public SSLConnectionSocketFactory(final SSLContext sslContext) { + this(sslContext, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + public SSLConnectionSocketFactory( + final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) { + this(Args.notNull(sslContext, "SSL context").getSocketFactory(), + null, null, hostnameVerifier); + } + + public SSLConnectionSocketFactory( + final SSLContext sslContext, + final String[] supportedProtocols, + final String[] supportedCipherSuites, + final X509HostnameVerifier hostnameVerifier) { + this(Args.notNull(sslContext, "SSL context").getSocketFactory(), + supportedProtocols, supportedCipherSuites, hostnameVerifier); + } + + public SSLConnectionSocketFactory( + final javax.net.ssl.SSLSocketFactory socketfactory, + final X509HostnameVerifier hostnameVerifier) { + this(socketfactory, null, null, hostnameVerifier); + } + + public SSLConnectionSocketFactory( + final javax.net.ssl.SSLSocketFactory socketfactory, + final String[] supportedProtocols, + final String[] supportedCipherSuites, + final X509HostnameVerifier hostnameVerifier) { + this.socketfactory = Args.notNull(socketfactory, "SSL socket factory"); + this.supportedProtocols = supportedProtocols; + this.supportedCipherSuites = supportedCipherSuites; + this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; + } + + /** + * Performs any custom initialization for a newly created SSLSocket + * (before the SSL handshake happens). + * + * The default implementation is a no-op, but could be overridden to, e.g., + * call {@link javax.net.ssl.SSLSocket#setEnabledCipherSuites(String[])}. + */ + protected void prepareSocket(final SSLSocket socket) throws IOException { + } + + public Socket createSocket(final HttpContext context) throws IOException { + return SocketFactory.getDefault().createSocket(); + } + + public Socket connectSocket( + final int connectTimeout, + final Socket socket, + final HttpHost host, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpContext context) throws IOException { + Args.notNull(host, "HTTP host"); + Args.notNull(remoteAddress, "Remote address"); + final Socket sock = socket != null ? socket : createSocket(context); + if (localAddress != null) { + sock.bind(localAddress); + } + try { + sock.connect(remoteAddress, connectTimeout); + } catch (final IOException ex) { + try { + sock.close(); + } catch (final IOException ignore) { + } + throw ex; + } + // Setup SSL layering if necessary + if (sock instanceof SSLSocket) { + final SSLSocket sslsock = (SSLSocket) sock; + sslsock.startHandshake(); + verifyHostname(sslsock, host.getHostName()); + return sock; + } else { + return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context); + } + } + + public Socket createLayeredSocket( + final Socket socket, + final String target, + final int port, + final HttpContext context) throws IOException { + final SSLSocket sslsock = (SSLSocket) this.socketfactory.createSocket( + socket, + target, + port, + true); + if (supportedProtocols != null) { + sslsock.setEnabledProtocols(supportedProtocols); + } + if (supportedCipherSuites != null) { + sslsock.setEnabledCipherSuites(supportedCipherSuites); + } + prepareSocket(sslsock); + sslsock.startHandshake(); + verifyHostname(sslsock, target); + return sslsock; + } + + X509HostnameVerifier getHostnameVerifier() { + return this.hostnameVerifier; + } + + private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException { + try { + this.hostnameVerifier.verify(hostname, sslsock); + // verifyHostName() didn't blowup - good! + } catch (final IOException iox) { + // close the socket before re-throwing the exception + try { sslsock.close(); } catch (final Exception x) { /*ignore*/ } + throw iox; + } + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContextBuilder.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContextBuilder.java new file mode 100644 index 000000000..89751a166 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContextBuilder.java @@ -0,0 +1,259 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.net.Socket; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.Principal; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509KeyManager; +import javax.net.ssl.X509TrustManager; + +import ch.boye.httpclientandroidlib.annotation.NotThreadSafe; + +/** + * Builder for {@link SSLContext} instances. + * + * @since 4.3 + */ +@NotThreadSafe +public class SSLContextBuilder { + + static final String TLS = "TLS"; + static final String SSL = "SSL"; + + private String protocol; + private Set<KeyManager> keymanagers; + private Set<TrustManager> trustmanagers; + private SecureRandom secureRandom; + + public SSLContextBuilder() { + super(); + this.keymanagers = new HashSet<KeyManager>(); + this.trustmanagers = new HashSet<TrustManager>(); + } + + public SSLContextBuilder useTLS() { + this.protocol = TLS; + return this; + } + + public SSLContextBuilder useSSL() { + this.protocol = SSL; + return this; + } + + public SSLContextBuilder useProtocol(final String protocol) { + this.protocol = protocol; + return this; + } + + public SSLContextBuilder setSecureRandom(final SecureRandom secureRandom) { + this.secureRandom = secureRandom; + return this; + } + + public SSLContextBuilder loadTrustMaterial( + final KeyStore truststore, + final TrustStrategy trustStrategy) throws NoSuchAlgorithmException, KeyStoreException { + final TrustManagerFactory tmfactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + tmfactory.init(truststore); + final TrustManager[] tms = tmfactory.getTrustManagers(); + if (tms != null) { + if (trustStrategy != null) { + for (int i = 0; i < tms.length; i++) { + final TrustManager tm = tms[i]; + if (tm instanceof X509TrustManager) { + tms[i] = new TrustManagerDelegate( + (X509TrustManager) tm, trustStrategy); + } + } + } + for (final TrustManager tm : tms) { + this.trustmanagers.add(tm); + } + } + return this; + } + + public SSLContextBuilder loadTrustMaterial( + final KeyStore truststore) throws NoSuchAlgorithmException, KeyStoreException { + return loadTrustMaterial(truststore, null); + } + + public SSLContextBuilder loadKeyMaterial( + final KeyStore keystore, + final char[] keyPassword) + throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException { + loadKeyMaterial(keystore, keyPassword, null); + return this; + } + + public SSLContextBuilder loadKeyMaterial( + final KeyStore keystore, + final char[] keyPassword, + final PrivateKeyStrategy aliasStrategy) + throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException { + final KeyManagerFactory kmfactory = KeyManagerFactory.getInstance( + KeyManagerFactory.getDefaultAlgorithm()); + kmfactory.init(keystore, keyPassword); + final KeyManager[] kms = kmfactory.getKeyManagers(); + if (kms != null) { + if (aliasStrategy != null) { + for (int i = 0; i < kms.length; i++) { + final KeyManager km = kms[i]; + if (km instanceof X509KeyManager) { + kms[i] = new KeyManagerDelegate( + (X509KeyManager) km, aliasStrategy); + } + } + } + for (final KeyManager km : kms) { + keymanagers.add(km); + } + } + return this; + } + + public SSLContext build() throws NoSuchAlgorithmException, KeyManagementException { + final SSLContext sslcontext = SSLContext.getInstance( + this.protocol != null ? this.protocol : TLS); + sslcontext.init( + !keymanagers.isEmpty() ? keymanagers.toArray(new KeyManager[keymanagers.size()]) : null, + !trustmanagers.isEmpty() ? trustmanagers.toArray(new TrustManager[trustmanagers.size()]) : null, + secureRandom); + return sslcontext; + } + + static class TrustManagerDelegate implements X509TrustManager { + + private final X509TrustManager trustManager; + private final TrustStrategy trustStrategy; + + TrustManagerDelegate(final X509TrustManager trustManager, final TrustStrategy trustStrategy) { + super(); + this.trustManager = trustManager; + this.trustStrategy = trustStrategy; + } + + public void checkClientTrusted( + final X509Certificate[] chain, final String authType) throws CertificateException { + this.trustManager.checkClientTrusted(chain, authType); + } + + public void checkServerTrusted( + final X509Certificate[] chain, final String authType) throws CertificateException { + if (!this.trustStrategy.isTrusted(chain, authType)) { + this.trustManager.checkServerTrusted(chain, authType); + } + } + + public X509Certificate[] getAcceptedIssuers() { + return this.trustManager.getAcceptedIssuers(); + } + + } + + static class KeyManagerDelegate implements X509KeyManager { + + private final X509KeyManager keyManager; + private final PrivateKeyStrategy aliasStrategy; + + KeyManagerDelegate(final X509KeyManager keyManager, final PrivateKeyStrategy aliasStrategy) { + super(); + this.keyManager = keyManager; + this.aliasStrategy = aliasStrategy; + } + + public String[] getClientAliases( + final String keyType, final Principal[] issuers) { + return this.keyManager.getClientAliases(keyType, issuers); + } + + public String chooseClientAlias( + final String[] keyTypes, final Principal[] issuers, final Socket socket) { + final Map<String, PrivateKeyDetails> validAliases = new HashMap<String, PrivateKeyDetails>(); + for (final String keyType: keyTypes) { + final String[] aliases = this.keyManager.getClientAliases(keyType, issuers); + if (aliases != null) { + for (final String alias: aliases) { + validAliases.put(alias, + new PrivateKeyDetails(keyType, this.keyManager.getCertificateChain(alias))); + } + } + } + return this.aliasStrategy.chooseAlias(validAliases, socket); + } + + public String[] getServerAliases( + final String keyType, final Principal[] issuers) { + return this.keyManager.getServerAliases(keyType, issuers); + } + + public String chooseServerAlias( + final String keyType, final Principal[] issuers, final Socket socket) { + final Map<String, PrivateKeyDetails> validAliases = new HashMap<String, PrivateKeyDetails>(); + final String[] aliases = this.keyManager.getServerAliases(keyType, issuers); + if (aliases != null) { + for (final String alias: aliases) { + validAliases.put(alias, + new PrivateKeyDetails(keyType, this.keyManager.getCertificateChain(alias))); + } + } + return this.aliasStrategy.chooseAlias(validAliases, socket); + } + + public X509Certificate[] getCertificateChain(final String alias) { + return this.keyManager.getCertificateChain(alias); + } + + public PrivateKey getPrivateKey(final String alias) { + return this.keyManager.getPrivateKey(alias); + } + + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContexts.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContexts.java new file mode 100644 index 000000000..a87a50168 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLContexts.java @@ -0,0 +1,90 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import javax.net.ssl.SSLContext; + +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * {@link SSLContext} factory methods. + * + * @since 4.3 + */ +@Immutable +public class SSLContexts { + + /** + * Creates default factory based on the standard JSSE trust material + * (<code>cacerts</code> file in the security properties directory). System properties + * are not taken into consideration. + * + * @return the default SSL socket factory + */ + public static SSLContext createDefault() throws SSLInitializationException { + try { + final SSLContext sslcontext = SSLContext.getInstance(SSLContextBuilder.TLS); + sslcontext.init(null, null, null); + return sslcontext; + } catch (final NoSuchAlgorithmException ex) { + throw new SSLInitializationException(ex.getMessage(), ex); + } catch (final KeyManagementException ex) { + throw new SSLInitializationException(ex.getMessage(), ex); + } + } + + /** + * Creates default SSL context based on system properties. This method obtains + * default SSL context by calling <code>SSLContext.getInstance("Default")</code>. + * Please note that <code>Default</code> algorithm is supported as of Java 6. + * This method will fall back onto {@link #createDefault()} when + * <code>Default</code> algorithm is not available. + * + * @return default system SSL context + */ + public static SSLContext createSystemDefault() throws SSLInitializationException { + try { + return SSLContext.getInstance("Default"); + } catch (final NoSuchAlgorithmException ex) { + return createDefault(); + } + } + + /** + * Creates custom SSL context. + * + * @return default system SSL context + */ + public static SSLContextBuilder custom() { + return new SSLContextBuilder(); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLInitializationException.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLInitializationException.java new file mode 100644 index 000000000..98cb5f9c3 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLInitializationException.java @@ -0,0 +1,37 @@ +/* + * ==================================================================== + * 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.ssl; + +public class SSLInitializationException extends IllegalStateException { + + private static final long serialVersionUID = -8243587425648536702L; + + public SSLInitializationException(final String message, final Throwable cause) { + super(message, cause); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLSocketFactory.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLSocketFactory.java new file mode 100644 index 000000000..5c514d780 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/SSLSocketFactory.java @@ -0,0 +1,570 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; + +import ch.boye.httpclientandroidlib.HttpHost; +import ch.boye.httpclientandroidlib.annotation.ThreadSafe; +import ch.boye.httpclientandroidlib.conn.ConnectTimeoutException; +import ch.boye.httpclientandroidlib.conn.HttpInetSocketAddress; +import ch.boye.httpclientandroidlib.conn.scheme.HostNameResolver; +import ch.boye.httpclientandroidlib.conn.scheme.LayeredSchemeSocketFactory; +import ch.boye.httpclientandroidlib.conn.scheme.LayeredSocketFactory; +import ch.boye.httpclientandroidlib.conn.scheme.SchemeLayeredSocketFactory; +import ch.boye.httpclientandroidlib.conn.socket.LayeredConnectionSocketFactory; +import ch.boye.httpclientandroidlib.params.HttpConnectionParams; +import ch.boye.httpclientandroidlib.params.HttpParams; +import ch.boye.httpclientandroidlib.protocol.HttpContext; +import ch.boye.httpclientandroidlib.util.Args; +import ch.boye.httpclientandroidlib.util.Asserts; +import ch.boye.httpclientandroidlib.util.TextUtils; + +/** + * Layered socket factory for TLS/SSL connections. + * <p> + * SSLSocketFactory can be used to validate the identity of the HTTPS server against a list of + * trusted certificates and to authenticate to the HTTPS server using a private key. + * <p> + * SSLSocketFactory will enable server authentication when supplied with + * a {@link KeyStore trust-store} file containing one or several trusted certificates. The client + * secure socket will reject the connection during the SSL session handshake if the target HTTPS + * server attempts to authenticate itself with a non-trusted certificate. + * <p> + * Use JDK keytool utility to import a trusted certificate and generate a trust-store file: + * <pre> + * keytool -import -alias "my server cert" -file server.crt -keystore my.truststore + * </pre> + * <p> + * In special cases the standard trust verification process can be bypassed by using a custom + * {@link TrustStrategy}. This interface is primarily intended for allowing self-signed + * certificates to be accepted as trusted without having to add them to the trust-store file. + * <p> + * SSLSocketFactory will enable client authentication when supplied with + * a {@link KeyStore key-store} file containing a private key/public certificate + * pair. The client secure socket will use the private key to authenticate + * itself to the target HTTPS server during the SSL session handshake if + * requested to do so by the server. + * The target HTTPS server will in its turn verify the certificate presented + * by the client in order to establish client's authenticity. + * <p> + * Use the following sequence of actions to generate a key-store file + * </p> + * <ul> + * <li> + * <p> + * Use JDK keytool utility to generate a new key + * <pre>keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore</pre> + * For simplicity use the same password for the key as that of the key-store + * </p> + * </li> + * <li> + * <p> + * Issue a certificate signing request (CSR) + * <pre>keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore</pre> + * </p> + * </li> + * <li> + * <p> + * Send the certificate request to the trusted Certificate Authority for signature. + * One may choose to act as her own CA and sign the certificate request using a PKI + * tool, such as OpenSSL. + * </p> + * </li> + * <li> + * <p> + * Import the trusted CA root certificate + * <pre>keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore</pre> + * </p> + * </li> + * <li> + * <p> + * Import the PKCS#7 file containg the complete certificate chain + * <pre>keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore</pre> + * </p> + * </li> + * <li> + * <p> + * Verify the content the resultant keystore file + * <pre>keytool -list -v -keystore my.keystore</pre> + * </p> + * </li> + * </ul> + * + * @since 4.0 + * + * @deprecated (4.3) use {@link SSLConnectionSocketFactory}. + */ +@ThreadSafe +@Deprecated +public class SSLSocketFactory implements LayeredConnectionSocketFactory, SchemeLayeredSocketFactory, + LayeredSchemeSocketFactory, LayeredSocketFactory { + + public static final String TLS = "TLS"; + public static final String SSL = "SSL"; + public static final String SSLV2 = "SSLv2"; + + public static final X509HostnameVerifier ALLOW_ALL_HOSTNAME_VERIFIER + = new AllowAllHostnameVerifier(); + + public static final X509HostnameVerifier BROWSER_COMPATIBLE_HOSTNAME_VERIFIER + = new BrowserCompatHostnameVerifier(); + + public static final X509HostnameVerifier STRICT_HOSTNAME_VERIFIER + = new StrictHostnameVerifier(); + + /** + * Obtains default SSL socket factory with an SSL context based on the standard JSSE + * trust material (<code>cacerts</code> file in the security properties directory). + * System properties are not taken into consideration. + * + * @return default SSL socket factory + */ + public static SSLSocketFactory getSocketFactory() throws SSLInitializationException { + return new SSLSocketFactory( + SSLContexts.createDefault(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + private static String[] split(final String s) { + if (TextUtils.isBlank(s)) { + return null; + } + return s.split(" *, *"); + } + + /** + * Obtains default SSL socket factory with an SSL context based on system properties + * as described in + * <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html"> + * "JavaTM Secure Socket Extension (JSSE) Reference Guide for the JavaTM 2 Platform + * Standard Edition 5</a> + * + * @return default system SSL socket factory + */ + public static SSLSocketFactory getSystemSocketFactory() throws SSLInitializationException { + return new SSLSocketFactory( + (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory.getDefault(), + split(System.getProperty("https.protocols")), + split(System.getProperty("https.cipherSuites")), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + private final javax.net.ssl.SSLSocketFactory socketfactory; + private final HostNameResolver nameResolver; + // TODO: make final + private volatile X509HostnameVerifier hostnameVerifier; + private final String[] supportedProtocols; + private final String[] supportedCipherSuites; + + public SSLSocketFactory( + final String algorithm, + final KeyStore keystore, + final String keyPassword, + final KeyStore truststore, + final SecureRandom random, + final HostNameResolver nameResolver) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + this(SSLContexts.custom() + .useProtocol(algorithm) + .setSecureRandom(random) + .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null) + .loadTrustMaterial(truststore) + .build(), + nameResolver); + } + + /** + * @since 4.1 + */ + public SSLSocketFactory( + final String algorithm, + final KeyStore keystore, + final String keyPassword, + final KeyStore truststore, + final SecureRandom random, + final TrustStrategy trustStrategy, + final X509HostnameVerifier hostnameVerifier) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + this(SSLContexts.custom() + .useProtocol(algorithm) + .setSecureRandom(random) + .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null) + .loadTrustMaterial(truststore, trustStrategy) + .build(), + hostnameVerifier); + } + + /** + * @since 4.1 + */ + public SSLSocketFactory( + final String algorithm, + final KeyStore keystore, + final String keyPassword, + final KeyStore truststore, + final SecureRandom random, + final X509HostnameVerifier hostnameVerifier) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + this(SSLContexts.custom() + .useProtocol(algorithm) + .setSecureRandom(random) + .loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null) + .loadTrustMaterial(truststore) + .build(), + hostnameVerifier); + } + + public SSLSocketFactory( + final KeyStore keystore, + final String keystorePassword, + final KeyStore truststore) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + this(SSLContexts.custom() + .loadKeyMaterial(keystore, keystorePassword != null ? keystorePassword.toCharArray() : null) + .loadTrustMaterial(truststore) + .build(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + public SSLSocketFactory( + final KeyStore keystore, + final String keystorePassword) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException{ + this(SSLContexts.custom() + .loadKeyMaterial(keystore, keystorePassword != null ? keystorePassword.toCharArray() : null) + .build(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + public SSLSocketFactory( + final KeyStore truststore) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + this(SSLContexts.custom() + .loadTrustMaterial(truststore) + .build(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + /** + * @since 4.1 + */ + public SSLSocketFactory( + final TrustStrategy trustStrategy, + final X509HostnameVerifier hostnameVerifier) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + this(SSLContexts.custom() + .loadTrustMaterial(null, trustStrategy) + .build(), + hostnameVerifier); + } + + /** + * @since 4.1 + */ + public SSLSocketFactory( + final TrustStrategy trustStrategy) + throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { + this(SSLContexts.custom() + .loadTrustMaterial(null, trustStrategy) + .build(), + BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + public SSLSocketFactory(final SSLContext sslContext) { + this(sslContext, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } + + public SSLSocketFactory( + final SSLContext sslContext, final HostNameResolver nameResolver) { + super(); + this.socketfactory = sslContext.getSocketFactory(); + this.hostnameVerifier = BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; + this.nameResolver = nameResolver; + this.supportedProtocols = null; + this.supportedCipherSuites = null; + } + + /** + * @since 4.1 + */ + public SSLSocketFactory( + final SSLContext sslContext, final X509HostnameVerifier hostnameVerifier) { + this(Args.notNull(sslContext, "SSL context").getSocketFactory(), + null, null, hostnameVerifier); + } + + /** + * @since 4.3 + */ + public SSLSocketFactory( + final SSLContext sslContext, + final String[] supportedProtocols, + final String[] supportedCipherSuites, + final X509HostnameVerifier hostnameVerifier) { + this(Args.notNull(sslContext, "SSL context").getSocketFactory(), + supportedProtocols, supportedCipherSuites, hostnameVerifier); + } + + /** + * @since 4.2 + */ + public SSLSocketFactory( + final javax.net.ssl.SSLSocketFactory socketfactory, + final X509HostnameVerifier hostnameVerifier) { + this(socketfactory, null, null, hostnameVerifier); + } + + /** + * @since 4.3 + */ + public SSLSocketFactory( + final javax.net.ssl.SSLSocketFactory socketfactory, + final String[] supportedProtocols, + final String[] supportedCipherSuites, + final X509HostnameVerifier hostnameVerifier) { + this.socketfactory = Args.notNull(socketfactory, "SSL socket factory"); + this.supportedProtocols = supportedProtocols; + this.supportedCipherSuites = supportedCipherSuites; + this.hostnameVerifier = hostnameVerifier != null ? hostnameVerifier : BROWSER_COMPATIBLE_HOSTNAME_VERIFIER; + this.nameResolver = null; + } + + /** + * @param params Optional parameters. Parameters passed to this method will have no effect. + * This method will create a unconnected instance of {@link Socket} class. + * @since 4.1 + */ + public Socket createSocket(final HttpParams params) throws IOException { + return createSocket((HttpContext) null); + } + + public Socket createSocket() throws IOException { + return createSocket((HttpContext) null); + } + + /** + * @since 4.1 + */ + public Socket connectSocket( + final Socket socket, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { + Args.notNull(remoteAddress, "Remote address"); + Args.notNull(params, "HTTP parameters"); + final HttpHost host; + if (remoteAddress instanceof HttpInetSocketAddress) { + host = ((HttpInetSocketAddress) remoteAddress).getHttpHost(); + } else { + host = new HttpHost(remoteAddress.getHostName(), remoteAddress.getPort(), "https"); + } + final int socketTimeout = HttpConnectionParams.getSoTimeout(params); + final int connectTimeout = HttpConnectionParams.getConnectionTimeout(params); + socket.setSoTimeout(socketTimeout); + return connectSocket(connectTimeout, socket, host, remoteAddress, localAddress, null); + } + + /** + * Checks whether a socket connection is secure. + * This factory creates TLS/SSL socket connections + * which, by default, are considered secure. + * <br/> + * Derived classes may override this method to perform + * runtime checks, for example based on the cypher suite. + * + * @param sock the connected socket + * + * @return <code>true</code> + * + * @throws IllegalArgumentException if the argument is invalid + */ + public boolean isSecure(final Socket sock) throws IllegalArgumentException { + Args.notNull(sock, "Socket"); + Asserts.check(sock instanceof SSLSocket, "Socket not created by this factory"); + Asserts.check(!sock.isClosed(), "Socket is closed"); + return true; + } + + /** + * @since 4.2 + */ + public Socket createLayeredSocket( + final Socket socket, + final String host, + final int port, + final HttpParams params) throws IOException, UnknownHostException { + return createLayeredSocket(socket, host, port, (HttpContext) null); + } + + public Socket createLayeredSocket( + final Socket socket, + final String host, + final int port, + final boolean autoClose) throws IOException, UnknownHostException { + return createLayeredSocket(socket, host, port, (HttpContext) null); + } + + public void setHostnameVerifier(final X509HostnameVerifier hostnameVerifier) { + Args.notNull(hostnameVerifier, "Hostname verifier"); + this.hostnameVerifier = hostnameVerifier; + } + + public X509HostnameVerifier getHostnameVerifier() { + return this.hostnameVerifier; + } + + public Socket connectSocket( + final Socket socket, + final String host, final int port, + final InetAddress local, final int localPort, + final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { + final InetAddress remote; + if (this.nameResolver != null) { + remote = this.nameResolver.resolve(host); + } else { + remote = InetAddress.getByName(host); + } + InetSocketAddress localAddress = null; + if (local != null || localPort > 0) { + localAddress = new InetSocketAddress(local, localPort > 0 ? localPort : 0); + } + final InetSocketAddress remoteAddress = new HttpInetSocketAddress( + new HttpHost(host, port), remote, port); + return connectSocket(socket, remoteAddress, localAddress, params); + } + + public Socket createSocket( + final Socket socket, + final String host, final int port, + final boolean autoClose) throws IOException, UnknownHostException { + return createLayeredSocket(socket, host, port, autoClose); + } + + /** + * Performs any custom initialization for a newly created SSLSocket + * (before the SSL handshake happens). + * + * The default implementation is a no-op, but could be overridden to, e.g., + * call {@link SSLSocket#setEnabledCipherSuites(java.lang.String[])}. + * + * @since 4.2 + */ + protected void prepareSocket(final SSLSocket socket) throws IOException { + } + + private void internalPrepareSocket(final SSLSocket socket) throws IOException { + if (supportedProtocols != null) { + socket.setEnabledProtocols(supportedProtocols); + } + if (supportedCipherSuites != null) { + socket.setEnabledCipherSuites(supportedCipherSuites); + } + prepareSocket(socket); + } + + public Socket createSocket(final HttpContext context) throws IOException { + final SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); + internalPrepareSocket(sock); + return sock; + } + + public Socket connectSocket( + final int connectTimeout, + final Socket socket, + final HttpHost host, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpContext context) throws IOException { + Args.notNull(host, "HTTP host"); + Args.notNull(remoteAddress, "Remote address"); + final Socket sock = socket != null ? socket : createSocket(context); + if (localAddress != null) { + sock.bind(localAddress); + } + try { + sock.connect(remoteAddress, connectTimeout); + } catch (final IOException ex) { + try { + sock.close(); + } catch (final IOException ignore) { + } + throw ex; + } + // Setup SSL layering if necessary + if (sock instanceof SSLSocket) { + final SSLSocket sslsock = (SSLSocket) sock; + sslsock.startHandshake(); + verifyHostname(sslsock, host.getHostName()); + return sock; + } else { + return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context); + } + } + + public Socket createLayeredSocket( + final Socket socket, + final String target, + final int port, + final HttpContext context) throws IOException { + final SSLSocket sslsock = (SSLSocket) this.socketfactory.createSocket( + socket, + target, + port, + true); + internalPrepareSocket(sslsock); + sslsock.startHandshake(); + verifyHostname(sslsock, target); + return sslsock; + } + + private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException { + try { + this.hostnameVerifier.verify(hostname, sslsock); + // verifyHostName() didn't blowup - good! + } catch (final IOException iox) { + // close the socket before re-throwing the exception + try { sslsock.close(); } catch (final Exception x) { /*ignore*/ } + throw iox; + } + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java new file mode 100644 index 000000000..a6328a10c --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java @@ -0,0 +1,69 @@ +/* + * ==================================================================== + * 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.ssl; + +import javax.net.ssl.SSLException; + +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * The Strict HostnameVerifier works the same way as Sun Java 1.4, Sun + * Java 5, Sun Java 6-rc. It's also pretty close to IE6. This + * implementation appears to be compliant with RFC 2818 for dealing with + * wildcards. + * <p/> + * The hostname must match either the first CN, or any of the subject-alts. + * A wildcard can occur in the CN, and in any of the subject-alts. The + * one divergence from IE6 is how we only check the first CN. IE6 allows + * a match against any of the CNs present. We decided to follow in + * Sun Java 1.4's footsteps and only check the first CN. (If you need + * to check all the CN's, feel free to write your own implementation!). + * <p/> + * A wildcard such as "*.foo.com" matches only subdomains in the same + * level, for example "a.foo.com". It does not match deeper subdomains + * such as "a.b.foo.com". + * + * + * @since 4.0 + */ +@Immutable +public class StrictHostnameVerifier extends AbstractVerifier { + + public final void verify( + final String host, + final String[] cns, + final String[] subjectAlts) throws SSLException { + verify(host, cns, subjectAlts, true); + } + + @Override + public final String toString() { + return "STRICT"; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TokenParser.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TokenParser.java new file mode 100644 index 000000000..25bdcc5e6 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TokenParser.java @@ -0,0 +1,266 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.util.BitSet; + +import ch.boye.httpclientandroidlib.message.ParserCursor; +import ch.boye.httpclientandroidlib.util.CharArrayBuffer; + +/** + * Low level parser for header field elements. The parsing routines of this class are designed + * to produce near zero intermediate garbage and make no intermediate copies of input data. + * <p> + * This class is immutable and thread safe. + * + * Temporary package-private copy of ch.boye.httpclientandroidlib.message.TokenParser + */ +class TokenParser { + + public static BitSet INIT_BITSET(final int ... b) { + final BitSet bitset = new BitSet(); + for (final int aB : b) { + bitset.set(aB); + } + return bitset; + } + + /** US-ASCII CR, carriage return (13) */ + public static final char CR = '\r'; + + /** US-ASCII LF, line feed (10) */ + public static final char LF = '\n'; + + /** US-ASCII SP, space (32) */ + public static final char SP = ' '; + + /** US-ASCII HT, horizontal-tab (9) */ + public static final char HT = '\t'; + + /** Double quote */ + public static final char DQUOTE = '\"'; + + /** Backward slash / escape character */ + public static final char ESCAPE = '\\'; + + public static boolean isWhitespace(final char ch) { + return ch == SP || ch == HT || ch == CR || ch == LF; + } + + public static final TokenParser INSTANCE = new TokenParser(); + + /** + * Extracts from the sequence of chars a token terminated with any of the given delimiters + * discarding semantically insignificant whitespace characters. + * + * @param buf buffer with the sequence of chars to be parsed + * @param cursor defines the bounds and current position of the buffer + * @param delimiters set of delimiting characters. Can be <code>null</code> if the token + * is not delimited by any character. + */ + public String parseToken(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) { + final StringBuilder dst = new StringBuilder(); + boolean whitespace = false; + while (!cursor.atEnd()) { + final char current = buf.charAt(cursor.getPos()); + if (delimiters != null && delimiters.get(current)) { + break; + } else if (isWhitespace(current)) { + skipWhiteSpace(buf, cursor); + whitespace = true; + } else { + if (whitespace && dst.length() > 0) { + dst.append(' '); + } + copyContent(buf, cursor, delimiters, dst); + whitespace = false; + } + } + return dst.toString(); + } + + /** + * Extracts from the sequence of chars a value which can be enclosed in quote marks and + * terminated with any of the given delimiters discarding semantically insignificant + * whitespace characters. + * + * @param buf buffer with the sequence of chars to be parsed + * @param cursor defines the bounds and current position of the buffer + * @param delimiters set of delimiting characters. Can be <code>null</code> if the value + * is not delimited by any character. + */ + public String parseValue(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters) { + final StringBuilder dst = new StringBuilder(); + boolean whitespace = false; + while (!cursor.atEnd()) { + final char current = buf.charAt(cursor.getPos()); + if (delimiters != null && delimiters.get(current)) { + break; + } else if (isWhitespace(current)) { + skipWhiteSpace(buf, cursor); + whitespace = true; + } else if (current == DQUOTE) { + if (whitespace && dst.length() > 0) { + dst.append(' '); + } + copyQuotedContent(buf, cursor, dst); + whitespace = false; + } else { + if (whitespace && dst.length() > 0) { + dst.append(' '); + } + copyUnquotedContent(buf, cursor, delimiters, dst); + whitespace = false; + } + } + return dst.toString(); + } + + /** + * Skips semantically insignificant whitespace characters and moves the cursor to the closest + * non-whitespace character. + * + * @param buf buffer with the sequence of chars to be parsed + * @param cursor defines the bounds and current position of the buffer + */ + public void skipWhiteSpace(final CharArrayBuffer buf, final ParserCursor cursor) { + int pos = cursor.getPos(); + final int indexFrom = cursor.getPos(); + final int indexTo = cursor.getUpperBound(); + for (int i = indexFrom; i < indexTo; i++) { + final char current = buf.charAt(i); + if (!isWhitespace(current)) { + break; + } else { + pos++; + } + } + cursor.updatePos(pos); + } + + /** + * Transfers content into the destination buffer until a whitespace character or any of + * the given delimiters is encountered. + * + * @param buf buffer with the sequence of chars to be parsed + * @param cursor defines the bounds and current position of the buffer + * @param delimiters set of delimiting characters. Can be <code>null</code> if the value + * is delimited by a whitespace only. + * @param dst destination buffer + */ + public void copyContent(final CharArrayBuffer buf, final ParserCursor cursor, final BitSet delimiters, + final StringBuilder dst) { + int pos = cursor.getPos(); + final int indexFrom = cursor.getPos(); + final int indexTo = cursor.getUpperBound(); + for (int i = indexFrom; i < indexTo; i++) { + final char current = buf.charAt(i); + if ((delimiters != null && delimiters.get(current)) || isWhitespace(current)) { + break; + } else { + pos++; + dst.append(current); + } + } + cursor.updatePos(pos); + } + + /** + * Transfers content into the destination buffer until a whitespace character, a quote, + * or any of the given delimiters is encountered. + * + * @param buf buffer with the sequence of chars to be parsed + * @param cursor defines the bounds and current position of the buffer + * @param delimiters set of delimiting characters. Can be <code>null</code> if the value + * is delimited by a whitespace or a quote only. + * @param dst destination buffer + */ + public void copyUnquotedContent(final CharArrayBuffer buf, final ParserCursor cursor, + final BitSet delimiters, final StringBuilder dst) { + int pos = cursor.getPos(); + final int indexFrom = cursor.getPos(); + final int indexTo = cursor.getUpperBound(); + for (int i = indexFrom; i < indexTo; i++) { + final char current = buf.charAt(i); + if ((delimiters != null && delimiters.get(current)) + || isWhitespace(current) || current == DQUOTE) { + break; + } else { + pos++; + dst.append(current); + } + } + cursor.updatePos(pos); + } + + /** + * Transfers content enclosed with quote marks into the destination buffer. + * + * @param buf buffer with the sequence of chars to be parsed + * @param cursor defines the bounds and current position of the buffer + * @param dst destination buffer + */ + public void copyQuotedContent(final CharArrayBuffer buf, final ParserCursor cursor, + final StringBuilder dst) { + if (cursor.atEnd()) { + return; + } + int pos = cursor.getPos(); + int indexFrom = cursor.getPos(); + final int indexTo = cursor.getUpperBound(); + char current = buf.charAt(pos); + if (current != DQUOTE) { + return; + } + pos++; + indexFrom++; + boolean escaped = false; + for (int i = indexFrom; i < indexTo; i++, pos++) { + current = buf.charAt(i); + if (escaped) { + if (current != DQUOTE && current != ESCAPE) { + dst.append(ESCAPE); + } + dst.append(current); + escaped = false; + } else { + if (current == DQUOTE) { + pos++; + break; + } + if (current == ESCAPE) { + escaped = true; + } else if (current != CR && current != LF) { + dst.append(current); + } + } + } + cursor.updatePos(pos); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java new file mode 100644 index 000000000..a3c23690b --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java @@ -0,0 +1,45 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * A trust strategy that accepts self-signed certificates as trusted. Verification of all other + * certificates is done by the trust manager configured in the SSL context. + * + * @since 4.1 + */ +public class TrustSelfSignedStrategy implements TrustStrategy { + + public boolean isTrusted( + final X509Certificate[] chain, final String authType) throws CertificateException { + return chain.length == 1; + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustStrategy.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustStrategy.java new file mode 100644 index 000000000..7f4914503 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/TrustStrategy.java @@ -0,0 +1,57 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * A strategy to establish trustworthiness of certificates without consulting the trust manager + * configured in the actual SSL context. This interface can be used to override the standard + * JSSE certificate verification process. + * + * @since 4.1 + */ +public interface TrustStrategy { + + /** + * Determines whether the certificate chain can be trusted without consulting the trust manager + * configured in the actual SSL context. This method can be used to override the standard JSSE + * certificate verification process. + * <p> + * Please note that, if this method returns <code>false</code>, the trust manager configured + * in the actual SSL context can still clear the certificate as trusted. + * + * @param chain the peer certificate chain + * @param authType the authentication type based on the client certificate + * @return <code>true</code> if the certificate can be trusted without verification by + * the trust manager, <code>false</code> otherwise. + * @throws CertificateException thrown if the certificate is not trusted or invalid. + */ + boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java new file mode 100644 index 000000000..cd57c623e --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/X509HostnameVerifier.java @@ -0,0 +1,85 @@ +/* + * ==================================================================== + * 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.ssl; + +import java.io.IOException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSocket; + +/** + * Interface for checking if a hostname matches the names stored inside the + * server's X.509 certificate. This interface extends + * {@link javax.net.ssl.HostnameVerifier}, but it is recommended to use + * methods added by X509HostnameVerifier. + * + * @since 4.0 + */ +public interface X509HostnameVerifier extends HostnameVerifier { + + /** + * Verifies that the host name is an acceptable match with the server's + * authentication scheme based on the given {@link SSLSocket}. + * + * @param host the host. + * @param ssl the SSL socket. + * @throws IOException if an I/O error occurs or the verification process + * fails. + */ + void verify(String host, SSLSocket ssl) throws IOException; + + /** + * Verifies that the host name is an acceptable match with the server's + * authentication scheme based on the given {@link X509Certificate}. + * + * @param host the host. + * @param cert the certificate. + * @throws SSLException if the verification process fails. + */ + void verify(String host, X509Certificate cert) throws SSLException; + + /** + * Checks to see if the supplied hostname matches any of the supplied CNs + * or "DNS" Subject-Alts. Most implementations only look at the first CN, + * and ignore any additional CNs. Most implementations do look at all of + * the "DNS" Subject-Alts. The CNs or Subject-Alts may contain wildcards + * according to RFC 2818. + * + * @param cns CN fields, in order, as extracted from the X.509 + * certificate. + * @param subjectAlts Subject-Alt fields of type 2 ("DNS"), as extracted + * from the X.509 certificate. + * @param host The hostname to verify. + * @throws SSLException if the verification process fails. + */ + void verify(String host, String[] cns, String[] subjectAlts) + throws SSLException; + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/package-info.java new file mode 100644 index 000000000..c05bf5be0 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/ssl/package-info.java @@ -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 TLS/SSL support. + */ +package ch.boye.httpclientandroidlib.conn.ssl; diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/InetAddressUtils.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/InetAddressUtils.java new file mode 100644 index 000000000..ac9a8e2db --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/InetAddressUtils.java @@ -0,0 +1,123 @@ +/* + * ==================================================================== + * 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.util; + +import java.util.regex.Pattern; + +import ch.boye.httpclientandroidlib.annotation.Immutable; + +/** + * A collection of utilities relating to InetAddresses. + * + * @since 4.0 + */ +@Immutable +public class InetAddressUtils { + + private InetAddressUtils() { + } + + private static final String IPV4_BASIC_PATTERN_STRING = + "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + // initial 3 fields, 0-255 followed by . + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255 + + private static final Pattern IPV4_PATTERN = + Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$"); + + private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros + Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$"); + + private static final Pattern IPV6_STD_PATTERN = + Pattern.compile( + "^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$"); + + private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = + Pattern.compile( + "^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields + "::" + + "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields + + /* + * The above pattern is not totally rigorous as it allows for more than 7 hex fields in total + */ + private static final char COLON_CHAR = ':'; + + // Must not have more than 7 colons (i.e. 8 fields) + private static final int MAX_COLON_COUNT = 7; + + /** + * Checks whether the parameter is a valid IPv4 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid IPv4 address + */ + public static boolean isIPv4Address(final String input) { + return IPV4_PATTERN.matcher(input).matches(); + } + + public static boolean isIPv4MappedIPv64Address(final String input) { + return IPV4_MAPPED_IPV6_PATTERN.matcher(input).matches(); + } + + /** + * Checks whether the parameter is a valid standard (non-compressed) IPv6 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid standard (non-compressed) IPv6 address + */ + public static boolean isIPv6StdAddress(final String input) { + return IPV6_STD_PATTERN.matcher(input).matches(); + } + + /** + * Checks whether the parameter is a valid compressed IPv6 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid compressed IPv6 address + */ + public static boolean isIPv6HexCompressedAddress(final String input) { + int colonCount = 0; + for(int i = 0; i < input.length(); i++) { + if (input.charAt(i) == COLON_CHAR) { + colonCount++; + } + } + return colonCount <= MAX_COLON_COUNT && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches(); + } + + /** + * Checks whether the parameter is a valid IPv6 address (including compressed). + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid standard or compressed IPv6 address + */ + public static boolean isIPv6Address(final String input) { + return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input); + } + +} diff --git a/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/package-info.java b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/package-info.java new file mode 100644 index 000000000..6db59b736 --- /dev/null +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/conn/util/package-info.java @@ -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/>. + * + */ + +/** + * Connection utility classes. + */ +package ch.boye.httpclientandroidlib.conn.util; |