blob: 0fff4e6dc4a02577ebc0ba82b164a908f458e098 [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 */
16
17#define LOG_TAG "incidentd"
18
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 Jin0eb22342017-11-06 17:17:27 -080029const bool DEBUG = false;
Yi Jin0a3406f2017-06-22 19:23:11 -070030const ssize_t BUFFER_SIZE = 16 * 1024; // 16 KB
Joe Onorato1754d742016-11-21 17:51:35 -080031const ssize_t MAX_BUFFER_COUNT = 256; // 4 MB max
32
Joe Onorato1754d742016-11-21 17:51:35 -080033FdBuffer::FdBuffer()
Yi Jinc23fad22017-09-15 17:24:59 -070034 :mBuffer(BUFFER_SIZE),
Joe Onorato1754d742016-11-21 17:51:35 -080035 mStartTime(-1),
36 mFinishTime(-1),
Joe Onorato1754d742016-11-21 17:51:35 -080037 mTimedOut(false),
38 mTruncated(false)
39{
40}
41
42FdBuffer::~FdBuffer()
43{
Joe Onorato1754d742016-11-21 17:51:35 -080044}
45
46status_t
47FdBuffer::read(int fd, int64_t timeout)
48{
49 struct pollfd pfds = {
50 .fd = fd,
51 .events = POLLIN
52 };
53 mStartTime = uptimeMillis();
54
55 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
56
Joe Onorato1754d742016-11-21 17:51:35 -080057 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -070058 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
59 mTruncated = true;
60 break;
Joe Onorato1754d742016-11-21 17:51:35 -080061 }
Yi Jinc23fad22017-09-15 17:24:59 -070062 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Joe Onorato1754d742016-11-21 17:51:35 -080063
64 int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
65 if (remainingTime <= 0) {
Yi Jin4bab3a12018-01-10 16:50:59 -080066 if (DEBUG) ALOGD("timed out due to long read");
Joe Onorato1754d742016-11-21 17:51:35 -080067 mTimedOut = true;
68 break;
69 }
70
71 int count = poll(&pfds, 1, remainingTime);
72 if (count == 0) {
Yi Jin4bab3a12018-01-10 16:50:59 -080073 if (DEBUG) ALOGD("timed out due to block calling poll");
Joe Onorato1754d742016-11-21 17:51:35 -080074 mTimedOut = true;
75 break;
76 } else if (count < 0) {
Yi Jin0eb22342017-11-06 17:17:27 -080077 if (DEBUG) ALOGD("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080078 return -errno;
79 } else {
80 if ((pfds.revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -080081 if (DEBUG) ALOGD("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080082 return errno != 0 ? -errno : UNKNOWN_ERROR;
83 } else {
Yi Jinc23fad22017-09-15 17:24:59 -070084 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Joe Onorato1754d742016-11-21 17:51:35 -080085 if (amt < 0) {
86 if (errno == EAGAIN || errno == EWOULDBLOCK) {
87 continue;
88 } else {
Yi Jin0eb22342017-11-06 17:17:27 -080089 if (DEBUG) ALOGD("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080090 return -errno;
91 }
92 } else if (amt == 0) {
93 break;
94 }
Yi Jinc23fad22017-09-15 17:24:59 -070095 mBuffer.wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080096 }
97 }
98 }
Joe Onorato1754d742016-11-21 17:51:35 -080099 mFinishTime = uptimeMillis();
100 return NO_ERROR;
101}
102
Yi Jin0a3406f2017-06-22 19:23:11 -0700103status_t
Yi Jin0eb22342017-11-06 17:17:27 -0800104FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs)
Yi Jin0a3406f2017-06-22 19:23:11 -0700105{
106 struct pollfd pfds[] = {
107 { .fd = fd, .events = POLLIN },
108 { .fd = toFd, .events = POLLOUT },
109 { .fd = fromFd, .events = POLLIN },
110 };
111
112 mStartTime = uptimeMillis();
113
114 // mark all fds non blocking
115 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
116 fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
117 fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
118
119 // A circular buffer holds data read from fd and writes to parsing process
120 uint8_t cirBuf[BUFFER_SIZE];
121 size_t cirSize = 0;
122 int rpos = 0, wpos = 0;
123
124 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700125 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700126 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
127 mTruncated = true;
128 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700129 }
Yi Jinc23fad22017-09-15 17:24:59 -0700130 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Yi Jin0a3406f2017-06-22 19:23:11 -0700131
132 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
133 if (remainingTime <= 0) {
Yi Jin4bab3a12018-01-10 16:50:59 -0800134 if (DEBUG) ALOGD("timed out due to long read");
Yi Jin0a3406f2017-06-22 19:23:11 -0700135 mTimedOut = true;
136 break;
137 }
138
139 // wait for any pfds to be ready to perform IO
140 int count = poll(pfds, 3, remainingTime);
141 if (count == 0) {
Yi Jin4bab3a12018-01-10 16:50:59 -0800142 if (DEBUG) ALOGD("timed out due to block calling poll");
Yi Jin0a3406f2017-06-22 19:23:11 -0700143 mTimedOut = true;
144 break;
145 } else if (count < 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800146 if (DEBUG) ALOGD("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700147 return -errno;
148 }
149
150 // make sure no errors occur on any fds
151 for (int i = 0; i < 3; ++i) {
152 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800153 if (i == 0 && isSysfs) {
154 if (DEBUG) ALOGD("fd %d is sysfs, ignore its POLLERR return value", fd);
155 continue;
156 }
157 if (DEBUG) ALOGD("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700158 return errno != 0 ? -errno : UNKNOWN_ERROR;
159 }
160 }
161
162 // read from fd
163 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
164 ssize_t amt;
165 if (rpos >= wpos) {
166 amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
167 } else {
Yi Jin0ed9b682017-08-18 14:51:20 -0700168 amt = ::read(fd, cirBuf + rpos, wpos - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700169 }
170 if (amt < 0) {
171 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin0eb22342017-11-06 17:17:27 -0800172 if (DEBUG) ALOGD("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700173 return -errno;
174 } // otherwise just continue
175 } else if (amt == 0) { // reach EOF so don't have to poll pfds[0].
176 ::close(pfds[0].fd);
177 pfds[0].fd = -1;
178 } else {
179 rpos += amt;
180 cirSize += amt;
181 }
182 }
183
184 // write to parsing process
185 if (cirSize > 0 && pfds[1].fd != -1) {
186 ssize_t amt;
187 if (rpos > wpos) {
188 amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
189 } else {
190 amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
191 }
192 if (amt < 0) {
193 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin0eb22342017-11-06 17:17:27 -0800194 if (DEBUG) ALOGD("Fail to write toFd %d: %s", toFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700195 return -errno;
196 } // otherwise just continue
197 } else {
198 wpos += amt;
199 cirSize -= amt;
200 }
201 }
202
203 // if buffer is empty and fd is closed, close write fd.
204 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
205 ::close(pfds[1].fd);
206 pfds[1].fd = -1;
207 }
208
209 // circular buffer, reset rpos and wpos
210 if (rpos >= BUFFER_SIZE) {
211 rpos = 0;
212 }
213 if (wpos >= BUFFER_SIZE) {
214 wpos = 0;
215 }
216
217 // read from parsing process
Yi Jinc23fad22017-09-15 17:24:59 -0700218 ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Yi Jin0a3406f2017-06-22 19:23:11 -0700219 if (amt < 0) {
220 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin0eb22342017-11-06 17:17:27 -0800221 if (DEBUG) ALOGD("Fail to read fromFd %d: %s", fromFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700222 return -errno;
223 } // otherwise just continue
224 } else if (amt == 0) {
225 break;
226 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700227 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700228 }
229 }
230
231 mFinishTime = uptimeMillis();
232 return NO_ERROR;
233}
234
Joe Onorato1754d742016-11-21 17:51:35 -0800235size_t
Yi Jin99c248f2017-08-25 18:11:58 -0700236FdBuffer::size() const
Joe Onorato1754d742016-11-21 17:51:35 -0800237{
Yi Jinc23fad22017-09-15 17:24:59 -0700238 return mBuffer.size();
Joe Onorato1754d742016-11-21 17:51:35 -0800239}
240
Yi Jinc23fad22017-09-15 17:24:59 -0700241EncodedBuffer::iterator
242FdBuffer::data() const
Joe Onorato1754d742016-11-21 17:51:35 -0800243{
Yi Jinc23fad22017-09-15 17:24:59 -0700244 return mBuffer.begin();
Yi Jin0f047162017-09-05 13:44:22 -0700245}