reuseport_plan9.go 867 Bytes
Newer Older
Fazlul Shahriar's avatar
Fazlul Shahriar committed
1 2 3 4 5 6 7
package tcpreuse

import (
	"net"
	"os"
)

8 9 10 11 12
const (
	EADDRINUSE   = "address in use"
	ECONNREFUSED = "connection refused"
)

Fazlul Shahriar's avatar
Fazlul Shahriar committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// reuseErrShouldRetry diagnoses whether to retry after a reuse error.
// if we failed to bind, we should retry. if bind worked and this is a
// real dial error (remote end didnt answer) then we should not retry.
func reuseErrShouldRetry(err error) bool {
	if err == nil {
		return false // hey, it worked! no need to retry.
	}

	// if it's a network timeout error, it's a legitimate failure.
	if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
		return false
	}

	e, ok := err.(*net.OpError)
	if !ok {
		return true
	}

	e1, ok := e.Err.(*os.PathError)
	if !ok {
		return true
	}

	switch e1.Err.Error() {
37
	case EADDRINUSE:
Fazlul Shahriar's avatar
Fazlul Shahriar committed
38
		return true
39
	case ECONNREFUSED:
Fazlul Shahriar's avatar
Fazlul Shahriar committed
40 41 42 43 44
		return false
	default:
		return true // optimistically default to retry.
	}
}