Files
fastlink/fastlink_manager.go
wenyifan 60b889a44b init
2022-08-03 10:30:59 +08:00

628 lines
15 KiB
Go

package main
import (
"github.com/beevik/guid"
"github.com/gorilla/websocket"
"math/rand"
"strconv"
"strings"
"sync"
"time"
)
type SessionInfo struct {
SessionId string `json:"sessionId"`
DeviceNo string `json:"deviceNo"`
ClientType string `json:"clientType"`
Guid string `json:"guid"`
WsConn *websocket.Conn `json:"-"`
}
type SignalSessionInfo struct {
Token string `json:"token"`
RelateDeviceId int `json:"relateDeviceId"`
RelateDeviceNo string `json:"relateDeviceNo"`
StreamUser string `json:"streamUser"`
StreamToken string `json:"streamToken"`
CreateTime time.Time `json:"createTime"`
Active bool `json:"active"`
Guid string `json:"guid"`
WsConn *websocket.Conn `json:"-"`
}
type UserInfo struct {
Name string `json:"name"`
Pass string `json:"pass"`
}
type TokenInfo struct {
Token string `json:"token"`
Type string `json:"type"`
User string `json:"user"`
SessionId string `json:"sessionId"`
LastActive time.Time `json:"lastActive"`
}
type DeviceInfo struct {
DeviceNo string `json:"deviceNo"`
DeviceId int `json:"deviceId"`
DeviceName string `json:"deviceName"`
IdentificationCode string `json:"identificationCode"`
VerificationCode string `json:"verificationCode"`
ShareRand string `json:"shareRand"`
BelongUser string `json:"belongUser"`
Visible bool `json:"visible"`
TwoStepPass string `json:"twoStepPass"`
VerificationType int `json:"verificationType"`
CustomName string `json:"customName"`
Online bool `json:"-"`
}
type FastLinkService struct {
sessionLock sync.Mutex
deviceLock sync.Mutex
userLock sync.Mutex
tokenLock sync.Mutex
signalLock sync.Mutex
Sessions []*SessionInfo `json:"sessions"`
Users []*UserInfo `json:"users"`
Devices []*DeviceInfo `json:"devices"`
Tokens []*TokenInfo `json:"tokens"`
SignalSessions []*SignalSessionInfo `json:"signalSessions"`
}
func (f *FastLinkService) FillUsers(users []*UserInfo) {
f.userLock.Lock()
defer f.userLock.Unlock()
f.Users = users
}
func (f *FastLinkService) FillDevices(devices []*DeviceInfo) {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
f.Devices = devices
}
func (f *FastLinkService) FillTokens(tokens []*TokenInfo) {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
f.Tokens = tokens
}
func (f *FastLinkService) NewSession(deviceNo string, sessionId string, sessionGuid string, clientType string, wsConn *websocket.Conn) {
f.sessionLock.Lock()
defer f.sessionLock.Unlock()
for _, session := range f.Sessions {
if session.SessionId == sessionId {
session.DeviceNo = deviceNo
session.WsConn = wsConn
session.ClientType = clientType
session.Guid = sessionGuid
return
}
}
f.Sessions = append(f.Sessions, &SessionInfo{
SessionId: sessionId,
DeviceNo: deviceNo,
WsConn: wsConn,
ClientType: clientType,
Guid: sessionGuid,
})
}
func (f *FastLinkService) SetOnlineStatus(deviceNo string) {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
session := f.GetSession(deviceNo, CLIENT_TYPE_FASTLINK_SERVICE)
for _, device := range f.Devices {
if device.DeviceNo == deviceNo {
if session == nil {
device.Online = false
} else {
device.Online = true
}
return
}
}
}
func (f *FastLinkService) GetSession(deviceNo string, clientType string) *SessionInfo {
f.sessionLock.Lock()
defer f.sessionLock.Unlock()
for _, session := range f.Sessions {
if session.DeviceNo == deviceNo && session.ClientType == clientType {
return session
}
}
return nil
}
func (f *FastLinkService) GetSessionsByUser(user string, clientType string) []*SessionInfo {
f.sessionLock.Lock()
defer f.sessionLock.Unlock()
var result []*SessionInfo
for _, session := range f.Sessions {
device := f.GetDeviceByNo(session.DeviceNo)
if device != nil && device.BelongUser == user && session.ClientType == clientType {
result = append(result, session)
}
}
return result
}
func (f *FastLinkService) PrepareSignalSession(token string, relateDeviceId int, relateDeviceNo string, streamToken string, streamUser string) {
f.signalLock.Lock()
defer f.signalLock.Unlock()
f.SignalSessions = append(f.SignalSessions, &SignalSessionInfo{
Token: token,
RelateDeviceId: relateDeviceId,
RelateDeviceNo: relateDeviceNo,
StreamToken: streamToken,
StreamUser: streamUser,
CreateTime: time.Now().In(TimeLocation),
})
}
func (f *FastLinkService) NewSignalSession(token string, sessionGuid string, wsConn *websocket.Conn) {
f.signalLock.Lock()
defer f.signalLock.Unlock()
for _, session := range f.SignalSessions {
if session.Token == token {
session.WsConn = wsConn
session.Active = true
session.Guid = sessionGuid
return
}
}
f.SignalSessions = append(f.SignalSessions, &SignalSessionInfo{
Token: token,
Active: true,
WsConn: wsConn,
Guid: sessionGuid,
})
}
func (f *FastLinkService) KillAloneSignalSession() {
f.signalLock.Lock()
defer f.signalLock.Unlock()
var tmp []*SignalSessionInfo
for _, session := range f.SignalSessions {
if session.Active == false && session.RelateDeviceNo != "" {
if time.Now().In(TimeLocation).Sub(session.CreateTime.In(TimeLocation)).Seconds() > 120 {
continue
}
}
tmp = append(tmp, session)
}
f.SignalSessions = tmp
}
func (f *FastLinkService) RemoveSession(sessionId string, sessionGuid string) {
f.sessionLock.Lock()
defer f.sessionLock.Unlock()
var tmp []*SessionInfo
needRemove := false
for _, session := range f.Sessions {
if session.SessionId == sessionId && session.Guid == sessionGuid {
needRemove = true
break
}
}
if needRemove {
for _, session := range f.Sessions {
if session.SessionId != sessionId {
tmp = append(tmp, session)
}
}
f.Sessions = tmp
}
}
func (f *FastLinkService) RemoveSignalSession(token string, sessionGuid string) {
f.signalLock.Lock()
defer f.signalLock.Unlock()
var tmp []*SignalSessionInfo
needRemove := false
for _, session := range f.SignalSessions {
if session.Token == token && session.Guid == sessionGuid {
needRemove = true
break
}
}
if needRemove {
for _, session := range f.SignalSessions {
if session.Token != token {
tmp = append(tmp, session)
}
}
f.SignalSessions = tmp
}
}
func (f *FastLinkService) GetSignalSession(token string) *SignalSessionInfo {
f.signalLock.Lock()
defer f.signalLock.Unlock()
for _, session := range f.SignalSessions {
if session.Token == token {
return session
}
}
return nil
}
func (f *FastLinkService) GetSignalSessionByDeviceId(deviceId int) []*SignalSessionInfo {
f.signalLock.Lock()
defer f.signalLock.Unlock()
var result []*SignalSessionInfo
for _, session := range f.SignalSessions {
if session.RelateDeviceId == deviceId {
result = append(result, session)
}
}
return result
}
func (f *FastLinkService) AddDevice(deviceNo string, deviceName string) *DeviceInfo {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
for _, device := range f.Devices {
if device.DeviceNo == deviceNo {
device.DeviceName = deviceName
return device
}
}
newDeviceId := 0
for i := LastDeviceId + 1; i < 10000; i++ {
exist := false
for _, device := range f.Devices {
if device.DeviceId == i {
exist = true
break
}
}
if !exist {
newDeviceId = i
LastDeviceId = i
break
}
}
identificationCode := RandNum(9)
for {
exist := false
for _, device := range f.Devices {
if device.IdentificationCode == identificationCode {
exist = true
break
}
}
if exist {
identificationCode = RandNum(9)
} else {
break
}
}
device := &DeviceInfo{
DeviceNo: deviceNo,
DeviceId: newDeviceId,
DeviceName: deviceName,
IdentificationCode: identificationCode,
VerificationCode: RandStr(6),
ShareRand: "1" + RandNum(9),
BelongUser: "",
Online: true,
Visible: true,
}
f.Devices = append(f.Devices, device)
return device
}
func (f *FastLinkService) RefreshDeviceVerificationCode(deviceNo string) *DeviceInfo {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
for _, device := range f.Devices {
if device.DeviceNo == deviceNo {
device.VerificationCode = RandStr(6)
device.ShareRand = "1" + RandNum(9)
return device
}
}
return nil
}
func (f *FastLinkService) GetDeviceByNo(deviceNo string) *DeviceInfo {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
for _, device := range f.Devices {
if device.DeviceNo == deviceNo {
return device
}
}
return nil
}
func (f *FastLinkService) removeDevice(deviceNo string) {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
var tmp []*DeviceInfo
for _, device := range f.Devices {
if device.DeviceNo != deviceNo {
tmp = append(tmp, device)
}
}
f.Devices = tmp
}
func (f *FastLinkService) GetDeviceByIdentificationCode(identificationCode string) *DeviceInfo {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
for _, device := range f.Devices {
if device.IdentificationCode == identificationCode {
return device
}
}
return nil
}
func (f *FastLinkService) GetDeviceById(deviceId int) *DeviceInfo {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
for _, device := range f.Devices {
if device.DeviceId == deviceId {
return device
}
}
return nil
}
func (f *FastLinkService) AddUser(username string, password string) *UserInfo {
f.userLock.Lock()
defer f.userLock.Unlock()
for _, user := range f.Users {
if user.Name == username {
return user
}
}
u := &UserInfo{
Name: username,
Pass: password,
}
f.Users = append(f.Users, u)
return u
}
func (f *FastLinkService) Login(username string, password string, deviceId int) string {
f.userLock.Lock()
defer f.userLock.Unlock()
succ := false
for _, user := range f.Users {
if user.Name == username && user.Pass == password {
succ = true
break
}
}
if !succ {
return ""
}
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
for _, device := range f.Devices {
if device.DeviceId == deviceId {
device.BelongUser = username
}
}
return f.NewToken(username, TOKEN_TYPE_PC)
}
func (f *FastLinkService) CheckUser(username string, password string) bool {
f.userLock.Lock()
defer f.userLock.Unlock()
for _, user := range f.Users {
if user.Name == username && user.Pass == password {
return true
}
}
return false
}
func (f *FastLinkService) CheckUserExist(username string) bool {
f.userLock.Lock()
defer f.userLock.Unlock()
for _, user := range f.Users {
if user.Name == username {
return true
}
}
return false
}
func (f *FastLinkService) EditUser(username string, password string) {
f.userLock.Lock()
defer f.userLock.Unlock()
for _, user := range f.Users {
if user.Name == username {
user.Pass = password
}
}
}
func (f *FastLinkService) removeUser(username string) {
f.userLock.Lock()
defer f.userLock.Unlock()
var tmp []*UserInfo
for _, user := range f.Users {
if user.Name != username {
tmp = append(tmp, user)
}
}
f.Users = tmp
}
func (f *FastLinkService) removeDevicesByUser(username string) {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
var tmp []*DeviceInfo
for _, device := range f.Devices {
if device.BelongUser != username {
tmp = append(tmp, device)
}
}
f.Devices = tmp
}
func (f *FastLinkService) removeTokenByUser(username string) {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
var tmp []*TokenInfo
for _, token := range f.Tokens {
if token.User != username {
tmp = append(tmp, token)
}
}
f.Tokens = tmp
}
func (f *FastLinkService) GetUserByToken(token string) string {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
for _, info := range f.Tokens {
if info.Token == token {
return info.User
}
}
return ""
}
func (f *FastLinkService) GetDeviceByToken(token string) []*DeviceInfo {
user := f.GetUserByToken(token)
if user == "" {
return []*DeviceInfo{}
}
f.RenewToken(token)
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
var dList []*DeviceInfo
for _, device := range f.Devices {
if device.BelongUser == user && device.Visible {
dList = append(dList, device)
}
}
return dList
}
func (f *FastLinkService) NewToken(username string, tokenType string) string {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
token := guid.New().String()
f.Tokens = append(f.Tokens, &TokenInfo{
Token: token,
User: username,
Type: tokenType,
LastActive: time.Now().In(TimeLocation),
})
return token
}
func (f *FastLinkService) BindSessionToToken(sessionId string, token string) {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
for _, info := range f.Tokens {
if info.Token == token {
info.SessionId = sessionId
return
}
}
}
func (f *FastLinkService) GetTokenBySession(sessionId string) string {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
for _, info := range f.Tokens {
if info.SessionId == sessionId {
return info.Token
}
}
return ""
}
func (f *FastLinkService) RemoveToken(token string) {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
var tmp []*TokenInfo
for _, info := range f.Tokens {
if info.Token != token {
tmp = append(tmp, info)
}
}
f.Tokens = tmp
}
func (f *FastLinkService) RenewToken(token string) {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
for _, info := range f.Tokens {
if info.Token == token {
info.LastActive = time.Now().In(TimeLocation)
}
}
}
func (f *FastLinkService) KillExpiredToken() {
f.tokenLock.Lock()
defer f.tokenLock.Unlock()
var tmp []*TokenInfo
for _, info := range f.Tokens {
life := TOKEN_APP_MAX_LIFE
if info.Type == "pc" {
life = TOKEN_PC_MAX_LIFE
}
if time.Now().In(TimeLocation).Sub(info.LastActive.In(TimeLocation)).Seconds() <= float64(life) {
tmp = append(tmp, info)
} else {
Logger.Println("Remove expired token:" + info.Token + ", LastActive time=" + info.LastActive.In(TimeLocation).Format("2006-01-02 15:04:05"))
}
}
f.Tokens = tmp
}
func (f *FastLinkService) CheckWebLogin(deviceNo string, random string) int {
f.deviceLock.Lock()
defer f.deviceLock.Unlock()
for _, device := range f.Devices {
if device.DeviceNo == deviceNo {
if device.ShareRand == random {
return 0
} else {
return 1
}
}
}
return 2
}
func RandNum(length int) string {
var result string
for i := 0; i < length; i++ {
result += strconv.Itoa(rand.Intn(9))
}
return result
}
func RandStr(length int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyz"
bytes := []byte(str)
result := []byte{}
rand.Seed(time.Now().UnixNano() + int64(rand.Intn(100)))
for i := 0; i < length; i++ {
result = append(result, bytes[rand.Intn(len(bytes))])
}
return string(result)
}
func GenShortGUID() string {
return strings.ReplaceAll(guid.New().String(), "-", "")
}