Skip to content

Commit b77ae3a

Browse files
committed
move interleaved frames logic into rtsp.Conn
1 parent 8a773a1 commit b77ae3a

File tree

3 files changed

+94
-63
lines changed

3 files changed

+94
-63
lines changed

main.go

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package main
22

33
import (
4-
"encoding/binary"
54
"fmt"
65
"log"
76
"net"
@@ -63,45 +62,37 @@ func (p *program) run() {
6362
<-infty
6463
}
6564

66-
func (p *program) handleRtp(buf []byte) {
65+
func (p *program) handleRtp(frame []byte) {
6766
p.mutex.RLock()
6867
defer p.mutex.RUnlock()
6968

70-
tcpHeader := [4]byte{0x24, 0x00, 0x00, 0x00}
71-
binary.BigEndian.PutUint16(tcpHeader[2:], uint16(len(buf)))
72-
7369
for c := range p.clients {
7470
if c.state == "PLAY" {
7571
if c.rtpProto == "udp" {
76-
p.rtpl.nconn.WriteTo(buf, &net.UDPAddr{
72+
p.rtpl.nconn.WriteTo(frame, &net.UDPAddr{
7773
IP: c.IP,
7874
Port: c.rtpPort,
7975
})
8076
} else {
81-
c.nconn.Write(tcpHeader[:])
82-
c.nconn.Write(buf)
77+
c.rconn.WriteInterleavedFrame(frame)
8378
}
8479
}
8580
}
8681
}
8782

88-
func (p *program) handleRtcp(buf []byte) {
83+
func (p *program) handleRtcp(frame []byte) {
8984
p.mutex.RLock()
9085
defer p.mutex.RUnlock()
9186

92-
tcpHeader := [4]byte{0x24, 0x00, 0x00, 0x00}
93-
binary.BigEndian.PutUint16(tcpHeader[2:], uint16(len(buf)))
94-
9587
for c := range p.clients {
9688
if c.state == "PLAY" {
9789
if c.rtpProto == "udp" {
98-
p.rtcpl.nconn.WriteTo(buf, &net.UDPAddr{
90+
p.rtcpl.nconn.WriteTo(frame, &net.UDPAddr{
9991
IP: c.IP,
10092
Port: c.rtcpPort,
10193
})
10294
} else {
103-
c.nconn.Write(tcpHeader[:])
104-
c.nconn.Write(buf)
95+
c.rconn.WriteInterleavedFrame(frame)
10596
}
10697
}
10798
}

rtsp/conn.go

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,86 @@
11
package rtsp
22

33
import (
4+
"encoding/binary"
5+
"fmt"
6+
"io"
47
"net"
58
)
69

710
type Conn struct {
8-
net.Conn
11+
c net.Conn
12+
writeBuf []byte
13+
}
14+
15+
func NewConn(c net.Conn) *Conn {
16+
return &Conn{
17+
c: c,
18+
writeBuf: make([]byte, 2048),
19+
}
20+
}
21+
22+
func (c *Conn) Close() error {
23+
return c.c.Close()
24+
}
25+
26+
func (c *Conn) RemoteAddr() net.Addr {
27+
return c.c.RemoteAddr()
928
}
1029

1130
func (c *Conn) ReadRequest() (*Request, error) {
12-
return requestDecode(c)
31+
return requestDecode(c.c)
1332
}
1433

1534
func (c *Conn) WriteRequest(req *Request) error {
16-
return requestEncode(c, req)
35+
return requestEncode(c.c, req)
1736
}
1837

1938
func (c *Conn) ReadResponse() (*Response, error) {
20-
return responseDecode(c)
39+
return responseDecode(c.c)
2140
}
2241

2342
func (c *Conn) WriteResponse(res *Response) error {
24-
return responseEncode(c, res)
43+
return responseEncode(c.c, res)
44+
}
45+
46+
func (c *Conn) ReadInterleavedFrame(frame []byte) (int, error) {
47+
var header [4]byte
48+
_, err := io.ReadFull(c.c, header[:])
49+
if err != nil {
50+
return 0, err
51+
}
52+
53+
// connection terminated
54+
if header[0] == 0x54 {
55+
return 0, io.EOF
56+
}
57+
58+
if header[0] != 0x24 {
59+
return 0, fmt.Errorf("wrong magic byte (0x%.2x)", header[0])
60+
}
61+
62+
framelen := binary.BigEndian.Uint16(header[2:])
63+
if framelen > 2048 {
64+
return 0, fmt.Errorf("frame length greater than 2048")
65+
}
66+
67+
_, err = io.ReadFull(c.c, frame[:framelen])
68+
if err != nil {
69+
return 0, err
70+
}
71+
72+
return int(framelen), nil
73+
}
74+
75+
func (c *Conn) WriteInterleavedFrame(frame []byte) error {
76+
c.writeBuf[0] = 0x24
77+
c.writeBuf[1] = 0x00
78+
binary.BigEndian.PutUint16(c.writeBuf[2:], uint16(len(frame)))
79+
n := copy(c.writeBuf[4:], frame)
80+
81+
_, err := c.c.Write(c.writeBuf[:4+n])
82+
if err != nil {
83+
return err
84+
}
85+
return nil
2586
}

rtsp_client.go

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package main
22

33
import (
4-
"bufio"
5-
"encoding/binary"
64
"errors"
75
"fmt"
86
"io"
@@ -23,7 +21,7 @@ var (
2321

2422
type rtspClient struct {
2523
p *program
26-
nconn net.Conn
24+
rconn *rtsp.Conn
2725
state string
2826
IP net.IP
2927
rtpProto string
@@ -34,7 +32,7 @@ type rtspClient struct {
3432
func newRtspClient(p *program, nconn net.Conn) *rtspClient {
3533
c := &rtspClient{
3634
p: p,
37-
nconn: nconn,
35+
rconn: rtsp.NewConn(nconn),
3836
state: "STARTING",
3937
}
4038

@@ -52,7 +50,7 @@ func (c *rtspClient) close() error {
5250
}
5351

5452
delete(c.p.clients, c)
55-
c.nconn.Close()
53+
c.rconn.Close()
5654

5755
if c.p.streamAuthor == c {
5856
c.p.streamAuthor = nil
@@ -69,7 +67,7 @@ func (c *rtspClient) close() error {
6967
}
7068

7169
func (c *rtspClient) log(format string, args ...interface{}) {
72-
format = "[RTSP client " + c.nconn.RemoteAddr().String() + "] " + format
70+
format = "[RTSP client " + c.rconn.RemoteAddr().String() + "] " + format
7371
log.Printf(format, args...)
7472
}
7573

@@ -81,15 +79,13 @@ func (c *rtspClient) run() {
8179
c.close()
8280
}()
8381

84-
ipstr, _, _ := net.SplitHostPort(c.nconn.RemoteAddr().String())
82+
ipstr, _, _ := net.SplitHostPort(c.rconn.RemoteAddr().String())
8583
c.IP = net.ParseIP(ipstr)
8684

87-
rconn := &rtsp.Conn{c.nconn}
88-
8985
c.log("connected")
9086

9187
for {
92-
req, err := rconn.ReadRequest()
88+
req, err := c.rconn.ReadRequest()
9389
if err != nil {
9490
if err != io.EOF {
9591
c.log("ERR: %s", err)
@@ -104,7 +100,7 @@ func (c *rtspClient) run() {
104100
switch err {
105101
// normal response
106102
case nil:
107-
err = rconn.WriteResponse(res)
103+
err = c.rconn.WriteResponse(res)
108104
if err != nil {
109105
c.log("ERR: %s", err)
110106
return
@@ -119,7 +115,7 @@ func (c *rtspClient) run() {
119115
// before the response
120116
// then switch to RTP if TCP
121117
case errPlay:
122-
err = rconn.WriteResponse(res)
118+
err = c.rconn.WriteResponse(res)
123119
if err != nil {
124120
c.log("ERR: %s", err)
125121
return
@@ -134,18 +130,21 @@ func (c *rtspClient) run() {
134130
// when rtp protocol is TCP, the RTSP connection becomes a RTP connection
135131
// receive RTP feedback, do not parse it, wait until connection closes
136132
if c.rtpProto == "tcp" {
137-
buf := make([]byte, 1024)
133+
buf := make([]byte, 2048)
138134
for {
139-
_, err := c.nconn.Read(buf)
135+
_, err := c.rconn.ReadInterleavedFrame(buf)
140136
if err != nil {
137+
if err != io.EOF {
138+
c.log("ERR: %s", err)
139+
}
141140
return
142141
}
143142
}
144143
}
145144

146145
// RECORD: switch to RTP if TCP
147146
case errRecord:
148-
err = rconn.WriteResponse(res)
147+
err = c.rconn.WriteResponse(res)
149148
if err != nil {
150149
c.log("ERR: %s", err)
151150
return
@@ -160,37 +159,17 @@ func (c *rtspClient) run() {
160159
// when rtp protocol is TCP, the RTSP connection becomes a RTP connection
161160
// receive RTP data and parse it
162161
if c.rtpProto == "tcp" {
163-
packet := make([]byte, 2048)
164-
bconn := bufio.NewReader(c.nconn)
162+
buf := make([]byte, 2048)
165163
for {
166-
byts, err := bconn.Peek(4)
167-
if err != nil {
168-
return
169-
}
170-
bconn.Discard(4)
171-
172-
if byts[0] != 0x24 {
173-
c.log("ERR: wrong magic byte")
174-
return
175-
}
176-
177-
if byts[1] != 0x00 {
178-
c.log("ERR: wrong channel")
179-
return
180-
}
181-
182-
plen := binary.BigEndian.Uint16(byts[2:])
183-
if plen > 2048 {
184-
c.log("ERR: packet len > 2048")
185-
return
186-
}
187-
188-
_, err = io.ReadFull(bconn, packet[:plen])
164+
n, err := c.rconn.ReadInterleavedFrame(buf)
189165
if err != nil {
166+
if err != io.EOF {
167+
c.log("ERR: %s", err)
168+
}
190169
return
191170
}
192171

193-
c.p.handleRtp(packet[:plen])
172+
c.p.handleRtp(buf[:n])
194173
}
195174
}
196175

@@ -199,15 +178,15 @@ func (c *rtspClient) run() {
199178
c.log("ERR: %s", err)
200179

201180
if cseq, ok := req.Headers["cseq"]; ok {
202-
rconn.WriteResponse(&rtsp.Response{
181+
c.rconn.WriteResponse(&rtsp.Response{
203182
StatusCode: 400,
204183
Status: "Bad Request",
205184
Headers: map[string]string{
206185
"CSeq": cseq,
207186
},
208187
})
209188
} else {
210-
rconn.WriteResponse(&rtsp.Response{
189+
c.rconn.WriteResponse(&rtsp.Response{
211190
StatusCode: 400,
212191
Status: "Bad Request",
213192
})

0 commit comments

Comments
 (0)