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     if (port < HTTP_MIN_PORT || port > HTTP_MAX_PORT) {
97         PRINT_HILOGE("port error!");
98         return false;
99     }
100 
101     std::shared_ptr<httplib::Server> newServer = std::make_shared<httplib::Server>();
102     if (newServer == nullptr) {
103         PRINT_HILOGE("newServer is null");
104         return false;
105     }
106 
107     if (!newServer->bind_to_port(LOCAL_HOST, port)) {
108         PRINT_HILOGE("bind to port : %{public}d failed.", port);
109         return false;
110     }
111     PRINT_HILOGI("bind to port : %{public}d success.", port);
112 
113     printHttpServerMap[printerName] = newServer;
114     printHttpPortMap[printerName] = port;
115     std::shared_ptr<PrintHttpRequestProcess> newProcess = std::make_shared<PrintHttpRequestProcess>();
116     if (newProcess == nullptr) {
117         PRINT_HILOGE("newProcess is null");
118         return false;
119     }
120     printHttpProcessMap[printerName] = newProcess;
121     newProcess->SetDeviceName(printerName);
122 
123     std::thread tServer = std::thread([this, printerName] {
124         this->StartServer(this->printHttpServerMap[printerName], this->printHttpProcessMap[printerName]);
125     });
126     tServer.detach();
127     return true;
128 }
129 
StopServer(std::string printerName)130 void PrintHttpServerManager::StopServer(std::string printerName)
131 {
132     PRINT_HILOGD("stopServer printerName: %{public}s", printerName.c_str());
133     if (printHttpServerMap.find(printerName) != printHttpServerMap.end()) {
134         if (printHttpServerMap[printerName]->is_running()) {
135             printHttpServerMap[printerName]->stop();
136             printHttpServerMap.erase(printerName);
137         }
138     }
139     if (printHttpPortMap.find(printerName) != printHttpPortMap.end()) {
140         printHttpPortMap.erase(printerName);
141     }
142     if (printHttpProcessMap.find(printerName) != printHttpProcessMap.end()) {
143         printHttpProcessMap[printerName]->Stop();
144         printHttpProcessMap.erase(printerName);
145     }
146 }
147 
DealUsbDevDetach(const std::string & devStr)148 void PrintHttpServerManager::DealUsbDevDetach(const std::string &devStr)
149 {
150     PRINT_HILOGD("devStr: %{public}s", devStr.c_str());
151     cJSON *devJson = cJSON_Parse(devStr.c_str());
152     if (!devJson) {
153         PRINT_HILOGE("Create devJson error");
154         return;
155     }
156     cJSON *jsonTemp = cJSON_GetObjectItem(devJson, "name");
157     if (jsonTemp == nullptr || jsonTemp->valuestring  == nullptr) {
158         PRINT_HILOGE("The devJson does not have a necessary attribute.");
159         cJSON_Delete(devJson);
160         return;
161     }
162     std::string name = jsonTemp->valuestring;
163     std::string printerName = DelayedSingleton<PrintUsbManager>::GetInstance()->GetPrinterName(name);
164     PRINT_HILOGD("DealUsbDevDetach name: %{public}s, printerName: %{public}s", name.c_str(), printerName.c_str());
165     if (printerName.empty()) {
166         cJSON_Delete(devJson);
167         return;
168     }
169     StopServer(printerName);
170     cJSON_Delete(devJson);
171 }
172 }
173 #endif // IPPOVERUSB_ENABLE