Fix: vmess udp crash

This commit is contained in:
Dreamacro
2020-02-17 17:34:19 +08:00
parent e9032c55fa
commit 7b48138ad0
9 changed files with 81 additions and 43 deletions

View File

@ -2,12 +2,14 @@ package outbound
import (
"context"
"errors"
"fmt"
"net"
"strconv"
"strings"
"github.com/Dreamacro/clash/component/dialer"
"github.com/Dreamacro/clash/component/resolver"
"github.com/Dreamacro/clash/component/vmess"
C "github.com/Dreamacro/clash/constant"
)
@ -44,6 +46,15 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
}
func (v *Vmess) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
// vmess use stream-oriented udp, so clash needs a net.UDPAddr
if !metadata.Resolved() {
ip, err := resolver.ResolveIP(metadata.Host)
if err != nil {
return nil, errors.New("can't resolve ip")
}
metadata.DstIP = ip
}
ctx, cancel := context.WithTimeout(context.Background(), tcpTimeout)
defer cancel()
c, err := dialer.DialContext(ctx, "tcp", v.server)
@ -55,7 +66,7 @@ func (v *Vmess) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
if err != nil {
return nil, fmt.Errorf("new vmess client error: %v", err)
}
return newPacketConn(&vmessUDPConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
return newPacketConn(&vmessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
}
func NewVmess(option VmessOption) (*Vmess, error) {
@ -116,16 +127,20 @@ func parseVmessAddr(metadata *C.Metadata) *vmess.DstAddr {
}
}
type vmessUDPConn struct {
type vmessPacketConn struct {
net.Conn
rAddr net.Addr
}
func (uc *vmessUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
func (uc *vmessPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
return uc.Conn.Write(b)
}
func (uc *vmessUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
func (uc *vmessPacketConn) WriteWithMetadata(p []byte, metadata *C.Metadata) (n int, err error) {
return uc.Conn.Write(p)
}
func (uc *vmessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
n, err := uc.Conn.Read(b)
return n, uc.rAddr, err
}