init
This commit is contained in:
commit
60b889a44b
28 files changed
+5366
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
.idea
|
||||||
|
fastlink
|
||||||
|
fastlink.exe
|
||||||
|
session
|
||||||
|
*.zip
|
||||||
|
config.conf
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
YY8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
YY8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
|||||||
|
packr build -ldflags "-s -w" -trimpath
|
||||||
|
set GOOS=linux
|
||||||
|
packr build -ldflags "-s -w" -trimpath
|
||||||
@@ -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-----
|
||||||
|
MIIFbjCCA1agAwIBAgIII1tVz2zmPdEwDQYJKoZIhvcNAQELBQAwTDELMAkGA1UE
|
||||||
|
BhMCQ04xDTALBgNVBAoTBEV2YW4xDTALBgNVBAsTBEV2YW4xHzAdBgNVBAMTFkV2
|
||||||
|
YW4gQXNzdXJhbmNlIFJvb3QgQ0EwIBcNMDgwMTAxMDAwMDAwWhgPMjA1MDEyMzEy
|
||||||
|
MzU5NTlaMEwxCzAJBgNVBAYTAkNOMQ0wCwYDVQQKEwRFdmFuMQ0wCwYDVQQLEwRF
|
||||||
|
dmFuMR8wHQYDVQQDExZFdmFuIEFzc3VyYW5jZSBSb290IENBMIICIjANBgkqhkiG
|
||||||
|
9w0BAQEFAAOCAg8AMIICCgKCAgEAq4vXbtUk8y6n3AgH7ApVQ7KOSwymwQnRg0HQ
|
||||||
|
iZJfamIWYsa1uN7n2/W3tJy82ij0JyIqqiUfTZu8dr6yd12Um7RTN1j32x+3hzSF
|
||||||
|
+2Hag08vd4ksrHAm61MjZVqdQdi5+EMwR5YlaEYFrgBYsKfo+B4vjFYz2PW7IFlI
|
||||||
|
SSeHBrtJdKf+pIr0+e2Sp7O91NwAp3JiDChqqyMQbKLaXag0G0o422Mj555L2k6r
|
||||||
|
E1lNm2JzMKaHqP2Ql/GtCaZXmsD4oRtBfMOr5OkNeGA0lA9OXkZxDXYTGrgGfaY+
|
||||||
|
kq7ig12eBwa2f09x++aPAYxci8I5fZGCpCPY5siAUpw7r9Tui8d2KOCVDGF4FZ3+
|
||||||
|
vDnLDPXrrN/2FYHt0p/kNqn9WINLOtfQyk8Ko+zicxjTA9DH5tNyKvxs5NncVXeH
|
||||||
|
Gjgmto3OAJcRNfu/NOo3IEHRmyOHCtMK/U1oR3ByYsRxc9raKrPI/CBcJQ48XIut
|
||||||
|
OxdQ+5cK+7IumEXqiAxnvKK1SMBVMnSav7jrfAfq66RNOOTvxng1p2W52dTJIIZB
|
||||||
|
KcEpzrnMGmLLDba9Zp7v/6PsXYLtwzg0oOJZcnnqOCMz2jMt9o06HFlqYke8Z8Nb
|
||||||
|
35njmwN4PWyHpEZhbC9VttXqVVD7UaAMStsP2yS2L6Wdt3Af7Mr/kurhLBwK6XOp
|
||||||
|
H403rdsCAwEAAaNSMFAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUK9GuH/q/
|
||||||
|
TaECv2bMT75Rrso+Hu4wCwYDVR0PBAQDAgGGMBEGCWCGSAGG+EIBAQQEAwIABzAN
|
||||||
|
BgkqhkiG9w0BAQsFAAOCAgEAjsWIGSK2ZJOiCBoH4CqMQNJa2nWOAAY99op8BXRi
|
||||||
|
Sx8tpbid+mZ6IOIBOY4GLT82lkbDbGmAOXhjDD9pMWYMbxko35MNX3j1/9BAIKU/
|
||||||
|
W4U5NEIEnWogJJirJjtW+3BGSrbtZyTODCGf2nuJQsXz+YnBAVUNjKILmAVR1bCx
|
||||||
|
KSXo9YJdrfroHTxk+TB6wewiO8cs5/YlMfKQEyUxTdMOEzRdGvl0dkw6t4346BcS
|
||||||
|
FqY0tpJ6tvbatVjc+ka//ZxBdKTHWJqkcR0f5g91L0AMllRnAUKAyXIzxUlMB8zN
|
||||||
|
zfKXhSce2Wk+39kBaDrw4YS6SiJTXVX5ID2Myz/NPDY3upbjPVtDABloF35PcKlr
|
||||||
|
lekQmYUtN+QoHCb+LEkmHn6/AUdUke7J0Vr1gtqEjqC4f5zPVAx81ZLoBU3FQvb/
|
||||||
|
DN8QLfdI2/qelfubCRv/XDH+ybhd9aQizKacbcEvpCCLCDkkDqhQyToVoJyeWlGY
|
||||||
|
s+v2oTcP2x+gPs/2uFGsCQE2U8re9B6BOwYaYaAhoPmHSz4hr7oYc45xop1B+70G
|
||||||
|
GTGHMHbrbKMPld66dKJQEJ9+mtkJbBrsX/ZHbRHCUjU2yMasSV/S9YHYWWqhC8E+
|
||||||
|
BSCwrlnMnu4TTxF7uHx0nzWOJFRVfmowsfN4ffHDVoAXfuN7NLc56JsJszVyY0ij
|
||||||
|
YY8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
+189
@@ -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"))
|
||||||
|
}
|
||||||
@@ -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(), "-", "")
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
)
|
||||||
@@ -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=
|
||||||
@@ -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
@@ -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
@@ -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"`
|
||||||
|
}
|
||||||
@@ -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...)
|
||||||
|
}
|
||||||
@@ -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...)
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
@@ -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>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/*!
|
||||||
|
*
|
||||||
|
* swRTC sdk update at Wed Feb 23 2022 11:15:25 GMT+0800 (GMT+08:00), by lxl;
|
||||||
|
* 1.model optimize;
|
||||||
|
* 2.auth token;
|
||||||
|
* 3.bug fix;
|
||||||
|
*
|
||||||
|
*/body,html{height:100%;margin:0;padding:0;width:100%;overflow:hidden;font-size:15px;font-family:MicrosoftYaHeiBold,PingFang SC,STHeitiSC-Light,Helvetica-Light,arial,sans-serif,Droid Sans Fallback;background-color:#000;color:#545454;-webkit-text-size-adjust:100%;text-size-adjust:100%}dd,dl,dt,li,ol,ul{list-style:none;padding:0;margin:0}a{text-decoration:none;color:#5a97e9;background-color:initial}p{margin:0;padding:0;font-weight:400}a:active,a:hover{outline:0}th{font-weight:400}*,:after,:before{box-sizing:border-box;-webkit-box-sizing:border-box}.clearfix:after,.clearfix:before,.pull-left:after,.pull-left:before,.pull-right:after,.pull-right:before{content:" "}audio,canvas,progress,video{display:inline-block;vertical-align:initial;outline:none;border:none}audio:not([controls]){display:none;height:0}[hidden],template{display:none}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:initial;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:initial}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}ol,td,th,ul{padding:0}ol,ul{list-style:none}.text-primary{color:#409eff}.text-danger{color:#f56c6c}.text-success{color:#67c23a}.text-warning{color:#e6a23c}.text-info{color:#909399}.clearfix,.pull-left,.pull-right{*zoom:1}.clearfix:after,.clearfix:before,.pull-left:after,.pull-left:before,.pull-right:after,.pull-right:before{display:table;content:"";height:0;line-height:0;overflow:hidden;visibility:hidden}.clearfix:after,.pull-left:after,.pull-right:after{clear:both}.pull-left{float:left}.pull-right{float:right}.form-item{margin-bottom:15px}.btn{overflow:visible;white-space:nowrap;text-align:center;padding:3px;margin:0;min-width:43px;line-height:normal;border-radius:3px;-webkit-user-select:none;user-select:none;touch-action:manipulation;background-color:hsla(0,0%,100%,.6);border:1px solid #d9d9d9;box-shadow:0 2px 0 rgba(0,0,0,.015);cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);-webkit-appearance:button;font-weight:400}.btn:focus,.btn:hover{outline:0;text-decoration:none;color:#409eff;background-color:#fff;border-color:#409eff}.btn:active{outline:0;box-shadow:none;color:#096dd9;background-color:#fff;border-color:#096dd9}input,select{line-height:normal;height:auto;padding:6px 8px}select{min-width:204px}#loading-mask{display:none;content:"";position:absolute;top:0;left:0;bottom:0;right:0;z-index:100;background:rgba(0,0,0,.9)}.loading-index{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:150px;text-align:center;z-index:110}.loading-index>div{width:30px;height:30px;background-color:#6300bf;border-radius:100%;display:inline-block;animation:bouncedelay 1.4s ease-in-out infinite;animation-fill-mode:both}.loading-index .bounce1{animation-delay:-.32s}.loading-index .bounce2{animation-delay:-.16s}@keyframes bouncedelay{0%,80%,to{transform:scale(0);-webkit-transform:scale(0)}40%{transform:scale(1);-webkit-transform:scale(1)}}textarea{font-family:monospace;margin:2px}.video-fill{object-fit:fill}h2{margin:0 0 10px}video::-webkit-media-controls{display:none!important}#stats{background-color:rgba(0,128,0,.5);position:absolute;top:0;right:0;padding:0 2em;float:right;z-index:14;white-space:pre-wrap;display:none;pointer-events:none;overflow:hidden}#stats.show{display:block}#video-and-stats{width:100%;height:100%}#video-and-stats video{width:100%;height:100%;z-index:10;background:#000;transform-origin:0 0;position:absolute;top:0;left:0;object-fit:contain;box-sizing:border-box}#video-and-stats video.is-fill{object-fit:fill}#video-and-stats video:focus,#video-and-stats video:focus-visible{outline:none}@media screen and (orientation:portrait){body{padding-top:0}}@media screen and (orientation:landscape){body{padding-right:0;padding-left:0;padding-bottom:0}}.pc #video-and-stats{min-height:350px;position:relative}.pLine truncated
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 996 B |
@@ -0,0 +1,9 @@
|
|||||||
|
/*!
|
||||||
|
*
|
||||||
|
* swRTC sdk update at Wed Feb 23 2022 11:15:25 GMT+0800 (GMT+08:00), by lxl;
|
||||||
|
* 1.model optimize;
|
||||||
|
* 2.auth token;
|
||||||
|
* 3.bug fix;
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
(window.webpackJsonp=window.webpackJsonp||[]).push([[1],{0:function(e,t){},"0PJp":function(e,t,n){},"7Szd":function(e,t,n){},"9/Cq":function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return Ajax}));var qs__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__("Qyje"),qs__WEBPACK_IMPORTED_MODULE_0___default=__webpack_require__.n(qs__WEBPACK_IMPORTED_MODULE_0__),md5=__webpack_require__("aCH8"),str2utf8=window.TextEncoder?function(e){for(var t=new TextEncoder("utf8").encode(e),n="",i=0;i<t.length;++i)n+=String.fromCharCode(t[i]);return n}:function(str){return eval("'"+encodeURI(str).replace(/%/gm,"\\x")+"'")};function str2md5(e,t){try{var n=Secret_+ProjectId+"|"+t+"|"+JSON.stringify(e)+Secret_;return md5(str2utf8(n)).toUpperCase()}catch(e){return" "}}var Secret_="54p1zyyQh8ApUOzJUJJS1DtOSGYa1rnG",ProjectId="streamData",SwPvReport={projectId:"streamData",businessId:"dataRecordV2",report_time:"",ip:"",wwType:"",wwAccount:"",billingType:"",billlingAccount:"",mac:"",guid:"",pageURL:window.location.href,rptData:"",native_jsonp:function(){var e={send:function(e,t){var n=t||{},i=n.callbackName||"callback",a=n.onSuccess||function(){},r=n.onTimeout||function(){},o=n.timeout||10,s=window.setTimeout((function(){window[i]=function(){},r()}),1e3*o);window[i]=function(e){window.clearTimeout(s),a(e)};var c=document.createElement("script");c.type="text/javascript",c.async=!0,c.src=e,document.getElementsByTagName("head")[0].appendChild(c)}};return e},_params:function(e){if(null==e)return e;var t=[];for(var n in e)t.push(encodeURIComponent(n)+"="+encodeURIComponent(e[n]));return t.join("&")},decrypt_mode1:function(e){for(var t="",n=e.length,i=new Uint8Array([33,67,101,135,144,186,220,254]),a=0,r=0;r<n;++r){var o=e[r].charCodeAt()^i[a];t+=String.fromCharCode(o),a=(a+1)%i.length}return t},Decode:function(e){for(var t,n=e.length,i=new Array(-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-2,-2,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,62,-2,-2,-2,63,52,53,54,55,56,57,58,59,60,61,-2,-2,-2,-2,-2,-2,-2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-2,-2,-2,-2,-2,-2,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2),a=0,r=0,o="",s=e,c=0;"\0"!=(t=s[c])&&n-- >0;)if("="!=t){c++;var d=t.charCodeAt();if(!((t=i[d])<0)){switch(r%4){case 0:a=t<<2;break;case 1:a|=t>>4,o+=String.fromCharCode(a),a=(15&t)<<4;break;case 2:a|=t>>2,o+=String.fromCharCode(a),a=(3&t)<<6;break;case 3:a|=t,o+=String.fromCharCode(a)}r++}}else if("="!=s[c++]&&r%4==1)return NULL;return o},getSessionId:function(){for(var e=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"],t="",n=0;n<32;n++){t+=e[parseInt(61*Math.random())]}return t},shangbao:function(e){var t={projectId:this.projectId,businessId:this.businessId,data:this.rptData},n=this._params(t);this.native_jsonp().send("https://datapolaris.shunwang.com/commonReport/jsReport?"+n+"&callback=swcallback&_t="+(new Date).getTime(),{callbackName:"swcallback",onSuccess:function(t){e&&e(t)},onTimeout:function(t){e&&e()},timeout:3})},swcallback:function(e){}};function Ajax(e){var t=e.data,n=(e.success,e.failed,e.id);SwPvReport.businessId=n,SwPvReport.rptData=t,SwPvReport.shangbao()}},EfXH:function(e,t,n){},IUVT:function(e,t,n){},K1c7:function(e,t,n){},NA3w:function(e,t,n){"use strict";n.r(t);var i={};n.r(i),n.d(i,"P2PClient",(function(){return Be})),n.d(i,"P2PError",(function(){return H}));var a=n("QILm"),r=n.n(a),o=n("lSNA"),s=n.n(o),c=n("o0o1"),d=n.n(c),l=n("yXPU"),u=n.n(l),p=(n("LvDl"),n("RIqP")),h=n.n(p),v=n("cDf5"),f=n.n(v),m=n("lwsE"),y=n.n(m),g=n("W8MJ"),b=n.n(g),k=n("PJYZ"),_=n.n(k),w=n("7W2i"),S=n.n(w),P=n("a1gu"),E=n.n(P),x=n("Nsbk"),T=n.n(x),C=n("ym5e"),R=n.n(C),M=n("j6EF"),I=n.n(M),O=(n("0JNz"),function(){var e=function(){},t={DEBUG:0,TRACE:1,INFO:2,WARNING:3,ERROR:4,NONE:5};t.log=window.console.log.bind(window.console);var n=function(e){return"function"==typeof window.console[e]?window.console[e].bind(window.console):window.console.log.bind(window.console)},i=function(i){t.debug=i<=0?n("log"):e,t.trace=i<=1?n("trace"):e,t.info=i<=2?n("info"):e,t.warning=i<=3?n("warn"):e,t.error=i<=4?n("error"):e};return i(4),t.setLogLevel=i,t}());function L(e){return function(){var t,n=T()(e);if(D()){var i=T()(this).constructor;t=Reflect.construct(n,arguments,i)}else t=n.apply(this,arguments);reLine truncated
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*!
|
||||||
|
*
|
||||||
|
* swRTC sdk update at Wed Feb 23 2022 11:15:25 GMT+0800 (GMT+08:00), by lxl;
|
||||||
|
* 1.model optimize;
|
||||||
|
* 2.auth token;
|
||||||
|
* 3.bug fix;
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{"+SKG":function(e,t,n){(function(t){e.exports=function(e){return n&&t.isBuffer(e)||r&&(e instanceof ArrayBuffer||function(e){return"function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(e):e.buffer instanceof ArrayBuffer}(e))};var n="function"==typeof t&&"function"==typeof t.isBuffer,r="function"==typeof ArrayBuffer}).call(this,n("tjlA").Buffer)},"0JNz":function(e,t,n){"use strict";var r={};n.r(r),n.d(r,"shimGetUserMedia",(function(){return m})),n.d(r,"shimGetDisplayMedia",(function(){return b})),n.d(r,"shimMediaStream",(function(){return _})),n.d(r,"shimOnTrack",(function(){return w})),n.d(r,"shimGetSendersWithDtmf",(function(){return C})),n.d(r,"shimGetStats",(function(){return x})),n.d(r,"shimSenderReceiverGetStats",(function(){return k})),n.d(r,"shimAddTrackRemoveTrackWithNative",(function(){return T})),n.d(r,"shimAddTrackRemoveTrack",(function(){return S})),n.d(r,"shimPeerConnection",(function(){return E})),n.d(r,"fixNegotiationNeeded",(function(){return P}));var o={};n.r(o),n.d(o,"shimGetUserMedia",(function(){return R})),n.d(o,"shimGetDisplayMedia",(function(){return O})),n.d(o,"shimOnTrack",(function(){return A})),n.d(o,"shimPeerConnection",(function(){return j})),n.d(o,"shimSenderGetStats",(function(){return L})),n.d(o,"shimReceiverGetStats",(function(){return D})),n.d(o,"shimRemoveStream",(function(){return F})),n.d(o,"shimRTCDataChannel",(function(){return N})),n.d(o,"shimAddTransceiver",(function(){return I})),n.d(o,"shimGetParameters",(function(){return M})),n.d(o,"shimCreateOffer",(function(){return B})),n.d(o,"shimCreateAnswer",(function(){return U}));var i={};n.r(i),n.d(i,"shimLocalStreamsAPI",(function(){return q})),n.d(i,"shimRemoteStreamsAPI",(function(){return z})),n.d(i,"shimCallbacksAPI",(function(){return $})),n.d(i,"shimGetUserMedia",(function(){return H})),n.d(i,"shimConstraints",(function(){return W})),n.d(i,"shimRTCIceServerUrls",(function(){return Y})),n.d(i,"shimTrackEventTransceiver",(function(){return V})),n.d(i,"shimCreateOfferLegacy",(function(){return K})),n.d(i,"shimAudioContext",(function(){return J}));var a={};n.r(a),n.d(a,"shimRTCIceCandidate",(function(){return Q})),n.d(a,"shimMaxMessageSize",(function(){return Z})),n.d(a,"shimSendThrowTypeError",(function(){return ee})),n.d(a,"shimConnectionState",(function(){return te})),n.d(a,"removeExtmapAllowMixed",(function(){return ne})),n.d(a,"shimAddIceCandidateNullOrEmpty",(function(){return re}));let s=!0,c=!0;function u(e,t,n){const r=e.match(t);return r&&r.length>=n&&parseInt(r[n],10)}function l(e,t,n){if(!e.RTCPeerConnection)return;const r=e.RTCPeerConnection.prototype,o=r.addEventListener;r.addEventListener=function(e,r){if(e!==t)return o.apply(this,arguments);const i=e=>{const t=n(e);t&&(r.handleEvent?r.handleEvent(t):r(t))};return this._eventMap=this._eventMap||{},this._eventMap[t]||(this._eventMap[t]=new Map),this._eventMap[t].set(r,i),o.apply(this,[e,i])};const i=r.removeEventListener;r.removeEventListener=function(e,n){if(e!==t||!this._eventMap||!this._eventMap[t])return i.apply(this,arguments);if(!this._eventMap[t].has(n))return i.apply(this,arguments);const r=this._eventMap[t].get(n);return this._eventMap[t].delete(n),0===this._eventMap[t].size&&delete this._eventMap[t],0===Object.keys(this._eventMap).length&&delete this._eventMap,i.apply(this,[e,r])},Object.defineProperty(r,"on"+t,{get(){return this["_on"+t]},set(e){this["_on"+t]&&(this.removeEventListener(t,this["_on"+t]),delete this["_on"+t]),e&&this.addEventListener(t,this["_on"+t]=e)},enumerable:!0,configurable:!0})}function f(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(s=e,e?"adapter.js logging disabled":"adapter.js logging enabled")}function p(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(c=!e,"adapter.js deprecation warnings "+(e?"disabled":"enabled"))}function d(){if("object"==typeof window){if(s)return;"undefined"!=typeof console&&console.log}}function h(e){return"[object Object]"===Object.prototype.toString.call(e)}function v(e){return h(e)?Object.keys(e).reduce((function(t,n){const r=h(e[n]),o=r?v(e[n]):e[n],i=r&&!Object.keys(o).length;return void 0===o||i?t:Object.assign(t,{[n]:o})}),{}):e}function y(e,t,n){const r=n?"outbound-rtp":"inbound-rtp",o=new Map;if(null===t)return o;const i=[];return e.forEach(e=>{"track"===e.type&&e.trackIdentifier===t.id&&i.push(e)}),i.forEach(t=>{e.forEach(n=>{n.type===r&&n.trackId===t.id&&function e(t,n,r){n&&!r.has(n.id)&&(r.set(n.id,n),Object.keys(n).forEach(o=>{o.endsWith("Id")?e(t,t.get(n[o]),r):o.endsWith("Ids")&&n[o].forEach(n=>{e(t,t.get(n),r)})}))}(e,n,o)})}),o}const g=d;function m(e,t){const n=e&&e.navigator;if(!n.mediaDevices)return;const r=function(e){if("object"!=typeof e||e.mandatory||e.optional)return e;const t={};return Object.keys(e).forEach(n=>{if("require"===n||"advanced"===n||"mediaSource"===n)return;const r="object"==typeof e[n]?e[n]:{ideal:e[n]}Line truncated
|
||||||
|
/*!
|
||||||
|
* Determine if an object is a Buffer
|
||||||
|
*
|
||||||
|
* @author Feross Aboukhadijeh <https://feross.org>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
e.exports=function(e){return null!=e&&(n(e)||function(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&n(e.slice(0,0))}(e)||!!e._isBuffer)}},Bnag:function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}},C2QD:function(e,t){function n(e){e=e||{},this.ms=e.min||100,this.max=e.max||1e4,this.factor=e.factor||2,this.jitter=e.jitter>0&&e.jitter<=1?e.jitter:0,this.attempts=0}e.exports=n,n.prototype.duration=function(){var e=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var t=Math.random(),n=Math.floor(t*this.jitter*e);e=0==(1&Math.floor(10*t))?e-n:e+n}return 0|Math.min(e,this.max)},n.prototype.reset=function(){this.attempts=0},n.prototype.setMin=function(e){this.ms=e},n.prototype.setMax=function(e){this.max=e},n.prototype.setJitter=function(e){this.jitter=e}},CIKq:function(e,t,n){(function(t){var r,o,i=n("Gbct"),a=n("Wm4p"),s=n("TypT"),c=n("Yvos"),u=n("Aplp"),l=n("HjK1")("engine.io-client:websocket");if("undefined"!=typeof WebSocket)r=WebSocket;else if("undefined"!=typeof self)r=self.WebSocket||self.MozWebSocket;else try{o=n(0)}catch(e){}var f=r||o;function p(e){e&&e.forceBase64&&(this.supportsBinary=!1),this.perMessageDeflate=e.perMessageDeflate,this.usingBrowserWebSocket=r&&!e.forceNode,this.protocols=e.protocols,this.usingBrowserWebSocket||(f=o),i.call(this,e)}e.exports=p,c(p,i),p.prototype.name="websocket",p.prototype.supportsBinary=!0,p.prototype.doOpen=function(){if(this.check()){var e=this.uri(),t=this.protocols,n={agent:this.agent,perMessageDeflate:this.perMessageDeflate};n.pfx=this.pfx,n.key=this.key,n.passphrase=this.passphrase,n.cert=this.cert,n.ca=this.ca,n.ciphers=this.ciphers,n.rejectUnauthorized=this.rejectUnauthorized,this.extraHeaders&&(n.headers=this.extraHeaders),this.localAddress&&(n.localAddress=this.localAddress);try{this.ws=this.usingBrowserWebSocket&&!this.isReactNative?t?new f(e,t):new f(e):new f(e,t,n)}catch(e){return this.emit("error",e)}void 0===this.ws.binaryType&&(this.supportsBinary=!1),this.ws.supports&&this.ws.supports.binary?(this.supportsBinary=!0,this.ws.binaryType="nodebuffer"):this.ws.binaryType="arraybuffer",this.addEventListeners()}},p.prototype.addEventListeners=function(){var e=this;this.ws.onopen=function(){e.onOpen()},this.ws.onclose=function(){e.onClose()},this.ws.onmessage=function(t){e.onData(t.data)},this.ws.onerror=function(t){e.onError("websocket error",t)}},p.prototype.write=function(e){var n=this;this.writable=!1;for(var r=e.length,o=0,i=r;o<i;o++)!function(e){a.encodePacket(e,n.supportsBinary,(function(o){if(!n.usingBrowserWebSocket){var i={};if(e.options&&(i.compress=e.options.compress),n.perMessageDeflate)("string"==typeof o?t.byteLength(o):o.length)<n.perMessageDeflate.threshold&&(i.compress=!1)}try{n.usingBrowserWebSocket?n.ws.send(o):n.ws.send(o,i)}catch(e){l("websocket closed before onclose event")}--r||s()}))}(e[o]);function s(){n.emit("flush"),setTimeout((function(){n.writable=!0,n.emit("drain")}),0)}},p.prototype.onClose=function(){i.prototype.onClose.call(this)},p.prototype.doClose=function(){void 0!==this.ws&&this.ws.close()},p.prototype.uri=function(){var e=this.query||{},t=this.secure?"wss":"ws",n="";return this.port&&("wss"===t&&443!==Number(this.port)||"ws"===t&&80!==Number(this.port))&&(n=":"+this.port),this.timestampRequests&&(e[this.timestampParam]=u()),this.supportsBinary||(e.b64=1),(e=s.encode(e)).length&&(e="?"+e),t+"://"+(-1!==this.hostname.indexOf(":")?"["+this.hostname+"]":this.hostname)+n+this.path+e},p.prototype.check=function(){return!(!f||"__initialize"in f&&this.name===p.prototype.name)}}).call(this,n("tjlA").Buffer)},CUme:function(e,t,n){var r=n("Gbct"),o=n("TypT"),i=n("Wm4p"),a=n("Yvos"),s=n("Aplp"),c=n("HjK1")("engine.io-client:polling");e.exports=l;var u=null!=new(n("AdPF"))({xdomain:!1}).responseType;function l(e){var t=e&&e.forceBase64;u&&!t||(this.supportsBinary=!1),r.call(this,e)}a(l,r),l.prototype.name="polling",l.prototype.doOpen=function(){this.poll()},l.prototype.pause=function(e){var t=this;function n(){c("paused"),t.readyState="paused",e()}if(this.readyState="pausing",this.polling||!this.writable){var r=0;this.polling&&(c("we are currently polling - waiting to pause"),r++,this.once("pollComplete",(function(){c("pre-pause polling complete"),--r||n()}))),this.writable||(c("we are currently writing - waiting to pause"),r++,this.once("drain",(function(){c("pre-pause writing complete"),--r||n()})))}else n()},l.prototype.poll=function(){c("polling"),this.polling=!0,this.doPoll(),this.emit("poll")},l.prototype.onData=function(e){var t=this;c("polling got data %s",e);i.decodePayload(e,this.socket.binaryType,(function(e,n,r){if("opening"===t.readyState&&t.onOpen(),"close"===e.type)return t.onClose(),!1;t.onPacket(e)})),"closed"!==this.readyState&&(this.polling=!1,this.emit("pollComplete"),"open"===this.readyState?this.poll():c('ignoring poll - transport statLine truncated
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Lodash <https://lodash.com/>
|
||||||
|
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||||
|
* Released under MIT license <https://lodash.com/license>
|
||||||
|
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||||
|
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||||
|
*/(function(){var i="Expected a function",a="__lodash_placeholder__",s=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],c="[object Arguments]",u="[object Array]",l="[object Boolean]",f="[object Date]",p="[object Error]",d="[object Function]",h="[object GeneratorFunction]",v="[object Map]",y="[object Number]",g="[object Object]",m="[object RegExp]",b="[object Set]",_="[object String]",w="[object Symbol]",C="[object WeakMap]",x="[object ArrayBuffer]",k="[object DataView]",T="[object Float32Array]",S="[object Float64Array]",E="[object Int8Array]",P="[object Int16Array]",R="[object Int32Array]",O="[object Uint8Array]",A="[object Uint16Array]",j="[object Uint32Array]",L=/\b__p \+= '';/g,D=/\b(__p \+=) '' \+/g,F=/(__e\(.*?\)|\b__t\)) \+\n'';/g,N=/&(?:amp|lt|gt|quot|#39);/g,I=/[&<>"']/g,M=RegExp(N.source),B=RegExp(I.source),U=/<%-([\s\S]+?)%>/g,q=/<%([\s\S]+?)%>/g,z=/<%=([\s\S]+?)%>/g,$=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,H=/^\w*$/,W=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Y=/[\\^$.*+?()[\]{}|]/g,V=RegExp(Y.source),K=/^\s+|\s+$/g,J=/^\s+/,G=/\s+$/,X=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Q=/\{\n\/\* \[wrapped with (.+)\] \*/,Z=/,? & /,ee=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,te=/\\(\\)?/g,ne=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,re=/\w*$/,oe=/^[-+]0x[0-9a-f]+$/i,ie=/^0b[01]+$/i,ae=/^\[object .+?Constructor\]$/,se=/^0o[0-7]+$/i,ce=/^(?:0|[1-9]\d*)$/,ue=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,le=/($^)/,fe=/['\n\r\u2028\u2029\\]/g,pe="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",de="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",he="[\\ud800-\\udfff]",ve="["+de+"]",ye="["+pe+"]",ge="\\d+",me="[\\u2700-\\u27bf]",be="[a-z\\xdf-\\xf6\\xf8-\\xff]",_e="[^\\ud800-\\udfff"+de+ge+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",we="\\ud83c[\\udffb-\\udfff]",Ce="[^\\ud800-\\udfff]",xe="(?:\\ud83c[\\udde6-\\uddff]){2}",ke="[\\ud800-\\udbff][\\udc00-\\udfff]",Te="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Se="(?:"+be+"|"+_e+")",Ee="(?:"+Te+"|"+_e+")",Pe="(?:"+ye+"|"+we+")"+"?",Re="[\\ufe0e\\ufe0f]?"+Pe+("(?:\\u200d(?:"+[Ce,xe,ke].join("|")+")[\\ufe0e\\ufe0f]?"+Pe+")*"),Oe="(?:"+[me,xe,ke].join("|")+")"+Re,Ae="(?:"+[Ce+ye+"?",ye,xe,ke,he].join("|")+")",je=RegExp("['’]","g"),Le=RegExp(ye,"g"),De=RegExp(we+"(?="+we+")|"+Ae+Re,"g"),Fe=RegExp([Te+"?"+be+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[ve,Te,"$"].join("|")+")",Ee+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[ve,Te+Se,"$"].join("|")+")",Te+"?"+Se+"+(?:['’](?:d|ll|m|re|s|t|ve))?",Te+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",ge,Oe].join("|"),"g"),Ne=RegExp("[\\u200d\\ud800-\\udfff"+pe+"\\ufe0e\\ufe0f]"),Ie=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Me=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Be=-1,Ue={};Ue[T]=Ue[S]=Ue[E]=Ue[P]=Ue[R]=Ue[O]=Ue["[object Uint8ClampedArray]"]=Ue[A]=Ue[j]=!0,Ue[c]=Ue[u]=Ue[x]=Ue[l]=Ue[k]=Ue[f]=Ue[p]=Ue[d]=Ue[v]=Ue[y]=Ue[g]=Ue[m]=Ue[b]=Ue[_]=Ue[C]=!1;var qe={};qe[c]=qe[u]=qe[x]=qe[k]=qe[l]=qe[f]=qe[T]=qe[S]=qe[E]=qe[P]=qe[R]=qe[v]=qe[y]=qe[g]=qe[m]=qe[b]=qe[_]=qe[w]=qe[O]=qe["[object Uint8ClampedArray]"]=qe[A]=qe[j]=!0,qe[p]=qe[d]=qe[C]=!1;var ze={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$e=parseFloat,He=parseInt,We="object"==typeof e&&e&&e.Object===Object&&e,Ye="object"==typeof self&&self&&self.Object===Object&&self,Ve=We||Ye||Function("return this")(),Ke=t&&!t.nodeType&&t,Je=Ke&&"object"==typeof r&&r&&!r.nodeType&&r,Ge=Je&&Je.exports===Ke,Xe=Ge&&We.process,Qe=function(){try{var e=Je&&Je.require&&Je.require("util").types;return e||Xe&&Xe.binding&&Xe.binding("util")}catch(e){}}(),Ze=Qe&&Qe.isArrayBuffer,et=Qe&&Qe.isDate,tt=Qe&&Qe.isMap,nt=Qe&&Qe.isRegExp,rt=Qe&&Qe.isSet,ot=Qe&&Qe.isTypedArray;function it(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function at(e,t,n,r){for(var o=-1,i=null==e?0:e.length;++o<i;){var a=e[o];t(r,a,n(a),e)}return r}function st(e,t){for(var n=-1,r=null==e?0:e.length;++n<r&&!1!==t(e[n],n,e););return e}function ct(e,t){for(var n=null==e?0:e.length;n--&&!1!==t(e[n],n,e););return e}function ut(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(!t(e[n],n,e))return!1;return!0}function lt(e,t){for(var n=-1,r=null==e?0:e.lengtLine truncated
|
||||||
|
/*! https://mths.be/utf8js v2.1.2 by @mathias */
|
||||||
|
var n,r,o,i=String.fromCharCode;function a(e){for(var t,n,r=[],o=0,i=e.length;o<i;)(t=e.charCodeAt(o++))>=55296&&t<=56319&&o<i?56320==(64512&(n=e.charCodeAt(o++)))?r.push(((1023&t)<<10)+(1023&n)+65536):(r.push(t),o--):r.push(t);return r}function s(e,t){if(e>=55296&&e<=57343){if(t)throw Error("Lone surrogate U+"+e.toString(16).toUpperCase()+" is not a scalar value");return!1}return!0}function c(e,t){return i(e>>t&63|128)}function u(e,t){if(0==(4294967168&e))return i(e);var n="";return 0==(4294965248&e)?n=i(e>>6&31|192):0==(4294901760&e)?(s(e,t)||(e=65533),n=i(e>>12&15|224),n+=c(e,6)):0==(4292870144&e)&&(n=i(e>>18&7|240),n+=c(e,12),n+=c(e,6)),n+=i(63&e|128)}function l(){if(o>=r)throw Error("Invalid byte index");var e=255&n[o];if(o++,128==(192&e))return 63&e;throw Error("Invalid continuation byte")}function f(e){var t,i;if(o>r)throw Error("Invalid byte index");if(o==r)return!1;if(t=255&n[o],o++,0==(128&t))return t;if(192==(224&t)){if((i=(31&t)<<6|l())>=128)return i;throw Error("Invalid continuation byte")}if(224==(240&t)){if((i=(15&t)<<12|l()<<6|l())>=2048)return s(i,e)?i:65533;throw Error("Invalid continuation byte")}if(240==(248&t)&&(i=(7&t)<<18|l()<<12|l()<<6|l())>=65536&&i<=1114111)return i;throw Error("Invalid UTF-8 detected")}e.exports={version:"2.1.2",encode:function(e,t){for(var n=!1!==(t=t||{}).strict,r=a(e),o=r.length,i=-1,s="";++i<o;)s+=u(r[i],n);return s},decode:function(e,t){var s=!1!==(t=t||{}).strict;n=a(e),r=n.length,o=0;for(var c,u=[];!1!==(c=f(s));)u.push(c);return function(e){for(var t,n=e.length,r=-1,o="";++r<n;)(t=e[r])>65535&&(o+=i((t-=65536)>>>10&1023|55296),t=56320|1023&t),o+=i(t);return o}(u)}}},oShl:function(e,t,n){var r=n("Nsbk"),o=n("SksO"),i=n("xfeJ"),a=n("sXyB");function s(t){var n="function"==typeof Map?new Map:void 0;return e.exports=s=function(e){if(null===e||!i(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(e))return n.get(e);n.set(e,t)}function t(){return a(e,arguments,r(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),o(t,e)},s(t)}e.exports=s},ojuT:function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},sXyB:function(e,t,n){var r=n("SksO"),o=n("b48C");function i(t,n,a){return o()?e.exports=i=Reflect.construct:e.exports=i=function(e,t,n){var o=[null];o.push.apply(o,t);var i=new(Function.bind.apply(e,o));return n&&r(i,n.prototype),i},i.apply(null,arguments)}e.exports=i},sxOR:function(e,t,n){"use strict";var r=String.prototype.replace,o=/%20/g;e.exports={default:"RFC3986",formatters:{RFC1738:function(e){return r.call(e,o,"+")},RFC3986:function(e){return e}},RFC1738:"RFC1738",RFC3986:"RFC3986"}},tjlA:function(e,t,n){"use strict";(function(e){
|
||||||
|
/*!
|
||||||
|
* The buffer module from node.js, for the browser.
|
||||||
|
*
|
||||||
|
* @author Feross Aboukhadijeh <http://feross.org>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
var r=n("H7XF"),o=n("kVK+"),i=n("49sm");function a(){return c.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function s(e,t){if(a()<t)throw new RangeError("Invalid typed array length");return c.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=c.prototype:(null===e&&(e=new c(t)),e.length=t),e}function c(e,t,n){if(!(c.TYPED_ARRAY_SUPPORT||this instanceof c))return new c(e,t,n);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return f(this,e)}return u(this,e,t,n)}function u(e,t,n,r){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,n,r){if(t.byteLength,n<0||t.byteLength<n)throw new RangeError("'offset' is out of bounds");if(t.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");t=void 0===n&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,n):new Uint8Array(t,n,r);c.TYPED_ARRAY_SUPPORT?(e=t).__proto__=c.prototype:e=p(e,t);return e}(e,t,n,r):"string"==typeof t?function(e,t,n){"string"==typeof n&&""!==n||(n="utf8");if(!c.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|h(t,n),o=(e=s(e,r)).write(t,n);o!==r&&(e=e.slice(0,o));return e}(e,t,n):function(e,t){if(c.isBuffer(t)){var n=0|d(t.length);return 0===(e=s(e,n)).length||t.copy(e,0,0,n),e}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(r=t.length)!=r?s(e,0):p(e,t);if("Buffer"===t.type&&i(t.data))return p(e,t.data)}var r;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function l(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function f(e,t){if(l(t),e=s(e,t<0?0:0|d(t)),!c.TYPED_ARRAY_SUPPORT)for(var n=0;n<t;++n)e[n]=0;return e}function p(e,t){var n=t.length<0?0:0|d(t.length);e=s(e,n);for(var r=0;r<n;r+=1)e[r]=255&t[r];return e}function d(e){if(e>=a())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+a().toString(16)+" bytes");return 0|e}function h(e,t){if(c.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return U(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return q(e).length;default:if(r)return U(e).length;t=(""+t).toLowerCase(),r=!0}}function v(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,n);case"utf8":case"utf-8":return S(this,t,n);case"ascii":return E(this,t,n);case"latin1":case"binary":return P(this,t,n);case"base64":return T(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function y(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function g(e,t,n,r,o){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(o)return-1;n=e.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof t&&(t=c.from(t,r)),c.isBuffer(t))return 0===t.length?-1:m(e,t,n,r,o);if("number"==typeof t)return t&=255,c.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):m(e,[t],n,r,o);throw new TypeError("val must be string, number or Buffer")}function m(e,t,n,r,o){var i,a=1,s=e.length,c=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;a=2,s/=2,c/=2,n/=2}function u(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(o){var l=-1;for(i=n;i<s;i++)if(u(e,i)===u(t,-1===l?0:i-l)){if(-1===l&&(l=i),i-l+1===c)return l*a}else-1!==l&&(i-=i-l),l=-1}else for(n+c>s&&(n=s-c),i=n;i>=0;i--){for(var f=!0,p=0;p<c;p++)if(u(e,i+p)!==u(t,p)){f=!1;break}if(f)return i}return-1}function b(e,t,n,r){n=Number(n)||0;var o=e.length-n;r?(r=Number(r))>o&&(r=o):r=o;var i=t.length;if(i%2!=0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a<r;++a){var s=parseInt(t.substr(2*a,2),16);if(isNaN(s))return a;e[n+a]=s}return a}function _(e,t,n,r){return z(U(t,e.length-n),e,n,r)}function w(e,t,n,r){return z(function(e){for(var t=[],n=0;n<e.length;++n)t.push(255&e.charCodeAt(n));return t}(t),e,n,r)}function C(e,t,n,r){return w(e,t,n,r)}function x(e,t,n,r){return z(Line truncated
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,8 @@
|
|||||||
|
/*!
|
||||||
|
*
|
||||||
|
* swRTC sdk update at Wed Feb 23 2022 11:15:25 GMT+0800 (GMT+08:00), by lxl;
|
||||||
|
* 1.model optimize;
|
||||||
|
* 2.auth token;
|
||||||
|
* 3.bug fix;
|
||||||
|
*
|
||||||
|
*/!function(e){function r(r){for(var t,o,i=r[0],c=r[1],a=r[2],d=0,l=[];d<i.length;d++)o=i[d],Object.prototype.hasOwnProperty.call(A,o)&&A[o]&&l.push(A[o][0]),A[o]=0;for(t in c)Object.prototype.hasOwnProperty.call(c,t)&&(e[t]=c[t]);for(J&&J(r);l.length;)l.shift()();return M.push.apply(M,a||[]),n()}function n(){for(var e,r=0;r<M.length;r++){for(var n=M[r],t=!0,o=1;o<n.length;o++){var i=n[o];0!==A[i]&&(t=!1)}t&&(M.splice(r--,1),e=S(S.s=n[0]))}return e}var t=window.webpackHotUpdate;window.webpackHotUpdate=function(e,r){!function(e,r){if(!_[e]||!m[e])return;for(var n in m[e]=!1,r)Object.prototype.hasOwnProperty.call(r,n)&&(v[n]=r[n]);0==--w&&0===O&&P()}(e,r),t&&t(e,r)};var o,i=!0,c="15932efd6eb1875e4f18",a={},d=[],l=[];function p(r){var n={_acceptedDependencies:{},_declinedDependencies:{},_selfAccepted:!1,_selfDeclined:!1,_selfInvalidated:!1,_disposeHandlers:[],_main:o!==r,active:!0,accept:function(e,r){if(void 0===e)n._selfAccepted=!0;else if("function"==typeof e)n._selfAccepted=e;else if("object"==typeof e)for(var t=0;t<e.length;t++)n._acceptedDependencies[e[t]]=r||function(){};else n._acceptedDependencies[e]=r||function(){}},decline:function(e){if(void 0===e)n._selfDeclined=!0;else if("object"==typeof e)for(var r=0;r<e.length;r++)n._declinedDependencies[e[r]]=!0;else n._declinedDependencies[e]=!0},dispose:function(e){n._disposeHandlers.push(e)},addDisposeHandler:function(e){n._disposeHandlers.push(e)},removeDisposeHandler:function(e){var r=n._disposeHandlers.indexOf(e);r>=0&&n._disposeHandlers.splice(r,1)},invalidate:function(){switch(this._selfInvalidated=!0,u){case"idle":(v={})[r]=e[r],f("ready");break;case"ready":H(r);break;case"prepare":case"check":case"dispose":case"apply":(b=b||[]).push(r)}},check:D,apply:I,status:function(e){if(!e)return u;s.push(e)},addStatusHandler:function(e){s.push(e)},removeStatusHandler:function(e){var r=s.indexOf(e);r>=0&&s.splice(r,1)},data:a[r]};return o=void 0,n}var s=[],u="idle";function f(e){u=e;for(var r=0;r<s.length;r++)s[r].call(null,e)}var h,v,y,b,w=0,O=0,g={},m={},_={};function j(e){return+e+""===e?+e:e}function D(e){if("idle"!==u)throw new Error("check() is only allowed in idle status");return i=e,f("check"),(r=1e4,r=r||1e4,new Promise((function(e,n){if("undefined"==typeof XMLHttpRequest)return n(new Error("No browser support"));try{var t=new XMLHttpRequest,o=S.p+""+c+".hot-update.json";t.open("GET",o,!0),t.timeout=r,t.send(null)}catch(e){return n(e)}t.onreadystatechange=function(){if(4===t.readyState)if(0===t.status)n(new Error("Manifest request to "+o+" timed out."));else if(404===t.status)e();else if(200!==t.status&&304!==t.status)n(new Error("Manifest request to "+o+" failed."));else{try{var r=JSON.parse(t.responseText)}catch(e){return void n(e)}e(r)}}}))).then((function(e){if(!e)return f(x()?"ready":"idle"),null;m={},g={},_=e.c,y=e.h,f("prepare");var r=new Promise((function(e,r){h={resolve:e,reject:r}}));for(var n in v={},A)E(n);return"prepare"===u&&0===O&&0===w&&P(),r}));var r}function E(e){_[e]?(m[e]=!0,w++,function(e){var r=document.createElement("script");r.charset="utf-8",r.src=S.p+""+e+"."+c+".hot-update.js",document.head.appendChild(r)}(e)):g[e]=!0}function P(){f("ready");var e=h;if(h=null,e)if(i)Promise.resolve().then((function(){return I(i)})).then((function(r){e.resolve(r)}),(function(r){e.reject(r)}));else{var r=[];for(var n in v)Object.prototype.hasOwnProperty.call(v,n)&&r.push(j(n));e.resolve(r)}}function I(r){if("ready"!==u)throw new Error("apply() is only allowed in ready status");return function r(n){var t,i,l,p,s;function u(e){for(var r=[e],n={},t=r.map((function(e){return{chain:[e],id:e}}));t.length>0;){var o=t.pop(),i=o.id,c=o.chain;if((p=k[i])&&(!p.hot._selfAccepted||p.hot._selfInvalidated)){if(p.hot._selfDeclined)return{type:"self-declined",chain:c,moduleId:i};if(p.hot._main)return{type:"unaccepted",chain:c,moduleId:i};for(var a=0;a<p.parents.length;a++){var d=p.parents[a],l=k[d];if(l){if(l.hot._declinedDependencies[i])return{type:"declined",chain:c.concat([d]),moduleId:i,parentId:d};-1===r.indexOf(d)&&(l.hot._acceptedDependencies[i]?(n[d]||(n[d]=[]),h(n[d],[i])):(delete n[d],r.push(d),t.push({chain:c.concat([d]),id:d})))}}}}return{type:"accepted",moduleId:e,outdatedModules:r,outdatedDependencies:n}}function h(e,r){for(var n=0;n<r.length;n++){var t=r[n];-1===e.indexOf(t)&&e.push(t)}}x();var w={},O=[],g={},m=function(){};for(var D in v)if(Object.prototype.hasOwnProperty.call(v,D)){var E;s=j(D),E=v[D]?u(s):{type:"disposed",moduleId:D};var P=!1,I=!1,H=!1,M="";switch(E.chain&&(M="\nUpdate propagation: "+E.chain.join(" -> ")),E.type){case"self-declined":n.onDeclined&&n.onDeclined(E),n.ignoreDeclined||(P=new Error("Aborted because of self decline: "+E.moduleId+M));break;case"declined":n.onDeclined&&n.onDeclined(E),n.ignoreDeclined||(P=new Error("Aborted because of declined dependency: "+E.moduleId+" in "+E.parentId+M));break;case"unaccepted":n.onUnaccepted&&n.onUnaccepted(E),n.ignoreUnaccepted||(P=new Error("Aborted because "+s+" is not accepted"Line truncated
|
||||||
+458
@@ -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)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user