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_server_manager.h"
18 #include "print_http_request_process.h"
19 #include "print_usb_manager.h"
20 #include "print_log.h"
21 #include "nlohmann/json.hpp"
22 #include "cJSON.h"
23
24 namespace OHOS::Print {
25 using namespace OHOS;
26 using namespace httplib;
27
28 using json = nlohmann::json;
29
PrintHttpServerManager()30 PrintHttpServerManager::PrintHttpServerManager()
31 {}
32
~PrintHttpServerManager()33 PrintHttpServerManager::~PrintHttpServerManager()
34 {
35 }
36
AllocatePort(std::shared_ptr<httplib::Server> svr, int32_t &port)37 bool PrintHttpServerManager::AllocatePort(std::shared_ptr<httplib::Server> svr, int32_t &port)
38 {
39 for (int allocPort = HTTP_MIN_PORT; allocPort <= HTTP_MAX_PORT; allocPort++) {
40 bool isPortUse = false;
41 for (const auto& pair : printHttpPortMap) {
42 if (pair.second == allocPort) {
43 isPortUse = true;
44 break;
45 }
46 }
47 if (isPortUse) {
48 PRINT_HILOGD("port : %{public}d is using", allocPort);
49 continue;
50 }
51 if (svr != nullptr && svr->bind_to_port(LOCAL_HOST, allocPort)) {
52 PRINT_HILOGD("bind to port : %{public}d success", allocPort);
53 port = allocPort;
54 return true;
55 }
56 }
57 return false;
58 }
59
StartServer(std::shared_ptr<httplib::Server> svr, std::shared_ptr<PrintHttpRequestProcess> process)60 void PrintHttpServerManager::StartServer(std::shared_ptr<httplib::Server> svr,
61 std::shared_ptr<PrintHttpRequestProcess> process)
62 {
63 PRINT_HILOGD("startServer");
64 if (svr == nullptr) {
65 PRINT_HILOGE("svr is null");
66 return;
67 }
68 svr->set_payload_max_length(HTTP_SERVER_MAX_LENGTH);
69 PRINT_HILOGD("post /");
70 svr->Post("^/.*", [process](const httplib::Request &req, httplib::Response &res,
71 const httplib::ContentReader &content_reader) {
72 PRINT_HILOGD("listen path: %{public}s", req.path.c_str());
73 if (process != nullptr) {
74 process->ProcessRequest(req, res, content_reader);
75 }
76 });
77
78 PRINT_HILOGD("after post");
79 svr->listen_after_bind();
80 PRINT_HILOGD("after listen");
81 }
82
CreateServer(std::string printerName, int32_t &port)83 bool PrintHttpServerManager::CreateServer(std::string printerName, int32_t &port)
84 {
85 PRINT_HILOGD("PrintHttpServerManager init printerName: %{public}s, port: %{public}d", printerName.c_str(), port);
86 if (printHttpServerMap.find(printerName) != printHttpServerMap.end()) {
87 PRINT_HILOGI("printerName: %{public}s has server", printerName.c_str());
88 if (printHttpPortMap.find(printerName) != printHttpPortMap.end()) {
89 port = printHttpPortMap[printerName];
90 return true;
91 }
92 PRINT_HILOGE("printerName: %{public}s has server, but do not has port", printerName.c_str());
93 return false;
94 }
95
96 std::shared_ptr<httplib::Server> newServer = std::make_shared<httplib::Server>();
97 int32_t allocPort = HTTP_MIN_PORT;
98 if (newServer == nullptr) {
99 PRINT_HILOGE("newServer is null");
100 return false;
101 }
102 if (!AllocatePort(newServer, allocPort)) {
103 PRINT_HILOGE("AllocatePort fail, return!");
104 return false;
105 }
106 port = allocPort;
107 printHttpServerMap[printerName] = newServer;
108 printHttpPortMap[printerName] = port;
109 std::shared_ptr<PrintHttpRequestProcess> newProcess = std::make_shared<PrintHttpRequestProcess>();
110 if (newProcess == nullptr) {
111 PRINT_HILOGE("newProcess is null");
112 return false;
113 }
114 printHttpProcessMap[printerName] = newProcess;
115 newProcess->SetDeviceName(printerName);
116
117 std::thread tServer = std::thread([this, printerName] {
118 this->StartServer(this->printHttpServerMap[printerName], this->printHttpProcessMap[printerName]);
119 });
120 tServer.detach();
121 return true;
122 }
123
StopServer(std::string printerName)124 void PrintHttpServerManager::StopServer(std::string printerName)
125 {
126 PRINT_HILOGD("stopServer printerName: %{public}s", printerName.c_str());
127 if (printHttpServerMap.find(printerName) != printHttpServerMap.end()) {
128 if (printHttpServerMap[printerName]->is_running()) {
129 printHttpServerMap[printerName]->stop();
130 printHttpServerMap.erase(printerName);
131 }
132 }
133 if (printHttpPortMap.find(printerName) != printHttpPortMap.end()) {
134 printHttpPortMap.erase(printerName);
135 }
136 if (printHttpProcessMap.find(printerName) != printHttpProcessMap.end()) {
137 printHttpProcessMap[printerName]->Stop();
138 printHttpProcessMap.erase(printerName);
139 }
140 }
141
DealUsbDevDetach(const std::string &devStr)142 void PrintHttpServerManager::DealUsbDevDetach(const std::string &devStr)
143 {
144 PRINT_HILOGD("devStr: %{public}s", devStr.c_str());
145 cJSON *devJson = cJSON_Parse(devStr.c_str());
146 if (!devJson) {
147 PRINT_HILOGE("Create devJson error");
148 return;
149 }
150 cJSON *jsonTemp = cJSON_GetObjectItem(devJson, "name");
151 if (jsonTemp == nullptr || jsonTemp->valuestring == NULL) {
152 PRINT_HILOGE("The devJson does not have a necessary attribute.");
153 cJSON_Delete(devJson);
154 return;
155 }
156 std::string name = jsonTemp->valuestring;
157 std::string printerName = DelayedSingleton<PrintUsbManager>::GetInstance()->GetPrinterName(name);
158 PRINT_HILOGD("DealUsbDevDetach name: %{public}s, printerName: %{public}s", name.c_str(), printerName.c_str());
159 if (printerName.empty()) {
160 cJSON_Delete(devJson);
161 return;
162 }
163 StopServer(printerName);
164 cJSON_Delete(devJson);
165 }
166 }
167 #endif // IPPOVERUSB_ENABLE