Skip to content

Commit

Permalink
Feature/parse token (#198)
Browse files Browse the repository at this point in the history
* refactor: socket io

* feature: parse token
  • Loading branch information
kuoche1712003 committed Feb 4, 2024
1 parent 02a647d commit 77d9dea
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 126 deletions.
21 changes: 0 additions & 21 deletions domain/src/main/kotlin/tw/waterballsa/gaas/events/SocketioEvent.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
package tw.waterballsa.gaas.spring.configs.socketio

import com.corundumstudio.socketio.AuthorizationListener
import com.corundumstudio.socketio.SocketIOServer
import com.corundumstudio.socketio.listener.DefaultExceptionListener
import com.corundumstudio.socketio.annotation.SpringAnnotationScanner
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.cors.CorsConfiguration
import org.springframework.web.cors.reactive.CorsWebFilter
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource


@Configuration
@EnableConfigurationProperties(SocketIOProperties::class)
class SocketIOConfig{

@Bean
fun socketIOServer(socketIOProperties: SocketIOProperties): SocketIOServer {
val configuration = com.corundumstudio.socketio.Configuration()
.apply {
with(socketIOProperties){
hostname = socketHost
port = socketPort
allowHeaders = "Authorization, CustomHeaderName"
}
fun socketIOServer(
socketIOProperties: SocketIOProperties,
): SocketIOServer {
val configuration = com.corundumstudio.socketio.Configuration().apply {
with(socketIOProperties) {
hostname = socketHost
port = socketPort
allowHeaders = "Authorization, CustomHeaderName"
}
}


return SocketIOServer(configuration)
}

@Bean
fun springAnnotationScanner(socketIOServer: SocketIOServer): SpringAnnotationScanner {
return SpringAnnotationScanner(socketIOServer)
}
}
Original file line number Diff line number Diff line change
@@ -1,100 +1,95 @@
package tw.waterballsa.gaas.spring.configs.socketio

import com.corundumstudio.socketio.AckRequest
import com.corundumstudio.socketio.SocketIOClient
import com.corundumstudio.socketio.SocketIOServer
import io.netty.handler.codec.http.HttpHeaderNames
import com.corundumstudio.socketio.annotation.OnConnect
import com.corundumstudio.socketio.annotation.OnDisconnect
import com.corundumstudio.socketio.annotation.OnEvent
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.security.oauth2.jwt.Jwt
import org.springframework.security.oauth2.jwt.JwtDecoder
import org.springframework.stereotype.Component
import tw.waterballsa.gaas.application.eventbus.EventBus
import tw.waterballsa.gaas.application.repositories.RoomRepository
import tw.waterballsa.gaas.application.repositories.UserRepository
import tw.waterballsa.gaas.events.ChatData
import tw.waterballsa.gaas.events.SocketioEvent
import tw.waterballsa.gaas.events.enums.EventMessageType
import tw.waterballsa.gaas.spring.configs.socketio.event.SocketIOChatEvent
import tw.waterballsa.gaas.spring.configs.socketio.event.SocketIORoomEvent
import java.time.Instant


@Component
class SocketIOEventHandler(
private val socketIOServer: SocketIOServer,
private val eventBus: EventBus,
protected val roomRepository: RoomRepository,
private val jwtDecoder: JwtDecoder,
protected val userRepository: UserRepository,
) {

private val logger: Logger = LoggerFactory.getLogger(SocketIOEventHandler::class.java)


init {
configureEventHandlers()
companion object{
private const val USER_PREFIX = "USER_"
}


private final fun configureEventHandlers() {

socketIOServer.addConnectListener { client ->
val token = client.handshakeData.httpHeaders.get(HttpHeaderNames.COOKIE)
val customHeader = client.handshakeData.getSingleUrlParam("Authorization")

if (client != null ) {
logger.info("有新用戶連結 , SessionId: {}", client.sessionId)
val board = socketIOServer.broadcastOperations
logger.info("board clientId {}", board.clients)
}
}

socketIOServer.addEventListener(EventMessageType.GAME_STARTED.eventName, SocketioEvent::class.java)
{ client: SocketIOClient, socketioEvent: SocketioEvent, _ ->

logger.info(" ... " )
client.sendEvent(EventMessageType.GAME_STARTED.eventName, socketioEvent.data)

}





socketIOServer.addEventListener(SocketIOEventName.CHAT_MESSAGE.eventName, SocketioEvent::class.java)
{ client: SocketIOClient, socketioEvent: SocketioEvent, _ ->
// Handle the "chatMessage" event
logger.info(" CHAT_MESSAGE Received message: $socketioEvent from client: ${client.sessionId}")
client.handshakeData.getSingleUrlParam("")
// ECHO
client.sendEvent(SocketIOEventName.CHAT_MESSAGE.eventName, socketioEvent.data)
private val logger: Logger = LoggerFactory.getLogger(SocketIOEventHandler::class.java)

socketIOServer.broadcastOperations.sendEvent("test", socketioEvent.data)
@OnConnect
fun onConnect(client: SocketIOClient){
val userId = client.handshakeData.getSingleUrlParam("token")
?.toJwt()?.subject
?.let { userRepository.findByIdentity(it) }
?.id?.value

if(userId == null){
client.disconnect()
}else{
client.joinRoom("$USER_PREFIX$userId")
logger.info("user connect, SessionId: {}, UserId: {}", client.sessionId, userId)
}
}

socketIOServer.addEventListener(SocketIOEventName.JOIN_ROOM.eventName, ChatData::class.java) {
client: SocketIOClient, socketioEvent: ChatData, _ ->
@OnDisconnect
fun onDisconnect(client: SocketIOClient){
val userId = client.userId()
client.disconnect()
logger.info("user disconnect, SessionId: {}, UserId: {}", client.sessionId, userId)
}

client.joinRoom(socketioEvent.target)
logger.info("Client joined room: ${socketioEvent.target}")
logger.info("id = " + socketioEvent.user.id + " nickname " + socketioEvent.user.nickname + " targetRoom " + socketioEvent.target)
logger.info(" room size is : ${client.getCurrentRoomSize(socketioEvent.target)}")
}
@OnEvent(value = SocketIOEventName.JOIN_ROOM)
fun onJoinRoom(client: SocketIOClient, event: SocketIORoomEvent, ackRequest: AckRequest){
val userId = client.userId()
client.joinRoom(event.target)
logger.info("user join room, SessionId: {}, UserId: {}, RoomId: {}", client.sessionId, userId, event.target)
}

@OnEvent(value = SocketIOEventName.LEAVE_ROOM)
fun onLeaveRoom(client: SocketIOClient, event: SocketIORoomEvent, ackRequest: AckRequest){
val userId = client.userId()
client.leaveRoom(event.target)
logger.info("user leave room, SessionId: {}, UserId: {}, RoomId: {}", client.sessionId, userId, event.target)
}

socketIOServer.addEventListener(SocketIOEventName.LEAVE_ROOM.eventName, ChatData::class.java) {
client: SocketIOClient, socketioEvent: ChatData, _ ->
// ECHO
logger.info(" LEAVE_ROOM Received message: ${socketioEvent.target} from client: ${client.sessionId}")
client.leaveRoom(socketioEvent.target)
@OnEvent(value = SocketIOEventName.CHAT_MESSAGE)
fun onChatMessage(client: SocketIOClient, event: SocketIOChatEvent, ackRequest: AckRequest){
val userId = client.userId()
event.timestamp = Instant.now().toString()
val room = if(event.isLobby()){
socketIOServer.broadcastOperations
}else{
socketIOServer.getRoomOperations(event.target)
}
room.sendEvent(SocketIOEventName.CHAT_MESSAGE, event)
logger.info("user chat, SessionId: {}, UserId: {}, To: {}", client.sessionId, userId, event.target)
}


socketIOServer.addEventListener(SocketIOEventName.DISCONNECT.eventName, SocketioEvent::class.java) {
client: SocketIOClient, _: SocketioEvent, _ ->

client.disconnect()
logger.info(" client is leaven room with key disconnect")
}

socketIOServer.addDisconnectListener {
private fun SocketIOClient.userId(): String?{
return allRooms.firstOrNull { it.startsWith(USER_PREFIX) }
?.substringAfter(USER_PREFIX)
}

logger.info("Server disconnected on the server side")
private fun String.toJwt(): Jwt? {
return try {
jwtDecoder.decode(this)
} catch (e: Exception) {
null
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package tw.waterballsa.gaas.spring.configs.socketio

enum class SocketIOEventName (val eventName: String){
CHAT_MESSAGE("CHAT_MESSAGE"),
CHATROOM_JOIN("CHATROOM_JOIN"),
JOIN_ROOM("JOIN_ROOM"),
LEAVE_ROOM("LEAVE_ROOM"),
CONNECT_EVENT("CONNECT_EVENT"),
DISCONNECT("DISCONNECT");
object SocketIOEventName{
const val CHAT_MESSAGE = "CHAT_MESSAGE"
const val JOIN_ROOM = "JOIN_ROOM"
const val LEAVE_ROOM = "LEAVE_ROOM"
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tw.waterballsa.gaas.spring.configs.socketio.event


data class SocketIOChatEvent(
val from: SocketIOUser = SocketIOUser("", ""),
val content: String = "",
val target: String = "",
var timestamp: String? = null,
){
fun isLobby() = target == "LOBBY"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tw.waterballsa.gaas.spring.configs.socketio.event

data class SocketIORoomEvent(
val target: String = "",
val user: SocketIOUser = SocketIOUser("", ""),
)

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package tw.waterballsa.gaas.spring.configs.socketio.event

data class SocketIOUser(
val id: String = "",
val nickname: String = "",
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import org.springframework.stereotype.Component
import tw.waterballsa.gaas.application.eventbus.EventBus
import tw.waterballsa.gaas.events.DomainEvent
import tw.waterballsa.gaas.events.RoomEvent
import tw.waterballsa.gaas.spring.controllers.viewmodel.SocketioViewModel
import kotlin.reflect.safeCast

@Component
Expand All @@ -17,7 +16,6 @@ class WebSocketEventBus(

private val logger: Logger = LoggerFactory.getLogger(WebSocketEventBus::class.java)

lateinit var viewModel: SocketioViewModel
override fun broadcast(events: Collection<DomainEvent>) {
events.asSequence()
.mapNotNull { RoomEvent::class.safeCast(it) }
Expand Down

0 comments on commit 77d9dea

Please sign in to comment.