WIP: Bluetooth successfully sending entire HTTP responses to GET requests.

Now to move the code into a BluetoothDownloader and decide how best
to handle connections, error handling, multiple downloads over one
socket, etc.
This commit is contained in:
Peter Serwylo 2014-10-20 23:50:48 +10:30 committed by Peter Serwylo
parent 7dff9a9499
commit 41b3eab1fd
8 changed files with 64 additions and 15 deletions

View File

@ -168,6 +168,7 @@ public abstract class LocalRepoService extends Service {
} }
protected abstract String getIpAddressToBindTo(); protected abstract String getIpAddressToBindTo();
protected abstract int getPortToBindTo();
protected void startWebServer() { protected void startWebServer() {
Runnable webServer = new Runnable() { Runnable webServer = new Runnable() {
@ -178,7 +179,7 @@ public abstract class LocalRepoService extends Service {
localHttpd = new LocalHTTPD( localHttpd = new LocalHTTPD(
LocalRepoService.this, LocalRepoService.this,
getIpAddressToBindTo(), getIpAddressToBindTo(),
FDroidApp.port, getPortToBindTo(),
getFilesDir(), getFilesDir(),
useHttps()); useHttps());

View File

@ -144,4 +144,8 @@ public class HttpDownloader extends Downloader {
return this.statusCode != 304; return this.statusCode != 304;
} }
public int getStatusCode() {
return statusCode;
}
} }

View File

@ -151,7 +151,6 @@ public class WifiStateChangeService extends Service {
Intent intent = new Intent(BROADCAST); Intent intent = new Intent(BROADCAST);
LocalBroadcastManager.getInstance(WifiStateChangeService.this).sendBroadcast(intent); LocalBroadcastManager.getInstance(WifiStateChangeService.this).sendBroadcast(intent);
WifiStateChangeService.this.stopSelf(); WifiStateChangeService.this.stopSelf();
FDroidApp.localRepoWifi.restartIfRunning();
} }
} }

View File

