2022-09-17 19:07:00 +00:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net"
|
|
|
|
"net/url"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/Arceliar/phony"
|
|
|
|
)
|
|
|
|
|
|
|
|
type linkUNIX struct {
|
|
|
|
phony.Inbox
|
|
|
|
*links
|
|
|
|
dialer *net.Dialer
|
|
|
|
listener *net.ListenConfig
|
|
|
|
_listeners map[*Listener]context.CancelFunc
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *links) newLinkUNIX() *linkUNIX {
|
|
|
|
lt := &linkUNIX{
|
|
|
|
links: l,
|
|
|
|
dialer: &net.Dialer{
|
|
|
|
Timeout: time.Second * 5,
|
|
|
|
KeepAlive: -1,
|
|
|
|
},
|
|
|
|
listener: &net.ListenConfig{
|
|
|
|
KeepAlive: -1,
|
|
|
|
},
|
|
|
|
_listeners: map[*Listener]context.CancelFunc{},
|
|
|
|
}
|
|
|
|
return lt
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *linkUNIX) dial(url *url.URL, options linkOptions, _ string) error {
|
|
|
|
info := linkInfoFor("unix", "", url.Path)
|
|
|
|
if l.links.isConnectedTo(info) {
|
2022-10-21 18:49:49 +00:00
|
|
|
return nil
|
2022-09-17 19:07:00 +00:00
|
|
|
}
|
|
|
|
addr, err := net.ResolveUnixAddr("unix", url.Path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
conn, err := l.dialer.DialContext(l.core.ctx, "unix", addr.String())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-11-12 11:30:03 +00:00
|
|
|
dial := &linkDial{
|
|
|
|
url: url,
|
|
|
|
}
|
|
|
|
return l.handler(dial, url.String(), info, conn, options, false)
|
2022-09-17 19:07:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *linkUNIX) listen(url *url.URL, _ string) (*Listener, error) {
|
|
|
|
ctx, cancel := context.WithCancel(l.core.ctx)
|
|
|
|
listener, err := l.listener.Listen(ctx, "unix", url.Path)
|
|
|
|
if err != nil {
|
|
|
|
cancel()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
entry := &Listener{
|
|
|
|
Listener: listener,
|
|
|
|
closed: make(chan struct{}),
|
|
|
|
}
|
|
|
|
phony.Block(l, func() {
|
|
|
|
l._listeners[entry] = cancel
|
|
|
|
})
|
|
|
|
l.core.log.Printf("UNIX listener started on %s", listener.Addr())
|
|
|
|
go func() {
|
|
|
|
defer phony.Block(l, func() {
|
|
|
|
delete(l._listeners, entry)
|
|
|
|
})
|
|
|
|
for {
|
|
|
|
conn, err := listener.Accept()
|
|
|
|
if err != nil {
|
|
|
|
cancel()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
info := linkInfoFor("unix", "", url.String())
|
2022-11-12 11:30:03 +00:00
|
|
|
if err = l.handler(nil, url.String(), info, conn, linkOptionsForListener(url), true); err != nil {
|
2022-09-17 19:07:00 +00:00
|
|
|
l.core.log.Errorln("Failed to create inbound link:", err)
|
|
|
|
}
|
|
|
|
}
|
2022-09-24 16:05:44 +00:00
|
|
|
_ = listener.Close()
|
2022-09-17 19:07:00 +00:00
|
|
|
close(entry.closed)
|
|
|
|
l.core.log.Printf("UNIX listener stopped on %s", listener.Addr())
|
|
|
|
}()
|
|
|
|
return entry, nil
|
|
|
|
}
|
|
|
|
|
2022-11-12 11:30:03 +00:00
|
|
|
func (l *linkUNIX) handler(dial *linkDial, name string, info linkInfo, conn net.Conn, options linkOptions, incoming bool) error {
|
2022-09-17 19:07:00 +00:00
|
|
|
return l.links.create(
|
|
|
|
conn, // connection
|
2022-11-12 11:30:03 +00:00
|
|
|
dial, // connection URL
|
2022-09-17 19:07:00 +00:00
|
|
|
name, // connection name
|
|
|
|
info, // connection info
|
|
|
|
incoming, // not incoming
|
|
|
|
false, // not forced
|
|
|
|
options, // connection options
|
|
|
|
)
|
|
|
|
}
|