blob: af439898fb89b0615a1200be438135b0ddcf95f3 [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 Kerr5708dfb2017-01-19 15:11:19 +080035#define min(a,b) ({ \
36 const typeof(a) _a = (a); \
37 const typeof(b) _b = (b); \
38 _a < _b ? _a : _b; \
39 })
40
41const size_t buffer_size = 128 * 1024;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080042
Jeremy Kerr2bd05182016-03-10 16:59:43 +080043struct client {
44 struct poller *poller;
45 int fd;
Jeremy Kerr5708dfb2017-01-19 15:11:19 +080046 size_t buf_pos;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080047};
48
49struct socket_handler {
50 struct handler handler;
51 struct console *console;
Jeremy Kerr89ea8192016-03-15 17:57:43 +080052 struct poller *poller;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080053 int sd;
54
Jeremy Kerr5708dfb2017-01-19 15:11:19 +080055 uint8_t *buf;
56 size_t buf_len;
57
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080058 struct client **clients;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080059 int n_clients;
60};
61
62static struct socket_handler *to_socket_handler(struct handler *handler)
63{
64 return container_of(handler, struct socket_handler, handler);
65}
66
67static void client_close(struct socket_handler *sh, struct client *client)
68{
69 int idx;
70
71 close(client->fd);
72 if (client->poller)
73 console_unregister_poller(sh->console, client->poller);
74
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080075 for (idx = 0; idx < sh->n_clients; idx++)
76 if (sh->clients[idx] == client)
77 break;
78
79 assert(idx < sh->n_clients);
80
81 free(client);
82 client = NULL;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080083
84 sh->n_clients--;
85 memmove(&sh->clients[idx], &sh->clients[idx+1],
86 sizeof(*sh->clients) * (sh->n_clients - idx));
Joel Stanleyfbff1c62016-03-17 20:32:24 +103087 sh->clients = realloc(sh->clients,
88 sizeof(*sh->clients) * sh->n_clients);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080089}
90
Jeremy Kerr5708dfb2017-01-19 15:11:19 +080091static size_t client_buffer_len(struct socket_handler *sh,
92 struct client *client)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080093{
Jeremy Kerr5708dfb2017-01-19 15:11:19 +080094 return sh->buf_len - client->buf_pos;
Jeremy Kerr848fc872017-01-17 13:50:05 +080095}
Jeremy Kerr243cab32017-01-17 13:54:54 +080096
Jeremy Kerr5708dfb2017-01-19 15:11:19 +080097static void *client_buffer_data(struct socket_handler *sh,
98 struct client *client)
Jeremy Kerr848fc872017-01-17 13:50:05 +080099{
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800100 return sh->buf + client->buf_pos;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800101}
102
103static ssize_t send_all(int fd, void *buf, size_t len, bool block)
104{
105 int rc, flags;
106 size_t pos;
107
108 flags = MSG_NOSIGNAL;
109 if (!block)
110 flags |= MSG_DONTWAIT;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800111
112 for (pos = 0; pos < len; pos += rc) {
Jeremy Kerr848fc872017-01-17 13:50:05 +0800113 rc = send(fd, buf + pos, len - pos, flags);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800114 if (rc < 0) {
Jeremy Kerr848fc872017-01-17 13:50:05 +0800115 if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800116 break;
117
118 if (errno == EINTR)
119 continue;
120
121 return -1;
122 }
123 if (rc == 0)
124 return -1;
125 }
126
127 return pos;
128}
129
Jeremy Kerr848fc872017-01-17 13:50:05 +0800130/* Drain the queue to the socket and update the queue buffer. If force_len is
131 * set, send at least that many bytes from the queue, possibly while blocking
132 */
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800133static int client_drain_queue(struct socket_handler *sh,
134 struct client *client, size_t force_len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800135{
136 ssize_t wlen;
137 size_t len;
138 bool block;
139
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800140 len = client_buffer_len(sh, client);
141 if (!len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800142 return 0;
143
144 block = false;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800145 if (force_len) {
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800146 assert(force_len <= len);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800147 block = true;
148 len = force_len;
149 }
150
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800151 wlen = send_all(client->fd, client_buffer_data(sh, client), len, block);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800152 if (wlen < 0)
153 return -1;
154
155 if (force_len && wlen < force_len)
156 return -1;
157
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800158 client->buf_pos += wlen;
159 assert(client->buf_pos <= sh->buf_len);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800160
161 return 0;
162}
163
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800164static enum poller_ret client_poll(struct handler *handler,
165 int events, void *data)
166{
167 struct socket_handler *sh = to_socket_handler(handler);
168 struct client *client = data;
169 uint8_t buf[4096];
170 int rc;
171
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800172 if (events & POLLIN) {
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800173 rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800174 if (rc < 0) {
175 if (errno == EAGAIN || errno == EWOULDBLOCK)
176 return POLLER_OK;
177 else
178 goto err_close;
179 }
180 if (rc == 0)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800181 goto err_close;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800182
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800183 console_data_out(sh->console, buf, rc);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800184 }
185
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800186 if (events & POLLOUT) {
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800187 rc = client_drain_queue(sh, client, 0);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800188 if (rc)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800189 goto err_close;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800190 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800191
192 return POLLER_OK;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800193
194err_close:
195 client->poller = NULL;
196 client_close(sh, client);
197 return POLLER_REMOVE;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800198}
199
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800200static enum poller_ret socket_poll(struct handler *handler,
201 int events, void __attribute__((unused)) *data)
202{
203 struct socket_handler *sh = to_socket_handler(handler);
204 struct client *client;
205 int fd, n;
206
207 if (!(events & POLLIN))
208 return POLLER_OK;
209
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800210 fd = accept(sh->sd, NULL, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800211 if (fd < 0)
212 return POLLER_OK;
213
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800214 client = malloc(sizeof(*client));
215 memset(client, 0, sizeof(*client));
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800216
217 client->fd = fd;
218 client->poller = console_register_poller(sh->console, handler,
219 client_poll, client->fd, POLLIN, client);
220
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800221 n = sh->n_clients++;
222 sh->clients = realloc(sh->clients,
223 sizeof(*sh->clients) * sh->n_clients);
224 sh->clients[n] = client;
225
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800226 return POLLER_OK;
227
228}
229
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800230static int socket_init(struct handler *handler, struct console *console,
231 struct config *config __attribute__((unused)))
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800232{
233 struct socket_handler *sh = to_socket_handler(handler);
234 struct sockaddr_un addr;
235 int rc;
236
237 sh->console = console;
238 sh->clients = NULL;
239 sh->n_clients = 0;
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800240 sh->buf_len = 0;
241
242 sh->buf = malloc(buffer_size);
243 if (!sh->buf) {
244 warn("Can't allocate backlog buffer");
245 return -1;
246 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800247
248 sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
249 if(sh->sd < 0) {
250 warn("Can't create socket");
251 return -1;
252 }
253
254 memset(&addr, 0, sizeof(addr));
255 addr.sun_family = AF_UNIX;
Jeremy Kerr0cff6522016-03-18 09:57:01 +0800256 memcpy(&addr.sun_path, &console_socket_path, console_socket_path_len);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800257
258 rc = bind(sh->sd, (struct sockaddr *)&addr, sizeof(addr));
259 if (rc) {
260 warn("Can't bind to socket path %s",
261 console_socket_path_readable);
262 return -1;
263 }
264
265 rc = listen(sh->sd, 1);
266 if (rc) {
267 warn("Can't listen for incoming connections");
268 return -1;
269 }
270
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800271 sh->poller = console_register_poller(console, handler, socket_poll,
272 sh->sd, POLLIN, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800273
274 return 0;
275}
276
277static int socket_data(struct handler *handler, uint8_t *buf, size_t len)
278{
279 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800280 struct client *client;
281 size_t space, min_pos;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800282 int i, rc;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800283
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800284 space = buffer_size - sh->buf_len;
285 min_pos = sh->buf_len;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800286
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800287 /* Ensure there is at least len bytes available in the global buffer.
288 *
289 * The 'space' var tells us how many bytes are available at the tail of
290 * the buffer. However, if all clients have a non-zero buf_pos, then we
291 * can drop bytes from the beginning (in the memmove below). So, we
292 * account for each clients' buf_pos in the space check.
293 *
294 * If a client doesn't have sufficient space, perform a blocking write
295 * to create it. This will result in incrementing client->buf_pos to
296 * create space.
297 */
298 for (i = 0; i < sh->n_clients; i++) {
299 ssize_t client_space;
300
301 client = sh->clients[i];
302 client_space = space + client->buf_pos;
303
304 if (len > client_space) {
305 /* Blocking send enough to create len bytes of space in
306 * the global buffer. On success, this will increment
307 * client->buf_pos by the number of bytes written
308 */
309 rc = client_drain_queue(sh, client, len - client_space);
310 if (rc) {
311 client_close(sh, client);
312 i--;
313 continue;
314 }
315 }
316
317 min_pos = min(min_pos, client->buf_pos);
318 }
319
320 /* avoid pointless copying */
321 if (!sh->n_clients) {
322 sh->buf_len = 0;
323 return 0;
324 }
325
326 /* drop unneeded buffer data... */
327 sh->buf_len -= min_pos;
328 memmove(sh->buf, sh->buf + min_pos, sh->buf_len);
329
330 /* ... and add new data */
331 memcpy(sh->buf + sh->buf_len, buf, len);
332 sh->buf_len += len;
333
334 /* now that the queue contains the new data, perform non-blocking send
335 * to all clients */
336 for (i = 0; i < sh->n_clients; i++) {
337 client = sh->clients[i];
338
339 /* We've dropped data in the global buffer, so need to update
340 * clients' pos pointers to suit the new start of buffer
341 * data */
342 client->buf_pos -= min_pos;
343 assert(client->buf_pos >= 0);
344
345 rc = client_drain_queue(sh, client, 0);
346 if (rc) {
347 client_close(sh, client);
348 i--;
349 continue;
350 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800351 }
352 return 0;
353}
354
355static void socket_fini(struct handler *handler)
356{
357 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800358 int i;
359
360 for (i = 0; i < sh->n_clients; i++)
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800361 client_close(sh, sh->clients[i]);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800362
363 if (sh->poller)
364 console_unregister_poller(sh->console, sh->poller);
365
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800366 close(sh->sd);
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800367 free(sh->buf);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800368}
369
370static struct socket_handler socket_handler = {
371 .handler = {
372 .name = "socket",
373 .init = socket_init,
374 .data_in = socket_data,
375 .fini = socket_fini,
376 },
377};
378
379console_register_handler(&socket_handler.handler);
380