This commit is contained in:
arraykeys@gmail.com
2018-09-04 15:09:08 +08:00
parent 1d7eee0e69
commit 4d1c9ffa1f
8 changed files with 287 additions and 157 deletions

View File

@ -1,4 +1,11 @@
proxy更新日志 proxy更新日志
v5.5
1.预编译的二进制增加了armv8支持.
2.预编译的mipsle和mips二进制增加了softfloat支持.
3.优化连接HTTP(s)上级代理的CONNECT指令,附带更多的信息.
4.重构了内网穿透的UDP功能,性能大幅度提升,可以愉快的与异地基友玩依赖UDP的局域网游戏了.
5.重构了UDP端口映射,性能大幅度提升.
v5.4 v5.4
1.优化了获取本地IP信息导致CPU过高的问题. 1.优化了获取本地IP信息导致CPU过高的问题.
2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU. 2.所有服务都增加了--nolog参数,可以关闭日志输出,节省CPU.

View File

@ -18,10 +18,16 @@ CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -o proxy && tar zcfv "${REL
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=7 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm64-v7.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=7 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm64-v7.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm-v5.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=5 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm-v5.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=5 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm64-v5.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=5 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm64-v5.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm64-v8.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-arm-v8.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips64.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=mips64 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips64.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips64le.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=mips64le go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips64le.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mipsle.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mipsle.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mips GOMIPS=softfloat go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips-softfloat.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mips64 GOMIPS=softfloat go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips64-softfloat.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mips64le GOMIPS=softfloat go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mips64le-softfloat.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=mipsle GOMIPS=softfloat go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-mipsle-softfloat.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=ppc64 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-ppc64.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=ppc64 go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-ppc64.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-ppc64le.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=ppc64le go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-ppc64le.tar.gz" proxy direct blocked
CGO_ENABLED=0 GOOS=linux GOARCH=s390x go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-s390x.tar.gz" proxy direct blocked CGO_ENABLED=0 GOOS=linux GOARCH=s390x go build -o proxy && tar zcfv "${RELEASE}/proxy-linux-s390x.tar.gz" proxy direct blocked

View File

