// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package net import "sync" type streamListener struct { net, addr string ln Listener } type dualStackServer struct { lnmu sync.RWMutex lns []streamListener port string cmu sync.RWMutex cs []Conn // established connections at the passive open side } func (dss *dualStackServer) buildup(server func(*dualStackServer, Listener)) error { for i := range dss.lns { go server(dss, dss.lns[i].ln) } return nil } func (dss *dualStackServer) putConn(c Conn) error { dss.cmu.Lock() dss.cs = append(dss.cs, c) dss.cmu.Unlock() return nil } func (dss *dualStackServer) teardownNetwork(net string) error { dss.lnmu.Lock() for i := range dss.lns { if net == dss.lns[i].net && dss.lns[i].ln != nil { dss.lns[i].ln.Close() dss.lns[i].ln = nil } } dss.lnmu.Unlock() return nil } func (dss *dualStackServer) teardown() error { dss.lnmu.Lock() for i := range dss.lns { if dss.lns[i].ln != nil { dss.lns[i].ln.Close() } } dss.lnmu.Unlock() dss.cmu.Lock() for _, c := range dss.cs { c.Close() } dss.cmu.Unlock() return nil } func newDualStackServer(lns []streamListener) (*dualStackServer, error) { dss := &dualStackServer{lns: lns, port: "0"} for i := range dss.lns { ln, err := Listen(dss.lns[i].net, dss.lns[i].addr+":"+dss.port) if err != nil { dss.teardown() return nil, err } dss.lns[i].ln = ln if dss.port == "0" { if _, dss.port, err = SplitHostPort(ln.Addr().String()); err != nil { dss.teardown() return nil, err } } } return dss, nil }