Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.back.global.websocket.dto.WebSocketSessionInfo;
import com.back.global.websocket.service.WebSocketSessionManager;
import com.back.global.websocket.util.WebSocketAuthHelper;
import com.back.global.websocket.webrtc.dto.WebRTCErrorResponse;
import com.back.global.websocket.webrtc.dto.media.WebRTCMediaStateResponse;
import com.back.global.websocket.webrtc.dto.media.WebRTCMediaToggleRequest;
import com.back.global.websocket.webrtc.dto.signal.*;
Expand All @@ -16,7 +17,6 @@
import org.springframework.messaging.handler.annotation.MessageExceptionHandler;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
Expand All @@ -35,13 +35,10 @@ public class WebRTCSignalingController {

// WebRTC Offer 메시지 처리
@MessageMapping("/webrtc/offer")
public void handleOffer(@Validated @Payload WebRTCOfferRequest request,
SimpMessageHeaderAccessor headerAccessor,
Principal principal) {
public void handleOffer(@Validated @Payload WebRTCOfferRequest request, Principal principal) {
CustomUserDetails userDetails = WebSocketAuthHelper.extractUserDetails(principal);
if (userDetails == null) {
errorHelper.sendUnauthorizedError(headerAccessor.getSessionId());
return;
throw new CustomException(ErrorCode.UNAUTHORIZED);
}

Long fromUserId = userDetails.getUserId();
Expand All @@ -66,13 +63,10 @@ public void handleOffer(@Validated @Payload WebRTCOfferRequest request,

// WebRTC Answer 메시지 처리
@MessageMapping("/webrtc/answer")
public void handleAnswer(@Validated @Payload WebRTCAnswerRequest request,
SimpMessageHeaderAccessor headerAccessor,
Principal principal) {
public void handleAnswer(@Validated @Payload WebRTCAnswerRequest request, Principal principal) {
CustomUserDetails userDetails = WebSocketAuthHelper.extractUserDetails(principal);
if (userDetails == null) {
errorHelper.sendUnauthorizedError(headerAccessor.getSessionId());
return;
throw new CustomException(ErrorCode.UNAUTHORIZED);
}

Long fromUserId = userDetails.getUserId();
Expand All @@ -97,13 +91,10 @@ public void handleAnswer(@Validated @Payload WebRTCAnswerRequest request,

// ICE Candidate 메시지 처리
@MessageMapping("/webrtc/ice-candidate")
public void handleIceCandidate(@Validated @Payload WebRTCIceCandidateRequest request,
SimpMessageHeaderAccessor headerAccessor,
Principal principal) {
public void handleIceCandidate(@Validated @Payload WebRTCIceCandidateRequest request, Principal principal) {
CustomUserDetails userDetails = WebSocketAuthHelper.extractUserDetails(principal);
if (userDetails == null) {
errorHelper.sendUnauthorizedError(headerAccessor.getSessionId());
return;
throw new CustomException(ErrorCode.UNAUTHORIZED);
}

Long fromUserId = userDetails.getUserId();
Expand All @@ -127,13 +118,10 @@ public void handleIceCandidate(@Validated @Payload WebRTCIceCandidateRequest req

// 미디어 상태 토글 처리 (방 전체에 상태 공유)
@MessageMapping("/webrtc/media/toggle")
public void handleMediaToggle(@Validated @Payload WebRTCMediaToggleRequest request,
SimpMessageHeaderAccessor headerAccessor,
Principal principal) {
public void handleMediaToggle(@Validated @Payload WebRTCMediaToggleRequest request, Principal principal) {
CustomUserDetails userDetails = WebSocketAuthHelper.extractUserDetails(principal);
if (userDetails == null) {
errorHelper.sendUnauthorizedError(headerAccessor.getSessionId());
return;
throw new CustomException(ErrorCode.UNAUTHORIZED);
}

Long userId = userDetails.getUserId();
Expand All @@ -150,15 +138,41 @@ public void handleMediaToggle(@Validated @Payload WebRTCMediaToggleRequest reque

// WebRTC 시그널링 처리 중 발생하는 CustomException 처리
@MessageExceptionHandler(CustomException.class)
public void handleCustomException(CustomException e, SimpMessageHeaderAccessor headerAccessor) {
log.warn("WebRTC 시그널링 오류 발생: {}", e.getMessage());
errorHelper.sendCustomExceptionToUser(headerAccessor.getSessionId(), e);
public void handleCustomException(CustomException e, Principal principal) {
if (principal == null) {
log.warn("인증 정보 없는 사용자의 WebRTC 오류: {}", e.getMessage());
return;
}

log.warn("WebRTC 시그널링 오류 발생 (to {}): {}", principal.getName(), e.getMessage());

WebRTCErrorResponse errorResponse = WebRTCErrorResponse.from(e);

messagingTemplate.convertAndSendToUser(
principal.getName(), // 에러를 발생시킨 사람의 username
"/queue/webrtc",
errorResponse
);
}

// 예상치 못한 모든 Exception 처리
@MessageExceptionHandler(Exception.class)
public void handleGeneralException(Exception e, SimpMessageHeaderAccessor headerAccessor) {
log.error("WebRTC 시그널링 처리 중 예상치 못한 오류 발생", e);
errorHelper.sendGenericErrorToUser(headerAccessor.getSessionId(), e, "시그널링 처리 중 오류가 발생했습니다.");
public void handleGeneralException(Exception e, Principal principal) { // headerAccessor -> Principal
if (principal == null) {
log.error("WebRTC 처리 중 인증 정보 없는 사용자의 예외 발생", e);
return;
}

log.error("WebRTC 시그널링 처리 중 예상치 못한 오류 발생 (to {})", principal.getName(), e);

// CustomException으로 감싸서 일관된 형식의 에러 DTO를 생성
CustomException customException = new CustomException(ErrorCode.WS_INTERNAL_ERROR);
WebRTCErrorResponse errorResponse = WebRTCErrorResponse.from(customException);

messagingTemplate.convertAndSendToUser(
principal.getName(),
"/queue/webrtc",
errorResponse
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.back.global.websocket.webrtc.dto;

import com.back.global.exception.CustomException;
import java.time.LocalDateTime;

public record WebRTCErrorResponse(
String type,
ErrorPayload error,
LocalDateTime timestamp
) {
public record ErrorPayload(String code, String message) {}

public static WebRTCErrorResponse from(CustomException e) {
return new WebRTCErrorResponse(
"ERROR",
new ErrorPayload(e.getErrorCode().getCode(), e.getMessage()),
LocalDateTime.now()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.back.global.websocket.webrtc.dto.signal;

public record SdpData(String type, String sdp) {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public record WebRTCAnswerRequest(
@NotNull Long roomId,
@NotNull Long targetUserId,
@NotNull String sdp,
@NotNull SdpData sdp,
@NotNull WebRTCMediaType mediaType
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public record WebRTCOfferRequest(
@NotNull Long roomId,
@NotNull Long targetUserId,
@NotNull String sdp,
@NotNull SdpData sdp,
@NotNull WebRTCMediaType mediaType
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public record WebRTCSignalResponse(
Long fromUserId,
Long targetUserId,
Long roomId,
String sdp,
SdpData sdp,
WebRTCMediaType mediaType,
String candidate,
String sdpMid,
Expand All @@ -23,7 +23,7 @@ public static WebRTCSignalResponse offerOrAnswer(
Long fromUserId,
Long targetUserId,
Long roomId,
String sdp,
SdpData sdp,
WebRTCMediaType mediaType
) {
return new WebRTCSignalResponse(
Expand Down
Loading