diff --git a/socketserver/server/handlecore.go b/socketserver/server/handlecore.go index 3afab285..1ce86984 100644 --- a/socketserver/server/handlecore.go +++ b/socketserver/server/handlecore.go @@ -440,24 +440,7 @@ func runSocketReader(conn *websocket.Conn, client *ClientInfo, errorChan chan<- defer close(errorChan) defer close(clientChan) - for { - conn.SetReadDeadline(time.Now().Add(1 * time.Minute)) - messageType, packet, err = conn.ReadMessage() - // handle ReadDeadline by sending a ping - // writer loop handles repeated ping timeouts - if tmErr, ok := err.(interface { - Timeout() bool - }); ok && tmErr.Timeout() { - select { - case <-stoppedChan: - return - case clientChan <- ClientMessage{Command: "__readTimeout"}: - } - continue // re-set deadline and wait for pong packet - } - if err != nil { - break - } + for ; err == nil; messageType, packet, err = conn.ReadMessage() { if messageType == websocket.BinaryMessage { err = &CloseGotBinaryMessage break @@ -480,22 +463,23 @@ func runSocketReader(conn *websocket.Conn, client *ClientInfo, errorChan chan<- } else if msg.MessageID == 0 { continue } - select { + case clientChan <- msg: case <-stoppedChan: return - case clientChan <- msg: } } select { - case <-stoppedChan: case errorChan <- err: + case <-stoppedChan: } // exit goroutine } 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 { @@ -516,29 +500,12 @@ func runSocketWriter(conn *websocket.Conn, client *ClientInfo, errorChan <-chan } case msg := <-clientChan: - if msg.Command == "__readTimeout" { - // generated on 60 seconds without a message - now := time.Now() - if lastPacket.Add(5 * time.Minute).Before(now) { - return CloseTimedOut - } - conn.WriteControl( - websocket.PingMessage, - []byte(strconv.FormatInt(time.Now().Unix(), 10)), - getDeadline(), - ) - continue - } - if !client.HelloOK && msg.Command != HelloCommand { return CloseFirstMessageNotHello } lastPacket = time.Now() - if msg.Command == "__ping" { - // generated for PONG packets - // want this to run AFTER lastPacket was set - continue + continue // generated by server, not by client } for _, char := range msg.Command { @@ -558,6 +525,14 @@ func runSocketWriter(conn *websocket.Conn, client *ClientInfo, errorChan <-chan } SendMessage(conn, msg) + case <-pingTicker.C: + now := time.Now() + if lastPacket.Add(5 * time.Minute).Before(now) { + return CloseTimedOut + } else if lastPacket.Add(1 * time.Minute).Before(now) { + conn.WriteControl(websocket.PingMessage, []byte(strconv.FormatInt(time.Now().Unix(), 10)), getDeadline()) + } + case <-StopAcceptingConnectionsCh: return CloseGoingAway }