145 lines
5.0 KiB
Kotlin
145 lines
5.0 KiB
Kotlin
/*
|
|
* Copyright 2023 dorkbox, llc
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package dorkbox.network.handshake
|
|
|
|
/**
|
|
* Internal message to handle the connection registration process
|
|
*/
|
|
internal class HandshakeMessage private constructor() {
|
|
|
|
// the public key is used to encrypt the data in the handshake
|
|
var publicKey: ByteArray? = null
|
|
|
|
|
|
// used to keep track and associate UDP/IPC handshakes between client/server
|
|
// The connection info (session ID, etc) necessary to make a connection to the server are encrypted with the clients public key.
|
|
// so EVEN IF you can guess someone's connectKey, you must also know their private key in order to connect as them.
|
|
var connectKey = 0L
|
|
|
|
// -1 means there is an error
|
|
var state = INVALID
|
|
|
|
// used to name a connection (via the client)
|
|
var tag: String = ""
|
|
|
|
var errorMessage: String? = null
|
|
|
|
var port = 0
|
|
var streamId = 0
|
|
var sessionId = 0
|
|
|
|
|
|
// the client sends its registration data to the server to make sure that the registered classes are the same between the client/server
|
|
var registrationData: ByteArray? = null
|
|
|
|
companion object {
|
|
const val INVALID = -2
|
|
const val RETRY = -1
|
|
const val HELLO = 0
|
|
const val HELLO_ACK = 1
|
|
const val HELLO_ACK_IPC = 2
|
|
const val DONE = 3
|
|
const val DONE_ACK = 4
|
|
|
|
fun helloFromClient(connectKey: Long, publicKey: ByteArray, streamIdSub: Int, portSub: Int, tagName: String): HandshakeMessage {
|
|
val hello = HandshakeMessage()
|
|
hello.state = HELLO
|
|
hello.connectKey = connectKey // this is 'bounced back' by the server, so the client knows if it's the correct connection message
|
|
hello.publicKey = publicKey
|
|
hello.sessionId = 0 // not used by the server, since it connects in a different way!
|
|
hello.streamId = streamIdSub
|
|
hello.port = portSub
|
|
hello.tag = tagName
|
|
return hello
|
|
}
|
|
|
|
fun helloAckToClient(connectKey: Long): HandshakeMessage {
|
|
val hello = HandshakeMessage()
|
|
hello.state = HELLO_ACK
|
|
hello.connectKey = connectKey // THIS MUST NEVER CHANGE! (the server/client expect this)
|
|
return hello
|
|
}
|
|
|
|
fun helloAckIpcToClient(connectKey: Long): HandshakeMessage {
|
|
val hello = HandshakeMessage()
|
|
hello.state = HELLO_ACK_IPC
|
|
hello.connectKey = connectKey // THIS MUST NEVER CHANGE! (the server/client expect this)
|
|
return hello
|
|
}
|
|
|
|
fun doneFromClient(connectKey: Long, sessionIdSub: Int, streamIdSub: Int): HandshakeMessage {
|
|
val hello = HandshakeMessage()
|
|
hello.state = DONE
|
|
hello.connectKey = connectKey // THIS MUST NEVER CHANGE! (the server/client expect this)
|
|
hello.sessionId = sessionIdSub
|
|
hello.streamId = streamIdSub
|
|
return hello
|
|
}
|
|
|
|
fun doneToClient(connectKey: Long): HandshakeMessage {
|
|
val hello = HandshakeMessage()
|
|
hello.state = DONE_ACK
|
|
hello.connectKey = connectKey // THIS MUST NEVER CHANGE! (the server/client expect this)
|
|
return hello
|
|
}
|
|
|
|
fun error(errorMessage: String): HandshakeMessage {
|
|
val error = HandshakeMessage()
|
|
error.state = INVALID
|
|
error.errorMessage = errorMessage
|
|
return error
|
|
}
|
|
|
|
fun retry(errorMessage: String): HandshakeMessage {
|
|
val error = HandshakeMessage()
|
|
error.state = RETRY
|
|
error.errorMessage = errorMessage
|
|
return error
|
|
}
|
|
|
|
fun toStateString(state: Int) : String {
|
|
return when(state) {
|
|
INVALID -> "INVALID"
|
|
RETRY -> "RETRY"
|
|
HELLO -> "HELLO"
|
|
HELLO_ACK -> "HELLO_ACK"
|
|
HELLO_ACK_IPC -> "HELLO_ACK_IPC"
|
|
DONE -> "DONE"
|
|
DONE_ACK -> "DONE_ACK"
|
|
else -> "ERROR. THIS SHOULD NEVER HAPPEN FOR STATE!"
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun toString(): String {
|
|
val stateStr = toStateString(state)
|
|
|
|
val errorMsg = if (errorMessage == null) {
|
|
""
|
|
} else {
|
|
", Error: $errorMessage"
|
|
}
|
|
|
|
val connectInfo = if (connectKey != 0L) {
|
|
", key=$connectKey"
|
|
} else {
|
|
""
|
|
}
|
|
|
|
return "HandshakeMessage($tag :: $stateStr$errorMsg sessionId=$sessionId, streamId=$streamId, port=$port${connectInfo})"
|
|
}
|
|
}
|