daemon: use per-interface features

Signed-off-by: Steffen Vogel <post@steffenvogel.de>
This commit is contained in:
Steffen Vogel
2022-09-30 08:32:26 +02:00
parent 70e437d9a6
commit 92a7ad2f7f
99 changed files with 3510 additions and 2599 deletions

View File

@@ -0,0 +1,83 @@
package proxy
import (
"errors"
"fmt"
"io"
"net"
"github.com/pion/ice/v2"
"go.uber.org/zap"
"github.com/stv0g/cunicu/pkg/wg"
protoepdisc "github.com/stv0g/cunicu/pkg/proto/feature/epdisc"
)
type UserBindProxy struct {
bind *wg.UserBind
endpoint *wg.UserEndpoint
conn *ice.Conn
logger *zap.Logger
}
func NewUserBindProxy(bind *wg.UserBind) (*UserBindProxy, error) {
return &UserBindProxy{
bind: bind,
logger: zap.L().Named("proxy").With(zap.String("type", "user-bind")),
}, nil
}
func (p *UserBindProxy) Close() error {
return nil
}
func (p *UserBindProxy) UpdateCandidatePair(cp *ice.CandidatePair, conn *ice.Conn) (*net.UDPAddr, error) {
var err error
p.logger.Debug("Forwarding via in-process bind")
ep := &net.UDPAddr{
IP: net.ParseIP(cp.Remote.Address()),
Port: cp.Remote.Port(),
}
p.endpoint, err = p.bind.UpdateEndpoint(ep, conn)
if err != nil {
return nil, fmt.Errorf("failed to update endpoint: %w", err)
}
if conn != p.conn {
go p.read(conn)
}
return ep, nil
}
func (p *UserBindProxy) read(conn *ice.Conn) {
p.conn = conn
for {
buf := make([]byte, maxSegmentSize)
n, err := p.conn.Read(buf)
if err != nil {
if errors.Is(err, ice.ErrClosed) || errors.Is(err, io.EOF) {
return
}
p.logger.Error("Failed to read from ICE connection", zap.Error(err))
continue
}
if err := p.bind.OnData(buf[:n], p.endpoint); err != nil {
p.logger.Error("Failed to pass data to bind", zap.Error(err))
}
}
}
func (p *UserBindProxy) Type() protoepdisc.ProxyType {
return protoepdisc.ProxyType_USER_BIND
}