From 095c76c10deb9414fbf3e84caadbe00b0e20dd91 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Sun, 24 Sep 2017 23:11:27 +0200
Subject: [PATCH] =?UTF-8?q?Fixed=20a=20bug=20where=20Android=E2=80=99s=20i?=
 =?UTF-8?q?mplementation=20of=20Thread::interrupt=20and=20Channel::close?=
 =?UTF-8?q?=20was=20broken?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../quasseldroid_ng/service/QuasselService.kt | 30 +++++++++++++++++--
 .../libquassel/session/CoreConnection.kt      | 30 +++++++++----------
 .../de/kuschku/libquassel/session/Session.kt  |  7 +++--
 .../libquassel/util/nio/WrappedChannel.kt     | 14 ---------
 4 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
index 093e6fa00..adb777f4f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt
@@ -3,6 +3,8 @@ package de.kuschku.quasseldroid_ng.service
 import android.arch.lifecycle.LifecycleService
 import android.content.Intent
 import android.os.Binder
+import android.os.Handler
+import android.os.HandlerThread
 import de.kuschku.libquassel.protocol.*
 import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.session.Session
@@ -18,7 +20,7 @@ import javax.net.ssl.X509TrustManager
 class QuasselService : LifecycleService() {
   private lateinit var session: Session
 
-  private val backend = object : Backend {
+  private val backendImplementation = object : Backend {
     override fun session() = session
 
     override fun connect(address: SocketAddress, user: String, pass: String) {
@@ -33,6 +35,30 @@ class QuasselService : LifecycleService() {
     }
   }
 
+  private val asyncBackend = object : Backend {
+    private val thread = HandlerThread("BackendHandler")
+    private val handler: Handler
+
+    init {
+      thread.start()
+      handler = Handler(thread.looper)
+    }
+
+    override fun connect(address: SocketAddress, user: String, pass: String) {
+      handler.post {
+        backendImplementation.connect(address, user, pass)
+      }
+    }
+
+    override fun disconnect() {
+      handler.post {
+        backendImplementation.disconnect()
+      }
+    }
+
+    override fun session() = backendImplementation.session()
+  }
+
   private lateinit var database: QuasselDatabase
 
   override fun onCreate() {
@@ -63,7 +89,7 @@ class QuasselService : LifecycleService() {
 
   override fun onBind(intent: Intent?): QuasselBinder {
     super.onBind(intent)
-    return QuasselBinder(backend)
+    return QuasselBinder(asyncBackend)
   }
 
   class QuasselBinder(val backend: Backend) : Binder()
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt b/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt
index 81f4b8e69..af42d2d4c 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt
@@ -112,17 +112,13 @@ class CoreConnection(
   }
 
   override fun close() {
-    interrupt()
-    handlerService.quit()
-    val thread = Thread {
-      try {
-        channel?.close()
-      } catch (e: Throwable) {
-        log(WARN, TAG, "Error encountered while closing connection", e)
-      }
+    try {
+      channel?.close()
+      interrupt()
+      handlerService.quit()
+    } catch (e: Throwable) {
+      log(WARN, TAG, "Error encountered while closing connection", e)
     }
-    thread.start()
-    thread.join()
   }
 
   override fun dispatch(message: HandshakeMessage) {
@@ -166,15 +162,17 @@ class CoreConnection(
         if (size > 64 * 1024 * 1024)
           throw SocketException("Too large frame received: $size")
         val dataBuffer = ByteBuffer.allocateDirect(size)
-        while (dataBuffer.position() < dataBuffer.limit() && channel?.read(dataBuffer) ?: -1 > 0) {
+        while (!isInterrupted && dataBuffer.position() < dataBuffer.limit() && channel?.read(
+          dataBuffer) ?: -1 > 0) {
         }
         dataBuffer.flip()
-        handlerService.parse {
-          when (internalState.value) {
-            ConnectionState.HANDSHAKE -> processHandshake(dataBuffer)
-            else                      -> processSigProxy(dataBuffer)
+        if (!isInterrupted)
+          handlerService.parse {
+            when (internalState.value) {
+              ConnectionState.HANDSHAKE -> processHandshake(dataBuffer)
+              else                      -> processSigProxy(dataBuffer)
+            }
           }
-        }
       }
     } catch (e: Throwable) {
       log(WARN, TAG, "Error encountered in connection", e)
diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
index 389e90769..56dc9efdd 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
@@ -149,15 +149,16 @@ class Session(
     backlogManager = null
     bufferSyncer = null
     bufferViewManager = null
-    certManagers.clear()
     coreInfo = null
     dccConfig = null
-    identities.clear()
     ignoreListManager = null
     ircListHelper = null
-    networks.clear()
     networkConfig = null
 
+    certManagers.clear()
+    identities.clear()
+    networks.clear()
+
     super.cleanUp()
   }
 }
diff --git a/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt b/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt
index 4c98f3db2..1896f5f90 100644
--- a/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt
@@ -176,17 +176,3 @@ class WrappedChannel(
     flusher?.invoke()
   }
 }
-
-fun ByteArray.toHexDump(): String {
-  val buf = StringBuffer()
-  var i = 0
-  buf.append("HexDump ========================================================================\n")
-  while (i < this.size) {
-    buf.append(String.format("%02x ", this[i]))
-    if (i > 0 && (i + 1) % 32 == 0) {
-      buf.append("\n")
-    }
-    i++
-  }
-  return buf.toString()
-}
-- 
GitLab