mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
这是由两个问题造成的 问题1: 同时并发请求多个请求时,会出现同时建立两个mux的情况,导致先建立的mux被覆盖; 问题2: 一旦某个stream的连接失败后,代码 会关闭整个session。这是由于 iics无法分辨simplesocks和普通协议造成的。 加一个 isInner 标签即可分辨。
139 lines
4.0 KiB
Go
139 lines
4.0 KiB
Go
package proxy
|
||
|
||
import (
|
||
"io"
|
||
"net"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
|
||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||
"github.com/xtaci/smux"
|
||
)
|
||
|
||
// default recommended handshake read timeout
|
||
const CommonReadTimeout = time.Second * 4
|
||
|
||
//set read timeout after CommonReadTimeout
|
||
func SetCommonReadTimeout(c net.Conn) error {
|
||
return c.SetReadDeadline(time.Now().Add(CommonReadTimeout))
|
||
}
|
||
|
||
//规定,如果 proxy的server的handshake如果返回的是具有内层mux的连接,该连接要实现 MuxMarker 接口.
|
||
type MuxMarker interface {
|
||
io.ReadWriteCloser
|
||
IsMux()
|
||
}
|
||
|
||
//实现 MuxMarker
|
||
type MuxMarkerConn struct {
|
||
netLayer.ReadWrapper
|
||
}
|
||
|
||
func (mh *MuxMarkerConn) IsMux() {}
|
||
|
||
// some client may 建立tcp连接后首先由客户端读服务端的数据?虽较少见但确实存在.
|
||
// Anyway firstpayload might not be read, and we should try to reduce this delay.
|
||
// 也有可能是有人用 nc 来测试,也会遇到这种读不到 firstpayload 的情况
|
||
const FirstPayloadTimeout = time.Millisecond * 100
|
||
|
||
// Client is used to dial a server.
|
||
// Because Server is "target agnostic", Client's Handshake requires a target addr as param.
|
||
//
|
||
// A Client has all the data of all layers in its VSI model.
|
||
// Once a Client is fully defined, the flow of the data is fully defined.
|
||
type Client interface {
|
||
BaseInterface
|
||
|
||
//Perform handshake when request is TCP。firstPayload 用于如 vless/trojan 这种 没有握手包的协议,可为空。
|
||
Handshake(underlay net.Conn, firstPayload []byte, target netLayer.Addr) (wrappedConn io.ReadWriteCloser, err error)
|
||
|
||
//Establish a channel and constantly request data for each UDP addr through this channel. firstpayload and target can be empty theoretically, depending on the implementation.
|
||
EstablishUDPChannel(underlay net.Conn, firstPayload []byte, target netLayer.Addr) (netLayer.MsgConn, error)
|
||
|
||
//If udp is send through multiple connection or not
|
||
IsUDP_MultiChannel() bool
|
||
|
||
//get/listen a useable inner mux
|
||
GetClientInnerMuxSession(wrc io.ReadWriteCloser) *smux.Session
|
||
InnerMuxEstablished() bool
|
||
CloseInnerMuxSession()
|
||
|
||
sync.Locker //用于锁定 innerMux
|
||
}
|
||
|
||
type UserClient interface {
|
||
Client
|
||
GetUser() utils.User
|
||
}
|
||
|
||
// Server is used for listening clients.
|
||
// Because Server is "target agnostic",Handshake should return the target addr that the Client requested.
|
||
//
|
||
// A Server has all the data of all layers in its VSI model.
|
||
// Once a Server is fully defined, the flow of the data is fully defined.
|
||
type Server interface {
|
||
BaseInterface
|
||
|
||
//ReadWriteCloser is for TCP request, net.PacketConn is for UDP request.
|
||
// 约定,如果error返回的是 utils.ErrHandled, 则调用代码停止进一步处理。
|
||
Handshake(underlay net.Conn) (net.Conn, netLayer.MsgConn, netLayer.Addr, error)
|
||
|
||
//get/listen a useable inner mux
|
||
GetServerInnerMuxSession(wlc io.ReadWriteCloser) *smux.Session
|
||
}
|
||
|
||
type UserServer interface {
|
||
Server
|
||
utils.UserContainer
|
||
}
|
||
|
||
// FullName can fully represent the VSI model for a proxy.
|
||
// We think tcp/udp/kcp/raw_socket is FirstName,protocol of the proxy is LastName, and the rest is MiddleName。
|
||
//
|
||
// An Example of a full name: tcp+tls+ws+vless.
|
||
// 总之,类似【域名】的规则,只不过分隔符从 点号 变成了加号, 且层级关系是从左到右。
|
||
func GetFullName(pc BaseInterface) string {
|
||
if n := pc.Name(); n == DirectName {
|
||
return n
|
||
} else {
|
||
|
||
return getFullNameBuilder(pc, n).String()
|
||
}
|
||
}
|
||
|
||
// return GetFullName(pc) + "://" + pc.AddrStr() (+ #tag)
|
||
func GetVSI_url(pc BaseInterface) string {
|
||
n := pc.Name()
|
||
if n == DirectName {
|
||
return DirectURL
|
||
}
|
||
sb := getFullNameBuilder(pc, n)
|
||
sb.WriteString("://")
|
||
sb.WriteString(pc.AddrStr())
|
||
if t := pc.GetTag(); t != "" {
|
||
sb.WriteByte('#')
|
||
sb.WriteString(t)
|
||
}
|
||
|
||
return sb.String()
|
||
}
|
||
|
||
func getFullNameBuilder(pc BaseInterface, n string) *strings.Builder {
|
||
|
||
var sb strings.Builder
|
||
sb.WriteString(pc.Network())
|
||
sb.WriteString(pc.MiddleName())
|
||
sb.WriteString(n)
|
||
|
||
if i, innerProxyName := pc.HasInnerMux(); i == 2 {
|
||
sb.WriteString("+smux+")
|
||
sb.WriteString(innerProxyName)
|
||
|
||
}
|
||
|
||
return &sb
|
||
|
||
}
|