diff --git a/client/proxy/udp.go b/client/proxy/udp.go index d01d2c8e..e387da9c 100644 --- a/client/proxy/udp.go +++ b/client/proxy/udp.go @@ -108,8 +108,10 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) { pxy.mu.Lock() pxy.workConn = workConn - pxy.readCh = make(chan *msg.UDPPacket, 1024) - pxy.sendCh = make(chan msg.Message, 1024) + readCh := make(chan *msg.UDPPacket, 1024) + sendCh := make(chan msg.Message, 1024) + pxy.readCh = readCh + pxy.sendCh = sendCh pxy.closed = false pxy.mu.Unlock() @@ -160,10 +162,10 @@ func (pxy *UDPProxy) InWorkConn(conn net.Conn, _ *msg.StartWorkConn) { } } - go workConnSenderFn(payloadRW, pxy.sendCh) - go workConnReaderFn(payloadRW, pxy.readCh) - go heartbeatFn(pxy.sendCh) + go workConnSenderFn(payloadRW, sendCh) + go workConnReaderFn(payloadRW, readCh) + go heartbeatFn(sendCh) // Call Forwarder with proxy protocol version (empty string means no proxy protocol) - udp.Forwarder(pxy.localAddr, pxy.readCh, pxy.sendCh, int(pxy.clientCfg.UDPPacketSize), pxy.cfg.Transport.ProxyProtocolVersion) + udp.Forwarder(pxy.localAddr, readCh, sendCh, int(pxy.clientCfg.UDPPacketSize), pxy.cfg.Transport.ProxyProtocolVersion) } diff --git a/client/proxy/udp_test.go b/client/proxy/udp_test.go new file mode 100644 index 00000000..13995172 --- /dev/null +++ b/client/proxy/udp_test.go @@ -0,0 +1,63 @@ +// Copyright 2026 The frp Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !frps + +package proxy + +import ( + "context" + "net" + "sync" + "testing" + + "github.com/stretchr/testify/require" + + v1 "github.com/fatedier/frp/pkg/config/v1" + "github.com/fatedier/frp/pkg/msg" + "github.com/fatedier/frp/pkg/util/xlog" +) + +func TestUDPProxyInWorkConnGenerationChannels(t *testing.T) { + cfg := &v1.UDPProxyConfig{ProxyBaseConfig: v1.ProxyBaseConfig{ + Name: "udp", Type: "udp", + ProxyBackend: v1.ProxyBackend{LocalIP: "127.0.0.1", LocalPort: 9}, + }} + pxy := NewUDPProxy(&BaseProxy{ + baseCfg: &cfg.ProxyBaseConfig, clientCfg: &v1.ClientCommonConfig{UDPPacketSize: 1500}, + xl: xlog.New(), ctx: context.Background(), + }, cfg).(*UDPProxy) + require.NoError(t, pxy.Run()) + defer pxy.Close() + + conn1, peer1 := net.Pipe() + defer conn1.Close() + defer peer1.Close() + conn2, peer2 := net.Pipe() + defer conn2.Close() + defer peer2.Close() + + start := make(chan struct{}) + var wg sync.WaitGroup + wg.Add(2) + inWorkConn := func(conn net.Conn) { + defer wg.Done() + <-start + pxy.InWorkConn(conn, &msg.StartWorkConn{}) + } + go inWorkConn(conn1) + go inWorkConn(conn2) + close(start) + wg.Wait() +}