Skip to content

Instantly share code, notes, and snippets.

@naquad
Created June 27, 2014 14:50
Show Gist options
  • Save naquad/8a26877ec0cc1cd6d26a to your computer and use it in GitHub Desktop.
Save naquad/8a26877ec0cc1cd6d26a to your computer and use it in GitHub Desktop.
func parseAddr(spec string) (p string, a string, e error) {
split := strings.Split(p, "://")
switch len(split) {
case 1:
p = "tcp"
a = split[0]
case 2:
p = strings.ToLower(split[0])
a = split[1]
default:
e = fmt.Errorf("Invalid address specification: %s", spec)
return
}
a = strings.ToLower(a)
if p != "tcp" && p != "tcp6" {
e = fmt.Errorf("Unsupported protocol: %s", spec)
}
return
}
func closeListeners(x map[string]net.Listener) {
for _, l := range x {
l.Close()
}
}
func mkKey(p string, a string) (string) {
var b bytes.Buffer
b.WriteString(p)
b.WriteString("://")
if p == "tcp" && strings.HasPrefix(a, ":") {
b.WriteString("0.0.0.0")
} else if p == "tcp6" && strings.Count(a, ":") == 1 {
b.WriteString("::0")
}
b.WriteString(a)
return b.String()
}
// listen to given addresses.
// if at least one of the listens fails then close created listeners
// and return error, don't touch existing ones.
// in case when address is already listened then it should be kept
func (s *MultiServer) Listen(listen []string, err error) {
keep := make(map[string]net.Listener)
made := make(map[string]net.Listener)
for _, addr := range listen {
p, a, e := parseAddr(addr)
if e != nil {
closeListeners(made)
return
}
k := mkKey(p, a)
_, exists := s.listening[k]
if exists {
keep[k] = s.listening[k]
} else {
l, e := net.Listen(p, a)
if e != nil {
closeListeners(made)
return
}
made[k] = l
}
}
for k, x := range s.listening {
_, exists := keep[k]
if !exists {
s.closed[x] = true
delete(s.listening, k)
x.Close()
}
}
for k, x := range made {
s.listening[k] = x
}
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment