]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/frontends/android/app/src/main/java/org/strongswan/android/logic/SimpleFetcher.java
android: Make fetching OCSP/CRL interruptible
[thirdparty/strongswan.git] / src / frontends / android / app / src / main / java / org / strongswan / android / logic / SimpleFetcher.java
CommitLineData
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
16package org.strongswan.android.logic;
17
18import android.support.annotation.Keep;
19
829cc56a 20import java.io.BufferedOutputStream;
7b417757
TB
21import java.io.ByteArrayOutputStream;
22import java.io.IOException;
23import java.io.InputStream;
829cc56a 24import java.io.OutputStream;
7b417757 25import java.net.HttpURLConnection;
ad2d20e5 26import java.net.SocketTimeoutException;
7b417757 27import java.net.URL;
ad2d20e5
TB
28import java.util.ArrayList;
29import java.util.concurrent.CancellationException;
30import java.util.concurrent.ExecutionException;
31import java.util.concurrent.ExecutorService;
32import java.util.concurrent.Executors;
33import java.util.concurrent.Future;
34import java.util.concurrent.TimeUnit;
35import java.util.concurrent.TimeoutException;
7b417757
TB
36
37@Keep
38public 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}