diff --git a/DEVELOPER.md b/DEVELOPER.md index 77b3c3c8..12bc37ef 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -1140,7 +1140,7 @@ The following are the update records for the SRS Stack server. * FFmpeg: Restart if time and speed abnormal. v5.13.21 * Transcript: Fix panic bug for sync goroutines. [v5.13.21](https://github.com/ossrs/srs-stack/releases/tag/v5.13.21) * Support OpenAI organization for billing. v5.13.22 - * Room: Fix the empty room UI sort bug. [v5.13.23](https://github.com/ossrs/srs-stack/releases/tag/v5.13.23) + * Room: Fix the empty room UI sort and secret bug. [v5.13.23](https://github.com/ossrs/srs-stack/releases/tag/v5.13.23) * v5.12 * Refine local variable name conf to config. v5.12.1 * Add forced exit on timeout for program termination. v5.12.1 diff --git a/platform/live-room.go b/platform/live-room.go index 4f63dc9e..75d7e437 100644 --- a/platform/live-room.go +++ b/platform/live-room.go @@ -48,6 +48,12 @@ func handleLiveRoomService(ctx context.Context, handler *http.ServeMux) error { return errors.Wrapf(err, "hset %v %v %v", SRS_LIVE_ROOM, room.UUID, string(b)) } + // Note that we need to update the auth secret, because we do not use room uuid as stream name. + roomPublishAuthKey := GenerateRoomPublishKey(room.StreamName) + if err := rdb.HSet(ctx, SRS_AUTH_SECRET, roomPublishAuthKey, room.Secret).Err(); err != nil { + return errors.Wrapf(err, "hset %v %v %v", SRS_AUTH_SECRET, roomPublishAuthKey, room.Secret) + } + ohttp.WriteData(ctx, w, r, &room) logger.Tf(ctx, "srs live room create ok, title=%v, room=%v", title, room.String()) return nil @@ -124,6 +130,12 @@ func handleLiveRoomService(ctx context.Context, handler *http.ServeMux) error { return errors.Wrapf(err, "hset %v %v %v", SRS_LIVE_ROOM, room.UUID, string(b)) } + // Note that we need to update the auth secret, because we do not use room uuid as stream name. + roomPublishAuthKey := GenerateRoomPublishKey(room.StreamName) + if err := rdb.HSet(ctx, SRS_AUTH_SECRET, roomPublishAuthKey, room.Secret).Err(); err != nil { + return errors.Wrapf(err, "hset %v %v %v", SRS_AUTH_SECRET, roomPublishAuthKey, room.Secret) + } + // Limit the changing rate for AI Assistant. select { case <-ctx.Done(): @@ -185,12 +197,12 @@ func handleLiveRoomService(ctx context.Context, handler *http.ServeMux) error { logger.Tf(ctx, "Handle %v", ep) handler.HandleFunc(ep, func(w http.ResponseWriter, r *http.Request) { if err := func() error { - var token, rid string + var token, roomUUID string if err := ParseBody(ctx, r.Body, &struct { Token *string `json:"token"` RoomUUID *string `json:"uuid"` }{ - Token: &token, RoomUUID: &rid, + Token: &token, RoomUUID: &roomUUID, }); err != nil { return errors.Wrapf(err, "parse body") } @@ -200,18 +212,27 @@ func handleLiveRoomService(ctx context.Context, handler *http.ServeMux) error { return errors.Wrapf(err, "authenticate") } - if r0, err := rdb.HGet(ctx, SRS_LIVE_ROOM, rid).Result(); err != nil && err != redis.Nil { - return errors.Wrapf(err, "hget %v %v", SRS_LIVE_ROOM, rid) + var room SrsLiveRoom + if r0, err := rdb.HGet(ctx, SRS_LIVE_ROOM, roomUUID).Result(); err != nil && err != redis.Nil { + return errors.Wrapf(err, "hget %v %v", SRS_LIVE_ROOM, roomUUID) } else if r0 == "" { - return errors.Errorf("live room %v not exists", rid) + return errors.Errorf("live room %v not exists", roomUUID) + } else if err = json.Unmarshal([]byte(r0), &room); err != nil { + return errors.Wrapf(err, "unmarshal %v %v", roomUUID, r0) + } + + if err := rdb.HDel(ctx, SRS_LIVE_ROOM, roomUUID).Err(); err != nil && err != redis.Nil { + return errors.Wrapf(err, "hdel %v %v", SRS_LIVE_ROOM, roomUUID) } - if err := rdb.HDel(ctx, SRS_LIVE_ROOM, rid).Err(); err != nil && err != redis.Nil { - return errors.Wrapf(err, "hdel %v %v", SRS_LIVE_ROOM, rid) + // Note that we need to update the auth secret, because we do not use room uuid as stream name. + roomPublishAuthKey := GenerateRoomPublishKey(room.StreamName) + if err := rdb.HDel(ctx, SRS_AUTH_SECRET, roomPublishAuthKey).Err(); err != nil { + return errors.Wrapf(err, "hdel %v %v", SRS_AUTH_SECRET, roomPublishAuthKey) } ohttp.WriteData(ctx, w, r, nil) - logger.Tf(ctx, "srs remove room ok, uuid=%v", rid) + logger.Tf(ctx, "srs remove room ok, uuid=%v", roomUUID) return nil }(); err != nil { ohttp.WriteError(ctx, w, r, err) diff --git a/platform/srs-hooks.go b/platform/srs-hooks.go index c27c3dfe..7006a1ec 100644 --- a/platform/srs-hooks.go +++ b/platform/srs-hooks.go @@ -110,28 +110,19 @@ func handleHooksService(ctx context.Context, handler *http.ServeMux) error { } // Use live room secret to verify if stream name matches. - if r0, err := rdb.HGet(ctx, SRS_LIVE_ROOM, streamObj.Stream).Result(); (err == nil || err == redis.Nil) && r0 != "" { - var room SrsLiveRoom - if err = json.Unmarshal([]byte(r0), &room); err != nil { - return errors.Wrapf(err, "unmarshal %v %v", streamObj.Stream, r0) - } - - if !isSecretOK(room.Secret, streamObj.Stream, streamObj.Param) { - return errors.Errorf("invalid live room stream=%v, param=%v, action=%v", streamObj.Stream, streamObj.Param, action) - } - - verifiedBy = "LiveRoom" - } else { + roomPublishAuthKey := GenerateRoomPublishKey(streamObj.Stream) + publish, err := rdb.HGet(ctx, SRS_AUTH_SECRET, roomPublishAuthKey).Result() + verifiedBy = "room" + if publish == "" { // Use global publish secret to verify - publish, err := rdb.HGet(ctx, SRS_AUTH_SECRET, "pubSecret").Result() - if err != nil && err != redis.Nil { - return errors.Wrapf(err, "hget %v pubSecret", SRS_AUTH_SECRET) - } - if !isSecretOK(publish, streamObj.Stream, streamObj.Param) { - return errors.Errorf("invalid normal stream=%v, param=%v, action=%v", streamObj.Stream, streamObj.Param, action) - } - - verifiedBy = "NormalStream" + publish, err = rdb.HGet(ctx, SRS_AUTH_SECRET, "pubSecret").Result() + verifiedBy = "global" + } + if err != nil && err != redis.Nil { + return errors.Wrapf(err, "hget %v pubSecret", SRS_AUTH_SECRET) + } + if !isSecretOK(publish, streamObj.Stream, streamObj.Param) { + return errors.Errorf("invalid normal stream=%v, param=%v, action=%v", streamObj.Stream, streamObj.Param, action) } } diff --git a/platform/utils.go b/platform/utils.go index 51a29c2a..dac079b4 100644 --- a/platform/utils.go +++ b/platform/utils.go @@ -298,10 +298,11 @@ const ( SRS_CONTAINER_DISABLED = "SRS_CONTAINER_DISABLED" // For live stream and rooms. SRS_LIVE_ROOM = "SRS_LIVE_ROOM" + // About authentication. + SRS_AUTH_SECRET = "SRS_AUTH_SECRET" + SRS_SECRET_PUBLISH = "SRS_SECRET_PUBLISH" // For system settings. SRS_LOCALE = "SRS_LOCALE" - SRS_SECRET_PUBLISH = "SRS_SECRET_PUBLISH" - SRS_AUTH_SECRET = "SRS_AUTH_SECRET" SRS_FIRST_BOOT = "SRS_FIRST_BOOT" SRS_UPGRADING = "SRS_UPGRADING" SRS_UPGRADE_WINDOW = "SRS_UPGRADE_WINDOW" @@ -314,6 +315,11 @@ const ( SRS_SYS_LIMITS = "SRS_SYS_LIMITS" ) +// GenerateRoomPublishKey to build the redis hashset key from room stream name. +func GenerateRoomPublishKey(roomStreamName string) string { + return fmt.Sprintf("room-pub-%v", roomStreamName) +} + // Default limit to 5Mbps for virtual live streaming. const SrsSysLimitsVLive = 5 * 1000 diff --git a/test/liveroom_test.go b/test/liveroom_test.go index 7fea01b9..64ad9468 100644 --- a/test/liveroom_test.go +++ b/test/liveroom_test.go @@ -110,6 +110,8 @@ func TestMedia_WithStream_LiveRoomPublishStream(t *testing.T) { type LiveRoomCreateResult struct { // Live room UUID. UUID string `json:"uuid"` + // The stream name, should never use roomUUID because it's secret. + StreamName string `json:"stream"` // Live room title. Title string `json:"title"` // Live room secret. @@ -137,7 +139,7 @@ func TestMedia_WithStream_LiveRoomPublishStream(t *testing.T) { defer wg.Wait() // Start FFmpeg to publish stream. - streamID := liveRoom.UUID + streamID := liveRoom.StreamName streamURL := fmt.Sprintf("%v/live/%v?secret=%v", *endpointRTMP, streamID, liveRoom.Secret) ffmpeg := NewFFmpeg(func(v *ffmpegClient) { v.args = []string{ @@ -207,6 +209,8 @@ func TestMedia_WithStream_LiveRoomPublishInvalidStream(t *testing.T) { type LiveRoomCreateResult struct { // Live room UUID. UUID string `json:"uuid"` + // The stream name, should never use roomUUID because it's secret. + StreamName string `json:"stream"` // Live room title. Title string `json:"title"` // Live room secret. @@ -299,6 +303,8 @@ func TestMedia_WithStream_LiveRoomPublishInvalidSecret(t *testing.T) { type LiveRoomCreateResult struct { // Live room UUID. UUID string `json:"uuid"` + // The stream name, should never use roomUUID because it's secret. + StreamName string `json:"stream"` // Live room title. Title string `json:"title"` // Live room secret. @@ -327,7 +333,7 @@ func TestMedia_WithStream_LiveRoomPublishInvalidSecret(t *testing.T) { // Start FFmpeg to publish stream. // Use a invalid random stream ID, which should be failed. - streamID := liveRoom.UUID + streamID := liveRoom.StreamName streamURL := fmt.Sprintf("%v/live/%v?secret=%v", *endpointRTMP, streamID, uuid.NewString()) ffmpeg := NewFFmpeg(func(v *ffmpegClient) { v.args = []string{