├── 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 |
--------------------------------------------------------------------------------