package main import ( "github.com/gorilla/websocket" "math/rand" "strconv" "sync" "time" ) type UserInfo struct { UserId int Email string Password string } type PeerInfo struct { PeerId string Owner string Assign []string Online bool `json:"-"` Build string Name string Players int Public bool Secret string External string } type SessionInfo struct { SessionId string Email string UserId int HostPeerId string Role string AttemptId string Guid string WsConn *websocket.Conn `json:"-"` } type ParsecService struct { sessionLock sync.Mutex wsSessionLock sync.Mutex peerLock sync.Mutex userLock sync.Mutex Sessions []*SessionInfo `json:"sessions"` WsSessions []*SessionInfo `json:"wsSessions"` Users []*UserInfo `json:"users"` Peers []*PeerInfo `json:"peers"` } func (p *ParsecService) LoadConfig(config *ConfigData) { p.sessionLock.Lock() p.userLock.Lock() p.peerLock.Lock() defer p.sessionLock.Unlock() defer p.userLock.Unlock() defer p.peerLock.Unlock() p.Peers = config.Peers p.Users = config.Users p.Sessions = config.Sessions } func (p *ParsecService) Login(email string, password string) *UserInfo { p.userLock.Lock() defer p.userLock.Unlock() for _, user := range p.Users { if user.Email == email && user.Password == password { return user } } return nil } func (p *ParsecService) AddUser(email string, password string) *UserInfo { p.userLock.Lock() defer p.userLock.Unlock() for _, user := range p.Users { if user.Email == email { return user } } newUserId := 0 for i := LastUserId + 1; i < 10000; i++ { exist := false for _, user := range p.Users { if user.UserId == i { exist = true break } } if !exist { newUserId = i LastUserId = i break } } tmp := &UserInfo{ UserId: newUserId, Email: email, Password: password, } p.Users = append(p.Users, tmp) return tmp } func (p *ParsecService) GetUserByEmail(email string) *UserInfo { p.userLock.Lock() defer p.userLock.Unlock() for _, user := range p.Users { if user.Email == email { return user } } return nil } func (p *ParsecService) CheckUserExist(email string) bool { p.userLock.Lock() defer p.userLock.Unlock() for _, user := range p.Users { if user.Email == email { return true } } return false } func (p *ParsecService) AddPeer(email string) *PeerInfo { p.peerLock.Lock() defer p.peerLock.Unlock() newPeerId := GetRandomString(27) for { exist := false for _, peer := range p.Peers { if peer.PeerId == newPeerId { exist = true break } } if exist { newPeerId = GetRandomString(27) } else { break } } peer := &PeerInfo{ PeerId: newPeerId, Owner: email, Assign: []string{}, } p.Peers = append(p.Peers, peer) return peer } func (p *ParsecService) GetPeer(peerId string) *PeerInfo { p.peerLock.Lock() defer p.peerLock.Unlock() for _, peer := range p.Peers { if peer.PeerId == peerId { return peer } } return nil } func (p *ParsecService) NewSession(email string, userId int, PeerId string) *SessionInfo { p.sessionLock.Lock() defer p.sessionLock.Unlock() r := rand.New(rand.NewSource(time.Now().UnixNano())) sessionId := GetSHA256HashCode([]byte(strconv.Itoa(r.Intn(999999)))) for { exist := false for _, session := range p.Sessions { if session.SessionId == sessionId { exist = true break } } if exist { sessionId = GetSHA256HashCode([]byte(strconv.Itoa(r.Intn(999999)))) } else { break } } session := &SessionInfo{ SessionId: sessionId, Email: email, UserId: userId, HostPeerId: PeerId, } p.Sessions = append(p.Sessions, session) return session } func (p *ParsecService) NewWsSession(sessionId string, role string, guid string, wsConn *websocket.Conn) *SessionInfo { p.wsSessionLock.Lock() defer p.wsSessionLock.Unlock() session := p.GetSession(sessionId) if session != nil { for _, wsSession := range p.WsSessions { if wsSession.SessionId == sessionId && wsSession.Role == role { wsSession.WsConn = wsConn wsSession.Guid = guid return wsSession } } wsSession := &SessionInfo{ SessionId: session.SessionId, Email: session.Email, UserId: session.UserId, HostPeerId: session.HostPeerId, Role: role, Guid: guid, WsConn: wsConn, } p.WsSessions = append(p.WsSessions, wsSession) return wsSession } return nil } func (p *ParsecService) RemoveWsSession(sessionId string, role string, sessionGuid string) { p.wsSessionLock.Lock() defer p.wsSessionLock.Unlock() var tmp []*SessionInfo for _, session := range p.WsSessions { if !(session.SessionId == sessionId && session.Role == role && session.Guid == sessionGuid) { tmp = append(tmp, session) } } p.WsSessions = tmp } func (p *ParsecService) SetupOnlineStatus(hostPeer *PeerInfo) { p.wsSessionLock.Lock() defer p.wsSessionLock.Unlock() for _, session := range p.WsSessions { if session.HostPeerId == hostPeer.PeerId { return } } hostPeer.Online = false } func (p *ParsecService) GetWsSessionByPeerId(role string, peerId string) *SessionInfo { p.wsSessionLock.Lock() defer p.wsSessionLock.Unlock() for _, session := range p.WsSessions { if session.Role == role && session.HostPeerId == peerId { return session } } return nil } func (p *ParsecService) GetWsSessionByAttemptId(peerId string, attemptId string) *SessionInfo { p.wsSessionLock.Lock() defer p.wsSessionLock.Unlock() for _, session := range p.WsSessions { if session.AttemptId == attemptId && session.HostPeerId == peerId { return session } } return nil } func (p *ParsecService) GetSession(sessionId string) *SessionInfo { p.sessionLock.Lock() defer p.sessionLock.Unlock() for _, session := range p.Sessions { if session.SessionId == sessionId { return session } } return nil } func (p *ParsecService) GetPeersByEmail(email string) []*PeerInfo { p.peerLock.Lock() defer p.peerLock.Unlock() var peers []*PeerInfo for _, peer := range p.Peers { if peer.Owner == email || StringListContain(peer.Assign, email) { peers = append(peers, peer) } } return peers } func (p *ParsecService) RemoveUser(email string) { p.userLock.Lock() defer p.userLock.Unlock() var tmp []*UserInfo for _, user := range p.Users { if user.Email != email { tmp = append(tmp, user) } } p.Users = tmp } func (p *ParsecService) RemovePeerByUser(email string) { p.peerLock.Lock() defer p.peerLock.Unlock() var tmp []*PeerInfo for _, peer := range p.Peers { if peer.Owner != email { tmp = append(tmp, peer) } } p.Peers = tmp } func (p *ParsecService) RemoveSessionByUser(email string) { p.sessionLock.Lock() defer p.sessionLock.Unlock() var tmp []*SessionInfo for _, session := range p.Sessions { if session.Email != email { tmp = append(tmp, session) } else { if session.WsConn != nil { session.WsConn.Close() } } } p.Sessions = tmp } func (p *ParsecService) RemoveWsSessionByUser(email string) { p.wsSessionLock.Lock() defer p.wsSessionLock.Unlock() var tmp []*SessionInfo for _, session := range p.WsSessions { if session.Email != email { tmp = append(tmp, session) } else { if session.WsConn != nil { session.WsConn.Close() } } } p.WsSessions = tmp } func (p *ParsecService) RemoveSessionByPeerId(peerId string) { p.sessionLock.Lock() defer p.sessionLock.Unlock() var tmp []*SessionInfo for _, session := range p.Sessions { if session.HostPeerId != peerId { tmp = append(tmp, session) } else { if session.WsConn != nil { session.WsConn.Close() } } } p.Sessions = tmp } func (p *ParsecService) RemoveWsSessionByPeerId(peerId string) { p.wsSessionLock.Lock() defer p.wsSessionLock.Unlock() var tmp []*SessionInfo for _, session := range p.WsSessions { if session.HostPeerId != peerId { tmp = append(tmp, session) } else { if session.WsConn != nil { session.WsConn.Close() } } } p.WsSessions = tmp } func (p *ParsecService) AssignAdd(peerId string, email string) { peer := p.GetPeer(peerId) if peer != nil { if !StringListContain(peer.Assign, email) { peer.Assign = append(peer.Assign, email) } } } func (p *ParsecService) AssignClear(peerId string) { peer := p.GetPeer(peerId) if peer != nil { peer.Assign = []string{} } } func (p *ParsecService) AssignRemove(peerId string, email string) { peer := p.GetPeer(peerId) if peer != nil { var tmp []string for _, s := range peer.Assign { if s != email { tmp = append(tmp, s) } } peer.Assign = tmp } } func (p *ParsecService) RemoveOfflinePeers() { p.peerLock.Lock() defer p.peerLock.Unlock() var tmp []*PeerInfo for _, peer := range p.Peers { if peer.Online { tmp = append(tmp, peer) } else { p.RemoveSessionByPeerId(peer.PeerId) p.RemoveWsSessionByPeerId(peer.PeerId) } } p.Peers = tmp }