From cc68630e257f4a0eaf60012321710f4def561566 Mon Sep 17 00:00:00 2001 From: NorthLan <6995syu@163.com> Date: Tue, 19 Apr 2022 15:50:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90TCP?= =?UTF-8?q?/WS=E7=AB=AF,tcp=E5=8C=85=E5=8D=8F=E8=AE=AE,=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=8C=85=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 13 + benchmark/testdata/gen_proto.bat | 1 + benchmark/testdata/gen_proto.sh | 1 + benchmark/testdata/test.pb.go | 203 ++++ benchmark/testdata/test.proto | 13 + cluster/acceptor.go | 92 ++ cluster/agent.go | 299 ++++++ cluster/cluster.go | 172 ++++ cluster/clusterpb/cluster.pb.go | 1351 +++++++++++++++++++++++++ cluster/clusterpb/cluster_grpc.pb.go | 475 +++++++++ cluster/clusterpb/proto/cluster.proto | 95 ++ cluster/clusterpb/proto/gen_proto.bat | 1 + cluster/connpool.go | 122 +++ cluster/errors.go | 10 + cluster/handler.go | 445 ++++++++ cluster/member.go | 12 + cluster/node.go | 393 +++++++ cluster/vars.go | 9 + cluster/ws.go | 116 +++ docs/images/data-trans.png | Bin 0 -> 21913 bytes docs/images/handshake.png | Bin 0 -> 13899 bytes docs/images/heartbeat.png | Bin 0 -> 16600 bytes docs/images/message-flag.png | Bin 0 -> 8330 bytes docs/images/message-header.png | Bin 0 -> 9879 bytes docs/images/message-type.png | Bin 0 -> 22137 bytes docs/images/packet-format.png | Bin 0 -> 6065 bytes docs/images/route-compre.png | Bin 0 -> 15006 bytes docs/protocol.md | 160 +++ docs/protocol.pdf | Bin 0 -> 303684 bytes errors.go | 11 + go.mod | 16 +- go.sum | 135 +++ group.go | 209 ++++ group_test.go | 41 + interface.go | 111 ++ internal/codec/codec.go | 6 +- internal/codec/codec_test.go | 70 +- internal/env/env.go | 40 + internal/message/message.go | 222 ++++ internal/message/message_test.go | 164 +++ internal/message/util.go | 14 + internal/runtime/runtime.go | 5 + mock/net.go | 10 + options.go | 153 +++ pipeline/pipeline.go | 77 ++ scheduler/scheduler.go | 79 ++ scheduler/timer.go | 196 ++++ scheduler/timer_test.go | 84 ++ serialize/json/json.go | 25 + serialize/json/json_test.go | 62 ++ serialize/protobuf/protobuf.go | 37 + serialize/protobuf/protobuf_test.go | 56 + serialize/serializer.go | 19 + service/connection.go | 41 + service/connection_test.go | 29 + session/lifetime.go | 31 + session/router.go | 26 + session/session.go | 398 ++++++++ session/session_test.go | 175 ++++ 59 files changed, 6520 insertions(+), 5 deletions(-) create mode 100644 LICENSE create mode 100644 benchmark/testdata/gen_proto.bat create mode 100644 benchmark/testdata/gen_proto.sh create mode 100644 benchmark/testdata/test.pb.go create mode 100644 benchmark/testdata/test.proto create mode 100644 cluster/acceptor.go create mode 100644 cluster/agent.go create mode 100644 cluster/cluster.go create mode 100644 cluster/clusterpb/cluster.pb.go create mode 100644 cluster/clusterpb/cluster_grpc.pb.go create mode 100644 cluster/clusterpb/proto/cluster.proto create mode 100644 cluster/clusterpb/proto/gen_proto.bat create mode 100644 cluster/connpool.go create mode 100644 cluster/errors.go create mode 100644 cluster/handler.go create mode 100644 cluster/member.go create mode 100644 cluster/node.go create mode 100644 cluster/vars.go create mode 100644 cluster/ws.go create mode 100644 docs/images/data-trans.png create mode 100644 docs/images/handshake.png create mode 100644 docs/images/heartbeat.png create mode 100644 docs/images/message-flag.png create mode 100644 docs/images/message-header.png create mode 100644 docs/images/message-type.png create mode 100644 docs/images/packet-format.png create mode 100644 docs/images/route-compre.png create mode 100644 docs/protocol.md create mode 100644 docs/protocol.pdf create mode 100644 errors.go create mode 100644 go.sum create mode 100644 group.go create mode 100644 group_test.go create mode 100644 interface.go create mode 100644 internal/env/env.go create mode 100644 internal/message/message.go create mode 100644 internal/message/message_test.go create mode 100644 internal/message/util.go create mode 100644 internal/runtime/runtime.go create mode 100644 mock/net.go create mode 100644 options.go create mode 100644 pipeline/pipeline.go create mode 100644 scheduler/scheduler.go create mode 100644 scheduler/timer.go create mode 100644 scheduler/timer_test.go create mode 100644 serialize/json/json.go create mode 100644 serialize/json/json_test.go create mode 100644 serialize/protobuf/protobuf.go create mode 100644 serialize/protobuf/protobuf_test.go create mode 100644 serialize/serializer.go create mode 100644 service/connection.go create mode 100644 service/connection_test.go create mode 100644 session/lifetime.go create mode 100644 session/router.go create mode 100644 session/session.go create mode 100644 session/session_test.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..04855a6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright [2022-2025] [NorthLan] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/benchmark/testdata/gen_proto.bat b/benchmark/testdata/gen_proto.bat new file mode 100644 index 0000000..c026490 --- /dev/null +++ b/benchmark/testdata/gen_proto.bat @@ -0,0 +1 @@ +protoc --go_opt=paths=source_relative --go_out=. --proto_path=. *.proto \ No newline at end of file diff --git a/benchmark/testdata/gen_proto.sh b/benchmark/testdata/gen_proto.sh new file mode 100644 index 0000000..59a076a --- /dev/null +++ b/benchmark/testdata/gen_proto.sh @@ -0,0 +1 @@ +./protoc --go_out=. *.proto \ No newline at end of file diff --git a/benchmark/testdata/test.pb.go b/benchmark/testdata/test.pb.go new file mode 100644 index 0000000..30f11ad --- /dev/null +++ b/benchmark/testdata/test.pb.go @@ -0,0 +1,203 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.4 +// source: test.proto + +package testdata + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Ping struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Content string `protobuf:"bytes,1,opt,name=Content,proto3" json:"Content,omitempty"` +} + +func (x *Ping) Reset() { + *x = Ping{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ping) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ping) ProtoMessage() {} + +func (x *Ping) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ping.ProtoReflect.Descriptor instead. +func (*Ping) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{0} +} + +func (x *Ping) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +type Pong struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Content string `protobuf:"bytes,2,opt,name=Content,proto3" json:"Content,omitempty"` +} + +func (x *Pong) Reset() { + *x = Pong{} + if protoimpl.UnsafeEnabled { + mi := &file_test_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Pong) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Pong) ProtoMessage() {} + +func (x *Pong) ProtoReflect() protoreflect.Message { + mi := &file_test_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Pong.ProtoReflect.Descriptor instead. +func (*Pong) Descriptor() ([]byte, []int) { + return file_test_proto_rawDescGZIP(), []int{1} +} + +func (x *Pong) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +var File_test_proto protoreflect.FileDescriptor + +var file_test_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x74, 0x65, + 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x22, 0x20, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x18, + 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x20, 0x0a, 0x04, 0x50, 0x6f, 0x6e, 0x67, + 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x0b, 0x5a, 0x09, 0x2f, 0x74, + 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_proto_rawDescOnce sync.Once + file_test_proto_rawDescData = file_test_proto_rawDesc +) + +func file_test_proto_rawDescGZIP() []byte { + file_test_proto_rawDescOnce.Do(func() { + file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData) + }) + return file_test_proto_rawDescData +} + +var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_test_proto_goTypes = []interface{}{ + (*Ping)(nil), // 0: testdata.Ping + (*Pong)(nil), // 1: testdata.Pong +} +var file_test_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_test_proto_init() } +func file_test_proto_init() { + if File_test_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ping); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Pong); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_test_proto_goTypes, + DependencyIndexes: file_test_proto_depIdxs, + MessageInfos: file_test_proto_msgTypes, + }.Build() + File_test_proto = out.File + file_test_proto_rawDesc = nil + file_test_proto_goTypes = nil + file_test_proto_depIdxs = nil +} diff --git a/benchmark/testdata/test.proto b/benchmark/testdata/test.proto new file mode 100644 index 0000000..796b3c7 --- /dev/null +++ b/benchmark/testdata/test.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +package testdata; + +option go_package = "/testdata"; + +message Ping { + string Content = 1; +} + +message Pong { + string Content = 2; +} \ No newline at end of file diff --git a/cluster/acceptor.go b/cluster/acceptor.go new file mode 100644 index 0000000..6f7de22 --- /dev/null +++ b/cluster/acceptor.go @@ -0,0 +1,92 @@ +package cluster + +import ( + "context" + "net" + "ngs/cluster/clusterpb" + "ngs/internal/message" + "ngs/mock" + "ngs/session" +) + +type acceptor struct { + sid int64 + gateClient clusterpb.MemberClient + session *session.Session + lastMid uint64 + rpcHandler rpcHandler + gateAddr string +} + +// Push implements the session.NetworkEntity interface +func (a *acceptor) Push(route string, v interface{}) error { + // TODO: buffer + data, err := message.Serialize(v) + if err != nil { + return err + } + request := &clusterpb.PushMessage{ + SessionId: a.sid, + Route: route, + Data: data, + } + _, err = a.gateClient.HandlePush(context.Background(), request) + return err +} + +// RPC implements the session.NetworkEntity interface +func (a *acceptor) RPC(route string, v interface{}) error { + // TODO: buffer + data, err := message.Serialize(v) + if err != nil { + return err + } + msg := &message.Message{ + Type: message.Notify, + Route: route, + Data: data, + } + a.rpcHandler(a.session, msg, true) + return nil +} + +// LastMid implements the session.NetworkEntity interface +func (a *acceptor) LastMid() uint64 { + return a.lastMid +} + +// Response implements the session.NetworkEntity interface +func (a *acceptor) Response(v interface{}) error { + return a.ResponseMid(a.lastMid, v) +} + +// ResponseMid implements the session.NetworkEntity interface +func (a *acceptor) ResponseMid(mid uint64, v interface{}) error { + // TODO: buffer + data, err := message.Serialize(v) + if err != nil { + return err + } + request := &clusterpb.ResponseMessage{ + SessionId: a.sid, + Id: mid, + Data: data, + } + _, err = a.gateClient.HandleResponse(context.Background(), request) + return err +} + +// Close implements the session.NetworkEntity interface +func (a *acceptor) Close() error { + // TODO: buffer + request := &clusterpb.CloseSessionRequest{ + SessionId: a.sid, + } + _, err := a.gateClient.CloseSession(context.Background(), request) + return err +} + +// RemoteAddr implements the session.NetworkEntity interface +func (*acceptor) RemoteAddr() net.Addr { + return mock.NetAddr{} +} diff --git a/cluster/agent.go b/cluster/agent.go new file mode 100644 index 0000000..a649d74 --- /dev/null +++ b/cluster/agent.go @@ -0,0 +1,299 @@ +package cluster + +import ( + "errors" + "fmt" + "net" + "ngs/internal/codec" + "ngs/internal/env" + "ngs/internal/log" + "ngs/internal/message" + "ngs/internal/packet" + "ngs/pipeline" + "ngs/scheduler" + "ngs/session" + "reflect" + "sync/atomic" + "time" +) + +const ( + agentWriteBacklog = 16 +) + +var ( + // ErrBrokenPipe represents the low-level connection has broken. + ErrBrokenPipe = errors.New("broken low-level pipe") + // ErrBufferExceed indicates that the current session buffer is full and + // can not receive more data. + ErrBufferExceed = errors.New("session send buffer exceed") +) + +type ( + // Agent corresponding a user, used for store raw conn information + agent struct { + // regular agent member + session *session.Session // session + conn net.Conn // low-level conn fd + lastMid uint64 // last message id + state int32 // current agent state + chDie chan struct{} // wait for close + chSend chan pendingMessage // push message queue + lastAt int64 // last heartbeat unix time stamp + decoder *codec.Decoder // binary decoder + pipeline pipeline.Pipeline + + rpcHandler rpcHandler + srv reflect.Value // cached session reflect.Value + } + + pendingMessage struct { + typ message.Type // message type + route string // message route(push) + mid uint64 // response message id(response) + payload interface{} // payload + } +) + +// Create new agent instance +func newAgent(conn net.Conn, pipeline pipeline.Pipeline, rpcHandler rpcHandler) *agent { + a := &agent{ + conn: conn, + state: statusStart, + chDie: make(chan struct{}), + lastAt: time.Now().Unix(), + chSend: make(chan pendingMessage, agentWriteBacklog), + decoder: codec.NewDecoder(), + pipeline: pipeline, + rpcHandler: rpcHandler, + } + + // binding session + s := session.New(a) + a.session = s + a.srv = reflect.ValueOf(s) + + return a +} + +func (a *agent) send(m pendingMessage) (err error) { + defer func() { + if e := recover(); e != nil { + err = ErrBrokenPipe + } + }() + a.chSend <- m + return +} + +// LastMid implements the session.NetworkEntity interface +func (a *agent) LastMid() uint64 { + return a.lastMid +} + +// Push implementation for session.NetworkEntity interface +func (a *agent) Push(route string, v interface{}) error { + if a.status() == statusClosed { + return ErrBrokenPipe + } + + if len(a.chSend) >= agentWriteBacklog { + return ErrBufferExceed + } + + if env.Debug { + switch d := v.(type) { + case []byte: + log.Println(fmt.Sprintf("Type=Push, ID=%d, UID=%d, Route=%s, Data=%dbytes", + a.session.ID(), a.session.UID(), route, len(d))) + default: + log.Println(fmt.Sprintf("Type=Push, ID=%d, UID=%d, Route=%s, Data=%+v", + a.session.ID(), a.session.UID(), route, v)) + } + } + + return a.send(pendingMessage{typ: message.Push, route: route, payload: v}) +} + +// RPC implementation for session.NetworkEntity interface +func (a *agent) RPC(route string, v interface{}) error { + if a.status() == statusClosed { + return ErrBrokenPipe + } + + // TODO: buffer + data, err := message.Serialize(v) + if err != nil { + return err + } + msg := &message.Message{ + Type: message.Notify, + Route: route, + Data: data, + } + a.rpcHandler(a.session, msg, true) + return nil +} + +// Response implementation for session.NetworkEntity interface +// Response message to session +func (a *agent) Response(v interface{}) error { + return a.ResponseMid(a.lastMid, v) +} + +// ResponseMid implementation for session.NetworkEntity interface +// Response message to session +func (a *agent) ResponseMid(mid uint64, v interface{}) error { + if a.status() == statusClosed { + return ErrBrokenPipe + } + + if mid <= 0 { + return ErrSessionOnNotify + } + + if len(a.chSend) >= agentWriteBacklog { + return ErrBufferExceed + } + + if env.Debug { + switch d := v.(type) { + case []byte: + log.Println(fmt.Sprintf("Type=Response, ID=%d, UID=%d, MID=%d, Data=%dbytes", + a.session.ID(), a.session.UID(), mid, len(d))) + default: + log.Println(fmt.Sprintf("Type=Response, ID=%d, UID=%d, MID=%d, Data=%+v", + a.session.ID(), a.session.UID(), mid, v)) + } + } + + return a.send(pendingMessage{typ: message.Response, mid: mid, payload: v}) +} + +// Close implementation for session.NetworkEntity interface +// Close closes the agent, clean inner state and close low-level connection. +// Any blocked Read or Write operations will be unblocked and return errors. +func (a *agent) Close() error { + if a.status() == statusClosed { + return ErrCloseClosedSession + } + a.setStatus(statusClosed) + + if env.Debug { + log.Println(fmt.Sprintf("Session closed, ID=%d, UID=%d, IP=%s", + a.session.ID(), a.session.UID(), a.conn.RemoteAddr())) + } + + // prevent closing closed channel + select { + case <-a.chDie: + // expect + default: + close(a.chDie) + scheduler.PushTask(func() { session.Lifetime.Close(a.session) }) + } + + return a.conn.Close() +} + +// RemoteAddr implementation for session.NetworkEntity interface +// returns the remote network address. +func (a *agent) RemoteAddr() net.Addr { + return a.conn.RemoteAddr() +} + +// String, implementation for Stringer interface +func (a *agent) String() string { + return fmt.Sprintf("Remote=%s, LastTime=%d", a.conn.RemoteAddr().String(), atomic.LoadInt64(&a.lastAt)) +} + +func (a *agent) status() int32 { + return atomic.LoadInt32(&a.state) +} + +func (a *agent) setStatus(state int32) { + atomic.StoreInt32(&a.state, state) +} + +func (a *agent) write() { + ticker := time.NewTicker(env.Heartbeat) + chWrite := make(chan []byte, agentWriteBacklog) + // clean func + defer func() { + ticker.Stop() + close(a.chSend) + close(chWrite) + _ = a.Close() + if env.Debug { + log.Println(fmt.Sprintf("Session write goroutine exit, SessionID=%d, UID=%d", a.session.ID(), a.session.UID())) + } + }() + + for { + select { + case <-ticker.C: + deadline := time.Now().Add(-2 * env.Heartbeat).Unix() + if atomic.LoadInt64(&a.lastAt) < deadline { + log.Println(fmt.Sprintf("Session heartbeat timeout, LastTime=%d, Deadline=%d", atomic.LoadInt64(&a.lastAt), deadline)) + return + } + chWrite <- hbd + + case data := <-chWrite: + // close agent while low-level conn broken + if _, err := a.conn.Write(data); err != nil { + log.Println(err.Error()) + return + } + + case data := <-a.chSend: + payload, err := message.Serialize(data.payload) + if err != nil { + switch data.typ { + case message.Push: + log.Println(fmt.Sprintf("Push: %s error: %s", data.route, err.Error())) + case message.Response: + log.Println(fmt.Sprintf("Response message(id: %d) error: %s", data.mid, err.Error())) + default: + // expect + } + break + } + + // construct message and encode + m := &message.Message{ + Type: data.typ, + Data: payload, + Route: data.route, + ID: data.mid, + } + if pipe := a.pipeline; pipe != nil { + err := pipe.Outbound().Process(a.session, m) + if err != nil { + log.Println("broken pipeline", err.Error()) + break + } + } + + em, err := m.Encode() + if err != nil { + log.Println(err.Error()) + break + } + + // packet encode + p, err := codec.Encode(packet.Data, em) + if err != nil { + log.Println(err) + break + } + chWrite <- p + + case <-a.chDie: // agent closed signal + return + + case <-env.Die: // application quit + return + } + } +} diff --git a/cluster/cluster.go b/cluster/cluster.go new file mode 100644 index 0000000..243f66e --- /dev/null +++ b/cluster/cluster.go @@ -0,0 +1,172 @@ +package cluster + +import ( + "context" + "fmt" + "ngs/cluster/clusterpb" + "ngs/internal/log" + "sync" +) + +// cluster represents a ngs cluster, which contains a bunch of ngs nodes +// and each of them provide a group of different services. All services requests +// from client will send to gate firstly and be forwarded to appropriate node. +type cluster struct { + // If cluster is not large enough, use slice is OK + currentNode *Node + rpcClient *rpcClient + + mu sync.RWMutex + members []*Member +} + +func newCluster(currentNode *Node) *cluster { + return &cluster{currentNode: currentNode} +} + +// Register implements the MasterServer gRPC service +func (c *cluster) Register(_ context.Context, req *clusterpb.RegisterRequest) (*clusterpb.RegisterResponse, error) { + if req.MemberInfo == nil { + return nil, ErrInvalidRegisterReq + } + + resp := &clusterpb.RegisterResponse{} + for _, m := range c.members { + if m.memberInfo.ServiceAddr == req.MemberInfo.ServiceAddr { + return nil, fmt.Errorf("address %s has registered", req.MemberInfo.ServiceAddr) + } + } + + // Notify registered node to update remote services + newMember := &clusterpb.NewMemberRequest{MemberInfo: req.MemberInfo} + for _, m := range c.members { + resp.Members = append(resp.Members, m.memberInfo) + if m.isMaster { + continue + } + pool, err := c.rpcClient.getConnPool(m.memberInfo.ServiceAddr) + if err != nil { + return nil, err + } + client := clusterpb.NewMemberClient(pool.Get()) + _, err = client.NewMember(context.Background(), newMember) + if err != nil { + return nil, err + } + } + + log.Println("New peer register to cluster", req.MemberInfo.ServiceAddr) + + // Register services to current node + c.currentNode.handler.addRemoteService(req.MemberInfo) + c.mu.Lock() + c.members = append(c.members, &Member{isMaster: false, memberInfo: req.MemberInfo}) + c.mu.Unlock() + return resp, nil +} + +// Unregister implements the MasterServer gRPC service +func (c *cluster) Unregister(_ context.Context, req *clusterpb.UnregisterRequest) (*clusterpb.UnregisterResponse, error) { + if req.ServiceAddr == "" { + return nil, ErrInvalidRegisterReq + } + + var index = -1 + resp := &clusterpb.UnregisterResponse{} + for i, m := range c.members { + if m.memberInfo.ServiceAddr == req.ServiceAddr { + index = i + break + } + } + if index < 0 { + return nil, fmt.Errorf("address %s has notregistered", req.ServiceAddr) + } + + // Notify registered node to update remote services + delMember := &clusterpb.DelMemberRequest{ServiceAddr: req.ServiceAddr} + for _, m := range c.members { + if m.MemberInfo().ServiceAddr == c.currentNode.ServiceAddr { + continue + } + pool, err := c.rpcClient.getConnPool(m.memberInfo.ServiceAddr) + if err != nil { + return nil, err + } + client := clusterpb.NewMemberClient(pool.Get()) + _, err = client.DelMember(context.Background(), delMember) + if err != nil { + return nil, err + } + } + + log.Println("Exists peer unregister to cluster", req.ServiceAddr) + + // Register services to current node + c.currentNode.handler.delMember(req.ServiceAddr) + c.mu.Lock() + if index == len(c.members)-1 { + c.members = c.members[:index] + } else { + c.members = append(c.members[:index], c.members[index+1:]...) + } + c.mu.Unlock() + return resp, nil +} + +func (c *cluster) setRpcClient(client *rpcClient) { + c.rpcClient = client +} + +func (c *cluster) remoteAddrs() []string { + var addrs []string + c.mu.RLock() + for _, m := range c.members { + addrs = append(addrs, m.memberInfo.ServiceAddr) + } + c.mu.RUnlock() + return addrs +} + +func (c *cluster) initMembers(members []*clusterpb.MemberInfo) { + c.mu.Lock() + for _, info := range members { + c.members = append(c.members, &Member{ + memberInfo: info, + }) + } + c.mu.Unlock() +} + +func (c *cluster) addMember(info *clusterpb.MemberInfo) { + c.mu.Lock() + var found bool + for _, member := range c.members { + if member.memberInfo.ServiceAddr == info.ServiceAddr { + member.memberInfo = info + found = true + break + } + } + if !found { + c.members = append(c.members, &Member{ + memberInfo: info, + }) + } + c.mu.Unlock() +} + +func (c *cluster) delMember(addr string) { + c.mu.Lock() + var index = -1 + for i, member := range c.members { + if member.memberInfo.ServiceAddr == addr { + index = i + break + } + } + if index != -1 { + c.members = append(c.members[:index], c.members[index+1:]...) + } + c.mu.Unlock() +} diff --git a/cluster/clusterpb/cluster.pb.go b/cluster/clusterpb/cluster.pb.go new file mode 100644 index 0000000..6f79641 --- /dev/null +++ b/cluster/clusterpb/cluster.pb.go @@ -0,0 +1,1351 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.4 +// source: cluster.proto + +package clusterpb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type MemberInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Label string `protobuf:"bytes,1,opt,name=label,proto3" json:"label,omitempty"` + ServiceAddr string `protobuf:"bytes,2,opt,name=serviceAddr,proto3" json:"serviceAddr,omitempty"` + Services []string `protobuf:"bytes,3,rep,name=services,proto3" json:"services,omitempty"` +} + +func (x *MemberInfo) Reset() { + *x = MemberInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MemberInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MemberInfo) ProtoMessage() {} + +func (x *MemberInfo) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MemberInfo.ProtoReflect.Descriptor instead. +func (*MemberInfo) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{0} +} + +func (x *MemberInfo) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + +func (x *MemberInfo) GetServiceAddr() string { + if x != nil { + return x.ServiceAddr + } + return "" +} + +func (x *MemberInfo) GetServices() []string { + if x != nil { + return x.Services + } + return nil +} + +type RegisterRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MemberInfo *MemberInfo `protobuf:"bytes,1,opt,name=memberInfo,proto3" json:"memberInfo,omitempty"` +} + +func (x *RegisterRequest) Reset() { + *x = RegisterRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterRequest) ProtoMessage() {} + +func (x *RegisterRequest) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterRequest.ProtoReflect.Descriptor instead. +func (*RegisterRequest) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{1} +} + +func (x *RegisterRequest) GetMemberInfo() *MemberInfo { + if x != nil { + return x.MemberInfo + } + return nil +} + +type RegisterResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Members []*MemberInfo `protobuf:"bytes,1,rep,name=members,proto3" json:"members,omitempty"` +} + +func (x *RegisterResponse) Reset() { + *x = RegisterResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterResponse) ProtoMessage() {} + +func (x *RegisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterResponse.ProtoReflect.Descriptor instead. +func (*RegisterResponse) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{2} +} + +func (x *RegisterResponse) GetMembers() []*MemberInfo { + if x != nil { + return x.Members + } + return nil +} + +type UnregisterRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServiceAddr string `protobuf:"bytes,1,opt,name=serviceAddr,proto3" json:"serviceAddr,omitempty"` +} + +func (x *UnregisterRequest) Reset() { + *x = UnregisterRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnregisterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnregisterRequest) ProtoMessage() {} + +func (x *UnregisterRequest) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnregisterRequest.ProtoReflect.Descriptor instead. +func (*UnregisterRequest) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{3} +} + +func (x *UnregisterRequest) GetServiceAddr() string { + if x != nil { + return x.ServiceAddr + } + return "" +} + +type UnregisterResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *UnregisterResponse) Reset() { + *x = UnregisterResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnregisterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnregisterResponse) ProtoMessage() {} + +func (x *UnregisterResponse) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnregisterResponse.ProtoReflect.Descriptor instead. +func (*UnregisterResponse) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{4} +} + +type RequestMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GateAddr string `protobuf:"bytes,1,opt,name=gateAddr,proto3" json:"gateAddr,omitempty"` + SessionId int64 `protobuf:"varint,2,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + Id uint64 `protobuf:"varint,3,opt,name=id,proto3" json:"id,omitempty"` + Route string `protobuf:"bytes,4,opt,name=route,proto3" json:"route,omitempty"` + Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *RequestMessage) Reset() { + *x = RequestMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestMessage) ProtoMessage() {} + +func (x *RequestMessage) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestMessage.ProtoReflect.Descriptor instead. +func (*RequestMessage) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{5} +} + +func (x *RequestMessage) GetGateAddr() string { + if x != nil { + return x.GateAddr + } + return "" +} + +func (x *RequestMessage) GetSessionId() int64 { + if x != nil { + return x.SessionId + } + return 0 +} + +func (x *RequestMessage) GetId() uint64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *RequestMessage) GetRoute() string { + if x != nil { + return x.Route + } + return "" +} + +func (x *RequestMessage) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type NotifyMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GateAddr string `protobuf:"bytes,1,opt,name=gateAddr,proto3" json:"gateAddr,omitempty"` + SessionId int64 `protobuf:"varint,2,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + Route string `protobuf:"bytes,3,opt,name=route,proto3" json:"route,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *NotifyMessage) Reset() { + *x = NotifyMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NotifyMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NotifyMessage) ProtoMessage() {} + +func (x *NotifyMessage) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NotifyMessage.ProtoReflect.Descriptor instead. +func (*NotifyMessage) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{6} +} + +func (x *NotifyMessage) GetGateAddr() string { + if x != nil { + return x.GateAddr + } + return "" +} + +func (x *NotifyMessage) GetSessionId() int64 { + if x != nil { + return x.SessionId + } + return 0 +} + +func (x *NotifyMessage) GetRoute() string { + if x != nil { + return x.Route + } + return "" +} + +func (x *NotifyMessage) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type ResponseMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId int64 `protobuf:"varint,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + Id uint64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *ResponseMessage) Reset() { + *x = ResponseMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResponseMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResponseMessage) ProtoMessage() {} + +func (x *ResponseMessage) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResponseMessage.ProtoReflect.Descriptor instead. +func (*ResponseMessage) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{7} +} + +func (x *ResponseMessage) GetSessionId() int64 { + if x != nil { + return x.SessionId + } + return 0 +} + +func (x *ResponseMessage) GetId() uint64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *ResponseMessage) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type PushMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId int64 `protobuf:"varint,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"` + Route string `protobuf:"bytes,2,opt,name=route,proto3" json:"route,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *PushMessage) Reset() { + *x = PushMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PushMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushMessage) ProtoMessage() {} + +func (x *PushMessage) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushMessage.ProtoReflect.Descriptor instead. +func (*PushMessage) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{8} +} + +func (x *PushMessage) GetSessionId() int64 { + if x != nil { + return x.SessionId + } + return 0 +} + +func (x *PushMessage) GetRoute() string { + if x != nil { + return x.Route + } + return "" +} + +func (x *PushMessage) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type MemberHandleResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *MemberHandleResponse) Reset() { + *x = MemberHandleResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MemberHandleResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MemberHandleResponse) ProtoMessage() {} + +func (x *MemberHandleResponse) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MemberHandleResponse.ProtoReflect.Descriptor instead. +func (*MemberHandleResponse) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{9} +} + +type NewMemberRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MemberInfo *MemberInfo `protobuf:"bytes,1,opt,name=memberInfo,proto3" json:"memberInfo,omitempty"` +} + +func (x *NewMemberRequest) Reset() { + *x = NewMemberRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NewMemberRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NewMemberRequest) ProtoMessage() {} + +func (x *NewMemberRequest) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NewMemberRequest.ProtoReflect.Descriptor instead. +func (*NewMemberRequest) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{10} +} + +func (x *NewMemberRequest) GetMemberInfo() *MemberInfo { + if x != nil { + return x.MemberInfo + } + return nil +} + +type NewMemberResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *NewMemberResponse) Reset() { + *x = NewMemberResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NewMemberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NewMemberResponse) ProtoMessage() {} + +func (x *NewMemberResponse) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NewMemberResponse.ProtoReflect.Descriptor instead. +func (*NewMemberResponse) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{11} +} + +type DelMemberRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ServiceAddr string `protobuf:"bytes,1,opt,name=serviceAddr,proto3" json:"serviceAddr,omitempty"` +} + +func (x *DelMemberRequest) Reset() { + *x = DelMemberRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DelMemberRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DelMemberRequest) ProtoMessage() {} + +func (x *DelMemberRequest) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DelMemberRequest.ProtoReflect.Descriptor instead. +func (*DelMemberRequest) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{12} +} + +func (x *DelMemberRequest) GetServiceAddr() string { + if x != nil { + return x.ServiceAddr + } + return "" +} + +type DelMemberResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DelMemberResponse) Reset() { + *x = DelMemberResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DelMemberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DelMemberResponse) ProtoMessage() {} + +func (x *DelMemberResponse) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DelMemberResponse.ProtoReflect.Descriptor instead. +func (*DelMemberResponse) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{13} +} + +type SessionClosedRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId int64 `protobuf:"varint,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"` +} + +func (x *SessionClosedRequest) Reset() { + *x = SessionClosedRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SessionClosedRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionClosedRequest) ProtoMessage() {} + +func (x *SessionClosedRequest) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionClosedRequest.ProtoReflect.Descriptor instead. +func (*SessionClosedRequest) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{14} +} + +func (x *SessionClosedRequest) GetSessionId() int64 { + if x != nil { + return x.SessionId + } + return 0 +} + +type SessionClosedResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SessionClosedResponse) Reset() { + *x = SessionClosedResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SessionClosedResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionClosedResponse) ProtoMessage() {} + +func (x *SessionClosedResponse) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionClosedResponse.ProtoReflect.Descriptor instead. +func (*SessionClosedResponse) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{15} +} + +type CloseSessionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId int64 `protobuf:"varint,1,opt,name=sessionId,proto3" json:"sessionId,omitempty"` +} + +func (x *CloseSessionRequest) Reset() { + *x = CloseSessionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CloseSessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseSessionRequest) ProtoMessage() {} + +func (x *CloseSessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CloseSessionRequest.ProtoReflect.Descriptor instead. +func (*CloseSessionRequest) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{16} +} + +func (x *CloseSessionRequest) GetSessionId() int64 { + if x != nil { + return x.SessionId + } + return 0 +} + +type CloseSessionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *CloseSessionResponse) Reset() { + *x = CloseSessionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_cluster_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CloseSessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseSessionResponse) ProtoMessage() {} + +func (x *CloseSessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_cluster_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CloseSessionResponse.ProtoReflect.Descriptor instead. +func (*CloseSessionResponse) Descriptor() ([]byte, []int) { + return file_cluster_proto_rawDescGZIP(), []int{17} +} + +var File_cluster_proto protoreflect.FileDescriptor + +var file_cluster_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x22, 0x60, 0x0a, 0x0a, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x20, + 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, + 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x48, 0x0a, 0x0f, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x35, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x43, 0x0a, 0x10, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x35, 0x0a, 0x11, 0x55, + 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, + 0x64, 0x72, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x84, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x67, + 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, + 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, + 0x73, 0x0a, 0x0d, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x67, 0x61, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x09, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, + 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x22, 0x53, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x55, 0x0a, 0x0b, 0x50, 0x75, 0x73, + 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x22, 0x16, 0x0a, 0x14, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x49, 0x0a, 0x10, 0x4e, 0x65, 0x77, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x0a, + 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, + 0x6e, 0x66, 0x6f, 0x22, 0x13, 0x0a, 0x11, 0x4e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x22, 0x13, + 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x34, 0x0a, 0x14, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, + 0x6f, 0x73, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x33, 0x0a, 0x13, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x6c, 0x6f, 0x73, 0x65, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, + 0x9c, 0x01, 0x0a, 0x06, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x08, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x4b, 0x0a, 0x0a, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, + 0x1c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x55, 0x6e, 0x72, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x32, 0xfb, + 0x04, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4d, 0x0a, 0x0d, 0x48, 0x61, 0x6e, + 0x64, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1f, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, + 0x62, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0c, 0x48, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x18, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x1a, 0x1f, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x50, + 0x75, 0x73, 0x68, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, + 0x50, 0x75, 0x73, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1f, 0x2e, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, 0x61, + 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, + 0x0a, 0x0e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1a, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1f, 0x2e, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x48, 0x0a, 0x09, 0x4e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4e, 0x65, 0x77, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x09, 0x44, 0x65, 0x6c, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x70, 0x62, 0x2e, 0x44, 0x65, 0x6c, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, + 0x44, 0x65, 0x6c, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, + 0x6f, 0x73, 0x65, 0x64, 0x12, 0x1f, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, + 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, + 0x62, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0c, 0x5a, 0x0a, + 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_cluster_proto_rawDescOnce sync.Once + file_cluster_proto_rawDescData = file_cluster_proto_rawDesc +) + +func file_cluster_proto_rawDescGZIP() []byte { + file_cluster_proto_rawDescOnce.Do(func() { + file_cluster_proto_rawDescData = protoimpl.X.CompressGZIP(file_cluster_proto_rawDescData) + }) + return file_cluster_proto_rawDescData +} + +var file_cluster_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_cluster_proto_goTypes = []interface{}{ + (*MemberInfo)(nil), // 0: clusterpb.MemberInfo + (*RegisterRequest)(nil), // 1: clusterpb.RegisterRequest + (*RegisterResponse)(nil), // 2: clusterpb.RegisterResponse + (*UnregisterRequest)(nil), // 3: clusterpb.UnregisterRequest + (*UnregisterResponse)(nil), // 4: clusterpb.UnregisterResponse + (*RequestMessage)(nil), // 5: clusterpb.RequestMessage + (*NotifyMessage)(nil), // 6: clusterpb.NotifyMessage + (*ResponseMessage)(nil), // 7: clusterpb.ResponseMessage + (*PushMessage)(nil), // 8: clusterpb.PushMessage + (*MemberHandleResponse)(nil), // 9: clusterpb.MemberHandleResponse + (*NewMemberRequest)(nil), // 10: clusterpb.NewMemberRequest + (*NewMemberResponse)(nil), // 11: clusterpb.NewMemberResponse + (*DelMemberRequest)(nil), // 12: clusterpb.DelMemberRequest + (*DelMemberResponse)(nil), // 13: clusterpb.DelMemberResponse + (*SessionClosedRequest)(nil), // 14: clusterpb.SessionClosedRequest + (*SessionClosedResponse)(nil), // 15: clusterpb.SessionClosedResponse + (*CloseSessionRequest)(nil), // 16: clusterpb.CloseSessionRequest + (*CloseSessionResponse)(nil), // 17: clusterpb.CloseSessionResponse +} +var file_cluster_proto_depIdxs = []int32{ + 0, // 0: clusterpb.RegisterRequest.memberInfo:type_name -> clusterpb.MemberInfo + 0, // 1: clusterpb.RegisterResponse.members:type_name -> clusterpb.MemberInfo + 0, // 2: clusterpb.NewMemberRequest.memberInfo:type_name -> clusterpb.MemberInfo + 1, // 3: clusterpb.Master.Register:input_type -> clusterpb.RegisterRequest + 3, // 4: clusterpb.Master.Unregister:input_type -> clusterpb.UnregisterRequest + 5, // 5: clusterpb.Member.HandleRequest:input_type -> clusterpb.RequestMessage + 6, // 6: clusterpb.Member.HandleNotify:input_type -> clusterpb.NotifyMessage + 8, // 7: clusterpb.Member.HandlePush:input_type -> clusterpb.PushMessage + 7, // 8: clusterpb.Member.HandleResponse:input_type -> clusterpb.ResponseMessage + 10, // 9: clusterpb.Member.NewMember:input_type -> clusterpb.NewMemberRequest + 12, // 10: clusterpb.Member.DelMember:input_type -> clusterpb.DelMemberRequest + 14, // 11: clusterpb.Member.SessionClosed:input_type -> clusterpb.SessionClosedRequest + 16, // 12: clusterpb.Member.CloseSession:input_type -> clusterpb.CloseSessionRequest + 2, // 13: clusterpb.Master.Register:output_type -> clusterpb.RegisterResponse + 4, // 14: clusterpb.Master.Unregister:output_type -> clusterpb.UnregisterResponse + 9, // 15: clusterpb.Member.HandleRequest:output_type -> clusterpb.MemberHandleResponse + 9, // 16: clusterpb.Member.HandleNotify:output_type -> clusterpb.MemberHandleResponse + 9, // 17: clusterpb.Member.HandlePush:output_type -> clusterpb.MemberHandleResponse + 9, // 18: clusterpb.Member.HandleResponse:output_type -> clusterpb.MemberHandleResponse + 11, // 19: clusterpb.Member.NewMember:output_type -> clusterpb.NewMemberResponse + 13, // 20: clusterpb.Member.DelMember:output_type -> clusterpb.DelMemberResponse + 15, // 21: clusterpb.Member.SessionClosed:output_type -> clusterpb.SessionClosedResponse + 17, // 22: clusterpb.Member.CloseSession:output_type -> clusterpb.CloseSessionResponse + 13, // [13:23] is the sub-list for method output_type + 3, // [3:13] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_cluster_proto_init() } +func file_cluster_proto_init() { + if File_cluster_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_cluster_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MemberInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnregisterRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnregisterResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NotifyMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResponseMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PushMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MemberHandleResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NewMemberRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NewMemberResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DelMemberRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DelMemberResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SessionClosedRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SessionClosedResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CloseSessionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cluster_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CloseSessionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cluster_proto_rawDesc, + NumEnums: 0, + NumMessages: 18, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_cluster_proto_goTypes, + DependencyIndexes: file_cluster_proto_depIdxs, + MessageInfos: file_cluster_proto_msgTypes, + }.Build() + File_cluster_proto = out.File + file_cluster_proto_rawDesc = nil + file_cluster_proto_goTypes = nil + file_cluster_proto_depIdxs = nil +} diff --git a/cluster/clusterpb/cluster_grpc.pb.go b/cluster/clusterpb/cluster_grpc.pb.go new file mode 100644 index 0000000..96bd585 --- /dev/null +++ b/cluster/clusterpb/cluster_grpc.pb.go @@ -0,0 +1,475 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.19.4 +// source: cluster.proto + +package clusterpb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// MasterClient is the client API for Master service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type MasterClient interface { + Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) + Unregister(ctx context.Context, in *UnregisterRequest, opts ...grpc.CallOption) (*UnregisterResponse, error) +} + +type masterClient struct { + cc grpc.ClientConnInterface +} + +func NewMasterClient(cc grpc.ClientConnInterface) MasterClient { + return &masterClient{cc} +} + +func (c *masterClient) Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) { + out := new(RegisterResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Master/Register", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *masterClient) Unregister(ctx context.Context, in *UnregisterRequest, opts ...grpc.CallOption) (*UnregisterResponse, error) { + out := new(UnregisterResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Master/Unregister", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MasterServer is the server API for Master service. +// All implementations should embed UnimplementedMasterServer +// for forward compatibility +type MasterServer interface { + Register(context.Context, *RegisterRequest) (*RegisterResponse, error) + Unregister(context.Context, *UnregisterRequest) (*UnregisterResponse, error) +} + +// UnimplementedMasterServer should be embedded to have forward compatible implementations. +type UnimplementedMasterServer struct { +} + +func (UnimplementedMasterServer) Register(context.Context, *RegisterRequest) (*RegisterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Register not implemented") +} +func (UnimplementedMasterServer) Unregister(context.Context, *UnregisterRequest) (*UnregisterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Unregister not implemented") +} + +// UnsafeMasterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to MasterServer will +// result in compilation errors. +type UnsafeMasterServer interface { + mustEmbedUnimplementedMasterServer() +} + +func RegisterMasterServer(s grpc.ServiceRegistrar, srv MasterServer) { + s.RegisterService(&Master_ServiceDesc, srv) +} + +func _Master_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegisterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MasterServer).Register(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Master/Register", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MasterServer).Register(ctx, req.(*RegisterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Master_Unregister_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UnregisterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MasterServer).Unregister(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Master/Unregister", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MasterServer).Unregister(ctx, req.(*UnregisterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Master_ServiceDesc is the grpc.ServiceDesc for Master service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Master_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "clusterpb.Master", + HandlerType: (*MasterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Register", + Handler: _Master_Register_Handler, + }, + { + MethodName: "Unregister", + Handler: _Master_Unregister_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cluster.proto", +} + +// MemberClient is the client API for Member service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type MemberClient interface { + HandleRequest(ctx context.Context, in *RequestMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) + HandleNotify(ctx context.Context, in *NotifyMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) + HandlePush(ctx context.Context, in *PushMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) + HandleResponse(ctx context.Context, in *ResponseMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) + NewMember(ctx context.Context, in *NewMemberRequest, opts ...grpc.CallOption) (*NewMemberResponse, error) + DelMember(ctx context.Context, in *DelMemberRequest, opts ...grpc.CallOption) (*DelMemberResponse, error) + SessionClosed(ctx context.Context, in *SessionClosedRequest, opts ...grpc.CallOption) (*SessionClosedResponse, error) + CloseSession(ctx context.Context, in *CloseSessionRequest, opts ...grpc.CallOption) (*CloseSessionResponse, error) +} + +type memberClient struct { + cc grpc.ClientConnInterface +} + +func NewMemberClient(cc grpc.ClientConnInterface) MemberClient { + return &memberClient{cc} +} + +func (c *memberClient) HandleRequest(ctx context.Context, in *RequestMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) { + out := new(MemberHandleResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/HandleRequest", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memberClient) HandleNotify(ctx context.Context, in *NotifyMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) { + out := new(MemberHandleResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/HandleNotify", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memberClient) HandlePush(ctx context.Context, in *PushMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) { + out := new(MemberHandleResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/HandlePush", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memberClient) HandleResponse(ctx context.Context, in *ResponseMessage, opts ...grpc.CallOption) (*MemberHandleResponse, error) { + out := new(MemberHandleResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/HandleResponse", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memberClient) NewMember(ctx context.Context, in *NewMemberRequest, opts ...grpc.CallOption) (*NewMemberResponse, error) { + out := new(NewMemberResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/NewMember", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memberClient) DelMember(ctx context.Context, in *DelMemberRequest, opts ...grpc.CallOption) (*DelMemberResponse, error) { + out := new(DelMemberResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/DelMember", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memberClient) SessionClosed(ctx context.Context, in *SessionClosedRequest, opts ...grpc.CallOption) (*SessionClosedResponse, error) { + out := new(SessionClosedResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/SessionClosed", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memberClient) CloseSession(ctx context.Context, in *CloseSessionRequest, opts ...grpc.CallOption) (*CloseSessionResponse, error) { + out := new(CloseSessionResponse) + err := c.cc.Invoke(ctx, "/clusterpb.Member/CloseSession", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MemberServer is the server API for Member service. +// All implementations should embed UnimplementedMemberServer +// for forward compatibility +type MemberServer interface { + HandleRequest(context.Context, *RequestMessage) (*MemberHandleResponse, error) + HandleNotify(context.Context, *NotifyMessage) (*MemberHandleResponse, error) + HandlePush(context.Context, *PushMessage) (*MemberHandleResponse, error) + HandleResponse(context.Context, *ResponseMessage) (*MemberHandleResponse, error) + NewMember(context.Context, *NewMemberRequest) (*NewMemberResponse, error) + DelMember(context.Context, *DelMemberRequest) (*DelMemberResponse, error) + SessionClosed(context.Context, *SessionClosedRequest) (*SessionClosedResponse, error) + CloseSession(context.Context, *CloseSessionRequest) (*CloseSessionResponse, error) +} + +// UnimplementedMemberServer should be embedded to have forward compatible implementations. +type UnimplementedMemberServer struct { +} + +func (UnimplementedMemberServer) HandleRequest(context.Context, *RequestMessage) (*MemberHandleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HandleRequest not implemented") +} +func (UnimplementedMemberServer) HandleNotify(context.Context, *NotifyMessage) (*MemberHandleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HandleNotify not implemented") +} +func (UnimplementedMemberServer) HandlePush(context.Context, *PushMessage) (*MemberHandleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HandlePush not implemented") +} +func (UnimplementedMemberServer) HandleResponse(context.Context, *ResponseMessage) (*MemberHandleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HandleResponse not implemented") +} +func (UnimplementedMemberServer) NewMember(context.Context, *NewMemberRequest) (*NewMemberResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method NewMember not implemented") +} +func (UnimplementedMemberServer) DelMember(context.Context, *DelMemberRequest) (*DelMemberResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DelMember not implemented") +} +func (UnimplementedMemberServer) SessionClosed(context.Context, *SessionClosedRequest) (*SessionClosedResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SessionClosed not implemented") +} +func (UnimplementedMemberServer) CloseSession(context.Context, *CloseSessionRequest) (*CloseSessionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CloseSession not implemented") +} + +// UnsafeMemberServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to MemberServer will +// result in compilation errors. +type UnsafeMemberServer interface { + mustEmbedUnimplementedMemberServer() +} + +func RegisterMemberServer(s grpc.ServiceRegistrar, srv MemberServer) { + s.RegisterService(&Member_ServiceDesc, srv) +} + +func _Member_HandleRequest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).HandleRequest(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/HandleRequest", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).HandleRequest(ctx, req.(*RequestMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Member_HandleNotify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NotifyMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).HandleNotify(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/HandleNotify", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).HandleNotify(ctx, req.(*NotifyMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Member_HandlePush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PushMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).HandlePush(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/HandlePush", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).HandlePush(ctx, req.(*PushMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Member_HandleResponse_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResponseMessage) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).HandleResponse(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/HandleResponse", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).HandleResponse(ctx, req.(*ResponseMessage)) + } + return interceptor(ctx, in, info, handler) +} + +func _Member_NewMember_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NewMemberRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).NewMember(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/NewMember", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).NewMember(ctx, req.(*NewMemberRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Member_DelMember_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DelMemberRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).DelMember(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/DelMember", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).DelMember(ctx, req.(*DelMemberRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Member_SessionClosed_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SessionClosedRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).SessionClosed(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/SessionClosed", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).SessionClosed(ctx, req.(*SessionClosedRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Member_CloseSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CloseSessionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemberServer).CloseSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/clusterpb.Member/CloseSession", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemberServer).CloseSession(ctx, req.(*CloseSessionRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Member_ServiceDesc is the grpc.ServiceDesc for Member service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Member_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "clusterpb.Member", + HandlerType: (*MemberServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "HandleRequest", + Handler: _Member_HandleRequest_Handler, + }, + { + MethodName: "HandleNotify", + Handler: _Member_HandleNotify_Handler, + }, + { + MethodName: "HandlePush", + Handler: _Member_HandlePush_Handler, + }, + { + MethodName: "HandleResponse", + Handler: _Member_HandleResponse_Handler, + }, + { + MethodName: "NewMember", + Handler: _Member_NewMember_Handler, + }, + { + MethodName: "DelMember", + Handler: _Member_DelMember_Handler, + }, + { + MethodName: "SessionClosed", + Handler: _Member_SessionClosed_Handler, + }, + { + MethodName: "CloseSession", + Handler: _Member_CloseSession_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cluster.proto", +} diff --git a/cluster/clusterpb/proto/cluster.proto b/cluster/clusterpb/proto/cluster.proto new file mode 100644 index 0000000..22196c6 --- /dev/null +++ b/cluster/clusterpb/proto/cluster.proto @@ -0,0 +1,95 @@ +syntax = "proto3"; + +package clusterpb; + +option go_package = "/clusterpb"; + +message MemberInfo { + string label = 1; + string serviceAddr = 2; + repeated string services = 3; +} + +message RegisterRequest { + MemberInfo memberInfo = 1; +} + +message RegisterResponse { + repeated MemberInfo members = 1; +} + +message UnregisterRequest { + string serviceAddr = 1; +} + +message UnregisterResponse {} + +service Master { + rpc Register (RegisterRequest) returns (RegisterResponse) {} + rpc Unregister (UnregisterRequest) returns (UnregisterResponse) {} +} + +message RequestMessage { + string gateAddr = 1; + int64 sessionId = 2; + uint64 id = 3; + string route = 4; + bytes data = 5; +} + +message NotifyMessage { + string gateAddr = 1; + int64 sessionId = 2; + string route = 3; + bytes data = 4; +} + +message ResponseMessage { + int64 sessionId = 1; + uint64 id = 2; + bytes data = 3; +} + +message PushMessage { + int64 sessionId = 1; + string route = 2; + bytes data = 3; +} + +message MemberHandleResponse {} + +message NewMemberRequest { + MemberInfo memberInfo = 1; +} + +message NewMemberResponse {} + +message DelMemberRequest { + string serviceAddr = 1; +} + +message DelMemberResponse {} + +message SessionClosedRequest { + int64 sessionId = 1; +} + +message SessionClosedResponse {} + +message CloseSessionRequest { + int64 sessionId = 1; +} + +message CloseSessionResponse {} + +service Member { + rpc HandleRequest (RequestMessage) returns (MemberHandleResponse) {} + rpc HandleNotify (NotifyMessage) returns (MemberHandleResponse) {} + rpc HandlePush (PushMessage) returns (MemberHandleResponse) {} + rpc HandleResponse (ResponseMessage) returns (MemberHandleResponse) {} + + rpc NewMember (NewMemberRequest) returns (NewMemberResponse) {} + rpc DelMember (DelMemberRequest) returns (DelMemberResponse) {} + rpc SessionClosed(SessionClosedRequest) returns(SessionClosedResponse) {} + rpc CloseSession(CloseSessionRequest) returns(CloseSessionResponse) {} +} \ No newline at end of file diff --git a/cluster/clusterpb/proto/gen_proto.bat b/cluster/clusterpb/proto/gen_proto.bat new file mode 100644 index 0000000..3e119ac --- /dev/null +++ b/cluster/clusterpb/proto/gen_proto.bat @@ -0,0 +1 @@ +protoc --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative --go-grpc_opt=require_unimplemented_servers=false --go_out=.. --go-grpc_out=.. --proto_path=. *.proto \ No newline at end of file diff --git a/cluster/connpool.go b/cluster/connpool.go new file mode 100644 index 0000000..ed2ce0c --- /dev/null +++ b/cluster/connpool.go @@ -0,0 +1,122 @@ +package cluster + +import ( + "context" + "errors" + "google.golang.org/grpc" + "ngs/internal/env" + "sync" + "sync/atomic" + "time" +) + +type connPool struct { + index uint32 + v []*grpc.ClientConn +} + +type rpcClient struct { + sync.RWMutex + isClosed bool + pools map[string]*connPool +} + +func newConnArray(maxSize uint, addr string) (*connPool, error) { + a := &connPool{ + index: 0, + v: make([]*grpc.ClientConn, maxSize), + } + if err := a.init(addr); err != nil { + return nil, err + } + return a, nil +} + +func (a *connPool) init(addr string) error { + for i := range a.v { + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + conn, err := grpc.DialContext( + ctx, + addr, + env.GrpcOptions..., + ) + cancel() + if err != nil { + // Cleanup if the initialization fails. + a.Close() + return err + } + a.v[i] = conn + + } + return nil +} + +func (a *connPool) Get() *grpc.ClientConn { + next := atomic.AddUint32(&a.index, 1) % uint32(len(a.v)) + return a.v[next] +} + +func (a *connPool) Close() { + for i, c := range a.v { + if c != nil { + err := c.Close() + if err != nil { + // TODO: error handling + } + a.v[i] = nil + } + } +} + +func newRPCClient() *rpcClient { + return &rpcClient{ + pools: make(map[string]*connPool), + } +} + +func (c *rpcClient) getConnPool(addr string) (*connPool, error) { + c.RLock() + if c.isClosed { + c.RUnlock() + return nil, errors.New("rpc client is closed") + } + array, ok := c.pools[addr] + c.RUnlock() + if !ok { + var err error + array, err = c.createConnPool(addr) + if err != nil { + return nil, err + } + } + return array, nil +} + +func (c *rpcClient) createConnPool(addr string) (*connPool, error) { + c.Lock() + defer c.Unlock() + array, ok := c.pools[addr] + if !ok { + var err error + // TODO: make conn count configurable + array, err = newConnArray(10, addr) + if err != nil { + return nil, err + } + c.pools[addr] = array + } + return array, nil +} + +func (c *rpcClient) closePool() { + c.Lock() + if !c.isClosed { + c.isClosed = true + // close all connections + for _, array := range c.pools { + array.Close() + } + } + c.Unlock() +} diff --git a/cluster/errors.go b/cluster/errors.go new file mode 100644 index 0000000..f2337ad --- /dev/null +++ b/cluster/errors.go @@ -0,0 +1,10 @@ +package cluster + +import "errors" + +// Errors that could be occurred during message handling. +var ( + ErrSessionOnNotify = errors.New("current session working on notify mode") + ErrCloseClosedSession = errors.New("close closed session") + ErrInvalidRegisterReq = errors.New("invalid register request") +) diff --git a/cluster/handler.go b/cluster/handler.go new file mode 100644 index 0000000..ab21f92 --- /dev/null +++ b/cluster/handler.go @@ -0,0 +1,445 @@ +package cluster + +import ( + "context" + "encoding/json" + "fmt" + "github.com/gorilla/websocket" + "math/rand" + "net" + "ngs/cluster/clusterpb" + "ngs/component" + "ngs/internal/codec" + "ngs/internal/env" + "ngs/internal/log" + "ngs/internal/message" + "ngs/internal/packet" + "ngs/pipeline" + "ngs/scheduler" + "ngs/session" + "reflect" + "sort" + "strings" + "sync" + "time" +) + +var ( + // cached serialized data + hrd []byte // handshake response data + hbd []byte // heartbeat packet data +) + +type rpcHandler func(session *session.Session, msg *message.Message, noCopy bool) + +func cache() { + data, err := json.Marshal(map[string]interface{}{ + "code": 200, + "sys": map[string]float64{"heartbeat": env.Heartbeat.Seconds()}, + }) + if err != nil { + panic(err) + } + + hrd, err = codec.Encode(packet.Handshake, data) + if err != nil { + panic(err) + } + + hbd, err = codec.Encode(packet.Heartbeat, nil) + if err != nil { + panic(err) + } +} + +type LocalHandler struct { + localServices map[string]*component.Service // all registered service + localHandlers map[string]*component.Handler // all handler method + + mu sync.RWMutex + remoteServices map[string][]*clusterpb.MemberInfo + + pipeline pipeline.Pipeline + currentNode *Node +} + +func NewHandler(currentNode *Node, pipeline pipeline.Pipeline) *LocalHandler { + h := &LocalHandler{ + localServices: make(map[string]*component.Service), + localHandlers: make(map[string]*component.Handler), + remoteServices: map[string][]*clusterpb.MemberInfo{}, + pipeline: pipeline, + currentNode: currentNode, + } + + return h +} + +func (h *LocalHandler) register(comp component.Component, opts []component.Option) error { + s := component.NewService(comp, opts) + + if _, ok := h.localServices[s.Name]; ok { + return fmt.Errorf("handler: service already defined: %s", s.Name) + } + + if err := s.ExtractHandler(); err != nil { + return err + } + + // register all localHandlers + h.localServices[s.Name] = s + for name, handler := range s.Handlers { + n := fmt.Sprintf("%s.%s", s.Name, name) + log.Println("Register local handler", n) + h.localHandlers[n] = handler + } + return nil +} + +func (h *LocalHandler) initRemoteService(members []*clusterpb.MemberInfo) { + for _, m := range members { + h.addRemoteService(m) + } +} + +func (h *LocalHandler) addRemoteService(member *clusterpb.MemberInfo) { + h.mu.Lock() + defer h.mu.Unlock() + + for _, s := range member.Services { + log.Println("Register remote service", s) + h.remoteServices[s] = append(h.remoteServices[s], member) + } +} + +func (h *LocalHandler) delMember(addr string) { + h.mu.Lock() + defer h.mu.Unlock() + + for name, members := range h.remoteServices { + for i, maddr := range members { + if addr == maddr.ServiceAddr { + members = append(members[:i], members[i+1:]...) + } + } + if len(members) == 0 { + delete(h.remoteServices, name) + } else { + h.remoteServices[name] = members + } + } +} + +func (h *LocalHandler) LocalService() []string { + var result []string + for service := range h.localServices { + result = append(result, service) + } + sort.Strings(result) + return result +} + +func (h *LocalHandler) RemoteService() []string { + h.mu.RLock() + defer h.mu.RUnlock() + + var result []string + for service := range h.remoteServices { + result = append(result, service) + } + sort.Strings(result) + return result +} + +func (h *LocalHandler) handle(conn net.Conn) { + // create a client agent and startup write gorontine + agent := newAgent(conn, h.pipeline, h.remoteProcess) + h.currentNode.storeSession(agent.session) + + // startup write goroutine + go agent.write() + + if env.Debug { + log.Println(fmt.Sprintf("New session established: %s", agent.String())) + } + + // guarantee agent related resource be destroyed + defer func() { + request := &clusterpb.SessionClosedRequest{ + SessionId: agent.session.ID(), + } + + members := h.currentNode.cluster.remoteAddrs() + for _, remote := range members { + log.Println("Notify remote server success", remote) + pool, err := h.currentNode.rpcClient.getConnPool(remote) + if err != nil { + log.Println("Cannot retrieve connection pool for address", remote, err) + continue + } + client := clusterpb.NewMemberClient(pool.Get()) + _, err = client.SessionClosed(context.Background(), request) + if err != nil { + log.Println("Cannot closed session in remote address", remote, err) + continue + } + if env.Debug { + log.Println("Notify remote server success", remote) + } + } + + agent.Close() + if env.Debug { + log.Println(fmt.Sprintf("Session read goroutine exit, SessionID=%d, UID=%d", agent.session.ID(), agent.session.UID())) + } + }() + + // read loop + buf := make([]byte, 2048) + for { + n, err := conn.Read(buf) + if err != nil { + log.Println(fmt.Sprintf("Read message error: %s, session will be closed immediately", err.Error())) + return + } + + // TODO(warning): decoder use slice for performance, packet data should be copy before next Decode + packets, err := agent.decoder.Decode(buf[:n]) + if err != nil { + log.Println(err.Error()) + + // process packets decoded + for _, p := range packets { + if err := h.processPacket(agent, p); err != nil { + log.Println(err.Error()) + return + } + } + return + } + + // process all packets + for _, p := range packets { + if err := h.processPacket(agent, p); err != nil { + log.Println(err.Error()) + return + } + } + } +} + +func (h *LocalHandler) processPacket(agent *agent, p *packet.Packet) error { + switch p.Type { + case packet.Handshake: + if err := env.HandshakeValidator(p.Data); err != nil { + return err + } + + if _, err := agent.conn.Write(hrd); err != nil { + return err + } + + agent.setStatus(statusHandshake) + if env.Debug { + log.Println(fmt.Sprintf("Session handshake Id=%d, Remote=%s", agent.session.ID(), agent.conn.RemoteAddr())) + } + + case packet.HandshakeAck: + agent.setStatus(statusWorking) + if env.Debug { + log.Println(fmt.Sprintf("Receive handshake ACK Id=%d, Remote=%s", agent.session.ID(), agent.conn.RemoteAddr())) + } + + case packet.Data: + if agent.status() < statusWorking { + return fmt.Errorf("receive data on socket which not yet ACK, session will be closed immediately, remote=%s", + agent.conn.RemoteAddr().String()) + } + + msg, err := message.Decode(p.Data) + if err != nil { + return err + } + h.processMessage(agent, msg) + + case packet.Heartbeat: + // expected + } + + agent.lastAt = time.Now().Unix() + return nil +} + +func (h *LocalHandler) findMembers(service string) []*clusterpb.MemberInfo { + h.mu.RLock() + defer h.mu.RUnlock() + return h.remoteServices[service] +} + +func (h *LocalHandler) remoteProcess(session *session.Session, msg *message.Message, noCopy bool) { + index := strings.LastIndex(msg.Route, ".") + if index < 0 { + log.Println(fmt.Sprintf("ngs/handler: invalid route %s", msg.Route)) + return + } + + service := msg.Route[:index] + members := h.findMembers(service) + if len(members) == 0 { + log.Println(fmt.Sprintf("ngs/handler: %s not found(forgot registered?)", msg.Route)) + return + } + + // Select a remote service address + // 1. Use the service address directly if the router contains binding item + // 2. Select a remote service address randomly and bind to router + var remoteAddr string + if addr, found := session.Router().Find(service); found { + remoteAddr = addr + } else { + remoteAddr = members[rand.Intn(len(members))].ServiceAddr + session.Router().Bind(service, remoteAddr) + } + pool, err := h.currentNode.rpcClient.getConnPool(remoteAddr) + if err != nil { + log.Println(err) + return + } + var data = msg.Data + if !noCopy && len(msg.Data) > 0 { + data = make([]byte, len(msg.Data)) + copy(data, msg.Data) + } + + // Retrieve gate address and session id + gateAddr := h.currentNode.ServiceAddr + sessionId := session.ID() + switch v := session.NetworkEntity().(type) { + case *acceptor: + gateAddr = v.gateAddr + sessionId = v.sid + } + + client := clusterpb.NewMemberClient(pool.Get()) + switch msg.Type { + case message.Request: + request := &clusterpb.RequestMessage{ + GateAddr: gateAddr, + SessionId: sessionId, + Id: msg.ID, + Route: msg.Route, + Data: data, + } + _, err = client.HandleRequest(context.Background(), request) + case message.Notify: + request := &clusterpb.NotifyMessage{ + GateAddr: gateAddr, + SessionId: sessionId, + Route: msg.Route, + Data: data, + } + _, err = client.HandleNotify(context.Background(), request) + } + if err != nil { + log.Println(fmt.Sprintf("Process remote message (%d:%s) error: %+v", msg.ID, msg.Route, err)) + } +} + +func (h *LocalHandler) processMessage(agent *agent, msg *message.Message) { + var lastMid uint64 + switch msg.Type { + case message.Request: + lastMid = msg.ID + case message.Notify: + lastMid = 0 + default: + log.Println("Invalid message type: " + msg.Type.String()) + return + } + + handler, found := h.localHandlers[msg.Route] + if !found { + h.remoteProcess(agent.session, msg, false) + } else { + h.localProcess(handler, lastMid, agent.session, msg) + } +} + +func (h *LocalHandler) handleWS(conn *websocket.Conn) { + c, err := newWSConn(conn) + if err != nil { + log.Println(err) + return + } + go h.handle(c) +} + +func (h *LocalHandler) localProcess(handler *component.Handler, lastMid uint64, session *session.Session, msg *message.Message) { + if pipe := h.pipeline; pipe != nil { + err := pipe.Inbound().Process(session, msg) + if err != nil { + log.Println("Pipeline process failed: " + err.Error()) + return + } + } + + var payload = msg.Data + var data interface{} + if handler.IsRawArg { + data = payload + } else { + data = reflect.New(handler.Type.Elem()).Interface() + err := env.Serializer.Unmarshal(payload, data) + if err != nil { + log.Println(fmt.Sprintf("Deserialize to %T failed: %+v (%v)", data, err, payload)) + return + } + } + + if env.Debug { + log.Println(fmt.Sprintf("UID=%d, Message={%s}, Data=%+v", session.UID(), msg.String(), data)) + } + + args := []reflect.Value{handler.Receiver, reflect.ValueOf(session), reflect.ValueOf(data)} + task := func() { + switch v := session.NetworkEntity().(type) { + case *agent: + v.lastMid = lastMid + case *acceptor: + v.lastMid = lastMid + } + + result := handler.Method.Func.Call(args) + if len(result) > 0 { + if err := result[0].Interface(); err != nil { + log.Println(fmt.Sprintf("Service %s error: %+v", msg.Route, err)) + } + } + } + + index := strings.LastIndex(msg.Route, ".") + if index < 0 { + log.Println(fmt.Sprintf("ngs/handler: invalid route %s", msg.Route)) + return + } + + // A message can be dispatch to global thread or a user customized thread + service := msg.Route[:index] + if s, found := h.localServices[service]; found && s.SchedulerName != "" { + sched := session.Value(s.SchedulerName) + if sched == nil { + log.Println(fmt.Sprintf("nanl/handler: cannot found `schedular.LocalScheduler` by %s", s.SchedulerName)) + return + } + + local, ok := sched.(scheduler.LocalScheduler) + if !ok { + log.Println(fmt.Sprintf("nanl/handler: Type %T does not implement the `schedular.LocalScheduler` interface", + sched)) + return + } + local.Schedule(task) + } else { + scheduler.PushTask(task) + } +} diff --git a/cluster/member.go b/cluster/member.go new file mode 100644 index 0000000..22e3f38 --- /dev/null +++ b/cluster/member.go @@ -0,0 +1,12 @@ +package cluster + +import "ngs/cluster/clusterpb" + +type Member struct { + isMaster bool + memberInfo *clusterpb.MemberInfo +} + +func (m *Member) MemberInfo() *clusterpb.MemberInfo { + return m.memberInfo +} diff --git a/cluster/node.go b/cluster/node.go new file mode 100644 index 0000000..f78db6b --- /dev/null +++ b/cluster/node.go @@ -0,0 +1,393 @@ +package cluster + +import ( + "context" + "errors" + "fmt" + "github.com/gorilla/websocket" + "google.golang.org/grpc" + "net" + "net/http" + "ngs/cluster/clusterpb" + "ngs/component" + "ngs/internal/env" + "ngs/internal/log" + "ngs/internal/message" + "ngs/pipeline" + "ngs/scheduler" + "ngs/session" + "strings" + "sync" + "time" +) + +// Options contains some configurations for current node +type Options struct { + Pipeline pipeline.Pipeline + IsMaster bool + AdvertiseAddr string + RetryInterval time.Duration + ClientAddr string + Components *component.Components + Label string + IsWebsocket bool + TSLCertificate string + TSLKey string +} + +// Node represents a node in ngs cluster, which will contains a group of services. +// All services will register to cluster and messages will be forwarded to the node +// which provides respective service +type Node struct { + Options // current node options + ServiceAddr string // current server service address (RPC) + + cluster *cluster + handler *LocalHandler + server *grpc.Server + rpcClient *rpcClient + + mu sync.RWMutex + sessions map[int64]*session.Session +} + +func (n *Node) Startup() error { + if n.ServiceAddr == "" { + return errors.New("service address cannot be empty in master node") + } + n.sessions = map[int64]*session.Session{} + n.cluster = newCluster(n) + n.handler = NewHandler(n, n.Pipeline) + components := n.Components.List() + for _, c := range components { + err := n.handler.register(c.Comp, c.Opts) + if err != nil { + return err + } + } + + cache() + if err := n.initNode(); err != nil { + return err + } + + // Initialize all components + for _, c := range components { + c.Comp.Init() + } + for _, c := range components { + c.Comp.AfterInit() + } + + if n.ClientAddr != "" { + go func() { + if n.IsWebsocket { + if len(n.TSLCertificate) != 0 { + n.listenAndServeWSTLS() + } else { + n.listenAndServeWS() + } + } else { + n.listenAndServe() + } + }() + } + + return nil +} + +func (n *Node) Handler() *LocalHandler { + return n.handler +} + +func (n *Node) initNode() error { + // Current node is not master server and does not contains master + // address, so running in singleton mode + if !n.IsMaster && n.AdvertiseAddr == "" { + return nil + } + + listener, err := net.Listen("tcp", n.ServiceAddr) + if err != nil { + return err + } + + // Initialize the gRPC server and register service + n.server = grpc.NewServer() + n.rpcClient = newRPCClient() + clusterpb.RegisterMemberServer(n.server, n) + + go func() { + err := n.server.Serve(listener) + if err != nil { + log.Fatalf("Start current node failed: %v", err) + } + }() + + if n.IsMaster { + clusterpb.RegisterMasterServer(n.server, n.cluster) + member := &Member{ + isMaster: true, + memberInfo: &clusterpb.MemberInfo{ + Label: n.Label, + ServiceAddr: n.ServiceAddr, + Services: n.handler.LocalService(), + }, + } + n.cluster.members = append(n.cluster.members, member) + n.cluster.setRpcClient(n.rpcClient) + } else { + pool, err := n.rpcClient.getConnPool(n.AdvertiseAddr) + if err != nil { + return err + } + client := clusterpb.NewMasterClient(pool.Get()) + request := &clusterpb.RegisterRequest{ + MemberInfo: &clusterpb.MemberInfo{ + Label: n.Label, + ServiceAddr: n.ServiceAddr, + Services: n.handler.LocalService(), + }, + } + for { + resp, err := client.Register(context.Background(), request) + if err == nil { + n.handler.initRemoteService(resp.Members) + n.cluster.initMembers(resp.Members) + break + } + log.Println("Register current node to cluster failed", err, "and will retry in", n.RetryInterval.String()) + time.Sleep(n.RetryInterval) + } + + } + + return nil +} + +// Shutdowns all components registered by application, that +// call by reverse order against register +func (n *Node) Shutdown() { + // reverse call `BeforeShutdown` hooks + components := n.Components.List() + length := len(components) + for i := length - 1; i >= 0; i-- { + components[i].Comp.BeforeShutdown() + } + + // reverse call `Shutdown` hooks + for i := length - 1; i >= 0; i-- { + components[i].Comp.Shutdown() + } + + if !n.IsMaster && n.AdvertiseAddr != "" { + pool, err := n.rpcClient.getConnPool(n.AdvertiseAddr) + if err != nil { + log.Println("Retrieve master address error", err) + goto EXIT + } + client := clusterpb.NewMasterClient(pool.Get()) + request := &clusterpb.UnregisterRequest{ + ServiceAddr: n.ServiceAddr, + } + _, err = client.Unregister(context.Background(), request) + if err != nil { + log.Println("Unregister current node failed", err) + goto EXIT + } + } + +EXIT: + if n.server != nil { + n.server.GracefulStop() + } +} + +// Enable current server accept connection +func (n *Node) listenAndServe() { + listener, err := net.Listen("tcp", n.ClientAddr) + if err != nil { + log.Fatal(err.Error()) + } + + defer listener.Close() + for { + conn, err := listener.Accept() + if err != nil { + log.Println(err.Error()) + continue + } + + go n.handler.handle(conn) + } +} + +func (n *Node) listenAndServeWS() { + var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: env.CheckOrigin, + } + + http.HandleFunc("/"+strings.TrimPrefix(env.WSPath, "/"), func(w http.ResponseWriter, r *http.Request) { + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Println(fmt.Sprintf("Upgrade failure, URI=%s, Error=%s", r.RequestURI, err.Error())) + return + } + + n.handler.handleWS(conn) + }) + + if err := http.ListenAndServe(n.ClientAddr, nil); err != nil { + log.Fatal(err.Error()) + } +} + +func (n *Node) listenAndServeWSTLS() { + var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: env.CheckOrigin, + } + + http.HandleFunc("/"+strings.TrimPrefix(env.WSPath, "/"), func(w http.ResponseWriter, r *http.Request) { + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Println(fmt.Sprintf("Upgrade failure, URI=%s, Error=%s", r.RequestURI, err.Error())) + return + } + + n.handler.handleWS(conn) + }) + + if err := http.ListenAndServeTLS(n.ClientAddr, n.TSLCertificate, n.TSLKey, nil); err != nil { + log.Fatal(err.Error()) + } +} + +func (n *Node) storeSession(s *session.Session) { + n.mu.Lock() + n.sessions[s.ID()] = s + n.mu.Unlock() +} + +func (n *Node) findSession(sid int64) *session.Session { + n.mu.RLock() + s := n.sessions[sid] + n.mu.RUnlock() + return s +} + +func (n *Node) findOrCreateSession(sid int64, gateAddr string) (*session.Session, error) { + n.mu.RLock() + s, found := n.sessions[sid] + n.mu.RUnlock() + if !found { + conns, err := n.rpcClient.getConnPool(gateAddr) + if err != nil { + return nil, err + } + ac := &acceptor{ + sid: sid, + gateClient: clusterpb.NewMemberClient(conns.Get()), + rpcHandler: n.handler.remoteProcess, + gateAddr: gateAddr, + } + s = session.New(ac) + ac.session = s + n.mu.Lock() + n.sessions[sid] = s + n.mu.Unlock() + } + return s, nil +} + +func (n *Node) HandleRequest(_ context.Context, req *clusterpb.RequestMessage) (*clusterpb.MemberHandleResponse, error) { + handler, found := n.handler.localHandlers[req.Route] + if !found { + return nil, fmt.Errorf("service not found in current node: %v", req.Route) + } + s, err := n.findOrCreateSession(req.SessionId, req.GateAddr) + if err != nil { + return nil, err + } + msg := &message.Message{ + Type: message.Request, + ID: req.Id, + Route: req.Route, + Data: req.Data, + } + n.handler.localProcess(handler, req.Id, s, msg) + return &clusterpb.MemberHandleResponse{}, nil +} + +func (n *Node) HandleNotify(_ context.Context, req *clusterpb.NotifyMessage) (*clusterpb.MemberHandleResponse, error) { + handler, found := n.handler.localHandlers[req.Route] + if !found { + return nil, fmt.Errorf("service not found in current node: %v", req.Route) + } + s, err := n.findOrCreateSession(req.SessionId, req.GateAddr) + if err != nil { + return nil, err + } + msg := &message.Message{ + Type: message.Notify, + Route: req.Route, + Data: req.Data, + } + n.handler.localProcess(handler, 0, s, msg) + return &clusterpb.MemberHandleResponse{}, nil +} + +func (n *Node) HandlePush(_ context.Context, req *clusterpb.PushMessage) (*clusterpb.MemberHandleResponse, error) { + s := n.findSession(req.SessionId) + if s == nil { + return &clusterpb.MemberHandleResponse{}, fmt.Errorf("session not found: %v", req.SessionId) + } + return &clusterpb.MemberHandleResponse{}, s.Push(req.Route, req.Data) +} + +func (n *Node) HandleResponse(_ context.Context, req *clusterpb.ResponseMessage) (*clusterpb.MemberHandleResponse, error) { + s := n.findSession(req.SessionId) + if s == nil { + return &clusterpb.MemberHandleResponse{}, fmt.Errorf("session not found: %v", req.SessionId) + } + return &clusterpb.MemberHandleResponse{}, s.ResponseMID(req.Id, req.Data) +} + +func (n *Node) NewMember(_ context.Context, req *clusterpb.NewMemberRequest) (*clusterpb.NewMemberResponse, error) { + n.handler.addRemoteService(req.MemberInfo) + n.cluster.addMember(req.MemberInfo) + return &clusterpb.NewMemberResponse{}, nil +} + +func (n *Node) DelMember(_ context.Context, req *clusterpb.DelMemberRequest) (*clusterpb.DelMemberResponse, error) { + n.handler.delMember(req.ServiceAddr) + n.cluster.delMember(req.ServiceAddr) + return &clusterpb.DelMemberResponse{}, nil +} + +// SessionClosed implements the MemberServer interface +func (n *Node) SessionClosed(_ context.Context, req *clusterpb.SessionClosedRequest) (*clusterpb.SessionClosedResponse, error) { + n.mu.Lock() + s, found := n.sessions[req.SessionId] + delete(n.sessions, req.SessionId) + n.mu.Unlock() + if found { + scheduler.PushTask(func() { session.Lifetime.Close(s) }) + } + return &clusterpb.SessionClosedResponse{}, nil +} + +// CloseSession implements the MemberServer interface +func (n *Node) CloseSession(_ context.Context, req *clusterpb.CloseSessionRequest) (*clusterpb.CloseSessionResponse, error) { + n.mu.Lock() + s, found := n.sessions[req.SessionId] + delete(n.sessions, req.SessionId) + n.mu.Unlock() + if found { + s.Close() + } + return &clusterpb.CloseSessionResponse{}, nil +} diff --git a/cluster/vars.go b/cluster/vars.go new file mode 100644 index 0000000..84d6521 --- /dev/null +++ b/cluster/vars.go @@ -0,0 +1,9 @@ +package cluster + +const ( + _ int32 = iota + statusStart // 1 + statusHandshake + statusWorking + statusClosed +) diff --git a/cluster/ws.go b/cluster/ws.go new file mode 100644 index 0000000..afc000b --- /dev/null +++ b/cluster/ws.go @@ -0,0 +1,116 @@ +package cluster + +import ( + "github.com/gorilla/websocket" + "io" + "net" + "time" +) + +// wsConn is an adapter to t.Conn, which implements all t.Conn +// interface base on *websocket.Conn +type wsConn struct { + conn *websocket.Conn + typ int // message type + reader io.Reader +} + +// newWSConn return an initialized *wsConn +func newWSConn(conn *websocket.Conn) (*wsConn, error) { + c := &wsConn{conn: conn} + + t, r, err := conn.NextReader() + if err != nil { + return nil, err + } + + c.typ = t + c.reader = r + + return c, nil +} + +// Read reads data from the connection. +// Read can be made to time out and return an Error with Timeout() == true +// after a fixed time limit; see SetDeadline and SetReadDeadline. +func (c *wsConn) Read(b []byte) (int, error) { + n, err := c.reader.Read(b) + if err != nil && err != io.EOF { + return n, err + } else if err == io.EOF { + _, r, err := c.conn.NextReader() + if err != nil { + return 0, err + } + c.reader = r + } + + return n, nil +} + +// Write writes data to the connection. +// Write can be made to time out and return an Error with Timeout() == true +// after a fixed time limit; see SetDeadline and SetWriteDeadline. +func (c *wsConn) Write(b []byte) (int, error) { + err := c.conn.WriteMessage(websocket.BinaryMessage, b) + if err != nil { + return 0, err + } + + return len(b), nil +} + +// Close closes the connection. +// Any blocked Read or Write operations will be unblocked and return errors. +func (c *wsConn) Close() error { + return c.conn.Close() +} + +// LocalAddr returns the local network address. +func (c *wsConn) LocalAddr() net.Addr { + return c.conn.LocalAddr() +} + +// RemoteAddr returns the remote network address. +func (c *wsConn) RemoteAddr() net.Addr { + return c.conn.RemoteAddr() +} + +// SetDeadline sets the read and write deadlines associated +// with the connection. It is equivalent to calling both +// SetReadDeadline and SetWriteDeadline. +// +// A deadline is an absolute time after which I/O operations +// fail with a timeout (see type Error) instead of +// blocking. The deadline applies to all future and pending +// I/O, not just the immediately following call to Read or +// Write. After a deadline has been exceeded, the connection +// can be refreshed by setting a deadline in the future. +// +// An idle timeout can be implemented by repeatedly extending +// the deadline after successful Read or Write calls. +// +// A zero value for t means I/O operations will not time out. +func (c *wsConn) SetDeadline(t time.Time) error { + if err := c.conn.SetReadDeadline(t); err != nil { + return err + } + + return c.conn.SetWriteDeadline(t) +} + +// SetReadDeadline sets the deadline for future Read calls +// and any currently-blocked Read call. +// A zero value for t means Read will not time out. +func (c *wsConn) SetReadDeadline(t time.Time) error { + return c.conn.SetReadDeadline(t) +} + +// SetWriteDeadline sets the deadline for future Write calls +// and any currently-blocked Write call. +// Even if write times out, it may return n > 0, indicating that +// some of the data was successfully written. +// A zero value for t means Write will not time out. +func (c *wsConn) SetWriteDeadline(t time.Time) error { + return c.conn.SetWriteDeadline(t) +} diff --git a/docs/images/data-trans.png b/docs/images/data-trans.png new file mode 100644 index 0000000000000000000000000000000000000000..8a3f255668f38c267f3c556ffdee40349b6eb863 GIT binary patch literal 21913 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 literal 0 HcmV?d00001 diff --git a/docs/images/handshake.png b/docs/images/handshake.png new file mode 100644 index 0000000000000000000000000000000000000000..fdf4aa73aec27150016eac27e6cf80bd695cb335 GIT binary patch literal 13899 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 AXaE2J literal 0 HcmV?d00001 diff --git a/docs/images/heartbeat.png b/docs/images/heartbeat.png new file mode 100644 index 0000000000000000000000000000000000000000..ae4ec7e86fd3a34e403fb2b758727f27502f4439 GIT binary patch literal 16600 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 literal 0 HcmV?d00001 diff --git a/docs/images/message-header.png b/docs/images/message-header.png new file mode 100644 index 0000000000000000000000000000000000000000..aad3a55e6d9521133a11eec61507c91849563700 GIT binary patch literal 9879 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 literal 0 HcmV?d00001 diff --git a/docs/images/message-type.png b/docs/images/message-type.png new file mode 100644 index 0000000000000000000000000000000000000000..175febe0635cd97ffda2f30c28af52480fc4305a GIT binary patch literal 22137 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 Q)c#-DP|sAi0^$_)FaJTvApigX literal 0 HcmV?d00001 diff --git a/docs/images/packet-format.png b/docs/images/packet-format.png new file mode 100644 index 0000000000000000000000000000000000000000..2bde285f36e9106e2802784cce56a2df8f09a180 GIT binary patch literal 6065 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 PO?ADiM%wr*4iWzaw*Csp literal 0 HcmV?d00001 diff --git a/docs/images/route-compre.png b/docs/images/route-compre.png new file mode 100644 index 0000000000000000000000000000000000000000..c2ccc05f7af029abdb075ed47ab63d801df706a2 GIT binary patch literal 15006 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 z
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
Wafrej?P&BBfjuYsbxE-x{V)^$ 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 literal 0 HcmV?d00001 diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..666b3d8 --- /dev/null +++ b/errors.go @@ -0,0 +1,11 @@ +package ngs + +import "errors" + +// Errors that could be occurred during message handling. +var ( + ErrCloseClosedGroup = errors.New("close closed group") + ErrClosedGroup = errors.New("group closed") + ErrMemberNotFound = errors.New("member not found in the group") + ErrSessionDuplication = errors.New("session has existed in the current group") +) diff --git a/go.mod b/go.mod index 031f9c9..5181d7f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,17 @@ -module ng +module ngs go 1.18 + +require ( + github.com/gorilla/websocket v1.5.0 + google.golang.org/grpc v1.45.0 + google.golang.org/protobuf v1.28.0 +) + +require ( + github.com/golang/protobuf v1.5.2 // indirect + golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/text v0.3.7 // indirect + google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ceeb0c1 --- /dev/null +++ b/go.sum @@ -0,0 +1,135 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2 h1:6mzvA99KwZxbOrxww4EvWVQUnN1+xEu9tafK5ZxkYeA= +golang.org/x/net v0.0.0-20220418201149-a630d4f3e7a2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4 h1:myaecH64R0bIEDjNORIel4iXubqzaHU1K2z8ajBwWcM= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/group.go b/group.go new file mode 100644 index 0000000..a77abe1 --- /dev/null +++ b/group.go @@ -0,0 +1,209 @@ +package ngs + +import ( + "fmt" + "ngs/internal/env" + "ngs/internal/log" + "ngs/internal/message" + "ngs/session" + "sync" + "sync/atomic" +) + +const ( + groupStatusWorking = 0 + groupStatusClosed = 1 +) + +// SessionFilter represents a filter which was used to filter session when Multicast, +// the session will receive the message while filter returns true. +type SessionFilter func(*session.Session) bool + +// Group represents a session group which used to manage a number of +// sessions, data send to the group will send to all session in it. +type Group struct { + mu sync.RWMutex + status int32 // channel current status + name string // channel name + sessions map[int64]*session.Session // session id map to session instance +} + +// NewGroup returns a new group instance +func NewGroup(n string) *Group { + return &Group{ + status: groupStatusWorking, + name: n, + sessions: make(map[int64]*session.Session), + } +} + +// Member returns specified UID's session +func (c *Group) Member(uid int64) (*session.Session, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + for _, s := range c.sessions { + if s.UID() == uid { + return s, nil + } + } + + return nil, ErrMemberNotFound +} + +// Members returns all member's UID in current group +func (c *Group) Members() []int64 { + c.mu.RLock() + defer c.mu.RUnlock() + + var members []int64 + for _, s := range c.sessions { + members = append(members, s.UID()) + } + + return members +} + +// Multicast push the message to the filtered clients +func (c *Group) Multicast(route string, v interface{}, filter SessionFilter) error { + if c.isClosed() { + return ErrClosedGroup + } + + data, err := message.Serialize(v) + if err != nil { + return err + } + + if env.Debug { + log.Println(fmt.Sprintf("Multicast %s, Data=%+v", route, v)) + } + + c.mu.RLock() + defer c.mu.RUnlock() + + for _, s := range c.sessions { + if !filter(s) { + continue + } + if err = s.Push(route, data); err != nil { + log.Println(err.Error()) + } + } + + return nil +} + +// Broadcast push the message(s) to all members +func (c *Group) Broadcast(route string, v interface{}) error { + if c.isClosed() { + return ErrClosedGroup + } + + data, err := message.Serialize(v) + if err != nil { + return err + } + + if env.Debug { + log.Println(fmt.Sprintf("Broadcast %s, Data=%+v", route, v)) + } + + c.mu.RLock() + defer c.mu.RUnlock() + + for _, s := range c.sessions { + if err = s.Push(route, data); err != nil { + log.Println(fmt.Sprintf("Session push message error, ID=%d, UID=%d, Error=%s", s.ID(), s.UID(), err.Error())) + } + } + + return err +} + +// Contains check whether a UID is contained in current group or not +func (c *Group) Contains(uid int64) bool { + _, err := c.Member(uid) + return err == nil +} + +// Add add session to group +func (c *Group) Add(session *session.Session) error { + if c.isClosed() { + return ErrClosedGroup + } + + if env.Debug { + log.Println(fmt.Sprintf("Add session to group %s, ID=%d, UID=%d", c.name, session.ID(), session.UID())) + } + + c.mu.Lock() + defer c.mu.Unlock() + + id := session.ID() + _, ok := c.sessions[session.ID()] + if ok { + return ErrSessionDuplication + } + + c.sessions[id] = session + return nil +} + +// Leave remove specified UID related session from group +func (c *Group) Leave(s *session.Session) error { + if c.isClosed() { + return ErrClosedGroup + } + + if env.Debug { + log.Println(fmt.Sprintf("Remove session from group %s, UID=%d", c.name, s.UID())) + } + + c.mu.Lock() + defer c.mu.Unlock() + + delete(c.sessions, s.ID()) + return nil +} + +// LeaveAll clear all sessions in the group +func (c *Group) LeaveAll() error { + if c.isClosed() { + return ErrClosedGroup + } + + c.mu.Lock() + defer c.mu.Unlock() + + c.sessions = make(map[int64]*session.Session) + return nil +} + +// Count get current member amount in the group +func (c *Group) Count() int { + c.mu.RLock() + defer c.mu.RUnlock() + + return len(c.sessions) +} + +func (c *Group) isClosed() bool { + if atomic.LoadInt32(&c.status) == groupStatusClosed { + return true + } + return false +} + +// Close destroy group, which will release all resource in the group +func (c *Group) Close() error { + if c.isClosed() { + return ErrCloseClosedGroup + } + + atomic.StoreInt32(&c.status, groupStatusClosed) + + // release all reference + c.sessions = make(map[int64]*session.Session) + return nil +} diff --git a/group_test.go b/group_test.go new file mode 100644 index 0000000..e084607 --- /dev/null +++ b/group_test.go @@ -0,0 +1,41 @@ +package ngs + +import ( + "math/rand" + "ngs/session" + "testing" +) + +func TestChannel_Add(t *testing.T) { + c := NewGroup("test_add") + + var paraCount = 100 + w := make(chan bool, paraCount) + for i := 0; i < paraCount; i++ { + go func(id int) { + s := session.New(nil) + s.Bind(int64(id + 1)) + c.Add(s) + w <- true + }(i) + } + + for i := 0; i < paraCount; i++ { + <-w + } + + if c.Count() != paraCount { + t.Fatalf("count expect: %d, got: %d", paraCount, c.Count()) + } + + n := rand.Int63n(int64(paraCount)) + 1 + if !c.Contains(n) { + t.Fail() + } + + // leave + c.LeaveAll() + if c.Count() != 0 { + t.Fail() + } +} diff --git a/interface.go b/interface.go new file mode 100644 index 0000000..ba79da4 --- /dev/null +++ b/interface.go @@ -0,0 +1,111 @@ +package ngs + +import ( + "fmt" + "ngs/cluster" + "ngs/component" + "ngs/internal/env" + "ngs/internal/log" + "ngs/internal/runtime" + "ngs/scheduler" + "os" + "os/signal" + "path/filepath" + "strings" + "sync/atomic" + "syscall" + "time" +) + +var running int32 + +// VERSION returns current ngs version +var VERSION = "0.1.0" + +var ( + // app represents the current server process + app = &struct { + name string // current application name + startAt time.Time // startup time + }{} +) + +// Listen listens on the TCP network address addr +// and then calls Serve with handler to handle requests +// on incoming connections. +func Listen(addr string, opts ...Option) { + if atomic.AddInt32(&running, 1) != 1 { + log.Println("Ngs has running") + return + } + + // application initialize + app.name = strings.TrimLeft(filepath.Base(os.Args[0]), "/") + app.startAt = time.Now() + + // environment initialize + if wd, err := os.Getwd(); err != nil { + panic(err) + } else { + env.Wd, _ = filepath.Abs(wd) + } + + opt := cluster.Options{ + Components: &component.Components{}, + } + for _, option := range opts { + option(&opt) + } + + // Use listen address as client address in non-cluster mode + if !opt.IsMaster && opt.AdvertiseAddr == "" && opt.ClientAddr == "" { + log.Println("The current server running in singleton mode") + opt.ClientAddr = addr + } + + // Set the retry interval to 3 secondes if doesn't set by user + if opt.RetryInterval == 0 { + opt.RetryInterval = time.Second * 3 + } + + node := &cluster.Node{ + Options: opt, + ServiceAddr: addr, + } + err := node.Startup() + if err != nil { + log.Fatalf("Node startup failed: %v", err) + } + runtime.CurrentNode = node + + if node.ClientAddr != "" { + log.Println(fmt.Sprintf("Startup *Ngs gate server* %s, client address: %v, service address: %s", + app.name, node.ClientAddr, node.ServiceAddr)) + } else { + log.Println(fmt.Sprintf("Startup *Ngs backend server* %s, service address %s", + app.name, node.ServiceAddr)) + } + + go scheduler.Schedule() + sg := make(chan os.Signal) + signal.Notify(sg, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM) + + select { + case <-env.Die: + log.Println("The app will shutdown in a few seconds") + case s := <-sg: + log.Println("Ngs server got signal", s) + } + + log.Println("Ngs server is stopping...") + + node.Shutdown() + runtime.CurrentNode = nil + scheduler.Close() + atomic.StoreInt32(&running, 0) +} + +// Shutdown send a signal to let 'ngs' shutdown itself. +func Shutdown() { + close(env.Die) +} diff --git a/internal/codec/codec.go b/internal/codec/codec.go index 8325aa8..41bff8b 100644 --- a/internal/codec/codec.go +++ b/internal/codec/codec.go @@ -3,7 +3,7 @@ package codec import ( "bytes" "errors" - "ng/internal/packet" + "ngs/internal/packet" ) // Codec constants. @@ -84,7 +84,7 @@ func (c *Decoder) Decode(data []byte) ([]*packet.Packet, error) { return packets, nil } -// Encode create a packet.Packet from the raw bytes slice and then encode to network bytes slice +// Encode 从原始raw bytes创建一个用于网络传输的 packet.Packet 结构,参考网易 pomelo 协议 // Protocol refs: https://github.com/NetEase/pomelo/wiki/Communication-Protocol // // --|----------------|-- @@ -97,7 +97,7 @@ func Encode(typ packet.Type, data []byte) ([]byte, error) { p := &packet.Packet{Type: typ, Length: len(data)} buf := make([]byte, p.Length+HeadLength) - buf[0] = byte(p.Type) + buf[0] = byte(p.Type) // 编译器提示,此处 byte 转换不能删 copy(buf[1:HeadLength], intToBytes(p.Length)) copy(buf[HeadLength:], data) diff --git a/internal/codec/codec_test.go b/internal/codec/codec_test.go index 31a99a9..0dd8dd0 100644 --- a/internal/codec/codec_test.go +++ b/internal/codec/codec_test.go @@ -1,10 +1,78 @@ package codec import ( - . "ng/internal/packet" + . "ngs/internal/packet" + "reflect" "testing" ) +func TestPack(t *testing.T) { + data := []byte("hello world") + p1 := &Packet{Type: Handshake, Data: data, Length: len(data)} + pp1, err := Encode(Handshake, data) + if err != nil { + t.Error(err.Error()) + } + + d1 := NewDecoder() + packets, err := d1.Decode(pp1) + if err != nil { + t.Fatal(err.Error()) + } + if len(packets) < 1 { + t.Fatal("packets should not empty") + } + if !reflect.DeepEqual(p1, packets[0]) { + t.Fatalf("expect: %v, got: %v", p1, packets[0]) + } + + p2 := &Packet{Type: Type(5), Data: data, Length: len(data)} + pp2, err := Encode(Kick, data) + if err != nil { + t.Error(err.Error()) + } + + d2 := NewDecoder() + upp2, err := d2.Decode(pp2) + if err != nil { + t.Fatal(err.Error()) + } + if len(upp2) < 1 { + t.Fatal("packets should not empty") + } + if !reflect.DeepEqual(p2, upp2[0]) { + t.Fatalf("expect: %v, got: %v", p2, upp2[0]) + } + + _ = &Packet{Type: Type(0), Data: data, Length: len(data)} + if _, err := Encode(Type(0), data); err == nil { + t.Error("should err") + } + + _ = &Packet{Type: Type(6), Data: data, Length: len(data)} + if _, err = Encode(Type(6), data); err == nil { + t.Error("should err") + } + + p5 := &Packet{Type: Type(5), Data: data, Length: len(data)} + pp5, err := Encode(Kick, data) + if err != nil { + t.Fatal(err.Error()) + } + d3 := NewDecoder() + upp5, err := d3.Decode(append(pp5, []byte{0x01, 0x00, 0x00, 0x00}...)) + if err != nil { + t.Fatal(err.Error()) + } + if len(upp5) < 1 { + t.Fatal("packets should not empty") + } + + if !reflect.DeepEqual(p5, upp5[0]) { + t.Fatalf("expect: %v, got: %v", p2, upp5[0]) + } +} + func BenchmarkDecoder_Decode(b *testing.B) { data := []byte("hello world") pp1, err := Encode(Handshake, data) diff --git a/internal/env/env.go b/internal/env/env.go new file mode 100644 index 0000000..2cb2b3a --- /dev/null +++ b/internal/env/env.go @@ -0,0 +1,40 @@ +package env + +import ( + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "net/http" + "ngs/serialize" + "ngs/serialize/protobuf" + "time" +) + +var ( + Wd string // working path + Die chan bool // wait for end application + Heartbeat time.Duration // Heartbeat internal + CheckOrigin func(*http.Request) bool // check origin when websocket enabled + Debug bool // enable Debug + WSPath string // WebSocket path(eg: ws://127.0.0.1/WSPath) + HandshakeValidator func([]byte) error // When you need to verify the custom data of the handshake request + + // TimerPrecision indicates the precision of timer, default is time.Second + TimerPrecision = time.Second + + // GlobalTicker represents global ticker that all cron job will be executed + // in globalTicker. + GlobalTicker *time.Ticker + + Serializer serialize.Serializer + + GrpcOptions = []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())} +) + +func init() { + Die = make(chan bool) + Heartbeat = 30 * time.Second + Debug = false + CheckOrigin = func(_ *http.Request) bool { return true } + HandshakeValidator = func(_ []byte) error { return nil } + Serializer = protobuf.NewSerializer() +} diff --git a/internal/message/message.go b/internal/message/message.go new file mode 100644 index 0000000..8c0c251 --- /dev/null +++ b/internal/message/message.go @@ -0,0 +1,222 @@ +package message + +import ( + "encoding/binary" + "errors" + "fmt" + "ngs/internal/log" + "strings" +) + +// Type represents the type of message, which could be Request/Notify/Response/Push +type Type byte + +// Message types +const ( + Request Type = 0x00 + Notify = 0x01 + Response = 0x02 + Push = 0x03 +) + +const ( + msgRouteCompressMask = 0x01 // 0000 0001 last bit + msgTypeMask = 0x07 // 0000 0111 1-3 bit (需要>>) + msgRouteLengthMask = 0xFF // 1111 1111 last 8 bit + msgHeadLength = 0x02 // 0000 0010 2 bit +) + +var types = map[Type]string{ + Request: "Request", + Notify: "Notify", + Response: "Response", + Push: "Push", +} + +func (t Type) String() string { + return types[t] +} + +var ( + routes = make(map[string]uint16) // route map to code + codes = make(map[uint16]string) // code map to route +) + +// Errors that could be occurred in message codec +var ( + ErrWrongMessageType = errors.New("wrong message type") + ErrInvalidMessage = errors.New("invalid message") + ErrRouteInfoNotFound = errors.New("route info not found in dictionary") + ErrWrongMessage = errors.New("wrong message") +) + +// Message represents an unmarshaler message or a message which to be marshaled +type Message struct { + Type Type // message type (flag) + ID uint64 // unique id, zero while notify mode + Route string // route for locating service + Data []byte // payload + compressed bool // if message compressed +} + +// New returns a new message instance +func New() *Message { + return &Message{} +} + +// String, implementation of fmt.Stringer interface +func (m *Message) String() string { + return fmt.Sprintf("%s %s (%dbytes)", types[m.Type], m.Route, len(m.Data)) +} + +// Encode marshals message to binary format. +func (m *Message) Encode() ([]byte, error) { + return Encode(m) +} + +func routable(t Type) bool { + return t == Request || t == Notify || t == Push +} + +func invalidType(t Type) bool { + return t < Request || t > Push +} + +// Encode marshals message to binary format. Different message types is corresponding to +// different message header, message types is identified by 2-4 bit of flag field. The +// relationship between message types and message header is presented as follows: +// ------------------------------------------ +// | type | flag | other | +// |----------|--------|--------------------| +// | request |----000-||| +// | notify |----001-| | +// | response |----010-| | +// | push |----011-| | +// ------------------------------------------ +// The figure above indicates that the bit does not affect the type of message. +func Encode(m *Message) ([]byte, error) { + if invalidType(m.Type) { + return nil, ErrWrongMessageType + } + + buf := make([]byte, 0) + flag := byte(m.Type << 1) // 编译器提示,此处 byte 转换不能删 + + code, compressed := routes[m.Route] + if compressed { + flag |= msgRouteCompressMask + } + buf = append(buf, flag) + + if m.Type == Request || m.Type == Response { + n := m.ID + // variant length encode + for { + b := byte(n % 128) + n >>= 7 + if n != 0 { + buf = append(buf, b+128) + } else { + buf = append(buf, b) + break + } + } + } + + if routable(m.Type) { + if compressed { + buf = append(buf, byte((code>>8)&0xFF)) + buf = append(buf, byte(code&0xFF)) + } else { + buf = append(buf, byte(len(m.Route))) + buf = append(buf, []byte(m.Route)...) + } + } + + buf = append(buf, m.Data...) + return buf, nil +} + +// Decode unmarshal the bytes slice to a message +func Decode(data []byte) (*Message, error) { + if len(data) < msgHeadLength { + return nil, ErrInvalidMessage + } + m := New() + flag := data[0] + offset := 1 + m.Type = Type((flag >> 1) & msgTypeMask) // 编译器提示,此处Type转换不能删 + + if invalidType(m.Type) { + return nil, ErrWrongMessageType + } + + if m.Type == Request || m.Type == Response { + id := uint64(0) + // little end byte order + // WARNING: must can be stored in 64 bits integer + // variant length encode + for i := offset; i < len(data); i++ { + b := data[i] + id += uint64(b&0x7F) << uint64(7*(i-offset)) + if b < 128 { + offset = i + 1 + break + } + } + m.ID = id + } + + if offset >= len(data) { + return nil, ErrWrongMessage + } + + if routable(m.Type) { + if flag&msgRouteCompressMask == 1 { + m.compressed = true + code := binary.BigEndian.Uint16(data[offset:(offset + 2)]) + route, ok := codes[code] + if !ok { + return nil, ErrRouteInfoNotFound + } + m.Route = route + offset += 2 + } else { + m.compressed = false + rl := data[offset] + offset++ + if offset+int(rl) > len(data) { + return nil, ErrWrongMessage + } + m.Route = string(data[offset:(offset + int(rl))]) + offset += int(rl) + } + } + + if offset > len(data) { + return nil, ErrWrongMessage + } + m.Data = data[offset:] + return m, nil +} + +// SetDictionary set routes map which be used to compress route. +// TODO(warning): set dictionary in runtime would be a dangerous operation!!!!!! +func SetDictionary(dict map[string]uint16) { + for route, code := range dict { + r := strings.TrimSpace(route) + + // duplication check + if _, ok := routes[r]; ok { + log.Println(fmt.Sprintf("duplicated route(route: %s, code: %d)", r, code)) + } + + if _, ok := codes[code]; ok { + log.Println(fmt.Sprintf("duplicated route(route: %s, code: %d)", r, code)) + } + + // update map, using last value when key duplicated + routes[r] = code + codes[code] = r + } +} diff --git a/internal/message/message_test.go b/internal/message/message_test.go new file mode 100644 index 0000000..d9696b5 --- /dev/null +++ b/internal/message/message_test.go @@ -0,0 +1,164 @@ +package message + +import ( + "reflect" + "testing" +) + +func TestEncode(t *testing.T) { + dict := map[string]uint16{ + "test.test.test": 100, + "test.test.test1": 101, + "test.test.test2": 102, + "test.test.test3": 103, + } + SetDictionary(dict) + m1 := &Message{ + Type: Request, + ID: 100, + Route: "test.test.test", + Data: []byte(`hello world`), + compressed: true, + } + em1, err := m1.Encode() + if err != nil { + t.Error(err.Error()) + } + dm1, err := Decode(em1) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m1, dm1) { + t.Error("not equal") + } + + m2 := &Message{ + Type: Request, + ID: 100, + Route: "test.test.test4", + Data: []byte(`hello world`), + } + em2, err := m2.Encode() + if err != nil { + t.Error(err.Error()) + } + dm2, err := Decode(em2) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m2, dm2) { + t.Error("not equal") + } + + m3 := &Message{ + Type: Response, + ID: 100, + Data: []byte(`hello world`), + } + em3, err := m3.Encode() + if err != nil { + t.Error(err.Error()) + } + dm3, err := Decode(em3) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m3, dm3) { + t.Error("not equal") + } + + m4 := &Message{ + Type: Response, + ID: 100, + Data: []byte(`hello world`), + } + em4, err := m4.Encode() + if err != nil { + t.Error(err.Error()) + } + dm4, err := Decode(em4) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m4, dm4) { + t.Error("not equal") + } + + m5 := &Message{ + Type: Notify, + Route: "test.test.test", + Data: []byte(`hello world`), + compressed: true, + } + em5, err := m5.Encode() + if err != nil { + t.Error(err.Error()) + } + dm5, err := Decode(em5) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m5, dm5) { + t.Error("not equal") + } + + m6 := &Message{ + Type: Notify, + Route: "test.test.test20", + Data: []byte(`hello world`), + } + em6, err := m6.Encode() + if err != nil { + t.Error(err.Error()) + } + dm6, err := Decode(em6) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m6, dm6) { + t.Error("not equal") + } + + m7 := &Message{ + Type: Push, + Route: "test.test.test9", + Data: []byte(`hello world`), + } + em7, err := m7.Encode() + if err != nil { + t.Error(err.Error()) + } + dm7, err := Decode(em7) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m7, dm7) { + t.Error("not equal") + } + + m8 := &Message{ + Type: Push, + Route: "test.test.test3", + Data: []byte(`hello world`), + compressed: true, + } + em8, err := m8.Encode() + if err != nil { + t.Error(err.Error()) + } + dm8, err := Decode(em8) + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(m8, dm8) { + t.Error("not equal") + } +} diff --git a/internal/message/util.go b/internal/message/util.go new file mode 100644 index 0000000..ad984c4 --- /dev/null +++ b/internal/message/util.go @@ -0,0 +1,14 @@ +package message + +import "ngs/internal/env" + +func Serialize(v interface{}) ([]byte, error) { + if data, ok := v.([]byte); ok { + return data, nil + } + data, err := env.Serializer.Marshal(v) + if err != nil { + return nil, err + } + return data, nil +} diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go new file mode 100644 index 0000000..0f44df3 --- /dev/null +++ b/internal/runtime/runtime.go @@ -0,0 +1,5 @@ +package runtime + +import "ngs/cluster" + +var CurrentNode *cluster.Node diff --git a/mock/net.go b/mock/net.go new file mode 100644 index 0000000..4b64822 --- /dev/null +++ b/mock/net.go @@ -0,0 +1,10 @@ +package mock + +// NetAddr mock the net.Addr interface +type NetAddr struct{} + +// Network implements the net.Addr interface +func (a NetAddr) Network() string { return "mock" } + +// String implements the net.Addr interface +func (a NetAddr) String() string { return "mock-addr" } diff --git a/options.go b/options.go new file mode 100644 index 0000000..51f20bc --- /dev/null +++ b/options.go @@ -0,0 +1,153 @@ +package ngs + +import ( + "google.golang.org/grpc" + "net/http" + "ngs/cluster" + "ngs/component" + "ngs/internal/env" + "ngs/internal/log" + "ngs/internal/message" + "ngs/pipeline" + "ngs/serialize" + "time" +) + +type Option func(*cluster.Options) + +func WithPipeline(pipeline pipeline.Pipeline) Option { + return func(opt *cluster.Options) { + opt.Pipeline = pipeline + } +} + +// WithAdvertiseAddr sets the advertisement address option, it will be the listen address in +// master node and an advertisement address which cluster member to connect +func WithAdvertiseAddr(addr string, retryInterval ...time.Duration) Option { + return func(opt *cluster.Options) { + opt.AdvertiseAddr = addr + if len(retryInterval) > 0 { + opt.RetryInterval = retryInterval[0] + } + } +} + +// WithClientAddr sets the listen address which is used to establish connection between +// cluster members. Will select an available port automatically if no member address +// setting and panic if no available port +func WithClientAddr(addr string) Option { + return func(opt *cluster.Options) { + opt.ClientAddr = addr + } +} + +// WithMaster sets the option to indicate whether the current node is master node +func WithMaster() Option { + return func(opt *cluster.Options) { + opt.IsMaster = true + } +} + +// WithGrpcOptions sets the grpc dial options +func WithGrpcOptions(opts ...grpc.DialOption) Option { + return func(_ *cluster.Options) { + env.GrpcOptions = append(env.GrpcOptions, opts...) + } +} + +// WithComponents sets the Components +func WithComponents(components *component.Components) Option { + return func(opt *cluster.Options) { + opt.Components = components + } +} + +// WithHeartbeatInterval sets Heartbeat time interval +func WithHeartbeatInterval(d time.Duration) Option { + return func(_ *cluster.Options) { + env.Heartbeat = d + } +} + +// WithCheckOriginFunc sets the function that check `Origin` in http headers +func WithCheckOriginFunc(fn func(*http.Request) bool) Option { + return func(opt *cluster.Options) { + env.CheckOrigin = fn + } +} + +// WithDebugMode let 'ngs' to run under Debug mode. +func WithDebugMode() Option { + return func(_ *cluster.Options) { + env.Debug = true + } +} + +// WithDictionary sets routes map +func WithDictionary(dict map[string]uint16) Option { + return func(_ *cluster.Options) { + message.SetDictionary(dict) + } +} + +func WithWSPath(path string) Option { + return func(_ *cluster.Options) { + env.WSPath = path + } +} + +// WithTimerPrecision sets the ticker precision, and time precision can not less +// than a Millisecond, and can not change after application running. The default +// precision is time.Second +func WithTimerPrecision(precision time.Duration) Option { + if precision < time.Millisecond { + panic("time precision can not less than a Millisecond") + } + return func(_ *cluster.Options) { + env.TimerPrecision = precision + } +} + +// WithSerializer customizes application serializer, which automatically Marshal +// and UnMarshal handler payload +func WithSerializer(serializer serialize.Serializer) Option { + return func(opt *cluster.Options) { + env.Serializer = serializer + } +} + +// WithLabel sets the current node label in cluster +func WithLabel(label string) Option { + return func(opt *cluster.Options) { + opt.Label = label + } +} + +// WithIsWebsocket indicates whether current node WebSocket is enabled +func WithIsWebsocket(enableWs bool) Option { + return func(opt *cluster.Options) { + opt.IsWebsocket = enableWs + } +} + +// WithTSLConfig sets the `key` and `certificate` of TSL +func WithTSLConfig(certificate, key string) Option { + return func(opt *cluster.Options) { + opt.TSLCertificate = certificate + opt.TSLKey = key + } +} + +// WithLogger overrides the default logger +func WithLogger(l log.Logger) Option { + return func(opt *cluster.Options) { + log.SetLogger(l) + } +} + +// WithHandshakeValidator sets the function that Verify `handshake` data +func WithHandshakeValidator(fn func([]byte) error) Option { + return func(opt *cluster.Options) { + env.HandshakeValidator = fn + } +} diff --git a/pipeline/pipeline.go b/pipeline/pipeline.go new file mode 100644 index 0000000..f1c2e16 --- /dev/null +++ b/pipeline/pipeline.go @@ -0,0 +1,77 @@ +package pipeline + +import ( + "ngs/internal/message" + "ngs/session" + "sync" +) + +type ( + // Message is the alias of `message.Message` + Message = message.Message + + Func func(s *session.Session, msg *message.Message) error + + Pipeline interface { + Outbound() Channel + Inbound() Channel + } + + pipeline struct { + outbound, inbound *pipelineChannel + } + + Channel interface { + PushFront(h Func) + PushBack(h Func) + Process(s *session.Session, msg *message.Message) error + } + + pipelineChannel struct { + mu sync.RWMutex + handlers []Func + } +) + +func New() Pipeline { + return &pipeline{ + outbound: &pipelineChannel{}, + inbound: &pipelineChannel{}, + } +} + +func (p *pipeline) Outbound() Channel { return p.outbound } +func (p *pipeline) Inbound() Channel { return p.inbound } + +// PushFront push a function to the front of the pipeline +func (p *pipelineChannel) PushFront(h Func) { + p.mu.Lock() + defer p.mu.Unlock() + handlers := make([]Func, len(p.handlers)+1) + handlers[0] = h + copy(handlers[1:], p.handlers) + p.handlers = handlers +} + +// PushBack push a function to the end of the pipeline +func (p *pipelineChannel) PushBack(h Func) { + p.mu.Lock() + defer p.mu.Unlock() + p.handlers = append(p.handlers, h) +} + +// Process message with all pipeline functions +func (p *pipelineChannel) Process(s *session.Session, msg *message.Message) error { + p.mu.RLock() + defer p.mu.RUnlock() + if len(p.handlers) < 1 { + return nil + } + for _, h := range p.handlers { + err := h(s, msg) + if err != nil { + return err + } + } + return nil +} diff --git a/scheduler/scheduler.go b/scheduler/scheduler.go new file mode 100644 index 0000000..316164c --- /dev/null +++ b/scheduler/scheduler.go @@ -0,0 +1,79 @@ +package scheduler + +import ( + "fmt" + "ngs/internal/env" + "ngs/internal/log" + "runtime/debug" + "sync/atomic" + "time" +) + +const ( + messageQueueBacklog = 1 << 10 // 1024 + sessionCloseBacklog = 1 << 8 // 256 +) + +// LocalScheduler schedules task to a customized goroutine +type LocalScheduler interface { + Schedule(Task) +} + +type Task func() + +type Hook func() + +var ( + chDie = make(chan struct{}) + chExit = make(chan struct{}) + chTasks = make(chan Task, 1<<8) + started int32 + closed int32 +) + +func try(f func()) { + defer func() { + if err := recover(); err != nil { + log.Println(fmt.Sprintf("Handle message panic: %+v\n%s", err, debug.Stack())) + } + }() + f() +} + +func Schedule() { + if atomic.AddInt32(&started, 1) != 1 { + return + } + + ticker := time.NewTicker(env.TimerPrecision) + defer func() { + ticker.Stop() + close(chExit) + }() + + for { + select { + case <-ticker.C: + cron() + + case f := <-chTasks: + try(f) + + case <-chDie: + return + } + } +} + +func Close() { + if atomic.AddInt32(&closed, 1) != 1 { + return + } + close(chDie) + <-chExit + log.Println("Scheduler stopped") +} + +func PushTask(task Task) { + chTasks <- task +} diff --git a/scheduler/timer.go b/scheduler/timer.go new file mode 100644 index 0000000..7738a4a --- /dev/null +++ b/scheduler/timer.go @@ -0,0 +1,196 @@ +package scheduler + +import ( + "fmt" + "math" + "ngs/internal/log" + "runtime/debug" + "sync" + "sync/atomic" + "time" +) + +const ( + infinite = -1 +) + +var ( + timerManager = &struct { + incrementID int64 // auto increment id + timers map[int64]*Timer // all timers + + muClosingTimer sync.RWMutex // 关闭锁,避免重复关闭 + closingTimer []int64 // 已关闭的timer id + muCreatedTimer sync.RWMutex // 创建锁,避免重复创建 + createdTimer []*Timer // 已创建的Timer + }{} +) + +type ( + // TimerFunc represents a function which will be called periodically in main + // logic goroutine. + TimerFunc func() + + // TimerCondition represents a checker that returns true when cron job needs + // to execute + TimerCondition interface { + Check(now time.Time) bool + } + + // Timer represents a cron job + Timer struct { + id int64 // timer id + fn TimerFunc // function that execute + createAt int64 // timer create time + interval time.Duration // execution interval + condition TimerCondition // condition to cron job execution + elapse int64 // total elapse time + closed int32 // is timer closed + counter int // counter + } +) + +func init() { + timerManager.timers = map[int64]*Timer{} +} + +// ID returns id of current timer +func (t *Timer) ID() int64 { + return t.id +} + +// Stop turns off a timer. After Stop, fn will not be called forever +func (t *Timer) Stop() { + if atomic.AddInt32(&t.closed, 1) != 1 { + return + } + + t.counter = 0 +} + +// safeCall 安全调用,收集所有 fn 触发的 panic,给与提示即可 +func safeCall(_ int64, fn TimerFunc) { + defer func() { + if err := recover(); err != nil { + log.Println(fmt.Sprintf("Handle timer panic: %+v\n%s", err, debug.Stack())) + } + }() + + fn() +} + +func cron() { + if len(timerManager.createdTimer) > 0 { + timerManager.muCreatedTimer.Lock() + for _, t := range timerManager.createdTimer { + timerManager.timers[t.id] = t + } + timerManager.createdTimer = timerManager.createdTimer[:0] + timerManager.muCreatedTimer.Unlock() + } + + if len(timerManager.timers) < 1 { + return + } + + now := time.Now() + unn := now.UnixNano() + for id, t := range timerManager.timers { + if t.counter == infinite || t.counter > 0 { + // condition timer + if t.condition != nil { + if t.condition.Check(now) { + safeCall(id, t.fn) + } + continue + } + + // execute job + if t.createAt+t.elapse <= unn { + safeCall(id, t.fn) + t.elapse += int64(t.interval) + + // update timer counter + if t.counter != infinite && t.counter > 0 { + t.counter-- + } + } + } + + if t.counter == 0 { + timerManager.muClosingTimer.Lock() + timerManager.closingTimer = append(timerManager.closingTimer, t.id) + timerManager.muClosingTimer.Unlock() + continue + } + } + + if len(timerManager.closingTimer) > 0 { + timerManager.muClosingTimer.Lock() + for _, id := range timerManager.closingTimer { + delete(timerManager.timers, id) + } + timerManager.closingTimer = timerManager.closingTimer[:0] + timerManager.muClosingTimer.Unlock() + } +} + +// NewTimer returns a new Timer containing a function that will be called +// with a period specified by the duration argument. It adjusts the intervals +// for slow receivers. +// The duration d must be greater than zero; if not, NewTimer will panic. +// Stop the timer to release associated resources. +func NewTimer(interval time.Duration, fn TimerFunc) *Timer { + return NewCountTimer(interval, infinite, fn) +} + +// NewCountTimer returns a new Timer containing a function that will be called +// with a period specified by the duration argument. After count times, timer +// will be stopped automatically, It adjusts the intervals for slow receivers. +// The duration d must be greater than zero; if not, NewCountTimer will panic. +// Stop the timer to release associated resources. +func NewCountTimer(interval time.Duration, count int, fn TimerFunc) *Timer { + if fn == nil { + panic("ngs/timer: nil timer function") + } + if interval <= 0 { + panic("non-positive interval for NewTimer") + } + + t := &Timer{ + id: atomic.AddInt64(&timerManager.incrementID, 1), + fn: fn, + createAt: time.Now().UnixNano(), + interval: interval, + elapse: int64(interval), // first execution will be after interval + counter: count, + } + + timerManager.muCreatedTimer.Lock() + timerManager.createdTimer = append(timerManager.createdTimer, t) + timerManager.muCreatedTimer.Unlock() + return t +} + +// NewAfterTimer returns a new Timer containing a function that will be called +// after duration that specified by the duration argument. +// The duration d must be greater than zero; if not, NewAfterTimer will panic. +// Stop the timer to release associated resources. +func NewAfterTimer(duration time.Duration, fn TimerFunc) *Timer { + return NewCountTimer(duration, 1, fn) +} + +// NewCondTimer returns a new Timer containing a function that will be called +// when condition satisfied that specified by the condition argument. +// The duration d must be greater than zero; if not, NewCondTimer will panic. +// Stop the timer to release associated resources. +func NewCondTimer(condition TimerCondition, fn TimerFunc) *Timer { + if condition == nil { + panic("ngs/timer: nil condition") + } + + t := NewCountTimer(time.Duration(math.MaxInt64), infinite, fn) + t.condition = condition + + return t +} diff --git a/scheduler/timer_test.go b/scheduler/timer_test.go new file mode 100644 index 0000000..5d8786a --- /dev/null +++ b/scheduler/timer_test.go @@ -0,0 +1,84 @@ +package scheduler + +import ( + "sync/atomic" + "testing" + "time" +) + +func TestNewTimer(t *testing.T) { + var exists = struct { + timers int + createdTimes int + closingTimers int + }{ + timers: len(timerManager.timers), + createdTimes: len(timerManager.createdTimer), + closingTimers: len(timerManager.closingTimer), + } + + const tc = 1000 + var counter int64 + for i := 0; i < tc; i++ { + NewTimer(1*time.Millisecond, func() { + atomic.AddInt64(&counter, 1) + }) + } + + <-time.After(5 * time.Millisecond) + cron() + cron() + if counter != tc*2 { + t.Fatalf("expect: %d, got: %d", tc*2, counter) + } + + if len(timerManager.timers) != exists.timers+tc { + t.Fatalf("timers: %d", len(timerManager.timers)) + } + + if len(timerManager.createdTimer) != exists.createdTimes { + t.Fatalf("createdTimer: %d", len(timerManager.createdTimer)) + } + + if len(timerManager.closingTimer) != exists.closingTimers { + t.Fatalf("closingTimer: %d", len(timerManager.closingTimer)) + } +} + +func TestNewAfterTimer(t *testing.T) { + var exists = struct { + timers int + createdTimes int + closingTimers int + }{ + timers: len(timerManager.timers), + createdTimes: len(timerManager.createdTimer), + closingTimers: len(timerManager.closingTimer), + } + + const tc = 1000 + var counter int64 + for i := 0; i < tc; i++ { + NewAfterTimer(1*time.Millisecond, func() { + atomic.AddInt64(&counter, 1) + }) + } + + <-time.After(5 * time.Millisecond) + cron() + if counter != tc { + t.Fatalf("expect: %d, got: %d", tc, counter) + } + + if len(timerManager.timers) != exists.timers { + t.Fatalf("timers: %d", len(timerManager.timers)) + } + + if len(timerManager.createdTimer) != exists.createdTimes { + t.Fatalf("createdTimer: %d", len(timerManager.createdTimer)) + } + + if len(timerManager.closingTimer) != exists.closingTimers { + t.Fatalf("closingTimer: %d", len(timerManager.closingTimer)) + } +} diff --git a/serialize/json/json.go b/serialize/json/json.go new file mode 100644 index 0000000..8261d1d --- /dev/null +++ b/serialize/json/json.go @@ -0,0 +1,25 @@ +package json + +import ( + "encoding/json" + "ngs/serialize" +) + +// Serializer implements the serialize.Serializer interface +type Serializer struct{} + +// NewSerializer returns a new serialize.Serializer. +func NewSerializer() serialize.Serializer { + return &Serializer{} +} + +// Marshal returns the JSON encoding of v. +func (s *Serializer) Marshal(v interface{}) ([]byte, error) { + return json.Marshal(v) +} + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. +func (s *Serializer) Unmarshal(data []byte, v interface{}) error { + return json.Unmarshal(data, v) +} diff --git a/serialize/json/json_test.go b/serialize/json/json_test.go new file mode 100644 index 0000000..e4e097f --- /dev/null +++ b/serialize/json/json_test.go @@ -0,0 +1,62 @@ +package json + +import ( + "reflect" + "testing" +) + +type Message struct { + Code int `json:"code"` + Data string `json:"data"` +} + +func TestSerializer_Serialize(t *testing.T) { + m := Message{1, "hello world"} + s := NewSerializer() + b, err := s.Marshal(m) + if err != nil { + t.Fail() + } + + m2 := Message{} + if err := s.Unmarshal(b, &m2); err != nil { + t.Fail() + } + + if !reflect.DeepEqual(m, m2) { + t.Fail() + } +} + +func BenchmarkSerializer_Serialize(b *testing.B) { + m := &Message{100, "hell world"} + s := NewSerializer() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + if _, err := s.Marshal(m); err != nil { + b.Fatalf("unmarshal failed: %v", err) + } + } + + b.ReportAllocs() +} + +func BenchmarkSerializer_Deserialize(b *testing.B) { + m := &Message{100, "hell world"} + s := NewSerializer() + + d, err := s.Marshal(m) + if err != nil { + b.Error(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + m1 := &Message{} + if err := s.Unmarshal(d, m1); err != nil { + b.Fatalf("unmarshal failed: %v", err) + } + } + b.ReportAllocs() +} diff --git a/serialize/protobuf/protobuf.go b/serialize/protobuf/protobuf.go new file mode 100644 index 0000000..f59b2e5 --- /dev/null +++ b/serialize/protobuf/protobuf.go @@ -0,0 +1,37 @@ +package protobuf + +import ( + "errors" + "google.golang.org/protobuf/proto" + "ngs/serialize" +) + +// ErrWrongValueType is the error used for marshal the value with protobuf encoding. +var ErrWrongValueType = errors.New("protobuf: convert on wrong type value") + +// Serializer implements the serialize.Serializer interface +type Serializer struct{} + +// NewSerializer returns a new Serializer. +func NewSerializer() serialize.Serializer { + return &Serializer{} +} + +// Marshal returns the protobuf encoding of v. +func (s *Serializer) Marshal(v interface{}) ([]byte, error) { + pb, ok := v.(proto.Message) + if !ok { + return nil, ErrWrongValueType + } + return proto.Marshal(pb) +} + +// Unmarshal parses the protobuf-encoded data and stores the result +// in the value pointed to by v. +func (s *Serializer) Unmarshal(data []byte, v interface{}) error { + pb, ok := v.(proto.Message) + if !ok { + return ErrWrongValueType + } + return proto.Unmarshal(data, pb) +} diff --git a/serialize/protobuf/protobuf_test.go b/serialize/protobuf/protobuf_test.go new file mode 100644 index 0000000..46657cc --- /dev/null +++ b/serialize/protobuf/protobuf_test.go @@ -0,0 +1,56 @@ +package protobuf + +import ( + "google.golang.org/protobuf/proto" + "ngs/benchmark/testdata" + "testing" +) + +func TestProtobufSerialezer_Serialize(t *testing.T) { + m := &testdata.Ping{Content: "hello"} + s := NewSerializer() + + b, err := s.Marshal(m) + if err != nil { + t.Error(err) + } + + m1 := &testdata.Ping{} + if err := s.Unmarshal(b, m1); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + // refer: https://developers.google.com/protocol-buffers/docs/reference/go/faq#deepequal + if !proto.Equal(m, m1) { + t.Fail() + } +} + +func BenchmarkSerializer_Serialize(b *testing.B) { + m := &testdata.Ping{Content: "hello"} + s := NewSerializer() + + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if _, err := s.Marshal(m); err != nil { + b.Fatalf("unmarshal failed: %v", err) + } + } +} + +func BenchmarkSerializer_Deserialize(b *testing.B) { + m := &testdata.Ping{Content: "hello"} + s := NewSerializer() + + d, err := s.Marshal(m) + if err != nil { + b.Error(err) + } + + b.ReportAllocs() + for i := 0; i < b.N; i++ { + m1 := &testdata.Ping{} + if err := s.Unmarshal(d, m1); err != nil { + b.Fatalf("unmarshal failed: %v", err) + } + } +} diff --git a/serialize/serializer.go b/serialize/serializer.go new file mode 100644 index 0000000..c145e2b --- /dev/null +++ b/serialize/serializer.go @@ -0,0 +1,19 @@ +package serialize + +type ( + // Marshaler is the interface implemented by types that + Marshaler interface { + Marshal(interface{}) ([]byte, error) + } + + // Unmarshaler represents an Unmarshal interface + Unmarshaler interface { + Unmarshal([]byte, interface{}) error + } + + // Serializer is the interface that groups the basic Marshal and Unmarshal methods. + Serializer interface { + Marshaler + Unmarshaler + } +) diff --git a/service/connection.go b/service/connection.go new file mode 100644 index 0000000..e5260be --- /dev/null +++ b/service/connection.go @@ -0,0 +1,41 @@ +package service + +import "sync/atomic" + +// Connections is a global variable which is used by session. thread-safe +var Connections = newConnectionService() + +type connectionService struct { + count int64 + sid int64 +} + +func newConnectionService() *connectionService { + return &connectionService{sid: 0} +} + +// Increment the connection count +func (c *connectionService) Increment() { + atomic.AddInt64(&c.count, 1) +} + +// Decrement the connection count +func (c *connectionService) Decrement() { + atomic.AddInt64(&c.count, -1) +} + +// Count returns the connection numbers in current +func (c *connectionService) Count() int64 { + return atomic.LoadInt64(&c.count) +} + +// Reset the connection service status +func (c *connectionService) Reset() { + atomic.StoreInt64(&c.count, 0) + atomic.StoreInt64(&c.sid, 0) +} + +// SessionID returns the session id +func (c *connectionService) SessionID() int64 { + return atomic.AddInt64(&c.sid, 1) +} diff --git a/service/connection_test.go b/service/connection_test.go new file mode 100644 index 0000000..754e04e --- /dev/null +++ b/service/connection_test.go @@ -0,0 +1,29 @@ +package service + +import "testing" + +const paraCount = 500000 + +func TestNewConnectionService(t *testing.T) { + service := newConnectionService() + w := make(chan bool, paraCount) + for i := 0; i < paraCount; i++ { + go func() { + service.Increment() + service.SessionID() + w <- true + }() + } + + for i := 0; i < paraCount; i++ { + <-w + } + + if service.Count() != paraCount { + t.Error("wrong connection count") + } + + if service.SessionID() != paraCount+1 { + t.Error("wrong session id") + } +} diff --git a/session/lifetime.go b/session/lifetime.go new file mode 100644 index 0000000..4708b60 --- /dev/null +++ b/session/lifetime.go @@ -0,0 +1,31 @@ +package session + +type ( + // LifetimeHandler represents a callback + // that will be called when a session close or + // session low-level connection broken. + LifetimeHandler func(*Session) + + lifetime struct { + // callbacks that emitted on session closed + onClosed []LifetimeHandler + } +) + +var Lifetime = &lifetime{} + +// OnClosed set the Callback which will be called +// when session is closed Waring: session has closed. +func (lt *lifetime) OnClosed(h LifetimeHandler) { + lt.onClosed = append(lt.onClosed, h) +} + +func (lt *lifetime) Close(s *Session) { + if len(lt.onClosed) < 1 { + return + } + + for _, h := range lt.onClosed { + h(s) + } +} diff --git a/session/router.go b/session/router.go new file mode 100644 index 0000000..2e3fe91 --- /dev/null +++ b/session/router.go @@ -0,0 +1,26 @@ +package session + +import "sync" + +// Router is used to select remote service address +type Router struct { + routes sync.Map +} + +func newRouter() *Router { + return &Router{} +} + +// Bind bound an address to remote service +func (r *Router) Bind(service, address string) { + r.routes.Store(service, address) +} + +// Find finds the address corresponding a remote service +func (r *Router) Find(service string) (string, bool) { + v, found := r.routes.Load(service) + if !found { + return "", false + } + return v.(string), true +} diff --git a/session/session.go b/session/session.go new file mode 100644 index 0000000..b55cbb0 --- /dev/null +++ b/session/session.go @@ -0,0 +1,398 @@ +package session + +import ( + "errors" + "net" + "ngs/service" + "sync" + "sync/atomic" + "time" +) + +// NetworkEntity represent low-level network instance +type NetworkEntity interface { + Push(route string, v interface{}) error + RPC(route string, v interface{}) error + LastMid() uint64 + Response(v interface{}) error + ResponseMid(mid uint64, v interface{}) error + Close() error + RemoteAddr() net.Addr +} + +var ( + // ErrIllegalUID represents a invalid uid + ErrIllegalUID = errors.New("illegal uid") +) + +// Session represents a client session which could storage temp data during low-level +// keep connected, all data will be released when the low-level connection was broken. +// Session instance related to the client will be passed to Handler method as the first +// parameter. +type Session struct { + sync.RWMutex // protect data + id int64 // session global unique id + uid int64 // binding user id + lastTime int64 // last heartbeat time + entity NetworkEntity // low-level network entity + data map[string]interface{} // session data store + router *Router +} + +// New returns a new session instance +// a NetworkEntity is a low-level network instance +func New(entity NetworkEntity) *Session { + return &Session{ + id: service.Connections.SessionID(), + entity: entity, + data: make(map[string]interface{}), + lastTime: time.Now().Unix(), + router: newRouter(), + } +} + +// NetworkEntity returns the low-level network agent object +func (s *Session) NetworkEntity() NetworkEntity { + return s.entity +} + +// Router returns the service router +func (s *Session) Router() *Router { + return s.router +} + +// RPC sends message to remote server +func (s *Session) RPC(route string, v interface{}) error { + return s.entity.RPC(route, v) +} + +// Push message to client +func (s *Session) Push(route string, v interface{}) error { + return s.entity.Push(route, v) +} + +// Response message to client +func (s *Session) Response(v interface{}) error { + return s.entity.Response(v) +} + +// ResponseMID responses message to client, mid is +// request message ID +func (s *Session) ResponseMID(mid uint64, v interface{}) error { + return s.entity.ResponseMid(mid, v) +} + +// ID returns the session id +func (s *Session) ID() int64 { + return s.id +} + +// UID returns uid that bind to current session +func (s *Session) UID() int64 { + return atomic.LoadInt64(&s.uid) +} + +// LastMid returns the last message id +func (s *Session) LastMid() uint64 { + return s.entity.LastMid() +} + +// Bind UID to current session +func (s *Session) Bind(uid int64) error { + if uid < 1 { + return ErrIllegalUID + } + + atomic.StoreInt64(&s.uid, uid) + return nil +} + +// Close terminate current session, session related data will not be released, +// all related data should be Clear explicitly in Session closed callback +func (s *Session) Close() { + _ = s.entity.Close() +} + +// RemoteAddr returns the remote network address. +func (s *Session) RemoteAddr() net.Addr { + return s.entity.RemoteAddr() +} + +// Remove delete data associated with the key from session storage +func (s *Session) Remove(key string) { + s.Lock() + defer s.Unlock() + + delete(s.data, key) +} + +// Set associates value with the key in session storage +func (s *Session) Set(key string, value interface{}) { + s.Lock() + defer s.Unlock() + + s.data[key] = value +} + +// HasKey decides whether a key has associated value +func (s *Session) HasKey(key string) bool { + s.RLock() + defer s.RUnlock() + + _, has := s.data[key] + return has +} + +// Int returns the value associated with the key as a int. +func (s *Session) Int(key string) int { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(int) + if !ok { + return 0 + } + return value +} + +// Int8 returns the value associated with the key as a int8. +func (s *Session) Int8(key string) int8 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(int8) + if !ok { + return 0 + } + return value +} + +// Int16 returns the value associated with the key as a int16. +func (s *Session) Int16(key string) int16 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(int16) + if !ok { + return 0 + } + return value +} + +// Int32 returns the value associated with the key as a int32. +func (s *Session) Int32(key string) int32 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(int32) + if !ok { + return 0 + } + return value +} + +// Int64 returns the value associated with the key as a int64. +func (s *Session) Int64(key string) int64 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(int64) + if !ok { + return 0 + } + return value +} + +// Uint returns the value associated with the key as a uint. +func (s *Session) Uint(key string) uint { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(uint) + if !ok { + return 0 + } + return value +} + +// Uint8 returns the value associated with the key as a uint8. +func (s *Session) Uint8(key string) uint8 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(uint8) + if !ok { + return 0 + } + return value +} + +// Uint16 returns the value associated with the key as a uint16. +func (s *Session) Uint16(key string) uint16 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(uint16) + if !ok { + return 0 + } + return value +} + +// Uint32 returns the value associated with the key as a uint32. +func (s *Session) Uint32(key string) uint32 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(uint32) + if !ok { + return 0 + } + return value +} + +// Uint64 returns the value associated with the key as a uint64. +func (s *Session) Uint64(key string) uint64 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(uint64) + if !ok { + return 0 + } + return value +} + +// Float32 returns the value associated with the key as a float32. +func (s *Session) Float32(key string) float32 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(float32) + if !ok { + return 0 + } + return value +} + +// Float64 returns the value associated with the key as a float64. +func (s *Session) Float64(key string) float64 { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return 0 + } + + value, ok := v.(float64) + if !ok { + return 0 + } + return value +} + +// String returns the value associated with the key as a string. +func (s *Session) String(key string) string { + s.RLock() + defer s.RUnlock() + + v, ok := s.data[key] + if !ok { + return "" + } + + value, ok := v.(string) + if !ok { + return "" + } + return value +} + +// Value returns the value associated with the key as a interface{}. +func (s *Session) Value(key string) interface{} { + s.RLock() + defer s.RUnlock() + + return s.data[key] +} + +// State returns all session state +func (s *Session) State() map[string]interface{} { + s.RLock() + defer s.RUnlock() + + return s.data +} + +// Restore session state after reconnect +func (s *Session) Restore(data map[string]interface{}) { + s.Lock() + defer s.Unlock() + + s.data = data +} + +// Clear releases all data related to current session +func (s *Session) Clear() { + s.Lock() + defer s.Unlock() + + s.uid = 0 + s.data = map[string]interface{}{} +} diff --git a/session/session_test.go b/session/session_test.go new file mode 100644 index 0000000..7ba8472 --- /dev/null +++ b/session/session_test.go @@ -0,0 +1,175 @@ +package session + +import "testing" + +func TestNewSession(t *testing.T) { + s := New(nil) + if s.ID() < 1 { + t.Fail() + } +} + +func TestSession_Bind(t *testing.T) { + s := New(nil) + uids := []int64{100, 1000, 10000000} + for i, uid := range uids { + s.Bind(uid) + if s.UID() != uids[i] { + t.Fail() + } + } +} + +func TestSession_HasKey(t *testing.T) { + s := New(nil) + key := "hello" + value := "world" + s.Set(key, value) + if !s.HasKey(key) { + t.Fail() + } +} + +func TestSession_Float32(t *testing.T) { + s := New(nil) + key := "hello" + value := float32(1.2000) + s.Set(key, value) + if value != s.Float32(key) { + t.Fail() + } +} + +func TestSession_Float64(t *testing.T) { + s := New(nil) + key := "hello" + value := 1.2000 + s.Set(key, value) + if value != s.Float64(key) { + t.Fail() + } +} + +func TestSession_Int(t *testing.T) { + s := New(nil) + key := "testkey" + value := 234 + s.Set(key, value) + if value != s.Int(key) { + t.Fail() + } +} + +func TestSession_Int8(t *testing.T) { + s := New(nil) + key := "testkey" + value := int8(123) + s.Set(key, value) + if value != s.Int8(key) { + t.Fail() + } +} + +func TestSession_Int16(t *testing.T) { + s := New(nil) + key := "testkey" + value := int16(3245) + s.Set(key, value) + if value != s.Int16(key) { + t.Fail() + } +} + +func TestSession_Int32(t *testing.T) { + s := New(nil) + key := "testkey" + value := int32(5454) + s.Set(key, value) + if value != s.Int32(key) { + t.Fail() + } +} + +func TestSession_Int64(t *testing.T) { + s := New(nil) + key := "testkey" + value := int64(444454) + s.Set(key, value) + if value != s.Int64(key) { + t.Fail() + } +} + +func TestSession_Uint(t *testing.T) { + s := New(nil) + key := "testkey" + value := uint(24254) + s.Set(key, value) + if value != s.Uint(key) { + t.Fail() + } +} + +func TestSession_Uint8(t *testing.T) { + s := New(nil) + key := "testkey" + value := uint8(34) + s.Set(key, value) + if value != s.Uint8(key) { + t.Fail() + } +} + +func TestSession_Uint16(t *testing.T) { + s := New(nil) + key := "testkey" + value := uint16(4645) + s.Set(key, value) + if value != s.Uint16(key) { + t.Fail() + } +} + +func TestSession_Uint32(t *testing.T) { + s := New(nil) + key := "testkey" + value := uint32(12365) + s.Set(key, value) + if value != s.Uint32(key) { + t.Fail() + } +} + +func TestSession_Uint64(t *testing.T) { + s := New(nil) + key := "testkey" + value := uint64(1000) + s.Set(key, value) + if value != s.Uint64(key) { + t.Fail() + } +} + +func TestSession_State(t *testing.T) { + s := New(nil) + key := "testkey" + value := uint64(1000) + s.Set(key, value) + state := s.State() + if value != state[key].(uint64) { + t.Fail() + } +} + +func TestSession_Restore(t *testing.T) { + s := New(nil) + s2 := New(nil) + key := "testkey" + value := uint64(1000) + s.Set(key, value) + state := s.State() + s2.Restore(state) + if value != s2.Uint64(key) { + t.Fail() + } +}