Coverage Report

Created: 2025-06-24 06:17

/src/adhd/cras/server/main_message.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2015 The ChromiumOS Authors
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 "cras/server/main_message.h"
7
8
#include <errno.h>
9
#include <linux/limits.h>
10
#include <stdint.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <syslog.h>
14
#include <unistd.h>
15
16
#include "cras/common/check.h"
17
#include "cras_util.h"
18
#include "third_party/utlist/utlist.h"
19
20
static_assert(CRAS_MAIN_MESSAGE_MAX_LENGTH <= PIPE_BUF,
21
              "CRAS_MAIN_MESSAGE_MAX_LENGTH must not be longer than PIPE_BUF "
22
              "to ensure atomic writes");
23
24
// Callback to handle specific type of main thread message.
25
struct cras_main_msg_callback {
26
  enum CRAS_MAIN_MESSAGE_TYPE type;
27
  cras_message_callback callback;
28
  void* callback_data;
29
  struct cras_main_msg_callback *prev, *next;
30
};
31
32
static int main_msg_fds[2] = {-1, -1};
33
static struct cras_main_msg_callback* main_msg_callbacks;
34
35
int cras_main_message_add_handler(enum CRAS_MAIN_MESSAGE_TYPE type,
36
                                  cras_message_callback callback,
37
397
                                  void* callback_data) {
38
397
  struct cras_main_msg_callback* msg_cb;
39
40
397
  DL_FOREACH (main_msg_callbacks, msg_cb) {
41
393
    if (msg_cb->type == type) {
42
0
      syslog(LOG_ERR, "Main message type %u already exists", type);
43
0
      return -EEXIST;
44
0
    }
45
393
  }
46
47
397
  msg_cb = (struct cras_main_msg_callback*)calloc(1, sizeof(*msg_cb));
48
397
  msg_cb->type = type;
49
397
  msg_cb->callback = callback;
50
397
  msg_cb->callback_data = callback_data;
51
52
397
  DL_APPEND(main_msg_callbacks, msg_cb);
53
397
  return 0;
54
397
}
55
56
393
void cras_main_message_rm_handler(enum CRAS_MAIN_MESSAGE_TYPE type) {
57
393
  struct cras_main_msg_callback* cb;
58
59
786
  DL_FOREACH (main_msg_callbacks, cb) {
60
786
    if (cb->type == type) {
61
393
      DL_DELETE(main_msg_callbacks, cb);
62
393
      free(cb);
63
393
      break;
64
393
    }
65
786
  }
66
393
}
67
68
1.05k
int cras_main_message_send(struct cras_main_message* msg) {
69
1.05k
  CRAS_CHECK(msg->length <= CRAS_MAIN_MESSAGE_MAX_LENGTH && "message too long");
70
71
1.05k
  int err = write(main_msg_fds[1], msg, msg->length);
72
1.05k
  if (err < 0) {
73
1.05k
    syslog(LOG_ERR, "Failed to send main message, type %u", msg->type);
74
1.05k
    return err;
75
1.05k
  }
76
0
  return 0;
77
1.05k
}
78
79
0
static int read_main_message(int msg_fd, uint8_t* buf, size_t max_len) {
80
0
  int to_read, nread, rc;
81
0
  struct cras_main_message* msg = (struct cras_main_message*)buf;
82
83
0
  nread = read(msg_fd, buf, sizeof(msg->length));
84
0
  if (nread < 0) {
85
0
    return nread;
86
0
  }
87
0
  if (msg->length > max_len) {
88
0
    return -ENOMEM;
89
0
  }
90
91
0
  to_read = msg->length - nread;
92
0
  rc = read(msg_fd, &buf[0] + nread, to_read);
93
0
  if (rc < 0) {
94
0
    return rc;
95
0
  }
96
0
  return 0;
97
0
}
98
99
0
void handle_main_messages(void* arg, int revents) {
100
0
  uint8_t buf[CRAS_MAIN_MESSAGE_MAX_LENGTH];
101
0
  int rc;
102
0
  struct cras_main_msg_callback* main_msg_cb;
103
0
  struct cras_main_message* msg = (struct cras_main_message*)buf;
104
105
0
  rc = read_main_message(main_msg_fds[0], buf, sizeof(buf));
106
0
  if (rc < 0) {
107
0
    syslog(LOG_ERR, "Failed to read main message");
108
0
    return;
109
0
  }
110
111
0
  DL_FOREACH (main_msg_callbacks, main_msg_cb) {
112
0
    if (main_msg_cb->type == msg->type) {
113
0
      main_msg_cb->callback(msg, main_msg_cb->callback_data);
114
0
      break;
115
0
    }
116
0
  }
117
0
}
118
119
0
int cras_main_message_init() {
120
0
  int rc;
121
122
0
  rc = pipe(main_msg_fds);
123
0
  if (rc < 0) {
124
0
    syslog(LOG_ERR, "Fatal: main message init");
125
0
    exit(-ENOMEM);
126
0
  }
127
128
  // When full it's preferred to get error instead of blocked.
129
0
  cras_make_fd_nonblocking(main_msg_fds[0]);
130
0
  cras_make_fd_nonblocking(main_msg_fds[1]);
131
132
0
  return main_msg_fds[0];
133
0
}