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