File indexing completed on 2024-05-26 05:13:56

0001 /***************************************************************************
0002  *   SPDX-FileCopyrightText: 2013 Volker Krause <vkrause@kde.org>          *
0003  *                                                                         *
0004  *   SPDX-License-Identifier: LGPL-2.0-or-later                            *
0005  ***************************************************************************/
0006 
0007 #include "session.h"
0008 
0009 #include "private/standarddirs_p.h"
0010 
0011 #include <QCoreApplication>
0012 #include <QFile>
0013 #include <QSettings>
0014 #include <QSocketNotifier>
0015 
0016 #include <fcntl.h>
0017 #include <iostream>
0018 #include <unistd.h>
0019 
0020 Session::Session(const QString &input, QObject *parent)
0021     : QObject(parent)
0022 {
0023     auto file = new QFile(this);
0024     if (input != QLatin1StringView("-")) {
0025         file->setFileName(input);
0026         if (!file->open(QFile::ReadOnly)) {
0027             qFatal("Failed to open %s", qPrintable(input));
0028         }
0029     } else {
0030         // ### does that work on Windows?
0031         const int flags = fcntl(0, F_GETFL);
0032         fcntl(0, F_SETFL, flags | O_NONBLOCK); // NOLINT(hicpp-signed-bitwise)
0033 
0034         if (!file->open(stdin, QFile::ReadOnly | QFile::Unbuffered)) {
0035             qFatal("Failed to open stdin!");
0036         }
0037         m_notifier = new QSocketNotifier(0, QSocketNotifier::Read, this);
0038         connect(m_notifier, &QSocketNotifier::activated, this, &Session::inputAvailable);
0039     }
0040     m_input = file;
0041 }
0042 
0043 Session::~Session()
0044 {
0045 }
0046 
0047 void Session::connectToHost()
0048 {
0049     const QSettings connectionSettings(Akonadi::StandardDirs::connectionConfigFile(), QSettings::IniFormat);
0050 
0051     QString serverAddress;
0052 #ifdef Q_OS_WIN
0053     serverAddress = connectionSettings.value(QStringLiteral("Data/NamedPipe"), QString()).toString();
0054 #else
0055     serverAddress = connectionSettings.value(QStringLiteral("Data/UnixPath"), QString()).toString();
0056 #endif
0057     if (serverAddress.isEmpty()) {
0058         qFatal("Unable to determine server address.");
0059     }
0060 
0061     auto socket = new QLocalSocket(this);
0062     connect(socket, &QLocalSocket::errorOccurred, this, &Session::serverError);
0063     connect(socket, &QLocalSocket::disconnected, this, &Session::serverDisconnected);
0064     connect(socket, &QIODevice::readyRead, this, &Session::serverRead);
0065     connect(socket, &QLocalSocket::connected, this, &Session::inputAvailable);
0066 
0067     m_session = socket;
0068     socket->connectToServer(serverAddress);
0069 
0070     m_connectionTime.start();
0071 }
0072 
0073 void Session::inputAvailable()
0074 {
0075     if (!m_session->isOpen()) {
0076         return;
0077     }
0078 
0079     if (m_notifier) {
0080         m_notifier->setEnabled(false);
0081     }
0082 
0083     if (m_input->atEnd()) {
0084         return;
0085     }
0086 
0087     QByteArray buffer(1024, Qt::Uninitialized);
0088     qint64 readSize = 0;
0089 
0090     while ((readSize = m_input->read(buffer.data(), buffer.size())) > 0) {
0091         m_session->write(buffer.constData(), readSize);
0092         m_sentBytes += readSize;
0093     }
0094 
0095     if (m_notifier) {
0096         m_notifier->setEnabled(true);
0097     }
0098 }
0099 
0100 void Session::serverDisconnected()
0101 {
0102     QCoreApplication::exit(0);
0103 }
0104 
0105 void Session::serverError(QLocalSocket::LocalSocketError socketError)
0106 {
0107     if (socketError == QLocalSocket::PeerClosedError) {
0108         QCoreApplication::exit(0);
0109         return;
0110     }
0111 
0112     std::cerr << qPrintable(m_session->errorString());
0113     QCoreApplication::exit(1);
0114 }
0115 
0116 void Session::serverRead()
0117 {
0118     QByteArray buffer(1024, Qt::Uninitialized);
0119     qint64 readSize = 0;
0120 
0121     while ((readSize = m_session->read(buffer.data(), buffer.size())) > 0) {
0122         write(1, buffer.data(), readSize);
0123         m_receivedBytes += readSize;
0124     }
0125 }
0126 
0127 void Session::printStats() const
0128 {
0129     std::cerr << "Connection time: " << m_connectionTime.elapsed() << " ms" << std::endl;
0130     std::cerr << "Sent: " << m_sentBytes << " bytes" << std::endl;
0131     std::cerr << "Received: " << m_receivedBytes << " bytes" << std::endl;
0132 }
0133 
0134 #include "moc_session.cpp"