• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2017 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  #include "PipeRelay.h"
18  
19  #include <sys/socket.h>
20  #include <utils/Thread.h>
21  
22  namespace android {
23  namespace lshal {
24  
25  struct PipeRelay::RelayThread : public Thread {
26      explicit RelayThread(int fd, std::ostream &os);
27  
28      bool threadLoop() override;
29  
30  private:
31      int mFd;
32      std::ostream &mOutStream;
33  
34      DISALLOW_COPY_AND_ASSIGN(RelayThread);
35  };
36  
37  ////////////////////////////////////////////////////////////////////////////////
38  
RelayThread(int fd,std::ostream & os)39  PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
40      : mFd(fd),
41        mOutStream(os) {
42  }
43  
threadLoop()44  bool PipeRelay::RelayThread::threadLoop() {
45      char buffer[1024];
46      ssize_t n = read(mFd, buffer, sizeof(buffer));
47  
48      if (n <= 0) {
49          return false;
50      }
51  
52      mOutStream.write(buffer, n);
53  
54      return true;
55  }
56  
57  ////////////////////////////////////////////////////////////////////////////////
58  
PipeRelay(std::ostream & os)59  PipeRelay::PipeRelay(std::ostream &os)
60      : mOutStream(os),
61        mInitCheck(NO_INIT) {
62      int res = socketpair(AF_UNIX, SOCK_STREAM, 0 /* protocol */, mFds);
63  
64      if (res < 0) {
65          mInitCheck = -errno;
66          return;
67      }
68  
69      mThread = new RelayThread(mFds[0], os);
70      mInitCheck = mThread->run("RelayThread");
71  }
72  
CloseFd(int * fd)73  void PipeRelay::CloseFd(int *fd) {
74      if (*fd >= 0) {
75          close(*fd);
76          *fd = -1;
77      }
78  }
79  
~PipeRelay()80  PipeRelay::~PipeRelay() {
81      if (mFds[1] >= 0) {
82          shutdown(mFds[1], SHUT_WR);
83      }
84  
85      if (mFds[0] >= 0) {
86          shutdown(mFds[0], SHUT_RD);
87      }
88  
89      if (mThread != NULL) {
90          mThread->join();
91          mThread.clear();
92      }
93  
94      CloseFd(&mFds[1]);
95      CloseFd(&mFds[0]);
96  }
97  
initCheck() const98  status_t PipeRelay::initCheck() const {
99      return mInitCheck;
100  }
101  
fd() const102  int PipeRelay::fd() const {
103      return mFds[1];
104  }
105  
106  }  // namespace lshal
107  }  // namespace android
108