Home | History | Annotate | Download | only in proxy
      1 /*
      2  * Copyright (C) 2016 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 #include <assert.h>
     17 #include <errno.h>
     18 #include <stdbool.h>
     19 #include <stdint.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <sys/uio.h>
     23 #include <unistd.h>
     24 
     25 #include <trusty/tipc.h>
     26 
     27 #include "ipc.h"
     28 #include "log.h"
     29 
     30 #define MAX_RECONNECT_RETRY_COUNT 5
     31 #define TRUSTY_RECONNECT_TIMEOUT_SEC 5
     32 
     33 static int tipc_fd = -1;
     34 
     35 int ipc_connect(const char *device, const char *port)
     36 {
     37     int rc;
     38     uint retry_cnt = 0;
     39 
     40     assert(tipc_fd == -1);
     41 
     42     while(true) {
     43         rc = tipc_connect(device, port);
     44         if (rc >= 0)
     45             break;
     46 
     47         ALOGE("failed (%d) to connect to storage server\n", rc);
     48         if (++retry_cnt > MAX_RECONNECT_RETRY_COUNT) {
     49             ALOGE("max number of reconnect retries (%d) has been reached\n",
     50                    retry_cnt);
     51             return -1;
     52         }
     53         sleep(TRUSTY_RECONNECT_TIMEOUT_SEC);
     54     }
     55     tipc_fd = rc;
     56     return 0;
     57 }
     58 
     59 void ipc_disconnect(void)
     60 {
     61     assert(tipc_fd >=  0);
     62 
     63     tipc_close(tipc_fd);
     64     tipc_fd = -1;
     65 }
     66 
     67 ssize_t ipc_get_msg(struct storage_msg *msg, void *req_buf, size_t req_buf_len)
     68 {
     69     ssize_t rc;
     70     struct iovec iovs[2] = {{msg, sizeof(*msg)}, {req_buf, req_buf_len}};
     71 
     72     assert(tipc_fd >=  0);
     73 
     74     rc = readv(tipc_fd, iovs, 2);
     75     if (rc < 0) {
     76         ALOGE("failed to read request: %s\n", strerror(errno));
     77         return rc;
     78     }
     79 
     80    /* check for minimum size */
     81    if ((size_t)rc < sizeof(*msg)) {
     82        ALOGE("message is too short (%zu bytes received)\n", rc);
     83        return -1;
     84    }
     85 
     86    /* check for message completeness */
     87    if (msg->size != (uint32_t)rc) {
     88        ALOGE("inconsistent message size [cmd=%d] (%u != %u)\n",
     89              msg->cmd, msg->size, (uint32_t)rc);
     90        return -1;
     91    }
     92 
     93    return rc - sizeof(*msg);
     94 }
     95 
     96 int ipc_respond(struct storage_msg *msg, void *out, size_t out_size)
     97 {
     98     ssize_t rc;
     99     struct iovec iovs[2] = {{msg, sizeof(*msg)}, {out, out_size}};
    100 
    101     assert(tipc_fd >=  0);
    102 
    103     msg->cmd |= STORAGE_RESP_BIT;
    104 
    105     rc = writev(tipc_fd, iovs, out ? 2 : 1);
    106     if (rc < 0) {
    107         ALOGE("error sending response 0x%x: %s\n",
    108               msg->cmd, strerror(errno));
    109         return -1;
    110     }
    111 
    112     return 0;
    113 }
    114 
    115 
    116