628 lines
15 KiB
Go
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(), "-", "")
|
|
}
|