Browse Source

add serverUdpListener.close()

pull/31/head
aler9 5 years ago
parent
commit
83608a2fdd
  1. 6
      main.go
  2. 10
      server-client.go
  3. 109
      server-udpl.go

6
main.go

@ -167,7 +167,7 @@ func (p *program) forwardTrack(path string, id int, flow trackFlow, frame []byte
if c.path == path && c.state == _CLIENT_STATE_PLAY { if c.path == path && c.state == _CLIENT_STATE_PLAY {
if c.streamProtocol == _STREAM_PROTOCOL_UDP { if c.streamProtocol == _STREAM_PROTOCOL_UDP {
if flow == _TRACK_FLOW_RTP { if flow == _TRACK_FLOW_RTP {
p.rtpl.chanWrite <- &udpWrite{ p.rtpl.write <- &udpWrite{
addr: &net.UDPAddr{ addr: &net.UDPAddr{
IP: c.ip(), IP: c.ip(),
Zone: c.zone(), Zone: c.zone(),
@ -176,7 +176,7 @@ func (p *program) forwardTrack(path string, id int, flow trackFlow, frame []byte
buf: frame, buf: frame,
} }
} else { } else {
p.rtcpl.chanWrite <- &udpWrite{ p.rtcpl.write <- &udpWrite{
addr: &net.UDPAddr{ addr: &net.UDPAddr{
IP: c.ip(), IP: c.ip(),
Zone: c.zone(), Zone: c.zone(),
@ -187,7 +187,7 @@ func (p *program) forwardTrack(path string, id int, flow trackFlow, frame []byte
} }
} else { } else {
c.chanWrite <- &gortsplib.InterleavedFrame{ c.write <- &gortsplib.InterleavedFrame{
Channel: trackToInterleavedChannel(id, flow), Channel: trackToInterleavedChannel(id, flow),
Content: frame, Content: frame,
} }

10
server-client.go

@ -113,7 +113,7 @@ type serverClient struct {
streamSdpParsed *sdp.Message // filled only if publisher streamSdpParsed *sdp.Message // filled only if publisher
streamProtocol streamProtocol streamProtocol streamProtocol
streamTracks []*track streamTracks []*track
chanWrite chan *gortsplib.InterleavedFrame write chan *gortsplib.InterleavedFrame
} }
func newServerClient(p *program, nconn net.Conn) *serverClient { func newServerClient(p *program, nconn net.Conn) *serverClient {
@ -124,8 +124,8 @@ func newServerClient(p *program, nconn net.Conn) *serverClient {
ReadTimeout: _READ_TIMEOUT, ReadTimeout: _READ_TIMEOUT,
WriteTimeout: _WRITE_TIMEOUT, WriteTimeout: _WRITE_TIMEOUT,
}), }),
state: _CLIENT_STATE_STARTING, state: _CLIENT_STATE_STARTING,
chanWrite: make(chan *gortsplib.InterleavedFrame), write: make(chan *gortsplib.InterleavedFrame),
} }
c.p.mutex.Lock() c.p.mutex.Lock()
@ -143,7 +143,7 @@ func (c *serverClient) close() error {
delete(c.p.clients, c) delete(c.p.clients, c)
c.conn.NetConn().Close() c.conn.NetConn().Close()
close(c.chanWrite) close(c.write)
if c.path != "" { if c.path != "" {
if pub, ok := c.p.publishers[c.path]; ok && pub == c { if pub, ok := c.p.publishers[c.path]; ok && pub == c {
@ -755,7 +755,7 @@ func (c *serverClient) handleRequest(req *gortsplib.Request) bool {
if c.streamProtocol == _STREAM_PROTOCOL_TCP { if c.streamProtocol == _STREAM_PROTOCOL_TCP {
// write RTP frames sequentially // write RTP frames sequentially
go func() { go func() {
for frame := range c.chanWrite { for frame := range c.write {
c.conn.WriteInterleavedFrame(frame) c.conn.WriteInterleavedFrame(frame)
} }
}() }()

109
server-udpl.go

@ -12,10 +12,11 @@ type udpWrite struct {
} }
type serverUdpListener struct { type serverUdpListener struct {
p *program p *program
nconn *net.UDPConn nconn *net.UDPConn
flow trackFlow flow trackFlow
chanWrite chan *udpWrite write chan *udpWrite
done chan struct{}
} }
func newServerUdpListener(p *program, port int, flow trackFlow) (*serverUdpListener, error) { func newServerUdpListener(p *program, port int, flow trackFlow) (*serverUdpListener, error) {
@ -27,10 +28,11 @@ func newServerUdpListener(p *program, port int, flow trackFlow) (*serverUdpListe
} }
l := &serverUdpListener{ l := &serverUdpListener{
p: p, p: p,
nconn: nconn, nconn: nconn,
flow: flow, flow: flow,
chanWrite: make(chan *udpWrite), write: make(chan *udpWrite),
done: make(chan struct{}),
} }
l.log("opened on :%d", port) l.log("opened on :%d", port)
@ -49,56 +51,61 @@ func (l *serverUdpListener) log(format string, args ...interface{}) {
func (l *serverUdpListener) run() { func (l *serverUdpListener) run() {
go func() { go func() {
for { for w := range l.write {
// create a buffer for each read. l.nconn.SetWriteDeadline(time.Now().Add(_WRITE_TIMEOUT))
// this is necessary since the buffer is propagated with channels l.nconn.WriteTo(w.buf, w.addr)
// so it must be unique. }
buf := make([]byte, 2048) // UDP MTU is 1400 }()
n, addr, err := l.nconn.ReadFromUDP(buf)
if err != nil { for {
l.log("ERR: %s", err) // create a buffer for each read.
break // this is necessary since the buffer is propagated with channels
} // so it must be unique.
buf := make([]byte, 2048) // UDP MTU is 1400
n, addr, err := l.nconn.ReadFromUDP(buf)
if err != nil {
break
}
func() { func() {
l.p.mutex.RLock() l.p.mutex.RLock()
defer l.p.mutex.RUnlock() defer l.p.mutex.RUnlock()
// find path and track id from ip and port // find path and track id from ip and port
path, trackId := func() (string, int) { path, trackId := func() (string, int) {
for _, pub := range l.p.publishers { for _, pub := range l.p.publishers {
for i, t := range pub.streamTracks { for i, t := range pub.streamTracks {
if !pub.ip().Equal(addr.IP) { if !pub.ip().Equal(addr.IP) {
continue continue
} }
if l.flow == _TRACK_FLOW_RTP { if l.flow == _TRACK_FLOW_RTP {
if t.rtpPort == addr.Port { if t.rtpPort == addr.Port {
return pub.path, i return pub.path, i
} }
} else { } else {
if t.rtcpPort == addr.Port { if t.rtcpPort == addr.Port {
return pub.path, i return pub.path, i
}
} }
} }
} }
return "", -1
}()
if path == "" {
return
} }
return "", -1
l.p.forwardTrack(path, trackId, l.flow, buf[:n])
}() }()
} if path == "" {
}() return
}
go func() { l.p.forwardTrack(path, trackId, l.flow, buf[:n])
for { }()
w := <-l.chanWrite }
l.nconn.SetWriteDeadline(time.Now().Add(_WRITE_TIMEOUT))
l.nconn.WriteTo(w.buf, w.addr) close(l.write)
}
}() l.done <- struct{}{}
}
func (l *serverUdpListener) close() {
l.nconn.Close()
<-l.done
} }

Loading…
Cancel
Save