init
This commit is contained in:
commit
60b889a44b
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.idea
|
||||
fastlink
|
||||
fastlink.exe
|
||||
session
|
||||
*.zip
|
||||
config.conf
|
32
9d18eed7.0
Normal file
32
9d18eed7.0
Normal file
@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
YY8=
|
||||
-----END CERTIFICATE-----
|
32
Evan_Assurance_Root_CA.crt
Normal file
32
Evan_Assurance_Root_CA.crt
Normal file
@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
YY8=
|
||||
-----END CERTIFICATE-----
|
BIN
app/FastLink_android_v1.1.8_14-16.apk
Normal file
BIN
app/FastLink_android_v1.1.8_14-16.apk
Normal file
Binary file not shown.
BIN
app/FastlinkSetup_v1.4.2.0.exe
Normal file
BIN
app/FastlinkSetup_v1.4.2.0.exe
Normal file
Binary file not shown.
BIN
app/fastlink.apk
Normal file
BIN
app/fastlink.apk
Normal file
Binary file not shown.
3
build.bat
Normal file
3
build.bat
Normal file
@ -0,0 +1,3 @@
|
||||
packr build -ldflags "-s -w" -trimpath
|
||||
set GOOS=linux
|
||||
packr build -ldflags "-s -w" -trimpath
|
82
cert.crt
Normal file
82
cert.crt
Normal file
@ -0,0 +1,82 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDyzCCArOgAwIBAgIIcK3jv9ks97kwDQYJKoZIhvcNAQELBQAwRTELMAkGA1UE
|
||||
BhMCQ04xDTALBgNVBAoTBEV2YW4xDTALBgNVBAsTBEV2YW4xGDAWBgNVBAMTD0V2
|
||||
YW4gVExTIFJTQSBDQTAeFw0yMjAzMjQwMDAwMDBaFw0yMzAzMjMyMzU5NTlaMEcx
|
||||
CzAJBgNVBAYTAkNOMQ0wCwYDVQQKEwRFdmFuMQ0wCwYDVQQLEwRFdmFuMRowGAYD
|
||||
VQQDExFFdmFuIEZhc3RsaW5rIFRMUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||
AQoCggEBALv0Mo21LKTJjFCZcgzWQX5cffJdb2fTObCBv0fkU+0OlsILJYePSD59
|
||||
/kn59jG9oSwFgFv0Rsr73hg1NRY2+StNslo1eRh8jd0dyQXXaX1cmm3GxrlS0xY5
|
||||
WEdGYSNrqTEhloBq1bMEmZCAVc7gKemektvOAE0wtZcWILT8B1mo5bkn/ROdhJzW
|
||||
DBWlZQQRUt5eqxQRVGGllP9k1BUki/ZonA6RdEKzaRl3baUf3MY8tW4S4Sk5yR7W
|
||||
X8VRZPjCFUFjrFDoFtFCZIziaB6OeTnDmi0+evkPUoUvW4+xFjoWgC/eGYNe2i/k
|
||||
65Emy5vCmChPrwn3PMDjl+4/cKdM4T0CAwEAAaOBvDCBuTAMBgNVHRMBAf8EAjAA
|
||||
MB0GA1UdDgQWBBRkwj6Ebx5tnVn21zfPkq/k+WI8aTAfBgNVHSMEGDAWgBTkzE//
|
||||
yCDVeD30iijpcqJ4vgc95jALBgNVHQ8EBAMCA+gwHQYDVR0lBBYwFAYIKwYBBQUH
|
||||
AwEGCCsGAQUFBwMCMCoGA1UdEQQjMCGCEmZhc3RsaW5rLmljbG91ZC5jboILKi5p
|
||||
Y2xvdWQuY24wEQYJYIZIAYb4QgEBBAQDAgbAMA0GCSqGSIb3DQEBCwUAA4IBAQAd
|
||||
F1m3sw3Ygf8ISoMeaGvMS2qhDiCqZoICy0YEQWuuMowmPVr+6y+dGPbCPCGx/V/+
|
||||
aD8TH8ZfmlNYz0QYohtWVzsDUdmb/dZkMijFaqWf77QwzA1/ObUUOL3xvE8+8rLD
|
||||
TvLx7Wg8vVntPnG/3EocW//F+tvoDDE626Moxx02iFxdt7OKkntr5C/CQCIAXSbj
|
||||
jCzo4GsByGRmGv4jvez1fZ4/MoRcwH19tpoJLEINU9JDm78E0rt9DNKR3f1vPQBO
|
||||
AR4NKmlZLxPKbhnEgvKbGgIG5R66tHcL4JF4DI/J/bEFK3vWwVfufRA84wKUK07l
|
||||
w74dNHVmcL3sq9SvK7At
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEhDCCAmygAwIBAgIIUw9sncwT5HcwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UE
|
||||
BhMCQ04xDTALBgNVBAoTBEV2YW4xDTALBgNVBAsTBEV2YW4xHzAdBgNVBAMTFkV2
|
||||
YW4gQXNzdXJhbmNlIFJvb3QgQ0EwHhcNMjIwMTAxMDAwMDAwWhcNMzIxMjMxMjM1
|
||||
OTU5WjBFMQswCQYDVQQGEwJDTjENMAsGA1UEChMERXZhbjENMAsGA1UECxMERXZh
|
||||
bjEYMBYGA1UEAxMPRXZhbiBUTFMgUlNBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||
AQ8AMIIBCgKCAQEAox2P/00Y8RimWNxKi/iA3ERywf21imyNy+v8d47Bg2iH8PaZ
|
||||
RAKYya19OkLQOsWFCS6L8/Bx/c/HPZfMOS62ro9IQ6D5UWP0rK0nSd7gvUU63f6K
|
||||
6ZJ5LR1owAVx0xZ9b+sL89J+VlNuVR8+SjYx2OlOUonk3IPHkvm9WCtFMA2bkHjd
|
||||
uG2KSJTn4roXr5nVhIi53RnSaiyBlRJ0OeJ2IPgmA/U5v/0Rr2I3YN7NJ/n+3bCO
|
||||
kNeX/o3qa+C4PoedXfnlIGJyqcc3l6SCSsZ5IFyvQDgE8kuO9UYXk/jFQnYyHsNb
|
||||
QA/ZiiR2mzQ12eeDxaqZAYYeC0ys/OL7ZvZt5QIDAQABo3EwbzAPBgNVHRMBAf8E
|
||||
BTADAQH/MB0GA1UdDgQWBBTkzE//yCDVeD30iijpcqJ4vgc95jALBgNVHQ8EBAMC
|
||||
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBEGCWCGSAGG+EIBAQQE
|
||||
AwIAxzANBgkqhkiG9w0BAQsFAAOCAgEAPcEmb/L749blVCP5+RDFN+lS78MYQyMT
|
||||
ZikN3AJP6pV5pTM3uc+zD+sproRslJum7DkeuPn2WltRN3bcB4cemvFMZyx0luFc
|
||||
XVJ3Gy+wx0L0JexBri5B9iFovZaHxKM0uaBmHDyHfGV6NhsFJWlPL9XQTRQD6EQ4
|
||||
meWRNpEs+W5RCXMMQ7VqyRLovC4OdbnPkyZv+UGKajGzGPzm6hZfG3bA5TxSFney
|
||||
ZerpxSnLASkzAe1w5G91RU3dPKPiULJq01l5uv2fy7p5KYDWSqxOrB0KvpZtAVRx
|
||||
6VbmFEogmG66M2OGEm9ptz4FOh08KsTfcuS3KWiyVjBi/IcqzbOMWkkIrw0SM7Bu
|
||||
tbgIrS4bbYUFfCJqYsRw0Nfmn1Ndll2sLD3iTqL5kqSaAsI9zGyEn5QPnZCGvx3R
|
||||
ryAHAI+ImvfFMZjvbZ95++IBJ/7CDYlp25oVd/JBzxq2fpNqO+Z5r4Cg+UFve1uU
|
||||
c6M1KGeKF15sQi69gkbcUPQpYaxT5+zTag88V0NIwhuGgmaMvvo1vN5O+tziL4B4
|
||||
HxJNaUJbv2rolJ7stspw8C6L6daP+7qfyIaZONJCGEXt46V4mDH9vV5/JWyhhuSE
|
||||
rL39I9OzjaUhsooodJwcKUuU1BAzg3oaXxANzEPMILDHo7dPDWkY+JoVa/VW5Huc
|
||||
2kzz4/hrJdU=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
YY8=
|
||||
-----END CERTIFICATE-----
|
189
fastlink.go
Normal file
189
fastlink.go
Normal file
@ -0,0 +1,189 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/gobuffalo/packr"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
Logger = log.New(io.Writer(os.Stdout), "", log.Lshortfile|log.LstdFlags)
|
||||
rand.Seed(time.Now().Unix())
|
||||
var port string
|
||||
var address string
|
||||
flag.StringVar(&port, "port", "1443", "serve port")
|
||||
flag.StringVar(&address, "listen", "", "listen address")
|
||||
flag.StringVar(&configPath, "config", "config.conf", "config path")
|
||||
flag.Parse()
|
||||
|
||||
fastLinkService = new(FastLinkService)
|
||||
ReadConfig()
|
||||
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, os.Kill)
|
||||
go func() {
|
||||
<-c //阻塞直至有信号传入
|
||||
Logger.Println("Saving config")
|
||||
SaveConfig()
|
||||
Logger.Println("Save config done,exit now.")
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(time.Minute)
|
||||
for range ticker.C {
|
||||
<-ticker.C
|
||||
fastLinkService.KillAloneSignalSession()
|
||||
fastLinkService.KillExpiredToken()
|
||||
SaveConfig()
|
||||
Logger.Println("Saving config")
|
||||
ticker.Reset(time.Minute)
|
||||
}
|
||||
}()
|
||||
|
||||
http.HandleFunc("/admin/config", configHandler)
|
||||
http.HandleFunc("/admin/addUser", addUserHandler)
|
||||
http.HandleFunc("/admin/editUser", editUserHandler)
|
||||
http.HandleFunc("/admin/removeUser", removeUserHandler)
|
||||
http.HandleFunc("/admin/kickUser", kickUserHandler)
|
||||
http.HandleFunc("/admin/removeDevice", removeDeviceHandler)
|
||||
http.HandleFunc("/admin/removeCustomName", removeCustomNameHandler)
|
||||
http.HandleFunc("/socket.io/", socketHandler)
|
||||
http.HandleFunc("/fastLink/shareUrl/connect/check", checkHandler)
|
||||
http.HandleFunc("/fastLink/device/deviceVerificationType", deviceVerificationTypeHandler)
|
||||
http.HandleFunc("/fastLink/config/idTransfer", idTransferHandler)
|
||||
http.HandleFunc("/fastLink/stream/record/close", closeHandler)
|
||||
http.HandleFunc("/fastLink/user/loginForApp", loginForAppHandler)
|
||||
http.HandleFunc("/fastLink/device/list", appListDeviceHandler)
|
||||
http.HandleFunc("/fastLink/user/logout", logoutHandler)
|
||||
http.HandleFunc("/fastLink/user/register", registerHandler)
|
||||
http.HandleFunc("/fastLink/code/send", sendCodeHandler)
|
||||
|
||||
box := packr.NewBox("web")
|
||||
http.Handle("/", http.FileServer(box))
|
||||
|
||||
err := http.ListenAndServeTLS(address+":"+port, "cert.crt", "private.key", nil)
|
||||
//套nginx或Caddy可直接使用Http
|
||||
//err := http.ListenAndServe(address+":"+port, nil)
|
||||
if err != nil {
|
||||
fmt.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
func socketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
clientType := r.FormValue("clientType")
|
||||
|
||||
if clientType == CLIENT_TYPE_CPP || clientType == CLIENT_TYPE_WEB {
|
||||
signalHandler(w, r)
|
||||
} else {
|
||||
serviceHandler(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func configHandler(w http.ResponseWriter, r *http.Request) {
|
||||
marshal, _ := json.Marshal(fastLinkService)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func addUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.FormValue("user")
|
||||
pass := r.FormValue("pass")
|
||||
if user == "" {
|
||||
w.Write([]byte("user is empty"))
|
||||
return
|
||||
}
|
||||
if pass == "" {
|
||||
w.Write([]byte("pass is empty"))
|
||||
return
|
||||
}
|
||||
exist := fastLinkService.CheckUserExist(user)
|
||||
if exist {
|
||||
w.Write([]byte("user exist"))
|
||||
return
|
||||
}
|
||||
fastLinkService.AddUser(user, pass)
|
||||
w.Write([]byte("success"))
|
||||
}
|
||||
|
||||
func editUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.FormValue("user")
|
||||
pass := r.FormValue("pass")
|
||||
if user == "" {
|
||||
w.Write([]byte("user is empty"))
|
||||
return
|
||||
}
|
||||
if pass == "" {
|
||||
w.Write([]byte("pass is empty"))
|
||||
return
|
||||
}
|
||||
exist := fastLinkService.CheckUserExist(user)
|
||||
if !exist {
|
||||
w.Write([]byte("user not exist"))
|
||||
return
|
||||
}
|
||||
fastLinkService.EditUser(user, pass)
|
||||
w.Write([]byte("success"))
|
||||
}
|
||||
|
||||
func removeUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.FormValue("user")
|
||||
if user == "" {
|
||||
w.Write([]byte("user is empty"))
|
||||
return
|
||||
}
|
||||
fastLinkService.removeUser(user)
|
||||
fastLinkService.removeDevicesByUser(user)
|
||||
fastLinkService.removeTokenByUser(user)
|
||||
w.Write([]byte("success"))
|
||||
}
|
||||
|
||||
func kickUserHandler(w http.ResponseWriter, r *http.Request) {
|
||||
user := r.FormValue("user")
|
||||
if user == "" {
|
||||
w.Write([]byte("user is empty"))
|
||||
return
|
||||
}
|
||||
fastLinkService.removeTokenByUser(user)
|
||||
w.Write([]byte("success"))
|
||||
}
|
||||
|
||||
func removeDeviceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
deviceNo := r.FormValue("deviceNo")
|
||||
if deviceNo == "" {
|
||||
w.Write([]byte("deviceNo is empty"))
|
||||
return
|
||||
}
|
||||
device := fastLinkService.GetDeviceByNo(deviceNo)
|
||||
if device != nil {
|
||||
user := device.BelongUser
|
||||
fastLinkService.removeDevice(deviceNo)
|
||||
if user != "" {
|
||||
notifyDeviceChange(user)
|
||||
}
|
||||
}
|
||||
w.Write([]byte("success"))
|
||||
}
|
||||
|
||||
func removeCustomNameHandler(w http.ResponseWriter, r *http.Request) {
|
||||
deviceNo := r.FormValue("deviceNo")
|
||||
if deviceNo == "" {
|
||||
w.Write([]byte("deviceNo is empty"))
|
||||
return
|
||||
}
|
||||
device := fastLinkService.GetDeviceByNo(deviceNo)
|
||||
if device != nil {
|
||||
device.CustomName = ""
|
||||
if device.BelongUser != "" {
|
||||
notifyDeviceChange(device.BelongUser)
|
||||
}
|
||||
}
|
||||
w.Write([]byte("success"))
|
||||
}
|
627
fastlink_manager.go
Normal file
627
fastlink_manager.go
Normal file
@ -0,0 +1,627 @@
|
||||
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(), "-", "")
|
||||
}
|
54
fastlink_test.go
Normal file
54
fastlink_test.go
Normal file
@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/beevik/guid"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
var params *MessageResponse
|
||||
params = &MessageResponse{
|
||||
Id: "fsdgsdgsdg",
|
||||
Method: "Add",
|
||||
Result: &AddDeviceResponse{
|
||||
Code: 0,
|
||||
DeviceId: 453565,
|
||||
},
|
||||
}
|
||||
response := makeMessageResponse("fff", params)
|
||||
fmt.Println(string(response))
|
||||
}
|
||||
|
||||
func TestName2(t *testing.T) {
|
||||
fmt.Println(guid.New().String())
|
||||
}
|
||||
|
||||
func TestName3(t *testing.T) {
|
||||
var items []interface{}
|
||||
json.Unmarshal([]byte("[\"owt-message\",{\"data\":\"{\\\"type\\\":\\\"chat-reset\\\"}\",\"from\":\"5ff5fce328f74b8f964fd282f0c4e1b8\",\"to\":\"b5f5ceab-d964-5f41-a7b7-e16f197f0692\"}]"), &items)
|
||||
s := items[1].(map[string]interface{})["data"].(string)
|
||||
fmt.Println(s)
|
||||
}
|
||||
|
||||
func TestName4(t *testing.T) {
|
||||
toString := base64.StdEncoding.EncodeToString([]byte("b5f5ceab-d964-5f41-a7b7-e16f197f0692"))
|
||||
fmt.Println(toString)
|
||||
|
||||
decodeString, _ := base64.StdEncoding.DecodeString("YjVmNWNlYWItZDk2NC01ZjQxLWE3YjctZTE2ZjE5N2YwNjky")
|
||||
fmt.Println(string(decodeString))
|
||||
}
|
||||
|
||||
func TestAAA(t *testing.T) {
|
||||
str := "{\"id\":\"182ade4f-b515-8e4f-bf19-4d2b10f651a5\",\"method\":\"NotifyClientOffline\",\"params\":{\"clientIds\":[\"7bc127b80aea4ab598dd35ac589752e1\"],\"reason\":3}}"
|
||||
|
||||
var item MessageInfo
|
||||
json.Unmarshal([]byte(str), &item)
|
||||
uuu := item.Params.(map[string]interface{})["clientIds"].([]interface{})
|
||||
for _, i2 := range uuu {
|
||||
fmt.Println(i2)
|
||||
}
|
||||
|
||||
}
|
94
global.go
Normal file
94
global.go
Normal file
@ -0,0 +1,94 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
const CLIENT_TYPE_CPP = "cpp"
|
||||
const CLIENT_TYPE_WEB = "Web"
|
||||
const CLIENT_TYPE_FASTLINK_UI = "fastlink_ui"
|
||||
const CLIENT_TYPE_FASTLINK_SERVICE = "fastlink_service"
|
||||
const TOKEN_TYPE_APP = "app"
|
||||
const TOKEN_TYPE_PC = "pc"
|
||||
const TOKEN_PC_MAX_LIFE = 3600
|
||||
const TOKEN_APP_MAX_LIFE = 86400
|
||||
const WEB_URL = "https://fastlink.evan.run/"
|
||||
|
||||
var (
|
||||
Logger *log.Logger
|
||||
fastLinkService *FastLinkService
|
||||
globalConfig = GlobalConfig{
|
||||
SignalServer: "https://fastlink.evan.run",
|
||||
StunServers: []string{"stun:106.54.197.45:3478"},
|
||||
TurnServers: []TurnServer{{
|
||||
Addr: "turn:106.54.197.45:3478",
|
||||
Password: "evanturn",
|
||||
UserName: "evan",
|
||||
}, {
|
||||
Addr: "turn:221.229.220.67:3478",
|
||||
Password: "evanturn",
|
||||
UserName: "evan",
|
||||
}},
|
||||
}
|
||||
configPath string
|
||||
LastDeviceId = 0
|
||||
TimeLocation *time.Location = time.FixedZone("CST", 8*3600)
|
||||
)
|
||||
|
||||
type GlobalConfig struct {
|
||||
SignalServer string `json:"signalServer"`
|
||||
StunServers []string `json:"stunServers"`
|
||||
TurnServers []TurnServer `json:"turnServers"`
|
||||
}
|
||||
|
||||
type TurnServer struct {
|
||||
Addr string `json:"addr"`
|
||||
Password string `json:"password"`
|
||||
UserName string `json:"userName"`
|
||||
}
|
||||
|
||||
type ConfigData struct {
|
||||
LastDeviceId int `json:"lastDeviceId"`
|
||||
Users []*UserInfo `json:"users"`
|
||||
Devices []*DeviceInfo `json:"devices"`
|
||||
Tokens []*TokenInfo `json:"tokens"`
|
||||
}
|
||||
|
||||
func SaveConfig() {
|
||||
config := &ConfigData{
|
||||
Users: fastLinkService.Users,
|
||||
Devices: fastLinkService.Devices,
|
||||
Tokens: fastLinkService.Tokens,
|
||||
LastDeviceId: LastDeviceId,
|
||||
}
|
||||
marshal, _ := json.Marshal(config)
|
||||
ioutil.WriteFile(configPath, marshal, 0777)
|
||||
}
|
||||
|
||||
func ReadConfig() {
|
||||
b, _ := exists(configPath)
|
||||
if b {
|
||||
configData, _ := ioutil.ReadFile(configPath)
|
||||
var config *ConfigData
|
||||
json.Unmarshal(configData, &config)
|
||||
fastLinkService.FillUsers(config.Users)
|
||||
fastLinkService.FillDevices(config.Devices)
|
||||
fastLinkService.FillTokens(config.Tokens)
|
||||
LastDeviceId = config.LastDeviceId
|
||||
}
|
||||
}
|
||||
|
||||
func exists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return true, err
|
||||
}
|
16
go.mod
Normal file
16
go.mod
Normal file
@ -0,0 +1,16 @@
|
||||
module fastlink
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/beevik/guid v0.0.0-20170504223318-d0ea8faecee0
|
||||
github.com/gobuffalo/packr v1.30.1
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/gobuffalo/envy v1.7.0 // indirect
|
||||
github.com/gobuffalo/packd v0.3.0 // indirect
|
||||
github.com/joho/godotenv v1.3.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.3.0 // indirect
|
||||
)
|
73
go.sum
Normal file
73
go.sum
Normal file
@ -0,0 +1,73 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beevik/guid v0.0.0-20170504223318-d0ea8faecee0 h1:oLd/YLOTOgA4D4aAUhIE8vhl/LAP1ZJrj0mDQpl7GB8=
|
||||
github.com/beevik/guid v0.0.0-20170504223318-d0ea8faecee0/go.mod h1:XzXWuOd1wJ63MtICHh5+PnvCuxsB/d58T8TswEhI/9I=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
|
||||
github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
|
||||
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
|
||||
github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg=
|
||||
github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk=
|
||||
github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
3
host.txt
Normal file
3
host.txt
Normal file
@ -0,0 +1,3 @@
|
||||
106.54.197.45 fastlink.icloud.cn
|
||||
106.54.197.45 signalserver.icloud.cn
|
||||
127.0.0.1 datapolaris.shunwang.com
|
27
private.key
Normal file
27
private.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAu/QyjbUspMmMUJlyDNZBflx98l1vZ9M5sIG/R+RT7Q6Wwgsl
|
||||
h49IPn3+Sfn2Mb2hLAWAW/RGyvveGDU1Fjb5K02yWjV5GHyN3R3JBddpfVyabcbG
|
||||
uVLTFjlYR0ZhI2upMSGWgGrVswSZkIBVzuAp6Z6S284ATTC1lxYgtPwHWajluSf9
|
||||
E52EnNYMFaVlBBFS3l6rFBFUYaWU/2TUFSSL9micDpF0QrNpGXdtpR/cxjy1bhLh
|
||||
KTnJHtZfxVFk+MIVQWOsUOgW0UJkjOJoHo55OcOaLT56+Q9ShS9bj7EWOhaAL94Z
|
||||
g17aL+TrkSbLm8KYKE+vCfc8wOOX7j9wp0zhPQIDAQABAoIBAQCG2JVoe8Jy27MS
|
||||
pHRh51oHuX4W45gpCi9KhlvgzVy1KBFbWDntvwua4jQNiQtr9lvqxGuqDWC5Auj9
|
||||
vza+IGS1/8Fk3RZrTflN2a++xCSH72dQORucHGMbf7rpMAJDMlupxyo+Kef1zugJ
|
||||
9zkY+lS3qrA8iNhIiRjPM+31SxhO5xW1XLP8lRi8N5eC3wzp0J0UMWfd+JN+H2Ew
|
||||
rgWNuJ5nmsNq59ZQ9oXNzLvyLmHZIFMrU9hrmSj5qZF8MSsLuzd61Z0Pvs3hHS6u
|
||||
70jjREn9X21UdKezU5c3pOFBG95HR/6t/MHXJzYQ3zT4eV8RwesPn7Hsn2PzNtqM
|
||||
oq7k4T+BAoGBAOomjDmfU0O/bWzbNaFkUdgdF2hyu72Q15icMxiytSYjramjiISD
|
||||
LVKgxG5Ryk5N+42zV6iEa0AIf7PI9YhsHZphJ5xCaayVjeIpXetUrFONMBrJk04j
|
||||
6HJ/7sZQG0EQnC43tcxCfgScnMiC7rNg2cBGdcA3H7AXHs0p1jN95HldAoGBAM1+
|
||||
F0coYuY+PT8L+CAiUrf23fNKEjnVkyZWfaffWCo4RtcvnG9nS3eKqHU+y5yeFSwL
|
||||
HvIxjr+xM7d1eHdYdyQ/GdgLxbE/aDh43E3zeq6QdTuPoOUVbII2zv4iI+LEbKYk
|
||||
oc34SlxHp5qBq4+Y1D9Q4QpjTrfJXstIJGDJxylhAoGAOu4EsKPmotBUy+bHspy6
|
||||
9Hct4v2tPmJrwF7fhUHE0Zp9JIqh2yfgikEn7tPq5JY/z0PpteHN1EnPSgIzuWfs
|
||||
c2QsQel9CxCAqwDaQFYJIOYRy0wcJLho0hhckdCra06w3/jpakT5zlNUKiq5xK+F
|
||||
XhzdmcjF0t2exOfYnxD6JYkCgYEAlWHmVio7yxjPuTdgRyvsaiOiMaxVF4n1ENer
|
||||
PRAVrYt/pArOdAXpTJuV3rWpms8ooP3sny/7j8qnx+QzkL7UzZq5lN7p9fIcN4FU
|
||||
1a38L06Aiq3czuwGF5r0WrZC1CTqvtS+c1bd57uHUcCWESuOkACht8V9ggl3SdvF
|
||||
5j6I88ECgYAkmL0vnZyQyt3oGvr0bGdSfrTqtkx0e2XZR9ysu3KnMEkjWQOndnag
|
||||
Vo9bG2zzBnY8D3tXFWJIpt8M9PBWW7EZiWLac/N8JwtcktcfcQg40wKSCUvQpwKx
|
||||
LWh0V+LWMdMgGrRU2NeYFENoqyiMHeh8z79eBl0SJJMHITrnGch6kg==
|
||||
-----END RSA PRIVATE KEY-----
|
168
socket_model.go
Normal file
168
socket_model.go
Normal file
@ -0,0 +1,168 @@
|
||||
package main
|
||||
|
||||
type MessageInfo struct {
|
||||
Id string `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Params interface{}
|
||||
}
|
||||
|
||||
type AddDeviceParam struct {
|
||||
DeviceNo string `json:"deviceNo"`
|
||||
DeviceName string `json:"deviceName"`
|
||||
}
|
||||
type MessageResponse struct {
|
||||
Id string `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
type MessageErrorResponse struct {
|
||||
Error *ErrorResponse `json:"error"`
|
||||
Id string `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type AddDeviceResponse struct {
|
||||
Code int `json:"code"`
|
||||
DeviceId int `json:"deviceId"`
|
||||
}
|
||||
|
||||
type CheckVersionResponse struct {
|
||||
Code int `json:"code"`
|
||||
DownloadUrl string `json:"downloadUrl"`
|
||||
IsUpdate bool `json:"isUpdate"`
|
||||
NewVersion string `json:"newVersion"`
|
||||
}
|
||||
|
||||
type GetDeviceRemoteControlInfoParam struct {
|
||||
DeviceId int `json:"deviceId"`
|
||||
DeviceNo string `json:"deviceNo"`
|
||||
}
|
||||
|
||||
type GetDeviceRemoteControlInfoResponse struct {
|
||||
Code int `json:"code"`
|
||||
DeviceId int `json:"deviceId"`
|
||||
IdentificationCode string `json:"identificationCode"`
|
||||
ShareUrl string `json:"shareUrl"`
|
||||
VerificationCode string `json:"verificationCode"`
|
||||
}
|
||||
|
||||
type GetFileTransferConfigResponse struct {
|
||||
Code int `json:"code"`
|
||||
DownloadSpeedRatio int `json:"downloadSpeedRatio"`
|
||||
UploadSpeedRatio int `json:"uploadSpeedRatio"`
|
||||
}
|
||||
|
||||
type GetTurnTransferConfigResponse struct {
|
||||
Code int `json:"code"`
|
||||
VideoBitrate int `json:"videoBitrate"`
|
||||
}
|
||||
|
||||
type LoginParam struct {
|
||||
PhoneNo string `json:"phoneNo"`
|
||||
Password string `json:"password"`
|
||||
DeviceId int `json:"deviceId"`
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
Code int `json:"code"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type GetDeviceResponse struct {
|
||||
Code int `json:"code"`
|
||||
Devices []*DeviceResponse `json:"devices"`
|
||||
}
|
||||
|
||||
type DeviceResponse struct {
|
||||
DeviceId int `json:"deviceId"`
|
||||
DeviceName string `json:"deviceName"`
|
||||
DeviceNo string `json:"deviceNo"`
|
||||
OnlineState int `json:"onlineState"`
|
||||
}
|
||||
|
||||
type StartRemoteControlParam struct {
|
||||
Type int `json:"type"`
|
||||
Token string `json:"token"`
|
||||
RemoteDeviceId int `json:"remoteDeviceId"`
|
||||
RemoteIdentificationCode string `json:"remoteIdentificationCode"`
|
||||
RemoteVerificationCode string `json:"remoteVerificationCode"`
|
||||
VerificationType int `json:"verificationType"`
|
||||
UserName string `json:"userName"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
type StartRemoteControlResponse struct {
|
||||
Code int `json:"code"`
|
||||
StreamingConfig StreamingConfig `json:"streamingConfig"`
|
||||
}
|
||||
|
||||
type RemoteStartRemoteControlResponse struct {
|
||||
Id string `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Params RemoteStreamingConfig `json:"params"`
|
||||
}
|
||||
|
||||
type NotifyResponse struct {
|
||||
Id string `json:"id"`
|
||||
Method string `json:"method"`
|
||||
Params interface{} `json:"params"`
|
||||
}
|
||||
|
||||
type EmptyObj struct {
|
||||
}
|
||||
|
||||
type StreamingConfig struct {
|
||||
ClientId string `json:"clientId"`
|
||||
ClientIds []string `json:"clientIds"`
|
||||
ServiceId string `json:"serviceId"`
|
||||
SignalServer string `json:"signalServer"`
|
||||
StunAddrs []string `json:"stunAddrs"`
|
||||
Token string `json:"token"`
|
||||
TurnAddrs []TurnServer `json:"turnAddrs"`
|
||||
}
|
||||
|
||||
type RemoteStreamingConfig struct {
|
||||
ClientId string `json:"clientId"`
|
||||
SignalServer string `json:"signalServer"`
|
||||
StunAddrs []string `json:"stunAddrs"`
|
||||
Token string `json:"token"`
|
||||
TurnAddrs []TurnServer `json:"turnAddrs"`
|
||||
}
|
||||
|
||||
type GetDeviceVerificationTypeResponse struct {
|
||||
Code int `json:"code"`
|
||||
VerificationType int `json:"verificationType"`
|
||||
}
|
||||
|
||||
type GetOnlineUsersResponse struct {
|
||||
Code int `json:"code"`
|
||||
DeviceId int `json:"deviceId"`
|
||||
Users []OnlineUser `json:"users"`
|
||||
}
|
||||
|
||||
type OnlineUser struct {
|
||||
ClientId string `json:"clientId"`
|
||||
ClientOS string `json:"clientOS"`
|
||||
UserName string `json:"userName"`
|
||||
VisitTime string `json:"visitTime"`
|
||||
}
|
||||
|
||||
type SimpleResponse struct {
|
||||
Code int `json:"code"`
|
||||
}
|
||||
|
||||
type DeleteDeviceResponse struct {
|
||||
Code int `json:"code"`
|
||||
DeviceId int `json:"deviceId"`
|
||||
}
|
||||
|
||||
type ForceClientOfflineParam struct {
|
||||
ClientIds []string `json:"clientIds"`
|
||||
Reason int `json:"reason"`
|
||||
}
|
660
socket_service.go
Normal file
660
socket_service.go
Normal file
@ -0,0 +1,660 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/beevik/guid"
|
||||
"github.com/gorilla/websocket"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
upgrader = websocket.Upgrader{
|
||||
//允许跨域访问
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
EnableCompression: false,
|
||||
}
|
||||
)
|
||||
|
||||
func serviceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
deviceNo := r.FormValue("deviceNo")
|
||||
sessionId := r.FormValue("session_id")
|
||||
clientType := r.FormValue("client_type")
|
||||
|
||||
wsConn, upgradeErr := upgrader.Upgrade(w, r, w.Header())
|
||||
|
||||
if upgradeErr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if reco := recover(); reco != any(nil) {
|
||||
fmt.Printf("Service Runtime error caught: %v", reco)
|
||||
}
|
||||
}()
|
||||
|
||||
tokenOfSession := fastLinkService.GetTokenBySession(sessionId)
|
||||
sessionGuid := guid.New().String()
|
||||
|
||||
fastLinkService.NewSession(deviceNo, sessionId, sessionGuid, clientType, wsConn)
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("0{\"sid\":\""+guid.New().String()+"\",\"upgrades\":[\"websocket\"],\"pingInterval\":25000,\"pingTimeout\":60000}"))
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("40"))
|
||||
if clientType == CLIENT_TYPE_FASTLINK_SERVICE {
|
||||
Logger.Println("Online DeviceNo:" + deviceNo + " Session:" + sessionId)
|
||||
fastLinkService.SetOnlineStatus(deviceNo)
|
||||
device := fastLinkService.GetDeviceByNo(deviceNo)
|
||||
if device != nil && device.BelongUser != "" {
|
||||
notifyDeviceChange(device.BelongUser)
|
||||
}
|
||||
}
|
||||
for {
|
||||
wsConn.SetReadDeadline(time.Now().In(TimeLocation).Add(time.Second * 60))
|
||||
messageType, p, readError := wsConn.ReadMessage()
|
||||
if readError != nil {
|
||||
Logger.Println("Service WebSocket异常断开," + wsConn.RemoteAddr().String() + ",异常信息:" + readError.Error())
|
||||
fastLinkService.RemoveSession(sessionId, sessionGuid)
|
||||
if clientType == CLIENT_TYPE_FASTLINK_SERVICE {
|
||||
Logger.Println("Offline DeviceNo:" + deviceNo + " Session:" + sessionId)
|
||||
fastLinkService.SetOnlineStatus(deviceNo)
|
||||
device := fastLinkService.GetDeviceByNo(deviceNo)
|
||||
if device != nil {
|
||||
//推送通知
|
||||
notifyDeviceChange(device.BelongUser)
|
||||
}
|
||||
}
|
||||
wsConn.Close()
|
||||
return
|
||||
}
|
||||
if messageType == websocket.CloseMessage {
|
||||
Logger.Println("Service WebSocket断开," + wsConn.RemoteAddr().String())
|
||||
fastLinkService.RemoveSession(sessionId, sessionGuid)
|
||||
if clientType == CLIENT_TYPE_FASTLINK_SERVICE {
|
||||
Logger.Println("Offline DeviceNo:" + deviceNo + " Session:" + sessionId)
|
||||
fastLinkService.SetOnlineStatus(deviceNo)
|
||||
device := fastLinkService.GetDeviceByNo(deviceNo)
|
||||
if device != nil {
|
||||
//推送通知
|
||||
notifyDeviceChange(device.BelongUser)
|
||||
}
|
||||
}
|
||||
wsConn.Close()
|
||||
return
|
||||
}
|
||||
strData := string(p)
|
||||
//fmt.Printf("DATA:" + strData + "\n")
|
||||
|
||||
index := strings.Index(strData, "[")
|
||||
cmd := ""
|
||||
var items []interface{}
|
||||
if index != -1 {
|
||||
cmd = strData[0:index]
|
||||
json.Unmarshal([]byte(strData[index:]), &items)
|
||||
} else {
|
||||
cmd = strData
|
||||
}
|
||||
|
||||
switch cmd {
|
||||
case "2":
|
||||
if tokenOfSession != "" {
|
||||
fastLinkService.RenewToken(tokenOfSession)
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("3"))
|
||||
case "42":
|
||||
if items[0] == "KeepAlive" {
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("42[\"KeepAliveAck\",{\"code\":200,\"message\":\"\",\"success\":true,\"error\":false}]"))
|
||||
} else if items[0] == "message" {
|
||||
msg := items[1].(map[string]interface{})["message"].(string)
|
||||
var messageInfo *MessageInfo
|
||||
json.Unmarshal([]byte(msg), &messageInfo)
|
||||
|
||||
if messageInfo != nil {
|
||||
switch messageInfo.Method {
|
||||
case "AddDevice":
|
||||
var param AddDeviceParam
|
||||
param.DeviceName = messageInfo.Params.(map[string]interface{})["deviceName"].(string)
|
||||
param.DeviceNo = messageInfo.Params.(map[string]interface{})["deviceNo"].(string)
|
||||
device := fastLinkService.AddDevice(param.DeviceNo, param.DeviceName)
|
||||
addDeviceResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "AddDeviceAck",
|
||||
Result: &AddDeviceResponse{
|
||||
Code: 200,
|
||||
DeviceId: device.DeviceId,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, addDeviceResp))
|
||||
|
||||
case "CheckVersion":
|
||||
checkVersionResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "CheckVersionAck",
|
||||
Result: &CheckVersionResponse{
|
||||
Code: 200,
|
||||
DownloadUrl: "",
|
||||
IsUpdate: false,
|
||||
NewVersion: "1.4.2.0",
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, checkVersionResp))
|
||||
|
||||
case "GetDeviceRemoteControlInfo":
|
||||
var param GetDeviceRemoteControlInfoParam
|
||||
param.DeviceNo = messageInfo.Params.(map[string]interface{})["deviceNo"].(string)
|
||||
param.DeviceId = int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
device := fastLinkService.GetDeviceByNo(param.DeviceNo)
|
||||
if device != nil {
|
||||
getDeviceRemoteControlInfoResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "GetDeviceRemoteControlInfoAck",
|
||||
Result: &GetDeviceRemoteControlInfoResponse{
|
||||
Code: 200,
|
||||
DeviceId: device.DeviceId,
|
||||
IdentificationCode: device.IdentificationCode,
|
||||
ShareUrl: WEB_URL + "?d=" + base64.StdEncoding.EncodeToString([]byte(device.DeviceNo)) + "&r=" + device.ShareRand,
|
||||
VerificationCode: device.VerificationCode,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, getDeviceRemoteControlInfoResp))
|
||||
}
|
||||
case "GetFileTransferConfig":
|
||||
getFileTransferConfigResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "GetFileTransferConfigAck",
|
||||
Result: &GetFileTransferConfigResponse{
|
||||
Code: 200,
|
||||
DownloadSpeedRatio: 80,
|
||||
UploadSpeedRatio: 80,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo+"_service", getFileTransferConfigResp))
|
||||
case "GetTurnTransferConfig":
|
||||
getTurnTransferConfigResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "GetTurnTransferConfigAck",
|
||||
Result: &GetTurnTransferConfigResponse{
|
||||
Code: 200,
|
||||
VideoBitrate: 4194377,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo+"_service", getTurnTransferConfigResp))
|
||||
|
||||
case "Login":
|
||||
var param LoginParam
|
||||
param.PhoneNo = messageInfo.Params.(map[string]interface{})["phoneNo"].(string)
|
||||
param.Password = messageInfo.Params.(map[string]interface{})["password"].(string)
|
||||
param.DeviceId = int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
|
||||
token := fastLinkService.Login(param.PhoneNo, param.Password, param.DeviceId)
|
||||
loginResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "LoginAck",
|
||||
}
|
||||
result := &LoginResponse{}
|
||||
if token == "" {
|
||||
result.Code = 1009
|
||||
} else {
|
||||
result.Code = 200
|
||||
result.Token = token
|
||||
notifyDeviceChange(param.PhoneNo)
|
||||
}
|
||||
loginResp.Result = result
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, loginResp))
|
||||
tokenOfSession = token
|
||||
fastLinkService.BindSessionToToken(sessionId, token)
|
||||
case "Logout":
|
||||
token := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
fastLinkService.RemoveToken(token)
|
||||
logoutResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "LogoutAck",
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, logoutResp))
|
||||
case "GetDevices":
|
||||
token := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
deviceList := fastLinkService.GetDeviceByToken(token)
|
||||
var dList []*DeviceResponse
|
||||
for _, info := range deviceList {
|
||||
d := &DeviceResponse{
|
||||
DeviceId: info.DeviceId,
|
||||
DeviceName: info.DeviceName,
|
||||
DeviceNo: info.DeviceNo,
|
||||
}
|
||||
if info.CustomName != "" {
|
||||
d.DeviceName = info.CustomName
|
||||
}
|
||||
if info.Online {
|
||||
d.OnlineState = 1
|
||||
} else {
|
||||
d.OnlineState = 0
|
||||
}
|
||||
dList = append(dList, d)
|
||||
}
|
||||
getDevicesResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "GetDevicesAck",
|
||||
Result: &GetDeviceResponse{
|
||||
Code: 200,
|
||||
Devices: dList,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, getDevicesResp))
|
||||
case "UpdateDeviceVerificationCode":
|
||||
paramDeviceNo := messageInfo.Params.(map[string]interface{})["deviceNo"].(string)
|
||||
device := fastLinkService.RefreshDeviceVerificationCode(paramDeviceNo)
|
||||
if device != nil {
|
||||
updateDeviceVerificationCodeResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "UpdateDeviceVerificationCodeAck",
|
||||
Result: &GetDeviceRemoteControlInfoResponse{
|
||||
Code: 200,
|
||||
DeviceId: device.DeviceId,
|
||||
IdentificationCode: device.IdentificationCode,
|
||||
ShareUrl: WEB_URL + "?d=" + device.DeviceNo + "&r=" + device.ShareRand,
|
||||
VerificationCode: device.VerificationCode,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, updateDeviceVerificationCodeResp))
|
||||
}
|
||||
|
||||
case "GetDeviceVerificationType":
|
||||
paramDeviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
device := fastLinkService.GetDeviceById(paramDeviceId)
|
||||
verificationType := 0
|
||||
if device != nil {
|
||||
verificationType = device.VerificationType
|
||||
}
|
||||
getDeviceVerificationTypeResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "GetDeviceVerificationTypeAck",
|
||||
Result: &GetDeviceVerificationTypeResponse{
|
||||
Code: 200,
|
||||
VerificationType: verificationType,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, getDeviceVerificationTypeResp))
|
||||
|
||||
case "UpdateDeviceVerificationType":
|
||||
verifyDeviceNo := messageInfo.Params.(map[string]interface{})["deviceNo"].(string)
|
||||
verifyPass := messageInfo.Params.(map[string]interface{})["password"].(string)
|
||||
verifyType := int(messageInfo.Params.(map[string]interface{})["verificationType"].(float64))
|
||||
deviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
device := fastLinkService.GetDeviceByNo(verifyDeviceNo)
|
||||
if device != nil {
|
||||
switch verifyType {
|
||||
case 0:
|
||||
device.VerificationType = 0
|
||||
device.TwoStepPass = ""
|
||||
case 1:
|
||||
//未实现
|
||||
device.VerificationType = 0
|
||||
device.TwoStepPass = ""
|
||||
case 2:
|
||||
device.VerificationType = 2
|
||||
device.TwoStepPass = verifyPass
|
||||
}
|
||||
}
|
||||
updateDeviceVerificationTypeResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "UpdateDeviceVerificationTypeAck",
|
||||
Result: &DeleteDeviceResponse{
|
||||
Code: 200,
|
||||
DeviceId: deviceId,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, updateDeviceVerificationTypeResp))
|
||||
case "StartRemoteControl":
|
||||
remoteControlParam := StartRemoteControlParam{
|
||||
Type: int(messageInfo.Params.(map[string]interface{})["type"].(float64)),
|
||||
Token: messageInfo.Params.(map[string]interface{})["token"].(string),
|
||||
RemoteDeviceId: int(messageInfo.Params.(map[string]interface{})["remoteDeviceId"].(float64)),
|
||||
RemoteIdentificationCode: messageInfo.Params.(map[string]interface{})["remoteIdentificationCode"].(string),
|
||||
RemoteVerificationCode: messageInfo.Params.(map[string]interface{})["remoteVerificationCode"].(string),
|
||||
VerificationType: int(messageInfo.Params.(map[string]interface{})["verificationType"].(float64)),
|
||||
UserName: messageInfo.Params.(map[string]interface{})["userName"].(string),
|
||||
Password: messageInfo.Params.(map[string]interface{})["password"].(string),
|
||||
}
|
||||
var device *DeviceInfo
|
||||
if remoteControlParam.RemoteDeviceId != 0 {
|
||||
device = fastLinkService.GetDeviceById(remoteControlParam.RemoteDeviceId)
|
||||
} else {
|
||||
device = fastLinkService.GetDeviceByIdentificationCode(remoteControlParam.RemoteIdentificationCode)
|
||||
}
|
||||
if device.Online && device.Visible {
|
||||
verifyResult := true
|
||||
userName := "游客"
|
||||
if remoteControlParam.Token != "" {
|
||||
userName = fastLinkService.GetUserByToken(remoteControlParam.Token)
|
||||
if device.BelongUser != userName {
|
||||
verifyResult = false
|
||||
}
|
||||
} else {
|
||||
if device.VerificationCode != remoteControlParam.RemoteVerificationCode || device.IdentificationCode != remoteControlParam.RemoteIdentificationCode {
|
||||
verifyResult = false
|
||||
}
|
||||
}
|
||||
|
||||
if device.VerificationType == 2 && device.TwoStepPass != "" {
|
||||
if device.TwoStepPass != remoteControlParam.Password {
|
||||
verifyResult = false
|
||||
}
|
||||
}
|
||||
|
||||
if !verifyResult {
|
||||
errorResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "StartRemoteControlAck",
|
||||
Result: &ErrorResponse{
|
||||
Code: 5004,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, errorResp))
|
||||
} else {
|
||||
fastLinkService.RenewToken(remoteControlParam.Token)
|
||||
clientId := GenShortGUID()
|
||||
streamToken := GenShortGUID()
|
||||
|
||||
fastLinkService.PrepareSignalSession(clientId, device.DeviceId, device.DeviceNo, streamToken, userName)
|
||||
targetRemoteControlResp := &RemoteStartRemoteControlResponse{
|
||||
Id: guid.New().String(),
|
||||
Method: "SetStreamingConfig",
|
||||
Params: RemoteStreamingConfig{
|
||||
ClientId: clientId,
|
||||
SignalServer: globalConfig.SignalServer,
|
||||
StunAddrs: globalConfig.StunServers,
|
||||
Token: streamToken,
|
||||
TurnAddrs: globalConfig.TurnServers,
|
||||
},
|
||||
}
|
||||
remoteSession := fastLinkService.GetSession(device.DeviceNo, CLIENT_TYPE_FASTLINK_SERVICE)
|
||||
remoteSession.WsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(device.DeviceNo+"_service", targetRemoteControlResp))
|
||||
|
||||
//推送UI提示
|
||||
notifyOnlineUserChange(device.DeviceNo)
|
||||
|
||||
startRemoteControlResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "StartRemoteControlAck",
|
||||
Result: &StartRemoteControlResponse{
|
||||
Code: 200,
|
||||
StreamingConfig: StreamingConfig{
|
||||
ClientId: clientId,
|
||||
ClientIds: []string{},
|
||||
ServiceId: device.DeviceNo,
|
||||
SignalServer: globalConfig.SignalServer,
|
||||
StunAddrs: globalConfig.StunServers,
|
||||
Token: streamToken,
|
||||
TurnAddrs: globalConfig.TurnServers,
|
||||
},
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, startRemoteControlResp))
|
||||
}
|
||||
} else {
|
||||
errorResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "StartRemoteControlAck",
|
||||
Result: &ErrorResponse{
|
||||
Code: 5007,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, errorResp))
|
||||
}
|
||||
case "GetOnlineUsers":
|
||||
paramDeviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
clients := fastLinkService.GetSignalSessionByDeviceId(paramDeviceId)
|
||||
|
||||
var onlineUsers []OnlineUser
|
||||
onlineUsers = []OnlineUser{}
|
||||
for _, client := range clients {
|
||||
onlineUsers = append(onlineUsers, OnlineUser{
|
||||
ClientId: client.Token,
|
||||
ClientOS: "Windows 8(OS build number: 9200)",
|
||||
UserName: client.StreamUser,
|
||||
VisitTime: client.CreateTime.Format("2006-01-02 15:04"),
|
||||
})
|
||||
}
|
||||
getOnlineUsersResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "GetOnlineUsersAck",
|
||||
Result: &GetOnlineUsersResponse{
|
||||
Code: 200,
|
||||
DeviceId: paramDeviceId,
|
||||
Users: onlineUsers,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, getOnlineUsersResp))
|
||||
|
||||
case "VerifyStreamingToken":
|
||||
streamToken := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
clientId := messageInfo.Params.(map[string]interface{})["clientId"].(string)
|
||||
signalSession := fastLinkService.GetSignalSession(clientId)
|
||||
if streamToken == signalSession.StreamToken {
|
||||
verifyStreamingTokenResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "VerifyStreamingTokenAck",
|
||||
Result: &SimpleResponse{
|
||||
Code: 200,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo+"_service", verifyStreamingTokenResp))
|
||||
}
|
||||
case "DeleteDevice":
|
||||
token := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
deviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
userName := fastLinkService.GetUserByToken(token)
|
||||
device := fastLinkService.GetDeviceById(deviceId)
|
||||
if device != nil && userName != "" && device.BelongUser == userName {
|
||||
fastLinkService.RenewToken(token)
|
||||
device.Visible = false
|
||||
//推送通知
|
||||
notifyDeviceChange(userName)
|
||||
}
|
||||
deleteDeviceResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "DeleteDeviceAck",
|
||||
Result: &DeleteDeviceResponse{
|
||||
Code: 200,
|
||||
DeviceId: deviceId,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, deleteDeviceResp))
|
||||
case "BindDevice":
|
||||
token := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
bindDeviceNo := messageInfo.Params.(map[string]interface{})["deviceNo"].(string)
|
||||
deviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
userName := fastLinkService.GetUserByToken(token)
|
||||
device := fastLinkService.GetDeviceByNo(bindDeviceNo)
|
||||
if device != nil && userName != "" {
|
||||
fastLinkService.RenewToken(token)
|
||||
device.BelongUser = userName
|
||||
device.Visible = true
|
||||
//推送通知
|
||||
notifyDeviceChange(userName)
|
||||
}
|
||||
deleteDeviceResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "BindDeviceAck",
|
||||
Result: &DeleteDeviceResponse{
|
||||
Code: 200,
|
||||
DeviceId: deviceId,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, deleteDeviceResp))
|
||||
|
||||
case "UpdateDeviceVerificationUpdateFrequency":
|
||||
//未实现,直接返回
|
||||
deleteDeviceResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "UpdateDeviceVerificationUpdateFrequencyAck",
|
||||
Result: &SimpleResponse{
|
||||
Code: 200,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, deleteDeviceResp))
|
||||
case "RebootDevice":
|
||||
token := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
deviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
device := fastLinkService.GetDeviceById(deviceId)
|
||||
user := fastLinkService.GetUserByToken(token)
|
||||
if device != nil && user != "" && device.BelongUser == user {
|
||||
fastLinkService.RenewToken(token)
|
||||
session := fastLinkService.GetSession(device.DeviceNo, CLIENT_TYPE_FASTLINK_SERVICE)
|
||||
if session != nil {
|
||||
notifyResp := &NotifyResponse{
|
||||
Id: guid.New().String(),
|
||||
Method: "NotifyReboot",
|
||||
Params: EmptyObj{},
|
||||
}
|
||||
session.WsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(session.DeviceNo+"_service", notifyResp))
|
||||
}
|
||||
}
|
||||
rebootDeviceResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "RebootDeviceAck",
|
||||
Result: &AddDeviceResponse{
|
||||
Code: 200,
|
||||
DeviceId: deviceId,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, rebootDeviceResp))
|
||||
case "ShutdownDevice":
|
||||
token := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
deviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
device := fastLinkService.GetDeviceById(deviceId)
|
||||
user := fastLinkService.GetUserByToken(token)
|
||||
if device != nil && user != "" && device.BelongUser == user {
|
||||
fastLinkService.RenewToken(token)
|
||||
session := fastLinkService.GetSession(device.DeviceNo, CLIENT_TYPE_FASTLINK_SERVICE)
|
||||
if session != nil {
|
||||
notifyResp := &NotifyResponse{
|
||||
Id: guid.New().String(),
|
||||
Method: "NotifyShutdown",
|
||||
Params: EmptyObj{},
|
||||
}
|
||||
session.WsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(session.DeviceNo+"_service", notifyResp))
|
||||
}
|
||||
}
|
||||
shutdownDeviceResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "ShutdownDeviceAck",
|
||||
Result: &AddDeviceResponse{
|
||||
Code: 200,
|
||||
DeviceId: deviceId,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, shutdownDeviceResp))
|
||||
case "UpdateDeviceName":
|
||||
token := messageInfo.Params.(map[string]interface{})["token"].(string)
|
||||
deviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
newDeviceName := messageInfo.Params.(map[string]interface{})["newDeviceName"].(string)
|
||||
|
||||
user := fastLinkService.GetUserByToken(token)
|
||||
device := fastLinkService.GetDeviceById(deviceId)
|
||||
if user != "" && device != nil && device.BelongUser == user {
|
||||
fastLinkService.RenewToken(token)
|
||||
device.CustomName = newDeviceName
|
||||
notifyDeviceChange(user)
|
||||
}
|
||||
updateDeviceNameResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "UpdateDeviceNameAck",
|
||||
Result: &AddDeviceResponse{
|
||||
Code: 200,
|
||||
DeviceId: deviceId,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, updateDeviceNameResp))
|
||||
case "ForceClientOffline":
|
||||
deviceId := int(messageInfo.Params.(map[string]interface{})["deviceId"].(float64))
|
||||
offlineDeviceNo := messageInfo.Params.(map[string]interface{})["deviceNo"].(string)
|
||||
device := fastLinkService.GetDeviceByNo(offlineDeviceNo)
|
||||
if device != nil && device.DeviceId == deviceId {
|
||||
session := fastLinkService.GetSession(offlineDeviceNo, CLIENT_TYPE_FASTLINK_SERVICE)
|
||||
if session != nil {
|
||||
tClientIds := messageInfo.Params.(map[string]interface{})["clientIds"].([]interface{})
|
||||
var clientIds []string
|
||||
clientIds = []string{}
|
||||
for _, id := range tClientIds {
|
||||
clientIds = append(clientIds, id.(string))
|
||||
}
|
||||
notifyResp := &NotifyResponse{
|
||||
Id: guid.New().String(),
|
||||
Method: "NotifyClientOffline",
|
||||
Params: ForceClientOfflineParam{
|
||||
ClientIds: clientIds,
|
||||
Reason: 3,
|
||||
},
|
||||
}
|
||||
session.WsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(session.DeviceNo+"_service", notifyResp))
|
||||
}
|
||||
}
|
||||
forceClientOfflineResp := &MessageResponse{
|
||||
Id: messageInfo.Id,
|
||||
Method: "ForceClientOfflineAck",
|
||||
Result: &SimpleResponse{
|
||||
Code: 200,
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, forceClientOfflineResp))
|
||||
case "SetStreamingConfigAck":
|
||||
|
||||
default:
|
||||
errorResp := &MessageErrorResponse{
|
||||
Method: messageInfo.Method,
|
||||
Error: &ErrorResponse{
|
||||
Code: 2004,
|
||||
Message: "请求调用的方法不存在",
|
||||
},
|
||||
}
|
||||
wsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, errorResp))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func notifyDeviceChange(user string) {
|
||||
userUISessions := fastLinkService.GetSessionsByUser(user, CLIENT_TYPE_FASTLINK_UI)
|
||||
for _, session := range userUISessions {
|
||||
notifyResp := &NotifyResponse{
|
||||
Id: guid.New().String(),
|
||||
Method: "NotifyDevicesChange",
|
||||
Params: EmptyObj{},
|
||||
}
|
||||
Logger.Println("notifyDeviceChange: DeviceNo:" + session.DeviceNo + " User:" + user)
|
||||
session.WsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(session.DeviceNo, notifyResp))
|
||||
}
|
||||
}
|
||||
|
||||
func notifyOnlineUserChange(deviceNo string) {
|
||||
remoteUISession := fastLinkService.GetSession(deviceNo, CLIENT_TYPE_FASTLINK_UI)
|
||||
if remoteUISession != nil {
|
||||
notifyResp := &NotifyResponse{
|
||||
Id: guid.New().String(),
|
||||
Method: "NotifyOnlineUsersChange",
|
||||
Params: EmptyObj{},
|
||||
}
|
||||
Logger.Println("notifyOnlineUserChange: DeviceNo:" + deviceNo)
|
||||
remoteUISession.WsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(deviceNo, notifyResp))
|
||||
}
|
||||
}
|
||||
|
||||
func makeMessageResponse(deviceNo string, params interface{}) []byte {
|
||||
var result []interface{}
|
||||
result = append(result, "message")
|
||||
var msg map[string]interface{}
|
||||
msg = make(map[string]interface{})
|
||||
msg["deviceNo"] = deviceNo
|
||||
marshal, _ := json.Marshal(params)
|
||||
msg["message"] = string(marshal)
|
||||
result = append(result, msg)
|
||||
bytes, _ := json.Marshal(result)
|
||||
return append([]byte("42"), bytes...)
|
||||
}
|
117
socket_signal.go
Normal file
117
socket_signal.go
Normal file
@ -0,0 +1,117 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/beevik/guid"
|
||||
"github.com/gorilla/websocket"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func signalHandler(w http.ResponseWriter, r *http.Request) {
|
||||
token := r.FormValue("token")
|
||||
|
||||
if token == "" {
|
||||
fmt.Println("signalHandler Error : token is empty")
|
||||
}
|
||||
wsConn, upgradeErr := upgrader.Upgrade(w, r, w.Header())
|
||||
|
||||
if upgradeErr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if reco := recover(); reco != any(nil) {
|
||||
fmt.Printf("Signal Runtime error caught: %v", reco)
|
||||
}
|
||||
}()
|
||||
|
||||
sessionGuid := guid.New().String()
|
||||
|
||||
fastLinkService.NewSignalSession(token, sessionGuid, wsConn)
|
||||
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("0{\"sid\":\""+guid.New().String()+"\",\"upgrades\":[\"websocket\"],\"pingInterval\":25000,\"pingTimeout\":60000}"))
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("40"))
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("42[\"server-authenticated\",{\"uid\":\""+token+"\",\"authenticated\":true}]"))
|
||||
|
||||
for {
|
||||
wsConn.SetReadDeadline(time.Now().In(TimeLocation).Add(time.Second * 60))
|
||||
messageType, p, readError := wsConn.ReadMessage()
|
||||
if readError != nil {
|
||||
Logger.Println("Signal WebSocket异常断开," + wsConn.RemoteAddr().String() + ",异常信息:" + readError.Error())
|
||||
signalSession := fastLinkService.GetSignalSession(token)
|
||||
fastLinkService.RemoveSignalSession(token, sessionGuid)
|
||||
if signalSession != nil {
|
||||
//推送UI提示
|
||||
notifyOnlineUserChange(signalSession.RelateDeviceNo)
|
||||
}
|
||||
|
||||
wsConn.Close()
|
||||
return
|
||||
}
|
||||
if messageType == websocket.CloseMessage {
|
||||
Logger.Println("Signal WebSocket断开," + wsConn.RemoteAddr().String())
|
||||
signalSession := fastLinkService.GetSignalSession(token)
|
||||
fastLinkService.RemoveSignalSession(token, sessionGuid)
|
||||
if signalSession != nil {
|
||||
//推送UI提示
|
||||
notifyOnlineUserChange(signalSession.RelateDeviceNo)
|
||||
}
|
||||
wsConn.Close()
|
||||
return
|
||||
}
|
||||
strData := string(p)
|
||||
//fmt.Printf("SIGNAL:" + strData + "\n")
|
||||
|
||||
index := strings.Index(strData, "[")
|
||||
cmd := ""
|
||||
var items []interface{}
|
||||
if index != -1 {
|
||||
cmd = strData[0:index]
|
||||
json.Unmarshal([]byte(strData[index:]), &items)
|
||||
} else {
|
||||
cmd = strData
|
||||
}
|
||||
if len(cmd) > 1 && cmd[:2] == "42" {
|
||||
cmd = "42"
|
||||
}
|
||||
switch cmd {
|
||||
case "2":
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("3"))
|
||||
case "42":
|
||||
if items[0] == "KeepAlive" {
|
||||
wsConn.WriteMessage(websocket.TextMessage, []byte("42[\"KeepAliveAck\",{}]"))
|
||||
} else if items[0] == "owt-message" {
|
||||
from := ""
|
||||
if _, ok := items[1].(map[string]interface{})["from"]; ok {
|
||||
from = items[1].(map[string]interface{})["from"].(string)
|
||||
}
|
||||
if from == "" {
|
||||
from = token
|
||||
}
|
||||
|
||||
to := items[1].(map[string]interface{})["to"].(string)
|
||||
data := items[1].(map[string]interface{})["data"].(string)
|
||||
target := fastLinkService.GetSignalSession(to)
|
||||
if target != nil {
|
||||
target.WsConn.WriteMessage(websocket.TextMessage, makeOwtMessage(from, to, data))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeOwtMessage(from string, to string, data string) []byte {
|
||||
var message []interface{}
|
||||
message = append(message, "owt-message")
|
||||
var m map[string]string
|
||||
m = make(map[string]string)
|
||||
m["from"] = from
|
||||
m["to"] = to
|
||||
m["data"] = data
|
||||
message = append(message, m)
|
||||
marshal, _ := json.Marshal(message)
|
||||
return append([]byte("42"), marshal...)
|
||||
}
|
BIN
web/favicon.png
Normal file
BIN
web/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
24
web/index.html
Normal file
24
web/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="keywords" content="fastLink,FASTLINK,顺网云游戏,云游戏,顺网云玩,顺网">
|
||||
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,minimal-ui">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="browsermode" content="application">
|
||||
<meta name="full-screen" content="yes">
|
||||
<meta name="x5-fullscreen" content="true">
|
||||
<meta name="x5-page-mode" content="app">
|
||||
<meta name="360-fullscreen" content="true">
|
||||
<meta name="wap-font-scale" content="no">
|
||||
<meta name="format-detection" content="telphone=no, email=no">
|
||||
<title>FASTLINK</title>
|
||||
<link rel="shortcut icon" href="favicon.png"><link href="static1/css/tool.e82ab3594a815ab433dc.css" rel="stylesheet"></head>
|
||||
<body>
|
||||
<div id="video-and-stats"></div>
|
||||
<script src="./static1/js/hammer.js"></script>
|
||||
<script src="static1/js/runtimechunk~tool.js"></script><script src="static1/js/2.7473f57.js"></script><script src="static1/js/1.bdd544c.js"></script></body>
|
||||
</html>
|
8
web/static1/css/tool.e82ab3594a815ab433dc.css
Normal file
8
web/static1/css/tool.e82ab3594a815ab433dc.css
Normal file
File diff suppressed because one or more lines are too long
BIN
web/static1/img/eye.png
Normal file
BIN
web/static1/img/eye.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 996 B |
9
web/static1/js/1.bdd544c.js
Normal file
9
web/static1/js/1.bdd544c.js
Normal file
File diff suppressed because one or more lines are too long
33
web/static1/js/2.7473f57.js
Normal file
33
web/static1/js/2.7473f57.js
Normal file
File diff suppressed because one or more lines are too long
2643
web/static1/js/hammer.js
Normal file
2643
web/static1/js/hammer.js
Normal file
File diff suppressed because it is too large
Load Diff
8
web/static1/js/runtimechunk~tool.js
Normal file
8
web/static1/js/runtimechunk~tool.js
Normal file
File diff suppressed because one or more lines are too long
458
web_api.go
Normal file
458
web_api.go
Normal file
@ -0,0 +1,458 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"github.com/beevik/guid"
|
||||
"github.com/gorilla/websocket"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type WebApiRequest struct {
|
||||
DeviceNo string `json:"deviceNo"`
|
||||
Random string `json:"random"`
|
||||
ClientNo string `json:"clientNo"`
|
||||
UserName string `json:"userName"`
|
||||
VerificationPassword string `json:"verificationPassword"`
|
||||
}
|
||||
|
||||
type WebApiResponse struct {
|
||||
TraceId interface{} `json:"traceId"`
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
Success bool `json:"success"`
|
||||
Error bool `json:"error"`
|
||||
}
|
||||
type WebCheckData struct {
|
||||
Pass bool `json:"pass"`
|
||||
}
|
||||
type DeviceVerificationTypeData struct {
|
||||
DeviceId interface{} `json:"deviceId"`
|
||||
VerificationType interface{} `json:"verificationType"`
|
||||
}
|
||||
|
||||
type IdTransferData struct {
|
||||
StreamingConfig StreamingConfig `json:"streamingConfig"`
|
||||
StreamRecordId int `json:"streamRecordId"` //记录分析,没啥用,未实现相关功能
|
||||
}
|
||||
|
||||
type LoginRequest struct {
|
||||
Password string `json:"password"`
|
||||
Phone string `json:"phone"`
|
||||
}
|
||||
|
||||
type AppDeviceListData struct {
|
||||
DeviceId int `json:"deviceId"`
|
||||
DeviceNo string `json:"deviceNo"`
|
||||
DeviceName string `json:"deviceName"`
|
||||
ExpireTime interface{} `json:"expireTime"`
|
||||
ExpireTimeStr interface{} `json:"expireTimeStr"`
|
||||
OnlineState int `json:"onlineState"`
|
||||
EnableConnect int `json:"enableConnect"`
|
||||
ClientVersion interface{} `json:"clientVersion"`
|
||||
}
|
||||
|
||||
type RegisterModel struct {
|
||||
Code string `json:"code"`
|
||||
Password string `json:"password"`
|
||||
Password2 string `json:"password2"`
|
||||
Phone string `json:"phone"`
|
||||
UserName string `json:"userName"`
|
||||
}
|
||||
|
||||
func checkHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
defer r.Body.Close()
|
||||
var model *WebApiRequest
|
||||
json.Unmarshal(data, &model)
|
||||
decodeString, _ := base64.StdEncoding.DecodeString(model.DeviceNo)
|
||||
model.DeviceNo = string(decodeString)
|
||||
result := fastLinkService.CheckWebLogin(model.DeviceNo, model.Random)
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: &WebCheckData{
|
||||
Pass: true,
|
||||
},
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
switch result {
|
||||
case 1:
|
||||
resp.Data = nil
|
||||
resp.Error = true
|
||||
resp.Success = false
|
||||
resp.Message = "远程主机没有分享"
|
||||
resp.Code = 500
|
||||
case 2:
|
||||
resp.Data = nil
|
||||
resp.Error = true
|
||||
resp.Success = false
|
||||
resp.Message = "要连接的主机不存在"
|
||||
resp.Code = 500
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func deviceVerificationTypeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
defer r.Body.Close()
|
||||
var model *WebApiRequest
|
||||
json.Unmarshal(data, &model)
|
||||
device := fastLinkService.GetDeviceByNo(model.DeviceNo)
|
||||
vData := &DeviceVerificationTypeData{
|
||||
DeviceId: nil,
|
||||
VerificationType: nil,
|
||||
}
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: vData,
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
if device != nil {
|
||||
vData.DeviceId = device.DeviceId
|
||||
vData.VerificationType = device.VerificationType
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func idTransferHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
defer r.Body.Close()
|
||||
var model *WebApiRequest
|
||||
json.Unmarshal(data, &model)
|
||||
device := fastLinkService.GetDeviceByNo(model.DeviceNo)
|
||||
if device == nil {
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "设备不存在",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
} else {
|
||||
if device.Online && device.Visible {
|
||||
if device.VerificationType == 2 && device.TwoStepPass != "" && device.TwoStepPass != model.VerificationPassword {
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "访问密码不正确",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
|
||||
streamToken := GenShortGUID()
|
||||
if model.UserName == "" {
|
||||
model.UserName = "WEB客户端"
|
||||
}
|
||||
fastLinkService.PrepareSignalSession(model.ClientNo, device.DeviceId, device.DeviceNo, streamToken, model.UserName)
|
||||
|
||||
targetRemoteControlResp := &RemoteStartRemoteControlResponse{
|
||||
Id: guid.New().String(),
|
||||
Method: "SetStreamingConfig",
|
||||
Params: RemoteStreamingConfig{
|
||||
ClientId: model.ClientNo,
|
||||
SignalServer: globalConfig.SignalServer,
|
||||
StunAddrs: globalConfig.StunServers,
|
||||
Token: streamToken,
|
||||
TurnAddrs: globalConfig.TurnServers,
|
||||
},
|
||||
}
|
||||
remoteSession := fastLinkService.GetSession(device.DeviceNo, CLIENT_TYPE_FASTLINK_SERVICE)
|
||||
remoteSession.WsConn.WriteMessage(websocket.TextMessage, makeMessageResponse(device.DeviceNo+"_service", targetRemoteControlResp))
|
||||
|
||||
//推送UI提示
|
||||
notifyOnlineUserChange(device.DeviceNo)
|
||||
|
||||
idTransferData := IdTransferData{
|
||||
StreamingConfig: StreamingConfig{
|
||||
ClientId: model.ClientNo,
|
||||
ClientIds: []string{model.ClientNo},
|
||||
ServiceId: model.DeviceNo,
|
||||
SignalServer: globalConfig.SignalServer,
|
||||
StunAddrs: globalConfig.StunServers,
|
||||
Token: streamToken,
|
||||
TurnAddrs: globalConfig.TurnServers,
|
||||
},
|
||||
StreamRecordId: 0,
|
||||
}
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: idTransferData,
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
} else {
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "远程主机不在线",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func closeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
//记录埋点用,未实现,直接返回
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: nil,
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func loginForAppHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
defer r.Body.Close()
|
||||
var model *LoginRequest
|
||||
json.Unmarshal(data, &model)
|
||||
success := fastLinkService.CheckUser(model.Phone, model.Password)
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: nil,
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
if !success {
|
||||
resp.Success = false
|
||||
resp.Error = true
|
||||
resp.Code = 500
|
||||
resp.Message = "用户名或密码不正确!"
|
||||
}
|
||||
token := fastLinkService.NewToken(model.Phone, TOKEN_TYPE_APP)
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "token",
|
||||
Value: token,
|
||||
})
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func appListDeviceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
cookie := r.Header.Get("Cookie")
|
||||
user := ""
|
||||
token := ""
|
||||
if len(cookie) > 7 {
|
||||
index := strings.Index(cookie, "token=")
|
||||
token = cookie[index+6:]
|
||||
user = fastLinkService.GetUserByToken(token)
|
||||
}
|
||||
if user == "" {
|
||||
errResp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "用户未登录",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(errResp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
fastLinkService.RenewToken(token)
|
||||
devices := fastLinkService.GetDeviceByToken(token)
|
||||
var data []*AppDeviceListData
|
||||
for _, device := range devices {
|
||||
t := &AppDeviceListData{
|
||||
DeviceId: device.DeviceId,
|
||||
DeviceNo: device.DeviceNo,
|
||||
DeviceName: device.DeviceName,
|
||||
ExpireTime: nil,
|
||||
ExpireTimeStr: nil,
|
||||
ClientVersion: nil,
|
||||
}
|
||||
if device.CustomName != "" {
|
||||
t.DeviceName = device.CustomName
|
||||
}
|
||||
if device.Online {
|
||||
t.OnlineState = 1
|
||||
} else {
|
||||
t.OnlineState = 0
|
||||
}
|
||||
if device.Visible {
|
||||
t.EnableConnect = 1
|
||||
} else {
|
||||
t.EnableConnect = 0
|
||||
}
|
||||
|
||||
data = append(data, t)
|
||||
}
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: data,
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
cookie := r.Header.Get("Cookie")
|
||||
user := ""
|
||||
token := ""
|
||||
if len(cookie) > 7 {
|
||||
index := strings.Index(cookie, "token=")
|
||||
token = cookie[index+6:]
|
||||
user = fastLinkService.GetUserByToken(token)
|
||||
}
|
||||
if user == "" {
|
||||
errResp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "用户未登录",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(errResp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
fastLinkService.RemoveToken(token)
|
||||
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: nil,
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func registerHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data, _ := ioutil.ReadAll(r.Body)
|
||||
defer r.Body.Close()
|
||||
var model *RegisterModel
|
||||
json.Unmarshal(data, &model)
|
||||
|
||||
if model.UserName == "" || model.Phone == "" {
|
||||
errResp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "用户名不能为空",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(errResp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
if model.Password == "" {
|
||||
errResp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "密码不能为空",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(errResp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
if model.Password != model.Password2 {
|
||||
errResp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "两次密码输入不一致",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(errResp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
if model.Password != model.Password2 {
|
||||
errResp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "两次密码输入不一致",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(errResp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
exist := fastLinkService.CheckUserExist(model.UserName)
|
||||
if exist {
|
||||
errResp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "此手机号已被其他用户绑定!",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(errResp)
|
||||
w.Write(marshal)
|
||||
return
|
||||
}
|
||||
fastLinkService.AddUser(model.UserName, model.Password)
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 200,
|
||||
Message: "",
|
||||
Data: nil,
|
||||
Success: true,
|
||||
Error: false,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
||||
|
||||
func sendCodeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
resp := WebApiResponse{
|
||||
TraceId: nil,
|
||||
Code: 500,
|
||||
Message: "私服未实现发送验证码,输入任意验证码即可",
|
||||
Data: nil,
|
||||
Success: false,
|
||||
Error: true,
|
||||
}
|
||||
marshal, _ := json.Marshal(resp)
|
||||
w.Write(marshal)
|
||||
}
|
Loading…
Reference in New Issue
Block a user