diff --git a/go.mod b/go.mod index eb258f6..4fcd252 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/deckarep/golang-set/v2 v2.1.0 github.com/deepmap/oapi-codegen v1.12.4 github.com/disintegration/imaging v1.6.2 + github.com/docker/docker v23.0.1+incompatible github.com/dsoprea/go-exif/v3 v3.0.0-20221012082141-d21ac8e2de85 github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd github.com/getkin/kin-openapi v0.113.0 @@ -29,11 +30,13 @@ require ( github.com/labstack/echo/v4 v4.10.0 github.com/maruel/natural v1.1.0 github.com/mholt/archiver/v3 v3.5.1 + github.com/mileusna/useragent v1.2.1 github.com/moby/sys/mount v0.3.3 github.com/moby/sys/mountinfo v0.6.2 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/robfig/cron v1.2.0 + github.com/robfig/cron/v3 v3.0.1 github.com/satori/go.uuid v1.2.0 github.com/shirou/gopsutil/v3 v3.22.11 github.com/sirupsen/logrus v1.9.0 @@ -42,7 +45,7 @@ require ( go.uber.org/zap v1.24.0 golang.org/x/crypto v0.5.0 golang.org/x/oauth2 v0.3.0 - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c + golang.org/x/sync v0.1.0 gorm.io/gorm v1.24.3 gotest.tools v2.2.0+incompatible ) @@ -83,6 +86,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.15.13 // indirect github.com/klauspost/pgzip v1.2.5 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect diff --git a/go.sum b/go.sum index 46a5eba..f3fc000 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/docker/docker v23.0.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= +github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= @@ -170,8 +172,9 @@ github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -201,6 +204,8 @@ github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOj github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/mileusna/useragent v1.2.1 h1:p3RJWhi3LfuI6BHdddojREyK3p6qX67vIfOVMnUIVr0= +github.com/mileusna/useragent v1.2.1/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc= github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= @@ -235,9 +240,12 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shirou/gopsutil/v3 v3.22.11 h1:kxsPKS+Eeo+VnEQ2XCaGJepeP6KY53QoRTETx3+1ndM= @@ -323,8 +331,9 @@ golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pkg/sqlite/db.go b/pkg/sqlite/db.go index 3802d3d..cedea9d 100644 --- a/pkg/sqlite/db.go +++ b/pkg/sqlite/db.go @@ -14,7 +14,6 @@ import ( "time" "github.com/IceWhaleTech/CasaOS-Common/utils/logger" - "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" model2 "github.com/IceWhaleTech/CasaOS/service/model" "github.com/glebarez/sqlite" @@ -43,7 +42,7 @@ func GetDb(dbPath string) *gorm.DB { } gdb = db - err = db.AutoMigrate(&model2.AppNotify{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}, model.Storage{}) + err = db.AutoMigrate(&model2.AppNotify{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}, model2.PeerDriveDBModel{}) db.Exec("DROP TABLE IF EXISTS o_application") db.Exec("DROP TABLE IF EXISTS o_friend") db.Exec("DROP TABLE IF EXISTS o_person_download") diff --git a/route/v1.go b/route/v1.go index 03245f2..97f7b2e 100644 --- a/route/v1.go +++ b/route/v1.go @@ -95,7 +95,8 @@ func InitV1Router() *gin.Engine { v1FileGroup.POST("/upload", v1.PostFileUpload) v1FileGroup.GET("/upload", v1.GetFileUpload) // v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) - + v1FileGroup.GET("/ws", v1.ConnectWebSocket) + v1FileGroup.GET("/peers", v1.GetPeers) } v1CloudGroup := v1Group.Group("/cloud") v1CloudGroup.Use() @@ -156,6 +157,7 @@ func InitV1Router() *gin.Engine { // merge to system v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify) } + v1OtherGroup := v1Group.Group("/other") v1OtherGroup.Use() { diff --git a/route/v1/file.go b/route/v1/file.go index 2564f10..93645c7 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -1,6 +1,7 @@ package v1 import ( + "encoding/json" "errors" "fmt" "io" @@ -15,11 +16,15 @@ import ( "strconv" "strings" "sync" + "time" "github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS/internal/conf" "github.com/IceWhaleTech/CasaOS/internal/driver" "github.com/IceWhaleTech/CasaOS/model" + "github.com/gorilla/websocket" + "github.com/robfig/cron/v3" + "github.com/tidwall/gjson" "github.com/IceWhaleTech/CasaOS/pkg/utils" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" @@ -34,6 +39,18 @@ import ( "github.com/h2non/filetype" ) +var ( + // 升级成 WebSocket 协议 + upgraderFile = websocket.Upgrader{ + // 允许CORS跨域请求 + CheckOrigin: func(r *http.Request) bool { + return true + }, + } + conn *websocket.Conn + err error +) + // @Summary 读取文件 // @Produce application/json // @Accept application/json @@ -931,3 +948,217 @@ func CommonProxy(w http.ResponseWriter, r *http.Request, link *model.Link, file return nil } } + +type CenterHandler struct { + // 广播通道,有数据则循环每个用户广播出去 + broadcast chan []byte + // 注册通道,有用户进来 则推到用户集合map中 + register chan *Client + // 注销通道,有用户关闭连接 则将该用户剔出集合map中 + unregister chan *Client + // 用户集合,每个用户本身也在跑两个协程,监听用户的读、写的状态 + clients map[string]*Client +} + +type Client struct { + handler *CenterHandler + conn *websocket.Conn + // 每个用户自己的循环跑起来的状态监控 + send chan []byte + ID string `json:"id"` + IP string `json:"ip"` + Name service.Name `json:"name"` + RtcSupported bool `json:"rtcSupported"` + TimerId int `json:"timerId"` + LastBeat time.Time `json:"lastBeat"` +} + +func ConnectWebSocket(c *gin.Context) { + peerId := c.Query("peer") + writer := c.Writer + request := c.Request + key := uuid.NewV4().String() + peerModel := service.MyService.Peer().GetPeerByUserAgent(c.Request.UserAgent()) + //peerModel := model2.PeerDriveDBModel{} + name := service.GetName(request) + if conn, err = upgraderFile.Upgrade(writer, request, writer.Header()); err != nil { + log.Println(err) + return + } + client := &Client{handler: &handler, conn: conn, send: make(chan []byte, 256), ID: service.GetPeerId(request, key), IP: service.GetIP(request), Name: name, RtcSupported: true, TimerId: 0, LastBeat: time.Now()} + if peerId != "" || len(peerModel.ID) > 0 { + if len(peerModel.ID) == 0 { + peerModel = service.MyService.Peer().GetPeerByID(peerId) + } + if len(peerModel.ID) > 0 { + key = peerId + client.ID = peerModel.ID + client.Name = service.GetNameByDB(peerModel) + } + } + if len(peerModel.ID) == 0 { + peerModel.ID = key + peerModel.DisplayName = name.DisplayName + peerModel.DeviceName = name.DeviceName + peerModel.OS = name.OS + peerModel.Browser = name.Browser + peerModel.UserAgent = c.Request.UserAgent() + peerModel.IP = client.IP + service.MyService.Peer().CreatePeer(&peerModel) + } + cookie := http.Cookie{ + Name: "peerid", + Value: key, + Path: "/", + } + http.SetCookie(writer, &cookie) + + pmsg := make(map[string]interface{}) + pmsg["type"] = "peer-joined" + pmsg["peer"] = client + pby, err := json.Marshal(pmsg) + fmt.Println(err) + client.handler.broadcast <- pby + + clients := []Client{} + for _, v := range handler.clients { + + clients = append(clients, *v) + + } + + other := make(map[string]interface{}) + other["type"] = "peers" + other["peers"] = clients + otherBy, err := json.Marshal(other) + fmt.Println(err) + client.send <- otherBy + + // 推给监控中心注册到用户集合中 + handler.register <- client + + data := make(map[string]string) + data["displayName"] = client.Name.DisplayName + data["deviceName"] = client.Name.DeviceName + msg := make(map[string]interface{}) + msg["type"] = "display-name" + msg["message"] = data + by, _ := json.Marshal(msg) + client.send <- by + + // 每个 client 都挂起 2 个新的协程,监控读、写状态 + go client.writePump() + go client.readPump() + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) +} + +var handler = CenterHandler{broadcast: make(chan []byte), + register: make(chan *Client), + unregister: make(chan *Client), + clients: make(map[string]*Client)} + +func init() { + // 起个协程跑起来,监听注册、注销、消息 3 个 channel + go handler.monitoring() + + crontab := cron.New(cron.WithSeconds()) //精确到秒 + //定义定时器调用的任务函数 + + task := func() { + handler.broadcast <- []byte(`{"type":"ping"}`) + } + //定时任务 + spec := "*/20 * * * * ?" //cron表达式,每五秒一次 + // 添加定时任务, + crontab.AddFunc(spec, task) + // 启动定时器 + crontab.Start() +} +func (c *Client) writePump() { + defer func() { + c.handler.unregister <- c + c.conn.Close() + }() + for { + // 广播推过来的新消息,马上通过websocket推给自己 + message, _ := <-c.send + if err := c.conn.WriteMessage(websocket.TextMessage, message); err != nil { + return + } + } +} + +// 读,监听客户端是否有推送内容过来服务端 +func (c *Client) readPump() { + defer func() { + c.handler.unregister <- c + c.conn.Close() + }() + for { + // 循环监听是否该用户是否要发言 + _, message, err := c.conn.ReadMessage() + if err != nil { + // 异常关闭的处理 + if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) { + log.Printf("error: %v", err) + } + break + } + // 要的话,推给广播中心,广播中心再推给每个用户 + + t := gjson.GetBytes(message, "type") + if t.String() == "disconnect" { + c.handler.unregister <- c + c.conn.Close() + c.handler.broadcast <- []byte(`{"type":"peer-left","peerId":"` + c.ID + `"}`) + break + } else if t.String() == "pong" { + c.LastBeat = time.Now() + continue + } + to := gjson.GetBytes(message, "to") + + if len(to.String()) > 0 { + toC := c.handler.clients[to.String()] + if toC == nil { + continue + } + data := map[string]interface{}{} + json.Unmarshal(message, &data) + data["sender"] = c.ID + delete(data, "to") + message, err = json.Marshal(data) + toC.send <- message + } + + c.handler.broadcast <- message + } +} +func (ch *CenterHandler) monitoring() { + for { + select { + // 注册,新用户连接过来会推进注册通道,这里接收推进来的用户指针 + case client := <-ch.register: + ch.clients[client.ID] = client + // 注销,关闭连接或连接异常会将用户推出群聊 + case client := <-ch.unregister: + delete(ch.clients, client.ID) + // 消息,监听到有新消息到来 + case message := <-ch.broadcast: + println("消息来了,message:" + string(message)) + // 推送给每个用户的通道,每个用户都有跑协程起了writePump的监听 + for _, client := range ch.clients { + client.send <- message + } + } + } +} +func GetPeers(c *gin.Context) { + peers := service.MyService.Peer().GetPeers() + for i := 0; i < len(peers); i++ { + if _, ok := handler.clients[peers[i].ID]; ok { + peers[i].Online = true + } + } + c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: peers}) +} diff --git a/service/model/o_drive.go b/service/model/o_drive.go new file mode 100644 index 0000000..94d02cc --- /dev/null +++ b/service/model/o_drive.go @@ -0,0 +1,14 @@ +package model + +type PeerDriveDBModel struct { + ID string `gorm:"column:id;primary_key" json:"id"` + Updated int64 `gorm:"autoUpdateTime"` + Created int64 `gorm:"autoCreateTime"` + UserAgent string `json:"user_agent"` + DisplayName string `json:"display_name"` + DeviceName string `json:"device_name"` + IP string `json:"ip"` + OS string `json:"os"` + Browser string `json:"browser"` + Online bool `gorm:"-" json:"online"` +} diff --git a/service/peer.go b/service/peer.go new file mode 100644 index 0000000..ac5d97f --- /dev/null +++ b/service/peer.go @@ -0,0 +1,60 @@ +/* + * @Author: LinkLeong link@icewhale.org + * @Date: 2022-07-26 18:13:22 + * @LastEditors: LinkLeong + * @LastEditTime: 2022-08-04 20:10:31 + * @FilePath: /CasaOS/service/connections.go + * @Description: + * @Website: https://www.casaos.io + * Copyright (c) 2022 by icewhale, All Rights Reserved. + */ +package service + +import ( + "github.com/IceWhaleTech/CasaOS/service/model" + model2 "github.com/IceWhaleTech/CasaOS/service/model" + "gorm.io/gorm" +) + +type PeerService interface { + GetPeerByUserAgent(ua string) (m model2.PeerDriveDBModel) + GetPeerByID(id string) (m model2.PeerDriveDBModel) + GetPeers() (peers []model2.PeerDriveDBModel) + CreatePeer(m *model2.PeerDriveDBModel) + DeletePeer(id string) +} + +type peerStruct struct { + db *gorm.DB +} + +func (s *peerStruct) GetPeerByUserAgent(ua string) (m model2.PeerDriveDBModel) { + s.db.Where("user_agent = ?", ua).First(&m) + return +} +func (s *peerStruct) GetPeerByID(id string) (m model2.PeerDriveDBModel) { + s.db.Where("id = ?", id).First(&m) + return +} +func (s *peerStruct) GetPeers() (peers []model2.PeerDriveDBModel) { + s.db.Find(&peers) + return +} +func (s *peerStruct) CreatePeer(m *model2.PeerDriveDBModel) { + var list []model.PeerDriveDBModel + s.db.Order("updated desc").Find(&list) + if len(list) > 10 { + for _, v := range list[10:] { + s.db.Where("id = ?", v.ID).Delete(&model.PeerDriveDBModel{}) + } + } + s.db.Create(m) +} + +func (s *peerStruct) DeletePeer(id string) { + s.db.Where("id= ?", id).Delete(&model.PeerDriveDBModel{}) +} + +func NewPeerService(db *gorm.DB) PeerService { + return &peerStruct{db: db} +} diff --git a/service/service.go b/service/service.go index 4c2f96b..26eb389 100644 --- a/service/service.go +++ b/service/service.go @@ -46,6 +46,7 @@ type Repository interface { FsLinkService() FsLinkService FsService() FsService MessageBus() *message_bus.ClientWithResponses + Peer() PeerService Other() OtherService } @@ -70,6 +71,7 @@ func NewService(db *gorm.DB, RuntimePath string) Repository { fs_list: NewFsListService(), fs_link: NewFsLinkService(), fs: NewFsService(), + peer: NewPeerService(db), other: NewOtherService(), } } @@ -90,9 +92,14 @@ type store struct { fs_link FsLinkService fs FsService health HealthService + peer PeerService other OtherService } +func (c *store) Peer() PeerService { + return c.peer +} + func (c *store) Other() OtherService { return c.other } diff --git a/service/socket.go b/service/socket.go new file mode 100644 index 0000000..fd60c98 --- /dev/null +++ b/service/socket.go @@ -0,0 +1,98 @@ +package service + +import ( + "net/http" + "strings" + + model2 "github.com/IceWhaleTech/CasaOS/service/model" + "github.com/docker/docker/pkg/namesgenerator" + "github.com/mileusna/useragent" +) + +type Name struct { + Model string `json:"model"` + OS string `json:"os"` + Browser string `json:"browser"` + Type string `json:"type"` + DeviceName string `json:"deviceName"` + DisplayName string `json:"displayName"` //随机生成 +} + +func GetPeerId(request *http.Request, id string) string { + + cookiePree, err := request.Cookie("peerid") + if err != nil { + return id + } + if len(cookiePree.Value) > 0 { + return cookiePree.Value + } + return id + +} + +func GetIP(request *http.Request) string { + ip := "" + if len(request.Header.Get("x-forwarded-for")) > 0 { + ip = strings.Split(request.Header.Get("x-forwarded-for"), ",")[0] + } else { + ip = request.RemoteAddr + } + + if ip == "::1" || ip == "::ffff:127.0.0.1" { + ip = "127.0.0.1" + } + return ip +} + +func GetName(request *http.Request) Name { + us := useragent.Parse(request.Header.Get("user-agent")) + + device := "" + if len(us.Device) > 0 { + device += us.Device + } else { + device += us.Name + } + + return Name{ + Model: us.Device, + OS: us.OS, + Browser: us.Name, + DeviceName: device, + DisplayName: Generate(), + } +} +func GetNameByDB(m model2.PeerDriveDBModel) Name { + device := "" + if len(m.DeviceName) > 0 { + device += m.DeviceName + } else { + device += m.Browser + } + return Name{ + Model: m.DeviceName, + OS: m.OS, + Browser: m.Browser, + DeviceName: device, + DisplayName: m.DisplayName, + } +} +func Generate() string { + nameParts := strings.Split(namesgenerator.GetRandomName(0), "_") + + for i := 0; i < len(nameParts); i++ { + nameParts[i] = strings.Title(nameParts[i]) + } + + return strings.Join(nameParts, " ") +} + +func GenerateMultiple(count int) []string { + s := make([]string, count) + for i := 0; i <= count; i++ { + s[i] = Generate() + } + + return s +}