From a97684923a2c7391bc94d23d419d1b03ea4e8990 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Thu, 11 Oct 2018 21:17:43 +0200 Subject: [PATCH] refactor: socketpair into utils package (useful elsewhere) --- daemon/serve/serve_local.go | 48 ++-------------------------------- util/socketpair/socketpair.go | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 46 deletions(-) create mode 100644 util/socketpair/socketpair.go diff --git a/daemon/serve/serve_local.go b/daemon/serve/serve_local.go index 19498fc..f71ba70 100644 --- a/daemon/serve/serve_local.go +++ b/daemon/serve/serve_local.go @@ -4,9 +4,8 @@ import ( "context" "fmt" "github.com/zrepl/zrepl/config" - "golang.org/x/sys/unix" + "github.com/zrepl/zrepl/util/socketpair" "net" - "os" "sync" ) @@ -135,7 +134,7 @@ func (l *LocalListener) Accept(ctx context.Context) (AuthenticatedConn, error) { } getLogger(ctx).Debug("creating socketpair") - left, right, err := makeSocketpairConn() + left, right, err := socketpair.SocketPair() if err != nil { res := connectResult{nil, fmt.Errorf("server error: %s", err)} if respErr := respondToRequest(req, res); respErr != nil { @@ -161,49 +160,6 @@ func (l *LocalListener) Accept(ctx context.Context) (AuthenticatedConn, error) { return localConn{right, req.clientIdentity}, nil } -type fileConn struct { - net.Conn // net.FileConn - f *os.File -} - -func (c fileConn) Close() error { - if err := c.Conn.Close(); err != nil { - return err - } - if err := c.f.Close(); err != nil { - return err - } - return nil -} - -func makeSocketpairConn() (a, b net.Conn, err error) { - // don't use net.Pipe, as it doesn't implement things like lingering, which our code relies on - sockpair, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0) - if err != nil { - return nil, nil, err - } - toConn := func(fd int) (net.Conn, error) { - f := os.NewFile(uintptr(fd), "fileconn") - if f == nil { - panic(fd) - } - c, err := net.FileConn(f) - if err != nil { - f.Close() - return nil, err - } - return fileConn{Conn: c, f: f}, nil - } - if a, err = toConn(sockpair[0]); err != nil { // shadowing - return nil, nil, err - } - if b, err = toConn(sockpair[1]); err != nil { // shadowing - a.Close() - return nil, nil, err - } - return a, b, nil -} - func (l *LocalListener) Close() error { // FIXME: make sure concurrent Accepts return with error, and further Accepts return that error, too // Example impl: for each accept, do context.WithCancel, and store the cancel in a list diff --git a/util/socketpair/socketpair.go b/util/socketpair/socketpair.go new file mode 100644 index 0000000..615c8f2 --- /dev/null +++ b/util/socketpair/socketpair.go @@ -0,0 +1,49 @@ +package socketpair + +import ( + "golang.org/x/sys/unix" + "net" + "os" +) +type fileConn struct { + net.Conn // net.FileConn + f *os.File +} + +func (c fileConn) Close() error { + if err := c.Conn.Close(); err != nil { + return err + } + if err := c.f.Close(); err != nil { + return err + } + return nil +} + +func SocketPair() (a, b net.Conn, err error) { + // don't use net.Pipe, as it doesn't implement things like lingering, which our code relies on + sockpair, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0) + if err != nil { + return nil, nil, err + } + toConn := func(fd int) (net.Conn, error) { + f := os.NewFile(uintptr(fd), "fileconn") + if f == nil { + panic(fd) + } + c, err := net.FileConn(f) + if err != nil { + f.Close() + return nil, err + } + return fileConn{Conn: c, f: f}, nil + } + if a, err = toConn(sockpair[0]); err != nil { // shadowing + return nil, nil, err + } + if b, err = toConn(sockpair[1]); err != nil { // shadowing + a.Close() + return nil, nil, err + } + return a, b, nil +}