1
0
Fork 0
forked from External/mediamtx

move conf into dedicated folder

This commit is contained in:
aler9 2020-10-14 00:50:08 +02:00
parent a0e053196d
commit 606806777a
8 changed files with 134 additions and 130 deletions

View file

@ -16,6 +16,7 @@ import (
"github.com/aler9/gortsplib/headers"
"github.com/aler9/gortsplib/rtcpreceiver"
"github.com/aler9/rtsp-simple-server/conf"
"github.com/aler9/rtsp-simple-server/externalcmd"
)
@ -27,14 +28,14 @@ const (
type clientDescribeReq struct {
client *client
pathName string
pathConf *pathConf
pathConf *conf.PathConf
}
type clientAnnounceReq struct {
res chan error
client *client
pathName string
pathConf *pathConf
pathConf *conf.PathConf
trackCount int
sdp []byte
}
@ -260,7 +261,7 @@ func (c *client) authenticate(ips []interface{}, user string, pass string, req *
if c.authHelper == nil || c.authUser != user || c.authPass != pass {
c.authUser = user
c.authPass = pass
c.authHelper = auth.NewServer(user, pass, c.p.conf.authMethodsParsed)
c.authHelper = auth.NewServer(user, pass, c.p.conf.AuthMethodsParsed)
}
err := c.authHelper.ValidateHeader(req.Header["Authorization"], req.Method, req.Url)
@ -371,13 +372,13 @@ func (c *client) handleRequest(req *base.Request) error {
pathName = removeQueryFromPath(pathName)
pathConf, err := c.p.conf.checkPathNameAndFindConf(pathName)
pathConf, err := c.p.conf.CheckPathNameAndFindConf(pathName)
if err != nil {
c.writeResError(cseq, base.StatusBadRequest, err)
return errRunTerminate
}
err = c.authenticate(pathConf.readIpsParsed, pathConf.ReadUser, pathConf.ReadPass, req)
err = c.authenticate(pathConf.ReadIpsParsed, pathConf.ReadUser, pathConf.ReadPass, req)
if err != nil {
if err == errAuthCritical {
return errRunTerminate
@ -401,13 +402,13 @@ func (c *client) handleRequest(req *base.Request) error {
pathName = removeQueryFromPath(pathName)
pathConf, err := c.p.conf.checkPathNameAndFindConf(pathName)
pathConf, err := c.p.conf.CheckPathNameAndFindConf(pathName)
if err != nil {
c.writeResError(cseq, base.StatusBadRequest, err)
return errRunTerminate
}
err = c.authenticate(pathConf.publishIpsParsed, pathConf.PublishUser, pathConf.PublishPass, req)
err = c.authenticate(pathConf.PublishIpsParsed, pathConf.PublishUser, pathConf.PublishPass, req)
if err != nil {
if err == errAuthCritical {
return errRunTerminate
@ -483,13 +484,13 @@ func (c *client) handleRequest(req *base.Request) error {
return errRunTerminate
}
pathConf, err := c.p.conf.checkPathNameAndFindConf(basePath)
pathConf, err := c.p.conf.CheckPathNameAndFindConf(basePath)
if err != nil {
c.writeResError(cseq, base.StatusBadRequest, err)
return errRunTerminate
}
err = c.authenticate(pathConf.readIpsParsed, pathConf.ReadUser, pathConf.ReadPass, req)
err = c.authenticate(pathConf.ReadIpsParsed, pathConf.ReadUser, pathConf.ReadPass, req)
if err != nil {
if err == errAuthCritical {
return errRunTerminate
@ -521,7 +522,7 @@ func (c *client) handleRequest(req *base.Request) error {
// play with UDP
if th.Protocol == gortsplib.StreamProtocolUDP {
if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolUDP]; !ok {
if _, ok := c.p.conf.ProtocolsParsed[gortsplib.StreamProtocolUDP]; !ok {
c.writeResError(cseq, base.StatusUnsupportedTransport, fmt.Errorf("UDP streaming is disabled"))
return errRunTerminate
}
@ -572,7 +573,7 @@ func (c *client) handleRequest(req *base.Request) error {
// play with TCP
} else {
if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolTCP]; !ok {
if _, ok := c.p.conf.ProtocolsParsed[gortsplib.StreamProtocolTCP]; !ok {
c.writeResError(cseq, base.StatusUnsupportedTransport, fmt.Errorf("TCP streaming is disabled"))
return errRunTerminate
}
@ -629,7 +630,7 @@ func (c *client) handleRequest(req *base.Request) error {
// record with UDP
if th.Protocol == gortsplib.StreamProtocolUDP {
if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolUDP]; !ok {
if _, ok := c.p.conf.ProtocolsParsed[gortsplib.StreamProtocolUDP]; !ok {
c.writeResError(cseq, base.StatusUnsupportedTransport, fmt.Errorf("UDP streaming is disabled"))
return errRunTerminate
}
@ -677,7 +678,7 @@ func (c *client) handleRequest(req *base.Request) error {
// record with TCP
} else {
if _, ok := c.p.conf.protocolsParsed[gortsplib.StreamProtocolTCP]; !ok {
if _, ok := c.p.conf.ProtocolsParsed[gortsplib.StreamProtocolTCP]; !ok {
c.writeResError(cseq, base.StatusUnsupportedTransport, fmt.Errorf("TCP streaming is disabled"))
return errRunTerminate
}

View file

@ -1,8 +1,8 @@
package main
package conf
import (
"fmt"
"io"
"net"
"net/url"
"os"
"regexp"
@ -17,12 +17,58 @@ import (
"github.com/aler9/rtsp-simple-server/loghandler"
)
type pathConf struct {
regexp *regexp.Regexp
func parseIpCidrList(in []string) ([]interface{}, error) {
if len(in) == 0 {
return nil, nil
}
var ret []interface{}
for _, t := range in {
_, ipnet, err := net.ParseCIDR(t)
if err == nil {
ret = append(ret, ipnet)
continue
}
ip := net.ParseIP(t)
if ip != nil {
ret = append(ret, ip)
continue
}
return nil, fmt.Errorf("unable to parse ip/network '%s'", t)
}
return ret, nil
}
var rePathName = regexp.MustCompile("^[0-9a-zA-Z_\\-/]+$")
func checkPathName(name string) error {
if name == "" {
return fmt.Errorf("cannot be empty")
}
if name[0] == '/' {
return fmt.Errorf("can't begin with a slash")
}
if name[len(name)-1] == '/' {
return fmt.Errorf("can't end with a slash")
}
if !rePathName.MatchString(name) {
return fmt.Errorf("can contain only alfanumeric characters, underscore, minus or slash")
}
return nil
}
type PathConf struct {
Regexp *regexp.Regexp
Source string `yaml:"source"`
sourceUrl *url.URL ``
SourceUrl *url.URL `yaml:"-"`
SourceProtocol string `yaml:"sourceProtocol"`
sourceProtocolParsed gortsplib.StreamProtocol ``
SourceProtocolParsed gortsplib.StreamProtocol `yaml:"-"`
SourceOnDemand bool `yaml:"sourceOnDemand"`
RunOnInit string `yaml:"runOnInit"`
RunOnDemand string `yaml:"runOnDemand"`
@ -31,16 +77,16 @@ type pathConf struct {
PublishUser string `yaml:"publishUser"`
PublishPass string `yaml:"publishPass"`
PublishIps []string `yaml:"publishIps"`
publishIpsParsed []interface{} ``
PublishIpsParsed []interface{} `yaml:"-"`
ReadUser string `yaml:"readUser"`
ReadPass string `yaml:"readPass"`
ReadIps []string `yaml:"readIps"`
readIpsParsed []interface{} ``
ReadIpsParsed []interface{} `yaml:"-"`
}
type conf struct {
type Conf struct {
Protocols []string `yaml:"protocols"`
protocolsParsed map[gortsplib.StreamProtocol]struct{} ``
ProtocolsParsed map[gortsplib.StreamProtocol]struct{} `yaml:"-"`
RtspPort int `yaml:"rtspPort"`
RtpPort int `yaml:"rtpPort"`
RtcpPort int `yaml:"rtcpPort"`
@ -48,19 +94,19 @@ type conf struct {
ReadTimeout time.Duration `yaml:"readTimeout"`
WriteTimeout time.Duration `yaml:"writeTimeout"`
AuthMethods []string `yaml:"authMethods"`
authMethodsParsed []headers.AuthMethod ``
AuthMethodsParsed []headers.AuthMethod `yaml:"-"`
Metrics bool `yaml:"metrics"`
Pprof bool `yaml:"pprof"`
LogDestinations []string `yaml:"logDestinations"`
logDestinationsParsed map[loghandler.Destination]struct{} ``
LogDestinationsParsed map[loghandler.Destination]struct{} `yaml:"-"`
LogFile string `yaml:"logFile"`
Paths map[string]*pathConf `yaml:"paths"`
Paths map[string]*PathConf `yaml:"paths"`
}
func loadConf(fpath string) (*conf, error) {
conf := &conf{}
func Load(fpath string) (*Conf, error) {
conf := &Conf{}
// read from file or stdin
// read from file
err := func() error {
// rtsp-simple-server.yml is optional
if fpath == "rtsp-simple-server.yml" {
@ -95,20 +141,20 @@ func loadConf(fpath string) (*conf, error) {
if len(conf.Protocols) == 0 {
conf.Protocols = []string{"udp", "tcp"}
}
conf.protocolsParsed = make(map[gortsplib.StreamProtocol]struct{})
conf.ProtocolsParsed = make(map[gortsplib.StreamProtocol]struct{})
for _, proto := range conf.Protocols {
switch proto {
case "udp":
conf.protocolsParsed[gortsplib.StreamProtocolUDP] = struct{}{}
conf.ProtocolsParsed[gortsplib.StreamProtocolUDP] = struct{}{}
case "tcp":
conf.protocolsParsed[gortsplib.StreamProtocolTCP] = struct{}{}
conf.ProtocolsParsed[gortsplib.StreamProtocolTCP] = struct{}{}
default:
return nil, fmt.Errorf("unsupported protocol: %s", proto)
}
}
if len(conf.protocolsParsed) == 0 {
if len(conf.ProtocolsParsed) == 0 {
return nil, fmt.Errorf("no protocols provided")
}
@ -141,10 +187,10 @@ func loadConf(fpath string) (*conf, error) {
for _, method := range conf.AuthMethods {
switch method {
case "basic":
conf.authMethodsParsed = append(conf.authMethodsParsed, headers.AuthBasic)
conf.AuthMethodsParsed = append(conf.AuthMethodsParsed, headers.AuthBasic)
case "digest":
conf.authMethodsParsed = append(conf.authMethodsParsed, headers.AuthDigest)
conf.AuthMethodsParsed = append(conf.AuthMethodsParsed, headers.AuthDigest)
default:
return nil, fmt.Errorf("unsupported authentication method: %s", method)
@ -154,17 +200,17 @@ func loadConf(fpath string) (*conf, error) {
if len(conf.LogDestinations) == 0 {
conf.LogDestinations = []string{"stdout"}
}
conf.logDestinationsParsed = make(map[loghandler.Destination]struct{})
conf.LogDestinationsParsed = make(map[loghandler.Destination]struct{})
for _, dest := range conf.LogDestinations {
switch dest {
case "stdout":
conf.logDestinationsParsed[loghandler.DestinationStdout] = struct{}{}
conf.LogDestinationsParsed[loghandler.DestinationStdout] = struct{}{}
case "file":
conf.logDestinationsParsed[loghandler.DestinationFile] = struct{}{}
conf.LogDestinationsParsed[loghandler.DestinationFile] = struct{}{}
case "syslog":
conf.logDestinationsParsed[loghandler.DestinationSyslog] = struct{}{}
conf.LogDestinationsParsed[loghandler.DestinationSyslog] = struct{}{}
default:
return nil, fmt.Errorf("unsupported log destination: %s", dest)
@ -175,7 +221,7 @@ func loadConf(fpath string) (*conf, error) {
}
if len(conf.Paths) == 0 {
conf.Paths = map[string]*pathConf{
conf.Paths = map[string]*PathConf{
"all": {},
}
}
@ -188,7 +234,7 @@ func loadConf(fpath string) (*conf, error) {
for name, pconf := range conf.Paths {
if pconf == nil {
conf.Paths[name] = &pathConf{}
conf.Paths[name] = &PathConf{}
pconf = conf.Paths[name]
}
@ -209,7 +255,7 @@ func loadConf(fpath string) (*conf, error) {
if err != nil {
return nil, fmt.Errorf("invalid regular expression: %s", name[1:])
}
pconf.regexp = pathRegexp
pconf.Regexp = pathRegexp
}
if pconf.Source == "" {
@ -217,20 +263,20 @@ func loadConf(fpath string) (*conf, error) {
}
if strings.HasPrefix(pconf.Source, "rtsp://") {
if pconf.regexp != nil {
if pconf.Regexp != nil {
return nil, fmt.Errorf("a path with a regular expression (or path 'all') cannot have a RTSP source; use another path")
}
pconf.sourceUrl, err = url.Parse(pconf.Source)
pconf.SourceUrl, err = url.Parse(pconf.Source)
if err != nil {
return nil, fmt.Errorf("'%s' is not a valid url", pconf.Source)
}
if pconf.sourceUrl.Port() == "" {
pconf.sourceUrl.Host += ":554"
if pconf.SourceUrl.Port() == "" {
pconf.SourceUrl.Host += ":554"
}
if pconf.sourceUrl.User != nil {
pass, _ := pconf.sourceUrl.User.Password()
user := pconf.sourceUrl.User.Username()
if pconf.SourceUrl.User != nil {
pass, _ := pconf.SourceUrl.User.Password()
user := pconf.SourceUrl.User.Username()
if user != "" && pass == "" ||
user == "" && pass != "" {
fmt.Errorf("username and password must be both provided")
@ -242,26 +288,26 @@ func loadConf(fpath string) (*conf, error) {
}
switch pconf.SourceProtocol {
case "udp":
pconf.sourceProtocolParsed = gortsplib.StreamProtocolUDP
pconf.SourceProtocolParsed = gortsplib.StreamProtocolUDP
case "tcp":
pconf.sourceProtocolParsed = gortsplib.StreamProtocolTCP
pconf.SourceProtocolParsed = gortsplib.StreamProtocolTCP
default:
return nil, fmt.Errorf("unsupported protocol '%s'", pconf.SourceProtocol)
}
} else if strings.HasPrefix(pconf.Source, "rtmp://") {
if pconf.regexp != nil {
if pconf.Regexp != nil {
return nil, fmt.Errorf("a path with a regular expression (or path 'all') cannot have a RTMP source; use another path")
}
pconf.sourceUrl, err = url.Parse(pconf.Source)
pconf.SourceUrl, err = url.Parse(pconf.Source)
if err != nil {
return nil, fmt.Errorf("'%s' is not a valid url", pconf.Source)
}
if pconf.sourceUrl.Port() == "" {
pconf.sourceUrl.Host += ":1935"
if pconf.SourceUrl.Port() == "" {
pconf.SourceUrl.Host += ":1935"
}
} else if pconf.Source == "record" {
@ -280,7 +326,7 @@ func loadConf(fpath string) (*conf, error) {
return nil, fmt.Errorf("publish password must be alphanumeric")
}
}
pconf.publishIpsParsed, err = parseIpCidrList(pconf.PublishIps)
pconf.PublishIpsParsed, err = parseIpCidrList(pconf.PublishIps)
if err != nil {
return nil, err
}
@ -301,12 +347,12 @@ func loadConf(fpath string) (*conf, error) {
if pconf.ReadUser != "" && pconf.ReadPass == "" || pconf.ReadUser == "" && pconf.ReadPass != "" {
return nil, fmt.Errorf("read username and password must be both filled")
}
pconf.readIpsParsed, err = parseIpCidrList(pconf.ReadIps)
pconf.ReadIpsParsed, err = parseIpCidrList(pconf.ReadIps)
if err != nil {
return nil, err
}
if pconf.regexp != nil && pconf.RunOnInit != "" {
if pconf.Regexp != nil && pconf.RunOnInit != "" {
return nil, fmt.Errorf("a path with a regular expression does not support option 'runOnInit'; use another path")
}
}
@ -314,7 +360,7 @@ func loadConf(fpath string) (*conf, error) {
return conf, nil
}
func (conf *conf) checkPathNameAndFindConf(name string) (*pathConf, error) {
func (conf *Conf) CheckPathNameAndFindConf(name string) (*PathConf, error) {
err := checkPathName(name)
if err != nil {
return nil, fmt.Errorf("invalid path name: %s (%s)", err, name)
@ -327,7 +373,7 @@ func (conf *conf) checkPathNameAndFindConf(name string) (*pathConf, error) {
// regular expression path
for _, pconf := range conf.Paths {
if pconf.regexp != nil && pconf.regexp.MatchString(name) {
if pconf.Regexp != nil && pconf.Regexp.MatchString(name) {
return pconf, nil
}
}

View file

@ -94,14 +94,14 @@ func process(env map[string]string, envKey string, rv reflect.Value) error {
case reflect.Struct:
flen := rt.NumField()
for i := 0; i < flen; i++ {
fieldName := rt.Field(i).Name
f := rt.Field(i)
// process only public fields
if fieldName[0] < 'A' || fieldName[0] > 'Z' {
if f.Tag.Get("yaml") == "-" {
continue
}
fieldEnvKey := envKey + "_" + strings.ToUpper(fieldName)
fieldEnvKey := envKey + "_" + strings.ToUpper(f.Name)
err := process(env, fieldEnvKey, rv.Field(i))
if err != nil {
return err

11
main.go
View file

@ -12,6 +12,7 @@ import (
"github.com/aler9/gortsplib"
"gopkg.in/alecthomas/kingpin.v2"
"github.com/aler9/rtsp-simple-server/conf"
"github.com/aler9/rtsp-simple-server/loghandler"
)
@ -22,7 +23,7 @@ const (
)
type program struct {
conf *conf
conf *conf.Conf
logHandler *loghandler.LogHandler
metrics *metrics
pprof *pprof
@ -72,12 +73,12 @@ func newProgram(args []string, stdin io.Reader) (*program, error) {
os.Exit(0)
}
conf, err := loadConf(*argConfPath)
conf, err := conf.Load(*argConfPath)
if err != nil {
return nil, err
}
logHandler, err := loghandler.New(conf.logDestinationsParsed, conf.LogFile)
logHandler, err := loghandler.New(conf.LogDestinationsParsed, conf.LogFile)
if err != nil {
return nil, err
}
@ -149,12 +150,12 @@ func newProgram(args []string, stdin io.Reader) (*program, error) {
}
for name, pathConf := range conf.Paths {
if pathConf.regexp == nil {
if pathConf.Regexp == nil {
p.paths[name] = newPath(p, name, pathConf)
}
}
if _, ok := conf.protocolsParsed[gortsplib.StreamProtocolUDP]; ok {
if _, ok := conf.ProtocolsParsed[gortsplib.StreamProtocolUDP]; ok {
p.serverUdpRtp, err = newServerUDP(p, conf.RtpPort, gortsplib.StreamTypeRtp)
if err != nil {
return nil, err

View file

@ -12,6 +12,8 @@ import (
"github.com/aler9/gortsplib"
"github.com/stretchr/testify/require"
"github.com/aler9/rtsp-simple-server/conf"
)
var ownDockerIp = func() string {
@ -163,20 +165,20 @@ func TestEnvironment(t *testing.T) {
pa, ok := p.conf.Paths["test2"]
require.Equal(t, true, ok)
require.Equal(t, &pathConf{
require.Equal(t, &conf.PathConf{
Source: "record",
}, pa)
pa, ok = p.conf.Paths["test"]
require.Equal(t, true, ok)
require.Equal(t, &pathConf{
require.Equal(t, &conf.PathConf{
Source: "rtsp://testing",
sourceUrl: func() *url.URL {
SourceUrl: func() *url.URL {
u, _ := url.Parse("rtsp://testing:554")
return u
}(),
SourceProtocol: "tcp",
sourceProtocolParsed: gortsplib.StreamProtocolTCP,
SourceProtocolParsed: gortsplib.StreamProtocolTCP,
}, pa)
}

View file

@ -6,6 +6,7 @@ import (
"sync/atomic"
"time"
"github.com/aler9/rtsp-simple-server/conf"
"github.com/aler9/rtsp-simple-server/externalcmd"
)
@ -23,7 +24,7 @@ type source interface {
type path struct {
p *program
name string
conf *pathConf
conf *conf.PathConf
source source
sourceReady bool
sourceTrackCount int
@ -34,7 +35,7 @@ type path struct {
onDemandCmd *externalcmd.ExternalCmd
}
func newPath(p *program, name string, conf *pathConf) *path {
func newPath(p *program, name string, conf *conf.PathConf) *path {
pa := &path{
p: p,
name: name,
@ -189,7 +190,7 @@ func (pa *path) onCheck() {
}
// remove regular expression paths
if pa.conf.regexp != nil &&
if pa.conf.Regexp != nil &&
pa.source == nil &&
!pa.hasClients() {
pa.onClose(false)

View file

@ -128,7 +128,7 @@ func (s *sourceRtsp) runInnerInner() bool {
go func() {
defer close(dialDone)
conn, err = gortsplib.NewConnClient(gortsplib.ConnClientConf{
Host: s.path.conf.sourceUrl.Host,
Host: s.path.conf.SourceUrl.Host,
ReadTimeout: s.p.conf.ReadTimeout,
WriteTimeout: s.p.conf.WriteTimeout,
ReadBufferCount: 2,
@ -146,14 +146,14 @@ func (s *sourceRtsp) runInnerInner() bool {
return true
}
_, err = conn.Options(s.path.conf.sourceUrl)
_, err = conn.Options(s.path.conf.SourceUrl)
if err != nil {
conn.Close()
s.path.log("rtsp source ERR: %s", err)
return true
}
tracks, _, err := conn.Describe(s.path.conf.sourceUrl)
tracks, _, err := conn.Describe(s.path.conf.SourceUrl)
if err != nil {
conn.Close()
s.path.log("rtsp source ERR: %s", err)
@ -165,7 +165,7 @@ func (s *sourceRtsp) runInnerInner() bool {
s.path.sourceTrackCount = len(tracks)
s.tracks = tracks
if s.path.conf.sourceProtocolParsed == gortsplib.StreamProtocolUDP {
if s.path.conf.SourceProtocolParsed == gortsplib.StreamProtocolUDP {
return s.runUDP(conn)
} else {
return s.runTCP(conn)
@ -174,7 +174,7 @@ func (s *sourceRtsp) runInnerInner() bool {
func (s *sourceRtsp) runUDP(conn *gortsplib.ConnClient) bool {
for _, track := range s.tracks {
_, err := conn.SetupUDP(s.path.conf.sourceUrl, gortsplib.TransportModePlay, track, 0, 0)
_, err := conn.SetupUDP(s.path.conf.SourceUrl, gortsplib.TransportModePlay, track, 0, 0)
if err != nil {
conn.Close()
s.path.log("rtsp source ERR: %s", err)
@ -182,7 +182,7 @@ func (s *sourceRtsp) runUDP(conn *gortsplib.ConnClient) bool {
}
}
_, err := conn.Play(s.path.conf.sourceUrl)
_, err := conn.Play(s.path.conf.SourceUrl)
if err != nil {
conn.Close()
s.path.log("rtsp source ERR: %s", err)
@ -264,7 +264,7 @@ outer:
func (s *sourceRtsp) runTCP(conn *gortsplib.ConnClient) bool {
for _, track := range s.tracks {
_, err := conn.SetupTCP(s.path.conf.sourceUrl, gortsplib.TransportModePlay, track)
_, err := conn.SetupTCP(s.path.conf.SourceUrl, gortsplib.TransportModePlay, track)
if err != nil {
conn.Close()
s.path.log("rtsp source ERR: %s", err)
@ -272,7 +272,7 @@ func (s *sourceRtsp) runTCP(conn *gortsplib.ConnClient) bool {
}
}
_, err := conn.Play(s.path.conf.sourceUrl)
_, err := conn.Play(s.path.conf.SourceUrl)
if err != nil {
conn.Close()
s.path.log("rtsp source ERR: %s", err)

View file

@ -3,7 +3,6 @@ package main
import (
"fmt"
"net"
"regexp"
"strings"
"sync"
@ -11,30 +10,6 @@ import (
"github.com/aler9/gortsplib/base"
)
func parseIpCidrList(in []string) ([]interface{}, error) {
if len(in) == 0 {
return nil, nil
}
var ret []interface{}
for _, t := range in {
_, ipnet, err := net.ParseCIDR(t)
if err == nil {
ret = append(ret, ipnet)
continue
}
ip := net.ParseIP(t)
if ip != nil {
ret = append(ret, ip)
continue
}
return nil, fmt.Errorf("unable to parse ip/network '%s'", t)
}
return ret, nil
}
func ipEqualOrInRange(ip net.IP, ips []interface{}) bool {
for _, item := range ips {
switch titem := item.(type) {
@ -88,28 +63,6 @@ func removeQueryFromPath(path string) string {
return path
}
var rePathName = regexp.MustCompile("^[0-9a-zA-Z_\\-/]+$")
func checkPathName(name string) error {
if name == "" {
return fmt.Errorf("cannot be empty")
}
if name[0] == '/' {
return fmt.Errorf("can't begin with a slash")
}
if name[len(name)-1] == '/' {
return fmt.Errorf("can't end with a slash")
}
if !rePathName.MatchString(name) {
return fmt.Errorf("can contain only alfanumeric characters, underscore, minus or slash")
}
return nil
}
type udpPublisherAddr struct {
ip [net.IPv6len]byte // use a fixed-size array to enable the equality operator
port int