diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/server/connectivity/NetworkMonitor.java | 74 |
1 files changed, 65 insertions, 9 deletions
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java index 6fc146d..9ee4cd9 100644 --- a/src/com/android/server/connectivity/NetworkMonitor.java +++ b/src/com/android/server/connectivity/NetworkMonitor.java @@ -153,11 +153,15 @@ import com.android.networkstack.netlink.TcpSocketTracker; import com.android.networkstack.util.DnsUtils; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -171,6 +175,8 @@ import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * {@hide} @@ -1810,15 +1816,10 @@ public class NetworkMonitor extends StateMachine { final int oldTag = TrafficStats.getAndSetThreadStatsTag( TrafficStatsConstants.TAG_SYSTEM_PROBE); try { - urlConnection = (HttpURLConnection) mCleartextDnsNetwork.openConnection(url); - urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC); - urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS); - urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS); - urlConnection.setRequestProperty("Connection", "close"); - urlConnection.setUseCaches(false); - if (mCaptivePortalUserAgent != null) { - urlConnection.setRequestProperty("User-Agent", mCaptivePortalUserAgent); - } + // Follow redirects for PAC probes as such probes verify connectivity by fetching the + // PAC proxy file, which may be configured behind a redirect. + final boolean followRedirect = probeType == ValidationProbeEvent.PROBE_PAC; + urlConnection = makeProbeConnection(url, followRedirect); // cannot read request header after connection String requestHeader = urlConnection.getRequestProperties().toString(); @@ -1886,6 +1887,61 @@ public class NetworkMonitor extends StateMachine { } } + private HttpURLConnection makeProbeConnection(URL url, boolean followRedirects) + throws IOException { + final HttpURLConnection conn = (HttpURLConnection) mCleartextDnsNetwork.openConnection(url); + conn.setInstanceFollowRedirects(followRedirects); + conn.setConnectTimeout(SOCKET_TIMEOUT_MS); + conn.setReadTimeout(SOCKET_TIMEOUT_MS); + conn.setRequestProperty("Connection", "close"); + conn.setUseCaches(false); + if (mCaptivePortalUserAgent != null) { + conn.setRequestProperty("User-Agent", mCaptivePortalUserAgent); + } + return conn; + } + + @VisibleForTesting + @NonNull + protected static String readAsString(InputStream is, int maxLength, Charset charset) + throws IOException { + final InputStreamReader reader = new InputStreamReader(is, charset); + final char[] buffer = new char[1000]; + final StringBuilder builder = new StringBuilder(); + int totalReadLength = 0; + while (totalReadLength < maxLength) { + final int availableLength = Math.min(maxLength - totalReadLength, buffer.length); + final int currentLength = reader.read(buffer, 0, availableLength); + if (currentLength < 0) break; // EOF + + totalReadLength += currentLength; + builder.append(buffer, 0, currentLength); + } + return builder.toString(); + } + + /** + * Attempt to extract the {@link Charset} of the response from its Content-Type header. + * + * <p>If the {@link Charset} cannot be extracted, UTF-8 is returned by default. + */ + @VisibleForTesting + @NonNull + protected static Charset extractCharset(@Nullable String contentTypeHeader) { + if (contentTypeHeader == null) return StandardCharsets.UTF_8; + // See format in https://tools.ietf.org/html/rfc7231#section-3.1.1.1 + final Pattern charsetPattern = Pattern.compile("; *charset=\"?([^ ;\"]+)\"?", + Pattern.CASE_INSENSITIVE); + final Matcher matcher = charsetPattern.matcher(contentTypeHeader); + if (!matcher.find()) return StandardCharsets.UTF_8; + + try { + return Charset.forName(matcher.group(1)); + } catch (IllegalArgumentException e) { + return StandardCharsets.UTF_8; + } + } + private CaptivePortalProbeResult sendParallelHttpProbes( ProxyInfo proxy, URL httpsUrl, URL httpUrl) { // Number of probes to wait for. If a probe completes with a conclusive answer |