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
|
// Start is used by server.go to start the rpc listener.
func (s *rpcServer) Start() {
if atomic.AddInt32(&s.started, 1) != 1 {
return
}
rpcsLog.Trace("Starting RPC server")
rpcServeMux := http.NewServeMux()
httpServer := &http.Server{
Handler: rpcServeMux,
// Timeout connections which don't complete the initial
// handshake within the allowed timeframe.
ReadTimeout: time.Second * rpcAuthTimeoutSeconds,
}
rpcServeMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Connection", "close")
w.Header().Set("Content-Type", "application/json")
r.Close = true
// Limit the number of connections to max allowed.
if s.limitConnections(w, r.RemoteAddr) {
return
}
// Keep track of the number of connected clients.
s.incrementClients()
defer s.decrementClients()
_, isAdmin, err := s.checkAuth(r, true)
if err != nil {
jsonAuthFail(w)
return
}
// Read and respond to the request.
s.jsonRPCRead(w, r, isAdmin)
})
// Websocket endpoint.
rpcServeMux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
authenticated, isAdmin, err := s.checkAuth(r, false)
if err != nil {
jsonAuthFail(w)
return
}
// Attempt to upgrade the connection to a websocket connection
// using the default size for read/write buffers.
ws, err := websocket.Upgrade(w, r, nil, 0, 0)
if err != nil {
if _, ok := err.(websocket.HandshakeError); !ok {
rpcsLog.Errorf("Unexpected websocket error: %v",
err)
}
http.Error(w, "400 Bad Request.", http.StatusBadRequest)
return
}
s.WebsocketHandler(ws, r.RemoteAddr, authenticated, isAdmin)
})
for _, listener := range s.cfg.Listeners {
s.wg.Add(1)
go func(listener net.Listener) {
rpcsLog.Infof("RPC server listening on %s", listener.Addr())
httpServer.Serve(listener)
rpcsLog.Tracef("RPC listener done for %s", listener.Addr())
s.wg.Done()
}(listener)
}
s.ntfnMgr.Start()
}
|