Blame


1 d93ecf7d 2022-12-14 stsp /*
2 d93ecf7d 2022-12-14 stsp * Copyright (c) 2022 Stefan Sperling <stsp@openbsd.org>
3 d93ecf7d 2022-12-14 stsp *
4 d93ecf7d 2022-12-14 stsp * Permission to use, copy, modify, and distribute this software for any
5 d93ecf7d 2022-12-14 stsp * purpose with or without fee is hereby granted, provided that the above
6 d93ecf7d 2022-12-14 stsp * copyright notice and this permission notice appear in all copies.
7 d93ecf7d 2022-12-14 stsp *
8 d93ecf7d 2022-12-14 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 d93ecf7d 2022-12-14 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 d93ecf7d 2022-12-14 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 d93ecf7d 2022-12-14 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 d93ecf7d 2022-12-14 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 d93ecf7d 2022-12-14 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 d93ecf7d 2022-12-14 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 d93ecf7d 2022-12-14 stsp */
16 d93ecf7d 2022-12-14 stsp
17 d93ecf7d 2022-12-14 stsp #include <sys/types.h>
18 d93ecf7d 2022-12-14 stsp #include <sys/queue.h>
19 d93ecf7d 2022-12-14 stsp #include <sys/socket.h>
20 d93ecf7d 2022-12-14 stsp #include <sys/uio.h>
21 d93ecf7d 2022-12-14 stsp
22 d93ecf7d 2022-12-14 stsp #include <errno.h>
23 d93ecf7d 2022-12-14 stsp #include <event.h>
24 d93ecf7d 2022-12-14 stsp #include <siphash.h>
25 d93ecf7d 2022-12-14 stsp #include <stdint.h>
26 d93ecf7d 2022-12-14 stsp #include <stdio.h>
27 d93ecf7d 2022-12-14 stsp #include <stdlib.h>
28 d93ecf7d 2022-12-14 stsp #include <string.h>
29 d93ecf7d 2022-12-14 stsp #include <imsg.h>
30 d93ecf7d 2022-12-14 stsp #include <limits.h>
31 d93ecf7d 2022-12-14 stsp #include <sha1.h>
32 d93ecf7d 2022-12-14 stsp #include <signal.h>
33 d93ecf7d 2022-12-14 stsp #include <unistd.h>
34 d93ecf7d 2022-12-14 stsp
35 d93ecf7d 2022-12-14 stsp #include "got_error.h"
36 d93ecf7d 2022-12-14 stsp
37 d93ecf7d 2022-12-14 stsp #include "gotd.h"
38 d93ecf7d 2022-12-14 stsp #include "log.h"
39 d93ecf7d 2022-12-14 stsp #include "listen.h"
40 d93ecf7d 2022-12-14 stsp
41 d93ecf7d 2022-12-14 stsp #ifndef nitems
42 d93ecf7d 2022-12-14 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
43 d93ecf7d 2022-12-14 stsp #endif
44 d93ecf7d 2022-12-14 stsp
45 d93ecf7d 2022-12-14 stsp struct gotd_listen_client {
46 d93ecf7d 2022-12-14 stsp STAILQ_ENTRY(gotd_listen_client) entry;
47 d93ecf7d 2022-12-14 stsp uint32_t id;
48 d93ecf7d 2022-12-14 stsp int fd;
49 d93ecf7d 2022-12-14 stsp };
50 d93ecf7d 2022-12-14 stsp STAILQ_HEAD(gotd_listen_clients, gotd_listen_client);
51 d93ecf7d 2022-12-14 stsp
52 d93ecf7d 2022-12-14 stsp static struct gotd_listen_clients gotd_listen_clients[GOTD_CLIENT_TABLE_SIZE];
53 d93ecf7d 2022-12-14 stsp static SIPHASH_KEY clients_hash_key;
54 d93ecf7d 2022-12-14 stsp static volatile int listen_client_cnt;
55 d93ecf7d 2022-12-14 stsp static int inflight;
56 d93ecf7d 2022-12-14 stsp
57 d93ecf7d 2022-12-14 stsp static struct {
58 d93ecf7d 2022-12-14 stsp pid_t pid;
59 d93ecf7d 2022-12-14 stsp const char *title;
60 d93ecf7d 2022-12-14 stsp int fd;
61 d93ecf7d 2022-12-14 stsp struct gotd_imsgev iev;
62 d93ecf7d 2022-12-14 stsp struct gotd_imsgev pause;
63 d93ecf7d 2022-12-14 stsp } gotd_listen;
64 d93ecf7d 2022-12-14 stsp
65 d93ecf7d 2022-12-14 stsp static int inflight;
66 d93ecf7d 2022-12-14 stsp
67 d93ecf7d 2022-12-14 stsp static void listen_shutdown(void);
68 d93ecf7d 2022-12-14 stsp
69 d93ecf7d 2022-12-14 stsp static void
70 d93ecf7d 2022-12-14 stsp listen_sighdlr(int sig, short event, void *arg)
71 d93ecf7d 2022-12-14 stsp {
72 d93ecf7d 2022-12-14 stsp /*
73 d93ecf7d 2022-12-14 stsp * Normal signal handler rules don't apply because libevent
74 d93ecf7d 2022-12-14 stsp * decouples for us.
75 d93ecf7d 2022-12-14 stsp */
76 d93ecf7d 2022-12-14 stsp
77 d93ecf7d 2022-12-14 stsp switch (sig) {
78 d93ecf7d 2022-12-14 stsp case SIGHUP:
79 d93ecf7d 2022-12-14 stsp break;
80 d93ecf7d 2022-12-14 stsp case SIGUSR1:
81 d93ecf7d 2022-12-14 stsp break;
82 d93ecf7d 2022-12-14 stsp case SIGTERM:
83 d93ecf7d 2022-12-14 stsp case SIGINT:
84 d93ecf7d 2022-12-14 stsp listen_shutdown();
85 d93ecf7d 2022-12-14 stsp /* NOTREACHED */
86 d93ecf7d 2022-12-14 stsp break;
87 d93ecf7d 2022-12-14 stsp default:
88 d93ecf7d 2022-12-14 stsp fatalx("unexpected signal");
89 d93ecf7d 2022-12-14 stsp }
90 d93ecf7d 2022-12-14 stsp }
91 d93ecf7d 2022-12-14 stsp
92 d93ecf7d 2022-12-14 stsp static uint64_t
93 d93ecf7d 2022-12-14 stsp client_hash(uint32_t client_id)
94 d93ecf7d 2022-12-14 stsp {
95 d93ecf7d 2022-12-14 stsp return SipHash24(&clients_hash_key, &client_id, sizeof(client_id));
96 d93ecf7d 2022-12-14 stsp }
97 d93ecf7d 2022-12-14 stsp
98 d93ecf7d 2022-12-14 stsp static void
99 d93ecf7d 2022-12-14 stsp add_client(struct gotd_listen_client *client)
100 d93ecf7d 2022-12-14 stsp {
101 d93ecf7d 2022-12-14 stsp uint64_t slot = client_hash(client->id) % nitems(gotd_listen_clients);
102 d93ecf7d 2022-12-14 stsp STAILQ_INSERT_HEAD(&gotd_listen_clients[slot], client, entry);
103 d93ecf7d 2022-12-14 stsp listen_client_cnt++;
104 d93ecf7d 2022-12-14 stsp }
105 d93ecf7d 2022-12-14 stsp
106 d93ecf7d 2022-12-14 stsp static struct gotd_listen_client *
107 d93ecf7d 2022-12-14 stsp find_client(uint32_t client_id)
108 d93ecf7d 2022-12-14 stsp {
109 d93ecf7d 2022-12-14 stsp uint64_t slot;
110 d93ecf7d 2022-12-14 stsp struct gotd_listen_client *c;
111 d93ecf7d 2022-12-14 stsp
112 d93ecf7d 2022-12-14 stsp slot = client_hash(client_id) % nitems(gotd_listen_clients);
113 d93ecf7d 2022-12-14 stsp STAILQ_FOREACH(c, &gotd_listen_clients[slot], entry) {
114 d93ecf7d 2022-12-14 stsp if (c->id == client_id)
115 d93ecf7d 2022-12-14 stsp return c;
116 d93ecf7d 2022-12-14 stsp }
117 d93ecf7d 2022-12-14 stsp
118 d93ecf7d 2022-12-14 stsp return NULL;
119 d93ecf7d 2022-12-14 stsp }
120 d93ecf7d 2022-12-14 stsp
121 d93ecf7d 2022-12-14 stsp static uint32_t
122 d93ecf7d 2022-12-14 stsp get_client_id(void)
123 d93ecf7d 2022-12-14 stsp {
124 d93ecf7d 2022-12-14 stsp int duplicate = 0;
125 d93ecf7d 2022-12-14 stsp uint32_t id;
126 d93ecf7d 2022-12-14 stsp
127 d93ecf7d 2022-12-14 stsp do {
128 d93ecf7d 2022-12-14 stsp id = arc4random();
129 d93ecf7d 2022-12-14 stsp duplicate = (find_client(id) != NULL);
130 d93ecf7d 2022-12-14 stsp } while (duplicate || id == 0);
131 d93ecf7d 2022-12-14 stsp
132 d93ecf7d 2022-12-14 stsp return id;
133 d93ecf7d 2022-12-14 stsp }
134 d93ecf7d 2022-12-14 stsp
135 d93ecf7d 2022-12-14 stsp static const struct got_error *
136 d93ecf7d 2022-12-14 stsp disconnect(struct gotd_listen_client *client)
137 d93ecf7d 2022-12-14 stsp {
138 d93ecf7d 2022-12-14 stsp uint64_t slot;
139 d93ecf7d 2022-12-14 stsp int client_fd;
140 d93ecf7d 2022-12-14 stsp
141 d93ecf7d 2022-12-14 stsp log_debug("client on fd %d disconnecting", client->fd);
142 d93ecf7d 2022-12-14 stsp
143 d93ecf7d 2022-12-14 stsp slot = client_hash(client->id) % nitems(gotd_listen_clients);
144 d93ecf7d 2022-12-14 stsp STAILQ_REMOVE(&gotd_listen_clients[slot], client,
145 d93ecf7d 2022-12-14 stsp gotd_listen_client, entry);
146 d93ecf7d 2022-12-14 stsp client_fd = client->fd;
147 d93ecf7d 2022-12-14 stsp free(client);
148 d93ecf7d 2022-12-14 stsp inflight--;
149 d93ecf7d 2022-12-14 stsp listen_client_cnt--;
150 d93ecf7d 2022-12-14 stsp if (close(client_fd) == -1)
151 d93ecf7d 2022-12-14 stsp return got_error_from_errno("close");
152 d93ecf7d 2022-12-14 stsp
153 d93ecf7d 2022-12-14 stsp return NULL;
154 d93ecf7d 2022-12-14 stsp }
155 d93ecf7d 2022-12-14 stsp
156 d93ecf7d 2022-12-14 stsp static int
157 d93ecf7d 2022-12-14 stsp accept_reserve(int fd, struct sockaddr *addr, socklen_t *addrlen,
158 d93ecf7d 2022-12-14 stsp int reserve, volatile int *counter)
159 d93ecf7d 2022-12-14 stsp {
160 d93ecf7d 2022-12-14 stsp int ret;
161 d93ecf7d 2022-12-14 stsp
162 d93ecf7d 2022-12-14 stsp if (getdtablecount() + reserve +
163 d93ecf7d 2022-12-14 stsp ((*counter + 1) * GOTD_FD_NEEDED) >= getdtablesize()) {
164 d93ecf7d 2022-12-14 stsp log_debug("inflight fds exceeded");
165 d93ecf7d 2022-12-14 stsp errno = EMFILE;
166 d93ecf7d 2022-12-14 stsp return -1;
167 d93ecf7d 2022-12-14 stsp }
168 d93ecf7d 2022-12-14 stsp
169 d93ecf7d 2022-12-14 stsp if ((ret = accept4(fd, addr, addrlen,
170 d93ecf7d 2022-12-14 stsp SOCK_NONBLOCK | SOCK_CLOEXEC)) > -1) {
171 d93ecf7d 2022-12-14 stsp (*counter)++;
172 d93ecf7d 2022-12-14 stsp }
173 d93ecf7d 2022-12-14 stsp
174 d93ecf7d 2022-12-14 stsp return ret;
175 d93ecf7d 2022-12-14 stsp }
176 d93ecf7d 2022-12-14 stsp
177 d93ecf7d 2022-12-14 stsp static void
178 d93ecf7d 2022-12-14 stsp gotd_accept_paused(int fd, short event, void *arg)
179 d93ecf7d 2022-12-14 stsp {
180 d93ecf7d 2022-12-14 stsp event_add(&gotd_listen.iev.ev, NULL);
181 d93ecf7d 2022-12-14 stsp }
182 d93ecf7d 2022-12-14 stsp
183 d93ecf7d 2022-12-14 stsp static void
184 d93ecf7d 2022-12-14 stsp gotd_accept(int fd, short event, void *arg)
185 d93ecf7d 2022-12-14 stsp {
186 d93ecf7d 2022-12-14 stsp struct gotd_imsgev *iev = arg;
187 d93ecf7d 2022-12-14 stsp struct sockaddr_storage ss;
188 d93ecf7d 2022-12-14 stsp struct timeval backoff;
189 d93ecf7d 2022-12-14 stsp socklen_t len;
190 d93ecf7d 2022-12-14 stsp int s = -1;
191 d93ecf7d 2022-12-14 stsp struct gotd_listen_client *client = NULL;
192 d93ecf7d 2022-12-14 stsp struct gotd_imsg_connect iconn;
193 d93ecf7d 2022-12-14 stsp
194 d93ecf7d 2022-12-14 stsp backoff.tv_sec = 1;
195 d93ecf7d 2022-12-14 stsp backoff.tv_usec = 0;
196 d93ecf7d 2022-12-14 stsp
197 d93ecf7d 2022-12-14 stsp if (event_add(&gotd_listen.iev.ev, NULL) == -1) {
198 d93ecf7d 2022-12-14 stsp log_warn("event_add");
199 d93ecf7d 2022-12-14 stsp return;
200 d93ecf7d 2022-12-14 stsp }
201 d93ecf7d 2022-12-14 stsp if (event & EV_TIMEOUT)
202 d93ecf7d 2022-12-14 stsp return;
203 d93ecf7d 2022-12-14 stsp
204 d93ecf7d 2022-12-14 stsp len = sizeof(ss);
205 d93ecf7d 2022-12-14 stsp
206 d93ecf7d 2022-12-14 stsp /* Other backoff conditions apart from EMFILE/ENFILE? */
207 d93ecf7d 2022-12-14 stsp s = accept_reserve(fd, (struct sockaddr *)&ss, &len, GOTD_FD_RESERVE,
208 d93ecf7d 2022-12-14 stsp &inflight);
209 d93ecf7d 2022-12-14 stsp if (s == -1) {
210 d93ecf7d 2022-12-14 stsp switch (errno) {
211 d93ecf7d 2022-12-14 stsp case EINTR:
212 d93ecf7d 2022-12-14 stsp case EWOULDBLOCK:
213 d93ecf7d 2022-12-14 stsp case ECONNABORTED:
214 d93ecf7d 2022-12-14 stsp return;
215 d93ecf7d 2022-12-14 stsp case EMFILE:
216 d93ecf7d 2022-12-14 stsp case ENFILE:
217 d93ecf7d 2022-12-14 stsp event_del(&gotd_listen.iev.ev);
218 d93ecf7d 2022-12-14 stsp evtimer_add(&gotd_listen.pause.ev, &backoff);
219 d93ecf7d 2022-12-14 stsp return;
220 d93ecf7d 2022-12-14 stsp default:
221 d93ecf7d 2022-12-14 stsp log_warn("accept");
222 d93ecf7d 2022-12-14 stsp return;
223 d93ecf7d 2022-12-14 stsp }
224 d93ecf7d 2022-12-14 stsp }
225 d93ecf7d 2022-12-14 stsp
226 d93ecf7d 2022-12-14 stsp if (listen_client_cnt >= GOTD_MAXCLIENTS)
227 d93ecf7d 2022-12-14 stsp goto err;
228 d93ecf7d 2022-12-14 stsp
229 d93ecf7d 2022-12-14 stsp client = calloc(1, sizeof(*client));
230 d93ecf7d 2022-12-14 stsp if (client == NULL) {
231 d93ecf7d 2022-12-14 stsp log_warn("%s: calloc", __func__);
232 d93ecf7d 2022-12-14 stsp goto err;
233 d93ecf7d 2022-12-14 stsp }
234 d93ecf7d 2022-12-14 stsp client->id = get_client_id();
235 d93ecf7d 2022-12-14 stsp client->fd = s;
236 d93ecf7d 2022-12-14 stsp s = -1;
237 d93ecf7d 2022-12-14 stsp add_client(client);
238 d93ecf7d 2022-12-14 stsp log_debug("%s: new client connected on fd %d", __func__, client->fd);
239 d93ecf7d 2022-12-14 stsp
240 d93ecf7d 2022-12-14 stsp memset(&iconn, 0, sizeof(iconn));
241 d93ecf7d 2022-12-14 stsp iconn.client_id = client->id;
242 d93ecf7d 2022-12-14 stsp s = dup(client->fd);
243 d93ecf7d 2022-12-14 stsp if (s == -1) {
244 d93ecf7d 2022-12-14 stsp log_warn("%s: dup", __func__);
245 d93ecf7d 2022-12-14 stsp goto err;
246 d93ecf7d 2022-12-14 stsp }
247 d93ecf7d 2022-12-14 stsp if (gotd_imsg_compose_event(iev, GOTD_IMSG_CONNECT, PROC_LISTEN, s,
248 d93ecf7d 2022-12-14 stsp &iconn, sizeof(iconn)) == -1) {
249 d93ecf7d 2022-12-14 stsp log_warn("imsg compose CONNECT");
250 d93ecf7d 2022-12-14 stsp goto err;
251 d93ecf7d 2022-12-14 stsp }
252 d93ecf7d 2022-12-14 stsp
253 d93ecf7d 2022-12-14 stsp return;
254 d93ecf7d 2022-12-14 stsp err:
255 d93ecf7d 2022-12-14 stsp inflight--;
256 d93ecf7d 2022-12-14 stsp if (client)
257 d93ecf7d 2022-12-14 stsp disconnect(client);
258 d93ecf7d 2022-12-14 stsp if (s != -1)
259 d93ecf7d 2022-12-14 stsp close(s);
260 d93ecf7d 2022-12-14 stsp }
261 d93ecf7d 2022-12-14 stsp
262 d93ecf7d 2022-12-14 stsp static const struct got_error *
263 d93ecf7d 2022-12-14 stsp recv_disconnect(struct imsg *imsg)
264 d93ecf7d 2022-12-14 stsp {
265 d93ecf7d 2022-12-14 stsp struct gotd_imsg_disconnect idisconnect;
266 d93ecf7d 2022-12-14 stsp size_t datalen;
267 d93ecf7d 2022-12-14 stsp struct gotd_listen_client *client = NULL;
268 d93ecf7d 2022-12-14 stsp
269 d93ecf7d 2022-12-14 stsp datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
270 d93ecf7d 2022-12-14 stsp if (datalen != sizeof(idisconnect))
271 d93ecf7d 2022-12-14 stsp return got_error(GOT_ERR_PRIVSEP_LEN);
272 d93ecf7d 2022-12-14 stsp memcpy(&idisconnect, imsg->data, sizeof(idisconnect));
273 d93ecf7d 2022-12-14 stsp
274 d93ecf7d 2022-12-14 stsp log_debug("client disconnecting");
275 d93ecf7d 2022-12-14 stsp
276 d93ecf7d 2022-12-14 stsp client = find_client(idisconnect.client_id);
277 d93ecf7d 2022-12-14 stsp if (client == NULL)
278 d93ecf7d 2022-12-14 stsp return got_error(GOT_ERR_CLIENT_ID);
279 d93ecf7d 2022-12-14 stsp
280 d93ecf7d 2022-12-14 stsp return disconnect(client);
281 d93ecf7d 2022-12-14 stsp }
282 d93ecf7d 2022-12-14 stsp
283 d93ecf7d 2022-12-14 stsp static void
284 d93ecf7d 2022-12-14 stsp listen_dispatch(int fd, short event, void *arg)
285 d93ecf7d 2022-12-14 stsp {
286 d93ecf7d 2022-12-14 stsp const struct got_error *err = NULL;
287 d93ecf7d 2022-12-14 stsp struct gotd_imsgev *iev = arg;
288 d93ecf7d 2022-12-14 stsp struct imsgbuf *ibuf = &iev->ibuf;
289 d93ecf7d 2022-12-14 stsp struct imsg imsg;
290 d93ecf7d 2022-12-14 stsp ssize_t n;
291 d93ecf7d 2022-12-14 stsp int shut = 0;
292 d93ecf7d 2022-12-14 stsp
293 d93ecf7d 2022-12-14 stsp if (event & EV_READ) {
294 d93ecf7d 2022-12-14 stsp if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
295 d93ecf7d 2022-12-14 stsp fatal("imsg_read error");
296 d93ecf7d 2022-12-14 stsp if (n == 0) /* Connection closed. */
297 d93ecf7d 2022-12-14 stsp shut = 1;
298 d93ecf7d 2022-12-14 stsp }
299 d93ecf7d 2022-12-14 stsp
300 d93ecf7d 2022-12-14 stsp if (event & EV_WRITE) {
301 d93ecf7d 2022-12-14 stsp n = msgbuf_write(&ibuf->w);
302 d93ecf7d 2022-12-14 stsp if (n == -1 && errno != EAGAIN)
303 d93ecf7d 2022-12-14 stsp fatal("msgbuf_write");
304 d93ecf7d 2022-12-14 stsp if (n == 0) /* Connection closed. */
305 d93ecf7d 2022-12-14 stsp shut = 1;
306 d93ecf7d 2022-12-14 stsp }
307 d93ecf7d 2022-12-14 stsp
308 d93ecf7d 2022-12-14 stsp for (;;) {
309 d93ecf7d 2022-12-14 stsp if ((n = imsg_get(ibuf, &imsg)) == -1)
310 d93ecf7d 2022-12-14 stsp fatal("%s: imsg_get", __func__);
311 d93ecf7d 2022-12-14 stsp if (n == 0) /* No more messages. */
312 d93ecf7d 2022-12-14 stsp break;
313 d93ecf7d 2022-12-14 stsp
314 d93ecf7d 2022-12-14 stsp switch (imsg.hdr.type) {
315 d93ecf7d 2022-12-14 stsp case GOTD_IMSG_DISCONNECT:
316 d93ecf7d 2022-12-14 stsp err = recv_disconnect(&imsg);
317 d93ecf7d 2022-12-14 stsp if (err)
318 d93ecf7d 2022-12-14 stsp log_warnx("%s: disconnect: %s",
319 d93ecf7d 2022-12-14 stsp gotd_listen.title, err->msg);
320 d93ecf7d 2022-12-14 stsp break;
321 d93ecf7d 2022-12-14 stsp default:
322 d93ecf7d 2022-12-14 stsp log_debug("%s: unexpected imsg %d", gotd_listen.title,
323 d93ecf7d 2022-12-14 stsp imsg.hdr.type);
324 d93ecf7d 2022-12-14 stsp break;
325 d93ecf7d 2022-12-14 stsp }
326 d93ecf7d 2022-12-14 stsp
327 d93ecf7d 2022-12-14 stsp imsg_free(&imsg);
328 d93ecf7d 2022-12-14 stsp }
329 d93ecf7d 2022-12-14 stsp
330 d93ecf7d 2022-12-14 stsp if (!shut) {
331 d93ecf7d 2022-12-14 stsp gotd_imsg_event_add(iev);
332 d93ecf7d 2022-12-14 stsp } else {
333 d93ecf7d 2022-12-14 stsp /* This pipe is dead. Remove its event handler */
334 d93ecf7d 2022-12-14 stsp event_del(&iev->ev);
335 d93ecf7d 2022-12-14 stsp event_loopexit(NULL);
336 d93ecf7d 2022-12-14 stsp }
337 d93ecf7d 2022-12-14 stsp }
338 d93ecf7d 2022-12-14 stsp
339 d93ecf7d 2022-12-14 stsp void
340 d93ecf7d 2022-12-14 stsp listen_main(const char *title, int gotd_socket)
341 d93ecf7d 2022-12-14 stsp {
342 d93ecf7d 2022-12-14 stsp struct gotd_imsgev iev;
343 d93ecf7d 2022-12-14 stsp struct event evsigint, evsigterm, evsighup, evsigusr1;
344 d93ecf7d 2022-12-14 stsp
345 d93ecf7d 2022-12-14 stsp gotd_listen.title = title;
346 d93ecf7d 2022-12-14 stsp gotd_listen.pid = getpid();
347 d93ecf7d 2022-12-14 stsp gotd_listen.fd = gotd_socket;
348 d93ecf7d 2022-12-14 stsp
349 d93ecf7d 2022-12-14 stsp signal_set(&evsigint, SIGINT, listen_sighdlr, NULL);
350 d93ecf7d 2022-12-14 stsp signal_set(&evsigterm, SIGTERM, listen_sighdlr, NULL);
351 d93ecf7d 2022-12-14 stsp signal_set(&evsighup, SIGHUP, listen_sighdlr, NULL);
352 d93ecf7d 2022-12-14 stsp signal_set(&evsigusr1, SIGUSR1, listen_sighdlr, NULL);
353 d93ecf7d 2022-12-14 stsp signal(SIGPIPE, SIG_IGN);
354 d93ecf7d 2022-12-14 stsp
355 d93ecf7d 2022-12-14 stsp signal_add(&evsigint, NULL);
356 d93ecf7d 2022-12-14 stsp signal_add(&evsigterm, NULL);
357 d93ecf7d 2022-12-14 stsp signal_add(&evsighup, NULL);
358 d93ecf7d 2022-12-14 stsp signal_add(&evsigusr1, NULL);
359 d93ecf7d 2022-12-14 stsp
360 d93ecf7d 2022-12-14 stsp imsg_init(&iev.ibuf, GOTD_FILENO_MSG_PIPE);
361 d93ecf7d 2022-12-14 stsp iev.handler = listen_dispatch;
362 d93ecf7d 2022-12-14 stsp iev.events = EV_READ;
363 d93ecf7d 2022-12-14 stsp iev.handler_arg = NULL;
364 d93ecf7d 2022-12-14 stsp event_set(&iev.ev, iev.ibuf.fd, EV_READ, listen_dispatch, &iev);
365 d93ecf7d 2022-12-14 stsp if (event_add(&iev.ev, NULL) == -1)
366 d93ecf7d 2022-12-14 stsp fatalx("event add");
367 d93ecf7d 2022-12-14 stsp
368 d93ecf7d 2022-12-14 stsp event_set(&gotd_listen.iev.ev, gotd_listen.fd, EV_READ | EV_PERSIST,
369 d93ecf7d 2022-12-14 stsp gotd_accept, &iev);
370 d93ecf7d 2022-12-14 stsp if (event_add(&gotd_listen.iev.ev, NULL))
371 d93ecf7d 2022-12-14 stsp fatalx("event add");
372 d93ecf7d 2022-12-14 stsp evtimer_set(&gotd_listen.pause.ev, gotd_accept_paused, NULL);
373 d93ecf7d 2022-12-14 stsp
374 d93ecf7d 2022-12-14 stsp event_dispatch();
375 d93ecf7d 2022-12-14 stsp
376 d93ecf7d 2022-12-14 stsp listen_shutdown();
377 d93ecf7d 2022-12-14 stsp }
378 d93ecf7d 2022-12-14 stsp
379 d93ecf7d 2022-12-14 stsp static void
380 d93ecf7d 2022-12-14 stsp listen_shutdown(void)
381 d93ecf7d 2022-12-14 stsp {
382 d93ecf7d 2022-12-14 stsp log_debug("%s: shutting down", gotd_listen.title);
383 d93ecf7d 2022-12-14 stsp
384 d93ecf7d 2022-12-14 stsp if (gotd_listen.fd != -1)
385 d93ecf7d 2022-12-14 stsp close(gotd_listen.fd);
386 d93ecf7d 2022-12-14 stsp
387 d93ecf7d 2022-12-14 stsp exit(0);
388 d93ecf7d 2022-12-14 stsp }