blob: 30dd339a629b6666ec6458fc45b4a30f689ac592 [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) {
66 mTimedOut = true;
67 break;
68 }
69
70 int count = poll(&pfds, 1, remainingTime);
71 if (count == 0) {
72 mTimedOut = true;
73 break;
74 } else if (count < 0) {
Yi Jin0eb22342017-11-06 17:17:27 -080075 if (DEBUG) ALOGD("poll failed: %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080076 return -errno;
77 } else {
78 if ((pfds.revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -080079 if (DEBUG) ALOGD("return event has error %s", strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080080 return errno != 0 ? -errno : UNKNOWN_ERROR;
81 } else {
Yi Jinc23fad22017-09-15 17:24:59 -070082 ssize_t amt = ::read(fd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Joe Onorato1754d742016-11-21 17:51:35 -080083 if (amt < 0) {
84 if (errno == EAGAIN || errno == EWOULDBLOCK) {
85 continue;
86 } else {
Yi Jin0eb22342017-11-06 17:17:27 -080087 if (DEBUG) ALOGD("Fail to read %d: %s", fd, strerror(errno));
Joe Onorato1754d742016-11-21 17:51:35 -080088 return -errno;
89 }
90 } else if (amt == 0) {
91 break;
92 }
Yi Jinc23fad22017-09-15 17:24:59 -070093 mBuffer.wp()->move(amt);
Joe Onorato1754d742016-11-21 17:51:35 -080094 }
95 }
96 }
Joe Onorato1754d742016-11-21 17:51:35 -080097 mFinishTime = uptimeMillis();
98 return NO_ERROR;
99}
100
Yi Jin0a3406f2017-06-22 19:23:11 -0700101status_t
Yi Jin0eb22342017-11-06 17:17:27 -0800102FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeoutMs, const bool isSysfs)
Yi Jin0a3406f2017-06-22 19:23:11 -0700103{
104 struct pollfd pfds[] = {
105 { .fd = fd, .events = POLLIN },
106 { .fd = toFd, .events = POLLOUT },
107 { .fd = fromFd, .events = POLLIN },
108 };
109
110 mStartTime = uptimeMillis();
111
112 // mark all fds non blocking
113 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
114 fcntl(toFd, F_SETFL, fcntl(toFd, F_GETFL, 0) | O_NONBLOCK);
115 fcntl(fromFd, F_SETFL, fcntl(fromFd, F_GETFL, 0) | O_NONBLOCK);
116
117 // A circular buffer holds data read from fd and writes to parsing process
118 uint8_t cirBuf[BUFFER_SIZE];
119 size_t cirSize = 0;
120 int rpos = 0, wpos = 0;
121
122 // This is the buffer used to store processed data
Yi Jin0a3406f2017-06-22 19:23:11 -0700123 while (true) {
Yi Jinc23fad22017-09-15 17:24:59 -0700124 if (mBuffer.size() >= MAX_BUFFER_COUNT * BUFFER_SIZE) {
125 mTruncated = true;
126 break;
Yi Jin0a3406f2017-06-22 19:23:11 -0700127 }
Yi Jinc23fad22017-09-15 17:24:59 -0700128 if (mBuffer.writeBuffer() == NULL) return NO_MEMORY;
Yi Jin0a3406f2017-06-22 19:23:11 -0700129
130 int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
131 if (remainingTime <= 0) {
132 mTimedOut = true;
133 break;
134 }
135
136 // wait for any pfds to be ready to perform IO
137 int count = poll(pfds, 3, remainingTime);
138 if (count == 0) {
139 mTimedOut = true;
140 break;
141 } else if (count < 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800142 if (DEBUG) ALOGD("Fail to poll: %s", strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700143 return -errno;
144 }
145
146 // make sure no errors occur on any fds
147 for (int i = 0; i < 3; ++i) {
148 if ((pfds[i].revents & POLLERR) != 0) {
Yi Jin0eb22342017-11-06 17:17:27 -0800149 if (i == 0 && isSysfs) {
150 if (DEBUG) ALOGD("fd %d is sysfs, ignore its POLLERR return value", fd);
151 continue;
152 }
153 if (DEBUG) ALOGD("fd[%d]=%d returns error events: %s", i, fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700154 return errno != 0 ? -errno : UNKNOWN_ERROR;
155 }
156 }
157
158 // read from fd
159 if (cirSize != BUFFER_SIZE && pfds[0].fd != -1) {
160 ssize_t amt;
161 if (rpos >= wpos) {
162 amt = ::read(fd, cirBuf + rpos, BUFFER_SIZE - rpos);
163 } else {
Yi Jin0ed9b682017-08-18 14:51:20 -0700164 amt = ::read(fd, cirBuf + rpos, wpos - rpos);
Yi Jin0a3406f2017-06-22 19:23:11 -0700165 }
166 if (amt < 0) {
167 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin0eb22342017-11-06 17:17:27 -0800168 if (DEBUG) ALOGD("Fail to read fd %d: %s", fd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700169 return -errno;
170 } // otherwise just continue
171 } else if (amt == 0) { // reach EOF so don't have to poll pfds[0].
172 ::close(pfds[0].fd);
173 pfds[0].fd = -1;
174 } else {
175 rpos += amt;
176 cirSize += amt;
177 }
178 }
179
180 // write to parsing process
181 if (cirSize > 0 && pfds[1].fd != -1) {
182 ssize_t amt;
183 if (rpos > wpos) {
184 amt = ::write(toFd, cirBuf + wpos, rpos - wpos);
185 } else {
186 amt = ::write(toFd, cirBuf + wpos, BUFFER_SIZE - wpos);
187 }
188 if (amt < 0) {
189 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin0eb22342017-11-06 17:17:27 -0800190 if (DEBUG) ALOGD("Fail to write toFd %d: %s", toFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700191 return -errno;
192 } // otherwise just continue
193 } else {
194 wpos += amt;
195 cirSize -= amt;
196 }
197 }
198
199 // if buffer is empty and fd is closed, close write fd.
200 if (cirSize == 0 && pfds[0].fd == -1 && pfds[1].fd != -1) {
201 ::close(pfds[1].fd);
202 pfds[1].fd = -1;
203 }
204
205 // circular buffer, reset rpos and wpos
206 if (rpos >= BUFFER_SIZE) {
207 rpos = 0;
208 }
209 if (wpos >= BUFFER_SIZE) {
210 wpos = 0;
211 }
212
213 // read from parsing process
Yi Jinc23fad22017-09-15 17:24:59 -0700214 ssize_t amt = ::read(fromFd, mBuffer.writeBuffer(), mBuffer.currentToWrite());
Yi Jin0a3406f2017-06-22 19:23:11 -0700215 if (amt < 0) {
216 if (!(errno == EAGAIN || errno == EWOULDBLOCK)) {
Yi Jin0eb22342017-11-06 17:17:27 -0800217 if (DEBUG) ALOGD("Fail to read fromFd %d: %s", fromFd, strerror(errno));
Yi Jin0a3406f2017-06-22 19:23:11 -0700218 return -errno;
219 } // otherwise just continue
220 } else if (amt == 0) {
221 break;
222 } else {
Yi Jinc23fad22017-09-15 17:24:59 -0700223 mBuffer.wp()->move(amt);
Yi Jin0a3406f2017-06-22 19:23:11 -0700224 }
225 }
226
227 mFinishTime = uptimeMillis();
228 return NO_ERROR;
229}
230
Joe Onorato1754d742016-11-21 17:51:35 -0800231size_t
Yi Jin99c248f2017-08-25 18:11:58 -0700232FdBuffer::size() const
Joe Onorato1754d742016-11-21 17:51:35 -0800233{
Yi Jinc23fad22017-09-15 17:24:59 -0700234 return mBuffer.size();
Joe Onorato1754d742016-11-21 17:51:35 -0800235}
236
Yi Jinc23fad22017-09-15 17:24:59 -0700237EncodedBuffer::iterator
238FdBuffer::data() const
Joe Onorato1754d742016-11-21 17:51:35 -0800239{
Yi Jinc23fad22017-09-15 17:24:59 -0700240 return mBuffer.begin();
Yi Jin0f047162017-09-05 13:44:22 -0700241}