Skip to content

Commit 108bf64

Browse files
committed
chore: merge the server-side and client-side vision implementations
1 parent 50e1afd commit 108bf64

File tree

2 files changed

+306
-33
lines changed

2 files changed

+306
-33
lines changed

listener/sing_vless/server.go

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import (
55
"errors"
66
"net"
77
"net/http"
8-
"reflect"
98
"strings"
10-
"unsafe"
119

1210
"github.com/metacubex/mihomo/adapter/inbound"
1311
"github.com/metacubex/mihomo/component/ca"
@@ -17,48 +15,19 @@ import (
1715
LC "github.com/metacubex/mihomo/listener/config"
1816
"github.com/metacubex/mihomo/listener/reality"
1917
"github.com/metacubex/mihomo/listener/sing"
20-
"github.com/metacubex/mihomo/log"
2118
"github.com/metacubex/mihomo/transport/gun"
2219
"github.com/metacubex/mihomo/transport/vless/encryption"
2320
mihomoVMess "github.com/metacubex/mihomo/transport/vmess"
2421

25-
"github.com/metacubex/sing-vmess/vless"
2622
"github.com/metacubex/sing/common"
2723
"github.com/metacubex/sing/common/metadata"
28-
"github.com/metacubex/sing/common/network"
2924
)
3025

31-
func init() {
32-
vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) {
33-
tlsConn, loaded := network.CastReader[*reality.Conn](conn) // *utls.Conn
34-
if !loaded {
35-
return
36-
}
37-
return true, tlsConn.NetConn(), reflect.TypeOf(tlsConn).Elem(), unsafe.Pointer(tlsConn)
38-
})
39-
40-
vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) {
41-
tlsConn, loaded := network.CastReader[*tlsC.UConn](conn) // *utls.UConn
42-
if !loaded {
43-
return
44-
}
45-
return true, tlsConn.NetConn(), reflect.TypeOf(tlsConn.Conn).Elem(), unsafe.Pointer(tlsConn.Conn)
46-
})
47-
48-
vless.RegisterTLS(func(conn net.Conn) (loaded bool, netConn net.Conn, reflectType reflect.Type, reflectPointer unsafe.Pointer) {
49-
tlsConn, loaded := network.CastReader[*encryption.CommonConn](conn)
50-
if !loaded {
51-
return
52-
}
53-
return true, tlsConn.Conn, reflect.TypeOf(tlsConn).Elem(), unsafe.Pointer(tlsConn)
54-
})
55-
}
56-
5726
type Listener struct {
5827
closed bool
5928
config LC.VlessServer
6029
listeners []net.Listener
61-
service *vless.Service[string]
30+
service *Service[string]
6231
decryption *encryption.ServerInstance
6332
}
6433

@@ -79,7 +48,7 @@ func New(config LC.VlessServer, tunnel C.Tunnel, additions ...inbound.Addition)
7948
return nil, err
8049
}
8150

