blob: 883924c83d82dc6733e490b00362fb8df6f37a19 [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 Jinb592e3b2018-02-01 15:17:04 -080016#include "Log.h"
Joe Onorato1754d742016-11-21 17:51:35 -080017
18#include "FdBuffer.h"
19
20#include <cutils/log.h>
21#include <utils/SystemClock.h>
22
23#include <fcntl.h>
24#include <poll.h>
25#include <unistd.h>
Yi Jin0a3406f2017-06-22 19:23:11 -070026#include <wait.h>
Joe Onorato1754d742016-11-21 17:51:35 -080027
Yi Jinb592e3b2018-02-01 15:17:04 -080028const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
29const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
Joe Onorato1754d742016-11-21 17:51:35 -080030
Joe Onorato1754d742016-11-21 17:51:35 -080031FdBuffer::FdBuffer()
Yi Jinb592e3b2018-02-01 15:17:04 -080032 : mBuffer(BUFFER_SIZE), mStartTime(-1), mFinishTime(-1), mTimedOut(false), mTruncated(false) {}
Joe Onorato1754d742016-11-21 17:51:35 -080033
Yi Jinb592e3b2018-02-01 15:17:04 -080034FdBuffer::~FdBuffer() {}
Joe Onorato1754d742016-11-21 17:51:35 -080035
Yi Jinb592e3b2018-02-01 15:17:04 -080036status_t FdBuffer::read(int fd, int64_t timeout) {
37 struct pollfd pfds = {.fd = fd, .events = POLLIN};
Joe Onorato1754d742016-11-21 17:51:35 -080038 mStartTime = uptimeMillis();
39
40 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
41
Joe Onorato1754d742016-11-21 17:51:35 -080042 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -070043 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
44 mTruncated = true;
45 break;
Joe Onorato1754d742016-11-21 17:51:35 -080046 }
Yi Jinc23fad22017-09-15 17:24:59 -070047 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Joe Onorato1754d742016-11-21 17:51:35 -080048
49 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
50 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080051 VLOG("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080052 mTimedOut = true;
53 break;
54 }
55
56 int count = poll(&pfds, 1, remainingTime);
57 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080058 VLOG("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080059 mTimedOut = true;
60 break;
61 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080062 VLOG("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080063 return -errno;
64 } else {
65 if ((pfds.revents & POLLERR) != 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -080066 VLOG("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080067 return errno != 0 ? -errno : UNKNOWN_ERROR;
68 } else {
Yi Jinc23fad22017-09-15 17:24:59 -070069 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Joe Onorato1754d742016-11-21 17:51:35 -080070 if (amt < 0) {
71 if (errno == EAGAIN || errno == EWOULDBLOCK) {
72 continue;
73 } else {
Yi Jinb592e3b2018-02-01 15:17:04 -080074 VLOG("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080075 return -errno;
76 }
77 } else if (amt == 0) {
78 break;
79 }
Yi Jinc23fad22017-09-15 17:24:59 -070080 mBuffer.wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080081 }
82 }
83 }
Joe Onorato1754d742016-11-21 17:51:35 -080084 mFinishTime = uptimeMillis();
85 return NO_ERROR;
86}
87
Yi Jinb592e3b2018-02-01 15:17:04 -080088status_t FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs,
89 const bool isSysfs) {
Yi Jin0a3406f2017-06-22 19:23:11 -070090 struct pollfd pfds[] = {
Yi Jinb592e3b2018-02-01 15:17:04 -080091 {.fd = fd, .events = POLLIN},
92 {.fd = toFd, .events = POLLOUT},
93 {.fd = fromFd, .events = POLLIN},
Yi Jin0a3406f2017-06-22 19:23:11 -070094 };
95
96 mStartTime = uptimeMillis();
97
98 // mark all fds non blocking
99 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
100 fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
101 fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
102
103 // A circular buffer holds data read from fd and writes to parsing process
104 uint8_t cirBuf[BUFFER_SIZE];
105 size_t cirSize = 0;
106 int rpos = 0, wpos = 0;
107
108 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700109 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700110 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
111 mTruncated = true;
112 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700113 }
Yi Jinc23fad22017-09-15 17:24:59 -0700114 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Yi Jin0a3406f2017-06-22 19:23:11 -0700115
116 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
117 if (remainingTime <= 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800118 VLOG("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700119 mTimedOut = true;
120 break;
121 }
122
123 // wait for any pfds to be ready to perform IO
124 int count = poll(pfds, 3, remainingTime);
125 if (count == 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800126 VLOG("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700127 mTimedOut = true;
128 break;
129 } else if (count < 0) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800130 VLOG("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700131 return -errno;
132 }
133
134 // make sure no errors occur on any fds
135 for (int i = 0; i < 3; ++i) {
136 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800137 if (i == 0 && isSysfs) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800138 VLOG("fd %d is sysfs, ignore its POLLERR return value", fd);
Yi Jin0eb22342017-11-06 17:17:27 -0800139 continue;
140 }
Yi Jinb592e3b2018-02-01 15:17:04 -0800141 VLOG("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700142 return errno != 0 ? -errno : UNKNOWN_ERROR;
143 }
144 }
145
146 // read from fd
147 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
148 ssize_t amt;
149 if (rpos >= wpos) {
150 amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
151 } else {
Yi Jin0ed9b682017-08-18 14:51:20 -0700152 amt = ::read(fd, cirBuf + rpos, wpos - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700153 }
154 if (amt < 0) {
155 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800156 VLOG("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700157 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800158 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700159 } else if (amt == 0) { // reach EOF so don't have to poll pfds[0].
160 ::close(pfds[0].fd);
161 pfds[0].fd = -1;
162 } else {
163 rpos += amt;
164 cirSize += amt;
165 }
166 }
167
168 // write to parsing process
169 if (cirSize > 0 && pfds[1].fd != -1) {
170 ssize_t amt;
171 if (rpos > wpos) {
172 amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
173 } else {
174 amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
175 }
176 if (amt < 0) {
177 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800178 VLOG("Fail to write toFd %d: %s", toFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700179 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800180 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700181 } else {
182 wpos += amt;
183 cirSize -= amt;
184 }
185 }
186
187 // if buffer is empty and fd is closed, close write fd.
188 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
189 ::close(pfds[1].fd);
190 pfds[1].fd = -1;
191 }
192
193 // circular buffer, reset rpos and wpos
194 if (rpos >= BUFFER_SIZE) {
195 rpos = 0;
196 }
197 if (wpos >= BUFFER_SIZE) {
198 wpos = 0;
199 }
200
201 // read from parsing process
Yi Jinc23fad22017-09-15 17:24:59 -0700202 ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Yi Jin0a3406f2017-06-22 19:23:11 -0700203 if (amt < 0) {
204 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jinb592e3b2018-02-01 15:17:04 -0800205 VLOG("Fail to read fromFd %d: %s", fromFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700206 return -errno;
Yi Jinb592e3b2018-02-01 15:17:04 -0800207 } // otherwise just continue
Yi Jin0a3406f2017-06-22 19:23:11 -0700208 } else if (amt == 0) {
209 break;
210 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700211 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700212 }
213 }
214
215 mFinishTime = uptimeMillis();
216 return NO_ERROR;
217}
218
Yi Jinb592e3b2018-02-01 15:17:04 -0800219size_t FdBuffer::size() const { return mBuffer.size(); }
Joe Onorato1754d742016-11-21 17:51:35 -0800220
Yi Jinb592e3b2018-02-01 15:17:04 -0800221EncodedBuffer::iterator FdBuffer::data() const { return mBuffer.begin(); }