<|start_filename|>src/types/constants.go<|end_filename|>
package types

const HTTP = 0
const WS = 1
const TCP = 2
const UDP = 3
const KCP = 4
const GRPC = 5


<|start_filename|>src/pb/gate/gate_msg.pb.go<|end_filename|>
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pb/gate/gate_msg.proto

package gate

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type GateMsgTest struct {
	I                    int32    `protobuf:"varint,1,opt,name=i,proto3" json:"i,omitempty"`
	S                    string   `protobuf:"bytes,2,opt,name=s,proto3" json:"s,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *GateMsgTest) Reset()         { *m = GateMsgTest{} }
func (m *GateMsgTest) String() string { return proto.CompactTextString(m) }
func (*GateMsgTest) ProtoMessage()    {}
func (*GateMsgTest) Descriptor() ([]byte, []int) {
	return fileDescriptor_gate_msg_d9f7104a9820281c, []int{0}
}
func (m *GateMsgTest) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_GateMsgTest.Unmarshal(m, b)
}
func (m *GateMsgTest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_GateMsgTest.Marshal(b, m, deterministic)
}
func (dst *GateMsgTest) XXX_Merge(src proto.Message) {
	xxx_messageInfo_GateMsgTest.Merge(dst, src)
}
func (m *GateMsgTest) XXX_Size() int {
	return xxx_messageInfo_GateMsgTest.Size(m)
}
func (m *GateMsgTest) XXX_DiscardUnknown() {
	xxx_messageInfo_GateMsgTest.DiscardUnknown(m)
}

var xxx_messageInfo_GateMsgTest proto.InternalMessageInfo

func (m *GateMsgTest) GetI() int32 {
	if m != nil {
		return m.I
	}
	return 0
}

func (m *GateMsgTest) GetS() string {
	if m != nil {
		return m.S
	}
	return ""
}

type GateMsgTestAck struct {
	IntList              []int32  `protobuf:"varint,1,rep,packed,name=intList,proto3" json:"intList,omitempty"`
	StrList              []string `protobuf:"bytes,2,rep,name=strList,proto3" json:"strList,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *GateMsgTestAck) Reset()         { *m = GateMsgTestAck{} }
func (m *GateMsgTestAck) String() string { return proto.CompactTextString(m) }
func (*GateMsgTestAck) ProtoMessage()    {}
func (*GateMsgTestAck) Descriptor() ([]byte, []int) {
	return fileDescriptor_gate_msg_d9f7104a9820281c, []int{1}
}
func (m *GateMsgTestAck) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_GateMsgTestAck.Unmarshal(m, b)
}
func (m *GateMsgTestAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_GateMsgTestAck.Marshal(b, m, deterministic)
}
func (dst *GateMsgTestAck) XXX_Merge(src proto.Message) {
	xxx_messageInfo_GateMsgTestAck.Merge(dst, src)
}
func (m *GateMsgTestAck) XXX_Size() int {
	return xxx_messageInfo_GateMsgTestAck.Size(m)
}
func (m *GateMsgTestAck) XXX_DiscardUnknown() {
	xxx_messageInfo_GateMsgTestAck.DiscardUnknown(m)
}

var xxx_messageInfo_GateMsgTestAck proto.InternalMessageInfo

func (m *GateMsgTestAck) GetIntList() []int32 {
	if m != nil {
		return m.IntList
	}
	return nil
}

func (m *GateMsgTestAck) GetStrList() []string {
	if m != nil {
		return m.StrList
	}
	return nil
}

type LoginReq struct {
	Account              string   `protobuf:"bytes,1,opt,name=Account,proto3" json:"Account,omitempty"`
	Password             string   `protobuf:"bytes,2,opt,name=Password,proto3" json:"Password,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *LoginReq) Reset()         { *m = LoginReq{} }
func (m *LoginReq) String() string { return proto.CompactTextString(m) }
func (*LoginReq) ProtoMessage()    {}
func (*LoginReq) Descriptor() ([]byte, []int) {
	return fileDescriptor_gate_msg_d9f7104a9820281c, []int{2}
}
func (m *LoginReq) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_LoginReq.Unmarshal(m, b)
}
func (m *LoginReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_LoginReq.Marshal(b, m, deterministic)
}
func (dst *LoginReq) XXX_Merge(src proto.Message) {
	xxx_messageInfo_LoginReq.Merge(dst, src)
}
func (m *LoginReq) XXX_Size() int {
	return xxx_messageInfo_LoginReq.Size(m)
}
func (m *LoginReq) XXX_DiscardUnknown() {
	xxx_messageInfo_LoginReq.DiscardUnknown(m)
}

var xxx_messageInfo_LoginReq proto.InternalMessageInfo

func (m *LoginReq) GetAccount() string {
	if m != nil {
		return m.Account
	}
	return ""
}

func (m *LoginReq) GetPassword() string {
	if m != nil {
		return m.Password
	}
	return ""
}

type LoginAck struct {
	Error                string   `protobuf:"bytes,1,opt,name=Error,proto3" json:"Error,omitempty"`
	UserId               int32    `protobuf:"varint,2,opt,name=UserId,proto3" json:"UserId,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *LoginAck) Reset()         { *m = LoginAck{} }
func (m *LoginAck) String() string { return proto.CompactTextString(m) }
func (*LoginAck) ProtoMessage()    {}
func (*LoginAck) Descriptor() ([]byte, []int) {
	return fileDescriptor_gate_msg_d9f7104a9820281c, []int{3}
}
func (m *LoginAck) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_LoginAck.Unmarshal(m, b)
}
func (m *LoginAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_LoginAck.Marshal(b, m, deterministic)
}
func (dst *LoginAck) XXX_Merge(src proto.Message) {
	xxx_messageInfo_LoginAck.Merge(dst, src)
}
func (m *LoginAck) XXX_Size() int {
	return xxx_messageInfo_LoginAck.Size(m)
}
func (m *LoginAck) XXX_DiscardUnknown() {
	xxx_messageInfo_LoginAck.DiscardUnknown(m)
}

var xxx_messageInfo_LoginAck proto.InternalMessageInfo

func (m *LoginAck) GetError() string {
	if m != nil {
		return m.Error
	}
	return ""
}

func (m *LoginAck) GetUserId() int32 {
	if m != nil {
		return m.UserId
	}
	return 0
}

func init() {
	proto.RegisterType((*GateMsgTest)(nil), "gate.GateMsgTest")
	proto.RegisterType((*GateMsgTestAck)(nil), "gate.GateMsgTestAck")
	proto.RegisterType((*LoginReq)(nil), "gate.LoginReq")
	proto.RegisterType((*LoginAck)(nil), "gate.LoginAck")
}

func init() { proto.RegisterFile("pb/gate/gate_msg.proto", fileDescriptor_gate_msg_d9f7104a9820281c) }

var fileDescriptor_gate_msg_d9f7104a9820281c = []byte{
	// 211 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0xcf, 0xc1, 0x4b, 0x04, 0x21,
	0x14, 0x06, 0x70, 0xdc, 0xcd, 0x6d, 0xe7, 0x15, 0x1d, 0x24, 0x16, 0xe9, 0x24, 0x9e, 0xec, 0x52,
	0x87, 0x2e, 0x1d, 0x5b, 0x28, 0x22, 0x98, 0x20, 0xa4, 0xce, 0x31, 0x33, 0x89, 0x48, 0x34, 0x4e,
	0xbe, 0x17, 0xfd, 0xfb, 0xa1, 0xe3, 0xc4, 0x5e, 0x84, 0x1f, 0xef, 0x7d, 0xfa, 0x09, 0xbb, 0xa9,
	0xbf, 0xf6, 0x1d, 0xb9, 0x72, 0xbc, 0x7f, 0xa1, 0xbf, 0x9a, 0x52, 0xa4, 0x28, 0x8e, 0xb2, 0xf5,
	0x25, 0x9c, 0x3c, 0x76, 0xe4, 0x9e, 0xd1, 0xbf, 0x3a, 0x24, 0x71, 0x0a, 0x2c, 0x48, 0xa6, 0x98,
	0xe1, 0x96, 0x85, 0x2c, 0x94, 0x2b, 0xc5, 0x4c, 0x63, 0x19, 0xea, 0x7b, 0x38, 0x3b, 0x58, 0xdd,
	0x0f, 0x9f, 0x42, 0xc2, 0x71, 0x18, 0xa9, 0x0d, 0x48, 0x92, 0xa9, 0xb5, 0xe1, 0x76, 0x61, 0x9e,
	0x20, 0xa5, 0x32, 0x59, 0xa9, 0xb5, 0x69, 0xec, 0x42, 0x7d, 0x07, 0xdb, 0x36, 0xfa, 0x30, 0x5a,
	0xf7, 0x9d, 0xb7, 0xf6, 0xc3, 0x10, 0x7f, 0x46, 0x2a, 0x6f, 0x36, 0x76, 0xa1, 0xb8, 0x80, 0xed,
	0x4b, 0x87, 0xf8, 0x1b, 0xd3, 0x47, 0x2d, 0xf0, 0x6f, 0x7d, 0x5b, 0x6f, 0xc8, 0x0d, 0xce, 0x81,
	0x3f, 0xa4, 0x14, 0x53, 0xcd, 0xcf, 0x10, 0x3b, 0xd8, 0xbc, 0xa1, 0x4b, 0x4f, 0x73, 0x96, 0xdb,
	0xaa, 0x7e, 0x53, 0x7e, 0x7e, 0xf3, 0x17, 0x00, 0x00, 0xff, 0xff, 0x57, 0x51, 0x26, 0x6a, 0x13,
	0x01, 0x00, 0x00,
}


<|start_filename|>src/pb/template/template_msg.gen.go<|end_filename|>
// DOT NOT EDIT THIS FILE, AUTO GEN!!
package template

import (
	"errors"
	"reflect"
	"log"

	"github.com/golang/protobuf/proto"
)


func GetProtoUseList() []string {
	protoUseList := []string{
		"TemplateMsgTest",
		"TemplateMsgTestAck",
		"TemplateMsgTestNtf",
	}
	return protoUseList
}

