Can't access .ONION websites using QT C++, How To do it? - c++

Can someone can tell me why my code does not work? I made a program using QT C++ to route through TOR, I can access normal websites and I have a different public IP but I can't access .ONION websites, I get no response and/or Host not found.
EDIT: AFTER FURTHER INSPECTION I THINK THE PROBLEM IS THAT I NEED TO RESOLVE THE DNS FOR THE .ONION ADDRESS, HOW CAN I DO THAT?
tester::tester(QObject *parent) :
QObject(parent)
{
}
QTcpSocket socket ;
void tester::GetUrl()
{
QNetworkProxy proxy;
proxy.setType(QNetworkProxy::DefaultProxy);
proxy.setHostName("127.0.0.1");
proxy.setPort(9050);
proxy.setCapabilities(QNetworkProxy::HostNameLookupCapability | proxy.capabilities());
QNetworkProxy::setApplicationProxy(proxy);
qDebug()<<"Connecting";
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
manager->setProxy(proxy);
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
//manager->get(QNetworkRequest(QUrl("http://www.whatsmyip.org"))); //works
//test access to random .onion website
manager->get(QNetworkRequest(QUrl("http://blackma6xtzkajcy2eahws4q65ayhnsa6kghu6oa6sci2ul47fq66jqd.onion/products.php")));
//test access to random .onion website via socket
socket.setProxy(proxy);
socket.connectToHost("http://blackma6xtzkajcy2eahws4q65ayhnsa6kghu6oa6sci2ul47fq66jqd.onion/products.php",9051);
qDebug() << "\nTCP SOCKET Response...\n";
if(!socket.waitForConnected(5000))
qDebug() << "Error: " + socket.errorString() +"\n";
}
void tester::replyFinished(QNetworkReply* Reply)
{
qDebug() << "Response...\n";
if (Reply->isOpen())
{
qDebug()<<Reply->read((5000));
Reply->close();
}
qDebug() << "\nTCP SOCKET Response...\n";
if(!socket.waitForConnected(5000))
qDebug() << "Error: " + socket.errorString() +"\n";
}

Related

Network reply always empty with error : RemoteHostClosedError

I have a secured URL working with an x509 certificate and I am supposed to receive a JSON as an answer. My certificate is in pfx format (ca certificate, local certificate, key). I added it on the computer and when launching a request on google chrome and internet explorer with the secured URL I have indeed the JSON as an answer.
My problem is when I try to do the same inside my Qt application I do not have any answer from the same URL. My code :
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setProtocol(QSsl::TlsV1_2);
_manager = std::make_unique<QNetworkAccessManager>();
auto line = "myurl";
qInfo() << line;
QNetworkRequest request((QUrl::fromUserInput(line)));
request.setSslConfiguration(config);
QEventLoop loop;
connect(_manager.get(), &QNetworkAccessManager::finished, &loop,
&QEventLoop::quit,
Qt::DirectConnection);
connect(_manager.get(), &QNetworkAccessManager::sslErrors, this,
&CheckConfController::sslErrors);
_loginReply = std::unique_ptr<QNetworkReply>(_manager->get(request));
connect(_loginReply.get(), &QNetworkReply::readyRead,
this, &CheckConfController::replyFinished);
connect(_loginReply.get(), &QNetworkReply::finished,
this, &CheckConfController::_loginReceive);
loop.exec();
The login receive method :
void CheckConfController::_loginReceive(){
qInfo() << "status code : " << _loginReply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
qInfo() << "error : " << _loginReply->error();
qInfo() << "error string : " << _loginReply->errorString();
QByteArray b = _loginReply->readAll();
qInfo() << "byte : " << b;
}
The SSL error method :
void CheckConfController::sslErrors(QNetworkReply* reply, const QList<QSslError> &errors)
{
QByteArray b = reply->readAll();
qInfo() << "reply : " << b;
for(auto element : errors){
qInfo() << "ssl error : " << element;
}
}
This is mu Outpput :
status code: QVariant(Invalid)
error: QNetworkReply::RemoteHostClosedError
err string: "Connection Closed"
byte : ""
SSL error is never called.
I switched my URL line to https://www.google.com and it works fine. I also tried with other urls and i receive my json correctly.
This is my configuration:
Qt version: 5.12.11
compiler: MSVC 2017 64 bits
Computer running the application: Windows 7
Any help would be appreciated. Thank you.
Update
After comments below this answer, I noticed the server that OP is trying to reach has certificate limitations, hence defaulting to system certificates is not an option, because we can't be sure which certificate is used.
Now that we know that, I suggest ensuring that your certificate is somehow preferred, for example try:
QSslConfiguration::setDefaultConfiguration(config);
I mean, at end of OP's original code:
QSslKey key;
QSslCertificate certificate;
QList<QSslCertificate> certChain;
bool imported = QSslCertificate::importPkcs12(&pfxFile, &key, &certificate, &certChain, "mypassphrase");
qInfo() << "imported : " << imported;
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setCaCertificates(certChain);
config.setLocalCertificate(certificate);
config.setPrivateKey(key);
config.setProtocol(QSsl::TlsV1_2);
Old answer
As comments said:
OP no longer adds certificate manually (and adds it to system),
Also, OP's code works for other HTTPS URLs.
Last but not least, OP's Site has valid certificate, and logs just mention closed connection.
Counting all together, this does not seem to have anything to do with Qt. OP's site simply rejects any JSON request.
Maybe try setting auth header (or, do whatever else the site's requirements are).
I usually use Postman App (to test sites' API and routes).

Client Server program in qt

I am new in Qt, I want to write a simple client server program that client send a message to server and server get it and send it back to client.I wrote the server program but i have problem in client and I don't know how should I write it. could you please help me?
Here is my client code:
#include "myclient.h"
#include "QTcpsocket"
#include "QTcpServer"
#include "mainwindow.h"
Client::Client(QObject* parent): QObject(parent)
{
connect(&client, SIGNAL(connected()),this, SLOT(sendData()),Qt::DirectConnection);
}
void myclient::attemptConnection()
{
connect(QTcpSocket, SIGNAL(newConnection()), this, SLOT(connectionAccepted()));
if(QTcpSocket->listen("127.0.0.1",1234))
{
qDebug() << "Server listening";
}
else
{
qDebug() << "Couldn't listen to port" << server->serverPort() << ":" << server->errorString();
}
}
void myclient::connect()
{
QTcpSocket->connectToHost(LocalHost,1234,QIODevice::ReadWrite);
if(QTcpSocket->waitForConnected())
{
QString string = "Hello";
QByteArray array;
array.append(string);
qDebug()<<QTcpSocket->write(array);
}
else
{
qDebug() << "couldn't connect";
}
}
QTcpSocket socket;
void myclient::connectionAccepted()
{
qDebug()<<"Connected";
connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
}
void myclient::readSocket()
{
qDebug()<<socket->readBufferSize();
QByteArray = socket->readAll();
}
I think You Should take A look at the Forutne Client Example From Qt Docs, And base your code on it.
In your code you are using Both Blocking Functions from the waitFor*(), And Non-Blocking signals/slots (readyRead() signal), The Non-Blocking approach is Highly recommended (especially if the code is executed in the GUI thread).
Also I am not sure about your function attemptConnection, which uses newConnection() signal, new Connection is not even a member of QTcpSocket.

BB 10 Cascades Internet Check

I need to check the Internet Connection If I get Socket Error. I am proceeding like this,
void Client::socketError(QAbstractSocket::SocketError socketError) {
HttpPost("https://www.google.co.in/");
}
void Client::HttpPost(QString URL ) {
QNetworkRequest request = QNetworkRequest();
request.setUrl(QUrl(URL));
QNetworkAccessManager *mNetworkAccessManager = new QNetworkAccessManager(this);
bool result = connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(HttpResponse(QNetworkReply *)));
mNetworkAccessManager->get(request);
qDebug() << "::: Client.cpp Request made to Service :::";
}
void Client::HttpResponse(QNetworkReply* reply) {
if (reply->error() == QNetworkReply::NoError) {
qDebug() << "\n Internet Ok **********";
} else {
qDebug() << "\n No Internet **********" << reply->errorString();
showDialog("No Inernet");
}
}
and I am connecting to Signals and Slots like
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(socketError(QAbstractSocket::SocketError)));
But some times I am getting "No Internet Dialog " Even If wi-fi Is Available. Why ?
Method 2:
// this method will return true If Net is available false other wise
// but even this is return false some times even Wi fi signal is Available
bool Client::isNetworkAvailable() {
bool isFound = false;
QNetworkConfigurationManager netMgr;
QList<QNetworkConfiguration> mNetList = netMgr.allConfigurations(QNetworkConfiguration::Active);
if (mNetList.count() > 0) {
if (netMgr.isOnline()) {
isFound = true;
}
}
qDebug() << "\n ************** isNetworkAvailable:::" << isFound;
return isFound;
}
Is there a problem in my code?
Your network check snippet seems a bit too complicated. You could simply just call the following method:
bool QNetworkConfigurationManager::isOnline () const
Returns true if the system is considered to be connected to another device via an active network interface; otherwise returns false.
If this does not work for someone, it very likely means that the internet connection is unreliably, especially if it does not work randomly.
What about
NetworkAccessibility QNetworkAccessManager::networkAccessible ()
networkAccessible : NetworkAccessibility
This property holds whether the network is currently accessible via
this network access manager.
If the network is not accessible the network access manager will not
process any new network requests, all such requests will fail with an
error. Requests with URLs with the file:// scheme will still be
processed.

