xref: /openbmc/obmc-console/socket-handler.c (revision 55c9712de99f56f575bfa6e49f85ab2c62538984)
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 const size_t buffer_size = 128 * 1024;
36 
37 struct client {
38 	struct socket_handler		*sh;
39 	struct poller			*poller;
40 	struct ringbuffer_consumer	*rbc;
41 	int				fd;
42 };
43 
44 struct socket_handler {
45 	struct handler		handler;
46 	struct console		*console;
47 	struct poller		*poller;
48 	struct ringbuffer	*ringbuffer;
49 	int			sd;
50 
51 	struct client		**clients;
52 	int			n_clients;
53 };
54 
55 static struct socket_handler *to_socket_handler(struct handler *handler)
56 {
57 	return container_of(handler, struct socket_handler, handler);
58 }
59 
60 static void client_close(struct client *client)
61 {
62 	struct socket_handler *sh = client->sh;
63 	int idx;
64 
65 	close(client->fd);
66 	if (client->poller)
67 		console_poller_unregister(sh->console, client->poller);
68 
69 	if (client->rbc)
70 		ringbuffer_consumer_unregister(client->rbc);
71 
72 	for (idx = 0; idx < sh->n_clients; idx++)
73 		if (sh->clients[idx] == client)
74 			break;
75 
76 	assert(idx < sh->n_clients);
77 
78 	free(client);
79 	client = NULL;
80 
81 	sh->n_clients--;
82 	memmove(&sh->clients[idx], &sh->clients[idx+1],
83 			sizeof(*sh->clients) * (sh->n_clients - idx));
84 	sh->clients = realloc(sh->clients,
85 			sizeof(*sh->clients) * sh->n_clients);
86 }
87 
88 static ssize_t send_all(int fd, void *buf, size_t len, bool block)
89 {
90 	int rc, flags;
91 	size_t pos;
92 
93 	flags = MSG_NOSIGNAL;
94 	if (!block)
95 		flags |= MSG_DONTWAIT;
96 
97 	for (pos = 0; pos < len; pos += rc) {
98 		rc = send(fd, buf + pos, len - pos, flags);
99 		if (rc < 0) {
100 			if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
101 				break;
102 
103 			if (errno == EINTR)
104 				continue;
105 
106 			return -1;
107 		}
108 		if (rc == 0)
109 			return -1;
110 	}
111 
112 	return pos;
113 }
114 
115 /* Drain the queue to the socket and update the queue buffer. If force_len is
116  * set, send at least that many bytes from the queue, possibly while blocking
117  */
118 static int client_drain_queue(struct client *client, size_t force_len)
119 {
120 	uint8_t *buf;
121 	ssize_t wlen;
122 	size_t len, total_len;
123 	bool block;
124 
125 	total_len = 0;
126 	wlen = 0;
127 	block = !!force_len;
128 
129 	for (;;) {
130 		len = ringbuffer_dequeue_peek(client->rbc, total_len, &buf);
131 		if (!len)
132 			break;
133 
134 		wlen = send_all(client->fd, buf, len, block);
135 		if (wlen <= 0)
136 			break;
137 
138 		total_len += wlen;
139 
140 		if (force_len && total_len >= force_len)
141 			break;
142 	}
143 
144 	if (wlen < 0)
145 		return -1;
146 
147 	if (force_len && total_len < force_len)
148 		return -1;
149 
150 	ringbuffer_dequeue_commit(client->rbc, total_len);
151 	return 0;
152 }
153 
154 static enum ringbuffer_poll_ret client_ringbuffer_poll(void *arg,
155 		size_t force_len)
156 {
157 	struct client *client = arg;
158 	int rc;
159 
160 	rc = client_drain_queue(client, force_len);
161 	if (rc) {
162 		client->rbc = NULL;
163 		client_close(client);
164 		return RINGBUFFER_POLL_REMOVE;
165 	}
166 
167 	return RINGBUFFER_POLL_OK;
168 }
169 
170 static enum poller_ret client_poll(struct handler *handler,
171 		int events, void *data)
172 {
173 	struct socket_handler *sh = to_socket_handler(handler);
174 	struct client *client = data;
175 	uint8_t buf[4096];
176 	int rc;
177 
178 	if (events & POLLIN) {
179 		rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
180 		if (rc < 0) {
181 			if (errno == EAGAIN || errno == EWOULDBLOCK)
182 				return POLLER_OK;
183 			else
184 				goto err_close;
185 		}
186 		if (rc == 0)
187 			goto err_close;
188 
189 		console_data_out(sh->console, buf, rc);
190 	}
191 
192 	if (events & POLLOUT) {
193 		rc = client_drain_queue(client, 0);
194 		if (rc)
195 			goto err_close;
196 	}
197 
198 	return POLLER_OK;
199 
200 err_close:
201 	client->poller = NULL;
202 	client_close(client);
203 	return POLLER_REMOVE;
204 }
205 
206 static enum poller_ret socket_poll(struct handler *handler,
207 		int events, void __attribute__((unused)) *data)
208 {
209 	struct socket_handler *sh = to_socket_handler(handler);
210 	struct client *client;
211 	int fd, n;
212 
213 	if (!(events & POLLIN))
214 		return POLLER_OK;
215 
216 	fd = accept(sh->sd, NULL, NULL);
217 	if (fd < 0)
218 		return POLLER_OK;
219 
220 	client = malloc(sizeof(*client));
221 	memset(client, 0, sizeof(*client));
222 
223 	client->sh = sh;
224 	client->fd = fd;
225 	client->poller = console_poller_register(sh->console, handler,
226 			client_poll, client->fd, POLLIN, client);
227 	client->rbc = ringbuffer_consumer_register(sh->ringbuffer,
228 			client_ringbuffer_poll, client);
229 
230 	n = sh->n_clients++;
231 	sh->clients = realloc(sh->clients,
232 			sizeof(*sh->clients) * sh->n_clients);
233 	sh->clients[n] = client;
234 
235 	return POLLER_OK;
236 
237 }
238 
239 static int socket_init(struct handler *handler, struct console *console,
240 		struct config *config __attribute__((unused)))
241 {
242 	struct socket_handler *sh = to_socket_handler(handler);
243 	struct sockaddr_un addr;
244 	int rc;
245 
246 	sh->console = console;
247 	sh->clients = NULL;
248 	sh->n_clients = 0;
249 
250 	sh->ringbuffer = ringbuffer_init(buffer_size);
251 	if (!sh->ringbuffer) {
252 		warn("Can't allocate backlog ring buffer");
253 		return -1;
254 	}
255 
256 	sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
257 	if(sh->sd < 0) {
258 		warn("Can't create socket");
259 		return -1;
260 	}
261 
262 	memset(&addr, 0, sizeof(addr));
263 	addr.sun_family = AF_UNIX;
264 	memcpy(&addr.sun_path, &console_socket_path, console_socket_path_len);
265 
266 	rc = bind(sh->sd, (struct sockaddr *)&addr, sizeof(addr));
267 	if (rc) {
268 		warn("Can't bind to socket path %s",
269 				console_socket_path_readable);
270 		return -1;
271 	}
272 
273 	rc = listen(sh->sd, 1);
274 	if (rc) {
275 		warn("Can't listen for incoming connections");
276 		return -1;
277 	}
278 
279 	sh->poller = console_poller_register(console, handler, socket_poll,
280 			sh->sd, POLLIN, NULL);
281 
282 	return 0;
283 }
284 
285 static int socket_data(struct handler *handler, uint8_t *buf, size_t len)
286 {
287 	struct socket_handler *sh = to_socket_handler(handler);
288 	ringbuffer_queue(sh->ringbuffer, buf, len);
289 	return 0;
290 }
291 
292 static void socket_fini(struct handler *handler)
293 {
294 	struct socket_handler *sh = to_socket_handler(handler);
295 
296 	while (sh->n_clients)
297 		client_close(sh->clients[0]);
298 
299 	if (sh->poller)
300 		console_poller_unregister(sh->console, sh->poller);
301 
302 	if (sh->ringbuffer)
303 		ringbuffer_fini(sh->ringbuffer);
304 
305 	close(sh->sd);
306 }
307 
308 static struct socket_handler socket_handler = {
309 	.handler = {
310 		.name		= "socket",
311 		.init		= socket_init,
312 		.data_in	= socket_data,
313 		.fini		= socket_fini,
314 	},
315 };
316 
317 console_handler_register(&socket_handler.handler);
318 
319