mirror of
https://github.com/aler9/rtsp-simple-server
synced 2026-04-22 15:07:19 +08:00
prevent out-of-memory errors (#5674)
impose a maximum size on body of incoming HTTP requests and responses.
This commit is contained in:
@@ -19,6 +19,10 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/httpp"
|
||||
)
|
||||
|
||||
const (
|
||||
maxInboundConfigSize = 10 * 1024 * 1024
|
||||
)
|
||||
|
||||
func interfaceIsEmpty(i any) bool {
|
||||
return reflect.ValueOf(i).Kind() != reflect.Pointer || reflect.ValueOf(i).IsNil()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package api //nolint:revive
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
@@ -18,7 +19,7 @@ func (a *API) onConfigGlobalGet(ctx *gin.Context) {
|
||||
|
||||
func (a *API) onConfigGlobalPatch(ctx *gin.Context) {
|
||||
var c conf.OptionalGlobal
|
||||
err := jsonwrapper.Decode(ctx.Request.Body, &c)
|
||||
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &c)
|
||||
if err != nil {
|
||||
a.writeError(ctx, http.StatusBadRequest, err)
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package api //nolint:revive
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
@@ -18,7 +19,7 @@ func (a *API) onConfigPathDefaultsGet(ctx *gin.Context) {
|
||||
|
||||
func (a *API) onConfigPathDefaultsPatch(ctx *gin.Context) {
|
||||
var p conf.OptionalPath
|
||||
err := jsonwrapper.Decode(ctx.Request.Body, &p)
|
||||
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
|
||||
if err != nil {
|
||||
a.writeError(ctx, http.StatusBadRequest, err)
|
||||
return
|
||||
|
||||
@@ -3,6 +3,7 @@ package api //nolint:revive
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/bluenviron/mediamtx/internal/conf"
|
||||
@@ -63,7 +64,7 @@ func (a *API) onConfigPathsAdd(ctx *gin.Context) { //nolint:dupl
|
||||
}
|
||||
|
||||
var p conf.OptionalPath
|
||||
err := jsonwrapper.Decode(ctx.Request.Body, &p)
|
||||
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
|
||||
if err != nil {
|
||||
a.writeError(ctx, http.StatusBadRequest, err)
|
||||
return
|
||||
@@ -100,7 +101,7 @@ func (a *API) onConfigPathsPatch(ctx *gin.Context) { //nolint:dupl
|
||||
}
|
||||
|
||||
var p conf.OptionalPath
|
||||
err := jsonwrapper.Decode(ctx.Request.Body, &p)
|
||||
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
|
||||
if err != nil {
|
||||
a.writeError(ctx, http.StatusBadRequest, err)
|
||||
return
|
||||
@@ -141,7 +142,7 @@ func (a *API) onConfigPathsReplace(ctx *gin.Context) { //nolint:dupl
|
||||
}
|
||||
|
||||
var p conf.OptionalPath
|
||||
err := jsonwrapper.Decode(ctx.Request.Body, &p)
|
||||
err := jsonwrapper.Decode(io.LimitReader(ctx.Request.Body, maxInboundConfigSize), &p)
|
||||
if err != nil {
|
||||
a.writeError(ctx, http.StatusBadRequest, err)
|
||||
return
|
||||
|
||||
@@ -24,7 +24,8 @@ const (
|
||||
// PauseAfterError is the pause to apply after an authentication failure.
|
||||
PauseAfterError = 2 * time.Second
|
||||
|
||||
jwksRefreshPeriod = 60 * 60 * time.Second
|
||||
maxInboundBodySize = 128 * 1024
|
||||
jwksRefreshPeriod = 60 * 60 * time.Second
|
||||
)
|
||||
|
||||
func isHTTP(req *Request) bool {
|
||||
@@ -234,7 +235,8 @@ func (m *Manager) authenticateHTTP(req *Request, token string) (string, error) {
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode < 200 || res.StatusCode > 299 {
|
||||
if resBody, err2 := io.ReadAll(res.Body); err2 == nil && len(resBody) != 0 {
|
||||
resBody, err2 := io.ReadAll(io.LimitReader(res.Body, maxInboundBodySize))
|
||||
if err2 == nil && len(resBody) != 0 {
|
||||
return "", fmt.Errorf("server replied with code %d: %s", res.StatusCode, string(resBody))
|
||||
}
|
||||
|
||||
@@ -304,7 +306,7 @@ func (m *Manager) pullJWTJWKS() (jwt.Keyfunc, error) {
|
||||
defer res.Body.Close()
|
||||
|
||||
var raw json.RawMessage
|
||||
err = json.NewDecoder(res.Body).Decode(&raw)
|
||||
err = json.NewDecoder(io.LimitReader(res.Body, maxInboundBodySize)).Decode(&raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ import (
|
||||
"github.com/bluenviron/mediamtx/internal/protocols/webrtc"
|
||||
)
|
||||
|
||||
const (
|
||||
maxInboundSDPSize = 128 * 1024
|
||||
)
|
||||
|
||||
// Client is a WHIP client.
|
||||
type Client struct {
|
||||
URL *url.URL
|
||||
@@ -260,7 +264,7 @@ func (c *Client) postOffer(
|
||||
return nil, fmt.Errorf("ETag is missing")
|
||||
}
|
||||
|
||||
sdp, err := io.ReadAll(res.Body)
|
||||
sdp, err := io.ReadAll(io.LimitReader(res.Body, maxInboundSDPSize))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
maxInboundHLSJSSize = 10 * 1024 * 1024
|
||||
)
|
||||
|
||||
func do() error {
|
||||
buf, err := os.ReadFile("./hlsjsdownloader/VERSION")
|
||||
if err != nil {
|
||||
@@ -34,7 +38,7 @@ func do() error {
|
||||
return fmt.Errorf("bad status code: %v", res.StatusCode)
|
||||
}
|
||||
|
||||
zipBuf, err := io.ReadAll(res.Body)
|
||||
zipBuf, err := io.ReadAll(io.LimitReader(res.Body, maxInboundHLSJSSize))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ func (s *httpServer) onWHIPPost(ctx *gin.Context, pathName string, publish bool)
|
||||
return
|
||||
}
|
||||
|
||||
offer, err := io.ReadAll(ctx.Request.Body)
|
||||
offer, err := io.ReadAll(io.LimitReader(ctx.Request.Body, maxInboundSDPSize))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -260,7 +260,7 @@ func (s *httpServer) onWHIPPatch(ctx *gin.Context, pathName string, rawSecret st
|
||||
return
|
||||
}
|
||||
|
||||
byts, err := io.ReadAll(ctx.Request.Body)
|
||||
byts, err := io.ReadAll(io.LimitReader(ctx.Request.Body, maxInboundSDPSize))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
webrtcTurnSecretExpiration = 24 * time.Hour
|
||||
turnSecretExpiration = 24 * time.Hour
|
||||
maxInboundSDPSize = 128 * 1024
|
||||
)
|
||||
|
||||
// ErrSessionNotFound is returned when a session is not found.
|
||||
@@ -475,7 +476,7 @@ func (s *Server) generateICEServers(clientConfig bool) ([]pwebrtc.ICEServer, err
|
||||
for _, server := range s.ICEServers {
|
||||
if !server.ClientOnly || clientConfig {
|
||||
if server.Username == "AUTH_SECRET" {
|
||||
expireDate := time.Now().Add(webrtcTurnSecretExpiration).Unix()
|
||||
expireDate := time.Now().Add(turnSecretExpiration).Unix()
|
||||
|
||||
user, err := randomTurnUser()
|
||||
if err != nil {
|
||||
|
||||
@@ -16,6 +16,10 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
maxInboundRPICameraSize = 10 * 1024 * 1024
|
||||
)
|
||||
|
||||
func dumpTar(src io.Reader) error {
|
||||
uncompressed, err := gzip.NewReader(src)
|
||||
if err != nil {
|
||||
@@ -75,7 +79,7 @@ func doSingle(version string, f string) error {
|
||||
return fmt.Errorf("bad status code: %v", res.StatusCode)
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(res.Body)
|
||||
buf, err := io.ReadAll(io.LimitReader(res.Body, maxInboundRPICameraSize))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user