diff --git a/pkg/transport/listener.go b/pkg/transport/listener.go index 4e38bf95f..d94757b2c 100644 --- a/pkg/transport/listener.go +++ b/pkg/transport/listener.go @@ -25,7 +25,6 @@ import ( "fmt" "math/big" "net" - "net/http" "os" "path" "strings" @@ -35,19 +34,19 @@ import ( "github.com/coreos/etcd/pkg/tlsutil" ) -func NewListener(addr string, scheme string, tlscfg *tls.Config) (net.Listener, error) { - nettype := "tcp" - if scheme == "unix" { +func NewListener(addr string, scheme string, tlscfg *tls.Config) (l net.Listener, err error) { + if scheme == "unix" || scheme == "unixs" { // unix sockets via unix://laddr - nettype = scheme + l, err = NewUnixListener(addr) + } else { + l, err = net.Listen("tcp", addr) } - l, err := net.Listen(nettype, addr) if err != nil { return nil, err } - if scheme == "https" { + if scheme == "https" || scheme == "unixs" { if tlscfg == nil { return nil, fmt.Errorf("cannot listen on TLS for %s: KeyFile and CertFile are not presented", scheme+"://"+addr) } @@ -58,27 +57,6 @@ func NewListener(addr string, scheme string, tlscfg *tls.Config) (net.Listener, return l, nil } -func NewTransport(info TLSInfo, dialtimeoutd time.Duration) (*http.Transport, error) { - cfg, err := info.ClientConfig() - if err != nil { - return nil, err - } - - t := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: (&net.Dialer{ - Timeout: dialtimeoutd, - // value taken from http.DefaultTransport - KeepAlive: 30 * time.Second, - }).Dial, - // value taken from http.DefaultTransport - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: cfg, - } - - return t, nil -} - type TLSInfo struct { CertFile string KeyFile string diff --git a/pkg/transport/transport.go b/pkg/transport/transport.go new file mode 100644 index 000000000..ca9ccfd80 --- /dev/null +++ b/pkg/transport/transport.go @@ -0,0 +1,70 @@ +// Copyright 2016 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "net" + "net/http" + "strings" + "time" +) + +type unixTransport struct{ *http.Transport } + +func NewTransport(info TLSInfo, dialtimeoutd time.Duration) (*http.Transport, error) { + cfg, err := info.ClientConfig() + if err != nil { + return nil, err + } + + t := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: (&net.Dialer{ + Timeout: dialtimeoutd, + // value taken from http.DefaultTransport + KeepAlive: 30 * time.Second, + }).Dial, + // value taken from http.DefaultTransport + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: cfg, + } + + dialer := (&net.Dialer{ + Timeout: dialtimeoutd, + KeepAlive: 30 * time.Second, + }) + dial := func(net, addr string) (net.Conn, error) { + return dialer.Dial("unix", addr) + } + + tu := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + Dial: dial, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: cfg, + } + ut := &unixTransport{tu} + + t.RegisterProtocol("unix", ut) + t.RegisterProtocol("unixs", ut) + + return t, nil +} + +func (urt *unixTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := *req + req2.URL.Scheme = strings.Replace(req.URL.Scheme, "unix", "http", 1) + return urt.Transport.RoundTrip(req) +} diff --git a/pkg/transport/unix_listener.go b/pkg/transport/unix_listener.go new file mode 100644 index 000000000..c126b6f7f --- /dev/null +++ b/pkg/transport/unix_listener.go @@ -0,0 +1,40 @@ +// Copyright 2016 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package transport + +import ( + "net" + "os" +) + +type unixListener struct{ net.Listener } + +func NewUnixListener(addr string) (net.Listener, error) { + if err := os.RemoveAll(addr); err != nil { + return nil, err + } + l, err := net.Listen("unix", addr) + if err != nil { + return nil, err + } + return &unixListener{l}, nil +} + +func (ul *unixListener) Close() error { + if err := os.RemoveAll(ul.Addr().String()); err != nil { + return err + } + return ul.Listener.Close() +}