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

Performance improvements

parent 5902cde0
Branches
Tags
No related merge requests found
Showing
with 475 additions and 272 deletions
...@@ -3,6 +3,7 @@ import org.gradle.api.Project ...@@ -3,6 +3,7 @@ import org.gradle.api.Project
import org.gradle.kotlin.dsl.* import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KaptAnnotationProcessorOptions import org.jetbrains.kotlin.gradle.plugin.KaptAnnotationProcessorOptions
import org.jetbrains.kotlin.gradle.plugin.KaptExtension import org.jetbrains.kotlin.gradle.plugin.KaptExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.util.* import java.util.*
...@@ -75,8 +76,11 @@ dependencies { ...@@ -75,8 +76,11 @@ dependencies {
implementation(appCompat("cardview-v7")) implementation(appCompat("cardview-v7"))
implementation(appCompat("recyclerview-v7")) implementation(appCompat("recyclerview-v7"))
implementation("io.reactivex.rxjava2:rxjava:2.1.3")
implementation(appArch("lifecycle", "runtime", version = "1.0.0")) implementation(appArch("lifecycle", "runtime", version = "1.0.0"))
implementation(appArch("lifecycle", "extensions")) implementation(appArch("lifecycle", "extensions"))
implementation(appArch("lifecycle", "reactivestreams"))
kapt(appArch("lifecycle", "compiler")) kapt(appArch("lifecycle", "compiler"))
implementation(appArch("persistence.room", "runtime")) implementation(appArch("persistence.room", "runtime"))
...@@ -104,6 +108,15 @@ dependencies { ...@@ -104,6 +108,15 @@ dependencies {
androidTestImplementation("com.android.support.test:rules:0.5") androidTestImplementation("com.android.support.test:rules:0.5")
} }
tasks.withType(KotlinCompile::class.java) {
kotlinOptions {
freeCompilerArgs = listOf(
"-Xno-param-assertions",
"-Xno-call-assertions"
)
}
}
fun cmd(vararg command: String) = try { fun cmd(vararg command: String) = try {
val stdOut = ByteArrayOutputStream() val stdOut = ByteArrayOutputStream()
exec { exec {
......
package de.kuschku.quasseldroid_ng.service package de.kuschku.quasseldroid_ng.service
import android.arch.lifecycle.LifecycleService import android.arch.lifecycle.LifecycleService
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.Transformations
import android.content.Intent import android.content.Intent
import android.os.Binder import android.os.Binder
import de.kuschku.libquassel.protocol.*
import de.kuschku.libquassel.session.Backend
import de.kuschku.libquassel.session.CoreConnection
import de.kuschku.libquassel.session.Session
import de.kuschku.libquassel.session.SocketAddress
import de.kuschku.quasseldroid_ng.BuildConfig import de.kuschku.quasseldroid_ng.BuildConfig
import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase
import de.kuschku.libquassel.protocol.*
import de.kuschku.libquassel.session.*
import de.kuschku.quasseldroid_ng.util.AndroidHandlerService import de.kuschku.quasseldroid_ng.util.AndroidHandlerService
import org.threeten.bp.Instant import org.threeten.bp.Instant
import java.security.cert.X509Certificate import java.security.cert.X509Certificate
...@@ -24,21 +25,14 @@ class QuasselService : LifecycleService() { ...@@ -24,21 +25,14 @@ class QuasselService : LifecycleService() {
override fun connect(address: SocketAddress, user: String, pass: String) { override fun connect(address: SocketAddress, user: String, pass: String) {
disconnect() disconnect()
val handlerService = AndroidHandlerService() val handlerService = AndroidHandlerService()
session.coreConnection = CoreConnection(session, address, handlerService) session.connection.onNext(CoreConnection(session, address, handlerService))
session.coreConnection?.start() session.connection.value.start()
session.userData = user to pass session.userData = user to pass
connection.postValue(session.coreConnection)
} }
override fun disconnect() { override fun disconnect() {
session.cleanUp() session.cleanUp()
connection.postValue(null)
ABSENT.postValue(ConnectionState.DISCONNECTED)
} }
private val connection = MutableLiveData<CoreConnection>()
val ABSENT = MutableLiveData<ConnectionState>()
} }
private lateinit var database: QuasselDatabase private lateinit var database: QuasselDatabase
......
package de.kuschku.quasseldroid_ng.ui package de.kuschku.quasseldroid_ng.ui
import android.arch.lifecycle.LiveData import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import android.support.design.widget.Snackbar
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.Button import android.widget.Button
...@@ -11,16 +13,16 @@ import android.widget.TextView ...@@ -11,16 +13,16 @@ import android.widget.TextView
import butterknife.BindView import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import de.kuschku.libquassel.session.Backend import de.kuschku.libquassel.session.Backend
import de.kuschku.libquassel.session.ConnectionState
import de.kuschku.libquassel.session.Session import de.kuschku.libquassel.session.Session
import de.kuschku.libquassel.session.SocketAddress import de.kuschku.libquassel.session.SocketAddress
import de.kuschku.libquassel.util.LoggingHandler
import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.util.helper.stickyMapNotNull import de.kuschku.quasseldroid_ng.util.helper.stickyMapNotNull
import org.threeten.bp.Instant import io.reactivex.disposables.Disposable
import org.threeten.bp.ZoneOffset import org.threeten.bp.ZoneOffset
import org.threeten.bp.ZonedDateTime
import org.threeten.bp.format.DateTimeFormatter import org.threeten.bp.format.DateTimeFormatter
import java.util.logging.Handler
import java.util.logging.LogManager
import java.util.logging.LogRecord
class MainActivity : ServiceBoundActivity() { class MainActivity : ServiceBoundActivity() {
@BindView(R.id.host) @BindView(R.id.host)
...@@ -47,37 +49,33 @@ class MainActivity : ServiceBoundActivity() { ...@@ -47,37 +49,33 @@ class MainActivity : ServiceBoundActivity() {
@BindView(R.id.errorList) @BindView(R.id.errorList)
lateinit var errorList: TextView lateinit var errorList: TextView
/*
private val status: LiveData<ConnectionState>
= stickySwitchMapNotNull(backend, Backend::status,
ConnectionState.DISCONNECTED)
*/
private val session: LiveData<Session?> private val session: LiveData<Session?>
= stickyMapNotNull(backend, Backend::session, null) = stickyMapNotNull(backend, Backend::session, null)
private var subscription: Disposable? = null
private val state = MutableLiveData<ConnectionState>()
private var snackbar: Snackbar? = null private var snackbar: Snackbar? = null
private val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ISO_TIME private val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ISO_TIME
private val handler = object : Handler() { private val handler = object : LoggingHandler() {
override fun publish(p0: LogRecord?) { override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
if (p0 != null) { if (logLevel.ordinal < LogLevel.INFO.ordinal)
return
val time = dateTimeFormatter.format(ZonedDateTime.now(ZoneOffset.UTC))
runOnUiThread { runOnUiThread {
errorList.append( errorList.append("$time $tag: ")
dateTimeFormatter.format(Instant.ofEpochMilli(p0.millis).atZone(ZoneOffset.UTC))) if (message != null) {
errorList.append(" ") errorList.append(message)
errorList.append(p0.loggerName)
errorList.append(": ")
errorList.append(p0.message)
errorList.append("\n")
} }
if (throwable != null) {
errorList.append("\n")
errorList.append(Log.getStackTraceString(throwable))
} }
errorList.append("\n")
} }
override fun flush() {
} }
override fun close() { override fun isLoggable(logLevel: LogLevel, tag: String) = true
}
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
...@@ -126,11 +124,11 @@ class MainActivity : ServiceBoundActivity() { ...@@ -126,11 +124,11 @@ class MainActivity : ServiceBoundActivity() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
LogManager.getLogManager().getLogger("").addHandler(handler) LoggingHandler.loggingHandlers.add(handler)
} }
override fun onStop() { override fun onStop() {
LogManager.getLogManager().getLogger("").removeHandler(handler) LoggingHandler.loggingHandlers.remove(handler)
super.onStop() super.onStop()
} }
} }
...@@ -18,9 +18,9 @@ class AndroidHandlerService : HandlerService { ...@@ -18,9 +18,9 @@ class AndroidHandlerService : HandlerService {
backendHandler.post(f) backendHandler.post(f)
} }
private val parseThread = HandlerThread("parse", Process.THREAD_PRIORITY_BACKGROUND) private val parseThread = HandlerThread("parse", Process.THREAD_PRIORITY_DISPLAY)
private val writeThread = HandlerThread("write", Process.THREAD_PRIORITY_BACKGROUND) private val writeThread = HandlerThread("write", Process.THREAD_PRIORITY_BACKGROUND)
private val backendThread = HandlerThread("backend", Process.THREAD_PRIORITY_BACKGROUND) private val backendThread = HandlerThread("backend", Process.THREAD_PRIORITY_DISPLAY)
private val parseHandler: Handler private val parseHandler: Handler
private val writeHandler: Handler private val writeHandler: Handler
......
package de.kuschku.quasseldroid_ng.util package de.kuschku.quasseldroid_ng.util
import android.util.Log import android.util.Log
import java.util.logging.Handler import de.kuschku.libquassel.util.LoggingHandler
import java.util.logging.Level
import java.util.logging.LogManager
import java.util.logging.LogRecord
/** object AndroidLoggingHandler : LoggingHandler() {
* Make JUL work on Android. override fun isLoggable(logLevel: LogLevel, tag: String): Boolean {
*/ return Log.isLoggable(tag, priority(logLevel))
class AndroidLoggingHandler : Handler() {
override fun close() {}
override fun flush() {}
override fun publish(record: LogRecord) {
if (!super.isLoggable(record))
return
val name = record.loggerName
val maxLength = 30
val tag = if (name.length > maxLength) name.substring(name.length - maxLength) else name
try {
val level = getAndroidLevel(record.level)
Log.println(level, tag, record.message)
if (record.thrown != null) {
Log.println(level, tag, Log.getStackTraceString(record.thrown))
}
} catch (e: RuntimeException) {
Log.e("AndroidLoggingHandler", "Error logging message.", e)
} }
override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) {
val priority = priority(logLevel)
if (message != null)
Log.println(priority, tag, message)
if (throwable != null)
Log.println(priority, tag, Log.getStackTraceString(throwable))
} }
companion object { private fun priority(logLevel: LogLevel): Int = when (logLevel) {
fun reset(rootHandler: Handler) { LogLevel.VERBOSE -> Log.VERBOSE
val rootLogger = LogManager.getLogManager().getLogger("") LogLevel.DEBUG -> Log.DEBUG
val handlers = rootLogger.handlers LogLevel.INFO -> Log.INFO
for (handler in handlers) { LogLevel.WARN -> Log.WARN
rootLogger.removeHandler(handler) LogLevel.ERROR -> Log.ERROR
} LogLevel.ASSERT -> Log.ASSERT
rootLogger.addHandler(rootHandler)
} }
fun init() { fun init() {
reset(AndroidLoggingHandler()) LoggingHandler.loggingHandlers.clear()
} LoggingHandler.loggingHandlers.add(this)
private fun getAndroidLevel(level: Level): Int {
val value = level.intValue()
return when {
value >= 1000 -> Log.ERROR
value >= 900 -> Log.WARN
value >= 800 -> Log.INFO
else -> Log.DEBUG
}
}
} }
} }
...@@ -5,6 +5,10 @@ import android.arch.lifecycle.LiveData ...@@ -5,6 +5,10 @@ import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MediatorLiveData import android.arch.lifecycle.MediatorLiveData
import android.arch.lifecycle.Observer import android.arch.lifecycle.Observer
import android.support.annotation.MainThread import android.support.annotation.MainThread
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.BehaviorSubject
@MainThread @MainThread
fun <X, Y> stickySwitchMapNotNull( fun <X, Y> stickySwitchMapNotNull(
...@@ -45,6 +49,93 @@ fun <X, Y> stickySwitchMapNotNull( ...@@ -45,6 +49,93 @@ fun <X, Y> stickySwitchMapNotNull(
return result return result
} }
@MainThread
inline fun <X, Y> rxStickySwitchMapNotNull(
trigger: LiveData<X?>,
crossinline func: (X) -> BehaviorSubject<Y>?,
defaultValue: Y
): LiveData<Y> {
return stickySwitchMapNotNull(trigger, {
val data = func(it)
if (data != null)
BehaviorSubjectLiveData(data)
else
null
}, defaultValue)
}
class BehaviorSubjectLiveData<T>(val observable: BehaviorSubject<T>) : LiveData<T>() {
var subscription: Disposable? = null
override fun getValue(): T? {
return observable.value
}
override fun setValue(value: T) {
observable.onNext(value)
}
override fun postValue(value: T) {
observable.onNext(value)
}
override fun observe(owner: LifecycleOwner?, observer: Observer<T>?) {
super.observe(owner, observer)
if (subscription == null && hasActiveObservers()) {
subscription = observable.subscribeOn(Schedulers.io()).subscribe(this::postValue)
}
}
override fun observeForever(observer: Observer<T>?) {
super.observeForever(observer)
if (subscription == null && hasActiveObservers()) {
subscription = observable.subscribeOn(Schedulers.io()).subscribe(this::postValue)
}
}
override fun removeObserver(observer: Observer<T>?) {
super.removeObserver(observer)
if (subscription != null && !hasActiveObservers()) {
subscription?.dispose()
}
}
override fun removeObservers(owner: LifecycleOwner?) {
super.removeObservers(owner)
if (subscription != null && !hasActiveObservers()) {
subscription?.dispose()
}
}
}
@MainThread
fun <X, Y> rxSwitchMap(
trigger: LiveData<X?>,
func: (X) -> Observable<Y>?,
defaultValue: Y
): LiveData<Y> {
val result = object : MediatorLiveData<Y>() {
override fun observe(owner: LifecycleOwner?, observer: Observer<Y>?) {
super.observe(owner, observer)
observer?.onChanged(value ?: defaultValue)
}
override fun observeForever(observer: Observer<Y>?) {
super.observeForever(observer)
observer?.onChanged(value ?: defaultValue)
}
}
result.addSource(trigger, object : Observer<X?> {
internal var mSource: Observable<Y>? = null
override fun onChanged(x: X?) {
val newLiveData = if (x != null) func(x) else null
}
})
return result
}
@MainThread @MainThread
fun <X, Y> stickyMapNotNull( fun <X, Y> stickyMapNotNull(
trigger: LiveData<X?>, trigger: LiveData<X?>,
......
...@@ -6,9 +6,11 @@ ...@@ -6,9 +6,11 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="16dp" android:paddingLeft="24dp"
android:paddingRight="16dp"> android:paddingRight="24dp">
<android.support.design.widget.TextInputLayout <android.support.design.widget.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
...@@ -19,8 +21,8 @@ ...@@ -19,8 +21,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Host" android:hint="Host"
android:singleLine="true" android:maxLines="1"
android:maxLines="1" /> android:singleLine="true" />
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout <android.support.design.widget.TextInputLayout
...@@ -33,9 +35,9 @@ ...@@ -33,9 +35,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Port" android:hint="Port"
android:inputType="number" android:inputType="number"
android:text="4242" android:maxLines="1"
android:singleLine="true" android:singleLine="true"
android:maxLines="1" /> android:text="4242" />
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout <android.support.design.widget.TextInputLayout
...@@ -47,8 +49,8 @@ ...@@ -47,8 +49,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Username" android:hint="Username"
android:singleLine="true" android:maxLines="1"
android:maxLines="1" /> android:singleLine="true" />
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout <android.support.design.widget.TextInputLayout
...@@ -61,8 +63,8 @@ ...@@ -61,8 +63,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Password" android:hint="Password"
android:inputType="textPassword" android:inputType="textPassword"
android:singleLine="true" android:maxLines="1"
android:maxLines="1" /> android:singleLine="true" />
</android.support.design.widget.TextInputLayout> </android.support.design.widget.TextInputLayout>
<LinearLayout <LinearLayout
......
...@@ -3,6 +3,7 @@ import org.gradle.api.Project ...@@ -3,6 +3,7 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.ExternalModuleDependency import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.kotlin.dsl.* import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.plugin.KaptExtension import org.jetbrains.kotlin.gradle.plugin.KaptExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
apply { apply {
plugin("kotlin") plugin("kotlin")
...@@ -23,6 +24,15 @@ dependencies { ...@@ -23,6 +24,15 @@ dependencies {
testImplementation("junit:junit:4.12") testImplementation("junit:junit:4.12")
} }
tasks.withType(KotlinCompile::class.java) {
kotlinOptions {
freeCompilerArgs = listOf(
"-Xno-param-assertions",
"-Xno-call-assertions"
)
}
}
/** /**
* Builds the dependency notation for the named AppCompat [module] at the given [version]. * Builds the dependency notation for the named AppCompat [module] at the given [version].
* *
......
...@@ -56,4 +56,10 @@ class Message( ...@@ -56,4 +56,10 @@ class Message(
override fun of(vararg flags: MessageFlag) = Flags.of(*flags) override fun of(vararg flags: MessageFlag) = Flags.of(*flags)
} }
} }
override fun toString(): String {
return "Message(messageId=$messageId, time=$time, type=$type, flag=$flag, bufferInfo=$bufferInfo, sender='$sender', senderPrefixes='$senderPrefixes', content='$content')"
}
} }
package de.kuschku.libquassel.protocol
import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer.UTF8
import de.kuschku.libquassel.protocol.primitive.serializer.deserializeString
import de.kuschku.libquassel.protocol.primitive.serializer.serializeString
import org.threeten.bp.Instant
import java.nio.ByteBuffer
enum class RequestType(val value: Int) {
Invalid(0),
Sync(1),
RpcCall(2),
InitRequest(3),
InitData(4),
HeartBeat(5),
HeartBeatReply(6);
companion object {
private val byId = enumValues<RequestType>().associateBy(RequestType::value)
fun of(value: Int) = byId[value] ?: Invalid
}
}
sealed class SignalProxyMessage {
class SyncMessage(val className: String, val objectName: String, val slotName: String,
val params: QVariantList) : SignalProxyMessage() {
override fun toString(): String {
return "SyncMessage::$className:${objectName.hashCode()}/$slotName"
}
}
class RpcCall(val slotName: String, val params: QVariantList) : SignalProxyMessage() {
override fun toString(): String {
return "RpcCall::$slotName"
}
}
class InitRequest(val className: String, val objectName: String) : SignalProxyMessage() {
override fun toString(): String {
return "InitRequest::$className:${objectName.hashCode()}"
}
}
class InitData(val className: String, val objectName: String, val initData: QVariantMap) :
SignalProxyMessage() {
override fun toString(): String {
return "InitData::$className:${objectName.hashCode()}"
}
}
class HeartBeat(val timestamp: Instant) : SignalProxyMessage() {
override fun toString(): String {
return "HeartBeat::$timestamp"
}
}
class HeartBeatReply(val timestamp: Instant) : SignalProxyMessage() {
override fun toString(): String {
return "HeartBeatReply::$timestamp"
}
}
companion object : SignalProxyMessageSerializer<SignalProxyMessage> {
override fun serialize(data: SignalProxyMessage) = when (data) {
is SignalProxyMessage.SyncMessage -> SyncMessageSerializer.serialize(data)
is SignalProxyMessage.RpcCall -> RpcCallSerializer.serialize(data)
is SignalProxyMessage.InitRequest -> InitRequestSerializer.serialize(data)
is SignalProxyMessage.InitData -> InitDataSerializer.serialize(data)
is SignalProxyMessage.HeartBeat -> HeartBeatSerializer.serialize(data)
is SignalProxyMessage.HeartBeatReply -> HeartBeatReplySerializer.serialize(data)
}
override fun deserialize(data: QVariantList): SignalProxyMessage {
val type = data.first().value(-1)
return when (RequestType.of(type)) {
RequestType.Sync -> SyncMessageSerializer.deserialize(data.drop(1))
RequestType.RpcCall -> RpcCallSerializer.deserialize(data.drop(1))
RequestType.InitRequest -> InitRequestSerializer.deserialize(data.drop(1))
RequestType.InitData -> InitDataSerializer.deserialize(data.drop(1))
RequestType.HeartBeat -> HeartBeatSerializer.deserialize(data.drop(1))
RequestType.HeartBeatReply -> HeartBeatReplySerializer.deserialize(data.drop(1))
else -> throw IllegalArgumentException("Invalid MsgType: $type")
}
}
}
}
object SyncMessageSerializer : SignalProxyMessageSerializer<SignalProxyMessage.SyncMessage> {
override fun serialize(data: SignalProxyMessage.SyncMessage): QVariantList = listOf(
QVariant_(RequestType.Sync.value, Type.Int),
QVariant_(data.className.serializeString(UTF8), Type.QByteArray),
QVariant_(data.objectName.serializeString(UTF8), Type.QByteArray),
QVariant_(data.slotName.serializeString(UTF8), Type.QByteArray),
*data.params.toTypedArray()
)
override fun deserialize(data: QVariantList) = SignalProxyMessage.SyncMessage(
data[0].value<ByteBuffer?>().deserializeString(UTF8) ?: "",
data[1].value<ByteBuffer?>().deserializeString(UTF8) ?: "",
data[2].value<ByteBuffer?>().deserializeString(UTF8) ?: "",
data.drop(3)
)
}
object RpcCallSerializer : SignalProxyMessageSerializer<SignalProxyMessage.RpcCall> {
override fun serialize(data: SignalProxyMessage.RpcCall) = listOf(
QVariant_(RequestType.RpcCall.value, Type.Int),
QVariant_(data.slotName.serializeString(UTF8), Type.QByteArray),
*data.params.toTypedArray()
)
override fun deserialize(data: QVariantList) = SignalProxyMessage.RpcCall(
data[0].value<ByteBuffer?>().deserializeString(UTF8) ?: "",
data.drop(1)
)
}
object InitRequestSerializer : SignalProxyMessageSerializer<SignalProxyMessage.InitRequest> {
override fun serialize(data: SignalProxyMessage.InitRequest) = listOf(
QVariant_(RequestType.InitRequest.value, Type.Int),
QVariant_(data.className.serializeString(UTF8), Type.QByteArray),
QVariant_(data.objectName.serializeString(UTF8), Type.QByteArray)
)
override fun deserialize(data: QVariantList) = SignalProxyMessage.InitRequest(
data[0].value<ByteBuffer?>().deserializeString(UTF8) ?: "",
data[1].value<ByteBuffer?>().deserializeString(UTF8) ?: ""
)
}
object InitDataSerializer : SignalProxyMessageSerializer<SignalProxyMessage.InitData> {
override fun serialize(data: SignalProxyMessage.InitData) = listOf(
QVariant_(RequestType.InitData.value, Type.Int),
QVariant_(data.className.serializeString(UTF8), Type.QByteArray),
QVariant_(data.objectName.serializeString(UTF8), Type.QByteArray),
QVariant_(data.initData, Type.QVariantMap)
)
override fun deserialize(data: QVariantList) = SignalProxyMessage.InitData(
data[0].value<ByteBuffer?>().deserializeString(UTF8) ?: "",
data[1].value<ByteBuffer?>().deserializeString(UTF8) ?: "",
data.drop(2).toVariantMap()
)
}
object HeartBeatSerializer : SignalProxyMessageSerializer<SignalProxyMessage.HeartBeat> {
override fun serialize(data: SignalProxyMessage.HeartBeat) = listOf(
QVariant_(RequestType.HeartBeat.value, Type.Int),
QVariant_(data.timestamp, Type.QDateTime)
)
override fun deserialize(data: QVariantList) = SignalProxyMessage.HeartBeat(
data[0].value(Instant.EPOCH)
)
}
object HeartBeatReplySerializer : SignalProxyMessageSerializer<SignalProxyMessage.HeartBeatReply> {
override fun serialize(data: SignalProxyMessage.HeartBeatReply) = listOf(
QVariant_(RequestType.HeartBeatReply.value, Type.Int),
QVariant_(data.timestamp, Type.QDateTime)
)
override fun deserialize(data: QVariantList) = SignalProxyMessage.HeartBeatReply(
data[0].value(Instant.EPOCH)
)
}
interface SignalProxyMessageSerializer<T : SignalProxyMessage> {
fun serialize(data: T): QVariantList
fun deserialize(data: QVariantList): T
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
import de.kuschku.libquassel.util.Flags
object ClientInitAckSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientInitAck> {
override fun serialize(data: HandshakeMessage.ClientInitAck) = mapOf(
"MsgType" to QVariant_("ClientInitAck", Type.QString),
"CoreFeatures" to QVariant_(data.coreFeatures?.toInt(), Type.UInt),
"StorageBackends" to QVariant_(data.backendInfo, Type.QVariantList),
"Authenticator" to QVariant_(data.authenticatorInfo, Type.QVariantList),
"Configured" to QVariant_(data.coreConfigured, Type.Bool)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInitAck(
coreFeatures = Flags.Companion.of(data["CoreFeatures"].value(0)),
backendInfo = data["StorageBackends"].value(),
authenticatorInfo = data["Authenticators"].value(),
coreConfigured = data["Configured"].value()
)
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
object ClientInitRejectSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientInitReject> {
override fun serialize(data: HandshakeMessage.ClientInitReject) = mapOf(
"MsgType" to QVariant_("ClientInitReject", Type.QString),
"Error" to QVariant_(data.errorString, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInitReject(
errorString = data["Error"].value()
)
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
import de.kuschku.libquassel.util.Flags
object ClientInitSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientInit> {
override fun serialize(data: HandshakeMessage.ClientInit) = mapOf(
"MsgType" to QVariant_("ClientInit", Type.QString),
"ClientVersion" to QVariant_(data.clientVersion, Type.QString),
"ClientDate" to QVariant_(data.buildDate, Type.QString),
"ClientFeatures" to QVariant_(data.clientFeatures?.toInt(), Type.UInt)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInit(
clientVersion = data["ClientVersion"].value(),
buildDate = data["ClientDate"].value(),
clientFeatures = Flags.Companion.of(data["ClientFeatures"].value(0))
)
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
object ClientLoginAckSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientLoginAck> {
override fun serialize(data: HandshakeMessage.ClientLoginAck) = mapOf(
"MsgType" to QVariant_("ClientLoginAck", Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientLoginAck()
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
object ClientLoginRejectSerializer :
HandshakeMessageSerializer<HandshakeMessage.ClientLoginReject> {
override fun serialize(data: HandshakeMessage.ClientLoginReject) = mapOf(
"MsgType" to QVariant_("ClientLoginReject", Type.QString),
"Error" to QVariant_(data.errorString, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientLoginReject(
errorString = data["Error"].value()
)
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
object ClientLoginSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientLogin> {
override fun serialize(data: HandshakeMessage.ClientLogin) = mapOf(
"MsgType" to QVariant_("ClientLogin", Type.QString),
"User" to QVariant_(data.user, Type.QString),
"Password" to QVariant_(data.password, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientLogin(
user = data["User"].value(),
password = data["Password"].value()
)
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
object CoreSetupAckSerializer : HandshakeMessageSerializer<HandshakeMessage.CoreSetupAck> {
override fun serialize(data: HandshakeMessage.CoreSetupAck) = mapOf(
"MsgType" to QVariant_("CoreSetupAck", Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.CoreSetupAck()
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
object CoreSetupDataSerializer : HandshakeMessageSerializer<HandshakeMessage.CoreSetupData> {
override fun serialize(data: HandshakeMessage.CoreSetupData) = mapOf(
"MsgType" to QVariant_("CoreSetupData", Type.QString),
"SetupData" to QVariant_(mapOf(
"AdminUser" to QVariant_(data.adminUser, Type.QString),
"AdminPasswd" to QVariant_(data.adminPassword, Type.QString),
"Backend" to QVariant_(data.backend, Type.QString),
"ConnectionProperties" to QVariant_(data.setupData, Type.QVariantMap),
"Authenticator" to QVariant_(data.authenticator, Type.QString),
"AuthProperties" to QVariant_(data.authSetupData, Type.QVariantMap)
), Type.QVariantMap)
)
override fun deserialize(data: QVariantMap): HandshakeMessage.CoreSetupData {
val setupData = data["SetupData"].value<QVariantMap?>()
return HandshakeMessage.CoreSetupData(
adminUser = setupData?.get("AdminUser").value(),
adminPassword = setupData?.get("AdminPasswd").value(),
backend = setupData?.get("Backend").value(),
setupData = setupData?.get("ConnectionProperties").value(),
authenticator = setupData?.get("Authenticator").value(),
authSetupData = setupData?.get("AuthProperties").value()
)
}
}
package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.QVariant_
import de.kuschku.libquassel.protocol.Type
import de.kuschku.libquassel.protocol.value
object CoreSetupRejectSerializer : HandshakeMessageSerializer<HandshakeMessage.CoreSetupReject> {
override fun serialize(data: HandshakeMessage.CoreSetupReject) = mapOf(
"MsgType" to QVariant_("CoreSetupReject", Type.QString),
"Error" to QVariant_(data.errorString, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.CoreSetupReject(
errorString = data["Error"].value()
)
}
package de.kuschku.libquassel.protocol package de.kuschku.libquassel.protocol.message
import de.kuschku.libquassel.util.Flags import de.kuschku.libquassel.protocol.QVariantList
import de.kuschku.libquassel.protocol.QVariantMap
import de.kuschku.libquassel.protocol.Quassel_Features
import de.kuschku.libquassel.protocol.value
sealed class HandshakeMessage { sealed class HandshakeMessage {
...@@ -30,7 +33,7 @@ sealed class HandshakeMessage { ...@@ -30,7 +33,7 @@ sealed class HandshakeMessage {
val authSetupData: QVariantMap?) : val authSetupData: QVariantMap?) :
HandshakeMessage() { HandshakeMessage() {
override fun toString(): String { override fun toString(): String {
return "CoreSetupData(adminUser=$adminUser, adminPassword=$adminPassword, backend=$backend, setupData=$setupData, authenticator=$authenticator, authSetupData=$authSetupData)" return "CoreSetupData"
} }
} }
...@@ -68,11 +71,12 @@ sealed class HandshakeMessage { ...@@ -68,11 +71,12 @@ sealed class HandshakeMessage {
val networkIds: QVariantList?) : val networkIds: QVariantList?) :
HandshakeMessage() { HandshakeMessage() {
override fun toString(): String { override fun toString(): String {
return "SessionInit(identities=$identities, bufferInfos=$bufferInfos, networkIds=$networkIds)" return "SessionInit"
} }
} }
companion object : HandshakeMessageSerializer<HandshakeMessage> { companion object :
HandshakeMessageSerializer<HandshakeMessage> {
override fun serialize(data: HandshakeMessage) = when (data) { override fun serialize(data: HandshakeMessage) = when (data) {
is ClientInit -> ClientInitSerializer.serialize(data) is ClientInit -> ClientInitSerializer.serialize(data)
is ClientInitReject -> ClientInitRejectSerializer.serialize(data) is ClientInitReject -> ClientInitRejectSerializer.serialize(data)
...@@ -107,149 +111,3 @@ sealed class HandshakeMessage { ...@@ -107,149 +111,3 @@ sealed class HandshakeMessage {
} }
} }
object ClientInitSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientInit> {
override fun serialize(data: HandshakeMessage.ClientInit) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"ClientVersion" to QVariant_(data.clientVersion, Type.QString),
"ClientDate" to QVariant_(data.buildDate, Type.QString),
"ClientFeatures" to QVariant_(data.clientFeatures?.toInt(), Type.UInt)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInit(
clientVersion = data["ClientVersion"].value(),
buildDate = data["ClientDate"].value(),
clientFeatures = Flags.of(data["ClientFeatures"].value(0))
)
}
object ClientInitRejectSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientInitReject> {
override fun serialize(data: HandshakeMessage.ClientInitReject) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"Error" to QVariant_(data.errorString, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInitReject(
errorString = data["Error"].value()
)
}
object ClientInitAckSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientInitAck> {
override fun serialize(data: HandshakeMessage.ClientInitAck) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"CoreFeatures" to QVariant_(data.coreFeatures?.toInt(), Type.UInt),
"StorageBackends" to QVariant_(data.backendInfo, Type.QVariantList),
"Authenticator" to QVariant_(data.authenticatorInfo, Type.QVariantList),
"Configured" to QVariant_(data.coreConfigured, Type.Bool)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientInitAck(
coreFeatures = Flags.of(data["CoreFeatures"].value(0)),
backendInfo = data["StorageBackends"].value(),
authenticatorInfo = data["Authenticators"].value(),
coreConfigured = data["Configured"].value()
)
}
object CoreSetupDataSerializer : HandshakeMessageSerializer<HandshakeMessage.CoreSetupData> {
override fun serialize(data: HandshakeMessage.CoreSetupData) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"SetupData" to QVariant_(mapOf(
"AdminUser" to QVariant_(data.adminUser, Type.QString),
"AdminPasswd" to QVariant_(data.adminPassword, Type.QString),
"Backend" to QVariant_(data.backend, Type.QString),
"ConnectionProperties" to QVariant_(data.setupData, Type.QVariantMap),
"Authenticator" to QVariant_(data.authenticator, Type.QString),
"AuthProperties" to QVariant_(data.authSetupData, Type.QVariantMap)
), Type.QVariantMap)
)
override fun deserialize(data: QVariantMap): HandshakeMessage.CoreSetupData {
val setupData = data["SetupData"].value<QVariantMap?>()
return HandshakeMessage.CoreSetupData(
adminUser = setupData?.get("AdminUser").value(),
adminPassword = setupData?.get("AdminPasswd").value(),
backend = setupData?.get("Backend").value(),
setupData = setupData?.get("ConnectionProperties").value(),
authenticator = setupData?.get("Authenticator").value(),
authSetupData = setupData?.get("AuthProperties").value()
)
}
}
object CoreSetupRejectSerializer : HandshakeMessageSerializer<HandshakeMessage.CoreSetupReject> {
override fun serialize(data: HandshakeMessage.CoreSetupReject) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"Error" to QVariant_(data.errorString, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.CoreSetupReject(
errorString = data["Error"].value()
)
}
object CoreSetupAckSerializer : HandshakeMessageSerializer<HandshakeMessage.CoreSetupAck> {
override fun serialize(data: HandshakeMessage.CoreSetupAck) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.CoreSetupAck()
}
object ClientLoginSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientLogin> {
override fun serialize(data: HandshakeMessage.ClientLogin) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"User" to QVariant_(data.user, Type.QString),
"Password" to QVariant_(data.password, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientLogin(
user = data["User"].value(),
password = data["Password"].value()
)
}
object ClientLoginRejectSerializer :
HandshakeMessageSerializer<HandshakeMessage.ClientLoginReject> {
override fun serialize(data: HandshakeMessage.ClientLoginReject) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"Error" to QVariant_(data.errorString, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientLoginReject(
errorString = data["Error"].value()
)
}
object ClientLoginAckSerializer : HandshakeMessageSerializer<HandshakeMessage.ClientLoginAck> {
override fun serialize(data: HandshakeMessage.ClientLoginAck) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString)
)
override fun deserialize(data: QVariantMap) = HandshakeMessage.ClientLoginAck()
}
object SessionInitSerializer : HandshakeMessageSerializer<HandshakeMessage.SessionInit> {
override fun serialize(data: HandshakeMessage.SessionInit) = mapOf(
"MsgType" to QVariant_(data::class.java.simpleName, Type.QString),
"SessionState" to QVariant_(mapOf(
"BufferInfos" to QVariant_(data.bufferInfos, Type.QVariantList),
"NetworkIds" to QVariant_(data.networkIds, Type.QVariantList),
"Identities" to QVariant_(data.identities, Type.QVariantList)
), Type.QVariantMap)
)
override fun deserialize(data: QVariantMap): HandshakeMessage.SessionInit {
val setupData = data["SessionState"].value<QVariantMap?>()
return HandshakeMessage.SessionInit(
bufferInfos = setupData?.get("BufferInfos").value(),
networkIds = setupData?.get("NetworkIds").value(),
identities = setupData?.get("Identities").value()
)
}
}
interface HandshakeMessageSerializer<T : HandshakeMessage> {
fun serialize(data: T): QVariantMap
fun deserialize(data: QVariantMap): T
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment