// Channel returns net.Conn or os.Error. It receives anything to mean close. func Listen(addr string, fdlim *http.FDLimiter) (chan interface{}, os.Error) { l, err := net.Listen("tcp", addr) if err != nil { return nil, err } cc := make(chan interface{}) go func() { for { _, sig := <-cc if sig || closed(cc) { l.Close() return } if fdlim == nil || fdlim.LockOrTimeout(10e9) == nil { c, err := l.Accept() if err != nil { if c != nil { c.Close() } if fdlim != nil { fdlim.Unlock() } l.Close() cc <- err return } if fdlim != nil { cc <- http.NewConnRunOnClose(c, func() { fdlim.Unlock() }) } else { cc <- c } } else { log.Stderrf("accept, fd starvation\n") } } // for }() return cc, nil }
func (y *Conn) Connect(addr string, fdlim *http.FDLimiter) (err os.Error) { var alrm <-chan int backoff := backoff.Backoff{ Lo: backoffLo, Hi: backoffHi, Ratio: backoffRatio, Current: backoffLo, Attempt: 0, } for { if err = y.setRegime(regimeConnect); err != nil { return err } if alrm != nil { <-alrm alrm = nil } var conn net.Conn if fdlim.LockOrTimeout(timeForFD) == nil { conn, err = net.Dial("tcp", "", addr) if err == nil { //fmt.Printf(term.FgGreen+"d·conn[%#p] —— connected\n"+term.Reset, y) if err := conn.(*net.TCPConn).SetKeepAlive(true); err != nil { //log.Stderrf("%#p d·conn —— cannot set tcp keepalive: %s", y, err) fmt.Fprintf(os.Stderr, "tonika: warn: cannot set tcp keepalive\n") } conn = http.NewConnRunOnClose(conn, func() { fdlim.Unlock() }) if err = y.Attach(conn); err != nil { conn.Close() } return err } fdlim.Unlock() } alrm = alarm.Ignite(backoff.Inc()) } panic("unreachable") }