@ -1,5 +1,7 @@
package org.fdroid.fdroid.localrepo; package org.fdroid.fdroid.localrepo;
import org.fdroid.fdroid.FDroidApp;
/** /**
* Starts the local repo service but bound to 127.0.0.1. * Starts the local repo service but bound to 127.0.0.1.
* Also, it does not care about whether wifi is connected or not, * Also, it does not care about whether wifi is connected or not,
@ -26,4 +28,9 @@ public class LocalRepoProxyService extends LocalRepoService {
protected String getIpAddressToBindTo() { protected String getIpAddressToBindTo() {
return "127.0.0.1"; return "127.0.0.1";
} }
@Override
protected int getPortToBindTo() {
return FDroidApp.port + 1;
}
} }

View File

@ -71,6 +71,11 @@ public class LocalRepoWifiService extends LocalRepoService {
return FDroidApp.ipAddressString; return FDroidApp.ipAddressString;
} }
@Override
protected int getPortToBindTo() {
return FDroidApp.port;
}
private Preferences.ChangeListener localRepoBonjourChangeListener = new Preferences.ChangeListener() { private Preferences.ChangeListener localRepoBonjourChangeListener = new Preferences.ChangeListener() {
@Override @Override
public void onPreferenceChange() { public void onPreferenceChange() {

View File

@ -5,6 +5,7 @@ import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothSocket;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.net.HttpDownloader; import org.fdroid.fdroid.net.HttpDownloader;
import org.fdroid.fdroid.net.bluetooth.httpish.Request; import org.fdroid.fdroid.net.bluetooth.httpish.Request;
@ -120,20 +121,21 @@ public class BluetoothServer extends Thread {
Log.d(TAG, "Received Bluetooth request from client, will process it now."); Log.d(TAG, "Received Bluetooth request from client, will process it now.");
try { try {
HttpDownloader downloader = new HttpDownloader("http://127.0.0.1/" + request.getPath(), context); HttpDownloader downloader = new HttpDownloader("http://127.0.0.1:" + ( FDroidApp.port + 1 ) + "/" + request.getPath(), context);
Response.ResponseBuilder builder; Response.Builder builder;
if (request.getMethod().equals(Request.Methods.HEAD)) { if (request.getMethod().equals(Request.Methods.HEAD)) {
builder = new Response.ResponseBuilder(); builder = new Response.Builder();
} else { } else {
builder = new Response.ResponseBuilder(downloader.getInputStream()); builder = new Response.Builder(downloader.getInputStream());
} }
// TODO: At this stage, will need to download the file to get this info. // TODO: At this stage, will need to download the file to get this info.
// However, should be able to make totalDownloadSize and getCacheTag work without downloading. // However, should be able to make totalDownloadSize and getCacheTag work without downloading.
return builder return builder
.setStatusCode(200) .setStatusCode(downloader.getStatusCode())
.setFileSize(downloader.totalDownloadSize())
.build(); .build();
} catch (IOException e) { } catch (IOException e) {

View File

@ -6,6 +6,7 @@ import org.fdroid.fdroid.net.bluetooth.BluetoothConnection;
import org.fdroid.fdroid.net.bluetooth.FileDetails; import org.fdroid.fdroid.net.bluetooth.FileDetails;
import org.fdroid.fdroid.net.bluetooth.httpish.headers.Header; import org.fdroid.fdroid.net.bluetooth.httpish.headers.Header;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
@ -41,6 +42,17 @@ public class Response {
return statusCode; return statusCode;
} }
public int getFileSize() {
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().toLowerCase().equals("content-length")) {
return Integer.parseInt( entry.getValue()); // TODO: error handling.
}
}
}
return -1;
}
/** /**
* Extracts meaningful headers from the response into a more useful and safe * Extracts meaningful headers from the response into a more useful and safe
* {@link org.fdroid.fdroid.net.bluetooth.FileDetails} object. * {@link org.fdroid.fdroid.net.bluetooth.FileDetails} object.
@ -85,30 +97,47 @@ public class Response {
} }
public static class ResponseBuilder { public String readContents() throws IOException {
int size = getFileSize();
if (contentStream == null || getFileSize() <= 0) {
return null;
}
int pos = 0;
byte[] buffer = new byte[4096];
ByteArrayOutputStream contents = new ByteArrayOutputStream(size);
while (pos < size) {
int read = contentStream.read(buffer);
pos += read;
contents.write(buffer, 0, read);
}
return contents.toString();
}
public static class Builder {
private InputStream contentStream; private InputStream contentStream;
private int statusCode = 200; private int statusCode = 200;
private int fileSize = -1; private int fileSize = -1;
private String etag = null; private String etag = null;
public ResponseBuilder() {} public Builder() {}
public ResponseBuilder(InputStream contentStream) { public Builder(InputStream contentStream) {
this.contentStream = contentStream; this.contentStream = contentStream;
} }
public ResponseBuilder setStatusCode(int statusCode) { public Builder setStatusCode(int statusCode) {
this.statusCode = statusCode; this.statusCode = statusCode;
return this; return this;
} }
public ResponseBuilder setFileSize(int fileSize) { public Builder setFileSize(int fileSize) {
this.fileSize = fileSize; this.fileSize = fileSize;
return this; return this;
} }
public ResponseBuilder setETag(String etag) { public Builder setETag(String etag) {
this.etag = etag; this.etag = etag;
return this; return this;
} }

View File

@ -133,12 +133,14 @@ public class BluetoothDeviceListFragment extends ThemeableListFragment {
Log.d(TAG, "Testing bluetooth connection (opening connection first)."); Log.d(TAG, "Testing bluetooth connection (opening connection first).");
BluetoothConnection connection = client.openConnection(); BluetoothConnection connection = client.openConnection();
Log.d(TAG, "Creating HEAD request for resource at \"/\"..."); Log.d(TAG, "Creating HEAD request for resource at \"/\"...");
Request head = Request.createHEAD("/", connection); Request head = Request.createGET("/", connection);
Log.d(TAG, "Sending request..."); Log.d(TAG, "Sending request...");
Response response = head.send(); Response response = head.send();
Log.d(TAG, "Response from bluetooth: " + response.getStatusCode()); Log.d(TAG, "Response from bluetooth: " + response.getStatusCode());
String contents = response.readContents();
Log.d(TAG, contents);
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Error: " + e.getMessage());
} }
/*if (device.getBondState() == BluetoothDevice.BOND_NONE) { /*if (device.getBondState() == BluetoothDevice.BOND_NONE) {