blob: 87db7f0d73d2ee2c2f15f523c188f656ce85313d [file] [log] [blame]
Jeremy Kerr9326d772016-03-17 17:15:02 +08001/**
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 */
Jeremy Kerr2bd05182016-03-10 16:59:43 +080016
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080017#define _GNU_SOURCE
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080018
19#include <assert.h>
Jeremy Kerr2bd05182016-03-10 16:59:43 +080020#include <err.h>
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080021#include <errno.h>
Jeremy Kerr2bd05182016-03-10 16:59:43 +080022#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
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080035const size_t buffer_size_max = 100 * 1024;
36
Jeremy Kerr2bd05182016-03-10 16:59:43 +080037struct client {
38 struct poller *poller;
39 int fd;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080040 uint8_t *buf;
41 size_t buf_alloc;
42 size_t buf_len;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080043};
44
45struct socket_handler {
46 struct handler handler;
47 struct console *console;
Jeremy Kerr89ea8192016-03-15 17:57:43 +080048 struct poller *poller;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080049 int sd;
50
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080051 struct client **clients;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080052 int n_clients;
53};
54
55static struct socket_handler *to_socket_handler(struct handler *handler)
56{
57 return container_of(handler, struct socket_handler, handler);
58}
59
60static void client_close(struct socket_handler *sh, struct client *client)
61{
62 int idx;
63
64 close(client->fd);
65 if (client->poller)
66 console_unregister_poller(sh->console, client->poller);
67
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080068 for (idx = 0; idx < sh->n_clients; idx++)
69 if (sh->clients[idx] == client)
70 break;
71
72 assert(idx < sh->n_clients);
73
74 free(client);
75 client = NULL;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080076
77 sh->n_clients--;
78 memmove(&sh->clients[idx], &sh->clients[idx+1],
79 sizeof(*sh->clients) * (sh->n_clients - idx));
Joel Stanleyfbff1c62016-03-17 20:32:24 +103080 sh->clients = realloc(sh->clients,
81 sizeof(*sh->clients) * sh->n_clients);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080082}
83
Jeremy Kerr848fc872017-01-17 13:50:05 +080084static size_t client_buffer_space(struct client *client)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080085{
Jeremy Kerr848fc872017-01-17 13:50:05 +080086 return buffer_size_max - client->buf_len;
87}
Jeremy Kerr243cab32017-01-17 13:54:54 +080088
Jeremy Kerr848fc872017-01-17 13:50:05 +080089static int client_queue_data(struct client *client, uint8_t *buf, size_t len)
90{
91 /* we may need to allocate space, but we know that increasing by len
92 * won't exceed buffer_size_max */
93
94 if (client->buf_len + len > client->buf_alloc) {
95 if (!client->buf_alloc)
96 client->buf_alloc = 2048;
97 client->buf_alloc *= 2;
98
99 if (client->buf_alloc > buffer_size_max)
100 client->buf_alloc = buffer_size_max;
101
102 client->buf = realloc(client->buf, client->buf_alloc);
103 }
104
105 memcpy(client->buf + client->buf_len, buf, len);
106 client->buf_len += len;
107 return 0;
108}
109
110static ssize_t send_all(int fd, void *buf, size_t len, bool block)
111{
112 int rc, flags;
113 size_t pos;
114
115 flags = MSG_NOSIGNAL;
116 if (!block)
117 flags |= MSG_DONTWAIT;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800118
119 for (pos = 0; pos < len; pos += rc) {
Jeremy Kerr848fc872017-01-17 13:50:05 +0800120 rc = send(fd, buf + pos, len - pos, flags);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800121 if (rc < 0) {
Jeremy Kerr848fc872017-01-17 13:50:05 +0800122 if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800123 break;
124
125 if (errno == EINTR)
126 continue;
127
128 return -1;
129 }
130 if (rc == 0)
131 return -1;
132 }
133
134 return pos;
135}
136
Jeremy Kerr848fc872017-01-17 13:50:05 +0800137/* Drain the queue to the socket and update the queue buffer. If force_len is
138 * set, send at least that many bytes from the queue, possibly while blocking
139 */
140static int client_drain_queue(struct client *client, size_t force_len)
141{
142 ssize_t wlen;
143 size_t len;
144 bool block;
145
146 if (!client->buf_len)
147 return 0;
148
149 block = false;
150 len = client->buf_len;
151 if (force_len) {
152 block = true;
153 len = force_len;
154 }
155
156 wlen = send_all(client->fd, client->buf, len, block);
157 if (wlen < 0)
158 return -1;
159
160 if (force_len && wlen < force_len)
161 return -1;
162
163 client->buf_len -= wlen;
164 memmove(client->buf, client->buf + wlen, client->buf_len);
165
166 return 0;
167}
168
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800169static enum poller_ret client_poll(struct handler *handler,
170 int events, void *data)
171{
172 struct socket_handler *sh = to_socket_handler(handler);
173 struct client *client = data;
174 uint8_t buf[4096];
175 int rc;
176
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800177 if (events & POLLIN) {
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800178 rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800179 if (rc < 0) {
180 if (errno == EAGAIN || errno == EWOULDBLOCK)
181 return POLLER_OK;
182 else
183 goto err_close;
184 }
185 if (rc == 0)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800186 goto err_close;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800187
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800188 console_data_out(sh->console, buf, rc);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800189 }
190
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800191 if (events & POLLOUT) {
Jeremy Kerr848fc872017-01-17 13:50:05 +0800192 rc = client_drain_queue(client, 0);
193 if (rc)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800194 goto err_close;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800195 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800196
197 return POLLER_OK;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800198
199err_close:
200 client->poller = NULL;
201 client_close(sh, client);
202 return POLLER_REMOVE;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800203}
204
Jeremy Kerr848fc872017-01-17 13:50:05 +0800205static int client_data(struct client *client, uint8_t *buf, size_t len)
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800206{
Jeremy Kerr848fc872017-01-17 13:50:05 +0800207 ssize_t wlen;
208 size_t space;
209 int rc;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800210
Jeremy Kerr848fc872017-01-17 13:50:05 +0800211 space = client_buffer_space(client);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800212
Jeremy Kerr848fc872017-01-17 13:50:05 +0800213 /* blocking send to create space in the queue for this data */
214 if (len > space) {
215 rc = client_drain_queue(client, len - space);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800216 if (rc)
217 return -1;
218 }
219
Jeremy Kerr848fc872017-01-17 13:50:05 +0800220 wlen = 0;
221
222 /* if the queue is empty, try to send without queuing */
223 if (!client->buf_len) {
224 wlen = send_all(client->fd, buf, len, false);
225 if (wlen < 0)
226 return -1;
227
228 if (wlen == len)
229 return 0;
230 }
231
232 /* queue anything unsent. this queue should always succeed, as we've
233 * created space above */
234 client_queue_data(client, buf + wlen, len - wlen);
235
236 return client_drain_queue(client, 0);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800237}
238
239static enum poller_ret socket_poll(struct handler *handler,
240 int events, void __attribute__((unused)) *data)
241{
242 struct socket_handler *sh = to_socket_handler(handler);
243 struct client *client;
244 int fd, n;
245
246 if (!(events & POLLIN))
247 return POLLER_OK;
248
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800249 fd = accept(sh->sd, NULL, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800250 if (fd < 0)
251 return POLLER_OK;
252
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800253 client = malloc(sizeof(*client));
254 memset(client, 0, sizeof(*client));
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800255
256 client->fd = fd;
257 client->poller = console_register_poller(sh->console, handler,
258 client_poll, client->fd, POLLIN, client);
259
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800260 n = sh->n_clients++;
261 sh->clients = realloc(sh->clients,
262 sizeof(*sh->clients) * sh->n_clients);
263 sh->clients[n] = client;
264
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800265 return POLLER_OK;
266
267}
268
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800269static int socket_init(struct handler *handler, struct console *console,
270 struct config *config __attribute__((unused)))
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800271{
272 struct socket_handler *sh = to_socket_handler(handler);
273 struct sockaddr_un addr;
274 int rc;
275
276 sh->console = console;
277 sh->clients = NULL;
278 sh->n_clients = 0;
279
280 sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
281 if(sh->sd < 0) {
282 warn("Can't create socket");
283 return -1;
284 }
285
286 memset(&addr, 0, sizeof(addr));
287 addr.sun_family = AF_UNIX;
Jeremy Kerr0cff6522016-03-18 09:57:01 +0800288 memcpy(&addr.sun_path, &console_socket_path, console_socket_path_len);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800289
290 rc = bind(sh->sd, (struct sockaddr *)&addr, sizeof(addr));
291 if (rc) {
292 warn("Can't bind to socket path %s",
293 console_socket_path_readable);
294 return -1;
295 }
296
297 rc = listen(sh->sd, 1);
298 if (rc) {
299 warn("Can't listen for incoming connections");
300 return -1;
301 }
302
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800303 sh->poller = console_register_poller(console, handler, socket_poll,
304 sh->sd, POLLIN, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800305
306 return 0;
307}
308
309static int socket_data(struct handler *handler, uint8_t *buf, size_t len)
310{
311 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800312 int i, rc;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800313
314 for (i = 0; i < sh->n_clients; i++) {
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800315 struct client *client = sh->clients[i];
Jeremy Kerr848fc872017-01-17 13:50:05 +0800316 rc = client_data(client, buf, len);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800317 if (!rc)
318 continue;
319
320 /* if we failed to send data, close the client. This will
321 * remove it from the clients array, so skip back to the item
322 * that has taken its place
323 */
324 client_close(sh, client);
325 i--;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800326 }
327 return 0;
328}
329
330static void socket_fini(struct handler *handler)
331{
332 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800333 int i;
334
335 for (i = 0; i < sh->n_clients; i++)
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800336 client_close(sh, sh->clients[i]);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800337
338 if (sh->poller)
339 console_unregister_poller(sh->console, sh->poller);
340
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800341 close(sh->sd);
342}
343
344static struct socket_handler socket_handler = {
345 .handler = {
346 .name = "socket",
347 .init = socket_init,
348 .data_in = socket_data,
349 .fini = socket_fini,
350 },
351};
352
353console_register_handler(&socket_handler.handler);
354