Files
cunicu/pkg/daemon/feature/epdisc/proxy/proxy_user.go
Steffen Vogel 92a7ad2f7f daemon: use per-interface features
Signed-off-by: Steffen Vogel <post@steffenvogel.de>
2022-10-07 18:30:50 +02:00

84 lines
1.6 KiB
Go

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
}