package autoradio import ( "crypto/rand" "encoding/base32" "fmt" "hash/crc32" "strings" ) const ( // All our keys are stored in etcd below this prefix. The // slash is used as hierarchy separator for our keyspace. EtcdPrefix = "autoradio/" // MountPrefix stores the path to the mount configuration in // etcd. This should never change between releases, upgrades // to the configuration format should be backwards-compatible. MountPrefix = EtcdPrefix + "icecast/mounts/" // Paths for the cluster runtime data. Whenever the format of // this data changes, the ABIVersion should be increased. A // rolling restart of the cluster will then seamlessly cause a // transition to the new consensus (the cluster will be // partitioned in the meantime). ABIVersion = "4" // Prefixes for the etcd-based leader elections. ElectionPrefix = EtcdPrefix + "election/" + ABIVersion + "/" IcecastElectionPrefix = ElectionPrefix + "icecast/" TranscoderElectionPrefix = ElectionPrefix + "transcode/" // Prefix for the streams served directly by Icecast. IcecastMountPrefix = "/_stream" // Prefixes for etcd-based service discovery. EndpointPrefix = EtcdPrefix + "endpoints/" + ABIVersion + "/" PublicEndpointPrefix = EndpointPrefix + "frontend/public/" StatusEndpointPrefix = EndpointPrefix + "frontend/status/" ) // IcecastPort is the port that the Icecast server will listen // on. Since we fully manage the system-wide Icecast instance, // there's not much point in making this configurable. var IcecastPort = 8000 // MountPathToIcecastPath returns the Icecast mount path for the given // public mount name. func MountPathToIcecastPath(mountPath string) string { return IcecastMountPrefix + mountPath } // IcecastPathToMountPath returns the public mount name from an // Icecast mount path. If 'path' does not start with // IcecastMountPrefix, it is returned unchanged (though arguably this // should be an error). func IcecastPathToMountPath(path string) string { return strings.TrimPrefix(path, IcecastMountPrefix) } // GeneratePassword returns a new random password. func GeneratePassword() string { b := make([]byte, 20) if _, err := rand.Read(b); err != nil { panic(err) } return strings.ToLower(base32.StdEncoding.EncodeToString(b)) } // GenerateUsername returns a username somehow related to the name of // the mount, possibly unique (but not actually guaranteed to be so). func GenerateUsername(path string) string { return fmt.Sprintf("source%d", crc32.ChecksumIEEE([]byte(path))) }