Implemented session id.

This commit is contained in:
Koen J 2024-11-22 19:02:07 +01:00
parent 196e55899e
commit f32498a444
4 changed files with 47 additions and 8 deletions

View file

@ -32,6 +32,7 @@ import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.*
import java.util.concurrent.ThreadLocalRandom
@ -232,4 +233,10 @@ fun String.decodeUnicode(): String {
i++
}
return sb.toString()
}
}
fun ByteBuffer.toUtf8String(): String {
val remainingBytes = ByteArray(remaining())
get(remainingBytes)
return String(remainingBytes, Charsets.UTF_8)
}

View file

@ -284,12 +284,16 @@ class StateSync {
return@SyncSocketSession
}
Logger.i(TAG, "Handshake complete with ${s.remotePublicKey}")
Logger.i(TAG, "Handshake complete with (LocalPublicKey = ${s.localPublicKey}, RemotePublicKey = ${s.remotePublicKey})")
synchronized(_sessions) {
session = _sessions[s.remotePublicKey]
if (session == null) {
session = SyncSession(remotePublicKey, onAuthorized = {
session = SyncSession(remotePublicKey, onAuthorized = { it, isNewlyAuthorized, isNewSession ->
if (!isNewSession) {
return@SyncSession
}
Logger.i(TAG, "${s.remotePublicKey} authorized")
synchronized(_lastAddressStorage) {
_lastAddressStorage.setAndSave(remotePublicKey, s.remoteAddress)
@ -358,6 +362,16 @@ class StateSync {
}
})
}
} else {
val publicKey = session!!.remotePublicKey
session!!.unauthorize(s)
session!!.close()
synchronized(_sessions) {
_sessions.remove(publicKey)
}
Logger.i(TAG, "Connection unauthorized for ${remotePublicKey} because not authorized and not on pairing activity to ask")
}
} else {
//Responder does not need to check because already approved

View file

@ -21,6 +21,7 @@ import com.futo.platformplayer.sync.models.SendToDevicePackage
import com.futo.platformplayer.sync.models.SyncPlaylistsPackage
import com.futo.platformplayer.sync.models.SyncSubscriptionGroupsPackage
import com.futo.platformplayer.sync.models.SyncSubscriptionsPackage
import com.futo.platformplayer.toUtf8String
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
@ -30,6 +31,7 @@ import java.nio.ByteBuffer
import java.time.Instant
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.util.UUID
interface IAuthorizable {
val isAuthorized: Boolean
@ -39,13 +41,16 @@ class SyncSession : IAuthorizable {
private val _socketSessions: MutableList<SyncSocketSession> = mutableListOf()
private var _authorized: Boolean = false
private var _remoteAuthorized: Boolean = false
private val _onAuthorized: (session: SyncSession) -> Unit
private val _onAuthorized: (session: SyncSession, isNewlyAuthorized: Boolean, isNewSession: Boolean) -> Unit
private val _onUnauthorized: (session: SyncSession) -> Unit
private val _onClose: (session: SyncSession) -> Unit
private val _onConnectedChanged: (session: SyncSession, connected: Boolean) -> Unit
val remotePublicKey: String
override val isAuthorized get() = _authorized && _remoteAuthorized
private var _wasAuthorized = false
private val _id = UUID.randomUUID()
private var _remoteId: UUID? = null
private var _lastAuthorizedRemoteId: UUID? = null
var connected: Boolean = false
private set(v) {
@ -55,7 +60,7 @@ class SyncSession : IAuthorizable {
}
}
constructor(remotePublicKey: String, onAuthorized: (session: SyncSession) -> Unit, onUnauthorized: (session: SyncSession) -> Unit, onConnectedChanged: (session: SyncSession, connected: Boolean) -> Unit, onClose: (session: SyncSession) -> Unit) {
constructor(remotePublicKey: String, onAuthorized: (session: SyncSession, isNewlyAuthorized: Boolean, isNewSession: Boolean) -> Unit, onUnauthorized: (session: SyncSession) -> Unit, onConnectedChanged: (session: SyncSession, connected: Boolean) -> Unit, onClose: (session: SyncSession) -> Unit) {
this.remotePublicKey = remotePublicKey
_onAuthorized = onAuthorized
_onUnauthorized = onUnauthorized
@ -77,7 +82,8 @@ class SyncSession : IAuthorizable {
}
fun authorize(socketSession: SyncSocketSession) {
socketSession.send(Opcode.NOTIFY_AUTHORIZED.value)
Logger.i(TAG, "Sent AUTHORIZED with session id $_id")
socketSession.send(Opcode.NOTIFY_AUTHORIZED.value, 0u, ByteBuffer.wrap(_id.toString().toByteArray()))
_authorized = true
checkAuthorized()
}
@ -95,9 +101,13 @@ class SyncSession : IAuthorizable {
}
private fun checkAuthorized() {
if (!_wasAuthorized && isAuthorized) {
if (isAuthorized) {
val isNewlyAuthorized = !_wasAuthorized;
val isNewSession = _lastAuthorizedRemoteId != _remoteId;
Logger.i(TAG, "onAuthorized (isNewlyAuthorized = $isNewlyAuthorized, isNewSession = $isNewSession)");
_onAuthorized.invoke(this, !_wasAuthorized, _lastAuthorizedRemoteId != _remoteId)
_wasAuthorized = true
_onAuthorized.invoke(this)
_lastAuthorizedRemoteId = _remoteId
}
}
@ -126,12 +136,19 @@ class SyncSession : IAuthorizable {
when (opcode) {
Opcode.NOTIFY_AUTHORIZED.value -> {
val str = data.toUtf8String()
_remoteId = if (data.remaining() >= 0) UUID.fromString(str) else UUID.fromString("00000000-0000-0000-0000-000000000000")
_remoteAuthorized = true
Logger.i(TAG, "Received AUTHORIZED with session id $_remoteId")
checkAuthorized()
return
}
Opcode.NOTIFY_UNAUTHORIZED.value -> {
_remoteId = null
_lastAuthorizedRemoteId = null
_remoteAuthorized = false
_onUnauthorized(this)
return
}
//TODO: Handle any kind of packet (that is not necessarily authorized)
}

View file

@ -10,6 +10,7 @@ import com.futo.platformplayer.noise.protocol.HandshakeState
import com.futo.platformplayer.states.StateSync
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.UUID
class SyncSocketSession {
enum class Opcode(val value: UByte) {