• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2020 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  #define TLOG_TAG "coverage-aggregator-srv"
18  
19  #include "coverage.h"
20  
21  #include <interface/coverage/aggregator.h>
22  #include <lib/coverage/common/ipc.h>
23  #include <lib/coverage/common/cov_shm.h>
24  #include <lib/tipc/tipc_srv.h>
25  #include <stdlib.h>
26  #include <trusty_log.h>
27  #include <uapi/err.h>
28  
29  static size_t ta_idx = 0;
30  
handle_register(handle_t chan,struct coverage_aggregator_req * req,struct coverage_record * record,struct cov_shm * mailbox)31  static int handle_register(handle_t chan,
32                             struct coverage_aggregator_req* req,
33                             struct coverage_record* record,
34                             struct cov_shm* mailbox) {
35      int rc;
36      struct coverage_aggregator_resp resp;
37  
38      resp.hdr.cmd = req->hdr.cmd | COVERAGE_AGGREGATOR_CMD_RESP_BIT;
39      resp.register_args.idx = record->idx;
40      resp.register_args.mailbox_len = mailbox->len;
41  
42      rc = coverage_send(chan, &resp, sizeof(resp), &mailbox->memref);
43      if (rc != NO_ERROR) {
44          TLOGE("failed (%d) to send mailbox memref\n", rc);
45          return rc;
46      }
47  
48      record->record_len = req->register_args.record_len;
49      return NO_ERROR;
50  }
51  
handle_get_record(handle_t chan,struct coverage_aggregator_req * req,struct coverage_record * record)52  static int handle_get_record(handle_t chan,
53                               struct coverage_aggregator_req* req,
54                               struct coverage_record* record) {
55      int rc;
56      struct coverage_aggregator_resp resp;
57  
58      if (record->data.memref == INVALID_IPC_HANDLE) {
59          return ERR_NOT_READY;
60      }
61  
62      resp.hdr.cmd = req->hdr.cmd | COVERAGE_AGGREGATOR_CMD_RESP_BIT;
63      resp.get_record_args.shm_len = record->data.len;
64  
65      rc = coverage_send(chan, &resp, sizeof(resp), &record->data.memref);
66      if (rc != NO_ERROR) {
67          TLOGE("failed (%d) to send coverage record memref\n", rc);
68          return rc;
69      }
70  
71      return NO_ERROR;
72  }
73  
on_connect(const struct tipc_port * port,handle_t chan,const struct uuid * peer,void ** ctx_p)74  static int on_connect(const struct tipc_port* port,
75                        handle_t chan,
76                        const struct uuid* peer,
77                        void** ctx_p) {
78      struct coverage_record* record;
79      char uuid_str[UUID_STR_SIZE];
80      struct srv_state* state = get_srv_state(port);
81  
82      uuid_to_str(peer, uuid_str);
83      TLOGI("App with UUID: %s connected to coverage aggregator\n", uuid_str);
84  
85      record = find_coverage_record(&state->coverage_record_list, peer);
86      if (record) {
87          *ctx_p = record;
88          return NO_ERROR;
89      }
90  
91      record = calloc(1, sizeof(*record));
92      if (!record) {
93          TLOGE("failed to allocate coverage record\n");
94          return ERR_NO_MEMORY;
95      }
96  
97      record->uuid = *peer;
98      record->idx = ta_idx++;
99      list_add_tail(&state->coverage_record_list, &record->node);
100  
101      *ctx_p = record;
102      return NO_ERROR;
103  }
104  
on_message(const struct tipc_port * port,handle_t chan,void * ctx)105  static int on_message(const struct tipc_port* port, handle_t chan, void* ctx) {
106      int rc;
107      struct coverage_aggregator_req req;
108      struct coverage_record* record = (struct coverage_record*)ctx;
109      struct srv_state* state = get_srv_state(port);
110  
111      rc = coverage_recv(chan, &req, sizeof(req), NULL);
112      if (rc != NO_ERROR) {
113          TLOGE("failed (%d) to receive coverage aggregator request\n", rc);
114          return rc;
115      }
116  
117      switch (req.hdr.cmd) {
118      case COVERAGE_AGGREGATOR_CMD_REGISTER:
119          return handle_register(chan, &req, record, &state->mailbox);
120  
121      case COVERAGE_AGGREGATOR_CMD_GET_RECORD:
122          return handle_get_record(chan, &req, record);
123  
124      default:
125          TLOGE("cmd 0x%x: unknown command\n", req.hdr.cmd);
126          return ERR_CMD_UNKNOWN;
127      }
128  }
129  
130  /* lib/tipc mandates we have this function. However, there is no work to do. */
on_channel_cleanup(void * ctx)131  static void on_channel_cleanup(void* ctx) {}
132  
coverage_aggregator_init(struct srv_state * state)133  int coverage_aggregator_init(struct srv_state* state) {
134      static struct tipc_port_acl port_acl = {
135              .flags = IPC_PORT_ALLOW_TA_CONNECT,
136      };
137      static struct tipc_port port = {
138              .name = COVERAGE_AGGREGATOR_PORT,
139              .msg_max_size = MAX(sizeof(struct coverage_aggregator_req),
140                                  sizeof(struct coverage_aggregator_resp)),
141              .msg_queue_len = 1,
142              .acl = &port_acl,
143      };
144      static struct tipc_srv_ops ops = {
145              .on_connect = on_connect,
146              .on_message = on_message,
147              .on_channel_cleanup = on_channel_cleanup,
148      };
149  
150      set_srv_state(&port, state);
151  
152      return tipc_add_service(state->hset, &port, 1, MAX_NUM_APPS, &ops);
153  }
154