82-
service := vless.NewService[string](log.SingLogger, h)
51+
service := NewService[string](h)
8352
service.UpdateUsers(
8453
common.Map(config.Users, func(it LC.VlessUser) string {
8554
return it.Username

listener/sing_vless/service.go

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
package sing_vless
2+
3+
// copy and modify from https://github.com/SagerNet/sing-vmess/tree/3c1cf255413250b09a57e4ecdf1def1fa505e3cc/vless
4+
5+
import (
6+
"context"
7+
"encoding/binary"
8+
"io"
9+
"net"
10+
11+
"github.com/metacubex/mihomo/transport/vless"
12+
"github.com/metacubex/mihomo/transport/vless/vision"
13+
14+
"github.com/gofrs/uuid/v5"
15+
"github.com/metacubex/sing-vmess"
16+
"github.com/metacubex/sing/common/auth"
17+
"github.com/metacubex/sing/common/buf"
18+
"github.com/metacubex/sing/common/bufio"
19+
E "github.com/metacubex/sing/common/exceptions"
20+
M "github.com/metacubex/sing/common/metadata"
21+
N "github.com/metacubex/sing/common/network"
22+
"google.golang.org/protobuf/proto"
23+
)
24+
25+
type Service[T comparable] struct {
26+
userMap map[[16]byte]T
27+
userFlow map[T]string
28+
handler Handler
29+
}
30+
31+
type Handler interface {
32+
N.TCPConnectionHandler
33+
N.UDPConnectionHandler
34+
E.Handler
35+
}
36+
37+
func NewService[T comparable](handler Handler) *Service[T] {
38+
return &Service[T]{
39+
handler: handler,
40+
}
41+
}
42+
43+
func (s *Service[T]) UpdateUsers(userList []T, userUUIDList []string, userFlowList []string) {
44+
userMap := make(map[[16]byte]T)
45+
userFlowMap := make(map[T]string)
46+
for i, userName := range userList {
47+
userID, err := uuid.FromString(userUUIDList[i])
48+
if err != nil {
49+
userID = uuid.NewV5(uuid.Nil, userUUIDList[i])
50+
}
51+
userMap[userID] = userName
52+
userFlowMap[userName] = userFlowList[i]
53+
}
54+
s.userMap = userMap
55+
s.userFlow = userFlowMap
56+
}
57+
58+
var _ N.TCPConnectionHandler = (*Service[int])(nil)
59+
60+
func (s *Service[T]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
61+
var version uint8
62+
err := binary.Read(conn, binary.BigEndian, &version)
63+
if err != nil {
64+
return err
65+
}
66+
if version != vless.Version {
67+
return E.New("unknown version: ", version)
68+
}
69+
70+
var requestUUID [16]byte
71+
_, err = io.ReadFull(conn, requestUUID[:])
72+
if err != nil {
73+
return err
74+
}
75+
76+
var addonsLen uint8
77+
err = binary.Read(conn, binary.BigEndian, &addonsLen)
78+
if err != nil {
79+
return err
80+
}
81+
82+
var addons vless.Addons
83+
if addonsLen > 0 {
84+
addonsBytes := make([]byte, addonsLen)
85+
_, err = io.ReadFull(conn, addonsBytes)
86+
if err != nil {
87+
return err
88+
}
89+
90+
err = proto.Unmarshal(addonsBytes, &addons)
91+
if err != nil {
92+
return err
93+
}
94+
}
95+
96+
var command byte
97+
err = binary.Read(conn, binary.BigEndian, &command)
98+
if err != nil {
99+
return err
100+
}
101+
102+
var destination M.Socksaddr
103+
if command != vless.CommandMux {
104+
destination, err = vmess.AddressSerializer.ReadAddrPort(conn)
105+
if err != nil {
106+
return err
107+
}
108+
}
109+
110+
user, loaded := s.userMap[requestUUID]
111+
if !loaded {
112+
return E.New("unknown UUID: ", uuid.FromBytesOrNil(requestUUID[:]))
113+
}
114+
ctx = auth.ContextWithUser(ctx, user)
115+
metadata.Destination = destination
116+
117+
userFlow := s.userFlow[user]
118+
requestFlow := addons.Flow
119+
if requestFlow != userFlow && requestFlow != "" {
120+
return E.New("flow mismatch: expected ", flowName(userFlow), ", but got ", flowName(requestFlow))
121+
}
122+
123+
responseConn := &serverConn{ExtendedConn: bufio.NewExtendedConn(conn)}
124+
switch requestFlow {
125+
case vless.XRV:
126+
conn, err = vision.NewConn(responseConn, conn, requestUUID)
127+
if err != nil {
128+
return E.Cause(err, "initialize vision")
129+
}
130+
case "":
131+
conn = responseConn
132+
default:
133+
return E.New("unknown flow: ", requestFlow)
134+
}
135+
switch command {
136+
case vless.CommandTCP:
137+
return s.handler.NewConnection(ctx, conn, metadata)
138+
case vless.CommandUDP:
139+
if requestFlow == vless.XRV {
140+
return E.New(vless.XRV, " flow does not support UDP")
141+
}
142+
return s.handler.NewPacketConnection(ctx, &serverPacketConn{ExtendedConn: bufio.NewExtendedConn(conn), destination: destination}, metadata)
143+
case vless.CommandMux:
144+
return vmess.HandleMuxConnection(ctx, conn, metadata, s.handler)
145+
default:
146+
return E.New("unknown command: ", command)
147+
}
148+
}
149+
150+
func flowName(value string) string {
151+
if value == "" {
152+
return "none"
153+
}
154+
return value
155+
}
156+
157+
type serverConn struct {
158+
N.ExtendedConn
159+
responseWritten bool
160+
}
161+
162+
func (c *serverConn) Write(b []byte) (n int, err error) {
163+
if !c.responseWritten {
164+
buffer := buf.NewSize(2 + len(b))
165+
buffer.WriteByte(vless.Version)
166+
buffer.WriteByte(0)
167+
buffer.Write(b)
168+
_, err = c.ExtendedConn.Write(buffer.Bytes())
169+
buffer.Release()
170+
if err == nil {
171+
n = len(b)
172+
}
173+
c.responseWritten = true
174+
return
175+
}
176+
return c.ExtendedConn.Write(b)
177+
}
178+
179+
func (c *serverConn) WriteBuffer(buffer *buf.Buffer) error {
180+
if !c.responseWritten {
181+
header := buffer.ExtendHeader(2)
182+
header[0] = vless.Version
183+
header[1] = 0
184+
c.responseWritten = true
185+
}
186+
return c.ExtendedConn.WriteBuffer(buffer)
187+
}
188+
189+
func (c *serverConn) FrontHeadroom() int {
190+
if c.responseWritten {
191+
return 0
192+
}
193+
return 2
194+
}
195+
196+
func (c *serverConn) ReaderReplaceable() bool {
197+
return true
198+
}
199+
200+
func (c *serverConn) WriterReplaceable() bool {
201+
return c.responseWritten
202+
}
203+
204+
func (c *serverConn) NeedAdditionalReadDeadline() bool {
205+
return true
206+
}
207+
208+
func (c *serverConn) Upstream() any {
209+
return c.ExtendedConn
210+
}
211+
212+
type serverPacketConn struct {
213+
N.ExtendedConn
214+
destination M.Socksaddr
215+
readWaitOptions N.ReadWaitOptions
216+
}
217+
218+
func (c *serverPacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
219+
c.readWaitOptions = options
220+
return false
221+
}
222+
223+
func (c *serverPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
224+
var packetLen uint16
225+
err = binary.Read(c.ExtendedConn, binary.BigEndian, &packetLen)
226+
if err != nil {
227+
return
228+
}
229+
230+
buffer = c.readWaitOptions.NewPacketBuffer()
231+
_, err = buffer.ReadFullFrom(c.ExtendedConn, int(packetLen))
232+
if err != nil {
233+
buffer.Release()
234+
return
235+
}
236+
c.readWaitOptions.PostReturn(buffer)
237+
238+
destination = c.destination
239+
return
240+
}
241+
242+
func (c *serverPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
243+
var packetLen uint16
244+
err = binary.Read(c.ExtendedConn, binary.BigEndian, &packetLen)
245+
if err != nil {
246+
return
247+
}
248+
if len(p) < int(packetLen) {
249+
err = io.ErrShortBuffer
250+
return
251+
}
252+
n, err = io.ReadFull(c.ExtendedConn, p[:packetLen])
253+
if err != nil {
254+
return
255+
}
256+
if c.destination.IsFqdn() {
257+
addr = c.destination
258+
} else {
259+
addr = c.destination.UDPAddr()
260+
}
261+
return
262+
}
263+
264+
func (c *serverPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
265+
err = binary.Write(c.ExtendedConn, binary.BigEndian, uint16(len(p)))
266+
if err != nil {
267+
return
268+
}
269+
return c.ExtendedConn.Write(p)
270+
}
271+
272+
func (c *serverPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
273+
var packetLen uint16
274+
err = binary.Read(c.ExtendedConn, binary.BigEndian, &packetLen)
275+
if err != nil {
276+
return
277+
}
278+
279+
_, err = buffer.ReadFullFrom(c.ExtendedConn, int(packetLen))
280+
if err != nil {
281+
return
282+
}
283+
284+
destination = c.destination
285+
return
286+
}
287+
288+
func (c *serverPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
289+
packetLen := buffer.Len()
290+
binary.BigEndian.PutUint16(buffer.ExtendHeader(2), uint16(packetLen))
291+
return c.ExtendedConn.WriteBuffer(buffer)
292+
}
293+
294+
func (c *serverPacketConn) FrontHeadroom() int {
295+
return 2
296+
}
297+
298+
func (c *serverPacketConn) NeedAdditionalReadDeadline() bool {
299+
return true
300+
}
301+
302+
func (c *serverPacketConn) Upstream() any {
303+
return c.ExtendedConn
304+
}

0 commit comments

Comments
 (0)