• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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