예제 #1
0
파일: mux.go 프로젝트: fjballest/clive
// Dial the given address and return a muxed connection
// The connection is secured if tlscfg is not nil.
func MuxDial(addr string, tlscfg ...*tls.Config) (m *ch.Mux, err error) {
	var cfg *tls.Config
	if len(tlscfg) > 0 {
		cfg = tlscfg[0]
	}
	nc, err := dial(addr, cfg)
	if err == nil {
		m = ch.NewMux(nc, true)
		m.Tag = addr
		go func() {
			for _ = range m.In {
			}
		}()
		return m, nil
	}
	return nil, err
}
예제 #2
0
파일: mux.go 프로젝트: fjballest/clive
func serveMuxLoop(l net.Listener, rc chan *ch.Mux, ec chan bool,
	addr, tag string, tlscfg *tls.Config) {
	if strings.HasPrefix(addr, "/tmp/") {
		defer os.Remove(addr)
	}
	closes := map[io.Closer]bool{}
	var closeslk sync.Mutex
	go func() {
		<-ec
		l.Close()
		closeslk.Lock()
		for c := range closes {
			c.Close()
		}
		closeslk.Unlock()
	}()
	var err error
	ncli := 0
	for {
		fd, e := l.Accept()
		if e != nil {
			err = e
			break
		}
		closeslk.Lock()
		var cfd io.Closer = fd
		closes[cfd] = true
		closeslk.Unlock()
		raddr := fd.RemoteAddr().String()
		if raddr == "" {
			// unix sockets do not provide raddr
			raddr = fmt.Sprintf("local!%d", ncli)
			ncli++
		} else {
			if n := strings.LastIndex(raddr, ":"); n > 0 {
				raddr = raddr[:n] + "!" + raddr[n+1:]
			}
		}
		if c, ok := fd.(*net.TCPConn); ok {
			c.SetKeepAlivePeriod(30 * time.Second)
			c.SetKeepAlive(true)
		}
		if tlscfg != nil {
			fd = tls.Server(fd, tlscfg)
		}
		mux := ch.NewMux(fd, false)
		mux.Tag = raddr
		if ok := rc <- mux; !ok {
			close(mux.In, cerror(rc))
			close(ec, cerror(rc))
			break
		}
	}
	close(rc, err)
	close(ec, err)
}

func serveMux1(nw, host, port string, tlscfg *tls.Config) (c <-chan *ch.Mux, ec chan bool, err error) {
	tag := fmt.Sprintf("%s!%s!%s", nw, host, port)
	if nw == "tls" {
		nw = "tcp"
		if tlscfg == nil {
			tlscfg = ServerTLSCfg
			if tlscfg == nil {
				return nil, nil, ErrNoTLSCfg
			}
		}
	}
	if nw == "tcp" && (host == "local" || host == "*" || host == "localhost") {
		host = ""
	}
	addr := host + ":" + port
	if nw == "unix" {
		addr = port
		tlscfg = nil
		os.Remove(port)
	}
	dbg.Warn("listen at %s (%s:%s)", tag, nw, addr)
	fd, err := net.Listen(nw, addr)
	if err != nil {
		return nil, nil, err
	}
	rc := make(chan *ch.Mux)
	rec := make(chan bool)
	go serveMuxLoop(fd, rc, rec, addr, tag, tlscfg)
	return rc, rec, nil
}

func serveMuxBoth(c1 <-chan *ch.Mux, ec1 chan<- bool,
	c2 <-chan *ch.Mux, ec2 chan bool) (c <-chan *ch.Mux, ec chan bool, err error) {
	xc := make(chan *ch.Mux)
	xec := make(chan bool)
	go func() {
		var err error
		doselect {
		case cn, ok := <-c1:
			if !ok {
				err = cerror(c1)
				if c2 == nil {
					break
				}
				c1 = nil
			}
			if ok = xc <- cn; !ok {
				err = cerror(xc)
				break
			}
		case cn, ok := <-c2:
			err = cerror(c2)
			if !ok {
				if c1 == nil {
					break
				}
				c2 = nil
			}
			if ok = xc <- cn; !ok {
				err = cerror(xc)
				break
			}
		case <-xec:
			err = cerror(xec)
			break
		}
		close(ec1, err)
		close(ec2, err)
		close(c1, err)
		close(c2, err)
		close(xec, err)
		close(xc, err)
	}()
	return xc, xec, nil
}