mirror of
https://github.com/zrepl/zrepl.git
synced 2025-06-20 09:47:50 +02:00
refactor: socketpair into utils package (useful elsewhere)
This commit is contained in:
parent
1643198713
commit
a97684923a
@ -4,9 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/zrepl/zrepl/config"
|
"github.com/zrepl/zrepl/config"
|
||||||
"golang.org/x/sys/unix"
|
"github.com/zrepl/zrepl/util/socketpair"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -135,7 +134,7 @@ func (l *LocalListener) Accept(ctx context.Context) (AuthenticatedConn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getLogger(ctx).Debug("creating socketpair")
|
getLogger(ctx).Debug("creating socketpair")
|
||||||
left, right, err := makeSocketpairConn()
|
left, right, err := socketpair.SocketPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res := connectResult{nil, fmt.Errorf("server error: %s", err)}
|
res := connectResult{nil, fmt.Errorf("server error: %s", err)}
|
||||||
if respErr := respondToRequest(req, res); respErr != nil {
|
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
|
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 {
|
func (l *LocalListener) Close() error {
|
||||||
// FIXME: make sure concurrent Accepts return with error, and further Accepts return that error, too
|
// 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
|
// Example impl: for each accept, do context.WithCancel, and store the cancel in a list
|
||||||
|
49
util/socketpair/socketpair.go
Normal file
49
util/socketpair/socketpair.go
Normal 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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user