refactor: socketpair into utils package (useful elsewhere)

This commit is contained in:
Christian Schwarz 2018-10-11 21:17:43 +02:00
parent 1643198713
commit a97684923a
2 changed files with 51 additions and 46 deletions

View File

@ -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

View File

@ -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
}