Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/parse token #198

Merged
merged 2 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading