@@ -8,17 +8,19 @@ import eu.rekawek.coffeegb.core.GameboyType
88import eu.rekawek.coffeegb.core.events.Event
99import eu.rekawek.coffeegb.core.events.EventBus
1010import eu.rekawek.coffeegb.core.joypad.Button
11- import org.slf4j.Logger
12- import org.slf4j.LoggerFactory
11+ import java.io.IOException
1312import java.io.InputStream
1413import java.io.OutputStream
1514import java.nio.ByteBuffer
1615import kotlin.concurrent.Volatile
16+ import org.slf4j.Logger
17+ import org.slf4j.LoggerFactory
1718
1819class Connection (
1920 private val inputStream : InputStream ,
2021 private val outputStream : OutputStream ,
2122 mainEventBus : EventBus ,
23+ private val server : Boolean ,
2224) : Runnable, AutoCloseable {
2325
2426 private val eventBus: EventBus = mainEventBus.fork(" connection" )
@@ -87,6 +89,7 @@ class Connection(
8789 }
8890
8991 override fun run () {
92+ handshake()
9093 while (! doStop) {
9194 val command = inputStream.read()
9295 if (command == - 1 ) {
@@ -190,6 +193,36 @@ class Connection(
190193 outputStream.close()
191194 }
192195
196+ private fun handshake () {
197+ val buf = ByteBuffer .allocate(PROTOCOL_NAME .length + 1 )
198+ if (server) {
199+ buf.put(PROTOCOL_NAME .toByteArray())
200+ buf.put(PROTOCOL_VERSION )
201+ outputStream.write(buf.array())
202+ LOG .atInfo().log(" Sent protocol name {} and version {}" , PROTOCOL_NAME , PROTOCOL_VERSION )
203+ } else {
204+ inputStream.read(buf.array())
205+ val receivedProtocolName = String (buf.array().take(PROTOCOL_NAME .length).toByteArray())
206+ if (receivedProtocolName != PROTOCOL_NAME ) {
207+ throw IOException (
208+ " Protocol mismatch: expected $PROTOCOL_NAME , received $receivedProtocolName "
209+ )
210+ }
211+ val receivedProtocolVersion = buf.array()[PROTOCOL_NAME .length]
212+ if (receivedProtocolVersion != PROTOCOL_VERSION ) {
213+ throw IOException (
214+ " Protocol mismatch: expected $PROTOCOL_VERSION , received $receivedProtocolVersion "
215+ )
216+ }
217+ LOG .atInfo()
218+ .log(
219+ " Received protocol name {} and version {}" ,
220+ receivedProtocolName,
221+ receivedProtocolVersion,
222+ )
223+ }
224+ }
225+
193226 data class PeerLoadedGameEvent (
194227 val rom : ByteArray ,
195228 val battery : ByteArray? ,
@@ -209,5 +242,7 @@ class Connection(
209242
210243 companion object {
211244 private val LOG : Logger = LoggerFactory .getLogger(Connection ::class .java)
245+ private const val PROTOCOL_NAME : String = " CoffeeGB NETPLAY"
246+ private const val PROTOCOL_VERSION : Byte = 0x01
212247 }
213248}
0 commit comments