1 /*
2  * Copyright (c) 2023 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 #ifdef IPPOVERUSB_ENABLE
17 #include "print_http_request_process.h"
18 #include <cmath>
19 #include "print_log.h"
20 #include "print_ipp_over_usb_util.h"
21 #include "print_util.h"
22 #include "usb_errors.h"
23 
24 namespace OHOS::Print {
25 using namespace std;
26 using namespace OHOS;
27 using namespace OHOS::USB;
28 using namespace httplib;
29 
PrintHttpRequestProcess()30 PrintHttpRequestProcess::PrintHttpRequestProcess()
31 {}
32 
~PrintHttpRequestProcess()33 PrintHttpRequestProcess::~PrintHttpRequestProcess()
34 {}
35 
PrintOperation(Operation operation)36 std::string PrintHttpRequestProcess::PrintOperation(Operation operation)
37 {
38     if (operation == Operation::Get_Printer_Attributes) {
39         return HTTP_OPERATION_GET_ATTR;
40     } else if (operation == Operation::Send_Document) {
41         return HTTP_OPERATION_SEND_DOC;
42     } else {
43         return HTTP_OPERATION_COMMON;
44     }
45 }
46 
NeedOffset(const std::vector<uint8_t> & readTempBuffer)47 size_t PrintHttpRequestProcess::NeedOffset(const std::vector<uint8_t> &readTempBuffer)
48 {
49     size_t readSize = readTempBuffer.size();
50     size_t reqindex = 0;
51     bool checkNeedOffset = (readSize > HTTP_COMMON_CONST_VALUE_25 && readTempBuffer[INDEX_0] == HTTP_RESPONSE_H &&
52         readTempBuffer[INDEX_1] == HTTP_RESPONSE_T && readTempBuffer[INDEX_2] == HTTP_RESPONSE_T &&
53         readTempBuffer[INDEX_3] == HTTP_RESPONSE_P &&
54         readTempBuffer[INDEX_4] == HTTP_RESPONSE_VERSION_SPLIT_GANG &&
55         readTempBuffer[INDEX_5] == HTTP_MSG_CHAR_1 &&
56         readTempBuffer[INDEX_6] == HTTP_MSG_CHAR_2E &&
57         readTempBuffer[INDEX_7] == HTTP_MSG_CHAR_1 &&
58         readTempBuffer[INDEX_8] == HTTP_MSG_CHAR_20 &&
59         readTempBuffer[INDEX_9] == HTTP_MSG_CHAR_1 &&
60         readTempBuffer[INDEX_10] == HTTP_MSG_CHAR_0 &&
61         readTempBuffer[INDEX_11] == HTTP_MSG_CHAR_0);
62     if (checkNeedOffset) {
63         PRINT_HILOGD("include HTTP/1.1 100");
64         reqindex = HTTP_COMMON_CONST_VALUE_25;
65     }
66     return reqindex;
67 }
68 
RecordBufByOperation(Operation operation,size_t requestId,const std::vector<uint8_t> & tmVector)69 void PrintHttpRequestProcess::RecordBufByOperation(Operation operation, size_t requestId,
70     const std::vector<uint8_t> &tmVector)
71 {
72     if (operation == Operation::Send_Document) {
73         std::lock_guard<std::mutex> mtx_locker(mutexSendDoc);
74         if (readSendDocBufMap.find(requestId) == readSendDocBufMap.end()) {
75             readSendDocBufMap[requestId] = tmVector;
76         }
77     } else {
78         if (reqIdOperaIdMap[requestId] == HTTP_REQUEST_GET_ATTR)  {
79             std::lock_guard<std::mutex> mtx_locker(mutexGetAttr);
80             if (readGetAttrBufMap.find(requestId) == readGetAttrBufMap.end()) {
81                 readGetAttrBufMap[requestId] = tmVector;
82             }
83         } else {
84             std::lock_guard<std::mutex> mtx_locker(mutexCommon);
85             if (readBufMap.find(requestId) == readBufMap.end()) {
86                 readBufMap[requestId] = tmVector;
87             }
88         }
89     }
90 }
91 
GetContentLength(const std::vector<uint8_t> & readTempBuffer,size_t index,bool & findContentLength,size_t & contentLength)92 void PrintHttpRequestProcess::GetContentLength(const std::vector<uint8_t> &readTempBuffer, size_t index,
93     bool &findContentLength, size_t &contentLength)
94 {
95     size_t readSize = readTempBuffer.size();
96     if ((index + HTTP_COMMON_CONST_VALUE_14) < readSize) {
97         std::string tmpStr = "";
98         for (size_t offset = 0; offset < HTTP_COMMON_CONST_VALUE_14; offset++) {
99             tmpStr += readTempBuffer[index + offset];
100         }
101         if (tmpStr == HTTP_CONTENT_LENGTH) {
102             findContentLength = true;
103             std::string lenStr = "";
104             size_t lenIndex = index + HTTP_COMMON_CONST_VALUE_14 + HTTP_COMMON_CONST_VALUE_2;
105             while (lenIndex < readSize - 1 && (!(readTempBuffer[lenIndex] == HTTP_SPLIT_R_CODE &&
106                                                   readTempBuffer[lenIndex + INDEX_1] == HTTP_SPLIT_N_CODE))) {
107                 lenStr += readTempBuffer[lenIndex];
108                 lenIndex++;
109             }
110             int32_t contentLengthTmp = 0;
111             if (!PrintUtil::ConvertToInt(lenStr, contentLengthTmp)) {
112                 PRINT_HILOGE("lenStr [%{public}s] can not parse to number.", lenStr.c_str());
113                 return;
114             }
115             contentLength = static_cast<size_t>(contentLengthTmp);
116             PRINT_HILOGD("contentLength = %{public}s,  %{public}lu", lenStr.c_str(), contentLength);
117         }
118     }
119 }
120 
DumpRespIdCode(const std::vector<uint8_t> & readTempBuffer,Operation operation,size_t begin,size_t maxSize)121 void PrintHttpRequestProcess::DumpRespIdCode(const std::vector<uint8_t> &readTempBuffer,
122     Operation operation, size_t begin, size_t maxSize)
123 {
124     for (size_t i = begin; i < (begin + HTTP_COMMON_CONST_VALUE_8) && i < maxSize; i++) {
125         PRINT_HILOGD("operation:%{public}s, readTempBuffer: %{public}x",
126             PrintOperation(operation).c_str(), readTempBuffer[i]);
127     }
128 }
129 
CheckLineEnd(std::vector<uint8_t> & readTempBuffer,size_t index)130 bool PrintHttpRequestProcess::CheckLineEnd(std::vector<uint8_t> &readTempBuffer, size_t index)
131 {
132     size_t readSize = readTempBuffer.size();
133     if ((index + HTTP_COMMON_CONST_VALUE_3) < readSize && readTempBuffer[index] == HTTP_SPLIT_R_CODE &&
134         readTempBuffer[index + INDEX_1] == HTTP_SPLIT_N_CODE && readTempBuffer[index + INDEX_2] == HTTP_SPLIT_R_CODE &&
135         readTempBuffer[index + INDEX_3] == HTTP_SPLIT_N_CODE) {
136         return true;
137     }
138     return false;
139 }
140 
CalculateRequestId(std::vector<uint8_t> & readTempBuffer,size_t index,Operation operation)141 size_t PrintHttpRequestProcess::CalculateRequestId(
142     std::vector<uint8_t> &readTempBuffer, size_t index, Operation operation)
143 {
144     size_t readSize = readTempBuffer.size();
145     if ((index + HTTP_COMMON_CONST_VALUE_11) < readSize) {
146         DumpRespIdCode(readTempBuffer, operation, index + HTTP_COMMON_CONST_VALUE_4, readSize);
147         return readTempBuffer[index + HTTP_COMMON_CONST_VALUE_8] *
148                 pow(HTTP_COMMON_CONST_VALUE_10, HTTP_COMMON_CONST_VALUE_3) +
149             readTempBuffer[index + HTTP_COMMON_CONST_VALUE_9] *
150                 pow(HTTP_COMMON_CONST_VALUE_10, HTTP_COMMON_CONST_VALUE_2) +
151             readTempBuffer[index + HTTP_COMMON_CONST_VALUE_10] * HTTP_COMMON_CONST_VALUE_10 +
152             readTempBuffer[index + HTTP_COMMON_CONST_VALUE_11];
153     }
154     PRINT_HILOGE("Invalid index");
155     return 0;
156 }
157 
CalculateFileDataBeginIndex(size_t index,Operation operation)158 size_t PrintHttpRequestProcess::CalculateFileDataBeginIndex(size_t index, Operation operation)
159 {
160     size_t fileDataBeginIndex = index + INDEX_4;
161     PRINT_HILOGD("operation:%{public}s, fileDataBeginIndex = %{public}lu",
162         PrintOperation(operation).c_str(), fileDataBeginIndex);
163     return fileDataBeginIndex;
164 }
165 
ProcessDataFromDevice(Operation operation)166 bool PrintHttpRequestProcess::ProcessDataFromDevice(Operation operation)
167 {
168     std::vector<uint8_t> readTempBuffer;
169     int32_t readFromUsbRes =
170         DelayedSingleton<PrintUsbManager>::GetInstance()->BulkTransferRead(devName, operation, readTempBuffer);
171     if (readFromUsbRes == EORROR_HDF_DEV_ERR_NO_DEVICE) {
172         PRINT_HILOGE("HDF_DEV_ERR_NO_DEVICE, The device module has no device");
173         deviceOpen = false;
174         return true;
175     }
176     size_t readSize = readTempBuffer.size();
177     if (readSize > 0 && readFromUsbRes == UEC_OK) {
178         PRINT_HILOGD("operation:%{public}s, readSize = %{public}lu", PrintOperation(operation).c_str(), readSize);
179         size_t reqindex = NeedOffset(readTempBuffer);
180         size_t requestId = 0;
181         std::vector<uint8_t> tmVector;
182         bool findRequestId = false;
183         bool findContentLength = false;
184         size_t contentLength = 0;
185         size_t fileDataBeginIndex = 0;
186         // 解析出报文中的RequestId 和 Content-Length
187         for (size_t index = reqindex; index < readSize; index++) {
188             bool findLineEnd = (!findRequestId && CheckLineEnd(readTempBuffer, index));
189             if (findLineEnd) {
190                 fileDataBeginIndex = CalculateFileDataBeginIndex(index, operation);
191                 findRequestId = true;
192             }
193             if (!findContentLength) {
194                 GetContentLength(readTempBuffer, index, findContentLength, contentLength);
195             }
196             tmVector.push_back(readTempBuffer[index]);
197         }
198         int count = 0;
199         int maxCount = 50;
200         // 一次读取的报文长度小于 Content-Length字段的值则需再读取一次
201         while (tmVector.size() < readSize + contentLength && count < maxCount) {
202             GetAttrAgain(operation, tmVector);
203             count++;
204         }
205         if (fileDataBeginIndex > HTTP_COMMON_CONST_VALUE_4) {
206             requestId = CalculateRequestId(tmVector, fileDataBeginIndex - HTTP_COMMON_CONST_VALUE_4, operation);
207         }
208         PRINT_HILOGD("operation:%{public}s requestId: %{public}lu ", PrintOperation(operation).c_str(), requestId);
209         RecordBufByOperation(operation, requestId, tmVector);
210         return true;
211     }
212     return false;
213 }
214 
GetAttrAgain(Operation operation,std::vector<uint8_t> & tmVector)215 void PrintHttpRequestProcess::GetAttrAgain(Operation operation, std::vector<uint8_t> &tmVector)
216 {
217     PRINT_HILOGD("GetAttr again");
218     std::vector<uint8_t> readBuffer;
219     int32_t readFromUsbRes =
220         DelayedSingleton<PrintUsbManager>::GetInstance()->BulkTransferRead(devName, operation, readBuffer);
221     size_t readSize = readBuffer.size();
222     if (readSize > 0 && readFromUsbRes == UEC_OK) {
223         PRINT_HILOGD("GetAttr again readSize = %{public}lu", readSize);
224         for (size_t index = 0; index < readSize; index++) {
225             tmVector.push_back(readBuffer[index]);
226         }
227     }
228 }
229 
StartReadSendDocDataFromPrinterLooper()230 void PrintHttpRequestProcess::StartReadSendDocDataFromPrinterLooper()
231 {
232     PRINT_HILOGD("StartReadSendDocDataFromPrinterLooper");
233     while (deviceOpen && needReadSendDoc) {
234         if (ProcessDataFromDevice(Operation::Send_Document)) {
235             break;
236         }
237         std::this_thread::sleep_for(std::chrono::milliseconds(USB_READ_INTERVAL));
238     }
239     PRINT_HILOGD("EndReadSendDocDataFromPrinterLooper");
240 }
241 
ProcessHttpResponse(httplib::Response & responseData,size_t requestId)242 void PrintHttpRequestProcess::ProcessHttpResponse(httplib::Response &responseData, size_t requestId)
243 {
244     PRINT_HILOGD("processHttpResponse enter");
245     int retryCount = 0;
246     // cups timeout is 30 seconds
247     while (retryCount < RESPONSE_RETRY_MAX_TIMES && deviceOpen) {
248         std::this_thread::sleep_for(std::chrono::milliseconds(RESPONSE_RETRY_INTERVAL));
249         retryCount++;
250         std::lock_guard<std::mutex> mtx_locker(mutexCommon);
251         if (readBufMap.find(requestId) != readBufMap.end()) {
252             size_t totalSize = readBufMap[requestId].size();
253             PRINT_HILOGD("Response totalSize:%{public}lu, retryCout = %{public}d", totalSize, retryCount);
254             PrintIppOverUsbUtil::ConstructHttpResponse(&readBufMap[requestId][0], totalSize, responseData);
255             readBufMap.erase(requestId);
256             break;
257         } else {
258             continue;
259         }
260     }
261     // 超时错误
262     if (retryCount >= RESPONSE_RETRY_MAX_TIMES) {
263         PRINT_HILOGE("process_http_response time out retryCout: %{public}d", retryCount);
264     }
265     PRINT_HILOGD("process_http_response out");
266 }
267 
ProcessHttpResponseGetAttr(httplib::Response & responseData,size_t requestId)268 void PrintHttpRequestProcess::ProcessHttpResponseGetAttr(httplib::Response &responseData, size_t requestId)
269 {
270     PRINT_HILOGD("processHttpResponseGetAttr enter");
271     int retryCount = 0;
272     while (retryCount < RESPONSE_RETRY_MAX_TIMES && deviceOpen) {
273         std::this_thread::sleep_for(std::chrono::milliseconds(RESPONSE_RETRY_INTERVAL));
274         retryCount++;
275         std::lock_guard<std::mutex> mtx_locker(mutexGetAttr);
276         if (readGetAttrBufMap.find(requestId) != readGetAttrBufMap.end()) {
277             size_t totalSize = readGetAttrBufMap[requestId].size();
278             PRINT_HILOGD("Response GetAttr totalSize:%{public}lu, retryCout = %{public}d", totalSize, retryCount);
279             PrintIppOverUsbUtil::ConstructHttpResponse(&readGetAttrBufMap[requestId][0], totalSize, responseData);
280             readGetAttrBufMap.erase(requestId);
281             break;
282         } else {
283             continue;
284         }
285     }
286     // 超时错误
287     if (retryCount >= RESPONSE_RETRY_MAX_TIMES) {
288         PRINT_HILOGE("process_http_response_get_attr time out retryCout: %{public}d", retryCount);
289     }
290     PRINT_HILOGD("process_http_response_get_attr out");
291 }
292 
ProcessHttpResponseSendDoc(httplib::Response & responseData,size_t requestId)293 void PrintHttpRequestProcess::ProcessHttpResponseSendDoc(httplib::Response &responseData, size_t requestId)
294 {
295     PRINT_HILOGD("ProcessHttpResponseSendDoc enter");
296     int retryCount = 0;
297     while (retryCount < RESPONSE_RETRY_MAX_TIMES && deviceOpen) {
298         std::this_thread::sleep_for(std::chrono::milliseconds(RESPONSE_RETRY_INTERVAL));
299         retryCount++;
300         std::lock_guard<std::mutex> mtx_locker(mutexSendDoc);
301         if (readSendDocBufMap.find(requestId) != readSendDocBufMap.end()) {
302             size_t totalSize = readSendDocBufMap[requestId].size();
303             PRINT_HILOGD("Response SendDoc totalSize:%{public}lu, retryCout = %{public}d", totalSize, retryCount);
304             PrintIppOverUsbUtil::ConstructHttpResponse(&readSendDocBufMap[requestId][0], totalSize, responseData);
305             readSendDocBufMap.erase(requestId);
306             break;
307         } else {
308             continue;
309         }
310     }
311     // 超时错误
312     if (retryCount >= RESPONSE_RETRY_MAX_TIMES) {
313         PRINT_HILOGE("ProcessHttpResponseSendDoc time out retryCout: %{public}d", retryCount);
314         needReadSendDoc = false;
315     }
316     PRINT_HILOGD("ProcessHttpResponseSendDoc out");
317 }
318 
DealRequestHeader(const httplib::Request & requestData,std::string & sHeadersAndBody)319 bool PrintHttpRequestProcess::DealRequestHeader(const httplib::Request &requestData, std::string &sHeadersAndBody)
320 {
321     bool ischunked = false;
322     for (const auto &x : requestData.headers) {
323         PRINT_HILOGD("requestData.headers first: %{public}s, second : %{public}s", x.first.c_str(), x.second.c_str());
324         if (x.first == HTTP_TRANSFER_ENCODING && x.second == HTTP_CHUNKED) {
325             ischunked = true;
326         }
327         if (x.first == HTTP_EXPECT) {
328             continue;
329         }
330         sHeadersAndBody += x.first;
331         sHeadersAndBody += SPLIT_VALUE_COLON;
332         sHeadersAndBody += x.second;
333         sHeadersAndBody += HTTP_MSG_STRING_R_AND_N;
334     }
335     sHeadersAndBody += HTTP_MSG_STRING_R_AND_N;
336     return ischunked;
337 }
338 
CalcReqIdOperaId(const char * data,size_t dataLength,size_t & requestId)339 void PrintHttpRequestProcess::CalcReqIdOperaId(const char *data, size_t dataLength, size_t &requestId)
340 {
341     if (data == nullptr) {
342         return;
343     }
344     if (dataLength < HTTP_COMMON_CONST_VALUE_8) {
345         return;
346     }
347     DumpReqIdOperaId(data, dataLength);
348     size_t operationId = (uint8_t)(*(data + INDEX_2)) * HTTP_COMMON_CONST_VALUE_10 + (uint8_t)(*(data + INDEX_3));
349     requestId = (uint8_t)(*(data + INDEX_4)) * HTTP_COMMON_CONST_VALUE_1000 +
350         (uint8_t)(*(data + INDEX_5)) * HTTP_COMMON_CONST_VALUE_100 +
351          (uint8_t)(*(data + INDEX_6)) * HTTP_COMMON_CONST_VALUE_10 + (uint8_t)(*(data + INDEX_7));
352     reqIdOperaIdMap[requestId] = operationId;
353 }
354 
StartWriteDataToPrinterLooper()355 void PrintHttpRequestProcess::StartWriteDataToPrinterLooper()
356 {
357     PRINT_HILOGD("StartWriteDataToPrinterLooper");
358     std::vector<uint8_t> vectorRequestBuffer;
359     while (deviceOpen && needWriteData) {
360         std::string str = "";
361         if (!ippDataQue.pop(str)) {
362             continue;
363         }
364 
365         vectorRequestBuffer.assign(str.begin(), str.end());
366         int32_t ret = 0;
367         int32_t writeDataRetryCount = 0;
368         do {
369             ret = DelayedSingleton<PrintUsbManager>::GetInstance()->BulkTransferWrite(
370                 devName, Operation::Common, vectorRequestBuffer);
371             PRINT_HILOGD("writeBody ret: %{public}d", ret);
372             if (ret == EORROR_HDF_DEV_ERR_TIME_OUT) {
373                 std::this_thread::sleep_for(std::chrono::milliseconds(USB_WRITE_INTERVAL));
374                 writeDataRetryCount++;
375                 PRINT_HILOGE(
376                     "StartWriteDataToPrinterLooper, retrwriteDataRetryCounty = %{public}d", writeDataRetryCount);
377             }
378         } while (ret == EORROR_HDF_DEV_ERR_TIME_OUT && writeDataRetryCount < WRITE_RETRY_MAX_TIMES);
379 
380         if (ret == EORROR_HDF_DEV_ERR_NO_DEVICE) {
381             PRINT_HILOGE("WriteData HDF_DEV_ERR_NO_DEVICE, The device module has no device");
382             needWriteData = false;
383             break;
384         }
385         vectorRequestBuffer.clear();
386         int retryCount = 0;
387         while (retryCount < READ_RETRY_MAX_TIMES) {
388             retryCount++;
389             if (ProcessDataFromDevice(Operation::Common)) {
390                 break;
391             }
392             std::this_thread::sleep_for(std::chrono::milliseconds(USB_READ_INTERVAL));
393         }
394         // 读超时错误
395         if (retryCount >= READ_RETRY_MAX_TIMES) {
396             PRINT_HILOGE("read data time out retryCout: %{public}d", retryCount);
397         }
398     }
399     PRINT_HILOGD("endtWriteDataToPrinterLooper");
400 }
401 
CreatWriteDataTask()402 void PrintHttpRequestProcess::CreatWriteDataTask()
403 {
404     PRINT_HILOGD("CreatWriteDataTask needWriteData: %{public}d", needWriteData);
405     if (!needWriteData) {
406         needWriteData = true;
407         std::thread writeDataTask([this] {this->StartWriteDataToPrinterLooper();});
408         writeDataTask.detach();
409     }
410 }
411 
ProcessOtherRequest(const char * data,size_t data_length,std::string & sHeadersAndBody,size_t requestId)412 void PrintHttpRequestProcess::ProcessOtherRequest(const char *data, size_t data_length,
413     std::string &sHeadersAndBody, size_t requestId)
414 {
415     CreatWriteDataTask();
416 
417     sHeadersAndBody.append(data, data_length);
418     ippDataQue.push(sHeadersAndBody);
419 }
420 
DumpReqIdOperaId(const char * data,size_t data_length)421 void PrintHttpRequestProcess::DumpReqIdOperaId(const char *data, size_t data_length)
422 {
423     if (data_length < REQID_OPERAID_LEN) {
424         return;
425     }
426     for (size_t i = 0; i < REQID_OPERAID_LEN; i++) {
427         PRINT_HILOGD("ipp: %{public}x", *(data + i));
428     }
429 }
430 
CreatReadSendDocTask()431 void PrintHttpRequestProcess::CreatReadSendDocTask()
432 {
433     PRINT_HILOGD("CreatReadSendDocTask needReadSendDoc: %{public}d", needReadSendDoc);
434     if (!needReadSendDoc) {
435         needReadSendDoc = true;
436         std::thread readSendDocTask([this] {this->StartReadSendDocDataFromPrinterLooper();});
437         readSendDocTask.detach();
438     }
439 }
440 
CreateChunk(const char * data,size_t data_length)441 std::string PrintHttpRequestProcess::CreateChunk(const char *data, size_t data_length)
442 {
443     std::string chunkStr = PrintIppOverUsbUtil::IntToHexString(static_cast<unsigned int>(data_length));
444     chunkStr += HTTP_MSG_STRING_R_AND_N;
445     chunkStr.append(data, data_length);
446     chunkStr += HTTP_MSG_STRING_R_AND_N;
447     return chunkStr;
448 }
449 
WriteDataSync(const std::string & dataStr)450 int32_t PrintHttpRequestProcess::WriteDataSync(const std::string &dataStr)
451 {
452     std::string sHeadersAndBody = dataStr;
453     int32_t ret = 0;
454     while (sHeadersAndBody.length() > USB_ENDPOINT_MAX_LENGTH) {
455         std::string send = sHeadersAndBody.substr(0, USB_ENDPOINT_MAX_LENGTH);
456         ret = BulkTransferWriteData(send);
457         if (ret != 0) {
458             return ret;
459         }
460         sHeadersAndBody = sHeadersAndBody.substr(USB_ENDPOINT_MAX_LENGTH);
461     }
462     if (!sHeadersAndBody.empty()) {
463         ret = BulkTransferWriteData(sHeadersAndBody);
464     }
465     return ret;
466 }
467 
BulkTransferWriteData(const std::string & dataStr)468 int32_t PrintHttpRequestProcess::BulkTransferWriteData(const std::string &dataStr)
469 {
470     std::vector<uint8_t> vectorRequestBuffer;
471     size_t len = dataStr.length();
472     sendDocTotalLen += len;
473     vectorRequestBuffer.assign(dataStr.begin(), dataStr.end());
474     uint32_t retryNum = 0;
475     int32_t ret = 0;
476     do {
477         ret = DelayedSingleton<PrintUsbManager>::GetInstance()->BulkTransferWrite(devName,
478             Operation::Send_Document, vectorRequestBuffer);
479         PRINT_HILOGD("writeBody chunk, ret: %{public}d, len: %{public}lu, sendDocTotalLen: %{public}lu",
480             ret, len, sendDocTotalLen);
481         if (ret == EORROR_HDF_DEV_ERR_NO_DEVICE) {
482             sendDocTotalLen = 0;
483             deviceOpen = false;
484             return ret;
485         }
486         if (ret == EORROR_HDF_DEV_ERR_TIME_OUT) {
487             std::this_thread::sleep_for(std::chrono::milliseconds(USB_BULKTRANSFER_WRITE_SLEEP));
488             retryNum++;
489         }
490     } while (ret == EORROR_HDF_DEV_ERR_TIME_OUT && retryNum < WRITE_RETRY_MAX_TIMES);
491     if (ret != 0) {
492         sendDocTotalLen = 0;
493         PRINT_HILOGD("Write data fail");
494         return ret;
495     }
496     vectorRequestBuffer.clear();
497     return ret;
498 }
499 
ProcessHttpResp(size_t requestId,httplib::Response & responseData,const std::string & sHeadersAndBody)500 void PrintHttpRequestProcess::ProcessHttpResp(size_t requestId, httplib::Response &responseData,
501     const std::string &sHeadersAndBody)
502 {
503     if (reqIdOperaIdMap[requestId] == HTTP_REQUEST_GET_ATTR) {
504         ProcessHttpResponseGetAttr(responseData, requestId);
505     } else if (reqIdOperaIdMap[requestId] == HTTP_REQUEST_SEND_DOC) {
506         if (!deviceOpen) {
507             PRINT_HILOGE("Device disconnect, return");
508             return;
509         }
510         PRINT_HILOGD("writeBody chunk end sHeadersAndBody len: %{public}lu", sHeadersAndBody.length());
511         std::string dataStr = sHeadersAndBody + HTTP_MSG_STRING_CHUNK_END;
512         auto ret = WriteDataSync(dataStr);
513         sendDocTotalLen = 0;
514         if (ret != 0) {
515             PRINT_HILOGE("writeBody chunk end fail");
516             return;
517         }
518         PRINT_HILOGD("writeBody chunk end");
519         ProcessHttpResponseSendDoc(responseData, requestId);
520     } else {
521         ProcessHttpResponse(responseData, requestId);
522     }
523 }
524 
ProcessRequest(const httplib::Request & requestData,httplib::Response & responseData,const httplib::ContentReader & content_reader)525 uint32_t PrintHttpRequestProcess::ProcessRequest(const httplib::Request &requestData, httplib::Response &responseData,
526     const httplib::ContentReader &content_reader)
527 {
528     PRINT_HILOGI("ProcessRequest devName: %{public}s", devName.c_str());
529     std::string sHeadersAndBody = HTTP_POST;
530     bool isChunked = DealRequestHeader(requestData, sHeadersAndBody);
531     size_t requestId = 0;
532     bool isFirstRead = true;
533     content_reader([&](const char *data, size_t data_length) {
534         if (isChunked) {
535             if (isFirstRead) {
536                 isFirstRead = false;
537                 CalcReqIdOperaId(data, data_length, requestId);
538                 CreatReadSendDocTask();
539                 sHeadersAndBody += CreateChunk(data, data_length);
540                 return CPP_HTTP_OK;
541             }
542         } else {
543             CalcReqIdOperaId(data, data_length, requestId);
544         }
545 
546         if (reqIdOperaIdMap[requestId] == HTTP_REQUEST_SEND_DOC) {
547             std::string dataChunk = CreateChunk(data, data_length);
548             if ((sHeadersAndBody.length() + dataChunk.length()) < USB_DATA_MAX_LENGTH) {
549                 sHeadersAndBody += dataChunk;
550                 return CPP_HTTP_OK;
551             }
552             auto ret = WriteDataSync(sHeadersAndBody);
553             if (ret != 0) {
554                 return CPP_HTTP_FAIL;
555             }
556             sHeadersAndBody = dataChunk;
557             return CPP_HTTP_OK;
558         }
559 
560         ProcessOtherRequest(data, data_length, sHeadersAndBody, requestId);
561         return CPP_HTTP_OK;
562     });
563     ProcessHttpResp(requestId, responseData, sHeadersAndBody);
564     PRINT_HILOGD("processRequest path: %{public}s end", requestData.path.c_str());
565     return 0;
566 }
567 
SetDeviceName(std::string name)568 void PrintHttpRequestProcess::SetDeviceName(std::string name)
569 {
570     devName = name;
571 }
572 
GetDeviceName()573 std::string PrintHttpRequestProcess::GetDeviceName()
574 {
575     return devName;
576 }
577 
Stop()578 void PrintHttpRequestProcess::Stop()
579 {
580     PRINT_HILOGD("stop read data looper");
581     needReadSendDoc = false;
582     needWriteSendDoc = false;
583     needWriteData = false;
584 }
585 
586 }
587 
588 #endif // IPPOVERUSB_ENABLE