forked from vladaionescu/leveros
/
server.go
95 lines (84 loc) · 2.17 KB
/
server.go
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
package http2stream
import (
"net"
"sync"
"github.com/leveros/leveros/leverutil"
)
var (
serverLogger = leverutil.GetLogger(PackageName, "server")
)
// StreamHandler is a function that handles incoming streams.
type StreamHandler func(stream *HTTP2Stream)
// HTTP2Server represents a HTTP2 server which listens for connections.
type HTTP2Server struct {
lock sync.Mutex
listeners map[net.Listener]bool
conns map[*http2Connection]bool
}
// NewHTTP2Server returns a new instance of HTTP2Server.
func NewHTTP2Server() *HTTP2Server {
return &HTTP2Server{
listeners: make(map[net.Listener]bool),
conns: make(map[*http2Connection]bool),
}
}
// Serve listens for connections on provided address.
func (server *HTTP2Server) Serve(
protocol string, listenAddr string,
streamHandler StreamHandler) (net.Listener, chan struct{}, error) {
stopServeChan := make(chan struct{})
listener, err := net.Listen(protocol, listenAddr)
if err != nil {
close(stopServeChan)
return nil, stopServeChan, err
}
server.lock.Lock()
server.listeners[listener] = true
server.lock.Unlock()
go func() {
defer func() {
listener.Close()
server.lock.Lock()
defer server.lock.Unlock()
delete(server.listeners, listener)
}()
for {
netConn, err := listener.Accept()
if err != nil {
serverLogger.WithFields("err", err).Error(
"Error accepting connections")
close(stopServeChan)
return
}
conn, err := newHTTP2Connection(true, netConn, streamHandler)
if err != nil {
serverLogger.WithFields("err", err).Error(
"Error creating connection")
continue
}
server.lock.Lock()
server.conns[conn] = true
server.lock.Unlock()
go server.handleClose(conn)
}
}()
return listener, stopServeChan, nil
}
func (server *HTTP2Server) handleClose(conn *http2Connection) {
<-conn.closed()
server.lock.Lock()
delete(server.conns, conn)
server.lock.Unlock()
}
// Stop causes the server to close all open connections and exit any serving
// loops.
func (server *HTTP2Server) Stop() {
server.lock.Lock()
for listener := range server.listeners {
listener.Close()
}
for conn := range server.conns {
conn.close(nil)
}
server.lock.Unlock()
}