xref: /openbmc/obmc-console/socket-handler.c (revision 2834c5b149151347309948034da4d8bb86ca5fde)
1 /**
2  * Copyright © 2016 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <assert.h>
18 #include <err.h>
19 #include <errno.h>
20 #include <limits.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <termios.h>
26 #include <unistd.h>
27 #include <endian.h>
28 
29 #include <sys/socket.h>
30 #include <sys/un.h>
31 #include <systemd/sd-daemon.h>
32 
33 #include "console-server.h"
34 
35 #define SOCKET_HANDLER_PKT_SIZE 512
36 /* Set poll() timeout to 4000 uS, or 4 mS */
37 #define SOCKET_HANDLER_PKT_US_TIMEOUT 4000
38 
39 struct client {
40 	struct socket_handler *sh;
41 	struct poller *poller;
42 	struct ringbuffer_consumer *rbc;
43 	int fd;
44 	bool blocked;
45 };
46 
47 struct socket_handler {
48 	struct handler handler;
49 	struct console *console;
50 	struct poller *poller;
51 	int sd;
52 
53 	struct client **clients;
54 	int n_clients;
55 };
56 
57 static struct timeval const socket_handler_timeout = {
58 	.tv_sec = 0,
59 	.tv_usec = SOCKET_HANDLER_PKT_US_TIMEOUT
60 };
61 
62 static struct socket_handler *to_socket_handler(struct handler *handler)
63 {
64 	return container_of(handler, struct socket_handler, handler);
65 }
66 
67 static void client_close(struct client *client)
68 {
69 	struct socket_handler *sh = client->sh;
70 	int idx;
71 
72 	close(client->fd);
73 	if (client->poller) {
74 		console_poller_unregister(sh->console, client->poller);
75 	}
76 
77 	if (client->rbc) {
78 		ringbuffer_consumer_unregister(client->rbc);
79 	}
80 
81 	for (idx = 0; idx < sh->n_clients; idx++) {
82 		if (sh->clients[idx] == client) {
83 			break;
84 		}
85 	}
86 
87 	assert(idx < sh->n_clients);
88 
89 	free(client);
90 	client = NULL;
91 
92 	sh->n_clients--;
93 	/*
94 	 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
95 	 * pointer type.
96 	 */
97 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
98 	memmove(&sh->clients[idx], &sh->clients[idx + 1],
99 		sizeof(*sh->clients) * (sh->n_clients - idx));
100 	sh->clients =
101 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
102 	/* NOLINTEND(bugprone-sizeof-expression) */
103 }
104 
105 static void client_set_blocked(struct client *client, bool blocked)
106 {
107 	int events;
108 
109 	if (client->blocked == blocked) {
110 		return;
111 	}
112 
113 	client->blocked = blocked;
114 
115 	events = POLLIN;
116 	if (client->blocked) {
117 		events |= POLLOUT;
118 	}
119 
120 	console_poller_set_events(client->sh->console, client->poller, events);
121 }
122 
123 static ssize_t send_all(struct client *client, void *buf, size_t len,
124 			bool block)
125 {
126 	int fd, flags;
127 	ssize_t rc;
128 	size_t pos;
129 
130 	if (len > SSIZE_MAX) {
131 		return -EINVAL;
132 	}
133 
134 	fd = client->fd;
135 
136 	flags = MSG_NOSIGNAL;
137 	if (!block) {
138 		flags |= MSG_DONTWAIT;
139 	}
140 
141 	for (pos = 0; pos < len; pos += rc) {
142 		rc = send(fd, (char *)buf + pos, len - pos, flags);
143 		if (rc < 0) {
144 			if (!block &&
145 			    (errno == EAGAIN || errno == EWOULDBLOCK)) {
146 				client_set_blocked(client, true);
147 				break;
148 			}
149 
150 			if (errno == EINTR) {
151 				continue;
152 			}
153 
154 			return -1;
155 		}
156 		if (rc == 0) {
157 			return -1;
158 		}
159 	}
160 
161 	return (ssize_t)pos;
162 }
163 
164 /* Drain the queue to the socket and update the queue buffer. If force_len is
165  * set, send at least that many bytes from the queue, possibly while blocking
166  */
167 static int client_drain_queue(struct client *client, size_t force_len)
168 {
169 	uint8_t *buf;
170 	ssize_t wlen;
171 	size_t len, total_len;
172 	bool block;
173 
174 	total_len = 0;
175 	wlen = 0;
176 	block = !!force_len;
177 
178 	/* if we're already blocked, no need for the write */
179 	if (!block && client->blocked) {
180 		return 0;
181 	}
182 
183 	for (;;) {
184 		len = ringbuffer_dequeue_peek(client->rbc, total_len, &buf);
185 		if (!len) {
186 			break;
187 		}
188 
189 		wlen = send_all(client, buf, len, block);
190 		if (wlen <= 0) {
191 			break;
192 		}
193 
194 		total_len += wlen;
195 
196 		if (force_len && total_len >= force_len) {
197 			break;
198 		}
199 	}
200 
201 	if (wlen < 0) {
202 		return -1;
203 	}
204 
205 	if (force_len && total_len < force_len) {
206 		return -1;
207 	}
208 
209 	ringbuffer_dequeue_commit(client->rbc, total_len);
210 	return 0;
211 }
212 
213 static enum ringbuffer_poll_ret client_ringbuffer_poll(void *arg,
214 						       size_t force_len)
215 {
216 	struct client *client = arg;
217 	size_t len;
218 	int rc;
219 
220 	len = ringbuffer_len(client->rbc);
221 	if (!force_len && (len < SOCKET_HANDLER_PKT_SIZE)) {
222 		/* Do nothing until many small requests have accumulated, or
223 		 * the UART is idle for awhile (as determined by the timeout
224 		 * value supplied to the poll function call in console_server.c. */
225 		console_poller_set_timeout(client->sh->console, client->poller,
226 					   &socket_handler_timeout);
227 		return RINGBUFFER_POLL_OK;
228 	}
229 
230 	rc = client_drain_queue(client, force_len);
231 	if (rc) {
232 		client->rbc = NULL;
233 		client_close(client);
234 		return RINGBUFFER_POLL_REMOVE;
235 	}
236 
237 	return RINGBUFFER_POLL_OK;
238 }
239 
240 static enum poller_ret
241 client_timeout(struct handler *handler __attribute__((unused)), void *data)
242 {
243 	struct client *client = data;
244 	int rc = 0;
245 
246 	if (client->blocked) {
247 		/* nothing to do here, we'll call client_drain_queue when
248 		 * we become unblocked */
249 		return POLLER_OK;
250 	}
251 
252 	rc = client_drain_queue(client, 0);
253 	if (rc) {
254 		client_close(client);
255 		return POLLER_REMOVE;
256 	}
257 
258 	return POLLER_OK;
259 }
260 
261 static enum poller_ret client_poll(struct handler *handler, int events,
262 				   void *data)
263 {
264 	struct socket_handler *sh = to_socket_handler(handler);
265 	struct client *client = data;
266 	uint8_t buf[4096];
267 	ssize_t rc;
268 
269 	if (events & POLLIN) {
270 		rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
271 		if (rc < 0) {
272 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
273 				return POLLER_OK;
274 			} else {
275 				goto err_close;
276 			}
277 		}
278 		if (rc == 0) {
279 			goto err_close;
280 		}
281 
282 		console_data_out(sh->console, buf, rc);
283 	}
284 
285 	if (events & POLLOUT) {
286 		client_set_blocked(client, false);
287 		rc = client_drain_queue(client, 0);
288 		if (rc) {
289 			goto err_close;
290 		}
291 	}
292 
293 	return POLLER_OK;
294 
295 err_close:
296 	client->poller = NULL;
297 	client_close(client);
298 	return POLLER_REMOVE;
299 }
300 
301 static enum poller_ret socket_poll(struct handler *handler, int events,
302 				   void __attribute__((unused)) * data)
303 {
304 	struct socket_handler *sh = to_socket_handler(handler);
305 	struct client *client;
306 	int fd, n;
307 
308 	if (!(events & POLLIN)) {
309 		return POLLER_OK;
310 	}
311 
312 	fd = accept(sh->sd, NULL, NULL);
313 	if (fd < 0) {
314 		return POLLER_OK;
315 	}
316 
317 	client = malloc(sizeof(*client));
318 	memset(client, 0, sizeof(*client));
319 
320 	client->sh = sh;
321 	client->fd = fd;
322 	client->poller = console_poller_register(sh->console, handler,
323 						 client_poll, client_timeout,
324 						 client->fd, POLLIN, client);
325 	client->rbc = console_ringbuffer_consumer_register(
326 		sh->console, client_ringbuffer_poll, client);
327 
328 	n = sh->n_clients++;
329 	/*
330 	 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
331 	 * pointer type.
332 	 */
333 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
334 	sh->clients =
335 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
336 	/* NOLINTEND(bugprone-sizeof-expression) */
337 	sh->clients[n] = client;
338 
339 	return POLLER_OK;
340 }
341 
342 static int socket_init(struct handler *handler, struct console *console,
343 		       struct config *config)
344 {
345 	struct socket_handler *sh = to_socket_handler(handler);
346 	struct sockaddr_un addr;
347 	size_t addrlen;
348 	ssize_t len;
349 	int rc;
350 
351 	sh->console = console;
352 	sh->clients = NULL;
353 	sh->n_clients = 0;
354 
355 	memset(&addr, 0, sizeof(addr));
356 	addr.sun_family = AF_UNIX;
357 	len = console_socket_path(&addr, config_get_value(config, "socket-id"));
358 	if (len < 0) {
359 		if (errno) {
360 			warn("Failed to configure socket: %s", strerror(errno));
361 		} else {
362 			warn("Socket name length exceeds buffer limits");
363 		}
364 		return -1;
365 	}
366 
367 	/* Try to take a socket from systemd first */
368 	if (sd_listen_fds(0) == 1 &&
369 	    sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1,
370 			      addr.sun_path, len) > 0) {
371 		sh->sd = SD_LISTEN_FDS_START;
372 	} else {
373 		sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
374 		if (sh->sd < 0) {
375 			warn("Can't create socket");
376 			return -1;
377 		}
378 
379 		addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
380 
381 		rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
382 		if (rc) {
383 			socket_path_t name;
384 			console_socket_path_readable(&addr, addrlen, name);
385 			warn("Can't bind to socket path %s (terminated at first null)",
386 			     name);
387 			goto cleanup;
388 		}
389 
390 		rc = listen(sh->sd, 1);
391 		if (rc) {
392 			warn("Can't listen for incoming connections");
393 			goto cleanup;
394 		}
395 	}
396 
397 	sh->poller = console_poller_register(console, handler, socket_poll,
398 					     NULL, sh->sd, POLLIN, NULL);
399 
400 	return 0;
401 cleanup:
402 	close(sh->sd);
403 	return -1;
404 }
405 
406 static void socket_fini(struct handler *handler)
407 {
408 	struct socket_handler *sh = to_socket_handler(handler);
409 
410 	while (sh->n_clients) {
411 		client_close(sh->clients[0]);
412 	}
413 
414 	if (sh->poller) {
415 		console_poller_unregister(sh->console, sh->poller);
416 	}
417 
418 	close(sh->sd);
419 }
420 
421 static struct socket_handler socket_handler = {
422 	.handler = {
423 		.name		= "socket",
424 		.init		= socket_init,
425 		.fini		= socket_fini,
426 	},
427 };
428 
429 console_handler_register(&socket_handler.handler);
430