package gate import ( "bet24.com/log" "bet24.com/network" "bet24.com/redis" "bet24.com/servers/insecureframe/message" platformconfig "bet24.com/servers/micros/platformconfig/proto" "bet24.com/servers/monitor" "bet24.com/servers/user" "bet24.com/utils" "encoding/json" "fmt" "sync" "time" ) var gate *Gate var sink GateSink type Gate struct { userlist map[int32]*client userList_lock *sync.RWMutex wsServer *network.WSServer userIndex int32 msgRecord *messageRecord lockIndex *sync.RWMutex logPort int } func run(s GateSink, logPath string) { sink = s port := sink.GetServerPort() gate = &Gate{} gate.msgRecord = newMessageRecord() gate.userlist = make(map[int32]*client) gate.userList_lock = &sync.RWMutex{} gate.lockIndex = &sync.RWMutex{} var wsServer *network.WSServer wsServer = new(network.WSServer) wsServer.Addr = fmt.Sprintf(":%d", port) wsServer.MaxConnNum = 20000 wsServer.PendingWriteNum = 1000 wsServer.MaxMsgLen = 65535 wsServer.HTTPTimeout = 10 * time.Second wsServer.CertFile = s.GetCertFile() wsServer.KeyFile = s.GetKeyFile() if s.GetGameName() == "walletbridgeserver" { wsServer.IsTextMessage = true } wsServer.NewAgent = func(conn *network.WSConn) network.Agent { userIndex := gate.GenUserIndex() a := NewClient(userIndex, conn, gate, false) log.Debug("NewAgent comes %v", a.RemoteAddr()) return a } wsServer.Start() log.Debug("wsServer = %v", wsServer) gate.wsServer = wsServer monitor.Run(port+100, logPath) gate.updateConsoleTitle() } func (g *Gate) GenUserIndex() int32 { g.lockIndex.Lock() defer g.lockIndex.Unlock() g.userIndex++ return g.userIndex } func (g *Gate) getUser(userIndex int32) *client { g.userList_lock.RLock() defer g.userList_lock.RUnlock() return g.userlist[userIndex] } func (g *Gate) getUserByUserID(userId int) *client { g.userList_lock.RLock() defer g.userList_lock.RUnlock() for _, v := range g.userlist { if v.userInfo.GetUserId() == userId { return v } } return nil } func (g *Gate) getUserCount() int { return len(g.userlist) } func (g *Gate) getPlayerCount() int { ret := 0 g.userList_lock.RLock() defer g.userList_lock.RUnlock() for _, v := range g.userlist { if !v.isRobot() { ret++ } } return ret } func (g *Gate) getUserList() []*user.UserInfo { var ret []*user.UserInfo g.userList_lock.RLock() defer g.userList_lock.RUnlock() for _, v := range g.userlist { ret = append(ret, v.userInfo) } return ret } func (g *Gate) removeUser(userIndex int32) { if userIndex >= 0 { g.userList_lock.Lock() delete(g.userlist, userIndex) g.userList_lock.Unlock() } g.updateConsoleTitle() } func (g *Gate) addUser(userIndex int32, pUser *client) { g.userList_lock.Lock() g.userlist[userIndex] = pUser g.userList_lock.Unlock() sink.OnUserEnter(userIndex) } func (g *Gate) refreshGold(userIndex int32) { c := g.getUser(userIndex) if c == nil { return } c.refreshGold() } func (g *Gate) userLogined(userIndex int32, userId int) { g.userList_lock.RLock() for k, v := range g.userlist { if k == userIndex { continue } if v.userInfo.GetUserId() == userId { robotDesc := "" if v.userInfo.IsRobot() { robotDesc = "Robot" } log.Release("same user logout %d[%s] %s", userId, v.userInfo.GetUserNickName(), robotDesc) // sink.OnUserExit(v.userIndex()) g.userList_lock.RUnlock() v.logout() g.removeUser(v.userIndex()) g.userList_lock.RLock() } } g.userList_lock.RUnlock() sink.OnUserLogined(userIndex) g.updateConsoleTitle() } func (g *Gate) updateConsoleTitle() { stopMsg := "running" if stopping { stopMsg = "stopping---" } roomType := "[G]" if sink.IsPrivateRoom() { roomType = "[P]" } if sink.IsChipRoom() { roomType = "[C]" } if sink.IsLadderRoom() { roomType = fmt.Sprintf("%s[L]", roomType) } var logInfo string if g.logPort > 0 { logInfo = fmt.Sprintf(" log:%d", g.logPort) } utils.SetConsoleTitle(fmt.Sprintf("%s%s port:%d monitor:%d%s user:%d ⬇ [%s]", roomType, sink.GetGameName(), sink.GetServerPort(), sink.GetServerPort()+100, logInfo, g.getPlayerCount(), stopMsg)) } func (g *Gate) getUserInfo(userIndex int32) *user.UserInfo { g.userList_lock.RLock() defer g.userList_lock.RUnlock() if user, ok := g.userlist[userIndex]; ok { return user.userInfo } return nil } func (g *Gate) getLoginedCount() int { ret := 0 g.userList_lock.RLock() defer g.userList_lock.RUnlock() for _, v := range g.userlist { if v.isLogined() { ret++ } } return ret } func (g *Gate) getRobotCount() int { ret := 0 g.userList_lock.RLock() defer g.userList_lock.RUnlock() for _, v := range g.userlist { if v.isRobot() { ret++ } } return ret } func (g *Gate) broadcastData(msg, data string) { g.userList_lock.RLock() defer g.userList_lock.RUnlock() m := message.BaseMsg{Data: data, Msg: msg} for _, v := range g.userlist { v.WriteMsg(msg, m) } } func (g *Gate) kickUser(userIndex int32) bool { c := g.getUser(userIndex) if c == nil { log.Debug("Gate.kickUser userIndex[%d] not exist", userIndex) return false } c.Close() return true } func (g *Gate) silentRemoveUser(userId int) { g.userList_lock.Lock() defer g.userList_lock.Unlock() for k, v := range g.userlist { if v.userInfo.GetUserId() == userId { delete(g.userlist, k) return } } } func (g *Gate) addMessageRecord(userId int, msg string) { g.msgRecord.addRecord(userId, msg) } func GetGate() *Gate { return gate } func RecvChannelData(data string) { log.Debug("RecvChannelData data = %+v", data) var msg redis.Channel_msg err := json.Unmarshal([]byte(data), &msg) if err != nil { log.Release("RecvChannelData Unmarshal data failed %v", data) return } switch msg.Message { case "RefreshChip": fallthrough case "RefreshGold": { u := gate.getUserByUserID(msg.UserID) if u == nil { return } if u.isRobot() { //log.Release("RecvChannelData.RefreshGold robot %d", msg.UserID) return } u.refreshGold() } case platformconfig.NOTIFY_MESSAGE: if gate == nil { return } sink.OnPlatformConfig(msg.Data) } }