How to write Client-Server application and implement simple protocol in Qt

Maybe this is stupid question, actually it's appeal, or Qt is just to complicated for me.
Here's the thing:
I'm used to java when writing client-server application, and it's very simple. I would like to do same things in C++ (I'm very familiar with C++ itself), and I choose to learn Qt. I tried to write some applications in qt, but with partial success.
First thing that bothers me is signals and slots. I know how to use them in GUI programming but it confuses me with networking. And there's problem with blocking. When I call BufferedReader's readLine() method in java it blocks until it receives line from socket connection. In Qt I must make sure that there is line available every time, and handle it when there isn't one.
And when I connect QSocket's error signal to some of my custom slots, the signal is emitted when server sends last line and closes the connection, and in client's slot/function that reads I never read that last line. That are some problems I faced so far.
Slots and checking if there is data available makes me confused when I had to implements even the simplest protocols.
Important part:
I tried to find good example on the internet, but problem is that all examples are to complicated an big. Is there anyone how can show me how to write simple client-server application. Server accepts only one client. Client sends textual line containing command. If command is "ADD" or "SUB", server sends "SUP" indicating that command is supported. Otherwise it sends "UNS" and closes the connection. If client receives "SUP" it sends to more lines containing numbers to be subtracted or added. Server responds with result and closes connection.
I know that C++ requires more coding, but in Java this would take only 5 minutes, so it shouldn't take to long to write it in C++ either.
I'm sure this example would be very valuable to anyone who wants to learn networking in Qt.
edit:
This is my try to make the application (described above):
here is the server part:
#ifndef TASK_H
#define TASK_H
#include <QObject>
#include <QTcpServer>
class Task : public QObject
{
Q_OBJECT
public:
Task(QObject *parent = 0) : QObject(parent) {}
public slots:
void run();
void on_newConnection();
void on_error(QAbstractSocket::SocketError);
signals:
void finished();
private:
QTcpServer server;
};
#endif // TASK_H
void Task::run()
{
connect(&server,SIGNAL(newConnection()),this,SLOT(on_newConnection()));
connect(&server,SIGNAL(acceptError(QAbstractSocket::SocketError)),this,SLOT(on_error(QAbstractSocket::SocketError)));
if(server.listen(QHostAddress::LocalHost, 9000)){
qDebug() << "listening";
}else{
qDebug() << "cannot listen";
qDebug() << server.errorString();
}
}
void Task::on_newConnection(){
std::cout << "handeling new connection...\n";
QTcpSocket* socket = server.nextPendingConnection();
QTextStream tstream(socket);
while(!socket->canReadLine()){
socket->waitForReadyRead((-1));
}
QString operation = tstream.readLine();
qDebug() << "dbg:" << operation;
if(operation != "ADD" && operation != "SUB"){
tstream << "UNS\n";
tstream.flush();
socket->disconnect();
return;
}
tstream << "SUP\n";
tstream.flush();
double op1,op2;
while(!socket->canReadLine()){
socket->waitForReadyRead((-1));
}
op1 = socket->readLine().trimmed().toDouble();
qDebug() << "op1:" << op1;
while(!socket->canReadLine()){
socket->waitForReadyRead(-1);
}
op2 = socket->readLine().trimmed().toDouble();
qDebug() << "op2:" << op2;
double r;
if(operation == "ADD"){
r = op1 + op2;
}else{
r = op1 - op2;
}
tstream << r << "\n";
tstream.flush();
qDebug() << "result is: " << r;
socket->disconnect();
}
void Task::on_error(QAbstractSocket::SocketError ){
qDebug() << "server error";
server.close();
}
This is client side (header is similar to server's so I wont post it):
void Task::run()
{
QTcpSocket socket;
std::string temp;
socket.connectToHost(QHostAddress::LocalHost,9000);
if(socket.waitForConnected(-1))
qDebug() << "connected";
else {
qDebug() << "cannot connect";
return;
}
QTextStream tstream(&socket);
QString op;
std::cout << "operation: ";
std::cin >> temp;
op = temp.c_str();
tstream << op << "\n";
tstream.flush();
qDebug() << "dbg:" << op << "\n";
while(!socket.canReadLine()){
socket.waitForReadyRead(-1);
}
QString response = tstream.readLine();
qDebug() << "dbg:" << response;
if(response == "SUP"){
std::cout << "operand 1: ";
std::cin >> temp;
op = temp.c_str();
tstream << op + "\n";
std::cout << "operand 2: ";
std::cin >> temp;
op = temp.c_str();
tstream << op + "\n";
tstream.flush();
while(!socket.canReadLine()){
socket.waitForReadyRead(-1);
}
QString result = tstream.readLine();
std::cout << qPrintable("result is: " + result);
}else if(response == "UNS"){
std::cout << "unsupported operatoion.";
}else{
std::cout << "unknown error.";
}
emit finished();
}
What I could do better?
What are some good practices in similar situations?
When using blocking (not signal/slot mechanism), what is the best way to handle event when other side closes the connection?
Can someone rewrite this to make it look more professional (I just what to see how it supposed to look like, because I think that my solution is far from perfect) ?
Can someone rewrite this using signals and slots?
Thanks you.
Sorry for my English, and probably stupidity :)
Networking with Qt is not that difficult.
Communication between two points is handled by a single class; in the case of TCP/IP, that would be the QTcpSocket class. Both the client and server will communicate with a QTcpSocket object.
The only difference with the server is that you start with a QTcpServer object and call listen() to await a connection...
QTcpServer* m_pTcpServer = new QTcpServer
//create the address that the server will listen on
QHostAddress addr(QHostAddress::LocalHost); // assuming local host (127.0.0.1)
// start listening
bool bListening = m_pServer->listen(addr, _PORT); //_PORT defined as whatever port you want to use
When the server receives a connection from a client QTcpSocket, it will notify you with a newConnection signal, so assuming you've made a connection to a socket in your own class to receive that signal, we can get the server QTcpSocket object to communicate with the client...
QTcpSocket* pServerSocket = m_pServer->nextPendingConnection();
The server will receive a QTcpSocket object for each connection made. The server socket can now be used to send data to a client socket, using the a write method...
pServerSocket->write("Hello!");
When a socket (either client or server) receives data, it emits the readyRead signal. So, assuming you have made a connection to the readyRead signal for the socket, a slot function can retrieve the data...
QString msg = pSocket->readAll();
The other code you'll need is to handle the connect, disconnect and error signals, which you should connect relevant slots for receiving these notifications.
Ensure you only send data when you know the connection has been made. Normally, I would have the server receive a connection and send a 'hello' message back to the client. Once the client receives the message, it knows it can send to the server.
When either side disconnects, the remaining side will receive the disconnect signal and can act appropriately.
As for the client, it will just have one QTcpSocket object and after calling connectToHost, you will either receive a connected signal if the connection was succesfully made, or the error signal.
Finally, you can use QLocalServer and QLocalSocket in the same way, if you're just trying to communicate between processes on the same machine.

Send HTTP post request BlackBerry 10

I am developing an app on BB 10 based on C++ where I need to send HTTP post requests to the server and retrieve some JSON data. Are there some framework classes that help you send HTTP post requests to the server? Any links to code etc.? Thanks.
I can't remember which sample app I found this code in, but this worked for what I needed in my app.
Add the following in c++
header file (.hpp)
public:
Q_INVOKABLE void doNetworkRequest(QString url);
signals:
void networkReply(const QVariantMap &data);
void networkError();
private Q_SLOTS:
void handleNetworkData(QNetworkReply *reply);
private:
QNetworkAccessManager networkManager;
Then in add this in your main file (.cpp)
this goes inside the main app function
// Hook this signal so we can respond to network replies
connect(&networkManager, SIGNAL(finished(QNetworkReply *)), this,
SLOT(handleNetworkData(QNetworkReply *)));
add these functions:
void Top12Wines::doNetworkRequest(QString url)
{
qDebug() << "Request URL " << url;
QUrl qurl = url;
networkManager.get(QNetworkRequest(qurl));
}
void Top12Wines::handleNetworkData(QNetworkReply *reply)
{
if (!reply->error()) {
qDebug() << "Got network data";
// Let's get ALL the data
const QByteArray response(reply->readAll());
JsonDataAccess jda;
QVariantMap results = jda.loadFromBuffer(response).toMap();
emit networkReply(results);
} else {
qDebug() << "Got network error";
emit networkError();
}
// Cleanup
reply->deleteLater();
}
Then in your QML you can access it like so:
_App.networkReply.connect(checkVersion); //
_App.networkError.connect(checkVersionError);
_App.doNetworkRequest("http://myserver/version.json");
function checkVersion(data)
{
_App.networkReply.disconnect(checkVersion); //disconnect links after retrieving data
_App.networkError.disconnect(checkVersionError);
var newVersion = data.version;
}
function checkVersionError()
{
_App.networkReply.disconnect(checkVersion); //disconnect links after retrieving data
_App.networkError.disconnect(checkVersionError);
//do something to alert user that an error occurred.
}