func main() { var normal tec.TempErrCatcher var skipper tec.TempErrCatcher skipper.IsTemp = func(e error) bool { return e == ErrSkip } fmt.Println("trying normal (uses Temporary interface)") tryTec(normal) fmt.Println("") fmt.Println("trying skipper (uses our IsTemp function)") tryTec(skipper) }
// Accept waits for and returns the next connection to the listener. // Note that unfortunately this func (l *listener) Accept() (net.Conn, error) { // listeners dont have contexts. given changes dont make sense here anymore // note that the parent of listener will Close, which will interrupt all io. // Contexts and io don't mix. ctx := context.Background() var catcher tec.TempErrCatcher catcher.IsTemp = func(e error) bool { // ignore connection breakages up to this point. but log them if e == io.EOF { log.Debugf("listener ignoring conn with EOF: %s", e) return true } te, ok := e.(tec.Temporary) if ok { log.Debugf("listener ignoring conn with temporary err: %s", e) return te.Temporary() } return false } for { maconn, err := l.Listener.Accept() if err != nil { if catcher.IsTemporary(err) { continue } return nil, err } log.Debugf("listener %s got connection: %s <---> %s", l, maconn.LocalMultiaddr(), maconn.RemoteMultiaddr()) if l.filters != nil && l.filters.AddrBlocked(maconn.RemoteMultiaddr()) { log.Debugf("blocked connection from %s", maconn.RemoteMultiaddr()) maconn.Close() continue } // If we have a wrapper func, wrap this conn if l.wrapper != nil { maconn = l.wrapper(maconn) } c, err := newSingleConn(ctx, l.local, "", maconn) if err != nil { if catcher.IsTemporary(err) { continue } return nil, err } if l.privk == nil || EncryptConnections == false { log.Warning("listener %s listening INSECURELY!", l) return c, nil } sc, err := newSecureConn(ctx, l.privk, c) if err != nil { log.Infof("ignoring conn we failed to secure: %s %s", err, c) continue } return sc, nil } }