mirror of
https://github.com/lwch/natpass
synced 2025-10-06 05:46:49 +08:00
110 lines
2.0 KiB
Go
110 lines
2.0 KiB
Go
package handler
|
|
|
|
import (
|
|
"errors"
|
|
"natpass/code/network"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/lwch/logging"
|
|
)
|
|
|
|
type client struct {
|
|
sync.RWMutex
|
|
parent *Handler
|
|
id string
|
|
trimID string
|
|
c *network.Conn
|
|
links map[string]struct{} // link id => struct{}
|
|
updated time.Time
|
|
}
|
|
|
|
func newClient(parent *Handler, id, trimID string, conn *network.Conn) *client {
|
|
return &client{
|
|
parent: parent,
|
|
id: id,
|
|
trimID: trimID,
|
|
c: conn,
|
|
links: make(map[string]struct{}),
|
|
updated: time.Now(),
|
|
}
|
|
}
|
|
|
|
func (c *client) run() {
|
|
for {
|
|
if time.Since(c.updated).Seconds() > 600 {
|
|
links := make([]string, 0, len(c.links))
|
|
c.RLock()
|
|
for id := range c.links {
|
|
links = append(links, id)
|
|
}
|
|
c.RUnlock()
|
|
logging.Info("%s is not keepalived, links: %v", c.id, links)
|
|
c.parent.closeAll(c)
|
|
return
|
|
}
|
|
msg, err := c.c.ReadMessage(c.parent.cfg.ReadTimeout)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "i/o timeout") {
|
|
continue
|
|
}
|
|
logging.Error("read message from %s: %v", c.id, err)
|
|
return
|
|
}
|
|
c.updated = time.Now()
|
|
c.parent.onMessage(c, c.c, msg)
|
|
}
|
|
}
|
|
|
|
func (c *client) writeMessage(msg *network.Msg) error {
|
|
for i := 0; i < 10; i++ {
|
|
err := c.c.WriteMessage(msg, c.parent.cfg.WriteTimeout)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "i/o timeout") {
|
|
continue
|
|
}
|
|
return err
|
|
}
|
|
}
|
|
return errors.New("too many retry")
|
|
}
|
|
|
|
func (c *client) addLink(id string) {
|
|
c.Lock()
|
|
c.links[id] = struct{}{}
|
|
c.Unlock()
|
|
}
|
|
|
|
func (c *client) removeLink(id string) {
|
|
c.Lock()
|
|
delete(c.links, id)
|
|
c.Unlock()
|
|
}
|
|
|
|
func (c *client) getLinks() []string {
|
|
ret := make([]string, 0, len(c.links))
|
|
c.RLock()
|
|
for link := range c.links {
|
|
ret = append(ret, link)
|
|
}
|
|
c.RUnlock()
|
|
return ret
|
|
}
|
|
|
|
func (c *client) close(id string) {
|
|
var msg network.Msg
|
|
msg.From = "server"
|
|
msg.To = c.id
|
|
msg.XType = network.Msg_disconnect
|
|
msg.Payload = &network.Msg_XDisconnect{
|
|
XDisconnect: &network.Disconnect{
|
|
Id: id,
|
|
},
|
|
}
|
|
c.c.WriteMessage(&msg, c.parent.cfg.WriteTimeout)
|
|
c.Lock()
|
|
delete(c.links, id)
|
|
c.Unlock()
|
|
}
|