diff --git a/beam/service.go b/beam/service.go new file mode 100644 index 0000000..69e82e7 --- /dev/null +++ b/beam/service.go @@ -0,0 +1,89 @@ +package beam + +import ( + "net" +) + +// Listen is a convenience interface for applications to create service endpoints +// which can be easily used with existing networking code. +// +// Listen registers a new service endpoint on the beam connection `conn`, using the +// service name `name`. It returns a listener which can be used in the usual +// way. Calling Accept() on the listener will block until a new connection is available +// on the service endpoint. The endpoint is then returned as a regular net.Conn and +// can be used as a regular network connection. +// +// Note that if the underlying file descriptor received in attachment is nil or does +// not point to a connection, that message will be skipped. +// +func Listen(conn *net.UnixConn, name string) (net.Listener, error) { + fEndpoint, err := SendPipe(conn, []byte(name)) + if err != nil { + return nil, err + } + endpoint, err := FdConn(int(fEndpoint.Fd())) + if err != nil { + return nil, err + } + return &listener{ + name: name, + endpoint: endpoint, + }, nil +} + +func Connect(ctx *net.UnixConn, name string) (net.Conn, error) { + l, err := Listen(ctx, name) + if err != nil { + return nil, err + } + conn, err := l.Accept() + if err != nil { + return nil, err + } + return conn, nil +} + +type listener struct { + name string + endpoint *net.UnixConn +} + +func (l *listener) Accept() (net.Conn, error) { + for { + _, f, err := Receive(l.endpoint) + if err != nil { + return nil, err + } + if f == nil { + // Skip empty attachments + continue + } + conn, err := net.FileConn(f) + if err != nil { + // Skip beam attachments which are not connections + // (for example might be a regular file, directory etc) + continue + } + return conn, nil + } + panic("impossibru!") + return nil, nil +} + +func (l *listener) Close() error { + return l.endpoint.Close() +} + +func (l *listener) Addr() net.Addr { + return addr(l.name) +} + +type addr string + +func (a addr) Network() string { + return "beam" +} + +func (a addr) String() string { + return string(a) +} diff --git a/beam/unix.go b/beam/unix.go index 0bee722..7549a51 100644 --- a/beam/unix.go +++ b/beam/unix.go @@ -1,10 +1,10 @@ package beam import ( - "syscall" "fmt" "net" "os" + "syscall" ) // Send sends a new message on conn with data and f as payload and @@ -100,7 +100,6 @@ func sendUnix(conn *net.UnixConn, data []byte, fds ...int) error { return err } - func extractFds(oob []byte) (fds []int) { scms, err := syscall.ParseSocketControlMessage(oob) if err != nil {