|
@@ -8,6 +8,7 @@ import (
|
|
|
"log"
|
|
"log"
|
|
|
"math/rand"
|
|
"math/rand"
|
|
|
"net"
|
|
"net"
|
|
|
|
|
+
|
|
|
// "regexp"
|
|
// "regexp"
|
|
|
"strconv"
|
|
"strconv"
|
|
|
"strings"
|
|
"strings"
|
|
@@ -34,13 +35,14 @@ func subStr(str string, length int) string {
|
|
|
|
|
|
|
|
type Hub struct {
|
|
type Hub struct {
|
|
|
sync.Mutex
|
|
sync.Mutex
|
|
|
- cf *config.Config
|
|
|
|
|
- globalID uint16
|
|
|
|
|
- channel string // 本地频道信息
|
|
|
|
|
- middle []MiddleFunc // 中间件
|
|
|
|
|
- connects sync.Map // map[*Line]bool(true) //记录当前的连接,方便查找
|
|
|
|
|
- subscribes sync.Map // [cmd]->[]*SubscribeData //注册绑定频道的函数,用于响应请求
|
|
|
|
|
- msgCache sync.Map // map[uint16]*GetMsg //请求的回应记录,key为id
|
|
|
|
|
|
|
+ cf *config.Config
|
|
|
|
|
+ globalID uint16
|
|
|
|
|
+ channel string // 本地频道信息
|
|
|
|
|
+ middle []MiddleFunc // 中间件
|
|
|
|
|
+ // connects sync.Map // map[*Line]bool(true) //记录当前的连接,方便查找
|
|
|
|
|
+ lines *Mapx // 记录当前的连接,统一管理
|
|
|
|
|
+ subscribes sync.Map // [cmd]->[]*SubscribeData //注册绑定频道的函数,用于响应请求
|
|
|
|
|
+ msgCache sync.Map // map[uint16]*GetMsg //请求的回应记录,key为id
|
|
|
|
|
|
|
|
// 客户端需要用的函数
|
|
// 客户端需要用的函数
|
|
|
connectHostFunc ConnectHostFunc // 获取对应频道的一个连接地址
|
|
connectHostFunc ConnectHostFunc // 获取对应频道的一个连接地址
|
|
@@ -74,9 +76,6 @@ func (h *Hub) convertData(data any) (reqData []byte, err error) {
|
|
|
}
|
|
}
|
|
|
default:
|
|
default:
|
|
|
if data != nil {
|
|
if data != nil {
|
|
|
- // if s, ok := data.(func() ([]uint8, error)); ok {
|
|
|
|
|
- // return s()
|
|
|
|
|
- // }
|
|
|
|
|
// 自动转换数据为json格式
|
|
// 自动转换数据为json格式
|
|
|
reqData, err = json.Marshal(data)
|
|
reqData, err = json.Marshal(data)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -90,18 +89,11 @@ func (h *Hub) convertData(data any) (reqData []byte, err error) {
|
|
|
|
|
|
|
|
// 清理异常连接
|
|
// 清理异常连接
|
|
|
func (h *Hub) cleanDeadConnect() {
|
|
func (h *Hub) cleanDeadConnect() {
|
|
|
- h.Lock()
|
|
|
|
|
- defer h.Unlock()
|
|
|
|
|
now := time.Now().UnixMilli()
|
|
now := time.Now().UnixMilli()
|
|
|
- if now-h.lastCleanDeadConnect > int64(h.cf.CleanDeadConnectWait) {
|
|
|
|
|
|
|
+ expired := now - int64(h.cf.CleanDeadConnectWait)
|
|
|
|
|
+ if h.lastCleanDeadConnect < expired {
|
|
|
h.lastCleanDeadConnect = now
|
|
h.lastCleanDeadConnect = now
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
- if line.state != Connected && now-line.updated.UnixMilli() > int64(h.cf.CleanDeadConnectWait) {
|
|
|
|
|
- h.connects.Delete(key)
|
|
|
|
|
- }
|
|
|
|
|
- return true
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ h.lines.DeleteInvalidLines(expired)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -157,18 +149,15 @@ func (h *Hub) Subscribe(filter FilterFunc, cmd string, backFunc SubscribeBackFun
|
|
|
|
|
|
|
|
// 遍历频道列表
|
|
// 遍历频道列表
|
|
|
// 如果 fn 返回 false,则 range 停止迭代
|
|
// 如果 fn 返回 false,则 range 停止迭代
|
|
|
-func (h *Hub) ConnectRange(fn func(line *Line) bool) {
|
|
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
- return fn(line)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+func (h *Hub) ConnectRange(fn func(id int, line *Line) bool) {
|
|
|
|
|
+ h.lines.Range(fn)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 获取当前在线的数量
|
|
// 获取当前在线的数量
|
|
|
func (h *Hub) ConnectNum() int {
|
|
func (h *Hub) ConnectNum() int {
|
|
|
var count int
|
|
var count int
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- if key.(*Line).state == Connected {
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
|
|
+ if line.state == Connected {
|
|
|
count++
|
|
count++
|
|
|
}
|
|
}
|
|
|
return true
|
|
return true
|
|
@@ -179,8 +168,7 @@ func (h *Hub) ConnectNum() int {
|
|
|
// 获取所有的在线连接频道
|
|
// 获取所有的在线连接频道
|
|
|
func (h *Hub) AllChannel() []string {
|
|
func (h *Hub) AllChannel() []string {
|
|
|
cs := make([]string, 0)
|
|
cs := make([]string, 0)
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
if line.state == Connected {
|
|
if line.state == Connected {
|
|
|
cs = append(cs, line.channel)
|
|
cs = append(cs, line.channel)
|
|
|
}
|
|
}
|
|
@@ -193,11 +181,9 @@ func (h *Hub) AllChannel() []string {
|
|
|
// 为了避免定义数据结构麻烦,采用|隔开, 频道名|连接开始时间
|
|
// 为了避免定义数据结构麻烦,采用|隔开, 频道名|连接开始时间
|
|
|
func (h *Hub) AllChannelWithStarted() []string {
|
|
func (h *Hub) AllChannelWithStarted() []string {
|
|
|
cs := make([]string, 0)
|
|
cs := make([]string, 0)
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
if line.state == Connected {
|
|
if line.state == Connected {
|
|
|
- // ti := time.Since(line.started).Milliseconds()
|
|
|
|
|
- cs = append(cs, line.channel+"|"+strconv.FormatInt(line.started.UnixMilli(), 10))
|
|
|
|
|
|
|
+ cs = append(cs, fmt.Sprintf("%s|%d", line.channel, line.started.UnixMilli()))
|
|
|
}
|
|
}
|
|
|
return true
|
|
return true
|
|
|
})
|
|
})
|
|
@@ -206,8 +192,7 @@ func (h *Hub) AllChannelWithStarted() []string {
|
|
|
|
|
|
|
|
// 获取频道并通过函数过滤,如果返回 false 将终止
|
|
// 获取频道并通过函数过滤,如果返回 false 将终止
|
|
|
func (h *Hub) ChannelToFunc(fn func(string) bool) {
|
|
func (h *Hub) ChannelToFunc(fn func(string) bool) {
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
if line.state == Connected {
|
|
if line.state == Connected {
|
|
|
return fn(line.channel)
|
|
return fn(line.channel)
|
|
|
}
|
|
}
|
|
@@ -217,8 +202,7 @@ func (h *Hub) ChannelToFunc(fn func(string) bool) {
|
|
|
|
|
|
|
|
// 从 channel 获取连接
|
|
// 从 channel 获取连接
|
|
|
func (h *Hub) ChannelToLine(channel string) (line *Line) {
|
|
func (h *Hub) ChannelToLine(channel string) (line *Line) {
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- l := key.(*Line)
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, l *Line) bool {
|
|
|
if l.channel == channel {
|
|
if l.channel == channel {
|
|
|
line = l
|
|
line = l
|
|
|
return false
|
|
return false
|
|
@@ -257,19 +241,18 @@ func (h *Hub) sendRequest(gd *GetData) (count int) {
|
|
|
log.Println(err)
|
|
log.Println(err)
|
|
|
return 0
|
|
return 0
|
|
|
}
|
|
}
|
|
|
- // 增加如果没有发送到消息,延时100ms重连直到超时
|
|
|
|
|
- for i := 0; i < gd.Timeout; i += 100 {
|
|
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- conn := key.(*Line)
|
|
|
|
|
|
|
+ // 如果没有发送到消息,延时100ms重连直到超时
|
|
|
|
|
+ for i := 0; i <= gd.Timeout; i += 100 {
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
// 检查连接是否OK
|
|
// 检查连接是否OK
|
|
|
- if conn.state != Connected {
|
|
|
|
|
|
|
+ if line.state != Connected {
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
// 验证连接是否达到发送数据的要求
|
|
// 验证连接是否达到发送数据的要求
|
|
|
- if h.checkConnectOkFunc != nil && !h.checkConnectOkFunc(conn, gd) {
|
|
|
|
|
|
|
+ if h.checkConnectOkFunc != nil && !h.checkConnectOkFunc(line, gd) {
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
- if gd.Filter(conn) {
|
|
|
|
|
|
|
+ if gd.Filter(line) {
|
|
|
var id uint16
|
|
var id uint16
|
|
|
if gd.backchan != nil {
|
|
if gd.backchan != nil {
|
|
|
id = h.GetID()
|
|
id = h.GetID()
|
|
@@ -294,7 +277,7 @@ func (h *Hub) sendRequest(gd *GetData) (count int) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }(id, conn)
|
|
|
|
|
|
|
+ }(id, line)
|
|
|
// 将要发送的请求缓存
|
|
// 将要发送的请求缓存
|
|
|
gm := &GetMsg{
|
|
gm := &GetMsg{
|
|
|
out: gd.backchan,
|
|
out: gd.backchan,
|
|
@@ -303,16 +286,16 @@ func (h *Hub) sendRequest(gd *GetData) (count int) {
|
|
|
h.msgCache.Store(id, gm)
|
|
h.msgCache.Store(id, gm)
|
|
|
}
|
|
}
|
|
|
// 组织数据并发送到Connect
|
|
// 组织数据并发送到Connect
|
|
|
- conn.sendRequest <- &RequestData{
|
|
|
|
|
|
|
+ line.sendRequest <- &RequestData{
|
|
|
Id: id,
|
|
Id: id,
|
|
|
Cmd: gd.Cmd,
|
|
Cmd: gd.Cmd,
|
|
|
Data: outData,
|
|
Data: outData,
|
|
|
timeout: gd.Timeout,
|
|
timeout: gd.Timeout,
|
|
|
backchan: gd.backchan,
|
|
backchan: gd.backchan,
|
|
|
- conn: conn,
|
|
|
|
|
|
|
+ conn: line,
|
|
|
}
|
|
}
|
|
|
if h.cf.PrintMsg {
|
|
if h.cf.PrintMsg {
|
|
|
- log.Println("[SEND]->", id, conn.channel, "["+gd.Cmd+"]", subStr(string(outData), 200))
|
|
|
|
|
|
|
+ log.Println("[SEND]->", id, line.channel, "["+gd.Cmd+"]", subStr(string(outData), 200))
|
|
|
}
|
|
}
|
|
|
count++
|
|
count++
|
|
|
if gd.Max > 0 && count >= gd.Max {
|
|
if gd.Max > 0 && count >= gd.Max {
|
|
@@ -360,7 +343,6 @@ func (h *Hub) requestFromNet(request *RequestData) {
|
|
|
// 倒序查找是为了新增的频道响应函数优先执行
|
|
// 倒序查找是为了新增的频道响应函数优先执行
|
|
|
for i := len(subs) - 1; i >= 0; i-- {
|
|
for i := len(subs) - 1; i >= 0; i-- {
|
|
|
rg := subs[i]
|
|
rg := subs[i]
|
|
|
- // if rg.Channel.MatchString(channel) {
|
|
|
|
|
if rg.Filter(request.conn) {
|
|
if rg.Filter(request.conn) {
|
|
|
state, data := rg.BackFunc(request)
|
|
state, data := rg.BackFunc(request)
|
|
|
// NEXT_SUBSCRIBE 表示当前的函数没有处理完成,还需要下个注册函数处理
|
|
// NEXT_SUBSCRIBE 表示当前的函数没有处理完成,还需要下个注册函数处理
|
|
@@ -534,44 +516,40 @@ func (h *Hub) PushWithMax(filter FilterFunc, cmd string, data any, max int) {
|
|
|
|
|
|
|
|
// 增加连接
|
|
// 增加连接
|
|
|
func (h *Hub) addLine(line *Line) {
|
|
func (h *Hub) addLine(line *Line) {
|
|
|
- if _, ok := h.connects.Load(line); ok {
|
|
|
|
|
|
|
+ if h.lines.Exist(line) {
|
|
|
log.Println("connect have exist")
|
|
log.Println("connect have exist")
|
|
|
// 连接已经存在,直接返回
|
|
// 连接已经存在,直接返回
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- // 检查是否有相同的channel,如果有的话将其关闭删除
|
|
|
|
|
- channel := line.channel
|
|
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- conn := key.(*Line)
|
|
|
|
|
- // 删除超时的连接
|
|
|
|
|
- if conn.state != Connected && conn.host == nil && time.Since(conn.lastRead) > time.Duration(h.cf.PingInterval*5*int(time.Millisecond)) {
|
|
|
|
|
- h.connects.Delete(key)
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
- if conn.channel == channel {
|
|
|
|
|
- conn.Close(true)
|
|
|
|
|
- h.connects.Delete(key)
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- return true
|
|
|
|
|
- })
|
|
|
|
|
- h.connects.Store(line, true)
|
|
|
|
|
|
|
+ h.lines.Store(line)
|
|
|
|
|
+ // // 检查是否有相同的channel,如果有的话将其关闭删除
|
|
|
|
|
+ // channel := line.channel
|
|
|
|
|
+ // h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
+ // conn := key.(*Line)
|
|
|
|
|
+ // // 删除超时的连接
|
|
|
|
|
+ // if conn.state != Connected && conn.host == nil && time.Since(conn.lastRead) > time.Duration(h.cf.PingInterval*5*int(time.Millisecond)) {
|
|
|
|
|
+ // h.connects.Delete(key)
|
|
|
|
|
+ // return true
|
|
|
|
|
+ // }
|
|
|
|
|
+ // if conn.channel == channel {
|
|
|
|
|
+ // conn.Close(true)
|
|
|
|
|
+ // h.connects.Delete(key)
|
|
|
|
|
+ // return false
|
|
|
|
|
+ // }
|
|
|
|
|
+ // return true
|
|
|
|
|
+ // })
|
|
|
|
|
+ // h.connects.Store(line, true)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 删除连接
|
|
// 删除连接
|
|
|
-func (h *Hub) removeLine(conn *Line) {
|
|
|
|
|
- conn.Close(true)
|
|
|
|
|
- h.connects.Delete(conn)
|
|
|
|
|
|
|
+func (h *Hub) removeLine(line *Line) {
|
|
|
|
|
+ line.Close(true)
|
|
|
|
|
+ h.lines.Delete(line)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 获取指定连接的连接持续时间
|
|
// 获取指定连接的连接持续时间
|
|
|
-func (h *Hub) ConnectDuration(conn *Line) time.Duration {
|
|
|
|
|
- t, ok := h.connects.Load(conn)
|
|
|
|
|
- if ok {
|
|
|
|
|
- return time.Since(t.(time.Time))
|
|
|
|
|
- }
|
|
|
|
|
- // 如果不存在直接返回0
|
|
|
|
|
- return time.Duration(0)
|
|
|
|
|
|
|
+func (h *Hub) ConnectDuration(line *Line) time.Duration {
|
|
|
|
|
+ return time.Since(line.started)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 绑定端口,建立服务
|
|
// 绑定端口,建立服务
|
|
@@ -602,8 +580,7 @@ func (h *Hub) BindForServer(info *HostInfo) (err error) {
|
|
|
}
|
|
}
|
|
|
// 将连接加入现有连接中
|
|
// 将连接加入现有连接中
|
|
|
done := false
|
|
done := false
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
if line.state == Disconnected && line.host == nil && line.ChannelEqualWithoutPrefix(channel) {
|
|
if line.state == Disconnected && line.host == nil && line.ChannelEqualWithoutPrefix(channel) {
|
|
|
line.Start(conn, nil)
|
|
line.Start(conn, nil)
|
|
|
done = true
|
|
done = true
|
|
@@ -747,8 +724,7 @@ func (h *Hub) ConnectToServer(channel string, force bool, host *HostInfo) (err e
|
|
|
|
|
|
|
|
// 将连接加入现有连接中
|
|
// 将连接加入现有连接中
|
|
|
done = false
|
|
done = false
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
if line.channel == channel {
|
|
if line.channel == channel {
|
|
|
if line.state == Connected {
|
|
if line.state == Connected {
|
|
|
if force {
|
|
if force {
|
|
@@ -804,8 +780,7 @@ func (h *Hub) checkProxyConnect() {
|
|
|
for {
|
|
for {
|
|
|
<-proxyTicker.C
|
|
<-proxyTicker.C
|
|
|
now := time.Now().UnixMilli()
|
|
now := time.Now().UnixMilli()
|
|
|
- h.connects.Range(func(key, _ any) bool {
|
|
|
|
|
- line := key.(*Line)
|
|
|
|
|
|
|
+ h.lines.Range(func(id int, line *Line) bool {
|
|
|
if line.host != nil && line.host.Proxy && now-line.updated.UnixMilli() > int64(h.cf.ProxyTimeout) {
|
|
if line.host != nil && line.host.Proxy && now-line.updated.UnixMilli() > int64(h.cf.ProxyTimeout) {
|
|
|
host, err := h.connectHostFunc(line.channel, Direct)
|
|
host, err := h.connectHostFunc(line.channel, Direct)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -842,6 +817,7 @@ func NewHub(
|
|
|
globalID: uint16(time.Now().UnixNano()) % config.ID_MAX,
|
|
globalID: uint16(time.Now().UnixNano()) % config.ID_MAX,
|
|
|
channel: channel,
|
|
channel: channel,
|
|
|
middle: make([]MiddleFunc, 0),
|
|
middle: make([]MiddleFunc, 0),
|
|
|
|
|
+ lines: NewMapx(),
|
|
|
connectHostFunc: connectHostFunc,
|
|
connectHostFunc: connectHostFunc,
|
|
|
authFunc: authFunc,
|
|
authFunc: authFunc,
|
|
|
checkAuthFunc: checkAuthFunc,
|
|
checkAuthFunc: checkAuthFunc,
|