Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
majora-go
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
majora
majora-go
Commits
7aeb66e2
Commit
7aeb66e2
authored
Nov 13, 2021
by
wei.xuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1112
parent
76aca1d4
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
398 additions
and
454 deletions
+398
-454
.gitignore
.gitignore
+2
-1
Makefile
Makefile
+3
-2
cli.go
cli.go
+57
-36
client.go
client/client.go
+37
-2
codec.go
client/codec.go
+18
-17
event.go
client/event.go
+78
-58
eventlistener.go
client/eventlistener.go
+7
-7
getty.go
client/getty.go
+14
-15
shell.go
client/shell.go
+3
-3
common.go
common/common.go
+3
-2
majora-dev.ini
conf/majora-dev.ini
+4
-6
majora.ini
conf/majora.ini
+8
-11
majora.service
conf/majora.service
+0
-15
start.sh
conf/start.sh
+11
-7
update.sh
conf/update.sh
+5
-17
go.mod
go.mod
+2
-2
go.sum
go.sum
+4
-4
httpping.go
infra/httpping.go
+23
-8
ip.go
infra/ip.go
+5
-5
process.go
infra/process.go
+6
-7
redail.go
infra/redail.go
+18
-8
updater.go
infra/updater.go
+0
-167
logger.go
log/logger.go
+69
-0
config.go
model/config.go
+12
-15
decoder.go
protocol/decoder.go
+7
-7
extra.go
protocol/extra.go
+2
-2
extra_test.go
protocol/extra_test.go
+0
-19
release.md
release.md
+0
-11
No files found.
.gitignore
View file @
7aeb66e2
...
...
@@ -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
Makefile
View file @
7aeb66e2
...
...
@@ -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
cli.go
View file @
7aeb66e2
...
...
@@ -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
d
isableUpdate
bool
configure
string
logLevel
int
pprofPort
int
natServer
string
account
string
dnsServer
string
localAddr
string
d
aemon
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
(
&
d
isableUpdate
,
"disableUpdate"
,
false
,
"disable self update
"
)
flag
.
BoolVar
(
&
d
aemon
,
"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
<-
sig
s
:
case
<-
sig
nalChan
:
time
.
Sleep
(
time
.
Second
*
3
)
getty
.
GetLogger
()
.
Warn
(
"main process exit..."
)
log
.
Run
()
.
Warn
(
"main process exit..."
)
}
}
client/client.go
View file @
7aeb66e2
...
...
@@ -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
)
}
}()
}
client/codec.go
View file @
7aeb66e2
...
...
@@ -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
()
.
Error
f
(
"[PacketCodec] buf not enough %d|%d"
,
reader
.
Len
(),
frameLen
)
log
.
Run
()
.
Debug
f
(
"[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
}
...
...
client/event.go
View file @
7aeb66e2
package
client
import
(
"fmt"
"net"
"strings"
"sync"
...
...
@@ -9,6 +8,7 @@ import (
"github.com/adamweixuan/getty"
"virjar.com/majora-go/common"
"virjar.com/majora-go/log"
"virjar.com/majora-go/protocol"
)
...
...
@@ -19,34 +19,39 @@ var (
func
(
client
*
Client
)
handleHeartbeat
(
session
getty
.
Session
)
{
go
func
()
{
if
_
,
_
,
err
:=
session
.
WritePkg
(
HeartbeatPacket
,
time
.
Second
*
3
);
err
!=
nil
{
getty
.
GetLogger
()
.
Errorf
(
"handleHeartbeat error %+v %v"
,
err
,
session
.
IsClosed
())
if
_
,
_
,
err
:=
session
.
WritePkg
(
HeartbeatPacket
,
common
.
HeartBeatTimeout
);
err
!=
nil
{
log
.
Heart
()
.
Errorf
(
"handleHeartbeat error %+v %v"
,
err
,
session
.
IsClosed
())
}
else
{
getty
.
GetLogger
()
.
Infof
(
"handleHeartbeat success %v"
,
session
.
IsClosed
()
)
log
.
Heart
()
.
Infof
(
"handleHeartbeat success"
)
}
}()
}
func
(
client
*
Client
)
handleConnect
(
packet
*
protocol
.
MajoraPacket
,
session
getty
.
Session
)
{
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
,
":"
)
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
)
return
}
addr
:=
fmt
.
Sprintf
(
"%s:%s"
,
hostPort
[
0
],
hostPort
[
1
])
dialer
:=
net
.
Dialer
{
Timeout
:
common
.
UpstreamTimeout
,
LocalAddr
:
client
.
localAddr
,
}
conn
,
err
:=
dialer
.
Dial
(
common
.
TCP
,
addr
)
conn
,
err
:=
dialer
.
Dial
(
common
.
TCP
,
packet
.
Extra
)
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
)
return
}
...
...
@@ -54,17 +59,22 @@ func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty
tcpConn
:=
conn
.
(
*
net
.
TCPConn
)
_
=
tcpConn
.
SetNoDelay
(
true
)
_
=
tcpConn
.
SetKeepAlive
(
true
)
client
.
AddConnection
(
packet
,
tcpConn
,
addr
)
client
.
AddConnection
(
packet
,
tcpConn
,
packet
.
Extra
)
majoraPacket
:=
protocol
.
TypeConnectReady
.
CreatePacket
()
majoraPacket
.
SerialNumber
=
packet
.
SerialNumber
majoraPacket
.
Extra
=
client
.
config
.
ClientID
if
_
,
_
,
err
:=
session
.
WritePkg
(
majoraPacket
,
common
.
SessionTimeout
);
err
!=
nil
{
getty
.
GetLogger
()
.
Errorf
(
"[handleConnect] %d->write pkg to nat server with error %s"
,
packet
.
SerialNumber
,
if
session
.
IsClosed
()
{
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
())
client
.
closeVirtualConnection
(
session
,
packet
.
SerialNumber
)
return
}
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
)
}(
packet
)
...
...
@@ -72,9 +82,12 @@ func (client *Client) handleConnect(packet *protocol.MajoraPacket, session getty
func
(
client
*
Client
)
handleTransfer
(
packet
*
protocol
.
MajoraPacket
,
session
getty
.
Session
)
{
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
)
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
)
return
}
...
...
@@ -82,52 +95,56 @@ func (client *Client) handleTransfer(packet *protocol.MajoraPacket, session gett
cnt
,
err
:=
conn
.
Write
(
packet
.
Data
)
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
)
return
}
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
)
client
.
closeVirtualConnection
(
session
,
packet
.
SerialNumber
)
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
)
}
func
(
client
*
Client
)
handleUpStream
(
conn
*
net
.
TCPConn
,
packet
*
protocol
.
MajoraPacket
,
session
getty
.
Session
)
{
getty
.
GetLogger
()
.
Infof
(
"[handleUpStream] %d-> handleUpStream start..."
,
packet
.
SerialNumber
)
defer
func
()
{
_
=
conn
.
Close
()
}()
for
{
buf
:=
make
([]
byte
,
common
.
BufSize
)
// 4k
cnt
,
err
:=
conn
.
Read
(
buf
)
if
err
!=
nil
{
getty
.
GetLogger
()
.
Warnf
(
"[handleUpStream] %d->read with error:%+v,l:%s->r:%s"
,
packet
.
SerialNumber
,
err
,
conn
.
LocalAddr
(),
conn
.
RemoteAddr
())
client
.
OnClose
(
session
,
conn
,
packet
.
SerialNumber
)
break
}
pack
:=
protocol
.
TypeTransfer
.
CreatePacket
()
pack
.
Data
=
buf
[
:
cnt
]
pack
.
SerialNumber
=
packet
.
SerialNumber
if
_
,
_
,
err
:=
session
.
WritePkg
(
pack
,
common
.
SessionTimeout
);
err
!=
nil
{
getty
.
GetLogger
()
.
Errorf
(
"[handleUpStream] %d-> write to server fail %+v"
,
packet
.
SerialNumber
,
err
.
Error
())
client
.
OnClose
(
session
,
conn
,
packet
.
SerialNumber
)
break
}
else
{
getty
.
GetLogger
()
.
Debugf
(
"[handleUpStream] %d->success %+v"
,
packet
.
SerialNumber
,
string
(
packet
.
Data
))
go
func
()
{
log
.
Event
()
.
Debugf
(
"[handleUpStream] %d-> handleUpStream start..."
,
packet
.
SerialNumber
)
defer
func
(
start
time
.
Time
)
{
_
=
conn
.
Close
()
log
.
Latency
()
.
Infof
(
"%d handleUpStream total latency %v"
,
packet
.
SerialNumber
,
time
.
Since
(
start
))
}(
time
.
Now
())
for
{
buf
:=
make
([]
byte
,
common
.
BufSize
)
// 4k
cnt
,
err
:=
conn
.
Read
(
buf
)
if
err
!=
nil
{
log
.
Event
()
.
Debugf
(
"[handleUpStream] %d->read with error:%+v,l:%s->r:%s"
,
packet
.
SerialNumber
,
err
,
conn
.
LocalAddr
(),
conn
.
RemoteAddr
())
client
.
OnClose
(
session
,
conn
,
packet
.
SerialNumber
)
break
}
pack
:=
protocol
.
TypeTransfer
.
CreatePacket
()
pack
.
Data
=
buf
[
:
cnt
]
pack
.
SerialNumber
=
packet
.
SerialNumber
if
_
,
_
,
err
:=
session
.
WritePkg
(
pack
,
0
);
err
!=
nil
{
log
.
Event
()
.
Errorf
(
"[handleUpStream] %d-> write to server fail %+v"
,
packet
.
SerialNumber
,
err
.
Error
())
client
.
OnClose
(
session
,
conn
,
packet
.
SerialNumber
)
break
}
else
{
log
.
Event
()
.
Debugf
(
"[handleUpStream] %d->success %+v"
,
packet
.
SerialNumber
,
string
(
packet
.
Data
))
}
}
}
}()
}
func
(
client
*
Client
)
handleDisconnectMessage
(
session
getty
.
Session
,
packet
*
protocol
.
MajoraPacket
)
{
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
{
client
.
OnClose
(
session
,
conn
.
(
net
.
Conn
),
packet
.
SerialNumber
)
}
...
...
@@ -136,7 +153,7 @@ func (client *Client) handleDisconnectMessage(session getty.Session, packet *pro
func
(
client
*
Client
)
handleControlMessage
(
_
*
protocol
.
MajoraPacket
)
{
go
func
()
{
getty
.
GetLogger
()
.
Debugf
(
"handleControlMessage"
)
log
.
Event
()
.
Debugf
(
"handleControlMessage"
)
}()
}
...
...
@@ -149,47 +166,50 @@ func (client *Client) handleDestroyMessage() {
func
(
client
*
Client
)
AddConnection
(
packet
*
protocol
.
MajoraPacket
,
conn
*
net
.
TCPConn
,
addr
string
)
{
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
)
getty
.
GetLogger
()
.
Info
f
(
"[AddConnection] %d->%s success"
,
packet
.
SerialNumber
,
addr
)
log
.
Event
()
.
Debug
f
(
"[AddConnection] %d->%s success"
,
packet
.
SerialNumber
,
addr
)
}
// OnClose 1. 本地缓存删除 2. 关闭连接 3. 通知natserver
func
(
client
*
Client
)
OnClose
(
netSession
getty
.
Session
,
upStreamSession
net
.
Conn
,
serialNumber
int64
)
{
defer
func
()
{
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
)
_
=
upStreamSession
.
Close
()
client
.
closeVirtualConnection
(
netSession
,
serialNumber
)
}
//closeVirtualConnection disconnect to server
func
(
client
*
Client
)
closeVirtualConnection
(
session
getty
.
Session
,
serialNumber
int64
)
{
getty
.
GetLogger
()
.
Warnf
(
"[closeVirtualConnection] %d->session status:%v"
,
serialNumber
,
session
.
IsClosed
())
if
!
session
.
IsClosed
()
{
majoraPacket
:=
protocol
.
TypeDisconnect
.
CreatePacket
()
majoraPacket
.
SerialNumber
=
serialNumber
majoraPacket
.
Extra
=
client
.
config
.
ClientID
if
_
,
_
,
err
:=
session
.
WritePkg
(
majoraPacket
,
common
.
SessionTimeout
);
err
!=
nil
{
getty
.
GetLogger
()
.
Errorf
(
"[closeVirtualConnection] ->%d error %s"
,
serialNumber
,
err
.
Error
())
}
log
.
Event
()
.
Debugf
(
"[closeVirtualConnection] %d->session closed %v"
,
serialNumber
,
session
.
IsClosed
())
if
session
.
IsClosed
()
{
log
.
Event
()
.
Warnf
(
"[closeVirtualConnection] %d->session is closed"
,
serialNumber
)
return
}
majoraPacket
:=
protocol
.
TypeDisconnect
.
CreatePacket
()
majoraPacket
.
SerialNumber
=
serialNumber
majoraPacket
.
Extra
=
client
.
config
.
ClientID
if
allCnt
,
sendCnt
,
err
:=
session
.
WritePkg
(
majoraPacket
,
0
);
err
!=
nil
{
log
.
Event
()
.
Warnf
(
"[closeVirtualConnection] ->%d error %s session closed %v allCnt %d sendCnt %d"
,
serialNumber
,
err
.
Error
(),
session
.
IsClosed
(),
allCnt
,
sendCnt
)
}
}
func
(
client
*
Client
)
CloseAll
(
session
getty
.
Session
)
{
defer
func
()
{
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
{
serialNumber
:=
key
.
(
int64
)
conn
,
_
:=
value
.
(
*
net
.
TCPConn
)
getty
.
GetLogger
()
.
Info
f
(
"[CloseAll] close serialNumber -> %d"
,
serialNumber
)
log
.
Event
()
.
Debug
f
(
"[CloseAll] close serialNumber -> %d"
,
serialNumber
)
client
.
OnClose
(
session
,
conn
,
serialNumber
)
return
true
})
...
...
client/eventlistener.go
View file @
7aeb66e2
...
...
@@ -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
()
.
Warn
f
(
"[OnOpen] registe to %s success"
,
m
.
client
.
config
.
TunnelAddr
)
log
.
Event
()
.
Info
f
(
"[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
:
...
...
client/getty.go
View file @
7aeb66e2
...
...
@@ -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
*
1
0
);
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
)
}
client/shell.go
View file @
7aeb66e2
...
...
@@ -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
}
...
...
common/common.go
View file @
7aeb66e2
...
...
@@ -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
(
...
...
conf/majora-dev.ini
View file @
7aeb66e2
...
...
@@ -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
conf/majora.ini
View file @
7aeb66e2
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
conf/majora.service
deleted
100644 → 0
View file @
76aca1d4
[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
conf/start.sh
View file @
7aeb66e2
#!/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
conf/update.sh
View file @
7aeb66e2
...
...
@@ -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
go.mod
View file @
7aeb66e2
...
...
@@ -3,8 +3,8 @@ module virjar.com/majora-go
go 1.17
require (
github.com/adamweixuan/getty v
1.8.4
github.com/adamweixuan/gostnops v
1.11.20-0.20211029124314-3f0589fceea6
github.com/adamweixuan/getty v
0.0.1
github.com/adamweixuan/gostnops v
0.0.1
github.com/google/uuid v1.3.0
gopkg.in/ini.v1 v1.63.2
)
...
...
go.sum
View file @
7aeb66e2
github.com/adamweixuan/getty v
1.8.4 h1:YhHVYwrSqky3cMrPV5/dfHUwrhc9XB7emobVXTe1wY4
=
github.com/adamweixuan/getty v
1.8.4/go.mod h1:+P0Afn1ky1/4q96pjJmR6GssmVYXN+2dZ/0BxkIDpGo
=
github.com/adamweixuan/gostnops v
1.11.20-0.20211029124314-3f0589fceea6 h1:UGMsACjkGfNRKCz5U8ijtkpKL8o/25rGHxTV1adWjak
=
github.com/adamweixuan/gostnops v
1.11.20-0.20211029124314-3f0589fceea6/go.mod h1:zZYjPhU2+ujyEOWWE0l1pEdf5H4CyfiMG//rSpNjwcQ
=
github.com/adamweixuan/getty v
0.0.1 h1:ze1++8zi9yF7QJnp9p1pbCn/7n5Ex5xrJKlFzpOu5q8
=
github.com/adamweixuan/getty v
0.0.1/go.mod h1:SnxNiA40Am3aSxaDnAYBBbd7iz9BtKUign8x1jNh2TU
=
github.com/adamweixuan/gostnops v
0.0.1 h1:oBfrRgBoRyaGjBTfq0DGH07jARS4OqN7jbSv1Mn05Fg
=
github.com/adamweixuan/gostnops v
0.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=
...
...
infra/httpping.go
View file @
7aeb66e2
...
...
@@ -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
))]
}
infra/ip.go
View file @
7aeb66e2
...
...
@@ -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
()
...
...
infra/process.go
View file @
7aeb66e2
...
...
@@ -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
)
}
}
infra/redail.go
View file @
7aeb66e2
...
...
@@ -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
()
.
Warn
f
(
"[redial] start, session is close :%d"
,
session
.
IsClosed
())
log
.
Run
()
.
Info
f
(
"[redial] start, session is close :%d"
,
session
.
IsClosed
())
beforeIp
:=
GetPPP
()
retry
:=
0
defer
func
(
start
time
.
Time
)
{
newIp
:=
GetPPP
()
getty
.
GetLogger
()
.
Warn
f
(
"[redial] retry %d, cost %v, ip change %s -> %s, session is close:%v"
,
log
.
Run
()
.
Info
f
(
"[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
()
.
Warn
f
(
"[redial] net check: %d->%v"
,
retry
,
pingBaidu
)
pingBaidu
:=
RandomPing
()
log
.
Run
()
.
Info
f
(
"[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
()
.
Warn
f
(
"[redial] success %+v resp:%s"
,
cmd
,
string
(
output
))
log
.
Run
()
.
Info
f
(
"[redial] success %+v resp:%s"
,
cmd
,
string
(
output
))
return
true
}
infra/updater.go
deleted
100644 → 0
View file @
76aca1d4
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
//}
log/logger.go
0 → 100644
View file @
7aeb66e2
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
}
model/config.go
View file @
7aeb66e2
...
...
@@ -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
}
...
...
protocol/decoder.go
View file @
7aeb66e2
...
...
@@ -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
}
...
...
protocol/extra.go
View file @
7aeb66e2
...
...
@@ -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
)
...
...
protocol/extra_test.go
deleted
100644 → 0
View file @
76aca1d4
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
))
}
release.md
deleted
100644 → 0
View file @
76aca1d4
# v0.0.3
-
[
x
]
重播 功能
-
[
x
]
执行脚本 执行间隔
-
[
]
http2 fix 抓包
-
[
x
]
重连时间 可配置
-
[
x
]
线程安全check
-
[
x
]
支持config 文件
-
[
x
]
代码的bug fix write/flush
-
[
]
control
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment