-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core.DialUDP: how to close Read the udp.dispatcherConn #1611
Comments
所以为什么需要提前返回呢?Read 阻塞是正常行为 |
though c.Close() closes the Read, i won't know the time when i should to close this conn.
|
as this blocks always except i call remoteConn.Close(), but where is the time point? var localConn net.Conn
var remoteConn, err := core.DialUDP(ctx, dest)
io.Copy(localConn, remoteConn) |
在 Xray 实现的代理协议中,超时不活跃的会被自动 Close(取决于你设置的 policy),这是在外部控制的 |
that's why there is a issue. either v2ray or xray do not call c.Close(), as core.Dial and core.DialUDP is for external api. but those won't provide any io.EOF mechanism to close its Read method. |
... |
though a timeout is not reliable enough i thought. |
to call handleInput() directly, rather than using c.cache channel to receive the packet is more immidiate and could give me a error, maybe? tested ok in my situation. func (c *dispatchConn) Read(p []byte) (int, error) {
mb, err := c.link.Reader.ReadMultiBuffer()
if err != nil {
return 0, err
}
return mb.Copy(p), nil
} |
看起来这个 |
yes. |
type Dispatcher struct {
sync.RWMutex
conns map[net.Destination]*connEntry
dispatcher routing.Dispatcher
callback ResponseCallback
callClose ...
} 给它加一个 |
这个问题本质上是因为,在代理协议中它是被控方,不用考虑 Close 别人,但作为 API 和代理协议的桥梁,它没有传导 Close 信息 所以最合适的做法是加个回调 |
thanks for reply. that won't solve, as c.cache is channel to be received out, the packets waited in c.cache would be received out or not on the time when callClose callback is called, says there is no garantee for c.cache is read out or not even then c.callClose done. Xray-core/transport/internet/udp/dispatcher.go Lines 105 to 133 in 58b81cb
|
the key point is that we won't know the time when c.cache would be read out. |
XTLS 对这种问题的做法是 |
或者可以判断一下,chan 里还有数据的话就处理,直到没有再返回 io.EOF |
func (c *dispatcherConn) ReadFrom(p []byte) (int, net.Addr, error) {
var packet *udp.Packet
select {
case <-c.done.Wait():
if len(c.cache) != 0 {
packet = <-c.cache
break
}
return 0, nil, io.EOF
case packet = <-c.cache:
}
return copy(p, packet.Payload.Bytes()), &net.UDPAddr{
IP: packet.Source.Address.IP(),
Port: int(packet.Source.Port),
}, nil
} 比如这样,我这边全改好了,你看没问题的话我就 commit 了 |
This comment was marked as resolved.
This comment was marked as resolved.
BTW is there any disadvantage of len(c.cache)? |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
sorry and that's ok. |
OK
Golang 对 channel 的内置方法,应该是并发安全的, |
写法改成了再 select 一次,我觉得这样更好, 麻烦你本地测一下 e0b0201 |
thanks for reply, tested ok. aware whether it's ok to add callClose() for all udp with NewDispatcher. (to change the ResponseCallbackFunc is not recommanded i thought). |
对,目前如果主动 Close 了 #1542 这个有点相似 |
as per: v2fly/v2ray-core#2258
a udp.dispatcherConn returned by core.DialUDP won't close it's c.Read(), blocks after the c.cache be received out.
Xray-core/transport/internet/udp/dispatcher.go
Lines 152 to 175 in 58b81cb
possible fix: call handleInput() directly like this
or a unreliable timeout simply:
The text was updated successfully, but these errors were encountered: