mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-23 00:51:29 +00:00
120 lines
2.4 KiB
Go
120 lines
2.4 KiB
Go
|
package mux
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"io"
|
||
|
|
||
|
C "github.com/sagernet/sing-box/constant"
|
||
|
"github.com/sagernet/sing/common"
|
||
|
"github.com/sagernet/sing/common/buf"
|
||
|
E "github.com/sagernet/sing/common/exceptions"
|
||
|
M "github.com/sagernet/sing/common/metadata"
|
||
|
N "github.com/sagernet/sing/common/network"
|
||
|
"github.com/sagernet/sing/common/rw"
|
||
|
|
||
|
"github.com/hashicorp/yamux"
|
||
|
)
|
||
|
|
||
|
var Destination = M.Socksaddr{
|
||
|
Fqdn: "sp.mux.sing-box.arpa",
|
||
|
Port: 444,
|
||
|
}
|
||
|
|
||
|
func newMuxConfig() *yamux.Config {
|
||
|
config := yamux.DefaultConfig()
|
||
|
config.LogOutput = io.Discard
|
||
|
config.StreamCloseTimeout = C.TCPTimeout
|
||
|
config.StreamOpenTimeout = C.TCPTimeout
|
||
|
return config
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
version0 = 0
|
||
|
flagUDP = 1
|
||
|
flagAddr = 2
|
||
|
statusSuccess = 0
|
||
|
statusError = 1
|
||
|
)
|
||
|
|
||
|
type Request struct {
|
||
|
Network string
|
||
|
Destination M.Socksaddr
|
||
|
PacketAddr bool
|
||
|
}
|
||
|
|
||
|
func ReadRequest(reader io.Reader) (*Request, error) {
|
||
|
version, err := rw.ReadByte(reader)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if version != version0 {
|
||
|
return nil, E.New("unsupported version: ", version)
|
||
|
}
|
||
|
var flags uint16
|
||
|
err = binary.Read(reader, binary.BigEndian, &flags)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
destination, err := M.SocksaddrSerializer.ReadAddrPort(reader)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
var network string
|
||
|
var udpAddr bool
|
||
|
if flags&flagUDP == 0 {
|
||
|
network = N.NetworkTCP
|
||
|
} else {
|
||
|
network = N.NetworkUDP
|
||
|
udpAddr = flags&flagAddr != 0
|
||
|
}
|
||
|
return &Request{network, destination, udpAddr}, nil
|
||
|
}
|
||
|
|
||
|
func requestLen(request Request) int {
|
||
|
var rLen int
|
||
|
rLen += 1 // version
|
||
|
rLen += 2 // flags
|
||
|
rLen += M.SocksaddrSerializer.AddrPortLen(request.Destination)
|
||
|
return rLen
|
||
|
}
|
||
|
|
||
|
func EncodeRequest(request Request, buffer *buf.Buffer) {
|
||
|
destination := request.Destination
|
||
|
var flags uint16
|
||
|
if request.Network == N.NetworkUDP {
|
||
|
flags |= flagUDP
|
||
|
}
|
||
|
if request.PacketAddr {
|
||
|
flags |= flagAddr
|
||
|
if !destination.IsValid() {
|
||
|
destination = Destination
|
||
|
}
|
||
|
}
|
||
|
common.Must(
|
||
|
buffer.WriteByte(version0),
|
||
|
binary.Write(buffer, binary.BigEndian, flags),
|
||
|
M.SocksaddrSerializer.WriteAddrPort(buffer, destination),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
type Response struct {
|
||
|
Status uint8
|
||
|
Message string
|
||
|
}
|
||
|
|
||
|
func ReadResponse(reader io.Reader) (*Response, error) {
|
||
|
var response Response
|
||
|
status, err := rw.ReadByte(reader)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
response.Status = status
|
||
|
if status == statusError {
|
||
|
response.Message, err = rw.ReadVString(reader)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
return &response, nil
|
||
|
}
|