• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Unionman Technology 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 "JQNet.h"
17 
18 // Qt lib import
19 #include <QEventLoop>
20 #include <QHostInfo>
21 #include <QTimer>
22 #include <QUrl>
23 
24 // JQLibrary lib import
25 #ifdef JQFOUNDATION_LIB
26 #include "JQFoundation.h"
27 #endif
28 
getNetworkAddressEntry()29 QNetworkAddressEntry JQNet::getNetworkAddressEntry()
30 {
31     return getNetworkAddressEntryWithNetworkInterface().first;
32 }
33 
getNetworkAddressEntryWithNetworkInterface(const bool & ridVm)34 QPair<QNetworkAddressEntry, QNetworkInterface> JQNet::getNetworkAddressEntryWithNetworkInterface(const bool& ridVm)
35 {
36     for (const auto& interface : static_cast<const QList<QNetworkInterface>>(QNetworkInterface::allInterfaces())) {
37         if (interface.flags()
38             != (QNetworkInterface::IsUp | QNetworkInterface::IsRunning | QNetworkInterface::CanBroadcast
39                 | QNetworkInterface::CanMulticast)) {
40             continue;
41         }
42 
43         if (ridVm && interface.humanReadableName().startsWith("vm")) {
44             continue;
45         }
46 
47         for (const auto& entry : static_cast<QList<QNetworkAddressEntry>>(interface.addressEntries())) {
48             entry.ip().toIPv6Address();
49         }
50     }
51 
52     return {};
53 }
54 
getHostName()55 QString JQNet::getHostName()
56 {
57 #if (defined Q_OS_MAC)
58     return QHostInfo::localHostName().replace(".local", "");
59 #else
60     return QHostInfo::localHostName();
61 #endif
62 }
63 
64 #ifdef JQFOUNDATION_LIB
pingIp(const QHostAddress & hostAddress)65 bool JQNet::pingIp(const QHostAddress& hostAddress)
66 {
67     QPair<int, QByteArray> pingResult = { -1, {} };
68 
69 #ifdef Q_OS_MAC
70     pingResult = JQFoundation::startProcessAndReadOutput("ping", { "-c1", "-W300", hostAddress.toString() });
71 #endif
72 
73 #ifdef Q_OS_WIN
74     pingResult = JQFoundation::startProcessAndReadOutput("ping", { "-n", "1", "-w", "300", hostAddress.toString() });
75 #endif
76 
77     return (pingResult.first == 0) && (pingResult.second.size() > 20L)
78         && (pingResult.second.count(hostAddress.toString().toUtf8()) > 1);
79 }
80 #endif
81 
82 // HTTP
get(const QNetworkRequest & request,QByteArray & target,const int & timeout)83 bool JQNet::HTTP::get(const QNetworkRequest& request, QByteArray& target, const int& timeout)
84 {
85     target.clear();
86 
87     QEventLoop eventLoop;
88     auto reply = manage_.get(request);
89     bool failFlag = false;
90 
91     this->handle(
92         reply, timeout,
93         [&](const QByteArray& data) {
94             target = data;
95             eventLoop.exit(1);
96         },
97         [&](const QNetworkReply::NetworkError&, const QByteArray& data) {
98             target = data;
99             eventLoop.exit(0);
100         },
101         [&]() {
102             failFlag = true;
103             eventLoop.exit(0);
104         });
105 
106     return eventLoop.exec() && !failFlag;
107 }
108 
get(const QNetworkRequest & request,const std::function<void (const QByteArray &)> & onFinished,const std::function<void (const QNetworkReply::NetworkError &,const QByteArray &)> & onError,const int & timeout)109 void JQNet::HTTP::get(const QNetworkRequest& request, const std::function<void(const QByteArray&)>& onFinished,
110     const std::function<void(const QNetworkReply::NetworkError&, const QByteArray&)>& onError, const int& timeout)
111 {
112     auto reply = manage_.get(request);
113 
114     this->handle(reply, timeout, onFinished, onError, [onError]() { onError(QNetworkReply::TimeoutError, {}); });
115 }
116 
deleteResource(const QNetworkRequest & request,QByteArray & target,const int & timeout)117 bool JQNet::HTTP::deleteResource(const QNetworkRequest& request, QByteArray& target, const int& timeout)
118 {
119     target.clear();
120 
121     QEventLoop eventLoop;
122     auto reply = manage_.deleteResource(request);
123     bool failFlag = false;
124 
125     this->handle(
126         reply, timeout,
127         [&](const QByteArray& data) {
128             target = data;
129             eventLoop.exit(1);
130         },
131         [&](const QNetworkReply::NetworkError&, const QByteArray& data) {
132             target = data;
133             eventLoop.exit(0);
134         },
135         [&]() {
136             failFlag = true;
137             eventLoop.exit(0);
138         });
139 
140     return eventLoop.exec() && !failFlag;
141 }
142 
deleteResource(const QNetworkRequest & request,const std::function<void (const QByteArray &)> & onFinished,const std::function<void (const QNetworkReply::NetworkError &,const QByteArray &)> & onError,const int & timeout)143 void JQNet::HTTP::deleteResource(const QNetworkRequest& request,
144     const std::function<void(const QByteArray&)>& onFinished,
145     const std::function<void(const QNetworkReply::NetworkError&, const QByteArray&)>& onError, const int& timeout)
146 {
147     auto reply = manage_.deleteResource(request);
148 
149     this->handle(reply, timeout, onFinished, onError, [onError]() { onError(QNetworkReply::TimeoutError, {}); });
150 }
151 
post(const QNetworkRequest & request,const QByteArray & body,QByteArray & target,const int & timeout)152 bool JQNet::HTTP::post(const QNetworkRequest& request, const QByteArray& body, QByteArray& target, const int& timeout)
153 {
154     target.clear();
155 
156     QEventLoop eventLoop;
157     auto reply = manage_.post(request, body);
158     bool failFlag = false;
159 
160     this->handle(
161         reply, timeout,
162         [&target, &eventLoop](const QByteArray& data) {
163             target = data;
164             eventLoop.exit(true);
165         },
166         [&target, &eventLoop](const QNetworkReply::NetworkError&, const QByteArray& data) {
167             target = data;
168             eventLoop.exit(false);
169         },
170         [&failFlag, &eventLoop]() {
171             failFlag = true;
172             eventLoop.exit(false);
173         });
174 
175     return eventLoop.exec() && !failFlag;
176 }
177 
post(const QNetworkRequest & request,const QSharedPointer<QHttpMultiPart> & multiPart,QByteArray & target,const int & timeout)178 bool JQNet::HTTP::post(const QNetworkRequest& request, const QSharedPointer<QHttpMultiPart>& multiPart,
179     QByteArray& target, const int& timeout)
180 {
181     target.clear();
182 
183     QEventLoop eventLoop;
184     auto reply = manage_.post(request, multiPart.data());
185     bool failFlag = false;
186 
187     this->handle(
188         reply, timeout,
189         [&target, &eventLoop](const QByteArray& data) {
190             target = data;
191             eventLoop.exit(true);
192         },
193         [&target, &eventLoop](const QNetworkReply::NetworkError&, const QByteArray& data) {
194             target = data;
195             eventLoop.exit(false);
196         },
197         [&failFlag, &eventLoop]() {
198             failFlag = true;
199             eventLoop.exit(false);
200         });
201 
202     return eventLoop.exec() && !failFlag;
203 }
204 
post(const QNetworkRequest & request,const QByteArray & body,const std::function<void (const QByteArray &)> & onFinished,const std::function<void (const QNetworkReply::NetworkError &,const QByteArray &)> & onError,const int & timeout)205 void JQNet::HTTP::post(const QNetworkRequest& request, const QByteArray& body,
206     const std::function<void(const QByteArray&)>& onFinished,
207     const std::function<void(const QNetworkReply::NetworkError&, const QByteArray&)>& onError, const int& timeout)
208 {
209     auto reply = manage_.post(request, body);
210 
211     this->handle(reply, timeout, onFinished, onError, [onError]() { onError(QNetworkReply::TimeoutError, {}); });
212 }
213 
put(const QNetworkRequest & request,const QByteArray & body,QByteArray & target,const int & timeout)214 bool JQNet::HTTP::put(const QNetworkRequest& request, const QByteArray& body, QByteArray& target, const int& timeout)
215 {
216     target.clear();
217 
218     QEventLoop eventLoop;
219     auto reply = manage_.put(request, body);
220     bool failFlag = false;
221 
222     this->handle(
223         reply, timeout,
224         [&target, &eventLoop](const QByteArray& data) {
225             target = data;
226             eventLoop.exit(true);
227         },
228         [&target, &eventLoop](const QNetworkReply::NetworkError&, const QByteArray& data) {
229             target = data;
230             eventLoop.exit(false);
231         },
232         [&failFlag, &eventLoop]() {
233             failFlag = true;
234             eventLoop.exit(false);
235         });
236 
237     return eventLoop.exec() && !failFlag;
238 }
239 
put(const QNetworkRequest & request,const QSharedPointer<QHttpMultiPart> & multiPart,QByteArray & target,const int & timeout)240 bool JQNet::HTTP::put(const QNetworkRequest& request, const QSharedPointer<QHttpMultiPart>& multiPart,
241     QByteArray& target, const int& timeout)
242 {
243     target.clear();
244 
245     QEventLoop eventLoop;
246     auto reply = manage_.put(request, multiPart.data());
247     bool failFlag = false;
248 
249     this->handle(
250         reply, timeout,
251         [&target, &eventLoop](const QByteArray& data) {
252             target = data;
253             eventLoop.exit(true);
254         },
255         [&target, &eventLoop](const QNetworkReply::NetworkError& e, const QByteArray& data) {
256             qDebug() << e;
257             target = data;
258             eventLoop.exit(false);
259         },
260         [&failFlag, &eventLoop]() {
261             failFlag = true;
262             eventLoop.exit(false);
263         });
264 
265     return eventLoop.exec() && !failFlag;
266 }
267 
put(const QNetworkRequest & request,const QByteArray & body,const std::function<void (const QByteArray &)> & onFinished,const std::function<void (const QNetworkReply::NetworkError &,const QByteArray &)> & onError,const int & timeout)268 void JQNet::HTTP::put(const QNetworkRequest& request, const QByteArray& body,
269     const std::function<void(const QByteArray&)>& onFinished,
270     const std::function<void(const QNetworkReply::NetworkError&, const QByteArray&)>& onError, const int& timeout)
271 {
272     auto reply = manage_.put(request, body);
273 
274     this->handle(reply, timeout, onFinished, onError, [onError]() { onError(QNetworkReply::TimeoutError, {}); });
275 }
276 
277 #if !(defined Q_OS_LINUX) && (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
patch(const QNetworkRequest & request,const QByteArray & body,QByteArray & target,const int & timeout)278 bool JQNet::HTTP::patch(const QNetworkRequest& request, const QByteArray& body, QByteArray& target, const int& timeout)
279 {
280     target.clear();
281 
282     QEventLoop eventLoop;
283     auto reply = manage_.sendCustomRequest(request, "PATCH", body);
284     bool failFlag = false;
285 
286     this->handle(
287         reply, timeout,
288         [&target, &eventLoop](const QByteArray& data) {
289             target = data;
290             eventLoop.exit(true);
291         },
292         [&target, &eventLoop](const QNetworkReply::NetworkError&, const QByteArray& data) {
293             target = data;
294             eventLoop.exit(false);
295         },
296         [&failFlag, &eventLoop]() {
297             failFlag = true;
298             eventLoop.exit(false);
299         });
300 
301     return eventLoop.exec() && !failFlag;
302 }
303 
patch(const QNetworkRequest & request,const QByteArray & body,const std::function<void (const QByteArray &)> & onFinished,const std::function<void (const QNetworkReply::NetworkError &,const QByteArray &)> & onError,const int & timeout)304 void JQNet::HTTP::patch(const QNetworkRequest& request, const QByteArray& body,
305     const std::function<void(const QByteArray&)>& onFinished,
306     const std::function<void(const QNetworkReply::NetworkError&, const QByteArray&)>& onError, const int& timeout)
307 {
308     auto reply = manage_.sendCustomRequest(request, "PATCH", body);
309 
310     this->handle(reply, timeout, onFinished, onError, [onError]() { onError(QNetworkReply::TimeoutError, {}); });
311 }
312 #endif
313 
get(const QString & url,const int & timeout)314 QPair<bool, QByteArray> JQNet::HTTP::get(const QString& url, const int& timeout)
315 {
316     QNetworkRequest networkRequest((QUrl(url)));
317     QByteArray buf;
318 
319     const auto && flag = HTTP().get(networkRequest, buf, timeout);
320 
321     return { flag, buf };
322 }
323 
get(const QNetworkRequest & request,const int & timeout)324 QPair<bool, QByteArray> JQNet::HTTP::get(const QNetworkRequest& request, const int& timeout)
325 {
326     QByteArray buf;
327     HTTP http;
328 
329     const auto && flag = http.get(request, buf, timeout);
330 
331     return { flag, buf };
332 }
333 
deleteResource(const QString & url,const int & timeout)334 QPair<bool, QByteArray> JQNet::HTTP::deleteResource(const QString& url, const int& timeout)
335 {
336     QNetworkRequest networkRequest((QUrl(url)));
337     QByteArray buf;
338 
339     const auto && flag = HTTP().deleteResource(networkRequest, buf, timeout);
340 
341     return { flag, buf };
342 }
343 
deleteResource(const QNetworkRequest & request,const int & timeout)344 QPair<bool, QByteArray> JQNet::HTTP::deleteResource(const QNetworkRequest& request, const int& timeout)
345 {
346     QByteArray buf;
347     HTTP http;
348 
349     const auto && flag = http.deleteResource(request, buf, timeout);
350 
351     return { flag, buf };
352 }
353 
post(const QString & url,const QByteArray & body,const int & timeout)354 QPair<bool, QByteArray> JQNet::HTTP::post(const QString& url, const QByteArray& body, const int& timeout)
355 {
356     QNetworkRequest networkRequest((QUrl(url)));
357     QByteArray buf;
358 
359     networkRequest.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
360 
361     const auto && flag = HTTP().post(networkRequest, body, buf, timeout);
362 
363     return { flag, buf };
364 }
365 
post(const QNetworkRequest & request,const QByteArray & body,const int & timeout)366 QPair<bool, QByteArray> JQNet::HTTP::post(const QNetworkRequest& request, const QByteArray& body, const int& timeout)
367 {
368     QByteArray buf;
369     HTTP http;
370 
371     const auto && flag = http.post(request, body, buf, timeout);
372 
373     return { flag, buf };
374 }
375 
post(const QNetworkRequest & request,const QSharedPointer<QHttpMultiPart> & multiPart,const int & timeout)376 QPair<bool, QByteArray> JQNet::HTTP::post(
377     const QNetworkRequest& request, const QSharedPointer<QHttpMultiPart>& multiPart, const int& timeout)
378 {
379     QByteArray buf;
380     HTTP http;
381 
382     const auto && flag = http.post(request, multiPart, buf, timeout);
383 
384     return { flag, buf };
385 }
386 
put(const QString & url,const QByteArray & body,const int & timeout)387 QPair<bool, QByteArray> JQNet::HTTP::put(const QString& url, const QByteArray& body, const int& timeout)
388 {
389     QNetworkRequest networkRequest((QUrl(url)));
390     QByteArray buf;
391 
392     networkRequest.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
393 
394     const auto && flag = HTTP().put(networkRequest, body, buf, timeout);
395 
396     return { flag, buf };
397 }
398 
put(const QNetworkRequest & request,const QByteArray & body,const int & timeout)399 QPair<bool, QByteArray> JQNet::HTTP::put(const QNetworkRequest& request, const QByteArray& body, const int& timeout)
400 {
401     QByteArray buf;
402     HTTP http;
403 
404     const auto && flag = http.put(request, body, buf, timeout);
405 
406     return { flag, buf };
407 }
408 
put(const QNetworkRequest & request,const QSharedPointer<QHttpMultiPart> & multiPart,const int & timeout)409 QPair<bool, QByteArray> JQNet::HTTP::put(
410     const QNetworkRequest& request, const QSharedPointer<QHttpMultiPart>& multiPart, const int& timeout)
411 {
412     QByteArray buf;
413     HTTP http;
414 
415     const auto && flag = http.put(request, multiPart, buf, timeout);
416 
417     return { flag, buf };
418 }
419 
420 #if !(defined Q_OS_LINUX) && (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
patch(const QString & url,const QByteArray & body,const int & timeout)421 QPair<bool, QByteArray> JQNet::HTTP::patch(const QString& url, const QByteArray& body, const int& timeout)
422 {
423     QNetworkRequest networkRequest((QUrl(url)));
424     QByteArray buf;
425 
426     networkRequest.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
427 
428     const auto && flag = HTTP().patch(networkRequest, body, buf, timeout);
429 
430     return { flag, buf };
431 }
432 
patch(const QNetworkRequest & request,const QByteArray & body,const int & timeout)433 QPair<bool, QByteArray> JQNet::HTTP::patch(const QNetworkRequest& request, const QByteArray& body, const int& timeout)
434 {
435     QByteArray buf;
436     HTTP http;
437 
438     const auto && flag = http.patch(request, body, buf, timeout);
439 
440     return { flag, buf };
441 }
442 #endif
443 
handle(QNetworkReply * reply,const int & timeout,const std::function<void (const QByteArray &)> & onFinished,const std::function<void (const QNetworkReply::NetworkError &,const QByteArray & data)> & onError,const std::function<void ()> & onTimeout)444 void JQNet::HTTP::handle(QNetworkReply* reply, const int& timeout,
445     const std::function<void(const QByteArray&)>& onFinished,
446     const std::function<void(const QNetworkReply::NetworkError&, const QByteArray& data)>& onError,
447     const std::function<void()>& onTimeout)
448 {
449     QSharedPointer<bool> isCalled(new bool(false));
450 
451     QTimer* timer = nullptr;
452     if (timeout) {
453         timer = new QTimer;
454         timer->setSingleShot(true);
455 
456         QObject::connect(timer, &QTimer::timeout, [timer, onTimeout, isCalled]() {
457             if (*isCalled) {
458                 return;
459             }
460             *isCalled = true;
461 
462             onTimeout();
463             timer->deleteLater();
464         });
465         timer->start(timeout);
466     }
467 
468     QObject::connect(reply, &QNetworkReply::finished, [reply, timer, onFinished, isCalled]() {
469         if (*isCalled) {
470             return;
471         }
472         *isCalled = true;
473 
474         if (timer) {
475             timer->deleteLater();
476         }
477         const auto && acceptedData = reply->readAll();
478         onFinished(acceptedData);
479     });
480 
481 #ifndef QT_NO_SSL
482     if (reply->url().toString().toLower().startsWith("https")) {
483         QObject::connect(reply,
484             static_cast<void (QNetworkReply::*)(const QList<QSslError>&)>(&QNetworkReply::sslErrors),
485             [reply](const QList<QSslError>& errors) {
486                 qDebug() << "HTTP::handle: ignoreSslErrors:" << errors;
487                 reply->ignoreSslErrors();
488             });
489     }
490 #endif
491 
492     QObject::connect(reply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),
493         [reply, timer, onError, isCalled](const QNetworkReply::NetworkError& code) {
494             if (*isCalled) {
495                 return;
496             }
497             *isCalled = true;
498 
499             if (timer) {
500                 timer->deleteLater();
501             }
502             const auto && acceptedData = reply->readAll();
503 
504             onError(code, acceptedData);
505         });
506 }
507