Merge branch 'dev' into cluster

This commit is contained in:
Ingo Oppermann 2023-05-05 10:25:09 +02:00
commit bd46d13bcf
No known key found for this signature in database
GPG Key ID: 2AB32426E9DD229E
11 changed files with 74 additions and 95 deletions

8
go.mod
View File

@ -8,11 +8,13 @@ require (
github.com/atrox/haikunatorgo/v2 v2.0.1
github.com/caddyserver/certmagic v0.17.2
github.com/datarhei/gosrt v0.3.1
github.com/datarhei/joy4 v0.0.0-20220914170649-23c70d207759
github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a
github.com/go-playground/validator/v10 v10.11.1
github.com/gobwas/glob v0.2.3
github.com/golang-jwt/jwt/v4 v4.4.3
github.com/google/uuid v1.3.0
github.com/hashicorp/go-hclog v1.5.0
github.com/hashicorp/raft v1.4.0
github.com/hashicorp/raft-boltdb/v2 v2.2.2
github.com/invopop/jsonschema v0.4.0
github.com/joho/godotenv v1.4.0
@ -31,7 +33,6 @@ require (
go.etcd.io/bbolt v1.3.7
go.uber.org/zap v1.24.0
golang.org/x/mod v0.7.0
golang.org/x/net v0.7.0
)
require (
@ -56,11 +57,9 @@ require (
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-msgpack v0.5.5 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/raft v1.4.0 // indirect
github.com/iancoleman/orderedmap v0.2.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
@ -105,6 +104,7 @@ require (
go.uber.org/goleak v1.1.12 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.3.0 // indirect

8
go.sum
View File

@ -50,8 +50,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/datarhei/gosrt v0.3.1 h1:9A75hIvnY74IUFyeguqYXh1lsGF8Qt8fjxJS2Ewr12Q=
github.com/datarhei/gosrt v0.3.1/go.mod h1:M2nl2WPrawncUc1FtUBK6gZX4tpZRC7FqL8NjOdBZV0=
github.com/datarhei/joy4 v0.0.0-20220914170649-23c70d207759 h1:h8NyekuQSDvLIsZVTV172m5/RVArXkEM/cnHaUzszQU=
github.com/datarhei/joy4 v0.0.0-20220914170649-23c70d207759/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw=
github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a h1:Tf4DSHY1xruBglr+yYP5Wct7czM86GKMYgbXH8a7OFo=
github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a/go.mod h1:Jcw/6jZDQQmPx8A7INEkXmuEF7E9jjBbSTfVSLwmiQw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -396,8 +396,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

View File

@ -178,6 +178,7 @@ func (self *Server) Serve(listener net.Listener) error {
if Debug {
fmt.Println("rtmp: server: client closed err:", err)
}
conn.Close()
}()
}
}
@ -190,6 +191,7 @@ func (self *Server) Close() {
close(self.doneChan)
self.listener.Close()
self.listener = nil
}
const (
@ -398,7 +400,7 @@ func getTcUrl(u *url.URL) string {
return nu.String()
}
func createURL(tcurl, app, play string) (u *url.URL) {
func createURL(tcurl, app, play string) (*url.URL, error) {
ps := strings.Split(app+"/"+play, "/")
out := []string{""}
for _, s := range ps {
@ -410,7 +412,11 @@ func createURL(tcurl, app, play string) (u *url.URL) {
out = append(out, "")
}
path := strings.Join(out, "/")
u, _ = url.ParseRequestURI(path)
u, err := url.ParseRequestURI(path)
if err != nil {
return nil, err
}
if tcurl != "" {
tu, _ := url.Parse(tcurl)
@ -419,7 +425,8 @@ func createURL(tcurl, app, play string) (u *url.URL) {
u.Scheme = tu.Scheme
}
}
return
return u, nil
}
var CodecTypes = flv.CodecTypes
@ -553,7 +560,13 @@ func (self *Conn) readConnect() (err error) {
return
}
self.URL = createURL(tcurl, connectpath, publishpath)
u, uerr := createURL(tcurl, connectpath, publishpath)
if uerr != nil {
err = fmt.Errorf("invalid URL: %w", uerr)
return
}
self.URL = u
self.publishing = true
self.reading = true
self.stage++
@ -599,7 +612,13 @@ func (self *Conn) readConnect() (err error) {
return
}
self.URL = createURL(tcurl, connectpath, playpath)
u, uerr := createURL(tcurl, connectpath, playpath)
if uerr != nil {
err = fmt.Errorf("invalid URL: %w", uerr)
return
}
self.URL = u
self.playing = true
self.writing = true
self.stage++

View File

@ -18,7 +18,7 @@ type inflow struct {
unsent int32
}
// init sets the initial window.
// set sets the initial window.
func (f *inflow) init(n int32) {
f.avail = n
}

View File

@ -662,15 +662,6 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
// It is the caller's responsibility not to violate the maximum frame size
// and to not call other Write methods concurrently.
func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
if err := f.startWriteDataPadded(streamID, endStream, data, pad); err != nil {
return err
}
return f.endWrite()
}
// startWriteDataPadded is WriteDataPadded, but only writes the frame to the Framer's internal buffer.
// The caller should call endWrite to flush the frame to the underlying writer.
func (f *Framer) startWriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
if !validStreamID(streamID) && !f.AllowIllegalWrites {
return errStreamID
}
@ -700,7 +691,7 @@ func (f *Framer) startWriteDataPadded(streamID uint32, endStream bool, data, pad
}
f.wbuf = append(f.wbuf, data...)
f.wbuf = append(f.wbuf, pad...)
return nil
return f.endWrite()
}
// A SettingsFrame conveys configuration parameters that affect how

View File

@ -211,7 +211,7 @@ func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
return dt.ents[dt.len()-(int(i)-staticTable.len())], true
}
// DecodeFull decodes an entire block.
// Decode decodes an entire block.
//
// TODO: remove this method and make it incremental later? This is
// easier for debugging now.
@ -359,7 +359,6 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
var hf HeaderField
wantStr := d.emitEnabled || it.indexed()
var undecodedName undecodedString
if nameIdx > 0 {
ihf, ok := d.at(nameIdx)
if !ok {
@ -367,27 +366,15 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
}
hf.Name = ihf.Name
} else {
undecodedName, buf, err = d.readString(buf)
hf.Name, buf, err = d.readString(buf, wantStr)
if err != nil {
return err
}
}
undecodedValue, buf, err := d.readString(buf)
hf.Value, buf, err = d.readString(buf, wantStr)
if err != nil {
return err
}
if wantStr {
if nameIdx <= 0 {
hf.Name, err = d.decodeString(undecodedName)
if err != nil {
return err
}
}
hf.Value, err = d.decodeString(undecodedValue)
if err != nil {
return err
}
}
d.buf = buf
if it.indexed() {
d.dynTab.add(hf)
@ -472,52 +459,46 @@ func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
return 0, origP, errNeedMore
}
// readString reads an hpack string from p.
// readString decodes an hpack string from p.
//
// It returns a reference to the encoded string data to permit deferring decode costs
// until after the caller verifies all data is present.
func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error) {
// wantStr is whether s will be used. If false, decompression and
// []byte->string garbage are skipped if s will be ignored
// anyway. This does mean that huffman decoding errors for non-indexed
// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
// is returning an error anyway, and because they're not indexed, the error
// won't affect the decoding state.
func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
if len(p) == 0 {
return u, p, errNeedMore
return "", p, errNeedMore
}
isHuff := p[0]&128 != 0
strLen, p, err := readVarInt(7, p)
if err != nil {
return u, p, err
return "", p, err
}
if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
// Returning an error here means Huffman decoding errors
// for non-indexed strings past the maximum string length
// are ignored, but the server is returning an error anyway
// and because the string is not indexed the error will not
// affect the decoding state.
return u, nil, ErrStringLength
return "", nil, ErrStringLength
}
if uint64(len(p)) < strLen {
return u, p, errNeedMore
return "", p, errNeedMore
}
u.isHuff = isHuff
u.b = p[:strLen]
return u, p[strLen:], nil
}
type undecodedString struct {
isHuff bool
b []byte
}
func (d *Decoder) decodeString(u undecodedString) (string, error) {
if !u.isHuff {
return string(u.b), nil
if !isHuff {
if wantStr {
s = string(p[:strLen])
}
return s, p[strLen:], nil
}
buf := bufPool.Get().(*bytes.Buffer)
buf.Reset() // don't trust others
var s string
err := huffmanDecode(buf, d.maxStrLen, u.b)
if err == nil {
if wantStr {
buf := bufPool.Get().(*bytes.Buffer)
buf.Reset() // don't trust others
defer bufPool.Put(buf)
if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
buf.Reset()
return "", nil, err
}
s = buf.String()
buf.Reset() // be nice to GC
}
buf.Reset() // be nice to GC
bufPool.Put(buf)
return s, err
return s, p[strLen:], nil
}

View File

@ -843,13 +843,8 @@ type frameWriteResult struct {
// and then reports when it's done.
// At most one goroutine can be running writeFrameAsync at a time per
// serverConn.
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) {
var err error
if wd == nil {
err = wr.write.writeFrame(sc)
} else {
err = sc.framer.endWrite()
}
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
err := wr.write.writeFrame(sc)
sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}
}
@ -1256,16 +1251,9 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
sc.writingFrameAsync = false
err := wr.write.writeFrame(sc)
sc.wroteFrame(frameWriteResult{wr: wr, err: err})
} else if wd, ok := wr.write.(*writeData); ok {
// Encode the frame in the serve goroutine, to ensure we don't have
// any lingering asynchronous references to data passed to Write.
// See https://go.dev/issue/58446.
sc.framer.startWriteDataPadded(wd.streamID, wd.endStream, wd.p, nil)
sc.writingFrameAsync = true
go sc.writeFrameAsync(wr, wd)
} else {
sc.writingFrameAsync = true
go sc.writeFrameAsync(wr, nil)
go sc.writeFrameAsync(wr)
}
}
@ -2204,7 +2192,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
tlsState = sc.tlsState
}
needsContinue := httpguts.HeaderValuesContainsToken(rp.header["Expect"], "100-continue")
needsContinue := rp.header.Get("Expect") == "100-continue"
if needsContinue {
rp.header.Del("Expect")
}

