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