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