blob: 682797853ccb7dd12d5c0ee61813728b9b727571 [file] [log] [blame]
Jeremy Kerr2bd05182016-03-10 16:59:43 +08001
2#include <err.h>
3#include <stdbool.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <termios.h>
8#include <unistd.h>
9#include <endian.h>
10
11#include <sys/socket.h>
12#include <sys/un.h>
13
14#include "console-server.h"
15
16struct client {
17 struct poller *poller;
18 int fd;
19};
20
21struct socket_handler {
22 struct handler handler;
23 struct console *console;
Jeremy Kerr89ea8192016-03-15 17:57:43 +080024 struct poller *poller;
Jeremy Kerr2bd05182016-03-10 16:59:43 +080025 int sd;
26
27 struct client *clients;
28 int n_clients;
29};
30
31static struct socket_handler *to_socket_handler(struct handler *handler)
32{
33 return container_of(handler, struct socket_handler, handler);
34}
35
36static void client_close(struct socket_handler *sh, struct client *client)
37{
38 int idx;
39
40 close(client->fd);
41 if (client->poller)
42 console_unregister_poller(sh->console, client->poller);
43
44 idx = client - sh->clients;
45
46 sh->n_clients--;
47 memmove(&sh->clients[idx], &sh->clients[idx+1],
48 sizeof(*sh->clients) * (sh->n_clients - idx));
49 sh->clients = realloc(sh->clients, sizeof(sh->clients) * sh->n_clients);
50}
51
52static enum poller_ret client_poll(struct handler *handler,
53 int events, void *data)
54{
55 struct socket_handler *sh = to_socket_handler(handler);
56 struct client *client = data;
57 uint8_t buf[4096];
58 int rc;
59
60 if (!(events & POLLIN))
61 return POLLER_OK;
62
63 rc = read(client->fd, buf, sizeof(buf));
64 if (rc <= 0) {
65 client->poller = NULL;
66 client_close(sh, client);
67 return POLLER_REMOVE;
68 }
69
70 console_data_out(sh->console, buf, rc);
71
72 return POLLER_OK;
73}
74
75static void client_send_data(struct socket_handler *sh,
76 struct client *client, uint8_t *buf, size_t len)
77{
78 int rc;
79
80 rc = write_buf_to_fd(client->fd, buf, len);
81 if (rc)
82 client_close(sh, client);
83}
84
85static enum poller_ret socket_poll(struct handler *handler,
86 int events, void __attribute__((unused)) *data)
87{
88 struct socket_handler *sh = to_socket_handler(handler);
89 struct client *client;
90 int fd, n;
91
92 if (!(events & POLLIN))
93 return POLLER_OK;
94
95 fd = accept(sh->sd, NULL, NULL);
96 if (fd < 0)
97 return POLLER_OK;
98
99 n = sh->n_clients++;
100 sh->clients = realloc(sh->clients, sizeof(*client) * sh->n_clients);
101 client = &sh->clients[n];
102
103 client->fd = fd;
104 client->poller = console_register_poller(sh->console, handler,
105 client_poll, client->fd, POLLIN, client);
106
107 return POLLER_OK;
108
109}
110
Jeremy Kerrd47963e2016-03-16 17:29:55 +0800111static int socket_init(struct handler *handler, struct console *console,
112 struct config *config __attribute__((unused)))
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800113{
114 struct socket_handler *sh = to_socket_handler(handler);
115 struct sockaddr_un addr;
116 int rc;
117
118 sh->console = console;
119 sh->clients = NULL;
120 sh->n_clients = 0;
121
122 sh->sd = socket(AF_UNIX, SOCK_STREAM, 0);
123 if(sh->sd < 0) {
124 warn("Can't create socket");
125 return -1;
126 }
127
128 memset(&addr, 0, sizeof(addr));
129 addr.sun_family = AF_UNIX;
130 memcpy(addr.sun_path, console_socket_path, console_socket_path_len);
131
132 rc = bind(sh->sd, (struct sockaddr *)&addr, sizeof(addr));
133 if (rc) {
134 warn("Can't bind to socket path %s",
135 console_socket_path_readable);
136 return -1;
137 }
138
139 rc = listen(sh->sd, 1);
140 if (rc) {
141 warn("Can't listen for incoming connections");
142 return -1;
143 }
144
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800145 sh->poller = console_register_poller(console, handler, socket_poll,
146 sh->sd, POLLIN, NULL);
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800147
148 return 0;
149}
150
151static int socket_data(struct handler *handler, uint8_t *buf, size_t len)
152{
153 struct socket_handler *sh = to_socket_handler(handler);
154 int i;
155
156 for (i = 0; i < sh->n_clients; i++) {
157 struct client *client = &sh->clients[i];
158 client_send_data(sh, client, buf, len);
159 }
160 return 0;
161}
162
163static void socket_fini(struct handler *handler)
164{
165 struct socket_handler *sh = to_socket_handler(handler);
Jeremy Kerr89ea8192016-03-15 17:57:43 +0800166 int i;
167
168 for (i = 0; i < sh->n_clients; i++)
169 client_close(sh, &sh->clients[i]);
170
171 if (sh->poller)
172 console_unregister_poller(sh->console, sh->poller);
173
Jeremy Kerr2bd05182016-03-10 16:59:43 +0800174 close(sh->sd);
175}
176
177static struct socket_handler socket_handler = {
178 .handler = {
179 .name = "socket",
180 .init = socket_init,
181 .data_in = socket_data,
182 .fini = socket_fini,
183 },
184};
185
186console_register_handler(&socket_handler.handler);
187