2 Commits

Author SHA1 Message Date
Alexey Danilov
e135bf0b42 ping proxy after starting to make sure it works fine 2015-09-25 20:46:02 +03:00
Alexey Danilov
edb12b574f fix readme 2015-09-25 17:08:50 +03:00
4 changed files with 89 additions and 5 deletions

View File

@@ -12,7 +12,7 @@ repositories {
maven { url 'https://dl.bintray.com/alexeydanilov/maven' }
}
dependencies {
compile 'com.danikula:videocache:2.1.2'
compile 'com.danikula:videocache:2.1.3'
}
```
@@ -59,8 +59,12 @@ More preferable way is use some dependency injector like [Dagger](http://square.
See `sample` app for details.
## Whats new
### 2.1.3
- ping proxy after starting to make sure it works fine
### 2.1.2
- fix offline work
### 2.1.1
- fix for too long cache file name
- url redirects support (thanks [ongakuer](https://github.com/ongakuer) for [PR](https://github.com/danikula/AndroidVideoCache/pull/12))

View File

@@ -26,7 +26,7 @@ publish {
userOrg = 'alexeydanilov'
groupId = 'com.danikula'
artifactId = 'videocache'
publishVersion = '2.1.2'
publishVersion = '2.1.3'
description = 'Cache support for android VideoView'
website = 'https://github.com/danikula/AndroidVideoCache'
}

View File

@@ -1,17 +1,25 @@
package com.danikula.videocache;
import android.os.SystemClock;
import android.util.Log;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static com.danikula.videocache.Preconditions.checkAllNotNull;
import static com.danikula.videocache.Preconditions.checkNotNull;
@@ -39,6 +47,8 @@ import static com.danikula.videocache.ProxyCacheUtils.LOG_TAG;
public class HttpProxyCacheServer {
private static final String PROXY_HOST = "127.0.0.1";
private static final String PING_REQUEST = "ping";
private static final String PING_RESPONSE = "ping ok";
private final Object clientsLock = new Object();
private final ExecutorService socketProcessor = Executors.newFixedThreadPool(8);
@@ -47,6 +57,7 @@ public class HttpProxyCacheServer {
private final int port;
private final Thread waitConnectionThread;
private final FileNameGenerator fileNameGenerator;
private boolean pinged;
public HttpProxyCacheServer(FileNameGenerator fileNameGenerator) {
this.fileNameGenerator = checkNotNull(fileNameGenerator);
@@ -58,13 +69,65 @@ public class HttpProxyCacheServer {
this.waitConnectionThread = new Thread(new WaitRequestsRunnable(startSignal));
this.waitConnectionThread.start();
startSignal.await(); // freeze thread, wait for server starts
Log.i(LOG_TAG, "Proxy cache server started. Ping it...");
makeSureServerWorks();
} catch (IOException | InterruptedException e) {
socketProcessor.shutdown();
throw new IllegalStateException("Error starting local proxy server", e);
}
}
private void makeSureServerWorks() {
int maxPingAttempts = 3;
int delay = 100;
int pingAttempts = 0;
while (pingAttempts < maxPingAttempts) {
try {
Future<Boolean> pingFuture = socketProcessor.submit(new PingCallable());
pinged = pingFuture.get(delay, TimeUnit.MILLISECONDS);
if (pinged) {
return;
}
pingAttempts++;
SystemClock.sleep(delay);
delay *= 2;
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.e(LOG_TAG, "Error pinging server. Shutdown it... If you see this message, please, email me danikula@gmail.com", e);
}
}
if (!pinged) {
shutdown();
}
}
private boolean pingServer() throws ProxyCacheException {
String pingUrl = appendToProxyUrl(PING_REQUEST);
HttpUrlSource source = new HttpUrlSource(pingUrl);
try {
byte[] expectedResponse = PING_RESPONSE.getBytes();
source.open(0);
byte[] response = new byte[expectedResponse.length];
source.read(response);
boolean pingOk = Arrays.equals(expectedResponse, response);
Log.d(LOG_TAG, "Ping response: `" + new String(response) + "`, pinged? " + pingOk);
return pingOk;
} catch (ProxyCacheException e) {
Log.e(LOG_TAG, "Error reading ping response", e);
return false;
} finally {
source.close();
}
}
public String getProxyUrl(String url) {
if (!pinged) {
Log.e(LOG_TAG, "Proxy server isn't pinged. Caching doesn't work. If you see this message, please, email me danikula@gmail.com");
}
return pinged ? appendToProxyUrl(url) : url;
}
private String appendToProxyUrl(String url) {
return String.format("http://%s:%d/%s", PROXY_HOST, port, ProxyCacheUtils.encode(url));
}
@@ -140,8 +203,12 @@ public class HttpProxyCacheServer {
GetRequest request = GetRequest.read(socket.getInputStream());
Log.i(LOG_TAG, "Request to cache proxy:" + request);
String url = ProxyCacheUtils.decode(request.uri);
HttpProxyCacheServerClients clients = getClients(url);
clients.processRequest(request, socket);
if (PING_REQUEST.equals(url)) {
responseToPing(socket);
} else {
HttpProxyCacheServerClients clients = getClients(url);
clients.processRequest(request, socket);
}
} catch (SocketException e) {
// There is no way to determine that client closed connection http://stackoverflow.com/a/10241044/999458
// So just to prevent log flooding don't log stacktrace
@@ -154,6 +221,12 @@ public class HttpProxyCacheServer {
}
}
private void responseToPing(Socket socket) throws IOException {
OutputStream out = socket.getOutputStream();
out.write("HTTP/1.1 200 OK\n\n".getBytes());
out.write(PING_RESPONSE.getBytes());
}
private HttpProxyCacheServerClients getClients(String url) throws ProxyCacheException {
synchronized (clientsLock) {
HttpProxyCacheServerClients clients = clientsMap.get(url);
@@ -248,4 +321,11 @@ public class HttpProxyCacheServer {
}
}
private class PingCallable implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
return pingServer();
}
}
}

View File

@@ -39,7 +39,7 @@ dependencies {
// compile project(':library')
compile 'com.android.support:support-v4:23.0.1'
compile 'org.androidannotations:androidannotations-api:3.3.2'
compile 'com.danikula:videocache:2.1.2'
compile 'com.danikula:videocache:2.1.3'
compile 'com.viewpagerindicator:library:2.4.2-SNAPSHOT@aar'
apt 'org.androidannotations:androidannotations:3.3.2'
}