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