Commit 7aeb66e2 authored by wei.xuan's avatar wei.xuan

1112

parent 76aca1d4
......@@ -9,4 +9,5 @@ release
./majora
*.log
majora.log
std.log
\ No newline at end of file
std.log
majora
\ No newline at end of file
......@@ -6,8 +6,9 @@ DATE=$(shell date +"%Y-%m-%d")
BUILDINFO := -X main.Version=latest -X main.Date=$(DATE)
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:
rm -fr majora-go
rm -fr majora
\ No newline at end of file
rm -fr majora
rm -fr output
\ No newline at end of file
......@@ -5,33 +5,32 @@ import (
"encoding/json"
"flag"
"fmt"
"log"
"math/rand"
"net"
"net/http"
_ "net/http/pprof"
"os"
"os/exec"
"os/signal"
"runtime"
"runtime/debug"
"syscall"
"time"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/client"
"virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/model"
)
var (
configure string
logLevel int
pprofPort int
natServer string
account string
dnsServer string
localAddr string
disableUpdate bool
configure string
logLevel int
pprofPort int
natServer string
account string
dnsServer string
localAddr string
daemon bool
)
var (
......@@ -39,6 +38,10 @@ var (
Date string
)
var (
cmd *exec.Cmd
)
func init() {
rand.Seed(time.Now().UnixNano())
flag.StringVar(&configure, "conf", "", "./majora -c path/to/your/majora.ini")
......@@ -48,21 +51,18 @@ func init() {
flag.StringVar(&account, "account", "unknown", "account")
flag.StringVar(&dnsServer, "dnsServer", common.DNSServer, "custom dns server")
flag.StringVar(&localAddr, "localIp", "", "bind local ip")
flag.BoolVar(&disableUpdate, "disableUpdate", false, "disable self update")
flag.BoolVar(&daemon, "daemon", false, "daemon")
flag.Parse()
}
func initial(cfg *model.Configure) {
if cfg.LogLevel > 0 {
_ = getty.SetLoggerLevel(getty.LoggerLevel(cfg.LogLevel - 1))
_ = getty.Online(cfg.LogPath)
}
log.Init(cfg.LogLevel - 1)
if cfg.PprofPort > 0 {
go func() {
addr := fmt.Sprintf("127.0.0.1:%d", cfg.PprofPort)
getty.GetLogger().Infof("enable pprof: %s", addr)
log.Fatal(http.ListenAndServe(addr, nil))
log.Run().Infof("enable pprof: %s", addr)
log.Run().Error(http.ListenAndServe(addr, nil))
}()
}
......@@ -73,7 +73,6 @@ func initial(cfg *model.Configure) {
return net.Dial("udp", dnsServer)
},
}
getty.GetLogger().Infof("use custom dns server %s", dnsServer)
}
}
......@@ -82,28 +81,36 @@ func parseFromCmd(cfg *model.Configure) {
cfg.LogLevel = logLevel
cfg.DNSServer = dnsServer
cfg.LocalAddr = localAddr
cfg.DisableUpdate = disableUpdate
// 先兼容吧
cfg.Extra.Account = account
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()
if len(configure) > 0 {
cfg = model.InitConf(configure)
} else {
parseFromCmd(cfg)
}
//runtime.GOMAXPROCS(runtime.NumCPU() * 2)
//debug.SetGCPercent(200)
initial(cfg)
runtime.GOMAXPROCS(runtime.NumCPU() * 2)
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)
return cfg
}
//main start
......@@ -112,15 +119,29 @@ func main() {
fmt.Println(Version)
os.Exit(0)
}
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
cfg := initConf()
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() {
cli()
}()
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
cli(cfg)
select {
case <-sigs:
case <-signalChan:
time.Sleep(time.Second * 3)
getty.GetLogger().Warn("main process exit...")
log.Run().Warn("main process exit...")
}
}
......@@ -3,8 +3,11 @@ package client
import (
"net"
"sync"
"time"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/infra"
"virjar.com/majora-go/log"
"virjar.com/majora-go/model"
)
......@@ -17,8 +20,7 @@ type Client struct {
}
func NewClientWithConf(cfg *model.Configure) {
client := NewCli(cfg)
client.StartUp()
NewCli(cfg).StartUp()
}
func NewCli(cfg *model.Configure) *Client {
......@@ -39,5 +41,38 @@ func NewCli(cfg *model.Configure) *Client {
}
func (client *Client) StartUp() {
client.check()
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 (
"github.com/adamweixuan/getty"
"virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/protocol"
)
......@@ -17,16 +18,16 @@ type PacketCodec struct {
}
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 {
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]
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))
return nil, 0, common.ErrInvalidMagic
}
......@@ -35,26 +36,26 @@ func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int
frameLen, err := common.ReadInt32(reader)
if err != nil {
getty.GetLogger().Errorf("[PacketCodec] frameLen error %+v", err)
log.Run().Errorf("[PacketCodec] frameLen error %+v", err)
return nil, 0, err
}
// 缓冲区数据不够
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
}
getty.GetLogger().Debugf("[PacketCodec] read frameLen %d", frameLen)
log.Run().Debugf("[PacketCodec] read frameLen %d", frameLen)
// type
msgType, err := common.ReadByte(reader)
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
}
getty.GetLogger().Debugf("[PacketCodec] read msgType %+v", msgType)
log.Run().Debugf("[PacketCodec] read msgType %+v", msgType)
pack := &protocol.MajoraPacket{}
pack.Ttype = protocol.MajoraPacketType(msgType)
......@@ -62,43 +63,43 @@ func (p *PacketCodec) Read(session getty.Session, data []byte) (interface{}, int
// num
pack.SerialNumber, err = common.ReadInt64(reader)
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
}
getty.GetLogger().Debugf("[PacketCodec] read SerialNumber %d", pack.SerialNumber)
log.Run().Debugf("[PacketCodec] read SerialNumber %d", pack.SerialNumber)
// extra size
extraSize, err := common.ReadByte(reader)
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
}
extra, err := common.ReadN(int(extraSize), reader)
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
}
pack.Extra = string(extra)
getty.GetLogger().Debugf("[PacketCodec] read extra %s", pack.Extra)
log.Run().Debugf("[PacketCodec] read extra %s", pack.Extra)
// dataFrame
dataSize := int(frameLen) - common.TypeSize - common.SerialNumberSize - common.ExtraSize - int(extraSize)
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
}
if dataSize > 0 {
data, err := common.ReadN(dataSize, reader)
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
}
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
}
......
This diff is collapsed.
......@@ -6,6 +6,7 @@ import (
"github.com/adamweixuan/getty"
"virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/protocol"
)
......@@ -20,32 +21,31 @@ func (m *MajoraEventListener) OnOpen(session getty.Session) error {
extraMap[common.ExtrakeyUser] = m.client.config.Extra.Account
packet.Data = protocol.EncodeExtra(extraMap)
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
}
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
}
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)
}
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)
}
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)
}
func (m *MajoraEventListener) OnMessage(session getty.Session, input interface{}) {
majoraPacket := input.(*protocol.MajoraPacket)
getty.GetLogger().Infof("receive packet from server %d->%s,extra:%s", majoraPacket.SerialNumber,
majoraPacket.Ttype.ToString(), majoraPacket.Extra)
log.Event().Debugf("receive packet from server %d->%s", majoraPacket.SerialNumber, majoraPacket.Ttype.ToString())
switch majoraPacket.Ttype {
case protocol.TypeHeartbeat:
......
......@@ -7,14 +7,14 @@ import (
"time"
"github.com/adamweixuan/getty"
gxsync "github.com/adamweixuan/gostnops/sync"
"virjar.com/majora-go/common"
"virjar.com/majora-go/infra"
"virjar.com/majora-go/log"
)
var (
taskPool = gxsync.NewTaskPoolSimple(5000)
)
//var (
//taskPool = gxsync.NewTaskPoolSimple(5000)
//)
func (client *Client) connect() {
hostPort := client.config.TunnelAddr
......@@ -27,9 +27,9 @@ func (client *Client) connect() {
gettyCli := getty.NewTCPClient(
getty.WithServerAddress(hostPort),
getty.WithConnectionNumber(1),
//getty.WithClientTaskPool(taskPool),
getty.WithReconnectInterval(int(reConnect.Milliseconds())),
getty.WithLocalAddressClient(client.localAddr),
getty.WithClientTaskPool(taskPool))
getty.WithLocalAddressClient(client.localAddr))
gettyCli.RunEventLoop(NewClientSession(client))
client.natTunnel = gettyCli
}
......@@ -43,7 +43,7 @@ func NewClientSession(client *Client) func(getty.Session) error {
func InitialSession(session getty.Session, client *Client) (err error) {
tcpConn, ok := session.Conn().(*net.TCPConn)
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 {
......@@ -63,7 +63,7 @@ func InitialSession(session getty.Session, client *Client) (err error) {
}
session.SetName(common.SessionName)
session.SetMaxMsgLen(common.KB8) // max message package length is 128k
session.SetMaxMsgLen(common.KB8)
session.SetReadTimeout(common.ReadTimeout)
session.SetWriteTimeout(common.WriteTimeout)
session.SetWaitTime(common.WaitTimeout)
......@@ -73,7 +73,7 @@ func InitialSession(session getty.Session, client *Client) (err error) {
// 加上随机 防止vps在同时间重启
randDuration := rand.Int63n(time.Minute.Milliseconds() * 5)
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.SetPkgHandler(PkgCodec)
......@@ -84,17 +84,16 @@ func InitialSession(session getty.Session, client *Client) (err error) {
}
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() {
return
}
getty.GetLogger().Warn("=================redial->offline ==============")
if _, _, err := session.WritePkg(OfflinePacket, time.Second*10); err != nil {
getty.GetLogger().Warnf("write offline to server error %s", err.Error())
log.Run().Warn("redial send offline message ...")
if _, _, err := session.WritePkg(OfflinePacket, 0); err != nil {
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)
getty.GetLogger().Warnf("=================redial->wait %v ==============", client.config.Redial.WaitTime)
time.Sleep(client.config.Redial.WaitTime)
infra.Redial(client.config, session)
}
......@@ -4,7 +4,7 @@ import (
"os/exec"
"strings"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/log"
)
var (
......@@ -30,7 +30,7 @@ func (e *ShellCmd) Handle(param map[string]string, callback Callback) {
callback.OnCmdResponse(false, cmdErrorMap)
return
}
getty.GetLogger().Infof("exec cmd %s", targetCmd)
log.Run().Infof("exec cmd %s", targetCmd)
trueCmd := strings.Split(targetCmd, " ")
......@@ -38,7 +38,7 @@ func (e *ShellCmd) Handle(param map[string]string, callback Callback) {
out, err := cmd.CombinedOutput()
if err != nil {
getty.GetLogger().Errorf("exec error %+v", err)
log.Run().Errorf("exec error %+v", err)
return
}
......
......@@ -50,8 +50,9 @@ const (
WaitTimeout = time.Minute
KeepAliveTimeout = time.Second * 10
SessionTimeout = time.Minute * 5
UpstreamTimeout = time.Minute
SessionTimeout = time.Minute * 5
HeartBeatTimeout = time.Second * 30
UpstreamTimeout = time.Minute
)
const (
......
......@@ -5,12 +5,10 @@ dns_server = 114.114.114.114:53
;local_ip = 192.168.0.100
;for performance pprof 0 is close
pprof_port = 16666
disable_update = false
; default is info
log_level = 1
reconn_interval = 5s
;client_id =
log_path = "./majora.log"
net_check_interval = 5s
net_check_url = https://www.baidu.com
[extra]
account = superman
......@@ -22,5 +20,5 @@ account = superman
; windows bat 脚本的绝对路径
; *nix shell脚本的绝对路径 D:\redial\redial.bat
;exec_path = ls
redial_duration = 30s
wait_time = 10s
;redial_duration = 30s
;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
;bind to local ip
;local_ip = 192.168.0.100
;for performance pprof 0 is close
;pprof_port = 0
disable_update = false
; default is info
log_level = 2
log_level = 1
reconn_interval = 5s
;client_id =
log_path = /root/majora.log
net_check_interval = 5s
net_check_url = https://www.baidu.com
[extra]
account = superman
[redial]
command = /bin/bash
exec_path = /root/ppp_auto_with_auth.sh
redial_duration = 10m
wait_time = 10s
;command = /bin/bash
;exec_path = /root/ppp_redial.sh
;redial_duration = 10m
;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
rm -fr /usr/lib/systemd/system/majora.service
# create link
ln -s /root/majora.service /usr/lib/systemd/system/majora.service
sudo rm -fr /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 @@
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 exec.sh
rm -fr start.sh
......@@ -11,21 +9,11 @@ rm -fr majora.ini
rm -fr majora.service
rm -fr majora-dev.ini
rm -fr majora.log
rm -fr output
rm -fr std.log
mv -f majora-cli*/* .
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
tar -zxvf majora-cli.tar.gz
echo "restart..."
systemctl restart majora.service
mv -f majora-cli*/* .
systemctl status majora.service
exec bash ./start.sh
......@@ -3,8 +3,8 @@ module virjar.com/majora-go
go 1.17
require (
github.com/adamweixuan/getty v1.8.4
github.com/adamweixuan/gostnops v1.11.20-0.20211029124314-3f0589fceea6
github.com/adamweixuan/getty v0.0.1
github.com/adamweixuan/gostnops v0.0.1
github.com/google/uuid v1.3.0
gopkg.in/ini.v1 v1.63.2
)
......
github.com/adamweixuan/getty v1.8.4 h1:YhHVYwrSqky3cMrPV5/dfHUwrhc9XB7emobVXTe1wY4=
github.com/adamweixuan/getty v1.8.4/go.mod h1:+P0Afn1ky1/4q96pjJmR6GssmVYXN+2dZ/0BxkIDpGo=
github.com/adamweixuan/gostnops v1.11.20-0.20211029124314-3f0589fceea6 h1:UGMsACjkGfNRKCz5U8ijtkpKL8o/25rGHxTV1adWjak=
github.com/adamweixuan/gostnops v1.11.20-0.20211029124314-3f0589fceea6/go.mod h1:zZYjPhU2+ujyEOWWE0l1pEdf5H4CyfiMG//rSpNjwcQ=
github.com/adamweixuan/getty v0.0.1 h1:ze1++8zi9yF7QJnp9p1pbCn/7n5Ex5xrJKlFzpOu5q8=
github.com/adamweixuan/getty v0.0.1/go.mod h1:SnxNiA40Am3aSxaDnAYBBbd7iz9BtKUign8x1jNh2TU=
github.com/adamweixuan/gostnops v0.0.1 h1:oBfrRgBoRyaGjBTfq0DGH07jARS4OqN7jbSv1Mn05Fg=
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/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
......
......@@ -2,10 +2,11 @@ package infra
import (
"crypto/tls"
"math/rand"
"net/http"
"time"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/log"
)
// 网络检测
......@@ -14,13 +15,23 @@ var (
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 (
defTimeout = time.Second * 5
baiduUrl = "https://www.baidu.com"
)
func init() {
rand.Seed(time.Now().UnixNano())
httpcli = &http.Client{
Transport: &http.Transport{
TLSHandshakeTimeout: defTimeout,
......@@ -35,14 +46,18 @@ func init() {
func Ping(url string) bool {
resp, err := httpcli.Head(url)
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
}
defer resp.Body.Close()
getty.GetLogger().Warnf("ping %s status code %d", url, resp.StatusCode)
return resp.StatusCode == http.StatusOK
return resp.StatusCode > 0
}
func RandomPing() bool {
return Ping(RandUrl())
}
func PingBaidu() bool {
return Ping(baiduUrl)
func RandUrl() string {
rand.Seed(time.Now().UnixNano())
return pingUrl[rand.Intn(len(pingUrl))]
}
......@@ -3,7 +3,7 @@ package infra
import (
"net"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/log"
)
const (
......@@ -18,19 +18,19 @@ func GetIpByName(netname string) string {
ni, err := net.InterfaceByName(netname)
if err != nil {
getty.GetLogger().Warnf("get %s ip error %s", netname, err)
log.Run().Warnf("get %s ip error %s", netname, err)
return ""
}
addrs, err := ni.Addrs()
if err != nil {
getty.GetLogger().Warnf("get ip addr err %s", err)
log.Run().Warnf("get ip addr err %s", err)
return ""
}
if len(addrs) == 0 {
getty.GetLogger().Warnf("get ip addr empty ")
log.Run().Warnf("get ip addr empty ")
return ""
}
......@@ -43,7 +43,7 @@ func GetIpByName(netname string) string {
}
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 ipv4Addr.String()
......
......@@ -5,19 +5,19 @@ import (
"os/exec"
"time"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/log"
)
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.Stdin = os.Stdin
cmd.Stdout = os.Stdout
getty.GetLogger().Debugf("Restart ... %+v", cmd)
log.Run().Debugf("Restart ... %+v", cmd)
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() {
func RestartBySignal(signal chan struct{}) {
go func() {
time.Sleep(time.Second * 5)
getty.GetLogger().Infof("=============cleanup==============")
signal <- struct{}{}
}()
......@@ -34,8 +33,8 @@ func RestartBySignal(signal chan struct{}) {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
getty.GetLogger().Infof("[RestartBySignal] ... %+v", cmd)
log.Run().Infof("[RestartBySignal] ... %+v", cmd)
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 (
"time"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/log"
"virjar.com/majora-go/model"
)
......@@ -15,34 +16,43 @@ const (
)
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()
retry := 0
defer func(start time.Time) {
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())
}(time.Now())
for {
retry++
status := command(cfg)
pingBaidu := PingBaidu()
getty.GetLogger().Warnf("[redial] net check: %d->%v", retry, pingBaidu)
pingBaidu := RandomPing()
log.Run().Infof("[redial] net check: %d->%v", retry, pingBaidu)
if pingBaidu && status {
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 {
execPath := cfg.Redial.ExecPath
if len(execPath) == 0 {
getty.GetLogger().Warn("[redial] exec file is empty")
log.Run().Warn("[redial] exec file is empty")
return true
}
command := cfg.Redial.Command
if len(command) == 0 {
getty.GetLogger().Warn("[redial] command is empty")
log.Run().Warn("[redial] command is empty")
return true
}
......@@ -54,9 +64,9 @@ func command(cfg *model.Configure) bool {
cmd := exec.Command(command, args, execPath)
output, err := cmd.Output()
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
}
getty.GetLogger().Warnf("[redial] success %+v resp:%s", cmd, string(output))
log.Run().Infof("[redial] success %+v resp:%s", cmd, string(output))
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
import (
"time"
"github.com/adamweixuan/getty"
"github.com/google/uuid"
"gopkg.in/ini.v1"
"virjar.com/majora-go/common"
......@@ -21,18 +20,17 @@ type Extra struct {
}
type Configure struct {
DisableUpdate bool `ini:"disable_update" json:"disable_update"`
LogLevel int `ini:"log_level" json:"log_level"`
PprofPort int `ini:"pprof_port" json:"pprof_port"`
TunnelAddr string `ini:"tunnel_addr" json:"tunnel_addr"`
DNSServer string `ini:"dns_server" json:"dns_server"`
LocalAddr string `ini:"local_ip" json:"local_ip"`
ReconnInterval time.Duration `ini:"reconn_interval" json:"reconn_interval"`
ClientID string `ini:"client_id" json:"client_id"`
LogPath string `ini:"log_path" json:"log_path"`
Extra Extra `ini:"extra" json:"extra"`
Redial Redial `ini:"redial" json:"redial"`
LogLevel int `ini:"log_level" json:"log_level"`
PprofPort int `ini:"pprof_port" json:"pprof_port"`
TunnelAddr string `ini:"tunnel_addr" json:"tunnel_addr"`
DNSServer string `ini:"dns_server" json:"dns_server"`
LocalAddr string `ini:"local_ip" json:"local_ip"`
ReconnInterval time.Duration `ini:"reconn_interval" json:"reconn_interval"`
ClientID string `ini:"client_id" json:"client_id"`
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"`
Redial Redial `ini:"redial" json:"redial"`
}
const (
......@@ -41,7 +39,6 @@ const (
func NewDefMajoraConf() *Configure {
return &Configure{
DisableUpdate: false,
LogLevel: 1,
PprofPort: 0,
TunnelAddr: common.DefNatAddr,
......@@ -60,7 +57,7 @@ func NewDefMajoraConf() *Configure {
func InitConf(path string) *Configure {
conf := NewDefMajoraConf()
if err := ini.MapTo(conf, path); err != nil {
getty.GetLogger().Errorf("InitConf with error %s, use default...", err.Error())
panic(err)
}
return conf
}
......
......@@ -3,8 +3,8 @@ package protocol
import (
"bufio"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/common"
"virjar.com/majora-go/log"
)
type Decoder interface {
......@@ -33,7 +33,7 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket
// type
msgType, err := common.ReadByte(reader)
if err != nil {
getty.GetLogger().Errorf("read type error %+v", err)
log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize
}
pack = &MajoraPacket{}
......@@ -42,20 +42,20 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket
// num
pack.SerialNumber, err = common.ReadInt64(reader)
if err != nil {
getty.GetLogger().Errorf("read type error %+v", err)
log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize
}
// extra size
extraSize, err := common.ReadByte(reader)
if err != nil {
getty.GetLogger().Errorf("read type error %+v", err)
log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize
}
extra, err := common.ReadN(int(extraSize), reader)
if err != nil {
getty.GetLogger().Errorf("read type error %+v", err)
log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize
}
pack.Extra = string(extra)
......@@ -63,14 +63,14 @@ func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket
// dataFrame
dataSize := int(frameLen) - common.TypeSize - common.SerialNumberSize - common.ExtraSize - int(extraSize)
if dataSize < 0 {
getty.GetLogger().Errorf("read type error %+v", err)
log.Run().Errorf("read type error %+v", err)
return nil, common.ErrInvalidSize
}
if dataSize > 0 {
data, err := common.ReadN(dataSize, reader)
if err != nil {
getty.GetLogger().Errorf("read type error %+v", err)
log.Run().Errorf("read type error %+v", err)
}
pack.Data = data
}
......
......@@ -3,7 +3,7 @@ package protocol
import (
"bytes"
"github.com/adamweixuan/getty"
"virjar.com/majora-go/log"
)
func EncodeExtra(extra map[string]string) []byte {
......@@ -33,7 +33,7 @@ func DecodeExtra(input []byte) map[string]string {
headerSize, err := buffer.ReadByte()
if err != nil {
getty.GetLogger().Errorf("DecodeExtra error %+v", err)
log.Run().Errorf("DecodeExtra error %+v", err)
return 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