From a900d1521e890ba65f2b936fd55115b1ecf5e447 Mon Sep 17 00:00:00 2001 From: Kane York Date: Fri, 27 Oct 2017 13:13:39 -0700 Subject: [PATCH] Optimize pings to reduce timer percolation --- socketserver/server/handlecore.go | 25 +++++++++++++------------ socketserver/server/types.go | 4 ---- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/socketserver/server/handlecore.go b/socketserver/server/handlecore.go index fe62c927..bba45d62 100644 --- a/socketserver/server/handlecore.go +++ b/socketserver/server/handlecore.go @@ -375,11 +375,7 @@ func RunSocketConnection(conn *websocket.Conn) { // report.RemoteAddr = client.RemoteAddr conn.SetPongHandler(func(pongBody string) error { - client.Mutex.Lock() - if client.HelloOK { // do not accept PONGs until hello sent - client.pingCount = 0 - } - client.Mutex.Unlock() + _clientChan <- ClientMessage{Command: "__ping"} return nil }) @@ -467,6 +463,10 @@ func runSocketReader(conn *websocket.Conn, client *ClientInfo, errorChan chan<- } func runSocketWriter(conn *websocket.Conn, client *ClientInfo, errorChan <-chan error, clientChan <-chan ClientMessage, serverMessageChan <-chan ClientMessage) websocket.CloseError { + pingTicker := time.NewTicker(1*time.Minute) + defer pingTicker.Stop() + lastPacket := time.Now() + for { select { case err := <-errorChan: @@ -488,6 +488,10 @@ func runSocketWriter(conn *websocket.Conn, client *ClientInfo, errorChan <-chan if !client.HelloOK && msg.Command != HelloCommand { return CloseFirstMessageNotHello } + lastPacket = time.Now() + if msg.Command == "__ping" { + continue // generated by server, not by client + } for _, char := range msg.Command { if char == utf8.RuneError { @@ -506,14 +510,11 @@ func runSocketWriter(conn *websocket.Conn, client *ClientInfo, errorChan <-chan } SendMessage(conn, msg) - case <-time.After(1 * time.Minute): - client.Mutex.Lock() - client.pingCount++ - tooManyPings := client.pingCount == 5 - client.Mutex.Unlock() - if tooManyPings { + case <-pingTicker.C: + now := time.Now() + if lastPacket.Add(5*time.Minute).Before(now) { return CloseTimedOut - } else { + } else if lastPacket.Add(1*time.Minute).Before(now) { conn.WriteControl(websocket.PingMessage, []byte(strconv.FormatInt(time.Now().Unix(), 10)), getDeadline()) } diff --git a/socketserver/server/types.go b/socketserver/server/types.go index 3face4c4..e5b464d9 100644 --- a/socketserver/server/types.go +++ b/socketserver/server/types.go @@ -141,10 +141,6 @@ type ClientInfo struct { // Take out an Add() on this during a command if you need to use the MessageChannel later. MsgChannelKeepalive sync.WaitGroup - - // The number of pings sent without a response. - // Protected by Mutex - pingCount int } func VersionFromString(v string) ClientVersion {