修订代码,注释,文档

This commit is contained in:
hahahrfool
2022-03-22 16:46:05 +08:00
parent 17ebc3a72a
commit 536a84def6
14 changed files with 97 additions and 83 deletions

View File

@@ -7,6 +7,7 @@
# #
# for embedding geoip file: # for embedding geoip file:
# make tags="embed_geoip" macm1 # make tags="embed_geoip" macm1
#
# 目前发布版直接使用go1.18编译你如果想编译出相同文件也要使用go1.18才行 # 目前发布版直接使用go1.18编译你如果想编译出相同文件也要使用go1.18才行
BUILD_VERSION := v1.0.7 BUILD_VERSION := v1.0.7

32
main.go
View File

@@ -31,6 +31,7 @@ const (
standardMode standardMode
v2rayCompatibleMode v2rayCompatibleMode
) )
const tlslazy_willuseSystemCall = runtime.GOOS == "linux" || runtime.GOOS == "darwin"
var ( var (
configFileName string configFileName string
@@ -216,12 +217,12 @@ func main() {
func listenSer(listener net.Listener, inServer proxy.Server) { func listenSer(listener net.Listener, inServer proxy.Server) {
theFunc := func(conn net.Conn) { handleFunc := func(conn net.Conn) {
handleNewIncomeConnection(inServer, conn) handleNewIncomeConnection(inServer, conn)
} }
network := inServer.Network() network := inServer.Network()
err := netLayer.ListenAndAccept(network, inServer.AddrStr(), theFunc) err := netLayer.ListenAndAccept(network, inServer.AddrStr(), handleFunc)
if err == nil { if err == nil {
if utils.CanLogInfo() { if utils.CanLogInfo() {
@@ -700,7 +701,18 @@ afterLocalServerHandshake:
} }
if utils.CanLogDebug() { if utils.CanLogDebug() {
/*
if netLayer.UseReadv {
go func() {
n, e := netLayer.TryCopy(wrc, wlc)
log.Println("本地->远程 转发结束", realTargetAddr.String(), n, e)
}()
n, e := netLayer.TryCopy(wlc, wrc)
log.Println("远程->本地 转发结束", realTargetAddr.String(), n, e)
} else {
go func() { go func() {
n, e := io.Copy(wrc, wlc) n, e := io.Copy(wrc, wlc)
log.Println("本地->远程 转发结束", realTargetAddr.String(), n, e) log.Println("本地->远程 转发结束", realTargetAddr.String(), n, e)
@@ -708,27 +720,15 @@ afterLocalServerHandshake:
n, e := io.Copy(wlc, wrc) n, e := io.Copy(wlc, wrc)
log.Println("远程->本地 转发结束", realTargetAddr.String(), n, e) log.Println("远程->本地 转发结束", realTargetAddr.String(), n, e)
*/
go func() { }
n, e := netLayer.TryCopy(wrc, wlc)
log.Println("本地->远程 转发结束", realTargetAddr.String(), n, e)
}()
n, e := netLayer.TryCopy(wlc, wrc)
log.Println("远程->本地 转发结束", realTargetAddr.String(), n, e)
} else { } else {
//如果两个都是 *net.TCPConn或uds, 则Copy会自动进行splice/sendfile无需额外处理
//go io.Copy(wrc, wlc)
//io.Copy(wlc, wrc)
netLayer.Relay(wlc, wrc) netLayer.Relay(wlc, wrc)
} }
} }
var tlslazy_willuseSystemCall = runtime.GOOS == "linux" || runtime.GOOS == "darwin"
// tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn也就是裸奔转发 // tryRawCopy 尝试能否直接对拷,对拷 直接使用 原始 TCPConn也就是裸奔转发
// 如果在linux上则和 xtls的splice 含义相同. 在其他系统时与xtls-direct含义相同。 // 如果在linux上则和 xtls的splice 含义相同. 在其他系统时与xtls-direct含义相同。
// 我们内部先 使用 DetectConn进行过滤分析然后再判断进化为splice 或者退化为普通拷贝 // 我们内部先 使用 DetectConn进行过滤分析然后再判断进化为splice 或者退化为普通拷贝

View File

@@ -28,22 +28,26 @@ type Addr struct {
Network string Network string
} }
func RandPortStr() string {
return strconv.Itoa(rand.Intn(60000) + 4096)
}
func GetRandLocalAddr() string { func GetRandLocalAddr() string {
return "0.0.0.0:" + strconv.Itoa(rand.Intn(60000)+4096) return "0.0.0.0:" + RandPortStr()
} }
func NewAddrFromUDPAddr(addr *net.UDPAddr) *Addr { func NewAddrFromUDPAddr(addr *net.UDPAddr) *Addr {
return &Addr{ return &Addr{
IP: addr.IP, IP: addr.IP,
Port: addr.Port, Port: addr.Port,
//IsUDP: true,
Network: "udp", Network: "udp",
} }
} }
//addrStr格式一般为 host:port 的格式;如果不含冒号,将直接认为该字符串是域名或文件名
func NewAddr(addrStr string) (*Addr, error) { func NewAddr(addrStr string) (*Addr, error) {
if !strings.Contains(addrStr, ":") { if !strings.Contains(addrStr, ":") {
//如果 是unix domain socket //unix domain socket, 或者域名默认端口的情况
return &Addr{Name: addrStr}, nil return &Addr{Name: addrStr}, nil
} }

View File

@@ -26,7 +26,7 @@ func GetRawConn(reader io.Reader) syscall.RawConn {
} }
// 用于读端实现了 readv但是写端的情况比如 从socks5读取 数据, 等裸协议的情况 // 用于读端实现了 readv但是写端的情况比如 从socks5读取 数据, 等裸协议的情况
// 小贴士:将该 net.Buffers 写入io.Writer的话只需使用 其WriteTo方法。 // 小贴士:将该 net.Buffers 写入io.Writer的话只需使用 其WriteTo方法, 即可自动适配writev
/* /*
使用方式 使用方式

View File

@@ -21,7 +21,7 @@ func init() {
} }
//这里认为能 splice 或 sendfile的 都算 //这里认为能 splice 或 sendfile的 都算具体可参考go标准代码的实现, 总之就是tcp和uds可以
func CanSplice(r interface{}) bool { func CanSplice(r interface{}) bool {
if _, ok := r.(*net.TCPConn); ok { if _, ok := r.(*net.TCPConn); ok {
@@ -90,7 +90,7 @@ copy:
return io.Copy(writeConn, readConn) return io.Copy(writeConn, readConn)
} }
// 类似TryCopy但是只会读写一次 // 类似TryCopy但是只会读写一次; 因为只读写一次所以没办法splice
func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err error) { func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err error) {
var mr utils.MultiReader var mr utils.MultiReader
var buffers net.Buffers var buffers net.Buffers
@@ -100,12 +100,6 @@ func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err err
log.Println("TryCopy", reflect.TypeOf(readConn), "->", reflect.TypeOf(writeConn)) log.Println("TryCopy", reflect.TypeOf(readConn), "->", reflect.TypeOf(writeConn))
} }
if SystemCanSplice && CanSplice(readConn) && CanSplice(writeConn) {
if utils.CanLogDebug() {
log.Println("copying with splice")
}
goto copy
}
// 不全 支持splice的话我们就考虑 read端 可 readv 的情况 // 不全 支持splice的话我们就考虑 read端 可 readv 的情况
// 连readv都不让 那就直接 经典拷贝 // 连readv都不让 那就直接 经典拷贝
if !UseReadv { if !UseReadv {
@@ -136,16 +130,22 @@ classic:
if utils.CanLogDebug() { if utils.CanLogDebug() {
log.Println("copying with classic method") log.Println("copying with classic method")
} }
copy:
//Copy内部实现 会自动进行splice, 若无splice实现则直接使用原始方法 “循环读取 并 写入” bs := utils.GetPacket()
return io.Copy(writeConn, readConn) n, e := readConn.Read(bs)
if e != nil {
return 0, e
}
n, e = writeConn.Write(bs[:n])
utils.PutPacket(bs)
return int64(n), e
} }
// 从conn1读取 写入到 conn2并同时从 conn2读取写入conn1 // 从conn1读取 写入到 conn2并同时从 conn2读取写入conn1
// 阻塞 // 阻塞
// 返回从 conn1读取 写入到 conn2的数据 // 返回从 conn1读取 写入到 conn2的数据
// UseReadv==true 时 内部使用 TryCopy 进行拷贝 // UseReadv==true 时 内部使用 TryCopy 进行拷贝
// 会自动优选 splicereadv不行则使用经典拷贝
func Relay(conn1, conn2 io.ReadWriter) (int64, error) { func Relay(conn1, conn2 io.ReadWriter) (int64, error) {
if UseReadv { if UseReadv {
@@ -157,31 +157,3 @@ func Relay(conn1, conn2 io.ReadWriter) (int64, error) {
return io.Copy(conn2, conn1) return io.Copy(conn2, conn1)
} }
} }
// 阻塞.
func RelayUDP(putter UDP_Putter, extractor UDP_Extractor) {
go func() {
for {
raddr, bs, err := extractor.GetNewUDPRequest()
if err != nil {
break
}
err = putter.WriteUDPRequest(raddr, bs)
if err != nil {
break
}
}
}()
for {
raddr, bs, err := putter.GetNewUDPResponse()
if err != nil {
break
}
err = extractor.WriteUDPResponse(raddr, bs)
if err != nil {
break
}
}
}

View File

@@ -11,6 +11,35 @@ const (
) )
//本文件内含 一些 转发 udp 数据的 接口与方法 //本文件内含 一些 转发 udp 数据的 接口与方法
// 阻塞.
func RelayUDP(putter UDP_Putter, extractor UDP_Extractor) {
go func() {
for {
raddr, bs, err := extractor.GetNewUDPRequest()
if err != nil {
break
}
err = putter.WriteUDPRequest(raddr, bs)
if err != nil {
break
}
}
}()
for {
raddr, bs, err := putter.GetNewUDPResponse()
if err != nil {
break
}
err = extractor.WriteUDPResponse(raddr, bs)
if err != nil {
break
}
}
}
//////////////////// 接口 //////////////////// //////////////////// 接口 ////////////////////
type UDPRequestReader interface { type UDPRequestReader interface {

View File

@@ -36,11 +36,11 @@ type UserConn struct {
remainFirstBufLen int //记录读取握手包头时读到的buf的长度. 如果我们读超过了这个部分的话,实际上我们就可以不再使用 optionalReader 读取, 而是直接从Conn读取 remainFirstBufLen int //记录读取握手包头时读到的buf的长度. 如果我们读超过了这个部分的话,实际上我们就可以不再使用 optionalReader 读取, 而是直接从Conn读取
uuid [16]byte uuid [16]byte
convertedStr string convertedUUIDStr string
version int version int
isUDP bool isUDP bool
isServerEnd bool //for v0 isServerEnd bool //for v0
// udpUnreadPart 不为空则表示上一次读取没读完整个包给Read传入的buf太小须接着读 // udpUnreadPart 不为空则表示上一次读取没读完整个包给Read传入的buf太小须接着读
udpUnreadPart []byte //for udp udpUnreadPart []byte //for udp
@@ -55,11 +55,11 @@ func (uc *UserConn) GetProtocolVersion() int {
return uc.version return uc.version
} }
func (uc *UserConn) GetIdentityStr() string { func (uc *UserConn) GetIdentityStr() string {
if uc.convertedStr == "" { if uc.convertedUUIDStr == "" {
uc.convertedStr = proxy.UUIDToStr(uc.uuid) uc.convertedUUIDStr = proxy.UUIDToStr(uc.uuid)
} }
return uc.convertedStr return uc.convertedUUIDStr
} }
//如果是udp则是多线程不安全的如果是tcp则安不安全看底层的链接。 //如果是udp则是多线程不安全的如果是tcp则安不安全看底层的链接。

View File

@@ -15,11 +15,11 @@ import (
) )
func TestVLess0(t *testing.T) { func TestVLess0(t *testing.T) {
testVLess(0, "9527", t) testVLess(0, netLayer.RandPortStr(), t)
} }
func TestVLess1(t *testing.T) { func TestVLess1(t *testing.T) {
testVLess(1, "9538", t) testVLess(1, netLayer.RandPortStr(), t)
} }
func testVLess(version int, port string, t *testing.T) { func testVLess(version int, port string, t *testing.T) {
@@ -115,7 +115,7 @@ func testVLess(version int, port string, t *testing.T) {
} }
func TestVLess0_udp(t *testing.T) { func TestVLess0_udp(t *testing.T) {
testVLessUDP(0, "9638", t) testVLessUDP(0, netLayer.RandPortStr(), t)
} }
//func TestVLess1_udp(t *testing.T) { //func TestVLess1_udp(t *testing.T) {

View File

@@ -14,7 +14,7 @@ import (
) )
func TestVlesss(t *testing.T) { func TestVlesss(t *testing.T) {
testTls("vlesss", "9507", t) testTls("vlesss", netLayer.RandPortStr(), t)
} }
func testTls(protocol string, port string, t *testing.T) { func testTls(protocol string, port string, t *testing.T) {

View File

@@ -46,10 +46,12 @@ func init() {
} }
} }
//从Pool中获取一个 *bytes.Buffer
func GetBuf() *bytes.Buffer { func GetBuf() *bytes.Buffer {
return bufPool.Get().(*bytes.Buffer) return bufPool.Get().(*bytes.Buffer)
} }
//将 buf 放回 Pool
func PutBuf(buf *bytes.Buffer) { func PutBuf(buf *bytes.Buffer) {
buf.Reset() buf.Reset()
bufPool.Put(buf) bufPool.Put(buf)
@@ -73,12 +75,12 @@ func PutPacket(bs []byte) {
standardPacketPool.Put(bs[:c]) standardPacketPool.Put(bs[:c])
} }
// 从Pool中获取一个 StandardBytesLength 长度的 []byte
func GetMTU() []byte { func GetMTU() []byte {
return standardBytesPool.Get().([]byte)[:StandardBytesLength] return standardBytesPool.Get().([]byte)[:StandardBytesLength]
} }
// 从pool中获取 []byte, 在 size <= StandardBytesLength 时有最佳性能 // 从pool中获取 []byte, 根据给出长度不同来源于的Pool会不同.
// 否则会直接调用 GetPacket
func GetBytes(size int) []byte { func GetBytes(size int) []byte {
if size <= StandardBytesLength { if size <= StandardBytesLength {
bs := standardBytesPool.Get().([]byte) bs := standardBytesPool.Get().([]byte)
@@ -89,7 +91,7 @@ func GetBytes(size int) []byte {
} }
// 根据bs长度 选择放入各种pool中, 只有cap>=1500 才会被处理 // 根据bs长度 选择放入各种pool中, 只有 cap(bs)>=1500 才会被处理
func PutBytes(bs []byte) { func PutBytes(bs []byte) {
c := cap(bs) c := cap(bs)
if c < StandardBytesLength { if c < StandardBytesLength {

View File

@@ -1,7 +1,7 @@
// Package utils provides utils that needed by all packages of verysimle // Package utils provides utils that needed by all sub-packages in verysimle
package utils package utils
//具体实现见 readv_*.go //具体实现见 readv_*.go; 用 GetReadVReader() 函数来获取本平台的对应实现。
type MultiReader interface { type MultiReader interface {
Init([][]byte) Init([][]byte)
Read(fd uintptr) int32 Read(fd uintptr) int32

View File

@@ -1,5 +1,8 @@
# vless v1 # vless v1
目前v1仍然处于研发当中。建议先用v0等v1完全出炉了再说本文只是理论探索实际代码暂未完整实现所有的设计.
## 握手协议格式
具体我的探讨还可以查看 https://github.com/v2fly/v2ray-core/discussions/1655 具体我的探讨还可以查看 https://github.com/v2fly/v2ray-core/discussions/1655
总的来说 vless v1 简化了一些流程, 约定永远使用tls与trojan相同,并重点考虑 非多路复用的 udp over tcp的 fullcone实现。 总的来说 vless v1 简化了一些流程, 约定永远使用tls与trojan相同,并重点考虑 非多路复用的 udp over tcp的 fullcone实现。

View File

@@ -54,7 +54,7 @@ func (c *Conn) Read(p []byte) (int, error) {
return n, e return n, e
} }
c.remainLenForLastFrame -= int64(n) c.remainLenForLastFrame -= int64(n)
// 这里之所以可以放心 减去 n不怕减成负的是因为 r的代码里 在读取一帧的数据时,用到了 io.LimitedReader, 一帧的读取长度的上限已被限定,直到 该帧完全被读完为止 // 这里之所以可以放心 减去 n不怕减成负的是因为 wsutil.Reader 的代码里 在读取一帧的数据时,用到了 io.LimitedReader, 一帧的读取长度的上限已被限定,直到 该帧完全被读完为止
return n, nil return n, nil
} }

View File

@@ -1,16 +1,19 @@
package ws package ws_test
import ( import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"net" "net"
"testing" "testing"
"github.com/hahahrfool/v2ray_simple/netLayer"
"github.com/hahahrfool/v2ray_simple/ws"
) )
// ws基本读写功能测试. // ws基本读写功能测试.
// 分别测试写入短数据和长数据 // 分别测试写入短数据和长数据
func TestWs(t *testing.T) { func TestWs(t *testing.T) {
listenAddr := "127.0.0.1:7777" listenAddr := netLayer.GetRandLocalAddr()
listener, err := net.Listen("tcp", listenAddr) listener, err := net.Listen("tcp", listenAddr)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
@@ -35,7 +38,7 @@ func TestWs(t *testing.T) {
return return
} }
s := NewServer(wsPath) s := ws.NewServer(wsPath)
wsConn, err := s.Handshake(conn) wsConn, err := s.Handshake(conn)
if err != nil { if err != nil {
@@ -64,7 +67,7 @@ func TestWs(t *testing.T) {
} }
}() }()
cli, err := NewClient(listenAddr, wsPath) cli, err := ws.NewClient(listenAddr, wsPath)
if err != nil { if err != nil {
t.Log(err) t.Log(err)
t.FailNow() t.FailNow()