func DecodeMessage(codec string, msgName string, msgData []byte) (interface{}, error) {
	if codec == "protobuf" {
		switch msgName {
			
		case "template.TemplateMsgTest":
			msg := &TemplateMsgTest{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		case "template.TemplateMsgTestAck":
			msg := &TemplateMsgTestAck{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		case "template.TemplateMsgTestNtf":
			msg := &TemplateMsgTestNtf{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		}
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}

func ToTemplateMsgTest(msg interface{}) *TemplateMsgTest {
	if reflect.TypeOf(msg).String() != "*template.TemplateMsgTest" {
		log.Panicln("msg type error")
	}
	return msg.(*TemplateMsgTest)
}

func ToTemplateMsgTestAck(msg interface{}) *TemplateMsgTestAck {
	if reflect.TypeOf(msg).String() != "*template.TemplateMsgTestAck" {
		log.Panicln("msg type error")
	}
	return msg.(*TemplateMsgTestAck)
}

func ToTemplateMsgTestNtf(msg interface{}) *TemplateMsgTestNtf {
	if reflect.TypeOf(msg).String() != "*template.TemplateMsgTestNtf" {
		log.Panicln("msg type error")
	}
	return msg.(*TemplateMsgTestNtf)
}

func EncodeMessage(codec string, msg interface{}) ([]byte, error) {
	if codec == "protobuf" {
		buf, err := proto.Marshal(msg.(proto.Message))
		if err != nil {
			return nil, err
		}
		return buf, nil
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}


<|start_filename|>src/examples/test_nsq/main.go<|end_filename|>
package main

import (
	"encoding/json"
	"events"
	"fmt"
)

type TestEvent struct {
	K string
	V int
}

func main() {
	events.Init("127.0.0.1:4150")

	events.Register("topic_test", "ch01", func(data []byte) {
		//fmt.Println(string(data))
		var t TestEvent
		json.Unmarshal(data, &t)
		fmt.Println(t.K, t.V)
	})

	for i := 0; i < 10; i++ {
		e := &TestEvent{K: "key", V: i}
		data, _ := json.Marshal(e)
		events.Publish("topic_test", data)
	}
	select {}
}


<|start_filename|>src/actors/actor.go<|end_filename|>
package actors

import (
	"errors"
	"reflect"
	"time"
)

type ActorHost interface {
	SetActor(actor *Actor)
	ActorLoop()
}

type BaseActorHost struct {
	actor *Actor
}

func (h *BaseActorHost) ActorLoop() {
}

func (h *BaseActorHost) SetActor(actor *Actor) {
	h.actor = actor
}

func (h *BaseActorHost) Actor() *Actor {
	return h.actor
}

func (h *BaseActorHost) ActorId() int32 {
	return h.actor.actorId
}

type actorCallRet struct {
	results []reflect.Value
}
type actorCall struct {
	method      reflect.Method
	params      []reflect.Value
	callRetChan chan *actorCallRet
}
type timeoutTimerCb func()
type tickTimerCb func(int32)

type timeoutTimer struct {
	done      chan bool
	timeoutCb timeoutTimerCb
	count     int32
}

type tickTimer struct {
	done   chan bool
	tickCb tickTimerCb
	count  int32
}

type Actor struct {
	actorId        int32
	callQueue      chan *actorCall
	done           chan bool
	host           ActorHost
	timerCount     int32
	timeoutTimers  map[int32]*timeoutTimer
	tickTimers     map[int32]*tickTimer
	timeoutCbQueue chan *timeoutTimer
	tickCbQueue    chan *tickTimer
}

func (a *Actor) init(actorId int32, host ActorHost) {
	a.actorId = actorId
	a.host = host
	host.SetActor(a)
	a.callQueue = make(chan *actorCall, 1000)
	a.done = make(chan bool, 1)
	a.timerCount = 0
	a.timeoutTimers = make(map[int32]*timeoutTimer, 0)
	a.tickTimers = make(map[int32]*tickTimer, 0)
	a.timeoutCbQueue = make(chan *timeoutTimer, 1000)
	a.tickCbQueue = make(chan *tickTimer, 1000)
	a.startLoop()
}

func (a *Actor) exit() {
	a.done <- true
}

func (a *Actor) GetTimerStats() (int, int) {
	return len(a.timeoutTimers), len(a.tickTimers)
}

func (a *Actor) ActorId() int32 {
	return a.actorId
}

func (a *Actor) assignTimerId() int32 {
	if a.timerCount >= (1<<31 - 10) {
		a.timerCount = 0
	}
	a.timerCount += 1
	return a.timerCount
}

func (a *Actor) SetTimeoutTimer(timeout time.Duration, cb timeoutTimerCb) int32 {
	timerId := a.assignTimerId()
	after := time.After(timeout)
	timer := &timeoutTimer{
		done:      make(chan bool, 1),
		timeoutCb: cb,
		count:     0,
	}
	a.timeoutTimers[timerId] = timer
	go func() {
		for {
			select {
			case <-after:
				a.timeoutCbQueue <- timer
				a.UnsetTimeoutTimer(timerId)
			case <-timer.done:
				return
			}
		}
	}()
	return timerId
}

func (a *Actor) UnsetTimeoutTimer(timerId int32) {
	timer, ok := a.timeoutTimers[timerId]
	if ok {
		timer.done <- true
		delete(a.timeoutTimers, timerId)
	}
}

func (a *Actor) SetTickTimer(du time.Duration, cb tickTimerCb) int32 {
	timerId := a.assignTimerId()
	ticker := time.NewTicker(du)
	timer := &tickTimer{
		done:   make(chan bool, 1),
		tickCb: cb,
		count:  0,
	}
	a.tickTimers[timerId] = timer
	go func() {
		for {
			select {
			case <-ticker.C:
				timer.count += 1
				a.tickCbQueue <- timer
			case <-timer.done:
				ticker.Stop()
				return
			}
		}
	}()
	return timerId
}

func (a *Actor) UnsetTickTimer(timerId int32) {
	timer, ok := a.tickTimers[timerId]
	if ok {
		timer.done <- true
		delete(a.tickTimers, timerId)
	}
}

func (a *Actor) SetLifeTickTimer(du time.Duration, ticks int32, cb tickTimerCb) int32 {
	timerId := a.assignTimerId()
	ticker := time.NewTicker(du)
	timer := &tickTimer{
		done:   make(chan bool, 1),
		tickCb: cb,
		count:  0,
	}
	a.tickTimers[timerId] = timer
	go func() {
		for {
			select {
			case <-ticker.C:
				timer.count += 1
				if timer.count > ticks {
					a.UnsetTickTimer(timerId)
				} else {
					a.tickCbQueue <- timer
				}

			case <-timer.done:
				ticker.Stop()
				return
			}
		}
	}()
	return timerId
}

func (a *Actor) UnsetLifeTickTimer(timerId int32) {
	timer, ok := a.tickTimers[timerId]
	if ok {
		timer.done <- true
		delete(a.tickTimers, timerId)
	}
}

func (a *Actor) putCall(callRetChan chan *actorCallRet, function interface{}, params ...interface{}) error {
	method, err := a.getHostMethod(false, function, params)
	if err != nil {
		return err
	}
	methodParams := make([]reflect.Value, len(params)+1)
	methodParams[0] = reflect.ValueOf(a.host)
	for i := 0; i < len(params); i++ {
		methodParams[i+1] = reflect.ValueOf(params[i])
	}
	call := &actorCall{
		method:      method,
		params:      methodParams,
		callRetChan: callRetChan,
	}
	a.callQueue <- call
	return nil
}

func (a *Actor) putAsynCall(callRetChan chan *actorCallRet, function interface{}, params ...interface{}) error {
	method, err := a.getHostMethod(true, function, params)
	if err != nil {
		return err
	}
	methodParams := make([]reflect.Value, len(params)+1)
	methodParams[0] = reflect.ValueOf(a.host)
	for i := 0; i < len(params); i++ {
		methodParams[i+1] = reflect.ValueOf(params[i])
	}
	call := &actorCall{
		method:      method,
		params:      methodParams,
		callRetChan: callRetChan,
	}
	a.callQueue <- call
	return nil
}

func (a *Actor) getHostMethod(isAsyn bool, function interface{}, params []interface{}) (reflect.Method, error) {
	var method reflect.Method
	funcT := reflect.TypeOf(function)
	funcV := reflect.ValueOf(function)
	hostT := reflect.TypeOf(a.host)
	hostV := reflect.ValueOf(a.host)
	if funcT == nil {
		return method, errors.New("call function is invalid")
	}
	if funcT.Kind() != reflect.Func || funcT.NumIn() < 1 {
		return method, errors.New("call function type is not Func")
	}
	if funcT.In(0) != hostT {
		return method, errors.New("dest actor id or call function is not right")
	}
	if isAsyn == false {
		if funcT.NumOut() != 1 {
			return method, errors.New("call function must return only 1 result")
		}
		if funcT.Out(0).Name() != "error" {
			return method, errors.New("call function's second return type must be error")
		}
	} else {
		if funcT.NumOut() != 0 {
			return method, errors.New("call function has no return result")
		}
	}
	// check function params
	if len(params) != funcT.NumIn()-1 {
		return method, errors.New("params num is not right")
	}
	for i := 1; i < funcT.NumIn(); i++ {
		t := reflect.TypeOf(params[i-1])
		if t.AssignableTo(funcT.In(i)) == false {
			return method, errors.New("papram type is wrong")
		}
	}
	// check if dest actor has this function
	isFind := false
	for i := 0; i < hostV.NumMethod(); i++ {
		if hostT.Method(i).Func.Pointer() == funcV.Pointer() {
			isFind = true
			method = hostT.Method(i)
			break
		}
	}
	if isFind == false {
		return method, errors.New("dest actor has no such call function")
	}
	return method, nil
}

func (a *Actor) startLoop() {
	go func() {
		for {
			a.host.ActorLoop()
			select {
			case tickTimer, _ := <-a.tickCbQueue:
				tickTimer.tickCb(tickTimer.count)

			case timeoutTimer, _ := <-a.timeoutCbQueue:
				timeoutTimer.timeoutCb()

			case call, _ := <-a.callQueue:
				if nil != call {
					ret := call.method.Func.Call(call.params)
					if call.callRetChan != nil {
						call.callRetChan <- &actorCallRet{results: ret}
					}
				}

			case <-a.done:
				return

			default:
			}
		}
	}()
}


<|start_filename|>src/examples/test_actors/test_actors.go<|end_filename|>
package main

import (
	"actors"
	"fmt"
	"time"
)

type Room struct {
	actors.BaseActorHost
}

func (r *Room) Add(a int, b int, out *int) error {
	fmt.Println("call:", a, b)
	*out = a + b
	return nil
}

type UserList struct {
	Users []string
}

func (r *Room) GetUserList(userId string, out *UserList) error {
	out.Users = []string{"aaaaa", "bbbbbb", "ccccc", userId}
	return nil
}

func (r *Room) Join(userId string) {
	fmt.Println("Join Room: ", userId)
}

// this function is loop each routine execute schedule
func (r *Room) ActorLoop() {
	//fmt.Println("loop..")
}

func main() {
	actors.Init()
	room := &Room{}
	actorId := actors.NewActor(room)
	actor := room.Actor()
	fmt.Println("actorId:", actorId)
	var ret int
	err := actors.Call(actorId, (*Room).Add, 100, 200, &ret)
	if err != nil {
		fmt.Println(err)
	}

	if ret == 300 {
		fmt.Println("ret:", ret)
	}
	var userList UserList
	err = actors.Call(actorId, (*Room).GetUserList, "xxxxxx", &userList)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(userList.Users)

	err = actors.AsynCall(actorId, (*Room).Join, "chris-li")
	if err != nil {
		fmt.Println(err)
	}

	actor.SetTimeoutTimer(5000*time.Millisecond, func() {
		fmt.Println("TimeoutTimer is time out now")
	})

	actor.SetLifeTickTimer(1000*time.Millisecond, 10, func(i int32) {
		fmt.Println("Life Ticker: tick ", i)
		if i == 10 {
			fmt.Println("Life Tiker is over")
		}
	})

	actor.SetTickTimer(1000*time.Millisecond, func(i int32) {
		fmt.Println("Test Tick:", i)
		a, b := actor.GetTimerStats()
		fmt.Println("timeout timers: ", a, " tick timers: ", b)
	})

	for {
		//actors.Call(actorId, (*Room).Add, 200, 300)
	}

}


<|start_filename|>src/pb/auth/auth_msg.pb.go<|end_filename|>
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pb/auth/auth_msg.proto

package auth

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type AuthMsgTest struct {
	I                    int32    `protobuf:"varint,1,opt,name=i,proto3" json:"i,omitempty"`
	S                    string   `protobuf:"bytes,2,opt,name=s,proto3" json:"s,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *AuthMsgTest) Reset()         { *m = AuthMsgTest{} }
func (m *AuthMsgTest) String() string { return proto.CompactTextString(m) }
func (*AuthMsgTest) ProtoMessage()    {}
func (*AuthMsgTest) Descriptor() ([]byte, []int) {
	return fileDescriptor_auth_msg_607216fccd27f44a, []int{0}
}
func (m *AuthMsgTest) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_AuthMsgTest.Unmarshal(m, b)
}
func (m *AuthMsgTest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_AuthMsgTest.Marshal(b, m, deterministic)
}
func (dst *AuthMsgTest) XXX_Merge(src proto.Message) {
	xxx_messageInfo_AuthMsgTest.Merge(dst, src)
}
func (m *AuthMsgTest) XXX_Size() int {
	return xxx_messageInfo_AuthMsgTest.Size(m)
}
func (m *AuthMsgTest) XXX_DiscardUnknown() {
	xxx_messageInfo_AuthMsgTest.DiscardUnknown(m)
}

var xxx_messageInfo_AuthMsgTest proto.InternalMessageInfo

func (m *AuthMsgTest) GetI() int32 {
	if m != nil {
		return m.I
	}
	return 0
}

func (m *AuthMsgTest) GetS() string {
	if m != nil {
		return m.S
	}
	return ""
}

type AuthMsgTestAck struct {
	IntList              []int32  `protobuf:"varint,1,rep,packed,name=intList,proto3" json:"intList,omitempty"`
	StrList              []string `protobuf:"bytes,2,rep,name=strList,proto3" json:"strList,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *AuthMsgTestAck) Reset()         { *m = AuthMsgTestAck{} }
func (m *AuthMsgTestAck) String() string { return proto.CompactTextString(m) }
func (*AuthMsgTestAck) ProtoMessage()    {}
func (*AuthMsgTestAck) Descriptor() ([]byte, []int) {
	return fileDescriptor_auth_msg_607216fccd27f44a, []int{1}
}
func (m *AuthMsgTestAck) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_AuthMsgTestAck.Unmarshal(m, b)
}
func (m *AuthMsgTestAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_AuthMsgTestAck.Marshal(b, m, deterministic)
}
func (dst *AuthMsgTestAck) XXX_Merge(src proto.Message) {
	xxx_messageInfo_AuthMsgTestAck.Merge(dst, src)
}
func (m *AuthMsgTestAck) XXX_Size() int {
	return xxx_messageInfo_AuthMsgTestAck.Size(m)
}
func (m *AuthMsgTestAck) XXX_DiscardUnknown() {
	xxx_messageInfo_AuthMsgTestAck.DiscardUnknown(m)
}

var xxx_messageInfo_AuthMsgTestAck proto.InternalMessageInfo

func (m *AuthMsgTestAck) GetIntList() []int32 {
	if m != nil {
		return m.IntList
	}
	return nil
}

func (m *AuthMsgTestAck) GetStrList() []string {
	if m != nil {
		return m.StrList
	}
	return nil
}

func init() {
	proto.RegisterType((*AuthMsgTest)(nil), "auth.AuthMsgTest")
	proto.RegisterType((*AuthMsgTestAck)(nil), "auth.AuthMsgTestAck")
}

func init() { proto.RegisterFile("pb/auth/auth_msg.proto", fileDescriptor_auth_msg_607216fccd27f44a) }

var fileDescriptor_auth_msg_607216fccd27f44a = []byte{
	// 138 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0x48, 0xd2, 0x4f,
	0x2c, 0x2d, 0xc9, 0x00, 0x13, 0xf1, 0xb9, 0xc5, 0xe9, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42,
	0x2c, 0x20, 0xbe, 0x92, 0x26, 0x17, 0xb7, 0x63, 0x69, 0x49, 0x86, 0x6f, 0x71, 0x7a, 0x48, 0x6a,
	0x71, 0x89, 0x10, 0x0f, 0x17, 0x63, 0xa6, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0x63, 0x26,
	0x88, 0x57, 0x2c, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x19, 0xc4, 0x58, 0xac, 0xe4, 0xc2, 0xc5, 0x87,
	0xa4, 0xd4, 0x31, 0x39, 0x5b, 0x48, 0x82, 0x8b, 0x3d, 0x33, 0xaf, 0xc4, 0x27, 0xb3, 0xb8, 0x44,
	0x82, 0x51, 0x81, 0x59, 0x83, 0x35, 0x08, 0xc6, 0x05, 0xc9, 0x14, 0x97, 0x14, 0x81, 0x65, 0x98,
	0x14, 0x98, 0x35, 0x38, 0x83, 0x60, 0xdc, 0x24, 0x36, 0xb0, 0xed, 0xc6, 0x80, 0x00, 0x00, 0x00,
	0xff, 0xff, 0x9e, 0xa0, 0x8e, 0x5c, 0x97, 0x00, 0x00, 0x00,
}


<|start_filename|>src/tools/server-gen/parser.go<|end_filename|>
package main

import (
	"log"
	"strconv"
)

/*
BNF Design:
	<message_type> ::= message <identifier> { <variable_declare> } |
					message <identifier> { <message_type> <variable_declare> } |
					message <identifier> { <variable_declare> <message_type> } |
					message <identifier> { <enum_type> <variable_declare> } |
					message <identifier> { <variable_declare> <enum_type> } |

	<enum_type> :: = enum <identifier> { <variable_declare> }

	<identifier> ::= "\w+"

	<variable_declare> ::= <type> <identifier> = <number>; 			|
						repeated <type> <identifier> = <number>; 	|
						option <type> <identifier> = <number>; 		|
						required <type> <identifier> = <number>; 	|

	<number> ::= "\d"

	<service_define> ::= service <identifier> {<rpc_define>}

	<rpc_define> ::= rpc <identifier> (<message_type>) returns (<message_type>) {};	|
					rpc <identifier> (stream <message_type>) returns (stream <message_type>) {};

	<type> ::= int32 | int64 | uint32 | uint64 | sint32 | sint64 | fixed32 | fixed64 | sfixed32 | sfixed64 |
			   float | double | bool | bytes | string | <message_type> | <enum_type>
*/
type DefRpc struct {
	isParamStream bool
	isRetStream   bool
	name          string
	param         string
	ret           string
}
type DefService struct {
	name    string
	rpcList []*DefRpc
}
type DefType struct {
	parentType string // "" or "xxx"
	def        string // "enum" or "message"
	name       string
	members    []*DefMember
}
type DefMember struct {
	typeName string
	name     string
	no       int
	tag      string // "" or "array"
}

type Parser struct {
	lexer         *Lexer
	v             string // "proto2" or "proto3"
	pkg           string
	types         []*DefType
	services      []*DefService
	typeCheckList []*Token
}

func newParser(lexer *Lexer) *Parser {
	p := &Parser{}
	p.lexer = lexer
	p.types = make([]*DefType, 0)
	p.services = make([]*DefService, 0)
	p.typeCheckList = make([]*Token, 0)
	return p
}

func ParseError(token *Token, m string) {
	log.Panicln(token.lineno, token.text, "ERR:", m)
}

func (p *Parser) isBasicType(tokenType int) bool {
	switch tokenType {
	case TOKEN_KEYWORD_DOUBLE, TOKEN_KEYWORD_FLOAT, TOKEN_KEYWORD_INT32,
		TOKEN_KEYWORD_INT64, TOKEN_KEYWORD_UINT32, TOKEN_KEYWORD_UINT64,
		TOKEN_KEYWORD_SINT32, TOKEN_KEYWORD_SINT64, TOKEN_KEYWORD_FIXED32,
		TOKEN_KEYWORD_FIXED64, TOKEN_KEYWORD_SFIXED32, TOKEN_KEYWORD_SFIXED64,
		TOKEN_KEYWORD_BOOL, TOKEN_KEYWORD_STRING, TOKEN_KEYWORD_BYTES:
		return true
	}
	return false
}

func (p *Parser) getDefType(name string) *DefType {
	for _, v := range p.types {
		if v.name == name {
			return v
		}
	}
	return nil
}

func (p *Parser) checkUnknownTypes() {
	for _, v := range p.typeCheckList {
		if p.isBasicType(v.tokenType) == false {
			if p.getDefType(v.text) == nil {
				ParseError(v, "unkonown type")
			}
		}
	}
}

func (p *Parser) printAll() {
	// print types
	for _, defType := range p.types {
		log.Printf("%s %s %s\n", defType.parentType, defType.def, defType.name)
		for _, defMember := range defType.members {
			log.Printf("	%s %s %s\n", defMember.tag, defMember.typeName, defMember.name)
		}
	}
	// print services
	for _, defService := range p.services {
		log.Printf("service %s\n", defService.name)
		for _, rpc := range defService.rpcList {
			if rpc.isParamStream && rpc.isRetStream {
				log.Printf("  %s (stream %s) (stream %s)\n", rpc.name, rpc.param, rpc.ret)
			} else if rpc.isParamStream {
				log.Printf("  %s (stream %s) (%s)\n", rpc.name, rpc.param, rpc.ret)
			} else if rpc.isRetStream {
				log.Printf("  %s (%s) (stream %s)\n", rpc.name, rpc.param, rpc.ret)
			} else {
				log.Printf("  %s (%s) (%s)\n", rpc.name, rpc.param, rpc.ret)
			}
		}
	}
}

func (p *Parser) checkToken(tokenType int) *Token {
	token := p.lexer.takeToken()
	if token.tokenType != tokenType {
		ParseError(token, "invalid syntax")
	}
	//log.Println("checkToken", token.lineno, token.text)
	return token
}

func (p *Parser) parse() {
	// 1. syntax token
	p.parse_syntax()

	// 2. package token
	p.parse_package()

	// 3. other tokens
	for {
		tokenType := p.lexer.nextTokenType()
		if tokenType == -1 {
			break
		}
		switch tokenType {
		case TOKEN_KEYWORD_ENUM:
			p.parse_enum("")
		case TOKEN_KEYWORD_MESSAGE:
			p.parse_message("")
		case TOKEN_KEYWORD_SERVICE:
			p.parse_service()
		default:
			ParseError(p.lexer.takeToken(), "proto error here")
		}
	}
	p.checkUnknownTypes()
	//p.printAll()
}

func (p *Parser) parse_syntax() {
	p.checkToken(TOKEN_KEYWORD_SYNTAX)   // syntax
	p.checkToken(TOKEN_ASSIGN)           // =
	p.checkToken(TOKEN_QUOTE)            // "
	syntax := p.checkToken(TOKEN_SYMBOL) // xxx
	p.checkToken(TOKEN_QUOTE)            // "
	p.checkToken(TOKEN_SEMICOLON)        // ;
	p.v = syntax.text
}

func (p *Parser) parse_package() {
	p.checkToken(TOKEN_KEYWORD_PACKAGE) // package
	pkg := p.checkToken(TOKEN_SYMBOL)   // xxx
	p.checkToken(TOKEN_SEMICOLON)       // ;
	p.pkg = pkg.text
}

func (p *Parser) parse_enum(parentType string) {
	//log.Println("parse_enum", parentType)
	p.checkToken(TOKEN_KEYWORD_ENUM)       // enum
	enumName := p.checkToken(TOKEN_SYMBOL) // xxx
	defType := &DefType{
		parentType: parentType,
		def:        "enum",
		name:       enumName.text,
		members:    make([]*DefMember, 0),
	}
	p.types = append(p.types, defType)
	p.checkToken(TOKEN_BRACE_LEFT) // {
	p.parse_enum_members(defType)
	p.checkToken(TOKEN_BRACE_RIGHT) // }
}

func (p *Parser) parse_enum_members(defType *DefType) {
	member := p.checkToken(TOKEN_SYMBOL) // xxx
	p.checkToken(TOKEN_ASSIGN)           // =
	no := p.checkToken(TOKEN_NUMBER)     // 1,2,3
	p.checkToken(TOKEN_SEMICOLON)        // ;
	num, _ := strconv.Atoi(no.text)
	defMember := &DefMember{
		typeName: "",
		name:     member.text,
		no:       num,
		tag:      "",
	}
	defType.members = append(defType.members, defMember)
	if p.lexer.nextTokenType() == TOKEN_SYMBOL {
		p.parse_enum_members(defType)
	}
}

func (p *Parser) parse_message(parentType string) {
	//log.Println("parse_message", parentType)
	p.checkToken(TOKEN_KEYWORD_MESSAGE)       // message
	messageName := p.checkToken(TOKEN_SYMBOL) // xxx
	defType := &DefType{
		parentType: parentType,
		def:        "message",
		name:       messageName.text,
		members:    make([]*DefMember, 0),
	}
	p.types = append(p.types, defType)
	p.checkToken(TOKEN_BRACE_LEFT) // {
	p.parse_message_members(defType)
	p.checkToken(TOKEN_BRACE_RIGHT) // }
}

func (p *Parser) parse_message_members(defType *DefType) {
	nextTokenType := p.lexer.nextTokenType()
	if nextTokenType == -1 {
		return
	}
	if p.v == "proto3" {
		switch nextTokenType {
		case TOKEN_KEYWORD_DOUBLE, TOKEN_KEYWORD_FLOAT, TOKEN_KEYWORD_INT32,
			TOKEN_KEYWORD_INT64, TOKEN_KEYWORD_UINT32, TOKEN_KEYWORD_UINT64,
			TOKEN_KEYWORD_SINT32, TOKEN_KEYWORD_SINT64, TOKEN_KEYWORD_FIXED32,
			TOKEN_KEYWORD_FIXED64, TOKEN_KEYWORD_SFIXED32, TOKEN_KEYWORD_SFIXED64,
			TOKEN_KEYWORD_BOOL, TOKEN_KEYWORD_STRING, TOKEN_KEYWORD_BYTES,
			TOKEN_SYMBOL, TOKEN_KEYWORD_REPEATED:
			tag := ""
			if nextTokenType == TOKEN_KEYWORD_REPEATED {
				tag = "array"
				p.checkToken(TOKEN_KEYWORD_REPEATED)
			}
			memberType := p.checkToken(p.lexer.nextTokenType()) // xxx
			p.typeCheckList = append(p.typeCheckList, memberType)
			member := p.checkToken(TOKEN_SYMBOL) // xxx
			p.checkToken(TOKEN_ASSIGN)           // =
			no := p.checkToken(TOKEN_NUMBER)     // 1,2,3
			p.checkToken(TOKEN_SEMICOLON)        // ;
			num, _ := strconv.Atoi(no.text)
			defMember := &DefMember{
				typeName: memberType.text,
				name:     member.text,
				no:       num,
				tag:      tag,
			}
			defType.members = append(defType.members, defMember)

		case TOKEN_KEYWORD_ENUM:
			p.parse_enum(defType.name)
		case TOKEN_KEYWORD_MESSAGE:
			p.parse_message(defType.name)
		// function end
		default:
			return
		}

	} else if p.v == "proto2" {

	}

	p.parse_message_members(defType)
}

func (p *Parser) parse_service() {
	//log.Println("parse_service")
	p.checkToken(TOKEN_KEYWORD_SERVICE)       // service
	serviceName := p.checkToken(TOKEN_SYMBOL) // xxx
	service := &DefService{
		name:    serviceName.text,
		rpcList: make([]*DefRpc, 0),
	}
	p.services = append(p.services, service)
	p.checkToken(TOKEN_BRACE_LEFT) // {
	p.parse_service_rpcs(service)
	p.checkToken(TOKEN_BRACE_RIGHT) // }
}

func (p *Parser) parse_service_rpcs(service *DefService) {
	if p.lexer.nextTokenType() != TOKEN_KEYWORD_RPC {
		return
	}
	p.checkToken(TOKEN_KEYWORD_RPC)       // rpc
	rpcName := p.checkToken(TOKEN_SYMBOL) //xxx
	p.checkToken(TOKEN_BRACKETS_LEFT)     // (

	isParamStream := false
	if p.lexer.nextTokenType() == TOKEN_KEYWORD_STREAM {
		p.checkToken(TOKEN_KEYWORD_STREAM) // stream
		isParamStream = true
	}
	paramType := p.checkToken(TOKEN_SYMBOL) // xxx
	p.checkToken(TOKEN_BRACKETS_RIGHT)      // )

	p.checkToken(TOKEN_KEYWORD_RETURNS) // returns

	p.checkToken(TOKEN_BRACKETS_LEFT) // (
	isRetStream := false
	if p.lexer.nextTokenType() == TOKEN_KEYWORD_STREAM {
		p.checkToken(TOKEN_KEYWORD_STREAM) // stream
		isRetStream = true
	}
	retType := p.checkToken(TOKEN_SYMBOL) // xxx
	p.checkToken(TOKEN_BRACKETS_RIGHT)    // )

	if p.lexer.nextTokenType() == TOKEN_BRACE_LEFT {
		p.checkToken(TOKEN_BRACE_LEFT)
		p.checkToken(TOKEN_BRACE_RIGHT)
	}

	p.checkToken(TOKEN_SEMICOLON) // ;

	p.typeCheckList = append(p.typeCheckList, paramType)
	p.typeCheckList = append(p.typeCheckList, retType)
	service.rpcList = append(service.rpcList, &DefRpc{
		name:          rpcName.text,
		isParamStream: isParamStream,
		isRetStream:   isRetStream,
		param:         paramType.text,
		ret:           retType.text,
	})

	p.parse_service_rpcs(service)
}


<|start_filename|>src/actors/actor_manager.go<|end_filename|>
package actors

import (
	"errors"
	"fmt"
	"log"
	"reflect"
	"sync"
)

var (
	_actorManager actorManager
	_once         sync.Once
)

func Init() {
	_once.Do(func() { _actorManager.init() })
}

func NewActor(host ActorHost) int32 {
	actorId := _actorManager.createActor(host)
	return actorId
}

func FreeActor(actorId int32) {
	_actorManager.freeActor(actorId)
}

func Call(actorId int32, function interface{}, params ...interface{}) error {
	currActor, ok := _actorManager.getActor(actorId)
	if !ok {
		log.Println("ERR: no actor find for ", actorId)
		return errors.New(fmt.Sprintf("ERR: no actor find for %d", actorId))
	}
	callRetChan := make(chan *actorCallRet, 0)
	err := currActor.putCall(callRetChan, function, params...)
	if err != nil {
		return err
	}
	callRet, ok := <-callRetChan
	if !ok {
		return errors.New("ret chan error")
	}
	// check results validation
	funcT := reflect.TypeOf(function)
	if len(callRet.results) != 1 {
		return errors.New("Call return must be error")
	}
	if callRet.results[0].IsNil() == false {
		if callRet.results[0].Type().AssignableTo(funcT.Out(0)) == false {
			return errors.New("dest call function first return type is wrong")
		}
	}
	return nil
}

func AsynCall(actorId int32, function interface{}, params ...interface{}) error {
	currActor, ok := _actorManager.getActor(actorId)
	if !ok {
		log.Println("ERR: no actor find for ", actorId)
		return errors.New(fmt.Sprintf("ERR: no actor find for %d", actorId))
	}
	err := currActor.putAsynCall(nil, function, params...)
	if err != nil {
		return err
	}
	return nil
}

type actorManager struct {
	count  int32
	actors sync.Map
}

func (m *actorManager) init() {
	m.count = 0
}

func (m *actorManager) assignId() int32 {
	if m.count >= (1<<31 - 10) {
		m.count = 0
	}
	m.count += 1
	return m.count
}

func (m *actorManager) createActor(host ActorHost) int32 {
	actorId := m.assignId()
	currActor := &Actor{
		actorId: actorId,
		host:    host,
	}
	currActor.init(actorId, host)
	m.actors.Store(actorId, currActor)
	return actorId
}

func (m *actorManager) getActor(actorId int32) (*Actor, bool) {
	currActor, ok := m.actors.Load(actorId)
	if ok {
		return currActor.(*Actor), true
	}
	return nil, false
}

func (m *actorManager) freeActor(actorId int32) {
	currActor, ok := m.actors.Load(actorId)
	if ok {
		currActor.(*Actor).exit()
		m.actors.Delete(actorId)
	}
}


<|start_filename|>src/tools/test/main.go<|end_filename|>
package main

import (
	"log"
)

type Person struct {
	name string
}

func (p *Person) PrintName() {
	log.Println("this is persion")
}

func (p *Person) PrintAge() {
	log.Println("persion age")
}

type Coder struct {
	Person
}

func (c *Coder) PrintName() {
	log.Println("this is coder")
}

func main() {
	coder := Coder{}

	coder.PrintName()
	coder.PrintAge()
}


<|start_filename|>src/types/errors.go<|end_filename|>
package types

import (
	"errors"
)

var (
	ERR_NO_SESSION         = errors.New("ERR_NO_SESSION")
	ERR_NO_SERVICE         = errors.New("ERR_NO_SERVICE")
	ERR_NO_SERVICE_CLIENT  = errors.New("ERR_NO_SERVICE_CLIENT")
	ERR_INVALID_SERVICE_ID = errors.New("ERR_INVALID_SERVICE_ID")
)


<|start_filename|>src/events/events.go<|end_filename|>
package events

import (
	"log"
	"net"

	"github.com/nsqio/go-nsq"
)

type EventCB func([]byte)

type consumerHandler struct {
	eventCB EventCB
}

func (h *consumerHandler) HandleMessage(message *nsq.Message) error {
	h.eventCB(message.Body)
	return nil
}

type EventManager struct {
	producer  *nsq.Producer
	consumers map[string]*nsq.Consumer
	addr      string
}

var defaultEventManager EventManager

func Init(addr string) {
	config := nsq.NewConfig()
	config.LocalAddr, _ = net.ResolveTCPAddr("tcp", addr+":0")
	producer, _ := nsq.NewProducer(addr, config)
	defaultEventManager.consumers = make(map[string]*nsq.Consumer, 0)
	defaultEventManager.producer = producer
	defaultEventManager.addr = addr
}

func Register(topic string, channel string, eventCB EventCB) {
	key := topic + channel
	config := nsq.NewConfig()
	consumer, _ := nsq.NewConsumer(topic, channel, config)
	handler := &consumerHandler{
		eventCB: eventCB,
	}
	consumer.AddHandler(handler)
	err := consumer.ConnectToNSQD(defaultEventManager.addr)
	if err != nil {
		log.Fatal(err)
	}
	preConsumer, ok := defaultEventManager.consumers[key]
	if ok {
		preConsumer.Stop()
	}
	defaultEventManager.consumers[key] = consumer
}

func Unregister(topic string, channel string) {
	key := topic + channel
	consumer, ok := defaultEventManager.consumers[key]
	if ok {
		consumer.Stop()
	}
	delete(defaultEventManager.consumers, key)
}

func Publish(topic string, eventData []byte) {
	err := defaultEventManager.producer.Publish(topic, eventData)
	if err != nil {
		log.Fatal(err)
	}
}


<|start_filename|>src/pb/template/template_rpc.gen.go<|end_filename|>
// DOT NOT EDIT THIS FILE, AUTO GEN!!
package template

import (
	"context"
	"errors"
)

type GrpcServer struct {
}

func (s *GrpcServer) Test(ctx context.Context, param *TestParam) (*TestRet, error) {
	return nil, errors.New("this api not support")
}



<|start_filename|>src/examples/test_reflect.go<|end_filename|>
package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Name string
}

type User2 struct {
	Name string
}

func (u *User) Hello() {
	fmt.Println("hello")
}
func (u *User) Hello2(a int, s string) string {
	fmt.Println("hello")
	return ""
}
func (u *User) ShakeHand(name string) {
	fmt.Printf("Shake hand with %s\n", name)
}
func main() {
	//user1 := &User{Name: "xxxx"}
	funcT := (*User).Hello

	fmt.Println("user1 func pointer:", reflect.ValueOf(funcT).Pointer())
	fmt.Println("f string:", reflect.TypeOf(funcT))

	user2 := &User{Name: "xxxx"}
	funcT2 := (*User).Hello
	fmt.Println("user2 func's struct:", reflect.TypeOf(funcT2).In(0))
	fmt.Println("user2 func pointer:", reflect.ValueOf(funcT2).Pointer())
	//user2 := user1
	v := reflect.ValueOf(user2)
	//t := v.Type()
	t := reflect.TypeOf(user2)
	fmt.Println("use 2 type name", t.String())
	user3 := &User2{}
	if reflect.TypeOf(funcT2).In(0) == reflect.TypeOf(user3) {
		fmt.Println("===")
	}
	for i := 0; i < v.NumMethod(); i++ {
		//fmt.Printf("method[%d]%s\n", i, t.Method(i).Name)
		fmt.Println(t.Method(i).Name, "func name:", t.Method(i).Func.Pointer())
	}
}


<|start_filename|>src/servers/template_s/user.go<|end_filename|>
package main

import (
	"log"
)

import (
	"actors"
	"pb/template"
)

type User struct {
	actors.BaseActorHost
	userId      string
	out         chan interface{}
	streamCodec string
}

func NewUser(userId string, out chan interface{}) *User {
	user := &User{
		userId: userId,
		out:    out,
	}
	actors.NewActor(user)
	return user
}

func (u *User) SetOutChan(out chan interface{}) {
	u.out = out
}

func (u *User) HandleMessages(name string, msg interface{}) {
	switch name {
	case "template.TemplateMsgTest":
		msgTemplateMsgTest := template.ToTemplateMsgTest(msg)
		if msgTemplateMsgTest == nil {
			log.Fatalln("type error")
		}
		log.Println(msgTemplateMsgTest.I, msgTemplateMsgTest.S)
		u.SendMessage(&template.TemplateMsgTestAck{
			IntList: []int32{1, 2, 3, 4},
			StrList: []string{"aa", "bb"},
		})
	}
}

func (u *User) SendMessage(message interface{}) {
	if u.out == nil {
		return
	}
	u.out <- message
	/*
		msgId := services.ToMsgId(name)
		data, _ := EncodeMessage(u.streamCodec, name, message)
		u.stream.Send(&pb.StreamFrame{
			Type:    pb.StreamFrameType_Message,
			Codec:   u.streamCodec,
			MsgId:   int32(msgId),
			MsgData: data,
		})
	*/
}


<|start_filename|>src/pb/template/template_msg.pb.go<|end_filename|>
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pb/template/template_msg.proto

package template

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type TemplateMsgTest struct {
	I                    int32    `protobuf:"varint,1,opt,name=i,proto3" json:"i,omitempty"`
	S                    string   `protobuf:"bytes,2,opt,name=s,proto3" json:"s,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *TemplateMsgTest) Reset()         { *m = TemplateMsgTest{} }
func (m *TemplateMsgTest) String() string { return proto.CompactTextString(m) }
func (*TemplateMsgTest) ProtoMessage()    {}
func (*TemplateMsgTest) Descriptor() ([]byte, []int) {
	return fileDescriptor_template_msg_ddd9db27993ceaa4, []int{0}
}
func (m *TemplateMsgTest) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_TemplateMsgTest.Unmarshal(m, b)
}
func (m *TemplateMsgTest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_TemplateMsgTest.Marshal(b, m, deterministic)
}
func (dst *TemplateMsgTest) XXX_Merge(src proto.Message) {
	xxx_messageInfo_TemplateMsgTest.Merge(dst, src)
}
func (m *TemplateMsgTest) XXX_Size() int {
	return xxx_messageInfo_TemplateMsgTest.Size(m)
}
func (m *TemplateMsgTest) XXX_DiscardUnknown() {
	xxx_messageInfo_TemplateMsgTest.DiscardUnknown(m)
}

var xxx_messageInfo_TemplateMsgTest proto.InternalMessageInfo

func (m *TemplateMsgTest) GetI() int32 {
	if m != nil {
		return m.I
	}
	return 0
}

func (m *TemplateMsgTest) GetS() string {
	if m != nil {
		return m.S
	}
	return ""
}

type TemplateMsgTestAck struct {
	IntList              []int32  `protobuf:"varint,1,rep,packed,name=intList,proto3" json:"intList,omitempty"`
	StrList              []string `protobuf:"bytes,2,rep,name=strList,proto3" json:"strList,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *TemplateMsgTestAck) Reset()         { *m = TemplateMsgTestAck{} }
func (m *TemplateMsgTestAck) String() string { return proto.CompactTextString(m) }
func (*TemplateMsgTestAck) ProtoMessage()    {}
func (*TemplateMsgTestAck) Descriptor() ([]byte, []int) {
	return fileDescriptor_template_msg_ddd9db27993ceaa4, []int{1}
}
func (m *TemplateMsgTestAck) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_TemplateMsgTestAck.Unmarshal(m, b)
}
func (m *TemplateMsgTestAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_TemplateMsgTestAck.Marshal(b, m, deterministic)
}
func (dst *TemplateMsgTestAck) XXX_Merge(src proto.Message) {
	xxx_messageInfo_TemplateMsgTestAck.Merge(dst, src)
}
func (m *TemplateMsgTestAck) XXX_Size() int {
	return xxx_messageInfo_TemplateMsgTestAck.Size(m)
}
func (m *TemplateMsgTestAck) XXX_DiscardUnknown() {
	xxx_messageInfo_TemplateMsgTestAck.DiscardUnknown(m)
}

var xxx_messageInfo_TemplateMsgTestAck proto.InternalMessageInfo

func (m *TemplateMsgTestAck) GetIntList() []int32 {
	if m != nil {
		return m.IntList
	}
	return nil
}

func (m *TemplateMsgTestAck) GetStrList() []string {
	if m != nil {
		return m.StrList
	}
	return nil
}

type TemplateMsgTestNtf struct {
	IntList              []int32  `protobuf:"varint,1,rep,packed,name=intList,proto3" json:"intList,omitempty"`
	StrList              []string `protobuf:"bytes,2,rep,name=strList,proto3" json:"strList,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *TemplateMsgTestNtf) Reset()         { *m = TemplateMsgTestNtf{} }
func (m *TemplateMsgTestNtf) String() string { return proto.CompactTextString(m) }
func (*TemplateMsgTestNtf) ProtoMessage()    {}
func (*TemplateMsgTestNtf) Descriptor() ([]byte, []int) {
	return fileDescriptor_template_msg_ddd9db27993ceaa4, []int{2}
}
func (m *TemplateMsgTestNtf) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_TemplateMsgTestNtf.Unmarshal(m, b)
}
func (m *TemplateMsgTestNtf) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_TemplateMsgTestNtf.Marshal(b, m, deterministic)
}
func (dst *TemplateMsgTestNtf) XXX_Merge(src proto.Message) {
	xxx_messageInfo_TemplateMsgTestNtf.Merge(dst, src)
}
func (m *TemplateMsgTestNtf) XXX_Size() int {
	return xxx_messageInfo_TemplateMsgTestNtf.Size(m)
}
func (m *TemplateMsgTestNtf) XXX_DiscardUnknown() {
	xxx_messageInfo_TemplateMsgTestNtf.DiscardUnknown(m)
}

var xxx_messageInfo_TemplateMsgTestNtf proto.InternalMessageInfo

func (m *TemplateMsgTestNtf) GetIntList() []int32 {
	if m != nil {
		return m.IntList
	}
	return nil
}

func (m *TemplateMsgTestNtf) GetStrList() []string {
	if m != nil {
		return m.StrList
	}
	return nil
}

func init() {
	proto.RegisterType((*TemplateMsgTest)(nil), "template.TemplateMsgTest")
	proto.RegisterType((*TemplateMsgTestAck)(nil), "template.TemplateMsgTestAck")
	proto.RegisterType((*TemplateMsgTestNtf)(nil), "template.TemplateMsgTestNtf")
}

func init() {
	proto.RegisterFile("pb/template/template_msg.proto", fileDescriptor_template_msg_ddd9db27993ceaa4)
}

var fileDescriptor_template_msg_ddd9db27993ceaa4 = []byte{
	// 149 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x48, 0xd2, 0x2f,
	0x49, 0xcd, 0x2d, 0xc8, 0x49, 0x2c, 0x49, 0x85, 0x33, 0xe2, 0x73, 0x8b, 0xd3, 0xf5, 0x0a, 0x8a,
	0xf2, 0x4b, 0xf2, 0x85, 0x38, 0x60, 0x62, 0x4a, 0xba, 0x5c, 0xfc, 0x21, 0x50, 0xb6, 0x6f, 0x71,
	0x7a, 0x48, 0x6a, 0x71, 0x89, 0x10, 0x0f, 0x17, 0x63, 0xa6, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x6b,
	0x10, 0x63, 0x26, 0x88, 0x57, 0x2c, 0xc1, 0xa4, 0xc0, 0xa8, 0xc1, 0x19, 0xc4, 0x58, 0xac, 0xe4,
	0xc1, 0x25, 0x84, 0xa6, 0xdc, 0x31, 0x39, 0x5b, 0x48, 0x82, 0x8b, 0x3d, 0x33, 0xaf, 0xc4, 0x27,
	0xb3, 0xb8, 0x44, 0x82, 0x51, 0x81, 0x59, 0x83, 0x35, 0x08, 0xc6, 0x05, 0xc9, 0x14, 0x97, 0x14,
	0x81, 0x65, 0x98, 0x14, 0x98, 0x35, 0x38, 0x83, 0x60, 0x5c, 0x2c, 0x26, 0xf9, 0x95, 0xa4, 0x91,
	0x63, 0x52, 0x12, 0x1b, 0xd8, 0x4f, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe5, 0x76, 0x96,
	0xf7, 0xf5, 0x00, 0x00, 0x00,
}


<|start_filename|>src/servers/gate_s/main.go<|end_filename|>
package main

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

import (
	"pb/gate"
	"services"
	"utils"

	"github.com/gorilla/websocket"
	//log "github.com/sirupsen/logrus"
)

type Config struct {
	Test string
	List []int
	Hash map[string]string
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func main() {
	/*
			testArray2 := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
			testArray2[0] = 99
			log.Println(testArray2)

			var testArray []int = make([]int, 0)
			//testArray[0] = 100
			testArray = append(testArray, 10)
			testArray = append(testArray, 20)
			testArray = append(testArray, 30)
			testArray = append(testArray, 40)
			testArray = append(testArray, 5)

			testArray = append(testArray[:1], testArray[2:]...)

			for i := 0; i < len(testArray); i++ {
				log.Println("slice:", testArray[i])
			}
			for i, v := range testArray {
				log.Println("range:", i, v)
			}
			log.Println(testArray)

			var testHash map[string]int
			if testHash == nil {
				log.Println("map is nil. Going to make one.")
				testHash = make(map[string]int, 0)
			}
			testHash["test_key2"] = 678
			testHash["test_key"] = 908
			for k, v := range testHash {
				log.Println(k, v)
			}

			testHash2 := make(map[string]int, 0)
			testHash2["test_key2"] = 111
			testHash2["test_key"] = 222
			testHash2["k"] = 222
			log.Println(testHash2)
			delete(testHash2, "k")
			log.Println(testHash2)
			for k, v := range testHash2 {
				log.Println(k, v)
			}

			log.Println("test_key", testHash)

			var testInt int
			log.Println("testInt:", testInt)
			log.Println("_test_global:", _test_global)
			var c Config
			c.Test = "test c"
			log.Println("test:", c.Test)

			d := Config{}
			d.Test = "test d"
			log.Println("test:", d.Test)
			d.List = append(d.List, 456)
			log.Println("test:", d.List)

			e := &Config{Test: "test e"}
			log.Println("test:", e.Test)

			f := new(Config)
			f.Test = "test f"
			log.Println("test:", f.Test)

		uuid := utils.CreateUUID()
		log.Println("uuid:", uuid)
		b64 := utils.Base64EncodeV2(uuid)
		log.Println("base64v2:", b64)
		reb64 := utils.Base64DecodeV2(b64)
		log.Println("base64decodev2", reb64)

		reb64_2 := utils.Base64DecodeV1(b64)
		log.Println("base64Decodev1", reb64_2)
	*/
	currServiceAddr := "127.0.0.1:9999"
	currServiceId := utils.CreateServiceId("gate", currServiceAddr)

	//ctx := context.WithValue(context.Background(), "curr_service_id", currServiceId)
	//ctx = context.WithValue(ctx, "curr_service_addr", currServiceAddr)
	ctx := context.Background()
	services.Register(ctx, &services.ServiceConf{
		ServiceType:    "gate",
		ServiceId:      currServiceId,
		ServiceAddr:    currServiceAddr,
		IsStream:       false,
		ProtoUseList:   gate.GetProtoUseList(),
		ServiceUseList: []string{"auth", "template"},
		TTL:            4,
	})
	go httpServer(nil)
	select {}
}

func httpServer(config *Config) {
	http.HandleFunc("/httpGate", httpHandler)
	http.HandleFunc("/wsGate", wsHandler)
	log.Println("start http server listen on 12345 ...")
	//err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
	err := http.ListenAndServe(":12345", nil)
	log.Fatal(err)
	fmt.Println("exit httpServer")
}

func httpHandler(w http.ResponseWriter, req *http.Request) {
	log.Println("New Http Connection")
	if req.Method != "POST" {
		w.Write([]byte("Only Support Post Method!"))
		return
	}
	body, _ := ioutil.ReadAll(req.Body)
	if len(body) == 0 {
		w.Write([]byte("Post Data Is Blank"))
		return
	}
	sessId := ""
	vars := req.URL.Query()
	if vars["sessId"] != nil {
		sessId = vars["sessId"][0]
	}

	log.Println("sessId:", sessId)
	ctx, cancel := context.WithCancel(context.Background())
	defer func() {
		cancel()
	}()
	agent := newAgent(sessId, func(data []byte) error {
		_, err := w.Write(data)
		cancel()
		return err
	})
	agent.start(ctx)
	defer freeAgent(agent)

	log.Printf("body:%s\n", body)
	agent.toService(body)
	select {
	case <-ctx.Done():
	}
}

func wsHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("ws connection")
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println(err)
		return
	}
	go handleWsClient(conn, nil)
}

func handleWsClient(conn *websocket.Conn, config *Config) {
	log.Println("New Websocket Connection")
	ctx, cancel := context.WithCancel(context.Background())
	sessId := ""
	agent := newAgent(sessId, func(data []byte) error {
		messageType := websocket.TextMessage
		err := conn.WriteMessage(messageType, data)
		return err
	})
	agent.start(ctx)

	// receive client message loop
	defer func() {
		conn.Close()
		cancel()
		freeAgent(agent)
		log.Printf("webscocket connection closed")
	}()

	for {
		// messageType is websocket.BinaryMessage or websocket.TextMessage.
		// message is a []byte
		messageType, message, err := conn.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}
		switch messageType {
		case websocket.TextMessage:
		case websocket.BinaryMessage:
			agent.toService(message)
		case websocket.CloseMessage:
		case websocket.PingMessage:
		case websocket.PongMessage:
		}
	}
}


<|start_filename|>src/servers/template_s/main.go<|end_filename|>
package main

import (
	"context"
	"log"
	"net"
	"os"
)

import (
	"pb"
	"pb/template"
	"services"
	"utils"

	"google.golang.org/grpc"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	server := &Server{}
	server.Init(ctx)

	serviceAddr := "127.0.0.1:9990"
	serviceId := utils.CreateServiceId("template", serviceAddr)

	lis, err := net.Listen("tcp", serviceAddr)
	if err != nil {
		log.Fatal(err)
		os.Exit(-1)
	}
	log.Println("Listen on", lis.Addr())

	s := grpc.NewServer()
	pb.RegisterStreamServer(s, server)
	template.RegisterTemplateServer(s, server)

	services.Register(context.Background(), &services.ServiceConf{
		ServiceType:    "template",
		ServiceId:      serviceId,
		ServiceAddr:    serviceAddr,
		IsStream:       true,
		ProtoUseList:   template.GetProtoUseList(),
		ServiceUseList: []string{},
		TTL:            4,
	})
	s.Serve(lis)

	defer func() {
		cancel()
	}()
	select {}
}


<|start_filename|>src/servers/auth_s/server.go<|end_filename|>
package main

import (
	"context"
	//"errors"
	"log"
	"reflect"
	"sync"
)
import (
	"actors"
	"pb"
	"pb/auth"
	"services"

	"google.golang.org/grpc/metadata"
)

type Server struct {
	auth.GrpcServer
	users sync.Map
}

func (s *Server) Init(ctx context.Context) {
}

func (s *Server) CreateUser(userId string, out chan interface{}) *User {
	user, ok := s.GetUser(userId)
	if !ok {
		user = NewUser(userId, out)
		s.users.Store(userId, user)
	}
	return user
}

func (s *Server) GetUser(userId string) (*User, bool) {
	user, ok := s.users.Load(userId)
	if !ok {
		return nil, false
	}
	return user.(*User), true
}

// ------------------------------------- grpc api -------------------------------------
func (s *Server) CreateStream(stream pb.Stream_CreateStreamServer) error {
	log.Println("new stream is coming..")
	meta, _ := metadata.FromIncomingContext(stream.Context())
	userId := meta["user-id"][0]
	codec := meta["codec"][0]
	out := make(chan interface{}, 1000)
	user := s.CreateUser(userId, out)

	go func() {
		for {
			select {
			case outMsg := <-out:
				msgName := reflect.TypeOf(outMsg)
				msgId := services.ToMsgId(msgName.String())
				data, _ := auth.EncodeMessage(codec, outMsg)
				stream.Send(&pb.StreamFrame{
					Type:    pb.StreamFrameType_Message,
					Codec:   codec,
					MsgId:   int32(msgId),
					MsgData: data,
				})
			case <-stream.Context().Done():
				return
			}
		}
	}()

	defer func() {
		close(out)
	}()

	// receive loop
	for {
		frame, err := stream.Recv()
		if err != nil {
			log.Println(err)
			return err
		}
		codec := frame.Codec
		msgName := services.ToMsgName(uint32(frame.MsgId))
		msgData := frame.MsgData
		msg, decodeErr := auth.DecodeMessage(codec, msgName, msgData)
		if decodeErr != nil {
			log.Println(decodeErr)
		} else {
			actors.AsynCall(user.ActorId(), (*User).HandleMessages, msgName, msg)
		}

		switch frame.Type {
		case pb.StreamFrameType_Message:
		case pb.StreamFrameType_Ping:
		case pb.StreamFrameType_Kick:
		}
	}
	return nil
}

func (s *Server) Login(ctx context.Context, param *auth.LoginParam) (*auth.LoginRet, error) {
	log.Println("Login")
	//return nil, errors.New("this api not support")
	return &auth.LoginRet{Error: "ok", UserId: 100000}, nil
}


<|start_filename|>src/services/services.go<|end_filename|>
package services

import (
	"context"
	"encoding/json"
	"log"
	"path/filepath"
	"sync"
	"time"
)

import (
	"types"
	"utils"

	etcdclient "github.com/coreos/etcd/client"
	"google.golang.org/grpc"
)

// https://github.com/letmefly/ant/blob/master/samples/template/sdk/rpc.gen.go

type ServiceConf struct {
	ServiceType    string   `json:"serviceType"`
	ServiceId      string   `json:"serviceId"`
	ServiceAddr    string   `json:"serviceAddr"`
	ServiceUseList []string `json:"serviceUseList"`
	ProtoUseList   []string `json:protoUseList`
	IsStream       bool     `json:"isStream"`
	TTL            int      `json:"ttl"`
}

type ServiceClient struct {
	use  int
	Conn *grpc.ClientConn
	Conf *ServiceConf
}

type RecvHandler func([]byte) error
type ServiceBundle struct {
	serviceType string
	//handlers       map[string]RecvHandler    // (sessId, handler)
	serviceClients map[string]*ServiceClient // (serviceId, ClientConn)
}

func newServiceBundle(serviceType string) *ServiceBundle {
	s := &ServiceBundle{
		serviceType: serviceType,
		//handlers:       make(map[string]RecvHandler, 0),
		serviceClients: make(map[string]*ServiceClient, 0),
	}
	return s
}

/*
func (s *ServiceBundle) AddRecvHandler(owner string, handler RecvHandler) {
	s.handlers[owner] = handler
}

func (s *ServiceBundle) Call(owner string, data []byte) ([]byte, error) {
	return nil, nil
}
*/

type ServiceManager struct {
	servicesRoot     string
	onlineServices   map[string]*ServiceConf
	serviceBundleMap map[string]*ServiceBundle
	toServiceTypeMap map[uint32]string // msgId to service type
	toMsgNameMap     map[uint32]string // msgId to msgName
	toMsgIdMap       map[string]uint32 // msgName 2 msgId
	currServiceConf  *ServiceConf
	etcdcli          etcdclient.Client
	mu               *sync.RWMutex
}

func (m *ServiceManager) init(ctx context.Context, conf *ServiceConf) {
	m.currServiceConf = conf
	m.onlineServices = make(map[string]*ServiceConf, 0)
	m.serviceBundleMap = make(map[string]*ServiceBundle, 0)
	m.toServiceTypeMap = make(map[uint32]string, 0)
	m.toMsgNameMap = make(map[uint32]string, 0)
	m.toMsgIdMap = make(map[string]uint32, 0)
	m.mu = new(sync.RWMutex)
	m.servicesRoot = "/serviceList/"

	cfg := etcdclient.Config{
		Endpoints:               []string{"http://127.0.0.1:2379"},
		Transport:               etcdclient.DefaultTransport,
		HeaderTimeoutPerRequest: 3 * time.Second,
	}

	cli, err := etcdclient.New(cfg)
	if err != nil {
		log.Println("etcdclient new fail")
		log.Fatal(err)
	}
	m.etcdcli = cli
	m.registerMyself(ctx)
	m.fetchOnlineServices(ctx)
	m.addOtherServices(ctx)
	go m.watchOnlineServices(ctx)

}

func (m *ServiceManager) registerMyself(ctx context.Context) {
	str, err := json.Marshal(m.currServiceConf)
	if err != nil {
		log.Fatal(err)
		return
	}
	kapi := etcdclient.NewKeysAPI(m.etcdcli)
	_, err1 := kapi.Set(ctx, m.servicesRoot+m.currServiceConf.ServiceId, string(str), &etcdclient.SetOptions{TTL: time.Duration(m.currServiceConf.TTL) * time.Second})
	if err1 != nil {
		log.Fatal(err1)
	}

	go func() {
		for {
			time.Sleep(time.Second * time.Duration(int(m.currServiceConf.TTL/2)))
			_, err2 := kapi.Set(ctx, m.servicesRoot+m.currServiceConf.ServiceId, "", &etcdclient.SetOptions{Refresh: true, TTL: time.Duration(m.currServiceConf.TTL) * time.Second})
			if err2 != nil {
				log.Fatal(err2)
				return
			}
		}
	}()
}

func (m *ServiceManager) fetchOnlineServices(ctx context.Context) {
	kapi := etcdclient.NewKeysAPI(m.etcdcli)
	ret, err := kapi.Get(ctx, m.servicesRoot, nil)
	if err != nil {
		log.Fatal(err)
	}
	if !ret.Node.Dir {
		log.Fatal("No Services Dir in Etcd")
	}
	for _, node := range ret.Node.Nodes {
		serviceId := filepath.Base(node.Key)
		confStr := node.Value
		log.Println(serviceId, confStr)
		serviceConf := ServiceConf{}
		json.Unmarshal([]byte(confStr), &serviceConf)
		m.onlineServices[serviceId] = &serviceConf
	}
}

func (m *ServiceManager) watchOnlineServices(ctx context.Context) {
	kapi := etcdclient.NewKeysAPI(m.etcdcli)
	watcher := kapi.Watcher(m.servicesRoot, &etcdclient.WatcherOptions{Recursive: true})
	for {
		r, err := watcher.Next(ctx)
		if err != nil {
			log.Println(err)
			return
		}

		switch r.Action {
		case "set", "create", "update", "compareAndSwap":
			serviceId := filepath.Base(r.Node.Key)
			confStr := r.Node.Value
			conf := &ServiceConf{}
			json.Unmarshal([]byte(confStr), conf)
			m.addService(serviceId, conf)
			log.Println("update:", serviceId)
		case "delete", "expire":
			serviceId := filepath.Base(r.Node.Key)
			log.Println("delete:", serviceId)
			m.removeService(serviceId)
		}
	}
}

func (m *ServiceManager) isUse(serviceType string) bool {
	for _, v := range m.currServiceConf.ServiceUseList {
		if v == serviceType || v == "*" {
			return true
		}
	}
	return false
}

// only connect services that diffient from current service type
func (m *ServiceManager) addOtherServices(ctx context.Context) {
	for serviceId, conf := range m.onlineServices {
		m.addService(serviceId, conf)
	}
}

func (m *ServiceManager) addService(serviceId string, conf *ServiceConf) {
	m.mu.Lock()
	defer m.mu.Unlock()
	serviceAddr := conf.ServiceAddr
	serviceType := conf.ServiceType

	m.createTLB(conf)
	if conf.ServiceType == m.currServiceConf.ServiceType {
		return
	}

	if !m.isUse(conf.ServiceType) {
		log.Println(conf.ServiceType, "no use")
		return
	}
	m.onlineServices[serviceId] = conf
	serviceBundle, ok1 := m.serviceBundleMap[serviceType]
	if !ok1 {
		m.serviceBundleMap[serviceType] = newServiceBundle(serviceType)
		serviceBundle = m.serviceBundleMap[serviceType]
	}

	// this service has been connected
	if _, ok2 := serviceBundle.serviceClients[serviceId]; ok2 {
		return
	}

	log.Println("[services] add service ", serviceId, "->", serviceAddr, "trying")
	conn, err := grpc.Dial(serviceAddr, grpc.WithBlock(), grpc.WithInsecure())
	if err != nil {
		log.Println(err)
		return
	}
	serviceBundle.serviceClients[serviceId] = &ServiceClient{Conn: conn, use: 0, Conf: conf}

	log.Println("[services] add service ", serviceId, "->", serviceAddr, "success")
}

func (m *ServiceManager) removeService(serviceId string) {
	m.mu.Lock()
	defer m.mu.Unlock()
	conf, ok1 := m.onlineServices[serviceId]
	if !ok1 {
		return
	}
	serviceType := conf.ServiceType
	serviceBundle, ok2 := m.serviceBundleMap[serviceType]
	if !ok2 {
		return
	}
	serviceClient, ok3 := serviceBundle.serviceClients[serviceId]
	if !ok3 {
		return
	}
	serviceClient.Conn.Close()
	delete(serviceBundle.serviceClients, serviceId)
	delete(m.onlineServices, serviceId)
	m.deleteTLB(conf)
	log.Println("[services] remvoe service ", serviceId, "success")
}

func (m *ServiceManager) createTLB(conf *ServiceConf) {
	for _, v := range conf.ProtoUseList {
		msgName := conf.ServiceType + "." + v
		msgId := utils.HashCode(msgName)
		m.toMsgIdMap[msgName] = msgId
		m.toMsgNameMap[msgId] = msgName
		m.toServiceTypeMap[msgId] = conf.ServiceType
		log.Println("msgName", msgName, "msgId", msgId)
	}
}

func (m *ServiceManager) deleteTLB(conf *ServiceConf) {
	for _, v := range conf.ProtoUseList {
		msgName := v
		msgId := utils.HashCode(conf.ServiceType + "." + msgName)
		delete(m.toMsgIdMap, msgName)
		delete(m.toMsgNameMap, msgId)
		delete(m.toServiceTypeMap, msgId)
	}
}

func (m *ServiceManager) assignServiceId(serviceType string) (string, error) {
	m.mu.Lock()
	defer m.mu.Unlock()
	serviceBundle, ok := m.serviceBundleMap[serviceType]
	if !ok {
		return "", types.ERR_NO_SERVICE
	}
	tmpId, tmpUse := "", int(^uint(0)>>1)
	for k, v := range serviceBundle.serviceClients {
		item := v
		if item.use < tmpUse {
			tmpUse = item.use
			tmpId = k
		}
	}
	serviceBundle.serviceClients[tmpId].use += 1
	return tmpId, nil
}

func (m *ServiceManager) unassignServiceId(serviceId string) {
	m.mu.Lock()
	defer m.mu.Unlock()
	serviceType := utils.GetServiceType(serviceId)
	if serviceType == "" {
		return
	}
	serviceBundle, ok1 := m.serviceBundleMap[serviceType]
	if !ok1 {
		return
	}
	serviceClient, ok2 := serviceBundle.serviceClients[serviceId]
	if !ok2 {
		return
	}
	serviceClient.use -= 1
}

func (m *ServiceManager) getServiceClient(serviceId string) (*ServiceClient, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()
	serviceType := utils.GetServiceType(serviceId)
	if serviceType == "" {
		return nil, types.ERR_INVALID_SERVICE_ID
	}
	serviceBundle, ok1 := m.serviceBundleMap[serviceType]
	if !ok1 {
		return nil, types.ERR_NO_SERVICE
	}
	serviceClient, ok2 := serviceBundle.serviceClients[serviceId]
	if !ok2 {
		return nil, types.ERR_NO_SERVICE_CLIENT
	}
	return serviceClient, nil
}

var (
	_service_manager ServiceManager
	_once            sync.Once
)

// services module init
func Register(ctx context.Context, conf *ServiceConf) {
	_once.Do(func() { _service_manager.init(ctx, conf) })
}

func GetServiceUseList() []string {
	conf := _service_manager.currServiceConf
	return conf.ServiceUseList
}

func AssignServiceId(serviceType string) (string, error) {
	return _service_manager.assignServiceId(serviceType)
}

func UnassignServiceId(serviceId string) {
	_service_manager.unassignServiceId(serviceId)
}

func GetServiceClient(serviceId string) (*ServiceClient, error) {
	return _service_manager.getServiceClient(serviceId)
}

func ToServiceType(msgId uint32) string {
	_service_manager.mu.RLock()
	defer _service_manager.mu.RUnlock()
	return _service_manager.toServiceTypeMap[msgId]
}

func ToMsgName(msgId uint32) string {
	_service_manager.mu.RLock()
	defer _service_manager.mu.RUnlock()
	return _service_manager.toMsgNameMap[msgId]
}

func ToMsgId(msgName string) uint32 {
	_service_manager.mu.RLock()
	defer _service_manager.mu.RUnlock()
	return _service_manager.toMsgIdMap[msgName]
}


<|start_filename|>src/pb/gate/gate_rpc.pb.go<|end_filename|>
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pb/gate/gate_rpc.proto

package gate

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

import (
	context "golang.org/x/net/context"
	grpc "google.golang.org/grpc"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type LoginParam struct {
	K                    string   `protobuf:"bytes,1,opt,name=k,proto3" json:"k,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *LoginParam) Reset()         { *m = LoginParam{} }
func (m *LoginParam) String() string { return proto.CompactTextString(m) }
func (*LoginParam) ProtoMessage()    {}
func (*LoginParam) Descriptor() ([]byte, []int) {
	return fileDescriptor_gate_rpc_245e6d529bac706a, []int{0}
}
func (m *LoginParam) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_LoginParam.Unmarshal(m, b)
}
func (m *LoginParam) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_LoginParam.Marshal(b, m, deterministic)
}
func (dst *LoginParam) XXX_Merge(src proto.Message) {
	xxx_messageInfo_LoginParam.Merge(dst, src)
}
func (m *LoginParam) XXX_Size() int {
	return xxx_messageInfo_LoginParam.Size(m)
}
func (m *LoginParam) XXX_DiscardUnknown() {
	xxx_messageInfo_LoginParam.DiscardUnknown(m)
}

var xxx_messageInfo_LoginParam proto.InternalMessageInfo

func (m *LoginParam) GetK() string {
	if m != nil {
		return m.K
	}
	return ""
}

type LoginRet struct {
	Err                  string   `protobuf:"bytes,1,opt,name=err,proto3" json:"err,omitempty"`
	K                    string   `protobuf:"bytes,2,opt,name=k,proto3" json:"k,omitempty"`
	V                    string   `protobuf:"bytes,3,opt,name=v,proto3" json:"v,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *LoginRet) Reset()         { *m = LoginRet{} }
func (m *LoginRet) String() string { return proto.CompactTextString(m) }
func (*LoginRet) ProtoMessage()    {}
func (*LoginRet) Descriptor() ([]byte, []int) {
	return fileDescriptor_gate_rpc_245e6d529bac706a, []int{1}
}
func (m *LoginRet) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_LoginRet.Unmarshal(m, b)
}
func (m *LoginRet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_LoginRet.Marshal(b, m, deterministic)
}
func (dst *LoginRet) XXX_Merge(src proto.Message) {
	xxx_messageInfo_LoginRet.Merge(dst, src)
}
func (m *LoginRet) XXX_Size() int {
	return xxx_messageInfo_LoginRet.Size(m)
}
func (m *LoginRet) XXX_DiscardUnknown() {
	xxx_messageInfo_LoginRet.DiscardUnknown(m)
}

var xxx_messageInfo_LoginRet proto.InternalMessageInfo

func (m *LoginRet) GetErr() string {
	if m != nil {
		return m.Err
	}
	return ""
}

func (m *LoginRet) GetK() string {
	if m != nil {
		return m.K
	}
	return ""
}

func (m *LoginRet) GetV() string {
	if m != nil {
		return m.V
	}
	return ""
}

func init() {
	proto.RegisterType((*LoginParam)(nil), "gate.LoginParam")
	proto.RegisterType((*LoginRet)(nil), "gate.LoginRet")
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4

// GateClient is the client API for Gate service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type GateClient interface {
	Login(ctx context.Context, in *LoginParam, opts ...grpc.CallOption) (*LoginRet, error)
}

type gateClient struct {
	cc *grpc.ClientConn
}

func NewGateClient(cc *grpc.ClientConn) GateClient {
	return &gateClient{cc}
}

func (c *gateClient) Login(ctx context.Context, in *LoginParam, opts ...grpc.CallOption) (*LoginRet, error) {
	out := new(LoginRet)
	err := c.cc.Invoke(ctx, "/gate.Gate/Login", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// GateServer is the server API for Gate service.
type GateServer interface {
	Login(context.Context, *LoginParam) (*LoginRet, error)
}

func RegisterGateServer(s *grpc.Server, srv GateServer) {
	s.RegisterService(&_Gate_serviceDesc, srv)
}

func _Gate_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(LoginParam)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(GateServer).Login(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/gate.Gate/Login",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(GateServer).Login(ctx, req.(*LoginParam))
	}
	return interceptor(ctx, in, info, handler)
}

var _Gate_serviceDesc = grpc.ServiceDesc{
	ServiceName: "gate.Gate",
	HandlerType: (*GateServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Login",
			Handler:    _Gate_Login_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "pb/gate/gate_rpc.proto",
}

func init() { proto.RegisterFile("pb/gate/gate_rpc.proto", fileDescriptor_gate_rpc_245e6d529bac706a) }

var fileDescriptor_gate_rpc_245e6d529bac706a = []byte{
	// 145 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0x48, 0xd2, 0x4f,
	0x4f, 0x2c, 0x49, 0x05, 0x13, 0xf1, 0x45, 0x05, 0xc9, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42,
	0x2c, 0x20, 0xbe, 0x92, 0x14, 0x17, 0x97, 0x4f, 0x7e, 0x7a, 0x66, 0x5e, 0x40, 0x62, 0x51, 0x62,
	0xae, 0x10, 0x0f, 0x17, 0x63, 0xb6, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, 0x63, 0xb6, 0x92,
	0x05, 0x17, 0x07, 0x58, 0x2e, 0x28, 0xb5, 0x44, 0x48, 0x80, 0x8b, 0x39, 0xb5, 0xa8, 0x08, 0x2a,
	0x07, 0x62, 0x42, 0xd4, 0x32, 0x41, 0xd5, 0x82, 0x78, 0x65, 0x12, 0xcc, 0x10, 0x5e, 0x99, 0x91,
	0x31, 0x17, 0x8b, 0x7b, 0x62, 0x49, 0xaa, 0x90, 0x36, 0x17, 0x2b, 0xd8, 0x04, 0x21, 0x01, 0x3d,
	0x90, 0x6d, 0x7a, 0x08, 0xab, 0xa4, 0xf8, 0x90, 0x44, 0x82, 0x52, 0x4b, 0x94, 0x18, 0x92, 0xd8,
	0xc0, 0xee, 0x32, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x27, 0x2f, 0xd4, 0xb1, 0x00, 0x00,
	0x00,
}


<|start_filename|>src/pb/stream.pb.go<|end_filename|>
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pb/stream.proto

package pb

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

import (
	context "golang.org/x/net/context"
	grpc "google.golang.org/grpc"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type StreamFrameType int32

const (
	StreamFrameType_Message StreamFrameType = 0
	StreamFrameType_Kick    StreamFrameType = 1
	StreamFrameType_Ping    StreamFrameType = 2
)

var StreamFrameType_name = map[int32]string{
	0: "Message",
	1: "Kick",
	2: "Ping",
}
var StreamFrameType_value = map[string]int32{
	"Message": 0,
	"Kick":    1,
	"Ping":    2,
}

func (x StreamFrameType) String() string {
	return proto.EnumName(StreamFrameType_name, int32(x))
}
func (StreamFrameType) EnumDescriptor() ([]byte, []int) {
	return fileDescriptor_stream_81626ac05c3da03e, []int{0}
}

type StreamFrame struct {
	Type                 StreamFrameType `protobuf:"varint,1,opt,name=Type,proto3,enum=pb.StreamFrameType" json:"Type,omitempty"`
	Codec                string          `protobuf:"bytes,2,opt,name=Codec,proto3" json:"Codec,omitempty"`
	MsgId                int32           `protobuf:"varint,3,opt,name=MsgId,proto3" json:"MsgId,omitempty"`
	MsgData              []byte          `protobuf:"bytes,4,opt,name=MsgData,proto3" json:"MsgData,omitempty"`
	XXX_NoUnkeyedLiteral struct{}        `json:"-"`
	XXX_unrecognized     []byte          `json:"-"`
	XXX_sizecache        int32           `json:"-"`
}

func (m *StreamFrame) Reset()         { *m = StreamFrame{} }
func (m *StreamFrame) String() string { return proto.CompactTextString(m) }
func (*StreamFrame) ProtoMessage()    {}
func (*StreamFrame) Descriptor() ([]byte, []int) {
	return fileDescriptor_stream_81626ac05c3da03e, []int{0}
}
func (m *StreamFrame) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_StreamFrame.Unmarshal(m, b)
}
func (m *StreamFrame) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_StreamFrame.Marshal(b, m, deterministic)
}
func (dst *StreamFrame) XXX_Merge(src proto.Message) {
	xxx_messageInfo_StreamFrame.Merge(dst, src)
}
func (m *StreamFrame) XXX_Size() int {
	return xxx_messageInfo_StreamFrame.Size(m)
}
func (m *StreamFrame) XXX_DiscardUnknown() {
	xxx_messageInfo_StreamFrame.DiscardUnknown(m)
}

var xxx_messageInfo_StreamFrame proto.InternalMessageInfo

func (m *StreamFrame) GetType() StreamFrameType {
	if m != nil {
		return m.Type
	}
	return StreamFrameType_Message
}

func (m *StreamFrame) GetCodec() string {
	if m != nil {
		return m.Codec
	}
	return ""
}

func (m *StreamFrame) GetMsgId() int32 {
	if m != nil {
		return m.MsgId
	}
	return 0
}

func (m *StreamFrame) GetMsgData() []byte {
	if m != nil {
		return m.MsgData
	}
	return nil
}

type PostParam struct {
	MsgId                int32    `protobuf:"varint,1,opt,name=MsgId,proto3" json:"MsgId,omitempty"`
	Data                 []byte   `protobuf:"bytes,2,opt,name=Data,proto3" json:"Data,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *PostParam) Reset()         { *m = PostParam{} }
func (m *PostParam) String() string { return proto.CompactTextString(m) }
func (*PostParam) ProtoMessage()    {}
func (*PostParam) Descriptor() ([]byte, []int) {
	return fileDescriptor_stream_81626ac05c3da03e, []int{1}
}
func (m *PostParam) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_PostParam.Unmarshal(m, b)
}
func (m *PostParam) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_PostParam.Marshal(b, m, deterministic)
}
func (dst *PostParam) XXX_Merge(src proto.Message) {
	xxx_messageInfo_PostParam.Merge(dst, src)
}
func (m *PostParam) XXX_Size() int {
	return xxx_messageInfo_PostParam.Size(m)
}
func (m *PostParam) XXX_DiscardUnknown() {
	xxx_messageInfo_PostParam.DiscardUnknown(m)
}

var xxx_messageInfo_PostParam proto.InternalMessageInfo

func (m *PostParam) GetMsgId() int32 {
	if m != nil {
		return m.MsgId
	}
	return 0
}

func (m *PostParam) GetData() []byte {
	if m != nil {
		return m.Data
	}
	return nil
}

type PostRet struct {
	MsgId                int32    `protobuf:"varint,1,opt,name=MsgId,proto3" json:"MsgId,omitempty"`
	Data                 []byte   `protobuf:"bytes,2,opt,name=Data,proto3" json:"Data,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *PostRet) Reset()         { *m = PostRet{} }
func (m *PostRet) String() string { return proto.CompactTextString(m) }
func (*PostRet) ProtoMessage()    {}
func (*PostRet) Descriptor() ([]byte, []int) {
	return fileDescriptor_stream_81626ac05c3da03e, []int{2}
}
func (m *PostRet) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_PostRet.Unmarshal(m, b)
}
func (m *PostRet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_PostRet.Marshal(b, m, deterministic)
}
func (dst *PostRet) XXX_Merge(src proto.Message) {
	xxx_messageInfo_PostRet.Merge(dst, src)
}
func (m *PostRet) XXX_Size() int {
	return xxx_messageInfo_PostRet.Size(m)
}
func (m *PostRet) XXX_DiscardUnknown() {
	xxx_messageInfo_PostRet.DiscardUnknown(m)
}

var xxx_messageInfo_PostRet proto.InternalMessageInfo

func (m *PostRet) GetMsgId() int32 {
	if m != nil {
		return m.MsgId
	}
	return 0
}

func (m *PostRet) GetData() []byte {
	if m != nil {
		return m.Data
	}
	return nil
}

func init() {
	proto.RegisterType((*StreamFrame)(nil), "pb.StreamFrame")
	proto.RegisterType((*PostParam)(nil), "pb.PostParam")
	proto.RegisterType((*PostRet)(nil), "pb.PostRet")
	proto.RegisterEnum("pb.StreamFrameType", StreamFrameType_name, StreamFrameType_value)
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4

// StreamClient is the client API for Stream service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type StreamClient interface {
	CreateStream(ctx context.Context, opts ...grpc.CallOption) (Stream_CreateStreamClient, error)
}

type streamClient struct {
	cc *grpc.ClientConn
}

func NewStreamClient(cc *grpc.ClientConn) StreamClient {
	return &streamClient{cc}
}

func (c *streamClient) CreateStream(ctx context.Context, opts ...grpc.CallOption) (Stream_CreateStreamClient, error) {
	stream, err := c.cc.NewStream(ctx, &_Stream_serviceDesc.Streams[0], "/pb.Stream/CreateStream", opts...)
	if err != nil {
		return nil, err
	}
	x := &streamCreateStreamClient{stream}
	return x, nil
}

type Stream_CreateStreamClient interface {
	Send(*StreamFrame) error
	Recv() (*StreamFrame, error)
	grpc.ClientStream
}

type streamCreateStreamClient struct {
	grpc.ClientStream
}

func (x *streamCreateStreamClient) Send(m *StreamFrame) error {
	return x.ClientStream.SendMsg(m)
}

func (x *streamCreateStreamClient) Recv() (*StreamFrame, error) {
	m := new(StreamFrame)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

// StreamServer is the server API for Stream service.
type StreamServer interface {
	CreateStream(Stream_CreateStreamServer) error
}

func RegisterStreamServer(s *grpc.Server, srv StreamServer) {
	s.RegisterService(&_Stream_serviceDesc, srv)
}

func _Stream_CreateStream_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(StreamServer).CreateStream(&streamCreateStreamServer{stream})
}

type Stream_CreateStreamServer interface {
	Send(*StreamFrame) error
	Recv() (*StreamFrame, error)
	grpc.ServerStream
}

type streamCreateStreamServer struct {
	grpc.ServerStream
}

func (x *streamCreateStreamServer) Send(m *StreamFrame) error {
	return x.ServerStream.SendMsg(m)
}

func (x *streamCreateStreamServer) Recv() (*StreamFrame, error) {
	m := new(StreamFrame)
	if err := x.ServerStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

var _Stream_serviceDesc = grpc.ServiceDesc{
	ServiceName: "pb.Stream",
	HandlerType: (*StreamServer)(nil),
	Methods:     []grpc.MethodDesc{},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "CreateStream",
			Handler:       _Stream_CreateStream_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
	},
	Metadata: "pb/stream.proto",
}

func init() { proto.RegisterFile("pb/stream.proto", fileDescriptor_stream_81626ac05c3da03e) }

var fileDescriptor_stream_81626ac05c3da03e = []byte{
	// 244 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xc1, 0x4b, 0xc3, 0x30,
	0x14, 0xc6, 0xf7, 0x6a, 0xb7, 0xba, 0xb7, 0x61, 0x4b, 0xf4, 0x10, 0x3c, 0x95, 0x5e, 0x0c, 0x1e,
	0xaa, 0x74, 0xe8, 0x59, 0x98, 0x08, 0x22, 0x85, 0x12, 0xfd, 0x07, 0xd2, 0xed, 0x51, 0x86, 0xd4,
	0x86, 0x24, 0x17, 0xc1, 0x3f, 0x5e, 0x92, 0x2a, 0x8e, 0x9e, 0xbc, 0xbd, 0xdf, 0xf7, 0xe5, 0x77,
	0xc8, 0x87, 0xa9, 0x6e, 0x6f, 0xac, 0x33, 0xa4, 0xfa, 0x52, 0x9b, 0xc1, 0x0d, 0x2c, 0xd2, 0x6d,
	0xf1, 0x85, 0xab, 0xd7, 0x90, 0x3d, 0x19, 0xd5, 0x13, 0xbb, 0xc2, 0xf8, 0xed, 0x53, 0x13, 0x87,
	0x1c, 0xc4, 0x59, 0x75, 0x5e, 0xea, 0xb6, 0x3c, 0xaa, 0x7d, 0x25, 0xc3, 0x03, 0x76, 0x81, 0xf3,
	0xed, 0xb0, 0xa7, 0x1d, 0x8f, 0x72, 0x10, 0x4b, 0x39, 0x82, 0x4f, 0x6b, 0xdb, 0x3d, 0xef, 0xf9,
	0x49, 0x0e, 0x62, 0x2e, 0x47, 0x60, 0x1c, 0x93, 0xda, 0x76, 0x8f, 0xca, 0x29, 0x1e, 0xe7, 0x20,
	0xd6, 0xf2, 0x17, 0x8b, 0x3b, 0x5c, 0x36, 0x83, 0x75, 0x8d, 0x32, 0xaa, 0xff, 0x93, 0xe1, 0x58,
	0x66, 0x18, 0x07, 0x33, 0x0a, 0x66, 0xb8, 0x8b, 0x0d, 0x26, 0x5e, 0x93, 0xe4, 0xfe, 0x2f, 0x5d,
	0x57, 0x98, 0x4e, 0xbe, 0xc2, 0x56, 0x98, 0xd4, 0x64, 0xad, 0xea, 0x28, 0x9b, 0xb1, 0x53, 0x8c,
	0x5f, 0x0e, 0xbb, 0xf7, 0x0c, 0xfc, 0xd5, 0x1c, 0x3e, 0xba, 0x2c, 0xaa, 0x1e, 0x70, 0x31, 0x3a,
	0xec, 0x1e, 0xd7, 0x5b, 0x43, 0xca, 0xd1, 0x0f, 0xa7, 0x93, 0x69, 0x2e, 0xa7, 0x41, 0x31, 0x13,
	0x70, 0x0b, 0xed, 0x22, 0x4c, 0xbd, 0xf9, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x5f, 0xf5, 0xa6, 0x26,
	0x7d, 0x01, 0x00, 0x00,
}


<|start_filename|>src/pb/auth/auth_msg.gen.go<|end_filename|>
// DOT NOT EDIT THIS FILE, AUTO GEN!!
package auth

import (
	"errors"
	"reflect"
	"log"

	"github.com/golang/protobuf/proto"
)


func GetProtoUseList() []string {
	protoUseList := []string{
		"AuthMsgTest",
		"AuthMsgTestAck",
	}
	return protoUseList
}

func DecodeMessage(codec string, msgName string, msgData []byte) (interface{}, error) {
	if codec == "protobuf" {
		switch msgName {
			
		case "auth.AuthMsgTest":
			msg := &AuthMsgTest{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		case "auth.AuthMsgTestAck":
			msg := &AuthMsgTestAck{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		}
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}

func ToAuthMsgTest(msg interface{}) *AuthMsgTest {
	if reflect.TypeOf(msg).String() != "*auth.AuthMsgTest" {
		log.Panicln("msg type error")
	}
	return msg.(*AuthMsgTest)
}

func ToAuthMsgTestAck(msg interface{}) *AuthMsgTestAck {
	if reflect.TypeOf(msg).String() != "*auth.AuthMsgTestAck" {
		log.Panicln("msg type error")
	}
	return msg.(*AuthMsgTestAck)
}

func EncodeMessage(codec string, msg interface{}) ([]byte, error) {
	if codec == "protobuf" {
		buf, err := proto.Marshal(msg.(proto.Message))
		if err != nil {
			return nil, err
		}
		return buf, nil
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}


<|start_filename|>src/servers/gate_s/handler.go<|end_filename|>
package main

import (
	"context"
	"log"
)
import (
	"pb/auth"
	"pb/gate"
	"services"
)

func gateHandler(agent *agent, msgName string, msgInterface interface{}) error {
	switch msgName {
	case "gate.LoginReq":
		msg := gate.ToLoginReq(msgInterface)
		log.Println("gateHandler", msg.Account, msg.Password)
		serviceId, err1 := services.AssignServiceId("auth")
		if err1 != nil {
			log.Println(err1)
			return err1
		}
		defer services.UnassignServiceId(serviceId)
		serviceClient, err2 := services.GetServiceClient(serviceId)
		if err2 != nil {
			log.Println(err2)
			return err2
		}
		authClient := auth.NewAuthClient(serviceClient.Conn)
		loginRet, err3 := authClient.Login(context.Background(), &auth.LoginParam{Account: msg.Account, Password: msg.Password})
		if err3 != nil {
			log.Println(err3)
			return err3
		}
		userId := loginRet.UserId
		sess, err4 := getSessionManager().createSession(userId)
		if err4 != nil {
			log.Println(err4)
			return err4
		}
		// bindng each other
		sess.bindAgent(agent)
		msgData, _ := gate.EncodeMessage("protobuf", &gate.LoginAck{Error: "ok", UserId: userId})
		agent.toClient(services.ToMsgId("gate.LoginAck"), msgData)
	}
	return nil
}


<|start_filename|>src/utils/safemap.go<|end_filename|>
package utils

import (
	"sync"
)

type SafeMap struct {
	mu      *sync.RWMutex
	currMap map[interface{}]interface{}
}

func NewSafeMap() *SafeMap {
	return &SafeMap{
		mu:      new(sync.RWMutex),
		currMap: make(map[interface{}]interface{}),
	}
}

func (m *SafeMap) Count() int {
	m.mu.RLock()
	defer m.mu.RUnlock()
	return len(m.currMap)
}

func (m *SafeMap) Get(k interface{}) interface{} {
	m.mu.RLock()
	defer m.mu.RUnlock()
	if v, ok := m.currMap[k]; ok {
		return v
	}
	return nil
}

func (m *SafeMap) Set(k interface{}, v interface{}) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.currMap[k] = v
}

func (m *SafeMap) Delete(k interface{}) {
	m.mu.Lock()
	defer m.mu.Unlock()
	delete(m.currMap, k)
}

func (m *SafeMap) Items() map[interface{}]interface{} {
	m.mu.RLock()
	defer m.mu.RUnlock()
	newMap := make(map[interface{}]interface{})
	for k, v := range m.currMap {
		newMap[k] = v
	}
	return newMap
}


<|start_filename|>src/tools/server-gen/generator.go<|end_filename|>
package main

import (
	"log"
	"os"
	"strings"
)

type ServerGen struct {
	genType          string
	genFile          string
	serverName       string
	parser           *Parser
	header           string
	protoUseList     string
	grpc             string
	msgDecode        string
	msgEncode        string
	toMsg            string
	sendFunc         string
	pbServerRegister string
}

func newServerGen(genType string, genFile string, name string, parser *Parser) *ServerGen {
	ret := &ServerGen{
		genType:          genType,
		genFile:          genFile,
		serverName:       name,
		parser:           parser,
		header:           "",
		protoUseList:     "",
		grpc:             "",
		msgDecode:        "",
		msgEncode:        "",
		toMsg:            "",
		sendFunc:         "",
		pbServerRegister: "",
	}
	return ret
}

func (g *ServerGen) gen() {
	if g.genType == "rpc" {
		g.gen_header()
		g.gen_grpc()
		//g.gen_clientApi()
		//g.gen_protoUseList()
		//g.gen_pbServerRegister()
		g.saveFile(g.genFile, g.header+g.grpc+g.pbServerRegister)
	} else {
		g.gen_header()
		//g.gen_grpc()
		//g.gen_clientApi()
		g.gen_protoUseList()
		g.gen_msg_decode()
		g.gen_to_msg()
		g.gen_msg_encode()
		//g.gen_pbServerRegister()
		g.saveFile(g.genFile, g.header+g.grpc+g.sendFunc+g.protoUseList+g.msgDecode+g.toMsg+g.msgEncode)
	}
}

func (g *ServerGen) gen_header() {
	if g.genType == "rpc" {
		g.header = grpc_gen_header_tpl
	} else {
		g.header = msg_gen_header_tpl
	}
	g.header = strings.Replace(g.header, "#{server_name}", g.serverName, -1)
}

func (g *ServerGen) gen_grpc() {
	for _, defService := range g.parser.services {
		//log.Printf("service %s\n", defService.name)
		for _, rpc := range defService.rpcList {
			//log.Printf("  %s (%s) (%s) isStream %d %d\n", rpc.name, rpc.param, rpc.ret, rpc.isParamStream, rpc.isRetStream)
			if rpc.isParamStream && rpc.isRetStream {
				//rpcStr := strings.Replace(server_gen_grpc_tpl, "#{rpc_name}", rpc.name, -1)
				//rpcParam := fmt.Sprintf("%s_%sServer", defService.name, defService.name)
				//rpcStr = strings.Replace(rpcStr, "#{rpc_param}", rpcParam, -1)
				//rpcRet := fmt.Sprintf("%s_%sServer", defService.name, defService.name)
				//rpcStr = strings.Replace(rpcStr, "#{rpc_ret}", rpcRet, -1)
				//g.grpc += rpcStr + "\n"
				//log.Printf("  %s (stream %s) (stream %s)\n", rpc.name, rpc.param, rpc.ret)
			} else if rpc.isParamStream {
				//log.Printf("  %s (stream %s) (%s)\n", rpc.name, rpc.param, rpc.ret)
				//rpcStr := strings.Replace(server_gen_grpc_tpl, "#{rpc_name}", rpc.name, -1)
				//rpcStr = strings.Replace(rpcStr, "#{rpc_param}", rpc.param, -1)
				//rpcStr = strings.Replace(rpcStr, "#{rpc_ret}", rpc.ret, -1)
				//g.grpc += rpcStr + "\n"
			} else if rpc.isRetStream {
				//log.Printf("  %s (%s) (stream %s)\n", rpc.name, rpc.param, rpc.ret)
			} else {
				//log.Printf("  %s (%s) (%s)\n", rpc.name, rpc.param, rpc.ret)
				rpcStr := strings.Replace(msg_gen_grpc_tpl, "#{rpc_name}", rpc.name, -1)
				rpcStr = strings.Replace(rpcStr, "#{rpc_param}", rpc.param, -1)
				rpcStr = strings.Replace(rpcStr, "#{rpc_ret}", rpc.ret, -1)
				g.grpc += rpcStr + "\n"
			}
		}
	}
}

func (g *ServerGen) gen_msg_decode() {
	g.msgDecode += msg_gen_decode_tpl
	decode_case_list := ""
	for _, defType := range g.parser.types {
		//log.Printf("%s %s %s\n", defType.parentType, defType.def, defType.name)
		if defType.def == "message" && defType.parentType == "" {
			decode_case := msg_gen_decode_case_tpl
			decode_case = strings.Replace(decode_case, "#{server_name}", g.serverName, -1)
			decode_case = strings.Replace(decode_case, "#{message_name}", defType.name, -1)
			decode_case_list += decode_case
		}
	}
	g.msgDecode = strings.Replace(g.msgDecode, "#{decode_case_list}", decode_case_list, -1)
}

func (g *ServerGen) gen_to_msg() {
	for _, defType := range g.parser.types {
		if defType.def == "message" && defType.parentType == "" {
			toMsgStr := msg_gen_to_msg_tpl
			toMsgStr = strings.Replace(toMsgStr, "#{message_name}", defType.name, -1)
			toMsgStr = strings.Replace(toMsgStr, "#{server_name}", g.serverName, -1)
			g.toMsg += toMsgStr
		}
	}
}

func (g *ServerGen) gen_msg_encode() {
	g.msgEncode = msg_gen_encode_tpl
}

func (g *ServerGen) gen_clientApi() {
	/*
		g.register += server_gen_register_part1_tpl
		for _, defType := range g.parser.types {
			//log.Printf("%s %s %s\n", defType.parentType, defType.def, defType.name)
			if defType.def == "message" && defType.parentType == "" {
				registerStr := server_gen_register_part2_tpl
				registerStr = strings.Replace(registerStr, "#{message_name}", defType.name, -1)
				sendFuncStr := server_gen_sendfunc_tpl
				sendFuncStr = strings.Replace(sendFuncStr, "#{message_name}", defType.name, -1)
				//log.Println(defType.name, sendFuncStr)
				g.register += registerStr
				g.sendFunc += sendFuncStr

				ntfFuncStr := server_gen_ntffunc_tpl
				ntfFuncStr = strings.Replace(ntfFuncStr, "#{message_name}", defType.name, -1)
				g.sendFunc += ntfFuncStr
			}
		}
		g.register += server_gen_register_part3_tpl
	*/
}

func (g *ServerGen) gen_protoUseList() {
	messageList := ""
	for _, defType := range g.parser.types {
		if defType.def == "message" && defType.parentType == "" {
			messageList += "\n		\"" + defType.name + "\"" + ","
		}
	}
	protoUseList := msg_gen_protouse_tpl
	protoUseList = strings.Replace(protoUseList, "#{proto_use_list}", messageList, -1)
	g.protoUseList = protoUseList
}

func (g *ServerGen) gen_pbServerRegister() {
	/*
		pbServerRegister := server_gen_pbregister_tpl
		for _, defService := range g.parser.services {
			pbServerRegister = strings.Replace(pbServerRegister, "#{service_name}", defService.name, -1)
		}
		g.pbServerRegister = pbServerRegister
	*/
}

func (g *ServerGen) saveFile(fileName string, txt string) {
	f, err := os.OpenFile(fileName, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
	if err != nil {
		log.Fatalf("[ServerGen] Create files error: %v", err)
	}
	defer f.Close()
	f.WriteString(txt)
}


<|start_filename|>src/examples/chat_client/main.go<|end_filename|>
package main

import (
	"fmt"
	//"utils"
	//"time"
)

func main() {
	client := NewChatClient("127.0.0.1:12345", "chris", "<PASSWORD>")
	client.Start()
	fmt.Println("start chat client ...")
	for i := 0; i < 50; i++ {
		//fmt.Println(utils.CreateUUID2())
		//fmt.Println(utils.CreateUUID())
	}
	/*
		var sumCost int64
		sumCost = 0
		for i := 0; i < 10; i++ {
			beginStamp := time.Now().UnixNano()
			client.LoginAuth("chris", "<PASSWORD>")
			endStamp := time.Now().UnixNano()
			sumCost += (endStamp - beginStamp)
			cost := (endStamp - beginStamp) / (1000 * 1000)
			fmt.Println("call cost:", cost, " ms")
			//time.Sleep(1 * time.Millisecond)
		}

		fmt.Println("Avg Cost:", sumCost/(1000*1000), "us")

		fmt.Println("start chat client ...")
	*/

	select {}
}


<|start_filename|>src/pb/template/template_rpc.pb.go<|end_filename|>
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pb/template/template_rpc.proto

package template

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

import (
	context "golang.org/x/net/context"
	grpc "google.golang.org/grpc"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type TestParam struct {
	K                    string   `protobuf:"bytes,1,opt,name=k,proto3" json:"k,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *TestParam) Reset()         { *m = TestParam{} }
func (m *TestParam) String() string { return proto.CompactTextString(m) }
func (*TestParam) ProtoMessage()    {}
func (*TestParam) Descriptor() ([]byte, []int) {
	return fileDescriptor_template_rpc_7b23dbc3175237ed, []int{0}
}
func (m *TestParam) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_TestParam.Unmarshal(m, b)
}
func (m *TestParam) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_TestParam.Marshal(b, m, deterministic)
}
func (dst *TestParam) XXX_Merge(src proto.Message) {
	xxx_messageInfo_TestParam.Merge(dst, src)
}
func (m *TestParam) XXX_Size() int {
	return xxx_messageInfo_TestParam.Size(m)
}
func (m *TestParam) XXX_DiscardUnknown() {
	xxx_messageInfo_TestParam.DiscardUnknown(m)
}

var xxx_messageInfo_TestParam proto.InternalMessageInfo

func (m *TestParam) GetK() string {
	if m != nil {
		return m.K
	}
	return ""
}

type TestRet struct {
	Err                  string   `protobuf:"bytes,1,opt,name=err,proto3" json:"err,omitempty"`
	K                    string   `protobuf:"bytes,2,opt,name=k,proto3" json:"k,omitempty"`
	V                    string   `protobuf:"bytes,3,opt,name=v,proto3" json:"v,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *TestRet) Reset()         { *m = TestRet{} }
func (m *TestRet) String() string { return proto.CompactTextString(m) }
func (*TestRet) ProtoMessage()    {}
func (*TestRet) Descriptor() ([]byte, []int) {
	return fileDescriptor_template_rpc_7b23dbc3175237ed, []int{1}
}
func (m *TestRet) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_TestRet.Unmarshal(m, b)
}
func (m *TestRet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_TestRet.Marshal(b, m, deterministic)
}
func (dst *TestRet) XXX_Merge(src proto.Message) {
	xxx_messageInfo_TestRet.Merge(dst, src)
}
func (m *TestRet) XXX_Size() int {
	return xxx_messageInfo_TestRet.Size(m)
}
func (m *TestRet) XXX_DiscardUnknown() {
	xxx_messageInfo_TestRet.DiscardUnknown(m)
}

var xxx_messageInfo_TestRet proto.InternalMessageInfo

func (m *TestRet) GetErr() string {
	if m != nil {
		return m.Err
	}
	return ""
}

func (m *TestRet) GetK() string {
	if m != nil {
		return m.K
	}
	return ""
}

func (m *TestRet) GetV() string {
	if m != nil {
		return m.V
	}
	return ""
}

func init() {
	proto.RegisterType((*TestParam)(nil), "template.TestParam")
	proto.RegisterType((*TestRet)(nil), "template.TestRet")
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4

// TemplateClient is the client API for Template service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type TemplateClient interface {
	Test(ctx context.Context, in *TestParam, opts ...grpc.CallOption) (*TestRet, error)
}

type templateClient struct {
	cc *grpc.ClientConn
}

func NewTemplateClient(cc *grpc.ClientConn) TemplateClient {
	return &templateClient{cc}
}

func (c *templateClient) Test(ctx context.Context, in *TestParam, opts ...grpc.CallOption) (*TestRet, error) {
	out := new(TestRet)
	err := c.cc.Invoke(ctx, "/template.Template/Test", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// TemplateServer is the server API for Template service.
type TemplateServer interface {
	Test(context.Context, *TestParam) (*TestRet, error)
}

func RegisterTemplateServer(s *grpc.Server, srv TemplateServer) {
	s.RegisterService(&_Template_serviceDesc, srv)
}

func _Template_Test_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(TestParam)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(TemplateServer).Test(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/template.Template/Test",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(TemplateServer).Test(ctx, req.(*TestParam))
	}
	return interceptor(ctx, in, info, handler)
}

var _Template_serviceDesc = grpc.ServiceDesc{
	ServiceName: "template.Template",
	HandlerType: (*TemplateServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Test",
			Handler:    _Template_Test_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "pb/template/template_rpc.proto",
}

func init() {
	proto.RegisterFile("pb/template/template_rpc.proto", fileDescriptor_template_rpc_7b23dbc3175237ed)
}

var fileDescriptor_template_rpc_7b23dbc3175237ed = []byte{
	// 147 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x48, 0xd2, 0x2f,
	0x49, 0xcd, 0x2d, 0xc8, 0x49, 0x2c, 0x49, 0x85, 0x33, 0xe2, 0x8b, 0x0a, 0x92, 0xf5, 0x0a, 0x8a,
	0xf2, 0x4b, 0xf2, 0x85, 0x38, 0x60, 0x62, 0x4a, 0x92, 0x5c, 0x9c, 0x21, 0xa9, 0xc5, 0x25, 0x01,
	0x89, 0x45, 0x89, 0xb9, 0x42, 0x3c, 0x5c, 0x8c, 0xd9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41,
	0x8c, 0xd9, 0x4a, 0xe6, 0x5c, 0xec, 0x20, 0xa9, 0xa0, 0xd4, 0x12, 0x21, 0x01, 0x2e, 0xe6, 0xd4,
	0xa2, 0x22, 0xa8, 0x14, 0x88, 0x09, 0x51, 0xca, 0x04, 0x55, 0x0a, 0xe2, 0x95, 0x49, 0x30, 0x43,
	0x78, 0x65, 0x46, 0x36, 0x5c, 0x1c, 0x21, 0x50, 0xf3, 0x85, 0x0c, 0xb8, 0x58, 0x40, 0x86, 0x08,
	0x09, 0xeb, 0xc1, 0xac, 0xd4, 0x83, 0xdb, 0x27, 0x25, 0x88, 0x2a, 0x18, 0x94, 0x5a, 0xa2, 0xc4,
	0x90, 0xc4, 0x06, 0x76, 0xa2, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x8e, 0xc1, 0x50, 0x0d, 0xc4,
	0x00, 0x00, 0x00,
}


<|start_filename|>src/tools/server-gen/server_gen_tpl.go<|end_filename|>
package main

var grpc_gen_header_tpl = `// DOT NOT EDIT THIS FILE, AUTO GEN!!
package #{server_name}

import (
	"context"
	"errors"
)

type GrpcServer struct {
}
`

var msg_gen_header_tpl = `// DOT NOT EDIT THIS FILE, AUTO GEN!!
package #{server_name}

import (
	"errors"
	"reflect"
	"log"

	"github.com/golang/protobuf/proto"
)

`

var msg_gen_protouse_tpl = `
func GetProtoUseList() []string {
	protoUseList := []string{#{proto_use_list}
	}
	return protoUseList
}
`

var msg_gen_grpc_tpl = `
func (s *GrpcServer) #{rpc_name}(ctx context.Context, param *#{rpc_param}) (*#{rpc_ret}, error) {
	return nil, errors.New("this api not support")
}
`
var msg_gen_decode_tpl = `
func DecodeMessage(codec string, msgName string, msgData []byte) (interface{}, error) {
	if codec == "protobuf" {
		switch msgName {
			#{decode_case_list}
		}
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}
`

var msg_gen_decode_case_tpl = `
		case "#{server_name}.#{message_name}":
			msg := &#{message_name}{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}
`

var msg_gen_to_msg_tpl = `
func To#{message_name}(msg interface{}) *#{message_name} {
	if reflect.TypeOf(msg).String() != "*#{server_name}.#{message_name}" {
		log.Panicln("msg type error")
	}
	return msg.(*#{message_name})
}
`

var msg_gen_encode_tpl = `
func EncodeMessage(codec string, msg interface{}) ([]byte, error) {
	if codec == "protobuf" {
		buf, err := proto.Marshal(msg.(proto.Message))
		if err != nil {
			return nil, err
		}
		return buf, nil
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}
`

/*
var msg_gen_pbregister_tpl = `
func RegisterPbServers(s *server, grpcServer *grpc.Server) {
	pb.RegisterStreamServer(grpcServer, s)
	Register#{service_name}Server(grpcServer, s)
}
`


var server_gen_register_part1_tpl = `func (s *server) registerClientHandlers() {`
var server_gen_register_part2_tpl = `
	s.registerHandler("#{message_name}", func(network int, data []byte) {
		msg := &#{message_name}{}
		err := proto.Unmarshal(data, msg)
		if err != nil {
			log.Println(err)
		} else {
			s.logic.handleMessage(network, "#{message_name}", msg)
		}
	})
`
var server_gen_register_part3_tpl = `}`

var server_gen_sendfunc_tpl = `
func (s *server) send_#{message_name}(network int, userId string, msg *#{message_name}) {
	buf, err := proto.Marshal(msg)
	if err != nil {
		return
	}
	s.sendClient(network, userId, "#{message_name}", buf)
}
`

var server_gen_ntffunc_tpl = `
func (s *server) ntf_#{message_name}(network int, userIdList []string, msg *#{message_name}) {
	buf, err := proto.Marshal(msg)
	if err != nil {
		return
	}
	s.sendClients(network, userIdList, "#{message_name}", buf)
}
`
*/


<|start_filename|>src/examples/chat_client/client.go<|end_filename|>
package main

import (
	"flag"
	"fmt"
	"net/url"
	"reflect"
	"utils"

	"pb/gate"
	"pb/template"
	"strings"

	"github.com/golang/protobuf/proto"
	"github.com/gorilla/websocket"
)

type ChatClient struct {
	Conn     *websocket.Conn
	seq      int32
	done     chan bool
	addr     string
	account  string
	password string
	userId   int32
}

func NewChatClient(addr string, account string, password string) *ChatClient {
	ret := &ChatClient{
		seq:      0,
		done:     make(chan bool, 0),
		addr:     addr,
		account:  account,
		password: password,
	}
	return ret
}

func (c *ChatClient) Start() {
	var host = flag.String("addr", c.addr, "http service address")
	u := url.URL{Scheme: "ws", Host: *host, Path: "/wsGate"}
	conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
	c.Conn = conn
	if err != nil {
		fmt.Printf("dial:", err)
		return
	}
	c.StartRecvLoop()

	// start login and auto chat
	// message 1
	c.LoginAuth(c.account, c.password)
}

func (c *ChatClient) StartRecvLoop() {
	go func() {
		for {
			_, message, err := c.Conn.ReadMessage()
			if err != nil {
				fmt.Println("read:", err)
				return
			}
			recevSeq, msgId, msgData := utils.UnpackMsg(message)
			fmt.Printf("recv: recevSeq %d, msgId %d\n", recevSeq, msgId)
			c.HandleMessage(msgId, msgData)
		}
	}()
}

func (c *ChatClient) Send(msg interface{}) {
	fmt.Println("call start")
	msgName := reflect.TypeOf(msg).String()
	msgName = strings.Replace(msgName, "*", "", 1)
	msgId := utils.HashCode(msgName)
	//fmt.Println(msgName, "msgId", msgId)
	buf, err := proto.Marshal(msg.(proto.Message))
	if err != nil {
		fmt.Errorf(err.Error())
		return
	}
	c.seq += 1
	pack := utils.PackMsg(c.seq, msgId, buf)
	c.Conn.WriteMessage(websocket.BinaryMessage, pack)
}

func (c *ChatClient) HandleMessage(msgId uint32, msgData []byte) {
	switch msgId {
	// message 2
	case utils.HashCode("gate.LoginAck"):
		loginAck := &gate.LoginAck{}
		err := proto.Unmarshal(msgData, loginAck)
		if err != nil {
			fmt.Errorf(err.Error())
			return
		}
		c.userId = loginAck.UserId
		//fmt.Println("loginAck:", loginAck.Error, loginAck.UserId)
		//c.done <- true
		//fmt.Println("call end")

		c.TemplateMsgTest()
	}
}

func (c *ChatClient) Distroy() {
	defer c.Conn.Close()
}

func (c *ChatClient) LoginAuth(account string, password string) {
	c.Send(&gate.LoginReq{Account: account, Password: password})
	/*
		select {
		case <-c.done:
			return
		}
	*/
}

func (c *ChatClient) TemplateMsgTest() {
	c.Send(&template.TemplateMsgTest{I: 10009, S: "this is test msg"})
}

func (c *ChatClient) GetRoom(userId string) {

}

func (c *ChatClient) JoinRoom(roomId string) {

}


<|start_filename|>src/tools/server-gen/lexer.go<|end_filename|>
package main

import (
	"bufio"
	"io"
	"log"
	"regexp"
	"strings"
)

const (
	TOKEN_MIN              = iota
	TOKEN_COMMENT          // //
	TOKEN_ASSIGN           // =
	TOKEN_SEMICOLON        // ;
	TOKEN_BRACE_LEFT       // {
	TOKEN_BRACE_RIGHT      // }
	TOKEN_BRACKETS_LEFT    // (
	TOKEN_BRACKETS_RIGHT   // )
	TOKEN_QUOTE            // "
	TOKEN_KEYWORD_SERVICE  // service
	TOKEN_KEYWORD_SYNTAX   // syntax
	TOKEN_KEYWORD_PACKAGE  // package
	TOKEN_KEYWORD_RPC      // rpc
	TOKEN_KEYWORD_RETURNS  // returns
	TOKEN_KEYWORD_ENUM     // enum
	TOKEN_KEYWORD_MESSAGE  // message
	TOKEN_KEYWORD_STREAM   // stream
	TOKEN_KEYWORD_DOUBLE   // double
	TOKEN_KEYWORD_FLOAT    // float
	TOKEN_KEYWORD_INT32    // int32
	TOKEN_KEYWORD_INT64    // int64
	TOKEN_KEYWORD_UINT32   // uint32
	TOKEN_KEYWORD_UINT64   // uint64
	TOKEN_KEYWORD_SINT32   // sint32
	TOKEN_KEYWORD_SINT64   // sint64
	TOKEN_KEYWORD_FIXED32  // fixed32
	TOKEN_KEYWORD_FIXED64  // fixed64
	TOKEN_KEYWORD_SFIXED32 // sfixed32
	TOKEN_KEYWORD_SFIXED64 // sfixed64
	TOKEN_KEYWORD_BOOL     // bool
	TOKEN_KEYWORD_STRING   // string
	TOKEN_KEYWORD_BYTES    // bytes
	TOKEN_KEYWORD_OPTION   // option
	TOKEN_KEYWORD_REQUIRED // required
	TOKEN_KEYWORD_REPEATED // repeated
	TOKEN_NUMBER
	TOKEN_SYMBOL
	TOKEN_MAX
)

var token_rules = map[int]string{
	TOKEN_COMMENT:          `\s*//\s*`,
	TOKEN_ASSIGN:           `\s*=\s*`,
	TOKEN_SEMICOLON:        `\s*;\s*`,
	TOKEN_BRACE_LEFT:       `\s*{\s*`,
	TOKEN_BRACE_RIGHT:      `\s*}\s*`,
	TOKEN_BRACKETS_LEFT:    `\s*\(\s*`,
	TOKEN_BRACKETS_RIGHT:   `\s*\)\s*`,
	TOKEN_QUOTE:            `\s*"\s*`,
	TOKEN_KEYWORD_SERVICE:  `^\s*service\s+`,
	TOKEN_KEYWORD_SYNTAX:   `^\s*syntax\s+`,
	TOKEN_KEYWORD_PACKAGE:  `^\s*package\s+`,
	TOKEN_KEYWORD_RPC:      `^\s*rpc\s+`,
	TOKEN_KEYWORD_RETURNS:  `^\s*returns\s+`,
	TOKEN_KEYWORD_ENUM:     `^\s*enum\s+`,
	TOKEN_KEYWORD_MESSAGE:  `^\s*message\s+`,
	TOKEN_KEYWORD_STREAM:   `^\s*stream\s+`,
	TOKEN_KEYWORD_DOUBLE:   `^\s*double\s+`,
	TOKEN_KEYWORD_FLOAT:    `^\s*float\s+`,
	TOKEN_KEYWORD_INT32:    `^\s*int32\s+`,
	TOKEN_KEYWORD_INT64:    `^\s*int64\s+`,
	TOKEN_KEYWORD_UINT32:   `^\s*uint32\s+`,
	TOKEN_KEYWORD_UINT64:   `^\s*uint64\s+`,
	TOKEN_KEYWORD_FIXED32:  `^\s*fixed32\s+`,
	TOKEN_KEYWORD_FIXED64:  `^\s*fixed64\s+`,
	TOKEN_KEYWORD_SFIXED32: `^\s*sfixed32\s+`,
	TOKEN_KEYWORD_SFIXED64: `^\s*sfixed64\s+`,
	TOKEN_KEYWORD_BOOL:     `^\s*bool\s+`,
	TOKEN_KEYWORD_STRING:   `^\s*string\s+`,
	TOKEN_KEYWORD_BYTES:    `^\s*bytes\s+`,
	TOKEN_KEYWORD_OPTION:   `^\s*option\s+`,
	TOKEN_KEYWORD_REQUIRED: `^\s*required\s+`,
	TOKEN_KEYWORD_REPEATED: `^\s*repeated\s+`,
	TOKEN_SYMBOL:           `\s*[\w]+\s*`,
	TOKEN_NUMBER:           `\s*[\d]+\s*`,
}

type Token struct {
	lineno    int
	tokenType int
	text      string
}

type Lexer struct {
	lines        []string
	rules        map[int]*regexp.Regexp
	tokens       []*Token
	currTokenIdx int
}

func newLexer(tplReader io.Reader) *Lexer {
	lexer := &Lexer{}
	lexer.init(tplReader)
	return lexer
}

func (lexer *Lexer) init(tplReader io.Reader) {
	lexer.currTokenIdx = 0
	lexer.rules = map[int]*regexp.Regexp{}
	for k, v := range token_rules {
		reg := regexp.MustCompile(v)
		lexer.rules[k] = reg
	}

	scanner := bufio.NewScanner(tplReader)
	for scanner.Scan() {
		line := scanner.Text()
		lexer.lines = append(lexer.lines, line)
	}
	for k, v := range lexer.lines {
		lexer.parseLine(k+1, v)
	}

	//for _, v := range lexer.tokens {
	//	log.Println("line ", v.lineno, v.text)
	//}
}

func (lexer *Lexer) parseLine(lineno int, lineText string) {
	line := lineText
	for len(line) > 0 {
		isMatch := false
		for tokenType := TOKEN_MIN + 1; tokenType < TOKEN_MAX; tokenType++ {
			reg := lexer.rules[tokenType]
			if reg == nil {
				continue
			}
			ret := reg.FindStringIndex(line)
			if len(ret) == 2 && ret[0] == 0 {
				// do not process comment words
				if tokenType == TOKEN_COMMENT {
					return
				}
				text := strings.TrimSpace(line[ret[0]:ret[1]])
				lexer.tokens = append(lexer.tokens, &Token{lineno: lineno, tokenType: tokenType, text: text})
				line = line[ret[1]:]
				isMatch = true
				break
			}
		}
		if isMatch == false {
			log.Fatalf("There is some error in proto file with line %v: %v", lineno, line)
			break
		}
	}
}

func (lexer *Lexer) takeToken() *Token {
	if lexer.currTokenIdx >= len(lexer.tokens) {
		return nil
	}
	ret := lexer.tokens[lexer.currTokenIdx]
	lexer.currTokenIdx++
	//fmt.Println("takeToken: ", ret.text)
	return ret
}

func (lexer *Lexer) nextTokenType() int {
	if lexer.currTokenIdx >= len(lexer.tokens) {
		return -1
	}
	return lexer.tokens[lexer.currTokenIdx].tokenType
}


<|start_filename|>src/servers/gate_s/session.go<|end_filename|>
package main

import (
	"context"
	"log"
	"strconv"
	"sync"
	"time"
)

import (
	"pb"
	"services"
	"types"
	"utils"

	"google.golang.org/grpc/metadata"
)

// session is user state in gate, it can store user's service using state.
// it is created when user login, and removed when user logout or timeout. each
// session has only one agent. agent find service by session, service repley find
// agent by session too.
type session struct {
	userId     int32
	sessId     string
	agent      *agent
	serviceMap map[string]string                       //serviceType to serviceId
	streams    map[string]pb.Stream_CreateStreamClient //binding serviceType and streamClient
	activeTime time.Time
	cancel     context.CancelFunc
}

func (s *session) init(userId int32) {
	s.userId = userId
	s.sessId = utils.CreateUUID()
	s.agent = nil
	s.serviceMap = make(map[string]string, 0)
	s.streams = make(map[string]pb.Stream_CreateStreamClient, 0)
	s.activeTime = time.Now()
	ctx, cancel := context.WithCancel(context.Background())
	s.cancel = cancel
	serviceUseList := services.GetServiceUseList()
	for _, v := range serviceUseList {
		serviceType := v
		serviceId, err := services.AssignServiceId(serviceType)
		if err != nil {
			return
		}
		s.serviceMap[serviceType] = serviceId
		serviceClient, err := services.GetServiceClient(serviceId)
		if err != nil {
			log.Println(err.Error())
			return
		}
		if serviceClient.Conf.IsStream {
			log.Println("create stream client..")
			cli := pb.NewStreamClient(serviceClient.Conn)
			streamCtx := metadata.NewOutgoingContext(ctx, metadata.New(map[string]string{"user-id": strconv.Itoa(int(s.userId)), "codec": "protobuf"}))
			streamClient, err := cli.CreateStream(streamCtx)
			if err != nil {
				log.Println(err.Error())
				return
			}
			s.streams[serviceType] = streamClient
			go func() {
				defer func() {

				}()
				for {
					select {
					case <-ctx.Done():
						return
					default:
						frame, err := streamClient.Recv()
						if err != nil {
							log.Println(err)
							return
						}
						if s.agent != nil {
							s.agent.toClient(uint32(frame.MsgId), frame.MsgData)
						}
					}
				}
			}()
		}
	}
}

