optimise tunnel nat udp module
This commit is contained in:
@ -36,6 +36,7 @@ type MuxClientArgs struct {
|
|||||||
}
|
}
|
||||||
type ClientUDPConnItem struct {
|
type ClientUDPConnItem struct {
|
||||||
conn *smux.Stream
|
conn *smux.Stream
|
||||||
|
isActive bool
|
||||||
touchtime int64
|
touchtime int64
|
||||||
srcAddr *net.UDPAddr
|
srcAddr *net.UDPAddr
|
||||||
localAddr *net.UDPAddr
|
localAddr *net.UDPAddr
|
||||||
@ -292,11 +293,6 @@ func (s *MuxClient) ServeUDP(inConn *smux.Stream, localAddr, ID string) {
|
|||||||
}
|
}
|
||||||
(*item).touchtime = time.Now().Unix()
|
(*item).touchtime = time.Now().Unix()
|
||||||
go (*item).udpConn.Write(body)
|
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) UDPRevecive(key, ID string) {
|
func (s *MuxClient) UDPRevecive(key, ID string) {
|
||||||
@ -334,16 +330,11 @@ func (s *MuxClient) UDPRevecive(key, ID string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// _, err = cui.conn.Write(utils.UDPPacket(cui.srcAddr.String(), buf[:n]))
|
|
||||||
// if err != nil {
|
|
||||||
// s.log.Printf("send udp packet to bridge fail, err : %s", err)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
func (s *MuxClient) UDPGCDeamon() {
|
func (s *MuxClient) UDPGCDeamon() {
|
||||||
gctime := int64(60)
|
gctime := int64(30)
|
||||||
go func() {
|
go func() {
|
||||||
if s.isStop {
|
if s.isStop {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -173,6 +173,7 @@ func NewMuxServer() services.Service {
|
|||||||
lockChn: make(chan bool, 1),
|
lockChn: make(chan bool, 1),
|
||||||
sessions: mapx.NewConcurrentMap(),
|
sessions: mapx.NewConcurrentMap(),
|
||||||
isStop: false,
|
isStop: false,
|
||||||
|
udpConns: mapx.NewConcurrentMap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +182,7 @@ type MuxUDPPacketItem struct {
|
|||||||
localAddr *net.UDPAddr
|
localAddr *net.UDPAddr
|
||||||
srcAddr *net.UDPAddr
|
srcAddr *net.UDPAddr
|
||||||
}
|
}
|
||||||
type UDPConnItem struct {
|
type MuxUDPConnItem struct {
|
||||||
conn *net.Conn
|
conn *net.Conn
|
||||||
touchtime int64
|
touchtime int64
|
||||||
srcAddr *net.UDPAddr
|
srcAddr *net.UDPAddr
|
||||||
@ -429,7 +430,7 @@ func (s *MuxServer) getParentConn() (conn net.Conn, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *MuxServer) UDPGCDeamon() {
|
func (s *MuxServer) UDPGCDeamon() {
|
||||||
gctime := int64(60)
|
gctime := int64(30)
|
||||||
go func() {
|
go func() {
|
||||||
if s.isStop {
|
if s.isStop {
|
||||||
return
|
return
|
||||||
@ -439,10 +440,10 @@ func (s *MuxServer) UDPGCDeamon() {
|
|||||||
<-timer.C
|
<-timer.C
|
||||||
gcKeys := []string{}
|
gcKeys := []string{}
|
||||||
s.udpConns.IterCb(func(key string, v interface{}) {
|
s.udpConns.IterCb(func(key string, v interface{}) {
|
||||||
if time.Now().Unix()-v.(*UDPConnItem).touchtime > gctime {
|
if time.Now().Unix()-v.(*MuxUDPConnItem).touchtime > gctime {
|
||||||
(*(v.(*UDPConnItem).conn)).Close()
|
(*(v.(*MuxUDPConnItem).conn)).Close()
|
||||||
gcKeys = append(gcKeys, key)
|
gcKeys = append(gcKeys, key)
|
||||||
s.log.Printf("gc udp conn %s", v.(*UDPConnItem).connid)
|
s.log.Printf("gc udp conn %s", v.(*MuxUDPConnItem).connid)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
for _, k := range gcKeys {
|
for _, k := range gcKeys {
|
||||||
@ -454,7 +455,7 @@ func (s *MuxServer) UDPGCDeamon() {
|
|||||||
}
|
}
|
||||||
func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
|
func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||||
var (
|
var (
|
||||||
uc *UDPConnItem
|
uc *MuxUDPConnItem
|
||||||
key = srcAddr.String()
|
key = srcAddr.String()
|
||||||
ID string
|
ID string
|
||||||
err error
|
err error
|
||||||
@ -475,7 +476,7 @@ func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
|
|||||||
s.log.Printf("connect to %s fail, err: %s", *s.cfg.Parent, err)
|
s.log.Printf("connect to %s fail, err: %s", *s.cfg.Parent, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
uc = &UDPConnItem{
|
uc = &MuxUDPConnItem{
|
||||||
conn: &outconn,
|
conn: &outconn,
|
||||||
srcAddr: srcAddr,
|
srcAddr: srcAddr,
|
||||||
localAddr: localAddr,
|
localAddr: localAddr,
|
||||||
@ -484,7 +485,7 @@ func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
|
|||||||
s.udpConns.Set(key, uc)
|
s.udpConns.Set(key, uc)
|
||||||
s.UDPRevecive(key, ID)
|
s.UDPRevecive(key, ID)
|
||||||
} else {
|
} else {
|
||||||
uc = v.(*UDPConnItem)
|
uc = v.(*MuxUDPConnItem)
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -506,7 +507,7 @@ func (s *MuxServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
|
|||||||
func (s *MuxServer) UDPRevecive(key, ID string) {
|
func (s *MuxServer) UDPRevecive(key, ID string) {
|
||||||
go func() {
|
go func() {
|
||||||
s.log.Printf("udp conn %s connected", ID)
|
s.log.Printf("udp conn %s connected", ID)
|
||||||
var uc *UDPConnItem
|
var uc *MuxUDPConnItem
|
||||||
defer func() {
|
defer func() {
|
||||||
if uc != nil {
|
if uc != nil {
|
||||||
(*uc.conn).Close()
|
(*uc.conn).Close()
|
||||||
@ -519,7 +520,7 @@ func (s *MuxServer) UDPRevecive(key, ID string) {
|
|||||||
s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
|
s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
uc = v.(*UDPConnItem)
|
uc = v.(*MuxUDPConnItem)
|
||||||
for {
|
for {
|
||||||
_, body, err := utils.ReadUDPPacket(*uc.conn)
|
_, body, err := utils.ReadUDPPacket(*uc.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -141,6 +141,7 @@ func (s *TunnelBridge) callback(inConn net.Conn) {
|
|||||||
var buf = make([]byte, 1024)
|
var buf = make([]byte, 1024)
|
||||||
n, _ := inConn.Read(buf)
|
n, _ := inConn.Read(buf)
|
||||||
reader := bytes.NewReader(buf[:n])
|
reader := bytes.NewReader(buf[:n])
|
||||||
|
|
||||||
//reader := bufio.NewReader(inConn)
|
//reader := bufio.NewReader(inConn)
|
||||||
|
|
||||||
var connType uint8
|
var connType uint8
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
logger "log"
|
logger "log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/snail007/goproxy/services"
|
"github.com/snail007/goproxy/services"
|
||||||
@ -28,6 +29,15 @@ type TunnelClientArgs struct {
|
|||||||
Timeout *int
|
Timeout *int
|
||||||
Jumper *string
|
Jumper *string
|
||||||
}
|
}
|
||||||
|
type ClientUDPConnItem struct {
|
||||||
|
conn *net.Conn
|
||||||
|
isActive bool
|
||||||
|
touchtime int64
|
||||||
|
srcAddr *net.UDPAddr
|
||||||
|
localAddr *net.UDPAddr
|
||||||
|
udpConn *net.UDPConn
|
||||||
|
connid string
|
||||||
|
}
|
||||||
type TunnelClient struct {
|
type TunnelClient struct {
|
||||||
cfg TunnelClientArgs
|
cfg TunnelClientArgs
|
||||||
ctrlConn net.Conn
|
ctrlConn net.Conn
|
||||||
@ -35,6 +45,7 @@ type TunnelClient struct {
|
|||||||
userConns mapx.ConcurrentMap
|
userConns mapx.ConcurrentMap
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
jumper *jumper.Jumper
|
jumper *jumper.Jumper
|
||||||
|
udpConns mapx.ConcurrentMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTunnelClient() services.Service {
|
func NewTunnelClient() services.Service {
|
||||||
@ -42,10 +53,12 @@ func NewTunnelClient() services.Service {
|
|||||||
cfg: TunnelClientArgs{},
|
cfg: TunnelClientArgs{},
|
||||||
userConns: mapx.NewConcurrentMap(),
|
userConns: mapx.NewConcurrentMap(),
|
||||||
isStop: false,
|
isStop: false,
|
||||||
|
udpConns: mapx.NewConcurrentMap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TunnelClient) InitService() (err error) {
|
func (s *TunnelClient) InitService() (err error) {
|
||||||
|
s.UDPGCDeamon()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +146,7 @@ func (s *TunnelClient) Start(args interface{}, log *logger.Logger) (err error) {
|
|||||||
s.log.Printf("read connection signal err: %s, retrying...", err)
|
s.log.Printf("read connection signal err: %s, retrying...", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s.log.Printf("signal revecived:%s %s %s", serverID, ID, clientLocalAddr)
|
//s.log.Printf("signal revecived:%s %s %s", serverID, ID, clientLocalAddr)
|
||||||
protocol := clientLocalAddr[:3]
|
protocol := clientLocalAddr[:3]
|
||||||
localAddr := clientLocalAddr[4:]
|
localAddr := clientLocalAddr[4:]
|
||||||
if protocol == "udp" {
|
if protocol == "udp" {
|
||||||
@ -240,62 +253,119 @@ func (s *TunnelClient) ServeUDP(localAddr, ID, serverID string) {
|
|||||||
}
|
}
|
||||||
// s.cm.Add(*s.cfg.Key, ID, &inConn)
|
// s.cm.Add(*s.cfg.Key, ID, &inConn)
|
||||||
s.log.Printf("conn %s created", ID)
|
s.log.Printf("conn %s created", ID)
|
||||||
|
var item *ClientUDPConnItem
|
||||||
|
var body []byte
|
||||||
|
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
|
||||||
}
|
}
|
||||||
srcAddr, body, err := utils.ReadUDPPacket(inConn)
|
srcAddr, body, err = utils.ReadUDPPacket(inConn)
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
if err != nil {
|
||||||
s.log.Printf("connection %s released", ID)
|
if strings.Contains(err.Error(), "n != int(") {
|
||||||
utils.CloseConn(&inConn)
|
continue
|
||||||
break
|
}
|
||||||
} else if err != nil {
|
if !utils.IsNetDeadlineErr(err) && err != io.EOF {
|
||||||
s.log.Printf("udp packet revecived fail, err: %s", err)
|
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()
|
||||||
|
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 s.processUDPPacket(&inConn, srcAddr, localAddr, body)
|
|
||||||
}
|
}
|
||||||
|
(*item).touchtime = time.Now().Unix()
|
||||||
|
go (*item).udpConn.Write(body)
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
func (s *TunnelClient) processUDPPacket(inConn *net.Conn, srcAddr, localAddr string, body []byte) {
|
func (s *TunnelClient) UDPRevecive(key, ID string) {
|
||||||
dstAddr, err := net.ResolveUDPAddr("udp", localAddr)
|
go func() {
|
||||||
if err != nil {
|
s.log.Printf("udp conn %s connected", ID)
|
||||||
s.log.Printf("can't resolve address: %s", err)
|
v, ok := s.udpConns.Get(key)
|
||||||
utils.CloseConn(inConn)
|
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() {
|
||||||
|
(*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)
|
}
|
||||||
length, _, err := conn.ReadFromUDP(buf)
|
}()
|
||||||
if err != nil {
|
}
|
||||||
s.log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err)
|
func (s *TunnelClient) 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
|
||||||
_, err = (*inConn).Write(bs)
|
gcKeys := []string{}
|
||||||
if err != nil {
|
s.udpConns.IterCb(func(key string, v interface{}) {
|
||||||
s.log.Printf("send udp response fail ,ERR:%s", err)
|
if time.Now().Unix()-v.(*ClientUDPConnItem).touchtime > gctime {
|
||||||
utils.CloseConn(inConn)
|
(*(v.(*ClientUDPConnItem).conn)).Close()
|
||||||
return
|
(v.(*ClientUDPConnItem).udpConn).Close()
|
||||||
|
gcKeys = append(gcKeys, key)
|
||||||
|
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 *TunnelClient) ServeConn(localAddr, ID, serverID string) {
|
func (s *TunnelClient) ServeConn(localAddr, ID, serverID string) {
|
||||||
var inConn, outConn net.Conn
|
var inConn, outConn net.Conn
|
||||||
|
|||||||
@ -38,18 +38,17 @@ type TunnelServerArgs struct {
|
|||||||
}
|
}
|
||||||
type TunnelServer struct {
|
type TunnelServer struct {
|
||||||
cfg TunnelServerArgs
|
cfg TunnelServerArgs
|
||||||
udpChn chan UDPItem
|
|
||||||
sc utils.ServerChannel
|
sc utils.ServerChannel
|
||||||
isStop bool
|
isStop bool
|
||||||
udpConn *net.Conn
|
udpConn *net.Conn
|
||||||
userConns mapx.ConcurrentMap
|
userConns mapx.ConcurrentMap
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
jumper *jumper.Jumper
|
jumper *jumper.Jumper
|
||||||
|
udpConns mapx.ConcurrentMap
|
||||||
}
|
}
|
||||||
|
|
||||||
type TunnelServerManager struct {
|
type TunnelServerManager struct {
|
||||||
cfg TunnelServerArgs
|
cfg TunnelServerArgs
|
||||||
udpChn chan UDPItem
|
|
||||||
serverID string
|
serverID string
|
||||||
servers []*services.Service
|
servers []*services.Service
|
||||||
log *logger.Logger
|
log *logger.Logger
|
||||||
@ -58,7 +57,6 @@ type TunnelServerManager struct {
|
|||||||
func NewTunnelServerManager() services.Service {
|
func NewTunnelServerManager() services.Service {
|
||||||
return &TunnelServerManager{
|
return &TunnelServerManager{
|
||||||
cfg: TunnelServerArgs{},
|
cfg: TunnelServerArgs{},
|
||||||
udpChn: make(chan UDPItem, 50000),
|
|
||||||
serverID: utils.Uniqueid(),
|
serverID: utils.Uniqueid(),
|
||||||
servers: []*services.Service{},
|
servers: []*services.Service{},
|
||||||
}
|
}
|
||||||
@ -146,17 +144,25 @@ func (s *TunnelServerManager) InitService() (err error) {
|
|||||||
func NewTunnelServer() services.Service {
|
func NewTunnelServer() services.Service {
|
||||||
return &TunnelServer{
|
return &TunnelServer{
|
||||||
cfg: TunnelServerArgs{},
|
cfg: TunnelServerArgs{},
|
||||||
udpChn: make(chan UDPItem, 50000),
|
|
||||||
isStop: false,
|
isStop: false,
|
||||||
userConns: mapx.NewConcurrentMap(),
|
userConns: mapx.NewConcurrentMap(),
|
||||||
|
udpConns: mapx.NewConcurrentMap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type UDPItem struct {
|
type TunnelUDPPacketItem struct {
|
||||||
packet *[]byte
|
packet *[]byte
|
||||||
localAddr *net.UDPAddr
|
localAddr *net.UDPAddr
|
||||||
srcAddr *net.UDPAddr
|
srcAddr *net.UDPAddr
|
||||||
}
|
}
|
||||||
|
type TunnelUDPConnItem struct {
|
||||||
|
conn *net.Conn
|
||||||
|
isActive bool
|
||||||
|
touchtime int64
|
||||||
|
srcAddr *net.UDPAddr
|
||||||
|
localAddr *net.UDPAddr
|
||||||
|
connid string
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TunnelServer) StopService() {
|
func (s *TunnelServer) StopService() {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -183,7 +189,7 @@ func (s *TunnelServer) StopService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (s *TunnelServer) InitService() (err error) {
|
func (s *TunnelServer) InitService() (err error) {
|
||||||
s.UDPConnDeamon()
|
s.UDPGCDeamon()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *TunnelServer) CheckArgs() (err error) {
|
func (s *TunnelServer) CheckArgs() (err error) {
|
||||||
@ -217,11 +223,7 @@ func (s *TunnelServer) 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(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr) {
|
err = s.sc.ListenUDP(func(listener *net.UDPConn, packet []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||||
s.udpChn <- UDPItem{
|
s.UDPSend(packet, localAddr, srcAddr)
|
||||||
packet: &packet,
|
|
||||||
localAddr: localAddr,
|
|
||||||
srcAddr: srcAddr,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -348,89 +350,103 @@ func (s *TunnelServer) GetConn() (conn net.Conn, err error) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *TunnelServer) UDPConnDeamon() {
|
func (s *TunnelServer) UDPGCDeamon() {
|
||||||
|
gctime := int64(30)
|
||||||
|
go func() {
|
||||||
|
if s.isStop {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
timer := time.NewTicker(time.Second)
|
||||||
|
for {
|
||||||
|
<-timer.C
|
||||||
|
gcKeys := []string{}
|
||||||
|
s.udpConns.IterCb(func(key string, v interface{}) {
|
||||||
|
if time.Now().Unix()-v.(*TunnelUDPConnItem).touchtime > gctime {
|
||||||
|
(*(v.(*TunnelUDPConnItem).conn)).Close()
|
||||||
|
gcKeys = append(gcKeys, key)
|
||||||
|
s.log.Printf("gc udp conn %s", v.(*TunnelUDPConnItem).connid)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
for _, k := range gcKeys {
|
||||||
|
s.udpConns.Remove(k)
|
||||||
|
}
|
||||||
|
gcKeys = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
func (s *TunnelServer) UDPSend(data []byte, localAddr, srcAddr *net.UDPAddr) {
|
||||||
|
var (
|
||||||
|
uc *TunnelUDPConnItem
|
||||||
|
key = srcAddr.String()
|
||||||
|
ID string
|
||||||
|
err error
|
||||||
|
outconn net.Conn
|
||||||
|
)
|
||||||
|
v, ok := s.udpConns.Get(key)
|
||||||
|
if !ok {
|
||||||
|
outconn, ID, err = s.GetOutConn(CONN_SERVER)
|
||||||
|
if err != nil {
|
||||||
|
s.log.Printf("connect to %s fail, err: %s", *s.cfg.Parent, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uc = &TunnelUDPConnItem{
|
||||||
|
conn: &outconn,
|
||||||
|
srcAddr: srcAddr,
|
||||||
|
localAddr: localAddr,
|
||||||
|
connid: ID,
|
||||||
|
}
|
||||||
|
s.udpConns.Set(key, uc)
|
||||||
|
s.UDPRevecive(key, ID)
|
||||||
|
} else {
|
||||||
|
uc = v.(*TunnelUDPConnItem)
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if e := recover(); e != nil {
|
||||||
s.log.Printf("udp conn deamon crashed with err : %s \nstack: %s", err, string(debug.Stack()))
|
(*uc.conn).Close()
|
||||||
|
s.udpConns.Remove(key)
|
||||||
|
s.log.Printf("udp sender crashed with error : %s", e)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var outConn net.Conn
|
uc.touchtime = time.Now().Unix()
|
||||||
// var hb utils.HeartbeatReadWriter
|
(*uc.conn).SetWriteDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
|
||||||
var ID string
|
_, err = (*uc.conn).Write(utils.UDPPacket(srcAddr.String(), data))
|
||||||
// var cmdChn = make(chan bool, 1000)
|
(*uc.conn).SetWriteDeadline(time.Time{})
|
||||||
var err error
|
|
||||||
for {
|
|
||||||
if s.isStop {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
item := <-s.udpChn
|
|
||||||
RETRY:
|
|
||||||
if s.isStop {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if outConn == nil {
|
|
||||||
for {
|
|
||||||
if s.isStop {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
outConn, ID, err = s.GetOutConn(CONN_SERVER)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// cmdChn <- true
|
s.log.Printf("write udp packet to %s fail ,flush err:%s ", *s.cfg.Parent, err)
|
||||||
outConn = nil
|
}
|
||||||
utils.CloseConn(&outConn)
|
}()
|
||||||
s.log.Printf("connect to %s fail, err: %s, retrying...", *s.cfg.Parent, err)
|
}
|
||||||
time.Sleep(time.Second * 3)
|
func (s *TunnelServer) UDPRevecive(key, ID string) {
|
||||||
continue
|
go func() {
|
||||||
} else {
|
s.log.Printf("udp conn %s connected", ID)
|
||||||
go func(outConn net.Conn, ID string) {
|
var uc *TunnelUDPConnItem
|
||||||
if s.udpConn != nil {
|
defer func() {
|
||||||
(*s.udpConn).Close()
|
if uc != nil {
|
||||||
}
|
(*uc.conn).Close()
|
||||||
s.udpConn = &outConn
|
}
|
||||||
for {
|
s.udpConns.Remove(key)
|
||||||
if s.isStop {
|
s.log.Printf("udp conn %s released", ID)
|
||||||
return
|
}()
|
||||||
}
|
v, ok := s.udpConns.Get(key)
|
||||||
srcAddrFromConn, body, err := utils.ReadUDPPacket(outConn)
|
if !ok {
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
s.log.Printf("[warn] udp conn not exists for %s, connid : %s", key, ID)
|
||||||
s.log.Printf("UDP deamon connection %s exited", ID)
|
return
|
||||||
break
|
}
|
||||||
}
|
uc = v.(*TunnelUDPConnItem)
|
||||||
if err != nil {
|
for {
|
||||||
s.log.Printf("parse revecived udp packet fail, err: %s ,%v", err, body)
|
_, body, err := utils.ReadUDPPacket(*uc.conn)
|
||||||
continue
|
if err != nil {
|
||||||
}
|
if strings.Contains(err.Error(), "n != int(") {
|
||||||
//s.log.Printf("udp packet revecived over parent , local:%s", srcAddrFromConn)
|
continue
|
||||||
_srcAddr := strings.Split(srcAddrFromConn, ":")
|
}
|
||||||
if len(_srcAddr) != 2 {
|
if err != io.EOF {
|
||||||
s.log.Printf("parse revecived udp packet fail, addr error : %s", srcAddrFromConn)
|
s.log.Printf("udp conn read udp packet fail , err: %s ", err)
|
||||||
continue
|
}
|
||||||
}
|
return
|
||||||
port, _ := strconv.Atoi(_srcAddr[1])
|
}
|
||||||
dstAddr := &net.UDPAddr{IP: net.ParseIP(_srcAddr[0]), Port: port}
|
uc.touchtime = time.Now().Unix()
|
||||||
_, err = s.sc.UDPListener.WriteToUDP(body, dstAddr)
|
go s.sc.UDPListener.WriteToUDP(body, uc.srcAddr)
|
||||||
if err != nil {
|
|
||||||
s.log.Printf("udp response to local %s fail,ERR:%s", srcAddrFromConn, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
//s.log.Printf("udp response to local %s success , %v", srcAddrFromConn, body)
|
|
||||||
}
|
|
||||||
}(outConn, ID)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outConn.SetWriteDeadline(time.Now().Add(time.Second))
|
|
||||||
_, err = outConn.Write(utils.UDPPacket(item.srcAddr.String(), *item.packet))
|
|
||||||
outConn.SetWriteDeadline(time.Time{})
|
|
||||||
if err != nil {
|
|
||||||
utils.CloseConn(&outConn)
|
|
||||||
outConn = nil
|
|
||||||
s.log.Printf("write udp packet to %s fail ,flush err:%s ,retrying...", *s.cfg.Parent, err)
|
|
||||||
goto RETRY
|
|
||||||
}
|
|
||||||
//s.log.Printf("write packet %v", *item.packet)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -577,7 +577,7 @@ func BuildPacket(packetType uint8, data ...string) []byte {
|
|||||||
binary.Write(pkg, binary.LittleEndian, packetType)
|
binary.Write(pkg, binary.LittleEndian, packetType)
|
||||||
for _, d := range data {
|
for _, d := range data {
|
||||||
bytes := []byte(d)
|
bytes := []byte(d)
|
||||||
binary.Write(pkg, binary.LittleEndian, uint16(len(bytes)))
|
binary.Write(pkg, binary.LittleEndian, uint64(len(bytes)))
|
||||||
binary.Write(pkg, binary.LittleEndian, bytes)
|
binary.Write(pkg, binary.LittleEndian, bytes)
|
||||||
}
|
}
|
||||||
return pkg.Bytes()
|
return pkg.Bytes()
|
||||||
|
|||||||
Reference in New Issue
Block a user