Handshake fails for certain RTMP clients
clone1018 opened this issue · 5 comments
clone1018 commented
Seems for some reason the handshake does not shake successfully with restream, so connecting does not work.
Server closed by error: Err = Random echo is not matched
github.com/yutopp/go-rtmp/handshake.HandshakeWithClient
/root/go/pkg/mod/github.com/yutopp/go-rtmp@v0.0.1/handshake/handshake.go:102
github.com/yutopp/go-rtmp.(*serverConn).Serve
/root/go/pkg/mod/github.com/yutopp/go-rtmp@v0.0.1/server_conn.go:28
github.com/yutopp/go-rtmp.(*Server).handleConn
/root/go/pkg/mod/github.com/yutopp/go-rtmp@v0.0.1/server.go:115
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1581
Failed to handshake
github.com/yutopp/go-rtmp.(*serverConn).Serve
/root/go/pkg/mod/github.com/yutopp/go-rtmp@v0.0.1/server_conn.go:31
github.com/yutopp/go-rtmp.(*Server).handleConn
/root/go/pkg/mod/github.com/yutopp/go-rtmp@v0.0.1/server.go:115
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1581
The primary example of this is restream.io
clone1018 commented
Seems owncast had the same issue: owncast/owncast#34
clone1018 commented
Need to look into if they maintain a fork of the RTMP library we should be using instead!
clone1018 commented
Here's some quick code to do a basic RTMP handshake (and send an invalid one for testing):
package main
import (
"bufio"
"crypto/rand"
"fmt"
"io"
"net"
)
func main() {
token := make([]byte, 1536)
rand.Read(token)
wrongResponse := make([]byte, 1536)
rand.Read(wrongResponse)
conn, err := net.Dial("tcp", "localhost:1935")
if err != nil {
panic(err)
}
reader := bufio.NewReader(conn)
// Write 0x03 and token
conn.Write([]byte{0x03})
conn.Write(token)
// Check status response
status := make([]byte, 1)
_, err = reader.Read(status)
if err != nil {
panic(err)
}
fmt.Printf("First Res: %#v\n", status)
// Generate handshake
handshake := make([]byte, 1536)
_, err = io.ReadFull(conn, handshake)
if err != nil {
panic(err)
}
conn.Write(handshake)
// Uncomment this if you want the handshake to fail
// conn.Write(wrongResponse)
_, err = reader.Read(status)
if err != nil {
panic(err)
}
fmt.Printf("Second Res: %#v\n", status)
}
clone1018 commented
clone1018 commented
That fixed it it seems, there were two issues:
- Digest handshake was not implemented. Glimesh/go-rtmp@a33e29d
- Publishing Type is sometimes missing from certain services, I made a patch to go-rtmp to default to live (it is a live streaming server after all). Glimesh/go-rtmp@4f0095b#diff-985ac45622f50b5032960af0abd0cca4e5b9bd93ee9b1d76c72093de0d0cd8b5R205-R207