safing-portmaster/spn/sluice/request.go

78 lines
1.7 KiB
Go

package sluice
import (
"errors"
"fmt"
"net"
"time"
"github.com/safing/portmaster/service/network"
"github.com/safing/portmaster/service/network/packet"
)
const (
defaultSluiceTTL = 30 * time.Second
)
var (
// ErrUnsupported is returned when a protocol is not supported.
ErrUnsupported = errors.New("unsupported protocol")
// ErrSluiceOffline is returned when the sluice for a network is offline.
ErrSluiceOffline = errors.New("is offline")
)
// Request holds request data for a sluice entry.
type Request struct {
ConnInfo *network.Connection
CallbackFn RequestCallbackFunc
Expires time.Time
}
// RequestCallbackFunc is called for taking a over handling connection that arrived at the sluice.
type RequestCallbackFunc func(connInfo *network.Connection, conn net.Conn)
// AwaitRequest pre-registers a connection at the sluice for initializing it when it arrives.
func AwaitRequest(connInfo *network.Connection, callbackFn RequestCallbackFunc) error {
network := getNetworkFromConnInfo(connInfo)
if network == "" {
return ErrUnsupported
}
sluice, ok := getSluice(network)
if !ok {
return fmt.Errorf("sluice for network %s %w", network, ErrSluiceOffline)
}
return sluice.AwaitRequest(&Request{
ConnInfo: connInfo,
CallbackFn: callbackFn,
Expires: time.Now().Add(defaultSluiceTTL),
})
}
func getNetworkFromConnInfo(connInfo *network.Connection) string {
var network string
// protocol
switch connInfo.IPProtocol { //nolint:exhaustive // Looking for specific values.
case packet.TCP:
network = "tcp"
case packet.UDP:
network = "udp"
default:
return ""
}
// IP version
switch connInfo.IPVersion {
case packet.IPv4:
network += "4"
case packet.IPv6:
network += "6"
default:
return ""
}
return network
}