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