Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 720914dd authored by Matthijs Tijink's avatar Matthijs Tijink

Use connection multiplexer in bluetooth link provider

parent bfd8ea92
......@@ -21,6 +21,7 @@
package org.kde.kdeconnect.Backends.BluetoothBackend;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
......@@ -43,7 +44,10 @@ import java.nio.charset.Charset;
import java.util.UUID;
public class BluetoothLink extends BaseLink {
private final BluetoothSocket socket;
private final ConnectionMultiplexer connection;
private final InputStream input;
private final OutputStream output;
private final BluetoothDevice remoteAddress;
private final BluetoothLinkProvider linkProvider;
private boolean continueAccepting = true;
......@@ -53,7 +57,7 @@ public class BluetoothLink extends BaseLink {
public void run() {
StringBuilder sb = new StringBuilder();
try {
Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8");
Reader reader = new InputStreamReader(input, "UTF-8");
char[] buf = new char[512];
while (continueAccepting) {
while (sb.indexOf("\n") == -1 && continueAccepting) {
......@@ -61,7 +65,12 @@ public class BluetoothLink extends BaseLink {
if ((charsRead = reader.read(buf)) > 0) {
sb.append(buf, 0, charsRead);
}
if (charsRead < 0) {
disconnect();
return;
}
}
if (!continueAccepting) break;
int endIndex = sb.indexOf("\n");
if (endIndex != -1) {
......@@ -71,7 +80,7 @@ public class BluetoothLink extends BaseLink {
}
}
} catch (IOException e) {
Log.e("BluetoothLink/receiving", "Connection to " + socket.getRemoteDevice().getAddress() + " likely broken.", e);
Log.e("BluetoothLink/receiving", "Connection to " + remoteAddress.getAddress() + " likely broken.", e);
disconnect();
}
}
......@@ -86,19 +95,11 @@ public class BluetoothLink extends BaseLink {
}
if (np.hasPayloadTransferInfo()) {
BluetoothSocket transferSocket = null;
try {
UUID transferUuid = UUID.fromString(np.getPayloadTransferInfo().getString("uuid"));
transferSocket = socket.getRemoteDevice().createRfcommSocketToServiceRecord(transferUuid);
transferSocket.connect();
np.setPayload(new NetworkPacket.Payload(transferSocket.getInputStream(), np.getPayloadSize()));
InputStream payloadInputStream = connection.getChannelInputStream(transferUuid);
np.setPayload(new NetworkPacket.Payload(payloadInputStream, np.getPayloadSize()));
} catch (Exception e) {
if (transferSocket != null) {
try {
transferSocket.close();
} catch (IOException ignored) {
}
}
Log.e("BluetoothLink/receiving", "Unable to get payload", e);
}
}
......@@ -107,9 +108,12 @@ public class BluetoothLink extends BaseLink {
}
});
public BluetoothLink(Context context, BluetoothSocket socket, String deviceId, BluetoothLinkProvider linkProvider) {
public BluetoothLink(Context context, ConnectionMultiplexer connection, InputStream input, OutputStream output, BluetoothDevice remoteAddress, String deviceId, BluetoothLinkProvider linkProvider) {
super(context, deviceId, linkProvider);
this.socket = socket;
this.connection = connection;
this.input = input;
this.output = output;
this.remoteAddress = remoteAddress;
this.linkProvider = linkProvider;
}
......@@ -128,22 +132,21 @@ public class BluetoothLink extends BaseLink {
}
public void disconnect() {
if (socket == null) {
if (connection == null) {
return;
}
continueAccepting = false;
try {
socket.close();
connection.close();
} catch (IOException ignored) {
}
linkProvider.disconnectedLink(this, getDeviceId(), socket);
linkProvider.disconnectedLink(this, getDeviceId(), remoteAddress);
}
private void sendMessage(NetworkPacket np) throws JSONException, IOException {
byte[] message = np.serialize().getBytes(Charset.forName("UTF-8"));
OutputStream socket = this.socket.getOutputStream();
Log.i("BluetoothLink", "Beginning to send message");
socket.write(message);
output.write(message);
Log.i("BluetoothLink", "Finished sending message");
}
......@@ -157,11 +160,9 @@ public class BluetoothLink extends BaseLink {
}*/
try {
BluetoothServerSocket serverSocket = null;
UUID transferUuid = null;
if (np.hasPayload()) {
UUID transferUuid = UUID.randomUUID();
serverSocket = BluetoothAdapter.getDefaultAdapter()
.listenUsingRfcommWithServiceRecord("KDE Connect Transfer", transferUuid);
transferUuid = connection.newChannel();
JSONObject payloadTransferInfo = new JSONObject();
payloadTransferInfo.put("uuid", transferUuid.toString());
np.setPayloadTransferInfo(payloadTransferInfo);
......@@ -169,28 +170,22 @@ public class BluetoothLink extends BaseLink {
sendMessage(np);
if (serverSocket != null) {
try (BluetoothSocket transferSocket = serverSocket.accept()) {
serverSocket.close();
if (transferUuid != null) {
try (OutputStream payloadStream = connection.getChannelOutputStream(transferUuid)) {
int BUFFER_LENGTH = 1024;
byte[] buffer = new byte[BUFFER_LENGTH];
int idealBufferLength = 4096;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& transferSocket.getMaxReceivePacketSize() > 0) {
idealBufferLength = transferSocket.getMaxReceivePacketSize();
}
byte[] buffer = new byte[idealBufferLength];
int bytesRead;
long progress = 0;
InputStream stream = np.getPayload().getInputStream();
while ((bytesRead = stream.read(buffer)) != -1) {
progress += bytesRead;
transferSocket.getOutputStream().write(buffer, 0, bytesRead);
payloadStream.write(buffer, 0, bytesRead);
if (np.getPayloadSize() > 0) {
callback.onProgressChanged((int) (100 * progress / np.getPayloadSize()));
}
}
transferSocket.getOutputStream().flush();
stream.close();
payloadStream.flush();
} catch (Exception e) {
callback.onFailure(e);
return false;
......
......@@ -38,6 +38,7 @@ import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.NetworkPacket;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
......@@ -132,8 +133,8 @@ public class BluetoothLinkProvider extends BaseLinkProvider {
return "BluetoothLinkProvider";
}
public void disconnectedLink(BluetoothLink link, String deviceId, BluetoothSocket socket) {
sockets.remove(socket.getRemoteDevice());
public void disconnectedLink(BluetoothLink link, String deviceId, BluetoothDevice remoteAddress) {
sockets.remove(remoteAddress);
visibleComputers.remove(deviceId);
connectionLost(link);
}
......@@ -164,57 +165,75 @@ public class BluetoothLinkProvider extends BaseLinkProvider {
return;
}
if (continueProcessing) {
while (continueProcessing) {
try {
BluetoothSocket socket = serverSocket.accept();
connect(socket);
} catch (Exception ignored) {
} catch (Exception e) {
Log.e("BTLinkProvider/Server", "Bluetooth error", e);
}
}
}
private void connect(BluetoothSocket socket) throws Exception {
//socket.connect();
OutputStream outputStream = socket.getOutputStream();
if (sockets.containsKey(socket.getRemoteDevice())) {
Log.i("BTLinkProvider/Server", "Received duplicate connection from " + socket.getRemoteDevice().getAddress());
socket.close();
return;
} else {
sockets.put(socket.getRemoteDevice(), socket);
synchronized (sockets) {
if (sockets.containsKey(socket.getRemoteDevice())) {
Log.i("BTLinkProvider/Server", "Received duplicate connection from " + socket.getRemoteDevice().getAddress());
socket.close();
return;
} else {
sockets.put(socket.getRemoteDevice(), socket);
}
}
Log.i("BTLinkProvider/Server", "Received connection from " + socket.getRemoteDevice().getAddress());
ConnectionMultiplexer connection = null;
try {
Log.i("BTLinkProvider/Server", "Received connection from " + socket.getRemoteDevice().getAddress());
NetworkPacket np = NetworkPacket.createIdentityPacket(context);
byte[] message = np.serialize().getBytes("UTF-8");
outputStream.write(message);
//Delay to let bluetooth initialize stuff correctly
Thread.sleep(500);
Log.i("BTLinkProvider/Server", "Sent identity package");
connection = new ConnectionMultiplexer(socket);
OutputStream outputStream = connection.getDefaultOutputStream();
InputStream inputStream = connection.getDefaultInputStream();
// Listen for the response
StringBuilder sb = new StringBuilder();
Reader reader = new InputStreamReader(socket.getInputStream(), "UTF-8");
int charsRead;
char[] buf = new char[512];
while (sb.lastIndexOf("\n") == -1 && (charsRead = reader.read(buf)) != -1) {
sb.append(buf, 0, charsRead);
}
NetworkPacket np = NetworkPacket.createIdentityPacket(context);
byte[] message = np.serialize().getBytes("UTF-8");
outputStream.write(message);
outputStream.flush();
String response = sb.toString();
final NetworkPacket identityPacket = NetworkPacket.unserialize(response);
Log.i("BTLinkProvider/Server", "Sent identity package");
if (!identityPacket.getType().equals(NetworkPacket.PACKET_TYPE_IDENTITY)) {
Log.e("BTLinkProvider/Server", "2 Expecting an identity package");
return;
}
// Listen for the response
StringBuilder sb = new StringBuilder();
Reader reader = new InputStreamReader(inputStream, "UTF-8");
int charsRead;
char[] buf = new char[512];
while (sb.lastIndexOf("\n") == -1 && (charsRead = reader.read(buf)) != -1) {
sb.append(buf, 0, charsRead);
}
Log.i("BTLinkProvider/Server", "Received identity package");
String response = sb.toString();
final NetworkPacket identityPacket = NetworkPacket.unserialize(response);
BluetoothLink link = new BluetoothLink(context, socket,
identityPacket.getString("deviceId"), BluetoothLinkProvider.this);
if (!identityPacket.getType().equals(NetworkPacket.PACKET_TYPE_IDENTITY)) {
Log.e("BTLinkProvider/Server", "2 Expecting an identity package");
return;
}
Log.i("BTLinkProvider/Server", "Received identity package");
addLink(identityPacket, link);
BluetoothLink link = new BluetoothLink(context, connection,
inputStream, outputStream, socket.getRemoteDevice(),
identityPacket.getString("deviceId"), BluetoothLinkProvider.this);
addLink(identityPacket, link);
} catch (Exception e) {
synchronized (sockets) {
sockets.remove(socket.getRemoteDevice());
if (connection != null) connection.close();
}
throw e;
}
}
}
......@@ -234,7 +253,7 @@ public class BluetoothLinkProvider extends BaseLinkProvider {
context.registerReceiver(this, filter);
}
while (continueProcessing) {
if (continueProcessing) {
connectToDevices();
try {
Thread.sleep(15000);
......@@ -328,9 +347,15 @@ public class BluetoothLinkProvider extends BaseLinkProvider {
Log.i("BTLinkProvider/Client", "Connected to " + device.getAddress());
try {
//Delay to let bluetooth initialize stuff correctly
Thread.sleep(500);
ConnectionMultiplexer connection = new ConnectionMultiplexer(socket);
OutputStream outputStream = connection.getDefaultOutputStream();
InputStream inputStream = connection.getDefaultInputStream();
int character;
StringBuilder sb = new StringBuilder();
while (sb.lastIndexOf("\n") == -1 && (character = socket.getInputStream().read()) != -1) {
while (sb.lastIndexOf("\n") == -1 && (character = inputStream.read()) != -1) {
sb.append((char) character);
}
......@@ -348,7 +373,7 @@ public class BluetoothLinkProvider extends BaseLinkProvider {
String myId = NetworkPacket.createIdentityPacket(context).getString("deviceId");
if (identityPacket.getString("deviceId").equals(myId)) {
// Probably won't happen, but just to be safe
socket.close();
connection.close();
return;
}
......@@ -358,8 +383,8 @@ public class BluetoothLinkProvider extends BaseLinkProvider {
Log.i("BTLinkProvider/Client", "Identity package received, creating link");
final BluetoothLink link = new BluetoothLink(context, socket,
identityPacket.getString("deviceId"), BluetoothLinkProvider.this);
final BluetoothLink link = new BluetoothLink(context, connection, inputStream, outputStream,
socket.getRemoteDevice(), identityPacket.getString("deviceId"), BluetoothLinkProvider.this);
NetworkPacket np2 = NetworkPacket.createIdentityPacket(context);
link.sendPacket(np2, new Device.SendPacketStatusCallback() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment