func main() { logger.Info("start fight server") var cfg config.SvrConfig if err := config.ReadConfig(*svrConfigFile, &cfg); err != nil { logger.Fatal("load config failed, error is: %v", err) return } fightserver.StartServices(&cfg, fightServerId) handler := func(s os.Signal, arg interface{}) { logger.Info("handle signal: %v\n", s) logger.Info("stop game server") os.Exit(0) } handlerArray := []os.Signal{syscall.SIGINT, syscall.SIGILL, syscall.SIGFPE, syscall.SIGSEGV, syscall.SIGTERM, syscall.SIGABRT} common.WatchSystemSignal(&handlerArray, handler) logger.Info("stop fight server") }
func CreateServices(authcfg config.AuthConfig) *AuthServer { //初始化db logger.Info("Init DB") db.Init() //初始化cache var cacheCfg config.CacheConfig if err := config.ReadConfig("etc/maincache.json", &cacheCfg); err != nil { logger.Fatal("load config failed, error is: %v", err) } logger.Info("Init Cache %v", cacheCfg) pAuthServices = &AuthServer{ maincache: db.NewCachePool(cacheCfg), rpcServer: rpc.NewServer(), exit: make(chan bool), } pAuthServices.rpcServer.Register(pAuthServices) pAuthServices.rpcServer.ListenAndServe(authcfg.AuthHost, nil) return pAuthServices }
func (server *Server) register(rcvr interface{}, name string, useName bool, rcvrFns ...interface{}) error { server.mu.Lock() if server.serviceMap == nil { server.serviceMap = make(map[string]*service) } rcvrValue := reflect.ValueOf(rcvr) sname := reflect.Indirect(rcvrValue).Type().Name() if useName { sname = name } if sname == "" { logger.Fatal("rpc: no service name for type %v", reflect.ValueOf(rcvr).Interface()) } if !isExported(sname) && !useName { s := "rpc Register: type " + sname + " is not exported" logger.Info(s) server.mu.Lock() return errors.New(s) } var s *service if value, ok := server.serviceMap[sname]; ok { server.mu.Lock() s = value logger.Warning("rpc: service already defined: %s", sname) //return errors.New("rpc: service already defined: " + sname) } else { s = new(service) s.typ = reflect.TypeOf(rcvr) s.rcvr = reflect.ValueOf(rcvr) s.name = sname s.method = make(map[uint32]*methodType) } // Install the methods // logger.Debug("Install the methods begine!") s.method = server.suitableMethods(rcvr, s, s.typ, true, rcvrFns...) if len(s.method) == 0 { str := "" // To help the user, see if a pointer receiver would work. method := server.suitableMethods(rcvr, s, reflect.PtrTo(s.typ), false) if len(method) != 0 { str = "rpc.Register: type " + sname + " has no exported methods of suitable type (hint: pass a pointer to value of that type)" } else { str = "rpc.Register: type " + sname + " has no exported methods of suitable type" } logger.Info(str) server.mu.Unlock() return errors.New(str) } server.serviceMap[s.name] = s server.mu.Unlock() return nil }
func (self *FServerConnMgr) Init(connnector *server.Server, cfg config.SvrConfig) { fsCount := len(cfg.FsHost) self.Open(uint8(fsCount)) for i := 0; i < fsCount; i++ { go func() { defer func() { if r := recover(); r != nil { fmt.Printf("FServerConnMgr runtime error:", r) debug.PrintStack() } }() connId := self.GetNewConnId() host := cfg.FsHost[connId] for { select { case <-self.quit: { logger.Info("FServerConnMgr Goroutine Quit ----->") return } default: { var err error var fsConn net.Conn for { fsConn, err = net.Dial("tcp", host) if err != nil { //logger.Fatal("Connect FightServer Error :%s", err.Error()) } else { break } } logger.Info("Connect to FightServer : %s ok!!!!", host) fsRpcConn := server.NewTCPSocketConn(connnector, fsConn, 1000, 0, 1) fsRpcConn.SetResultServer("FightServer") self.NewConn(fsRpcConn, connId) connnector.ServeConn(fsRpcConn) } } } }() } }
func (self *AuthServer) LA_CheckAccount(req *protobuf.LA_CheckAccount, ret *protobuf.AL_CheckAccountResult) error { uid := common.GenUUID(req.GetAccount()) if len(req.GetUid()) > 0 { if req.GetUid() != uid { //客户端伪造uid (*ret).SetResult(protobuf.AL_CheckAccountResult_AUTH_FAILED) return nil } } account := &protobuf.AccountInfo{} result, err := db.Query("AccountInfo", uid, account) if err != nil { (*ret).SetResult(protobuf.AL_CheckAccountResult_SERVERERROR) return nil } if result == false { //用户注册 account.SetUid(uid) account.SetAccount(req.GetAccount()) account.SetPassword(common.GenPassword(req.GetAccount(), req.GetPassword())) account.SetLanguage(req.GetLanguage()) account.SetOption(req.GetOption()) account.SetSessionKey(common.GenSessionKey()) account.SetUdid(req.GetUdid()) account.SetCreateTime(uint32(time.Now().Unix())) db.Write("AccountInfo", uid, account) logger.Info("Auth AccountInfo create") } else { //用户登陆 if !common.CheckPassword(account.GetPassword(), req.GetAccount(), req.GetPassword()) { (*ret).SetResult(protobuf.AL_CheckAccountResult_AUTH_FAILED) return nil } account.SetSessionKey(common.GenSessionKey()) //保存进缓存 db.Write("AccountInfo", uid, account) logger.Info("Auth Account find") } self.maincache.Do("SET", "SessionKey_"+uid, []byte(account.GetSessionKey())) (*ret).SetResult(protobuf.AL_CheckAccountResult_OK) (*ret).SetSessionKey(account.GetSessionKey()) (*ret).SetUid(account.GetUid()) logger.Info("ComeInto AuthServer.Login %v, %v", req, ret) return nil }
func (p *Player) OnQuit() { logger.Info("OnQuit Begin") //pConn if p.conn != nil { p.conn.Lock() defer func() { p.conn.Unlock() logger.Info("OnQuit End") }() } p.Save() }
func main() { logger.Info("start auth server") var authcfg config.AuthConfig if err := config.ReadConfig(*authConfigFile, &authcfg); err != nil { logger.Fatal("load config failed, error is: %v", err) return } server.CreateServices(authcfg) common.WatchSystemSignal() logger.Info("stop auth server") }
func main() { logger.Info("start db server") var dbcfg config.DBConfig if err := config.ReadConfig(*dbConfigFile, &dbcfg); err != nil { logger.Fatal("load config failed, error is: %v", err) return } server.CreateServices(dbcfg) common.WatchSystemSignal() logger.Info("stop db server") }
func DBCreator(cfg config.MySQLConfig) CreateDBFunc { dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s", cfg.Uname, cfg.Pass, cfg.Host, cfg.Port, cfg.Dbname, cfg.Charset) logger.Info("MySqlDNS: %s", dns) return func() (db *sql.DB, dnsInfo string, err error) { dnsInfo = dns var retry uint8 = 0 for { db, err = sql.Open("mysql", dns) if err == nil { break } logger.Error("Error on Create db: %s; try: %d/%d", err.Error(), retry, cfg.MaxRetry) if retry >= cfg.MaxRetry { return } retry++ } return } }
func (conn *ProtoBufConn) Close() (errret error) { conn.lockForClose.Lock() logger.Info("ProtoBufConn %d Close : %v", conn.id, errret) if conn.is_closed { conn.lockForClose.Unlock() return nil } if err := conn.c.Close(); err != nil { //再尝试一次 time.Sleep(10 * time.Millisecond) if err := conn.c.Close(); err != nil { conn.lockForClose.Unlock() return err } } conn.is_closed = true if conn.t != nil { conn.t.Stop() } conn.exit <- true conn.lockForClose.Unlock() return nil }
func (conn *ProtoBufConn) OnCheck() { time_diff := uint32(time.Now().Unix() - conn.last_time) if time_diff > conn.time_out<<1 { logger.Info("Conn %d TimeOut: %d", conn.GetId(), time_diff) conn.Close() } }
func main() { logger.Info("start game server") var cfg config.SvrConfig if err := config.ReadConfig(*svrConfigFile, &cfg); err != nil { logger.Fatal("load config failed, error is: %v", err) return } server.CreateConnectorServerForClient(cfg) common.WatchSystemSignal() //script.DefaultLuaScript().ExecuteScriptFile("script/runtime/gameserver/main.lua") logger.Info("stop game server") }
func WriteResult(conn server.RpcConn, value interface{}) bool { err := conn.WriteObj(value) if err != nil { logger.Info("WriteResult Error %s", err.Error()) return false } return true }
func (self *FightServer) addBattle(b *Battle) { logger.Info("Connector:addBattle %v, %v", b.GetBid(), b) self.l.Lock() defer self.l.Unlock() // self.battles[b.GetBid()] = b }
func (self *FightServer) delBattle(bid string) { logger.Info("Connector:delBattle %v", bid) _, exist := self.battles[bid] if exist { self.l.Lock() delete(self.battles, bid) self.l.Unlock() } }
//添加玩家到全局表中 func (self *Connector) addPlayer(connId uint64, p *Player) { logger.Info("Connector:addPlayer %v, %v", connId, p.GetUid()) self.l.Lock() defer self.l.Unlock() //进入服务器全局表 self.players[connId] = p self.playersbyid[p.GetUid()] = p }
func (self *FServerConnMgr) GetWorkConn() server.RpcConn { self.poollock.Lock() defer self.poollock.Unlock() self.workindex++ if uint8(self.workindex) >= self.poolsize { self.workindex = 0 } logger.Info("FServerConnMgr GetWorkConn -----> %v", self.workindex) return self.connpool[self.workindex] }
func (self *FServerConnMgr) Quit() { self.poollock.Lock() defer self.poollock.Unlock() for i, v := range self.connpool { logger.Info("ShutDown FServerConnMgr -----> %d", i) v.Close() self.quit <- true } }
//销毁玩家 func (self *Connector) delPlayer(connId uint64) { logger.Info("Connector:delPlayer %v", connId) p, exist := self.players[connId] if exist { p.OnQuit() self.l.Lock() delete(self.players, connId) delete(self.playersbyid, p.GetUid()) self.l.Unlock() } }
func wsServeConnHandler(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { fmt.Fprintln(w, "rpc: error") return } logger.Debug("wsServeConnHandler : %v", r.FormValue("method")) conn, err := upgrader.Upgrade(w, r, nil) if err != nil { logger.Info("Upgrade:", err.Error()) conn, bufrw, err := w.(http.Hijacker).Hijack() if err != nil { logger.Debug("rpc hijacking %v : %v", r.RemoteAddr, err.Error()) return } else { httpConn := server.NewTCPSocketConn(pConnector.rpcServer, conn, 1, 1, 1) logger.Debug("rpc hijacking %v : %v", r.RemoteAddr, r.FormValue("method")) fmt.Fprintln(w, "rpc: hello") buf := make([]byte, 10) for i := 0; i < len(buf); i++ { buf[i] = byte(i) } _, err = bufrw.Write(buf) if err == nil { err = bufrw.Flush() } if err != nil { fmt.Printf("ResponseError: %s\\n", err) } else { fmt.Println("Bye, Jack!") } logger.Debug("httpConn WriteObj %v", httpConn.GetRemoteIp()) } return } rpcConn := server.NewWebSocketConn(pConnector.rpcServer, *conn, 128, 45, 2) defer func() { rpcConn.Close() // 客户端退出减去计数 }() pConnector.rpcServer.ServeConn(rpcConn) }
func Register_lua_db_CachePool_newClass(L *lua.LState) int { cfg := L.CheckString(2) var cacheCfg config.CacheConfig if err := config.ReadConfig(cfg, &cacheCfg); err != nil { logger.Fatal("load config failed, error is: %v", err) } logger.Info("Init Cache %v", cacheCfg) cache := db.NewCachePool(cacheCfg) ud := L.NewUserData() ud.Value = cache L.SetMetatable(ud, L.GetTypeMetatable(luaCachePoolTypeName)) L.Push(ud) return 1 }
func (server *Server) wsServeConnHandler(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { logger.Info("Upgrade:", err) return } rpcConn := NewWebSocketConn(server, *conn, 4, 30, 2) defer func() { rpcConn.Close() }() server.ServeConn(rpcConn) }
func WatchSystemSignal() { callbackHandler := func(s os.Signal, arg interface{}) { logger.Info("handle signal: %v\n", s) logger.Info("stop game server") os.Exit(0) } watchsingals := []os.Signal{syscall.SIGINT, syscall.SIGILL, syscall.SIGFPE, syscall.SIGSEGV, syscall.SIGTERM, syscall.SIGABRT} ss := signalSetNew() for _, wathsingnal := range watchsingals { ss.register(wathsingnal, callbackHandler) } for { c := make(chan os.Signal) var sigs []os.Signal for sig := range ss.m { sigs = append(sigs, sig) } signal.Notify(c) sig := <-c err := ss.handle(sig, nil) if err != nil { fmt.Printf("unknown signal received: %v\n", sig) } } }
func testCommon() { logger.Info("uuid: %v", common.GenUUID("123")) logger.Info("uuid: %v", common.GenUUID("account")) passwdhash := common.GenPassword("account", "passwd") logger.Info("passwdhash: %v", passwdhash) logger.Info("check: %v", common.CheckPassword(passwdhash, "account", "passwd")) sessionKey := common.GenSessionKey() logger.Info("session: %v", sessionKey) logger.Info("check: %v", common.CheckSessionKey(sessionKey)) }
func (self *Connector) sendPlayerCountToGateServer() { go func() { defer func() { if r := recover(); r != nil { logger.Info("sendPlayerCountToGateServer runtime error:", r) debug.PrintStack() } }() for { time.Sleep(5 * time.Second) self.l.RLock() playerCount := uint32(len(self.players)) self.l.RUnlock() var ret []byte req := protobuf.SL_UpdatePlayerCount{} req.SetServerId(self.id) req.SetPlayerCount(playerCount) req.SetTcpServerIp(self.listenTcpIp) req.SetHttpServerIp(self.listenHttpIp) //logger.Debug("playerCount %v", playerCount) buf, err := proto.Marshal(&req) if err != nil { logger.Error("Error On Connector.sendPlayerCountToGateServer : %s", err.Error()) return } err = self.loginserver.Call("LoginRpcServer.SL_UpdatePlayerCount", &buf, &ret) if err != nil { logger.Error("Error On LoginRpcServer.SL_UpdatePlayerCount : %s", err.Error()) return } } }() }
func CreateConnectorServerForClient(cfg config.SvrConfig) *Connector { db.Init() var authCfg config.AuthConfig if err := config.ReadConfig("etc/authserver.json", &authCfg); err != nil { logger.Fatal("load config failed, error is: %v", err) } authConn, err := net.Dial("tcp", authCfg.AuthHost) if err != nil { logger.Fatal("connect logserver failed %s", err.Error()) } var gsCfg config.LoginConfig if err = config.ReadConfig("etc/loginserver.json", &gsCfg); err != nil { logger.Fatal("load config failed, error is: %v", err) } gsConn, err := net.Dial("tcp", gsCfg.LoginHost) if err != nil { logger.Fatal("%s", err.Error()) } pConnector = &Connector{ m: make(map[uint32]serverInfo), authserver: rpc.NewClient(authConn), loginserver: rpc.NewClient(gsConn), rpcServer: server.NewServer(), players: make(map[uint64]*Player), playersbyid: make(map[string]*Player), } //初始化cache logger.Info("Init Cache %v", authCfg.MainCacheProfile) pConnector.maincache = db.NewCachePool(authCfg.MainCacheProfile) pConnector.rpcServer.ApplyProtocol(protobuf.CS_Protocol_value) pConnector.rpcServer.Register(pConnector) pConnector.rpcServer.RegCallBackOnConn( func(conn server.RpcConn) { pConnector.onConn(conn) }, ) pConnector.rpcServer.RegCallBackOnDisConn( func(conn server.RpcConn) { pConnector.onDisConn(conn) }, ) pConnector.rpcServer.RegCallBackOnCallBefore( func(conn server.RpcConn) { conn.Lock() }, ) pConnector.rpcServer.RegCallBackOnCallAfter( func(conn server.RpcConn) { conn.Unlock() }, ) //开始对fightserver的RPC服务 pConnector.FsMgr.Init(pConnector.rpcServer, cfg) listener, err := net.Listen("tcp", cfg.TcpHost) if err != nil { logger.Fatal("net.Listen: %s", err.Error()) } pConnector.id = cfg.ServerID pConnector.listenTcpIp = cfg.TcpHost pConnector.listenHttpIp = cfg.HttpHost pConnector.sendPlayerCountToGateServer() go func() { for { //For Client///////////////////////////// time.Sleep(time.Millisecond * 5) conn, err := listener.Accept() if err != nil { logger.Error("cns StartServices %s", err.Error()) break } go func() { rpcConn := server.NewTCPSocketConn(pConnector.rpcServer, conn, 128, 45, 1) defer func() { if r := recover(); r != nil { logger.Error("player rpc runtime error begin:", r) debug.PrintStack() rpcConn.Close() logger.Error("player rpc runtime error end ") } }() pConnector.rpcServer.ServeConn(rpcConn) }() } }() http.HandleFunc("/", wsServeConnHandler) http.ListenAndServe(cfg.HttpHost, nil) return pConnector }
func NewDBServer(cfg config.DBConfig) (server *DBServer) { server = &DBServer{ dbGroups: map[string]dbGroup{}, cacheGroups: map[string]cacheGroup{}, tables: map[string]*table{}, exit: make(chan bool), } //http.Handle("/debug/state", debugHTTP{server}) //初始化所有的db for key, pools := range cfg.DBProfiles { logger.Info("Init DB Profile %s", key) server.dbGroups = make(map[string]dbGroup) server.dbVirNodes = make(map[string]map[uint32]uint32) server.dbNodes = make(map[string][]uint32) temDbs := make(map[uint32]uint32) temGroups := make(dbGroup) temDbInt := []uint32{} for _, poolCfg := range pools { logger.Info("Init DB %v", poolCfg) leng := makeHash(poolCfg.NodeName) temGroups[leng] = db.NewDBPool(poolCfg) if poolCfg.Vnode <= 0 { poolCfg.Vnode = 1 } var i uint8 for i = 0; i < poolCfg.Vnode; i++ { keys := makeHash(fmt.Sprintf("%s#%d", poolCfg.NodeName, i)) temDbs[keys] = leng temDbInt = append(temDbInt, keys) } } server.dbGroups[key] = temGroups bubbleSort(temDbInt) //排序节点 server.dbVirNodes[key] = temDbs server.dbNodes[key] = temDbInt } //初始化所有的cache for key, pools := range cfg.CacheProfiles { logger.Info("Init Cache Profile %s", key) server.cacheGroups = make(map[string]cacheGroup) server.cacheVirNodes = make(map[string]map[uint32]uint32) server.cacheNodes = make(map[string][]uint32) temDbs := make(map[uint32]uint32) temGroups := make(cacheGroup) temDbInt := []uint32{} for _, poolCfg := range pools { logger.Info("Init Cache %v", poolCfg) leng := makeHash(poolCfg.NodeName) temGroups[leng] = db.NewCachePool(poolCfg) if poolCfg.Vnode <= 0 { poolCfg.Vnode = 1 } //leng := len(server.cacheGroups[key]) - 1 var i uint8 for i = 0; i < poolCfg.Vnode; i++ { keys := makeHash(fmt.Sprintf("%s#%d", poolCfg.NodeName, i)) temDbs[keys] = leng temDbInt = append(temDbInt, keys) } } server.cacheGroups[key] = temGroups bubbleSort(temDbInt) //排序节点 server.cacheVirNodes[key] = temDbs server.cacheNodes[key] = temDbInt } //初始化table for key, table := range cfg.Tables { logger.Info("Init Table: %s %v", key, table) server.tables[key] = NewTable(key, table, server) } return server }
func NewTable(name string, cfg config.TableConfig, server *DBServer) (t *table) { var ( caches cacheGroup cacheNode []uint32 dbs dbGroup dbNode []uint32 dbVirNode map[uint32]uint32 cacheVirNode map[uint32]uint32 ) if cfg.CacheProfile != "" { var exist bool if caches, exist = server.cacheGroups[cfg.CacheProfile]; !exist { logger.Fatal("NewTable: table cache profile not found: %s", cfg.CacheProfile) } cacheNode, _ = server.cacheNodes[cfg.CacheProfile] cacheVirNode, _ = server.cacheVirNodes[cfg.CacheProfile] } if cfg.DBProfile != "" { var exist bool if dbs, exist = server.dbGroups[cfg.DBProfile]; !exist { logger.Fatal("NewTable: table db profile not found: %s", cfg.DBProfile) } dbNode, _ = server.dbNodes[cfg.DBProfile] dbVirNode, _ = server.dbVirNodes[cfg.DBProfile] for _, dbpool := range dbs { db := dbpool.Get() defer db.Recycle() /* query := fmt.Sprintf(` CREATE TABLE IF NOT EXISTS %s ( added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, id BINARY(32) NOT NULL, body MEDIUMBLOB, updated TIMESTAMP NOT NULL, UNIQUE KEY (id), KEY (updated) ) ENGINE=InnoDB; `, name) */ query := fmt.Sprintf(` CREATE TABLE IF NOT EXISTS %s ( id BINARY(64) NOT NULL PRIMARY KEY, auto_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, body MEDIUMBLOB, updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY (updated), key (auto_id) ) ENGINE=InnoDB; `, name) logger.Info("CreateQuery :%s", query) rst, err := db.Exec( query, ) if err != nil { logger.Fatal("NewTable: db %v create table %s faild! %s", dbpool, name, err.Error()) } logger.Info("NewTable: db %v init %s: %v", dbpool, name, rst) } } if caches == nil && dbs == nil { logger.Fatal("NewTable: table %s need a save func", name) } queryStats := stats.NewTimings("") qpsRates := stats.NewRates("", queryStats, 20, 10e9) return &table{ name, caches, dbs, cfg.DeleteExpiry, queryStats, qpsRates, cacheNode, dbNode, dbVirNode, cacheVirNode, } }
func (self *Connector) CS_CheckSession(conn server.RpcConn, login protobuf.CS_CheckSession) (err error) { rep := protobuf.SC_CheckSessionResult{} uid := login.GetUid() var rst []byte rst, err = redis.Bytes(self.maincache.Do("GET", "SessionKey_"+uid)) rep.SetResult(protobuf.SC_CheckSessionResult_AUTH_FAILED) rep.SetServerTime(uint32(time.Now().Unix())) if rst != nil || err == nil { if login.GetSessionKey() == string(rst) { rep.SetResult(protobuf.SC_CheckSessionResult_OK) } } logger.Debug("SC_CheckSessionResult %v", rep) rep.SetResult(rep.GetResult()) if rep.GetResult() == protobuf.SC_CheckSessionResult_OK { WriteResult(conn, &rep) if p, ok := self.playersbyid[login.GetUid()]; ok { if err := p.conn.Close(); err == nil { logger.Info("kick the online player") } } var base protobuf.PlayerBaseInfo logger.Info("query db : %v", login.GetUid()) result, err := db.Query("playerbase", login.GetUid(), &base) if result == false { base = protobuf.PlayerBaseInfo{} base.SetUid(login.GetUid()) stat := &protobuf.StatusInfo{} stat.SetName("test_" + uid) stat.SetLevel(1) base.SetStat(stat) db.Write("playerbase", login.GetUid(), &base) logger.Info("playerbase create %v", login.GetUid()) } else { if err != nil { logger.Info("err query db : %v", err) return err } logger.Info("playerbase find") } p := &Player{PlayerBaseInfo: &base, conn: conn} p.SetUid(uid) //进入服务器全局表 self.addPlayer(conn.GetId(), p) } else { WriteResult(conn, &rep) go func() { time.Sleep(time.Millisecond * 1000) defer func() { conn.Close() }() }() } return nil }
func (self *Connector) onDisConn(conn server.RpcConn) { logger.Info("Connector:onDisConn %v", conn.GetId()) self.delPlayer(conn.GetId()) }