blob: db60794a72255dfd5cd2737060d00d073d094bcd [file] [log] [blame]
Joe Onorato1754d742016-11-21 17:51:35 -08001/*
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 */
Yi Jin4e843102018-02-14 15:36:18 -080016#define DEBUG false
Yi Jinb592e3b2018-02-01 15:17:04 -080017#include "Log.h"
Joe Onorato1754d742016-11-21 17:51:35 -080018
19#include "FdBuffer.h"
20
21#include <cutils/log.h>
22#include <utils/SystemClock.h>
23
24#include <fcntl.h>
25#include <poll.h>
26#include <unistd.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070027#include <wait.h>
Joe Onorato1754d742016-11-21 17:51:35 -080028
Yi Jinb592e3b2018-02-01 15:17:04 -080029const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
30const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
Joe Onorato1754d742016-11-21 17:51:35 -080031
Joe Onorato1754d742016-11-21 17:51:35 -080032FdBuffer::FdBuffer()
Yi Jinb592e3b2018-02-01 15:17:04 -080033 : mBuffer(BUFFER_SIZE), mStartTime(-1), mFinishTime(-1), mTimedOut(false), mTruncated(false) {}
Joe Onorato1754d742016-11-21 17:51:35 -080034
Yi Jinb592e3b2018-02-01 15:17:04 -080035FdBuffer::~FdBuffer() {}
Joe Onorato1754d742016-11-21 17:51:35 -080036
Yi Jinb592e3b2018-02-01 15:17:04 -080037status_t FdBuffer::read(int fd, int64_t timeout) {
38 struct pollfd pfds = {.fd = fd, .events = POLLIN};
Joe Onorato1754d742016-11-21 17:51:35 -080039 mStartTime = uptimeMillis();
40
41 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
42
Joe Onorato1754d742016-11-21 17:51:35 -080043 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -070044 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
45 mTruncated = true;
46 break;
Joe Onorato1754d742016-11-21 17:51:35 -080047 }
Yi Jinc23fad22017-09-15 17:24:59 -070048 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Joe Onorato1754d742016-11-21 17:51:35 -080049
50 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
51 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080052 VLOG("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080053 mTimedOut = true;
54 break;
55 }
56
57 int count = poll(&pfds, 1, remainingTime);
58 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080059 VLOG("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080060 mTimedOut = true;
61 break;
62 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080063 VLOG("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080064 return -errno;
65 } else {
66 if ((pfds.revents & POLLERR) != 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080067 VLOG("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080068 return errno != 0 ? -errno : UNKNOWN_ERROR;
69 } else {
Yi Jinc23fad22017-09-15 17:24:59 -070070 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Joe Onorato1754d742016-11-21 17:51:35 -080071 if (amt < 0) {
72 if (errno == EAGAIN || errno == EWOULDBLOCK) {
73 continue;
74 } else {
Yi Jinb592e3b2018-02-01 15:17:04 -080075 VLOG("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080076 return -errno;
77 }
78 } else if (amt == 0) {
79 break;
80 }
Yi Jinc23fad22017-09-15 17:24:59 -070081 mBuffer.wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080082 }
83 }
84 }
Joe Onorato1754d742016-11-21 17:51:35 -080085 mFinishTime = uptimeMillis();
86 return NO_ERROR;
87}
88
Yi Jinb592e3b2018-02-01 15:17:04 -080089status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
90 const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -070091 struct pollfd pfds[] = {
Yi Jinb592e3b2018-02-01 15:17:04 -080092 {.fd = fd, .events = POLLIN},
93 {.fd = toFd, .events = POLLOUT},
94 {.fd = fromFd, .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -070095 };
96
97 mStartTime = uptimeMillis();
98
99 // mark all fds non blocking
100 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
101 fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
102 fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
103
104 // A circular buffer holds data read from fd and writes to parsing process
105 uint8_t cirBuf[BUFFER_SIZE];
106 size_t cirSize = 0;
107 int rpos = 0, wpos = 0;
108
109 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700110 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700111 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
112 mTruncated = true;
113 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700114 }
Yi Jinc23fad22017-09-15 17:24:59 -0700115 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Yi Jin0a3406f2017-06-22 19:23:11 -0700116
117 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
118 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800119 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700120 mTimedOut = true;
121 break;
122 }
123
124 // wait for any pfds to be ready to perform IO
125 int count = poll(pfds, 3, remainingTime);
126 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800127 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700128 mTimedOut = true;
129 break;
130 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800131 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700132 return -errno;
133 }
134
135 // make sure no errors occur on any fds
136 for (int i = 0; i < 3; ++i) {
137 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800138 if (i == 0 && isSysfs) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800139 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800140 continue;
141 }
Yi Jinb592e3b2018-02-01 15:17:04 -0800142 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700143 return errno != 0 ? -errno : UNKNOWN_ERROR;
144 }
145 }
146
147 // read from fd
148 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
149 ssize_t amt;
150 if (rpos >= wpos) {
151 amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
152 } else {
Yi Jin0ed9b682017-08-18 14:51:20 -0700153 amt = ::read(fd, cirBuf + rpos, wpos - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700154 }
155 if (amt < 0) {
156 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800157 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700158 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800159 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700160 } else if (amt == 0) { // reach EOF so don't have to poll pfds[0].
161 ::close(pfds[0].fd);
162 pfds[0].fd = -1;
163 } else {
164 rpos += amt;
165 cirSize += amt;
166 }
167 }
168
169 // write to parsing process
170 if (cirSize > 0 && pfds[1].fd != -1) {
171 ssize_t amt;
172 if (rpos > wpos) {
173 amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
174 } else {
175 amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
176 }
177 if (amt < 0) {
178 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800179 VLOG("Fail to write toFd %d: %s", toFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700180 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800181 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700182 } else {
183 wpos += amt;
184 cirSize -= amt;
185 }
186 }
187
188 // if buffer is empty and fd is closed, close write fd.
189 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
190 ::close(pfds[1].fd);
191 pfds[1].fd = -1;
192 }
193
194 // circular buffer, reset rpos and wpos
195 if (rpos >= BUFFER_SIZE) {
196 rpos = 0;
197 }
198 if (wpos >= BUFFER_SIZE) {
199 wpos = 0;
200 }
201
202 // read from parsing process
Yi Jinc23fad22017-09-15 17:24:59 -0700203 ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Yi Jin0a3406f2017-06-22 19:23:11 -0700204 if (amt < 0) {
205 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800206 VLOG("Fail to read fromFd %d: %s", fromFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700207 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800208 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700209 } else if (amt == 0) {
210 break;
211 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700212 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700213 }
214 }
215
216 mFinishTime = uptimeMillis();
217 return NO_ERROR;
218}
219
Yi Jinb592e3b2018-02-01 15:17:04 -0800220size_t FdBuffer::size() const { return mBuffer.size(); }
Joe Onorato1754d742016-11-21 17:51:35 -0800221
Yi Jinb592e3b2018-02-01 15:17:04 -0800222EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }