-
Notifications
You must be signed in to change notification settings - Fork 0
/
systemd.go
174 lines (155 loc) · 4.92 KB
/
systemd.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package net
import (
"crypto/tls"
"fmt"
"net"
"os"
"strconv"
"strings"
)
// ListenEnv Загрузка значений переменных окружения от systemd для работы через сокет.
func (nut *impl) ListenEnv() (ret *listenEnv, err error) {
const (
sepColon = ":"
listenPID = "LISTEN_PID"
listenFds = "LISTEN_FDS"
listenFdNames = "LISTEN_FDNAMES"
errPIDTpl = "получение PID из переменной окружения %q прервано ошибкой: %s"
errFDSTpl = "получение файлового дескриптора из переменной окружения %q прервано ошибкой: %s"
)
ret = new(listenEnv)
if ret.pid, err = strconv.Atoi(os.Getenv(listenPID)); err != nil {
err = fmt.Errorf(errPIDTpl, listenPID, err)
return
}
if ret.fds, err = strconv.Atoi(os.Getenv(listenFds)); err != nil {
err = fmt.Errorf(errFDSTpl, listenFds, err)
return
}
ret.names = strings.Split(os.Getenv(listenFdNames), sepColon)
// Проверка ID процесса.
if ret.pid != os.Getpid() {
err = Errors().ListenSystemdPID()
return
}
// Проверка количества передаваемых соединений.
if ret.fds == 0 {
err = Errors().ListenSystemdFDS()
return
}
// Проверка заявленного количества с фактически переданным количеством соединений.
if ret.fds != len(ret.names) {
err = Errors().ListenSystemdQuantityNotMatch()
return
}
return
}
// ListenLoadFilesFdWithNames Загрузка файловых дескрипторов на основе переменных окружения
func (nut *impl) ListenLoadFilesFdWithNames() (ret []*os.File, err error) {
const (
listenFdBegin = 3
listenFdPrefix = "LISTEN_FD_"
)
var (
env *listenEnv
name string
fd, offset int
)
if env, err = nut.ListenEnv(); err != nil {
return
}
ret = make([]*os.File, 0, env.fds)
for fd = listenFdBegin; fd < listenFdBegin+env.fds; fd++ {
//syscall.CloseOnExec(fd)
name = listenFdPrefix + strconv.Itoa(fd)
if offset = fd - listenFdBegin; offset < len(env.names) && len(env.names[offset]) > 0 {
name = env.names[offset]
}
ret = append(ret, nut.fnNf(uintptr(fd), name))
}
return
}
// ListenersSystemdWithoutNames Возвращает срез net.Listener сокетов переданных в процесс сервера
// из службы linux - systemd.
func (nut *impl) ListenersSystemdWithoutNames() (ret []net.Listener, err error) {
var (
file *os.File
files []*os.File
n int
pc net.Listener
)
files, err = nut.ListenLoadFilesFdWithNames()
ret = make([]net.Listener, len(files))
for n, file = range files {
if pc, err = nut.fnFl(file); err == nil {
ret[n], _ = pc, nut.fnFc(file)
}
}
return
}
// ListenersSystemdWithNames Возвращает карту срезов net.Listener сокетов переданных в процесс сервера
// из службы linux - systemd.
func (nut *impl) ListenersSystemdWithNames() (ret map[string][]net.Listener, err error) {
var (
file *os.File
files []*os.File
current []net.Listener
pc net.Listener
ok bool
)
files, err = nut.ListenLoadFilesFdWithNames()
ret = make(map[string][]net.Listener)
for _, file = range files {
if pc, err = nut.fnFl(file); err == nil {
if current, ok = ret[file.Name()]; !ok {
ret[file.Name()] = make([]net.Listener, 0, 1)
}
ret[file.Name()] = append(current, pc)
_ = nut.fnFc(file)
}
}
return
}
// ListenersSystemdTLSWithoutNames Возвращает срез net.nnlistener для TLS сокетов переданных в процесс сервера
// из службы linux - systemd.
func (nut *impl) ListenersSystemdTLSWithoutNames(tlsConfig *tls.Config) (ret []net.Listener, err error) {
var (
listeners []net.Listener
l net.Listener
)
if listeners, err = nut.ListenersSystemdWithoutNames(); len(listeners) == 0 || err != nil {
return
}
if tlsConfig == nil {
err = Errors().TLSIsNil()
return
}
ret = make([]net.Listener, 0, len(listeners))
for _, l = range listeners {
ret = append(ret, tls.NewListener(l, tlsConfig))
}
return
}
// ListenersSystemdTLSWithNames Возвращает карту срезов net.nnlistener для TLS сокетов переданных в процесс сервера
// из службы linux - systemd.
func (nut *impl) ListenersSystemdTLSWithNames(tlsConfig *tls.Config) (ret map[string][]net.Listener, err error) {
var (
listeners map[string][]net.Listener
ll []net.Listener
l net.Listener
n int
)
if listeners, err = nut.ListenersSystemdWithNames(); listeners == nil || err != nil {
return
}
if tlsConfig == nil {
err = Errors().TLSIsNil()
return
}
for _, ll = range listeners {
for n, l = range ll {
ll[n] = tls.NewListener(l, tlsConfig)
}
}
return
}