/
server.go
99 lines (90 loc) · 2.01 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
96
97
98
99
package server
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"net"
"strconv"
"time"
"github.com/aguerra/grp/radius"
)
var testHookListenAndServe func(*Server, net.Listener) // used if non-nil
type Handler interface {
Handle(net.Conn)
}
type ServerConfig struct {
Port int `default:"2083"`
CaFile string `split_words:"true" default:"ca.crt"`
CertFile string `split_words:"true" default:"server.crt"`
KeyFile string `split_words:"true" default:"server.key"`
radius.RadiusConfig
}
type Server struct {
conf *ServerConfig
Handler
}
func (srv *Server) ListenAndServe() error {
tlsConfig, err := srv.newTLSConfig()
if err != nil {
return err
}
addr := net.JoinHostPort("", strconv.Itoa(srv.conf.Port))
ln, err := tls.Listen("tcp", addr, tlsConfig)
if err != nil {
return err
}
defer ln.Close()
if fn := testHookListenAndServe; fn != nil {
fn(srv, ln)
}
var tempDelay time.Duration
for {
conn, err := ln.Accept()
if err != nil {
if ne, ok := err.(net.Error); ok && ne.Temporary() {
// Taken from net/http server
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
log.Printf(
"Accept error: %v; retrying in %v",
err,
tempDelay,
)
time.Sleep(tempDelay)
continue
}
return err
}
go srv.Handle(conn)
}
}
func (srv *Server) newTLSConfig() (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(srv.conf.CertFile, srv.conf.KeyFile)
if err != nil {
return nil, err
}
ca, err := ioutil.ReadFile(srv.conf.CaFile)
if err != nil {
return nil, err
}
caPool := x509.NewCertPool()
caPool.AppendCertsFromPEM(ca)
tls := &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: caPool,
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{cert},
}
return tls, nil
}
func New(conf *ServerConfig) *Server {
h := radius.NewHandler(&conf.RadiusConfig)
return &Server{conf: conf, Handler: h}
}