websocket/examples/chat/conn.go

106 lines
2.5 KiB
Go
Raw Normal View History

// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
2013-10-16 20:41:47 +04:00
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"github.com/gorilla/websocket"
"log"
"net/http"
"time"
)
const (
// Time allowed to write a message to the peer.
writeWait = 10 * time.Second
// Time allowed to read the next pong message from the peer.
pongWait = 60 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
// Maximum message size allowed from peer.
maxMessageSize = 512
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
2013-10-16 20:41:47 +04:00
// connection is an middleman between the websocket connection and the hub.
type connection struct {
// The websocket connection.
ws *websocket.Conn
// Buffered channel of outbound messages.
send chan []byte
}
// readPump pumps messages from the websocket connection to the hub.
func (conn *connection) readPump() {
2013-10-16 20:41:47 +04:00
defer func() {
mainHub.unregister <- conn
conn.ws.Close()
2013-10-16 20:41:47 +04:00
}()
conn.ws.SetReadLimit(maxMessageSize)
conn.ws.SetReadDeadline(time.Now().Add(pongWait))
conn.ws.SetPongHandler(func(string) error { conn.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
2013-10-16 20:41:47 +04:00
for {
_, message, err := conn.ws.ReadMessage()
2013-10-16 20:41:47 +04:00
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err)
}
2013-10-16 20:41:47 +04:00
break
}
2016-05-18 17:56:16 +03:00
mainHub.broadcast <- message
2013-10-16 20:41:47 +04:00
}
}
// write writes a message with the given message type and payload.
func (conn *connection) write(mt int, payload []byte) error {
conn.ws.SetWriteDeadline(time.Now().Add(writeWait))
return conn.ws.WriteMessage(mt, payload)
2013-10-16 20:41:47 +04:00
}
// writePump pumps messages from the hub to the websocket connection.
func (conn *connection) writePump() {
2013-10-16 20:41:47 +04:00
ticker := time.NewTicker(pingPeriod)
defer func() {
ticker.Stop()
conn.ws.Close()
2013-10-16 20:41:47 +04:00
}()
for {
select {
case message, ok := <-conn.send:
2013-10-16 20:41:47 +04:00
if !ok {
conn.write(websocket.CloseMessage, []byte{})
2013-10-16 20:41:47 +04:00
return
}
if err := conn.write(websocket.TextMessage, message); err != nil {
2013-10-16 20:41:47 +04:00
return
}
case <-ticker.C:
if err := conn.write(websocket.PingMessage, []byte{}); err != nil {
2013-10-16 20:41:47 +04:00
return
}
}
}
}
2015-10-06 21:40:04 +03:00
// serveWs handles websocket requests from the peer.
2013-10-16 20:41:47 +04:00
func serveWs(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
2014-04-16 19:42:15 +04:00
if err != nil {
log.Println(err)
2013-10-16 20:41:47 +04:00
return
}
conn := &connection{send: make(chan []byte, 256), ws: ws}
mainHub.register <- conn
go conn.writePump()
conn.readPump()
2013-10-16 20:41:47 +04:00
}