mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 15:26:40 +00:00
126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package bind
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/netip"
|
|
"sync"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"golang.zx2c4.com/wireguard/conn"
|
|
|
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
|
)
|
|
|
|
// RelayBindJS is a conn.Bind implementation for WebAssembly environments.
|
|
// Do not limit to build only js, because we want to be able to run tests
|
|
type RelayBindJS struct {
|
|
*conn.StdNetBind
|
|
|
|
recvChan chan recvMessage
|
|
endpoints map[netip.Addr]net.Conn
|
|
endpointsMu sync.Mutex
|
|
activityRecorder *ActivityRecorder
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
}
|
|
|
|
func NewRelayBindJS() *RelayBindJS {
|
|
return &RelayBindJS{
|
|
recvChan: make(chan recvMessage, 100),
|
|
endpoints: make(map[netip.Addr]net.Conn),
|
|
activityRecorder: NewActivityRecorder(),
|
|
}
|
|
}
|
|
|
|
// Open creates a receive function for handling relay packets in WASM.
|
|
func (s *RelayBindJS) Open(uport uint16) ([]conn.ReceiveFunc, uint16, error) {
|
|
log.Debugf("Open: creating receive function for port %d", uport)
|
|
|
|
s.ctx, s.cancel = context.WithCancel(context.Background())
|
|
|
|
receiveFn := func(bufs [][]byte, sizes []int, eps []conn.Endpoint) (int, error) {
|
|
select {
|
|
case <-s.ctx.Done():
|
|
return 0, net.ErrClosed
|
|
case msg, ok := <-s.recvChan:
|
|
if !ok {
|
|
return 0, net.ErrClosed
|
|
}
|
|
copy(bufs[0], msg.Buffer)
|
|
sizes[0] = len(msg.Buffer)
|
|
eps[0] = conn.Endpoint(msg.Endpoint)
|
|
return 1, nil
|
|
}
|
|
}
|
|
|
|
log.Debugf("Open: receive function created, returning port %d", uport)
|
|
return []conn.ReceiveFunc{receiveFn}, uport, nil
|
|
}
|
|
|
|
func (s *RelayBindJS) Close() error {
|
|
if s.cancel == nil {
|
|
return nil
|
|
}
|
|
log.Debugf("close RelayBindJS")
|
|
s.cancel()
|
|
return nil
|
|
}
|
|
|
|
func (s *RelayBindJS) ReceiveFromEndpoint(ctx context.Context, ep *Endpoint, buf []byte) {
|
|
select {
|
|
case <-s.ctx.Done():
|
|
return
|
|
case <-ctx.Done():
|
|
return
|
|
case s.recvChan <- recvMessage{ep, buf}:
|
|
}
|
|
}
|
|
|
|
// Send forwards packets through the relay connection for WASM.
|
|
func (s *RelayBindJS) Send(bufs [][]byte, ep conn.Endpoint) error {
|
|
if ep == nil {
|
|
return nil
|
|
}
|
|
|
|
fakeIP := ep.DstIP()
|
|
|
|
s.endpointsMu.Lock()
|
|
relayConn, ok := s.endpoints[fakeIP]
|
|
s.endpointsMu.Unlock()
|
|
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
for _, buf := range bufs {
|
|
if _, err := relayConn.Write(buf); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (b *RelayBindJS) SetEndpoint(fakeIP netip.Addr, conn net.Conn) {
|
|
b.endpointsMu.Lock()
|
|
b.endpoints[fakeIP] = conn
|
|
b.endpointsMu.Unlock()
|
|
}
|
|
|
|
func (s *RelayBindJS) RemoveEndpoint(fakeIP netip.Addr) {
|
|
s.endpointsMu.Lock()
|
|
defer s.endpointsMu.Unlock()
|
|
|
|
delete(s.endpoints, fakeIP)
|
|
}
|
|
|
|
// GetICEMux returns the ICE UDPMux that was created and used by ICEBind
|
|
func (s *RelayBindJS) GetICEMux() (*udpmux.UniversalUDPMuxDefault, error) {
|
|
return nil, ErrUDPMUXNotSupported
|
|
}
|
|
|
|
func (s *RelayBindJS) ActivityRecorder() *ActivityRecorder {
|
|
return s.activityRecorder
|
|
}
|