Moves the relay structure to quartz
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
package com.vitorpamplona.quartz.experimental.limits
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip13Pow.getPoWRank
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
|
||||
import androidx.collection.LruCache
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
class RelayStat(
|
||||
var receivedBytes: Long = 0L,
|
||||
var sentBytes: Long = 0L,
|
||||
var spamCounter: Long = 0L,
|
||||
var errorCounter: Long = 0L,
|
||||
var pingInMs: Long = 0L,
|
||||
) {
|
||||
val messages = LruCache<RelayDebugMessage, RelayDebugMessage>(100)
|
||||
|
||||
fun newNotice(notice: String?) {
|
||||
val debugMessage =
|
||||
RelayDebugMessage(
|
||||
type = RelayDebugMessageType.NOTICE,
|
||||
message = notice ?: "No error message provided",
|
||||
)
|
||||
|
||||
messages.put(debugMessage, debugMessage)
|
||||
}
|
||||
|
||||
fun newError(error: String?) {
|
||||
errorCounter++
|
||||
|
||||
val debugMessage =
|
||||
RelayDebugMessage(
|
||||
type = RelayDebugMessageType.ERROR,
|
||||
message = error ?: "No error message provided",
|
||||
)
|
||||
|
||||
messages.put(debugMessage, debugMessage)
|
||||
}
|
||||
|
||||
fun addBytesReceived(bytesUsedInMemory: Long) {
|
||||
receivedBytes += bytesUsedInMemory
|
||||
}
|
||||
|
||||
fun addBytesSent(bytesUsedInMemory: Long) {
|
||||
sentBytes += bytesUsedInMemory
|
||||
}
|
||||
|
||||
fun newSpam(spamDescriptor: String) {
|
||||
spamCounter++
|
||||
|
||||
val debugMessage =
|
||||
RelayDebugMessage(
|
||||
type = RelayDebugMessageType.SPAM,
|
||||
message = spamDescriptor,
|
||||
)
|
||||
|
||||
messages.put(debugMessage, debugMessage)
|
||||
}
|
||||
}
|
||||
|
||||
class RelayDebugMessage(
|
||||
val type: RelayDebugMessageType,
|
||||
val message: String,
|
||||
val time: Long = TimeUtils.now(),
|
||||
)
|
||||
|
||||
enum class RelayDebugMessageType {
|
||||
SPAM,
|
||||
NOTICE,
|
||||
ERROR,
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
|
||||
enum class RelayState {
|
||||
// Websocket connected
|
||||
CONNECTED,
|
||||
|
||||
// Websocket disconnecting
|
||||
DISCONNECTING,
|
||||
|
||||
// Websocket disconnected
|
||||
DISCONNECTED,
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
|
||||
import android.util.Log
|
||||
import com.vitorpamplona.quartz.nip01Core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.AuthMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.ClosedMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.EoseMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.EventMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.NoticeMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.NotifyMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.OkMessage
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toClient.ToClientParser
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.AuthCmd
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.CloseCmd
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.CountCmd
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.EventCmd
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.sockets.WebSocket
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.sockets.WebSocketListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.sockets.WebsocketBuilder
|
||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
class SimpleClientRelay(
|
||||
val url: String,
|
||||
val socketBuilder: WebsocketBuilder,
|
||||
val subs: SubscriptionCollection,
|
||||
val listener: Listener,
|
||||
val stats: RelayStat = RelayStat(),
|
||||
) {
|
||||
companion object {
|
||||
// waits 3 minutes to reconnect once things fail
|
||||
const val RECONNECTING_IN_SECONDS = 60 * 3
|
||||
}
|
||||
|
||||
private var socket: WebSocket? = null
|
||||
private var isReady: Boolean = false
|
||||
private var usingCompression: Boolean = false
|
||||
|
||||
private var lastConnectTentative: Long = 0L
|
||||
|
||||
private var afterEOSEPerSubscription = mutableMapOf<String, Boolean>()
|
||||
|
||||
private val authResponseWatcher = mutableMapOf<HexKey, Boolean>()
|
||||
private val authChallengesSent = mutableSetOf<String>()
|
||||
|
||||
/**
|
||||
* Auth procedures require us to keep track of the outgoing events
|
||||
* to make sure the relay waits for the auth to finish and send them.
|
||||
*/
|
||||
private val outboxCache = mutableMapOf<HexKey, Event>()
|
||||
|
||||
private var connectingMutex = AtomicBoolean()
|
||||
|
||||
private val parser = ToClientParser()
|
||||
|
||||
fun isConnectionStarted(): Boolean = socket != null
|
||||
|
||||
fun isConnected(): Boolean = socket != null && isReady
|
||||
|
||||
fun connect() = connectAndRunOverride(::sendEverything)
|
||||
|
||||
fun sendEverything() {
|
||||
renewSubscriptions()
|
||||
sendOutbox()
|
||||
}
|
||||
|
||||
fun sendOutbox() {
|
||||
synchronized(outboxCache) {
|
||||
outboxCache.values.forEach {
|
||||
send(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun connectAndRunAfterSync(onConnected: () -> Unit) {
|
||||
connectAndRunOverride {
|
||||
sendEverything()
|
||||
onConnected()
|
||||
}
|
||||
}
|
||||
|
||||
fun connectAndRunOverride(onConnected: () -> Unit) {
|
||||
Log.d("Relay", "Relay.connect $url isAlreadyConnecting: ${connectingMutex.get()}")
|
||||
|
||||
// If there is a connection, don't wait.
|
||||
if (connectingMutex.getAndSet(true)) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (socket != null) {
|
||||
connectingMutex.set(false)
|
||||
return
|
||||
}
|
||||
|
||||
lastConnectTentative = TimeUtils.now()
|
||||
|
||||
socket = socketBuilder.build(url, RelayListener(onConnected))
|
||||
socket?.connect()
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
|
||||
stats.newError(e.message ?: "Error trying to connect: ${e.javaClass.simpleName}")
|
||||
|
||||
markConnectionAsClosed()
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
connectingMutex.set(false)
|
||||
}
|
||||
}
|
||||
|
||||
inner class RelayListener(
|
||||
val onConnected: () -> Unit,
|
||||
) : WebSocketListener {
|
||||
override fun onOpen(
|
||||
pingMillis: Long,
|
||||
compression: Boolean,
|
||||
) {
|
||||
Log.d("Relay", "Connect onOpen $url $socket")
|
||||
|
||||
markConnectionAsReady(pingMillis, compression)
|
||||
|
||||
// Log.w("Relay", "Relay OnOpen, Loading All subscriptions $url")
|
||||
onConnected()
|
||||
|
||||
listener.onRelayStateChange(this@SimpleClientRelay, RelayState.CONNECTED)
|
||||
}
|
||||
|
||||
override fun onMessage(text: String) {
|
||||
stats.addBytesReceived(text.bytesUsedInMemory())
|
||||
|
||||
try {
|
||||
processNewRelayMessage(text)
|
||||
} catch (e: Throwable) {
|
||||
if (e is CancellationException) throw e
|
||||
stats.newError("Error processing: $text")
|
||||
Log.e("Relay", "Error processing: $text")
|
||||
listener.onError(this@SimpleClientRelay, "", Error("Error processing $text"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClosing(
|
||||
code: Int,
|
||||
reason: String,
|
||||
) {
|
||||
Log.w("Relay", "Relay onClosing $url: $reason")
|
||||
|
||||
listener.onRelayStateChange(this@SimpleClientRelay, RelayState.DISCONNECTING)
|
||||
}
|
||||
|
||||
override fun onClosed(
|
||||
code: Int,
|
||||
reason: String,
|
||||
) {
|
||||
markConnectionAsClosed()
|
||||
|
||||
Log.w("Relay", "Relay onClosed $url: $reason")
|
||||
|
||||
listener.onRelayStateChange(this@SimpleClientRelay, RelayState.DISCONNECTED)
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
t: Throwable,
|
||||
response: String?,
|
||||
) {
|
||||
socket?.cancel() // 1000, "Normal close"
|
||||
|
||||
// checks if this is an actual failure. Closing the socket generates an onFailure as well.
|
||||
if (!(socket == null && (t.message == "Socket is closed" || t.message == "Socket closed"))) {
|
||||
stats.newError(response ?: t.message ?: "onFailure event from server: ${t.javaClass.simpleName}")
|
||||
}
|
||||
|
||||
// Failures disconnect the relay.
|
||||
markConnectionAsClosed()
|
||||
|
||||
Log.w("Relay", "Relay onFailure $url, $response $response ${t.message} $socket")
|
||||
t.printStackTrace()
|
||||
listener.onError(
|
||||
this@SimpleClientRelay,
|
||||
"",
|
||||
Error("WebSocket Failure. Response: $response. Exception: ${t.message}", t),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun markConnectionAsReady(
|
||||
pingInMs: Long,
|
||||
usingCompression: Boolean,
|
||||
) {
|
||||
this.resetEOSEStatuses()
|
||||
this.isReady = true
|
||||
this.usingCompression = usingCompression
|
||||
|
||||
stats.pingInMs = pingInMs
|
||||
}
|
||||
|
||||
fun markConnectionAsClosed() {
|
||||
this.socket = null
|
||||
this.isReady = false
|
||||
this.usingCompression = false
|
||||
this.resetEOSEStatuses()
|
||||
}
|
||||
|
||||
fun processNewRelayMessage(newMessage: String) {
|
||||
when (val msg = parser.parse(newMessage)) {
|
||||
is EventMessage -> {
|
||||
// Log.w("Relay", "Relay onEVENT $url $newMessage")
|
||||
listener.onEvent(this, msg.subId, msg.event, afterEOSEPerSubscription[msg.subId] == true)
|
||||
}
|
||||
is EoseMessage -> {
|
||||
// Log.w("Relay", "Relay onEOSE $url $newMessage")
|
||||
afterEOSEPerSubscription[msg.subId] = true
|
||||
listener.onEOSE(this@SimpleClientRelay, msg.subId)
|
||||
}
|
||||
is NoticeMessage -> {
|
||||
// Log.w("Relay", "Relay onNotice $url, $newMessage")
|
||||
stats.newNotice(msg.message)
|
||||
listener.onError(this@SimpleClientRelay, msg.message, Error("Relay sent notice: $msg.message"))
|
||||
}
|
||||
is OkMessage -> {
|
||||
Log.w("Relay", "Relay on OK $url, $newMessage")
|
||||
|
||||
// if this is the OK of an auth event, renew all subscriptions and resend all outgoing events.
|
||||
if (authResponseWatcher.containsKey(msg.eventId)) {
|
||||
val wasAlreadyAuthenticated = authResponseWatcher.get(msg.eventId)
|
||||
authResponseWatcher.put(msg.eventId, msg.success)
|
||||
if (wasAlreadyAuthenticated != true && msg.success) {
|
||||
sendEverything()
|
||||
}
|
||||
}
|
||||
|
||||
// remove from cache for any error that is not an auth required error.
|
||||
// for auth required, we will do the auth and try to send again.
|
||||
if (outboxCache.contains(msg.eventId) && !msg.message.startsWith("auth-required")) {
|
||||
synchronized(outboxCache) {
|
||||
outboxCache.remove(msg.eventId)
|
||||
}
|
||||
}
|
||||
|
||||
if (!msg.success) {
|
||||
stats.newNotice("Rejected event $msg.eventId: $msg.message")
|
||||
}
|
||||
|
||||
listener.onSendResponse(this@SimpleClientRelay, msg.eventId, msg.success, msg.message)
|
||||
}
|
||||
is AuthMessage -> {
|
||||
// Log.d("Relay", "Relay onAuth $url, $newMessage")
|
||||
listener.onAuth(this@SimpleClientRelay, msg.challenge)
|
||||
}
|
||||
is NotifyMessage -> {
|
||||
// Log.w("Relay", "Relay onNotify $url, $newMessage")
|
||||
listener.onNotify(this@SimpleClientRelay, msg.message)
|
||||
}
|
||||
is ClosedMessage -> {
|
||||
// Log.w("Relay", "Relay Closed Subscription $url, $newMessage")
|
||||
listener.onClosed(this@SimpleClientRelay, msg.subscriptionId, msg.message)
|
||||
}
|
||||
else -> {
|
||||
stats.newError("Unsupported message: $newMessage")
|
||||
Log.w("Relay", "Unsupported message: $newMessage")
|
||||
listener.onError(this, "", Error("Unsupported message: $newMessage"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun disconnect() {
|
||||
Log.d("Relay", "Relay.disconnect $url")
|
||||
lastConnectTentative = 0L // this is not an error, so prepare to reconnect as soon as requested.
|
||||
socket?.cancel()
|
||||
socket = null
|
||||
isReady = false
|
||||
usingCompression = false
|
||||
resetEOSEStatuses()
|
||||
}
|
||||
|
||||
fun resetEOSEStatuses() {
|
||||
afterEOSEPerSubscription = LinkedHashMap(afterEOSEPerSubscription.size)
|
||||
|
||||
authResponseWatcher.clear()
|
||||
authChallengesSent.clear()
|
||||
}
|
||||
|
||||
fun sendRequest(
|
||||
requestId: String,
|
||||
filters: List<Filter>,
|
||||
) {
|
||||
if (isConnectionStarted()) {
|
||||
if (isReady) {
|
||||
if (filters.isNotEmpty()) {
|
||||
writeToSocket(
|
||||
com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.ReqCmd
|
||||
.toJson(requestId, filters),
|
||||
)
|
||||
afterEOSEPerSubscription[requestId] = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// waits 60 seconds to reconnect after disconnected.
|
||||
if (TimeUtils.now() > lastConnectTentative + RECONNECTING_IN_SECONDS) {
|
||||
// sends all filters after connection is successful.
|
||||
connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun sendCount(
|
||||
requestId: String,
|
||||
filters: List<Filter>,
|
||||
) {
|
||||
if (isConnectionStarted()) {
|
||||
if (isReady) {
|
||||
if (filters.isNotEmpty()) {
|
||||
writeToSocket(CountCmd.toJson(requestId, filters))
|
||||
afterEOSEPerSubscription[requestId] = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// waits 60 seconds to reconnect after disconnected.
|
||||
if (TimeUtils.now() > lastConnectTentative + RECONNECTING_IN_SECONDS) {
|
||||
// sends all filters after connection is successful.
|
||||
connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun connectAndSendFiltersIfDisconnected() {
|
||||
if (socket == null) {
|
||||
// waits 60 seconds to reconnect after disconnected.
|
||||
if (TimeUtils.now() > lastConnectTentative + RECONNECTING_IN_SECONDS) {
|
||||
connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun renewSubscriptions() {
|
||||
// Force update all filters after AUTH.
|
||||
subs.allSubscriptions().forEach {
|
||||
sendRequest(requestId = it.id, it.filters)
|
||||
}
|
||||
}
|
||||
|
||||
fun send(signedEvent: Event) {
|
||||
listener.onBeforeSend(this@SimpleClientRelay, signedEvent)
|
||||
|
||||
if (signedEvent is RelayAuthEvent) {
|
||||
sendAuth(signedEvent)
|
||||
} else {
|
||||
sendEvent(signedEvent)
|
||||
}
|
||||
}
|
||||
|
||||
fun sendAuth(signedEvent: RelayAuthEvent) {
|
||||
val challenge = signedEvent.challenge() ?: ""
|
||||
|
||||
// only send replies to new challenges to avoid infinite loop:
|
||||
// 1. Auth is sent
|
||||
// 2. auth is rejected
|
||||
// 3. auth is requested
|
||||
// 4. auth is sent
|
||||
// ...
|
||||
if (!authChallengesSent.contains(challenge)) {
|
||||
authResponseWatcher[signedEvent.id] = false
|
||||
authChallengesSent.add(challenge)
|
||||
writeToSocket(AuthCmd.toJson(signedEvent))
|
||||
}
|
||||
}
|
||||
|
||||
fun sendEvent(signedEvent: Event) {
|
||||
synchronized(outboxCache) {
|
||||
outboxCache.put(signedEvent.id, signedEvent)
|
||||
}
|
||||
|
||||
if (isConnectionStarted()) {
|
||||
if (isReady) {
|
||||
writeToSocket(EventCmd.toJson(signedEvent))
|
||||
}
|
||||
} else {
|
||||
// automatically sends all filters after connection is successful.
|
||||
connect()
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeToSocket(str: String) {
|
||||
if (socket == null) {
|
||||
listener.onError(
|
||||
this@SimpleClientRelay,
|
||||
"",
|
||||
Error("Failed to send $str. Relay is not connected."),
|
||||
)
|
||||
}
|
||||
socket?.let {
|
||||
val result = it.send(str)
|
||||
listener.onSend(this@SimpleClientRelay, str, result)
|
||||
stats.addBytesSent(str.bytesUsedInMemory())
|
||||
|
||||
Log.d("Relay", "Relay send $url (${str.length} chars) $str")
|
||||
}
|
||||
}
|
||||
|
||||
fun close(subscriptionId: String) {
|
||||
writeToSocket(CloseCmd.toJson(subscriptionId))
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onEvent(
|
||||
relay: SimpleClientRelay,
|
||||
subscriptionId: String,
|
||||
event: Event,
|
||||
afterEOSE: Boolean,
|
||||
)
|
||||
|
||||
fun onEOSE(
|
||||
relay: SimpleClientRelay,
|
||||
subscriptionId: String,
|
||||
)
|
||||
|
||||
fun onError(
|
||||
relay: SimpleClientRelay,
|
||||
subscriptionId: String,
|
||||
error: Error,
|
||||
)
|
||||
|
||||
fun onAuth(
|
||||
relay: SimpleClientRelay,
|
||||
challenge: String,
|
||||
)
|
||||
|
||||
fun onRelayStateChange(
|
||||
relay: SimpleClientRelay,
|
||||
type: RelayState,
|
||||
)
|
||||
|
||||
fun onNotify(
|
||||
relay: SimpleClientRelay,
|
||||
description: String,
|
||||
)
|
||||
|
||||
fun onClosed(
|
||||
relay: SimpleClientRelay,
|
||||
subscriptionId: String,
|
||||
message: String,
|
||||
)
|
||||
|
||||
fun onBeforeSend(
|
||||
relay: SimpleClientRelay,
|
||||
event: Event,
|
||||
)
|
||||
|
||||
fun onSend(
|
||||
relay: SimpleClientRelay,
|
||||
msg: String,
|
||||
success: Boolean,
|
||||
)
|
||||
|
||||
fun onSendResponse(
|
||||
relay: SimpleClientRelay,
|
||||
eventId: String,
|
||||
success: Boolean,
|
||||
message: String,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.Filter
|
||||
import java.util.UUID
|
||||
|
||||
class Subscription(
|
||||
val id: String = UUID.randomUUID().toString().substring(0, 4),
|
||||
val filters: List<Filter>,
|
||||
)
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.Filter
|
||||
|
||||
interface SubscriptionCollection {
|
||||
fun isActive(subscriptionId: String): Boolean
|
||||
|
||||
fun getFilters(subscriptionId: String): List<Filter>
|
||||
|
||||
fun allSubscriptions(): List<Subscription>
|
||||
|
||||
fun match(
|
||||
subscriptionId: String,
|
||||
event: Event,
|
||||
): Boolean
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
|
||||
class AuthMessage(
|
||||
val challenge: String,
|
||||
) : Message {
|
||||
companion object {
|
||||
const val LABEL = "AUTH"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): AuthMessage =
|
||||
AuthMessage(
|
||||
msgArray.get(1).asText(),
|
||||
)
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
|
||||
class ClosedMessage(
|
||||
val subscriptionId: String,
|
||||
val message: String,
|
||||
) : Message {
|
||||
companion object {
|
||||
const val LABEL = "CLOSED"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): ClosedMessage =
|
||||
ClosedMessage(
|
||||
msgArray[1].asText(),
|
||||
msgArray[2].asText(),
|
||||
)
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
|
||||
class EoseMessage(
|
||||
val subId: String,
|
||||
) : Message {
|
||||
companion object {
|
||||
const val LABEL = "EOSE"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): EoseMessage =
|
||||
EoseMessage(
|
||||
msgArray.get(1).asText(),
|
||||
)
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
|
||||
class EventMessage(
|
||||
val subId: String,
|
||||
val event: Event,
|
||||
) : Message {
|
||||
companion object {
|
||||
const val LABEL = "EVENT"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): EventMessage =
|
||||
EventMessage(
|
||||
msgArray.get(1).asText(),
|
||||
EventMapper.fromJson(msgArray.get(2)),
|
||||
)
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
interface Message
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
|
||||
class NoticeMessage(
|
||||
val message: String,
|
||||
) : Message {
|
||||
companion object {
|
||||
const val LABEL = "NOTICE"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): NoticeMessage =
|
||||
NoticeMessage(
|
||||
msgArray.get(1).asText(),
|
||||
)
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
|
||||
class NotifyMessage(
|
||||
val message: String,
|
||||
) : Message {
|
||||
companion object {
|
||||
const val LABEL = "NOTIFY"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): NotifyMessage =
|
||||
NotifyMessage(
|
||||
msgArray.get(1).asText(),
|
||||
)
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.vitorpamplona.quartz.nip01Core.HexKey
|
||||
|
||||
class OkMessage(
|
||||
val eventId: HexKey,
|
||||
val success: Boolean,
|
||||
val message: String,
|
||||
) : Message {
|
||||
companion object {
|
||||
const val LABEL = "OK"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): OkMessage =
|
||||
OkMessage(
|
||||
msgArray[1].asText(),
|
||||
msgArray[2].asBoolean(),
|
||||
if (msgArray.size() > 2) msgArray[3].asText() else "",
|
||||
)
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toClient
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
|
||||
class ToClientParser {
|
||||
fun parse(newMessage: String): Message? {
|
||||
val msgArray = EventMapper.mapper.readTree(newMessage)
|
||||
val type = msgArray.get(0).asText()
|
||||
return when (type) {
|
||||
EventMessage.LABEL -> EventMessage.parse(msgArray)
|
||||
EoseMessage.LABEL -> EoseMessage.parse(msgArray)
|
||||
NoticeMessage.LABEL -> NoticeMessage.parse(msgArray)
|
||||
OkMessage.LABEL -> OkMessage.parse(msgArray)
|
||||
AuthMessage.LABEL -> AuthMessage.parse(msgArray)
|
||||
NotifyMessage.LABEL -> NotifyMessage.parse(msgArray)
|
||||
ClosedMessage.LABEL -> ClosedMessage.parse(msgArray)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||
|
||||
class AuthCmd(
|
||||
val event: RelayAuthEvent,
|
||||
) : Command {
|
||||
companion object {
|
||||
const val LABEL = "AUTH"
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(authEvent: RelayAuthEvent): String = """["AUTH",${authEvent.toJson()}]"""
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): AuthCmd =
|
||||
AuthCmd(
|
||||
EventMapper.fromJson(msgArray.get(1)) as RelayAuthEvent,
|
||||
)
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
|
||||
class CloseCmd(
|
||||
val subscriptionId: String,
|
||||
) : Command {
|
||||
companion object {
|
||||
const val LABEL = "CLOSE"
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(subscriptionId: String): String = """["CLOSE","$subscriptionId"]"""
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): CloseCmd =
|
||||
CloseCmd(
|
||||
msgArray.get(1).asText(),
|
||||
)
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay
|
||||
|
||||
interface Command
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.FilterDeserializer
|
||||
import com.vitorpamplona.quartz.utils.joinToStringLimited
|
||||
|
||||
class CountCmd(
|
||||
val subscriptionId: String,
|
||||
val filters: List<Filter>,
|
||||
) : Command {
|
||||
companion object {
|
||||
const val LABEL = "COUNT"
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(
|
||||
requestId: String,
|
||||
filters: List<Filter>,
|
||||
): String =
|
||||
filters.joinToStringLimited(
|
||||
separator = ",",
|
||||
limit = 19,
|
||||
prefix = """["COUNT","$requestId",""",
|
||||
postfix = "]",
|
||||
) {
|
||||
it.toJson()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): CountCmd {
|
||||
val filters = mutableListOf<Filter>()
|
||||
|
||||
for (i in 2 until msgArray.size()) {
|
||||
val json = EventMapper.mapper.readTree(msgArray.get(i).asText())
|
||||
if (json is ObjectNode) {
|
||||
filters.add(FilterDeserializer.fromJson(json))
|
||||
}
|
||||
}
|
||||
|
||||
return CountCmd(msgArray.get(1).asText(), filters)
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
|
||||
class EventCmd(
|
||||
val event: Event,
|
||||
) : Command {
|
||||
companion object {
|
||||
const val LABEL = "EVENT"
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(event: Event): String = """["EVENT",${event.toJson()}]"""
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): EventCmd =
|
||||
EventCmd(
|
||||
EventMapper.fromJson(msgArray.get(1)),
|
||||
)
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relays.filters.FilterDeserializer
|
||||
import com.vitorpamplona.quartz.utils.joinToStringLimited
|
||||
|
||||
class ReqCmd(
|
||||
val subscriptionId: String,
|
||||
val filters: List<Filter>,
|
||||
) : com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.Command {
|
||||
companion object {
|
||||
const val LABEL = "REQ"
|
||||
|
||||
@JvmStatic
|
||||
fun toJson(
|
||||
requestId: String,
|
||||
filters: List<Filter>,
|
||||
limit: Int = 19,
|
||||
): String =
|
||||
filters.joinToStringLimited(
|
||||
separator = ",",
|
||||
limit = limit,
|
||||
prefix = """["REQ","$requestId",""",
|
||||
postfix = "]",
|
||||
) {
|
||||
it.toJson()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun parse(msgArray: JsonNode): com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.ReqCmd {
|
||||
val filters = mutableListOf<Filter>()
|
||||
|
||||
for (i in 2 until msgArray.size()) {
|
||||
val json = EventMapper.mapper.readTree(msgArray.get(i).asText())
|
||||
if (json is ObjectNode) {
|
||||
filters.add(FilterDeserializer.fromJson(json))
|
||||
}
|
||||
}
|
||||
|
||||
return com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.ReqCmd(
|
||||
msgArray.get(1).asText(),
|
||||
filters,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper
|
||||
|
||||
class ToRelayParser {
|
||||
fun parse(newMessage: String): Command? {
|
||||
val msgArray = EventMapper.mapper.readTree(newMessage)
|
||||
val type = msgArray.get(0).asText()
|
||||
return when (type) {
|
||||
AuthCmd.LABEL -> AuthCmd.parse(msgArray)
|
||||
CloseCmd.LABEL -> CloseCmd.parse(msgArray)
|
||||
CountCmd.LABEL -> CountCmd.parse(msgArray)
|
||||
EventCmd.LABEL -> EventCmd.parse(msgArray)
|
||||
com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.ReqCmd.LABEL ->
|
||||
com.vitorpamplona.quartz.nip01Core.relays.commands.toRelay.ReqCmd
|
||||
.parse(msgArray)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.filters
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.filters
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.filters
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.filters
|
||||
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.sockets
|
||||
|
||||
interface WebSocket {
|
||||
fun connect()
|
||||
|
||||
fun cancel()
|
||||
|
||||
fun send(msg: String): Boolean
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.sockets
|
||||
|
||||
interface WebSocketListener {
|
||||
fun onOpen(
|
||||
pingMillis: Long,
|
||||
compression: Boolean,
|
||||
)
|
||||
|
||||
fun onMessage(text: String)
|
||||
|
||||
fun onClosing(
|
||||
code: Int,
|
||||
reason: String,
|
||||
)
|
||||
|
||||
fun onClosed(
|
||||
code: Int,
|
||||
reason: String,
|
||||
)
|
||||
|
||||
fun onFailure(
|
||||
t: Throwable,
|
||||
response: String?,
|
||||
)
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.sockets
|
||||
|
||||
interface WebsocketBuilder {
|
||||
fun build(
|
||||
url: String,
|
||||
out: WebSocketListener,
|
||||
): WebSocket
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.relays.sockets
|
||||
|
||||
interface WebsocketBuilderFactory {
|
||||
fun build(forceProxy: Boolean): WebsocketBuilder
|
||||
}
|
||||
Reference in New Issue
Block a user