func (s *session) distroy() {
	s.cancel()
	for _, v := range s.serviceMap {
		services.UnassignServiceId(v)
	}
}

func (s *session) bindAgent(a *agent) {
	a.sessId = s.sessId
	s.agent = a
}

func (s *session) unbindAgent(a *agent) {
	a.sessId = ""
	s.agent = nil
}

func (s *session) streamSend(serviceType string, msgId uint32, msgData []byte) error {
	s.activeTime = time.Now()
	streamClient, ok := s.streams[serviceType]
	if !ok {
		return types.ERR_NO_SERVICE
	}
	frame := &pb.StreamFrame{
		Type:    pb.StreamFrameType_Message,
		Codec:   "protobuf",
		MsgId:   int32(msgId),
		MsgData: msgData,
	}
	err := streamClient.Send(frame)
	return err
}

type sessionManager struct {
	userId2sessId map[int32]string
	sessions      map[string]*session
	timeout       int
	pool          sync.Pool
}

func (p *sessionManager) init() {
	p.userId2sessId = make(map[int32]string, 0)
	p.sessions = make(map[string]*session, 0)
	p.timeout = 5 * 60
	p.pool = sync.Pool{
		New: func() interface{} {
			return new(session)
		},
	}
}

func (p *sessionManager) createSession(userId int32) (*session, error) {
	var sess *session
	sessId, ok := p.userId2sessId[userId]
	if !ok {
		sess = p.pool.Get().(*session)
		sess.init(userId)
		p.sessions[sess.sessId] = sess
		p.userId2sessId[userId] = sess.sessId
	} else {
		sess, _ = p.sessions[sessId]
		sess.activeTime = time.Now()
	}
	return sess, nil
}

