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