-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebserver.go
106 lines (94 loc) · 2.07 KB
/
webserver.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
96
97
98
99
100
101
102
103
104
105
106
package network
import (
"errors"
"net"
"net/http"
"time"
"github.com/gin-gonic/gin"
)
var stoppedError = errors.New("Gin: Webserver is being stopped")
type stoppableListener struct {
tcpKeepAliveListener
stop chan int
}
type WebServer struct {
Online bool
Host string
engine *gin.Engine
listener *stoppableListener
}
func InitializeWebServer(r *gin.Engine, host string) (server *WebServer) {
return &WebServer{
Online: false,
Host: host,
engine: r,
}
}
func (wServer *WebServer) Start() error {
if !wServer.Online {
hServer := &http.Server{Addr: wServer.Host, Handler: wServer.engine}
listener, err := net.Listen("tcp", wServer.Host)
if err != nil {
return err
}
wServer.listener, err = newStoppableListener(tcpKeepAliveListener{listener.(*net.TCPListener)})
if err != nil {
return err
}
go hServer.Serve(wServer.listener)
wServer.Online = true
if err != nil {
if err != stoppedError {
panic(err)
}
}
return nil
} else {
return errors.New("Gin: Web server is already online")
}
}
func (server *WebServer) Stop() bool {
close(server.listener.stop)
server.Online = false
return true
}
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}
func newStoppableListener(l net.Listener) (*stoppableListener, error) {
tcpL, ok := l.(tcpKeepAliveListener)
if !ok {
return nil, errors.New("Gin: Cannot wrap listener")
}
retval := &stoppableListener{}
retval.tcpKeepAliveListener = tcpL
retval.stop = make(chan int)
return retval, nil
}
func (sl *stoppableListener) Accept() (net.Conn, error) {
for {
sl.SetDeadline(time.Now().Add(time.Second))
newConn, err := sl.tcpKeepAliveListener.Accept()
select {
case <-sl.stop:
return nil, stoppedError
default:
}
if err != nil {
netErr, ok := err.(net.Error)
if ok && netErr.Timeout() && netErr.Temporary() {
continue
}
}
return newConn, err
}
}