relaycorp / awala-poweb-jvm Goto Github PK
View Code? Open in Web Editor NEWJVM implementation of the Awala PoWeb binding
License: MIT License
JVM implementation of the Awala PoWeb binding
License: MIT License
The Awala gateway just crashed because of the exception above.
Unfortunately, the logs prior to the crash were lost by the time I plugged the phone (Pixel 8) to the computer, but I captured this which suggests a bug in this library:
2024-01-10 17:15:26.024 9441-9441 AndroidRuntime pid-9441 E FATAL EXCEPTION: main
Process: tech.relaycorp.gateway, PID: 9441
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:562)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: android.os.strictmode.LeakedClosableViolation: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
at android.os.StrictMode$AndroidCloseGuardReporter.report(StrictMode.java:1994)
at dalvik.system.CloseGuard.warnIfOpen(CloseGuard.java:336)
at java.io.FileInputStream.finalize(FileInputStream.java:508)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:339)
at java.lang.Daemons$FinalizerDaemon.processReference(Daemons.java:324)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:300)
at java.lang.Daemons$Daemon.run(Daemons.java:145)
at java.lang.Thread.run(Thread.java:1012)
Caused by: java.lang.Throwable: Explicit termination method 'close' not called
at dalvik.system.CloseGuard.openWithCallSite(CloseGuard.java:288)
at dalvik.system.CloseGuard.open(CloseGuard.java:257)
at java.io.FileInputStream.<init>(FileInputStream.java:176)
at tech.relaycorp.gateway.data.disk.DiskMessageOperations$readMessage$2.invoke(DiskMessageOperations.kt:39)
at tech.relaycorp.gateway.data.disk.DiskMessageOperations$readMessage$2.invoke(DiskMessageOperations.kt:39)
at tech.relaycorp.gateway.domain.endpoint.CollectParcels.getInputStream(CollectParcels.kt:70)
at tech.relaycorp.gateway.domain.endpoint.CollectParcels.access$getInputStream(CollectParcels.kt:24)
at tech.relaycorp.gateway.domain.endpoint.CollectParcels$getInputStream$1.invokeSuspend(Unknown Source:19)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
2024-01-10 17:17:40.555 19717-19776 AndroidRuntime pid-19717 E FATAL EXCEPTION: DefaultDispatcher-worker-4
Process: tech.relaycorp.gateway, PID: 19717
java.lang.IllegalStateException: Flow exception transparency is violated:
Previous 'emit' call has thrown exception java.io.EOFException, but then emission attempt of value 'tech.relaycorp.relaynet.bindings.pdc.ParcelCollection@cc25341' has been detected.
Emissions from 'catch' blocks are prohibited in order to avoid unspecified behaviour, 'Flow.catch' operator can be used instead.
For a more detailed explanation, please refer to Flow documentation.
at kotlinx.coroutines.flow.internal.SafeCollector.exceptionTransparencyViolated(SafeCollector.kt:140)
at kotlinx.coroutines.flow.internal.SafeCollector.checkContext(SafeCollector.kt:104)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:83)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
at tech.relaycorp.poweb.PoWebClient.collectAndAckParcels(PoWebClient.kt:253)
at tech.relaycorp.poweb.PoWebClient.access$collectAndAckParcels(PoWebClient.kt:74)
at tech.relaycorp.poweb.PoWebClient$collectAndAckParcels$1.invokeSuspend(Unknown Source:19)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@6ec1640, Dispatchers.IO]
2024-01-10 17:19:19.499 20319-20349 AndroidRuntime pid-20319 E FATAL EXCEPTION: DefaultDispatcher-worker-4
Process: tech.relaycorp.gateway, PID: 20319
java.lang.IllegalStateException: Flow exception transparency is violated:
Previous 'emit' call has thrown exception java.io.EOFException, but then emission attempt of value 'tech.relaycorp.relaynet.bindings.pdc.ParcelCollection@670b7d4' has been detected.
Emissions from 'catch' blocks are prohibited in order to avoid unspecified behaviour, 'Flow.catch' operator can be used instead.
For a more detailed explanation, please refer to Flow documentation.
at kotlinx.coroutines.flow.internal.SafeCollector.exceptionTransparencyViolated(SafeCollector.kt:140)
at kotlinx.coroutines.flow.internal.SafeCollector.checkContext(SafeCollector.kt:104)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:83)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
at tech.relaycorp.poweb.PoWebClient.collectAndAckParcels(PoWebClient.kt:253)
at tech.relaycorp.poweb.PoWebClient.access$collectAndAckParcels(PoWebClient.kt:74)
at tech.relaycorp.poweb.PoWebClient$collectAndAckParcels$1.invokeSuspend(Unknown Source:19)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@55eb61f, Dispatchers.IO]
See #7 for the generator counterpart.
We need to explicitly set the ping interval in the OkHTTP engine: https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/ping-interval/
See server-side counterpart: relaycorp/awala-gateway-internet#325
But we don't have a way to test it yet due to square/okhttp#6333
See deliverParcels()
in client.js
in the PoC.
See collectParcels()
in client.js
in the PoC.
Triggered each time there's a new Git tag matching a semver pattern.
Alternatively, do it by hand each time it's needed.
This assumes Maven is already configured in #2.
That is, implement the counterpart to relaycorp/relaynet-gateway-android#7
This is mostly implemented in PoWebSocket/client.js
(and required files) in the PoC. The notable omissions from the PoC are: Requesting endpoint certificate signing from the gateway and submitting parcel delivery deauthorizations.
The following doesn't appear to have any effect (SocketTimeoutException
is a subclass of IOException
):
awala-poweb-jvm/src/main/kotlin/tech/relaycorp/poweb/PoWebClient.kt
Lines 325 to 327 in 380529f
Because Letro is crashing when the connection to the Awala server stops responding to pings:
E FATAL EXCEPTION: AwalaManagerMessageReceiverThread
Process: tech.relaycorp.letro, PID: 14200
java.net.SocketTimeoutException: sent ping but didn't receive pong within 5000ms (after 1 successful ping/pongs)
at okhttp3.internal.ws.RealWebSocket.writePingFrame$okhttp(RealWebSocket.kt:563)
at okhttp3.internal.ws.RealWebSocket$initReaderAndWriter$lambda-3$$inlined$schedule$1.runOnce(TaskQueue.kt:219)
at okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:116)
at okhttp3.internal.concurrent.TaskRunner.access$runTask(TaskRunner.kt:42)
at okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:65)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@a67a425, java.util.concurrent.ScheduledThreadPoolExecutor@bc259fa[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 4]]
We can't use java.util.Base64
because it's unavailable in Android API < 26, so I had to add Bouncy Castle as a dependency just to use its base64 encoder. We can't use Apache Commons Codec either.
I created this feature request to have the class backported via the desugaring functionality: https://issuetracker.google.com/issues/171293709
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.