View File

@ -1569,7 +1569,7 @@ func (cs *clientStream) cleanupWriteRequest(err error) {
close(cs.donec)
}
// awaitOpenSlotForStreamLocked waits until len(streams) < maxConcurrentStreams.
// awaitOpenSlotForStream waits until len(streams) < maxConcurrentStreams.
// Must hold cc.mu.
func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {
for {

View File

@ -245,7 +245,7 @@ func (c *dgramOpt) Checksum() (on bool, offset int, err error) {
return true, offset, nil
}
// SetChecksum enables the kernel checksum processing. If on is true,
// SetChecksum enables the kernel checksum processing. If on is ture,
// the offset should be an offset in bytes into the data of where the
// checksum field is located.
func (c *dgramOpt) SetChecksum(on bool, offset int) error {

View File

@ -655,7 +655,7 @@ func handlePropfindError(err error, info os.FileInfo) error {
// We need to be careful with other errors: there is no way to abort the xml stream
// part way through while returning a valid PROPFIND response. Returning only half
// the data would be misleading, but so would be returning results tainted by errors.
// The current behaviour by returning an error here leads to the stream being aborted,
// The curent behaviour by returning an error here leads to the stream being aborted,
// and the parent http server complaining about writing a spurious header. We should
// consider further enhancing this error handling to more gracefully fail, or perhaps
// buffer the entire response until we've walked the tree.

4
vendor/modules.txt vendored
View File

@ -65,7 +65,7 @@ github.com/datarhei/gosrt/internal/congestion
github.com/datarhei/gosrt/internal/crypto
github.com/datarhei/gosrt/internal/net
github.com/datarhei/gosrt/internal/packet
# github.com/datarhei/joy4 v0.0.0-20220914170649-23c70d207759
# github.com/datarhei/joy4 v0.0.0-20230505074825-fde05957445a
## explicit; go 1.14
github.com/datarhei/joy4/av
github.com/datarhei/joy4/av/avutil
@ -399,7 +399,7 @@ golang.org/x/crypto/sha3
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/module
golang.org/x/mod/semver
# golang.org/x/net v0.7.0
# golang.org/x/net v0.5.0
## explicit; go 1.17
golang.org/x/net/bpf
golang.org/x/net/http/httpguts