cras_server.c revision c3211501e365373b72e9ca423e837f07bc1f6ac5
1/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6#define _GNU_SOURCE /* Needed for Linux socket credential passing. */
7
8#include <errno.h>
9#include <stdint.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/select.h>
14#include <sys/socket.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17#include <sys/un.h>
18#include <syslog.h>
19#include <unistd.h>
20
21#include "cras_alert.h"
22#include "cras_bluetooth.h"
23#include "cras_config.h"
24#include "cras_dbus.h"
25#include "cras_dbus_control.h"
26#include "cras_iodev_list.h"
27#include "cras_messages.h"
28#include "cras_metrics.h"
29#include "cras_rclient.h"
30#include "cras_server.h"
31#include "cras_server_metrics.h"
32#include "cras_system_state.h"
33#include "cras_tm.h"
34#include "cras_udev.h"
35#include "cras_util.h"
36#include "utlist.h"
37
38/* Store a list of clients that are attached to the server.
39 * Members:
40 *    id - Unique identifier for this client.
41 *    fd - socket file descriptor used to communicate with client.
42 *    ucred - Process, user, and group ID of the client.
43 *    client - rclient to handle messages from this client.
44 */
45struct attached_client {
46	size_t id;
47	int fd;
48	struct ucred ucred;
49	struct cras_rclient *client;
50	struct attached_client *next, *prev;
51};
52
53/* Stores file descriptors to callback mappings for clients. Callback/fd/data
54 * args are registered by clients.  When fd is ready, the callback will be
55 * called on the main server thread and the callback data will be passed back to
56 * it.  This allows the use of the main server loop instead of spawning a thread
57 * to watch file descriptors.  The client can then read or write the fd.
58 * Members:
59 *    fd - The file descriptor passed to select.
60 *    callack - The funciton to call when fd is ready.
61 *    callback_data - Pointer passed to the callback.
62 */
63struct client_callback {
64	int select_fd;
65	void (*callback)(void *);
66	void *callback_data;
67	int deleted;
68	struct client_callback *prev, *next;
69};
70
71/* Local server data. */
72struct server_data {
73	struct attached_client *clients_head;
74	size_t num_clients;
75	struct client_callback *client_callbacks;
76	size_t next_client_id;
77} server_instance;
78
79/* Remove a client from the list and destroy it.  Calling rclient_destroy will
80 * also free all the streams owned by the client */
81static void remove_client(struct attached_client *client)
82{
83	close(client->fd);
84	DL_DELETE(server_instance.clients_head, client);
85	server_instance.num_clients--;
86	cras_rclient_destroy(client->client);
87	free(client);
88}
89
90/* This is called when "select" indicates that the client has written data to
91 * the socket.  Read out one message and pass it to the client message handler.
92 */
93static void handle_message_from_client(struct attached_client *client)
94{
95	uint8_t buf[CRAS_SERV_MAX_MSG_SIZE];
96	struct cras_server_message *msg;
97	int nread;
98	int fd;
99
100	msg = (struct cras_server_message *)buf;
101	nread = cras_recv_with_fd(client->fd, buf, sizeof(buf), &fd);
102	if (nread < sizeof(msg->length))
103		goto read_error;
104	if (msg->length != nread)
105		goto read_error;
106	cras_rclient_message_from_client(client->client, msg, fd);
107	return;
108
109read_error:
110	if (fd != -1)
111		close(fd);
112	syslog(LOG_DEBUG, "read err, removing client %zu", client->id);
113	remove_client(client);
114}
115
116/* Discovers and fills in info about the client that can be obtained from the
117 * socket. The pid of the attaching client identifies it in logs. */
118static void fill_client_info(struct attached_client *client)
119{
120	socklen_t ucred_length = sizeof(client->ucred);
121
122	if (getsockopt(client->fd, SOL_SOCKET, SO_PEERCRED,
123		       &client->ucred, &ucred_length))
124		syslog(LOG_INFO, "Failed to get client socket info\n");
125}
126
127/* Fills the server_state with the current list of attached clients. */
128static void send_client_list_to_clients(struct server_data *serv)
129{
130	struct attached_client *c;
131	struct cras_attached_client_info *info;
132	struct cras_server_state *state;
133	unsigned i;
134
135	state = cras_system_state_update_begin();
136	if (!state)
137		return;
138
139	state->num_attached_clients =
140		min(CRAS_MAX_ATTACHED_CLIENTS, serv->num_clients);
141
142	info = state->client_info;
143	i = 0;
144	DL_FOREACH(serv->clients_head, c) {
145		info->id = c->id;
146		info->pid = c->ucred.pid;
147		info->uid = c->ucred.uid;
148		info->gid = c->ucred.gid;
149		info++;
150		if (++i == CRAS_MAX_ATTACHED_CLIENTS)
151			break;
152	}
153
154	cras_system_state_update_complete();
155}
156
157/* Handles requests from a client to attach to the server.  Create a local
158 * structure to track the client, assign it a unique id and let it attach */
159static void handle_new_connection(struct sockaddr_un *address, int fd)
160{
161	int connection_fd;
162	struct attached_client *poll_client;
163	socklen_t address_length;
164
165	poll_client = malloc(sizeof(struct attached_client));
166	if (poll_client == NULL) {
167		syslog(LOG_ERR, "Allocating poll_client");
168		return;
169	}
170
171	memset(&address_length, 0, sizeof(address_length));
172	connection_fd = accept(fd, (struct sockaddr *) address,
173			       &address_length);
174	if (connection_fd < 0) {
175		syslog(LOG_ERR, "connecting");
176		free(poll_client);
177		return;
178	}
179
180	/* find next available client id */
181	while (1) {
182		struct attached_client *out;
183		DL_SEARCH_SCALAR(server_instance.clients_head, out, id,
184				 server_instance.next_client_id);
185		poll_client->id = server_instance.next_client_id;
186		server_instance.next_client_id++;
187		if (out == NULL)
188			break;
189	}
190
191	/* When full, getting an error is preferable to blocking. */
192	cras_make_fd_nonblocking(connection_fd);
193
194	poll_client->fd = connection_fd;
195	poll_client->next = NULL;
196	fill_client_info(poll_client);
197	poll_client->client = cras_rclient_create(connection_fd,
198						  poll_client->id);
199	if (poll_client->client == NULL) {
200		syslog(LOG_ERR, "failed to create client");
201		close(connection_fd);
202		free(poll_client);
203		return;
204	}
205
206	DL_APPEND(server_instance.clients_head, poll_client);
207	server_instance.num_clients++;
208	/* Send a current list of available inputs and outputs. */
209	cras_iodev_list_update_device_list();
210	send_client_list_to_clients(&server_instance);
211}
212
213/* Add a file descriptor to be passed to select in the main loop. This is
214 * registered with system state so that it is called when any client asks to
215 * have a callback triggered based on an fd being readable. */
216static int add_select_fd(int fd, void (*cb)(void *data),
217			 void *callback_data, void *server_data)
218{
219	struct client_callback *new_cb;
220	struct client_callback *client_cb;
221	struct server_data *serv;
222
223	serv = (struct server_data *)server_data;
224	if (serv == NULL)
225		return -EINVAL;
226
227	/* Check if fd already exists. */
228	DL_FOREACH(serv->client_callbacks, client_cb)
229		if (client_cb->select_fd == fd && !client_cb->deleted)
230			return -EEXIST;
231
232	new_cb = (struct  client_callback *)calloc(1, sizeof(*new_cb));
233	if (new_cb == NULL)
234		return -ENOMEM;
235
236	new_cb->select_fd = fd;
237	new_cb->callback = cb;
238	new_cb->callback_data = callback_data;
239	new_cb->deleted = 0;
240
241	DL_APPEND(serv->client_callbacks, new_cb);
242	return 0;
243}
244
245/* Removes a file descriptor to be passed to select in the main loop. This is
246 * registered with system state so that it is called when any client asks to
247 * remove a callback added with add_select_fd. */
248static void rm_select_fd(int fd, void *server_data)
249{
250	struct server_data *serv;
251	struct client_callback *client_cb, *temp_callback;
252
253	serv = (struct server_data *)server_data;
254	if (serv == NULL)
255		return;
256
257	DL_FOREACH_SAFE(serv->client_callbacks, client_cb, temp_callback)
258		if (client_cb->select_fd == fd)
259			client_cb->deleted = 1;
260}
261
262/* Cleans up the file descriptor list removing items deleted during the main
263 * loop iteration. */
264static void cleanup_select_fds(void *server_data)
265{
266	struct server_data *serv;
267	struct client_callback *client_cb, *temp_callback;
268
269	serv = (struct server_data *)server_data;
270	if (serv == NULL)
271		return;
272
273	DL_FOREACH_SAFE(serv->client_callbacks, client_cb, temp_callback)
274		if (client_cb->deleted) {
275			DL_DELETE(serv->client_callbacks, client_cb);
276			free(client_cb);
277		}
278}
279
280/* Checks that at least two outputs are present (one will be the "empty"
281 * default device. */
282void check_output_exists(struct cras_timer *t, void *data)
283{
284	if (cras_iodev_list_get_outputs(NULL) < 2)
285		cras_metrics_log_action(kNoCodecsFoundMetric);
286}
287
288/*
289 * Exported Interface.
290 */
291
292int cras_server_run()
293{
294	static const unsigned int OUTPUT_CHECK_MS = 5 * 1000;
295
296	DBusConnection *dbus_conn;
297	int socket_fd = -1;
298	int max_poll_fd;
299	fd_set poll_set;
300	int rc = 0;
301	const char *sockdir;
302	struct sockaddr_un addr;
303	struct attached_client *elm, *tmp;
304	struct client_callback *client_cb;
305	struct cras_tm *tm;
306	struct timespec ts;
307	int timers_active;
308
309	/* Log to syslog. */
310	openlog("cras_server", LOG_PID, LOG_USER);
311
312	/* Allow clients to register callbacks for file descriptors.
313	 * add_select_fd and rm_select_fd will add and remove file descriptors
314	 * from the list that are passed to select in the main loop below. */
315	cras_system_set_select_handler(add_select_fd, rm_select_fd,
316				       &server_instance);
317
318	cras_udev_start_sound_subsystem_monitor();
319	dbus_conn = cras_dbus_connect_system_bus();
320	if (dbus_conn) {
321		cras_bluetooth_start(dbus_conn);
322		cras_dbus_control_start(dbus_conn);
323	}
324
325	socket_fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
326	if (socket_fd < 0) {
327		syslog(LOG_ERR, "Main server socket failed.");
328		rc = socket_fd;
329		goto bail;
330	}
331
332	sockdir = cras_config_get_system_socket_file_dir();
333	if (sockdir == NULL) {
334		rc = -ENOTDIR;
335		goto bail;
336	}
337
338	memset(&addr, 0, sizeof(addr));
339	addr.sun_family = AF_UNIX;
340	snprintf(addr.sun_path, sizeof(addr.sun_path),
341		 "%s/%s", sockdir, CRAS_SOCKET_FILE);
342	unlink(addr.sun_path);
343
344	/* Linux quirk: calling fchmod before bind, sets the permissions of the
345	 * file created by bind, leaving no window for it to be modified. Start
346	 * with very restricted permissions. */
347	rc = fchmod(socket_fd, 0700);
348	if (rc < 0)
349		goto bail;
350
351	if (bind(socket_fd, (struct sockaddr *) &addr,
352		 sizeof(struct sockaddr_un)) != 0) {
353		syslog(LOG_ERR, "Bind to server socket failed.");
354		rc = errno;
355		goto bail;
356	}
357
358	/* Let other members in our group play audio through this socket. */
359	rc = chmod(addr.sun_path, 0770);
360	if (rc < 0)
361		goto bail;
362
363	if (listen(socket_fd, 5) != 0) {
364		syslog(LOG_ERR, "Listen on server socket failed.");
365		rc = errno;
366		goto bail;
367	}
368
369	tm = cras_system_state_get_tm();
370	if (!tm) {
371		syslog(LOG_ERR, "Getting timer manager.");
372		rc = -ENOMEM;
373		goto bail;
374	}
375
376	/* After a delay, make sure there is at least one real output device. */
377	cras_tm_create_timer(tm, OUTPUT_CHECK_MS, check_output_exists, 0);
378
379	/* Main server loop - client callbacks are run from this context. */
380	while (1) {
381		FD_ZERO(&poll_set);
382		FD_SET(socket_fd, &poll_set);
383		max_poll_fd = socket_fd;
384		DL_FOREACH(server_instance.clients_head, elm) {
385			if (elm->fd > max_poll_fd)
386				max_poll_fd = elm->fd;
387			FD_SET(elm->fd, &poll_set);
388		}
389		DL_FOREACH(server_instance.client_callbacks, client_cb) {
390			if (client_cb->deleted)
391				continue;
392			if (client_cb->select_fd > max_poll_fd)
393				max_poll_fd = client_cb->select_fd;
394			FD_SET(client_cb->select_fd, &poll_set);
395		}
396
397		timers_active = cras_tm_get_next_timeout(tm, &ts);
398
399		rc = pselect(max_poll_fd + 1, &poll_set, NULL, NULL,
400			     timers_active ? &ts : NULL, NULL);
401		if  (rc < 0)
402			continue;
403
404		cras_tm_call_callbacks(tm);
405
406		/* Check for new connections. */
407		if (FD_ISSET(socket_fd, &poll_set))
408			handle_new_connection(&addr, socket_fd);
409		/* Check if there are messages pending for any clients. */
410		DL_FOREACH_SAFE(server_instance.clients_head, elm, tmp)
411			if (FD_ISSET(elm->fd, &poll_set))
412				handle_message_from_client(elm);
413		/* Check any client-registered fd/callback pairs. */
414		DL_FOREACH(server_instance.client_callbacks, client_cb)
415			if (FD_ISSET(client_cb->select_fd, &poll_set) &&
416			    !client_cb->deleted)
417				client_cb->callback(client_cb->callback_data);
418
419		cleanup_select_fds(&server_instance);
420
421		if (dbus_conn)
422			cras_dbus_dispatch(dbus_conn);
423
424		cras_alert_process_all_pending_alerts();
425	}
426
427bail:
428	if (socket_fd >= 0) {
429		close(socket_fd);
430		unlink(addr.sun_path);
431	}
432	return rc;
433}
434
435void cras_server_send_to_all_clients(const struct cras_client_message *msg)
436{
437	struct attached_client *client;
438
439	DL_FOREACH(server_instance.clients_head, client)
440		cras_rclient_send_message(client->client, msg);
441}
442