mirror of
https://github.com/caddyserver/caddy.git
synced 2025-10-19 07:43:17 +00:00
core: Implement socket activation listeners (#6573)
* caddy adapt for listen_protocols * adapt listen_socket * allow multiple listen sockets for port ranges and readd socket fd listen logic * readd logic to start servers according to listener protocols * gofmt * adapt caddytest * gosec * fmt and rename listen to listenWithSocket * fmt and rename listen to listenWithSocket * more consistent error msg * non unix listenReusableWithSocketFile * remove unused func * doc comment typo * nonosec * commit * doc comments * more doc comments * comment was misleading, cardinality did not change * addressesWithProtocols * update test * fd/ and fdgram/ * rm addr * actually write... * i guess we doin' "skip": now * wrong var in placeholder * wrong var in placeholder II * update param name in comment * dont save nil file pointers * windows * key -> parsedKey * osx * multiple default_bind with protocols * check for h1 and h2 listener netw
This commit is contained in:
parent
1a345b4fa6
commit
4b1a9b6cc1
21 changed files with 946 additions and 364 deletions
80
listen.go
80
listen.go
|
@ -18,7 +18,11 @@ package caddy
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -31,10 +35,49 @@ func reuseUnixSocket(network, addr string) (any, error) {
|
|||
}
|
||||
|
||||
func listenReusable(ctx context.Context, lnKey string, network, address string, config net.ListenConfig) (any, error) {
|
||||
switch network {
|
||||
case "udp", "udp4", "udp6", "unixgram":
|
||||
var socketFile *os.File
|
||||
|
||||
fd := slices.Contains([]string{"fd", "fdgram"}, network)
|
||||
if fd {
|
||||
socketFd, err := strconv.ParseUint(address, 0, strconv.IntSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid file descriptor: %v", err)
|
||||
}
|
||||
|
||||
func() {
|
||||
socketFilesMu.Lock()
|
||||
defer socketFilesMu.Unlock()
|
||||
|
||||
socketFdWide := uintptr(socketFd)
|
||||
var ok bool
|
||||
|
||||
socketFile, ok = socketFiles[socketFdWide]
|
||||
|
||||
if !ok {
|
||||
socketFile = os.NewFile(socketFdWide, lnKey)
|
||||
if socketFile != nil {
|
||||
socketFiles[socketFdWide] = socketFile
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if socketFile == nil {
|
||||
return nil, fmt.Errorf("invalid socket file descriptor: %d", socketFd)
|
||||
}
|
||||
}
|
||||
|
||||
datagram := slices.Contains([]string{"udp", "udp4", "udp6", "unixgram", "fdgram"}, network)
|
||||
if datagram {
|
||||
sharedPc, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
|
||||
pc, err := config.ListenPacket(ctx, network, address)
|
||||
var (
|
||||
pc net.PacketConn
|
||||
err error
|
||||
)
|
||||
if fd {
|
||||
pc, err = net.FilePacketConn(socketFile)
|
||||
} else {
|
||||
pc, err = config.ListenPacket(ctx, network, address)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -44,20 +87,27 @@ func listenReusable(ctx context.Context, lnKey string, network, address string,
|
|||
return nil, err
|
||||
}
|
||||
return &fakeClosePacketConn{sharedPacketConn: sharedPc.(*sharedPacketConn)}, nil
|
||||
}
|
||||
|
||||
default:
|
||||
sharedLn, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
|
||||
ln, err := config.Listen(ctx, network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sharedListener{Listener: ln, key: lnKey}, nil
|
||||
})
|
||||
sharedLn, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
|
||||
var (
|
||||
ln net.Listener
|
||||
err error
|
||||
)
|
||||
if fd {
|
||||
ln, err = net.FileListener(socketFile)
|
||||
} else {
|
||||
ln, err = config.Listen(ctx, network, address)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fakeCloseListener{sharedListener: sharedLn.(*sharedListener), keepAlivePeriod: config.KeepAlive}, nil
|
||||
return &sharedListener{Listener: ln, key: lnKey}, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fakeCloseListener{sharedListener: sharedLn.(*sharedListener), keepAlivePeriod: config.KeepAlive}, nil
|
||||
}
|
||||
|
||||
// fakeCloseListener is a private wrapper over a listener that
|
||||
|
@ -260,3 +310,9 @@ var (
|
|||
Unwrap() net.PacketConn
|
||||
}) = (*fakeClosePacketConn)(nil)
|
||||
)
|
||||
|
||||
// socketFiles is a fd -> *os.File map used to make a FileListener/FilePacketConn from a socket file descriptor.
|
||||
var socketFiles = map[uintptr]*os.File{}
|
||||
|
||||
// socketFilesMu synchronizes socketFiles insertions
|
||||
var socketFilesMu sync.Mutex
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue