]>
Commit | Line | Data |
---|---|---|
7b417757 | 1 | /* |
ad2d20e5 | 2 | * Copyright (C) 2017-2018 Tobias Brunner |
19ef2aec TB |
3 | * |
4 | * Copyright (C) secunet Security Networks AG | |
7b417757 TB |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | */ | |
16 | ||
17 | package org.strongswan.android.logic; | |
18 | ||
829cc56a | 19 | import java.io.BufferedOutputStream; |
7b417757 TB |
20 | import java.io.ByteArrayOutputStream; |
21 | import java.io.IOException; | |
22 | import java.io.InputStream; | |
829cc56a | 23 | import java.io.OutputStream; |
7b417757 | 24 | import java.net.HttpURLConnection; |
b944159f | 25 | import java.net.Proxy; |
ad2d20e5 | 26 | import java.net.SocketTimeoutException; |
7b417757 | 27 | import java.net.URL; |
ad2d20e5 TB |
28 | import java.util.ArrayList; |
29 | import java.util.concurrent.CancellationException; | |
30 | import java.util.concurrent.ExecutionException; | |
31 | import java.util.concurrent.ExecutorService; | |
32 | import java.util.concurrent.Executors; | |
33 | import java.util.concurrent.Future; | |
34 | import java.util.concurrent.TimeUnit; | |
35 | import java.util.concurrent.TimeoutException; | |
7b417757 | 36 | |
3b9696fc TB |
37 | import androidx.annotation.Keep; |
38 | ||
7b417757 TB |
39 | @Keep |
40 | public class SimpleFetcher | |
41 | { | |
ad2d20e5 TB |
42 | private static ExecutorService mExecutor = Executors.newCachedThreadPool(); |
43 | private static Object mLock = new Object(); | |
44 | private static ArrayList<Future> mFutures = new ArrayList<>(); | |
45 | private static boolean mDisabled; | |
46 | ||
47 | public static byte[] fetch(String uri, byte[] data, String contentType) | |
7b417757 | 48 | { |
ad2d20e5 TB |
49 | Future<byte[]> future; |
50 | ||
51 | synchronized (mLock) | |
7b417757 | 52 | { |
ad2d20e5 | 53 | if (mDisabled) |
829cc56a | 54 | { |
ad2d20e5 | 55 | return null; |
829cc56a | 56 | } |
ad2d20e5 TB |
57 | future = mExecutor.submit(() -> { |
58 | URL url = new URL(uri); | |
b944159f | 59 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); |
ad2d20e5 TB |
60 | conn.setConnectTimeout(10000); |
61 | conn.setReadTimeout(10000); | |
7433f167 | 62 | conn.setRequestProperty("Connection", "close"); |
ad2d20e5 TB |
63 | try |
64 | { | |
65 | if (contentType != null) | |
66 | { | |
67 | conn.setRequestProperty("Content-Type", contentType); | |
68 | } | |
69 | if (data != null) | |
70 | { | |
71 | conn.setDoOutput(true); | |
72 | conn.setFixedLengthStreamingMode(data.length); | |
73 | OutputStream out = new BufferedOutputStream(conn.getOutputStream()); | |
74 | out.write(data); | |
75 | out.close(); | |
76 | } | |
77 | return streamToArray(conn.getInputStream()); | |
78 | } | |
79 | catch (SocketTimeoutException e) | |
80 | { | |
81 | return null; | |
82 | } | |
83 | finally | |
84 | { | |
85 | conn.disconnect(); | |
86 | } | |
87 | }); | |
88 | ||
89 | mFutures.add(future); | |
90 | } | |
91 | ||
92 | try | |
93 | { | |
94 | /* this enforces a timeout as the ones set on HttpURLConnection might not work reliably */ | |
95 | return future.get(10000, TimeUnit.MILLISECONDS); | |
96 | } | |
97 | catch (InterruptedException|ExecutionException|TimeoutException|CancellationException e) | |
98 | { | |
99 | return null; | |
100 | } | |
101 | finally | |
102 | { | |
103 | synchronized (mLock) | |
829cc56a | 104 | { |
ad2d20e5 | 105 | mFutures.remove(future); |
829cc56a | 106 | } |
7b417757 | 107 | } |
ad2d20e5 TB |
108 | } |
109 | ||
110 | /** | |
111 | * Enable fetching after it has been disabled. | |
112 | */ | |
113 | public static void enable() | |
114 | { | |
115 | synchronized (mLock) | |
116 | { | |
117 | mDisabled = false; | |
118 | } | |
119 | } | |
120 | ||
121 | /** | |
122 | * Disable the fetcher and abort any future requests. | |
123 | * | |
f6aafb30 | 124 | * The native thread is not cancelable as it is working on an IKE_SA (canceling the methods of |
ad2d20e5 TB |
125 | * HttpURLConnection is not reliably possible anyway), so to abort while fetching we cancel the |
126 | * Future (causing a return from fetch() immediately) and let the executor thread continue its | |
127 | * thing in the background. | |
128 | * | |
129 | * Also prevents future fetches until enabled again (e.g. if we aborted OCSP but would then | |
130 | * block in the subsequent fetch for a CRL). | |
131 | */ | |
132 | public static void disable() | |
133 | { | |
134 | synchronized (mLock) | |
7b417757 | 135 | { |
ad2d20e5 TB |
136 | mDisabled = true; |
137 | for (Future future : mFutures) | |
138 | { | |
139 | future.cancel(true); | |
140 | } | |
7b417757 TB |
141 | } |
142 | } | |
143 | ||
829cc56a | 144 | private static byte[] streamToArray(InputStream in) throws IOException |
7b417757 TB |
145 | { |
146 | ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
147 | byte[] buf = new byte[1024]; | |
148 | int len; | |
149 | ||
150 | try | |
151 | { | |
152 | while ((len = in.read(buf)) != -1) | |
153 | { | |
154 | out.write(buf, 0, len); | |
155 | } | |
156 | return out.toByteArray(); | |
157 | } | |
158 | catch (IOException e) | |
159 | { | |
160 | e.printStackTrace(); | |
161 | } | |
829cc56a TB |
162 | finally |
163 | { | |
164 | in.close(); | |
165 | } | |
7b417757 TB |
166 | return null; |
167 | } | |
168 | } |