conn.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package main
  5. import (
  6. "github.com/gorilla/websocket"
  7. "log"
  8. "net/http"
  9. "time"
  10. )
  11. const (
  12. // Time allowed to write a message to the peer.
  13. writeWait = 10 * time.Second
  14. // Time allowed to read the next pong message from the peer.
  15. pongWait = 60 * time.Second
  16. // Send pings to peer with this period. Must be less than pongWait.
  17. pingPeriod = (pongWait * 9) / 10
  18. // Maximum message size allowed from peer.
  19. maxMessageSize = 512
  20. )
  21. var upgrader = websocket.Upgrader{
  22. ReadBufferSize: 1024,
  23. WriteBufferSize: 1024,
  24. }
  25. // connection is an middleman between the websocket connection and the hub.
  26. type connection struct {
  27. // The websocket connection.
  28. ws *websocket.Conn
  29. // Buffered channel of outbound messages.
  30. send chan []byte
  31. }
  32. // readPump pumps messages from the websocket connection to the hub.
  33. func (c *connection) readPump() {
  34. defer func() {
  35. h.unregister <- c
  36. c.ws.Close()
  37. }()
  38. c.ws.SetReadLimit(maxMessageSize)
  39. c.ws.SetReadDeadline(time.Now().Add(pongWait))
  40. c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
  41. for {
  42. _, message, err := c.ws.ReadMessage()
  43. if err != nil {
  44. break
  45. }
  46. h.broadcast <- message
  47. }
  48. }
  49. // write writes a message with the given message type and payload.
  50. func (c *connection) write(mt int, payload []byte) error {
  51. c.ws.SetWriteDeadline(time.Now().Add(writeWait))
  52. return c.ws.WriteMessage(mt, payload)
  53. }
  54. // writePump pumps messages from the hub to the websocket connection.
  55. func (c *connection) writePump() {
  56. ticker := time.NewTicker(pingPeriod)
  57. defer func() {
  58. ticker.Stop()
  59. c.ws.Close()
  60. }()
  61. for {
  62. select {
  63. case message, ok := <-c.send:
  64. if !ok {
  65. c.write(websocket.CloseMessage, []byte{})
  66. return
  67. }
  68. if err := c.write(websocket.TextMessage, message); err != nil {
  69. return
  70. }
  71. case <-ticker.C:
  72. if err := c.write(websocket.PingMessage, []byte{}); err != nil {
  73. return
  74. }
  75. }
  76. }
  77. }
  78. // serverWs handles webocket requests from the peer.
  79. func serveWs(w http.ResponseWriter, r *http.Request) {
  80. if r.Method != "GET" {
  81. http.Error(w, "Method not allowed", 405)
  82. return
  83. }
  84. ws, err := upgrader.Upgrade(w, r, nil)
  85. if err != nil {
  86. if _, ok := err.(websocket.HandshakeError); !ok {
  87. log.Println(err)
  88. }
  89. return
  90. }
  91. c := &connection{send: make(chan []byte, 256), ws: ws}
  92. h.register <- c
  93. go c.writePump()
  94. c.readPump()
  95. }