documentation

This commit is contained in:
Ola Holmström
2015-05-13 23:15:10 +02:00
parent d1e23276ef
commit 9f353b18a2
7 changed files with 52 additions and 40 deletions
+1
View File
@@ -2,6 +2,7 @@ package melody
import "time" import "time"
// Melody configuration, all times in milliseconds.
type Config struct { type Config struct {
WriteWait time.Duration WriteWait time.Duration
PongWait time.Duration PongWait time.Duration
+1 -1
View File
@@ -8,7 +8,7 @@ import (
func main() { func main() {
r := gin.Default() r := gin.Default()
m := melody.Default() m := melody.New()
r.GET("/", func(c *gin.Context) { r.GET("/", func(c *gin.Context) {
http.ServeFile(c.Writer, c.Request, "index.html") http.ServeFile(c.Writer, c.Request, "index.html")
+1 -1
View File
@@ -12,7 +12,7 @@ func main() {
file := "file.txt" file := "file.txt"
r := gin.Default() r := gin.Default()
m := melody.Default() m := melody.New()
w, _ := fsnotify.NewWatcher() w, _ := fsnotify.NewWatcher()
r.GET("/", func(c *gin.Context) { r.GET("/", func(c *gin.Context) {
+1 -1
View File
@@ -25,7 +25,7 @@ func (h *hub) run() {
if _, ok := h.sessions[s]; ok { if _, ok := h.sessions[s]; ok {
delete(h.sessions, s) delete(h.sessions, s)
close(s.output) close(s.output)
s.Conn.Close() s.conn.Close()
} }
case m := <-h.broadcast: case m := <-h.broadcast:
for s := range h.sessions { for s := range h.sessions {
+32 -24
View File
@@ -12,15 +12,16 @@ type filterFunc func(*Session) bool
type Melody struct { type Melody struct {
Config *Config Config *Config
Upgrader *websocket.Upgrader upgrader *websocket.Upgrader
MessageHandler handleMessageFunc messageHandler handleMessageFunc
ErrorHandler handleErrorFunc errorHandler handleErrorFunc
ConnectHandler handleSessionFunc connectHandler handleSessionFunc
DisconnectHandler handleSessionFunc disconnectHandler handleSessionFunc
hub *hub hub *hub
} }
func Default() *Melody { // Returns a new melody instance.
func New() *Melody {
upgrader := &websocket.Upgrader{ upgrader := &websocket.Upgrader{
ReadBufferSize: 1024, ReadBufferSize: 1024,
WriteBufferSize: 1024, WriteBufferSize: 1024,
@@ -32,33 +33,38 @@ func Default() *Melody {
return &Melody{ return &Melody{
Config: newConfig(), Config: newConfig(),
Upgrader: upgrader, upgrader: upgrader,
MessageHandler: func(*Session, []byte) {}, messageHandler: func(*Session, []byte) {},
ErrorHandler: func(*Session, error) {}, errorHandler: func(*Session, error) {},
ConnectHandler: func(*Session) {}, connectHandler: func(*Session) {},
DisconnectHandler: func(*Session) {}, disconnectHandler: func(*Session) {},
hub: hub, hub: hub,
} }
} }
func (m *Melody) HandleConnect(fn handleSessionFunc) { // Fires fn when a session connects.
m.ConnectHandler = fn func (m *Melody) HandleConnect(fn func(*Session)) {
m.connectHandler = fn
} }
func (m *Melody) HandleDisconnect(fn handleSessionFunc) { // Fires fn when a session disconnects.
m.DisconnectHandler = fn func (m *Melody) HandleDisconnect(fn func(*Session)) {
m.disconnectHandler = fn
} }
func (m *Melody) HandleMessage(fn handleMessageFunc) { // Callback when a message comes in.
m.MessageHandler = fn func (m *Melody) HandleMessage(fn func(*Session, []byte)) {
m.messageHandler = fn
} }
// Fires when a session has an error.
func (m *Melody) HandleError(fn handleErrorFunc) { func (m *Melody) HandleError(fn handleErrorFunc) {
m.ErrorHandler = fn m.errorHandler = fn
} }
// Handles a http request and upgrades it to a websocket.
func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) error { func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) error {
conn, err := m.Upgrader.Upgrade(w, r, nil) conn, err := m.upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
return err return err
@@ -68,25 +74,27 @@ func (m *Melody) HandleRequest(w http.ResponseWriter, r *http.Request) error {
m.hub.register <- session m.hub.register <- session
go m.ConnectHandler(session) go m.connectHandler(session)
go session.writePump(m.ErrorHandler) go session.writePump(m.errorHandler)
session.readPump(m.MessageHandler, m.ErrorHandler) session.readPump(m.messageHandler, m.errorHandler)
m.hub.unregister <- session m.hub.unregister <- session
go m.DisconnectHandler(session) go m.disconnectHandler(session)
return nil return nil
} }
// Broadcasts a message to all sessions.
func (m *Melody) Broadcast(msg []byte) { func (m *Melody) Broadcast(msg []byte) {
message := &envelope{t: websocket.TextMessage, msg: msg} message := &envelope{t: websocket.TextMessage, msg: msg}
m.hub.broadcast <- message m.hub.broadcast <- message
} }
func (m *Melody) BroadcastFilter(fn filterFunc, msg []byte) { // Broadcasts a message to all sessions that fn returns true for.
func (m *Melody) BroadcastFilter(fn func(*Session) bool, msg []byte) {
message := &envelope{t: websocket.TextMessage, msg: msg, filter: fn} message := &envelope{t: websocket.TextMessage, msg: msg, filter: fn}
m.hub.broadcast <- message m.hub.broadcast <- message
} }
+2 -2
View File
@@ -15,7 +15,7 @@ type TestServer struct {
} }
func NewTestServerHandler(handler handleMessageFunc) *TestServer { func NewTestServerHandler(handler handleMessageFunc) *TestServer {
m := Default() m := New()
m.HandleMessage(handler) m.HandleMessage(handler)
return &TestServer{ return &TestServer{
m: m, m: m,
@@ -23,7 +23,7 @@ func NewTestServerHandler(handler handleMessageFunc) *TestServer {
} }
func NewTestServer() *TestServer { func NewTestServer() *TestServer {
m := Default() m := New()
return &TestServer{ return &TestServer{
m: m, m: m,
} }
+14 -11
View File
@@ -5,15 +5,16 @@ import (
"time" "time"
) )
// A melody session.
type Session struct { type Session struct {
Conn *websocket.Conn conn *websocket.Conn
output chan *envelope output chan *envelope
config *Config config *Config
} }
func newSession(config *Config, conn *websocket.Conn) *Session { func newSession(config *Config, conn *websocket.Conn) *Session {
return &Session{ return &Session{
Conn: conn, conn: conn,
output: make(chan *envelope, config.MessageBufferSize), output: make(chan *envelope, config.MessageBufferSize),
config: config, config: config,
} }
@@ -24,8 +25,8 @@ func (s *Session) writeMessage(message *envelope) {
} }
func (s *Session) writeRaw(message *envelope) error { func (s *Session) writeRaw(message *envelope) error {
s.Conn.SetWriteDeadline(time.Now().Add(s.config.WriteWait)) s.conn.SetWriteDeadline(time.Now().Add(s.config.WriteWait))
return s.Conn.WriteMessage(message.t, message.msg) return s.conn.WriteMessage(message.t, message.msg)
} }
func (s *Session) close() { func (s *Session) close() {
@@ -37,7 +38,7 @@ func (s *Session) ping() {
} }
func (s *Session) writePump(errorHandler handleErrorFunc) { func (s *Session) writePump(errorHandler handleErrorFunc) {
defer s.Conn.Close() defer s.conn.Close()
ticker := time.NewTicker(s.config.PingPeriod) ticker := time.NewTicker(s.config.PingPeriod)
defer ticker.Stop() defer ticker.Stop()
@@ -60,18 +61,18 @@ func (s *Session) writePump(errorHandler handleErrorFunc) {
} }
func (s *Session) readPump(messageHandler handleMessageFunc, errorHandler handleErrorFunc) { func (s *Session) readPump(messageHandler handleMessageFunc, errorHandler handleErrorFunc) {
defer s.Conn.Close() defer s.conn.Close()
s.Conn.SetReadLimit(s.config.MaxMessageSize) s.conn.SetReadLimit(s.config.MaxMessageSize)
s.Conn.SetReadDeadline(time.Now().Add(s.config.PongWait)) s.conn.SetReadDeadline(time.Now().Add(s.config.PongWait))
s.Conn.SetPongHandler(func(string) error { s.conn.SetPongHandler(func(string) error {
s.Conn.SetReadDeadline(time.Now().Add(s.config.PongWait)) s.conn.SetReadDeadline(time.Now().Add(s.config.PongWait))
return nil return nil
}) })
for { for {
_, message, err := s.Conn.ReadMessage() _, message, err := s.conn.ReadMessage()
if err != nil { if err != nil {
go errorHandler(s, err) go errorHandler(s, err)
@@ -82,10 +83,12 @@ func (s *Session) readPump(messageHandler handleMessageFunc, errorHandler handle
} }
} }
// Write a message to session.
func (s *Session) Write(msg []byte) { func (s *Session) Write(msg []byte) {
s.writeMessage(&envelope{t: websocket.TextMessage, msg: msg}) s.writeMessage(&envelope{t: websocket.TextMessage, msg: msg})
} }
// Close a session.
func (s *Session) Close() { func (s *Session) Close() {
s.writeMessage(&envelope{t: websocket.CloseMessage, msg: []byte{}}) s.writeMessage(&envelope{t: websocket.CloseMessage, msg: []byte{}})
} }