blob: cf5a2de8a5cbd12f6a473fddbcd77e54fe99f846 [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
35struct client {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080036 struct socket_handler *sh;
37 struct poller *poller;
38 struct ringbuffer_consumer *rbc;
39 int fd;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080040};
41
42struct socket_handler {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080043 struct handler handler;
44 struct console *console;
45 struct poller *poller;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080046 int sd;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080047
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080048 struct client **clients;
49 int n_clients;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080050};
51
52static struct socket_handler *to_socket_handler(struct handler *handler)
53{
54 return container_of(handler, struct socket_handler, handler);
55}
56
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080057static void client_close(struct client *client)
Jeremy Kerr2bd05182016-03-10 16:59:43 +080058{
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080059 struct socket_handler *sh = client->sh;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080060 int idx;
61
62 close(client->fd);
63 if (client->poller)
Jeremy Kerr55c97122017-02-07 17:06:46 +080064 console_poller_unregister(sh->console, client->poller);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080065
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080066 if (client->rbc)
67 ringbuffer_consumer_unregister(client->rbc);
68
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080069 for (idx = 0; idx < sh->n_clients; idx++)
70 if (sh->clients[idx] == client)
71 break;
72
73 assert(idx < sh->n_clients);
74
75 free(client);
76 client = NULL;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080077
78 sh->n_clients--;
79 memmove(&sh->clients[idx], &sh->clients[idx+1],
80 sizeof(*sh->clients) * (sh->n_clients - idx));
Joel Stanleyfbff1c62016-03-17 20:32:24 +103081 sh->clients = realloc(sh->clients,
82 sizeof(*sh->clients) * sh->n_clients);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080083}
84
Jeremy Kerr848fc872017-01-17 13:50:05 +080085static ssize_t send_all(int fd, void *buf, size_t len, bool block)
86{
87 int rc, flags;
88 size_t pos;
89
90 flags = MSG_NOSIGNAL;
91 if (!block)
92 flags |= MSG_DONTWAIT;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080093
94 for (pos = 0; pos < len; pos += rc) {
Jeremy Kerr848fc872017-01-17 13:50:05 +080095 rc = send(fd, buf + pos, len - pos, flags);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080096 if (rc < 0) {
Jeremy Kerr848fc872017-01-17 13:50:05 +080097 if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080098 break;
99
100 if (errno == EINTR)
101 continue;
102
103 return -1;
104 }
105 if (rc == 0)
106 return -1;
107 }
108
109 return pos;
110}
111
Jeremy Kerr848fc872017-01-17 13:50:05 +0800112/* Drain the queue to the socket and update the queue buffer. If force_len is
113 * set, send at least that many bytes from the queue, possibly while blocking
114 */
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800115static int client_drain_queue(struct client *client, size_t force_len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800116{
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800117 uint8_t *buf;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800118 ssize_t wlen;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800119 size_t len, total_len;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800120 bool block;
121
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800122 total_len = 0;
123 wlen = 0;
124 block = !!force_len;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800125
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800126 for (;;) {
127 len = ringbuffer_dequeue_peek(client->rbc, total_len, &buf);
128 if (!len)
129 break;
130
131 wlen = send_all(client->fd, buf, len, block);
132 if (wlen <= 0)
133 break;
134
135 total_len += wlen;
136
137 if (force_len && total_len >= force_len)
138 break;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800139 }
140
Jeremy Kerr848fc872017-01-17 13:50:05 +0800141 if (wlen < 0)
142 return -1;
143
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800144 if (force_len && total_len < force_len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800145 return -1;
146
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800147 ringbuffer_dequeue_commit(client->rbc, total_len);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800148 return 0;
149}
150
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800151static enum ringbuffer_poll_ret client_ringbuffer_poll(void *arg,
152 size_t force_len)
153{
154 struct client *client = arg;
155 int rc;
156
157 rc = client_drain_queue(client, force_len);
158 if (rc) {
159 client->rbc = NULL;
160 client_close(client);
161 return RINGBUFFER_POLL_REMOVE;
162 }
163
164 return RINGBUFFER_POLL_OK;
165}
166
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800167static enum poller_ret client_poll(struct handler *handler,
168 int events, void *data)
169{
170 struct socket_handler *sh = to_socket_handler(handler);
171 struct client *client = data;
172 uint8_t buf[4096];
173 int rc;
174
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800175 if (events & POLLIN) {
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800176 rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800177 if (rc < 0) {
178 if (errno == EAGAIN || errno == EWOULDBLOCK)
179 return POLLER_OK;
180 else
181 goto err_close;
182 }
183 if (rc == 0)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800184 goto err_close;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800185
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800186 console_data_out(sh->console, buf, rc);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800187 }
188
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800189 if (events & POLLOUT) {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800190 rc = client_drain_queue(client, 0);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800191 if (rc)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800192 goto err_close;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800193 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800194
195 return POLLER_OK;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800196
197err_close:
198 client->poller = NULL;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800199 client_close(client);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800200 return POLLER_REMOVE;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800201}
202
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800203static enum poller_ret socket_poll(struct handler *handler,
204 int events, void __attribute__((unused)) *data)
205{
206 struct socket_handler *sh = to_socket_handler(handler);
207 struct client *client;
208 int fd, n;
209
210 if (!(events & POLLIN))
211 return POLLER_OK;
212
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800213 fd = accept(sh->sd, NULL, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800214 if (fd < 0)
215 return POLLER_OK;
216
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800217 client = malloc(sizeof(*client));
218 memset(client, 0, sizeof(*client));
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800219
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800220 client->sh = sh;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800221 client->fd = fd;
Jeremy Kerr55c97122017-02-07 17:06:46 +0800222 client->poller = console_poller_register(sh->console, handler,
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800223 client_poll, client->fd, POLLIN, client);
Jeremy Kerrf733c852017-02-07 18:40:10 +0800224 client->rbc = console_ringbuffer_consumer_register(sh->console,
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800225 client_ringbuffer_poll, client);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800226
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800227 n = sh->n_clients++;
228 sh->clients = realloc(sh->clients,
229 sizeof(*sh->clients) * sh->n_clients);
230 sh->clients[n] = client;
231
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800232 return POLLER_OK;
233
234}
235
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800236static int socket_init(struct handler *handler, struct console *console,
237 struct config *config __attribute__((unused)))
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800238{
239 struct socket_handler *sh = to_socket_handler(handler);
240 struct sockaddr_un addr;
241 int rc;
242
243 sh->console = console;
244 sh->clients = NULL;
245 sh->n_clients = 0;
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800246
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800247 sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
248 if(sh->sd < 0) {
249 warn("Can't create socket");
250 return -1;
251 }
252
253 memset(&addr, 0, sizeof(addr));
254 addr.sun_family = AF_UNIX;
Jeremy Kerr0cff6522016-03-18 09:57:01 +0800255 memcpy(&addr.sun_path, &console_socket_path, console_socket_path_len);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800256
257 rc = bind(sh->sd, (struct sockaddr *)&addr, sizeof(addr));
258 if (rc) {
259 warn("Can't bind to socket path %s",
260 console_socket_path_readable);
261 return -1;
262 }
263
264 rc = listen(sh->sd, 1);
265 if (rc) {
266 warn("Can't listen for incoming connections");
267 return -1;
268 }
269
Jeremy Kerr55c97122017-02-07 17:06:46 +0800270 sh->poller = console_poller_register(console, handler, socket_poll,
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800271 sh->sd, POLLIN, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800272
273 return 0;
274}
275
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800276static void socket_fini(struct handler *handler)
277{
278 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800279
Jeremy Kerrabd8e252017-01-19 15:42:48 +0800280 while (sh->n_clients)
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800281 client_close(sh->clients[0]);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800282
283 if (sh->poller)
Jeremy Kerr55c97122017-02-07 17:06:46 +0800284 console_poller_unregister(sh->console, sh->poller);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800285
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800286 close(sh->sd);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800287}
288
289static struct socket_handler socket_handler = {
290 .handler = {
291 .name = "socket",
292 .init = socket_init,
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800293 .fini = socket_fini,
294 },
295};
296
Jeremy Kerr55c97122017-02-07 17:06:46 +0800297console_handler_register(&socket_handler.handler);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800298