diff --git a/KdeConnect/KdeConnect.iml b/KdeConnect/KdeConnect.iml index e79ec377..ef070ffd 100644 --- a/KdeConnect/KdeConnect.iml +++ b/KdeConnect/KdeConnect.iml @@ -68,6 +68,8 @@ + + diff --git a/KdeConnect/build.gradle b/KdeConnect/build.gradle index e3d81fa5..725bc903 100644 --- a/KdeConnect/build.gradle +++ b/KdeConnect/build.gradle @@ -10,6 +10,8 @@ apply plugin: 'android' dependencies { compile files('libs/android-support-v4.jar') + compile files('libs/mina-core-2.0.7.jar') + compile files('libs/slf4j-api-1.6.6.jar') } android { diff --git a/KdeConnect/libs/mina-core-2.0.7.jar b/KdeConnect/libs/mina-core-2.0.7.jar new file mode 100644 index 00000000..5ec135bb Binary files /dev/null and b/KdeConnect/libs/mina-core-2.0.7.jar differ diff --git a/KdeConnect/libs/slf4j-api-1.6.6.jar b/KdeConnect/libs/slf4j-api-1.6.6.jar new file mode 100644 index 00000000..4c03fa6b Binary files /dev/null and b/KdeConnect/libs/slf4j-api-1.6.6.jar differ diff --git a/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java b/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java index 42183581..621aa88d 100644 --- a/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java +++ b/KdeConnect/src/main/java/org/kde/connect/BackgroundService.java @@ -31,25 +31,22 @@ public class BackgroundService extends Service { PingPackageInterface pingEmitter; - private void registerEmitters() { - if (settings.getBoolean("emit_call", true)) { + private void registerPackageInterfaces() { + if (settings.getBoolean("call_interface", true)) { emitters.add(new CallPackageInterface(getApplicationContext())); } - if (settings.getBoolean("emit_ping", true)) { + if (settings.getBoolean("ping_interface", true)) { emitters.add(pingEmitter); } - if (settings.getBoolean("emit_clipboard", true)) { + if (settings.getBoolean("clipboard_interface", true)) { emitters.add(new ClipboardPackageInterface(getApplicationContext())); } } - public void registerAnnouncers() { - /*if (settings.getBoolean("announce_avahi", true)) { - locators.add(new AvahiLinkProvider(this)); - }*/ - if (settings.getBoolean("announce_avahi_tcp", true)) { + public void registerLinkProviders() { + if (settings.getBoolean("avahitcp_link", true)) { locators.add(new AvahiTcpLinkProvider(this)); } } @@ -65,7 +62,7 @@ public class BackgroundService extends Service { //This will be called for each intent launch, even if the service is already started and is reused @Override public int onStartCommand(Intent intent, int flags, int startId) { - Log.e("BackgroundService","Running callbacks waiting service to be ready"); + Log.i("BackgroundService","onStartCommand"); for (InstanceCallback c : callbacks) { c.onServiceStart(this); } @@ -74,19 +71,18 @@ public class BackgroundService extends Service { } private void startDiscovery() { - Log.e("StartDiscovery","Registering connection receivers"); + Log.i("StartDiscovery","Registering connection receivers"); for (BaseLinkProvider a : locators) { - Log.e("Registerign", a.toString()); a.reachComputers(new BaseLinkProvider.ConnectionReceiver() { @Override public void onConnectionAccepted(String deviceId, String name, BaseComputerLink link) { - Log.e("BackgroundService", "Connection accepted!"); + Log.i("BackgroundService", "Connection accepted!"); if (devices.containsKey(deviceId)) { - Log.e("BackgroundService", "known device"); + Log.i("BackgroundService", "known device"); devices.get(deviceId).addLink(link); } else { - Log.e("BackgroundService", "unknown device"); + Log.i("BackgroundService", "unknown device"); Device device = new Device(deviceId, name, link); devices.put(deviceId, device); for (BasePackageInterface pe : emitters) { @@ -119,14 +115,14 @@ public class BackgroundService extends Service { public void onCreate() { super.onCreate(); - Log.e("BackgroundService","Service not started yet, initializing..."); + Log.i("BackgroundService","Service not started yet, initializing..."); settings = getSharedPreferences("KdeConnect", 0); pingEmitter = new PingPackageInterface(getApplicationContext()); - registerEmitters(); - registerAnnouncers(); + registerPackageInterfaces(); + registerLinkProviders(); startDiscovery(); } @@ -138,7 +134,7 @@ public class BackgroundService extends Service { @Override public void onDestroy() { - Log.e("BackgroundService", "Destroying"); + Log.i("BackgroundService", "Destroying"); super.onDestroy(); } diff --git a/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/TcpComputerLink.java b/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/TcpComputerLink.java index 91885fad..53b1f07b 100644 --- a/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/TcpComputerLink.java +++ b/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/TcpComputerLink.java @@ -3,142 +3,82 @@ package org.kde.connect.ComputerLinks; import android.os.AsyncTask; import android.util.Log; +import org.apache.mina.core.buffer.SimpleBufferAllocator; +import org.apache.mina.core.filterchain.IoFilter; +import org.apache.mina.core.future.ConnectFuture; +import org.apache.mina.core.service.IoHandlerAdapter; +import org.apache.mina.core.session.IoSession; +import org.apache.mina.filter.codec.ProtocolCodecFilter; +import org.apache.mina.filter.codec.textline.LineDelimiter; +import org.apache.mina.filter.codec.textline.TextLineCodecFactory; +import org.apache.mina.filter.keepalive.KeepAliveFilter; +import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.kde.connect.LinkProviders.BaseLinkProvider; import org.kde.connect.NetworkPackage; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.SocketChannel; import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.util.Iterator; public class TcpComputerLink extends BaseComputerLink { - private boolean listenign = false; - private SocketChannel sChannel; - private Charset charset = Charset.forName("US-ASCII"); + private IoSession session = null; - public TcpComputerLink(BaseLinkProvider linkProvider, InetAddress ip, int port) throws java.io.IOException { + public TcpComputerLink(BaseLinkProvider linkProvider) { super(linkProvider); + } - sChannel = SocketChannel.open(); - sChannel.socket().setSoTimeout(0); - sChannel.socket().setKeepAlive(true); - sChannel.configureBlocking(false); - sChannel.connect(new InetSocketAddress(ip, port)); + public void connect(final InetAddress ip, final int port) { + + final NioSocketConnector connector = new NioSocketConnector(); + connector.setHandler(new IoHandlerAdapter() { + @Override + public void messageReceived(IoSession session, Object message) throws Exception { + super.messageReceived(session, message); + Log.e("TcpComputerLink","messageReceived (" + message.getClass() + ") " + message.toString()); + try { + String theMessage = (String) message; + NetworkPackage np = NetworkPackage.unserialize(theMessage); + packageReceived(np); + } catch (Exception e) { + e.printStackTrace(); + Log.e("TcpComputerLink","Could not unserialize package"); + } + } + }); + + //TextLineCodecFactory will split incoming data delimited by the given string + connector.getFilterChain().addLast("codec", + new ProtocolCodecFilter( + new TextLineCodecFactory(Charset.forName("UTF-8"), LineDelimiter.UNIX, LineDelimiter.UNIX) + ) + ); + connector.getSessionConfig().setKeepAlive(true); + + new Thread(new Runnable() { + @Override + public void run() { + ConnectFuture future = connector.connect(new InetSocketAddress(ip, port)); + //Wait unit it is connected (this call makes it blocking, but we are on a thread anyway) + future.awaitUninterruptibly(); + if (!future.isConnected()) Log.e("TcpComputerLink","Could not connect"); + Log.e("TcpComputerLink","connected"); + session = future.getSession(); + } + }).run(); } @Override public boolean sendPackage(NetworkPackage np) { - Log.e("TcpComputerLink","sendPackage"); - try { - String s = np.serialize(); - Log.e("SendPackage",s); - - CharsetEncoder enc = charset.newEncoder(); - ByteBuffer bytes = enc.encode(CharBuffer.wrap(s)); - Log.e("asdads",""+bytes.array().length); - int written = sChannel.write(bytes); - - Log.e("SendPackage","sent "+written+" bytes"); - } catch(Exception e) { - Log.e("TcpComputerLink","Exception"); - e.printStackTrace(); + Log.e("TcpComputerLink", "sendPackage"); + if (session == null) { + Log.e("TcpComputerLink","not yet connected"); + return false; + } else { + session.write(np.serialize()); + return true; } - return true; } - public void startReceivingPackages() { - if (listenign) return; - - listenign = true; - - try { - - /* - Log.e("TcpComputerLink","start receiving packages"); - InputStreamReader reader = new InputStreamReader(socket.getInputStream()); - Log.e("TcpComputerLink","Entering loop"); - - while (socket.isConnected()) { - if (serverMessage == null) { - //wait(100); - continue; - } - NetworkPackage np = NetworkPackage.unserialize(serverMessage); - Log.e("TcpComputerLink",serverMessage); - packageReceived(np); - }*/ - - - final Selector selector = Selector.open(); - sChannel.register(selector, SelectionKey.OP_CONNECT + SelectionKey.OP_READ); - - new Thread(new Runnable() { - @Override - public void run() { - while (true) { - try { - selector.select(); //blocking - Iterator it = selector.selectedKeys().iterator(); - // Process each key at a time - while (it.hasNext()) { - // Get the selection key - SelectionKey selKey = (SelectionKey)it.next(); - - // Remove it from the list to indicate that it is being processed - it.remove(); - - if (selKey.isValid() && selKey.isConnectable()) { - // Get channel with connection request - SocketChannel sChannel = (SocketChannel)selKey.channel(); - - boolean success = sChannel.finishConnect(); - if (!success) { - // An error occurred; handle it - - // Unregister the channel with this selector - selKey.cancel(); - } - } - if (selKey.isValid() && selKey.isReadable()) { - // Get channel with bytes to read - - SocketChannel sChannel = (SocketChannel)selKey.channel(); - - ByteBuffer buffer = ByteBuffer.allocate(4096); - int read = sChannel.read(buffer); - //TODO: Check if there is more to read (or otherwise if we have read more than one package) - String s = new String( buffer.array(), 0, read, charset ); - Log.e("readable","Read "+read+" bytes: "+s); - - NetworkPackage np = NetworkPackage.unserialize(s); - packageReceived(np); - - } - } - } catch (Exception e) { - Log.e("TcpComputerLink","Inner loop exception"); - e.printStackTrace(); - listenign = false; - break; - } - } - Log.e("TcpComputerLink","Exiting loop"); - } - }).run(); - - } catch (Exception e) { - Log.e("TcpComputerLink","Exception"); - listenign = false; - e.printStackTrace(); - } - - } } diff --git a/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/UdpComputerLink.java b/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/UdpComputerLink.java deleted file mode 100644 index 27f28202..00000000 --- a/KdeConnect/src/main/java/org/kde/connect/ComputerLinks/UdpComputerLink.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.kde.connect.ComputerLinks; - -import android.os.AsyncTask; -import android.util.Log; - -import org.kde.connect.LinkProviders.AvahiLinkProvider; -import org.kde.connect.NetworkPackage; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; -import java.net.InetAddress; - -public class UdpComputerLink extends BaseComputerLink { - - DatagramSocket socket = null; - int UDP_PORT; - InetAddress IP; - - final int BUFFER_SIZE = 5*1024; - - public UdpComputerLink(AvahiLinkProvider linkProvider, InetAddress ip, int port) throws IOException { - super(linkProvider); - UDP_PORT = port; - IP = ip; - } - - @Override - public boolean sendPackage(NetworkPackage np) { - if (socket == null) startReceivingPackages(); - Log.e("UdpComputerLink","sendPackage"); - final String messageStr = np.serialize(); - Log.e("UdpComputerLink", "aboutToSend"); - int msg_length = messageStr.length(); - byte[] message = messageStr.getBytes(); - DatagramPacket p = new DatagramPacket(message, msg_length, IP, UDP_PORT); - Log.e("UdpComputerLink", "aboutToSend " + IP + ":" + UDP_PORT); - try { - socket.send(p); - } catch (Exception e) { - Log.e("UdpComputerLink", "Exception!"); - } - Log.e("UdpComputerLink", "sent"); - return true; - } - - public void startReceivingPackages() { - try { - socket = new DatagramSocket(UDP_PORT); - }catch(Exception e) { - Log.e("UdpComputerLink","Exception"); - e.printStackTrace(); - } - Log.e("UdpComputerLink","" + IP + ":" + UDP_PORT); - new Thread(new Runnable() { - @Override - public void run() { - try { - Log.e("UdpComputerLink","Waiting for udp datagrams"); - byte[] buffer = new byte[BUFFER_SIZE]; - while(true){ - DatagramPacket packet = new DatagramPacket(buffer, buffer.length ); - socket.receive(packet); - String s = new String(packet.getData(), 0, packet.getLength()); - packageReceived(NetworkPackage.unserialize(s)); - } - } catch (java.io.IOException e) { - Log.e("UdpComputerLink","Exception"); - e.printStackTrace(); - } - } - }).run(); - } -} diff --git a/KdeConnect/src/main/java/org/kde/connect/LinkProviders/AvahiLinkProvider.java b/KdeConnect/src/main/java/org/kde/connect/LinkProviders/AvahiLinkProvider.java deleted file mode 100644 index 22f3fd17..00000000 --- a/KdeConnect/src/main/java/org/kde/connect/LinkProviders/AvahiLinkProvider.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.kde.connect.LinkProviders; - -import android.content.Context; -import android.net.nsd.NsdManager; -import android.net.nsd.NsdServiceInfo; -import android.util.Log; - -import org.kde.connect.ComputerLinks.BaseComputerLink; -import org.kde.connect.ComputerLinks.UdpComputerLink; -import org.kde.connect.Device; -import org.kde.connect.NetworkPackage; - -import java.lang.Override; -import java.util.ArrayList; - -public class AvahiLinkProvider implements BaseLinkProvider { - - String serviceType = "_kdeconnect._udp"; - - NsdManager mNsdManager; - - ArrayList visibleComputers = new ArrayList(); - - Context ctx; - - private NsdManager.DiscoveryListener oldListener = null; - - public AvahiLinkProvider(Context context) { - mNsdManager = (NsdManager)context.getSystemService(Context.NSD_SERVICE); - ctx = context; - } - - @Override - public void reachComputers(final ConnectionReceiver cr) { - - visibleComputers.clear(); - - if (oldListener != null) mNsdManager.stopServiceDiscovery(oldListener); - - Log.e("AvahiLinkProvider", "Discovering computers..."); - - final NsdManager.ResolveListener mResolveListener = new NsdManager.ResolveListener() { - - @Override - public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) { - Log.e("AvahiLinkProvider", "Resolve failed: " + errorCode); - } - - @Override - public void onServiceResolved(final NsdServiceInfo serviceInfo) { - Log.e("AvahiLinkProvider", "Resolve Succeeded: " + serviceInfo); - - //Handshake link - try { - UdpComputerLink link = new UdpComputerLink(AvahiLinkProvider.this,serviceInfo.getHost(),serviceInfo.getPort()); - link.addPackageReceiver(new BaseComputerLink.PackageReceiver() { - @Override - public void onPackageReceived(NetworkPackage np) { - Log.e("AvahiLinkProvider","Received reply"); - if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) { - String id = np.getString("deviceId"); - String name = np.getString("deviceName"); - //Real data link - try { - UdpComputerLink link2 = new UdpComputerLink(AvahiLinkProvider.this,serviceInfo.getHost(),10603); - visibleComputers.add(link2); - cr.onConnectionAccepted(id, name, link2); - } catch (Exception e) { - - } - } else { - Log.e("AvahiLinkProvider","Received non-identity package"); - } - } - }); - link.startReceivingPackages(); - Log.e("AvahiLinkProvider","Sending identity package"); - NetworkPackage np = NetworkPackage.createIdentityPackage(ctx); - link.sendPackage(np); - } catch (Exception e) { - - } - } - - }; - - NsdManager.DiscoveryListener mDiscoveryListener = new NsdManager.DiscoveryListener() { - - @Override - public void onDiscoveryStarted(String regType) { - Log.e("AvahiLinkProvider", "Service discovery started"); - } - - @Override - public void onServiceFound(NsdServiceInfo service) { - Log.e("AvahiLinkProvider", "Service discovery success" + service); - - if (!service.getServiceType().startsWith(serviceType)) { - Log.e("AvahiLinkProvider", "Unknown Service Type: " + service.getServiceType()); - } else { - Log.e("AvahiLinkProvider", "Computer found, resolving..."); - mNsdManager.resolveService(service, mResolveListener); - } - - } - - @Override - public void onServiceLost(NsdServiceInfo service) { - Log.e("AvahiLinkProvider", "Service lost: " + service); - } - - @Override - public void onDiscoveryStopped(String serviceType) { - Log.e("AvahiLinkProvider", "Discovery stopped: " + serviceType); - } - - @Override - public void onStartDiscoveryFailed(String serviceType, int errorCode) { - Log.e("AvahiLinkProvider", "Discovery failed: Error code:" + errorCode); - mNsdManager.stopServiceDiscovery(this); - } - - @Override - public void onStopDiscoveryFailed(String serviceType, int errorCode) { - Log.e("AvahiLinkProvider", "Discovery failed: Error code:" + errorCode); - mNsdManager.stopServiceDiscovery(this); - } - }; - - oldListener = mDiscoveryListener; - mNsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener); - - } - - - @Override - public int getPriority() { - return 100; - } - - - @Override - public String getName() { - return "AvahiUdpLinkProvider"; - } - -} diff --git a/KdeConnect/src/main/java/org/kde/connect/LinkProviders/AvahiTcpLinkProvider.java b/KdeConnect/src/main/java/org/kde/connect/LinkProviders/AvahiTcpLinkProvider.java index 360e6325..e5677374 100644 --- a/KdeConnect/src/main/java/org/kde/connect/LinkProviders/AvahiTcpLinkProvider.java +++ b/KdeConnect/src/main/java/org/kde/connect/LinkProviders/AvahiTcpLinkProvider.java @@ -54,11 +54,10 @@ public class AvahiTcpLinkProvider implements BaseLinkProvider { Log.e("AvahiTcpLinkProvider", "Resolve Succeeded. " + serviceInfo); try { - Log.e("AvahiTcpLinkProvider", "Creating link"); + Log.e("AvahiTcpLinkProvider", "Connecting and waiting identity package"); final InetAddress host = serviceInfo.getHost(); final int port = serviceInfo.getPort(); - final TcpComputerLink link = new TcpComputerLink(AvahiTcpLinkProvider.this,host,port); - Log.e("AvahiTcpLinkProvider", "Waiting identity package"); + final TcpComputerLink link = new TcpComputerLink(AvahiTcpLinkProvider.this); link.addPackageReceiver(new BaseComputerLink.PackageReceiver() { @Override public void onPackageReceived(NetworkPackage np) { @@ -77,12 +76,13 @@ public class AvahiTcpLinkProvider implements BaseLinkProvider { } visibleComputers.put(host,link); cr.onConnectionAccepted(id,name,link); + link.removePackageReceiver(this); } } }); - link.startReceivingPackages(); + link.connect(host,port); } catch (Exception e) { Log.e("AvahiTcpLinkProvider","Exception"); e.printStackTrace(); diff --git a/KdeConnect/src/main/res/layout/activity_main.xml b/KdeConnect/src/main/res/layout/activity_main.xml index 0afd3477..dcc73874 100644 --- a/KdeConnect/src/main/res/layout/activity_main.xml +++ b/KdeConnect/src/main/res/layout/activity_main.xml @@ -20,12 +20,4 @@ android:id="@+id/listView1" android:layout_weight="1"/> - - diff --git a/build.gradle b/build.gradle index 495c5038..f82180e3 100644 --- a/build.gradle +++ b/build.gradle @@ -1 +1,2 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. +