diff --git a/cmd/server.go b/cmd/server.go index 66ed26a..9cee664 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -43,41 +43,50 @@ var ServerCmd = &cobra.Command{ } func Server(cmd *cobra.Command, args []string) { - tcpServerAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", conf.Conf.Server.Listen, conf.Conf.Server.Port)) + tcpServerHttpAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", conf.Conf.Server.Http.Listen, conf.Conf.Server.Http.Port)) if err != nil { log.Panic(err) } - udpServerAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", conf.Conf.Server.Listen, conf.Conf.Server.Port)) + udpServerHttpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", conf.Conf.Server.Http.Listen, conf.Conf.Server.Http.Port)) if err != nil { log.Panic(err) } - serverListener, err := net.ListenTCP("tcp", tcpServerAddr) + serverHttpListener, err := net.ListenTCP("tcp", tcpServerHttpAddr) if err != nil { log.Panic(err) } + + if conf.Conf.Server.Rtmp.Listen == "" { + conf.Conf.Server.Rtmp.Listen = conf.Conf.Server.Http.Listen + } + if conf.Conf.Server.Rtmp.Port == 0 { + conf.Conf.Server.Rtmp.Port = conf.Conf.Server.Http.Port + } var useMux bool - if conf.Conf.Rtmp.Port == 0 || conf.Conf.Rtmp.Port == conf.Conf.Server.Port { + if conf.Conf.Server.Rtmp.Port == conf.Conf.Server.Http.Port && conf.Conf.Server.Rtmp.Listen == conf.Conf.Server.Http.Listen { useMux = true - conf.Conf.Rtmp.Port = conf.Conf.Server.Port + conf.Conf.Server.Rtmp.Port = conf.Conf.Server.Http.Port + conf.Conf.Server.Rtmp.Listen = conf.Conf.Server.Http.Listen } - tcpRtmpAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", conf.Conf.Server.Listen, conf.Conf.Rtmp.Port)) + + serverRtmpAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", conf.Conf.Server.Rtmp.Listen, conf.Conf.Server.Rtmp.Port)) if err != nil { log.Fatal(err) } - utils.OptFilePath(&conf.Conf.Server.CertPath) - utils.OptFilePath(&conf.Conf.Server.KeyPath) - if conf.Conf.Rtmp.Enable { + utils.OptFilePath(&conf.Conf.Server.Http.CertPath) + utils.OptFilePath(&conf.Conf.Server.Http.KeyPath) + if conf.Conf.Server.Rtmp.Enable { if useMux { - muxer := cmux.New(serverListener) + muxer := cmux.New(serverHttpListener) e := server.NewAndInit() switch { - case conf.Conf.Server.CertPath != "" && conf.Conf.Server.KeyPath != "": + case conf.Conf.Server.Http.CertPath != "" && conf.Conf.Server.Http.KeyPath != "": httpl := muxer.Match(cmux.HTTP2(), cmux.TLS()) - go http.ServeTLS(httpl, e.Handler(), conf.Conf.Server.CertPath, conf.Conf.Server.KeyPath) - if conf.Conf.Server.Quic { - go http3.ListenAndServeQUIC(udpServerAddr.String(), conf.Conf.Server.CertPath, conf.Conf.Server.KeyPath, e.Handler()) + go http.ServeTLS(httpl, e.Handler(), conf.Conf.Server.Http.CertPath, conf.Conf.Server.Http.KeyPath) + if conf.Conf.Server.Http.Quic { + go http3.ListenAndServeQUIC(udpServerHttpAddr.String(), conf.Conf.Server.Http.CertPath, conf.Conf.Server.Http.KeyPath, e.Handler()) } - case conf.Conf.Server.CertPath == "" && conf.Conf.Server.KeyPath == "": + case conf.Conf.Server.Http.CertPath == "" && conf.Conf.Server.Http.KeyPath == "": httpl := muxer.Match(cmux.HTTP1Fast()) go e.RunListener(httpl) default: @@ -89,17 +98,17 @@ func Server(cmd *cobra.Command, args []string) { } else { e := server.NewAndInit() switch { - case conf.Conf.Server.CertPath != "" && conf.Conf.Server.KeyPath != "": - go http.ServeTLS(serverListener, e.Handler(), conf.Conf.Server.CertPath, conf.Conf.Server.KeyPath) - if conf.Conf.Server.Quic { - go http3.ListenAndServeQUIC(udpServerAddr.String(), conf.Conf.Server.CertPath, conf.Conf.Server.KeyPath, e.Handler()) + case conf.Conf.Server.Http.CertPath != "" && conf.Conf.Server.Http.KeyPath != "": + go http.ServeTLS(serverHttpListener, e.Handler(), conf.Conf.Server.Http.CertPath, conf.Conf.Server.Http.KeyPath) + if conf.Conf.Server.Http.Quic { + go http3.ListenAndServeQUIC(udpServerHttpAddr.String(), conf.Conf.Server.Http.CertPath, conf.Conf.Server.Http.KeyPath, e.Handler()) } - case conf.Conf.Server.CertPath == "" && conf.Conf.Server.KeyPath == "": - go e.RunListener(serverListener) + case conf.Conf.Server.Http.CertPath == "" && conf.Conf.Server.Http.KeyPath == "": + go e.RunListener(serverHttpListener) default: log.Panic("cert and key must be both set") } - rtmpListener, err := net.ListenTCP("tcp", tcpRtmpAddr) + rtmpListener, err := net.ListenTCP("tcp", serverRtmpAddr) if err != nil { log.Fatal(err) } @@ -108,27 +117,27 @@ func Server(cmd *cobra.Command, args []string) { } else { e := server.NewAndInit() switch { - case conf.Conf.Server.CertPath != "" && conf.Conf.Server.KeyPath != "": - go http.ServeTLS(serverListener, e.Handler(), conf.Conf.Server.CertPath, conf.Conf.Server.KeyPath) - if conf.Conf.Server.Quic { - go http3.ListenAndServeQUIC(udpServerAddr.String(), conf.Conf.Server.CertPath, conf.Conf.Server.KeyPath, e.Handler()) + case conf.Conf.Server.Http.CertPath != "" && conf.Conf.Server.Http.KeyPath != "": + go http.ServeTLS(serverHttpListener, e.Handler(), conf.Conf.Server.Http.CertPath, conf.Conf.Server.Http.KeyPath) + if conf.Conf.Server.Http.Quic { + go http3.ListenAndServeQUIC(udpServerHttpAddr.String(), conf.Conf.Server.Http.CertPath, conf.Conf.Server.Http.KeyPath, e.Handler()) } - case conf.Conf.Server.CertPath == "" && conf.Conf.Server.KeyPath == "": - go e.RunListener(serverListener) + case conf.Conf.Server.Http.CertPath == "" && conf.Conf.Server.Http.KeyPath == "": + go e.RunListener(serverHttpListener) default: log.Panic("cert and key must be both set") } } - if conf.Conf.Rtmp.Enable { - log.Infof("rtmp run on tcp://%s:%d", tcpServerAddr.IP, tcpRtmpAddr.Port) + if conf.Conf.Server.Rtmp.Enable { + log.Infof("rtmp run on tcp://%s:%d", serverRtmpAddr.IP, serverRtmpAddr.Port) } - if conf.Conf.Server.CertPath != "" && conf.Conf.Server.KeyPath != "" { - if conf.Conf.Server.Quic { - log.Infof("quic run on udp://%s:%d", udpServerAddr.IP, udpServerAddr.Port) + if conf.Conf.Server.Http.CertPath != "" && conf.Conf.Server.Http.KeyPath != "" { + if conf.Conf.Server.Http.Quic { + log.Infof("quic run on udp://%s:%d", udpServerHttpAddr.IP, udpServerHttpAddr.Port) } - log.Infof("website run on https://%s:%d", tcpServerAddr.IP, tcpServerAddr.Port) + log.Infof("website run on https://%s:%d", tcpServerHttpAddr.IP, tcpServerHttpAddr.Port) } else { - log.Infof("website run on http://%s:%d", tcpServerAddr.IP, tcpServerAddr.Port) + log.Infof("website run on http://%s:%d", tcpServerHttpAddr.IP, tcpServerHttpAddr.Port) } sysnotify.WaitCbk() } diff --git a/internal/bootstrap/rtmp.go b/internal/bootstrap/rtmp.go index 4694119..1f7503d 100644 --- a/internal/bootstrap/rtmp.go +++ b/internal/bootstrap/rtmp.go @@ -34,7 +34,7 @@ func auth(ReqAppName, ReqChannelName string, IsPublisher bool) (*rtmps.Channel, return r.GetChannel(channelName) } - if !conf.Conf.Rtmp.RtmpPlayer { + if !conf.Conf.Server.Rtmp.RtmpPlayer { log.Warnf("rtmp: dial to %s/%s error: %s", ReqAppName, ReqChannelName, "rtmp player is not enabled") return nil, fmt.Errorf("rtmp: dial to %s/%s error: %s", ReqAppName, ReqChannelName, "rtmp player is not enabled") } diff --git a/internal/conf/config.go b/internal/conf/config.go index d6036fb..3165fc1 100644 --- a/internal/conf/config.go +++ b/internal/conf/config.go @@ -14,9 +14,6 @@ type Config struct { // Jwt Jwt JwtConfig `yaml:"jwt"` - // Rtmp - Rtmp RtmpConfig `yaml:"rtmp" hc:"you can use rtmp to publish live"` - // Proxy Proxy ProxyConfig `yaml:"proxy" hc:"you can use proxy to proxy movie and live when custom headers or network is slow to connect to origin server"` @@ -45,9 +42,6 @@ func DefaultConfig() *Config { // Jwt Jwt: DefaultJwtConfig(), - // Rtmp - Rtmp: DefaultRtmpConfig(), - // Proxy Proxy: DefaultProxyConfig(), diff --git a/internal/conf/rtmp.go b/internal/conf/rtmp.go deleted file mode 100644 index a21e279..0000000 --- a/internal/conf/rtmp.go +++ /dev/null @@ -1,20 +0,0 @@ -package conf - -type RtmpConfig struct { - Enable bool `yaml:"enable" env:"RTMP_ENABLE"` - Port uint16 `yaml:"port" lc:"default use server port" env:"RTMP_PORT"` - - CustomPublishHost string `yaml:"custom_publish_host" lc:"default use http header host" env:"RTMP_CUSTOM_PUBLISH_HOST"` - RtmpPlayer bool `yaml:"rtmp_player" hc:"can watch live streams through the RTMP protocol (without authentication, insecure)." env:"RTMP_PLAYER"` - TsDisguisedAsPng bool `yaml:"ts_disguised_as_png" hc:"disguise the .ts file as a .png file" env:"RTMP_TS_DISGUISED_AS_PNG"` -} - -func DefaultRtmpConfig() RtmpConfig { - return RtmpConfig{ - Enable: true, - Port: 0, - CustomPublishHost: "", - RtmpPlayer: false, - TsDisguisedAsPng: true, - } -} diff --git a/internal/conf/server.go b/internal/conf/server.go index be1affd..94d7ce1 100644 --- a/internal/conf/server.go +++ b/internal/conf/server.go @@ -1,6 +1,11 @@ package conf type ServerConfig struct { + Http HttpServerConfig `yaml:"http"` + Rtmp RtmpServerConfig `yaml:"rtmp"` +} + +type HttpServerConfig struct { Listen string `yaml:"listen" env:"SERVER_LISTEN"` Port uint16 `yaml:"port" env:"SERVER_PORT"` Quic bool `yaml:"quic" hc:"enable http3/quic need set cert and key file" env:"SERVER_QUIC"` @@ -9,12 +14,31 @@ type ServerConfig struct { KeyPath string `yaml:"key_path" env:"SERVER_KEY_PATH"` } +type RtmpServerConfig struct { + Enable bool `yaml:"enable" env:"RTMP_ENABLE"` + Listen string `yaml:"listen" lc:"default use http listen" env:"RTMP_LISTEN"` + Port uint16 `yaml:"port" lc:"default use server port" env:"RTMP_PORT"` + + CustomPublishHost string `yaml:"custom_publish_host" lc:"default use http header host" env:"RTMP_CUSTOM_PUBLISH_HOST"` + RtmpPlayer bool `yaml:"rtmp_player" hc:"can watch live streams through the RTMP protocol (without authentication, insecure)." env:"RTMP_PLAYER"` + TsDisguisedAsPng bool `yaml:"ts_disguised_as_png" hc:"disguise the .ts file as a .png file" env:"RTMP_TS_DISGUISED_AS_PNG"` +} + func DefaultServerConfig() ServerConfig { return ServerConfig{ - Listen: "0.0.0.0", - Port: 8080, - Quic: true, - CertPath: "", - KeyPath: "", + Http: HttpServerConfig{ + Listen: "0.0.0.0", + Port: 8080, + Quic: true, + CertPath: "", + KeyPath: "", + }, + Rtmp: RtmpServerConfig{ + Enable: true, + Port: 0, + CustomPublishHost: "", + RtmpPlayer: false, + TsDisguisedAsPng: true, + }, } } diff --git a/internal/model/movie.go b/internal/model/movie.go index 62a9306..6e742c6 100644 --- a/internal/model/movie.go +++ b/internal/model/movie.go @@ -57,7 +57,7 @@ func (m *BaseMovie) Validate() error { case m.RtmpSource && m.Proxy: return errors.New("rtmp source and proxy can't be true at the same time") case m.Live && m.RtmpSource: - if !conf.Conf.Rtmp.Enable { + if !conf.Conf.Server.Rtmp.Enable { return errors.New("rtmp is not enabled") } case m.Live && m.Proxy: diff --git a/server/handlers/movie.go b/server/handlers/movie.go index 8261d21..90c4421 100644 --- a/server/handlers/movie.go +++ b/server/handlers/movie.go @@ -269,7 +269,7 @@ func NewPublishKey(ctx *gin.Context) { return } - host := conf.Conf.Rtmp.CustomPublishHost + host := conf.Conf.Server.Rtmp.CustomPublishHost if host == "" { host = ctx.Request.Host } @@ -537,10 +537,6 @@ func (e FormatErrNotSupportFileType) Error() string { } func JoinLive(ctx *gin.Context) { - if !conf.Conf.Proxy.LiveProxy && !conf.Conf.Rtmp.Enable { - ctx.AbortWithStatusJSON(http.StatusForbidden, model.NewApiErrorStringResp("live proxy and rtmp source is not enabled")) - return - } room := ctx.MustGet("room").(*op.Room) // user := ctx.MustGet("user").(*op.User) @@ -564,7 +560,7 @@ func JoinLive(ctx *gin.Context) { ctx.Header("Cache-Control", "no-store") b, err := channel.GenM3U8File(func(tsName string) (tsPath string) { ext := "ts" - if conf.Conf.Rtmp.TsDisguisedAsPng { + if conf.Conf.Server.Rtmp.TsDisguisedAsPng { ext = "png" } return fmt.Sprintf("/api/movie/live/%s/%s.%s", channelName, tsName, ext) @@ -575,7 +571,7 @@ func JoinLive(ctx *gin.Context) { } ctx.Data(http.StatusOK, hls.M3U8ContentType, b) case ".ts": - if conf.Conf.Rtmp.TsDisguisedAsPng { + if conf.Conf.Server.Rtmp.TsDisguisedAsPng { ctx.AbortWithStatusJSON(http.StatusNotFound, model.NewApiErrorResp(FormatErrNotSupportFileType(fileExt))) return } @@ -587,7 +583,7 @@ func JoinLive(ctx *gin.Context) { ctx.Header("Cache-Control", "public, max-age=90") ctx.Data(http.StatusOK, hls.TSContentType, b) case ".png": - if !conf.Conf.Rtmp.TsDisguisedAsPng { + if !conf.Conf.Server.Rtmp.TsDisguisedAsPng { ctx.AbortWithStatusJSON(http.StatusNotFound, model.NewApiErrorResp(FormatErrNotSupportFileType(fileExt))) return } diff --git a/server/handlers/public.go b/server/handlers/public.go index a8d3a09..61d4318 100644 --- a/server/handlers/public.go +++ b/server/handlers/public.go @@ -9,8 +9,8 @@ import ( func Settings(ctx *gin.Context) { ctx.JSON(200, model.NewApiDataResp(gin.H{ "rtmp": gin.H{ - "enable": conf.Conf.Rtmp.Enable, - "rtmpPlayer": conf.Conf.Rtmp.RtmpPlayer, + "enable": conf.Conf.Server.Rtmp.Enable, + "rtmpPlayer": conf.Conf.Server.Rtmp.RtmpPlayer, }, "proxy": gin.H{ "movieProxy": conf.Conf.Proxy.MovieProxy, diff --git a/server/middlewares/init.go b/server/middlewares/init.go index 5ab7eeb..b4aa9e5 100644 --- a/server/middlewares/init.go +++ b/server/middlewares/init.go @@ -27,7 +27,7 @@ func Init(e *gin.Engine) { } e.Use(NewLimiter(d, conf.Conf.RateLimit.Limit, options...)) } - if conf.Conf.Server.Quic && conf.Conf.Server.CertPath != "" && conf.Conf.Server.KeyPath != "" { + if conf.Conf.Server.Http.Quic && conf.Conf.Server.Http.CertPath != "" && conf.Conf.Server.Http.KeyPath != "" { e.Use(NewQuic()) } }