parent
528a98ddfa
commit
4c40755d3b
@ -0,0 +1,11 @@
|
||||
木兰宽松许可证
|
||||
|
||||
Copyright (c) [2019] [link1st]
|
||||
[gowebsocket] is licensed under the Mulan PSL v1.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||
You may obtain a copy of Mulan PSL v1 at:
|
||||
http://license.coscl.org.cn/MulanPSL
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
See the Mulan PSL v1 for more details.
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 12:11
|
||||
*/
|
||||
|
||||
package common
|
||||
|
||||
const (
|
||||
OK = 200 // Success
|
||||
NotLoggedIn = 1000 // 未登录
|
||||
ParameterIllegal = 1001 // 参数不合法
|
||||
UnauthorizedUserId = 1002 // 非法的用户Id
|
||||
Unauthorized = 1003 // 未授权
|
||||
ServerError = 1004 // 系统错误
|
||||
NotData = 1005 // 没有数据
|
||||
ModelAddError = 1006 // 添加错误
|
||||
ModelDeleteError = 1007 // 删除错误
|
||||
ModelStoreError = 1008 // 存储错误
|
||||
OperationFailure = 1009 // 操作失败
|
||||
RoutingNotExist = 1010 // 路由不存在
|
||||
)
|
||||
|
||||
// 根据错误码 获取错误信息
|
||||
func GetErrorMessage(code uint32, message string) string {
|
||||
var codeMessage string
|
||||
codeMap := map[uint32]string{
|
||||
OK: "Success",
|
||||
NotLoggedIn: "未登录",
|
||||
ParameterIllegal: "参数不合法",
|
||||
UnauthorizedUserId: "非法的用户Id",
|
||||
Unauthorized: "未授权",
|
||||
NotData: "没有数据",
|
||||
ServerError: "系统错误",
|
||||
ModelAddError: "添加错误",
|
||||
ModelDeleteError: "删除错误",
|
||||
ModelStoreError: "存储错误",
|
||||
OperationFailure: "操作失败",
|
||||
RoutingNotExist: "路由不存在",
|
||||
}
|
||||
|
||||
if message == "" {
|
||||
if value, ok := codeMap[code]; ok {
|
||||
// 存在
|
||||
codeMessage = value
|
||||
} else {
|
||||
codeMessage = "未定义错误类型!"
|
||||
}
|
||||
} else {
|
||||
codeMessage = message
|
||||
}
|
||||
|
||||
return codeMessage
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 12:11
|
||||
*/
|
||||
|
||||
package common
|
||||
|
||||
type JsonResult struct {
|
||||
Code uint32 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func Response(code uint32, message string, data interface{}) JsonResult {
|
||||
|
||||
message = GetErrorMessage(code, message)
|
||||
jsonMap := grantMap(code, message, data)
|
||||
|
||||
return jsonMap
|
||||
}
|
||||
|
||||
// 按照接口格式生成原数据数组
|
||||
func grantMap(code uint32, message string, data interface{}) JsonResult {
|
||||
|
||||
jsonMap := JsonResult{
|
||||
Code: code,
|
||||
Msg: message,
|
||||
Data: data,
|
||||
}
|
||||
return jsonMap
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
app:
|
||||
logFile: log/gin.log
|
||||
httpPort: 8080
|
||||
webSocketPort: 8089
|
||||
rpcPort: 9001
|
||||
httpUrl: 127.0.0.1:8080
|
||||
webSocketUrl: 127.0.0.1:8089
|
||||
|
||||
|
||||
redis:
|
||||
addr: "localhost:6379"
|
||||
password: ""
|
||||
DB: 0
|
||||
poolSize: 30
|
||||
minIdleConns: 30
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 12:11
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gowebsocket/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type BaseController struct {
|
||||
gin.Context
|
||||
}
|
||||
|
||||
// 获取全部请求解析到map
|
||||
func Response(c *gin.Context, code uint32, msg string, data map[string]interface{}) {
|
||||
message := common.Response(code, msg, data)
|
||||
|
||||
// 允许跨域
|
||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
c.Header("Access-Control-Allow-Origin", "*") // 这是允许访问所有域
|
||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") // 服务器支持的所有跨域请求的方法,为了避免浏览次请求的多次'预检'请求
|
||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
|
||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析
|
||||
c.Header("Access-Control-Allow-Credentials", "true") // 跨域请求是否需要带cookie信息 默认设置为true
|
||||
c.Set("content-type", "application/json") // 设置返回格式是json
|
||||
|
||||
c.JSON(http.StatusOK, message)
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 12:11
|
||||
*/
|
||||
|
||||
package home
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/viper"
|
||||
"gowebsocket/servers/websocket"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 聊天页面
|
||||
func Index(c *gin.Context) {
|
||||
|
||||
appIdStr := c.Query("appId")
|
||||
appIdUint64, _ := strconv.ParseInt(appIdStr, 10, 32)
|
||||
appId := uint32(appIdUint64)
|
||||
if !websocket.InAppIds(appId) {
|
||||
appId = websocket.GetDefaultAppId()
|
||||
}
|
||||
|
||||
fmt.Println("http_request 聊天首页", appId)
|
||||
|
||||
data := gin.H{
|
||||
"title": "聊天首页",
|
||||
"appId": appId,
|
||||
"httpUrl": viper.GetString("app.httpUrl"),
|
||||
"webSocketUrl": viper.GetString("app.webSocketUrl"),
|
||||
}
|
||||
c.HTML(http.StatusOK, "index.tpl", data)
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 12:11
|
||||
*/
|
||||
|
||||
package systems
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gowebsocket/common"
|
||||
"gowebsocket/controllers"
|
||||
"gowebsocket/servers/websocket"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// 查询系统状态
|
||||
func Status(c *gin.Context) {
|
||||
|
||||
isDebug := c.Query("isDebug")
|
||||
fmt.Println("http_request 查询系统状态", isDebug)
|
||||
|
||||
data := make(map[string]interface{})
|
||||
|
||||
numGoroutine := runtime.NumGoroutine()
|
||||
numCPU := runtime.NumCPU()
|
||||
|
||||
// goroutine 的数量
|
||||
data["numGoroutine"] = numGoroutine
|
||||
data["numCPU"] = numCPU
|
||||
|
||||
// ClientManager 信息
|
||||
data["managerInfo"] = websocket.GetManagerInfo(isDebug)
|
||||
|
||||
controllers.Response(c, common.OK, "", data)
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
module gowebsocket
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.4.8-0.20190312181446-1485a34d5d57 // indirect
|
||||
github.com/gin-gonic/gin v1.7.2
|
||||
github.com/go-playground/validator/v10 v10.8.0 // indirect
|
||||
github.com/go-redis/redis v0.0.0-20190719092155-6bc7daa5b1e8
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/hcl v1.0.1-0.20190611123218-cf7d376da96d // indirect
|
||||
github.com/json-iterator/go v1.1.11 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/pelletier/go-toml v1.4.1-0.20190725070617-84da2c4a25c5 // indirect
|
||||
github.com/spf13/afero v1.2.2 // indirect
|
||||
github.com/spf13/cast v1.3.1-0.20190531093228-c01685bb8421 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.4-0.20181223182923-24fa6976df40 // indirect
|
||||
github.com/spf13/viper v1.4.1-0.20190728125013-1b33e8258e07
|
||||
github.com/subosito/gotenv v1.1.1 // indirect
|
||||
github.com/ugorji/go v1.2.6 // indirect
|
||||
google.golang.org/grpc v1.21.0
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
@ -0,0 +1,239 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.8-0.20190312181446-1485a34d5d57 h1:r+AdyYQnMjCqabCiXfAES7u0tbaqXlLXuZ5FT+5OEQs=
|
||||
github.com/fsnotify/fsnotify v1.4.8-0.20190312181446-1485a34d5d57/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
|
||||
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.8.0 h1:1kAa0fCrnpv+QYdkdcRzrRM7AyYs5o8+jZdJCz9xj6k=
|
||||
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
|
||||
github.com/go-redis/redis v0.0.0-20190719092155-6bc7daa5b1e8 h1:+fE3DwORl28yutMsVT36NnW52u8el5F3Ye9bgXZtokc=
|
||||
github.com/go-redis/redis v0.0.0-20190719092155-6bc7daa5b1e8/go.mod h1:nuQKdm6S7SnV28NJEN2ZNbKpddAM1O76Z2LMJcIxJVM=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/hcl v1.0.1-0.20190611123218-cf7d376da96d h1:r4iSf+UX1tNxFJZ64FsUoOfysT7TePSbRNz4/mYGUIE=
|
||||
github.com/hashicorp/hcl v1.0.1-0.20190611123218-cf7d376da96d/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.4.1-0.20190725070617-84da2c4a25c5 h1:rW9pqjOLUVvikJFWrF53GlhmZNTFtsjjNA0LD2sYLvg=
|
||||
github.com/pelletier/go-toml v1.4.1-0.20190725070617-84da2c4a25c5/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1-0.20190531093228-c01685bb8421 h1:s+WESDalIlUupImv6znWrHX6XIRXuVTBsX633p7Ymms=
|
||||
github.com/spf13/cast v1.3.1-0.20190531093228-c01685bb8421/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.4-0.20181223182923-24fa6976df40 h1:2gwxRRQ5I+FcDbxGtkIC9kWD7EFBewHjQqD8rDQAVQA=
|
||||
github.com/spf13/pflag v1.0.4-0.20181223182923-24fa6976df40/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.4.1-0.20190728125013-1b33e8258e07 h1:Bxzp40S+I62o0BB0Jd23i3OYDtIP2Gs8NtP+Sv6rYHg=
|
||||
github.com/spf13/viper v1.4.1-0.20190728125013-1b33e8258e07/go.mod h1:LLu5zwCkRPEBY0VPcRMqh58VtcO8Lp1DgqwstU7rYlk=
|
||||
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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.1.1 h1:TWxckSF6WVKWbo2M3tMqCtWa9NFUgqM1SSynxmYONOI=
|
||||
github.com/subosito/gotenv v1.1.1/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
|
||||
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-01
|
||||
* Time: 18:13
|
||||
*/
|
||||
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetOrderIdTime() (orderId string) {
|
||||
|
||||
currentTime := time.Now().Nanosecond()
|
||||
orderId = fmt.Sprintf("%d", currentTime)
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-03
|
||||
* Time: 15:23
|
||||
*/
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gowebsocket/lib/redislib"
|
||||
"gowebsocket/models"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
serversHashKey = "acc:hash:servers" // 全部的服务器
|
||||
serversHashCacheTime = 2 * 60 * 60 // key过期时间
|
||||
serversHashTimeout = 3 * 60 // 超时时间
|
||||
)
|
||||
|
||||
func getServersHashKey() (key string) {
|
||||
key = fmt.Sprintf("%s", serversHashKey)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 设置服务器信息
|
||||
func SetServerInfo(server *models.Server, currentTime uint64) (err error) {
|
||||
key := getServersHashKey()
|
||||
|
||||
value := fmt.Sprintf("%d", currentTime)
|
||||
|
||||
redisClient := redislib.GetClient()
|
||||
number, err := redisClient.Do("hSet", key, server.String(), value).Int()
|
||||
if err != nil {
|
||||
fmt.Println("SetServerInfo", key, number, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if number != 1 {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
redisClient.Do("Expire", key, serversHashCacheTime)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 下线服务器信息
|
||||
func DelServerInfo(server *models.Server) (err error) {
|
||||
key := getServersHashKey()
|
||||
redisClient := redislib.GetClient()
|
||||
number, err := redisClient.Do("hDel", key, server.String()).Int()
|
||||
if err != nil {
|
||||
fmt.Println("DelServerInfo", key, number, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if number != 1 {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
redisClient.Do("Expire", key, serversHashCacheTime)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetServerAll(currentTime uint64) (servers []*models.Server, err error) {
|
||||
|
||||
servers = make([]*models.Server, 0)
|
||||
key := getServersHashKey()
|
||||
|
||||
redisClient := redislib.GetClient()
|
||||
|
||||
val, err := redisClient.Do("hGetAll", key).Result()
|
||||
|
||||
valByte, _ := json.Marshal(val)
|
||||
fmt.Println("GetServerAll", key, string(valByte))
|
||||
|
||||
serverMap, err := redisClient.HGetAll(key).Result()
|
||||
if err != nil {
|
||||
fmt.Println("SetServerInfo", key, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for key, value := range serverMap {
|
||||
valueUint64, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
fmt.Println("GetServerAll", key, err)
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 超时
|
||||
if valueUint64+serversHashTimeout <= currentTime {
|
||||
continue
|
||||
}
|
||||
|
||||
server, err := models.StringToServer(key)
|
||||
if err != nil {
|
||||
fmt.Println("GetServerAll", key, err)
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
servers = append(servers, server)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-26
|
||||
* Time: 09:18
|
||||
*/
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gowebsocket/lib/redislib"
|
||||
)
|
||||
|
||||
const (
|
||||
submitAgainPrefix = "acc:submit:again:" // 数据不重复提交
|
||||
)
|
||||
|
||||
/********************* 查询数据是否处理过 ************************/
|
||||
|
||||
// 获取数据提交去除key
|
||||
func getSubmitAgainKey(from string, value string) (key string) {
|
||||
key = fmt.Sprintf("%s%s:%s", submitAgainPrefix, from, value)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 重复提交
|
||||
// return true:重复提交 false:第一次提交
|
||||
func submitAgain(from string, second int, value string) (isSubmitAgain bool) {
|
||||
|
||||
// 默认重复提交
|
||||
isSubmitAgain = true
|
||||
key := getSubmitAgainKey(from, value)
|
||||
|
||||
redisClient := redislib.GetClient()
|
||||
number, err := redisClient.Do("setNx", key, "1").Int()
|
||||
if err != nil {
|
||||
fmt.Println("submitAgain", key, number, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if number != 1 {
|
||||
|
||||
return
|
||||
}
|
||||
// 第一次提交
|
||||
isSubmitAgain = false
|
||||
|
||||
redisClient.Do("Expire", key, second)
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// Seq 重复提交
|
||||
func SeqDuplicates(seq string) (result bool) {
|
||||
result = submitAgain("seq", 12*60*60, seq)
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 17:28
|
||||
*/
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/go-redis/redis"
|
||||
"gowebsocket/lib/redislib"
|
||||
"gowebsocket/models"
|
||||
)
|
||||
|
||||
const (
|
||||
userOnlinePrefix = "acc:user:online:" // 用户在线状态
|
||||
userOnlineCacheTime = 24 * 60 * 60
|
||||
)
|
||||
|
||||
/********************* 查询用户是否在线 ************************/
|
||||
func getUserOnlineKey(userKey string) (key string) {
|
||||
key = fmt.Sprintf("%s%s", userOnlinePrefix, userKey)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetUserOnlineInfo(userKey string) (userOnline *models.UserOnline, err error) {
|
||||
redisClient := redislib.GetClient()
|
||||
|
||||
key := getUserOnlineKey(userKey)
|
||||
|
||||
data, err := redisClient.Get(key).Bytes()
|
||||
if err != nil {
|
||||
if err == redis.Nil {
|
||||
fmt.Println("GetUserOnlineInfo", userKey, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("GetUserOnlineInfo", userKey, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userOnline = &models.UserOnline{}
|
||||
err = json.Unmarshal(data, userOnline)
|
||||
if err != nil {
|
||||
fmt.Println("获取用户在线数据 json Unmarshal", userKey, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("获取用户在线数据", userKey, "time", userOnline.LoginTime, userOnline.HeartbeatTime, "AccIp", userOnline.AccIp, userOnline.IsLogoff)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 设置用户在线数据
|
||||
func SetUserOnlineInfo(userKey string, userOnline *models.UserOnline) (err error) {
|
||||
|
||||
redisClient := redislib.GetClient()
|
||||
key := getUserOnlineKey(userKey)
|
||||
|
||||
valueByte, err := json.Marshal(userOnline)
|
||||
if err != nil {
|
||||
fmt.Println("设置用户在线数据 json Marshal", key, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
_, err = redisClient.Do("setEx", key, userOnlineCacheTime, string(valueByte)).Result()
|
||||
if err != nil {
|
||||
fmt.Println("设置用户在线数据 ", key, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 14:18
|
||||
*/
|
||||
|
||||
package redislib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var (
|
||||
client *redis.Client
|
||||
)
|
||||
|
||||
func ExampleNewClient() {
|
||||
|
||||
client = redis.NewClient(&redis.Options{
|
||||
Addr: viper.GetString("redis.addr"),
|
||||
Password: viper.GetString("redis.password"),
|
||||
DB: viper.GetInt("redis.DB"),
|
||||
PoolSize: viper.GetInt("redis.poolSize"),
|
||||
MinIdleConns: viper.GetInt("redis.minIdleConns"),
|
||||
})
|
||||
|
||||
pong, err := client.Ping().Result()
|
||||
fmt.Println("初始化redis:", pong, err)
|
||||
// Output: PONG <nil>
|
||||
}
|
||||
|
||||
func GetClient() (c *redis.Client) {
|
||||
|
||||
return client
|
||||
}
|
@ -0,0 +1 @@
|
||||
!.gitignore
|
@ -0,0 +1,21 @@
|
||||
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
|
||||
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
- using env: export GIN_MODE=release
|
||||
- using code: gin.SetMode(gin.ReleaseMode)
|
||||
|
||||
[GIN-debug] Loaded HTML Templates (3):
|
||||
-
|
||||
- index.html
|
||||
- index.tpl
|
||||
|
||||
[GIN-debug] GET /user/list --> gowebsocket/controllers/user.List (3 handlers)
|
||||
[GIN-debug] GET /user/online --> gowebsocket/controllers/user.Online (3 handlers)
|
||||
[GIN-debug] POST /user/sendMessage --> gowebsocket/controllers/user.SendMessage (3 handlers)
|
||||
[GIN-debug] POST /user/sendMessageAll --> gowebsocket/controllers/user.SendMessageAll (3 handlers)
|
||||
[GIN-debug] GET /system/state --> gowebsocket/controllers/systems.Status (3 handlers)
|
||||
[GIN-debug] GET /home/index --> gowebsocket/controllers/home.Index (3 handlers)
|
||||
[GIN] 2021/11/20 - 00:19:19 | 200 | 2.067409ms | 127.0.0.1 | GET "/home/index"
|
||||
[GIN] 2021/11/20 - 00:19:20 | 200 | 748.062µs | 127.0.0.1 | GET "/user/list?appId=101"
|
||||
[GIN] 2021/11/20 - 00:19:30 | 200 | 1.828355ms | 127.0.0.1 | GET "/home/index?appId=104"
|
||||
[GIN] 2021/11/20 - 00:19:31 | 200 | 490.323µs | 127.0.0.1 | GET "/user/list?appId=104"
|
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 09:59
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/viper"
|
||||
"gowebsocket/lib/redislib"
|
||||
"gowebsocket/routers"
|
||||
"gowebsocket/servers/grpcserver"
|
||||
"gowebsocket/servers/task"
|
||||
"gowebsocket/servers/websocket"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
initConfig()
|
||||
|
||||
initFile()
|
||||
|
||||
initRedis()
|
||||
|
||||
router := gin.Default()
|
||||
// 初始化路由
|
||||
routers.Init(router)
|
||||
routers.WebsocketInit()
|
||||
|
||||
// 定时任务
|
||||
task.Init()
|
||||
|
||||
// 服务注册
|
||||
task.ServerInit()
|
||||
|
||||
go websocket.StartWebSocket()
|
||||
// grpc
|
||||
go grpcserver.Init()
|
||||
|
||||
go open()
|
||||
|
||||
httpPort := viper.GetString("app.httpPort")
|
||||
http.ListenAndServe(":"+httpPort, router)
|
||||
|
||||
}
|
||||
|
||||
// 初始化日志
|
||||
func initFile() {
|
||||
// Disable Console Color, you don't need console color when writing the logs to file.
|
||||
gin.DisableConsoleColor()
|
||||
|
||||
// Logging to a file.
|
||||
logFile := viper.GetString("app.logFile")
|
||||
f, _ := os.Create(logFile)
|
||||
gin.DefaultWriter = io.MultiWriter(f)
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
viper.SetConfigName("config/app")
|
||||
viper.AddConfigPath(".") // 添加搜索路径
|
||||
|
||||
err := viper.ReadInConfig()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Fatal error config file: %s \n", err))
|
||||
}
|
||||
|
||||
fmt.Println("config app:", viper.Get("app"))
|
||||
fmt.Println("config redis:", viper.Get("redis"))
|
||||
|
||||
}
|
||||
|
||||
func initRedis() {
|
||||
redislib.ExampleNewClient()
|
||||
}
|
||||
|
||||
func open() {
|
||||
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
|
||||
httpUrl := viper.GetString("app.httpUrl")
|
||||
httpUrl = "http://" + httpUrl + "/home/index"
|
||||
|
||||
fmt.Println("访问页面体验:", httpUrl)
|
||||
|
||||
cmd := exec.Command("open", httpUrl)
|
||||
cmd.Output()
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-01
|
||||
* Time: 10:40
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import "gowebsocket/common"
|
||||
|
||||
const (
|
||||
MessageTypeText = "text"
|
||||
|
||||
MessageCmdMsg = "msg"
|
||||
MessageCmdEnter = "enter"
|
||||
MessageCmdExit = "exit"
|
||||
)
|
||||
|
||||
// 消息的定义
|
||||
type Message struct {
|
||||
Target string `json:"target"` // 目标
|
||||
Type string `json:"type"` // 消息类型 text/img/
|
||||
Msg string `json:"msg"` // 消息内容
|
||||
From string `json:"from"` // 发送者
|
||||
}
|
||||
|
||||
func NewTestMsg(from string, Msg string) (message *Message) {
|
||||
|
||||
message = &Message{
|
||||
Type: MessageTypeText,
|
||||
From: from,
|
||||
Msg: Msg,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getTextMsgData(cmd, uuId, msgId, message string) string {
|
||||
textMsg := NewTestMsg(uuId, message)
|
||||
head := NewResponseHead(msgId, cmd, common.OK, "Ok", textMsg)
|
||||
|
||||
return head.String()
|
||||
}
|
||||
|
||||
// 文本消息
|
||||
func GetMsgData(uuId, msgId, cmd, message string) string {
|
||||
|
||||
return getTextMsgData(cmd, uuId, msgId, message)
|
||||
}
|
||||
|
||||
// 文本消息
|
||||
func GetTextMsgData(uuId, msgId, message string) string {
|
||||
|
||||
return getTextMsgData("msg", uuId, msgId, message)
|
||||
}
|
||||
|
||||
// 用户进入消息
|
||||
func GetTextMsgDataEnter(uuId, msgId, message string) string {
|
||||
|
||||
return getTextMsgData("enter", uuId, msgId, message)
|
||||
}
|
||||
|
||||
// 用户退出消息
|
||||
func GetTextMsgDataExit(uuId, msgId, message string) string {
|
||||
|
||||
return getTextMsgData("exit", uuId, msgId, message)
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-27
|
||||
* Time: 14:41
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
/************************ 请求数据 **************************/
|
||||
// 通用请求数据格式
|
||||
type Request struct {
|
||||
Seq string `json:"seq"` // 消息的唯一Id
|
||||
Cmd string `json:"cmd"` // 请求命令字
|
||||
Data interface{} `json:"data,omitempty"` // 数据 json
|
||||
}
|
||||
|
||||
// 登录请求数据
|
||||
type Login struct {
|
||||
ServiceToken string `json:"serviceToken"` // 验证用户是否登录
|
||||
AppId uint32 `json:"appId,omitempty"`
|
||||
UserId string `json:"userId,omitempty"`
|
||||
}
|
||||
|
||||
// 心跳请求数据
|
||||
type HeartBeat struct {
|
||||
UserId string `json:"userId,omitempty"`
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-01
|
||||
* Time: 10:46
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
/************************ 响应数据 **************************/
|
||||
type Head struct {
|
||||
Seq string `json:"seq"` // 消息的Id
|
||||
Cmd string `json:"cmd"` // 消息的cmd 动作
|
||||
Response *Response `json:"response"` // 消息体
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
Code uint32 `json:"code"`
|
||||
CodeMsg string `json:"codeMsg"`
|
||||
Data interface{} `json:"data"` // 数据 json
|
||||
}
|
||||
|
||||
// push 数据结构体
|
||||
type PushMsg struct {
|
||||
Seq string `json:"seq"`
|
||||
Uuid uint64 `json:"uuid"`
|
||||
Type string `json:"type"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// 设置返回消息
|
||||
func NewResponseHead(seq string, cmd string, code uint32, codeMsg string, data interface{}) *Head {
|
||||
response := NewResponse(code, codeMsg, data)
|
||||
|
||||
return &Head{Seq: seq, Cmd: cmd, Response: response}
|
||||
}
|
||||
|
||||
func (h *Head) String() (headStr string) {
|
||||
headBytes, _ := json.Marshal(h)
|
||||
headStr = string(headBytes)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func NewResponse(code uint32, codeMsg string, data interface{}) *Response {
|
||||
return &Response{Code: code, CodeMsg: codeMsg, Data: data}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-03
|
||||
* Time: 15:38
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Ip string `json:"ip"` // ip
|
||||
Port string `json:"port"` // 端口
|
||||
}
|
||||
|
||||
func NewServer(ip string, port string) *Server {
|
||||
|
||||
return &Server{Ip: ip, Port: port}
|
||||
}
|
||||
|
||||
func (s *Server) String() (str string) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
str = fmt.Sprintf("%s:%s", s.Ip, s.Port)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func StringToServer(str string) (server *Server, err error) {
|
||||
list := strings.Split(str, ":")
|
||||
if len(list) != 2 {
|
||||
|
||||
return nil, errors.New("err")
|
||||
}
|
||||
|
||||
server = &Server{
|
||||
Ip: list[0],
|
||||
Port: list[1],
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 17:36
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
heartbeatTimeout = 3 * 60 // 用户心跳超时时间
|
||||
)
|
||||
|
||||
// 用户在线状态
|
||||
type UserOnline struct {
|
||||
AccIp string `json:"accIp"` // acc Ip
|
||||
AccPort string `json:"accPort"` // acc 端口
|
||||
AppId uint32 `json:"appId"` // appId
|
||||
UserId string `json:"userId"` // 用户Id
|
||||
ClientIp string `json:"clientIp"` // 客户端Ip
|
||||
ClientPort string `json:"clientPort"` // 客户端端口
|
||||
LoginTime uint64 `json:"loginTime"` // 用户上次登录时间
|
||||
HeartbeatTime uint64 `json:"heartbeatTime"` // 用户上次心跳时间
|
||||
LogOutTime uint64 `json:"logOutTime"` // 用户退出登录的时间
|
||||
Qua string `json:"qua"` // qua
|
||||
DeviceInfo string `json:"deviceInfo"` // 设备信息
|
||||
IsLogoff bool `json:"isLogoff"` // 是否下线
|
||||
}
|
||||
|
||||
/********************** 数据处理 *********************************/
|
||||
|
||||
// 用户登录
|
||||
func UserLogin(accIp, accPort string, appId uint32, userId string, addr string, loginTime uint64) (userOnline *UserOnline) {
|
||||
|
||||
userOnline = &UserOnline{
|
||||
AccIp: accIp,
|
||||
AccPort: accPort,
|
||||
AppId: appId,
|
||||
UserId: userId,
|
||||
ClientIp: addr,
|
||||
LoginTime: loginTime,
|
||||
HeartbeatTime: loginTime,
|
||||
IsLogoff: false,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 用户心跳
|
||||
func (u *UserOnline) Heartbeat(currentTime uint64) {
|
||||
|
||||
u.HeartbeatTime = currentTime
|
||||
u.IsLogoff = false
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 用户退出登录
|
||||
func (u *UserOnline) LogOut() {
|
||||
|
||||
currentTime := uint64(time.Now().Unix())
|
||||
u.LogOutTime = currentTime
|
||||
u.IsLogoff = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/********************** 数据操作 *********************************/
|
||||
|
||||
// 用户是否在线
|
||||
func (u *UserOnline) IsOnline() (online bool) {
|
||||
if u.IsLogoff {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
currentTime := uint64(time.Now().Unix())
|
||||
|
||||
if u.HeartbeatTime < (currentTime - heartbeatTimeout) {
|
||||
fmt.Println("用户是否在线 心跳超时", u.AppId, u.UserId, u.HeartbeatTime)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if u.IsLogoff {
|
||||
fmt.Println("用户是否在线 用户已经下线", u.AppId, u.UserId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 用户是否在本台机器上
|
||||
func (u *UserOnline) UserIsLocal(localIp, localPort string) (result bool) {
|
||||
|
||||
if u.AccIp == localIp && u.AccPort == localPort {
|
||||
result = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
protoc --go_out=plugins=grpc:. im_protobuf.proto
|
@ -0,0 +1,740 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: im_protobuf.proto
|
||||
|
||||
package protobuf
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// 查询用户是否在线
|
||||
type QueryUsersOnlineReq struct {
|
||||
AppId uint32 `protobuf:"varint,1,opt,name=appId,proto3" json:"appId,omitempty"`
|
||||
UserId string `protobuf:"bytes,2,opt,name=userId,proto3" json:"userId,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *QueryUsersOnlineReq) Reset() { *m = QueryUsersOnlineReq{} }
|
||||
func (m *QueryUsersOnlineReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*QueryUsersOnlineReq) ProtoMessage() {}
|
||||
func (*QueryUsersOnlineReq) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{0}
|
||||
}
|
||||
|
||||
func (m *QueryUsersOnlineReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_QueryUsersOnlineReq.Unmarshal(m, b)
|
||||
}
|
||||
func (m *QueryUsersOnlineReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_QueryUsersOnlineReq.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *QueryUsersOnlineReq) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_QueryUsersOnlineReq.Merge(m, src)
|
||||
}
|
||||
func (m *QueryUsersOnlineReq) XXX_Size() int {
|
||||
return xxx_messageInfo_QueryUsersOnlineReq.Size(m)
|
||||
}
|
||||
func (m *QueryUsersOnlineReq) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_QueryUsersOnlineReq.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_QueryUsersOnlineReq proto.InternalMessageInfo
|
||||
|
||||
func (m *QueryUsersOnlineReq) GetAppId() uint32 {
|
||||
if m != nil {
|
||||
return m.AppId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *QueryUsersOnlineReq) GetUserId() string {
|
||||
if m != nil {
|
||||
return m.UserId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type QueryUsersOnlineRsp struct {
|
||||
RetCode uint32 `protobuf:"varint,1,opt,name=retCode,proto3" json:"retCode,omitempty"`
|
||||
ErrMsg string `protobuf:"bytes,2,opt,name=errMsg,proto3" json:"errMsg,omitempty"`
|
||||
Online bool `protobuf:"varint,3,opt,name=online,proto3" json:"online,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *QueryUsersOnlineRsp) Reset() { *m = QueryUsersOnlineRsp{} }
|
||||
func (m *QueryUsersOnlineRsp) String() string { return proto.CompactTextString(m) }
|
||||
func (*QueryUsersOnlineRsp) ProtoMessage() {}
|
||||
func (*QueryUsersOnlineRsp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{1}
|
||||
}
|
||||
|
||||
func (m *QueryUsersOnlineRsp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_QueryUsersOnlineRsp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *QueryUsersOnlineRsp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_QueryUsersOnlineRsp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *QueryUsersOnlineRsp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_QueryUsersOnlineRsp.Merge(m, src)
|
||||
}
|
||||
func (m *QueryUsersOnlineRsp) XXX_Size() int {
|
||||
return xxx_messageInfo_QueryUsersOnlineRsp.Size(m)
|
||||
}
|
||||
func (m *QueryUsersOnlineRsp) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_QueryUsersOnlineRsp.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_QueryUsersOnlineRsp proto.InternalMessageInfo
|
||||
|
||||
func (m *QueryUsersOnlineRsp) GetRetCode() uint32 {
|
||||
if m != nil {
|
||||
return m.RetCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *QueryUsersOnlineRsp) GetErrMsg() string {
|
||||
if m != nil {
|
||||
return m.ErrMsg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *QueryUsersOnlineRsp) GetOnline() bool {
|
||||
if m != nil {
|
||||
return m.Online
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
type SendMsgReq struct {
|
||||
Seq string `protobuf:"bytes,1,opt,name=seq,proto3" json:"seq,omitempty"`
|
||||
AppId uint32 `protobuf:"varint,2,opt,name=appId,proto3" json:"appId,omitempty"`
|
||||
UserId string `protobuf:"bytes,3,opt,name=userId,proto3" json:"userId,omitempty"`
|
||||
Cms string `protobuf:"bytes,4,opt,name=cms,proto3" json:"cms,omitempty"`
|
||||
Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Msg string `protobuf:"bytes,6,opt,name=msg,proto3" json:"msg,omitempty"`
|
||||
IsLocal bool `protobuf:"varint,7,opt,name=isLocal,proto3" json:"isLocal,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) Reset() { *m = SendMsgReq{} }
|
||||
func (m *SendMsgReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendMsgReq) ProtoMessage() {}
|
||||
func (*SendMsgReq) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{2}
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendMsgReq.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SendMsgReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SendMsgReq.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SendMsgReq) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SendMsgReq.Merge(m, src)
|
||||
}
|
||||
func (m *SendMsgReq) XXX_Size() int {
|
||||
return xxx_messageInfo_SendMsgReq.Size(m)
|
||||
}
|
||||
func (m *SendMsgReq) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SendMsgReq.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SendMsgReq proto.InternalMessageInfo
|
||||
|
||||
func (m *SendMsgReq) GetSeq() string {
|
||||
if m != nil {
|
||||
return m.Seq
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) GetAppId() uint32 {
|
||||
if m != nil {
|
||||
return m.AppId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) GetUserId() string {
|
||||
if m != nil {
|
||||
return m.UserId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) GetCms() string {
|
||||
if m != nil {
|
||||
return m.Cms
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) GetType() string {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgReq) GetIsLocal() bool {
|
||||
if m != nil {
|
||||
return m.IsLocal
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type SendMsgRsp struct {
|
||||
RetCode uint32 `protobuf:"varint,1,opt,name=retCode,proto3" json:"retCode,omitempty"`
|
||||
ErrMsg string `protobuf:"bytes,2,opt,name=errMsg,proto3" json:"errMsg,omitempty"`
|
||||
SendMsgId string `protobuf:"bytes,3,opt,name=sendMsgId,proto3" json:"sendMsgId,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SendMsgRsp) Reset() { *m = SendMsgRsp{} }
|
||||
func (m *SendMsgRsp) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendMsgRsp) ProtoMessage() {}
|
||||
func (*SendMsgRsp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{3}
|
||||
}
|
||||
|
||||
func (m *SendMsgRsp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendMsgRsp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SendMsgRsp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SendMsgRsp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SendMsgRsp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SendMsgRsp.Merge(m, src)
|
||||
}
|
||||
func (m *SendMsgRsp) XXX_Size() int {
|
||||
return xxx_messageInfo_SendMsgRsp.Size(m)
|
||||
}
|
||||
func (m *SendMsgRsp) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SendMsgRsp.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SendMsgRsp proto.InternalMessageInfo
|
||||
|
||||
func (m *SendMsgRsp) GetRetCode() uint32 {
|
||||
if m != nil {
|
||||
return m.RetCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *SendMsgRsp) GetErrMsg() string {
|
||||
if m != nil {
|
||||
return m.ErrMsg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgRsp) GetSendMsgId() string {
|
||||
if m != nil {
|
||||
return m.SendMsgId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
type SendMsgAllReq struct {
|
||||
Seq string `protobuf:"bytes,1,opt,name=seq,proto3" json:"seq,omitempty"`
|
||||
AppId uint32 `protobuf:"varint,2,opt,name=appId,proto3" json:"appId,omitempty"`
|
||||
UserId string `protobuf:"bytes,3,opt,name=userId,proto3" json:"userId,omitempty"`
|
||||
Cms string `protobuf:"bytes,4,opt,name=cms,proto3" json:"cms,omitempty"`
|
||||
Type string `protobuf:"bytes,5,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Msg string `protobuf:"bytes,6,opt,name=msg,proto3" json:"msg,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SendMsgAllReq) Reset() { *m = SendMsgAllReq{} }
|
||||
func (m *SendMsgAllReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendMsgAllReq) ProtoMessage() {}
|
||||
func (*SendMsgAllReq) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{4}
|
||||
}
|
||||
|
||||
func (m *SendMsgAllReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendMsgAllReq.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SendMsgAllReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SendMsgAllReq.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SendMsgAllReq) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SendMsgAllReq.Merge(m, src)
|
||||
}
|
||||
func (m *SendMsgAllReq) XXX_Size() int {
|
||||
return xxx_messageInfo_SendMsgAllReq.Size(m)
|
||||
}
|
||||
func (m *SendMsgAllReq) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SendMsgAllReq.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SendMsgAllReq proto.InternalMessageInfo
|
||||
|
||||
func (m *SendMsgAllReq) GetSeq() string {
|
||||
if m != nil {
|
||||
return m.Seq
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgAllReq) GetAppId() uint32 {
|
||||
if m != nil {
|
||||
return m.AppId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *SendMsgAllReq) GetUserId() string {
|
||||
if m != nil {
|
||||
return m.UserId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgAllReq) GetCms() string {
|
||||
if m != nil {
|
||||
return m.Cms
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgAllReq) GetType() string {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgAllReq) GetMsg() string {
|
||||
if m != nil {
|
||||
return m.Msg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type SendMsgAllRsp struct {
|
||||
RetCode uint32 `protobuf:"varint,1,opt,name=retCode,proto3" json:"retCode,omitempty"`
|
||||
ErrMsg string `protobuf:"bytes,2,opt,name=errMsg,proto3" json:"errMsg,omitempty"`
|
||||
SendMsgId string `protobuf:"bytes,3,opt,name=sendMsgId,proto3" json:"sendMsgId,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SendMsgAllRsp) Reset() { *m = SendMsgAllRsp{} }
|
||||
func (m *SendMsgAllRsp) String() string { return proto.CompactTextString(m) }
|
||||
func (*SendMsgAllRsp) ProtoMessage() {}
|
||||
func (*SendMsgAllRsp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{5}
|
||||
}
|
||||
|
||||
func (m *SendMsgAllRsp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SendMsgAllRsp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *SendMsgAllRsp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_SendMsgAllRsp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *SendMsgAllRsp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_SendMsgAllRsp.Merge(m, src)
|
||||
}
|
||||
func (m *SendMsgAllRsp) XXX_Size() int {
|
||||
return xxx_messageInfo_SendMsgAllRsp.Size(m)
|
||||
}
|
||||
func (m *SendMsgAllRsp) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_SendMsgAllRsp.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_SendMsgAllRsp proto.InternalMessageInfo
|
||||
|
||||
func (m *SendMsgAllRsp) GetRetCode() uint32 {
|
||||
if m != nil {
|
||||
return m.RetCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *SendMsgAllRsp) GetErrMsg() string {
|
||||
if m != nil {
|
||||
return m.ErrMsg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *SendMsgAllRsp) GetSendMsgId() string {
|
||||
if m != nil {
|
||||
return m.SendMsgId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 获取用户列表
|
||||
type GetUserListReq struct {
|
||||
AppId uint32 `protobuf:"varint,1,opt,name=appId,proto3" json:"appId,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GetUserListReq) Reset() { *m = GetUserListReq{} }
|
||||
func (m *GetUserListReq) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetUserListReq) ProtoMessage() {}
|
||||
func (*GetUserListReq) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{6}
|
||||
}
|
||||
|
||||
func (m *GetUserListReq) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetUserListReq.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GetUserListReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GetUserListReq.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GetUserListReq) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GetUserListReq.Merge(m, src)
|
||||
}
|
||||
func (m *GetUserListReq) XXX_Size() int {
|
||||
return xxx_messageInfo_GetUserListReq.Size(m)
|
||||
}
|
||||
func (m *GetUserListReq) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GetUserListReq.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GetUserListReq proto.InternalMessageInfo
|
||||
|
||||
func (m *GetUserListReq) GetAppId() uint32 {
|
||||
if m != nil {
|
||||
return m.AppId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetUserListRsp struct {
|
||||
RetCode uint32 `protobuf:"varint,1,opt,name=retCode,proto3" json:"retCode,omitempty"`
|
||||
ErrMsg string `protobuf:"bytes,2,opt,name=errMsg,proto3" json:"errMsg,omitempty"`
|
||||
UserId []string `protobuf:"bytes,3,rep,name=userId,proto3" json:"userId,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GetUserListRsp) Reset() { *m = GetUserListRsp{} }
|
||||
func (m *GetUserListRsp) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetUserListRsp) ProtoMessage() {}
|
||||
func (*GetUserListRsp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_62691ff0994625a6, []int{7}
|
||||
}
|
||||
|
||||
func (m *GetUserListRsp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GetUserListRsp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GetUserListRsp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GetUserListRsp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GetUserListRsp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GetUserListRsp.Merge(m, src)
|
||||
}
|
||||
func (m *GetUserListRsp) XXX_Size() int {
|
||||
return xxx_messageInfo_GetUserListRsp.Size(m)
|
||||
}
|
||||
func (m *GetUserListRsp) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GetUserListRsp.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GetUserListRsp proto.InternalMessageInfo
|
||||
|
||||
func (m *GetUserListRsp) GetRetCode() uint32 {
|
||||
if m != nil {
|
||||
return m.RetCode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *GetUserListRsp) GetErrMsg() string {
|
||||
if m != nil {
|
||||
return m.ErrMsg
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GetUserListRsp) GetUserId() []string {
|
||||
if m != nil {
|
||||
return m.UserId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*QueryUsersOnlineReq)(nil), "protobuf.QueryUsersOnlineReq")
|
||||
proto.RegisterType((*QueryUsersOnlineRsp)(nil), "protobuf.QueryUsersOnlineRsp")
|
||||
proto.RegisterType((*SendMsgReq)(nil), "protobuf.SendMsgReq")
|
||||
proto.RegisterType((*SendMsgRsp)(nil), "protobuf.SendMsgRsp")
|
||||
proto.RegisterType((*SendMsgAllReq)(nil), "protobuf.SendMsgAllReq")
|
||||
proto.RegisterType((*SendMsgAllRsp)(nil), "protobuf.SendMsgAllRsp")
|
||||
proto.RegisterType((*GetUserListReq)(nil), "protobuf.GetUserListReq")
|
||||
proto.RegisterType((*GetUserListRsp)(nil), "protobuf.GetUserListRsp")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("im_protobuf.proto", fileDescriptor_62691ff0994625a6) }
|
||||
|
||||
var fileDescriptor_62691ff0994625a6 = []byte{
|
||||
// 413 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x53, 0x4d, 0xab, 0xd3, 0x40,
|
||||
0x14, 0x35, 0xcd, 0x7b, 0xed, 0xcb, 0x95, 0xca, 0x73, 0x7c, 0xe8, 0x18, 0x14, 0xca, 0x2c, 0xa4,
|
||||
0x0b, 0xc9, 0x42, 0x17, 0x6e, 0x6d, 0xbb, 0x90, 0x42, 0x8b, 0x35, 0xc5, 0x8d, 0x08, 0xa5, 0x4d,
|
||||
0xae, 0x21, 0x90, 0x34, 0xd3, 0xb9, 0xa9, 0xd8, 0x5f, 0xe0, 0xbf, 0xd0, 0xbf, 0x2a, 0x33, 0xf9,
|
||||
0x6a, 0x35, 0x75, 0x51, 0x10, 0x57, 0xb9, 0xe7, 0xde, 0x73, 0x0f, 0x67, 0x2e, 0x27, 0xf0, 0x30,
|
||||
0x4e, 0x57, 0x52, 0x65, 0x79, 0xb6, 0xd9, 0x7f, 0xf1, 0x4c, 0xc1, 0x6e, 0x2a, 0x2c, 0x26, 0xf0,
|
||||
0xe8, 0xc3, 0x1e, 0xd5, 0xe1, 0x23, 0xa1, 0xa2, 0xf7, 0xdb, 0x24, 0xde, 0xa2, 0x8f, 0x3b, 0x76,
|
||||
0x07, 0xd7, 0x6b, 0x29, 0xa7, 0x21, 0xb7, 0x06, 0xd6, 0xb0, 0xef, 0x17, 0x80, 0x3d, 0x86, 0xee,
|
||||
0x9e, 0x50, 0x4d, 0x43, 0xde, 0x19, 0x58, 0x43, 0xc7, 0x2f, 0x91, 0x58, 0xb5, 0x88, 0x90, 0x64,
|
||||
0x1c, 0x7a, 0x0a, 0xf3, 0x49, 0x16, 0x62, 0x29, 0x53, 0x41, 0x2d, 0x84, 0x4a, 0xcd, 0x29, 0xaa,
|
||||
0x84, 0x0a, 0xa4, 0xfb, 0x99, 0x59, 0xe7, 0xf6, 0xc0, 0x1a, 0xde, 0xf8, 0x25, 0x12, 0x3f, 0x2c,
|
||||
0x80, 0x25, 0x6e, 0xc3, 0x39, 0x45, 0xda, 0xdd, 0x2d, 0xd8, 0x84, 0x3b, 0x23, 0xea, 0xf8, 0xba,
|
||||
0x6c, 0xfc, 0x76, 0xda, 0xfd, 0xda, 0xc7, 0x7e, 0xf5, 0x7e, 0x90, 0x12, 0xbf, 0x2a, 0xf6, 0x83,
|
||||
0x94, 0x18, 0x83, 0xab, 0xfc, 0x20, 0x91, 0x5f, 0x9b, 0x96, 0xa9, 0x35, 0x2b, 0xa5, 0x88, 0x77,
|
||||
0x0b, 0x56, 0x4a, 0x91, 0x7e, 0x50, 0x4c, 0xb3, 0x2c, 0x58, 0x27, 0xbc, 0x67, 0xfc, 0x55, 0x50,
|
||||
0x7c, 0x6e, 0xfc, 0x5d, 0xf4, 0xf0, 0x67, 0xe0, 0x50, 0xb1, 0x5f, 0x9b, 0x6d, 0x1a, 0xe2, 0xbb,
|
||||
0x05, 0xfd, 0x52, 0x7e, 0x94, 0x24, 0xff, 0xf1, 0x02, 0x62, 0x75, 0x62, 0xe4, 0x1f, 0x3c, 0xf5,
|
||||
0x05, 0x3c, 0x78, 0x87, 0xb9, 0x0e, 0xd2, 0x2c, 0xa6, 0xfc, 0x6c, 0x14, 0xc5, 0xa7, 0x53, 0xde,
|
||||
0xa5, 0x69, 0xab, 0x8f, 0x63, 0x37, 0xc7, 0x79, 0xf5, 0xb3, 0x03, 0xce, 0x28, 0x08, 0x96, 0xa8,
|
||||
0xbe, 0xa2, 0x62, 0x3e, 0xdc, 0xfe, 0x1e, 0x6e, 0xf6, 0xdc, 0xab, 0x7f, 0xa8, 0x96, 0xbf, 0xc7,
|
||||
0xfd, 0xdb, 0x98, 0xa4, 0xb8, 0xc7, 0xde, 0x40, 0xaf, 0x3c, 0x23, 0xbb, 0x6b, 0xb8, 0x4d, 0xc2,
|
||||
0xdd, 0x96, 0xae, 0x59, 0x7c, 0x5b, 0xe7, 0x6c, 0x94, 0x24, 0xec, 0xc9, 0x1f, 0xac, 0x22, 0x1e,
|
||||
0x6e, 0xfb, 0xc0, 0x28, 0x4c, 0xe0, 0xfe, 0xd1, 0xe1, 0x18, 0x6f, 0x98, 0xa7, 0x77, 0x77, 0xcf,
|
||||
0x4c, 0xb4, 0xc8, 0xf8, 0x25, 0x3c, 0x8d, 0x33, 0x2f, 0x52, 0x32, 0xf0, 0xf0, 0xdb, 0x3a, 0x95,
|
||||
0x09, 0x52, 0xcd, 0x1e, 0xf7, 0x17, 0x65, 0x65, 0xbe, 0x0b, 0x6b, 0xd3, 0x35, 0xa3, 0xd7, 0xbf,
|
||||
0x02, 0x00, 0x00, 0xff, 0xff, 0x53, 0x3e, 0x6a, 0x5a, 0x89, 0x04, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// AccServerClient is the client API for AccServer service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type AccServerClient interface {
|
||||
// 查询用户是否在线
|
||||
QueryUsersOnline(ctx context.Context, in *QueryUsersOnlineReq, opts ...grpc.CallOption) (*QueryUsersOnlineRsp, error)
|
||||
// 发送消息
|
||||
SendMsg(ctx context.Context, in *SendMsgReq, opts ...grpc.CallOption) (*SendMsgRsp, error)
|
||||
// 发送消息
|
||||
SendMsgAll(ctx context.Context, in *SendMsgAllReq, opts ...grpc.CallOption) (*SendMsgAllRsp, error)
|
||||
// 获取用户列表
|
||||
GetUserList(ctx context.Context, in *GetUserListReq, opts ...grpc.CallOption) (*GetUserListRsp, error)
|
||||
}
|
||||
|
||||
type accServerClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewAccServerClient(cc *grpc.ClientConn) AccServerClient {
|
||||
return &accServerClient{cc}
|
||||
}
|
||||
|
||||
func (c *accServerClient) QueryUsersOnline(ctx context.Context, in *QueryUsersOnlineReq, opts ...grpc.CallOption) (*QueryUsersOnlineRsp, error) {
|
||||
out := new(QueryUsersOnlineRsp)
|
||||
err := c.cc.Invoke(ctx, "/protobuf.AccServer/QueryUsersOnline", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *accServerClient) SendMsg(ctx context.Context, in *SendMsgReq, opts ...grpc.CallOption) (*SendMsgRsp, error) {
|
||||
out := new(SendMsgRsp)
|
||||
err := c.cc.Invoke(ctx, "/protobuf.AccServer/SendMsg", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *accServerClient) SendMsgAll(ctx context.Context, in *SendMsgAllReq, opts ...grpc.CallOption) (*SendMsgAllRsp, error) {
|
||||
out := new(SendMsgAllRsp)
|
||||
err := c.cc.Invoke(ctx, "/protobuf.AccServer/SendMsgAll", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *accServerClient) GetUserList(ctx context.Context, in *GetUserListReq, opts ...grpc.CallOption) (*GetUserListRsp, error) {
|
||||
out := new(GetUserListRsp)
|
||||
err := c.cc.Invoke(ctx, "/protobuf.AccServer/GetUserList", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// AccServerServer is the server API for AccServer service.
|
||||
type AccServerServer interface {
|
||||
// 查询用户是否在线
|
||||
QueryUsersOnline(context.Context, *QueryUsersOnlineReq) (*QueryUsersOnlineRsp, error)
|
||||
// 发送消息
|
||||
SendMsg(context.Context, *SendMsgReq) (*SendMsgRsp, error)
|
||||
// 发送消息
|
||||
SendMsgAll(context.Context, *SendMsgAllReq) (*SendMsgAllRsp, error)
|
||||
// 获取用户列表
|
||||
GetUserList(context.Context, *GetUserListReq) (*GetUserListRsp, error)
|
||||
}
|
||||
|
||||
// UnimplementedAccServerServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedAccServerServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedAccServerServer) QueryUsersOnline(ctx context.Context, req *QueryUsersOnlineReq) (*QueryUsersOnlineRsp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method QueryUsersOnline not implemented")
|
||||
}
|
||||
func (*UnimplementedAccServerServer) SendMsg(ctx context.Context, req *SendMsgReq) (*SendMsgRsp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SendMsg not implemented")
|
||||
}
|
||||
func (*UnimplementedAccServerServer) SendMsgAll(ctx context.Context, req *SendMsgAllReq) (*SendMsgAllRsp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SendMsgAll not implemented")
|
||||
}
|
||||
func (*UnimplementedAccServerServer) GetUserList(ctx context.Context, req *GetUserListReq) (*GetUserListRsp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetUserList not implemented")
|
||||
}
|
||||
|
||||
func RegisterAccServerServer(s *grpc.Server, srv AccServerServer) {
|
||||
s.RegisterService(&_AccServer_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _AccServer_QueryUsersOnline_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryUsersOnlineReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AccServerServer).QueryUsersOnline(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/protobuf.AccServer/QueryUsersOnline",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AccServerServer).QueryUsersOnline(ctx, req.(*QueryUsersOnlineReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _AccServer_SendMsg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SendMsgReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AccServerServer).SendMsg(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/protobuf.AccServer/SendMsg",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AccServerServer).SendMsg(ctx, req.(*SendMsgReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _AccServer_SendMsgAll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(SendMsgAllReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AccServerServer).SendMsgAll(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/protobuf.AccServer/SendMsgAll",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AccServerServer).SendMsgAll(ctx, req.(*SendMsgAllReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _AccServer_GetUserList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetUserListReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AccServerServer).GetUserList(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/protobuf.AccServer/GetUserList",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AccServerServer).GetUserList(ctx, req.(*GetUserListReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _AccServer_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "protobuf.AccServer",
|
||||
HandlerType: (*AccServerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "QueryUsersOnline",
|
||||
Handler: _AccServer_QueryUsersOnline_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SendMsg",
|
||||
Handler: _AccServer_SendMsg_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SendMsgAll",
|
||||
Handler: _AccServer_SendMsgAll_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetUserList",
|
||||
Handler: _AccServer_GetUserList_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "im_protobuf.proto",
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 16:02
|
||||
*/
|
||||
|
||||
package routers
|
||||
|
||||
import (
|
||||
"gowebsocket/servers/websocket"
|
||||
)
|
||||
|
||||
// Websocket 路由
|
||||
func WebsocketInit() {
|
||||
websocket.Register("login", websocket.LoginController)
|
||||
websocket.Register("heartbeat", websocket.HeartbeatController)
|
||||
websocket.Register("ping", websocket.PingController)
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 12:20
|
||||
*/
|
||||
|
||||
package routers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"gowebsocket/controllers/home"
|
||||
"gowebsocket/controllers/systems"
|
||||
"gowebsocket/controllers/user"
|
||||
)
|
||||
|
||||
func Init(router *gin.Engine) {
|
||||
router.LoadHTMLGlob("views/**/*")
|
||||
|
||||
// 用户组
|
||||
userRouter := router.Group("/user")
|
||||
{
|
||||
userRouter.GET("/list", user.List)
|
||||
userRouter.GET("/online", user.Online)
|
||||
userRouter.POST("/sendMessage", user.SendMessage)
|
||||
userRouter.POST("/sendMessageAll", user.SendMessageAll)
|
||||
}
|
||||
|
||||
// 系统
|
||||
systemRouter := router.Group("/system")
|
||||
{
|
||||
systemRouter.GET("/state", systems.Status)
|
||||
}
|
||||
|
||||
// home
|
||||
homeRouter := router.Group("/home")
|
||||
{
|
||||
homeRouter.GET("/index", home.Index)
|
||||
}
|
||||
|
||||
// router.POST("/user/online", user.Online)
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-03
|
||||
* Time: 16:43
|
||||
*/
|
||||
|
||||
package grpcclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"google.golang.org/grpc"
|
||||
"gowebsocket/common"
|
||||
"gowebsocket/models"
|
||||
"gowebsocket/protobuf"
|
||||
"time"
|
||||
)
|
||||
|
||||
// rpc client
|
||||
// 给全体用户发送消息
|
||||
// link::https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_client/main.go
|
||||
func SendMsgAll(server *models.Server, seq string, appId uint32, userId string, cmd string, message string) (sendMsgId string, err error) {
|
||||
// Set up a connection to the server.
|
||||
conn, err := grpc.Dial(server.String(), grpc.WithInsecure())
|
||||
if err != nil {
|
||||
fmt.Println("连接失败", server.String())
|
||||
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
c := protobuf.NewAccServerClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
req := protobuf.SendMsgAllReq{
|
||||
Seq: seq,
|
||||
AppId: appId,
|
||||
UserId: userId,
|
||||
Cms: cmd,
|
||||
Msg: message,
|
||||
}
|
||||
rsp, err := c.SendMsgAll(ctx, &req)
|
||||
if err != nil {
|
||||
fmt.Println("给全体用户发送消息", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if rsp.GetRetCode() != common.OK {
|
||||
fmt.Println("给全体用户发送消息", rsp.String())
|
||||
err = errors.New(fmt.Sprintf("发送消息失败 code:%d", rsp.GetRetCode()))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
sendMsgId = rsp.GetSendMsgId()
|
||||
fmt.Println("给全体用户发送消息 成功:", sendMsgId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户列表
|
||||
// link::https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_client/main.go
|
||||
func GetUserList(server *models.Server, appId uint32) (userIds []string, err error) {
|
||||
userIds = make([]string, 0)
|
||||
|
||||
conn, err := grpc.Dial(server.String(), grpc.WithInsecure())
|
||||
if err != nil {
|
||||
fmt.Println("连接失败", server.String())
|
||||
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
c := protobuf.NewAccServerClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
req := protobuf.GetUserListReq{
|
||||
AppId: appId,
|
||||
}
|
||||
rsp, err := c.GetUserList(ctx, &req)
|
||||
if err != nil {
|
||||
fmt.Println("获取用户列表 发送请求错误:", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if rsp.GetRetCode() != common.OK {
|
||||
fmt.Println("获取用户列表 返回码错误:", rsp.String())
|
||||
err = errors.New(fmt.Sprintf("发送消息失败 code:%d", rsp.GetRetCode()))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userIds = rsp.GetUserId()
|
||||
fmt.Println("获取用户列表 成功:", userIds)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// rpc client
|
||||
// 发送消息
|
||||
// link::https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_client/main.go
|
||||
func SendMsg(server *models.Server, seq string, appId uint32, userId string, cmd string, msgType string, message string) (sendMsgId string, err error) {
|
||||
// Set up a connection to the server.
|
||||
conn, err := grpc.Dial(server.String(), grpc.WithInsecure())
|
||||
if err != nil {
|
||||
fmt.Println("连接失败", server.String())
|
||||
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
c := protobuf.NewAccServerClient(conn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
|
||||
req := protobuf.SendMsgReq{
|
||||
Seq: seq,
|
||||
AppId: appId,
|
||||
UserId: userId,
|
||||
Cms: cmd,
|
||||
Type: msgType,
|
||||
Msg: message,
|
||||
IsLocal: false,
|
||||
}
|
||||
rsp, err := c.SendMsg(ctx, &req)
|
||||
if err != nil {
|
||||
fmt.Println("发送消息", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if rsp.GetRetCode() != common.OK {
|
||||
fmt.Println("发送消息", rsp.String())
|
||||
err = errors.New(fmt.Sprintf("发送消息失败 code:%d", rsp.GetRetCode()))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
sendMsgId = rsp.GetSendMsgId()
|
||||
fmt.Println("发送消息 成功:", sendMsgId)
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-03
|
||||
* Time: 16:43
|
||||
*/
|
||||
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
"gowebsocket/common"
|
||||
"gowebsocket/models"
|
||||
"gowebsocket/protobuf"
|
||||
"gowebsocket/servers/websocket"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
}
|
||||
|
||||
func setErr(rsp proto.Message, code uint32, message string) {
|
||||
|
||||
message = common.GetErrorMessage(code, message)
|
||||
switch v := rsp.(type) {
|
||||
case *protobuf.QueryUsersOnlineRsp:
|
||||
v.RetCode = code
|
||||
v.ErrMsg = message
|
||||
case *protobuf.SendMsgRsp:
|
||||
v.RetCode = code
|
||||
v.ErrMsg = message
|
||||
case *protobuf.SendMsgAllRsp:
|
||||
v.RetCode = code
|
||||
v.ErrMsg = message
|
||||
case *protobuf.GetUserListRsp:
|
||||
v.RetCode = code
|
||||
v.ErrMsg = message
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 查询用户是否在线
|
||||
func (s *server) QueryUsersOnline(c context.Context, req *protobuf.QueryUsersOnlineReq) (rsp *protobuf.QueryUsersOnlineRsp, err error) {
|
||||
|
||||
fmt.Println("grpc_request 查询用户是否在线", req.String())
|
||||
|
||||
rsp = &protobuf.QueryUsersOnlineRsp{}
|
||||
|
||||
online := websocket.CheckUserOnline(req.GetAppId(), req.GetUserId())
|
||||
|
||||
setErr(req, common.OK, "")
|
||||
rsp.Online = online
|
||||
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
// 给本机用户发消息
|
||||
func (s *server) SendMsg(c context.Context, req *protobuf.SendMsgReq) (rsp *protobuf.SendMsgRsp, err error) {
|
||||
|
||||
fmt.Println("grpc_request 给本机用户发消息", req.String())
|
||||
|
||||
rsp = &protobuf.SendMsgRsp{}
|
||||
|
||||
if req.GetIsLocal() {
|
||||
|
||||
// 不支持
|
||||
setErr(rsp, common.ParameterIllegal, "")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
data := models.GetMsgData(req.GetUserId(), req.GetSeq(), req.GetCms(), req.GetMsg())
|
||||
sendResults, err := websocket.SendUserMessageLocal(req.GetAppId(), req.GetUserId(), data)
|
||||
if err != nil {
|
||||
fmt.Println("系统错误", err)
|
||||
setErr(rsp, common.ServerError, "")
|
||||
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
if !sendResults {
|
||||
fmt.Println("发送失败", err)
|
||||
setErr(rsp, common.OperationFailure, "")
|
||||
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
setErr(rsp, common.OK, "")
|
||||
|
||||
fmt.Println("grpc_response 给本机用户发消息", rsp.String())
|
||||
return
|
||||
}
|
||||
|
||||
// 给本机全体用户发消息
|
||||
func (s *server) SendMsgAll(c context.Context, req *protobuf.SendMsgAllReq) (rsp *protobuf.SendMsgAllRsp, err error) {
|
||||
|
||||
fmt.Println("grpc_request 给本机全体用户发消息", req.String())
|
||||
|
||||
rsp = &protobuf.SendMsgAllRsp{}
|
||||
|
||||
data := models.GetMsgData(req.GetUserId(), req.GetSeq(), req.GetCms(), req.GetMsg())
|
||||
websocket.AllSendMessages(req.GetAppId(), req.GetUserId(), data)
|
||||
|
||||
setErr(rsp, common.OK, "")
|
||||
|
||||
fmt.Println("grpc_response 给本机全体用户发消息:", rsp.String())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取本机用户列表
|
||||
func (s *server) GetUserList(c context.Context, req *protobuf.GetUserListReq) (rsp *protobuf.GetUserListRsp, err error) {
|
||||
|
||||
fmt.Println("grpc_request 获取本机用户列表", req.String())
|
||||
|
||||
appId := req.GetAppId()
|
||||
rsp = &protobuf.GetUserListRsp{}
|
||||
|
||||
// 本机
|
||||
userList := websocket.GetUserList(appId)
|
||||
|
||||
setErr(rsp, common.OK, "")
|
||||
rsp.UserId = userList
|
||||
|
||||
fmt.Println("grpc_response 获取本机用户列表:", rsp.String())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// rpc server
|
||||
// link::https://github.com/grpc/grpc-go/blob/master/examples/helloworld/greeter_server/main.go
|
||||
func Init() {
|
||||
|
||||
rpcPort := viper.GetString("app.rpcPort")
|
||||
fmt.Println("rpc server 启动", rpcPort)
|
||||
|
||||
lis, err := net.Listen("tcp", ":"+rpcPort)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
s := grpc.NewServer()
|
||||
protobuf.RegisterAccServerServer(s, &server{})
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Fatalf("failed to serve: %v", err)
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-31
|
||||
* Time: 15:17
|
||||
*/
|
||||
|
||||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gowebsocket/servers/websocket"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Init() {
|
||||
Timer(3*time.Second, 30*time.Second, cleanConnection, "", nil, nil)
|
||||
|
||||
}
|
||||
|
||||
// 清理超时连接
|
||||
func cleanConnection(param interface{}) (result bool) {
|
||||
result = true
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("ClearTimeoutConnections stop", r, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
fmt.Println("定时任务,清理超时连接", param)
|
||||
|
||||
websocket.ClearTimeoutConnections()
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-08-03
|
||||
* Time: 15:44
|
||||
*/
|
||||
|
||||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gowebsocket/lib/cache"
|
||||
"gowebsocket/servers/websocket"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ServerInit() {
|
||||
Timer(2*time.Second, 60*time.Second, server, "", serverDefer, "")
|
||||
}
|
||||
|
||||
// 服务注册
|
||||
func server(param interface{}) (result bool) {
|
||||
result = true
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("服务注册 stop", r, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
server := websocket.GetServer()
|
||||
currentTime := uint64(time.Now().Unix())
|
||||
fmt.Println("定时任务,服务注册", param, server, currentTime)
|
||||
|
||||
cache.SetServerInfo(server, currentTime)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 服务下线
|
||||
func serverDefer(param interface{}) (result bool) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("服务下线 stop", r, string(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
|
||||
fmt.Println("服务下线", param)
|
||||
|
||||
server := websocket.GetServer()
|
||||
cache.DelServerInfo(server)
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-29
|
||||
* Time: 14:15
|
||||
*/
|
||||
|
||||
package task
|
||||
|
||||
import "time"
|
||||
|
||||
type TimerFunc func(interface{}) bool
|
||||
|
||||
/**
|
||||
* 定时调用
|
||||
* @delay 首次延时
|
||||
* @tick 间隔
|
||||
* @fun 定时执行function
|
||||
* @param fun参数
|
||||
*/
|
||||
func Timer(delay, tick time.Duration, fun TimerFunc, param interface{}, funcDefer TimerFunc, paramDefer interface{}) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if funcDefer != nil {
|
||||
funcDefer(paramDefer)
|
||||
}
|
||||
}()
|
||||
|
||||
if fun == nil {
|
||||
return
|
||||
}
|
||||
|
||||
t := time.NewTimer(delay)
|
||||
defer t.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
if fun(param) == false {
|
||||
return
|
||||
}
|
||||
t.Reset(tick)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-27
|
||||
* Time: 14:38
|
||||
*/
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gowebsocket/common"
|
||||
"gowebsocket/models"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type DisposeFunc func(client *Client, seq string, message []byte) (code uint32, msg string, data interface{})
|
||||
|
||||
var (
|
||||
handlers = make(map[string]DisposeFunc)
|
||||
handlersRWMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// 注册
|
||||
func Register(key string, value DisposeFunc) {
|
||||
handlersRWMutex.Lock()
|
||||
defer handlersRWMutex.Unlock()
|
||||
handlers[key] = value
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getHandlers(key string) (value DisposeFunc, ok bool) {
|
||||
handlersRWMutex.RLock()
|
||||
defer handlersRWMutex.RUnlock()
|
||||
|
||||
value, ok = handlers[key]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 处理数据
|
||||
func ProcessData(client *Client, message []byte) {
|
||||
|
||||
fmt.Println("处理数据", client.Addr, string(message))
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("处理数据 stop", r)
|
||||
}
|
||||
}()
|
||||
|
||||
request := &models.Request{}
|
||||
|
||||
err := json.Unmarshal(message, request)
|
||||
if err != nil {
|
||||
fmt.Println("处理数据 json Unmarshal", err)
|
||||
client.SendMsg([]byte("数据不合法"))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
requestData, err := json.Marshal(request.Data)
|
||||
if err != nil {
|
||||
fmt.Println("处理数据 json Marshal", err)
|
||||
client.SendMsg([]byte("处理数据失败"))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
seq := request.Seq
|
||||
cmd := request.Cmd
|
||||
|
||||
var (
|
||||
code uint32
|
||||
msg string
|
||||
data interface{}
|
||||
)
|
||||
|
||||
// request
|
||||
fmt.Println("acc_request", cmd, client.Addr)
|
||||
|
||||
// 采用 map 注册的方式
|
||||
if value, ok := getHandlers(cmd); ok {
|
||||
code, msg, data = value(client, seq, requestData)
|
||||
} else {
|
||||
code = common.RoutingNotExist
|
||||
fmt.Println("处理数据 路由不存在", client.Addr, "cmd", cmd)
|
||||
}
|
||||
|
||||
msg = common.GetErrorMessage(code, msg)
|
||||
|
||||
responseHead := models.NewResponseHead(seq, cmd, code, msg, data)
|
||||
|
||||
headByte, err := json.Marshal(responseHead)
|
||||
if err != nil {
|
||||
fmt.Println("处理数据 json Marshal", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
client.SendMsg(headByte)
|
||||
|
||||
fmt.Println("acc_response send", client.Addr, client.AppId, client.UserId, "cmd", cmd, "code", code)
|
||||
|
||||
return
|
||||
}
|
@ -0,0 +1,384 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 16:24
|
||||
*/
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gowebsocket/helper"
|
||||
"gowebsocket/lib/cache"
|
||||
"gowebsocket/models"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 连接管理
|
||||
type ClientManager struct {
|
||||
Clients map[*Client]bool // 全部的连接
|
||||
ClientsLock sync.RWMutex // 读写锁
|
||||
Users map[string]*Client // 登录的用户 // appId+uuid
|
||||
UserLock sync.RWMutex // 读写锁
|
||||
Register chan *Client // 连接连接处理
|
||||
Login chan *login // 用户登录处理
|
||||
Unregister chan *Client // 断开连接处理程序
|
||||
Broadcast chan []byte // 广播 向全部成员发送数据
|
||||
}
|
||||
|
||||
func NewClientManager() (clientManager *ClientManager) {
|
||||
clientManager = &ClientManager{
|
||||
Clients: make(map[*Client]bool),
|
||||
Users: make(map[string]*Client),
|
||||
Register: make(chan *Client, 1000),
|
||||
Login: make(chan *login, 1000),
|
||||
Unregister: make(chan *Client, 1000),
|
||||
Broadcast: make(chan []byte, 1000),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户key
|
||||
func GetUserKey(appId uint32, userId string) (key string) {
|
||||
key = fmt.Sprintf("%d_%s", appId, userId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
/************************** manager ***************************************/
|
||||
|
||||
func (manager *ClientManager) InClient(client *Client) (ok bool) {
|
||||
manager.ClientsLock.RLock()
|
||||
defer manager.ClientsLock.RUnlock()
|
||||
|
||||
// 连接存在,在添加
|
||||
_, ok = manager.Clients[client]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetClients
|
||||
func (manager *ClientManager) GetClients() (clients map[*Client]bool) {
|
||||
|
||||
clients = make(map[*Client]bool)
|
||||
|
||||
manager.ClientsRange(func(client *Client, value bool) (result bool) {
|
||||
clients[client] = value
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 遍历
|
||||
func (manager *ClientManager) ClientsRange(f func(client *Client, value bool) (result bool)) {
|
||||
|
||||
manager.ClientsLock.RLock()
|
||||
defer manager.ClientsLock.RUnlock()
|
||||
|
||||
for key, value := range manager.Clients {
|
||||
result := f(key, value)
|
||||
if result == false {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetClientsLen
|
||||
func (manager *ClientManager) GetClientsLen() (clientsLen int) {
|
||||
|
||||
clientsLen = len(manager.Clients)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 添加客户端
|
||||
func (manager *ClientManager) AddClients(client *Client) {
|
||||
manager.ClientsLock.Lock()
|
||||
defer manager.ClientsLock.Unlock()
|
||||
|
||||
manager.Clients[client] = true
|
||||
}
|
||||
|
||||
// 删除客户端
|
||||
func (manager *ClientManager) DelClients(client *Client) {
|
||||
manager.ClientsLock.Lock()
|
||||
defer manager.ClientsLock.Unlock()
|
||||
|
||||
if _, ok := manager.Clients[client]; ok {
|
||||
delete(manager.Clients, client)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户的连接
|
||||
func (manager *ClientManager) GetUserClient(appId uint32, userId string) (client *Client) {
|
||||
|
||||
manager.UserLock.RLock()
|
||||
defer manager.UserLock.RUnlock()
|
||||
|
||||
userKey := GetUserKey(appId, userId)
|
||||
if value, ok := manager.Users[userKey]; ok {
|
||||
client = value
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetClientsLen
|
||||
func (manager *ClientManager) GetUsersLen() (userLen int) {
|
||||
userLen = len(manager.Users)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 添加用户
|
||||
func (manager *ClientManager) AddUsers(key string, client *Client) {
|
||||
manager.UserLock.Lock()
|
||||
defer manager.UserLock.Unlock()
|
||||
|
||||
manager.Users[key] = client
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
func (manager *ClientManager) DelUsers(client *Client) (result bool) {
|
||||
manager.UserLock.Lock()
|
||||
defer manager.UserLock.Unlock()
|
||||
|
||||
key := GetUserKey(client.AppId, client.UserId)
|
||||
if value, ok := manager.Users[key]; ok {
|
||||
// 判断是否为相同的用户
|
||||
if value.Addr != client.Addr {
|
||||
|
||||
return
|
||||
}
|
||||
delete(manager.Users, key)
|
||||
result = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户的key
|
||||
func (manager *ClientManager) GetUserKeys() (userKeys []string) {
|
||||
|
||||
userKeys = make([]string, 0)
|
||||
manager.UserLock.RLock()
|
||||
defer manager.UserLock.RUnlock()
|
||||
for key := range manager.Users {
|
||||
userKeys = append(userKeys, key)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户的key
|
||||
func (manager *ClientManager) GetUserList(appId uint32) (userList []string) {
|
||||
|
||||
userList = make([]string, 0)
|
||||
|
||||
manager.UserLock.RLock()
|
||||
defer manager.UserLock.RUnlock()
|
||||
|
||||
for _, v := range manager.Users {
|
||||
if v.AppId == appId {
|
||||
userList = append(userList, v.UserId)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("GetUserList len:", len(manager.Users))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户的key
|
||||
func (manager *ClientManager) GetUserClients() (clients []*Client) {
|
||||
|
||||
clients = make([]*Client, 0)
|
||||
manager.UserLock.RLock()
|
||||
defer manager.UserLock.RUnlock()
|
||||
for _, v := range manager.Users {
|
||||
clients = append(clients, v)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 向全部成员(除了自己)发送数据
|
||||
func (manager *ClientManager) sendAll(message []byte, ignoreClient *Client) {
|
||||
|
||||
clients := manager.GetUserClients()
|
||||
for _, conn := range clients {
|
||||
if conn != ignoreClient {
|
||||
conn.SendMsg(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 向全部成员(除了自己)发送数据
|
||||
func (manager *ClientManager) sendAppIdAll(message []byte, appId uint32, ignoreClient *Client) {
|
||||
|
||||
clients := manager.GetUserClients()
|
||||
for _, conn := range clients {
|
||||
if conn != ignoreClient && conn.AppId == appId {
|
||||
conn.SendMsg(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 用户建立连接事件
|
||||
func (manager *ClientManager) EventRegister(client *Client) {
|
||||
manager.AddClients(client)
|
||||
|
||||
fmt.Println("EventRegister 用户建立连接", client.Addr)
|
||||
|
||||
// client.Send <- []byte("连接成功")
|
||||
}
|
||||
|
||||
// 用户登录
|
||||
func (manager *ClientManager) EventLogin(login *login) {
|
||||
|
||||
client := login.Client
|
||||
// 连接存在,在添加
|
||||
if manager.InClient(client) {
|
||||
userKey := login.GetKey()
|
||||
manager.AddUsers(userKey, login.Client)
|
||||
}
|
||||
|
||||
fmt.Println("EventLogin 用户登录", client.Addr, login.AppId, login.UserId)
|
||||
|
||||
orderId := helper.GetOrderIdTime()
|
||||
SendUserMessageAll(login.AppId, login.UserId, orderId, models.MessageCmdEnter, "哈喽~")
|
||||
}
|
||||
|
||||
// 用户断开连接
|
||||
func (manager *ClientManager) EventUnregister(client *Client) {
|
||||
manager.DelClients(client)
|
||||
|
||||
// 删除用户连接
|
||||
deleteResult := manager.DelUsers(client)
|
||||
if deleteResult == false {
|
||||
// 不是当前连接的客户端
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 清除redis登录数据
|
||||
userOnline, err := cache.GetUserOnlineInfo(client.GetKey())
|
||||
if err == nil {
|
||||
userOnline.LogOut()
|
||||
cache.SetUserOnlineInfo(client.GetKey(), userOnline)
|
||||
}
|
||||
|
||||
// 关闭 chan
|
||||
// close(client.Send)
|
||||
|
||||
fmt.Println("EventUnregister 用户断开连接", client.Addr, client.AppId, client.UserId)
|
||||
|
||||
if client.UserId != "" {
|
||||
orderId := helper.GetOrderIdTime()
|
||||
SendUserMessageAll(client.AppId, client.UserId, orderId, models.MessageCmdExit, "用户已经离开~")
|
||||
}
|
||||
}
|
||||
|
||||
// 管道处理程序
|
||||
func (manager *ClientManager) start() {
|
||||
for {
|
||||
select {
|
||||
case conn := <-manager.Register:
|
||||
// 建立连接事件
|
||||
manager.EventRegister(conn)
|
||||
|
||||
case login := <-manager.Login:
|
||||
// 用户登录
|
||||
manager.EventLogin(login)
|
||||
|
||||
case conn := <-manager.Unregister:
|
||||
// 断开连接事件
|
||||
manager.EventUnregister(conn)
|
||||
|
||||
case message := <-manager.Broadcast:
|
||||
// 广播事件
|
||||
clients := manager.GetClients()
|
||||
for conn := range clients {
|
||||
select {
|
||||
case conn.Send <- message:
|
||||
default:
|
||||
close(conn.Send)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************** manager info ***************************************/
|
||||
// 获取管理者信息
|
||||
func GetManagerInfo(isDebug string) (managerInfo map[string]interface{}) {
|
||||
managerInfo = make(map[string]interface{})
|
||||
|
||||
managerInfo["clientsLen"] = clientManager.GetClientsLen() // 客户端连接数
|
||||
managerInfo["usersLen"] = clientManager.GetUsersLen() // 登录用户数
|
||||
managerInfo["chanRegisterLen"] = len(clientManager.Register) // 未处理连接事件数
|
||||
managerInfo["chanLoginLen"] = len(clientManager.Login) // 未处理登录事件数
|
||||
managerInfo["chanUnregisterLen"] = len(clientManager.Unregister) // 未处理退出登录事件数
|
||||
managerInfo["chanBroadcastLen"] = len(clientManager.Broadcast) // 未处理广播事件数
|
||||
|
||||
if isDebug == "true" {
|
||||
addrList := make([]string, 0)
|
||||
clientManager.ClientsRange(func(client *Client, value bool) (result bool) {
|
||||
addrList = append(addrList, client.Addr)
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
users := clientManager.GetUserKeys()
|
||||
|
||||
managerInfo["clients"] = addrList // 客户端列表
|
||||
managerInfo["users"] = users // 登录用户列表
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户所在的连接
|
||||
func GetUserClient(appId uint32, userId string) (client *Client) {
|
||||
client = clientManager.GetUserClient(appId, userId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 定时清理超时连接
|
||||
func ClearTimeoutConnections() {
|
||||
currentTime := uint64(time.Now().Unix())
|
||||
|
||||
clients := clientManager.GetClients()
|
||||
for client := range clients {
|
||||
if client.IsHeartbeatTimeout(currentTime) {
|
||||
fmt.Println("心跳时间超时 关闭连接", client.Addr, client.UserId, client.LoginTime, client.HeartbeatTime)
|
||||
|
||||
client.Socket.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取全部用户
|
||||
func GetUserList(appId uint32) (userList []string) {
|
||||
fmt.Println("获取全部用户", appId)
|
||||
|
||||
userList = clientManager.GetUserList(appId)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 全员广播
|
||||
func AllSendMessages(appId uint32, userId string, data string) {
|
||||
fmt.Println("全员广播", appId, userId, data)
|
||||
|
||||
ignoreClient := clientManager.GetUserClient(appId, userId)
|
||||
clientManager.sendAppIdAll([]byte(data), appId, ignoreClient)
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-25
|
||||
* Time: 16:04
|
||||
*/
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gowebsocket/helper"
|
||||
"gowebsocket/models"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultAppId = 101 // 默认平台Id
|
||||
)
|
||||
|
||||
var (
|
||||
clientManager = NewClientManager() // 管理者
|
||||
appIds = []uint32{defaultAppId, 102, 103, 104} // 全部的平台
|
||||
|
||||
serverIp string
|
||||
serverPort string
|
||||
)
|
||||
|
||||
func GetAppIds() []uint32 {
|
||||
|
||||
return appIds
|
||||
}
|
||||
|
||||
func GetServer() (server *models.Server) {
|
||||
server = models.NewServer(serverIp, serverPort)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func IsLocal(server *models.Server) (isLocal bool) {
|
||||
if server.Ip == serverIp && server.Port == serverPort {
|
||||
isLocal = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func InAppIds(appId uint32) (inAppId bool) {
|
||||
|
||||
for _, value := range appIds {
|
||||
if value == appId {
|
||||
inAppId = true
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetDefaultAppId() (appId uint32) {
|
||||
appId = defaultAppId
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 启动程序
|
||||
func StartWebSocket() {
|
||||
|
||||
serverIp = helper.GetServerIp()
|
||||
|
||||
webSocketPort := viper.GetString("app.webSocketPort")
|
||||
rpcPort := viper.GetString("app.rpcPort")
|
||||
|
||||
serverPort = rpcPort
|
||||
|
||||
http.HandleFunc("/acc", wsPage)
|
||||
|
||||
// 添加处理程序
|
||||
go clientManager.start()
|
||||
fmt.Println("WebSocket 启动程序成功", serverIp, serverPort)
|
||||
|
||||
http.ListenAndServe(":"+webSocketPort, nil)
|
||||
}
|
||||
|
||||
func wsPage(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
// 升级协议
|
||||
conn, err := (&websocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
|
||||
fmt.Println("升级协议", "ua:", r.Header["User-Agent"], "referer:", r.Header["Referer"])
|
||||
|
||||
return true
|
||||
}}).Upgrade(w, req, nil)
|
||||
if err != nil {
|
||||
http.NotFound(w, req)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("webSocket 建立连接:", conn.RemoteAddr().String())
|
||||
|
||||
currentTime := uint64(time.Now().Unix())
|
||||
client := NewClient(conn.RemoteAddr().String(), conn, currentTime)
|
||||
|
||||
go client.read()
|
||||
go client.write()
|
||||
|
||||
// 用户连接事件
|
||||
clientManager.Register <- client
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* Created by GoLand.
|
||||
* User: link1st
|
||||
* Date: 2019-07-30
|
||||
* Time: 12:27
|
||||
*/
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-redis/redis"
|
||||
"gowebsocket/lib/cache"
|
||||
"gowebsocket/models"
|
||||
"gowebsocket/servers/grpcclient"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 查询所有用户
|
||||
func UserList(appId uint32) (userList []string) {
|
||||
|
||||
userList = make([]string, 0)
|
||||
currentTime := uint64(time.Now().Unix())
|
||||
servers, err := cache.GetServerAll(currentTime)
|
||||
if err != nil {
|
||||
fmt.Println("给全体用户发消息", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, server := range servers {
|
||||
var (
|
||||
list []string
|
||||
)
|
||||
if IsLocal(server) {
|
||||
list = GetUserList(appId)
|
||||
} else {
|
||||
list, _ = grpcclient.GetUserList(server, appId)
|
||||
}
|
||||
userList = append(userList, list...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 查询用户是否在线
|
||||
func CheckUserOnline(appId uint32, userId string) (online bool) {
|
||||
// 全平台查询
|
||||
if appId == 0 {
|
||||
for _, appId := range GetAppIds() {
|
||||
online, _ = checkUserOnline(appId, userId)
|
||||
if online == true {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
online, _ = checkUserOnline(appId, userId)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 查询用户 是否在线
|
||||
func checkUserOnline(appId uint32, userId string) (online bool, err error) {
|
||||
key := GetUserKey(appId, userId)
|
||||
userOnline, err := cache.GetUserOnlineInfo(key)
|
||||
if err != nil {
|
||||
if err == redis.Nil {
|
||||
fmt.Println("GetUserOnlineInfo", appId, userId, err)
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
fmt.Println("GetUserOnlineInfo", appId, userId, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
online = userOnline.IsOnline()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 给用户发送消息
|
||||
func SendUserMessage(appId uint32, userId string, msgId, message string) (sendResults bool, err error) {
|
||||
|
||||
data := models.GetTextMsgData(userId, msgId, message)
|
||||
|
||||
client := GetUserClient(appId, userId)
|
||||
|
||||
if client != nil {
|
||||
// 在本机发送
|
||||
sendResults, err = SendUserMessageLocal(appId, userId, data)
|
||||
if err != nil {
|
||||
fmt.Println("给用户发送消息", appId, userId, err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
key := GetUserKey(appId, userId)
|
||||
info, err := cache.GetUserOnlineInfo(key)
|
||||
if err != nil {
|
||||
fmt.Println("给用户发送消息失败", key, err)
|
||||
|
||||
return false, nil
|
||||
}
|
||||
if !info.IsOnline() {
|
||||
fmt.Println("用户不在线", key)
|
||||
return false, nil
|
||||
}
|
||||
server := models.NewServer(info.AccIp, info.AccPort)
|
||||
msg, err := grpcclient.SendMsg(server, msgId, appId, userId, models.MessageCmdMsg, models.MessageCmdMsg, message)
|
||||
if err != nil {
|
||||
fmt.Println("给用户发送消息失败", key, err)
|
||||
|
||||
return false, err
|
||||
}
|
||||
fmt.Println("给用户发送消息成功-rpc", msg)
|
||||
sendResults = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 给本机用户发送消息
|
||||
func SendUserMessageLocal(appId uint32, userId string, data string) (sendResults bool, err error) {
|
||||
|
||||
client := GetUserClient(appId, userId)
|
||||
if client == nil {
|
||||
err = errors.New("用户不在线")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
client.SendMsg([]byte(data))
|
||||
sendResults = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 给全体用户发消息
|
||||
func SendUserMessageAll(appId uint32, userId string, msgId, cmd, message string) (sendResults bool, err error) {
|
||||
sendResults = true
|
||||
|
||||
currentTime := uint64(time.Now().Unix())
|
||||
servers, err := cache.GetServerAll(currentTime)
|
||||
if err != nil {
|
||||
fmt.Println("给全体用户发消息", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, server := range servers {
|
||||
if IsLocal(server) {
|
||||
data := models.GetMsgData(userId, msgId, cmd, message)
|
||||
AllSendMessages(appId, userId, data)
|
||||
} else {
|
||||
grpcclient.SendMsgAll(server, msgId, appId, userId, cmd, message)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,60 @@
|
||||
## 目录
|
||||
- 1、项目说明
|
||||
- 1.1 goWebSocket
|
||||
- 1.2 项目体验
|
||||
- 2、介绍webSocket
|
||||
- 2.1 webSocket 是什么
|
||||
- 2.2 webSocket的兼容性
|
||||
- 2.3 为什么要用webSocket
|
||||
- 2.4 webSocket建立过程
|
||||
- 3、如何实现基于webSocket的长连接系统
|
||||
- 3.1 使用go实现webSocket服务端
|
||||
- 3.1.1 启动端口监听
|
||||
- 3.1.2 升级协议
|
||||
- 3.1.3 客户端连接的管理
|
||||
- 3.1.4 注册客户端的socket的写的异步处理程序
|
||||
- 3.1.5 注册客户端的socket的读的异步处理程序
|
||||
- 3.1.6 接收客户端数据并处理
|
||||
- 3.1.7 使用路由的方式处理客户端的请求数据
|
||||
- 3.1.8 防止内存溢出和Goroutine不回收
|
||||
- 3.2 使用javaScript实现webSocket客户端
|
||||
- 3.2.1 启动并注册监听程序
|
||||
- 3.2.2 发送数据
|
||||
- 3.3 发送消息
|
||||
- 3.3.1 文本消息
|
||||
- 3.3.2 图片和语言消息
|
||||
- 4、goWebSocket 项目
|
||||
- 4.1 项目说明
|
||||
- 4.2 项目依赖
|
||||
- 4.3 项目启动
|
||||
- 4.4 接口文档
|
||||
- 4.4.1 HTTP接口文档
|
||||
- 4.4.1.1 接口说明
|
||||
- 4.4.1.2 聊天页面
|
||||
- 4.4.1.3 获取房间用户列表
|
||||
- 4.4.1.4 查询用户是否在线
|
||||
- 4.4.1.5 给用户发送消息
|
||||
- 4.4.1.6 给全员用户发送消息
|
||||
- 4.4.2 RPC接口文档
|
||||
- 4.4.2.1 接口说明
|
||||
- 4.4.2.2 查询用户是否在线
|
||||
- 4.4.2.3 发送消息
|
||||
- 4.4.2.4 给指定房间所有用户发送消息
|
||||
- 4.4.2.5 获取房间内全部用户
|
||||
- 5、webSocket项目Nginx配置
|
||||
- 5.1 为什么要配置Nginx
|
||||
- 5.2 nginx配置
|
||||
- 5.3 问题处理
|
||||
- 6、压测
|
||||
- 6.1 Linux内核优化
|
||||
- 6.2 压测准备
|
||||
- 6.3 压测数据
|
||||
- 7、如何基于webSocket实现一个分布式Im
|
||||
- 7.1 说明
|
||||
- 7.2 架构
|
||||
- 7.3 分布式系统部署
|
||||
- 8、回顾和反思
|
||||
- 8.1 在其它系统应用
|
||||
- 8.2 需要完善、优化
|
||||
- 8.3 总结
|
||||
- 9、参考文献
|
Loading…
Reference in new issue