Platform.java revision aefd3aaff8334d99f42cd8229e749e110aaf1d34
1/*
2 * Copyright (C) 2012 Square, Inc.
3 * Copyright (C) 2012 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package com.squareup.okhttp.internal;
18
19import dalvik.system.SocketTagger;
20import java.io.OutputStream;
21import java.net.Socket;
22import java.net.SocketException;
23import java.net.URI;
24import java.net.URISyntaxException;
25import java.net.URL;
26import java.util.zip.Deflater;
27import java.util.zip.DeflaterOutputStream;
28import javax.net.ssl.SSLSocket;
29import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
30
31/**
32 * Access to proprietary Android APIs. Doesn't use reflection.
33 */
34public final class Platform {
35    private static final Platform PLATFORM = new Platform();
36
37    public static Platform get() {
38        return PLATFORM;
39    }
40
41    public void logW(String warning) {
42        System.logW(warning);
43    }
44
45    public void tagSocket(Socket socket) throws SocketException {
46        SocketTagger.get().tag(socket);
47    }
48
49    public void untagSocket(Socket socket) throws SocketException {
50        SocketTagger.get().untag(socket);
51    }
52
53    public URI toUriLenient(URL url) throws URISyntaxException {
54        return url.toURILenient();
55    }
56
57    public void enableTlsExtensions(SSLSocket socket, String uriHost) {
58        if (socket instanceof OpenSSLSocketImpl) {
59            OpenSSLSocketImpl openSSLSocket = (OpenSSLSocketImpl) socket;
60            openSSLSocket.setUseSessionTickets(true);
61            openSSLSocket.setHostname(uriHost);
62        }
63    }
64
65    public void supportTlsIntolerantServer(SSLSocket socket) {
66        // In accordance with https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00
67        // the SCSV cipher is added to signal that a protocol fallback has taken place.
68        final String fallbackScsv = "TLS_FALLBACK_SCSV";
69        boolean socketSupportsFallbackScsv = false;
70        String[] supportedCipherSuites = socket.getSupportedCipherSuites();
71        for (int i = supportedCipherSuites.length - 1; i >= 0; i--) {
72            String supportedCipherSuite = supportedCipherSuites[i];
73            if (fallbackScsv.equals(supportedCipherSuite)) {
74                socketSupportsFallbackScsv = true;
75                break;
76            }
77        }
78        if (socketSupportsFallbackScsv) {
79            // Add the SCSV cipher to the set of enabled ciphers.
80            String[] enabledCipherSuites = socket.getEnabledCipherSuites();
81            String[] newEnabledCipherSuites = new String[enabledCipherSuites.length + 1];
82            System.arraycopy(enabledCipherSuites, 0,
83                    newEnabledCipherSuites, 0, enabledCipherSuites.length);
84            newEnabledCipherSuites[newEnabledCipherSuites.length - 1] = fallbackScsv;
85            socket.setEnabledCipherSuites(newEnabledCipherSuites);
86        }
87        socket.setEnabledProtocols(new String[]{"SSLv3"});
88    }
89
90    /**
91     * Returns the negotiated protocol, or null if no protocol was negotiated.
92     */
93    public byte[] getNpnSelectedProtocol(SSLSocket socket) {
94        return socket instanceof OpenSSLSocketImpl
95                ? ((OpenSSLSocketImpl) socket).getNpnSelectedProtocol()
96                : null;
97    }
98
99    /**
100     * Sets client-supported protocols on a socket to send to a server. The
101     * protocols are only sent if the socket implementation supports NPN.
102     */
103    public void setNpnProtocols(SSLSocket socket, byte[] npnProtocols) {
104        if (socket instanceof OpenSSLSocketImpl) {
105            ((OpenSSLSocketImpl) socket).setNpnProtocols(npnProtocols);
106        }
107    }
108
109    /**
110     * Returns a deflater output stream that supports SYNC_FLUSH for SPDY name
111     * value blocks. This throws an {@link UnsupportedOperationException} on
112     * Java 6 and earlier where there is no built-in API to do SYNC_FLUSH.
113     */
114    public OutputStream newDeflaterOutputStream(
115            OutputStream out, Deflater deflater, boolean syncFlush) {
116        return new DeflaterOutputStream(out, deflater, syncFlush);
117    }
118}
119