mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-08 02:00:33 +08:00
修订代码,注释,示例
This commit is contained in:
@@ -25,10 +25,10 @@ host = "127.0.0.1" # 必填, 可填ip或域名;如果 network是unix的话,
|
||||
port = 10800 # 必填
|
||||
|
||||
[[dial]]
|
||||
tag = "my_vlesss1" # 可选, 但不可与其他tag重复
|
||||
tag = "my_vlesss1" # 同listen对应配置, 可选, 但不可与其他tag重复
|
||||
protocol = "vlesss" # vless 的 尾缀s 表示 使用tls
|
||||
uuid = "a684455c-b14f-11ea-bf0d-42010aaa0003" # 这个只是一个示例uuid,请自己生成一个新的.
|
||||
host = "127.0.0.1"
|
||||
host = "127.0.0.1" # 同listen对应配置, 可填ip或域名;如果 network是unix的话,要填一个文件名(不需要已存在,可以是完整路径).
|
||||
#network = "udp"
|
||||
|
||||
# network 目前支持 tcp,udp 和unix;如果不给出则默认为 tcp; dial和listen都可配置此项
|
||||
@@ -47,7 +47,7 @@ host = "127.0.0.1"
|
||||
# 除了在 protocol 字段使用 s尾缀 之外,还可以明示使用tls.
|
||||
# 这两种方法不可重复使用.我们首选前者, 更简约, 当然如果你使用时,需要频繁开关tls,那么可以单独列出来 便于配置
|
||||
|
||||
port = 4433
|
||||
port = 4433 # 必填
|
||||
version = 0 # 协议版本, 可省略, 省略则默认为最老版本
|
||||
insecure = true # 我们示例使用自签名证书,所以要开启 insecure. 实际场合请使用真证书并关闭 insecure
|
||||
utls = true #是否使用 utls 来应用 chrome指纹进行伪装
|
||||
|
@@ -3,7 +3,7 @@ package grpc
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
sync "sync"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/netLayer"
|
||||
@@ -21,11 +21,11 @@ var (
|
||||
type ClientConn *grpc.ClientConn
|
||||
|
||||
/*
|
||||
调用过程
|
||||
建立新客户端连接的调用过程:
|
||||
|
||||
先用 GetEstablishedConnFor 看看有没有已存在的 clientConn
|
||||
|
||||
没有已存在的话,自己先拨号tcp,然后拨号tls,然后把tls连接 传递给 ClientHandshake, 生成一个 clientConn
|
||||
没有 已存在的 时,自己先拨号tcp,然后拨号tls,然后把tls连接 传递给 ClientHandshake, 生成一个 clientConn
|
||||
|
||||
然后把获取到的 clientConn传递给 DialNewSubConn, 获取可用的一条 grpc 连接
|
||||
|
||||
@@ -34,16 +34,18 @@ type ClientConn *grpc.ClientConn
|
||||
//获取与 某grpc服务器的 已存在的grpc连接
|
||||
func GetEstablishedConnFor(addr *netLayer.Addr) ClientConn {
|
||||
clientconnMutex.RLock()
|
||||
clieintconn := clientconnMap[addr.GetHashable()]
|
||||
clientconn := clientconnMap[addr.GetHashable()]
|
||||
clientconnMutex.RUnlock()
|
||||
|
||||
if clieintconn == nil {
|
||||
if clientconn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if (*grpc.ClientConn)(clieintconn).GetState() != connectivity.Shutdown {
|
||||
return clieintconn
|
||||
if (*grpc.ClientConn)(clientconn).GetState() != connectivity.Shutdown {
|
||||
return clientconn
|
||||
}
|
||||
//如果state是shutdown的话,我们也不用特地清除map,因为下一次申请就会覆盖map中的该项.
|
||||
//如果底层tcp被关闭,state就会为 Shutdown
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -51,10 +53,11 @@ func GetEstablishedConnFor(addr *netLayer.Addr) ClientConn {
|
||||
//该 underlay一般为 tls连接。 addr为实际的远程地址,我们不从 underlay里获取addr,避免转换.
|
||||
func ClientHandshake(underlay net.Conn, addr *netLayer.Addr) (ClientConn, error) {
|
||||
|
||||
//v2ray的实现中用到了一个 globalDialerMap[dest], 可以利用现有连接,
|
||||
// 用到了一个 clientconnMap , 可以利用现有连接,
|
||||
// 只有map里没有与对应目标远程地址的连接的时候才会拨号;
|
||||
// 这 应该就是一种mux的实现
|
||||
// 如果有之前播过的client的话,直接利用现有client进行 NewStream, 然后服务端的话, 实际上会获得到第二条连接;
|
||||
// 这就是一种mux的实现
|
||||
// 如果有之前拨号过的client的话,直接利用现有client进行 NewStream,
|
||||
// 然后服务端的话, 实际上会获得到同一条tcp链接上的第二条子连接;
|
||||
|
||||
//也就是说,底层连接在客户端-服务端只用了一条,但是 服务端处理时却会抽象出 多条Stream连接进行处理
|
||||
|
||||
@@ -84,7 +87,8 @@ func ClientHandshake(underlay net.Conn, addr *netLayer.Addr) (ClientConn, error)
|
||||
//在一个已存在的grpc连接中 进行新的子连接申请
|
||||
func DialNewSubConn(path string, clientconn ClientConn, addr *netLayer.Addr) (net.Conn, error) {
|
||||
|
||||
//不像服务端需要自己写一个实现StreamServer接口的结构, 我们Client端直接可以调用函数生成 StreamClient
|
||||
// 帮助理解:
|
||||
// 不像服务端需要自己写一个实现StreamServer接口的结构, 我们Client端直接可以调用函数生成 StreamClient
|
||||
// 这也是grpc的特点, 客户端只负责 “调用“ ”service“,而具体的service的实现 是在服务端.
|
||||
|
||||
streamClient := NewStreamClient((*grpc.ClientConn)(clientconn)).(StreamClient_withName)
|
||||
|
@@ -9,8 +9,8 @@ import (
|
||||
)
|
||||
|
||||
// google.golang.org/grpc.(*Server).handleRawConn
|
||||
//go:linkname HandleRawConn google.golang.org/grpc.(*Server).handleRawConn
|
||||
func HandleRawConn(c *grpc.Server, lisAddr string, rawConn net.Conn)
|
||||
//go:linkname handle_grpcRawConn google.golang.org/grpc.(*Server).handleRawConn
|
||||
func handle_grpcRawConn(c *grpc.Server, lisAddr string, rawConn net.Conn)
|
||||
|
||||
//Server实现 grpc生成的 StreamServer 接口,用于不断处理一个客户端传来的新需求
|
||||
type Server struct {
|
||||
@@ -25,15 +25,17 @@ type Server struct {
|
||||
}
|
||||
|
||||
// StartHandle方法 被用于 手动给 grpc提供新连接.
|
||||
// 在本作中 我们不使用 grpc的listen的方法。
|
||||
//非阻塞,
|
||||
// 在本作中 我们不使用 grpc的listen的方法。这样更加灵活.
|
||||
//非阻塞.
|
||||
func (s *Server) StartHandle(conn net.Conn) {
|
||||
|
||||
//非阻塞,因为 grpc.(*Server).handleRawConn 是非阻塞的,里面用了新的goroutine
|
||||
HandleRawConn(s.gs, "", conn)
|
||||
handle_grpcRawConn(s.gs, "", conn)
|
||||
}
|
||||
|
||||
// 该 Tun方法会被 grpc包调用, stream_TunServer就是获取到的新连接;
|
||||
// 实际上就是在 handle_grpcRawConn 后, 每一条客户端发来的子连接 都会调用一次 s.Tun .
|
||||
//
|
||||
// 我们把该 stream_TunServer 包装成 net.Conn 并传入 NewConnChan
|
||||
// 该方法是自动调用的, 我们不用管.
|
||||
func (s *Server) Tun(stream_TunServer Stream_TunServer) error {
|
||||
@@ -66,7 +68,7 @@ func NewServer(serviceName string) *Server {
|
||||
newConnChan := make(chan net.Conn, 10)
|
||||
|
||||
s := &Server{
|
||||
NewConnChan: newConnChan,
|
||||
NewConnChan: newConnChan, //该NewConnChan目前是永远不会被关闭的, 因为我们始终在监听新连接
|
||||
gs: gs,
|
||||
serviceName: serviceName,
|
||||
}
|
||||
|
74
main.go
74
main.go
@@ -399,9 +399,8 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy
|
||||
for {
|
||||
newGConn, ok := <-grpcs.NewConnChan
|
||||
if !ok {
|
||||
if utils.CanLogErr() {
|
||||
log.Println("upgrade grpc not ok")
|
||||
|
||||
if utils.CanLogWarn() {
|
||||
log.Println("grpc getNewSubConn not ok")
|
||||
}
|
||||
|
||||
iics.baseLocalConn.Close()
|
||||
@@ -706,35 +705,34 @@ afterLocalServerHandshake:
|
||||
// server也一样,会在特定的场合给 CRUMFURS 传值,这个机制是与main函数无关的
|
||||
|
||||
// 而且 wrappedConn 会被 inServer 保存起来,用于后面的 unknownRemoteAddrMsgWriter
|
||||
|
||||
return
|
||||
} else {
|
||||
//如果不是CRUMFURS命令,那就是普通的针对某udp地址的连接,见下文 uniExtractor 的使用
|
||||
//defer wrappedConn.Close()
|
||||
|
||||
iics.shouldCloseBaseConnAfterCopyComplete = true
|
||||
}
|
||||
|
||||
case "socks5":
|
||||
|
||||
// UDP Associate:
|
||||
//
|
||||
// 因为socks5的 UDP Associate 办法是较为特殊的,不使用现有tcp而是新建立udp,所以此时该tcp连接已经没用了
|
||||
// 另外,此时 targetAddr.IsUDP 只是用于告知此链接是udp Associate,并不包含实际地址信息
|
||||
|
||||
//但是根据socks5标准,这个tcp链接同样是 keep alive的,否则客户端就会认为服务端挂掉了.
|
||||
|
||||
default:
|
||||
//defer wrappedConn.Close()
|
||||
iics.shouldCloseBaseConnAfterCopyComplete = true
|
||||
|
||||
}
|
||||
} else {
|
||||
if !(iics.isTlsLazyServerEnd) {
|
||||
|
||||
//lazy_encrypt情况比较特殊
|
||||
// 如果不是lazy的情况的话,转发结束后,要自动关闭
|
||||
//defer wrappedConn.Close()
|
||||
iics.shouldCloseBaseConnAfterCopyComplete = true
|
||||
//lazy_encrypt情况比较特殊,基础连接何时被关闭会在tlslazy相关代码中处理。
|
||||
// 如果不是lazy的情况的话,转发结束后,要自动关闭
|
||||
if !iics.isTlsLazyServerEnd {
|
||||
|
||||
//实测 grpc.Conn 被调用了Close 也不会实际关闭连接,而是会卡住,阻塞,直到底层tcp连接被关闭后才会返回
|
||||
// 但是我们还是 直接避免这种情况
|
||||
if !inServer.IsMux() {
|
||||
iics.shouldCloseBaseConnAfterCopyComplete = true
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -742,7 +740,7 @@ afterLocalServerHandshake:
|
||||
|
||||
// 下面一段代码 单独处理 udp承载数据的特殊转发。
|
||||
//
|
||||
// 这里只处理 vless v1 的CRUMFURS 转发到direct的情况 以及 socks5 的udp associate 转发到vless v1的情况;
|
||||
// 这里只处理 vless v1 的CRUMFURS 转发到direct的情况 以及 socks5 的udp associate 转发到vless 的情况;
|
||||
// 如果条件不符合则会跳过而进入下一阶段
|
||||
if targetAddr.IsUDP() {
|
||||
|
||||
@@ -791,11 +789,11 @@ afterLocalServerHandshake:
|
||||
|
||||
// 将 outClient 视为 UDP_Putter ,就可以转发udp信息了
|
||||
|
||||
//direct 和 vless 都实现了 UDP_Putter.
|
||||
//direct 和 vless 的Client 都实现了 UDP_Putter.
|
||||
|
||||
// direct 实现了 UDP_Putter (通过 UDP_Pipe和 RelayUDP_to_Direct函数), 所以目前 socks5直接转发udp到direct 的功能 已经实现。
|
||||
// direct 通过 UDP_Pipe和 RelayUDP_to_Direct函数 实现了 UDP_Putter
|
||||
|
||||
// 我在 vless 的client 的 UserConn 中实现了 UDP_Putter, 新连接的Handshake过程会在 dialFunc 被调用 时发生
|
||||
// vless 的client 实现了 UDP_Putter, 新连接的Handshake过程会在 dialFunc 被调用 时发生
|
||||
|
||||
if putter := client.(netLayer.UDP_Putter); putter != nil {
|
||||
|
||||
@@ -818,6 +816,9 @@ afterLocalServerHandshake:
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////// 拨号阶段 /////////////////////////////////////
|
||||
|
||||
//log.Println("will dial", iics.shouldCloseBaseConnAfterCopyComplete)
|
||||
dialClient(iics, targetAddr, client, isTlsLazy_clientEnd, wlc, false)
|
||||
}
|
||||
|
||||
@@ -830,11 +831,19 @@ afterLocalServerHandshake:
|
||||
func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, client proxy.Client, isTlsLazy_clientEnd bool, wlc io.ReadWriter, noCopy bool) (io.ReadWriter, error) {
|
||||
|
||||
if iics.shouldCloseBaseConnAfterCopyComplete && !noCopy {
|
||||
|
||||
/*
|
||||
log.Println("iics.wrappedConn will close after", reflect.TypeOf(iics.wrappedConn))
|
||||
defer func() {
|
||||
log.Println("iics.wrappedConn called")
|
||||
iics.wrappedConn.Close()
|
||||
log.Println("iics.wrappedConn closed")
|
||||
}()
|
||||
*/
|
||||
defer iics.wrappedConn.Close()
|
||||
}
|
||||
|
||||
var err error
|
||||
////////////////////////////// 拨号阶段 /////////////////////////////////////
|
||||
|
||||
//先确认拨号地址
|
||||
|
||||
@@ -847,7 +856,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
||||
log.Println("request isn't the appointed domain", targetAddr, uniqueTestDomain)
|
||||
|
||||
}
|
||||
return nil, &utils.NumErr{N: 1, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 1, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
if utils.CanLogInfo() {
|
||||
@@ -890,7 +899,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
||||
log.Println("failed in dial", realTargetAddr.String(), ", Reason: ", err)
|
||||
|
||||
}
|
||||
return nil, &utils.NumErr{N: 2, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 2, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
//log.Println("dial real addr ok", realTargetAddr)
|
||||
@@ -912,7 +921,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
||||
|
||||
}
|
||||
|
||||
return nil, &utils.NumErr{N: 3, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 3, Prefix: "dialClient err, "}
|
||||
|
||||
} else {
|
||||
clientEndRemoteClientTlsRawReadRecorder = tlsLayer.NewRecorder()
|
||||
@@ -925,7 +934,7 @@ func dialClient(iics incomingInserverConnState, targetAddr *netLayer.Addr, clien
|
||||
tlsConn, err := client.GetTLS_Client().Handshake(clientConn)
|
||||
if err != nil {
|
||||
log.Println("failed in handshake outClient tls", targetAddr.String(), ", Reason: ", err)
|
||||
return nil, &utils.NumErr{N: 4, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 4, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
clientConn = tlsConn
|
||||
@@ -950,7 +959,7 @@ advLayerStep:
|
||||
iics.baseLocalConn.Close()
|
||||
|
||||
}
|
||||
return nil, &utils.NumErr{N: 5, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 5, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -960,11 +969,14 @@ advLayerStep:
|
||||
if utils.CanLogErr() {
|
||||
log.Println("grpc.DialNewSubConn failed,", err)
|
||||
|
||||
//如果底层tcp连接被关闭了的话,错误会是:
|
||||
// rpc error: code = Unavailable desc = connection error: desc = "transport: failed to write client preface: tls: use of closed connection"
|
||||
|
||||
}
|
||||
if iics.baseLocalConn != nil {
|
||||
iics.baseLocalConn.Close()
|
||||
}
|
||||
return nil, &utils.NumErr{N: 6, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 6, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
case "ws":
|
||||
@@ -981,7 +993,7 @@ advLayerStep:
|
||||
if utils.CanLogErr() {
|
||||
log.Println("err when reading ws early data", e)
|
||||
}
|
||||
return nil, &utils.NumErr{N: 7, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 7, Prefix: "dialClient err, "}
|
||||
}
|
||||
ed = edBuf[:n]
|
||||
//log.Println("will send early data", n, ed)
|
||||
@@ -1007,7 +1019,7 @@ advLayerStep:
|
||||
log.Println("failed in handshake ws to", targetAddr.String(), ", Reason: ", err)
|
||||
|
||||
}
|
||||
return nil, &utils.NumErr{N: 8, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 8, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
clientConn = wc
|
||||
@@ -1022,7 +1034,7 @@ advLayerStep:
|
||||
log.Println("failed in handshake to", targetAddr.String(), ", Reason: ", err)
|
||||
|
||||
}
|
||||
return nil, &utils.NumErr{N: 9, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 9, Prefix: "dialClient err, "}
|
||||
}
|
||||
//log.Println("all handshake finished")
|
||||
|
||||
@@ -1041,7 +1053,7 @@ advLayerStep:
|
||||
//必须是 UserClient
|
||||
if userClient := client.(proxy.UserClient); userClient != nil {
|
||||
tryTlsLazyRawCopy(false, userClient, nil, nil, wrc, wlc, iics.baseLocalConn, true, clientEndRemoteClientTlsRawReadRecorder)
|
||||
return nil, &utils.NumErr{N: 11, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 11, Prefix: "dialClient err, "}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1052,7 +1064,7 @@ advLayerStep:
|
||||
|
||||
if userServer, ok := iics.inServer.(proxy.UserServer); ok {
|
||||
tryTlsLazyRawCopy(false, nil, userServer, nil, wrc, wlc, iics.baseLocalConn, false, iics.inServerTlsRawReadRecorder)
|
||||
return nil, &utils.NumErr{N: 12, Prefix: "dialClient err, "}
|
||||
return nil, utils.NumErr{N: 12, Prefix: "dialClient err, "}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ func Client_EstablishUDPAssociate(conn net.Conn) (port int, err error) {
|
||||
return
|
||||
}
|
||||
if n != 2 || ba[0] != Version5 || ba[1] != 0 {
|
||||
return 0, &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
||||
return 0, utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
||||
}
|
||||
|
||||
//请求udp associate 阶段
|
||||
@@ -45,6 +45,8 @@ func Client_EstablishUDPAssociate(conn net.Conn) (port int, err error) {
|
||||
ba[8] = 0 //port
|
||||
ba[9] = 0 //port
|
||||
// 按理说要告诉服务端我们要用到的ip和端口,但是我们不知道,所以全填零
|
||||
// 在内网中的话,我们是可以知道的,但是因为内网很安全所以无所谓;在NAT中我们肯定是不知道的。
|
||||
// 如果是在纯外网中则是可以知道的,但是为啥非要socks5这么不安全的协议呢?所以还是不予考虑。
|
||||
|
||||
_, err = conn.Write(ba[:10])
|
||||
if err != nil {
|
||||
@@ -56,7 +58,7 @@ func Client_EstablishUDPAssociate(conn net.Conn) (port int, err error) {
|
||||
return
|
||||
}
|
||||
if n != 10 || ba[0] != Version5 || ba[1] != 0 || ba[2] != 0 || ba[3] != 1 || ba[4] != 0 || ba[5] != 0 || ba[6] != 0 || ba[7] != 0 {
|
||||
return 0, &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
||||
return 0, utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
||||
}
|
||||
|
||||
port = int(ba[8])<<8 | int(ba[9])
|
||||
@@ -126,7 +128,7 @@ func Client_ReadUDPResponse(udpConn *net.UDPConn, supposedServerAddr *net.UDPAdd
|
||||
return
|
||||
}
|
||||
if buf[0] != 0 || buf[1] != 0 || buf[2] != 0 {
|
||||
e = &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
||||
e = utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 1}
|
||||
return
|
||||
}
|
||||
atype := buf[3]
|
||||
@@ -149,7 +151,7 @@ func Client_ReadUDPResponse(udpConn *net.UDPConn, supposedServerAddr *net.UDPAdd
|
||||
target.Name = string(nameBuf)
|
||||
|
||||
default:
|
||||
e = &utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
||||
e = utils.NumErr{Prefix: "EstablishUDPAssociate,protocol err", N: 2}
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -164,7 +164,7 @@ func (s *Server) Handshake(underlay net.Conn) (io.ReadWriter, *netLayer.Addr, er
|
||||
Network: "udp",
|
||||
}
|
||||
|
||||
//这里为了解析域名, 就是用了用 netLayer.Addr 作为中介的方式
|
||||
//这里为了解析域名, 就用了 netLayer.Addr 作为中介的方式
|
||||
uc := &UDPConn{
|
||||
clientSupposedAddr: clientFutureAddr.ToUDPAddr(),
|
||||
UDPConn: udpRC,
|
||||
@@ -243,6 +243,7 @@ func (u *UDPConn) StartPushResponse(udpPutter netLayer.UDP_Putter) {
|
||||
// 监听 与客户端的udp连接 (u.UDPConn);循环查看客户端发来的请求信息;
|
||||
// 然后将该请求 用 udpPutter.WriteUDPRequest 发送给 udpPutter
|
||||
// 至于fullcone与否它是不管的。
|
||||
// 如果客户端一开始没有指明自己连接本服务端的ip和端口, 则将第一个发来的正确的socks5请求视为该客户端,并记录。
|
||||
func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(targetAddr *netLayer.Addr) (io.ReadWriter, error)) {
|
||||
|
||||
var clientSupposedAddrIsNothing bool
|
||||
@@ -269,11 +270,14 @@ func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(
|
||||
continue
|
||||
}
|
||||
|
||||
if !clientSupposedAddrIsNothing && (!addr.IP.Equal(u.clientSupposedAddr.IP) || addr.Port != u.clientSupposedAddr.Port) {
|
||||
if !clientSupposedAddrIsNothing {
|
||||
|
||||
//just random attack message.
|
||||
continue
|
||||
if !addr.IP.Equal(u.clientSupposedAddr.IP) || addr.Port != u.clientSupposedAddr.Port {
|
||||
|
||||
//just random attack message.
|
||||
continue
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
atyp := bs[3]
|
||||
@@ -322,7 +326,8 @@ func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(
|
||||
|
||||
newStart := off + l
|
||||
|
||||
thisaddr := &netLayer.Addr{
|
||||
//为了解析域名, 我们用 netLayer.Addr 作为中介.
|
||||
requestAddr := &netLayer.Addr{
|
||||
IP: theIP,
|
||||
Name: theName,
|
||||
Port: thePort,
|
||||
@@ -336,7 +341,7 @@ func (u *UDPConn) StartReadRequest(udpPutter netLayer.UDP_Putter, dialFunc func(
|
||||
|
||||
//log.Println("socks5 server,StartReadRequest, got msg", thisaddr, string(bs[newStart:n]))
|
||||
|
||||
udpPutter.WriteUDPRequest(thisaddr.ToUDPAddr(), bs[newStart:n], dialFunc)
|
||||
udpPutter.WriteUDPRequest(requestAddr.ToUDPAddr(), bs[newStart:n], dialFunc)
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ type NumErr struct {
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func (ne *NumErr) Error() string {
|
||||
func (ne NumErr) Error() string {
|
||||
|
||||
return ne.Prefix + strconv.Itoa(ne.N)
|
||||
}
|
||||
@@ -23,57 +23,51 @@ type ErrFirstBuffer struct {
|
||||
First *bytes.Buffer
|
||||
}
|
||||
|
||||
func (ef *ErrFirstBuffer) Unwarp() error {
|
||||
func (ef ErrFirstBuffer) Unwarp() error {
|
||||
|
||||
return ef.Err
|
||||
}
|
||||
|
||||
func (ef *ErrFirstBuffer) Error() string {
|
||||
func (ef ErrFirstBuffer) Error() string {
|
||||
|
||||
return ef.Err.Error()
|
||||
}
|
||||
|
||||
func NewErr(desc string, e error) *ErrInErr {
|
||||
return &ErrInErr{
|
||||
// 返回结构体,而不是指针, 这样可以避免内存逃逸到堆
|
||||
func NewErr(desc string, e error) ErrInErr {
|
||||
return ErrInErr{
|
||||
ErrDesc: desc,
|
||||
ErrDetail: e,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDataErr(desc string, e error, data interface{}) *ErrInErr {
|
||||
return &ErrInErr{
|
||||
// 返回结构体,而不是指针, 这样可以避免内存逃逸到堆
|
||||
func NewDataErr(desc string, e error, data interface{}) ErrInErr {
|
||||
return ErrInErr{
|
||||
ErrDesc: desc,
|
||||
ErrDetail: e,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrInErr 很适合一个err包含另一个err,并且提供附带数据的情况
|
||||
// ErrInErr 很适合一个err包含另一个err,并且提供附带数据的情况.
|
||||
type ErrInErr struct {
|
||||
ErrDesc string
|
||||
ErrDetail error
|
||||
Data any
|
||||
|
||||
cachedStr string
|
||||
}
|
||||
|
||||
func (e *ErrInErr) Error() string {
|
||||
func (e ErrInErr) Error() string {
|
||||
return e.String()
|
||||
}
|
||||
|
||||
func (e *ErrInErr) Unwarp() error {
|
||||
func (e ErrInErr) Unwarp() error {
|
||||
|
||||
return e.ErrDetail
|
||||
}
|
||||
|
||||
func (e *ErrInErr) String() string {
|
||||
if e.cachedStr == "" {
|
||||
e.cachedStr = e.string()
|
||||
}
|
||||
return e.cachedStr
|
||||
}
|
||||
func (e ErrInErr) String() string {
|
||||
|
||||
func (e *ErrInErr) string() string {
|
||||
if e.Data != nil {
|
||||
|
||||
if e.ErrDetail != nil {
|
||||
|
Reference in New Issue
Block a user