func (p *sessionManager) getSession(sessId string) (*session, bool) {
	sess, ok := p.sessions[sessId]
	return sess, ok
}

func (p *sessionManager) releaseSession(sess *session) {
	for k, v := range p.userId2sessId {
		if v == sess.sessId {
			delete(p.userId2sessId, k)
			break
		}
	}
	delete(p.sessions, sess.sessId)
	sess.distroy()
	p.pool.Put(sess)
}

// remove seesion that active time is expired
func (p *sessionManager) watchSessions() {
	go func() {
		for {
			now := time.Now()
			isDel := false
			for _, v := range p.sessions {
				if now.Second()-v.activeTime.Second() > p.timeout {
					p.releaseSession(v)
					isDel = true
					break
				}
			}
			if isDel == false {
				time.Sleep(1)
			}
		}
	}()
}

var (
	_session_manager sessionManager
	_once            sync.Once
)

func getSessionManager() *sessionManager {
	_once.Do(func() { _session_manager.init() })
	return &_session_manager
}


<|start_filename|>src/pb/gate/gate_msg.gen.go<|end_filename|>
// DOT NOT EDIT THIS FILE, AUTO GEN!!
package gate

import (
	"errors"
	"reflect"
	"log"

	"github.com/golang/protobuf/proto"
)


