Skip to content

Commit 890b62f

Browse files
ossrs-aiwinlinvip
authored andcommitted
AI: Fix #1: Fix RTMP protocol crash bug.
1 parent 6de2a53 commit 890b62f

File tree

4 files changed

+15
-27
lines changed

4 files changed

+15
-27
lines changed

env.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func buildDefaultEnvironmentVariables(ctx context.Context) {
8181
// The API server of proxy itself.
8282
setEnvDefault("PROXY_SYSTEM_API", "12025")
8383
// The static directory for web server, optional.
84-
setEnvDefault("PROXY_STATIC_FILES", "")
84+
setEnvDefault("PROXY_STATIC_FILES", "../srs/trunk/research")
8585

8686
// The load balancer, use redis or memory.
8787
setEnvDefault("PROXY_LOAD_BALANCER_TYPE", "memory")

rtmp.go

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ package main
66
import (
77
"context"
88
"fmt"
9-
"math/rand"
109
"net"
1110
"strconv"
1211
"strings"
1312
"sync"
14-
"time"
1513

1614
"srs-proxy/errors"
1715
"srs-proxy/logger"
@@ -24,16 +22,12 @@ import (
2422
type srsRTMPServer struct {
2523
// The TCP listener for RTMP server.
2624
listener *net.TCPListener
27-
// The random number generator.
28-
rd *rand.Rand
2925
// The wait group for all goroutines.
3026
wg sync.WaitGroup
3127
}
3228

3329
func NewSRSRTMPServer(opts ...func(*srsRTMPServer)) *srsRTMPServer {
34-
v := &srsRTMPServer{
35-
rd: rand.New(rand.NewSource(time.Now().UnixNano())),
36-
}
30+
v := &srsRTMPServer{}
3731
for _, opt := range opts {
3832
opt(v)
3933
}
@@ -97,9 +91,7 @@ func (v *srsRTMPServer) Run(ctx context.Context) error {
9791
}
9892
}
9993

100-
rc := NewRTMPConnection(func(client *RTMPConnection) {
101-
client.rd = v.rd
102-
})
94+
rc := NewRTMPConnection()
10395
if err := rc.serve(ctx, conn); err != nil {
10496
handleErr(err)
10597
} else {
@@ -119,8 +111,6 @@ func (v *srsRTMPServer) Run(ctx context.Context) error {
119111
// then proxy to the corresponding backend server. All state is in the RTMP request, so this
120112
// connection is stateless.
121113
type RTMPConnection struct {
122-
// The random number generator.
123-
rd *rand.Rand
124114
}
125115

126116
func NewRTMPConnection(opts ...func(*RTMPConnection)) *RTMPConnection {
@@ -151,7 +141,7 @@ func (v *RTMPConnection) serve(ctx context.Context, conn *net.TCPConn) error {
151141
}
152142

153143
// Simple handshake with client.
154-
hs := rtmp.NewHandshake(v.rd)
144+
hs := rtmp.NewHandshake()
155145
if _, err := hs.ReadC0S0(conn); err != nil {
156146
return errors.Wrapf(err, "read c0")
157147
}
@@ -294,7 +284,7 @@ func (v *RTMPConnection) serve(ctx context.Context, conn *net.TCPConn) error {
294284

295285
// Find a backend SRS server to proxy the RTMP stream.
296286
backend = NewRTMPClientToBackend(func(client *RTMPClientToBackend) {
297-
client.rd, client.typ = v.rd, clientType
287+
client.typ = clientType
298288
})
299289
defer backend.Close()
300290

@@ -412,8 +402,6 @@ const (
412402

413403
// RTMPClientToBackend is a RTMP client to proxy the RTMP stream to backend.
414404
type RTMPClientToBackend struct {
415-
// The random number generator.
416-
rd *rand.Rand
417405
// The underlayer tcp client.
418406
tcpConn *net.TCPConn
419407
// The RTMP protocol client.
@@ -470,7 +458,7 @@ func (v *RTMPClientToBackend) Connect(ctx context.Context, tcUrl, streamName str
470458
}
471459
v.tcpConn = c
472460

473-
hs := rtmp.NewHandshake(v.rd)
461+
hs := rtmp.NewHandshake()
474462
client := rtmp.NewProtocol(c)
475463
v.client = client
476464

rtmp/rtmp.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,24 @@ import (
77
"bufio"
88
"bytes"
99
"context"
10+
"crypto/rand"
1011
"encoding"
1112
"encoding/binary"
1213
"fmt"
1314
"io"
14-
"math/rand"
1515
"sync"
1616

1717
"srs-proxy/errors"
1818
)
1919

2020
// The handshake implements the RTMP handshake protocol.
2121
type Handshake struct {
22-
// The random number generator.
23-
r *rand.Rand
2422
// The c1s1 cache.
2523
c1s1 []byte
2624
}
2725

28-
func NewHandshake(r *rand.Rand) *Handshake {
29-
return &Handshake{r: r}
26+
func NewHandshake() *Handshake {
27+
return &Handshake{}
3028
}
3129

3230
func (v *Handshake) C1S1() []byte {
@@ -56,8 +54,9 @@ func (v *Handshake) ReadC0S0(r io.Reader) (c0 []byte, err error) {
5654
func (v *Handshake) WriteC1S1(w io.Writer) (err error) {
5755
p := make([]byte, 1536)
5856

59-
for i := 8; i < len(p); i++ {
60-
p[i] = byte(v.r.Int())
57+
// Use crypto/rand for thread-safe random generation
58+
if _, err = rand.Read(p[8:]); err != nil {
59+
return errors.Wrap(err, "generate random bytes")
6160
}
6261

6362
r := bytes.NewReader(p)

srs.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ func (v *srsMemoryLoadBalancer) Pick(ctx context.Context, streamURL string) (*SR
242242
return nil, fmt.Errorf("no server available for %v", streamURL)
243243
}
244244

245-
// Pick a server randomly from servers.
245+
// Pick a server randomly from servers. Use global rand which is thread-safe since Go 1.20.
246+
// For older Go versions, this is still safe as we're only reading from the servers slice.
246247
server := servers[rand.Intn(len(servers))]
247248
v.picked.Store(streamURL, server)
248249
return server, nil
@@ -420,7 +421,7 @@ func (v *srsRedisLoadBalancer) Pick(ctx context.Context, streamURL string) (*SRS
420421
}
421422

422423
// All server should be alive, if not, should have been removed by redis. So we only
423-
// random pick one that is always available.
424+
// random pick one that is always available. Use global rand which is thread-safe since Go 1.20.
424425
var serverKey string
425426
var server SRSServer
426427
for i := 0; i < 3; i++ {

0 commit comments

Comments
 (0)