xref: /openbmc/obmc-console/socket-handler.c (revision 91b5217505272f355868d08afecf585ec7f859b2)
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 	if (client->rbc)
77 		ringbuffer_consumer_unregister(client->rbc);
78 
79 	for (idx = 0; idx < sh->n_clients; idx++)
80 		if (sh->clients[idx] == client)
81 			break;
82 
83 	assert(idx < sh->n_clients);
84 
85 	free(client);
86 	client = NULL;
87 
88 	sh->n_clients--;
89 	/*
90 	 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
91 	 * pointer type.
92 	 */
93 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
94 	memmove(&sh->clients[idx], &sh->clients[idx + 1],
95 		sizeof(*sh->clients) * (sh->n_clients - idx));
96 	sh->clients =
97 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
98 	/* NOLINTEND(bugprone-sizeof-expression) */
99 }
100 
101 static void client_set_blocked(struct client *client, bool blocked)
102 {
103 	int events;
104 
105 	if (client->blocked == blocked)
106 		return;
107 
108 	client->blocked = blocked;
109 
110 	events = POLLIN;
111 	if (client->blocked)
112 		events |= POLLOUT;
113 
114 	console_poller_set_events(client->sh->console, client->poller, events);
115 }
116 
117 static ssize_t send_all(struct client *client, void *buf, size_t len,
118 			bool block)
119 {
120 	int fd, flags;
121 	ssize_t rc;
122 	size_t pos;
123 
124 	if (len > SSIZE_MAX)
125 		return -EINVAL;
126 
127 	fd = client->fd;
128 
129 	flags = MSG_NOSIGNAL;
130 	if (!block)
131 		flags |= MSG_DONTWAIT;
132 
133 	for (pos = 0; pos < len; pos += rc) {
134 		rc = send(fd, (char *)buf + pos, len - pos, flags);
135 		if (rc < 0) {
136 			if (!block &&
137 			    (errno == EAGAIN || errno == EWOULDBLOCK)) {
138 				client_set_blocked(client, true);
139 				break;
140 			}
141 
142 			if (errno == EINTR)
143 				continue;
144 
145 			return -1;
146 		}
147 		if (rc == 0)
148 			return -1;
149 	}
150 
151 	return (ssize_t)pos;
152 }
153 
154 /* Drain the queue to the socket and update the queue buffer. If force_len is
155  * set, send at least that many bytes from the queue, possibly while blocking
156  */
157 static int client_drain_queue(struct client *client, size_t force_len)
158 {
159 	uint8_t *buf;
160 	ssize_t wlen;
161 	size_t len, total_len;
162 	bool block;
163 
164 	total_len = 0;
165 	wlen = 0;
166 	block = !!force_len;
167 
168 	/* if we're already blocked, no need for the write */
169 	if (!block && client->blocked)
170 		return 0;
171 
172 	for (;;) {
173 		len = ringbuffer_dequeue_peek(client->rbc, total_len, &buf);
174 		if (!len)
175 			break;
176 
177 		wlen = send_all(client, buf, len, block);
178 		if (wlen <= 0)
179 			break;
180 
181 		total_len += wlen;
182 
183 		if (force_len && total_len >= force_len)
184 			break;
185 	}
186 
187 	if (wlen < 0)
188 		return -1;
189 
190 	if (force_len && total_len < force_len)
191 		return -1;
192 
193 	ringbuffer_dequeue_commit(client->rbc, total_len);
194 	return 0;
195 }
196 
197 static enum ringbuffer_poll_ret client_ringbuffer_poll(void *arg,
198 						       size_t force_len)
199 {
200 	struct client *client = arg;
201 	size_t len;
202 	int rc;
203 
204 	len = ringbuffer_len(client->rbc);
205 	if (!force_len && (len < SOCKET_HANDLER_PKT_SIZE)) {
206 		/* Do nothing until many small requests have accumulated, or
207 		 * the UART is idle for awhile (as determined by the timeout
208 		 * value supplied to the poll function call in console_server.c. */
209 		console_poller_set_timeout(client->sh->console, client->poller,
210 					   &socket_handler_timeout);
211 		return RINGBUFFER_POLL_OK;
212 	}
213 
214 	rc = client_drain_queue(client, force_len);
215 	if (rc) {
216 		client->rbc = NULL;
217 		client_close(client);
218 		return RINGBUFFER_POLL_REMOVE;
219 	}
220 
221 	return RINGBUFFER_POLL_OK;
222 }
223 
224 static enum poller_ret
225 client_timeout(struct handler *handler __attribute__((unused)), void *data)
226 {
227 	struct client *client = data;
228 	int rc = 0;
229 
230 	if (client->blocked) {
231 		/* nothing to do here, we'll call client_drain_queue when
232 		 * we become unblocked */
233 		return POLLER_OK;
234 	}
235 
236 	rc = client_drain_queue(client, 0);
237 	if (rc) {
238 		client_close(client);
239 		return POLLER_REMOVE;
240 	}
241 
242 	return POLLER_OK;
243 }
244 
245 static enum poller_ret client_poll(struct handler *handler, int events,
246 				   void *data)
247 {
248 	struct socket_handler *sh = to_socket_handler(handler);
249 	struct client *client = data;
250 	uint8_t buf[4096];
251 	ssize_t rc;
252 
253 	if (events & POLLIN) {
254 		rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
255 		if (rc < 0) {
256 			if (errno == EAGAIN || errno == EWOULDBLOCK)
257 				return POLLER_OK;
258 			else
259 				goto err_close;
260 		}
261 		if (rc == 0)
262 			goto err_close;
263 
264 		console_data_out(sh->console, buf, rc);
265 	}
266 
267 	if (events & POLLOUT) {
268 		client_set_blocked(client, false);
269 		rc = client_drain_queue(client, 0);
270 		if (rc)
271 			goto err_close;
272 	}
273 
274 	return POLLER_OK;
275 
276 err_close:
277 	client->poller = NULL;
278 	client_close(client);
279 	return POLLER_REMOVE;
280 }
281 
282 static enum poller_ret socket_poll(struct handler *handler, int events,
283 				   void __attribute__((unused)) * data)
284 {
285 	struct socket_handler *sh = to_socket_handler(handler);
286 	struct client *client;
287 	int fd, n;
288 
289 	if (!(events & POLLIN))
290 		return POLLER_OK;
291 
292 	fd = accept(sh->sd, NULL, NULL);
293 	if (fd < 0)
294 		return POLLER_OK;
295 
296 	client = malloc(sizeof(*client));
297 	memset(client, 0, sizeof(*client));
298 
299 	client->sh = sh;
300 	client->fd = fd;
301 	client->poller = console_poller_register(sh->console, handler,
302 						 client_poll, client_timeout,
303 						 client->fd, POLLIN, client);
304 	client->rbc = console_ringbuffer_consumer_register(
305 		sh->console, client_ringbuffer_poll, client);
306 
307 	n = sh->n_clients++;
308 	/*
309 	 * We're managing an array of pointers to aggregates, so don't warn about sizeof() on a
310 	 * pointer type.
311 	 */
312 	/* NOLINTBEGIN(bugprone-sizeof-expression) */
313 	sh->clients =
314 		reallocarray(sh->clients, sh->n_clients, sizeof(*sh->clients));
315 	/* NOLINTEND(bugprone-sizeof-expression) */
316 	sh->clients[n] = client;
317 
318 	return POLLER_OK;
319 }
320 
321 static int socket_init(struct handler *handler, struct console *console,
322 		       struct config *config)
323 {
324 	struct socket_handler *sh = to_socket_handler(handler);
325 	struct sockaddr_un addr;
326 	size_t addrlen;
327 	ssize_t len;
328 	int rc;
329 
330 	sh->console = console;
331 	sh->clients = NULL;
332 	sh->n_clients = 0;
333 
334 	memset(&addr, 0, sizeof(addr));
335 	addr.sun_family = AF_UNIX;
336 	len = console_socket_path(&addr, config_get_value(config, "socket-id"));
337 	if (len < 0) {
338 		if (errno)
339 			warn("Failed to configure socket: %s", strerror(errno));
340 		else
341 			warn("Socket name length exceeds buffer limits");
342 		return -1;
343 	}
344 
345 	/* Try to take a socket from systemd first */
346 	if (sd_listen_fds(0) == 1 &&
347 	    sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1,
348 			      addr.sun_path, len) > 0) {
349 		sh->sd = SD_LISTEN_FDS_START;
350 	} else {
351 		sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
352 		if (sh->sd < 0) {
353 			warn("Can't create socket");
354 			return -1;
355 		}
356 
357 		addrlen = sizeof(addr) - sizeof(addr.sun_path) + len;
358 
359 		rc = bind(sh->sd, (struct sockaddr *)&addr, addrlen);
360 		if (rc) {
361 			socket_path_t name;
362 			console_socket_path_readable(&addr, addrlen, name);
363 			warn("Can't bind to socket path %s (terminated at first null)",
364 			     name);
365 			goto cleanup;
366 		}
367 
368 		rc = listen(sh->sd, 1);
369 		if (rc) {
370 			warn("Can't listen for incoming connections");
371 			goto cleanup;
372 		}
373 	}
374 
375 	sh->poller = console_poller_register(console, handler, socket_poll,
376 					     NULL, sh->sd, POLLIN, NULL);
377 
378 	return 0;
379 cleanup:
380 	close(sh->sd);
381 	return -1;
382 }
383 
384 static void socket_fini(struct handler *handler)
385 {
386 	struct socket_handler *sh = to_socket_handler(handler);
387 
388 	while (sh->n_clients)
389 		client_close(sh->clients[0]);
390 
391 	if (sh->poller)
392 		console_poller_unregister(sh->console, sh->poller);
393 
394 	close(sh->sd);
395 }
396 
397 static struct socket_handler socket_handler = {
398 	.handler = {
399 		.name		= "socket",
400 		.init		= socket_init,
401 		.fini		= socket_fini,
402 	},
403 };
404 
405 console_handler_register(&socket_handler.handler);
406