diff --git a/api_signaling.go b/api_signaling.go index 98523f3..734e9ec 100644 --- a/api_signaling.go +++ b/api_signaling.go @@ -32,6 +32,7 @@ import ( "time" "github.com/golang-jwt/jwt/v4" + "github.com/pion/sdp/v3" ) const ( @@ -563,12 +564,33 @@ type MessageClientMessageData struct { RoomType string `json:"roomType"` Bitrate int `json:"bitrate,omitempty"` Payload map[string]interface{} `json:"payload"` + + offerSdp *sdp.SessionDescription // Only set if Type == "offer" } func (m *MessageClientMessageData) CheckValid() error { if !IsValidStreamType(m.RoomType) { return fmt.Errorf("invalid room type: %s", m.RoomType) } + if m.Type == "offer" { + sdpValue, found := m.Payload["sdp"] + if !found { + return NewError("no_offer_sdp", "Offer does not contain a SDP.") + } + sdpText, ok := sdpValue.(string) + if !ok { + return NewError("invalid_offer_sdp", "Offer does not contain a valid SDP.") + } + + var sdp sdp.SessionDescription + if err := sdp.Unmarshal([]byte(sdpText)); err != nil { + return NewErrorDetail("invalid_offer_sdp", "Error parsing offer SDP.", map[string]interface{}{ + "error": err.Error(), + }) + } + + m.offerSdp = &sdp + } return nil } diff --git a/clientsession.go b/clientsession.go index 53e8e55..4e96b2c 100644 --- a/clientsession.go +++ b/clientsession.go @@ -740,23 +740,6 @@ func (s *ClientSession) SubscriberClosed(subscriber McuSubscriber) { } } -type SdpError struct { - message string -} - -func (e *SdpError) Error() string { - return e.message -} - -type WrappedSdpError struct { - SdpError - err error -} - -func (e *WrappedSdpError) Unwrap() error { - return e.err -} - type PermissionError struct { permission Permission } @@ -769,23 +752,10 @@ func (e *PermissionError) Error() string { return fmt.Sprintf("permission \"%s\" not found", e.permission) } -func (s *ClientSession) isSdpAllowedToSendLocked(payload map[string]interface{}) (MediaType, error) { - sdpValue, found := payload["sdp"] - if !found { - return 0, &SdpError{"payload does not contain a sdp"} - } - sdpText, ok := sdpValue.(string) - if !ok { - return 0, &SdpError{"payload does not contain a valid sdp"} - } - var sdp sdp.SessionDescription - if err := sdp.Unmarshal([]byte(sdpText)); err != nil { - return 0, &WrappedSdpError{ - SdpError: SdpError{ - message: fmt.Sprintf("could not parse sdp: %s", err), - }, - err: err, - } +func (s *ClientSession) isSdpAllowedToSendLocked(sdp *sdp.SessionDescription) (MediaType, error) { + if sdp == nil { + // Should have already been checked when data was validated. + return 0, fmt.Errorf("no offer sdp provided") } var mediaTypes MediaType @@ -823,8 +793,8 @@ func (s *ClientSession) IsAllowedToSend(data *MessageClientMessageData) error { // Client is allowed to publish any media (audio / video). return nil } else if data != nil && data.Type == "offer" { - // Parse SDP to check what user is trying to publish and check permissions accordingly. - if _, err := s.isSdpAllowedToSendLocked(data.Payload); err != nil { + // Check what user is trying to publish and check permissions accordingly. + if _, err := s.isSdpAllowedToSendLocked(data.offerSdp); err != nil { return err } @@ -854,7 +824,7 @@ func (s *ClientSession) checkOfferTypeLocked(streamType StreamType, data *Messag return MediaTypeScreen, nil } else if data != nil && data.Type == "offer" { - mediaTypes, err := s.isSdpAllowedToSendLocked(data.Payload) + mediaTypes, err := s.isSdpAllowedToSendLocked(data.offerSdp) if err != nil { return 0, err } diff --git a/hub.go b/hub.go index 301ac08..dc098e2 100644 --- a/hub.go +++ b/hub.go @@ -2178,11 +2178,6 @@ func (h *Hub) processMcuMessage(session *ClientSession, client_message *ClientMe sendNotAllowed(session, client_message, "Not allowed to publish.") return } - if err, ok := err.(*SdpError); ok { - log.Printf("Session %s sent unsupported offer %s, ignoring (%s)", session.PublicId(), data.RoomType, err) - sendNotAllowed(session, client_message, "Not allowed to publish.") - return - } case "selectStream": if session.PublicId() == message.Recipient.SessionId { log.Printf("Not selecting substream for own %s stream in session %s", data.RoomType, session.PublicId()) diff --git a/proxy/proxy_server.go b/proxy/proxy_server.go index 6978c0e..df2505b 100644 --- a/proxy/proxy_server.go +++ b/proxy/proxy_server.go @@ -777,9 +777,10 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s fallthrough case "candidate": mcuData = &signaling.MessageClientMessageData{ - Type: payload.Type, - Sid: payload.Sid, - Payload: payload.Payload, + RoomType: string(mcuClient.StreamType()), + Type: payload.Type, + Sid: payload.Sid, + Payload: payload.Payload, } case "endOfCandidates": // Ignore but confirm, not passed along to Janus anyway. @@ -796,14 +797,21 @@ func (s *ProxyServer) processPayload(ctx context.Context, client *ProxyClient, s fallthrough case "sendoffer": mcuData = &signaling.MessageClientMessageData{ - Type: payload.Type, - Sid: payload.Sid, + RoomType: string(mcuClient.StreamType()), + Type: payload.Type, + Sid: payload.Sid, } default: session.sendMessage(message.NewErrorServerMessage(UnsupportedPayload)) return } + if err := mcuData.CheckValid(); err != nil { + log.Printf("Received invalid payload %+v for %s client %s: %s", mcuData, mcuClient.StreamType(), payload.ClientId, err) + session.sendMessage(message.NewErrorServerMessage(UnsupportedPayload)) + return + } + mcuClient.SendMessage(ctx, nil, mcuData, func(err error, response map[string]interface{}) { var responseMsg *signaling.ProxyServerMessage if err != nil {