diff --git a/client.go b/client.go index a03d8593..aca2694b 100644 --- a/client.go +++ b/client.go @@ -494,7 +494,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error { return errRunTerminate } - if _, ok := th["multicast"]; ok { + if th.Cast != nil && *th.Cast == gortsplib.StreamMulticast { c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("multicast is not supported")) return errRunTerminate } @@ -548,7 +548,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error { } // play via UDP - if th.IsUDP() { + if th.Protocol == gortsplib.StreamProtocolUDP { if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolUDP]; !ok { c.writeResError(cseq, gortsplib.StatusUnsupportedTransport, fmt.Errorf("UDP streaming is disabled")) return errRunTerminate @@ -559,8 +559,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error { return errRunTerminate } - rtpPort, rtcpPort := th.Ports("client_port") - if rtpPort == 0 || rtcpPort == 0 { + if th.ClientPorts == nil { c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not have valid client ports (%v)", req.Header["Transport"])) return errRunTerminate } @@ -575,27 +574,32 @@ func (c *client) handleRequest(req *gortsplib.Request) error { c.streamProtocol = gortsplib.StreamProtocolUDP c.streamTracks[trackId] = &clientTrack{ - rtpPort: rtpPort, - rtcpPort: rtcpPort, + rtpPort: (*th.ClientPorts)[0], + rtcpPort: (*th.ClientPorts)[1], + } + + th := &gortsplib.HeaderTransport{ + Protocol: gortsplib.StreamProtocolUDP, + Cast: func() *gortsplib.StreamCast { + v := gortsplib.StreamUnicast + return &v + }(), + ClientPorts: th.ClientPorts, + ServerPorts: &[2]int{c.p.conf.RtpPort, c.p.conf.RtcpPort}, } c.conn.WriteResponse(&gortsplib.Response{ StatusCode: gortsplib.StatusOK, Header: gortsplib.Header{ - "CSeq": cseq, - "Transport": gortsplib.HeaderValue{strings.Join([]string{ - "RTP/AVP/UDP", - "unicast", - fmt.Sprintf("client_port=%d-%d", rtpPort, rtcpPort), - fmt.Sprintf("server_port=%d-%d", c.p.conf.RtpPort, c.p.conf.RtcpPort), - }, ";")}, - "Session": gortsplib.HeaderValue{"12345678"}, + "CSeq": cseq, + "Transport": th.Write(), + "Session": gortsplib.HeaderValue{"12345678"}, }, }) return nil // play via TCP - } else if th.IsTCP() { + } else { if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolTCP]; !ok { c.writeResError(cseq, gortsplib.StatusUnsupportedTransport, fmt.Errorf("TCP streaming is disabled")) return errRunTerminate @@ -620,30 +624,27 @@ func (c *client) handleRequest(req *gortsplib.Request) error { rtcpPort: 0, } - interleaved := fmt.Sprintf("%d-%d", ((trackId) * 2), ((trackId)*2)+1) + interleavedIds := [2]int{trackId * 2, (trackId * 2) + 1} + + th := &gortsplib.HeaderTransport{ + Protocol: gortsplib.StreamProtocolTCP, + InterleavedIds: &interleavedIds, + } c.conn.WriteResponse(&gortsplib.Response{ StatusCode: gortsplib.StatusOK, Header: gortsplib.Header{ - "CSeq": cseq, - "Transport": gortsplib.HeaderValue{strings.Join([]string{ - "RTP/AVP/TCP", - "unicast", - fmt.Sprintf("interleaved=%s", interleaved), - }, ";")}, - "Session": gortsplib.HeaderValue{"12345678"}, + "CSeq": cseq, + "Transport": th.Write(), + "Session": gortsplib.HeaderValue{"12345678"}, }, }) return nil - - } else { - c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain a valid protocol (RTP/AVP, RTP/AVP/UDP or RTP/AVP/TCP) (%s)", req.Header["Transport"])) - return errRunTerminate } // record case clientStatePreRecord: - if strings.ToLower(th.Value("mode")) != "record" { + if th.Mode == nil || *th.Mode != "record" { c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain mode=record")) return errRunTerminate } @@ -655,7 +656,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error { } // record via UDP - if th.IsUDP() { + if th.Protocol == gortsplib.StreamProtocolUDP { if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolUDP]; !ok { c.writeResError(cseq, gortsplib.StatusUnsupportedTransport, fmt.Errorf("UDP streaming is disabled")) return errRunTerminate @@ -666,8 +667,7 @@ func (c *client) handleRequest(req *gortsplib.Request) error { return errRunTerminate } - rtpPort, rtcpPort := th.Ports("client_port") - if rtpPort == 0 || rtcpPort == 0 { + if th.ClientPorts == nil { c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not have valid client ports (%s)", req.Header["Transport"])) return errRunTerminate } @@ -679,27 +679,32 @@ func (c *client) handleRequest(req *gortsplib.Request) error { c.streamProtocol = gortsplib.StreamProtocolUDP c.streamTracks[len(c.streamTracks)] = &clientTrack{ - rtpPort: rtpPort, - rtcpPort: rtcpPort, + rtpPort: (*th.ClientPorts)[0], + rtcpPort: (*th.ClientPorts)[1], + } + + th := &gortsplib.HeaderTransport{ + Protocol: gortsplib.StreamProtocolUDP, + Cast: func() *gortsplib.StreamCast { + v := gortsplib.StreamUnicast + return &v + }(), + ClientPorts: th.ClientPorts, + ServerPorts: &[2]int{c.p.conf.RtpPort, c.p.conf.RtcpPort}, } c.conn.WriteResponse(&gortsplib.Response{ StatusCode: gortsplib.StatusOK, Header: gortsplib.Header{ - "CSeq": cseq, - "Transport": gortsplib.HeaderValue{strings.Join([]string{ - "RTP/AVP/UDP", - "unicast", - fmt.Sprintf("client_port=%d-%d", rtpPort, rtcpPort), - fmt.Sprintf("server_port=%d-%d", c.p.conf.RtpPort, c.p.conf.RtcpPort), - }, ";")}, - "Session": gortsplib.HeaderValue{"12345678"}, + "CSeq": cseq, + "Transport": th.Write(), + "Session": gortsplib.HeaderValue{"12345678"}, }, }) return nil // record via TCP - } else if th.IsTCP() { + } else { if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolTCP]; !ok { c.writeResError(cseq, gortsplib.StatusUnsupportedTransport, fmt.Errorf("TCP streaming is disabled")) return errRunTerminate @@ -710,15 +715,15 @@ func (c *client) handleRequest(req *gortsplib.Request) error { return errRunTerminate } - interleaved := th.Value("interleaved") - if interleaved == "" { + interleavedIds := [2]int{len(c.streamTracks) * 2, 1 + len(c.streamTracks)*2} + + if th.InterleavedIds == nil { c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain the interleaved field")) return errRunTerminate } - expInterleaved := fmt.Sprintf("%d-%d", 0+len(c.streamTracks)*2, 1+len(c.streamTracks)*2) - if interleaved != expInterleaved { - c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("wrong interleaved value, expected '%s', got '%s'", expInterleaved, interleaved)) + if (*th.InterleavedIds)[0] != interleavedIds[0] || (*th.InterleavedIds)[1] != interleavedIds[1] { + c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("wrong interleaved ids, expected %v, got %v", interleavedIds, *th.InterleavedIds)) return errRunTerminate } @@ -733,23 +738,20 @@ func (c *client) handleRequest(req *gortsplib.Request) error { rtcpPort: 0, } + ht := &gortsplib.HeaderTransport{ + Protocol: gortsplib.StreamProtocolTCP, + InterleavedIds: &interleavedIds, + } + c.conn.WriteResponse(&gortsplib.Response{ StatusCode: gortsplib.StatusOK, Header: gortsplib.Header{ - "CSeq": cseq, - "Transport": gortsplib.HeaderValue{strings.Join([]string{ - "RTP/AVP/TCP", - "unicast", - fmt.Sprintf("interleaved=%s", interleaved), - }, ";")}, - "Session": gortsplib.HeaderValue{"12345678"}, + "CSeq": cseq, + "Transport": ht.Write(), + "Session": gortsplib.HeaderValue{"12345678"}, }, }) return nil - - } else { - c.writeResError(cseq, gortsplib.StatusBadRequest, fmt.Errorf("transport header does not contain a valid protocol (RTP/AVP, RTP/AVP/UDP or RTP/AVP/TCP) (%s)", req.Header["Transport"])) - return errRunTerminate } default: diff --git a/go.mod b/go.mod index 563664db..11e0c567 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.12 require ( github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect - github.com/aler9/gortsplib v0.0.0-20200905183437-37e3a1f29f40 + github.com/aler9/gortsplib v0.0.0-20200905203510-a2addc0fc446 github.com/davecgh/go-spew v1.1.1 // indirect github.com/stretchr/testify v1.6.1 gopkg.in/alecthomas/kingpin.v2 v2.2.6 diff --git a/go.sum b/go.sum index 8d11fcce..d3f714c2 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/aler9/gortsplib v0.0.0-20200905183437-37e3a1f29f40 h1:l6De9lyccqCRoIlUrTi5XfHku8oO2V1LAbqROGeJuo4= -github.com/aler9/gortsplib v0.0.0-20200905183437-37e3a1f29f40/go.mod h1:XybE/Zt1yFtnNEjNhAyg2w6VjD8aJ79GFfpSjkfLNd8= +github.com/aler9/gortsplib v0.0.0-20200905203510-a2addc0fc446 h1:HfBcbZEKf202ssmZStJzAdVHxyopmRvRaEdy/2+JnLw= +github.com/aler9/gortsplib v0.0.0-20200905203510-a2addc0fc446/go.mod h1:XybE/Zt1yFtnNEjNhAyg2w6VjD8aJ79GFfpSjkfLNd8= github.com/aler9/sdp-dirty/v3 v3.0.0-20200905103724-214b7cc25cfd h1:s/l20rPNGiyjggMdkhsLu0aQ0K0OFcROUMBDu7fGT+I= github.com/aler9/sdp-dirty/v3 v3.0.0-20200905103724-214b7cc25cfd/go.mod h1:5bO/aUQr9m3OasDatNNcVqKAgs7r5hgGXmszWHaC6mI= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=