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

Merge branch '1112' into 'master'

1112

See merge request !9
parents 76aca1d4 7aeb66e2
...@@ -10,3 +10,4 @@ release ...@@ -10,3 +10,4 @@ release
*.log *.log
majora.log majora.log
std.log std.log
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
rm -fr output
\ No newline at end of file
...@@ -5,21 +5,20 @@ import ( ...@@ -5,21 +5,20 @@ 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"
) )
...@@ -31,7 +30,7 @@ var ( ...@@ -31,7 +30,7 @@ var (
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,31 +95,33 @@ func (client *Client) handleTransfer(packet *protocol.MajoraPacket, session gett ...@@ -82,31 +95,33 @@ 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)
defer func(start time.Time) {
_ = conn.Close() _ = conn.Close()
}() log.Latency().Infof("%d handleUpStream total latency %v", packet.SerialNumber, time.Since(start))
}(time.Now())
for { for {
buf := make([]byte, common.BufSize) // 4k buf := make([]byte, common.BufSize) // 4k
cnt, err := conn.Read(buf) cnt, err := conn.Read(buf)
if err != nil { if err != nil {
getty.GetLogger().Warnf("[handleUpStream] %d->read with error:%+v,l:%s->r:%s", log.Event().Debugf("[handleUpStream] %d->read with error:%+v,l:%s->r:%s",
packet.SerialNumber, err, conn.LocalAddr(), conn.RemoteAddr()) packet.SerialNumber, err, conn.LocalAddr(), conn.RemoteAddr())
client.OnClose(session, conn, packet.SerialNumber) client.OnClose(session, conn, packet.SerialNumber)
break break
...@@ -115,19 +130,21 @@ func (client *Client) handleUpStream(conn *net.TCPConn, packet *protocol.MajoraP ...@@ -115,19 +130,21 @@ func (client *Client) handleUpStream(conn *net.TCPConn, packet *protocol.MajoraP
pack.Data = buf[:cnt] pack.Data = buf[:cnt]
pack.SerialNumber = packet.SerialNumber pack.SerialNumber = packet.SerialNumber
if _, _, err := session.WritePkg(pack, common.SessionTimeout); err != nil { if _, _, err := session.WritePkg(pack, 0); err != nil {
getty.GetLogger().Errorf("[handleUpStream] %d-> write to server fail %+v", packet.SerialNumber, err.Error()) log.Event().Errorf("[handleUpStream] %d-> write to server fail %+v", packet.SerialNumber, err.Error())
client.OnClose(session, conn, packet.SerialNumber) client.OnClose(session, conn, packet.SerialNumber)
break break
} else { } else {
getty.GetLogger().Debugf("[handleUpStream] %d->success %+v", packet.SerialNumber, string(packet.Data)) 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() {
log.Event().Warnf("[closeVirtualConnection] %d->session is closed", serialNumber)
return
}
majoraPacket := protocol.TypeDisconnect.CreatePacket() majoraPacket := protocol.TypeDisconnect.CreatePacket()
majoraPacket.SerialNumber = serialNumber majoraPacket.SerialNumber = serialNumber
majoraPacket.Extra = client.config.ClientID majoraPacket.Extra = client.config.ClientID
if _, _, err := session.WritePkg(majoraPacket, common.SessionTimeout); err != nil { if allCnt, sendCnt, err := session.WritePkg(majoraPacket, 0); err != nil {
getty.GetLogger().Errorf("[closeVirtualConnection] ->%d error %s", serialNumber, err.Error()) 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
} }
......
...@@ -51,6 +51,7 @@ const ( ...@@ -51,6 +51,7 @@ const (
KeepAliveTimeout = time.Second * 10 KeepAliveTimeout = time.Second * 10
SessionTimeout = time.Minute * 5 SessionTimeout = time.Minute * 5
HeartBeatTimeout = time.Second * 30
UpstreamTimeout = time.Minute UpstreamTimeout = time.Minute
) )
......
...@@ -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,7 +20,6 @@ type Extra struct { ...@@ -21,7 +20,6 @@ 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"`
...@@ -29,8 +27,8 @@ type Configure struct { ...@@ -29,8 +27,8 @@ type Configure struct {
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"`
LogPath string `ini:"log_path" json:"log_path"` NetCheckInterval time.Duration `ini:"net_check_interval" json:"net_check_interval"`
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"`
} }
...@@ -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