1 /* Copyright 2019 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 #include <syslog.h>
7
8 #include "cras_iodev_list.h"
9 #include "cras_messages.h"
10 #include "cras_observer.h"
11 #include "cras_rclient.h"
12 #include "cras_rclient_util.h"
13 #include "cras_rstream.h"
14 #include "cras_system_state.h"
15 #include "cras_types.h"
16 #include "cras_util.h"
17 #include "stream_list.h"
18
19 /* Entry point for handling a message from the client. Called from the main
20 * server context. */
cpr_handle_message_from_client(struct cras_rclient * client,const struct cras_server_message * msg,int * fds,unsigned int num_fds)21 static int cpr_handle_message_from_client(struct cras_rclient *client,
22 const struct cras_server_message *msg,
23 int *fds, unsigned int num_fds)
24 {
25 int rc = 0;
26 assert(client && msg);
27
28 rc = rclient_validate_message_fds(msg, fds, num_fds);
29 if (rc < 0) {
30 for (int i = 0; i < (int)num_fds; i++)
31 if (fds[i] >= 0)
32 close(fds[i]);
33 return rc;
34 }
35 int fd = num_fds > 0 ? fds[0] : -1;
36
37 switch (msg->id) {
38 case CRAS_SERVER_CONNECT_STREAM: {
39 int client_shm_fd = num_fds > 1 ? fds[1] : -1;
40 struct cras_connect_message cmsg;
41 if (MSG_LEN_VALID(msg, struct cras_connect_message)) {
42 rc = rclient_handle_client_stream_connect(
43 client,
44 (const struct cras_connect_message *)msg, fd,
45 client_shm_fd);
46 } else if (!convert_connect_message_old(msg, &cmsg)) {
47 rc = rclient_handle_client_stream_connect(
48 client, &cmsg, fd, client_shm_fd);
49 } else {
50 return -EINVAL;
51 }
52 break;
53 }
54 case CRAS_SERVER_DISCONNECT_STREAM:
55 if (!MSG_LEN_VALID(msg, struct cras_disconnect_stream_message))
56 return -EINVAL;
57 rc = rclient_handle_client_stream_disconnect(
58 client,
59 (const struct cras_disconnect_stream_message *)msg);
60 break;
61 default:
62 break;
63 }
64
65 return rc;
66 }
67
68 /* Declarations of cras_rclient operators for cras_playback_rclient. */
69 static const struct cras_rclient_ops cras_playback_rclient_ops = {
70 .handle_message_from_client = cpr_handle_message_from_client,
71 .send_message_to_client = rclient_send_message_to_client,
72 .destroy = rclient_destroy,
73 };
74
75 /*
76 * Exported Functions.
77 */
78
79 /* Creates a client structure and sends a message back informing the client that
80 * the connection has succeeded. */
cras_playback_rclient_create(int fd,size_t id)81 struct cras_rclient *cras_playback_rclient_create(int fd, size_t id)
82 {
83 struct cras_rclient *client;
84 struct cras_client_connected msg;
85 int state_fd;
86
87 client = (struct cras_rclient *)calloc(1, sizeof(struct cras_rclient));
88 if (!client)
89 return NULL;
90
91 client->fd = fd;
92 client->id = id;
93
94 client->ops = &cras_playback_rclient_ops;
95 client->supported_directions =
96 cras_stream_direction_mask(CRAS_STREAM_OUTPUT);
97
98 cras_fill_client_connected(&msg, client->id);
99 state_fd = cras_sys_state_shm_fd();
100 client->ops->send_message_to_client(client, &msg.header, &state_fd, 1);
101
102 return client;
103 }
104