1153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath/*
2153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * Copyright (C) 2012 The Android Open Source Project
3153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath *
4153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * Licensed under the Apache License, Version 2.0 (the "License");
5153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * you may not use this file except in compliance with the License.
6153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * You may obtain a copy of the License at
7153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath *
8153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath *      http://www.apache.org/licenses/LICENSE-2.0
9153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath *
10153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * Unless required by applicable law or agreed to in writing, software
11153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * distributed under the License is distributed on an "AS IS" BASIS,
12153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * See the License for the specific language governing permissions and
14153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * limitations under the License.
15153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath */
16153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
17153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathpackage libcore.util;
18153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
19153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport javax.net.ssl.SSLSocket;
20153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.io.File;
21153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.io.IOException;
229542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamathimport java.io.OutputStream;
239542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamathimport java.lang.reflect.Constructor;
24153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.lang.reflect.InvocationTargetException;
25153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.lang.reflect.Method;
26153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.net.Socket;
27153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.net.SocketException;
28153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.net.URI;
29153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.net.URISyntaxException;
30153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.net.URL;
31153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathimport java.nio.ByteOrder;
329542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamathimport java.util.zip.Deflater;
339542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamathimport java.util.zip.DeflaterOutputStream;
34153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
35153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath/**
36153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * APIs for interacting with Android's core library. The main purpose of this
37153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * class is to access hidden methods on
38153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath *
39153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl
40153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath *
41153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath * via reflection.
42153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath */
43153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamathpublic final class Libcore {
44153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
45153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    private Libcore() {
46153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
47153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
48153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    private static final Class<?> openSslSocketClass;
49153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    private static final Method setUseSessionTickets;
50153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    private static final Method setHostname;
51153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    private static final Method setNpnProtocols;
52153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    private static final Method getNpnSelectedProtocol;
539542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath    private static final Constructor<DeflaterOutputStream> deflaterOutputStreamConstructor;
54153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
55153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    static {
56153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        try {
57153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            openSslSocketClass = Class.forName(
58153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                    "org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl");
59153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            setUseSessionTickets = openSslSocketClass.getMethod(
60153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                    "setUseSessionTickets", boolean.class);
61153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            setHostname = openSslSocketClass.getMethod("setHostname", String.class);
62153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            setNpnProtocols = openSslSocketClass.getMethod("setNpnProtocols", byte[].class);
63153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            getNpnSelectedProtocol = openSslSocketClass.getMethod("getNpnSelectedProtocol");
649542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath            deflaterOutputStreamConstructor = DeflaterOutputStream.class.getConstructor(
659542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath                   new Class[] { OutputStream.class, Deflater.class, boolean.class });
66153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } catch (ClassNotFoundException cnfe) {
67153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            throw new RuntimeException(cnfe);
68153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } catch (NoSuchMethodException nsme) {
69153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            throw new RuntimeException(nsme);
70153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
71153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
72153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
739542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath    public static DeflaterOutputStream newDeflaterOutputStream(
749542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath            OutputStream os, Deflater deflater, boolean syncFlush) {
759542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath        try {
769542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath            return deflaterOutputStreamConstructor.newInstance(os, deflater, syncFlush);
779542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath        } catch (InstantiationException e) {
789542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath            throw new RuntimeException("Unknown DeflaterOutputStream implementation.");
799542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath        } catch (IllegalAccessException e) {
809542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath            throw new RuntimeException("Unknown DeflaterOutputStream implementation.");
819542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath        } catch (InvocationTargetException e) {
829542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath            throw new RuntimeException("Unknown DeflaterOutputStream implementation.");
839542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath        }
849542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath    }
859542e750421542d4dea1f1d33c0f4349b3c48536Narayan Kamath
86153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void makeTlsTolerant(SSLSocket socket, String socketHost, boolean tlsTolerant) {
87153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if (!tlsTolerant) {
88153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            socket.setEnabledProtocols(new String[] {"SSLv3"});
89153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            return;
90153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
91153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
92153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if (openSslSocketClass.isInstance(socket)) {
93153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            try {
94153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                setUseSessionTickets.invoke(socket, true);
95153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                setHostname.invoke(socket, socketHost);
96153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            } catch (InvocationTargetException e) {
97153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                throw new RuntimeException(e);
98153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            } catch (IllegalAccessException e) {
99153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                throw new AssertionError(e);
100153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            }
101153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } else {
102153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            throw new RuntimeException("Unknown socket implementation.");
103153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
104153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
105153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
106153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    /**
107153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath     * Returns the negotiated protocol, or null if no protocol was negotiated.
108153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath     */
109153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static byte[] getNpnSelectedProtocol(SSLSocket socket) {
110153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if (openSslSocketClass.isInstance(socket)) {
111153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            try {
112153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                return (byte[]) getNpnSelectedProtocol.invoke(socket);
113153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            } catch (InvocationTargetException e) {
114153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                throw new RuntimeException(e);
115153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            } catch (IllegalAccessException e) {
116153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                throw new AssertionError(e);
117153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            }
118153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } else {
119153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            throw new RuntimeException("Unknown socket implementation.");
120153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
121153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
122153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
123153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void setNpnProtocols(SSLSocket socket, byte[] npnProtocols) {
124153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if (openSslSocketClass.isInstance(socket)) {
125153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            try {
126153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                setNpnProtocols.invoke(socket, new Object[] {npnProtocols});
127153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            } catch (IllegalAccessException e) {
128153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                throw new AssertionError(e);
129153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            } catch (InvocationTargetException e) {
130153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath                throw new RuntimeException(e);
131153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            }
132153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } else {
133153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            throw new RuntimeException("Unknown socket implementation.");
134153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
135153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
136153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
137153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void deleteIfExists(File file) throws IOException {
138153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        // okhttp-changed: was Libcore.os.remove() in a try/catch block
139153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        file.delete();
140153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
141153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
142153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void logW(String warning) {
143153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        // okhttp-changed: was System.logw()
144153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        System.out.println(warning);
145153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
146153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
147153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static int getEffectivePort(URI uri) {
148153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        return getEffectivePort(uri.getScheme(), uri.getPort());
149153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
150153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
151153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static int getEffectivePort(URL url) {
152153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        return getEffectivePort(url.getProtocol(), url.getPort());
153153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
154153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
155153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    private static int getEffectivePort(String scheme, int specifiedPort) {
156153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if (specifiedPort != -1) {
157153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            return specifiedPort;
158153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
159153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
160153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if ("http".equalsIgnoreCase(scheme)) {
161153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            return 80;
162153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } else if ("https".equalsIgnoreCase(scheme)) {
163153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            return 443;
164153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } else {
165153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            return -1;
166153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
167153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
168153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
169153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
170153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
171153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            throw new ArrayIndexOutOfBoundsException();
172153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
173153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
174153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
175153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void tagSocket(Socket socket) {
176153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
177153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
178153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void untagSocket(Socket socket) throws SocketException {
179153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
180153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
181153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static URI toUriLenient(URL url) throws URISyntaxException {
182153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        return url.toURI(); // this isn't as good as the built-in toUriLenient
183153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
184153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath
185153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    public static void pokeInt(byte[] dst, int offset, int value, ByteOrder order) {
186153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        if (order == ByteOrder.BIG_ENDIAN) {
187153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset++] = (byte) ((value >> 24) & 0xff);
188153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset++] = (byte) ((value >> 16) & 0xff);
189153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset++] = (byte) ((value >>  8) & 0xff);
190153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset  ] = (byte) ((value >>  0) & 0xff);
191153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        } else {
192153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset++] = (byte) ((value >>  0) & 0xff);
193153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset++] = (byte) ((value >>  8) & 0xff);
194153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset++] = (byte) ((value >> 16) & 0xff);
195153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath            dst[offset  ] = (byte) ((value >> 24) & 0xff);
196153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath        }
197153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath    }
198153d0953fe0df254bf3ffaa56934c97020b86edbNarayan Kamath}
199