├── leaf_kcp_server ├── leaf │ ├── version.go │ ├── network │ │ ├── agent.go │ │ ├── processor.go │ │ ├── udp_server.go │ │ ├── udp_msg.go │ │ └── json │ │ │ └── json.go │ ├── gate │ │ ├── agent.go │ │ └── gate.go │ ├── util │ │ ├── semaphore.go │ │ ├── example_test.go │ │ ├── rand.go │ │ ├── deepcopy.go │ │ └── map.go │ ├── recordfile │ │ ├── test.txt │ │ ├── example_test.go │ │ └── recordfile.go │ ├── conf │ │ └── conf.go │ ├── log │ │ ├── example_test.go │ │ └── log.go │ ├── leaf.go │ ├── db │ │ └── mongodb │ │ │ ├── example_test.go │ │ │ └── mongodb.go │ ├── go │ │ ├── example_test.go │ │ └── go.go │ ├── timer │ │ ├── example_test.go │ │ ├── timer.go │ │ └── cronexpr.go │ ├── module │ │ ├── module.go │ │ └── skeleton.go │ ├── chanrpc │ │ ├── example_test.go │ │ └── chanrpc.go │ └── kcp │ │ ├── sess_test.go │ │ ├── kcp_test.go │ │ ├── sess.go │ │ └── kcp.go └── server │ ├── gate │ ├── external.go │ ├── router.go │ └── internal │ │ └── module.go │ ├── login │ ├── external.go │ └── internal │ │ ├── handler.go │ │ └── module.go │ ├── robot │ ├── external.go │ └── internal │ │ ├── module.go │ │ ├── chanrpc.go │ │ └── handler.go │ ├── msg │ └── msg.go │ ├── main.go │ ├── base │ └── skeleton.go │ ├── conf │ ├── conf.go │ └── json.go │ └── robotdata │ └── reader.go └── README.md /leaf_kcp_server/leaf/version.go: -------------------------------------------------------------------------------- 1 | package leaf 2 | 3 | const version = "1.1.2_0.0.1" 4 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/network/agent.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type Agent interface { 4 | Run() 5 | OnClose() 6 | } 7 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/gate/external.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | "server/gate/internal" 5 | ) 6 | 7 | var ( 8 | Module = new(internal.Module) 9 | ) 10 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/gate/agent.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | type Agent interface { 4 | Write(msg interface{}) 5 | Close() 6 | UserData() interface{} 7 | SetUserData(data interface{}) 8 | } 9 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/gate/router.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import "server/msg" 4 | import "server/robot" 5 | 6 | func init() { 7 | msg.JSONProcessor.SetRouter(&msg.C2S_AddUser{}, robot.ChanRPC) 8 | } 9 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/login/external.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "server/login/internal" 5 | ) 6 | 7 | var ( 8 | Module = new(internal.Module) 9 | ChanRPC = internal.ChanRPC 10 | ) 11 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/robot/external.go: -------------------------------------------------------------------------------- 1 | package robot 2 | 3 | import ( 4 | "server/robot/internal" 5 | ) 6 | 7 | var ( 8 | Module = new(internal.Module) 9 | ChanRPC = internal.ChanRPC 10 | ) 11 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/login/internal/handler.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | func handleMsg(m interface{}, h interface{}) { 8 | skeleton.RegisterChanRPC(reflect.TypeOf(m), h) 9 | } 10 | 11 | func init() { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/msg/msg.go: -------------------------------------------------------------------------------- 1 | package msg 2 | 3 | import ( 4 | "leaf/network/json" 5 | ) 6 | 7 | var JSONProcessor = json.NewProcessor() 8 | 9 | func init() { 10 | JSONProcessor.Register(&C2S_AddUser{}) 11 | } 12 | 13 | type C2S_AddUser struct { 14 | UserName string 15 | } 16 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/util/semaphore.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | type Semaphore chan struct{} 4 | 5 | func MakeSemaphore(n int) Semaphore { 6 | return make(Semaphore, n) 7 | } 8 | 9 | func (s Semaphore) Acquire() { 10 | s <- struct{}{} 11 | } 12 | 13 | func (s Semaphore) Release() { 14 | <-s 15 | } 16 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/network/processor.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | type Processor interface { 4 | // must goroutine safe 5 | Route(msg interface{}, userData interface{}) error 6 | // must goroutine safe 7 | Unmarshal(data []byte) (interface{}, error) 8 | // must goroutine safe 9 | Marshal(msg interface{}) ([]byte, error) 10 | } 11 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/recordfile/test.txt: -------------------------------------------------------------------------------- 1 | 数字索引 字符串索引 数字类型 字符串类型 数组类型 嵌套数组 变长数组 结构体类型 2 | 1 one 0 knife "[1, 2]" "[[0,1], [1,2], [2,3]]" "[1, 2, 3]" "{""name"": ""name5566"", ""num"": 1}" 3 | 2 two 0 cat "[3, 4]" "[[1,2], [2,3], [3,4]]" "[4, 5]" "{""name"": ""name5566"", ""num"": 2}" 4 | 3 three 0 book "[5, 6]" "[[2,3], [3,4], [4,5]]" [6] "{""name"": ""name5566"", ""num"": 3}" 5 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | var ( 4 | LenStackBuf = 4096 5 | 6 | // log 7 | LogLevel string 8 | LogPath string 9 | 10 | // console 11 | ConsolePort int 12 | ConsolePrompt string = "Leaf# " 13 | ProfilePath string 14 | 15 | // cluster 16 | ListenAddr string 17 | ConnAddrs []string 18 | PendingWriteNum int 19 | ) 20 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "server/conf" 5 | "server/gate" 6 | "server/login" 7 | "server/robot" 8 | 9 | "leaf" 10 | lconf "leaf/conf" 11 | ) 12 | 13 | func main() { 14 | lconf.LogLevel = conf.Server.LogLevel 15 | lconf.LogPath = conf.Server.LogPath 16 | 17 | leaf.Run( 18 | robot.Module, 19 | gate.Module, 20 | login.Module, 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/login/internal/module.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "leaf/module" 5 | "server/base" 6 | ) 7 | 8 | var ( 9 | skeleton = base.NewSkeleton() 10 | ChanRPC = skeleton.ChanRPCServer 11 | ) 12 | 13 | type Module struct { 14 | *module.Skeleton 15 | } 16 | 17 | func (m *Module) OnInit() { 18 | m.Skeleton = skeleton 19 | } 20 | 21 | func (m *Module) OnDestroy() { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/robot/internal/module.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "leaf/module" 5 | "server/base" 6 | ) 7 | 8 | var ( 9 | skeleton = base.NewSkeleton() 10 | ChanRPC = skeleton.ChanRPCServer 11 | ) 12 | 13 | type Module struct { 14 | *module.Skeleton 15 | } 16 | 17 | func (m *Module) OnInit() { 18 | m.Skeleton = skeleton 19 | } 20 | 21 | func (m *Module) OnDestroy() { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/base/skeleton.go: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import ( 4 | "leaf/chanrpc" 5 | "leaf/module" 6 | "server/conf" 7 | ) 8 | 9 | func NewSkeleton() *module.Skeleton { 10 | skeleton := &module.Skeleton{ 11 | GoLen: conf.GoLen, 12 | TimerDispatcherLen: conf.TimerDispatcherLen, 13 | ChanRPCServer: chanrpc.NewServer(conf.ChanRPCLen), 14 | } 15 | skeleton.Init() 16 | return skeleton 17 | } 18 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/conf/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | var ( 8 | // gate conf 9 | PendingWriteNum = 2000 10 | MaxMsgLen uint32 = 4096 11 | HTTPTimeout = 10 * time.Second 12 | LenMsgLen = 2 13 | LittleEndian = false 14 | 15 | // skeleton conf 16 | GoLen = 10000 17 | TimerDispatcherLen = 10000 18 | ChanRPCLen = 10000 19 | ) 20 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/robotdata/reader.go: -------------------------------------------------------------------------------- 1 | package robotdata 2 | 3 | import ( 4 | "reflect" 5 | 6 | "leaf/log" 7 | "leaf/recordfile" 8 | ) 9 | 10 | func readRf(st interface{}) *recordfile.RecordFile { 11 | rf, err := recordfile.New(st) 12 | if err != nil { 13 | log.Fatal("%v", err) 14 | } 15 | fn := reflect.TypeOf(st).Name() + ".txt" 16 | err = rf.Read("gamedata/" + fn) 17 | if err != nil { 18 | log.Fatal("%v: %v", fn, err) 19 | } 20 | 21 | return rf 22 | } 23 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/conf/json.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "leaf/log" 7 | ) 8 | 9 | var Server struct { 10 | LogLevel string 11 | LogPath string 12 | MaxConnNum int 13 | 14 | UDPAddr string 15 | } 16 | 17 | func init() { 18 | data, err := ioutil.ReadFile("conf/server.json") 19 | if err != nil { 20 | log.Fatal("%v", err) 21 | } 22 | err = json.Unmarshal(data, &Server) 23 | if err != nil { 24 | log.Fatal("%v", err) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/robot/internal/chanrpc.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "leaf/gate" 5 | "leaf/log" 6 | ) 7 | 8 | func init() { 9 | skeleton.RegisterChanRPC("NewAgent", rpcNewAgent) 10 | skeleton.RegisterChanRPC("CloseAgent", rpcCloseAgent) 11 | } 12 | 13 | func rpcNewAgent(args []interface{}) { 14 | a := args[0].(gate.Agent) 15 | _ = a 16 | log.Debug("rpcNewAgent") 17 | } 18 | 19 | func rpcCloseAgent(args []interface{}) { 20 | a := args[0].(gate.Agent) 21 | _ = a 22 | log.Debug("rpcCloseAgent") 23 | } 24 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/robot/internal/handler.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "fmt" 5 | "leaf/gate" 6 | "reflect" 7 | "server/msg" 8 | ) 9 | 10 | func handleMsg(m interface{}, h interface{}) { 11 | skeleton.RegisterChanRPC(reflect.TypeOf(m), h) 12 | } 13 | 14 | func init() { 15 | handleMsg(&msg.C2S_AddUser{}, handleAddUser) 16 | } 17 | 18 | func handleAddUser(args []interface{}) { 19 | m := args[0].(*msg.C2S_AddUser) 20 | a := args[1].(gate.Agent) 21 | 22 | a.Write("123456789") 23 | fmt.Println(m.UserName) 24 | } 25 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/log/example_test.go: -------------------------------------------------------------------------------- 1 | package log_test 2 | 3 | import ( 4 | "leaf/log" 5 | ) 6 | 7 | func Example() { 8 | name := "Leaf" 9 | 10 | log.Debug("My name is %v", name) 11 | log.Release("My name is %v", name) 12 | log.Error("My name is %v", name) 13 | // log.Fatal("My name is %v", name) 14 | 15 | logger, err := log.New("release", "") 16 | if err != nil { 17 | return 18 | } 19 | defer logger.Close() 20 | 21 | logger.Debug("will not print") 22 | logger.Release("My name is %v", name) 23 | 24 | log.Export(logger) 25 | 26 | log.Debug("will not print") 27 | log.Release("My name is %v", name) 28 | } 29 | -------------------------------------------------------------------------------- /leaf_kcp_server/server/gate/internal/module.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "server/conf" 5 | "server/msg" 6 | "server/robot" 7 | 8 | "leaf/gate" 9 | ) 10 | 11 | type Module struct { 12 | *gate.Gate 13 | } 14 | 15 | func (m *Module) OnInit() { 16 | m.Gate = &gate.Gate{ 17 | MaxConnNum: conf.Server.MaxConnNum, 18 | PendingWriteNum: conf.PendingWriteNum, 19 | MaxMsgLen: conf.MaxMsgLen, 20 | 21 | LenMsgLen: conf.LenMsgLen, 22 | LittleEndian: conf.LittleEndian, 23 | Processor: msg.JSONProcessor, 24 | AgentChanRPC: robot.ChanRPC, 25 | 26 | UDPAddr: conf.Server.UDPAddr, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # leaf_kcp_server 2 | 基于leaf的游戏框架,加入了kcp支持。演示DEMO. 3 | 4 | 5 | 6 | ## 协议 7 | 8 | 本项目基于GNU开源协议,不得用于商业用途 9 | 10 | 本项目仅供学习交流使用,本人不承担任何法律责任 11 | 12 | 若有侵权请联系删除。 13 | 14 | ## 支持 (support) 15 | 16 | * **如果您使用的还算顺手, 可以支持一杯咖啡予以鼓励.** 17 | 18 | * **Encourage the price of a cup of coffee.** 19 | 20 |
21 |              22 | 23 |
24 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/leaf.go: -------------------------------------------------------------------------------- 1 | package leaf 2 | 3 | import ( 4 | "leaf/conf" 5 | "leaf/log" 6 | "leaf/module" 7 | "os" 8 | "os/signal" 9 | ) 10 | 11 | func Run(mods ...module.Module) { 12 | // logger 13 | if conf.LogLevel != "" { 14 | logger, err := log.New(conf.LogLevel, conf.LogPath) 15 | if err != nil { 16 | panic(err) 17 | } 18 | log.Export(logger) 19 | defer logger.Close() 20 | } 21 | 22 | log.Release("Leaf %v starting up", version) 23 | 24 | // module 25 | for i := 0; i < len(mods); i++ { 26 | module.Register(mods[i]) 27 | } 28 | module.Init() 29 | 30 | // close 31 | c := make(chan os.Signal, 1) 32 | signal.Notify(c, os.Interrupt, os.Kill) 33 | sig := <-c 34 | log.Release("Leaf closing down (signal: %v)", sig) 35 | 36 | module.Destroy() 37 | } 38 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/db/mongodb/example_test.go: -------------------------------------------------------------------------------- 1 | package mongodb_test 2 | 3 | import ( 4 | "fmt" 5 | "leaf/db/mongodb" 6 | 7 | "gopkg.in/mgo.v2" 8 | ) 9 | 10 | func Example() { 11 | c, err := mongodb.Dial("localhost", 10) 12 | if err != nil { 13 | fmt.Println(err) 14 | return 15 | } 16 | defer c.Close() 17 | 18 | // session 19 | s := c.Ref() 20 | defer c.UnRef(s) 21 | err = s.DB("test").C("counters").RemoveId("test") 22 | if err != nil && err != mgo.ErrNotFound { 23 | fmt.Println(err) 24 | return 25 | } 26 | 27 | // auto increment 28 | err = c.EnsureCounter("test", "counters", "test") 29 | if err != nil { 30 | fmt.Println(err) 31 | return 32 | } 33 | for i := 0; i < 3; i++ { 34 | id, err := c.NextSeq("test", "counters", "test") 35 | if err != nil { 36 | fmt.Println(err) 37 | return 38 | } 39 | fmt.Println(id) 40 | } 41 | 42 | // index 43 | c.EnsureUniqueIndex("test", "counters", []string{"key1"}) 44 | 45 | // Output: 46 | // 1 47 | // 2 48 | // 3 49 | } 50 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/go/example_test.go: -------------------------------------------------------------------------------- 1 | package g_test 2 | 3 | import ( 4 | "fmt" 5 | "leaf/go" 6 | "time" 7 | ) 8 | 9 | func Example() { 10 | d := g.New(10) 11 | 12 | // go 1 13 | var res int 14 | d.Go(func() { 15 | fmt.Println("1 + 1 = ?") 16 | res = 1 + 1 17 | }, func() { 18 | fmt.Println(res) 19 | }) 20 | 21 | d.Cb(<-d.ChanCb) 22 | 23 | // go 2 24 | d.Go(func() { 25 | fmt.Print("My name is ") 26 | }, func() { 27 | fmt.Println("Leaf") 28 | }) 29 | 30 | d.Close() 31 | 32 | // Output: 33 | // 1 + 1 = ? 34 | // 2 35 | // My name is Leaf 36 | } 37 | 38 | func ExampleLinearContext() { 39 | d := g.New(10) 40 | 41 | // parallel 42 | d.Go(func() { 43 | time.Sleep(time.Second / 2) 44 | fmt.Println("1") 45 | }, nil) 46 | d.Go(func() { 47 | fmt.Println("2") 48 | }, nil) 49 | 50 | d.Cb(<-d.ChanCb) 51 | d.Cb(<-d.ChanCb) 52 | 53 | // linear 54 | c := d.NewLinearContext() 55 | c.Go(func() { 56 | time.Sleep(time.Second / 2) 57 | fmt.Println("1") 58 | }, nil) 59 | c.Go(func() { 60 | fmt.Println("2") 61 | }, nil) 62 | 63 | d.Close() 64 | 65 | // Output: 66 | // 2 67 | // 1 68 | // 1 69 | // 2 70 | } 71 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/recordfile/example_test.go: -------------------------------------------------------------------------------- 1 | package recordfile_test 2 | 3 | import ( 4 | "fmt" 5 | "leaf/recordfile" 6 | ) 7 | 8 | func Example() { 9 | type Record struct { 10 | // index 0 11 | IndexInt int "index" 12 | // index 1 13 | IndexStr string "index" 14 | _Number int32 15 | Str string 16 | Arr1 [2]int 17 | Arr2 [3][2]int 18 | Arr3 []int 19 | St struct { 20 | Name string "name" 21 | Num int "num" 22 | } 23 | } 24 | 25 | rf, err := recordfile.New(Record{}) 26 | if err != nil { 27 | return 28 | } 29 | 30 | err = rf.Read("test.txt") 31 | if err != nil { 32 | return 33 | } 34 | 35 | for i := 0; i < rf.NumRecord(); i++ { 36 | r := rf.Record(i).(*Record) 37 | fmt.Println(r.IndexInt) 38 | } 39 | 40 | r := rf.Index(2).(*Record) 41 | fmt.Println(r.Str) 42 | 43 | r = rf.Indexes(0)[2].(*Record) 44 | fmt.Println(r.Str) 45 | 46 | r = rf.Indexes(1)["three"].(*Record) 47 | fmt.Println(r.Str) 48 | fmt.Println(r.Arr1[1]) 49 | fmt.Println(r.Arr2[2][0]) 50 | fmt.Println(r.Arr3[0]) 51 | fmt.Println(r.St.Name) 52 | 53 | // Output: 54 | // 1 55 | // 2 56 | // 3 57 | // cat 58 | // cat 59 | // book 60 | // 6 61 | // 4 62 | // 6 63 | // name5566 64 | } 65 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/timer/example_test.go: -------------------------------------------------------------------------------- 1 | package timer_test 2 | 3 | import ( 4 | "fmt" 5 | "leaf/timer" 6 | "time" 7 | ) 8 | 9 | func ExampleTimer() { 10 | d := timer.NewDispatcher(10) 11 | 12 | // timer 1 13 | d.AfterFunc(1, func() { 14 | fmt.Println("My name is Leaf") 15 | }) 16 | 17 | // timer 2 18 | t := d.AfterFunc(1, func() { 19 | fmt.Println("will not print") 20 | }) 21 | t.Stop() 22 | 23 | // dispatch 24 | (<-d.ChanTimer).Cb() 25 | 26 | // Output: 27 | // My name is Leaf 28 | } 29 | 30 | func ExampleCronExpr() { 31 | cronExpr, err := timer.NewCronExpr("0 * * * *") 32 | if err != nil { 33 | return 34 | } 35 | 36 | fmt.Println(cronExpr.Next(time.Date( 37 | 2000, 1, 1, 38 | 20, 10, 5, 39 | 0, time.UTC, 40 | ))) 41 | 42 | // Output: 43 | // 2000-01-01 21:00:00 +0000 UTC 44 | } 45 | 46 | func ExampleCron() { 47 | d := timer.NewDispatcher(10) 48 | 49 | // cron expr 50 | cronExpr, err := timer.NewCronExpr("* * * * * *") 51 | if err != nil { 52 | return 53 | } 54 | 55 | // cron 56 | var c *timer.Cron 57 | c = d.CronFunc(cronExpr, func() { 58 | fmt.Println("My name is Leaf") 59 | c.Stop() 60 | }) 61 | 62 | // dispatch 63 | (<-d.ChanTimer).Cb() 64 | 65 | // Output: 66 | // My name is Leaf 67 | } 68 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/module/module.go: -------------------------------------------------------------------------------- 1 | package module 2 | 3 | import ( 4 | "leaf/conf" 5 | "leaf/log" 6 | "runtime" 7 | "sync" 8 | ) 9 | 10 | type Module interface { 11 | OnInit() 12 | OnDestroy() 13 | Run(closeSig chan bool) 14 | } 15 | 16 | type module struct { 17 | mi Module 18 | closeSig chan bool 19 | wg sync.WaitGroup 20 | } 21 | 22 | var mods []*module 23 | 24 | func Register(mi Module) { 25 | m := new(module) 26 | m.mi = mi 27 | m.closeSig = make(chan bool, 1) 28 | 29 | mods = append(mods, m) 30 | } 31 | 32 | func Init() { 33 | for i := 0; i < len(mods); i++ { 34 | mods[i].mi.OnInit() 35 | } 36 | 37 | for i := 0; i < len(mods); i++ { 38 | go run(mods[i]) 39 | } 40 | } 41 | 42 | func Destroy() { 43 | for i := len(mods) - 1; i >= 0; i-- { 44 | m := mods[i] 45 | m.closeSig <- true 46 | m.wg.Wait() 47 | destroy(m) 48 | } 49 | } 50 | 51 | func run(m *module) { 52 | m.wg.Add(1) 53 | m.mi.Run(m.closeSig) 54 | m.wg.Done() 55 | } 56 | 57 | func destroy(m *module) { 58 | defer func() { 59 | if r := recover(); r != nil { 60 | if conf.LenStackBuf > 0 { 61 | buf := make([]byte, conf.LenStackBuf) 62 | l := runtime.Stack(buf, false) 63 | log.Error("%v: %s", r, buf[:l]) 64 | } else { 65 | log.Error("%v", r) 66 | } 67 | } 68 | }() 69 | 70 | m.mi.OnDestroy() 71 | } 72 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/network/udp_server.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "leaf/kcp" 5 | "leaf/log" 6 | "sync" 7 | ) 8 | 9 | type UDPServer struct { 10 | Addr string 11 | MaxConnNum int 12 | NewAgent func(*kcp.UDPSession) Agent 13 | ln *kcp.Listener 14 | 15 | wgLn sync.WaitGroup 16 | } 17 | 18 | func (server *UDPServer) Start() { 19 | server.init() 20 | go server.run() 21 | } 22 | 23 | func (server *UDPServer) init() { 24 | ln, err := kcp.Listen(kcp.MODE_NORMAL, server.Addr) 25 | if err != nil { 26 | log.Fatal("%v", err) 27 | } 28 | 29 | if server.MaxConnNum <= 0 { 30 | server.MaxConnNum = 100 31 | log.Release("invalid MaxConnNum, reset to %v", server.MaxConnNum) 32 | } 33 | if server.NewAgent == nil { 34 | log.Fatal("NewAgent must not be nil") 35 | } 36 | 37 | server.ln = ln 38 | 39 | } 40 | 41 | func (server *UDPServer) run() { 42 | server.wgLn.Add(1) 43 | defer server.wgLn.Done() 44 | 45 | for { 46 | conn, err := server.ln.Accept() 47 | if err != nil { 48 | log.Release("accept error: %v", err) 49 | return 50 | } 51 | if server.ln.SessionCount() >= server.MaxConnNum { 52 | conn.Close() 53 | log.Debug("too many connections") 54 | continue 55 | } 56 | 57 | agent := server.NewAgent(conn) 58 | 59 | go func() { 60 | agent.Run() 61 | agent.OnClose() 62 | 63 | }() 64 | } 65 | } 66 | 67 | func (server *UDPServer) Close() { 68 | server.ln.Close() 69 | server.wgLn.Wait() 70 | } 71 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/util/example_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | "fmt" 5 | "leaf/util" 6 | ) 7 | 8 | func ExampleMap() { 9 | m := new(util.Map) 10 | 11 | fmt.Println(m.Get("key")) 12 | m.Set("key", "value") 13 | fmt.Println(m.Get("key")) 14 | m.Del("key") 15 | fmt.Println(m.Get("key")) 16 | 17 | m.Set(1, "1") 18 | m.Set(2, 2) 19 | m.Set("3", 3) 20 | 21 | fmt.Println(m.Len()) 22 | 23 | // Output: 24 | // 25 | // value 26 | // 27 | // 3 28 | } 29 | 30 | func ExampleRandGroup() { 31 | i := util.RandGroup(0, 0, 50, 50) 32 | switch i { 33 | case 2, 3: 34 | fmt.Println("ok") 35 | } 36 | 37 | // Output: 38 | // ok 39 | } 40 | 41 | func ExampleRandInterval() { 42 | v := util.RandInterval(-1, 1) 43 | switch v { 44 | case -1, 0, 1: 45 | fmt.Println("ok") 46 | } 47 | 48 | // Output: 49 | // ok 50 | } 51 | 52 | func ExampleRandIntervalN() { 53 | r := util.RandIntervalN(-1, 0, 2) 54 | if r[0] == -1 && r[1] == 0 || 55 | r[0] == 0 && r[1] == -1 { 56 | fmt.Println("ok") 57 | } 58 | 59 | // Output: 60 | // ok 61 | } 62 | 63 | func ExampleDeepCopy() { 64 | src := []int{1, 2, 3} 65 | 66 | var dst []int 67 | util.DeepCopy(&dst, &src) 68 | 69 | for _, v := range dst { 70 | fmt.Println(v) 71 | } 72 | 73 | // Output: 74 | // 1 75 | // 2 76 | // 3 77 | } 78 | 79 | func ExampleDeepClone() { 80 | src := []int{1, 2, 3} 81 | 82 | dst := util.DeepClone(src).([]int) 83 | 84 | for _, v := range dst { 85 | fmt.Println(v) 86 | } 87 | 88 | // Output: 89 | // 1 90 | // 2 91 | // 3 92 | } 93 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/util/rand.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | func init() { 9 | rand.Seed(time.Now().UnixNano()) 10 | } 11 | 12 | func RandGroup(p ...uint32) int { 13 | if p == nil { 14 | panic("args not found") 15 | } 16 | 17 | r := make([]uint32, len(p)) 18 | for i := 0; i < len(p); i++ { 19 | if i == 0 { 20 | r[0] = p[0] 21 | } else { 22 | r[i] = r[i-1] + p[i] 23 | } 24 | } 25 | 26 | rl := r[len(r)-1] 27 | if rl == 0 { 28 | return 0 29 | } 30 | 31 | rn := uint32(rand.Int63n(int64(rl))) 32 | for i := 0; i < len(r); i++ { 33 | if rn < r[i] { 34 | return i 35 | } 36 | } 37 | 38 | panic("bug") 39 | } 40 | 41 | func RandInterval(b1, b2 int32) int32 { 42 | if b1 == b2 { 43 | return b1 44 | } 45 | 46 | min, max := int64(b1), int64(b2) 47 | if min > max { 48 | min, max = max, min 49 | } 50 | return int32(rand.Int63n(max-min+1) + min) 51 | } 52 | 53 | func RandIntervalN(b1, b2 int32, n uint32) []int32 { 54 | if b1 == b2 { 55 | return []int32{b1} 56 | } 57 | 58 | min, max := int64(b1), int64(b2) 59 | if min > max { 60 | min, max = max, min 61 | } 62 | l := max - min + 1 63 | if int64(n) > l { 64 | n = uint32(l) 65 | } 66 | 67 | r := make([]int32, n) 68 | m := make(map[int32]int32) 69 | for i := uint32(0); i < n; i++ { 70 | v := int32(rand.Int63n(l) + min) 71 | 72 | if mv, ok := m[v]; ok { 73 | r[i] = mv 74 | } else { 75 | r[i] = v 76 | } 77 | 78 | lv := int32(l - 1 + min) 79 | if v != lv { 80 | if mv, ok := m[lv]; ok { 81 | m[v] = mv 82 | } else { 83 | m[v] = lv 84 | } 85 | } 86 | 87 | l-- 88 | } 89 | 90 | return r 91 | } 92 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/timer/timer.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | import ( 4 | "leaf/conf" 5 | "leaf/log" 6 | "runtime" 7 | "time" 8 | ) 9 | 10 | // one dispatcher per goroutine (goroutine not safe) 11 | type Dispatcher struct { 12 | ChanTimer chan *Timer 13 | } 14 | 15 | func NewDispatcher(l int) *Dispatcher { 16 | disp := new(Dispatcher) 17 | disp.ChanTimer = make(chan *Timer, l) 18 | return disp 19 | } 20 | 21 | // Timer 22 | type Timer struct { 23 | t *time.Timer 24 | cb func() 25 | } 26 | 27 | func (t *Timer) Stop() { 28 | t.t.Stop() 29 | t.cb = nil 30 | } 31 | 32 | func (t *Timer) Cb() { 33 | defer func() { 34 | t.cb = nil 35 | if r := recover(); r != nil { 36 | if conf.LenStackBuf > 0 { 37 | buf := make([]byte, conf.LenStackBuf) 38 | l := runtime.Stack(buf, false) 39 | log.Error("%v: %s", r, buf[:l]) 40 | } else { 41 | log.Error("%v", r) 42 | } 43 | } 44 | }() 45 | 46 | if t.cb != nil { 47 | t.cb() 48 | } 49 | } 50 | 51 | func (disp *Dispatcher) AfterFunc(d time.Duration, cb func()) *Timer { 52 | t := new(Timer) 53 | t.cb = cb 54 | t.t = time.AfterFunc(d, func() { 55 | disp.ChanTimer <- t 56 | }) 57 | return t 58 | } 59 | 60 | // Cron 61 | type Cron struct { 62 | t *Timer 63 | } 64 | 65 | func (c *Cron) Stop() { 66 | if c.t != nil { 67 | c.t.Stop() 68 | } 69 | } 70 | 71 | func (disp *Dispatcher) CronFunc(cronExpr *CronExpr, _cb func()) *Cron { 72 | c := new(Cron) 73 | 74 | now := time.Now() 75 | nextTime := cronExpr.Next(now) 76 | if nextTime.IsZero() { 77 | return c 78 | } 79 | 80 | // callback 81 | var cb func() 82 | cb = func() { 83 | defer _cb() 84 | 85 | now := time.Now() 86 | nextTime := cronExpr.Next(now) 87 | if nextTime.IsZero() { 88 | return 89 | } 90 | c.t = disp.AfterFunc(nextTime.Sub(now), cb) 91 | } 92 | 93 | c.t = disp.AfterFunc(nextTime.Sub(now), cb) 94 | return c 95 | } 96 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/util/deepcopy.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | // reference: https://github.com/mohae/deepcopy 4 | import ( 5 | "reflect" 6 | ) 7 | 8 | func deepCopy(dst, src reflect.Value) { 9 | switch src.Kind() { 10 | case reflect.Interface: 11 | value := src.Elem() 12 | if !value.IsValid() { 13 | return 14 | } 15 | newValue := reflect.New(value.Type()).Elem() 16 | deepCopy(newValue, value) 17 | dst.Set(newValue) 18 | case reflect.Ptr: 19 | value := src.Elem() 20 | if !value.IsValid() { 21 | return 22 | } 23 | dst.Set(reflect.New(value.Type())) 24 | deepCopy(dst.Elem(), value) 25 | case reflect.Map: 26 | dst.Set(reflect.MakeMap(src.Type())) 27 | keys := src.MapKeys() 28 | for _, key := range keys { 29 | value := src.MapIndex(key) 30 | newValue := reflect.New(value.Type()).Elem() 31 | deepCopy(newValue, value) 32 | dst.SetMapIndex(key, newValue) 33 | } 34 | case reflect.Slice: 35 | dst.Set(reflect.MakeSlice(src.Type(), src.Len(), src.Cap())) 36 | for i := 0; i < src.Len(); i++ { 37 | deepCopy(dst.Index(i), src.Index(i)) 38 | } 39 | case reflect.Struct: 40 | for i := 0; i < src.NumField(); i++ { 41 | value := src.Field(i) 42 | if value.CanSet() { 43 | deepCopy(dst.Field(i), value) 44 | } 45 | } 46 | default: 47 | dst.Set(src) 48 | } 49 | } 50 | 51 | func DeepCopy(dst, src interface{}) { 52 | typeDst := reflect.TypeOf(dst) 53 | typeSrc := reflect.TypeOf(src) 54 | if typeDst != typeSrc { 55 | panic("DeepCopy: " + typeDst.String() + " != " + typeSrc.String()) 56 | } 57 | if typeSrc.Kind() != reflect.Ptr { 58 | panic("DeepCopy: pass arguments by address") 59 | } 60 | 61 | valueDst := reflect.ValueOf(dst).Elem() 62 | valueSrc := reflect.ValueOf(src).Elem() 63 | if !valueDst.IsValid() || !valueSrc.IsValid() { 64 | panic("DeepCopy: invalid arguments") 65 | } 66 | 67 | deepCopy(valueDst, valueSrc) 68 | } 69 | 70 | func DeepClone(v interface{}) interface{} { 71 | dst := reflect.New(reflect.TypeOf(v)).Elem() 72 | deepCopy(dst, reflect.ValueOf(v)) 73 | return dst.Interface() 74 | } 75 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/util/map.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type Map struct { 8 | sync.RWMutex 9 | m map[interface{}]interface{} 10 | } 11 | 12 | func (m *Map) init() { 13 | if m.m == nil { 14 | m.m = make(map[interface{}]interface{}) 15 | } 16 | } 17 | 18 | func (m *Map) UnsafeGet(key interface{}) interface{} { 19 | if m.m == nil { 20 | return nil 21 | } else { 22 | return m.m[key] 23 | } 24 | } 25 | 26 | func (m *Map) Get(key interface{}) interface{} { 27 | m.RLock() 28 | defer m.RUnlock() 29 | return m.UnsafeGet(key) 30 | } 31 | 32 | func (m *Map) UnsafeSet(key interface{}, value interface{}) { 33 | m.init() 34 | m.m[key] = value 35 | } 36 | 37 | func (m *Map) Set(key interface{}, value interface{}) { 38 | m.Lock() 39 | defer m.Unlock() 40 | m.UnsafeSet(key, value) 41 | } 42 | 43 | func (m *Map) TestAndSet(key interface{}, value interface{}) interface{} { 44 | m.Lock() 45 | defer m.Unlock() 46 | 47 | m.init() 48 | 49 | if v, ok := m.m[key]; ok { 50 | return v 51 | } else { 52 | m.m[key] = value 53 | return nil 54 | } 55 | } 56 | 57 | func (m *Map) UnsafeDel(key interface{}) { 58 | m.init() 59 | delete(m.m, key) 60 | } 61 | 62 | func (m *Map) Del(key interface{}) { 63 | m.Lock() 64 | defer m.Unlock() 65 | m.UnsafeDel(key) 66 | } 67 | 68 | func (m *Map) UnsafeLen() int { 69 | if m.m == nil { 70 | return 0 71 | } else { 72 | return len(m.m) 73 | } 74 | } 75 | 76 | func (m *Map) Len() int { 77 | m.RLock() 78 | defer m.RUnlock() 79 | return m.UnsafeLen() 80 | } 81 | 82 | func (m *Map) UnsafeRange(f func(interface{}, interface{})) { 83 | if m.m == nil { 84 | return 85 | } 86 | for k, v := range m.m { 87 | f(k, v) 88 | } 89 | } 90 | 91 | func (m *Map) RLockRange(f func(interface{}, interface{})) { 92 | m.RLock() 93 | defer m.RUnlock() 94 | m.UnsafeRange(f) 95 | } 96 | 97 | func (m *Map) LockRange(f func(interface{}, interface{})) { 98 | m.Lock() 99 | defer m.Unlock() 100 | m.UnsafeRange(f) 101 | } 102 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/module/skeleton.go: -------------------------------------------------------------------------------- 1 | package module 2 | 3 | import ( 4 | "leaf/chanrpc" 5 | "leaf/go" 6 | "leaf/log" 7 | "leaf/timer" 8 | "time" 9 | ) 10 | 11 | type Skeleton struct { 12 | GoLen int 13 | TimerDispatcherLen int 14 | ChanRPCServer *chanrpc.Server 15 | g *g.Go 16 | dispatcher *timer.Dispatcher 17 | server *chanrpc.Server 18 | commandServer *chanrpc.Server 19 | } 20 | 21 | func (s *Skeleton) Init() { 22 | if s.GoLen <= 0 { 23 | s.GoLen = 0 24 | } 25 | if s.TimerDispatcherLen <= 0 { 26 | s.TimerDispatcherLen = 0 27 | } 28 | 29 | s.g = g.New(s.GoLen) 30 | s.dispatcher = timer.NewDispatcher(s.TimerDispatcherLen) 31 | s.server = s.ChanRPCServer 32 | 33 | if s.server == nil { 34 | s.server = chanrpc.NewServer(0) 35 | } 36 | s.commandServer = chanrpc.NewServer(0) 37 | } 38 | 39 | func (s *Skeleton) Run(closeSig chan bool) { 40 | for { 41 | select { 42 | case <-closeSig: 43 | s.commandServer.Close() 44 | s.server.Close() 45 | s.g.Close() 46 | return 47 | case ci := <-s.server.ChanCall: 48 | err := s.server.Exec(ci) 49 | if err != nil { 50 | log.Error("%v", err) 51 | } 52 | case ci := <-s.commandServer.ChanCall: 53 | err := s.commandServer.Exec(ci) 54 | if err != nil { 55 | log.Error("%v", err) 56 | } 57 | case cb := <-s.g.ChanCb: 58 | s.g.Cb(cb) 59 | case t := <-s.dispatcher.ChanTimer: 60 | t.Cb() 61 | } 62 | } 63 | } 64 | 65 | func (s *Skeleton) AfterFunc(d time.Duration, cb func()) *timer.Timer { 66 | if s.TimerDispatcherLen == 0 { 67 | panic("invalid TimerDispatcherLen") 68 | } 69 | 70 | return s.dispatcher.AfterFunc(d, cb) 71 | } 72 | 73 | func (s *Skeleton) CronFunc(cronExpr *timer.CronExpr, cb func()) *timer.Cron { 74 | if s.TimerDispatcherLen == 0 { 75 | panic("invalid TimerDispatcherLen") 76 | } 77 | 78 | return s.dispatcher.CronFunc(cronExpr, cb) 79 | } 80 | 81 | func (s *Skeleton) Go(f func(), cb func()) { 82 | if s.GoLen == 0 { 83 | panic("invalid GoLen") 84 | } 85 | 86 | s.g.Go(f, cb) 87 | } 88 | 89 | func (s *Skeleton) NewLinearContext() *g.LinearContext { 90 | if s.GoLen == 0 { 91 | panic("invalid GoLen") 92 | } 93 | 94 | return s.g.NewLinearContext() 95 | } 96 | 97 | func (s *Skeleton) RegisterChanRPC(id interface{}, f interface{}) { 98 | if s.ChanRPCServer == nil { 99 | panic("invalid ChanRPCServer") 100 | } 101 | 102 | s.server.Register(id, f) 103 | } 104 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/chanrpc/example_test.go: -------------------------------------------------------------------------------- 1 | package chanrpc_test 2 | 3 | import ( 4 | "fmt" 5 | "leaf/chanrpc" 6 | "sync" 7 | ) 8 | 9 | func Example() { 10 | s := chanrpc.NewServer(10) 11 | 12 | var wg sync.WaitGroup 13 | wg.Add(1) 14 | 15 | // goroutine 1 16 | go func() { 17 | s.Register("f0", func(args []interface{}) { 18 | 19 | }) 20 | 21 | s.Register("f1", func(args []interface{}) interface{} { 22 | return 1 23 | }) 24 | 25 | s.Register("fn", func(args []interface{}) []interface{} { 26 | return []interface{}{1, 2, 3} 27 | }) 28 | 29 | s.Register("add", func(args []interface{}) interface{} { 30 | n1 := args[0].(int) 31 | n2 := args[1].(int) 32 | return n1 + n2 33 | }) 34 | 35 | wg.Done() 36 | 37 | for { 38 | err := s.Exec(<-s.ChanCall) 39 | if err != nil { 40 | fmt.Println(err) 41 | } 42 | } 43 | }() 44 | 45 | wg.Wait() 46 | wg.Add(1) 47 | 48 | // goroutine 2 49 | go func() { 50 | c := s.Open(10) 51 | 52 | // sync 53 | err := c.Call0("f0") 54 | if err != nil { 55 | fmt.Println(err) 56 | } 57 | 58 | r1, err := c.Call1("f1") 59 | if err != nil { 60 | fmt.Println(err) 61 | } else { 62 | fmt.Println(r1) 63 | } 64 | 65 | rn, err := c.CallN("fn") 66 | if err != nil { 67 | fmt.Println(err) 68 | } else { 69 | fmt.Println(rn[0], rn[1], rn[2]) 70 | } 71 | 72 | ra, err := c.Call1("add", 1, 2) 73 | if err != nil { 74 | fmt.Println(err) 75 | } else { 76 | fmt.Println(ra) 77 | } 78 | 79 | // asyn 80 | c.AsynCall("f0", func(err error) { 81 | if err != nil { 82 | fmt.Println(err) 83 | } 84 | }) 85 | 86 | c.AsynCall("f1", func(ret interface{}, err error) { 87 | if err != nil { 88 | fmt.Println(err) 89 | } else { 90 | fmt.Println(ret) 91 | } 92 | }) 93 | 94 | c.AsynCall("fn", func(ret []interface{}, err error) { 95 | if err != nil { 96 | fmt.Println(err) 97 | } else { 98 | fmt.Println(ret[0], ret[1], ret[2]) 99 | } 100 | }) 101 | 102 | c.AsynCall("add", 1, 2, func(ret interface{}, err error) { 103 | if err != nil { 104 | fmt.Println(err) 105 | } else { 106 | fmt.Println(ret) 107 | } 108 | }) 109 | 110 | c.Cb(<-c.ChanAsynRet) 111 | c.Cb(<-c.ChanAsynRet) 112 | c.Cb(<-c.ChanAsynRet) 113 | c.Cb(<-c.ChanAsynRet) 114 | 115 | // go 116 | s.Go("f0") 117 | 118 | wg.Done() 119 | }() 120 | 121 | wg.Wait() 122 | 123 | // Output: 124 | // 1 125 | // 1 2 3 126 | // 3 127 | // 1 128 | // 1 2 3 129 | // 3 130 | } 131 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/go/go.go: -------------------------------------------------------------------------------- 1 | package g 2 | 3 | import ( 4 | "container/list" 5 | "leaf/conf" 6 | "leaf/log" 7 | "runtime" 8 | "sync" 9 | ) 10 | 11 | // one Go per goroutine (goroutine not safe) 12 | type Go struct { 13 | ChanCb chan func() 14 | pendingGo int 15 | } 16 | 17 | type LinearGo struct { 18 | f func() 19 | cb func() 20 | } 21 | 22 | type LinearContext struct { 23 | g *Go 24 | linearGo *list.List 25 | mutexLinearGo sync.Mutex 26 | mutexExecution sync.Mutex 27 | } 28 | 29 | func New(l int) *Go { 30 | g := new(Go) 31 | g.ChanCb = make(chan func(), l) 32 | return g 33 | } 34 | 35 | func (g *Go) Go(f func(), cb func()) { 36 | g.pendingGo++ 37 | 38 | go func() { 39 | defer func() { 40 | g.ChanCb <- cb 41 | if r := recover(); r != nil { 42 | if conf.LenStackBuf > 0 { 43 | buf := make([]byte, conf.LenStackBuf) 44 | l := runtime.Stack(buf, false) 45 | log.Error("%v: %s", r, buf[:l]) 46 | } else { 47 | log.Error("%v", r) 48 | } 49 | } 50 | }() 51 | 52 | f() 53 | }() 54 | } 55 | 56 | func (g *Go) Cb(cb func()) { 57 | defer func() { 58 | g.pendingGo-- 59 | if r := recover(); r != nil { 60 | if conf.LenStackBuf > 0 { 61 | buf := make([]byte, conf.LenStackBuf) 62 | l := runtime.Stack(buf, false) 63 | log.Error("%v: %s", r, buf[:l]) 64 | } else { 65 | log.Error("%v", r) 66 | } 67 | } 68 | }() 69 | 70 | if cb != nil { 71 | cb() 72 | } 73 | } 74 | 75 | func (g *Go) Close() { 76 | for g.pendingGo > 0 { 77 | g.Cb(<-g.ChanCb) 78 | } 79 | } 80 | 81 | func (g *Go) NewLinearContext() *LinearContext { 82 | c := new(LinearContext) 83 | c.g = g 84 | c.linearGo = list.New() 85 | return c 86 | } 87 | 88 | func (c *LinearContext) Go(f func(), cb func()) { 89 | c.g.pendingGo++ 90 | 91 | c.mutexLinearGo.Lock() 92 | c.linearGo.PushBack(&LinearGo{f: f, cb: cb}) 93 | c.mutexLinearGo.Unlock() 94 | 95 | go func() { 96 | c.mutexExecution.Lock() 97 | defer c.mutexExecution.Unlock() 98 | 99 | c.mutexLinearGo.Lock() 100 | e := c.linearGo.Remove(c.linearGo.Front()).(*LinearGo) 101 | c.mutexLinearGo.Unlock() 102 | 103 | defer func() { 104 | c.g.ChanCb <- e.cb 105 | if r := recover(); r != nil { 106 | if conf.LenStackBuf > 0 { 107 | buf := make([]byte, conf.LenStackBuf) 108 | l := runtime.Stack(buf, false) 109 | log.Error("%v: %s", r, buf[:l]) 110 | } else { 111 | log.Error("%v", r) 112 | } 113 | } 114 | }() 115 | 116 | e.f() 117 | }() 118 | } 119 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/network/udp_msg.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "math" 7 | ) 8 | 9 | // -------------- 10 | // | len | data | 11 | // -------------- 12 | type MsgParser struct { 13 | lenMsgLen int 14 | minMsgLen uint32 15 | maxMsgLen uint32 16 | littleEndian bool 17 | } 18 | 19 | func NewMsgParser() *MsgParser { 20 | p := new(MsgParser) 21 | p.lenMsgLen = 2 22 | p.minMsgLen = 1 23 | p.maxMsgLen = 4096 24 | p.littleEndian = false 25 | 26 | return p 27 | } 28 | 29 | // It's dangerous to call the method on reading or writing 30 | func (p *MsgParser) SetMsgLen(lenMsgLen int, minMsgLen uint32, maxMsgLen uint32) { 31 | if lenMsgLen == 1 || lenMsgLen == 2 || lenMsgLen == 4 { 32 | p.lenMsgLen = lenMsgLen 33 | } 34 | if minMsgLen != 0 { 35 | p.minMsgLen = minMsgLen 36 | } 37 | if maxMsgLen != 0 { 38 | p.maxMsgLen = maxMsgLen 39 | } 40 | 41 | var max uint32 42 | switch p.lenMsgLen { 43 | case 1: 44 | max = math.MaxUint8 45 | case 2: 46 | max = math.MaxUint16 47 | case 4: 48 | max = math.MaxUint32 49 | } 50 | if p.minMsgLen > max { 51 | p.minMsgLen = max 52 | } 53 | if p.maxMsgLen > max { 54 | p.maxMsgLen = max 55 | } 56 | } 57 | 58 | // It's dangerous to call the method on reading or writing 59 | func (p *MsgParser) SetByteOrder(littleEndian bool) { 60 | p.littleEndian = littleEndian 61 | } 62 | 63 | // goroutine safe 64 | func (p *MsgParser) ReadParse(data []byte) ([]byte, error) { 65 | var b [4]byte 66 | bufMsgLen := b[:p.lenMsgLen] 67 | 68 | copy(bufMsgLen, data) 69 | 70 | // parse len 71 | var msgLen uint32 72 | switch p.lenMsgLen { 73 | case 1: 74 | msgLen = uint32(bufMsgLen[0]) 75 | case 2: 76 | if p.littleEndian { 77 | msgLen = uint32(binary.LittleEndian.Uint16(bufMsgLen)) 78 | } else { 79 | msgLen = uint32(binary.BigEndian.Uint16(bufMsgLen)) 80 | } 81 | case 4: 82 | if p.littleEndian { 83 | msgLen = binary.LittleEndian.Uint32(bufMsgLen) 84 | } else { 85 | msgLen = binary.BigEndian.Uint32(bufMsgLen) 86 | } 87 | } 88 | 89 | // check len 90 | if msgLen > p.maxMsgLen { 91 | return nil, errors.New("message too long") 92 | } else if msgLen < p.minMsgLen { 93 | return nil, errors.New("message too short") 94 | } 95 | 96 | // data 97 | msgData := make([]byte, msgLen) 98 | 99 | copy(msgData, data[p.lenMsgLen:]) 100 | 101 | return msgData, nil 102 | } 103 | 104 | // goroutine safe 105 | func (p *MsgParser) WriteParse(data []byte) ([]byte, error) { 106 | // get len 107 | var msgLen uint32 = uint32(len(data)) 108 | 109 | // check len 110 | if msgLen > p.maxMsgLen { 111 | return nil, errors.New("message too long") 112 | } else if msgLen < p.minMsgLen { 113 | return nil, errors.New("message too short") 114 | } 115 | 116 | msg := make([]byte, uint32(p.lenMsgLen)+msgLen) 117 | 118 | // write len 119 | switch p.lenMsgLen { 120 | case 1: 121 | msg[0] = byte(msgLen) 122 | case 2: 123 | if p.littleEndian { 124 | binary.LittleEndian.PutUint16(msg, uint16(msgLen)) 125 | } else { 126 | binary.BigEndian.PutUint16(msg, uint16(msgLen)) 127 | } 128 | case 4: 129 | if p.littleEndian { 130 | binary.LittleEndian.PutUint32(msg, msgLen) 131 | } else { 132 | binary.BigEndian.PutUint32(msg, msgLen) 133 | } 134 | } 135 | 136 | // write data 137 | l := p.lenMsgLen 138 | copy(msg[l:], data) 139 | 140 | return msg, nil 141 | } 142 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "os" 8 | "path" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | // levels 14 | const ( 15 | debugLevel = 0 16 | releaseLevel = 1 17 | errorLevel = 2 18 | fatalLevel = 3 19 | ) 20 | 21 | const ( 22 | printDebugLevel = "[debug ] " 23 | printReleaseLevel = "[release] " 24 | printErrorLevel = "[error ] " 25 | printFatalLevel = "[fatal ] " 26 | ) 27 | 28 | type Logger struct { 29 | level int 30 | baseLogger *log.Logger 31 | baseFile *os.File 32 | } 33 | 34 | func New(strLevel string, pathname string) (*Logger, error) { 35 | // level 36 | var level int 37 | switch strings.ToLower(strLevel) { 38 | case "debug": 39 | level = debugLevel 40 | case "release": 41 | level = releaseLevel 42 | case "error": 43 | level = errorLevel 44 | case "fatal": 45 | level = fatalLevel 46 | default: 47 | return nil, errors.New("unknown level: " + strLevel) 48 | } 49 | 50 | // logger 51 | var baseLogger *log.Logger 52 | var baseFile *os.File 53 | if pathname != "" { 54 | now := time.Now() 55 | 56 | filename := fmt.Sprintf("%d%02d%02d_%02d_%02d_%02d.log", 57 | now.Year(), 58 | now.Month(), 59 | now.Day(), 60 | now.Hour(), 61 | now.Minute(), 62 | now.Second()) 63 | 64 | file, err := os.Create(path.Join(pathname, filename)) 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | baseLogger = log.New(file, "", log.LstdFlags) 70 | baseFile = file 71 | } else { 72 | baseLogger = log.New(os.Stdout, "", log.LstdFlags) 73 | } 74 | 75 | // new 76 | logger := new(Logger) 77 | logger.level = level 78 | logger.baseLogger = baseLogger 79 | logger.baseFile = baseFile 80 | 81 | return logger, nil 82 | } 83 | 84 | // It's dangerous to call the method on logging 85 | func (logger *Logger) Close() { 86 | if logger.baseFile != nil { 87 | logger.baseFile.Close() 88 | } 89 | 90 | logger.baseLogger = nil 91 | logger.baseFile = nil 92 | } 93 | 94 | func (logger *Logger) doPrintf(level int, printLevel string, format string, a ...interface{}) { 95 | if level < logger.level { 96 | return 97 | } 98 | if logger.baseLogger == nil { 99 | panic("logger closed") 100 | } 101 | 102 | format = printLevel + format 103 | logger.baseLogger.Printf(format, a...) 104 | 105 | if level == fatalLevel { 106 | os.Exit(1) 107 | } 108 | } 109 | 110 | func (logger *Logger) Debug(format string, a ...interface{}) { 111 | logger.doPrintf(debugLevel, printDebugLevel, format, a...) 112 | } 113 | 114 | func (logger *Logger) Release(format string, a ...interface{}) { 115 | logger.doPrintf(releaseLevel, printReleaseLevel, format, a...) 116 | } 117 | 118 | func (logger *Logger) Error(format string, a ...interface{}) { 119 | logger.doPrintf(errorLevel, printErrorLevel, format, a...) 120 | } 121 | 122 | func (logger *Logger) Fatal(format string, a ...interface{}) { 123 | logger.doPrintf(fatalLevel, printFatalLevel, format, a...) 124 | } 125 | 126 | var gLogger, _ = New("debug", "") 127 | 128 | // It's dangerous to call the method on logging 129 | func Export(logger *Logger) { 130 | if logger != nil { 131 | gLogger = logger 132 | } 133 | } 134 | 135 | func Debug(format string, a ...interface{}) { 136 | gLogger.Debug(format, a...) 137 | } 138 | 139 | func Release(format string, a ...interface{}) { 140 | gLogger.Release(format, a...) 141 | } 142 | 143 | func Error(format string, a ...interface{}) { 144 | gLogger.Error(format, a...) 145 | } 146 | 147 | func Fatal(format string, a ...interface{}) { 148 | gLogger.Fatal(format, a...) 149 | } 150 | 151 | func Close() { 152 | gLogger.Close() 153 | } 154 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/gate/gate.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | "leaf/chanrpc" 5 | "leaf/kcp" 6 | "leaf/log" 7 | "leaf/network" 8 | "reflect" 9 | "time" 10 | ) 11 | 12 | type Gate struct { 13 | MaxConnNum int 14 | PendingWriteNum int 15 | 16 | Processor network.Processor 17 | AgentChanRPC *chanrpc.Server 18 | 19 | //udp 20 | UDPAddr string 21 | 22 | // msg parser 23 | LenMsgLen int 24 | MinMsgLen uint32 25 | MaxMsgLen uint32 26 | LittleEndian bool 27 | MsgParser *network.MsgParser 28 | } 29 | 30 | func (gate *Gate) Run(closeSig chan bool) { 31 | 32 | var udpServer *network.UDPServer 33 | if gate.UDPAddr != "" { 34 | udpServer = new(network.UDPServer) 35 | udpServer.Addr = gate.UDPAddr 36 | udpServer.MaxConnNum = gate.MaxConnNum 37 | 38 | udpServer.NewAgent = func(conn *kcp.UDPSession) network.Agent { 39 | a := &agent{conn: conn, gate: gate} 40 | if gate.AgentChanRPC != nil { 41 | gate.AgentChanRPC.Go("NewAgent", a) 42 | } 43 | return a 44 | } 45 | // msg parser 46 | msgParser := network.NewMsgParser() 47 | msgParser.SetMsgLen(gate.LenMsgLen, gate.MinMsgLen, gate.MaxMsgLen) 48 | msgParser.SetByteOrder(gate.LittleEndian) 49 | gate.MsgParser = msgParser 50 | 51 | } 52 | 53 | if udpServer != nil { 54 | udpServer.Start() 55 | } 56 | 57 | <-closeSig 58 | 59 | if udpServer != nil { 60 | udpServer.Close() 61 | } 62 | } 63 | 64 | func (gate *Gate) OnDestroy() {} 65 | 66 | type agent struct { 67 | conn *kcp.UDPSession 68 | gate *Gate 69 | userData interface{} 70 | } 71 | 72 | func (a *agent) Run() { 73 | buf := make([]byte, 1024*10) 74 | for { 75 | a.conn.SetReadDeadline(time.Now().Add(2 * time.Second)) 76 | 77 | //1.数据读出来 78 | n, err := a.conn.Read(buf) 79 | if err != nil { 80 | log.Debug("read message: %v", err) 81 | break 82 | } 83 | log.Debug("a.conn.Read(buf): %v", n) 84 | 85 | //2.数据格式化 86 | msgData, err := a.gate.MsgParser.ReadParse(buf[:n]) 87 | if err != nil { 88 | log.Debug("read message MsgParser ReadParse: %v", err) 89 | break 90 | } 91 | 92 | if a.gate.Processor != nil { 93 | msg, err := a.gate.Processor.Unmarshal(msgData) 94 | if err != nil { 95 | log.Debug("unmarshal message error: %v", err) 96 | break 97 | } 98 | err = a.gate.Processor.Route(msg, a) 99 | if err != nil { 100 | log.Debug("route message error: %v", err) 101 | break 102 | } 103 | } 104 | } 105 | } 106 | 107 | func (a *agent) OnClose() { 108 | if a.gate.AgentChanRPC != nil { 109 | err := a.gate.AgentChanRPC.Open(0).Call0("CloseAgent", a) 110 | if err != nil { 111 | log.Error("chanrpc error: %v", err) 112 | } 113 | } 114 | } 115 | 116 | func (a *agent) Write(msg interface{}) { 117 | switch msg.(type) { 118 | case string: 119 | msgData, err := a.gate.MsgParser.WriteParse([]byte(msg.(string))) 120 | if err != nil { 121 | log.Error("string message MsgParser WriteParse: %v", err) 122 | return 123 | } 124 | a.conn.Write(msgData) 125 | default: 126 | if a.gate.Processor != nil { 127 | data, err := a.gate.Processor.Marshal(msg) 128 | if err != nil { 129 | log.Error("marshal message %v error: %v", reflect.TypeOf(msg), err) 130 | return 131 | } 132 | msgData, err := a.gate.MsgParser.WriteParse(data) 133 | if err != nil { 134 | log.Error("marshal message MsgParser WriteParse: %v", err) 135 | return 136 | } 137 | a.conn.Write(msgData) 138 | } 139 | } 140 | } 141 | 142 | func (a *agent) Close() { 143 | a.conn.Close() 144 | } 145 | 146 | func (a *agent) UserData() interface{} { 147 | return a.userData 148 | } 149 | 150 | func (a *agent) SetUserData(data interface{}) { 151 | a.userData = data 152 | } 153 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/kcp/sess_test.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | const port = "127.0.0.1:9999" 11 | const key = "testkey" 12 | 13 | func server() { 14 | l, err := ListenEncrypted(MODE_NORMAL, port, key) 15 | if err != nil { 16 | panic(err) 17 | } 18 | for { 19 | s, err := l.Accept() 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | go handle_client(s) 25 | } 26 | } 27 | 28 | func init() { 29 | go server() 30 | } 31 | 32 | func handle_client(conn *UDPSession) { 33 | conn.SetWindowSize(1024, 1024) 34 | fmt.Println("new client", conn.RemoteAddr()) 35 | buf := make([]byte, 65536) 36 | count := 0 37 | for { 38 | n, err := conn.Read(buf) 39 | if err != nil { 40 | panic(err) 41 | } 42 | count++ 43 | conn.Write(buf[:n]) 44 | } 45 | } 46 | 47 | func TestSendRecv(t *testing.T) { 48 | var wg sync.WaitGroup 49 | const par = 10 50 | wg.Add(par) 51 | for i := 0; i < par; i++ { 52 | go client(&wg) 53 | } 54 | wg.Wait() 55 | } 56 | 57 | func client(wg *sync.WaitGroup) { 58 | cli, err := DialEncrypted(MODE_NORMAL, port, key) 59 | if err != nil { 60 | panic(err) 61 | } 62 | const N = 100 63 | buf := make([]byte, 10) 64 | for i := 0; i < N; i++ { 65 | msg := fmt.Sprintf("hello%v", i) 66 | fmt.Println("sent:", msg) 67 | cli.Write([]byte(msg)) 68 | if n, err := cli.Read(buf); err == nil { 69 | fmt.Println("recv:", string(buf[:n])) 70 | } else { 71 | panic(err) 72 | } 73 | } 74 | cli.Close() 75 | wg.Done() 76 | } 77 | 78 | func TestBigPacket(t *testing.T) { 79 | var wg sync.WaitGroup 80 | wg.Add(1) 81 | go client2(&wg) 82 | wg.Wait() 83 | } 84 | 85 | func client2(wg *sync.WaitGroup) { 86 | cli, err := DialEncrypted(MODE_NORMAL, port, key) 87 | if err != nil { 88 | panic(err) 89 | } 90 | const N = 10 91 | buf := make([]byte, 1024*512) 92 | msg := make([]byte, 1024*512) 93 | for i := 0; i < N; i++ { 94 | cli.Write(msg) 95 | } 96 | println("total written:", len(msg)*N) 97 | 98 | nrecv := 0 99 | cli.SetReadDeadline(time.Now().Add(3 * time.Second)) 100 | for { 101 | n, err := cli.Read(buf) 102 | if err != nil { 103 | break 104 | } else { 105 | nrecv += n 106 | if nrecv == len(msg)*N { 107 | break 108 | } 109 | } 110 | } 111 | 112 | println("total recv:", nrecv) 113 | cli.Close() 114 | wg.Done() 115 | } 116 | 117 | func TestSpeed(t *testing.T) { 118 | start := time.Now() 119 | var wg sync.WaitGroup 120 | wg.Add(1) 121 | go client3(&wg) 122 | wg.Wait() 123 | fmt.Println("time for 1MB rtt", time.Now().Sub(start)) 124 | } 125 | 126 | func client3(wg *sync.WaitGroup) { 127 | cli, err := DialEncrypted(MODE_NORMAL, port, key) 128 | if err != nil { 129 | panic(err) 130 | } 131 | msg := make([]byte, 1024*1024) 132 | buf := make([]byte, 65536) 133 | cli.SetWindowSize(1024, 1024) 134 | cli.Write(msg) 135 | nrecv := 0 136 | for { 137 | n, err := cli.Read(buf) 138 | if err != nil { 139 | fmt.Println(err) 140 | break 141 | } else { 142 | nrecv += n 143 | if nrecv == 1024*1024 { 144 | break 145 | } 146 | } 147 | } 148 | 149 | println("total recv:", nrecv) 150 | cli.Close() 151 | wg.Done() 152 | } 153 | 154 | func TestParallel(t *testing.T) { 155 | par := 200 156 | var wg sync.WaitGroup 157 | wg.Add(par) 158 | fmt.Println("testing parallel", par, "connections") 159 | for i := 0; i < par; i++ { 160 | go client4(&wg) 161 | } 162 | wg.Wait() 163 | } 164 | 165 | func client4(wg *sync.WaitGroup) { 166 | cli, err := DialEncrypted(MODE_NORMAL, port, key) 167 | if err != nil { 168 | panic(err) 169 | } 170 | const N = 1000 171 | buf := make([]byte, 10) 172 | for i := 0; i < N; i++ { 173 | msg := fmt.Sprintf("hello%v", i) 174 | cli.Write([]byte(msg)) 175 | if _, err := cli.Read(buf); err != nil { 176 | break 177 | } 178 | } 179 | cli.Close() 180 | wg.Done() 181 | } 182 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/network/json/json.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "leaf/chanrpc" 8 | "leaf/log" 9 | "reflect" 10 | ) 11 | 12 | type Processor struct { 13 | msgInfo map[string]*MsgInfo 14 | } 15 | 16 | type MsgInfo struct { 17 | msgType reflect.Type 18 | msgRouter *chanrpc.Server 19 | msgHandler MsgHandler 20 | } 21 | 22 | type MsgHandler func([]interface{}) 23 | 24 | func NewProcessor() *Processor { 25 | p := new(Processor) 26 | p.msgInfo = make(map[string]*MsgInfo) 27 | return p 28 | } 29 | 30 | // It's dangerous to call the method on routing or marshaling (unmarshaling) 31 | func (p *Processor) Register(msg interface{}) { 32 | msgType := reflect.TypeOf(msg) 33 | if msgType == nil || msgType.Kind() != reflect.Ptr { 34 | log.Fatal("json message pointer required") 35 | } 36 | msgID := msgType.Elem().Name() 37 | if msgID == "" { 38 | log.Fatal("unnamed json message") 39 | } 40 | if _, ok := p.msgInfo[msgID]; ok { 41 | log.Fatal("message %v is already registered", msgID) 42 | } 43 | 44 | i := new(MsgInfo) 45 | i.msgType = msgType 46 | p.msgInfo[msgID] = i 47 | } 48 | 49 | // It's dangerous to call the method on routing or marshaling (unmarshaling) 50 | func (p *Processor) SetRouter(msg interface{}, msgRouter *chanrpc.Server) { 51 | msgType := reflect.TypeOf(msg) 52 | if msgType == nil || msgType.Kind() != reflect.Ptr { 53 | log.Fatal("json message pointer required") 54 | } 55 | msgID := msgType.Elem().Name() 56 | i, ok := p.msgInfo[msgID] 57 | if !ok { 58 | log.Fatal("message %v not registered", msgID) 59 | } 60 | 61 | i.msgRouter = msgRouter 62 | } 63 | 64 | // It's dangerous to call the method on routing or marshaling (unmarshaling) 65 | func (p *Processor) SetHandler(msg interface{}, msgHandler MsgHandler) { 66 | msgType := reflect.TypeOf(msg) 67 | if msgType == nil || msgType.Kind() != reflect.Ptr { 68 | log.Fatal("json message pointer required") 69 | } 70 | msgID := msgType.Elem().Name() 71 | i, ok := p.msgInfo[msgID] 72 | if !ok { 73 | log.Fatal("message %v not registered", msgID) 74 | } 75 | 76 | i.msgHandler = msgHandler 77 | } 78 | 79 | // goroutine safe 80 | func (p *Processor) Route(msg interface{}, userData interface{}) error { 81 | msgType := reflect.TypeOf(msg) 82 | if msgType == nil || msgType.Kind() != reflect.Ptr { 83 | return errors.New("json message pointer required") 84 | } 85 | msgID := msgType.Elem().Name() 86 | i, ok := p.msgInfo[msgID] 87 | if !ok { 88 | return fmt.Errorf("message %v not registered", msgID) 89 | } 90 | 91 | if i.msgHandler != nil { 92 | i.msgHandler([]interface{}{msg, userData}) 93 | } 94 | if i.msgRouter != nil { 95 | i.msgRouter.Go(msgType, msg, userData) 96 | } 97 | return nil 98 | } 99 | 100 | // goroutine safe 101 | func (p *Processor) Unmarshal(data []byte) (interface{}, error) { 102 | var m map[string]json.RawMessage 103 | err := json.Unmarshal(data, &m) 104 | if err != nil { 105 | return nil, err 106 | } 107 | if len(m) != 1 { 108 | return nil, errors.New("invalid json data") 109 | } 110 | 111 | for msgID, data := range m { 112 | i, ok := p.msgInfo[msgID] 113 | if !ok { 114 | return nil, fmt.Errorf("message %v not registered", msgID) 115 | } 116 | 117 | // msg 118 | msg := reflect.New(i.msgType.Elem()).Interface() 119 | return msg, json.Unmarshal(data, msg) 120 | } 121 | 122 | panic("bug") 123 | } 124 | 125 | // goroutine safe 126 | func (p *Processor) Marshal(msg interface{}) ([]byte, error) { 127 | msgType := reflect.TypeOf(msg) 128 | if msgType == nil || msgType.Kind() != reflect.Ptr { 129 | return nil, errors.New("json message pointer required") 130 | } 131 | msgID := msgType.Elem().Name() 132 | if _, ok := p.msgInfo[msgID]; !ok { 133 | return nil, fmt.Errorf("message %v not registered", msgID) 134 | } 135 | 136 | // data 137 | m := map[string]interface{}{msgID: msg} 138 | data, err := json.Marshal(m) 139 | return data, err 140 | } 141 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/db/mongodb/mongodb.go: -------------------------------------------------------------------------------- 1 | package mongodb 2 | 3 | import ( 4 | "container/heap" 5 | "leaf/log" 6 | "sync" 7 | "time" 8 | 9 | "gopkg.in/mgo.v2" 10 | "gopkg.in/mgo.v2/bson" 11 | ) 12 | 13 | // session 14 | type Session struct { 15 | *mgo.Session 16 | ref int 17 | index int 18 | } 19 | 20 | // session heap 21 | type SessionHeap []*Session 22 | 23 | func (h SessionHeap) Len() int { 24 | return len(h) 25 | } 26 | 27 | func (h SessionHeap) Less(i, j int) bool { 28 | return h[i].ref < h[j].ref 29 | } 30 | 31 | func (h SessionHeap) Swap(i, j int) { 32 | h[i], h[j] = h[j], h[i] 33 | h[i].index = i 34 | h[j].index = j 35 | } 36 | 37 | func (h *SessionHeap) Push(s interface{}) { 38 | s.(*Session).index = len(*h) 39 | *h = append(*h, s.(*Session)) 40 | } 41 | 42 | func (h *SessionHeap) Pop() interface{} { 43 | l := len(*h) 44 | s := (*h)[l-1] 45 | s.index = -1 46 | *h = (*h)[:l-1] 47 | return s 48 | } 49 | 50 | type DialContext struct { 51 | sync.Mutex 52 | sessions SessionHeap 53 | } 54 | 55 | // goroutine safe 56 | func Dial(url string, sessionNum int) (*DialContext, error) { 57 | c, err := DialWithTimeout(url, sessionNum, 10*time.Second, 5*time.Minute) 58 | return c, err 59 | } 60 | 61 | // goroutine safe 62 | func DialWithTimeout(url string, sessionNum int, dialTimeout time.Duration, timeout time.Duration) (*DialContext, error) { 63 | if sessionNum <= 0 { 64 | sessionNum = 100 65 | log.Release("invalid sessionNum, reset to %v", sessionNum) 66 | } 67 | 68 | s, err := mgo.DialWithTimeout(url, dialTimeout) 69 | if err != nil { 70 | return nil, err 71 | } 72 | s.SetSyncTimeout(timeout) 73 | s.SetSocketTimeout(timeout) 74 | 75 | c := new(DialContext) 76 | 77 | // sessions 78 | c.sessions = make(SessionHeap, sessionNum) 79 | c.sessions[0] = &Session{s, 0, 0} 80 | for i := 1; i < sessionNum; i++ { 81 | c.sessions[i] = &Session{s.New(), 0, i} 82 | } 83 | heap.Init(&c.sessions) 84 | 85 | return c, nil 86 | } 87 | 88 | // goroutine safe 89 | func (c *DialContext) Close() { 90 | c.Lock() 91 | for _, s := range c.sessions { 92 | s.Close() 93 | if s.ref != 0 { 94 | log.Error("session ref = %v", s.ref) 95 | } 96 | } 97 | c.Unlock() 98 | } 99 | 100 | // goroutine safe 101 | func (c *DialContext) Ref() *Session { 102 | c.Lock() 103 | s := c.sessions[0] 104 | if s.ref == 0 { 105 | s.Refresh() 106 | } 107 | s.ref++ 108 | heap.Fix(&c.sessions, 0) 109 | c.Unlock() 110 | 111 | return s 112 | } 113 | 114 | // goroutine safe 115 | func (c *DialContext) UnRef(s *Session) { 116 | c.Lock() 117 | s.ref-- 118 | heap.Fix(&c.sessions, s.index) 119 | c.Unlock() 120 | } 121 | 122 | // goroutine safe 123 | func (c *DialContext) EnsureCounter(db string, collection string, id string) error { 124 | s := c.Ref() 125 | defer c.UnRef(s) 126 | 127 | err := s.DB(db).C(collection).Insert(bson.M{ 128 | "_id": id, 129 | "seq": 0, 130 | }) 131 | if mgo.IsDup(err) { 132 | return nil 133 | } else { 134 | return err 135 | } 136 | } 137 | 138 | // goroutine safe 139 | func (c *DialContext) NextSeq(db string, collection string, id string) (int, error) { 140 | s := c.Ref() 141 | defer c.UnRef(s) 142 | 143 | var res struct { 144 | Seq int 145 | } 146 | _, err := s.DB(db).C(collection).FindId(id).Apply(mgo.Change{ 147 | Update: bson.M{"$inc": bson.M{"seq": 1}}, 148 | ReturnNew: true, 149 | }, &res) 150 | 151 | return res.Seq, err 152 | } 153 | 154 | // goroutine safe 155 | func (c *DialContext) EnsureIndex(db string, collection string, key []string) error { 156 | s := c.Ref() 157 | defer c.UnRef(s) 158 | 159 | return s.DB(db).C(collection).EnsureIndex(mgo.Index{ 160 | Key: key, 161 | Unique: false, 162 | Sparse: true, 163 | }) 164 | } 165 | 166 | // goroutine safe 167 | func (c *DialContext) EnsureUniqueIndex(db string, collection string, key []string) error { 168 | s := c.Ref() 169 | defer c.UnRef(s) 170 | 171 | return s.DB(db).C(collection).EnsureIndex(mgo.Index{ 172 | Key: key, 173 | Unique: true, 174 | Sparse: true, 175 | }) 176 | } 177 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/recordfile/recordfile.go: -------------------------------------------------------------------------------- 1 | package recordfile 2 | 3 | import ( 4 | "encoding/csv" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "os" 9 | "reflect" 10 | "strconv" 11 | ) 12 | 13 | var Comma = '\t' 14 | var Comment = '#' 15 | 16 | type Index map[interface{}]interface{} 17 | 18 | type RecordFile struct { 19 | Comma rune 20 | Comment rune 21 | typeRecord reflect.Type 22 | records []interface{} 23 | indexes []Index 24 | } 25 | 26 | func New(st interface{}) (*RecordFile, error) { 27 | typeRecord := reflect.TypeOf(st) 28 | if typeRecord == nil || typeRecord.Kind() != reflect.Struct { 29 | return nil, errors.New("st must be a struct") 30 | } 31 | 32 | for i := 0; i < typeRecord.NumField(); i++ { 33 | f := typeRecord.Field(i) 34 | 35 | kind := f.Type.Kind() 36 | switch kind { 37 | case reflect.Bool: 38 | case reflect.Int: 39 | case reflect.Int8: 40 | case reflect.Int16: 41 | case reflect.Int32: 42 | case reflect.Int64: 43 | case reflect.Uint: 44 | case reflect.Uint8: 45 | case reflect.Uint16: 46 | case reflect.Uint32: 47 | case reflect.Uint64: 48 | case reflect.Float32: 49 | case reflect.Float64: 50 | case reflect.String: 51 | case reflect.Struct: 52 | case reflect.Array: 53 | case reflect.Slice: 54 | default: 55 | return nil, fmt.Errorf("invalid type: %v %s", 56 | f.Name, kind) 57 | } 58 | 59 | tag := f.Tag 60 | if tag == "index" { 61 | switch kind { 62 | case reflect.Struct, reflect.Array, reflect.Slice: 63 | return nil, fmt.Errorf("could not index %s field %v %v", 64 | kind, i, f.Name) 65 | } 66 | } 67 | } 68 | 69 | rf := new(RecordFile) 70 | rf.typeRecord = typeRecord 71 | 72 | return rf, nil 73 | } 74 | 75 | func (rf *RecordFile) Read(name string) error { 76 | file, err := os.Open(name) 77 | if err != nil { 78 | return err 79 | } 80 | defer file.Close() 81 | 82 | if rf.Comma == 0 { 83 | rf.Comma = Comma 84 | } 85 | if rf.Comment == 0 { 86 | rf.Comment = Comment 87 | } 88 | reader := csv.NewReader(file) 89 | reader.Comma = rf.Comma 90 | reader.Comment = rf.Comment 91 | lines, err := reader.ReadAll() 92 | if err != nil { 93 | return err 94 | } 95 | 96 | typeRecord := rf.typeRecord 97 | 98 | // make records 99 | records := make([]interface{}, len(lines)-1) 100 | 101 | // make indexes 102 | indexes := []Index{} 103 | for i := 0; i < typeRecord.NumField(); i++ { 104 | tag := typeRecord.Field(i).Tag 105 | if tag == "index" { 106 | indexes = append(indexes, make(Index)) 107 | } 108 | } 109 | 110 | for n := 1; n < len(lines); n++ { 111 | value := reflect.New(typeRecord) 112 | records[n-1] = value.Interface() 113 | record := value.Elem() 114 | 115 | line := lines[n] 116 | if len(line) != typeRecord.NumField() { 117 | return fmt.Errorf("line %v, field count mismatch: %v %v", 118 | n, len(line), typeRecord.NumField()) 119 | } 120 | 121 | iIndex := 0 122 | 123 | for i := 0; i < typeRecord.NumField(); i++ { 124 | f := typeRecord.Field(i) 125 | 126 | // records 127 | strField := line[i] 128 | field := record.Field(i) 129 | if !field.CanSet() { 130 | continue 131 | } 132 | 133 | var err error 134 | 135 | kind := f.Type.Kind() 136 | if kind == reflect.Bool { 137 | var v bool 138 | v, err = strconv.ParseBool(strField) 139 | if err == nil { 140 | field.SetBool(v) 141 | } 142 | } else if kind == reflect.Int || 143 | kind == reflect.Int8 || 144 | kind == reflect.Int16 || 145 | kind == reflect.Int32 || 146 | kind == reflect.Int64 { 147 | var v int64 148 | v, err = strconv.ParseInt(strField, 0, f.Type.Bits()) 149 | if err == nil { 150 | field.SetInt(v) 151 | } 152 | } else if kind == reflect.Uint || 153 | kind == reflect.Uint8 || 154 | kind == reflect.Uint16 || 155 | kind == reflect.Uint32 || 156 | kind == reflect.Uint64 { 157 | var v uint64 158 | v, err = strconv.ParseUint(strField, 0, f.Type.Bits()) 159 | if err == nil { 160 | field.SetUint(v) 161 | } 162 | } else if kind == reflect.Float32 || 163 | kind == reflect.Float64 { 164 | var v float64 165 | v, err = strconv.ParseFloat(strField, f.Type.Bits()) 166 | if err == nil { 167 | field.SetFloat(v) 168 | } 169 | } else if kind == reflect.String { 170 | field.SetString(strField) 171 | } else if kind == reflect.Struct || 172 | kind == reflect.Array || 173 | kind == reflect.Slice { 174 | err = json.Unmarshal([]byte(strField), field.Addr().Interface()) 175 | } 176 | 177 | if err != nil { 178 | return fmt.Errorf("parse field (row=%v, col=%v) error: %v", 179 | n, i, err) 180 | } 181 | 182 | // indexes 183 | if f.Tag == "index" { 184 | index := indexes[iIndex] 185 | iIndex++ 186 | if _, ok := index[field.Interface()]; ok { 187 | return fmt.Errorf("index error: duplicate at (row=%v, col=%v)", 188 | n, i) 189 | } 190 | index[field.Interface()] = records[n-1] 191 | } 192 | } 193 | } 194 | 195 | rf.records = records 196 | rf.indexes = indexes 197 | 198 | return nil 199 | } 200 | 201 | func (rf *RecordFile) Record(i int) interface{} { 202 | return rf.records[i] 203 | } 204 | 205 | func (rf *RecordFile) NumRecord() int { 206 | return len(rf.records) 207 | } 208 | 209 | func (rf *RecordFile) Indexes(i int) Index { 210 | if i >= len(rf.indexes) { 211 | return nil 212 | } 213 | return rf.indexes[i] 214 | } 215 | 216 | func (rf *RecordFile) Index(i interface{}) interface{} { 217 | index := rf.Indexes(0) 218 | if index == nil { 219 | return nil 220 | } 221 | return index[i] 222 | } 223 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/timer/cronexpr.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | // reference: https://github.com/robfig/cron 4 | import ( 5 | "fmt" 6 | "math" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | // Field name | Mandatory? | Allowed values | Allowed special characters 13 | // ---------- | ---------- | -------------- | -------------------------- 14 | // Seconds | No | 0-59 | * / , - 15 | // Minutes | Yes | 0-59 | * / , - 16 | // Hours | Yes | 0-23 | * / , - 17 | // Day of month | Yes | 1-31 | * / , - 18 | // Month | Yes | 1-12 | * / , - 19 | // Day of week | Yes | 0-6 | * / , - 20 | type CronExpr struct { 21 | sec uint64 22 | min uint64 23 | hour uint64 24 | dom uint64 25 | month uint64 26 | dow uint64 27 | } 28 | 29 | // goroutine safe 30 | func NewCronExpr(expr string) (cronExpr *CronExpr, err error) { 31 | fields := strings.Fields(expr) 32 | if len(fields) != 5 && len(fields) != 6 { 33 | err = fmt.Errorf("invalid expr %v: expected 5 or 6 fields, got %v", expr, len(fields)) 34 | return 35 | } 36 | 37 | if len(fields) == 5 { 38 | fields = append([]string{"0"}, fields...) 39 | } 40 | 41 | cronExpr = new(CronExpr) 42 | // Seconds 43 | cronExpr.sec, err = parseCronField(fields[0], 0, 59) 44 | if err != nil { 45 | goto onError 46 | } 47 | // Minutes 48 | cronExpr.min, err = parseCronField(fields[1], 0, 59) 49 | if err != nil { 50 | goto onError 51 | } 52 | // Hours 53 | cronExpr.hour, err = parseCronField(fields[2], 0, 23) 54 | if err != nil { 55 | goto onError 56 | } 57 | // Day of month 58 | cronExpr.dom, err = parseCronField(fields[3], 1, 31) 59 | if err != nil { 60 | goto onError 61 | } 62 | // Month 63 | cronExpr.month, err = parseCronField(fields[4], 1, 12) 64 | if err != nil { 65 | goto onError 66 | } 67 | // Day of week 68 | cronExpr.dow, err = parseCronField(fields[5], 0, 6) 69 | if err != nil { 70 | goto onError 71 | } 72 | return 73 | 74 | onError: 75 | err = fmt.Errorf("invalid expr %v: %v", expr, err) 76 | return 77 | } 78 | 79 | // 1. * 80 | // 2. num 81 | // 3. num-num 82 | // 4. */num 83 | // 5. num/num (means num-max/num) 84 | // 6. num-num/num 85 | func parseCronField(field string, min int, max int) (cronField uint64, err error) { 86 | fields := strings.Split(field, ",") 87 | for _, field := range fields { 88 | rangeAndIncr := strings.Split(field, "/") 89 | if len(rangeAndIncr) > 2 { 90 | err = fmt.Errorf("too many slashes: %v", field) 91 | return 92 | } 93 | 94 | // range 95 | startAndEnd := strings.Split(rangeAndIncr[0], "-") 96 | if len(startAndEnd) > 2 { 97 | err = fmt.Errorf("too many hyphens: %v", rangeAndIncr[0]) 98 | return 99 | } 100 | 101 | var start, end int 102 | if startAndEnd[0] == "*" { 103 | if len(startAndEnd) != 1 { 104 | err = fmt.Errorf("invalid range: %v", rangeAndIncr[0]) 105 | return 106 | } 107 | start = min 108 | end = max 109 | } else { 110 | // start 111 | start, err = strconv.Atoi(startAndEnd[0]) 112 | if err != nil { 113 | err = fmt.Errorf("invalid range: %v", rangeAndIncr[0]) 114 | return 115 | } 116 | // end 117 | if len(startAndEnd) == 1 { 118 | if len(rangeAndIncr) == 2 { 119 | end = max 120 | } else { 121 | end = start 122 | } 123 | } else { 124 | end, err = strconv.Atoi(startAndEnd[1]) 125 | if err != nil { 126 | err = fmt.Errorf("invalid range: %v", rangeAndIncr[0]) 127 | return 128 | } 129 | } 130 | } 131 | 132 | if start > end { 133 | err = fmt.Errorf("invalid range: %v", rangeAndIncr[0]) 134 | return 135 | } 136 | if start < min { 137 | err = fmt.Errorf("out of range [%v, %v]: %v", min, max, rangeAndIncr[0]) 138 | return 139 | } 140 | if end > max { 141 | err = fmt.Errorf("out of range [%v, %v]: %v", min, max, rangeAndIncr[0]) 142 | return 143 | } 144 | 145 | // increment 146 | var incr int 147 | if len(rangeAndIncr) == 1 { 148 | incr = 1 149 | } else { 150 | incr, err = strconv.Atoi(rangeAndIncr[1]) 151 | if err != nil { 152 | err = fmt.Errorf("invalid increment: %v", rangeAndIncr[1]) 153 | return 154 | } 155 | if incr <= 0 { 156 | err = fmt.Errorf("invalid increment: %v", rangeAndIncr[1]) 157 | return 158 | } 159 | } 160 | 161 | // cronField 162 | if incr == 1 { 163 | cronField |= ^(math.MaxUint64 << uint(end+1)) & (math.MaxUint64 << uint(start)) 164 | } else { 165 | for i := start; i <= end; i += incr { 166 | cronField |= 1 << uint(i) 167 | } 168 | } 169 | } 170 | 171 | return 172 | } 173 | 174 | func (e *CronExpr) matchDay(t time.Time) bool { 175 | // day-of-month blank 176 | if e.dom == 0xfffffffe { 177 | return 1< year+1 { 200 | return time.Time{} 201 | } 202 | 203 | // Month 204 | for 1< p.rttmin { 79 | delay += rand.Int() % (p.rttmax - p.rttmin) 80 | } 81 | pkt.setts(p.current + int32(delay)) 82 | if peer == 0 { 83 | p.p12.PushBack(pkt) 84 | } else { 85 | p.p21.PushBack(pkt) 86 | } 87 | return 1 88 | } 89 | 90 | // 接收数据 91 | func (p *LatencySimulator) recv(peer int, data []byte, maxsize int) int32 { 92 | var it *list.Element 93 | if peer == 0 { 94 | it = p.p21.Front() 95 | if p.p21.Len() == 0 { 96 | return -1 97 | } 98 | } else { 99 | it = p.p12.Front() 100 | if p.p12.Len() == 0 { 101 | return -1 102 | } 103 | } 104 | pkt := it.Value.(*DelayPacket) 105 | p.current = iclock() 106 | if p.current < pkt.ts() { 107 | return -2 108 | } 109 | if maxsize < pkt.size() { 110 | return -3 111 | } 112 | if peer == 0 { 113 | p.p21.Remove(it) 114 | } else { 115 | p.p12.Remove(it) 116 | } 117 | maxsize = pkt.size() 118 | copy(data, pkt.ptr()[:maxsize]) 119 | return int32(maxsize) 120 | } 121 | 122 | //===================================================================== 123 | //===================================================================== 124 | 125 | // 模拟网络 126 | var vnet *LatencySimulator 127 | 128 | // 测试用例 129 | func test(mode int) { 130 | // 创建模拟网络:丢包率10%,Rtt 60ms~125ms 131 | vnet = &LatencySimulator{} 132 | vnet.Init(10, 60, 125, 1000) 133 | 134 | // 创建两个端点的 kcp对象,第一个参数 conv是会话编号,同一个会话需要相同 135 | // 最后一个是 user参数,用来传递标识 136 | output1 := func(buf []byte, size int) { 137 | if vnet.send(0, buf, size) != 1 { 138 | } 139 | } 140 | output2 := func(buf []byte, size int) { 141 | if vnet.send(1, buf, size) != 1 { 142 | } 143 | } 144 | kcp1 := NewKCP(0x11223344, output1) 145 | kcp2 := NewKCP(0x11223344, output2) 146 | 147 | current := uint32(iclock()) 148 | slap := current + 20 149 | index := 0 150 | next := 0 151 | var sumrtt uint32 = 0 152 | count := 0 153 | maxrtt := 0 154 | 155 | // 配置窗口大小:平均延迟200ms,每20ms发送一个包, 156 | // 而考虑到丢包重发,设置最大收发窗口为128 157 | kcp1.WndSize(128, 128) 158 | kcp2.WndSize(128, 128) 159 | 160 | // 判断测试用例的模式 161 | if mode == 0 { 162 | // 默认模式 163 | kcp1.NoDelay(0, 10, 0, 0) 164 | kcp2.NoDelay(0, 10, 0, 0) 165 | } else if mode == 1 { 166 | // 普通模式,关闭流控等 167 | kcp1.NoDelay(0, 10, 0, 1) 168 | kcp2.NoDelay(0, 10, 0, 1) 169 | } else { 170 | // 启动快速模式 171 | // 第二个参数 nodelay-启用以后若干常规加速将启动 172 | // 第三个参数 interval为内部处理时钟,默认设置为 10ms 173 | // 第四个参数 resend为快速重传指标,设置为2 174 | // 第五个参数 为是否禁用常规流控,这里禁止 175 | kcp1.NoDelay(1, 10, 2, 1) 176 | kcp2.NoDelay(1, 10, 2, 1) 177 | } 178 | 179 | var buffer []byte = make([]byte, 2000) 180 | var hr int32 181 | 182 | ts1 := iclock() 183 | 184 | for { 185 | time.Sleep(100 * time.Millisecond) 186 | current = uint32(iclock()) 187 | kcp1.Update(uint32(iclock())) 188 | kcp2.Update(uint32(iclock())) 189 | 190 | // 每隔 20ms,kcp1发送数据 191 | for ; current >= slap; slap += 20 { 192 | buf := new(bytes.Buffer) 193 | binary.Write(buf, binary.LittleEndian, uint32(index)) 194 | index++ 195 | binary.Write(buf, binary.LittleEndian, uint32(current)) 196 | // 发送上层协议包 197 | kcp1.Send(buf.Bytes()) 198 | //println("now", iclock()) 199 | } 200 | 201 | // 处理虚拟网络:检测是否有udp包从p1->p2 202 | for { 203 | hr = vnet.recv(1, buffer, 2000) 204 | if hr < 0 { 205 | break 206 | } 207 | // 如果 p2收到udp,则作为下层协议输入到kcp2 208 | kcp2.Input(buffer[:hr]) 209 | } 210 | 211 | // 处理虚拟网络:检测是否有udp包从p2->p1 212 | for { 213 | hr = vnet.recv(0, buffer, 2000) 214 | if hr < 0 { 215 | break 216 | } 217 | // 如果 p1收到udp,则作为下层协议输入到kcp1 218 | kcp1.Input(buffer[:hr]) 219 | //println("@@@@", hr, r) 220 | } 221 | 222 | // kcp2接收到任何包都返回回去 223 | for { 224 | hr = int32(kcp2.Recv(buffer[:10])) 225 | // 没有收到包就退出 226 | if hr < 0 { 227 | break 228 | } 229 | // 如果收到包就回射 230 | buf := bytes.NewReader(buffer) 231 | var sn uint32 232 | binary.Read(buf, binary.LittleEndian, &sn) 233 | kcp2.Send(buffer[:hr]) 234 | } 235 | 236 | // kcp1收到kcp2的回射数据 237 | for { 238 | hr = int32(kcp1.Recv(buffer[:10])) 239 | buf := bytes.NewReader(buffer) 240 | // 没有收到包就退出 241 | if hr < 0 { 242 | break 243 | } 244 | var sn uint32 245 | var ts, rtt uint32 246 | binary.Read(buf, binary.LittleEndian, &sn) 247 | binary.Read(buf, binary.LittleEndian, &ts) 248 | rtt = uint32(current) - ts 249 | 250 | if sn != uint32(next) { 251 | // 如果收到的包不连续 252 | //for i:=0;i<8 ;i++ { 253 | //println("---", i, buffer[i]) 254 | //} 255 | println("ERROR sn ", count, "<->", next, sn) 256 | return 257 | } 258 | 259 | next++ 260 | sumrtt += rtt 261 | count++ 262 | if rtt > uint32(maxrtt) { 263 | maxrtt = int(rtt) 264 | } 265 | 266 | println("[RECV] mode=", mode, " sn=", sn, " rtt=", rtt) 267 | } 268 | 269 | if next > 100 { 270 | break 271 | } 272 | } 273 | 274 | ts1 = iclock() - ts1 275 | 276 | names := []string{"default", "normal", "fast"} 277 | fmt.Printf("%s mode result (%dms):\n", names[mode], ts1) 278 | fmt.Printf("avgrtt=%d maxrtt=%d\n", int(sumrtt/uint32(count)), maxrtt) 279 | } 280 | 281 | func TestNetwork(t *testing.T) { 282 | test(0) // 默认模式,类似 TCP:正常模式,无快速重传,常规流控 283 | test(1) // 普通模式,关闭流控等 284 | test(2) // 快速模式,所有开关都打开,且关闭流控 285 | } 286 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/chanrpc/chanrpc.go: -------------------------------------------------------------------------------- 1 | package chanrpc 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "leaf/conf" 7 | "runtime" 8 | ) 9 | 10 | // one server per goroutine (goroutine not safe) 11 | // one client per goroutine (goroutine not safe) 12 | type Server struct { 13 | // id -> function 14 | // 15 | // function: 16 | // func(args []interface{}) 17 | // func(args []interface{}) interface{} 18 | // func(args []interface{}) []interface{} 19 | functions map[interface{}]interface{} 20 | ChanCall chan *CallInfo 21 | } 22 | 23 | type CallInfo struct { 24 | f interface{} 25 | args []interface{} 26 | chanRet chan *RetInfo 27 | cb interface{} 28 | } 29 | 30 | type RetInfo struct { 31 | // nil 32 | // interface{} 33 | // []interface{} 34 | ret interface{} 35 | err error 36 | // callback: 37 | // func(err error) 38 | // func(ret interface{}, err error) 39 | // func(ret []interface{}, err error) 40 | cb interface{} 41 | } 42 | 43 | type Client struct { 44 | s *Server 45 | chanSyncRet chan *RetInfo 46 | ChanAsynRet chan *RetInfo 47 | pendingAsynCall int 48 | } 49 | 50 | func NewServer(l int) *Server { 51 | s := new(Server) 52 | s.functions = make(map[interface{}]interface{}) 53 | s.ChanCall = make(chan *CallInfo, l) 54 | return s 55 | } 56 | 57 | // you must call the function before calling Open and Go 58 | func (s *Server) Register(id interface{}, f interface{}) { 59 | switch f.(type) { 60 | case func([]interface{}): 61 | case func([]interface{}) interface{}: 62 | case func([]interface{}) []interface{}: 63 | default: 64 | panic(fmt.Sprintf("function id %v: definition of function is invalid", id)) 65 | } 66 | 67 | if _, ok := s.functions[id]; ok { 68 | panic(fmt.Sprintf("function id %v: already registered", id)) 69 | } 70 | 71 | s.functions[id] = f 72 | } 73 | 74 | func (s *Server) ret(ci *CallInfo, ri *RetInfo) (err error) { 75 | if ci.chanRet == nil { 76 | return 77 | } 78 | 79 | defer func() { 80 | if r := recover(); r != nil { 81 | err = r.(error) 82 | } 83 | }() 84 | 85 | ri.cb = ci.cb 86 | ci.chanRet <- ri 87 | return 88 | } 89 | 90 | func (s *Server) Exec(ci *CallInfo) (err error) { 91 | defer func() { 92 | if r := recover(); r != nil { 93 | if conf.LenStackBuf > 0 { 94 | buf := make([]byte, conf.LenStackBuf) 95 | l := runtime.Stack(buf, false) 96 | err = fmt.Errorf("%v: %s", r, buf[:l]) 97 | } else { 98 | err = fmt.Errorf("%v", r) 99 | } 100 | 101 | s.ret(ci, &RetInfo{err: fmt.Errorf("%v", r)}) 102 | } 103 | }() 104 | 105 | // execute 106 | switch ci.f.(type) { 107 | case func([]interface{}): 108 | ci.f.(func([]interface{}))(ci.args) 109 | return s.ret(ci, &RetInfo{}) 110 | case func([]interface{}) interface{}: 111 | ret := ci.f.(func([]interface{}) interface{})(ci.args) 112 | return s.ret(ci, &RetInfo{ret: ret}) 113 | case func([]interface{}) []interface{}: 114 | ret := ci.f.(func([]interface{}) []interface{})(ci.args) 115 | return s.ret(ci, &RetInfo{ret: ret}) 116 | } 117 | 118 | panic("bug") 119 | } 120 | 121 | // goroutine safe 122 | func (s *Server) Go(id interface{}, args ...interface{}) { 123 | f := s.functions[id] 124 | if f == nil { 125 | return 126 | } 127 | 128 | defer func() { 129 | recover() 130 | }() 131 | 132 | s.ChanCall <- &CallInfo{ 133 | f: f, 134 | args: args, 135 | } 136 | } 137 | 138 | func (s *Server) Close() { 139 | close(s.ChanCall) 140 | 141 | for ci := range s.ChanCall { 142 | s.ret(ci, &RetInfo{ 143 | err: errors.New("chanrpc server closed"), 144 | }) 145 | } 146 | } 147 | 148 | // goroutine safe 149 | func (s *Server) Open(l int) *Client { 150 | c := new(Client) 151 | c.s = s 152 | c.chanSyncRet = make(chan *RetInfo, 1) 153 | c.ChanAsynRet = make(chan *RetInfo, l) 154 | return c 155 | } 156 | 157 | func (c *Client) call(ci *CallInfo, block bool) (err error) { 158 | defer func() { 159 | if r := recover(); r != nil { 160 | err = r.(error) 161 | } 162 | }() 163 | 164 | if block { 165 | c.s.ChanCall <- ci 166 | } else { 167 | select { 168 | case c.s.ChanCall <- ci: 169 | default: 170 | err = errors.New("chanrpc channel full") 171 | } 172 | } 173 | return 174 | } 175 | 176 | func (c *Client) f(id interface{}, n int) (f interface{}, err error) { 177 | f = c.s.functions[id] 178 | if f == nil { 179 | err = fmt.Errorf("function id %v: function not registered", id) 180 | return 181 | } 182 | 183 | var ok bool 184 | switch n { 185 | case 0: 186 | _, ok = f.(func([]interface{})) 187 | case 1: 188 | _, ok = f.(func([]interface{}) interface{}) 189 | case 2: 190 | _, ok = f.(func([]interface{}) []interface{}) 191 | default: 192 | panic("bug") 193 | } 194 | 195 | if !ok { 196 | err = fmt.Errorf("function id %v: return type mismatch", id) 197 | } 198 | return 199 | } 200 | 201 | func (c *Client) Call0(id interface{}, args ...interface{}) error { 202 | f, err := c.f(id, 0) 203 | if err != nil { 204 | return err 205 | } 206 | 207 | err = c.call(&CallInfo{ 208 | f: f, 209 | args: args, 210 | chanRet: c.chanSyncRet, 211 | }, true) 212 | if err != nil { 213 | return err 214 | } 215 | 216 | ri := <-c.chanSyncRet 217 | return ri.err 218 | } 219 | 220 | func (c *Client) Call1(id interface{}, args ...interface{}) (interface{}, error) { 221 | f, err := c.f(id, 1) 222 | if err != nil { 223 | return nil, err 224 | } 225 | 226 | err = c.call(&CallInfo{ 227 | f: f, 228 | args: args, 229 | chanRet: c.chanSyncRet, 230 | }, true) 231 | if err != nil { 232 | return nil, err 233 | } 234 | 235 | ri := <-c.chanSyncRet 236 | return ri.ret, ri.err 237 | } 238 | 239 | func (c *Client) CallN(id interface{}, args ...interface{}) ([]interface{}, error) { 240 | f, err := c.f(id, 2) 241 | if err != nil { 242 | return nil, err 243 | } 244 | 245 | err = c.call(&CallInfo{ 246 | f: f, 247 | args: args, 248 | chanRet: c.chanSyncRet, 249 | }, true) 250 | if err != nil { 251 | return nil, err 252 | } 253 | 254 | ri := <-c.chanSyncRet 255 | return ri.ret.([]interface{}), ri.err 256 | } 257 | 258 | func (c *Client) asynCall(id interface{}, args []interface{}, cb interface{}, n int) error { 259 | f, err := c.f(id, n) 260 | if err != nil { 261 | return err 262 | } 263 | 264 | err = c.call(&CallInfo{ 265 | f: f, 266 | args: args, 267 | chanRet: c.ChanAsynRet, 268 | cb: cb, 269 | }, false) 270 | if err != nil { 271 | return err 272 | } 273 | 274 | c.pendingAsynCall++ 275 | return nil 276 | } 277 | 278 | func (c *Client) AsynCall(id interface{}, _args ...interface{}) { 279 | if len(_args) < 1 { 280 | panic("callback function not found") 281 | } 282 | 283 | // args 284 | var args []interface{} 285 | if len(_args) > 1 { 286 | args = _args[:len(_args)-1] 287 | } 288 | 289 | // cb 290 | cb := _args[len(_args)-1] 291 | switch cb.(type) { 292 | case func(error): 293 | err := c.asynCall(id, args, cb, 0) 294 | if err != nil { 295 | cb.(func(error))(err) 296 | } 297 | case func(interface{}, error): 298 | err := c.asynCall(id, args, cb, 1) 299 | if err != nil { 300 | cb.(func(interface{}, error))(nil, err) 301 | } 302 | case func([]interface{}, error): 303 | err := c.asynCall(id, args, cb, 2) 304 | if err != nil { 305 | cb.(func([]interface{}, error))(nil, err) 306 | } 307 | default: 308 | panic("definition of callback function is invalid") 309 | } 310 | } 311 | 312 | func (c *Client) Cb(ri *RetInfo) { 313 | switch ri.cb.(type) { 314 | case func(error): 315 | ri.cb.(func(error))(ri.err) 316 | case func(interface{}, error): 317 | ri.cb.(func(interface{}, error))(ri.ret, ri.err) 318 | case func([]interface{}, error): 319 | ri.cb.(func([]interface{}, error))(ri.ret.([]interface{}), ri.err) 320 | default: 321 | panic("bug") 322 | } 323 | 324 | c.pendingAsynCall-- 325 | } 326 | 327 | func (c *Client) Close() { 328 | for c.pendingAsynCall > 0 { 329 | c.Cb(<-c.ChanAsynRet) 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/kcp/sess.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "errors" 7 | "log" 8 | "math/rand" 9 | "net" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | var ( 15 | ERR_TIMEOUT = errors.New("i/o timeout") 16 | ERR_BROKEN_PIPE = errors.New("broken pipe") 17 | IV = []byte{167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107} 18 | ) 19 | 20 | type Mode int 21 | 22 | const ( 23 | MODE_DEFAULT Mode = iota 24 | MODE_NORMAL 25 | MODE_FAST 26 | BASE_PORT = 20000 27 | MAX_PORT = 65535 28 | DEFAULT_WND_SIZE = 128 29 | XOR_TABLE_SIZE = 16384 30 | ) 31 | 32 | type ( 33 | UDPSession struct { 34 | kcp *KCP // the core ARQ 35 | conn *net.UDPConn // the underlying UDP socket 36 | xor_tbl []byte 37 | l *Listener // point to server listener if it's a server socket 38 | local, remote net.Addr 39 | rd time.Time // read deadline 40 | sockbuff []byte // kcp receiving is based on packet, I turn it into stream 41 | die chan struct{} 42 | is_closed bool 43 | need_update bool 44 | mu sync.Mutex 45 | event_read chan bool 46 | } 47 | ) 48 | 49 | // create a new udp session for client or server 50 | func newUDPSession(conv uint32, mode Mode, l *Listener, conn *net.UDPConn, remote *net.UDPAddr, xor_tbl []byte) *UDPSession { 51 | sess := new(UDPSession) 52 | sess.die = make(chan struct{}) 53 | sess.local = conn.LocalAddr() 54 | sess.event_read = make(chan bool, 1) 55 | sess.remote = remote 56 | sess.conn = conn 57 | sess.l = l 58 | sess.xor_tbl = xor_tbl 59 | sess.kcp = NewKCP(conv, func(buf []byte, size int) { 60 | if size >= IKCP_OVERHEAD { 61 | if sess.xor_tbl != nil { 62 | xor(sess.xor_tbl, buf) 63 | } 64 | n, err := conn.WriteToUDP(buf[:size], remote) 65 | if err != nil { 66 | log.Println(err, n) 67 | } 68 | } 69 | }) 70 | sess.kcp.WndSize(DEFAULT_WND_SIZE, DEFAULT_WND_SIZE) 71 | switch mode { 72 | case MODE_FAST: 73 | sess.kcp.NoDelay(1, 10, 2, 1) 74 | case MODE_NORMAL: 75 | sess.kcp.NoDelay(0, 20, 0, 1) 76 | default: 77 | sess.kcp.NoDelay(0, 40, 0, 0) 78 | } 79 | 80 | go sess.update_task() 81 | if l == nil { // it's a client connection 82 | go sess.read_loop() 83 | } 84 | return sess 85 | } 86 | 87 | // Read implements the Conn Read method. 88 | func (s *UDPSession) Read(b []byte) (n int, err error) { 89 | for { 90 | s.mu.Lock() 91 | if len(s.sockbuff) > 0 { // copy from buffer 92 | n := copy(b, s.sockbuff) 93 | s.sockbuff = s.sockbuff[n:] 94 | s.mu.Unlock() 95 | return n, nil 96 | } 97 | 98 | if s.is_closed { 99 | s.mu.Unlock() 100 | return 0, ERR_BROKEN_PIPE 101 | } 102 | 103 | if !s.rd.IsZero() { 104 | if time.Now().After(s.rd) { // timeout 105 | s.mu.Unlock() 106 | return 0, ERR_TIMEOUT 107 | } 108 | } 109 | 110 | if n := s.kcp.PeekSize(); n > 0 { // data arrived 111 | buf := make([]byte, n) 112 | if s.kcp.Recv(buf) > 0 { // if Recv() succeeded 113 | n := copy(b, buf) 114 | s.sockbuff = buf[n:] // store remaining bytes into sockbuff for next read 115 | s.mu.Unlock() 116 | return n, nil 117 | } 118 | } 119 | s.mu.Unlock() 120 | 121 | // wait for read event or timeout 122 | select { 123 | case <-s.event_read: 124 | case <-time.After(1 * time.Second): 125 | } 126 | } 127 | } 128 | 129 | // Write implements the Conn Write method. 130 | func (s *UDPSession) Write(b []byte) (n int, err error) { 131 | s.mu.Lock() 132 | defer s.mu.Unlock() 133 | if s.is_closed { 134 | return 0, ERR_BROKEN_PIPE 135 | } 136 | 137 | max := int(s.kcp.mss * 255) 138 | if s.kcp.snd_wnd < 255 { 139 | max = int(s.kcp.mss * s.kcp.snd_wnd) 140 | } 141 | for { 142 | if len(b) <= max { // in most cases 143 | s.kcp.Send(b) 144 | break 145 | } else { 146 | s.kcp.Send(b[:max]) 147 | b = b[max:] 148 | } 149 | } 150 | s.need_update = true 151 | return 152 | } 153 | 154 | // Close closes the connection. 155 | func (s *UDPSession) Close() error { 156 | s.mu.Lock() 157 | defer s.mu.Unlock() 158 | if s.is_closed { 159 | return ERR_BROKEN_PIPE 160 | } 161 | close(s.die) 162 | s.is_closed = true 163 | if s.l == nil { // client socket close 164 | s.conn.Close() 165 | } 166 | return nil 167 | } 168 | 169 | // LocalAddr returns the local network address. The Addr returned is shared by all invocations of LocalAddr, so do not modify it. 170 | func (s *UDPSession) LocalAddr() net.Addr { 171 | return s.local 172 | } 173 | 174 | // RemoteAddr returns the remote network address. The Addr returned is shared by all invocations of RemoteAddr, so do not modify it. 175 | func (s *UDPSession) RemoteAddr() net.Addr { return s.remote } 176 | 177 | // SetDeadline sets the deadline associated with the listener. A zero time value disables the deadline. 178 | func (s *UDPSession) SetDeadline(t time.Time) error { 179 | s.mu.Lock() 180 | defer s.mu.Unlock() 181 | s.rd = t 182 | return nil 183 | } 184 | 185 | // SetReadDeadline implements the Conn SetReadDeadline method. 186 | func (s *UDPSession) SetReadDeadline(t time.Time) error { 187 | s.mu.Lock() 188 | defer s.mu.Unlock() 189 | s.rd = t 190 | return nil 191 | } 192 | 193 | // SetWriteDeadline implements the Conn SetWriteDeadline method. 194 | func (s *UDPSession) SetWriteDeadline(t time.Time) error { 195 | return nil 196 | } 197 | 198 | // SetWindowSize set maximum window size 199 | func (s *UDPSession) SetWindowSize(sndwnd, rcvwnd int) { 200 | s.mu.Lock() 201 | defer s.mu.Unlock() 202 | s.kcp.WndSize(sndwnd, rcvwnd) 203 | } 204 | 205 | // kcp update, input loop 206 | func (s *UDPSession) update_task() { 207 | trigger := time.NewTicker(10 * time.Millisecond) 208 | var nextupdate uint32 209 | for { 210 | select { 211 | case <-trigger.C: 212 | current := uint32(time.Now().UnixNano() / int64(time.Millisecond)) 213 | s.mu.Lock() 214 | if current >= nextupdate || s.need_update { 215 | s.kcp.Update(current) 216 | nextupdate = s.kcp.Check(current) 217 | } 218 | s.need_update = false 219 | s.mu.Unlock() 220 | // deadlink detection may fail fast in high packet lost environment 221 | // I just ignore it for the moment 222 | /* 223 | if s.kcp.state != 0 { // deadlink 224 | close(s.die) 225 | } 226 | */ 227 | case <-s.die: 228 | if s.l != nil { // has listener 229 | s.l.ch_deadlinks <- s.remote 230 | } 231 | return 232 | } 233 | } 234 | } 235 | 236 | func (s *UDPSession) GetConv() uint32 { 237 | return s.kcp.conv 238 | } 239 | 240 | func (s *UDPSession) read_event() { 241 | select { 242 | case s.event_read <- true: 243 | default: 244 | } 245 | } 246 | 247 | // read loop for client session 248 | func (s *UDPSession) read_loop() { 249 | conn := s.conn 250 | buffer := make([]byte, 4096) 251 | for { 252 | conn.SetReadDeadline(time.Now().Add(time.Second)) 253 | if n, err := conn.Read(buffer); err == nil && n >= IKCP_OVERHEAD { 254 | if s.xor_tbl != nil { 255 | xor(s.xor_tbl, buffer) 256 | } 257 | s.mu.Lock() 258 | s.kcp.Input(buffer[:n]) 259 | s.need_update = true 260 | s.mu.Unlock() 261 | s.read_event() 262 | } else if err, ok := err.(*net.OpError); ok && err.Timeout() { 263 | } else { 264 | return 265 | } 266 | 267 | select { 268 | case <-s.die: 269 | return 270 | default: 271 | } 272 | } 273 | } 274 | 275 | type ( 276 | Listener struct { 277 | xor_tbl []byte 278 | conn *net.UDPConn 279 | mode Mode 280 | sessions map[string]*UDPSession 281 | ch_accepts chan *UDPSession 282 | ch_deadlinks chan net.Addr 283 | die chan struct{} 284 | } 285 | ) 286 | 287 | // monitor incoming data for all connections of server 288 | func (l *Listener) monitor() { 289 | conn := l.conn 290 | ch_feed := make(chan func(), 65535) 291 | go l.feed(ch_feed) 292 | buffer := make([]byte, 4096) 293 | for { 294 | conn.SetReadDeadline(time.Now().Add(time.Second)) 295 | if n, from, err := conn.ReadFromUDP(buffer); err == nil && n >= IKCP_OVERHEAD { 296 | data := make([]byte, n) 297 | copy(data, buffer[:n]) 298 | if l.xor_tbl != nil { // decrypt 299 | xor(l.xor_tbl, data) 300 | } 301 | addr := from.String() 302 | s, ok := l.sessions[addr] 303 | if !ok { 304 | var conv uint32 305 | ikcp_decode32u(data, &conv) // conversation id 306 | s := newUDPSession(conv, l.mode, l, conn, from, l.xor_tbl) 307 | ch_feed <- func() { 308 | s.mu.Lock() 309 | s.kcp.Input(data) 310 | s.need_update = true 311 | s.mu.Unlock() 312 | s.read_event() 313 | } 314 | l.sessions[addr] = s 315 | l.ch_accepts <- s 316 | } else { 317 | ch_feed <- func() { 318 | s.mu.Lock() 319 | s.kcp.Input(data) 320 | s.need_update = true 321 | s.mu.Unlock() 322 | s.read_event() 323 | } 324 | } 325 | } 326 | 327 | select { 328 | case deadlink := <-l.ch_deadlinks: // remove deadlinks 329 | delete(l.sessions, deadlink.String()) 330 | case <-l.die: // listener close 331 | return 332 | default: 333 | } 334 | } 335 | } 336 | 337 | // feed data from listener to UDPSessions 338 | func (l *Listener) feed(ch chan func()) { 339 | for { 340 | select { 341 | case f := <-ch: 342 | f() 343 | case <-l.die: 344 | return 345 | } 346 | } 347 | } 348 | 349 | // Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn. 350 | func (l *Listener) Accept() (*UDPSession, error) { 351 | select { 352 | case c := <-l.ch_accepts: 353 | return c, nil 354 | case <-l.die: 355 | return nil, errors.New("listener stopped") 356 | } 357 | } 358 | 359 | // Close stops listening on the TCP address. Already Accepted connections are not closed. 360 | func (l *Listener) Close() error { 361 | if err := l.conn.Close(); err == nil { 362 | close(l.die) 363 | return nil 364 | } else { 365 | return err 366 | } 367 | } 368 | 369 | // Addr returns the listener's network address, The Addr returned is shared by all invocations of Addr, so do not modify it. 370 | func (l *Listener) Addr() net.Addr { 371 | return l.conn.LocalAddr() 372 | } 373 | 374 | func (l *Listener) SessionCount() int { 375 | return len(l.sessions) 376 | } 377 | 378 | // Listen listens for incoming KCP packets addressed to the local address laddr on the network "udp", 379 | // mode must be one of: MODE_DEFAULT,MODE_NORMAL,MODE_FAST 380 | func Listen(mode Mode, laddr string) (*Listener, error) { 381 | return ListenEncrypted(mode, laddr, "") 382 | } 383 | 384 | // Listen listens for incoming KCP packets addressed to the local address laddr on the network "udp" with packet encryption, 385 | // mode must be one of: MODE_DEFAULT,MODE_NORMAL,MODE_FAST 386 | func ListenEncrypted(mode Mode, laddr string, key string) (*Listener, error) { 387 | udpaddr, err := net.ResolveUDPAddr("udp", laddr) 388 | if err != nil { 389 | return nil, err 390 | } 391 | conn, err := net.ListenUDP("udp", udpaddr) 392 | if err != nil { 393 | return nil, err 394 | } 395 | 396 | l := new(Listener) 397 | l.conn = conn 398 | l.mode = mode 399 | l.sessions = make(map[string]*UDPSession) 400 | l.ch_accepts = make(chan *UDPSession, 10) 401 | l.ch_deadlinks = make(chan net.Addr, 10) 402 | l.die = make(chan struct{}) 403 | if key != "" { 404 | pass := make([]byte, aes.BlockSize) 405 | copy(pass, []byte(key)) 406 | if block, err := aes.NewCipher(pass); err == nil { 407 | l.xor_tbl = make([]byte, XOR_TABLE_SIZE) 408 | stream := cipher.NewOFB(block, IV) 409 | stream.XORKeyStream(l.xor_tbl, l.xor_tbl) 410 | } else { 411 | log.Println(err) 412 | } 413 | } 414 | go l.monitor() 415 | return l, nil 416 | } 417 | 418 | // Dial connects to the remote address raddr on the network "udp", mode is same as Listen 419 | func Dial(mode Mode, raddr string) (*UDPSession, error) { 420 | return DialEncrypted(mode, raddr, "") 421 | } 422 | 423 | // Dial connects to the remote address raddr on the network "udp" with packet encryption, mode is same as Listen 424 | func DialEncrypted(mode Mode, raddr string, key string) (*UDPSession, error) { 425 | udpaddr, err := net.ResolveUDPAddr("udp", raddr) 426 | if err != nil { 427 | return nil, err 428 | } 429 | 430 | for { 431 | port := BASE_PORT + rand.Int()%(MAX_PORT-BASE_PORT) 432 | if udpconn, err := net.ListenUDP("udp", &net.UDPAddr{Port: port}); err == nil { 433 | var xor_tbl []byte 434 | if key != "" { 435 | pass := make([]byte, aes.BlockSize) 436 | copy(pass, []byte(key)) 437 | if block, err := aes.NewCipher(pass); err == nil { 438 | xor_tbl = make([]byte, XOR_TABLE_SIZE) 439 | stream := cipher.NewOFB(block, IV) 440 | stream.XORKeyStream(xor_tbl, xor_tbl) 441 | } else { 442 | log.Println(err) 443 | } 444 | 445 | } 446 | sess := newUDPSession(rand.Uint32(), mode, nil, udpconn, udpaddr, xor_tbl) 447 | return sess, nil 448 | } 449 | } 450 | } 451 | 452 | // packet encryption 453 | func xor(xor_tbl []byte, data []byte) { 454 | sz := 0 455 | if len(xor_tbl) > len(data) { 456 | sz = len(data) 457 | } else { 458 | sz = len(xor_tbl) 459 | } 460 | 461 | for i := 0; i < sz; i++ { 462 | data[i] = data[i] ^ xor_tbl[i] 463 | } 464 | } 465 | -------------------------------------------------------------------------------- /leaf_kcp_server/leaf/kcp/kcp.go: -------------------------------------------------------------------------------- 1 | // KCP - A Fast and Reliable ARQ Protocol 2 | package kcp 3 | 4 | import "encoding/binary" 5 | 6 | const ( 7 | IKCP_RTO_NDL = 30 // no delay min rto 8 | IKCP_RTO_MIN = 100 // normal min rto 9 | IKCP_RTO_DEF = 200 10 | IKCP_RTO_MAX = 60000 11 | IKCP_CMD_PUSH = 81 // cmd: push data 12 | IKCP_CMD_ACK = 82 // cmd: ack 13 | IKCP_CMD_WASK = 83 // cmd: window probe (ask) 14 | IKCP_CMD_WINS = 84 // cmd: window size (tell) 15 | IKCP_ASK_SEND = 1 // need to send IKCP_CMD_WASK 16 | IKCP_ASK_TELL = 2 // need to send IKCP_CMD_WINS 17 | IKCP_WND_SND = 32 18 | IKCP_WND_RCV = 32 19 | IKCP_MTU_DEF = 1400 20 | IKCP_ACK_FAST = 3 21 | IKCP_INTERVAL = 100 22 | IKCP_OVERHEAD = 24 23 | IKCP_DEADLINK = 10 24 | IKCP_THRESH_INIT = 2 25 | IKCP_THRESH_MIN = 2 26 | IKCP_PROBE_INIT = 7000 // 7 secs to probe window size 27 | IKCP_PROBE_LIMIT = 120000 // up to 120 secs to probe window 28 | ) 29 | 30 | // In general, Output is a closure which captures conn and calls conn.Write 31 | type Output func(buf []byte, size int) 32 | 33 | /* encode 8 bits unsigned int */ 34 | func ikcp_encode8u(p []byte, c byte) []byte { 35 | p[0] = c 36 | return p[1:] 37 | } 38 | 39 | /* decode 8 bits unsigned int */ 40 | func ikcp_decode8u(p []byte, c *byte) []byte { 41 | *c = p[0] 42 | return p[1:] 43 | } 44 | 45 | /* encode 16 bits unsigned int (lsb) */ 46 | func ikcp_encode16u(p []byte, w uint16) []byte { 47 | binary.LittleEndian.PutUint16(p, w) 48 | return p[2:] 49 | } 50 | 51 | /* decode 16 bits unsigned int (lsb) */ 52 | func ikcp_decode16u(p []byte, w *uint16) []byte { 53 | *w = binary.LittleEndian.Uint16(p) 54 | return p[2:] 55 | } 56 | 57 | /* encode 32 bits unsigned int (lsb) */ 58 | func ikcp_encode32u(p []byte, l uint32) []byte { 59 | binary.LittleEndian.PutUint32(p, l) 60 | return p[4:] 61 | } 62 | 63 | /* decode 32 bits unsigned int (lsb) */ 64 | func ikcp_decode32u(p []byte, l *uint32) []byte { 65 | *l = binary.LittleEndian.Uint32(p) 66 | return p[4:] 67 | } 68 | 69 | func _imin_(a, b uint32) uint32 { 70 | if a <= b { 71 | return a 72 | } else { 73 | return b 74 | } 75 | } 76 | 77 | func _imax_(a, b uint32) uint32 { 78 | if a >= b { 79 | return a 80 | } else { 81 | return b 82 | } 83 | } 84 | 85 | func _ibound_(lower, middle, upper uint32) uint32 { 86 | return _imin_(_imax_(lower, middle), upper) 87 | } 88 | 89 | func _itimediff(later, earlier uint32) int32 { 90 | return (int32)(later - earlier) 91 | } 92 | 93 | // KCP Segment Definition 94 | type Segment struct { 95 | conv uint32 96 | cmd uint32 97 | frg uint32 98 | wnd uint32 99 | ts uint32 100 | sn uint32 101 | una uint32 102 | resendts uint32 103 | rto uint32 104 | fastack uint32 105 | xmit uint32 106 | data []byte 107 | } 108 | 109 | // encode a segment into buffer 110 | func (seg *Segment) encode(ptr []byte) []byte { 111 | ptr = ikcp_encode32u(ptr, seg.conv) 112 | ptr = ikcp_encode8u(ptr, uint8(seg.cmd)) 113 | ptr = ikcp_encode8u(ptr, uint8(seg.frg)) 114 | ptr = ikcp_encode16u(ptr, uint16(seg.wnd)) 115 | ptr = ikcp_encode32u(ptr, seg.ts) 116 | ptr = ikcp_encode32u(ptr, seg.sn) 117 | ptr = ikcp_encode32u(ptr, seg.una) 118 | ptr = ikcp_encode32u(ptr, uint32(len(seg.data))) 119 | return ptr 120 | } 121 | 122 | func NewSegment(size int) *Segment { 123 | seg := new(Segment) 124 | seg.data = make([]byte, size) 125 | return seg 126 | } 127 | 128 | // KCP Connection Definition 129 | type KCP struct { 130 | conv, mtu, mss, state uint32 131 | snd_una, snd_nxt, rcv_nxt uint32 132 | ts_recent, ts_lastack, ssthresh uint32 133 | rx_rttval, rx_srtt, rx_rto, rx_minrto uint32 134 | snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe uint32 135 | current, interval, ts_flush, xmit uint32 136 | nodelay, updated uint32 137 | ts_probe, probe_wait uint32 138 | dead_link, incr uint32 139 | 140 | snd_queue []Segment 141 | rcv_queue []Segment 142 | snd_buf []Segment 143 | rcv_buf []Segment 144 | 145 | acklist []uint32 146 | 147 | buffer []byte 148 | fastresend int32 149 | nocwnd int32 150 | logmask int32 151 | output Output 152 | } 153 | 154 | // create a new kcp control object, 'conv' must equal in two endpoint 155 | // from the same connection. 156 | func NewKCP(conv uint32, output Output) *KCP { 157 | kcp := new(KCP) 158 | kcp.conv = conv 159 | kcp.snd_wnd = IKCP_WND_SND 160 | kcp.rcv_wnd = IKCP_WND_RCV 161 | kcp.rmt_wnd = IKCP_WND_RCV 162 | kcp.mtu = IKCP_MTU_DEF 163 | kcp.mss = kcp.mtu - IKCP_OVERHEAD 164 | kcp.buffer = make([]byte, (kcp.mtu+IKCP_OVERHEAD)*3) 165 | kcp.rx_rto = IKCP_RTO_DEF 166 | kcp.rx_minrto = IKCP_RTO_MIN 167 | kcp.interval = IKCP_INTERVAL 168 | kcp.ts_flush = IKCP_INTERVAL 169 | kcp.ssthresh = IKCP_THRESH_INIT 170 | kcp.dead_link = IKCP_DEADLINK 171 | kcp.output = output 172 | return kcp 173 | } 174 | 175 | // check the size of next message in the recv queue 176 | func (kcp *KCP) PeekSize() (length int) { 177 | if len(kcp.rcv_queue) == 0 { 178 | return -1 179 | } 180 | 181 | seg := &kcp.rcv_queue[0] 182 | if seg.frg == 0 { 183 | return len(seg.data) 184 | } 185 | 186 | if len(kcp.rcv_queue) < int(seg.frg+1) { 187 | return -1 188 | } 189 | 190 | for k := range kcp.rcv_queue { 191 | seg := &kcp.rcv_queue[k] 192 | length += len(seg.data) 193 | if seg.frg == 0 { 194 | break 195 | } 196 | } 197 | return 198 | } 199 | 200 | // user/upper level recv: returns size, returns below zero for EAGAIN 201 | func (kcp *KCP) Recv(buffer []byte) (n int) { 202 | if len(kcp.rcv_queue) == 0 { 203 | return -1 204 | } 205 | 206 | peeksize := kcp.PeekSize() 207 | if peeksize < 0 { 208 | return -2 209 | } 210 | 211 | if peeksize > len(buffer) { 212 | return -3 213 | } 214 | 215 | var fast_recover bool 216 | if len(kcp.rcv_queue) >= int(kcp.rcv_wnd) { 217 | fast_recover = true 218 | } 219 | 220 | // merge fragment 221 | count := 0 222 | for k := range kcp.rcv_queue { 223 | seg := &kcp.rcv_queue[k] 224 | copy(buffer, seg.data) 225 | buffer = buffer[len(seg.data):] 226 | n += len(seg.data) 227 | count++ 228 | if seg.frg == 0 { 229 | break 230 | } 231 | } 232 | kcp.rcv_queue = kcp.rcv_queue[count:] 233 | 234 | // move available data from rcv_buf -> rcv_queue 235 | count = 0 236 | for k := range kcp.rcv_buf { 237 | seg := &kcp.rcv_buf[k] 238 | if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) { 239 | kcp.rcv_queue = append(kcp.rcv_queue, *seg) 240 | kcp.rcv_nxt++ 241 | count++ 242 | } else { 243 | break 244 | } 245 | } 246 | kcp.rcv_buf = kcp.rcv_buf[count:] 247 | 248 | // fast recover 249 | if len(kcp.rcv_queue) < int(kcp.rcv_wnd) && fast_recover { 250 | // ready to send back IKCP_CMD_WINS in ikcp_flush 251 | // tell remote my window size 252 | kcp.probe |= IKCP_ASK_TELL 253 | } 254 | return 255 | } 256 | 257 | // user/upper level send, returns below zero for error 258 | func (kcp *KCP) Send(buffer []byte) int { 259 | var count int 260 | if len(buffer) == 0 { 261 | return -1 262 | } 263 | 264 | if len(buffer) < int(kcp.mss) { 265 | count = 1 266 | } else { 267 | count = (len(buffer) + int(kcp.mss) - 1) / int(kcp.mss) 268 | } 269 | 270 | if count > 255 { 271 | return -2 272 | } 273 | 274 | if count == 0 { 275 | count = 1 276 | } 277 | 278 | for i := 0; i < count; i++ { 279 | var size int 280 | if len(buffer) > int(kcp.mss) { 281 | size = int(kcp.mss) 282 | } else { 283 | size = len(buffer) 284 | } 285 | seg := NewSegment(size) 286 | copy(seg.data, buffer[:size]) 287 | seg.frg = uint32(count - i - 1) 288 | kcp.snd_queue = append(kcp.snd_queue, *seg) 289 | buffer = buffer[size:] 290 | } 291 | return 0 292 | } 293 | 294 | func (kcp *KCP) update_ack(rtt int32) { 295 | var rto uint32 = 0 296 | if kcp.rx_srtt == 0 { 297 | kcp.rx_srtt = uint32(rtt) 298 | kcp.rx_rttval = uint32(rtt) / 2 299 | } else { 300 | delta := rtt - int32(kcp.rx_srtt) 301 | if delta < 0 { 302 | delta = -delta 303 | } 304 | kcp.rx_rttval = (3*kcp.rx_rttval + uint32(delta)) / 4 305 | kcp.rx_srtt = (7*kcp.rx_srtt + uint32(rtt)) / 8 306 | if kcp.rx_srtt < 1 { 307 | kcp.rx_srtt = 1 308 | } 309 | } 310 | rto = kcp.rx_srtt + _imax_(1, 4*kcp.rx_rttval) 311 | kcp.rx_rto = _ibound_(kcp.rx_minrto, rto, IKCP_RTO_MAX) 312 | } 313 | 314 | func (kcp *KCP) shrink_buf() { 315 | if len(kcp.snd_buf) > 0 { 316 | seg := &kcp.snd_buf[0] 317 | kcp.snd_una = seg.sn 318 | } else { 319 | kcp.snd_una = kcp.snd_nxt 320 | } 321 | } 322 | 323 | func (kcp *KCP) parse_ack(sn uint32) { 324 | if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 { 325 | return 326 | } 327 | 328 | for k := range kcp.snd_buf { 329 | seg := &kcp.snd_buf[k] 330 | if sn == seg.sn { 331 | kcp.snd_buf = append(kcp.snd_buf[:k], kcp.snd_buf[k+1:]...) 332 | break 333 | } else { 334 | seg.fastack++ 335 | } 336 | } 337 | } 338 | 339 | func (kcp *KCP) parse_una(una uint32) { 340 | count := 0 341 | for k := range kcp.snd_buf { 342 | seg := &kcp.snd_buf[k] 343 | if _itimediff(una, seg.sn) > 0 { 344 | count++ 345 | } else { 346 | break 347 | } 348 | } 349 | kcp.snd_buf = kcp.snd_buf[count:] 350 | } 351 | 352 | // ack append 353 | func (kcp *KCP) ack_push(sn, ts uint32) { 354 | kcp.acklist = append(kcp.acklist, sn, ts) 355 | } 356 | 357 | func (kcp *KCP) ack_get(p int) (sn, ts uint32) { 358 | return kcp.acklist[p*2+0], kcp.acklist[p*2+1] 359 | } 360 | 361 | func (kcp *KCP) parse_data(newseg *Segment) { 362 | sn := newseg.sn 363 | if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) >= 0 || 364 | _itimediff(sn, kcp.rcv_nxt) < 0 { 365 | return 366 | } 367 | 368 | n := len(kcp.rcv_buf) - 1 369 | after_idx := -1 370 | repeat := false 371 | for i := n; i >= 0; i-- { 372 | seg := &kcp.rcv_buf[i] 373 | if seg.sn == sn { 374 | repeat = true 375 | break 376 | } 377 | if _itimediff(sn, seg.sn) > 0 { 378 | after_idx = i 379 | break 380 | } 381 | } 382 | 383 | if !repeat { 384 | if after_idx == -1 { 385 | kcp.rcv_buf = append([]Segment{*newseg}, kcp.rcv_buf...) 386 | } else { 387 | kcp.rcv_buf = append(kcp.rcv_buf[:after_idx+1], append([]Segment{*newseg}, kcp.rcv_buf[after_idx+1:]...)...) 388 | } 389 | } 390 | 391 | // move available data from rcv_buf -> rcv_queue 392 | count := 0 393 | for k := range kcp.rcv_buf { 394 | seg := &kcp.rcv_buf[k] 395 | if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) { 396 | kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[k]) 397 | kcp.rcv_nxt++ 398 | count++ 399 | } else { 400 | break 401 | } 402 | } 403 | kcp.rcv_buf = kcp.rcv_buf[count:] 404 | } 405 | 406 | // when you received a low level packet (eg. UDP packet), call it 407 | func (kcp *KCP) Input(data []byte) int { 408 | una := kcp.snd_una 409 | if len(data) < IKCP_OVERHEAD { 410 | return 0 411 | } 412 | 413 | for { 414 | var ts, sn, length, una, conv uint32 415 | var wnd uint16 416 | var cmd, frg uint8 417 | 418 | if len(data) < int(IKCP_OVERHEAD) { 419 | break 420 | } 421 | 422 | data = ikcp_decode32u(data, &conv) 423 | if conv != kcp.conv { 424 | return -1 425 | } 426 | 427 | data = ikcp_decode8u(data, &cmd) 428 | data = ikcp_decode8u(data, &frg) 429 | data = ikcp_decode16u(data, &wnd) 430 | data = ikcp_decode32u(data, &ts) 431 | data = ikcp_decode32u(data, &sn) 432 | data = ikcp_decode32u(data, &una) 433 | data = ikcp_decode32u(data, &length) 434 | if len(data) < int(length) { 435 | return -2 436 | } 437 | 438 | if cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK && 439 | cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS { 440 | return -3 441 | } 442 | 443 | kcp.rmt_wnd = uint32(wnd) 444 | kcp.parse_una(una) 445 | kcp.shrink_buf() 446 | 447 | if cmd == IKCP_CMD_ACK { 448 | if _itimediff(kcp.current, ts) >= 0 { 449 | kcp.update_ack(_itimediff(kcp.current, ts)) 450 | } 451 | kcp.parse_ack(sn) 452 | kcp.shrink_buf() 453 | } else if cmd == IKCP_CMD_PUSH { 454 | if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) < 0 { 455 | kcp.ack_push(sn, ts) 456 | if _itimediff(sn, kcp.rcv_nxt) >= 0 { 457 | seg := NewSegment(int(length)) 458 | seg.conv = conv 459 | seg.cmd = uint32(cmd) 460 | seg.frg = uint32(frg) 461 | seg.wnd = uint32(wnd) 462 | seg.ts = ts 463 | seg.sn = sn 464 | seg.una = una 465 | copy(seg.data, data[:length]) 466 | kcp.parse_data(seg) 467 | } 468 | } 469 | } else if cmd == IKCP_CMD_WASK { 470 | // ready to send back IKCP_CMD_WINS in Ikcp_flush 471 | // tell remote my window size 472 | kcp.probe |= IKCP_ASK_TELL 473 | } else if cmd == IKCP_CMD_WINS { 474 | // do nothing 475 | } else { 476 | return -3 477 | } 478 | 479 | data = data[length:] 480 | } 481 | 482 | if _itimediff(kcp.snd_una, una) > 0 { 483 | if kcp.cwnd < kcp.rmt_wnd { 484 | mss := kcp.mss 485 | if kcp.cwnd < kcp.ssthresh { 486 | kcp.cwnd++ 487 | kcp.incr += mss 488 | } else { 489 | if kcp.incr < mss { 490 | kcp.incr = mss 491 | } 492 | kcp.incr += (mss*mss)/kcp.incr + (mss / 16) 493 | if (kcp.cwnd+1)*mss <= kcp.incr { 494 | kcp.cwnd++ 495 | } 496 | } 497 | if kcp.cwnd > kcp.rmt_wnd { 498 | kcp.cwnd = kcp.rmt_wnd 499 | kcp.incr = kcp.rmt_wnd * mss 500 | } 501 | } 502 | } 503 | 504 | return 0 505 | } 506 | 507 | func (kcp *KCP) wnd_unused() int32 { 508 | if len(kcp.rcv_queue) < int(kcp.rcv_wnd) { 509 | return int32(int(kcp.rcv_wnd) - len(kcp.rcv_queue)) 510 | } 511 | return 0 512 | } 513 | 514 | // flush pending data 515 | func (kcp *KCP) flush() { 516 | current := kcp.current 517 | buffer := kcp.buffer 518 | change := 0 519 | lost := false 520 | 521 | if kcp.updated == 0 { 522 | return 523 | } 524 | var seg Segment 525 | seg.conv = kcp.conv 526 | seg.cmd = IKCP_CMD_ACK 527 | seg.wnd = uint32(kcp.wnd_unused()) 528 | seg.una = kcp.rcv_nxt 529 | 530 | // flush acknowledges 531 | count := len(kcp.acklist) / 2 532 | ptr := buffer 533 | for i := 0; i < count; i++ { 534 | size := len(buffer) - len(ptr) 535 | if size+IKCP_OVERHEAD > int(kcp.mtu) { 536 | kcp.output(buffer, size) 537 | ptr = buffer 538 | } 539 | seg.sn, seg.ts = kcp.ack_get(i) 540 | ptr = seg.encode(ptr) 541 | } 542 | kcp.acklist = nil 543 | 544 | // probe window size (if remote window size equals zero) 545 | if kcp.rmt_wnd == 0 { 546 | if kcp.probe_wait == 0 { 547 | kcp.probe_wait = IKCP_PROBE_INIT 548 | kcp.ts_probe = kcp.current + kcp.probe_wait 549 | } else { 550 | if _itimediff(kcp.current, kcp.ts_probe) >= 0 { 551 | if kcp.probe_wait < IKCP_PROBE_INIT { 552 | kcp.probe_wait = IKCP_PROBE_INIT 553 | } 554 | kcp.probe_wait += kcp.probe_wait / 2 555 | if kcp.probe_wait > IKCP_PROBE_LIMIT { 556 | kcp.probe_wait = IKCP_PROBE_LIMIT 557 | } 558 | kcp.ts_probe = kcp.current + kcp.probe_wait 559 | kcp.probe |= IKCP_ASK_SEND 560 | } 561 | } 562 | } else { 563 | kcp.ts_probe = 0 564 | kcp.probe_wait = 0 565 | } 566 | 567 | // flush window probing commands 568 | if (kcp.probe & IKCP_ASK_SEND) != 0 { 569 | seg.cmd = IKCP_CMD_WASK 570 | size := len(buffer) - len(ptr) 571 | if size+IKCP_OVERHEAD > int(kcp.mtu) { 572 | kcp.output(buffer, size) 573 | ptr = buffer 574 | } 575 | ptr = seg.encode(ptr) 576 | } 577 | 578 | // flush window probing commands 579 | if (kcp.probe & IKCP_ASK_TELL) != 0 { 580 | seg.cmd = IKCP_CMD_WINS 581 | size := len(buffer) - len(ptr) 582 | if size+IKCP_OVERHEAD > int(kcp.mtu) { 583 | kcp.output(buffer, size) 584 | ptr = buffer 585 | } 586 | ptr = seg.encode(ptr) 587 | } 588 | 589 | kcp.probe = 0 590 | 591 | // calculate window size 592 | cwnd := _imin_(kcp.snd_wnd, kcp.rmt_wnd) 593 | if kcp.nocwnd == 0 { 594 | cwnd = _imin_(kcp.cwnd, cwnd) 595 | } 596 | 597 | count = 0 598 | for k := range kcp.snd_queue { 599 | if _itimediff(kcp.snd_nxt, kcp.snd_una+cwnd) >= 0 { 600 | break 601 | } 602 | newseg := kcp.snd_queue[k] 603 | newseg.conv = kcp.conv 604 | newseg.cmd = IKCP_CMD_PUSH 605 | newseg.wnd = seg.wnd 606 | newseg.ts = current 607 | newseg.sn = kcp.snd_nxt 608 | newseg.una = kcp.rcv_nxt 609 | newseg.resendts = current 610 | newseg.rto = kcp.rx_rto 611 | newseg.fastack = 0 612 | newseg.xmit = 0 613 | kcp.snd_buf = append(kcp.snd_buf, newseg) 614 | kcp.snd_nxt++ 615 | count++ 616 | } 617 | kcp.snd_queue = kcp.snd_queue[count:] 618 | 619 | // calculate resent 620 | resent := uint32(kcp.fastresend) 621 | if kcp.fastresend <= 0 { 622 | resent = 0xffffffff 623 | } 624 | rtomin := (kcp.rx_rto >> 3) 625 | if kcp.nodelay != 0 { 626 | rtomin = 0 627 | } 628 | 629 | // flush data segments 630 | for k := range kcp.snd_buf { 631 | segment := &kcp.snd_buf[k] 632 | needsend := false 633 | if segment.xmit == 0 { 634 | needsend = true 635 | segment.xmit++ 636 | segment.rto = kcp.rx_rto 637 | segment.resendts = current + segment.rto + rtomin 638 | } else if _itimediff(current, segment.resendts) >= 0 { 639 | needsend = true 640 | segment.xmit++ 641 | kcp.xmit++ 642 | if kcp.nodelay == 0 { 643 | segment.rto += kcp.rx_rto 644 | } else { 645 | segment.rto += kcp.rx_rto / 2 646 | } 647 | segment.resendts = current + segment.rto 648 | lost = true 649 | } else if segment.fastack >= resent { 650 | needsend = true 651 | segment.xmit++ 652 | segment.fastack = 0 653 | segment.resendts = current + segment.rto 654 | change++ 655 | } 656 | 657 | if needsend { 658 | segment.ts = current 659 | segment.wnd = seg.wnd 660 | segment.una = kcp.rcv_nxt 661 | 662 | size := len(buffer) - len(ptr) 663 | need := IKCP_OVERHEAD + len(segment.data) 664 | 665 | if size+need >= int(kcp.mtu) { 666 | kcp.output(buffer, size) 667 | ptr = buffer 668 | } 669 | 670 | ptr = segment.encode(ptr) 671 | copy(ptr, segment.data) 672 | ptr = ptr[len(segment.data):] 673 | 674 | if segment.xmit >= kcp.dead_link { 675 | kcp.state = 0xFFFFFFFF 676 | } 677 | } 678 | } 679 | 680 | // flash remain segments 681 | size := len(buffer) - len(ptr) 682 | if size > 0 { 683 | kcp.output(buffer, size) 684 | } 685 | 686 | // update ssthresh 687 | if change != 0 { 688 | inflight := kcp.snd_nxt - kcp.snd_una 689 | kcp.ssthresh = inflight / 2 690 | if kcp.ssthresh < IKCP_THRESH_MIN { 691 | kcp.ssthresh = IKCP_THRESH_MIN 692 | } 693 | kcp.cwnd = kcp.ssthresh + resent 694 | kcp.incr = kcp.cwnd * kcp.mss 695 | } 696 | 697 | if lost { 698 | kcp.ssthresh = cwnd / 2 699 | if kcp.ssthresh < IKCP_THRESH_MIN { 700 | kcp.ssthresh = IKCP_THRESH_MIN 701 | } 702 | kcp.cwnd = 1 703 | kcp.incr = kcp.mss 704 | } 705 | 706 | if kcp.cwnd < 1 { 707 | kcp.cwnd = 1 708 | kcp.incr = kcp.mss 709 | } 710 | } 711 | 712 | // update state (call it repeatedly, every 10ms-100ms), or you can ask 713 | // ikcp_check when to call it again (without ikcp_input/_send calling). 714 | // 'current' - current timestamp in millisec. 715 | func (kcp *KCP) Update(current uint32) { 716 | var slap int32 717 | 718 | kcp.current = current 719 | 720 | if kcp.updated == 0 { 721 | kcp.updated = 1 722 | kcp.ts_flush = kcp.current 723 | } 724 | 725 | slap = _itimediff(kcp.current, kcp.ts_flush) 726 | 727 | if slap >= 10000 || slap < -10000 { 728 | kcp.ts_flush = kcp.current 729 | slap = 0 730 | } 731 | 732 | if slap >= 0 { 733 | kcp.ts_flush += kcp.interval 734 | if _itimediff(kcp.current, kcp.ts_flush) >= 0 { 735 | kcp.ts_flush = kcp.current + kcp.interval 736 | } 737 | kcp.flush() 738 | } 739 | } 740 | 741 | // Determine when should you invoke ikcp_update: 742 | // returns when you should invoke ikcp_update in millisec, if there 743 | // is no ikcp_input/_send calling. you can call ikcp_update in that 744 | // time, instead of call update repeatly. 745 | // Important to reduce unnacessary ikcp_update invoking. use it to 746 | // schedule ikcp_update (eg. implementing an epoll-like mechanism, 747 | // or optimize ikcp_update when handling massive kcp connections) 748 | func (kcp *KCP) Check(current uint32) uint32 { 749 | ts_flush := kcp.ts_flush 750 | tm_flush := int32(0x7fffffff) 751 | tm_packet := int32(0x7fffffff) 752 | minimal := uint32(0) 753 | if kcp.updated == 0 { 754 | return current 755 | } 756 | 757 | if _itimediff(current, ts_flush) >= 10000 || 758 | _itimediff(current, ts_flush) < -10000 { 759 | ts_flush = current 760 | } 761 | 762 | if _itimediff(current, ts_flush) >= 0 { 763 | return current 764 | } 765 | 766 | tm_flush = _itimediff(ts_flush, current) 767 | 768 | for k := range kcp.snd_buf { 769 | seg := &kcp.snd_buf[k] 770 | diff := _itimediff(seg.resendts, current) 771 | if diff <= 0 { 772 | return current 773 | } 774 | if diff < tm_packet { 775 | tm_packet = diff 776 | } 777 | } 778 | 779 | minimal = uint32(tm_packet) 780 | if tm_packet >= tm_flush { 781 | minimal = uint32(tm_flush) 782 | } 783 | if minimal >= kcp.interval { 784 | minimal = kcp.interval 785 | } 786 | 787 | return current + minimal 788 | } 789 | 790 | // change MTU size, default is 1400 791 | func (kcp *KCP) SetMtu(mtu int) int { 792 | if mtu < 50 || mtu < IKCP_OVERHEAD { 793 | return -1 794 | } 795 | buffer := make([]byte, (mtu+IKCP_OVERHEAD)*3) 796 | if buffer == nil { 797 | return -2 798 | } 799 | kcp.mtu = uint32(mtu) 800 | kcp.mss = kcp.mtu - IKCP_OVERHEAD 801 | kcp.buffer = buffer 802 | return 0 803 | } 804 | 805 | func (kcp *KCP) Interval(interval int) int { 806 | if interval > 5000 { 807 | interval = 5000 808 | } else if interval < 10 { 809 | interval = 10 810 | } 811 | kcp.interval = uint32(interval) 812 | return 0 813 | } 814 | 815 | // fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) 816 | // nodelay: 0:disable(default), 1:enable 817 | // interval: internal update timer interval in millisec, default is 100ms 818 | // resend: 0:disable fast resend(default), 1:enable fast resend 819 | // nc: 0:normal congestion control(default), 1:disable congestion control 820 | func (kcp *KCP) NoDelay(nodelay, interval, resend, nc int) int { 821 | if nodelay >= 0 { 822 | kcp.nodelay = uint32(nodelay) 823 | if nodelay != 0 { 824 | kcp.rx_minrto = IKCP_RTO_NDL 825 | } else { 826 | kcp.rx_minrto = IKCP_RTO_MIN 827 | } 828 | } 829 | if interval >= 0 { 830 | if interval > 5000 { 831 | interval = 5000 832 | } else if interval < 10 { 833 | interval = 10 834 | } 835 | kcp.interval = uint32(interval) 836 | } 837 | if resend >= 0 { 838 | kcp.fastresend = int32(resend) 839 | } 840 | if nc >= 0 { 841 | kcp.nocwnd = int32(nc) 842 | } 843 | return 0 844 | } 845 | 846 | // set maximum window size: sndwnd=32, rcvwnd=32 by default 847 | func (kcp *KCP) WndSize(sndwnd, rcvwnd int) int { 848 | if sndwnd > 0 { 849 | kcp.snd_wnd = uint32(sndwnd) 850 | } 851 | if rcvwnd > 0 { 852 | kcp.rcv_wnd = uint32(rcvwnd) 853 | } 854 | return 0 855 | } 856 | 857 | // get how many packet is waiting to be sent 858 | func (kcp *KCP) WaitSnd() int { 859 | return len(kcp.snd_buf) + len(kcp.snd_queue) 860 | } 861 | --------------------------------------------------------------------------------