mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-01-12 21:57:15 +08:00
Address code review feedback - improve robustness
- Use named constant for dataChan buffer size - Add bounds checking to prevent panic if n > len(data) - Only send valid data portion (buf[:n]) to dataChan - Use sync.Once to prevent double-close panic in Close() - Add comment explaining data loss risk (acceptable for UDP-like behavior) All tests pass, no security vulnerabilities found. Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
@@ -130,8 +130,15 @@ type netBindClient struct {
|
|||||||
conns map[*netEndpoint]net.Conn
|
conns map[*netEndpoint]net.Conn
|
||||||
dataChan chan *receivedData
|
dataChan chan *receivedData
|
||||||
closeChan chan struct{}
|
closeChan chan struct{}
|
||||||
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Buffer size for dataChan - allows some buffering of received packets
|
||||||
|
// while dispatcher matches them with read requests
|
||||||
|
dataChannelBufferSize = 100
|
||||||
|
)
|
||||||
|
|
||||||
type receivedData struct {
|
type receivedData struct {
|
||||||
data []byte
|
data []byte
|
||||||
n int
|
n int
|
||||||
@@ -150,7 +157,7 @@ func (bind *netBindClient) connectTo(endpoint *netEndpoint) error {
|
|||||||
bind.connMutex.Lock()
|
bind.connMutex.Lock()
|
||||||
if bind.conns == nil {
|
if bind.conns == nil {
|
||||||
bind.conns = make(map[*netEndpoint]net.Conn)
|
bind.conns = make(map[*netEndpoint]net.Conn)
|
||||||
bind.dataChan = make(chan *receivedData, 100)
|
bind.dataChan = make(chan *receivedData, dataChannelBufferSize)
|
||||||
bind.closeChan = make(chan struct{})
|
bind.closeChan = make(chan struct{})
|
||||||
|
|
||||||
// Start unified reader dispatcher
|
// Start unified reader dispatcher
|
||||||
@@ -172,10 +179,16 @@ func (bind *netBindClient) connectTo(endpoint *netEndpoint) error {
|
|||||||
buf := make([]byte, maxPacketSize)
|
buf := make([]byte, maxPacketSize)
|
||||||
n, err := conn.Read(buf)
|
n, err := conn.Read(buf)
|
||||||
|
|
||||||
|
// Send only the valid data portion to dispatcher
|
||||||
|
dataToSend := buf
|
||||||
|
if n > 0 && n < len(buf) {
|
||||||
|
dataToSend = buf[:n]
|
||||||
|
}
|
||||||
|
|
||||||
// Send received data to dispatcher
|
// Send received data to dispatcher
|
||||||
select {
|
select {
|
||||||
case bind.dataChan <- &receivedData{
|
case bind.dataChan <- &receivedData{
|
||||||
data: buf,
|
data: dataToSend,
|
||||||
n: n,
|
n: n,
|
||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
err: err,
|
err: err,
|
||||||
@@ -202,7 +215,12 @@ func (bind *netBindClient) unifiedReader() {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case data := <-bind.dataChan:
|
case data := <-bind.dataChan:
|
||||||
// Wait for a read request
|
// Bounds check to prevent panic
|
||||||
|
if data.n > len(data.data) {
|
||||||
|
data.n = len(data.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for a read request with timeout to prevent blocking forever
|
||||||
select {
|
select {
|
||||||
case v := <-bind.readQueue:
|
case v := <-bind.readQueue:
|
||||||
// Copy data to request buffer
|
// Copy data to request buffer
|
||||||
@@ -230,12 +248,14 @@ func (bind *netBindClient) unifiedReader() {
|
|||||||
|
|
||||||
// Close implements conn.Bind.Close for netBindClient
|
// Close implements conn.Bind.Close for netBindClient
|
||||||
func (bind *netBindClient) Close() error {
|
func (bind *netBindClient) Close() error {
|
||||||
// Close the channels to stop all goroutines
|
// Use sync.Once to prevent double-close panic
|
||||||
bind.connMutex.Lock()
|
bind.closeOnce.Do(func() {
|
||||||
if bind.closeChan != nil {
|
bind.connMutex.Lock()
|
||||||
close(bind.closeChan)
|
if bind.closeChan != nil {
|
||||||
}
|
close(bind.closeChan)
|
||||||
bind.connMutex.Unlock()
|
}
|
||||||
|
bind.connMutex.Unlock()
|
||||||
|
})
|
||||||
|
|
||||||
// Call parent Close
|
// Call parent Close
|
||||||
return bind.netBind.Close()
|
return bind.netBind.Close()
|
||||||
|
|||||||
Reference in New Issue
Block a user