aboutsummaryrefslogtreecommitdiffstats
path: root/websocket/server.go
blob: b0658b1b4488695b9c6b1eea275c3304392756f7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package websocket

import (
    "net/http"

    "github.com/ethereum/go-ethereum/logger"

    ws "code.google.com/p/go.net/websocket"
)

var wslogger = logger.NewLogger("WS")

// Chat server.
type Server struct {
    httpServ  string
    pattern   string
    messages  []*Message
    clients   map[int]*Client
    addCh     chan *Client
    delCh     chan *Client
    sendAllCh chan string
    doneCh    chan bool
    errCh     chan error
    msgFunc   MsgFunc
}

// Create new chat server.
func NewServer(pattern, httpServ string) *Server {
    clients := make(map[int]*Client)
    addCh := make(chan *Client)
    delCh := make(chan *Client)
    sendAllCh := make(chan string)
    doneCh := make(chan bool)
    errCh := make(chan error)

    return &Server{
        httpServ,
        pattern,
        nil,
        clients,
        addCh,
        delCh,
        sendAllCh,
        doneCh,
        errCh,
        nil,
    }
}

func (s *Server) Add(c *Client) {
    s.addCh <- c
}

func (s *Server) Del(c *Client) {
    s.delCh <- c
}

func (s *Server) SendAll(msg string) {
    s.sendAllCh <- msg
}

func (s *Server) Done() {
    s.doneCh <- true
}

func (s *Server) Err(err error) {
    s.errCh <- err
}

func (s *Server) servHTTP() {
    wslogger.Debugln("Serving http", s.httpServ)
    err := http.ListenAndServe(s.httpServ, nil)

    wslogger.Warnln(err)
}

func (s *Server) MessageFunc(f MsgFunc) {
    s.msgFunc = f
}

// Listen and serve.
// It serves client connection and broadcast request.
func (s *Server) Listen() {
    // ws handler
    onConnected := func(ws *ws.Conn) {
        defer func() {
            err := ws.Close()
            if err != nil {
                s.errCh <- err
            }
        }()

        client := NewClient(ws, s)
        client.onMessage = s.msgFunc
        s.Add(client)
        client.Listen()
    }
    // Disable Origin check. Request don't need to come necessarily from origin.
    http.HandleFunc(s.pattern, func(w http.ResponseWriter, req *http.Request) {
        s := ws.Server{Handler: ws.Handler(onConnected)}
        s.ServeHTTP(w, req)
    })
    wslogger.Debugln("Created handler")

    go s.servHTTP()

    for {
        select {

        // Add new a client
        case c := <-s.addCh:
            s.clients[c.id] = c

        // del a client
        case c := <-s.delCh:
            delete(s.clients, c.id)

        case err := <-s.errCh:
            wslogger.Debugln("Error:", err.Error())

        case <-s.doneCh:
            return
        }
    }
}