func (s *Session) Teardown() error {
	return s.command(VerbTeardown, s.BaseURI, nil)
}
Teardown handles client TEARDOWN request in RTSP.
package rtsp
import (
	"log"
	"strings"
	"sync"
	"time"
)
var (
	keepAliveTimeout = time.Second * 2
)
type (
	Session struct {
		*Conn
		sync.Mutex
		stage   int         
		State   chan int    
		auth    DigestAuth  
		queue   Queue       
		done    chan struct{}
		session string
		feeds   []*Feed
		feedidx int
		verbs   map[string]struct{}
		last    time.Time
		cseq    int
	}
)
func NewSession() *Session {
	return &Session{
		State: make(chan int),
		stage: StageInit,
		queue: make(Queue),
		verbs: make(map[string]struct{}, 11),
	}
}
func (s *Session) Open(uri string, proto int) error {
	conn, err := Dial(uri, proto)
	if err != nil {
		return err
	}
	s.Conn = conn
	go s.process()
	return s.Options()
}
func (s *Session) authorize(challenge string) error {
	digest, err := NewDigest(s.BaseURI, challenge)
	if err != nil {
		return err
	}
	if s.URL.User == nil {
		return errNoCredentials
	}
	username := s.URL.User.Username()
	password, _ := s.URL.User.Password()
	s.auth = digest.Authenticate(username, password)
	return nil
}
func (s *Session) enqueue(req *Request) {
	s.Lock()
	defer s.Unlock()
	req.Cseq = s.cseq
	req.Session = s.session
	s.queue[req.Cseq] = req
}
func (s *Session) dequeue(seq int) (req *Request, ok bool) {
	s.Lock()
	defer s.Unlock()
	req, ok = s.queue[seq]
	if ok {
		delete(s.queue, seq)
	}
	return
}
func (s *Session) command(verb, uri string, headers Headers) error {
	if s.Conn == nil {
		return errNoConnection
	}
	req := &Request{Verb: verb, URI: uri, Header: make(MessageHeader)}
	for key, value := range headers {
		req.Header.Set(key, value)
	}
	if s.auth != nil {
		req.Auth = s.auth(req.Verb, nil)
	}
	s.cseq++
	s.enqueue(req)
	buf := req.Pack()
	log.Println(string(buf))
	if _, err := s.Write(buf); err != nil {
		return err
	}
	return nil
}
func (s *Session) Options() error {
	return s.command(VerbOptions, s.BaseURI, nil)
}
func (s *Session) Describe() error {
	return s.command(VerbDescribe, s.BaseURI, Headers{HeaderAccept: "application/sdp"})
}
func (s *Session) Setup() error {
	for i := range s.feeds {
		uri := s.feeds[i].Control
		if !strings.HasPrefix(uri, "rtsp://") {
			uri = s.BaseURI + "/" + uri
		}
		err := s.command(VerbSetup, uri, Headers{HeaderTransport: s.feeds[i].TransportHeader()})
		if err != nil {
			return err
		}
		s.feeds[i].cseq = s.cseq
	}
	return nil
}
func (s *Session) Play() error {
	return s.command(VerbPlay, s.BaseURI, nil)
}
func (s *Session) Pause() error {
	return s.command(VerbPause, s.BaseURI, nil)
}