Skip to content
Snippets Groups Projects
Verified Commit 80fc81de authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Connection handling improvements

parent beba0f48
Branches
Tags
No related merge requests found
...@@ -172,13 +172,12 @@ class CoreConnection( ...@@ -172,13 +172,12 @@ class CoreConnection(
override fun close() { override fun close() {
try { try {
setState(ConnectionState.CLOSED) setState(ConnectionState.CLOSED)
channel?.flush()
channel?.close() channel?.close()
setHandlers(null, null, null)
interrupt()
} catch (e: Throwable) { } catch (e: Throwable) {
log(WARN, TAG, "Error encountered while closing connection: $e") log(WARN, TAG, "Error encountered while closing connection: $e")
} }
setHandlers(null, null, null)
interrupt()
} }
fun dispatch(message: HandshakeMessage) { fun dispatch(message: HandshakeMessage) {
...@@ -218,7 +217,7 @@ class CoreConnection( ...@@ -218,7 +217,7 @@ class CoreConnection(
connect() connect()
sendHandshake() sendHandshake()
readHandshake() readHandshake()
while (!isInterrupted && state != ConnectionState.CLOSED) { while (!isInterrupted && state.value != ConnectionState.CLOSED) {
sizeBuffer.clear() sizeBuffer.clear()
if (channel?.read(sizeBuffer) == -1) if (channel?.read(sizeBuffer) == -1)
break break
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
package de.kuschku.libquassel.util.compatibility package de.kuschku.libquassel.util.compatibility
import de.kuschku.libquassel.util.compatibility.backport.BackportedSyncFlushDeflaterOutputStream
import de.kuschku.libquassel.util.compatibility.backport.ProperlyClosingSyncFlushDeflaterOutputStream
import java.io.OutputStream import java.io.OutputStream
import java.util.zip.Deflater import java.util.zip.Deflater
import java.util.zip.DeflaterOutputStream import java.util.zip.DeflaterOutputStream
...@@ -36,27 +38,9 @@ object CompatibilityUtils { ...@@ -36,27 +38,9 @@ object CompatibilityUtils {
*/ */
fun createDeflaterOutputStream(rawOut: OutputStream?): DeflaterOutputStream { fun createDeflaterOutputStream(rawOut: OutputStream?): DeflaterOutputStream {
return if (supportsCompression) { return if (supportsCompression) {
DeflaterOutputStream(rawOut, true) ProperlyClosingSyncFlushDeflaterOutputStream(rawOut)
} else { } else {
DeflaterOutputStream(rawOut, createSyncFlushDeflater()) BackportedSyncFlushDeflaterOutputStream(rawOut)
} }
} }
/**
* Creates a SyncFlush Deflater for use on pre-KitKat Android
*
* @return The modified Deflater, or null if the creation failed
*/
private fun createSyncFlushDeflater(): Deflater? {
val def = Deflater()
try {
val f = def.javaClass.getDeclaredField("flushParm")
f.isAccessible = true
f.setInt(def, 2) // Z_SYNC_FLUSH
} catch (e: Exception) {
return null
}
return def
}
} }
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2019 Janne Koschinski
* Copyright (c) 2019 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.libquassel.util.compatibility.backport
import java.io.OutputStream
import java.util.zip.Deflater
import java.util.zip.DeflaterOutputStream
class BackportedSyncFlushDeflaterOutputStream(
rawOut: OutputStream?,
private val deflater: Deflater? = createSyncFlushDeflater()
) : DeflaterOutputStream(rawOut, deflater) {
override fun close() {
deflater?.end()
super.close()
}
companion object {
/**
* Creates a SyncFlush Deflater for use on pre-KitKat Android
*
* @return The modified Deflater, or null if the creation failed
*/
private fun createSyncFlushDeflater(): Deflater? {
val def = Deflater()
try {
val f = def.javaClass.getDeclaredField("flushParm")
f.isAccessible = true
f.setInt(def, 2) // Z_SYNC_FLUSH
} catch (e: Exception) {
return null
}
return def
}
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2019 Janne Koschinski
* Copyright (c) 2019 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.kuschku.libquassel.util.compatibility.backport
import java.io.OutputStream
import java.util.zip.DeflaterOutputStream
class ProperlyClosingSyncFlushDeflaterOutputStream(
stream: OutputStream?
) : DeflaterOutputStream(stream, true) {
override fun close() {
try {
super.close()
} finally {
def.end()
}
}
}
...@@ -19,14 +19,15 @@ ...@@ -19,14 +19,15 @@
package de.kuschku.libquassel.util.nio package de.kuschku.libquassel.util.nio
import de.kuschku.libquassel.connection.CoreConnection
import de.kuschku.libquassel.connection.HostnameVerifier import de.kuschku.libquassel.connection.HostnameVerifier
import de.kuschku.libquassel.connection.SocketAddress import de.kuschku.libquassel.connection.SocketAddress
import de.kuschku.libquassel.util.compatibility.CompatibilityUtils import de.kuschku.libquassel.util.compatibility.CompatibilityUtils
import de.kuschku.libquassel.util.compatibility.LoggingHandler
import de.kuschku.libquassel.util.compatibility.LoggingHandler.Companion.log
import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.*
import de.kuschku.libquassel.util.compatibility.StreamChannelFactory import de.kuschku.libquassel.util.compatibility.StreamChannelFactory
import java.io.Flushable import java.io.*
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.net.Socket import java.net.Socket
import java.net.SocketException import java.net.SocketException
import java.nio.ByteBuffer import java.nio.ByteBuffer
...@@ -42,11 +43,12 @@ import javax.net.ssl.SSLSocket ...@@ -42,11 +43,12 @@ import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager import javax.net.ssl.X509TrustManager
class WrappedChannel( class WrappedChannel private constructor(
private val socket: Socket, private val socket: Socket,
private var rawInStream: InputStream? = null, private var rawInStream: InputStream? = null,
private var rawOutStream: OutputStream? = null, private var rawOutStream: OutputStream? = null,
private var flusher: (() -> Unit)? = null private var flusher: (() -> Unit)? = null,
private val closeListeners: List<Closeable> = emptyList()
) : Flushable, ByteChannel, InterruptibleChannel { ) : Flushable, ByteChannel, InterruptibleChannel {
private var rawIn: ReadableByteChannel? = null private var rawIn: ReadableByteChannel? = null
private var rawOut: WritableByteChannel? = null private var rawOut: WritableByteChannel? = null
...@@ -62,10 +64,12 @@ class WrappedChannel( ...@@ -62,10 +64,12 @@ class WrappedChannel(
} }
companion object { companion object {
fun ofSocket(s: Socket): WrappedChannel { fun ofSocket(s: Socket, closeListeners: List<Closeable> = emptyList()): WrappedChannel {
return WrappedChannel( return WrappedChannel(
s, s.getInputStream(), s,
s.getOutputStream() s.getInputStream(),
s.getOutputStream(),
closeListeners = closeListeners + s.getInputStream() + s.getOutputStream()
) )
} }
} }
...@@ -74,7 +78,8 @@ class WrappedChannel( ...@@ -74,7 +78,8 @@ class WrappedChannel(
val deflaterOutputStream = CompatibilityUtils.createDeflaterOutputStream(rawOutStream) val deflaterOutputStream = CompatibilityUtils.createDeflaterOutputStream(rawOutStream)
return WrappedChannel( return WrappedChannel(
socket, InflaterInputStream(rawInStream), deflaterOutputStream, socket, InflaterInputStream(rawInStream), deflaterOutputStream,
deflaterOutputStream::flush deflaterOutputStream::flush,
closeListeners = closeListeners + deflaterOutputStream
) )
} }
...@@ -96,7 +101,7 @@ class WrappedChannel( ...@@ -96,7 +101,7 @@ class WrappedChannel(
) )
} }
socket.startHandshake() socket.startHandshake()
return WrappedChannel.ofSocket(socket) return ofSocket(socket)
} }
/** /**
...@@ -206,6 +211,16 @@ class WrappedChannel( ...@@ -206,6 +211,16 @@ class WrappedChannel(
rawOut?.close() rawOut?.close()
rawOut = null rawOut = null
socket.close() socket.close()
/*
for (listener in closeListeners + socket) {
try {
log(INFO, "WrappedChannel", "Closing: ${listener::class.java}")
listener.close()
} catch (e: Throwable) {
log(WARN, "WrappedChannel", "Error encountered while closing connection: $e")
}
}
*/
} }
/** /**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment