Fix RTMP server handshake for FFmpeg #1318

This commit is contained in:
Alex X
2025-03-09 07:20:40 +03:00
parent 830e476120
commit c9724e2024
+45 -7
View File
@@ -2,10 +2,13 @@ package rtmp
import ( import (
"bufio" "bufio"
"crypto/rand"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io" "io"
"net" "net"
"time"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/flv/amf" "github.com/AlexxIT/go2rtc/pkg/flv/amf"
@@ -34,23 +37,54 @@ func NewServer(conn net.Conn) (*Conn, error) {
} }
func (c *Conn) serverHandshake() error { func (c *Conn) serverHandshake() error {
b := make([]byte, 1+1536) // based on https://rtmp.veriskope.com/docs/spec/
// read C0+C1 _ = c.conn.SetDeadline(time.Now().Add(core.ConnDeadline))
// read C0
b := make([]byte, 1)
if _, err := io.ReadFull(c.rd, b); err != nil { if _, err := io.ReadFull(c.rd, b); err != nil {
return err return err
} }
// write S0+S1, skip random
if b[0] != 3 {
return errors.New("rtmp: wrong handshake")
}
// write S0
if _, err := c.conn.Write([]byte{3}); err != nil {
return err
}
b = make([]byte, 1536)
// write S1
tsS1 := nowMS()
binary.BigEndian.PutUint32(b, tsS1)
binary.BigEndian.PutUint32(b[4:], 0)
_, _ = rand.Read(b[8:])
if _, err := c.conn.Write(b); err != nil { if _, err := c.conn.Write(b); err != nil {
return err return err
} }
// read S1, skip check
if _, err := io.ReadFull(c.rd, make([]byte, 1536)); err != nil { // read C1
if _, err := io.ReadFull(c.rd, b); err != nil {
return err return err
} }
// write C1
if _, err := c.conn.Write(b[1:]); err != nil { // write S2
tsS2 := nowMS()
binary.BigEndian.PutUint32(b, tsS1)
binary.BigEndian.PutUint32(b[4:], tsS2)
if _, err := c.conn.Write(b); err != nil {
return err return err
} }
// read C2
if _, err := io.ReadFull(c.rd, b); err != nil {
return err
}
_ = c.conn.SetDeadline(time.Time{})
return nil return nil
} }
@@ -161,3 +195,7 @@ func (c *Conn) WriteStart() error {
payload := amf.EncodeItems("onStatus", 0, nil, map[string]any{"code": code}) payload := amf.EncodeItems("onStatus", 0, nil, map[string]any{"code": code})
return c.writeMessage(3, TypeCommand, 0, payload) return c.writeMessage(3, TypeCommand, 0, payload)
} }
func nowMS() uint32 {
return uint32(time.Now().UnixNano() / int64(time.Millisecond))
}