aboutsummaryrefslogtreecommitdiffstats
path: root/websocket/server.go
blob: 1b4c00433f2565dc7a0ca99f11c8b0e6feae2915 (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
126
127
package websocket

import (
    "net/http"

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

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

var logger = ethlog.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() {
    logger.Debugln("Serving http", s.httpServ)
    err := http.ListenAndServe(s.httpServ, nil)

    logger.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() {
    logger.Debugln("Listening server...")

    // 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)
    })
    logger.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:
            logger.Debugln("Error:", err.Error())

        case <-s.doneCh:
            return
        }
    }
}