mirror of
https://codeberg.org/cunicu/cunicu.git
synced 2025-10-06 01:06:59 +08:00
84 lines
1.6 KiB
Go
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
|
|
}
|