Skip to content

Commit

Permalink
Data is no longer held between sends
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanIlchev committed Mar 30, 2024
1 parent 868fcdc commit ccbaa65
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package service.elementum.android
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import ilchev.stefan.binarywrapper.BaseDaemonInvoker
import java.io.ByteArrayOutputStream
import java.io.File
import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.channels.Channels
import java.nio.channels.ServerSocketChannel
import java.nio.channels.WritableByteChannel
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream

Expand Down Expand Up @@ -72,22 +72,6 @@ class DaemonInvoker(
}
}

private fun toData(
addonId: String
) = ByteArrayOutputStream().use { out ->
ZipOutputStream(out).use { zip ->
for (file in File(addonsDir, addonId).walkTopDown()) {
if (file.isDirectory) {
zip.putNextEntry(ZipEntry("${file.relativeTo(addonsDir).path}/"))
} else if (file.isFile) {
zip.putNextEntry(ZipEntry(file.relativeTo(addonsDir).path))
file.inputStream().use { it.copyTo(zip) }
}
}
}
out.toByteArray()
}

private fun toSetChannelRunnable(
value: ServerSocketChannel
) = Runnable {
Expand All @@ -101,56 +85,61 @@ class DaemonInvoker(
}
}

private fun send(port: Int, data: ByteArray): Long {
private inline fun send(port: Int, consumer: (WritableByteChannel) -> Unit): Long {
if (isDestroyed) return -1L
ServerSocketChannel.open().use { channel ->
if (!mainHandler.post(toSetChannelRunnable(channel))) return -1L
channel.bind(InetSocketAddress(port))
channel.accept().use { it.write(ByteBuffer.wrap(data)) }
consumer(channel.accept())
return if (isDestroyed ||
!mainHandler.post(clearChannelRunnable)
) -1L else 1_000L
}
}

private fun toSendInvoker(data: ByteArray): () -> Long {
private inline fun toSendInvoker(crossinline consumer: (WritableByteChannel) -> Unit): () -> Long {
val regex = """${BuildConfig.ARG_LOCAL_PORT}=(\d+)""".toRegex()
val port = subprocessCmd.firstNotNullOfOrNull {
regex.matchEntire(it)?.groupValues?.get(1)?.toIntOrNull()
} ?: BuildConfig.LOCAL_PORT
return {
try {
send(port, data)
send(port, consumer)
} catch (ignored: Throwable) {
-1L
}
}
}

private val invoker by lazy {
try {
"""${BuildConfig.ARG_ADDON_INFO}=(\S+)""".toRegex().let { regex ->
subprocessCmd.firstNotNullOfOrNull { regex.matchEntire(it)?.groupValues?.get(1) }?.let {
toSendInvoker(toData(it))
private fun toAddonInfoConsumer(
addonId: String
): (WritableByteChannel) -> Unit = { channel ->
ZipOutputStream(Channels.newOutputStream(channel).buffered()).use { zip ->
for (file in File(addonsDir, addonId).walkTopDown()) {
if (file.isDirectory) {
zip.putNextEntry(ZipEntry("${file.relativeTo(addonsDir).path}/"))
} else if (file.isFile) {
zip.putNextEntry(ZipEntry(file.relativeTo(addonsDir).path))
file.inputStream().use { it.copyTo(zip) }
}
} ?: if (subprocessCmd.contains(BuildConfig.ARG_TRANSLATE_PATH)) {
toSendInvoker("${homeDir.path}/\u0000${xbmcDir.path}/".toByteArray())
} else {
null
}
} catch (t: Throwable) {
Log.w(TAG, t)
null
} ?: {
}
}

private val invoker = """${BuildConfig.ARG_ADDON_INFO}=(\S+)""".toRegex().let { regex ->
subprocessCmd.firstNotNullOfOrNull { regex.matchEntire(it)?.groupValues?.get(1) }?.let {
toSendInvoker(toAddonInfoConsumer(it))
}
} ?: if (subprocessCmd.contains(BuildConfig.ARG_TRANSLATE_PATH)) {
toSendInvoker { channel ->
channel.use { it.write(ByteBuffer.wrap("${homeDir.path}/\u0000${xbmcDir.path}/".toByteArray())) }
}
} else {
{
lockfile.delete()
super.invoke()
}
}

override fun invoke() = invoker()

companion object {

private const val TAG = "DaemonInvoker"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package service.lt2http.android
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import ilchev.stefan.binarywrapper.BaseDaemonInvoker
import java.io.ByteArrayOutputStream
import java.io.File
import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.channels.Channels
import java.nio.channels.ServerSocketChannel
import java.nio.channels.WritableByteChannel
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream

Expand Down Expand Up @@ -72,22 +72,6 @@ class DaemonInvoker(
}
}

private fun toData(
addonId: String
) = ByteArrayOutputStream().use { out ->
ZipOutputStream(out).use { zip ->
for (file in File(addonsDir, addonId).walkTopDown()) {
if (file.isDirectory) {
zip.putNextEntry(ZipEntry("${file.relativeTo(addonsDir).path}/"))
} else if (file.isFile) {
zip.putNextEntry(ZipEntry(file.relativeTo(addonsDir).path))
file.inputStream().use { it.copyTo(zip) }
}
}
}
out.toByteArray()
}

private fun toSetChannelRunnable(
value: ServerSocketChannel
) = Runnable {
Expand All @@ -101,56 +85,61 @@ class DaemonInvoker(
}
}

private fun send(port: Int, data: ByteArray): Long {
private inline fun send(port: Int, consumer: (WritableByteChannel) -> Unit): Long {
if (isDestroyed) return -1L
ServerSocketChannel.open().use { channel ->
if (!mainHandler.post(toSetChannelRunnable(channel))) return -1L
channel.bind(InetSocketAddress(port))
channel.accept().use { it.write(ByteBuffer.wrap(data)) }
consumer(channel.accept())
return if (isDestroyed ||
!mainHandler.post(clearChannelRunnable)
) -1L else 1_000L
}
}

private fun toSendInvoker(data: ByteArray): () -> Long {
private inline fun toSendInvoker(crossinline consumer: (WritableByteChannel) -> Unit): () -> Long {
val regex = """${BuildConfig.ARG_LOCAL_PORT}=(\d+)""".toRegex()
val port = subprocessCmd.firstNotNullOfOrNull {
regex.matchEntire(it)?.groupValues?.get(1)?.toIntOrNull()
} ?: BuildConfig.LOCAL_PORT
return {
try {
send(port, data)
send(port, consumer)
} catch (ignored: Throwable) {
-1L
}
}
}

private val invoker by lazy {
try {
"""${BuildConfig.ARG_ADDON_INFO}=(\S+)""".toRegex().let { regex ->
subprocessCmd.firstNotNullOfOrNull { regex.matchEntire(it)?.groupValues?.get(1) }?.let {
toSendInvoker(toData(it))
private fun toAddonInfoConsumer(
addonId: String
): (WritableByteChannel) -> Unit = { channel ->
ZipOutputStream(Channels.newOutputStream(channel).buffered()).use { zip ->
for (file in File(addonsDir, addonId).walkTopDown()) {
if (file.isDirectory) {
zip.putNextEntry(ZipEntry("${file.relativeTo(addonsDir).path}/"))
} else if (file.isFile) {
zip.putNextEntry(ZipEntry(file.relativeTo(addonsDir).path))
file.inputStream().use { it.copyTo(zip) }
}
} ?: if (subprocessCmd.contains(BuildConfig.ARG_TRANSLATE_PATH)) {
toSendInvoker("${homeDir.path}/\u0000${xbmcDir.path}/".toByteArray())
} else {
null
}
} catch (t: Throwable) {
Log.w(TAG, t)
null
} ?: {
}
}

private val invoker = """${BuildConfig.ARG_ADDON_INFO}=(\S+)""".toRegex().let { regex ->
subprocessCmd.firstNotNullOfOrNull { regex.matchEntire(it)?.groupValues?.get(1) }?.let {
toSendInvoker(toAddonInfoConsumer(it))
}
} ?: if (subprocessCmd.contains(BuildConfig.ARG_TRANSLATE_PATH)) {
toSendInvoker { channel ->
channel.use { it.write(ByteBuffer.wrap("${homeDir.path}/\u0000${xbmcDir.path}/".toByteArray())) }
}
} else {
{
lockfile.delete()
super.invoke()
}
}

override fun invoke() = invoker()

companion object {

private const val TAG = "DaemonInvoker"
}
}

0 comments on commit ccbaa65

Please sign in to comment.