github.com/cnotch/ipchub@v1.1.0/service/rtsp/rtptransport.go (about)

     1  // Copyright (c) 2019,CAOHONGJU All rights reserved.
     2  // Use of this source code is governed by a MIT-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package rtsp
     6  
     7  import (
     8  	"errors"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/cnotch/ipchub/utils/scan"
    13  )
    14  
    15  // RTPTransportType RTP 传输模式
    16  type RTPTransportType int
    17  
    18  // SessionMode 会话模式
    19  type SessionMode int
    20  
    21  // 通讯类型
    22  const (
    23  	RTPUnknownTrans RTPTransportType = iota
    24  	RTPTCPUnicast                    // TCP
    25  	RTPUDPUnicast                    // UDP
    26  	RTPMulticast                     // 组播
    27  )
    28  
    29  // 会话类型
    30  const (
    31  	UnknownSession SessionMode = iota
    32  	PlaySession                // 播放
    33  	RecordSession              // 录像
    34  )
    35  
    36  // RTPTransport RTP传输设置
    37  type RTPTransport struct {
    38  	Mode        SessionMode
    39  	Append      bool
    40  	Type        RTPTransportType
    41  	Channels    [rtpChannelCount]int
    42  	ClientPorts [rtpChannelCount]int
    43  	ServerPorts [rtpChannelCount]int
    44  
    45  	// 组播相关设置
    46  	Ports       [rtpChannelCount]int // 组播端口
    47  	MulticastIP string            // 组播地址 224.0.1.0~238.255.255.255
    48  	TTL         int
    49  	Source      string // 组播源地址
    50  }
    51  
    52  func parseRange(p string) (begin int, end int) {
    53  	begin = -1
    54  	end = -1
    55  
    56  	var s1, s2 string
    57  	index := strings.IndexByte(p, '-')
    58  	if index < 0 {
    59  		s1 = p
    60  	} else {
    61  		s1 = strings.TrimSpace(p[:index])
    62  		s2 = strings.TrimSpace(p[index+1:])
    63  	}
    64  	var err error
    65  	if len(s1) > 0 {
    66  		begin, err = strconv.Atoi(s1)
    67  		if err != nil {
    68  			begin = -1
    69  		}
    70  	}
    71  	if len(s2) > 0 {
    72  		end, err = strconv.Atoi(s2)
    73  		if err != nil {
    74  			end = -1
    75  		}
    76  	}
    77  	return
    78  }
    79  
    80  // ParseTransport 解析Setup中的传输配置
    81  func (t *RTPTransport) ParseTransport(rtpType int, ts string) (err error) {
    82  	if t.Mode == UnknownSession {
    83  		t.Mode = PlaySession
    84  	}
    85  
    86  	// 确定传输类型
    87  	index := strings.IndexByte(ts, ';')
    88  	if index < 0 {
    89  		return errors.New("malformed trannsport")
    90  	}
    91  	transportSpec := strings.TrimSpace(ts[:index])
    92  	ts = ts[index+1:]
    93  
    94  	if transportSpec == "RTP/AVP/TCP" {
    95  		t.Type = RTPTCPUnicast
    96  	} else if transportSpec == "RTP/AVP" || transportSpec == "RTP/AVP/UDP" {
    97  		t.Type = RTPMulticast // 默认组播
    98  	} else {
    99  		return errors.New("malformed trannsport")
   100  	}
   101  
   102  	// 扫描参数
   103  	advance := ts
   104  	token := ""
   105  	continueScan := true
   106  	for continueScan {
   107  		advance, token, continueScan = scan.Semicolon.Scan(advance)
   108  		if token == "unicast" && t.Type == RTPMulticast {
   109  			t.Type = RTPUDPUnicast
   110  			continue
   111  		}
   112  		if token == "multicast" && t.Type == RTPTCPUnicast {
   113  			err = errors.New("malformed trannsport")
   114  			continue
   115  		}
   116  		if token == "append" {
   117  			t.Append = true
   118  			continue
   119  		}
   120  
   121  		k, v, _ := scan.EqualPair.Scan(token)
   122  		switch k {
   123  		case "mode":
   124  			if v == "record" {
   125  				t.Mode = RecordSession
   126  			} else {
   127  				t.Mode = PlaySession
   128  			}
   129  		case "interleaved":
   130  			begin, end := parseRange(v)
   131  			if begin >= 0 {
   132  				t.Channels[rtpType] = begin
   133  			}
   134  			if end >= 0 {
   135  				t.Channels[rtpType+1] = end
   136  			}
   137  			if begin < 0 {
   138  				err = errors.New("malformed trannsport")
   139  			}
   140  		case "client_port":
   141  			t.ClientPorts[rtpType], t.ClientPorts[rtpType+1] = parseRange(v)
   142  			if t.ClientPorts[rtpType] < 0 {
   143  				err = errors.New("malformed trannsport")
   144  			}
   145  		case "server_port":
   146  			t.ServerPorts[rtpType], t.ServerPorts[rtpType+1] = parseRange(v)
   147  			if t.ServerPorts[rtpType] < 0 {
   148  				err = errors.New("malformed trannsport")
   149  			}
   150  		case "port":
   151  			t.Ports[rtpType], t.Ports[rtpType+1] = parseRange(v)
   152  			if t.Ports[rtpType] < 0 {
   153  				err = errors.New("malformed trannsport")
   154  			}
   155  		case "destination":
   156  			t.MulticastIP = v
   157  		case "source":
   158  			t.Source = v
   159  		case "ttl":
   160  			t.TTL, _ = strconv.Atoi(v)
   161  		}
   162  	}
   163  	return
   164  }