blob: 24389c9254081e68093e92997ad56020d94e13e6 [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 +080035const size_t buffer_size = 128 * 1024;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080036
Jeremy Kerr2bd05182016-03-10 16:59:43 +080037struct client {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080038 struct socket_handler *sh;
39 struct poller *poller;
40 struct ringbuffer_consumer *rbc;
41 int fd;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080042};
43
44struct socket_handler {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080045 struct handler handler;
46 struct console *console;
47 struct poller *poller;
48 struct ringbuffer *ringbuffer;
49 int sd;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080050
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080051 struct client **clients;
52 int n_clients;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080053};
54
55static struct socket_handler *to_socket_handler(struct handler *handler)
56{
57 return container_of(handler, struct socket_handler, handler);
58}
59
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080060static void client_close(struct client *client)
Jeremy Kerr2bd05182016-03-10 16:59:43 +080061{
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080062 struct socket_handler *sh = client->sh;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080063 int idx;
64
65 close(client->fd);
66 if (client->poller)
Jeremy Kerr55c97122017-02-07 17:06:46 +080067 console_poller_unregister(sh->console, client->poller);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080068
Jeremy Kerrc9775ce2017-02-07 16:25:34 +080069 if (client->rbc)
70 ringbuffer_consumer_unregister(client->rbc);
71
Jeremy Kerrce0e68b2016-03-18 13:55:46 +080072 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;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080080
81 sh->n_clients--;
82 memmove(&sh->clients[idx], &sh->clients[idx+1],
83 sizeof(*sh->clients) * (sh->n_clients - idx));
Joel Stanleyfbff1c62016-03-17 20:32:24 +103084 sh->clients = realloc(sh->clients,
85 sizeof(*sh->clients) * sh->n_clients);
Jeremy Kerr2bd05182016-03-10 16:59:43 +080086}
87
Jeremy Kerr848fc872017-01-17 13:50:05 +080088static 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;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080096
97 for (pos = 0; pos < len; pos += rc) {
Jeremy Kerr848fc872017-01-17 13:50:05 +080098 rc = send(fd, buf + pos, len - pos, flags);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +080099 if (rc < 0) {
Jeremy Kerr848fc872017-01-17 13:50:05 +0800100 if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800101 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
Jeremy Kerr848fc872017-01-17 13:50:05 +0800115/* 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 */
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800118static int client_drain_queue(struct client *client, size_t force_len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800119{
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800120 uint8_t *buf;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800121 ssize_t wlen;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800122 size_t len, total_len;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800123 bool block;
124
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800125 total_len = 0;
126 wlen = 0;
127 block = !!force_len;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800128
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800129 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;
Jeremy Kerr848fc872017-01-17 13:50:05 +0800142 }
143
Jeremy Kerr848fc872017-01-17 13:50:05 +0800144 if (wlen < 0)
145 return -1;
146
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800147 if (force_len && total_len < force_len)
Jeremy Kerr848fc872017-01-17 13:50:05 +0800148 return -1;
149
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800150 ringbuffer_dequeue_commit(client->rbc, total_len);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800151 return 0;
152}
153
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800154static 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
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800170static 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
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800178 if (events & POLLIN) {
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800179 rc = recv(client->fd, buf, sizeof(buf), MSG_DONTWAIT);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800180 if (rc < 0) {
181 if (errno == EAGAIN || errno == EWOULDBLOCK)
182 return POLLER_OK;
183 else
184 goto err_close;
185 }
186 if (rc == 0)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800187 goto err_close;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800188
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800189 console_data_out(sh->console, buf, rc);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800190 }
191
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800192 if (events & POLLOUT) {
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800193 rc = client_drain_queue(client, 0);
Jeremy Kerr848fc872017-01-17 13:50:05 +0800194 if (rc)
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800195 goto err_close;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800196 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800197
198 return POLLER_OK;
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800199
200err_close:
201 client->poller = NULL;
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800202 client_close(client);
Jeremy Kerr4d80a5b2016-03-18 13:47:43 +0800203 return POLLER_REMOVE;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800204}
205
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800206static 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
Jeremy Kerr68a2ece2017-01-17 13:52:41 +0800216 fd = accept(sh->sd, NULL, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800217 if (fd < 0)
218 return POLLER_OK;
219
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800220 client = malloc(sizeof(*client));
221 memset(client, 0, sizeof(*client));
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800222
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800223 client->sh = sh;
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800224 client->fd = fd;
Jeremy Kerr55c97122017-02-07 17:06:46 +0800225 client->poller = console_poller_register(sh->console, handler,
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800226 client_poll, client->fd, POLLIN, client);
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800227 client->rbc = ringbuffer_consumer_register(sh->ringbuffer,
228 client_ringbuffer_poll, client);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800229
Jeremy Kerrce0e68b2016-03-18 13:55:46 +0800230 n = sh->n_clients++;
231 sh->clients = realloc(sh->clients,
232 sizeof(*sh->clients) * sh->n_clients);
233 sh->clients[n] = client;
234
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800235 return POLLER_OK;
236
237}
238
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800239static int socket_init(struct handler *handler, struct console *console,
240 struct config *config __attribute__((unused)))
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800241{
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;
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800249
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800250 sh->ringbuffer = ringbuffer_init(buffer_size);
251 if (!sh->ringbuffer) {
252 warn("Can't allocate backlog ring buffer");
Jeremy Kerr5708dfb2017-01-19 15:11:19 +0800253 return -1;
254 }
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800255
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;
Jeremy Kerr0cff6522016-03-18 09:57:01 +0800264 memcpy(&addr.sun_path, &console_socket_path, console_socket_path_len);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800265
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
Jeremy Kerr55c97122017-02-07 17:06:46 +0800279 sh->poller = console_poller_register(console, handler, socket_poll,
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800280 sh->sd, POLLIN, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800281
282 return 0;
283}
284
285static int socket_data(struct handler *handler, uint8_t *buf, size_t len)
286{
287 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800288 ringbuffer_queue(sh->ringbuffer, buf, len);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800289 return 0;
290}
291
292static void socket_fini(struct handler *handler)
293{
294 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800295
Jeremy Kerrabd8e252017-01-19 15:42:48 +0800296 while (sh->n_clients)
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800297 client_close(sh->clients[0]);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800298
299 if (sh->poller)
Jeremy Kerr55c97122017-02-07 17:06:46 +0800300 console_poller_unregister(sh->console, sh->poller);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800301
Jeremy Kerrc9775ce2017-02-07 16:25:34 +0800302 if (sh->ringbuffer)
303 ringbuffer_fini(sh->ringbuffer);
304
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800305 close(sh->sd);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800306}
307
308static 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
Jeremy Kerr55c97122017-02-07 17:06:46 +0800317console_handler_register(&socket_handler.handler);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800318