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

feat: 调整结构 支持动态库生成

parent 7e97decb
project_name: echocli
project_name: majora-go
before:
hooks:
# You may remove this if you don't use go modules.
......@@ -30,7 +30,7 @@ builds:
gcflags:
- all=-trimpath={{.Env.GOPATH}}
ldflags:
- -s -w -X app.Version={{.Version}}
- -s -w -X virjar.com/majora/main.Version=v0.01.beta
# tags:
# - osusergo
# - netgo
......@@ -42,10 +42,12 @@ archives:
linux: Linux
windows: Windows
amd64: x86_64
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
......
build:
CGO_ENABLE=0 go build -ldflags '-w -s' -o majora-cli
CGO_ENABLE=0 go build -trimpath -ldflags '-w -s' -o majora-cli
release:
goreleaser build --rm-dist --snapshot --single-target
......@@ -8,7 +8,11 @@ release:
releaseall:
goreleaser build --rm-dist --snapshot
sdk:
CGO_ENABLED=1 go build -trimpath -ldflags '-s -w --extldflags "-static -fpic"' --buildmode=c-shared -o libmajora.so lib/sdk.go
clean:
rm -fr dist
rm -fr majora-cli
\ No newline at end of file
rm -fr majora-cli
rm -fr libmajora.so
rm -fr libmajora.h
\ No newline at end of file
......@@ -2,14 +2,13 @@ package main
import (
"flag"
"fmt"
"log"
"net/http"
_ "net/http/pprof" //nolint:gosec
)
var (
Version string
BuildDate string
"virjar.com/majora/client"
"virjar.com/majora/common"
"virjar.com/majora/logger"
)
var (
......@@ -17,13 +16,14 @@ var (
pprof bool
debugAddr string
natServer string
Version string
)
func init() {
flag.IntVar(&logLevel, "log", 1, "log logLevel")
flag.BoolVar(&pprof, "pprof", false, "pprof")
flag.StringVar(&debugAddr, "debugPort", "127.0.0.1:6060", "debugPort")
flag.StringVar(&natServer, "natServer", fmt.Sprintf("%s:%d", DefNatServerHost, DefPort), "natServer")
flag.BoolVar(&pprof, "pprof", false, "enable pprof")
flag.StringVar(&debugAddr, "debugPort", common.PprofAddr, "debugPort")
flag.StringVar(&natServer, "natServer", common.DefNatAddr, "natServer")
flag.Parse()
}
......@@ -33,15 +33,13 @@ func initPprof() {
return
}
go func() {
logger.Fatal().Err(http.ListenAndServe(debugAddr, nil))
log.Fatal(http.ListenAndServe(debugAddr, nil))
}()
}
func main() {
InitLogger(logLevel)
initPprof()
//logger.Info().Msgf("build in %s, version %s", BuildDate, Version)
NewClient(WithNatServerAddr(natServer)).StartUp()
logger.Info().Msgf("current version %s", Version)
client.NewClient(client.WithNatServerAddr(natServer))
select {}
}
package main
package client
import (
"bufio"
......@@ -11,48 +11,40 @@ import (
"time"
"github.com/google/uuid"
)
const (
DefNatServerHost = "majora.virjar.com"
DefPort = 5879
BufSize = 1000
"virjar.com/majora/common"
"virjar.com/majora/logger"
"virjar.com/majora/protocol"
)
func NewOptions() *Options {
return &Options{
natHostPort: fmt.Sprintf("%s:%d", DefNatServerHost, DefPort),
clientID: uuid.New().String(),
bufSize: BufSize,
NatHostPort: common.DefNatAddr,
ClientID: uuid.New().String(),
}
}
type Client struct {
options *Options
Options *Options
natTunnel atomic.Value
codec ICodec
Codec protocol.ICodec
connStore sync.Map
}
func NewClient(opts ...Option) *Client {
func NewClient(opts ...Option) {
options := NewOptions()
for _, opt := range opts {
opt(options)
}
return &Client{options: options, codec: NewDefCodec()}
}
func NewDefClient() *Client {
options := NewOptions()
return &Client{options: options, codec: NewDefCodec()}
client := &Client{Options: options, Codec: protocol.NewDefCodec()}
client.StartUp()
}
func (client *Client) StartUp() {
if client.options == nil {
client.options = NewOptions()
logger.Warn().Msgf("use default nat host %s port %d", DefNatServerHost, DefPort)
if client.Options == nil {
client.Options = NewOptions()
logger.Warn().Msgf("use default nat addr %s", common.DefNatServerHost)
}
client.connect()
client.register()
......@@ -60,9 +52,9 @@ func (client *Client) StartUp() {
}
func (client *Client) register() {
packet := TypeRegister.CreatePacket()
packet.Extra = client.options.clientID
encode, _ := client.codec.Encode(packet)
packet := protocol.TypeRegister.CreatePacket()
packet.Extra = client.Options.ClientID
encode, _ := client.Codec.Encode(packet)
if err := client.WriteAndFlush(encode); err != nil {
logger.Error().Msgf("register to nat server with error %s", err.Error())
} else {
......@@ -74,7 +66,7 @@ func (client *Client) handleNatEvent() {
go func() {
for {
reader := bufio.NewReader(client.natTunnel.Load().(net.Conn))
majoraPacket, err := client.codec.Decode(reader)
majoraPacket, err := client.Codec.Decode(reader)
if errors.Is(err, io.EOF) {
logger.Error().Msgf("*********disconnect******")
client.reConnect()
......@@ -88,17 +80,17 @@ func (client *Client) handleNatEvent() {
logger.Debug().Msgf("receive packet type %s", majoraPacket.Ttype.ToString())
switch majoraPacket.Ttype {
case TypeHeartbeat:
case protocol.TypeHeartbeat:
client.handleHeartbeatMessage()
case TypeConnect:
case protocol.TypeConnect:
go client.handleConnect(majoraPacket)
case TypeTransfer:
case protocol.TypeTransfer:
go client.handleTransfer(majoraPacket)
case TypeDisconnect:
case protocol.TypeDisconnect:
go client.handleDisconnectMessage(majoraPacket)
case TypeControl:
case protocol.TypeControl:
go client.handleControlMessage(majoraPacket)
case TypeDestroy:
case protocol.TypeDestroy:
go client.handleDestroyMessage()
}
}
......@@ -107,18 +99,18 @@ func (client *Client) handleNatEvent() {
func (client *Client) reConnect() {
// 已经check 过
hostPort := client.options.natHostPort
hostPort := client.Options.NatHostPort
var (
conn net.Conn
err error
)
for {
conn, err = net.DialTimeout(TCP, hostPort, connTimeout)
conn, err = net.DialTimeout(common.TCP, hostPort, common.ConnTimeout)
if err != nil || conn == nil {
// 不断重试
logger.Info().Msgf("reconnect to nathost with error %+v ...", err)
time.Sleep(reConnInterval)
time.Sleep(common.ReConnInterval)
} else {
break
}
......@@ -130,13 +122,13 @@ func (client *Client) reConnect() {
}
func (client *Client) connect() {
hostPort := client.options.natHostPort
hostPort := client.Options.NatHostPort
if len(hostPort) == 0 {
panic("invalid nat host/port info")
}
conn, err := net.DialTimeout(TCP, hostPort, connTimeout)
conn, err := net.DialTimeout(common.TCP, hostPort, common.ConnTimeout)
if err != nil || conn == nil {
panic(fmt.Sprintf("connect to nathost %s with err %s", hostPort, err.Error()))
}
......
package main
package client
import (
"bufio"
......@@ -7,20 +7,24 @@ import (
"io"
"net"
"strings"
"virjar.com/majora/common"
"virjar.com/majora/logger"
"virjar.com/majora/protocol"
)
func (client *Client) handleHeartbeatMessage() {
go func() {
logger.Debug().Msg("receive heartbeat message from nat server")
packet := TypeHeartbeat.CreatePacket()
encode, _ := client.codec.Encode(packet)
packet := protocol.TypeHeartbeat.CreatePacket()
encode, _ := client.Codec.Encode(packet)
if err := client.WriteAndFlush(encode); err != nil {
logger.Error().Msgf("flush heart beat message error %s", err.Error())
}
}()
}
func (client *Client) handleConnect(packet *MajoraPacket) {
func (client *Client) handleConnect(packet *protocol.MajoraPacket) {
if len(packet.Extra) == 0 {
client.disconnect(packet, "empty extra")
client.connStore.Delete(packet.SerialNumber)
......@@ -41,18 +45,18 @@ func (client *Client) handleConnect(packet *MajoraPacket) {
)
addr := fmt.Sprintf("%s:%s", hostPort[0], hostPort[1])
conn, err = net.DialTimeout(TCP, addr, connTimeout)
conn, err = net.DialTimeout(common.TCP, addr, common.ConnTimeout)
if err != nil {
client.disconnect(packet, "connect to target host error "+err.Error())
return
}
client.connStore.Store(packet.SerialNumber, conn)
majoraPacket := TypeConnectReady.CreatePacket()
majoraPacket := protocol.TypeConnectReady.CreatePacket()
majoraPacket.SerialNumber = packet.SerialNumber
majoraPacket.Extra = client.options.clientID
majoraPacket.Extra = client.Options.ClientID
encode, _ := client.codec.Encode(majoraPacket)
encode, _ := client.Codec.Encode(majoraPacket)
if err := client.WriteAndFlush(encode); err != nil {
logger.Error().Msgf("handleConnect message error %s", err.Error())
_ = conn.Close()
......@@ -71,7 +75,7 @@ func (client *Client) WriteAndFlush(packet []byte) error {
return writer.Flush()
}
func (client *Client) handleTransfer(packet *MajoraPacket) {
func (client *Client) handleTransfer(packet *protocol.MajoraPacket) {
load, ok := client.connStore.Load(packet.SerialNumber)
if !ok || load == nil {
......@@ -90,7 +94,7 @@ func (client *Client) handleTransfer(packet *MajoraPacket) {
}
}
func (client *Client) handleConnection(conn net.Conn, packet *MajoraPacket) {
func (client *Client) handleConnection(conn net.Conn, packet *protocol.MajoraPacket) {
logger.Debug().Msg("handleConnection start...")
reader := bufio.NewReader(conn)
for {
......@@ -109,17 +113,17 @@ func (client *Client) handleConnection(conn net.Conn, packet *MajoraPacket) {
break
}
pack := TypeTransfer.CreatePacket()
pack := protocol.TypeTransfer.CreatePacket()
pack.Data = buf
pack.SerialNumber = packet.SerialNumber
encode, _ := client.codec.Encode(pack)
encode, _ := client.Codec.Encode(pack)
if err = client.WriteAndFlush(encode); err != nil {
logger.Error().Msgf("write to nat server error %+v", err)
}
}
}
func (client *Client) handleDisconnectMessage(packet *MajoraPacket) {
func (client *Client) handleDisconnectMessage(packet *protocol.MajoraPacket) {
go func() {
// delete from local cache
load, ok := client.connStore.Load(packet.SerialNumber)
......@@ -132,7 +136,7 @@ func (client *Client) handleDisconnectMessage(packet *MajoraPacket) {
}()
}
func (client *Client) handleControlMessage(packet *MajoraPacket) {
func (client *Client) handleControlMessage(packet *protocol.MajoraPacket) {
logger.Debug().Msgf("handleControlMessage %s", string(packet.Data))
}
......@@ -140,11 +144,11 @@ func (client *Client) handleDestroyMessage() {
}
func (client *Client) disconnect(packet *MajoraPacket, msg string) {
func (client *Client) disconnect(packet *protocol.MajoraPacket, msg string) {
logger.Info().Msgf("disconnect to server %s", msg)
disconnectCmd := TypeDisconnect.CreatePacket()
disconnectCmd := protocol.TypeDisconnect.CreatePacket()
disconnectCmd.SerialNumber = packet.SerialNumber
disconnectCmd.Data = []byte(msg)
encode, _ := client.codec.Encode(disconnectCmd)
encode, _ := client.Codec.Encode(disconnectCmd)
_ = client.WriteAndFlush(encode)
}
package main
package client
type (
Options struct {
natHostPort string
clientID string
bufSize int
NatHostPort string
ClientID string
}
Option func(*Options)
......@@ -12,12 +11,12 @@ type (
func WithNatServerAddr(natHostPort string) Option {
return func(options *Options) {
options.natHostPort = natHostPort
options.NatHostPort = natHostPort
}
}
func WithClientID(clientID string) Option {
return func(options *Options) {
options.clientID = clientID
options.ClientID = clientID
}
}
package main
package common
import (
"bytes"
......@@ -10,17 +10,10 @@ import (
const (
MagicSize = 8
HeaderSize = 12
BodySize = 4
TypeSize = 1
ExtraSize = 1
SerialNumberSize = 8
HeaderSizeSize = 1
KeyLenSize = 1
ValueLenSize = 1
MaxFrameLength = 8 * 1024
MAGIC = int64(0x6D616A6F72613031)
MAGIC = int64(0x6D616A6F72613031)
)
const (
......@@ -28,8 +21,15 @@ const (
)
const (
connTimeout = time.Second * 10
reConnInterval = time.Second * 5
DefNatServerHost = "majora.virjar.com"
DefPort = 5879
DefNatAddr = "majora.virjar.com:5879"
PprofAddr = "127.0.0.1:6060"
)
const (
ConnTimeout = time.Second * 10
ReConnInterval = time.Second * 5
)
var (
......
module ints.com/goecho
module virjar.com/majora
go 1.17
require (
github.com/google/uuid v1.3.0
github.com/rs/zerolog v1.24.0
github.com/rs/zerolog v1.25.0
)
......@@ -4,8 +4,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.24.0 h1:76ivFxmVSRs1u2wUwJVg5VZDYQgeH1JpoS6ndgr9Wy8=
github.com/rs/zerolog v1.24.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI=
github.com/rs/zerolog v1.25.0 h1:Rj7XygbUHKUlDPcVdoLyR91fJBsduXj5fRxyqIQj/II=
github.com/rs/zerolog v1.25.0/go.mod h1:7KHcEGe0QZPOm2IE4Kpb5rTh6n1h2hIgS5OOnu1rUaI=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
......
package main
import "C"
import (
"virjar.com/majora/client"
"virjar.com/majora/protocol"
)
//export NewDefClient
func NewDefClient(asyn C.int) {
options := client.NewOptions()
cli := &client.Client{Options: options, Codec: protocol.NewDefCodec()}
if int(asyn) > 0 {
go cli.StartUp()
} else {
cli.StartUp()
}
}
//export NewClientWithNatServer
func NewClientWithNatServer(addr *C.char, clientID *C.char, asyn C.int) {
options := client.NewOptions()
newAddr := C.GoString(addr)
newClientID := C.GoString(clientID)
if len(newAddr) > 0 {
options.NatHostPort = newAddr
}
if len(newClientID) > 0 {
options.ClientID = newClientID
}
cli := &client.Client{Options: options, Codec: protocol.NewDefCodec()}
if int(asyn) > 0 {
go cli.StartUp()
} else {
cli.StartUp()
}
}
func main() {}
/* Code generated by cmd/cgo; DO NOT EDIT. */
/* package command-line-arguments */
#line 1 "cgo-builtin-export-prolog"
#include <stddef.h> /* for ptrdiff_t below */
#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#endif
#endif
/* Start of preamble from import "C" comments. */
/* End of preamble from import "C" comments. */
/* Start of boilerplate cgo prologue. */
#line 1 "cgo-gcc-export-header-prolog"
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
/*
static assertion to make sure the file is being used on architecture
at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef _GoString_ GoString;
#endif
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
extern void NewDefClient(int asyn);
extern void NewClientWithNatServer(char* addr, char* clientID, int asyn);
#ifdef __cplusplus
}
#endif
File added
package main
package logger
import (
"os"
......@@ -11,8 +11,15 @@ var (
logger zerolog.Logger
)
func InitLogger(level int) {
zerolog.SetGlobalLevel(zerolog.Level(level))
func init() {
zerolog.SetGlobalLevel(zerolog.InfoLevel)
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339, NoColor: true}
logger = zerolog.New(output).With().Caller().Timestamp().Logger()
}
var (
Error = logger.Error
Info = logger.Info
Warn = logger.Warn
Debug = logger.Debug
)
package main
import (
"sync"
)
const (
bufSize = 1024 * 4 // 4k
)
var (
bytesPool = sync.Pool{
New: func() interface{} {
return make([]byte, bufSize)
},
}
)
func GetBuffer() *[]byte {
bytes := bytesPool.Get().([]byte)
return &bytes
}
func PutBuffer(buf *[]byte) {
bytesPool.Put((*buf)[:0])
}
package main
package protocol
import (
"bufio"
......
package main
package protocol
import (
"bufio"
"virjar.com/majora/common"
"virjar.com/majora/logger"
)
type Decoder interface {
......@@ -13,60 +16,60 @@ type MajoraPacketDecoder struct {
}
func (mpd *MajoraPacketDecoder) Decode(reader *bufio.Reader) (pack *MajoraPacket, err error) {
magicbs := make([]byte, MagicSize)
magicbs := make([]byte, common.MagicSize)
_, err = reader.Read(magicbs)
if err != nil {
return nil, err
}
if !ReadMagic(magicbs) {
return nil, InvalidMagicError
if !common.ReadMagic(magicbs) {
return nil, common.InvalidMagicError
}
frameLen, err := ReadInt32(reader)
frameLen, err := common.ReadInt32(reader)
if err != nil {
return nil, InvalidSizeError
return nil, common.InvalidSizeError
}
// type
msgType, err := ReadByte(reader)
msgType, err := common.ReadByte(reader)
if err != nil {
logger.Error().Msgf("read type error %+v", err)
return nil, InvalidSizeError
return nil, common.InvalidSizeError
}
pack = &MajoraPacket{}
pack.Ttype = MajoraPacketType(msgType)
// num
pack.SerialNumber, err = ReadInt64(reader)
pack.SerialNumber, err = common.ReadInt64(reader)
if err != nil {
logger.Error().Msgf("read type error %+v", err)
return nil, InvalidSizeError
return nil, common.InvalidSizeError
}
// extra size
extraSize, err := ReadByte(reader)
extraSize, err := common.ReadByte(reader)
if err != nil {
logger.Error().Msgf("read type error %+v", err)
return nil, InvalidSizeError
return nil, common.InvalidSizeError
}
extra, err := ReadN(int(extraSize), reader)
extra, err := common.ReadN(int(extraSize), reader)
if err != nil {
logger.Error().Msgf("read type error %+v", err)
return nil, InvalidSizeError
return nil, common.InvalidSizeError
}
pack.Extra = string(extra)
// dataFrame
dataSize := int(frameLen) - TypeSize - SerialNumberSize - ExtraSize - int(extraSize)
dataSize := int(frameLen) - common.TypeSize - common.SerialNumberSize - common.ExtraSize - int(extraSize)
if dataSize < 0 {
logger.Error().Msgf("read type error %+v", err)
return nil, InvalidSizeError
return nil, common.InvalidSizeError
}
if dataSize > 0 {
data, err := ReadN(dataSize, reader)
data, err := common.ReadN(dataSize, reader)
if err != nil {
logger.Error().Msgf("read type error %+v", err)
}
......
package main
package protocol
import (
"bytes"
"virjar.com/majora/common"
)
type Encoder interface {
......@@ -13,9 +15,9 @@ type MajoraPacketEncoder struct {
func (s *MajoraPacketEncoder) Encode(packet *MajoraPacket) ([]byte, error) {
if packet == nil {
return nil, NilPacketError
return nil, common.NilPacketError
}
bodyLength := TypeSize + SerialNumberSize + ExtraSize
bodyLength := common.TypeSize + common.SerialNumberSize + common.ExtraSize
bodyLength += len(packet.Data)
......@@ -29,13 +31,13 @@ func (s *MajoraPacketEncoder) Encode(packet *MajoraPacket) ([]byte, error) {
)
// magic 8byte
buffer.Write(ConvertInt64ToBytes(MAGIC))
buffer.Write(common.ConvertInt64ToBytes(common.MAGIC))
// body length 4byte
buffer.Write(ConvertInt32ToBytes(int32(bodyLength)))
buffer.Write(common.ConvertInt32ToBytes(int32(bodyLength)))
// type 1byte
buffer.WriteByte(byte(packet.Ttype))
// serial num 4byte
buffer.Write(ConvertInt64ToBytes(packet.SerialNumber))
buffer.Write(common.ConvertInt64ToBytes(packet.SerialNumber))
// extra
if len(packet.Extra) > 0 {
......
package main
package protocol
type MajoraPacket struct {
Ttype MajoraPacketType // 消息类型
......
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