Commit ca8bf906 authored by wei.xuan's avatar wei.xuan

Merge branch '1112' into 'master'

1112

See merge request !9
parents 76aca1d4 7aeb66e2
...@@ -9,4 +9,5 @@ release ...@@ -9,4 +9,5 @@ release
./majora ./majora
*.log *.log
majora.log majora.log
std.log std.log
\ No newline at end of file majora
\ No newline at end of file
...@@ -6,8 +6,9 @@ DATE=$(shell date +"%Y-%m-%d") ...@@ -6,8 +6,9 @@ DATE=$(shell date +"%Y-%m-%d")
BUILDINFO := -X main.Version=latest -X main.Date=$(DATE) BUILDINFO := -X main.Version=latest -X main.Date=$(DATE)
all: all:
env CGO_ENABLED=0 go build -trimpath -ldflags '-w -s $(BUILDINFO)' -o bin/majora env CGO_ENABLED=0 go build -trimpath -ldflags '-w -s $(BUILDINFO)' -o majora
clean: clean:
rm -fr majora-go rm -fr majora-go
rm -fr majora rm -fr majora
\ No newline at end of file rm -fr output
\ No newline at end of file
...@@ -5,33 +5,32 @@ import ( ...@@ -5,33 +5,32 @@ import (
"encoding/json" "encoding/json"
"flag" "flag"
"fmt" "fmt"
"log"
"math/rand" "math/rand"
"net" "net"
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
"os/exec"
"os/signal" "os/signal"
"runtime" "runtime"
"runtime/debug"
"syscall" "syscall"
"time" "time"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/client" "virjar.com/majora-go/client"
"virjar.com/majora-go/common" "virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/model" "virjar.com/majora-go/model"
) )
var ( var (
configure string configure string
logLevel int logLevel int
pprofPort int pprofPort int
natServer string natServer string
account string account string
dnsServer string dnsServer string
localAddr string localAddr string
disableUpdate bool daemon bool
) )
var ( var (
...@@ -39,6 +38,10 @@ var ( ...@@ -39,6 +38,10 @@ var (
Date string Date string
) )
var (
cmd *exec.Cmd
)
func init() { func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
flag.StringVar(&configure, "conf", "", "./majora -c path/to/your/majora.ini") flag.StringVar(&configure, "conf", "", "./majora -c path/to/your/majora.ini")
...@@ -48,21 +51,18 @@ func init() { ...@@ -48,21 +51,18 @@ func init() {
flag.StringVar(&account, "account", "unknown", "account") flag.StringVar(&account, "account", "unknown", "account")
flag.StringVar(&dnsServer, "dnsServer", common.DNSServer, "custom dns server") flag.StringVar(&dnsServer, "dnsServer", common.DNSServer, "custom dns server")
flag.StringVar(&localAddr, "localIp", "", "bind local ip") flag.StringVar(&localAddr, "localIp", "", "bind local ip")
flag.BoolVar(&disableUpdate, "disableUpdate", false, "disable self update") flag.BoolVar(&daemon, "daemon", false, "daemon")
flag.Parse() flag.Parse()
} }
func initial(cfg *model.Configure) { func initial(cfg *model.Configure) {
if cfg.LogLevel > 0 { log.Init(cfg.LogLevel - 1)
_ = getty.SetLoggerLevel(getty.LoggerLevel(cfg.LogLevel - 1))
_ = getty.Online(cfg.LogPath)
}
if cfg.PprofPort > 0 { if cfg.PprofPort > 0 {
go func() { go func() {
addr := fmt.Sprintf("127.0.0.1:%d", cfg.PprofPort) addr := fmt.Sprintf("127.0.0.1:%d", cfg.PprofPort)
getty.GetLogger().Infof("enable pprof: %s", addr) log.Run().Infof("enable pprof: %s", addr)
log.Fatal(http.ListenAndServe(addr, nil)) log.Run().Error(http.ListenAndServe(addr, nil))
}() }()
} }
...@@ -73,7 +73,6 @@ func initial(cfg *model.Configure) { ...@@ -73,7 +73,6 @@ func initial(cfg *model.Configure) {
return net.Dial("udp", dnsServer) return net.Dial("udp", dnsServer)
}, },
} }
getty.GetLogger().Infof("use custom dns server %s", dnsServer)
} }
} }
...@@ -82,28 +81,36 @@ func parseFromCmd(cfg *model.Configure) { ...@@ -82,28 +81,36 @@ func parseFromCmd(cfg *model.Configure) {
cfg.LogLevel = logLevel cfg.LogLevel = logLevel
cfg.DNSServer = dnsServer cfg.DNSServer = dnsServer
cfg.LocalAddr = localAddr cfg.LocalAddr = localAddr
cfg.DisableUpdate = disableUpdate
// 先兼容吧 // 先兼容吧
cfg.Extra.Account = account cfg.Extra.Account = account
cfg.PprofPort = pprofPort cfg.PprofPort = pprofPort
} }
func cli() { func cli(cfg *model.Configure) {
defer func() {
if err := recover(); err != nil {
log.Run().Errorf("cli panic %+v", err)
}
}()
log.Run().Infof("cpu count %d proc %d", runtime.NumCPU(), runtime.NumCPU()*2)
log.Run().Infof("current Version %s, build at %s", Version, Date)
log.Run().Infof("hostinfo os:%s, arch:%s", runtime.GOOS, runtime.GOARCH)
cfgInfo, _ := json.Marshal(cfg)
log.Run().Infof("config info:%s", string(cfgInfo))
client.NewClientWithConf(cfg)
}
func initConf() *model.Configure {
cfg := model.NewDefMajoraConf() cfg := model.NewDefMajoraConf()
if len(configure) > 0 { if len(configure) > 0 {
cfg = model.InitConf(configure) cfg = model.InitConf(configure)
} else { } else {
parseFromCmd(cfg) parseFromCmd(cfg)
} }
//runtime.GOMAXPROCS(runtime.NumCPU() * 2)
//debug.SetGCPercent(200)
initial(cfg) initial(cfg)
runtime.GOMAXPROCS(runtime.NumCPU() * 2) return cfg
debug.SetGCPercent(200)
getty.GetLogger().Warnf("cpu count %d proc %d", runtime.NumCPU(), runtime.NumCPU()*2)
getty.GetLogger().Warnf("current Version %s, build at %s", Version, Date)
getty.GetLogger().Warnf("hostinfo os:%s, arch:%s", runtime.GOOS, runtime.GOARCH)
cfgInfo, _ := json.Marshal(cfg)
getty.GetLogger().Warnf("config info:%s", string(cfgInfo))
client.NewClientWithConf(cfg)
} }
//main start //main start
...@@ -112,15 +119,29 @@ func main() { ...@@ -112,15 +119,29 @@ func main() {
fmt.Println(Version) fmt.Println(Version)
os.Exit(0) os.Exit(0)
} }
sigs := make(chan os.Signal, 1) cfg := initConf()
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) if daemon {
var args []string
for _, arg := range os.Args[1:] {
if arg != "-daemon" {
args = append(args, arg)
}
}
cmd = exec.Command(os.Args[0], args...)
cmd.Env = os.Environ()
if err := cmd.Start(); err != nil {
panic(err)
}
log.Run().Infof("%s [pid-%d] running...\n", os.Args[0], cmd.Process.Pid)
os.Exit(0)
}
go func() { signalChan := make(chan os.Signal, 1)
cli() signal.Notify(signalChan, os.Interrupt, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
}() cli(cfg)
select { select {
case <-sigs: case <-signalChan:
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
getty.GetLogger().Warn("main process exit...") log.Run().Warn("main process exit...")
} }
} }
...@@ -3,8 +3,11 @@ package client ...@@ -3,8 +3,11 @@ package client
import ( import (
"net" "net"
"sync" "sync"
"time"
"github.com/adamweixuan/getty" "github.com/adamweixuan/getty"
"virjar.com/majora-go/infra"
"virjar.com/majora-go/log"
"virjar.com/majora-go/model" "virjar.com/majora-go/model"
) )
...@@ -17,8 +20,7 @@ type Client struct { ...@@ -17,8 +20,7 @@ type Client struct {
} }
func NewClientWithConf(cfg *model.Configure) { func NewClientWithConf(cfg *model.Configure) {
client := NewCli(cfg) NewCli(cfg).StartUp()
client.StartUp()
} }
func NewCli(cfg *model.Configure) *Client { func NewCli(cfg *model.Configure) *Client {
...@@ -39,5 +41,38 @@ func NewCli(cfg *model.Configure) *Client { ...@@ -39,5 +41,38 @@ func NewCli(cfg *model.Configure) *Client {
} }
func (client *Client) StartUp() { func (client *Client) StartUp() {
client.check()
client.connect() client.connect()
} }
func (client *Client) check() {
cfg := client.config
if !cfg.Redial.Valid() {
return
}
interval := cfg.NetCheckInterval
if interval <= 0 {
interval = time.Second * 5
}
url := infra.RandUrl()
if len(cfg.NetCheckUrl) > 0 {
url = cfg.NetCheckUrl
}
go func() {
var timer = time.NewTimer(interval)
for {
timer.Reset(interval)
<-timer.C
success := infra.Ping(url)
if success {
continue
}
log.Run().Warnf("net check fail, redial...")
infra.RedialByCheck(cfg)
}
}()
}
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"github.com/adamweixuan/getty" "github.com/adamweixuan/getty"
"virjar.com/majora-go/common" "virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/protocol" "virjar.com/majora-go/protocol"
) )
...@@ -17,16 +18,16 @@ type PacketCodec struct { ...@@ -17,16 +18,16 @@ type PacketCodec struct {
} }
func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int, error) { func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int, error) {
getty.GetLogger().Debugf("[PacketCodec] %s->%d", string(data), len(data)) log.Run().Debugf("[PacketCodec] %s->%d", string(data), len(data))
if len(data) < common.MagicSize+common.FrameSize { if len(data) < common.MagicSize+common.FrameSize {
return nil, 0, nil return nil, 0, nil
} }
getty.GetLogger().Debugf("[PacketCodec] read magic %+v", binary.BigEndian.Uint64(data[0:8])) log.Run().Debugf("[PacketCodec] read magic %+v", binary.BigEndian.Uint64(data[0:8]))
readmagic := data[0:common.MagicSize] readmagic := data[0:common.MagicSize]
if !common.ReadMagic(readmagic) { if !common.ReadMagic(readmagic) {
getty.GetLogger().Errorf("[PacketCodec] invalid magic %d|%s", log.Run().Errorf("[PacketCodec] invalid magic %d|%s",
binary.BigEndian.Uint64(readmagic), string(readmagic)) binary.BigEndian.Uint64(readmagic), string(readmagic))
return nil, 0, common.ErrInvalidMagic return nil, 0, common.ErrInvalidMagic
} }
...@@ -35,26 +36,26 @@ func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int ...@@ -35,26 +36,26 @@ func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int
frameLen, err := common.ReadInt32(reader) frameLen, err := common.ReadInt32(reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[PacketCodec] frameLen error %+v", err) log.Run().Errorf("[PacketCodec] frameLen error %+v", err)
return nil, 0, err return nil, 0, err
} }
// 缓冲区数据不够
if reader.Len() < int(frameLen) { if reader.Len() < int(frameLen) {
getty.GetLogger().Errorf("[PacketCodec] buf not enough %d|%d", reader.Len(), frameLen) log.Run().Debugf("[PacketCodec] buf not enough %d|%d", reader.Len(), frameLen)
return nil, 0, nil return nil, 0, nil
} }
log.Run().Debugf("[PacketCodec] read frameLen %d", frameLen)
getty.GetLogger().Debugf("[PacketCodec] read frameLen %d", frameLen)
// type // type
msgType, err := common.ReadByte(reader) msgType, err := common.ReadByte(reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[PacketCodec] read type error %+v", err) log.Run().Errorf("[PacketCodec] read type error %+v", err)
return nil, 0, err return nil, 0, err
} }
getty.GetLogger().Debugf("[PacketCodec] read msgType %+v", msgType) log.Run().Debugf("[PacketCodec] read msgType %+v", msgType)
pack := &protocol.MajoraPacket{} pack := &protocol.MajoraPacket{}
pack.Ttype = protocol.MajoraPacketType(msgType) pack.Ttype = protocol.MajoraPacketType(msgType)
...@@ -62,43 +63,43 @@ func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int ...@@ -62,43 +63,43 @@ func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int
// num // num
pack.SerialNumber, err = common.ReadInt64(reader) pack.SerialNumber, err = common.ReadInt64(reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[PacketCodec] read num error %+v", err) log.Run().Errorf("[PacketCodec] read num error %+v", err)
return nil, len(data), nil return nil, len(data), nil
} }
getty.GetLogger().Debugf("[PacketCodec] read SerialNumber %d", pack.SerialNumber) log.Run().Debugf("[PacketCodec] read SerialNumber %d", pack.SerialNumber)
// extra size // extra size
extraSize, err := common.ReadByte(reader) extraSize, err := common.ReadByte(reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[PacketCodec] read extra size error %+v", err) log.Run().Errorf("[PacketCodec] read extra size error %+v", err)
return nil, len(data), nil return nil, len(data), nil
} }
extra, err := common.ReadN(int(extraSize), reader) extra, err := common.ReadN(int(extraSize), reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[PacketCodec] read extra error %+v", err) log.Run().Errorf("[PacketCodec] read extra error %+v", err)
return nil, len(data), nil return nil, len(data), nil
} }
pack.Extra = string(extra) pack.Extra = string(extra)
getty.GetLogger().Debugf("[PacketCodec] read extra %s", pack.Extra) log.Run().Debugf("[PacketCodec] read extra %s", pack.Extra)
// dataFrame // dataFrame
dataSize := int(frameLen) - common.TypeSize - common.SerialNumberSize - common.ExtraSize - int(extraSize) dataSize := int(frameLen) - common.TypeSize - common.SerialNumberSize - common.ExtraSize - int(extraSize)
if dataSize < 0 { if dataSize < 0 {
getty.GetLogger().Errorf("[PacketCodec] read frameLen error %+v", err) log.Run().Errorf("[PacketCodec] read frameLen error %+v", err)
return nil, len(data), common.ErrInvalidSize return nil, len(data), common.ErrInvalidSize
} }
if dataSize > 0 { if dataSize > 0 {
data, err := common.ReadN(dataSize, reader) data, err := common.ReadN(dataSize, reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[PacketCodec] read data error %+v", err) log.Run().Errorf("[PacketCodec] read data error %+v", err)
return nil, len(data), nil return nil, len(data), nil
} }
pack.Data = data pack.Data = data
} }
getty.GetLogger().Debugf("[PacketCodec] read response %d", int(frameLen+12)) log.Run().Debugf("[PacketCodec] read response %d", int(frameLen+12))
return pack, int(frameLen + 12), nil return pack, int(frameLen + 12), nil
} }
......
package client package client
import ( import (
"fmt"
"net" "net"
"strings" "strings"
"sync" "sync"
...@@ -9,6 +8,7 @@ import ( ...@@ -9,6 +8,7 @@ import (
"github.com/adamweixuan/getty" "github.com/adamweixuan/getty"
"virjar.com/majora-go/common" "virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/protocol" "virjar.com/majora-go/protocol"
) )
...@@ -19,34 +19,39 @@ var ( ...@@ -19,34 +19,39 @@ var (
func (client *Client) handleHeartbeat(session getty.Session) { func (client *Client) handleHeartbeat(session getty.Session) {
go func() { go func() {
if _, _, err := session.WritePkg(HeartbeatPacket, time.Second*3); err != nil { if _, _, err := session.WritePkg(HeartbeatPacket, common.HeartBeatTimeout); err != nil {
getty.GetLogger().Errorf("handleHeartbeat error %+v %v", err, session.IsClosed()) log.Heart().Errorf("handleHeartbeat error %+v %v", err, session.IsClosed())
} else { } else {
getty.GetLogger().Infof("handleHeartbeat success %v", session.IsClosed()) log.Heart().Infof("handleHeartbeat success")
} }
}() }()
} }
func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty.Session) { func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty.Session) {
go func(packet *protocol.MajoraPacket) { go func(packet *protocol.MajoraPacket) {
defer func(start time.Time) {
log.Latency().Infof("%d handleConnect total latency %v", packet.SerialNumber, time.Since(start))
}(time.Now())
if session.IsClosed() {
log.Event().Warnf("[handleConnect] %d -> nat server is closed", packet.SerialNumber)
client.closeVirtualConnection(session, packet.SerialNumber)
return
}
hostPort := strings.Split(packet.Extra, ":") hostPort := strings.Split(packet.Extra, ":")
if len(packet.Extra) == 0 || len(hostPort) != 2 { if len(packet.Extra) == 0 || len(hostPort) != 2 {
getty.GetLogger().Errorf("[handleConnect] invalid extra %s", packet.Extra) log.Event().Errorf("[handleConnect] invalid extra %s", packet.Extra)
client.closeVirtualConnection(session, packet.SerialNumber) client.closeVirtualConnection(session, packet.SerialNumber)
return return
} }
addr := fmt.Sprintf("%s:%s", hostPort[0], hostPort[1])
dialer := net.Dialer{ dialer := net.Dialer{
Timeout: common.UpstreamTimeout, Timeout: common.UpstreamTimeout,
LocalAddr: client.localAddr, LocalAddr: client.localAddr,
} }
conn, err := dialer.Dial(common.TCP, addr) conn, err := dialer.Dial(common.TCP, packet.Extra)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[handleConnect] %d->connect to %s->%s", packet.SerialNumber, addr, err.Error()) log.Event().Errorf("[handleConnect] %d->connect to %s->%s", packet.SerialNumber, packet.Extra, err.Error())
client.closeVirtualConnection(session, packet.SerialNumber) client.closeVirtualConnection(session, packet.SerialNumber)
return return
} }
...@@ -54,17 +59,22 @@ func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty ...@@ -54,17 +59,22 @@ func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty
tcpConn := conn.(*net.TCPConn) tcpConn := conn.(*net.TCPConn)
_ = tcpConn.SetNoDelay(true) _ = tcpConn.SetNoDelay(true)
_ = tcpConn.SetKeepAlive(true) _ = tcpConn.SetKeepAlive(true)
client.AddConnection(packet, tcpConn, addr) client.AddConnection(packet, tcpConn, packet.Extra)
majoraPacket := protocol.TypeConnectReady.CreatePacket() majoraPacket := protocol.TypeConnectReady.CreatePacket()
majoraPacket.SerialNumber = packet.SerialNumber majoraPacket.SerialNumber = packet.SerialNumber
majoraPacket.Extra = client.config.ClientID majoraPacket.Extra = client.config.ClientID
if _, _, err := session.WritePkg(majoraPacket, common.SessionTimeout); err != nil { if session.IsClosed() {
getty.GetLogger().Errorf("[handleConnect] %d->write pkg to nat server with error %s", packet.SerialNumber, log.Event().Warnf("[handleConnect] %d -> nat server is closed", packet.SerialNumber)
client.closeVirtualConnection(session, packet.SerialNumber)
return
}
if _, _, err := session.WritePkg(majoraPacket, 0); err != nil {
log.Event().Errorf("[handleConnect] %d->write pkg to nat server with error %s", packet.SerialNumber,
err.Error()) err.Error())
client.closeVirtualConnection(session, packet.SerialNumber) client.closeVirtualConnection(session, packet.SerialNumber)
return return
} else { } else {
getty.GetLogger().Infof("[handleConnect] %d->connect success to %s ", packet.SerialNumber, addr) log.Event().Debugf("[handleConnect] %d->connect success to %s ", packet.SerialNumber, packet.Extra)
} }
client.handleUpStream(tcpConn, packet, session) client.handleUpStream(tcpConn, packet, session)
}(packet) }(packet)
...@@ -72,9 +82,12 @@ func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty ...@@ -72,9 +82,12 @@ func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty
func (client *Client) handleTransfer(packet *protocol.MajoraPacket, session getty.Session) { func (client *Client) handleTransfer(packet *protocol.MajoraPacket, session getty.Session) {
go func(packet *protocol.MajoraPacket) { go func(packet *protocol.MajoraPacket) {
defer func(start time.Time) {
log.Latency().Infof("%d handleTransfer total latency %v", packet.SerialNumber, time.Since(start))
}(time.Now())
load, ok := client.connStore.Load(packet.SerialNumber) load, ok := client.connStore.Load(packet.SerialNumber)
if !ok { if !ok {
getty.GetLogger().Errorf("[handleTransfer] %d-> can not find connection", packet.SerialNumber) log.Event().Errorf("[handleTransfer] %d-> can not find connection", packet.SerialNumber)
client.closeVirtualConnection(session, packet.SerialNumber) client.closeVirtualConnection(session, packet.SerialNumber)
return return
} }
...@@ -82,52 +95,56 @@ func (client *Client) handleTransfer(packet *protocol.MajoraPacket, session gett ...@@ -82,52 +95,56 @@ func (client *Client) handleTransfer(packet *protocol.MajoraPacket, session gett
cnt, err := conn.Write(packet.Data) cnt, err := conn.Write(packet.Data)
if err != nil { if err != nil {
getty.GetLogger().Errorf("[handleTransfer] %d->write to upstream fail for %s", packet.SerialNumber, err) log.Event().Errorf("[handleTransfer] %d->write to upstream fail for %s", packet.SerialNumber, err)
client.closeVirtualConnection(session, packet.SerialNumber) client.closeVirtualConnection(session, packet.SerialNumber)
return return
} }
if cnt != len(packet.Data) { if cnt != len(packet.Data) {
getty.GetLogger().Errorf("[handleTransfer] %d-> write not all data for expect->%d/%d", log.Event().Errorf("[handleTransfer] %d-> write not all data for expect->%d/%d",
packet.SerialNumber, len(packet.Data), cnt) packet.SerialNumber, len(packet.Data), cnt)
client.closeVirtualConnection(session, packet.SerialNumber) client.closeVirtualConnection(session, packet.SerialNumber)
return return
} }
getty.GetLogger().Debugf("[handleTransfer] %d-> success %+v", packet.SerialNumber, string(packet.Data)) log.Event().Debugf("[handleTransfer] %d-> success %+v", packet.SerialNumber, string(packet.Data))
}(packet) }(packet)
} }
func (client *Client) handleUpStream(conn *net.TCPConn, packet *protocol.MajoraPacket, session getty.Session) { func (client *Client) handleUpStream(conn *net.TCPConn, packet *protocol.MajoraPacket, session getty.Session) {
getty.GetLogger().Infof("[handleUpStream] %d-> handleUpStream start...", packet.SerialNumber) go func() {
defer func() { log.Event().Debugf("[handleUpStream] %d-> handleUpStream start...", packet.SerialNumber)
_ = conn.Close() defer func(start time.Time) {
}() _ = conn.Close()
for { log.Latency().Infof("%d handleUpStream total latency %v", packet.SerialNumber, time.Since(start))
buf := make([]byte, common.BufSize) // 4k }(time.Now())
cnt, err := conn.Read(buf) for {
if err != nil { buf := make([]byte, common.BufSize) // 4k
getty.GetLogger().Warnf("[handleUpStream] %d->read with error:%+v,l:%s->r:%s", cnt, err := conn.Read(buf)
packet.SerialNumber, err, conn.LocalAddr(), conn.RemoteAddr()) if err != nil {
client.OnClose(session, conn, packet.SerialNumber) log.Event().Debugf("[handleUpStream] %d->read with error:%+v,l:%s->r:%s",
break packet.SerialNumber, err, conn.LocalAddr(), conn.RemoteAddr())
} client.OnClose(session, conn, packet.SerialNumber)
pack := protocol.TypeTransfer.CreatePacket() break
pack.Data = buf[:cnt] }
pack.SerialNumber = packet.SerialNumber pack := protocol.TypeTransfer.CreatePacket()
pack.Data = buf[:cnt]
if _, _, err := session.WritePkg(pack, common.SessionTimeout); err != nil { pack.SerialNumber = packet.SerialNumber
getty.GetLogger().Errorf("[handleUpStream] %d-> write to server fail %+v", packet.SerialNumber, err.Error())
client.OnClose(session, conn, packet.SerialNumber) if _, _, err := session.WritePkg(pack, 0); err != nil {
break log.Event().Errorf("[handleUpStream] %d-> write to server fail %+v", packet.SerialNumber, err.Error())
} else { client.OnClose(session, conn, packet.SerialNumber)
getty.GetLogger().Debugf("[handleUpStream] %d->success %+v", packet.SerialNumber, string(packet.Data)) break
} else {
log.Event().Debugf("[handleUpStream] %d->success %+v", packet.SerialNumber, string(packet.Data))
}
} }
} }()
} }
func (client *Client) handleDisconnectMessage(session getty.Session, packet *protocol.MajoraPacket) { func (client *Client) handleDisconnectMessage(session getty.Session, packet *protocol.MajoraPacket) {
go func() { go func() {
getty.GetLogger().Infof("[handleDisconnectMessage] %d->%v", packet.SerialNumber, session.IsClosed()) log.Event().Debugf("[handleDisconnectMessage] %d->session closesd %v", packet.SerialNumber, session.IsClosed())
if conn, ok := client.connStore.Load(packet.SerialNumber); ok { if conn, ok := client.connStore.Load(packet.SerialNumber); ok {
client.OnClose(session, conn.(net.Conn), packet.SerialNumber) client.OnClose(session, conn.(net.Conn), packet.SerialNumber)
} }
...@@ -136,7 +153,7 @@ func (client *Client) handleDisconnectMessage(session getty.Session, packet *pro ...@@ -136,7 +153,7 @@ func (client *Client) handleDisconnectMessage(session getty.Session, packet *pro
func (client *Client) handleControlMessage(_ *protocol.MajoraPacket) { func (client *Client) handleControlMessage(_ *protocol.MajoraPacket) {
go func() { go func() {
getty.GetLogger().Debugf("handleControlMessage") log.Event().Debugf("handleControlMessage")
}() }()
} }
...@@ -149,47 +166,50 @@ func (client *Client) handleDestroyMessage() { ...@@ -149,47 +166,50 @@ func (client *Client) handleDestroyMessage() {
func (client *Client) AddConnection(packet *protocol.MajoraPacket, conn *net.TCPConn, addr string) { func (client *Client) AddConnection(packet *protocol.MajoraPacket, conn *net.TCPConn, addr string) {
if _, ok := client.connStore.Load(packet.SerialNumber); ok { if _, ok := client.connStore.Load(packet.SerialNumber); ok {
getty.GetLogger().Errorf("[AddConnection] %d->error, has one", packet.SerialNumber) log.Event().Errorf("[AddConnection] %d->error, has one", packet.SerialNumber)
} }
client.connStore.Store(packet.SerialNumber, conn) client.connStore.Store(packet.SerialNumber, conn)
getty.GetLogger().Infof("[AddConnection] %d->%s success", packet.SerialNumber, addr) log.Event().Debugf("[AddConnection] %d->%s success", packet.SerialNumber, addr)
} }
// OnClose 1. 本地缓存删除 2. 关闭连接 3. 通知natserver // OnClose 1. 本地缓存删除 2. 关闭连接 3. 通知natserver
func (client *Client) OnClose(netSession getty.Session, upStreamSession net.Conn, serialNumber int64) { func (client *Client) OnClose(netSession getty.Session, upStreamSession net.Conn, serialNumber int64) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
getty.GetLogger().Errorf("OnClose %+v", err) log.Event().Errorf("OnClose %+v", err)
} }
}() }()
client.closeVirtualConnection(netSession, serialNumber)
client.connStore.Delete(serialNumber) client.connStore.Delete(serialNumber)
_ = upStreamSession.Close() _ = upStreamSession.Close()
client.closeVirtualConnection(netSession, serialNumber)
} }
//closeVirtualConnection disconnect to server //closeVirtualConnection disconnect to server
func (client *Client) closeVirtualConnection(session getty.Session, serialNumber int64) { func (client *Client) closeVirtualConnection(session getty.Session, serialNumber int64) {
getty.GetLogger().Warnf("[closeVirtualConnection] %d->session status:%v", serialNumber, session.IsClosed()) log.Event().Debugf("[closeVirtualConnection] %d->session closed %v", serialNumber, session.IsClosed())
if !session.IsClosed() { if session.IsClosed() {
majoraPacket := protocol.TypeDisconnect.CreatePacket() log.Event().Warnf("[closeVirtualConnection] %d->session is closed", serialNumber)
majoraPacket.SerialNumber = serialNumber return
majoraPacket.Extra = client.config.ClientID }
if _, _, err := session.WritePkg(majoraPacket, common.SessionTimeout); err != nil { majoraPacket := protocol.TypeDisconnect.CreatePacket()
getty.GetLogger().Errorf("[closeVirtualConnection] ->%d error %s", serialNumber, err.Error()) majoraPacket.SerialNumber = serialNumber
} majoraPacket.Extra = client.config.ClientID
if allCnt, sendCnt, err := session.WritePkg(majoraPacket, 0); err != nil {
log.Event().Warnf("[closeVirtualConnection] ->%d error %s session closed %v allCnt %d sendCnt %d",
serialNumber, err.Error(), session.IsClosed(), allCnt, sendCnt)
} }
} }
func (client *Client) CloseAll(session getty.Session) { func (client *Client) CloseAll(session getty.Session) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
getty.GetLogger().Errorf("OnClose %+v", err) log.Event().Errorf("OnClose %+v", err)
} }
}() }()
client.connStore.Range(func(key, value interface{}) bool { client.connStore.Range(func(key, value interface{}) bool {
serialNumber := key.(int64) serialNumber := key.(int64)
conn, _ := value.(*net.TCPConn) conn, _ := value.(*net.TCPConn)
getty.GetLogger().Infof("[CloseAll] close serialNumber -> %d", serialNumber) log.Event().Debugf("[CloseAll] close serialNumber -> %d", serialNumber)
client.OnClose(session, conn, serialNumber) client.OnClose(session, conn, serialNumber)
return true return true
}) })
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"github.com/adamweixuan/getty" "github.com/adamweixuan/getty"
"virjar.com/majora-go/common" "virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/protocol" "virjar.com/majora-go/protocol"
) )
...@@ -20,32 +21,31 @@ func (m *MajoraEventListener) OnOpen(session getty.Session) error { ...@@ -20,32 +21,31 @@ func (m *MajoraEventListener) OnOpen(session getty.Session) error {
extraMap[common.ExtrakeyUser] = m.client.config.Extra.Account extraMap[common.ExtrakeyUser] = m.client.config.Extra.Account
packet.Data = protocol.EncodeExtra(extraMap) packet.Data = protocol.EncodeExtra(extraMap)
if _, _, err := session.WritePkg(packet, time.Second*10); err != nil { if _, _, err := session.WritePkg(packet, time.Second*10); err != nil {
getty.GetLogger().Errorf("register to server error %+v", err) log.Event().Errorf("register to server error %+v", err)
return err return err
} }
getty.GetLogger().Warnf("[OnOpen] registe to %s success", m.client.config.TunnelAddr) log.Event().Infof("[OnOpen] registe to %s success", m.client.config.TunnelAddr)
return nil return nil
} }
func (m *MajoraEventListener) OnClose(session getty.Session) { func (m *MajoraEventListener) OnClose(session getty.Session) {
getty.GetLogger().Errorf("OnClose->%v,clean local session...", session.IsClosed()) log.Event().Errorf("OnClose-> session closed %v", session.IsClosed())
m.client.CloseAll(session) m.client.CloseAll(session)
} }
func (m *MajoraEventListener) OnError(session getty.Session, err error) { func (m *MajoraEventListener) OnError(session getty.Session, err error) {
getty.GetLogger().Errorf("OnError %s", err.Error()) log.Event().Errorf("OnError %s", err.Error())
m.client.CloseAll(session) m.client.CloseAll(session)
} }
func (m *MajoraEventListener) OnCron(session getty.Session) { func (m *MajoraEventListener) OnCron(session getty.Session) {
getty.GetLogger().Warnf("thread:%d stat:%v", runtime.NumGoroutine(), session.IsClosed()) log.Event().Warnf("thread:%d session closed %v", runtime.NumGoroutine(), session.IsClosed())
m.client.Redial(session) m.client.Redial(session)
} }
func (m *MajoraEventListener) OnMessage(session getty.Session, input interface{}) { func (m *MajoraEventListener) OnMessage(session getty.Session, input interface{}) {
majoraPacket := input.(*protocol.MajoraPacket) majoraPacket := input.(*protocol.MajoraPacket)
getty.GetLogger().Infof("receive packet from server %d->%s,extra:%s", majoraPacket.SerialNumber, log.Event().Debugf("receive packet from server %d->%s", majoraPacket.SerialNumber, majoraPacket.Ttype.ToString())
majoraPacket.Ttype.ToString(), majoraPacket.Extra)
switch majoraPacket.Ttype { switch majoraPacket.Ttype {
case protocol.TypeHeartbeat: case protocol.TypeHeartbeat:
......
...@@ -7,14 +7,14 @@ import ( ...@@ -7,14 +7,14 @@ import (
"time" "time"
"github.com/adamweixuan/getty" "github.com/adamweixuan/getty"
gxsync "github.com/adamweixuan/gostnops/sync"
"virjar.com/majora-go/common" "virjar.com/majora-go/common"
"virjar.com/majora-go/infra" "virjar.com/majora-go/infra"
"virjar.com/majora-go/log"
) )
var ( //var (
taskPool = gxsync.NewTaskPoolSimple(5000) //taskPool = gxsync.NewTaskPoolSimple(5000)
) //)
func (client *Client) connect() { func (client *Client) connect() {
hostPort := client.config.TunnelAddr hostPort := client.config.TunnelAddr
...@@ -27,9 +27,9 @@ func (client *Client) connect() { ...@@ -27,9 +27,9 @@ func (client *Client) connect() {
gettyCli := getty.NewTCPClient( gettyCli := getty.NewTCPClient(
getty.WithServerAddress(hostPort), getty.WithServerAddress(hostPort),
getty.WithConnectionNumber(1), getty.WithConnectionNumber(1),
//getty.WithClientTaskPool(taskPool),
getty.WithReconnectInterval(int(reConnect.Milliseconds())), getty.WithReconnectInterval(int(reConnect.Milliseconds())),
getty.WithLocalAddressClient(client.localAddr), getty.WithLocalAddressClient(client.localAddr))
getty.WithClientTaskPool(taskPool))
gettyCli.RunEventLoop(NewClientSession(client)) gettyCli.RunEventLoop(NewClientSession(client))
client.natTunnel = gettyCli client.natTunnel = gettyCli
} }
...@@ -43,7 +43,7 @@ func NewClientSession(client *Client) func(getty.Session) error { ...@@ -43,7 +43,7 @@ func NewClientSession(client *Client) func(getty.Session) error {
func InitialSession(session getty.Session, client *Client) (err error) { func InitialSession(session getty.Session, client *Client) (err error) {
tcpConn, ok := session.Conn().(*net.TCPConn) tcpConn, ok := session.Conn().(*net.TCPConn)
if !ok { if !ok {
panic(fmt.Sprintf("newSession: %s, session.conn{%#v} is not tcp connection", session.Stat(), session.Conn())) panic(fmt.Sprintf("invalid session %+v", session.Conn()))
} }
if err = tcpConn.SetNoDelay(true); err != nil { if err = tcpConn.SetNoDelay(true); err != nil {
...@@ -63,7 +63,7 @@ func InitialSession(session getty.Session, client *Client) (err error) { ...@@ -63,7 +63,7 @@ func InitialSession(session getty.Session, client *Client) (err error) {
} }
session.SetName(common.SessionName) session.SetName(common.SessionName)
session.SetMaxMsgLen(common.KB8) // max message package length is 128k session.SetMaxMsgLen(common.KB8)
session.SetReadTimeout(common.ReadTimeout) session.SetReadTimeout(common.ReadTimeout)
session.SetWriteTimeout(common.WriteTimeout) session.SetWriteTimeout(common.WriteTimeout)
session.SetWaitTime(common.WaitTimeout) session.SetWaitTime(common.WaitTimeout)
...@@ -73,7 +73,7 @@ func InitialSession(session getty.Session, client *Client) (err error) { ...@@ -73,7 +73,7 @@ func InitialSession(session getty.Session, client *Client) (err error) {
// 加上随机 防止vps在同时间重启 // 加上随机 防止vps在同时间重启
randDuration := rand.Int63n(time.Minute.Milliseconds() * 5) randDuration := rand.Int63n(time.Minute.Milliseconds() * 5)
interval := randDuration + client.config.Redial.RedialDuration.Milliseconds() interval := randDuration + client.config.Redial.RedialDuration.Milliseconds()
getty.GetLogger().Infof("ReconnInterval %+v", interval) log.Run().Infof("redial interval %+v", time.Duration(interval)*time.Millisecond)
session.SetCronPeriod(int(interval)) session.SetCronPeriod(int(interval))
} }
session.SetPkgHandler(PkgCodec) session.SetPkgHandler(PkgCodec)
...@@ -84,17 +84,16 @@ func InitialSession(session getty.Session, client *Client) (err error) { ...@@ -84,17 +84,16 @@ func InitialSession(session getty.Session, client *Client) (err error) {
} }
func (client *Client) Redial(session getty.Session) { func (client *Client) Redial(session getty.Session) {
getty.GetLogger().Warnf("=================redial start %v ==============", client.config.Redial.Valid()) log.Run().Infof("redial start ...%v", client.config.Redial.Valid())
if !client.config.Redial.Valid() { if !client.config.Redial.Valid() {
return return
} }
getty.GetLogger().Warn("=================redial->offline ==============") log.Run().Warn("redial send offline message ...")
if _, _, err := session.WritePkg(OfflinePacket, time.Second*10); err != nil { if _, _, err := session.WritePkg(OfflinePacket, 0); err != nil {
getty.GetLogger().Warnf("write offline to server error %s", err.Error()) log.Run().Warnf("write offline to server error %s", err.Error())
} }
getty.GetLogger().Warn("=================redial->close local session ==============") log.Run().Warn("redial close local session")
client.CloseAll(session) client.CloseAll(session)
getty.GetLogger().Warnf("=================redial->wait %v ==============", client.config.Redial.WaitTime)
time.Sleep(client.config.Redial.WaitTime) time.Sleep(client.config.Redial.WaitTime)
infra.Redial(client.config, session) infra.Redial(client.config, session)
} }
...@@ -4,7 +4,7 @@ import ( ...@@ -4,7 +4,7 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"github.com/adamweixuan/getty" "virjar.com/majora-go/log"
) )
var ( var (
...@@ -30,7 +30,7 @@ func (e *ShellCmd) Handle(param map[string]string, callback Callback) { ...@@ -30,7 +30,7 @@ func (e *ShellCmd) Handle(param map[string]string, callback Callback) {
callback.OnCmdResponse(false, cmdErrorMap) callback.OnCmdResponse(false, cmdErrorMap)
return return
} }
getty.GetLogger().Infof("exec cmd %s", targetCmd) log.Run().Infof("exec cmd %s", targetCmd)
trueCmd := strings.Split(targetCmd, " ") trueCmd := strings.Split(targetCmd, " ")
...@@ -38,7 +38,7 @@ func (e *ShellCmd) Handle(param map[string]string, callback Callback) { ...@@ -38,7 +38,7 @@ func (e *ShellCmd) Handle(param map[string]string, callback Callback) {
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
getty.GetLogger().Errorf("exec error %+v", err) log.Run().Errorf("exec error %+v", err)
return return
} }
......
...@@ -50,8 +50,9 @@ const ( ...@@ -50,8 +50,9 @@ const (
WaitTimeout = time.Minute WaitTimeout = time.Minute
KeepAliveTimeout = time.Second * 10 KeepAliveTimeout = time.Second * 10
SessionTimeout = time.Minute * 5 SessionTimeout = time.Minute * 5
UpstreamTimeout = time.Minute HeartBeatTimeout = time.Second * 30
UpstreamTimeout = time.Minute
) )
const ( const (
......
...@@ -5,12 +5,10 @@ dns_server = 114.114.114.114:53 ...@@ -5,12 +5,10 @@ dns_server = 114.114.114.114:53
;local_ip = 192.168.0.100 ;local_ip = 192.168.0.100
;for performance pprof 0 is close ;for performance pprof 0 is close
pprof_port = 16666 pprof_port = 16666
disable_update = false
; default is info
log_level = 1 log_level = 1
reconn_interval = 5s reconn_interval = 5s
;client_id = net_check_interval = 5s
log_path = "./majora.log" net_check_url = https://www.baidu.com
[extra] [extra]
account = superman account = superman
...@@ -22,5 +20,5 @@ account = superman ...@@ -22,5 +20,5 @@ account = superman
; windows bat 脚本的绝对路径 ; windows bat 脚本的绝对路径
; *nix shell脚本的绝对路径 D:\redial\redial.bat ; *nix shell脚本的绝对路径 D:\redial\redial.bat
;exec_path = ls ;exec_path = ls
redial_duration = 30s ;redial_duration = 30s
wait_time = 10s ;wait_time = 10s
tunnel_addr = majora-dev.virjar.com:5879 tunnel_addr = majora-vps-zj.virjar.com:5879
dns_server = 114.114.114.114:53 dns_server = 114.114.114.114:53
;bind to local ip ;bind to local ip
;local_ip = 192.168.0.100 ;local_ip = 192.168.0.100
;for performance pprof 0 is close
;pprof_port = 0
disable_update = false
; default is info ; default is info
log_level = 2 log_level = 1
reconn_interval = 5s reconn_interval = 5s
;client_id = net_check_interval = 5s
log_path = /root/majora.log net_check_url = https://www.baidu.com
[extra] [extra]
account = superman account = superman
[redial] [redial]
command = /bin/bash ;command = /bin/bash
exec_path = /root/ppp_auto_with_auth.sh ;exec_path = /root/ppp_redial.sh
redial_duration = 10m ;redial_duration = 10m
wait_time = 10s ;wait_time = 10s
[Unit]
Description=majora client
After=network.target
[Service]
Type=simple
User=root
Restart=always
RestartSec=5s
ExecStart=/root/majora -conf /root/majora.ini
ExecReload=/root/majora -conf /root/majora.ini
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
\ No newline at end of file
#!/usr/bin/env bash #!/usr/bin/env bash
rm -fr /usr/lib/systemd/system/majora.service
# create link sudo rm -fr /usr/lib/systemd/system/majora.service
ln -s /root/majora.service /usr/lib/systemd/system/majora.service sudo systemctl daemon-reload
sudo systemctl stop majora.service
systemctl daemon-reload old_pid=$(ps -ef | grep majora | grep -v grep | awk '{print $2}')
echo "restart..." echo "old pid is ${old_pid}"
systemctl restart majora.service echo "clean old ..."
systemctl status majora.service `ps -ef | grep majora | grep -v grep | awk '{print $2}'| xargs kill -9`
mkdir -p output/log
exec ./majora -daemon -conf majora.ini
\ No newline at end of file
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
wget https://oss.virjar.com/majora/bin/latest/majora-cli_latest_linux_amd64.tar.gz -O majora-cli.tar.gz wget https://oss.virjar.com/majora/bin/latest/majora-cli_latest_linux_amd64.tar.gz -O majora-cli.tar.gz
tar -zxvf majora-cli.tar.gz
rm -fr majora rm -fr majora
rm -fr exec.sh rm -fr exec.sh
rm -fr start.sh rm -fr start.sh
...@@ -11,21 +9,11 @@ rm -fr majora.ini ...@@ -11,21 +9,11 @@ rm -fr majora.ini
rm -fr majora.service rm -fr majora.service
rm -fr majora-dev.ini rm -fr majora-dev.ini
rm -fr majora.log rm -fr majora.log
rm -fr output
rm -fr std.log
mv -f majora-cli*/* . tar -zxvf majora-cli.tar.gz
rm -fr /usr/lib/systemd/system/majora.service
# create link
ln -s /root/majora.service /usr/lib/systemd/system/majora.service
systemctl daemon-reload
echo "start on reboot ..."
systemctl enable majora.service
echo "restart..." mv -f majora-cli*/* .
systemctl restart majora.service
systemctl status majora.service exec bash ./start.sh
...@@ -3,8 +3,8 @@ module virjar.com/majora-go ...@@ -3,8 +3,8 @@ module virjar.com/majora-go
go 1.17 go 1.17
require ( require (
github.com/adamweixuan/getty v1.8.4 github.com/adamweixuan/getty v0.0.1
github.com/adamweixuan/gostnops v1.11.20-0.20211029124314-3f0589fceea6 github.com/adamweixuan/gostnops v0.0.1
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
gopkg.in/ini.v1 v1.63.2 gopkg.in/ini.v1 v1.63.2
) )
......
github.com/adamweixuan/getty v1.8.4 h1:YhHVYwrSqky3cMrPV5/dfHUwrhc9XB7emobVXTe1wY4= github.com/adamweixuan/getty v0.0.1 h1:ze1++8zi9yF7QJnp9p1pbCn/7n5Ex5xrJKlFzpOu5q8=
github.com/adamweixuan/getty v1.8.4/go.mod h1:+P0Afn1ky1/4q96pjJmR6GssmVYXN+2dZ/0BxkIDpGo= github.com/adamweixuan/getty v0.0.1/go.mod h1:SnxNiA40Am3aSxaDnAYBBbd7iz9BtKUign8x1jNh2TU=
github.com/adamweixuan/gostnops v1.11.20-0.20211029124314-3f0589fceea6 h1:UGMsACjkGfNRKCz5U8ijtkpKL8o/25rGHxTV1adWjak= github.com/adamweixuan/gostnops v0.0.1 h1:oBfrRgBoRyaGjBTfq0DGH07jARS4OqN7jbSv1Mn05Fg=
github.com/adamweixuan/gostnops v1.11.20-0.20211029124314-3f0589fceea6/go.mod h1:zZYjPhU2+ujyEOWWE0l1pEdf5H4CyfiMG//rSpNjwcQ= github.com/adamweixuan/gostnops v0.0.1/go.mod h1:lTe81VUWCpja0NOVqXyi2cH28m2hYezzhTt3MudpDbU=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
......
...@@ -2,10 +2,11 @@ package infra ...@@ -2,10 +2,11 @@ package infra
import ( import (
"crypto/tls" "crypto/tls"
"math/rand"
"net/http" "net/http"
"time" "time"
"github.com/adamweixuan/getty" "virjar.com/majora-go/log"
) )
// 网络检测 // 网络检测
...@@ -14,13 +15,23 @@ var ( ...@@ -14,13 +15,23 @@ var (
httpcli *http.Client httpcli *http.Client
) )
var (
pingUrl = []string{
"https://www.baidu.com",
"https://www.bilibili.com",
"https://www.taobao.com",
"https://www.xiaohongshu.com",
"https://www.bytedance.com",
"https://pvp.qq.com",
}
)
const ( const (
defTimeout = time.Second * 5 defTimeout = time.Second * 5
baiduUrl = "https://www.baidu.com"
) )
func init() { func init() {
rand.Seed(time.Now().UnixNano())
httpcli = &http.Client{ httpcli = &http.Client{
Transport: &http.Transport{ Transport: &http.Transport{
TLSHandshakeTimeout: defTimeout, TLSHandshakeTimeout: defTimeout,
...@@ -35,14 +46,18 @@ func init() { ...@@ -35,14 +46,18 @@ func init() {
func Ping(url string) bool { func Ping(url string) bool {
resp, err := httpcli.Head(url) resp, err := httpcli.Head(url)
if err != nil { if err != nil {
getty.GetLogger().Warnf("ping %s with error %+v", url, err) log.Run().Warnf("ping %s with error %+v", url, err)
return false return false
} }
defer resp.Body.Close() defer resp.Body.Close()
getty.GetLogger().Warnf("ping %s status code %d", url, resp.StatusCode) return resp.StatusCode > 0
return resp.StatusCode == http.StatusOK }
func RandomPing() bool {
return Ping(RandUrl())
} }
func PingBaidu() bool { func RandUrl() string {
return Ping(baiduUrl) rand.Seed(time.Now().UnixNano())
return pingUrl[rand.Intn(len(pingUrl))]
} }
...@@ -3,7 +3,7 @@ package infra ...@@ -3,7 +3,7 @@ package infra
import ( import (
"net" "net"
"github.com/adamweixuan/getty" "virjar.com/majora-go/log"
) )
const ( const (
...@@ -18,19 +18,19 @@ func GetIpByName(netname string) string { ...@@ -18,19 +18,19 @@ func GetIpByName(netname string) string {
ni, err := net.InterfaceByName(netname) ni, err := net.InterfaceByName(netname)
if err != nil { if err != nil {
getty.GetLogger().Warnf("get %s ip error %s", netname, err) log.Run().Warnf("get %s ip error %s", netname, err)
return "" return ""
} }
addrs, err := ni.Addrs() addrs, err := ni.Addrs()
if err != nil { if err != nil {
getty.GetLogger().Warnf("get ip addr err %s", err) log.Run().Warnf("get ip addr err %s", err)
return "" return ""
} }
if len(addrs) == 0 { if len(addrs) == 0 {
getty.GetLogger().Warnf("get ip addr empty ") log.Run().Warnf("get ip addr empty ")
return "" return ""
} }
...@@ -43,7 +43,7 @@ func GetIpByName(netname string) string { ...@@ -43,7 +43,7 @@ func GetIpByName(netname string) string {
} }
if ipv4Addr == nil { if ipv4Addr == nil {
getty.GetLogger().Warnf("interface %s don't have an ipv4 address", netname) log.Run().Warnf("interface %s don't have an ipv4 address", netname)
return "" return ""
} }
return ipv4Addr.String() return ipv4Addr.String()
......
...@@ -5,19 +5,19 @@ import ( ...@@ -5,19 +5,19 @@ import (
"os/exec" "os/exec"
"time" "time"
"github.com/adamweixuan/getty" "virjar.com/majora-go/log"
) )
func Restart() { func Restart() {
cmd := exec.Command(os.Args[0], os.Args[1:]...) //nolint:gosec cmd := exec.Command(os.Args[0], os.Args[1:]...)
cmd.Env = os.Environ() cmd.Env = os.Environ()
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
getty.GetLogger().Debugf("Restart ... %+v", cmd) log.Run().Debugf("Restart ... %+v", cmd)
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
getty.GetLogger().Errorf("Restart error %+v", err) log.Run().Errorf("Restart error %+v", err)
} }
} }
...@@ -25,7 +25,6 @@ func Restart() { ...@@ -25,7 +25,6 @@ func Restart() {
func RestartBySignal(signal chan struct{}) { func RestartBySignal(signal chan struct{}) {
go func() { go func() {
time.Sleep(time.Second * 5) time.Sleep(time.Second * 5)
getty.GetLogger().Infof("=============cleanup==============")
signal <- struct{}{} signal <- struct{}{}
}() }()
...@@ -34,8 +33,8 @@ func RestartBySignal(signal chan struct{}) { ...@@ -34,8 +33,8 @@ func RestartBySignal(signal chan struct{}) {
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
getty.GetLogger().Infof("[RestartBySignal] ... %+v", cmd) log.Run().Infof("[RestartBySignal] ... %+v", cmd)
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
getty.GetLogger().Errorf("Restart error %+v", err) log.Run().Errorf("Restart error %+v", err)
} }
} }
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/adamweixuan/getty" "github.com/adamweixuan/getty"
"virjar.com/majora-go/log"
"virjar.com/majora-go/model" "virjar.com/majora-go/model"
) )
...@@ -15,34 +16,43 @@ const ( ...@@ -15,34 +16,43 @@ const (
) )
func Redial(cfg *model.Configure, session getty.Session) { func Redial(cfg *model.Configure, session getty.Session) {
getty.GetLogger().Warnf("[redial] start, session is close :%d", session.IsClosed()) log.Run().Infof("[redial] start, session is close :%d", session.IsClosed())
beforeIp := GetPPP() beforeIp := GetPPP()
retry := 0 retry := 0
defer func(start time.Time) { defer func(start time.Time) {
newIp := GetPPP() newIp := GetPPP()
getty.GetLogger().Warnf("[redial] retry %d, cost %v, ip change %s -> %s, session is close:%v", log.Run().Infof("[redial] retry %d, cost %v, ip change %s -> %s, session is close:%v",
retry, time.Since(start), beforeIp, newIp, session.IsClosed()) retry, time.Since(start), beforeIp, newIp, session.IsClosed())
}(time.Now()) }(time.Now())
for { for {
retry++ retry++
status := command(cfg) status := command(cfg)
pingBaidu := PingBaidu() pingBaidu := RandomPing()
getty.GetLogger().Warnf("[redial] net check: %d->%v", retry, pingBaidu) log.Run().Infof("[redial] net check: %d->%v", retry, pingBaidu)
if pingBaidu && status { if pingBaidu && status {
break break
} }
} }
} }
func RedialByCheck(cfg *model.Configure) bool {
beforeIp := GetPPP()
defer func(start time.Time) {
newIp := GetPPP()
log.Run().Infof("[RedialByCheck] cost %v, ip change %s -> %s", time.Since(start), beforeIp, newIp)
}(time.Now())
return command(cfg)
}
func command(cfg *model.Configure) bool { func command(cfg *model.Configure) bool {
execPath := cfg.Redial.ExecPath execPath := cfg.Redial.ExecPath
if len(execPath) == 0 { if len(execPath) == 0 {
getty.GetLogger().Warn("[redial] exec file is empty") log.Run().Warn("[redial] exec file is empty")
return true return true
} }
command := cfg.Redial.Command command := cfg.Redial.Command
if len(command) == 0 { if len(command) == 0 {
getty.GetLogger().Warn("[redial] command is empty") log.Run().Warn("[redial] command is empty")
return true return true
} }
...@@ -54,9 +64,9 @@ func command(cfg *model.Configure) bool { ...@@ -54,9 +64,9 @@ func command(cfg *model.Configure) bool {
cmd := exec.Command(command, args, execPath) cmd := exec.Command(command, args, execPath)
output, err := cmd.Output() output, err := cmd.Output()
if err != nil { if err != nil {
getty.GetLogger().Errorf("[redial] Execute Shell:%s failed with error:%s", command, err.Error()) log.Run().Errorf("[redial] Execute Shell:%s failed with error:%s", command, err.Error())
return false return false
} }
getty.GetLogger().Warnf("[redial] success %+v resp:%s", cmd, string(output)) log.Run().Infof("[redial] success %+v resp:%s", cmd, string(output))
return true return true
} }
package infra
//// getBinary 下载二进制
//func getBinary(name, os, arch, version string) (io.ReadCloser, error) {
// fileName := fmt.Sprintf(common.VersionTpl, name, version, os, arch)
// if os == "windows" {
// fileName += ".exe"
// }
// url := common.UpdateServer + common.UpdateBinaryPath + fileName
// getty.GetLogger().Debugf("getBinary url %s, filename %s", url, fileName)
//
// body, err := http.DefaultClient.Get(url)
// if err != nil {
// return nil, err
// }
// return body.Body, nil
//}
//
//func downloadFile(name, os, arch, version string, f *os.File) error {
// binary, err := getBinary(name, os, arch, version)
// if err != nil {
// return err
// }
//
// defer func(binary io.ReadCloser) {
// _ = binary.Close()
// }(binary)
//
// body, err := ioutil.ReadAll(binary)
//
// if err != nil {
// return err
// }
//
// cnt, err := f.Write(body)
// if err != nil {
// return err
// }
//
// if cnt != len(body) {
// return errors.New("write to file is not enough")
// }
// return nil
//}
//
//func rename(src, dst string) error {
// if err := os.Chmod(src, common.DefaultMode); err != nil {
// return err
// }
//
// if err := os.Rename(src, dst); err != nil {
// return err
// }
// getty.GetLogger().Debugf("rename %s to %s", src, dst)
// return nil
//}
//
//func UpdateCore(name, latestVer, targetFile string) (bool, error) {
// tf, err := ioutil.TempFile("", "")
// if err != nil {
// getty.GetLogger().Debugf("UpdateCore TempFile with error %s", err.Error())
// return false, err
// }
//
// if err := downloadFile(name, runtime.GOOS, runtime.GOARCH, latestVer, tf); err != nil {
// getty.GetLogger().Debugf("UpdateCore downloadFile with error %s", err.Error())
// return false, err
// }
//
// if err := tf.Close(); err != nil {
// getty.GetLogger().Debugf("UpdateCore tf close with error %s", err.Error())
// return false, err
// }
//
// if err := rename(tf.Name(), targetFile); err != nil {
// return false, err
// }
// Restart()
// return true, nil
//}
//
//func getLatestVersion() (string, error) {
// url := common.UpdateServer + common.UpdateBinaryPath + common.Latest
// getty.GetLogger().Debugf("getLatestVersion from %s", url)
// resp, err := http.DefaultClient.Get(url) //nolint:bodyclose
// if err != nil || resp == nil {
// return "", err
// }
//
// defer func(Body io.ReadCloser) {
// _ = Body.Close()
// }(resp.Body)
//
// if resp.StatusCode != http.StatusOK {
// getty.GetLogger().Errorf("get latest version with error %s->%d", url, resp.StatusCode)
// return "", nil
// }
//
// bytes, err := ioutil.ReadAll(resp.Body)
// if err != nil {
// return "", err
// }
//
// return strings.ReplaceAll(string(bytes), "\n", ""), nil
//}
//
//func needUpdate(curVer string) (bool, string) {
// if len(curVer) == 0 {
// return false, ""
// }
// latestVer, err := getLatestVersion()
// if err != nil {
// getty.GetLogger().Errorf("getLatestVersion with error %s", err.Error())
// return false, ""
// }
//
// if len(latestVer) == 0 {
// getty.GetLogger().Errorf("getLatestVersion with empty")
// return false, ""
// }
//
// if curVer[0] == 'v' || curVer[0] == 'V' {
// curVer = curVer[1:]
// }
//
// latest := latestVer
// if latestVer[0] == 'v' || latestVer[0] == 'V' {
// latest = latest[1:]
// }
// cur, _ := semver.Make(curVer)
// next, _ := semver.Make(latest)
// getty.GetLogger().Debugf("curVer %s->cur %s, latestVer %s->next %s", curVer, cur, latest, next)
//
// return cur.Compare(next) < 0, latestVer
//}
//
//// Update update to the latest version
//func Update(name, curVer string) (bool, error) {
// defer func() {
// if err := recover(); err != nil {
// getty.GetLogger().Errorf("Update with error %+v", err)
// }
// }()
//
// // get current exec path
// executable, err := os.Executable()
// if err != nil {
// return false, err
// }
//
// getty.GetLogger().Debugf("current exec info %s", executable)
//
// // check has new version
// needUpdate, latestVer := needUpdate(curVer)
// getty.GetLogger().Debugf("curVer %s, latestVer %s, need update %v", curVer, latestVer, needUpdate)
// if !needUpdate {
// getty.GetLogger().Debugf("no need update ...")
// return false, nil
// }
// updateStatus, err := UpdateCore(name, latestVer, executable)
// if err != nil {
// getty.GetLogger().Errorf("update to latest version with error %s", err)
// return false, err
// }
// getty.GetLogger().Infof("update from %s to %s with success %v", curVer, latestVer, updateStatus)
// return updateStatus, nil
//}
package log
import (
"os"
"path/filepath"
"github.com/adamweixuan/getty"
)
var (
runLogger getty.Logger
eventLogger getty.Logger
heartLogger getty.Logger
latencyLogger getty.Logger
)
const (
logDir = "./output/log/"
run = "run.log"
event = "event.log"
heart = "heart.log"
latency = "latency.log"
)
func getCurPath() string {
exePath, err := os.Executable()
if err != nil {
panic(err)
}
return filepath.Dir(exePath)
}
func Init(level int) {
curPath := getCurPath()
base := filepath.Join(curPath, logDir)
if _, err := os.Stat(base); err != nil {
if os.IsNotExist(err) {
if err := os.MkdirAll(base, os.ModePerm); err != nil {
panic(err)
}
} else {
panic(err)
}
}
if len(curPath) == 0 {
panic("invalid current path")
}
runLogger = getty.NewLogger(filepath.Join(base, run), getty.LoggerLevel(level))
eventLogger = getty.NewLogger(filepath.Join(base, event), getty.LoggerLevel(level))
heartLogger = getty.NewLogger(filepath.Join(base, heart), getty.LoggerLevel(level))
latencyLogger = getty.NewLogger(filepath.Join(base, latency), getty.LoggerLevel(level))
}
func Run() getty.Logger {
return runLogger
}
func Event() getty.Logger {
return eventLogger
}
func Heart() getty.Logger {
return heartLogger
}
func Latency() getty.Logger {
return latencyLogger
}
...@@ -3,7 +3,6 @@ package model ...@@ -3,7 +3,6 @@ package model
import ( import (
"time" "time"
"github.com/adamweixuan/getty"
"github.com/google/uuid" "github.com/google/uuid"
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"virjar.com/majora-go/common" "virjar.com/majora-go/common"
...@@ -21,18 +20,17 @@ type Extra struct { ...@@ -21,18 +20,17 @@ type Extra struct {
} }
type Configure struct { type Configure struct {
DisableUpdate bool `ini:"disable_update" json:"disable_update"` LogLevel int `ini:"log_level" json:"log_level"`
LogLevel int `ini:"log_level" json:"log_level"` PprofPort int `ini:"pprof_port" json:"pprof_port"`
PprofPort int `ini:"pprof_port" json:"pprof_port"` TunnelAddr string `ini:"tunnel_addr" json:"tunnel_addr"`
TunnelAddr string `ini:"tunnel_addr" json:"tunnel_addr"` DNSServer string `ini:"dns_server" json:"dns_server"`
DNSServer string `ini:"dns_server" json:"dns_server"` LocalAddr string `ini:"local_ip" json:"local_ip"`
LocalAddr string `ini:"local_ip" json:"local_ip"` ReconnInterval time.Duration `ini:"reconn_interval" json:"reconn_interval"`
ReconnInterval time.Duration `ini:"reconn_interval" json:"reconn_interval"` ClientID string `ini:"client_id" json:"client_id"`
ClientID string `ini:"client_id" json:"client_id"` NetCheckInterval time.Duration `ini:"net_check_interval" json:"net_check_interval"`
LogPath string `ini:"log_path" json:"log_path"` NetCheckUrl string `ini:"net_check_url" json:"net_check_url"`
Extra Extra `ini:"extra" json:"extra"`
Extra Extra `ini:"extra" json:"extra"` Redial Redial `ini:"redial" json:"redial"`
Redial Redial `ini:"redial" json:"redial"`
} }
const ( const (
...@@ -41,7 +39,6 @@ const ( ...@@ -41,7 +39,6 @@ const (
func NewDefMajoraConf() *Configure { func NewDefMajoraConf() *Configure {
return &Configure{ return &Configure{
DisableUpdate: false,
LogLevel: 1, LogLevel: 1,
PprofPort: 0, PprofPort: 0,
TunnelAddr: common.DefNatAddr, TunnelAddr: common.DefNatAddr,
...@@ -60,7 +57,7 @@ func NewDefMajoraConf() *Configure { ...@@ -60,7 +57,7 @@ func NewDefMajoraConf() *Configure {
func InitConf(path string) *Configure { func InitConf(path string) *Configure {
conf := NewDefMajoraConf() conf := NewDefMajoraConf()
if err := ini.MapTo(conf, path); err != nil { if err := ini.MapTo(conf, path); err != nil {
getty.GetLogger().Errorf("InitConf with error %s, use default...", err.Error()) panic(err)
} }
return conf return conf
} }
......
...@@ -3,8 +3,8 @@ package protocol ...@@ -3,8 +3,8 @@ package protocol
import ( import (
"bufio" "bufio"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/common" "virjar.com/majora-go/common"
"virjar.com/majora-go/log"
) )
type Decoder interface { type Decoder interface {
...@@ -33,7 +33,7 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket ...@@ -33,7 +33,7 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket
// type // type
msgType, err := common.ReadByte(reader) msgType, err := common.ReadByte(reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("read type error %+v", err) log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize return nil, common.ErrInvalidSize
} }
pack = &MajoraPacket{} pack = &MajoraPacket{}
...@@ -42,20 +42,20 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket ...@@ -42,20 +42,20 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket
// num // num
pack.SerialNumber, err = common.ReadInt64(reader) pack.SerialNumber, err = common.ReadInt64(reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("read type error %+v", err) log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize return nil, common.ErrInvalidSize
} }
// extra size // extra size
extraSize, err := common.ReadByte(reader) extraSize, err := common.ReadByte(reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("read type error %+v", err) log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize return nil, common.ErrInvalidSize
} }
extra, err := common.ReadN(int(extraSize), reader) extra, err := common.ReadN(int(extraSize), reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("read type error %+v", err) log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize return nil, common.ErrInvalidSize
} }
pack.Extra = string(extra) pack.Extra = string(extra)
...@@ -63,14 +63,14 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket ...@@ -63,14 +63,14 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket
// dataFrame // dataFrame
dataSize := int(frameLen) - common.TypeSize - common.SerialNumberSize - common.ExtraSize - int(extraSize) dataSize := int(frameLen) - common.TypeSize - common.SerialNumberSize - common.ExtraSize - int(extraSize)
if dataSize < 0 { if dataSize < 0 {
getty.GetLogger().Errorf("read type error %+v", err) log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize return nil, common.ErrInvalidSize
} }
if dataSize > 0 { if dataSize > 0 {
data, err := common.ReadN(dataSize, reader) data, err := common.ReadN(dataSize, reader)
if err != nil { if err != nil {
getty.GetLogger().Errorf("read type error %+v", err) log.Run().Errorf("read type error %+v", err)
} }
pack.Data = data pack.Data = data
} }
......
...@@ -3,7 +3,7 @@ package protocol ...@@ -3,7 +3,7 @@ package protocol
import ( import (
"bytes" "bytes"
"github.com/adamweixuan/getty" "virjar.com/majora-go/log"
) )
func EncodeExtra(extra map[string]string) []byte { func EncodeExtra(extra map[string]string) []byte {
...@@ -33,7 +33,7 @@ func DecodeExtra(input []byte) map[string]string { ...@@ -33,7 +33,7 @@ func DecodeExtra(input []byte) map[string]string {
headerSize, err := buffer.ReadByte() headerSize, err := buffer.ReadByte()
if err != nil { if err != nil {
getty.GetLogger().Errorf("DecodeExtra error %+v", err) log.Run().Errorf("DecodeExtra error %+v", err)
return map[string]string{} return map[string]string{}
} }
data := make(map[string]string) data := make(map[string]string)
......
package protocol
import (
"reflect"
"testing"
)
func TestEncodeExtra(t *testing.T) {
data := make(map[string]string)
data["hello"] = "world"
data["1"] = "world1"
data["2"] = "world2"
data["3"] = "world3"
data["account"] = "superman"
extra := EncodeExtra(data)
decodeExtra := DecodeExtra(extra)
t.Logf("TestEncodeExtra %+v", decodeExtra)
t.Logf("equal %v", reflect.DeepEqual(data, decodeExtra))
}
# v0.0.3
- [x] 重播 功能
- [x] 执行脚本 执行间隔
- [ ] http2 fix 抓包
- [x] 重连时间 可配置
- [x] 线程安全check
- [x] 支持config 文件
- [x] 代码的bug fix write/flush
- [ ] control
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment