mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
修订文档,代码
This commit is contained in:
@@ -169,6 +169,10 @@ CRUMFURS 信道与普通UDP信道一样,要传 udp长度头。
|
||||
|
||||
此时从socks5读出的每一个udp链接,视其raddr而定,如果raddr是没遇到过的地址,则我们会新建立一个新信道
|
||||
|
||||
### 代码参考
|
||||
|
||||
阅读 prox/vless/udpConn.go 以及 netLayer/relay_udp.go 的 RelayUDP_separate 函数
|
||||
|
||||
## 连接池
|
||||
|
||||
我们可以通过使用新协议命令来做到 非mux的 连接池技术,可以在每个vless 头部添加 “是否关闭连接”的信息
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
// implements NetDeadliner. Must call InitEasyDeadline before use.
|
||||
// Can be embed to a struct to make it have SetWriteDeadline, SetReadDeadline and SetDeadline method.
|
||||
// And MUST use select and ReadTimeoutChan or WriteTimeoutChan when reading or writing.
|
||||
//
|
||||
// see IOWrapper for reference.
|
||||
type EasyDeadline struct {
|
||||
readDeadline PipeDeadline
|
||||
writeDeadline PipeDeadline
|
||||
|
||||
@@ -189,6 +189,8 @@ func relayUDP_rc_toLC(rc, lc MsgConn, downloadByteCount *uint64, mutex *sync.RWM
|
||||
// 不过分离信道只能用于代理,不能用于 direct, 因为direct为了实现fullcone, 对所有rc连接都用的同一个udp端口。
|
||||
// 阻塞. 返回从 rc 下载的总字节数. 拷贝完成后自动关闭双端连接.
|
||||
func RelayUDP_separate(rc, lc MsgConn, firstAddr *Addr, downloadByteCount, uploadByteCount *uint64, dialfunc func(raddr Addr) MsgConn) uint64 {
|
||||
//一般而言,lc为 socks5 的MsgConn,rc 为 vless v1 客户端的 MsgConn
|
||||
|
||||
var lc_mutex sync.RWMutex
|
||||
|
||||
var mainhash HashableAddr
|
||||
@@ -239,7 +241,6 @@ func RelayUDP_separate(rc, lc MsgConn, firstAddr *Addr, downloadByteCount, uploa
|
||||
go func() {
|
||||
_, rcwrong := relayUDP_rc_toLC(rc, lc, downloadByteCount, &lc_mutex)
|
||||
//rc到lc转发结束,一定也是因为读取/写入失败, 如果是rc的错误, 则我们要删掉rc, 释放资源
|
||||
//一般而言,lc为 socks5 的MsgConn,rc 为 vless v1 的 MsgConn
|
||||
|
||||
if rcwrong {
|
||||
lc_mutex.Lock()
|
||||
@@ -297,65 +298,65 @@ func RelayUDP_separate(rc, lc MsgConn, firstAddr *Addr, downloadByteCount, uploa
|
||||
return count2
|
||||
}
|
||||
|
||||
/*
|
||||
relay udp 有两种针对不同通道的技术
|
||||
// /*
|
||||
// relay udp 有两种针对不同通道的技术
|
||||
|
||||
一种是针对单来源通道的技术,通常是udp in tcp的情况,此时,我们用MsgConn + RelayUDP 方法很方便
|
||||
// 一种是针对单来源通道的技术,通常是udp in tcp的情况,此时,我们用MsgConn + RelayUDP 方法很方便
|
||||
|
||||
另一种是直接读udp的技术,目前我们用很多代码来适配它,也能包装MsgConn里,但是非常不美观,繁琐。
|
||||
因为udp是多来源的,我们为了确定单一来源,就要全局读,然后定义一个map, 为每一个来源的地址存储一个MsgConn
|
||||
// 另一种是直接读udp的技术,目前我们用很多代码来适配它,也能包装MsgConn里,但是非常不美观,繁琐。
|
||||
// 因为udp是多来源的,我们为了确定单一来源,就要全局读,然后定义一个map, 为每一个来源的地址存储一个MsgConn
|
||||
|
||||
我们重新定义一个MsgProducer 和 MsgConsumer,就方便很多. 这是针对多来源的转发。
|
||||
// 我们重新定义一个MsgProducer 和 MsgConsumer,就方便很多. 这是针对多来源的转发。
|
||||
|
||||
如此,一个 UDPConn就相当于一个 MsgProducer, 它的to 可以由 tproxy 或者 msg内部的数据提取出来
|
||||
// 如此,一个 UDPConn就相当于一个 MsgProducer, 它的to 可以由 tproxy 或者 msg内部的数据提取出来
|
||||
|
||||
不过,这种抽象一样需要map进行记忆,才能区分不同来源的from。针对不同的from,要使用以前对它发信号所使用的端口。
|
||||
// 不过,这种抽象一样需要map进行记忆,才能区分不同来源的from。针对不同的from,要使用以前对它发信号所使用的端口。
|
||||
|
||||
所以两种技术可能是等价的。
|
||||
*/
|
||||
func RelayMsg(rc, lc MsgHub, downloadByteCount, uploadByteCount *uint64) uint64 {
|
||||
go CopyMsgFromP2C(lc, rc, uploadByteCount)
|
||||
// 所以两种技术可能是等价的。
|
||||
// */
|
||||
// func RelayMsg(rc, lc MsgHub, downloadByteCount, uploadByteCount *uint64) uint64 {
|
||||
// go CopyMsgFromP2C(lc, rc, uploadByteCount)
|
||||
|
||||
var dbc uint64
|
||||
CopyMsgFromP2C(rc, lc, &dbc)
|
||||
// var dbc uint64
|
||||
// CopyMsgFromP2C(rc, lc, &dbc)
|
||||
|
||||
if downloadByteCount != nil {
|
||||
atomic.AddUint64(downloadByteCount, dbc)
|
||||
}
|
||||
return dbc
|
||||
// if downloadByteCount != nil {
|
||||
// atomic.AddUint64(downloadByteCount, dbc)
|
||||
// }
|
||||
// return dbc
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
func CopyMsgFromP2C(p MsgProducer, c MsgConsumer, countPtr *uint64) {
|
||||
var bc uint64
|
||||
// func CopyMsgFromP2C(p MsgProducer, c MsgConsumer, countPtr *uint64) {
|
||||
// var bc uint64
|
||||
|
||||
for {
|
||||
msg, from, to, err := p.ProduceMsg()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
err = c.ConsumeMsg(msg, from, to)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
bc += uint64(len(msg))
|
||||
}
|
||||
// for {
|
||||
// msg, from, to, err := p.ProduceMsg()
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
// err = c.ConsumeMsg(msg, from, to)
|
||||
// if err != nil {
|
||||
// break
|
||||
// }
|
||||
// bc += uint64(len(msg))
|
||||
// }
|
||||
|
||||
if countPtr != nil {
|
||||
atomic.AddUint64(countPtr, bc)
|
||||
}
|
||||
// if countPtr != nil {
|
||||
// atomic.AddUint64(countPtr, bc)
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
type MsgHub interface {
|
||||
MsgProducer
|
||||
MsgConsumer
|
||||
}
|
||||
// type MsgHub interface {
|
||||
// MsgProducer
|
||||
// MsgConsumer
|
||||
// }
|
||||
|
||||
type MsgProducer interface {
|
||||
ProduceMsg() (msg []byte, from, to Addr, err error)
|
||||
}
|
||||
// type MsgProducer interface {
|
||||
// ProduceMsg() (msg []byte, from, to Addr, err error)
|
||||
// }
|
||||
|
||||
type MsgConsumer interface {
|
||||
ConsumeMsg(msg []byte, from, to Addr) (err error)
|
||||
}
|
||||
// type MsgConsumer interface {
|
||||
// ConsumeMsg(msg []byte, from, to Addr) (err error)
|
||||
// }
|
||||
|
||||
@@ -10,6 +10,11 @@ import (
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
flag_orig = 0
|
||||
flag_new_source = 1
|
||||
)
|
||||
|
||||
type UDPConn struct {
|
||||
net.Conn
|
||||
|
||||
@@ -56,7 +61,7 @@ func (u *UDPConn) WriteMsgTo(p []byte, raddr netLayer.Addr) error {
|
||||
}
|
||||
defer utils.PutBuf(writeBuf)
|
||||
|
||||
//v0很垃圾,不支持fullcone,而是无视raddr,始终向最开始的raddr发送。
|
||||
//v0设计有问题,不支持fullcone,无视raddr,始终向最开始的raddr发送。
|
||||
if u.version == 0 {
|
||||
|
||||
if !u.isClientEnd && !u.notFirst {
|
||||
@@ -84,11 +89,11 @@ func (u *UDPConn) WriteMsgTo(p []byte, raddr netLayer.Addr) error {
|
||||
// umfurs信息将会提示客户端 下一次发送到此地址时,拨号一个新的 udp信道.
|
||||
|
||||
if u.raddr.GetHashable() == raddr.GetHashable() {
|
||||
writeBuf.WriteByte(0)
|
||||
writeBuf.WriteByte(flag_orig)
|
||||
return u.writeDataTo(writeBuf, p)
|
||||
|
||||
} else {
|
||||
writeBuf.WriteByte(1)
|
||||
writeBuf.WriteByte(flag_new_source)
|
||||
WriteAddrTo(writeBuf, raddr)
|
||||
return u.writeDataTo(writeBuf, p)
|
||||
|
||||
@@ -192,10 +197,10 @@ func (u *UDPConn) ReadMsgFrom() ([]byte, netLayer.Addr, error) {
|
||||
switch b1 {
|
||||
default:
|
||||
return nil, netLayer.Addr{}, utils.ErrInErr{ErrDesc: "Vless udp_multi client read first byte unexpected", ErrDetail: utils.ErrInvalidData, Data: b1}
|
||||
case 0:
|
||||
case flag_orig:
|
||||
bs, err := u.readData_with_len()
|
||||
return bs, u.raddr, err
|
||||
case 1:
|
||||
case flag_new_source:
|
||||
raddr, err := netLayer.V2rayGetAddrFrom(u.bufr)
|
||||
if err != nil {
|
||||
return nil, raddr, err
|
||||
|
||||
Reference in New Issue
Block a user