mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 15:16:51 +08:00
move errors into subpackage
This commit is contained in:
175
clientconn.go
175
clientconn.go
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/aler9/gortsplib/pkg/auth"
|
"github.com/aler9/gortsplib/pkg/auth"
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
"github.com/aler9/gortsplib/pkg/headers"
|
"github.com/aler9/gortsplib/pkg/headers"
|
||||||
|
"github.com/aler9/gortsplib/pkg/liberrors"
|
||||||
"github.com/aler9/gortsplib/pkg/multibuffer"
|
"github.com/aler9/gortsplib/pkg/multibuffer"
|
||||||
"github.com/aler9/gortsplib/pkg/rtcpreceiver"
|
"github.com/aler9/gortsplib/pkg/rtcpreceiver"
|
||||||
"github.com/aler9/gortsplib/pkg/rtcpsender"
|
"github.com/aler9/gortsplib/pkg/rtcpsender"
|
||||||
@@ -35,142 +36,6 @@ const (
|
|||||||
clientConnUDPKeepalivePeriod = 30 * time.Second
|
clientConnUDPKeepalivePeriod = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrClientWrongState is returned in case of a wrong client state.
|
|
||||||
type ErrClientWrongState struct {
|
|
||||||
allowedList []clientConnState
|
|
||||||
state clientConnState
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientWrongState) Error() string {
|
|
||||||
return fmt.Sprintf("must be in state %v, while is in state %v",
|
|
||||||
e.allowedList, e.state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientSessionHeaderInvalid is returned in case of an invalid session header.
|
|
||||||
type ErrClientSessionHeaderInvalid struct {
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientSessionHeaderInvalid) Error() string {
|
|
||||||
return fmt.Sprintf("invalid session header: %v", e.err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientWrongStatusCode is returned in case of a wrong status code.
|
|
||||||
type ErrClientWrongStatusCode struct {
|
|
||||||
code base.StatusCode
|
|
||||||
message string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientWrongStatusCode) Error() string {
|
|
||||||
return fmt.Sprintf("wrong status code: %d (%s)", e.code, e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientContentTypeMissing is returned in case the Content-Type header is missing.
|
|
||||||
type ErrClientContentTypeMissing struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientContentTypeMissing) Error() string {
|
|
||||||
return "Content-Type header is missing"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientContentTypeUnsupported is returned in case the Content-Type header is unsupported.
|
|
||||||
type ErrClientContentTypeUnsupported struct {
|
|
||||||
ct base.HeaderValue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientContentTypeUnsupported) Error() string {
|
|
||||||
return fmt.Sprintf("unsupported Content-Type header '%v'", e.ct)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientCannotReadPublishAtSameTime is returned when the client is trying to read and publish at the same time.
|
|
||||||
type ErrClientCannotReadPublishAtSameTime struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientCannotReadPublishAtSameTime) Error() string {
|
|
||||||
return "cannot read and publish at the same time"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientCannotSetupTracksDifferentURLs is returned when the client is trying to setup tracks with different base URLs.
|
|
||||||
type ErrClientCannotSetupTracksDifferentURLs struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientCannotSetupTracksDifferentURLs) Error() string {
|
|
||||||
return "cannot setup tracks with different base URLs"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientUDPPortsZero is returned when one of the UDP ports is zero.
|
|
||||||
type ErrClientUDPPortsZero struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientUDPPortsZero) Error() string {
|
|
||||||
return "rtpPort and rtcpPort must be both zero or non-zero"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientUDPPortsNotConsecutive is returned when the two UDP ports are not consecutive.
|
|
||||||
type ErrClientUDPPortsNotConsecutive struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientUDPPortsNotConsecutive) Error() string {
|
|
||||||
return "rtcpPort must be rtpPort + 1"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientServerPortsZero is returned when one of the server ports is zero.
|
|
||||||
type ErrClientServerPortsZero struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientServerPortsZero) Error() string {
|
|
||||||
return "server ports must be both zero or both not zero"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientServerPortsNotProvided is returned in case the server ports have not been provided.
|
|
||||||
type ErrClientServerPortsNotProvided struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientServerPortsNotProvided) Error() string {
|
|
||||||
return "server ports have not been provided. Use AnyPortEnable to communicate with this server"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientTransportHeaderNoInterleavedIDs is returned in case the transport header doesn't contain interleaved IDs.
|
|
||||||
type ErrClientTransportHeaderNoInterleavedIDs struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientTransportHeaderNoInterleavedIDs) Error() string {
|
|
||||||
return "transport header does not contain interleaved IDs"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientTransportHeaderWrongInterleavedIDs is returned in case the transport header contains wrong interleaved IDs.
|
|
||||||
type ErrClientTransportHeaderWrongInterleavedIDs struct {
|
|
||||||
expected [2]int
|
|
||||||
value [2]int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientTransportHeaderWrongInterleavedIDs) Error() string {
|
|
||||||
return fmt.Sprintf("wrong interleaved IDs, expected %v, got %v", e.expected, e.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientNoUDPPacketsRecently is returned when no UDP packets have been received recently.
|
|
||||||
type ErrClientNoUDPPacketsRecently struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientNoUDPPacketsRecently) Error() string {
|
|
||||||
return "no UDP packets received recently (maybe there's a firewall/NAT in between)"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrClientRTPInfoInvalid is returned in case of an invalid RTP-Info.
|
|
||||||
type ErrClientRTPInfoInvalid struct {
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrClientRTPInfoInvalid) Error() string {
|
|
||||||
return fmt.Sprintf("unable to parse RTP-Info: %v", e.err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientConnState int
|
type clientConnState int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -329,13 +194,13 @@ func (c *ClientConn) checkState(allowed map[clientConnState]struct{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedList := make([]clientConnState, len(allowed))
|
allowedList := make([]fmt.Stringer, len(allowed))
|
||||||
i := 0
|
i := 0
|
||||||
for a := range allowed {
|
for a := range allowed {
|
||||||
allowedList[i] = a
|
allowedList[i] = a
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return ErrClientWrongState{allowedList, c.state}
|
return liberrors.ErrClientWrongState{AllowedList: allowedList, State: c.state}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetConn returns the underlying net.Conn.
|
// NetConn returns the underlying net.Conn.
|
||||||
@@ -406,7 +271,7 @@ func (c *ClientConn) Do(req *base.Request) (*base.Response, error) {
|
|||||||
var sx headers.Session
|
var sx headers.Session
|
||||||
err := sx.Read(v)
|
err := sx.Read(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrClientSessionHeaderInvalid{err}
|
return nil, liberrors.ErrClientSessionHeaderInvalid{Err: err}
|
||||||
}
|
}
|
||||||
c.session = sx.Session
|
c.session = sx.Session
|
||||||
}
|
}
|
||||||
@@ -454,7 +319,7 @@ func (c *ClientConn) Options(u *base.URL) (*base.Response, error) {
|
|||||||
if res.StatusCode == base.StatusNotFound {
|
if res.StatusCode == base.StatusNotFound {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
return res, ErrClientWrongStatusCode{res.StatusCode, res.StatusMessage}
|
return res, liberrors.ErrClientWrongStatusCode{Code: res.StatusCode, Message: res.StatusMessage}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.getParameterSupported = func() bool {
|
c.getParameterSupported = func() bool {
|
||||||
@@ -524,16 +389,16 @@ func (c *ClientConn) Describe(u *base.URL) (Tracks, *base.Response, error) {
|
|||||||
return c.Describe(u)
|
return c.Describe(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, res, ErrClientWrongStatusCode{res.StatusCode, res.StatusMessage}
|
return nil, res, liberrors.ErrClientWrongStatusCode{Code: res.StatusCode, Message: res.StatusMessage}
|
||||||
}
|
}
|
||||||
|
|
||||||
ct, ok := res.Header["Content-Type"]
|
ct, ok := res.Header["Content-Type"]
|
||||||
if !ok || len(ct) != 1 {
|
if !ok || len(ct) != 1 {
|
||||||
return nil, nil, ErrClientContentTypeMissing{}
|
return nil, nil, liberrors.ErrClientContentTypeMissing{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ct[0] != "application/sdp" {
|
if ct[0] != "application/sdp" {
|
||||||
return nil, nil, ErrClientContentTypeUnsupported{ct}
|
return nil, nil, liberrors.ErrClientContentTypeUnsupported{CT: ct}
|
||||||
}
|
}
|
||||||
|
|
||||||
tracks, err := ReadTracks(res.Body, u)
|
tracks, err := ReadTracks(res.Body, u)
|
||||||
@@ -561,11 +426,11 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track,
|
|||||||
if (mode == headers.TransportModeRecord && c.state != clientConnStatePreRecord) ||
|
if (mode == headers.TransportModeRecord && c.state != clientConnStatePreRecord) ||
|
||||||
(mode == headers.TransportModePlay && c.state != clientConnStatePrePlay &&
|
(mode == headers.TransportModePlay && c.state != clientConnStatePrePlay &&
|
||||||
c.state != clientConnStateInitial) {
|
c.state != clientConnStateInitial) {
|
||||||
return nil, ErrClientCannotReadPublishAtSameTime{}
|
return nil, liberrors.ErrClientCannotReadPublishAtSameTime{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.streamURL != nil && *track.BaseURL != *c.streamURL {
|
if c.streamURL != nil && *track.BaseURL != *c.streamURL {
|
||||||
return nil, ErrClientCannotSetupTracksDifferentURLs{}
|
return nil, liberrors.ErrClientCannotSetupTracksDifferentURLs{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rtpListener *clientConnUDPListener
|
var rtpListener *clientConnUDPListener
|
||||||
@@ -604,11 +469,11 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track,
|
|||||||
if proto == base.StreamProtocolUDP {
|
if proto == base.StreamProtocolUDP {
|
||||||
if (rtpPort == 0 && rtcpPort != 0) ||
|
if (rtpPort == 0 && rtcpPort != 0) ||
|
||||||
(rtpPort != 0 && rtcpPort == 0) {
|
(rtpPort != 0 && rtcpPort == 0) {
|
||||||
return nil, ErrClientUDPPortsZero{}
|
return nil, liberrors.ErrClientUDPPortsZero{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rtpPort != 0 && rtcpPort != (rtpPort+1) {
|
if rtpPort != 0 && rtcpPort != (rtpPort+1) {
|
||||||
return nil, ErrClientUDPPortsNotConsecutive{}
|
return nil, liberrors.ErrClientUDPPortsNotConsecutive{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@@ -700,7 +565,7 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track,
|
|||||||
return c.Setup(headers.TransportModePlay, track, 0, 0)
|
return c.Setup(headers.TransportModePlay, track, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, ErrClientWrongStatusCode{res.StatusCode, res.StatusMessage}
|
return res, liberrors.ErrClientWrongStatusCode{Code: res.StatusCode, Message: res.StatusMessage}
|
||||||
}
|
}
|
||||||
|
|
||||||
var thRes headers.Transport
|
var thRes headers.Transport
|
||||||
@@ -710,7 +575,7 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track,
|
|||||||
rtpListener.close()
|
rtpListener.close()
|
||||||
rtcpListener.close()
|
rtcpListener.close()
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("transport header: %s", err)
|
return nil, liberrors.ErrClientTransportHeaderInvalid{Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if proto == StreamProtocolUDP {
|
if proto == StreamProtocolUDP {
|
||||||
@@ -719,7 +584,7 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track,
|
|||||||
(thRes.ServerPorts[0] != 0 && thRes.ServerPorts[1] == 0) {
|
(thRes.ServerPorts[0] != 0 && thRes.ServerPorts[1] == 0) {
|
||||||
rtpListener.close()
|
rtpListener.close()
|
||||||
rtcpListener.close()
|
rtcpListener.close()
|
||||||
return nil, ErrClientServerPortsZero{}
|
return nil, liberrors.ErrClientServerPortsZero{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -727,18 +592,19 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track,
|
|||||||
if thRes.ServerPorts == nil || (thRes.ServerPorts[0] == 0 && thRes.ServerPorts[1] == 0) {
|
if thRes.ServerPorts == nil || (thRes.ServerPorts[0] == 0 && thRes.ServerPorts[1] == 0) {
|
||||||
rtpListener.close()
|
rtpListener.close()
|
||||||
rtcpListener.close()
|
rtcpListener.close()
|
||||||
return nil, ErrClientServerPortsNotProvided{}
|
return nil, liberrors.ErrClientServerPortsNotProvided{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if thRes.InterleavedIDs == nil {
|
if thRes.InterleavedIDs == nil {
|
||||||
return nil, ErrClientTransportHeaderNoInterleavedIDs{}
|
return nil, liberrors.ErrClientTransportHeaderNoInterleavedIDs{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if thRes.InterleavedIDs[0] != th.InterleavedIDs[0] ||
|
if thRes.InterleavedIDs[0] != th.InterleavedIDs[0] ||
|
||||||
thRes.InterleavedIDs[1] != th.InterleavedIDs[1] {
|
thRes.InterleavedIDs[1] != th.InterleavedIDs[1] {
|
||||||
return nil, ErrClientTransportHeaderWrongInterleavedIDs{*th.InterleavedIDs, *thRes.InterleavedIDs}
|
return nil, liberrors.ErrClientTransportHeaderWrongInterleavedIDs{
|
||||||
|
Expected: *th.InterleavedIDs, Value: *thRes.InterleavedIDs}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,7 +677,8 @@ func (c *ClientConn) Pause() (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.StatusCode != base.StatusOK {
|
if res.StatusCode != base.StatusOK {
|
||||||
return res, ErrClientWrongStatusCode{res.StatusCode, res.StatusMessage}
|
return res, liberrors.ErrClientWrongStatusCode{
|
||||||
|
Code: res.StatusCode, Message: res.StatusMessage}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch c.state {
|
switch c.state {
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
psdp "github.com/pion/sdp/v3"
|
psdp "github.com/pion/sdp/v3"
|
||||||
|
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
"github.com/aler9/gortsplib/pkg/liberrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Announce writes an ANNOUNCE request and reads a Response.
|
// Announce writes an ANNOUNCE request and reads a Response.
|
||||||
@@ -43,7 +44,8 @@ func (c *ClientConn) Announce(u *base.URL, tracks Tracks) (*base.Response, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.StatusCode != base.StatusOK {
|
if res.StatusCode != base.StatusOK {
|
||||||
return nil, ErrClientWrongStatusCode{res.StatusCode, res.StatusMessage}
|
return nil, liberrors.ErrClientWrongStatusCode{
|
||||||
|
Code: res.StatusCode, Message: res.StatusMessage}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.streamURL = u
|
c.streamURL = u
|
||||||
@@ -71,7 +73,8 @@ func (c *ClientConn) Record() (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.StatusCode != base.StatusOK {
|
if res.StatusCode != base.StatusOK {
|
||||||
return nil, ErrClientWrongStatusCode{res.StatusCode, res.StatusMessage}
|
return nil, liberrors.ErrClientWrongStatusCode{
|
||||||
|
Code: res.StatusCode, Message: res.StatusMessage}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.state = clientConnStateRecord
|
c.state = clientConnStateRecord
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
"github.com/aler9/gortsplib/pkg/headers"
|
"github.com/aler9/gortsplib/pkg/headers"
|
||||||
|
"github.com/aler9/gortsplib/pkg/liberrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Play writes a PLAY request and reads a Response.
|
// Play writes a PLAY request and reads a Response.
|
||||||
@@ -28,14 +29,15 @@ func (c *ClientConn) Play() (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if res.StatusCode != base.StatusOK {
|
if res.StatusCode != base.StatusOK {
|
||||||
return nil, ErrClientWrongStatusCode{res.StatusCode, res.StatusMessage}
|
return nil, liberrors.ErrClientWrongStatusCode{
|
||||||
|
Code: res.StatusCode, Message: res.StatusMessage}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := res.Header["RTP-Info"]; ok {
|
if v, ok := res.Header["RTP-Info"]; ok {
|
||||||
var ri headers.RTPInfo
|
var ri headers.RTPInfo
|
||||||
err := ri.Read(v)
|
err := ri.Read(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrClientRTPInfoInvalid{err}
|
return nil, liberrors.ErrClientRTPInfoInvalid{Err: err}
|
||||||
}
|
}
|
||||||
c.rtpInfo = &ri
|
c.rtpInfo = &ri
|
||||||
}
|
}
|
||||||
@@ -144,7 +146,7 @@ func (c *ClientConn) backgroundPlayUDP(done chan error) {
|
|||||||
if now.Sub(last) >= c.conf.ReadTimeout {
|
if now.Sub(last) >= c.conf.ReadTimeout {
|
||||||
c.nconn.SetReadDeadline(time.Now())
|
c.nconn.SetReadDeadline(time.Now())
|
||||||
<-readerDone
|
<-readerDone
|
||||||
returnError = ErrClientNoUDPPacketsRecently{}
|
returnError = liberrors.ErrClientNoUDPPacketsRecently{}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
153
pkg/liberrors/client.go
Normal file
153
pkg/liberrors/client.go
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
package liberrors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrClientWrongState is returned in case of a wrong client state.
|
||||||
|
type ErrClientWrongState struct {
|
||||||
|
AllowedList []fmt.Stringer
|
||||||
|
State fmt.Stringer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientWrongState) Error() string {
|
||||||
|
return fmt.Sprintf("must be in state %v, while is in state %v",
|
||||||
|
e.AllowedList, e.State)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientSessionHeaderInvalid is returned in case of an invalid session header.
|
||||||
|
type ErrClientSessionHeaderInvalid struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientSessionHeaderInvalid) Error() string {
|
||||||
|
return fmt.Sprintf("invalid session header: %v", e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientWrongStatusCode is returned in case of a wrong status code.
|
||||||
|
type ErrClientWrongStatusCode struct {
|
||||||
|
Code base.StatusCode
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientWrongStatusCode) Error() string {
|
||||||
|
return fmt.Sprintf("wrong status code: %d (%s)", e.Code, e.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientContentTypeMissing is returned in case the Content-Type header is missing.
|
||||||
|
type ErrClientContentTypeMissing struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientContentTypeMissing) Error() string {
|
||||||
|
return "Content-Type header is missing"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientContentTypeUnsupported is returned in case the Content-Type header is unsupported.
|
||||||
|
type ErrClientContentTypeUnsupported struct {
|
||||||
|
CT base.HeaderValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientContentTypeUnsupported) Error() string {
|
||||||
|
return fmt.Sprintf("unsupported Content-Type header '%v'", e.CT)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientCannotReadPublishAtSameTime is returned when the client is trying to read and publish at the same time.
|
||||||
|
type ErrClientCannotReadPublishAtSameTime struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientCannotReadPublishAtSameTime) Error() string {
|
||||||
|
return "cannot read and publish at the same time"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientCannotSetupTracksDifferentURLs is returned when the client is trying to setup tracks with different base URLs.
|
||||||
|
type ErrClientCannotSetupTracksDifferentURLs struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientCannotSetupTracksDifferentURLs) Error() string {
|
||||||
|
return "cannot setup tracks with different base URLs"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientUDPPortsZero is returned when one of the UDP ports is zero.
|
||||||
|
type ErrClientUDPPortsZero struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientUDPPortsZero) Error() string {
|
||||||
|
return "rtpPort and rtcpPort must be both zero or non-zero"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientUDPPortsNotConsecutive is returned when the two UDP ports are not consecutive.
|
||||||
|
type ErrClientUDPPortsNotConsecutive struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientUDPPortsNotConsecutive) Error() string {
|
||||||
|
return "rtcpPort must be rtpPort + 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientServerPortsZero is returned when one of the server ports is zero.
|
||||||
|
type ErrClientServerPortsZero struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientServerPortsZero) Error() string {
|
||||||
|
return "server ports must be both zero or both not zero"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientServerPortsNotProvided is returned in case the server ports have not been provided.
|
||||||
|
type ErrClientServerPortsNotProvided struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientServerPortsNotProvided) Error() string {
|
||||||
|
return "server ports have not been provided. Use AnyPortEnable to communicate with this server"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientTransportHeaderInvalid is returned in case the transport header is invalid.
|
||||||
|
type ErrClientTransportHeaderInvalid struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientTransportHeaderInvalid) Error() string {
|
||||||
|
return fmt.Sprintf("invalid transport header: %v", e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientTransportHeaderNoInterleavedIDs is returned in case the transport header doesn't contain interleaved IDs.
|
||||||
|
type ErrClientTransportHeaderNoInterleavedIDs struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientTransportHeaderNoInterleavedIDs) Error() string {
|
||||||
|
return "transport header does not contain interleaved IDs"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientTransportHeaderWrongInterleavedIDs is returned in case the transport header contains wrong interleaved IDs.
|
||||||
|
type ErrClientTransportHeaderWrongInterleavedIDs struct {
|
||||||
|
Expected [2]int
|
||||||
|
Value [2]int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientTransportHeaderWrongInterleavedIDs) Error() string {
|
||||||
|
return fmt.Sprintf("wrong interleaved IDs, expected %v, got %v", e.Expected, e.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientNoUDPPacketsRecently is returned when no UDP packets have been received recently.
|
||||||
|
type ErrClientNoUDPPacketsRecently struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientNoUDPPacketsRecently) Error() string {
|
||||||
|
return "no UDP packets received recently (maybe there's a firewall/NAT in between)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrClientRTPInfoInvalid is returned in case of an invalid RTP-Info.
|
||||||
|
type ErrClientRTPInfoInvalid struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrClientRTPInfoInvalid) Error() string {
|
||||||
|
return fmt.Sprintf("invalid RTP-Info: %v", e.Err)
|
||||||
|
}
|
2
pkg/liberrors/liberrors.go
Normal file
2
pkg/liberrors/liberrors.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package liberrors contains errors returned by the library.
|
||||||
|
package liberrors
|
169
pkg/liberrors/server.go
Normal file
169
pkg/liberrors/server.go
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
package liberrors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
"github.com/aler9/gortsplib/pkg/headers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrServerTeardown is returned in case of a teardown request.
|
||||||
|
type ErrServerTeardown struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTeardown) Error() string {
|
||||||
|
return "teardown"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerCSeqMissing is returned in case the CSeq is missing.
|
||||||
|
type ErrServerCSeqMissing struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerCSeqMissing) Error() string {
|
||||||
|
return "CSeq is missing"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerWrongState is returned in case of a wrong client state.
|
||||||
|
type ErrServerWrongState struct {
|
||||||
|
AllowedList []fmt.Stringer
|
||||||
|
State fmt.Stringer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerWrongState) Error() string {
|
||||||
|
return fmt.Sprintf("must be in state %v, while is in state %v",
|
||||||
|
e.AllowedList, e.State)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerNoPath is returned in case the path can't be retrieved.
|
||||||
|
type ErrServerNoPath struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerNoPath) Error() string {
|
||||||
|
return "RTSP path can't be retrieved"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerContentTypeMissing is returned in case the Content-Type header is missing.
|
||||||
|
type ErrServerContentTypeMissing struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerContentTypeMissing) Error() string {
|
||||||
|
return "Content-Type header is missing"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerContentTypeUnsupported is returned in case the Content-Type header is unsupported.
|
||||||
|
type ErrServerContentTypeUnsupported struct {
|
||||||
|
CT base.HeaderValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerContentTypeUnsupported) Error() string {
|
||||||
|
return fmt.Sprintf("unsupported Content-Type header '%v'", e.CT)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerSDPInvalid is returned in case the SDP is invalid.
|
||||||
|
type ErrServerSDPInvalid struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerSDPInvalid) Error() string {
|
||||||
|
return fmt.Sprintf("invalid SDP: %v", e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerSDPNoTracksDefined is returned in case the SDP has no tracks defined.
|
||||||
|
type ErrServerSDPNoTracksDefined struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerSDPNoTracksDefined) Error() string {
|
||||||
|
return "no tracks defined in the SDP"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerTransportHeaderInvalid is returned in case the transport header is invalid.
|
||||||
|
type ErrServerTransportHeaderInvalid struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTransportHeaderInvalid) Error() string {
|
||||||
|
return fmt.Sprintf("invalid transport header: %v", e.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerTrackAlreadySetup is returned in case a track has already been setup.
|
||||||
|
type ErrServerTrackAlreadySetup struct {
|
||||||
|
TrackID int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTrackAlreadySetup) Error() string {
|
||||||
|
return fmt.Sprintf("track %d has already been setup", e.TrackID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerTransportHeaderWrongMode is returned in case the transport header contains a wrong mode.
|
||||||
|
type ErrServerTransportHeaderWrongMode struct {
|
||||||
|
Mode *headers.TransportMode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTransportHeaderWrongMode) Error() string {
|
||||||
|
return fmt.Sprintf("transport header contains a wrong mode (%v)", e.Mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerTransportHeaderNoClientPorts is returned in case the transport header doesn't contain client ports.
|
||||||
|
type ErrServerTransportHeaderNoClientPorts struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTransportHeaderNoClientPorts) Error() string {
|
||||||
|
return "transport header does not contain client ports"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerTransportHeaderNoInterleavedIDs is returned in case the transport header doesn't contain interleaved IDs.
|
||||||
|
type ErrServerTransportHeaderNoInterleavedIDs struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTransportHeaderNoInterleavedIDs) Error() string {
|
||||||
|
return "transport header does not contain interleaved IDs"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerTransportHeaderWrongInterleavedIDs is returned in case the transport header contains wrong interleaved IDs.
|
||||||
|
type ErrServerTransportHeaderWrongInterleavedIDs struct {
|
||||||
|
Expected [2]int
|
||||||
|
Value [2]int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTransportHeaderWrongInterleavedIDs) Error() string {
|
||||||
|
return fmt.Sprintf("wrong interleaved IDs, expected %v, got %v", e.Expected, e.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerTracksDifferentProtocols is returned in case the client is trying to setup tracks with different protocols.
|
||||||
|
type ErrServerTracksDifferentProtocols struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerTracksDifferentProtocols) Error() string {
|
||||||
|
return "can't setup tracks with different protocols"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerNoTracksSetup is returned in case no tracks have been setup.
|
||||||
|
type ErrServerNoTracksSetup struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerNoTracksSetup) Error() string {
|
||||||
|
return "no tracks have been setup"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerNotAllAnnouncedTracksSetup is returned in case not all announced tracks have been setup.
|
||||||
|
type ErrServerNotAllAnnouncedTracksSetup struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerNotAllAnnouncedTracksSetup) Error() string {
|
||||||
|
return "not all announced tracks have been setup"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrServerNoUDPPacketsRecently is returned when no UDP packets have been received recently.
|
||||||
|
type ErrServerNoUDPPacketsRecently struct{}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ErrServerNoUDPPacketsRecently) Error() string {
|
||||||
|
return "no UDP packets received recently (maybe there's a firewall/NAT in between)"
|
||||||
|
}
|
226
serverconn.go
226
serverconn.go
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
"github.com/aler9/gortsplib/pkg/headers"
|
"github.com/aler9/gortsplib/pkg/headers"
|
||||||
|
"github.com/aler9/gortsplib/pkg/liberrors"
|
||||||
"github.com/aler9/gortsplib/pkg/multibuffer"
|
"github.com/aler9/gortsplib/pkg/multibuffer"
|
||||||
"github.com/aler9/gortsplib/pkg/ringbuffer"
|
"github.com/aler9/gortsplib/pkg/ringbuffer"
|
||||||
"github.com/aler9/gortsplib/pkg/rtcpreceiver"
|
"github.com/aler9/gortsplib/pkg/rtcpreceiver"
|
||||||
@@ -24,167 +25,6 @@ const (
|
|||||||
serverConnReceiverReportInterval = 10 * time.Second
|
serverConnReceiverReportInterval = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrServerTeardown is returned in case of a teardown request.
|
|
||||||
type ErrServerTeardown struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTeardown) Error() string {
|
|
||||||
return "teardown"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerCSeqMissing is returned in case the CSeq is missing.
|
|
||||||
type ErrServerCSeqMissing struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerCSeqMissing) Error() string {
|
|
||||||
return "CSeq is missing"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerWrongState is returned in case of a wrong client state.
|
|
||||||
type ErrServerWrongState struct {
|
|
||||||
allowedList []ServerConnState
|
|
||||||
state ServerConnState
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerWrongState) Error() string {
|
|
||||||
return fmt.Sprintf("must be in state %v, while is in state %v",
|
|
||||||
e.allowedList, e.state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerNoPath is returned in case the path can't be retrieved.
|
|
||||||
type ErrServerNoPath struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerNoPath) Error() string {
|
|
||||||
return "RTSP path can't be retrieved"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerContentTypeMissing is returned in case the Content-Type header is missing.
|
|
||||||
type ErrServerContentTypeMissing struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerContentTypeMissing) Error() string {
|
|
||||||
return "Content-Type header is missing"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerContentTypeUnsupported is returned in case the Content-Type header is unsupported.
|
|
||||||
type ErrServerContentTypeUnsupported struct {
|
|
||||||
ct base.HeaderValue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerContentTypeUnsupported) Error() string {
|
|
||||||
return fmt.Sprintf("unsupported Content-Type header '%v'", e.ct)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerSDPInvalid is returned in case the SDP is invalid.
|
|
||||||
type ErrServerSDPInvalid struct {
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerSDPInvalid) Error() string {
|
|
||||||
return fmt.Sprintf("invalid SDP: %v", e.err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerSDPNoTracksDefined is returned in case the SDP has no tracks defined.
|
|
||||||
type ErrServerSDPNoTracksDefined struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerSDPNoTracksDefined) Error() string {
|
|
||||||
return "no tracks defined in the SDP"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerTransportHeaderInvalid is returned in case the transport header is invalid.
|
|
||||||
type ErrServerTransportHeaderInvalid struct {
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTransportHeaderInvalid) Error() string {
|
|
||||||
return fmt.Sprintf("invalid transport header: %v", e.err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerTrackAlreadySetup is returned in case a track has already been setup.
|
|
||||||
type ErrServerTrackAlreadySetup struct {
|
|
||||||
trackID int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTrackAlreadySetup) Error() string {
|
|
||||||
return fmt.Sprintf("track %d has already been setup", e.trackID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerTransportHeaderWrongMode is returned in case the transport header contains a wrong mode.
|
|
||||||
type ErrServerTransportHeaderWrongMode struct {
|
|
||||||
mode *headers.TransportMode
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTransportHeaderWrongMode) Error() string {
|
|
||||||
return fmt.Sprintf("transport header contains a wrong mode (%v)", e.mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerTransportHeaderNoClientPorts is returned in case the transport header doesn't contain client ports.
|
|
||||||
type ErrServerTransportHeaderNoClientPorts struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTransportHeaderNoClientPorts) Error() string {
|
|
||||||
return "transport header does not contain client ports"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerTransportHeaderNoInterleavedIDs is returned in case the transport header doesn't contain interleaved IDs.
|
|
||||||
type ErrServerTransportHeaderNoInterleavedIDs struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTransportHeaderNoInterleavedIDs) Error() string {
|
|
||||||
return "transport header does not contain interleaved IDs"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerTransportHeaderWrongInterleavedIDs is returned in case the transport header contains wrong interleaved IDs.
|
|
||||||
type ErrServerTransportHeaderWrongInterleavedIDs struct {
|
|
||||||
expected [2]int
|
|
||||||
value [2]int
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTransportHeaderWrongInterleavedIDs) Error() string {
|
|
||||||
return fmt.Sprintf("wrong interleaved IDs, expected %v, got %v", e.expected, e.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerTracksDifferentProtocols is returned in case the client is trying to setup tracks with different protocols.
|
|
||||||
type ErrServerTracksDifferentProtocols struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerTracksDifferentProtocols) Error() string {
|
|
||||||
return "can't setup tracks with different protocols"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerNoTracksSetup is returned in case no tracks have been setup.
|
|
||||||
type ErrServerNoTracksSetup struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerNoTracksSetup) Error() string {
|
|
||||||
return "no tracks have been setup"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerNotAllAnnouncedTracksSetup is returned in case not all announced tracks have been setup.
|
|
||||||
type ErrServerNotAllAnnouncedTracksSetup struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerNotAllAnnouncedTracksSetup) Error() string {
|
|
||||||
return "not all announced tracks have been setup"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrServerNoUDPPacketsRecently is returned when no UDP packets have been received recently.
|
|
||||||
type ErrServerNoUDPPacketsRecently struct{}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (e ErrServerNoUDPPacketsRecently) Error() string {
|
|
||||||
return "no UDP packets received recently (maybe there's a firewall/NAT in between)"
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringsReverseIndex(s, substr string) int {
|
func stringsReverseIndex(s, substr string) int {
|
||||||
for i := len(s) - 1 - len(substr); i >= 0; i-- {
|
for i := len(s) - 1 - len(substr); i >= 0; i-- {
|
||||||
if s[i:i+len(substr)] == substr {
|
if s[i:i+len(substr)] == substr {
|
||||||
@@ -201,7 +41,7 @@ func setupGetTrackIDPathQuery(url *base.URL,
|
|||||||
|
|
||||||
pathAndQuery, ok := url.RTSPPathAndQuery()
|
pathAndQuery, ok := url.RTSPPathAndQuery()
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, "", "", ErrServerNoPath{}
|
return 0, "", "", liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if thMode == nil || *thMode == headers.TransportModePlay {
|
if thMode == nil || *thMode == headers.TransportModePlay {
|
||||||
@@ -519,13 +359,13 @@ func (sc *ServerConn) checkState(allowed map[ServerConnState]struct{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedList := make([]ServerConnState, len(allowed))
|
allowedList := make([]fmt.Stringer, len(allowed))
|
||||||
i := 0
|
i := 0
|
||||||
for a := range allowed {
|
for a := range allowed {
|
||||||
allowedList[i] = a
|
allowedList[i] = a
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return ErrServerWrongState{allowedList, sc.state}
|
return liberrors.ErrServerWrongState{AllowedList: allowedList, State: sc.state}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetConn returns the underlying net.Conn.
|
// NetConn returns the underlying net.Conn.
|
||||||
@@ -617,7 +457,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
Header: base.Header{},
|
Header: base.Header{},
|
||||||
}, ErrServerCSeqMissing{}
|
}, liberrors.ErrServerCSeqMissing{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sc.readHandlers.OnRequest != nil {
|
if sc.readHandlers.OnRequest != nil {
|
||||||
@@ -631,7 +471,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
path, query := base.PathSplitQuery(pathAndQuery)
|
path, query := base.PathSplitQuery(pathAndQuery)
|
||||||
@@ -690,7 +530,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
path, query := base.PathSplitQuery(pathAndQuery)
|
path, query := base.PathSplitQuery(pathAndQuery)
|
||||||
@@ -729,33 +569,33 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if !ok || len(ct) != 1 {
|
if !ok || len(ct) != 1 {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerContentTypeMissing{}
|
}, liberrors.ErrServerContentTypeMissing{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ct[0] != "application/sdp" {
|
if ct[0] != "application/sdp" {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerContentTypeUnsupported{ct}
|
}, liberrors.ErrServerContentTypeUnsupported{CT: ct}
|
||||||
}
|
}
|
||||||
|
|
||||||
tracks, err := ReadTracks(req.Body, req.URL)
|
tracks, err := ReadTracks(req.Body, req.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerSDPInvalid{err}
|
}, liberrors.ErrServerSDPInvalid{Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tracks) == 0 {
|
if len(tracks) == 0 {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerSDPNoTracksDefined{}
|
}, liberrors.ErrServerSDPNoTracksDefined{}
|
||||||
}
|
}
|
||||||
|
|
||||||
pathAndQuery, ok := req.URL.RTSPPath()
|
pathAndQuery, ok := req.URL.RTSPPath()
|
||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
path, query := base.PathSplitQuery(pathAndQuery)
|
path, query := base.PathSplitQuery(pathAndQuery)
|
||||||
@@ -829,7 +669,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTransportHeaderInvalid{err}
|
}, liberrors.ErrServerTransportHeaderInvalid{Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if th.Delivery != nil && *th.Delivery == base.StreamDeliveryMulticast {
|
if th.Delivery != nil && *th.Delivery == base.StreamDeliveryMulticast {
|
||||||
@@ -849,7 +689,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if _, ok := sc.setuppedTracks[trackID]; ok {
|
if _, ok := sc.setuppedTracks[trackID]; ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTrackAlreadySetup{trackID}
|
}, liberrors.ErrServerTrackAlreadySetup{TrackID: trackID}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch sc.state {
|
switch sc.state {
|
||||||
@@ -857,14 +697,14 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if th.Mode != nil && *th.Mode != headers.TransportModePlay {
|
if th.Mode != nil && *th.Mode != headers.TransportModePlay {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTransportHeaderWrongMode{th.Mode}
|
}, liberrors.ErrServerTransportHeaderWrongMode{Mode: th.Mode}
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // record
|
default: // record
|
||||||
if th.Mode == nil || *th.Mode != headers.TransportModeRecord {
|
if th.Mode == nil || *th.Mode != headers.TransportModeRecord {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTransportHeaderWrongMode{th.Mode}
|
}, liberrors.ErrServerTransportHeaderWrongMode{Mode: th.Mode}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,29 +718,29 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if th.ClientPorts == nil {
|
if th.ClientPorts == nil {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTransportHeaderNoClientPorts{}
|
}, liberrors.ErrServerTransportHeaderNoClientPorts{}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if th.InterleavedIDs == nil {
|
if th.InterleavedIDs == nil {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTransportHeaderNoInterleavedIDs{}
|
}, liberrors.ErrServerTransportHeaderNoInterleavedIDs{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if th.InterleavedIDs[0] != (trackID*2) ||
|
if th.InterleavedIDs[0] != (trackID*2) ||
|
||||||
th.InterleavedIDs[1] != (1+trackID*2) {
|
th.InterleavedIDs[1] != (1+trackID*2) {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTransportHeaderWrongInterleavedIDs{
|
}, liberrors.ErrServerTransportHeaderWrongInterleavedIDs{
|
||||||
[2]int{(trackID * 2), (1 + trackID*2)}, *th.InterleavedIDs}
|
Expected: [2]int{(trackID * 2), (1 + trackID*2)}, Value: *th.InterleavedIDs}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sc.setupProtocol != nil && *sc.setupProtocol != th.Protocol {
|
if sc.setupProtocol != nil && *sc.setupProtocol != th.Protocol {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerTracksDifferentProtocols{}
|
}, liberrors.ErrServerTracksDifferentProtocols{}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := sc.readHandlers.OnSetup(&ServerConnSetupCtx{
|
res, err := sc.readHandlers.OnSetup(&ServerConnSetupCtx{
|
||||||
@@ -987,14 +827,14 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if len(sc.setuppedTracks) == 0 {
|
if len(sc.setuppedTracks) == 0 {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoTracksSetup{}
|
}, liberrors.ErrServerNoTracksSetup{}
|
||||||
}
|
}
|
||||||
|
|
||||||
pathAndQuery, ok := req.URL.RTSPPath()
|
pathAndQuery, ok := req.URL.RTSPPath()
|
||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// path can end with a slash due to Content-Base, remove it
|
// path can end with a slash due to Content-Base, remove it
|
||||||
@@ -1030,20 +870,20 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if len(sc.setuppedTracks) == 0 {
|
if len(sc.setuppedTracks) == 0 {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoTracksSetup{}
|
}, liberrors.ErrServerNoTracksSetup{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(sc.setuppedTracks) != len(sc.announcedTracks) {
|
if len(sc.setuppedTracks) != len(sc.announcedTracks) {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNotAllAnnouncedTracksSetup{}
|
}, liberrors.ErrServerNotAllAnnouncedTracksSetup{}
|
||||||
}
|
}
|
||||||
|
|
||||||
pathAndQuery, ok := req.URL.RTSPPath()
|
pathAndQuery, ok := req.URL.RTSPPath()
|
||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// path can end with a slash due to Content-Base, remove it
|
// path can end with a slash due to Content-Base, remove it
|
||||||
@@ -1083,7 +923,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// path can end with a slash due to Content-Base, remove it
|
// path can end with a slash due to Content-Base, remove it
|
||||||
@@ -1118,7 +958,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
path, query := base.PathSplitQuery(pathAndQuery)
|
path, query := base.PathSplitQuery(pathAndQuery)
|
||||||
@@ -1145,7 +985,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
path, query := base.PathSplitQuery(pathAndQuery)
|
path, query := base.PathSplitQuery(pathAndQuery)
|
||||||
@@ -1163,7 +1003,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusBadRequest,
|
StatusCode: base.StatusBadRequest,
|
||||||
}, ErrServerNoPath{}
|
}, liberrors.ErrServerNoPath{}
|
||||||
}
|
}
|
||||||
|
|
||||||
path, query := base.PathSplitQuery(pathAndQuery)
|
path, query := base.PathSplitQuery(pathAndQuery)
|
||||||
@@ -1177,7 +1017,7 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
|||||||
|
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusOK,
|
StatusCode: base.StatusOK,
|
||||||
}, ErrServerTeardown{}
|
}, liberrors.ErrServerTeardown{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
@@ -1196,7 +1036,7 @@ func (sc *ServerConn) backgroundRead() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add cseq
|
// add cseq
|
||||||
if _, ok := err.(ErrServerCSeqMissing); !ok {
|
if _, ok := err.(liberrors.ErrServerCSeqMissing); !ok {
|
||||||
res.Header["CSeq"] = req.Header["CSeq"]
|
res.Header["CSeq"] = req.Header["CSeq"]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1286,7 +1126,7 @@ outer:
|
|||||||
err := req.Read(sc.br)
|
err := req.Read(sc.br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if atomic.LoadInt32(&sc.udpTimeout) == 1 {
|
if atomic.LoadInt32(&sc.udpTimeout) == 1 {
|
||||||
errRet = ErrServerNoUDPPacketsRecently{}
|
errRet = liberrors.ErrServerNoUDPPacketsRecently{}
|
||||||
} else {
|
} else {
|
||||||
errRet = err
|
errRet = err
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/aler9/gortsplib/pkg/base"
|
"github.com/aler9/gortsplib/pkg/base"
|
||||||
|
"github.com/aler9/gortsplib/pkg/liberrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testServ struct {
|
type testServ struct {
|
||||||
@@ -203,7 +204,7 @@ func (ts *testServ) handleConn(conn *ServerConn) {
|
|||||||
OnFrame: onFrame,
|
OnFrame: onFrame,
|
||||||
})
|
})
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
if _, ok := err.(ErrServerTeardown); !ok {
|
if _, ok := err.(liberrors.ErrServerTeardown); !ok {
|
||||||
fmt.Println("ERR", err)
|
fmt.Println("ERR", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -466,7 +467,7 @@ func TestServerConnTeardownResponse(t *testing.T) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
err = <-conn.Read(ServerConnReadHandlers{})
|
err = <-conn.Read(ServerConnReadHandlers{})
|
||||||
_, ok := err.(ErrServerTeardown)
|
_, ok := err.(liberrors.ErrServerTeardown)
|
||||||
require.Equal(t, true, ok)
|
require.Equal(t, true, ok)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user