Semaphore/api/sockets/handler.go

132 lines
3.0 KiB
Go
Raw Normal View History

2016-04-02 14:40:07 +02:00
package sockets
import (
"fmt"
"github.com/ansible-semaphore/semaphore/db"
2017-02-23 00:21:49 +01:00
"net/http"
2016-04-02 14:40:07 +02:00
"time"
log "github.com/Sirupsen/logrus"
"github.com/ansible-semaphore/semaphore/util"
2017-02-23 00:21:49 +01:00
"github.com/gorilla/context"
2016-04-02 14:40:07 +02:00
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
2017-05-20 16:14:36 +02:00
CheckOrigin: func(r *http.Request) bool {
return true
},
2016-04-02 14:40:07 +02:00
}
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
)
type connection struct {
ws *websocket.Conn
send chan []byte
userID int
}
// readPump pumps messages from the websocket connection to the hub.
func (c *connection) readPump() {
defer func() {
h.unregister <- c
util.LogErrorWithFields(c.ws.Close(), log.Fields{"error": "Error closing websocket"})
2016-04-02 14:40:07 +02:00
}()
c.ws.SetReadLimit(maxMessageSize)
util.LogErrorWithFields(c.ws.SetReadDeadline(time.Now().Add(pongWait)), log.Fields{"error": "Socket state corrupt"})
2016-04-02 14:40:07 +02:00
c.ws.SetPongHandler(func(string) error {
util.LogErrorWithFields(c.ws.SetReadDeadline(time.Now().Add(pongWait)), log.Fields{"error": "Socket state corrupt"})
2016-04-02 14:40:07 +02:00
return nil
})
for {
_, message, err := c.ws.ReadMessage()
fmt.Println(string(message))
2016-04-17 12:41:36 +02:00
2016-04-02 14:40:07 +02:00
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
util.LogError(err)
2016-04-02 14:40:07 +02:00
}
break
}
}
}
// write writes a message with the given message type and payload.
func (c *connection) write(mt int, payload []byte) error {
util.LogErrorWithFields(c.ws.SetWriteDeadline(time.Now().Add(writeWait)), log.Fields{"error": "Socket state corrupt"})
2016-04-02 14:40:07 +02:00
return c.ws.WriteMessage(mt, payload)
}
// writePump pumps messages from the hub to the websocket connection.
func (c *connection) writePump() {
ticker := time.NewTicker(pingPeriod)
defer func() {
ticker.Stop()
util.LogError(c.ws.Close())
2016-04-02 14:40:07 +02:00
}()
for {
select {
case message, ok := <-c.send:
if !ok {
util.LogError(c.write(websocket.CloseMessage, []byte{}))
2016-04-02 14:40:07 +02:00
return
}
if err := c.write(websocket.TextMessage, message); err != nil {
util.LogError(err)
2016-04-02 14:40:07 +02:00
return
}
case <-ticker.C:
if err := c.write(websocket.PingMessage, []byte{}); err != nil {
util.LogError(err)
2016-04-02 14:40:07 +02:00
return
}
}
}
}
// Handler is used by the router to handle the /ws endpoint
2017-02-23 00:21:49 +01:00
func Handler(w http.ResponseWriter, r *http.Request) {
user := context.Get(r, "user").(*db.User)
2017-02-23 00:21:49 +01:00
ws, err := upgrader.Upgrade(w, r, nil)
2016-04-02 14:40:07 +02:00
if err != nil {
panic(err)
}
c := &connection{
send: make(chan []byte, 256),
ws: ws,
userID: user.ID,
}
h.register <- c
go c.writePump()
c.readPump()
}
2016-04-04 15:44:34 +02:00
// Message allows a message to be sent to the websockets, called in API task logging
2016-04-17 12:41:36 +02:00
func Message(userID int, message []byte) {
h.broadcast <- &sendRequest{
userID: userID,
msg: message,
}
2016-04-04 15:44:34 +02:00
}