@ -6,6 +6,7 @@ import (
"io" "io"
logger "log" logger "log"
"net" "net"
"strings"
"time" "time"
"github.com/golang/snappy" "github.com/golang/snappy"
@ -31,12 +32,21 @@ type MuxClientArgs struct {
KCP kcpcfg.KCPConfigArgs KCP kcpcfg.KCPConfigArgs
Jumper *string Jumper *string
} }
type ClientUDPConnItem struct {
conn *smux.Stream
touchtime int64
srcAddr *net.UDPAddr
localAddr *net.UDPAddr
udpConn *net.UDPConn
connid string
}
type MuxClient struct { type MuxClient struct {
cfg MuxClientArgs cfg MuxClientArgs
isStop bool isStop bool
sessions utils.ConcurrentMap sessions utils.ConcurrentMap
log *logger.Logger log *logger.Logger
jumper *jumper.Jumper jumper *jumper.Jumper
udpConns utils.ConcurrentMap
} }
func NewMuxClient() services.Service { func NewMuxClient() services.Service {
@ -44,10 +54,12 @@ func NewMuxClient() services.Service {
cfg: MuxClientArgs{}, cfg: MuxClientArgs{},
isStop: false, isStop: false,
sessions: utils.NewConcurrentMap(), sessions: utils.NewConcurrentMap(),
udpConns: utils.NewConcurrentMap(),
} }
} }
func (s *MuxClient) InitService() (err error) { func (s *MuxClient) InitService() (err error) {
s.UDPGCDeamon()
return return
} }
@ -178,7 +190,7 @@ func (s *MuxClient) Start(args interface{}, log *logger.Logger) (err error) {
stream.Close() stream.Close()
return return
} }
s.log.Printf("worker[%d] signal revecived,server %s stream %s %s", i, serverID, ID, clientLocalAddr) //s.log.Printf("worker[%d] signal revecived,server %s stream %s %s", i, serverID, ID, clientLocalAddr)
protocol := clientLocalAddr[:3] protocol := clientLocalAddr[:3]
localAddr := clientLocalAddr[4:] localAddr := clientLocalAddr[4:]
if protocol == "udp" { if protocol == "udp" {
@ -228,76 +240,130 @@ func (s *MuxClient) getParentConn() (conn net.Conn, err error) {
return return
} }
func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) { func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) {
var item *ClientUDPConnItem
var body []byte
var err error
srcAddr := ""
defer func() {
if item != nil {
(*item).conn.Close()
(*item).udpConn.Close()
s.udpConns.Remove(srcAddr)
inConn.Close()
}
}()
for { for {
if s.isStop { if s.isStop {
return return
} }
inConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) srcAddr, body, err = utils.ReadUDPPacket(inConn)
srcAddr, body, err := utils.ReadUDPPacket(inConn)
inConn.SetDeadline(time.Time{})
if err != nil { if err != nil {
s.log.Printf("udp packet revecived fail, err: %s", err) if strings.Contains(err.Error(), "n != int(") {
s.log.Printf("connection %s released", ID) continue
}
if !utils.IsNetDeadlineErr(err) && err != io.EOF {
s.log.Printf("udp packet revecived from bridge fail, err: %s", err)
}
return
}
if v, ok := s.udpConns.Get(srcAddr); !ok {
_srcAddr, _ := net.ResolveUDPAddr("udp", srcAddr)
zeroAddr, _ := net.ResolveUDPAddr("udp", ":")
_localAddr, _ := net.ResolveUDPAddr("udp", localAddr)
c, err := net.DialUDP("udp", zeroAddr, _localAddr)
if err != nil {
s.log.Printf("create local udp conn fail, err : %s", err)
inConn.Close() inConn.Close()
break return
}
item = &ClientUDPConnItem{
conn: inConn,
srcAddr: _srcAddr,
localAddr: _localAddr,
udpConn: c,
connid: ID,
}
s.udpConns.Set(srcAddr, item)
s.UDPRevecive(srcAddr, ID)
} else { } else {
//s.log.Printf("udp packet revecived:%s,%v", srcAddr, body) item = v.(*ClientUDPConnItem)
go func() {
defer func() {
if e := recover(); e != nil {
s.log.Printf("client processUDPPacket crashed,err: %s", e)
}
}()
s.processUDPPacket(inConn, srcAddr, localAddr, body)
}()
}
} }
(*item).touchtime = time.Now().Unix()
go (*item).udpConn.Write(body)
//_, err = (*item).udpConn.Write(body)
// if err != nil {
// s.log.Printf("send udp packet to %s fail, err : %s", item.localAddr, err)
// return
// } // }
} }
func (s *MuxClient) processUDPPacket(inConn *smux.Stream, srcAddr, localAddr string, body []byte) { }
dstAddr, err := net.ResolveUDPAddr("udp", localAddr) func (s *MuxClient) UDPRevecive(key, ID string) {
if err != nil { go func() {
s.log.Printf("can't resolve address: %s", err) s.log.Printf("udp conn %s connected", ID)
inConn.Close() v, ok := s.udpConns.Get(key)
if !ok {
s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
return return
} }
clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0} cui := v.(*ClientUDPConnItem)
conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr) buf := utils.LeakyBuffer.Get()
defer func() {
utils.LeakyBuffer.Put(buf)
cui.conn.Close()
cui.udpConn.Close()
s.udpConns.Remove(key)
s.log.Printf("udp conn %s released", ID)
}()
for {
n, err := cui.udpConn.Read(buf)
if err != nil { if err != nil {
s.log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err) if !utils.IsNetClosedErr(err) {
s.log.Printf("udp conn read udp packet fail , err: %s ", err)
}
return return
} }
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) cui.touchtime = time.Now().Unix()
_, err = conn.Write(body) go func() {
conn.SetDeadline(time.Time{}) cui.conn.SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
_, err = cui.conn.Write(utils.UDPPacket(cui.srcAddr.String(), buf[:n]))
cui.conn.SetWriteDeadline(time.Time{})
if err != nil { if err != nil {
s.log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err) cui.udpConn.Close()
return return
} }
//s.log.Printf("send udp packet to %s success", dstAddr.String()) }()
buf := make([]byte, 1024) // _, err = cui.conn.Write(utils.UDPPacket(cui.srcAddr.String(), buf[:n]))
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) // if err != nil {
length, _, err := conn.ReadFromUDP(buf) // s.log.Printf("send udp packet to bridge fail, err : %s", err)
conn.SetDeadline(time.Time{}) // return
if err != nil { // }
s.log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err) }
}()
}
func (s *MuxClient) UDPGCDeamon() {
gctime := int64(30)
go func() {
if s.isStop {
return return
} }
respBody := buf[0:length] timer := time.NewTicker(time.Second)
//s.log.Printf("revecived udp packet from %s , %v", dstAddr.String(), respBody) for {
bs := utils.UDPPacket(srcAddr, respBody) <-timer.C
(*inConn).SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) gcKeys := []string{}
_, err = (*inConn).Write(bs) s.udpConns.IterCb(func(key string, v interface{}) {
(*inConn).SetDeadline(time.Time{}) if time.Now().Unix()-v.(*ClientUDPConnItem).touchtime > gctime {
if err != nil { (*(v.(*ClientUDPConnItem).conn)).Close()
s.log.Printf("send udp response fail ,ERR:%s", err) (v.(*ClientUDPConnItem).udpConn).Close()
inConn.Close() gcKeys = append(gcKeys, key)
return s.log.Printf("gc udp conn %s", v.(*ClientUDPConnItem).connid)
} }
//s.log.Printf("send udp response success ,from:%s ,%d ,%v", dstAddr.String(), len(bs), bs) })
for _, k := range gcKeys {
s.udpConns.Remove(k)
}
gcKeys = nil
}
}()
} }
func (s *MuxClient) ServeConn(inConn *smux.Stream, localAddr, ID string) { func (s *MuxClient) ServeConn(inConn *smux.Stream, localAddr, ID string) {
var err error var err error

View File

@ -42,15 +42,20 @@ type MuxServerArgs struct {
Jumper *string Jumper *string
} }
type MuxUDPItem struct { type MuxUDPPacketItem struct {
packet *[]byte packet *[]byte
localAddr *net.UDPAddr localAddr *net.UDPAddr
srcAddr *net.UDPAddr srcAddr *net.UDPAddr
} }
type UDPConnItem struct {
conn *net.Conn
touchtime int64
srcAddr *net.UDPAddr
localAddr *net.UDPAddr
connid string
}
type MuxServerManager struct { type MuxServerManager struct {
cfg MuxServerArgs cfg MuxServerArgs
udpChn chan MuxUDPItem
serverID string serverID string
servers []*services.Service servers []*services.Service
log *logger.Logger log *logger.Logger
@ -59,7 +64,6 @@ type MuxServerManager struct {
func NewMuxServerManager() services.Service { func NewMuxServerManager() services.Service {
return &MuxServerManager{ return &MuxServerManager{
cfg: MuxServerArgs{}, cfg: MuxServerArgs{},
udpChn: make(chan MuxUDPItem, 50000),
serverID: utils.Uniqueid(), serverID: utils.Uniqueid(),
servers: []*services.Service{}, servers: []*services.Service{},
} }
@ -160,23 +164,24 @@ func (s *MuxServerManager) InitService() (err error) {
type MuxServer struct { type MuxServer struct {
cfg MuxServerArgs cfg MuxServerArgs
udpChn chan MuxUDPItem
sc utils.ServerChannel sc utils.ServerChannel
sessions utils.ConcurrentMap sessions utils.ConcurrentMap
lockChn chan bool lockChn chan bool
isStop bool isStop bool
udpConn *net.Conn
log *logger.Logger log *logger.Logger
jumper *jumper.Jumper jumper *jumper.Jumper
udpConns utils.ConcurrentMap
// writelock *sync.Mutex
} }
func NewMuxServer() services.Service { func NewMuxServer() services.Service {
return &MuxServer{ return &MuxServer{
cfg: MuxServerArgs{}, cfg: MuxServerArgs{},
udpChn: make(chan MuxUDPItem, 50000),
lockChn: make(chan bool, 1), lockChn: make(chan bool, 1),
sessions: utils.NewConcurrentMap(), sessions: utils.NewConcurrentMap(),
isStop: false, isStop: false,
udpConns: utils.NewConcurrentMap(),
// writelock: &sync.Mutex{},
} }
} }
@ -199,12 +204,9 @@ func (s *MuxServer) StopService() {
if s.sc.UDPListener != nil { if s.sc.UDPListener != nil {
(*s.sc.UDPListener).Close() (*s.sc.UDPListener).Close()
} }
if s.udpConn != nil {
(*s.udpConn).Close()
}
} }
func (s *MuxServer) InitService() (err error) { func (s *MuxServer) InitService() (err error) {
s.UDPConnDeamon() s.UDPGCDeamon()
return return
} }
func (s *MuxServer) CheckArgs() (err error) { func (s *MuxServer) CheckArgs() (err error) {
@ -242,11 +244,7 @@ func (s *MuxServer) Start(args interface{}, log *logger.Logger) (err error) {
s.sc = utils.NewServerChannel(host, p, s.log) s.sc = utils.NewServerChannel(host, p, s.log)
if *s.cfg.IsUDP { if *s.cfg.IsUDP {
err = s.sc.ListenUDP(func(packet []byte, localAddr, srcAddr *net.UDPAddr) { err = s.sc.ListenUDP(func(packet []byte, localAddr, srcAddr *net.UDPAddr) {
s.udpChn <- MuxUDPItem{ s.UDPSend(packet, localAddr, srcAddr)
packet: &packet,
localAddr: localAddr,
srcAddr: srcAddr,
}
}) })
if err != nil { if err != nil {
return return
@ -317,7 +315,9 @@ func (s *MuxServer) GetOutConn() (outConn net.Conn, ID string, err error) {
} }
outConn, err = s.GetConn(fmt.Sprintf("%d", i)) outConn, err = s.GetConn(fmt.Sprintf("%d", i))
if err != nil { if err != nil {
if !strings.Contains(err.Error(), "can not connect at same time") {
s.log.Printf("connection err: %s", err) s.log.Printf("connection err: %s", err)
}
return return
} }
remoteAddr := "tcp:" + *s.cfg.Remote remoteAddr := "tcp:" + *s.cfg.Remote
@ -424,87 +424,111 @@ func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
} }
return return
} }
func (s *MuxServer) UDPConnDeamon() { func (s *MuxServer) UDPGCDeamon() {
gctime := int64(30)
go func() { go func() {
defer func() { if s.isStop {
if err := recover(); err != nil { return
s.log.Printf("udp conn deamon crashed with err : %s \nstack: %s", err, string(debug.Stack())) }
timer := time.NewTicker(time.Second)
for {
<-timer.C
gcKeys := []string{}
s.udpConns.IterCb(func(key string, v interface{}) {
if time.Now().Unix()-v.(*UDPConnItem).touchtime > gctime {
(*(v.(*UDPConnItem).conn)).Close()
gcKeys = append(gcKeys, key)
s.log.Printf("gc udp conn %s", v.(*UDPConnItem).connid)
}
})
for _, k := range gcKeys {
s.udpConns.Remove(k)
}
gcKeys = nil
} }
}() }()
var outConn net.Conn }
var ID string func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
var err error var (
uc *UDPConnItem
key = srcAddr.String()
ID string
err error
outconn net.Conn
)
v, ok := s.udpConns.Get(key)
if !ok {
for { for {
if s.isStop { outconn, ID, err = s.GetOutConn()
return if err != nil && strings.Contains(err.Error(), "can not connect at same time") {
} time.Sleep(time.Millisecond * 500)
item := <-s.udpChn
RETRY:
if s.isStop {
return
}
if outConn == nil {
for {
if s.isStop {
return
}
outConn, ID, err = s.GetOutConn()
if err != nil {
outConn = nil
utils.CloseConn(&outConn)
s.log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err)
time.Sleep(time.Second * 3)
continue continue
} else { } else {
go func(outConn net.Conn, ID string) { break
if s.udpConn != nil {
(*s.udpConn).Close()
} }
s.udpConn = &outConn }
for { if err != nil {
if s.isStop { s.log.Printf("connect to %s fail, err: %s", *s.cfg.Parent, err)
return return
} }
outConn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) uc = &UDPConnItem{
srcAddrFromConn, body, err := utils.ReadUDPPacket(outConn) conn: &outconn,
outConn.SetDeadline(time.Time{}) srcAddr: srcAddr,
localAddr: localAddr,
connid: ID,
}
s.udpConns.Set(key, uc)
s.UDPRevecive(key, ID)
} else {
uc = v.(*UDPConnItem)
}
go func() {
defer func() {
if e := recover(); e != nil {
(*uc.conn).Close()
s.udpConns.Remove(key)
s.log.Printf("udp sender crashed with error : %s", e)
}
}()
uc.touchtime = time.Now().Unix()
(*uc.conn).SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
_, err = (*uc.conn).Write(utils.UDPPacket(srcAddr.String(), data))
(*uc.conn).SetWriteDeadline(time.Time{})
if err != nil { if err != nil {
s.log.Printf("parse revecived udp packet fail, err: %s ,%v", err, body) s.log.Printf("write udp packet to %s fail ,flush err:%s ", *s.cfg.Parent, err)
s.log.Printf("UDP deamon connection %s exited", ID) }
break }()
} }
//s.log.Printf("udp packet revecived over parent , local:%s", srcAddrFromConn) func (s *MuxServer) UDPRevecive(key, ID string) {
_srcAddr := strings.Split(srcAddrFromConn, ":") go func() {
if len(_srcAddr) != 2 { s.log.Printf("udp conn %s connected", ID)
s.log.Printf("parse revecived udp packet fail, addr error : %s", srcAddrFromConn) var uc *UDPConnItem
continue defer func() {
} if uc != nil {
port, _ := strconv.Atoi(_srcAddr[1]) (*uc.conn).Close()
dstAddr := &net.UDPAddr{IP: net.ParseIP(_srcAddr[0]), Port: port} }
s.sc.UDPListener.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout))) s.udpConns.Remove(key)
_, err = s.sc.UDPListener.WriteToUDP(body, dstAddr) s.log.Printf("udp conn %s released", ID)
s.sc.UDPListener.SetDeadline(time.Time{}) }()
if err != nil { v, ok := s.udpConns.Get(key)
s.log.Printf("udp response to local %s fail,ERR:%s", srcAddrFromConn, err) if !ok {
continue s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
} return
//s.log.Printf("udp response to local %s success , %v", srcAddrFromConn, body) }
} uc = v.(*UDPConnItem)
}(outConn, ID) for {
break _, body, err := utils.ReadUDPPacket(*uc.conn)
} if err != nil {
} if strings.Contains(err.Error(), "n != int(") {
} continue
outConn.SetWriteDeadline(time.Now().Add(time.Second)) }
_, err = outConn.Write(utils.UDPPacket(item.srcAddr.String(), *item.packet)) if err != io.EOF {
outConn.SetWriteDeadline(time.Time{}) s.log.Printf("udp conn read udp packet fail , err: %s ", err)
if err != nil { }
utils.CloseConn(&outConn) return
outConn = nil }
s.log.Printf("write udp packet to %s fail ,flush err:%s ,retrying...", *s.cfg.Parent, err) uc.touchtime = time.Now().Unix()
goto RETRY go s.sc.UDPListener.WriteToUDP(body, uc.srcAddr)
}
//s.log.Printf("write packet %v", *item.packet)
} }
}() }()
} }

View File

@ -39,6 +39,7 @@ func GetService(name string) *ServiceItem {
func Stop(name string) { func Stop(name string) {
if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil { if s, ok := servicesMap.Load(name); ok && s.(*ServiceItem).S != nil {
s.(*ServiceItem).S.Clean() s.(*ServiceItem).S.Clean()
servicesMap.Delete(name)
} }
} }
func Run(name string, args interface{}) (service *ServiceItem, err error) { func Run(name string, args interface{}) (service *ServiceItem, err error) {

View File

@ -345,7 +345,10 @@ func (s *SPS) OutToTCP(inConn *net.Conn) (err error) {
isHTTPS = true isHTTPS = true
pb.Write([]byte(fmt.Sprintf("CONNECT %s HTTP/1.1\r\n", address))) pb.Write([]byte(fmt.Sprintf("CONNECT %s HTTP/1.1\r\n", address)))
} }
pb.WriteString(fmt.Sprintf("Host: %s\r\n", address))
pb.WriteString(fmt.Sprintf("Proxy-Host: %s\r\n", address))
pb.WriteString("Proxy-Connection: Keep-Alive\r\n") pb.WriteString("Proxy-Connection: Keep-Alive\r\n")
pb.WriteString("Connection: Keep-Alive\r\n")
u := "" u := ""
if *s.cfg.ParentAuth != "" { if *s.cfg.ParentAuth != "" {

View File

@ -585,6 +585,26 @@ func RemoveProxyHeaders(head []byte) []byte {
func InsertProxyHeaders(head []byte, headers string) []byte { func InsertProxyHeaders(head []byte, headers string) []byte {
return bytes.Replace(head, []byte("\r\n"), []byte("\r\n"+headers), 1) return bytes.Replace(head, []byte("\r\n"), []byte("\r\n"+headers), 1)
} }
func IsNetClosedErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "use of closed network connection")
}
func IsNetTimeoutErr(err error) bool {
if err == nil {
return false
}
e, ok := err.(net.Error)
return ok && e.Timeout()
}
func IsNetDeadlineErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "i/o deadline reached")
}
func IsNetRefusedErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "connection refused")
}
func IsNetSocketNotConnectedErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "socket is not connected")
}
// type sockaddr struct { // type sockaddr struct {
// family uint16 // family uint16

View File

@ -51,7 +51,10 @@ func (j *Jumper) dialHTTPS(address string, timeout time.Duration) (conn net.Conn
} }
pb := new(bytes.Buffer) pb := new(bytes.Buffer)
pb.Write([]byte(fmt.Sprintf("CONNECT %s HTTP/1.1\r\n", address))) pb.Write([]byte(fmt.Sprintf("CONNECT %s HTTP/1.1\r\n", address)))
pb.WriteString(fmt.Sprintf("Host: %s\r\n", address))
pb.WriteString(fmt.Sprintf("Proxy-Host: %s\r\n", address))
pb.WriteString("Proxy-Connection: Keep-Alive\r\n") pb.WriteString("Proxy-Connection: Keep-Alive\r\n")
pb.WriteString("Connection: Keep-Alive\r\n")
if j.proxyURL.User != nil { if j.proxyURL.User != nil {
p, _ := j.proxyURL.User.Password() p, _ := j.proxyURL.User.Password()
u := fmt.Sprintf("%s:%s", j.proxyURL.User.Username(), p) u := fmt.Sprintf("%s:%s", j.proxyURL.User.Username(), p)