1 /**
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rawfile_request.h"
17
18 #include "threads.h"
19
20 #include "hilog/log.h"
21 #include "rawfile/raw_file.h"
22 #include "rawfile/raw_file_manager.h"
23
24 #undef LOG_TAG
25 #define LOG_TAG "ss-handler"
26
27 namespace {
28
29 uint8_t buffer[1024];
30 cnd_t http_body_cnd;
31 mtx_t http_body_mtx;
32 const int BUFF_LEN = 1000;
33 const int DO_NOT_FOUND = 404;
34 const int DO_OK = 200;
35
36 // HttpBodyStream的读回调。
ReadCallback(const ArkWeb_HttpBodyStream * httpBodyStream,uint8_t * buffer,int bytesRead)37 void ReadCallback(const ArkWeb_HttpBodyStream *httpBodyStream, uint8_t *buffer, int bytesRead) {
38 OH_LOG_INFO(LOG_APP, "read http body back.");
39 bool isEof = OH_ArkWebHttpBodyStream_IsEof(httpBodyStream);
40 if (!isEof && bytesRead != 0) {
41 memset(buffer, 0, BUFF_LEN);
42 OH_ArkWebHttpBodyStream_Read(httpBodyStream, buffer, BUFF_LEN);
43 } else {
44 RawfileRequest *rawfileRequest = (RawfileRequest *)OH_ArkWebHttpBodyStream_GetUserData(httpBodyStream);
45 if (rawfileRequest) {
46 rawfileRequest->ReadRawfileDataOnWorkerThread();
47 }
48 }
49 }
50
ReadHttpBodyOnWorkerThread(void * userData)51 int ReadHttpBodyOnWorkerThread(void *userData) {
52 memset(buffer, 0, BUFF_LEN);
53 ArkWeb_HttpBodyStream *httpBodyStream = (ArkWeb_HttpBodyStream *)userData;
54 OH_ArkWebHttpBodyStream_Read(httpBodyStream, buffer, BUFF_LEN);
55
56 return 0;
57 }
58
ReadRawfileOnWorkerThread(void * userData)59 int ReadRawfileOnWorkerThread(void *userData) {
60 RawfileRequest *rawfileRequest = (RawfileRequest *)userData;
61 if (rawfileRequest) {
62 rawfileRequest->ReadRawfileDataOnWorkerThread();
63 }
64 return 0;
65 }
66
67 // ArkWeb_HttpBodyStream的初始化回调。
InitCallback(const ArkWeb_HttpBodyStream * httpBodyStream,ArkWeb_NetError result)68 void InitCallback(const ArkWeb_HttpBodyStream *httpBodyStream, ArkWeb_NetError result) {
69 OH_LOG_INFO(LOG_APP, "init http body stream done %{public}d.", result);
70 bool isChunked = OH_ArkWebHttpBodyStream_IsChunked(httpBodyStream);
71 OH_LOG_INFO(LOG_APP, "http body stream is chunked %{public}d.", isChunked);
72
73 ReadHttpBodyOnWorkerThread((void *)httpBodyStream);
74 }
75 const int blockSize = 1024 * 8;
76
77 } // namespace
78
RawfileRequest(const ArkWeb_ResourceRequest * resourceRequest,const ArkWeb_ResourceHandler * resourceHandler,const NativeResourceManager * resourceManager)79 RawfileRequest::RawfileRequest(const ArkWeb_ResourceRequest *resourceRequest,
80 const ArkWeb_ResourceHandler *resourceHandler,
81 const NativeResourceManager *resourceManager)
82 : resourceRequest_(resourceRequest), resourceHandler_(resourceHandler), resourceManager_(resourceManager) {}
83
~RawfileRequest()84 RawfileRequest::~RawfileRequest() {}
85
Start()86 void RawfileRequest::Start() {
87 OH_LOG_INFO(LOG_APP, "start a rawfile request.");
88 char *url;
89 OH_ArkWebResourceRequest_GetUrl(resourceRequest_, &url);
90
91 std::string urlStr(url);
92 reqUrl_ = urlStr;
93
94 std::size_t position = urlStr.rfind('/');
95 if (position != std::string::npos) {
96 rawfilePath_ = urlStr.substr(position + 1);
97 }
98 OH_ArkWeb_ReleaseString(url);
99 OH_ArkWeb_CreateResponse(&response_);
100 // 接口覆盖
101 OH_ArkWebResourceRequest_GetHttpBodyStream(resourceRequest(), &stream_);
102
103 if (rawfilePath_ == "Error") {
104 DidFailWithError(ARKWEB_ERR_FILE_NOT_FOUND);
105 return;
106 }
107
108 if (stream_) {
109 haveBodyStream_ = 0;
110 OH_LOG_ERROR(LOG_APP, "have http body stream");
111 OH_ArkWebHttpBodyStream_SetUserData(stream_, this);
112 isRead_ = OH_ArkWebHttpBodyStream_SetReadCallback(stream_, (ArkWeb_HttpBodyStreamReadCallback)ReadCallback);
113 isInit_ = OH_ArkWebHttpBodyStream_Init(stream_, (ArkWeb_HttpBodyStreamInitCallback)InitCallback);
114
115 } else {
116 ReadRawfileOnWorkerThread(reinterpret_cast<void *>(this));
117 }
118 }
119
120 // 在worker线程中读取rawfile,并通过ResourceHandler返回给Web内核。
ReadRawfileDataOnWorkerThread()121 void RawfileRequest::ReadRawfileDataOnWorkerThread() {
122 OH_LOG_INFO(LOG_APP, "read rawfile in worker thread.");
123 const struct UrlInfo {
124 std::string resource;
125 std::string mimeType;
126 } urlInfos[] = {
127 {"post_data.html", "text/html"},
128 {"chunked_post_stream.html", "text/html"},
129 {"xhr", "application/json"}
130 };
131
132 if (!resourceManager()) {
133 OH_LOG_ERROR(LOG_APP, "read rawfile error, resource manager is nullptr.");
134 return;
135 }
136
137 RawFile *rawfile = OH_ResourceManager_OpenRawFile(resourceManager(), rawfilePath().c_str());
138 OH_LOG_INFO(LOG_APP, "read OH_ResourceManager_OpenRawFile %{public}s", rawfilePath().c_str());
139
140 if (!rawfile) {
141 OH_LOG_INFO(LOG_APP, "read OH_ArkWebResponse_SetStatus %{public}d", DO_NOT_FOUND);
142 OH_ArkWebResponse_SetStatus(response(), DO_NOT_FOUND);
143 } else {
144 OH_LOG_INFO(LOG_APP, "read OH_ArkWebResponse_SetStatus %{public}d", DO_OK);
145 OH_ArkWebResponse_SetStatus(response(), DO_OK);
146 }
147
148 for (auto &urlInfo : urlInfos) {
149 if (urlInfo.resource == rawfilePath()) {
150 OH_ArkWebResponse_SetMimeType(response(), urlInfo.mimeType.c_str());
151 break;
152 }
153 }
154 OH_ArkWebResponse_SetCharset(response(), "UTF-8");
155
156 long len = OH_ResourceManager_GetRawFileSize(rawfile);
157 haveResponse_ = OH_ArkWebResponse_SetHeaderByName(response(), "content-length", std::to_string(len).c_str(), false);
158 haveResponse_ = OH_ArkWebResponse_SetHeaderByName(response(), "Access-Control-Allow-Origin", "*", false);
159
160 DidReceiveResponse();
161
162 long consumed = 0;
163 uint8_t buffer[blockSize];
164 while (true) {
165 int ret = OH_ResourceManager_ReadRawFile(rawfile, buffer, blockSize);
166 OH_LOG_INFO(LOG_APP, "read rawfile %{public}d bytes.", ret);
167 if (ret == 0) {
168 break;
169 }
170 consumed += ret;
171 OH_ResourceManager_SeekRawFile(rawfile, consumed, 0);
172 DidReceiveData(buffer, ret);
173 memset(buffer, 0, blockSize);
174 }
175 OH_ResourceManager_CloseRawFile(rawfile);
176 DidFinish();
177 }
178
Stop()179 void RawfileRequest::Stop() {
180 OH_LOG_INFO(LOG_APP, "stop the rawfile request.");
181 stopped_ = true;
182 if (response_) {
183 OH_ArkWeb_DestroyResponse(response_);
184 }
185 OH_ArkWebResourceRequest_Destroy(resourceRequest_);
186 haveResourceHandler_ = OH_ArkWebResourceHandler_Destroy(resourceHandler_);
187 }
188
DidReceiveResponse()189 void RawfileRequest::DidReceiveResponse() {
190 OH_LOG_INFO(LOG_APP, "did receive response.");
191
192 if (!stopped_) {
193 // 接口覆盖
194 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidReceiveResponse start.");
195 OH_ArkWebResourceHandler_DidReceiveResponse(resourceHandler_, response_);
196 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidReceiveResponse end.");
197 }
198 }
199
DidReceiveData(const uint8_t * buffer,int64_t bufLen)200 void RawfileRequest::DidReceiveData(const uint8_t *buffer, int64_t bufLen) {
201 OH_LOG_INFO(LOG_APP, "did receive data.");
202
203 if (!stopped_) {
204 // 接口覆盖
205 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidReceiveData start.");
206 OH_ArkWebResourceHandler_DidReceiveData(resourceHandler_, buffer, bufLen);
207 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidReceiveData end.");
208 }
209 }
210
DidFinish()211 void RawfileRequest::DidFinish() {
212 OH_LOG_INFO(LOG_APP, "did finish.");
213
214 if (!stopped_) {
215 // 接口覆盖
216 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidFinish start.");
217 OH_ArkWebResourceHandler_DidFinish(resourceHandler_);
218 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidFinish end.");
219 }
220 }
221
DidFailWithError(ArkWeb_NetError errorCode)222 void RawfileRequest::DidFailWithError(ArkWeb_NetError errorCode) {
223 OH_LOG_INFO(LOG_APP, "did finish with error %{public}d.", errorCode);
224 if (!stopped_) {
225 // 接口覆盖
226 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidFailWithError start.");
227 OH_ArkWebResourceHandler_DidFailWithError(resourceHandler_, errorCode);
228 OH_LOG_INFO(LOG_APP, "OH_ArkWebResourceHandler_DidFailWithError end.");
229 }
230 }
231
releaseString()232 int32_t RawfileRequest::releaseString() {
233 OH_LOG_INFO(LOG_APP, "OH_ArkWeb_ReleaseString .");
234 char* url = new char[10];
235 strcpy(url, "test");
236 OH_ArkWeb_ReleaseString(url);
237 return 0;
238 }
239
releaseByteArray()240 int32_t RawfileRequest::releaseByteArray() {
241 OH_LOG_INFO(LOG_APP, "OH_ArkWeb_ReleaseByteArray .");
242 uint8_t* buffer = new uint8_t[1024];
243 OH_ArkWeb_ReleaseByteArray(buffer);
244 return 0;
245 }
246
destroyHttpBodyStream()247 int32_t RawfileRequest::destroyHttpBodyStream() {
248 OH_ArkWebResourceRequest_DestroyHttpBodyStream(stream_);
249 return 0;
250 }
251
setHeaderByName()252 int32_t RawfileRequest::setHeaderByName() {
253 ArkWeb_Response* testResponse;
254 OH_ArkWeb_CreateResponse(&testResponse);
255 OH_ArkWebResponse_SetHeaderByName(testResponse, "test-headers", "test", true);
256
257 char* testHeader;
258 OH_ArkWebResponse_GetHeaderByName(testResponse, "test-headers", &testHeader);
259 std::string testHeader1(testHeader);
260 if( testHeader1 == "test") {
261 return 0;
262 } else {
263 return -1;
264 }
265 }
266
getRequestHeaderList()267 int32_t RawfileRequest::getRequestHeaderList() {
268 ArkWeb_RequestHeaderList* headerList;
269 OH_ArkWebResourceRequest_GetRequestHeaders(resourceRequest_, &headerList);
270 return OH_ArkWebRequestHeaderList_GetSize(headerList);
271 }