func GetProtoUseList() []string {
	protoUseList := []string{
		"GateMsgTest",
		"GateMsgTestAck",
		"LoginReq",
		"LoginAck",
	}
	return protoUseList
}

func DecodeMessage(codec string, msgName string, msgData []byte) (interface{}, error) {
	if codec == "protobuf" {
		switch msgName {
			
		case "gate.GateMsgTest":
			msg := &GateMsgTest{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		case "gate.GateMsgTestAck":
			msg := &GateMsgTestAck{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		case "gate.LoginReq":
			msg := &LoginReq{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		case "gate.LoginAck":
			msg := &LoginAck{}
			err := proto.Unmarshal(msgData, msg)
			if err != nil {
				return nil, err
			} else {
				return msg, nil
			}

		}
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}

func ToGateMsgTest(msg interface{}) *GateMsgTest {
	if reflect.TypeOf(msg).String() != "*gate.GateMsgTest" {
		log.Panicln("msg type error")
	}
	return msg.(*GateMsgTest)
}

func ToGateMsgTestAck(msg interface{}) *GateMsgTestAck {
	if reflect.TypeOf(msg).String() != "*gate.GateMsgTestAck" {
		log.Panicln("msg type error")
	}
	return msg.(*GateMsgTestAck)
}

func ToLoginReq(msg interface{}) *LoginReq {
	if reflect.TypeOf(msg).String() != "*gate.LoginReq" {
		log.Panicln("msg type error")
	}
	return msg.(*LoginReq)
}

func ToLoginAck(msg interface{}) *LoginAck {
	if reflect.TypeOf(msg).String() != "*gate.LoginAck" {
		log.Panicln("msg type error")
	}
	return msg.(*LoginAck)
}

func EncodeMessage(codec string, msg interface{}) ([]byte, error) {
	if codec == "protobuf" {
		buf, err := proto.Marshal(msg.(proto.Message))
		if err != nil {
			return nil, err
		}
		return buf, nil
	} else if codec == "json" {
	}
	return nil, errors.New("no proto support for " + codec)
}


<|start_filename|>src/tools/server-gen/main.go<|end_filename|>
// Ref: https://github.com/letmefly/ant/blob/master/cmd/ant/create/generator.go
package main

import (
	"io/ioutil"
	"log"
	"os"
	"strings"
)

func main() {
	srcRoot := "./"
	dirs, _ := ioutil.ReadDir(srcRoot + "pb")
	for _, dir := range dirs {
		if dir.IsDir() {
			files, _ := ioutil.ReadDir(srcRoot + "pb/" + dir.Name())
			for _, file := range files {
				if strings.HasSuffix(file.Name(), ".proto") {
					//log.Println(file.Name())
					strs := strings.Split(file.Name(), "_")
					serverName := strs[0]
					filePath := srcRoot + "pb/" + dir.Name() + "/" + file.Name()
					log.Println(filePath)
					protoFile, err := os.Open(filePath)
					if err != nil {
						log.Fatal(err)
					}
					lexer := newLexer(protoFile)
					defer protoFile.Close()

					parser := newParser(lexer)
					parser.parse()
					genType := "rpc"
					genFile := ""
					if strings.Contains(file.Name(), "_msg") {
						genType = "msg"
						genFile = srcRoot + "pb/" + dir.Name() + "/" + serverName + "_msg.gen.go"
					} else if strings.Contains(file.Name(), "_rpc") {
						genType = "rpc"
						genFile = srcRoot + "pb/" + dir.Name() + "/" + serverName + "_rpc.gen.go"
					}

					log.Println("genFile:", genFile)
					generator := newServerGen(genType, genFile, serverName, parser)
					generator.gen()
				}
			}
		}
	}
}


<|start_filename|>src/utils/utils.go<|end_filename|>
package utils

import (
	"encoding/base64"
	"encoding/binary"
	"hash/fnv"
	"log"
	"math/rand"
	"reflect"
	"strings"
	"time"

	"github.com/gofrs/uuid"
)

/******************************************************************************
 *  use example:
 *	type A struct {}
 *	Register(A{})
 *	a, _ = New("A")
 *	o, ok := a.(A)
*******************************************************************************/
var _registerTypes = make(map[string]reflect.Type, 0)

func Register(i interface{}) {
	t := reflect.TypeOf(i)
	_registerTypes[t.Name()] = t
}

func New(name string) (interface{}, bool) {
	t, ok := _registerTypes[name]
	if !ok {
		return nil, false
	}
	v := reflect.New(t)
	return v.Interface(), true
}

/*
			+----------------------------------------------------------------+
	    		| seq(4) | msgId(4) | msgData(SIZE-6)            			|
	    		+----------------------------------------------------------------+
*/
func UnpackMsg(buf []byte) (int32, uint32, []byte) {
	if len(buf) <= 6 {
		return 0, 0, nil
	}
	seq := binary.BigEndian.Uint32(buf[0:4])
	msgId := binary.BigEndian.Uint32(buf[4:8])
	msgData := buf[8:]
	return int32(seq), msgId, msgData
}

func PackMsg(seq int32, msgId uint32, msgData []byte) []byte {
	if msgId == 0 || len(msgData) == 0 {
		return nil
	}
	msg := make([]byte, len(msgData)+8)
	binary.BigEndian.PutUint32(msg[0:4], uint32(seq))
	binary.BigEndian.PutUint32(msg[4:8], msgId)
	copy(msg[8:], msgData)
	return msg
}

const (
	base64Table = "lmABdefghCDJNOP012QRSTUVWXYZabcijknopqrstuvGHwxyz3456KLM789+/EFI"
)

var _coder = base64.NewEncoding(base64Table)

func base64Encode(src []byte) ([]byte, error) {
	return []byte(_coder.EncodeToString(src)), nil
}

func base64Decode(src []byte) ([]byte, error) {
	return _coder.DecodeString(string(src))
}

func Base64EncodeV1(s string) string {
	b := []byte(s)
	return base64.StdEncoding.EncodeToString(b)
}

func Base64DecodeV1(s string) string {
	ret, err := base64.StdEncoding.DecodeString(s)
	if err != nil {
		log.Fatal("Base64EncodeV1 faile")
	}
	return string(ret)
}

func Base64EncodeV2(s string) string {
	b := []byte(s)
	ret, err := base64Encode(b)
	if err != nil {
		log.Fatal("base64 encode fail")
	}
	return string(ret)
}

func Base64DecodeV2(s string) string {
	b := []byte(s)
	ret, err := base64Decode(b)
	if err != nil {
		log.Fatal("base64 decode fail")
	}
	return string(ret)
}

func CreateUUID() string {
	u1, err := uuid.NewV1()
	if err != nil {
		log.Fatal("Create UUID fail")
		return ""
	}
	return Base64EncodeV2(u1.String())
}

func CreateUUID2() string {
	u1, err := uuid.NewV4()
	if err != nil {
		log.Fatal("Create UUID fail")
		return ""
	}
	return u1.String()
}

func CreateServiceId(serviceType string, addr string) string {
	ret := serviceType + "__" + Base64EncodeV1(addr)
	return string(ret[0 : len(ret)-1])
}

func GetServiceType(serviceId string) string {
	strs := strings.Split(serviceId, "__")
	if len(strs) != 2 {
		return ""
	}
	return strs[0]
}

var _isSeed = false

func Random(max int) int {
	if _isSeed == false {
		rand.Seed(time.Now().UnixNano())
		_isSeed = true
	}
	return rand.Intn(max)
}

func HashCode(s string) uint32 {
	h := fnv.New32a()
	h.Write([]byte(s))
	return h.Sum32()
}


<|start_filename|>src/pb/auth/auth_rpc.pb.go<|end_filename|>
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: pb/auth/auth_rpc.proto

package auth

import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

import (
	context "golang.org/x/net/context"
	grpc "google.golang.org/grpc"
)

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package

type LoginParam struct {
	Account              string   `protobuf:"bytes,1,opt,name=Account,proto3" json:"Account,omitempty"`
	Password             string   `protobuf:"bytes,2,opt,name=Password,proto3" json:"Password,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *LoginParam) Reset()         { *m = LoginParam{} }
func (m *LoginParam) String() string { return proto.CompactTextString(m) }
func (*LoginParam) ProtoMessage()    {}
func (*LoginParam) Descriptor() ([]byte, []int) {
	return fileDescriptor_auth_rpc_fe0a50fcc1ae47c7, []int{0}
}
func (m *LoginParam) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_LoginParam.Unmarshal(m, b)
}
func (m *LoginParam) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_LoginParam.Marshal(b, m, deterministic)
}
func (dst *LoginParam) XXX_Merge(src proto.Message) {
	xxx_messageInfo_LoginParam.Merge(dst, src)
}
func (m *LoginParam) XXX_Size() int {
	return xxx_messageInfo_LoginParam.Size(m)
}
func (m *LoginParam) XXX_DiscardUnknown() {
	xxx_messageInfo_LoginParam.DiscardUnknown(m)
}

var xxx_messageInfo_LoginParam proto.InternalMessageInfo

func (m *LoginParam) GetAccount() string {
	if m != nil {
		return m.Account
	}
	return ""
}

func (m *LoginParam) GetPassword() string {
	if m != nil {
		return m.Password
	}
	return ""
}

type LoginRet struct {
	Error                string   `protobuf:"bytes,1,opt,name=Error,proto3" json:"Error,omitempty"`
	UserId               int32    `protobuf:"varint,2,opt,name=UserId,proto3" json:"UserId,omitempty"`
	XXX_NoUnkeyedLiteral struct{} `json:"-"`
	XXX_unrecognized     []byte   `json:"-"`
	XXX_sizecache        int32    `json:"-"`
}

func (m *LoginRet) Reset()         { *m = LoginRet{} }
func (m *LoginRet) String() string { return proto.CompactTextString(m) }
func (*LoginRet) ProtoMessage()    {}
func (*LoginRet) Descriptor() ([]byte, []int) {
	return fileDescriptor_auth_rpc_fe0a50fcc1ae47c7, []int{1}
}
func (m *LoginRet) XXX_Unmarshal(b []byte) error {
	return xxx_messageInfo_LoginRet.Unmarshal(m, b)
}
func (m *LoginRet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
	return xxx_messageInfo_LoginRet.Marshal(b, m, deterministic)
}
func (dst *LoginRet) XXX_Merge(src proto.Message) {
	xxx_messageInfo_LoginRet.Merge(dst, src)
}
func (m *LoginRet) XXX_Size() int {
	return xxx_messageInfo_LoginRet.Size(m)
}
func (m *LoginRet) XXX_DiscardUnknown() {
	xxx_messageInfo_LoginRet.DiscardUnknown(m)
}

var xxx_messageInfo_LoginRet proto.InternalMessageInfo

func (m *LoginRet) GetError() string {
	if m != nil {
		return m.Error
	}
	return ""
}

func (m *LoginRet) GetUserId() int32 {
	if m != nil {
		return m.UserId
	}
	return 0
}

func init() {
	proto.RegisterType((*LoginParam)(nil), "auth.LoginParam")
	proto.RegisterType((*LoginRet)(nil), "auth.LoginRet")
}

// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4

// AuthClient is the client API for Auth service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type AuthClient interface {
	Login(ctx context.Context, in *LoginParam, opts ...grpc.CallOption) (*LoginRet, error)
}

type authClient struct {
	cc *grpc.ClientConn
}

func NewAuthClient(cc *grpc.ClientConn) AuthClient {
	return &authClient{cc}
}

func (c *authClient) Login(ctx context.Context, in *LoginParam, opts ...grpc.CallOption) (*LoginRet, error) {
	out := new(LoginRet)
	err := c.cc.Invoke(ctx, "/auth.Auth/Login", in, out, opts...)
	if err != nil {
		return nil, err
	}
	return out, nil
}

// AuthServer is the server API for Auth service.
type AuthServer interface {
	Login(context.Context, *LoginParam) (*LoginRet, error)
}

func RegisterAuthServer(s *grpc.Server, srv AuthServer) {
	s.RegisterService(&_Auth_serviceDesc, srv)
}

func _Auth_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(LoginParam)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(AuthServer).Login(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/auth.Auth/Login",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(AuthServer).Login(ctx, req.(*LoginParam))
	}
	return interceptor(ctx, in, info, handler)
}

var _Auth_serviceDesc = grpc.ServiceDesc{
	ServiceName: "auth.Auth",
	HandlerType: (*AuthServer)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "Login",
			Handler:    _Auth_Login_Handler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "pb/auth/auth_rpc.proto",
}

func init() { proto.RegisterFile("pb/auth/auth_rpc.proto", fileDescriptor_auth_rpc_fe0a50fcc1ae47c7) }

var fileDescriptor_auth_rpc_fe0a50fcc1ae47c7 = []byte{
	// 173 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0x48, 0xd2, 0x4f,
	0x2c, 0x2d, 0xc9, 0x00, 0x13, 0xf1, 0x45, 0x05, 0xc9, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42,
	0x2c, 0x20, 0xbe, 0x92, 0x13, 0x17, 0x97, 0x4f, 0x7e, 0x7a, 0x66, 0x5e, 0x40, 0x62, 0x51, 0x62,
	0xae, 0x90, 0x04, 0x17, 0xbb, 0x63, 0x72, 0x72, 0x7e, 0x69, 0x5e, 0x89, 0x04, 0xa3, 0x02, 0xa3,
	0x06, 0x67, 0x10, 0x8c, 0x2b, 0x24, 0xc5, 0xc5, 0x11, 0x90, 0x58, 0x5c, 0x5c, 0x9e, 0x5f, 0x94,
	0x22, 0xc1, 0x04, 0x96, 0x82, 0xf3, 0x95, 0x2c, 0xb8, 0x38, 0xc0, 0x66, 0x04, 0xa5, 0x96, 0x08,
	0x89, 0x70, 0xb1, 0xba, 0x16, 0x15, 0xe5, 0x17, 0x41, 0xf5, 0x43, 0x38, 0x42, 0x62, 0x5c, 0x6c,
	0xa1, 0xc5, 0xa9, 0x45, 0x9e, 0x10, 0xbd, 0xac, 0x41, 0x50, 0x9e, 0x91, 0x31, 0x17, 0x8b, 0x63,
	0x69, 0x49, 0x86, 0x90, 0x36, 0x17, 0x2b, 0xd8, 0x04, 0x21, 0x01, 0x3d, 0x90, 0xab, 0xf4, 0x10,
	0x4e, 0x92, 0xe2, 0x43, 0x12, 0x09, 0x4a, 0x2d, 0x51, 0x62, 0x48, 0x62, 0x03, 0xbb, 0xdf, 0x18,
	0x10, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x44, 0xf8, 0x24, 0xd9, 0x00, 0x00, 0x00,
}


<|start_filename|>src/examples/test_http/main.go<|end_filename|>
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"pb/gate"
	"reflect"
	"utils"

	"strings"

	"github.com/golang/protobuf/proto"
)

func main() {
	response, _ := http.Get("http://127.0.0.1:12345/httpGate?sessId=xxdfdd")
	//defer response.Body.Close()
	body, _ := ioutil.ReadAll(response.Body)
	fmt.Println(string(body))

	//tmp := `{"name":"junneyang", "age": 88}`
	pack := PackMsg(&gate.LoginReq{Account: "chris.li", Password: "<PASSWORD>"})
	postReq := bytes.NewBuffer([]byte(pack))
	bodyType := "application/json;charset=utf-8"
	resp, _ := http.Post("http://127.0.0.1:12345/httpGate?sessId=xxdfdd", bodyType, postReq)
	body, _ = ioutil.ReadAll(resp.Body)
	_, _, msgData := utils.UnpackMsg(body)
	loginAck := &gate.LoginAck{}
	proto.Unmarshal(msgData, loginAck)
	fmt.Println("loginAck:", loginAck.String())
	select {}
}

func PackMsg(msg interface{}) []byte {
	msgName := reflect.TypeOf(msg).String()
	msgName = strings.Replace(msgName, "*", "", 1)
	msgId := utils.HashCode(msgName)
	buf, err := proto.Marshal(msg.(proto.Message))
	if err != nil {
		fmt.Errorf(err.Error())
		return nil
	}
	seq := 1
	pack := utils.PackMsg(int32(seq), msgId, buf)
	return pack
}


<|start_filename|>src/servers/gate_s/agent.go<|end_filename|>
package main

import (
	"context"
	"log"
	"sync"
	"utils"
)

import (
	"pb/gate"
	"services"
	"types"
)

type clientSendFunc func([]byte) error

// agent is client's agent in gate, its role is fowarding client's message to service,
// and forwarding service message to client. It is created when socket connection or
// http request is coming, removed when connection close or http request is over.
// each agent has one session
type agent struct {
	sessId     string
	clientSend clientSendFunc
	inBuf      chan []byte
	outBuf     chan []byte
	status     int // 0 - not work, 1 - working
	mu         sync.RWMutex
	inSeq      int32
	outSeq     int32
}

var _agent_pool = sync.Pool{
	New: func() interface{} {
		return new(agent)
	},
}

func newAgent(sessId string, clientSend clientSendFunc) *agent {
	a := _agent_pool.Get().(*agent)
	a.sessId = sessId
	a.clientSend = clientSend
	a.inBuf = make(chan []byte, 100)
	a.outBuf = make(chan []byte, 100)
	a.status = 0
	a.inSeq = -1
	a.outSeq = 0
	return a
}

func freeAgent(a *agent) {
	_agent_pool.Put(a)
}

func (a *agent) start(ctx context.Context) {
	a.setStatus(1) // now agent is working
	// main loop
	go func() {
		defer func() {
			a.exit()
			log.Println("main loop end")
		}()
		for {
			select {
			case msg, ok := <-a.inBuf:
				if !ok {
					log.Fatalln("in Buf not ok")
				}
				log.Printf("recv: %s", msg)
				seq, msgId, msgData := utils.UnpackMsg(msg)
				if seq <= a.inSeq || msgId == 0 || msgData == nil {
					log.Println("invalid message format")
					return
				}
				a.inSeq = seq
				t := services.ToServiceType(msgId)
				if t == "" {
					log.Println("invalid msgId")
					return
				}
				log.Println("dest server:", t)
				if t == "gate" {
					a.handle(msgId, msgData)
				} else {
					err := a.forward(t, msgId, msgData)
					switch err {
					case types.ERR_NO_SESSION, types.ERR_NO_SERVICE:
					}
				}

			case msg, ok := <-a.outBuf:
				if !ok {
					return
				}
				_ = a.clientSend(msg)

			case <-ctx.Done():
				log.Print("exit ntf")
				return
			}
		}
	}()
}

func (a *agent) getStatus() int {
	status := 0
	a.mu.RLock()
	status = a.status
	a.mu.RUnlock()
	return status
}

func (a *agent) setStatus(status int) {
	a.mu.Lock()
	a.status = status
	a.mu.Unlock()
}

func (a *agent) exit() {
	a.setStatus(0)
	sess, ok := getSessionManager().getSession(a.sessId)
	if ok {
		sess.unbindAgent(a)
	}
	close(a.inBuf)
	close(a.outBuf)
}

func (a *agent) forward(serviceType string, msgId uint32, msgData []byte) error {
	sess, ok := getSessionManager().getSession(a.sessId)
	if !ok {
		return types.ERR_NO_SESSION
	}
	return sess.streamSend(serviceType, msgId, msgData)
}

func (a *agent) toService(msg []byte) {
	if a.getStatus() == 0 {
		return
	}
	select {
	case a.inBuf <- msg:
	}
}

func (a *agent) toClient(msgId uint32, msgData []byte) {
	if a.getStatus() == 0 {
		return
	}
	a.outSeq = a.outSeq + 1
	msg := utils.PackMsg(a.outSeq, msgId, msgData)
	select {
	case a.outBuf <- msg:
	}
}

func (a *agent) handle(msgId uint32, msgData []byte) error {
	msgName := services.ToMsgName(msgId)
	msgInterface, err := gate.DecodeMessage("protobuf", msgName, msgData)
	if err != nil {
		return err
	}
	gateHandler(a, msgName, msgInterface)
	return nil
}


<|start_filename|>src/servers/auth_s/user.go<|end_filename|>
package main

import (
	"log"
)

import (
	"actors"
	"pb/auth"
)

type User struct {
	actors.BaseActorHost
	userId      string
	out         chan interface{}
	streamCodec string
}

func NewUser(userId string, out chan interface{}) *User {
	user := &User{
		userId: userId,
		out:    out,
	}
	actors.NewActor(user)
	return user
}

func (u *User) SetOutChan(out chan interface{}) {
	u.out = out
}

func (u *User) HandleMessages(name string, msg interface{}) {
	switch name {
	case "AuthMsgTest":
		msgAuthMsgTest := auth.ToAuthMsgTest(msg)
		if msgAuthMsgTest == nil {
			log.Fatalln("type error")
		}
	}
}

func (u *User) SendMessage(message interface{}) {
	if u.out == nil {
		return
	}
	u.out <- message
}
