general: optimize codes

This commit is contained in:
nadoo 2017-08-16 22:37:42 +08:00
parent 5fef071349
commit 4574ab1c1a
14 changed files with 96 additions and 96 deletions

4
dns.go
View File

@ -32,9 +32,9 @@ type DNS struct {
} }
// DNSForwarder returns a dns forwarder. client -> dns.udp -> glider -> forwarder -> remote dns addr // DNSForwarder returns a dns forwarder. client -> dns.udp -> glider -> forwarder -> remote dns addr
func DNSForwarder(addr, raddr string, upProxy Proxy) (*DNS, error) { func NewDNS(addr, raddr string, upProxy Proxy) (*DNS, error) {
s := &DNS{ s := &DNS{
proxy: newProxy(addr, upProxy), proxy: NewProxy(addr, upProxy),
dnsServer: raddr, dnsServer: raddr,
dnsServerMap: make(map[string]string), dnsServerMap: make(map[string]string),
} }

View File

@ -2,7 +2,7 @@
package main package main
type dnstun struct { type DNSTun struct {
*proxy *proxy
raddr string raddr string
@ -10,21 +10,21 @@ type dnstun struct {
tcp Proxy tcp Proxy
} }
// DNSTun returns a dns forwarder. // NewDNSTun returns a dns forwarder.
func DNSTun(addr, raddr string, upProxy Proxy) (Proxy, error) { func NewDNSTun(addr, raddr string, upProxy Proxy) (*DNSTun, error) {
s := &dnstun{ s := &DNSTun{
proxy: newProxy(addr, upProxy), proxy: NewProxy(addr, upProxy),
raddr: raddr, raddr: raddr,
} }
s.udp, _ = DNSForwarder(addr, raddr, upProxy) s.udp, _ = NewDNS(addr, raddr, upProxy)
s.tcp, _ = TCPTun(addr, raddr, upProxy) s.tcp, _ = NewTCPTun(addr, raddr, upProxy)
return s, nil return s, nil
} }
// ListenAndServe . // ListenAndServe .
func (s *dnstun) ListenAndServe() { func (s *DNSTun) ListenAndServe() {
if s.udp != nil { if s.udp != nil {
go s.udp.ListenAndServe() go s.udp.ListenAndServe()
} }

16
http.go
View File

@ -17,21 +17,21 @@ import (
) )
// httpproxy // httpproxy
type httpproxy struct { type HTTPProxy struct {
*proxy *proxy
} }
// HTTPProxy returns a http proxy. // HTTPProxy returns a http proxy.
func HTTPProxy(addr string, upProxy Proxy) (Proxy, error) { func NewHTTPProxy(addr string, upProxy Proxy) (*HTTPProxy, error) {
s := &httpproxy{ s := &HTTPProxy{
proxy: newProxy(addr, upProxy), proxy: NewProxy(addr, upProxy),
} }
return s, nil return s, nil
} }
// ListenAndServe . // ListenAndServe .
func (s *httpproxy) ListenAndServe() { func (s *HTTPProxy) ListenAndServe() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", s.addr, err) logf("failed to listen on %s: %v", s.addr, err)
@ -53,7 +53,7 @@ func (s *httpproxy) ListenAndServe() {
} }
// Serve . // Serve .
func (s *httpproxy) Serve(c net.Conn) { func (s *HTTPProxy) Serve(c net.Conn) {
defer c.Close() defer c.Close()
if c, ok := c.(*net.TCPConn); ok { if c, ok := c.(*net.TCPConn); ok {
@ -147,7 +147,7 @@ func (s *httpproxy) Serve(c net.Conn) {
} }
func (s *httpproxy) servHTTPS(method, requestURI, proto string, c net.Conn) { func (s *HTTPProxy) servHTTPS(method, requestURI, proto string, c net.Conn) {
rc, err := s.GetProxy(requestURI).Dial("tcp", requestURI) rc, err := s.GetProxy(requestURI).Dial("tcp", requestURI)
if err != nil { if err != nil {
c.Write([]byte(proto)) c.Write([]byte(proto))
@ -170,7 +170,7 @@ func (s *httpproxy) servHTTPS(method, requestURI, proto string, c net.Conn) {
} }
// Dial connects to the address addr on the network net via the proxy. // Dial connects to the address addr on the network net via the proxy.
func (s *httpproxy) Dial(network, addr string) (net.Conn, error) { func (s *HTTPProxy) Dial(network, addr string) (net.Conn, error) {
rc, err := s.GetProxy(s.addr).Dial("tcp", s.addr) rc, err := s.GetProxy(s.addr).Dial("tcp", s.addr)
if err != nil { if err != nil {
logf("dial to %s error: %s", s.addr, err) logf("dial to %s error: %s", s.addr, err)

10
main.go
View File

@ -156,12 +156,12 @@ func main() {
} }
// combine forwarders to a singer strategy forwarder // combine forwarders to a singer strategy forwarder
forwarder := newStrategyForwarder(conf.Strategy, forwarders) forwarder := NewStrategyForwarder(conf.Strategy, forwarders)
// rule forwarders // rule forwarders
var ruleForwarders []*ruleForwarder var ruleForwarders []*RuleForwarder
for _, ruleFile := range conf.RuleFile { for _, ruleFile := range conf.RuleFile {
ruleForwarder, err := newRuleProxyFromFile(ruleFile) ruleForwarder, err := NewRuleProxyFromFile(ruleFile)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -170,7 +170,7 @@ func main() {
} }
// combine ruleforwarders and global strategy forwarder // combine ruleforwarders and global strategy forwarder
forwarder = newRulesForwarder(ruleForwarders, forwarder) forwarder = NewRulesForwarder(ruleForwarders, forwarder)
for _, listen := range conf.Listen { for _, listen := range conf.Listen {
local, err := ProxyFromURL(listen, forwarder) local, err := ProxyFromURL(listen, forwarder)
@ -188,7 +188,7 @@ func main() {
} }
if conf.DNS != "" { if conf.DNS != "" {
dns, err := DNSForwarder(conf.DNS, conf.DNSServer[0], forwarder) dns, err := NewDNS(conf.DNS, conf.DNSServer[0], forwarder)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -17,8 +17,8 @@ var httpMethods = [][]byte{
[]byte("TRACE"), []byte("TRACE"),
} }
// mixedproxy // MixedProxy .
type mixedproxy struct { type MixedProxy struct {
*proxy *proxy
http Proxy http Proxy
socks5 Proxy socks5 Proxy
@ -26,23 +26,23 @@ type mixedproxy struct {
} }
// MixedProxy returns a mixed proxy. // MixedProxy returns a mixed proxy.
func MixedProxy(network, addr, user, pass string, upProxy Proxy) (Proxy, error) { func NewMixedProxy(network, addr, user, pass string, upProxy Proxy) (*MixedProxy, error) {
p := &mixedproxy{ p := &MixedProxy{
proxy: newProxy(addr, upProxy), proxy: NewProxy(addr, upProxy),
} }
p.http, _ = HTTPProxy(addr, upProxy) p.http, _ = NewHTTPProxy(addr, upProxy)
p.socks5, _ = SOCKS5Proxy(network, addr, user, pass, upProxy) p.socks5, _ = NewSOCKS5Proxy(network, addr, user, pass, upProxy)
if user != "" && pass != "" { if user != "" && pass != "" {
p.ss, _ = SSProxy(addr, user, pass, upProxy) p.ss, _ = NewSSProxy(addr, user, pass, upProxy)
} }
return p, nil return p, nil
} }
// mixedproxy . // mixedproxy .
func (p *mixedproxy) ListenAndServe() { func (p *MixedProxy) ListenAndServe() {
l, err := net.Listen("tcp", p.addr) l, err := net.Listen("tcp", p.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", p.addr, err) logf("failed to listen on %s: %v", p.addr, err)

View File

@ -47,8 +47,8 @@ type proxy struct {
enabled bool enabled bool
} }
// newProxy . // NewProxy .
func newProxy(addr string, forward Proxy) *proxy { func NewProxy(addr string, forward Proxy) *proxy {
if forward == nil { if forward == nil {
forward = Direct forward = Direct
} }
@ -91,22 +91,22 @@ func ProxyFromURL(s string, forwarder Proxy) (Proxy, error) {
switch u.Scheme { switch u.Scheme {
case "mixed": case "mixed":
return MixedProxy("tcp", addr, user, pass, forwarder) return NewMixedProxy("tcp", addr, user, pass, forwarder)
case "http": case "http":
return HTTPProxy(addr, forwarder) return NewHTTPProxy(addr, forwarder)
case "socks5": case "socks5":
return SOCKS5Proxy("tcp", addr, user, pass, forwarder) return NewSOCKS5Proxy("tcp", addr, user, pass, forwarder)
case "ss": case "ss":
p, err := SSProxy(addr, user, pass, forwarder) p, err := NewSSProxy(addr, user, pass, forwarder)
return p, err return p, err
case "redir": case "redir":
return RedirProxy(addr, forwarder) return NewRedirProxy(addr, forwarder)
case "tcptun": case "tcptun":
d := strings.Split(addr, "=") d := strings.Split(addr, "=")
return TCPTun(d[0], d[1], forwarder) return NewTCPTun(d[0], d[1], forwarder)
case "dnstun": case "dnstun":
d := strings.Split(addr, "=") d := strings.Split(addr, "=")
return DNSTun(d[0], d[1], forwarder) return NewDNSTun(d[0], d[1], forwarder)
} }
return nil, errors.New("unknown schema '" + u.Scheme + "'") return nil, errors.New("unknown schema '" + u.Scheme + "'")

View File

@ -17,12 +17,12 @@ const (
IP6T_SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv6/ip6_tables.h IP6T_SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv6/ip6_tables.h
) )
type redir struct { type RedirProxy struct {
*proxy *proxy
} }
// RedirProxy returns a redirect proxy. // NewRedirProxy returns a redirect proxy.
func RedirProxy(addr string, upProxy Proxy) (Proxy, error) { func NewRedirProxy(addr string, upProxy Proxy) (*RedirProxy, error) {
s := &redir{ s := &redir{
proxy: newProxy(addr, upProxy), proxy: newProxy(addr, upProxy),
} }
@ -31,7 +31,7 @@ func RedirProxy(addr string, upProxy Proxy) (Proxy, error) {
} }
// ListenAndServe redirected requests as a server. // ListenAndServe redirected requests as a server.
func (s *redir) ListenAndServe() { func (s *RedirProxy) ListenAndServe() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", s.addr, err) logf("failed to listen on %s: %v", s.addr, err)

View File

@ -4,14 +4,14 @@ package main
import "log" import "log"
type redir struct{ *proxy } type RedirProxy struct{ *proxy }
// RedirProxy returns a redirect proxy. // NewRedirProxy returns a redirect proxy.
func RedirProxy(addr string, upProxy Proxy) (Proxy, error) { func NewRedirProxy(addr string, upProxy Proxy) (Proxy, error) {
return &redir{proxy: newProxy(addr, upProxy)}, nil return &RedirProxy{proxy: NewProxy(addr, upProxy)}, nil
} }
// ListenAndServe redirected requests as a server. // ListenAndServe redirected requests as a server.
func (s *redir) ListenAndServe() { func (s *RedirProxy) ListenAndServe() {
log.Fatal("redir not supported on this os") log.Fatal("redir not supported on this os")
} }

12
rule.go
View File

@ -9,8 +9,8 @@ import (
"github.com/nadoo/conflag" "github.com/nadoo/conflag"
) )
// ruleForwarder, every ruleForwarder points to a rule file // RuleForwarder, every ruleForwarder points to a rule file
type ruleForwarder struct { type RuleForwarder struct {
Forward []string Forward []string
Strategy string Strategy string
CheckWebSite string CheckWebSite string
@ -27,9 +27,9 @@ type ruleForwarder struct {
Proxy Proxy
} }
// newRuleProxyFromFile . // NewRuleProxyFromFile .
func newRuleProxyFromFile(ruleFile string) (*ruleForwarder, error) { func NewRuleProxyFromFile(ruleFile string) (*RuleForwarder, error) {
p := &ruleForwarder{name: ruleFile} p := &RuleForwarder{name: ruleFile}
f := conflag.NewFromFile("rule", ruleFile) f := conflag.NewFromFile("rule", ruleFile)
f.StringSliceUniqVar(&p.Forward, "forward", nil, "forward url, format: SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT[,SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT]") f.StringSliceUniqVar(&p.Forward, "forward", nil, "forward url, format: SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT[,SCHEMA://[USER|METHOD:PASSWORD@][HOST]:PORT]")
@ -63,7 +63,7 @@ func newRuleProxyFromFile(ruleFile string) (*ruleForwarder, error) {
forwarders = append(forwarders, forward) forwarders = append(forwarders, forward)
} }
forwarder := newStrategyForwarder(p.Strategy, forwarders) forwarder := NewStrategyForwarder(p.Strategy, forwarders)
for _, forward := range forwarders { for _, forward := range forwarders {
go check(forward, p.CheckWebSite, p.CheckDuration) go check(forward, p.CheckWebSite, p.CheckDuration)

View File

@ -5,7 +5,7 @@ import (
"strings" "strings"
) )
type rulesForwarder struct { type RulesForwarder struct {
globalForwarder Proxy globalForwarder Proxy
domainMap map[string]Proxy domainMap map[string]Proxy
@ -13,14 +13,14 @@ type rulesForwarder struct {
cidrMap map[string]Proxy cidrMap map[string]Proxy
} }
// newRulesForwarder . // NewRulesForwarder .
func newRulesForwarder(ruleForwarders []*ruleForwarder, globalForwarder Proxy) Proxy { func NewRulesForwarder(ruleForwarders []*RuleForwarder, globalForwarder Proxy) Proxy {
if len(ruleForwarders) == 0 { if len(ruleForwarders) == 0 {
return globalForwarder return globalForwarder
} }
p := &rulesForwarder{globalForwarder: globalForwarder} p := &RulesForwarder{globalForwarder: globalForwarder}
for _, f := range ruleForwarders { for _, f := range ruleForwarders {
p.domainMap = make(map[string]Proxy) p.domainMap = make(map[string]Proxy)
@ -42,12 +42,12 @@ func newRulesForwarder(ruleForwarders []*ruleForwarder, globalForwarder Proxy) P
return p return p
} }
func (p *rulesForwarder) Addr() string { return "rules forwarder" } func (p *RulesForwarder) Addr() string { return "rules forwarder" }
func (p *rulesForwarder) ListenAndServe() {} func (p *RulesForwarder) ListenAndServe() {}
func (p *rulesForwarder) Serve(c net.Conn) {} func (p *RulesForwarder) Serve(c net.Conn) {}
func (p *rulesForwarder) CurrentProxy() Proxy { return p.globalForwarder.CurrentProxy() } func (p *RulesForwarder) CurrentProxy() Proxy { return p.globalForwarder.CurrentProxy() }
func (p *rulesForwarder) GetProxy(dstAddr string) Proxy { func (p *RulesForwarder) GetProxy(dstAddr string) Proxy {
// TODO: change to index finders // TODO: change to index finders
host, _, err := net.SplitHostPort(dstAddr) host, _, err := net.SplitHostPort(dstAddr)
@ -89,13 +89,13 @@ func (p *rulesForwarder) GetProxy(dstAddr string) Proxy {
return p.globalForwarder.GetProxy(dstAddr) return p.globalForwarder.GetProxy(dstAddr)
} }
func (p *rulesForwarder) NextProxy() Proxy { func (p *RulesForwarder) NextProxy() Proxy {
return p.globalForwarder.NextProxy() return p.globalForwarder.NextProxy()
} }
func (p *rulesForwarder) Enabled() bool { return true } func (p *RulesForwarder) Enabled() bool { return true }
func (p *rulesForwarder) SetEnable(enable bool) {} func (p *RulesForwarder) SetEnable(enable bool) {}
func (p *rulesForwarder) Dial(network, addr string) (net.Conn, error) { func (p *RulesForwarder) Dial(network, addr string) (net.Conn, error) {
return p.GetProxy(addr).Dial(network, addr) return p.GetProxy(addr).Dial(network, addr)
} }

View File

@ -55,18 +55,18 @@ var socks5Errors = []string{
"address type not supported", "address type not supported",
} }
type socks5 struct { type SOCKS5Proxy struct {
*proxy *proxy
network string network string
user string user string
password string password string
} }
// SOCKS5Proxy returns a Proxy that makes SOCKSv5 connections to the given address // NewSOCKS5Proxy returns a Proxy that makes SOCKSv5 connections to the given address
// with an optional username and password. See RFC 1928. // with an optional username and password. See RFC 1928.
func SOCKS5Proxy(network, addr, user, pass string, upProxy Proxy) (Proxy, error) { func NewSOCKS5Proxy(network, addr, user, pass string, upProxy Proxy) (*SOCKS5Proxy, error) {
s := &socks5{ s := &SOCKS5Proxy{
proxy: newProxy(addr, upProxy), proxy: NewProxy(addr, upProxy),
user: user, user: user,
password: pass, password: pass,
} }
@ -75,7 +75,7 @@ func SOCKS5Proxy(network, addr, user, pass string, upProxy Proxy) (Proxy, error)
} }
// ListenAndServe connects to the address addr on the network net via the SOCKS5 proxy. // ListenAndServe connects to the address addr on the network net via the SOCKS5 proxy.
func (s *socks5) ListenAndServe() { func (s *SOCKS5Proxy) ListenAndServe() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", s.addr, err) logf("failed to listen on %s: %v", s.addr, err)
@ -95,7 +95,7 @@ func (s *socks5) ListenAndServe() {
} }
} }
func (s *socks5) Serve(c net.Conn) { func (s *SOCKS5Proxy) Serve(c net.Conn) {
defer c.Close() defer c.Close()
if c, ok := c.(*net.TCPConn); ok { if c, ok := c.(*net.TCPConn); ok {
@ -127,7 +127,7 @@ func (s *socks5) Serve(c net.Conn) {
} }
// Dial connects to the address addr on the network net via the SOCKS5 proxy. // Dial connects to the address addr on the network net via the SOCKS5 proxy.
func (s *socks5) Dial(network, addr string) (net.Conn, error) { func (s *SOCKS5Proxy) Dial(network, addr string) (net.Conn, error) {
switch network { switch network {
case "tcp", "tcp6", "tcp4": case "tcp", "tcp6", "tcp4":
default: default:
@ -155,7 +155,7 @@ func (s *socks5) Dial(network, addr string) (net.Conn, error) {
// connect takes an existing connection to a socks5 proxy server, // connect takes an existing connection to a socks5 proxy server,
// and commands the server to extend that connection to target, // and commands the server to extend that connection to target,
// which must be a canonical address with a host and port. // which must be a canonical address with a host and port.
func (s *socks5) connect(conn net.Conn, target string) error { func (s *SOCKS5Proxy) connect(conn net.Conn, target string) error {
host, portStr, err := net.SplitHostPort(target) host, portStr, err := net.SplitHostPort(target)
if err != nil { if err != nil {
return err return err
@ -286,7 +286,7 @@ func (s *socks5) connect(conn net.Conn, target string) error {
} }
// Handshake fast-tracks SOCKS initialization to get target address to connect. // Handshake fast-tracks SOCKS initialization to get target address to connect.
func (s *socks5) handshake(rw io.ReadWriter) (Addr, error) { func (s *SOCKS5Proxy) handshake(rw io.ReadWriter) (Addr, error) {
// Read RFC 1928 for request and reply structure and sizes. // Read RFC 1928 for request and reply structure and sizes.
buf := make([]byte, MaxAddrLen) buf := make([]byte, MaxAddrLen)
// read VER, NMETHODS, METHODS // read VER, NMETHODS, METHODS

16
ss.go
View File

@ -10,20 +10,20 @@ import (
) )
// ss // ss
type ss struct { type SSProxy struct {
*proxy *proxy
core.StreamConnCipher core.StreamConnCipher
} }
// SSProxy returns a shadowsocks proxy. // NewSSProxy returns a shadowsocks proxy.
func SSProxy(addr, method, pass string, upProxy Proxy) (Proxy, error) { func NewSSProxy(addr, method, pass string, upProxy Proxy) (*SSProxy, error) {
ciph, err := core.PickCipher(method, nil, pass) ciph, err := core.PickCipher(method, nil, pass)
if err != nil { if err != nil {
log.Fatalf("PickCipher for '%s', error: %s", method, err) log.Fatalf("PickCipher for '%s', error: %s", method, err)
} }
s := &ss{ s := &SSProxy{
proxy: newProxy(addr, upProxy), proxy: NewProxy(addr, upProxy),
StreamConnCipher: ciph, StreamConnCipher: ciph,
} }
@ -31,7 +31,7 @@ func SSProxy(addr, method, pass string, upProxy Proxy) (Proxy, error) {
} }
// ListenAndServe shadowsocks requests as a server. // ListenAndServe shadowsocks requests as a server.
func (s *ss) ListenAndServe() { func (s *SSProxy) ListenAndServe() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", s.addr, err) logf("failed to listen on %s: %v", s.addr, err)
@ -50,7 +50,7 @@ func (s *ss) ListenAndServe() {
} }
} }
func (s *ss) Serve(c net.Conn) { func (s *SSProxy) Serve(c net.Conn) {
defer c.Close() defer c.Close()
if c, ok := c.(*net.TCPConn); ok { if c, ok := c.(*net.TCPConn); ok {
@ -85,7 +85,7 @@ func (s *ss) Serve(c net.Conn) {
} }
// Dial connects to the address addr on the network net via the proxy. // Dial connects to the address addr on the network net via the proxy.
func (s *ss) Dial(network, addr string) (net.Conn, error) { func (s *SSProxy) Dial(network, addr string) (net.Conn, error) {
target := ParseAddr(addr) target := ParseAddr(addr)
if target == nil { if target == nil {

View File

@ -2,8 +2,8 @@ package main
import "net" import "net"
// newStrategyForwarder . // NewStrategyForwarder .
func newStrategyForwarder(strategy string, forwarders []Proxy) Proxy { func NewStrategyForwarder(strategy string, forwarders []Proxy) Proxy {
var proxy Proxy var proxy Proxy
if len(forwarders) == 0 { if len(forwarders) == 0 {
proxy = Direct proxy = Direct
@ -37,7 +37,7 @@ func newRRProxy(addr string, forwarders []Proxy) Proxy {
if len(forwarders) == 0 { if len(forwarders) == 0 {
return Direct return Direct
} else if len(forwarders) == 1 { } else if len(forwarders) == 1 {
return newProxy(addr, forwarders[0]) return NewProxy(addr, forwarders[0])
} }
return &rrProxy{forwarders: forwarders} return &rrProxy{forwarders: forwarders}

View File

@ -2,15 +2,15 @@ package main
import "net" import "net"
type tcptun struct { type TCPTun struct {
*proxy *proxy
raddr string raddr string
} }
// TCPTun returns a redirect proxy. // NewTCPTun returns a redirect proxy.
func TCPTun(addr, raddr string, upProxy Proxy) (Proxy, error) { func NewTCPTun(addr, raddr string, upProxy Proxy) (*TCPTun, error) {
s := &tcptun{ s := &TCPTun{
proxy: newProxy(addr, upProxy), proxy: NewProxy(addr, upProxy),
raddr: raddr, raddr: raddr,
} }
@ -18,7 +18,7 @@ func TCPTun(addr, raddr string, upProxy Proxy) (Proxy, error) {
} }
// ListenAndServe redirected requests as a server. // ListenAndServe redirected requests as a server.
func (s *tcptun) ListenAndServe() { func (s *TCPTun) ListenAndServe() {
l, err := net.Listen("tcp", s.addr) l, err := net.Listen("tcp", s.addr)
if err != nil { if err != nil {
logf("failed to listen on %s: %v", s.addr, err) logf("failed to listen on %s: %v", s.addr, err)