diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -63,8 +63,6 @@ if(UNIX) ecm_add_tests( - klocalsockettest.cpp - klocalsocketservertest.cpp privilegejobtest.cpp NAME_PREFIX "kiocore-" LINK_LIBRARIES KF5::KIOCore KF5::I18n Qt5::Test Qt5::Network diff --git a/autotests/klocalsocketservertest.h b/autotests/klocalsocketservertest.h deleted file mode 100644 --- a/autotests/klocalsocketservertest.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#ifndef KLOCALSOCKETSERVERTEST_H -#define KLOCALSOCKETSERVERTEST_H - -#include - -class tst_KLocalSocketServer : public QObject -{ - Q_OBJECT -public: - tst_KLocalSocketServer(); - ~tst_KLocalSocketServer(); - -private Q_SLOTS: - void cleanup(); - - void listen_data(); - void listen(); - - void waitForConnection(); - void newConnection(); - - void accept(); - - void state(); - - void setMaxPendingConnections(); - - void abstractUnixSocket_data(); - void abstractUnixSocket(); -}; - -#endif diff --git a/autotests/klocalsocketservertest.cpp b/autotests/klocalsocketservertest.cpp deleted file mode 100644 --- a/autotests/klocalsocketservertest.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "klocalsocketservertest.h" -#include -#include - -#include -#include -#include "klocalsocket.h" - -static const char afile[] = "/tmp/afile"; -static const char asocket[] = "/tmp/asocket"; - -tst_KLocalSocketServer::tst_KLocalSocketServer() -{ - QFile f(QString::fromLatin1(QFile::encodeName(QLatin1String(afile)))); - f.open(QIODevice::ReadWrite | QIODevice::Truncate); -} - -tst_KLocalSocketServer::~tst_KLocalSocketServer() -{ - QFile::remove(QLatin1String(afile)); -} - -class TimedConnection: public QThread -{ - Q_OBJECT -public: - ~TimedConnection() override - { - wait(); - } -protected: - void run() override { - KLocalSocket socket; - QThread::usleep(200); - socket.connectToPath(QLatin1String(asocket)); - socket.waitForConnected(); - } -}; - -void tst_KLocalSocketServer::cleanup() -{ - QFile::remove(QLatin1String(asocket)); -} - -void tst_KLocalSocketServer::listen_data() -{ - QTest::addColumn("path"); - QTest::addColumn("success"); - - QTest::newRow("null") << QString() << false; - QTest::newRow("empty") << "" << false; - QTest::newRow("a-dir") << "/tmp/" << false; - QTest::newRow("not-a-dir") << QString(afile + QLatin1String("/foo")) << false; - QTest::newRow("not-permitted") << "/root/foo" << false; - QTest::newRow("valid") << asocket << true; -} - -void tst_KLocalSocketServer::listen() -{ - QFETCH(QString, path); - KLocalSocketServer server; - QTEST(server.listen(path), "success"); -} - -void tst_KLocalSocketServer::waitForConnection() -{ - KLocalSocketServer server; - QVERIFY(server.listen(QLatin1String(asocket))); - QVERIFY(!server.hasPendingConnections()); - - { - KLocalSocket socket; - socket.connectToPath(QLatin1String(asocket)); - QVERIFY(socket.waitForConnected()); - - // make sure we can accept that connection - QVERIFY(server.waitForNewConnection()); - QVERIFY(server.hasPendingConnections()); - delete server.nextPendingConnection(); - } - - // test a timeout now - QVERIFY(!server.hasPendingConnections()); - QVERIFY(!server.waitForNewConnection(0)); - QVERIFY(!server.waitForNewConnection(200)); - - { - // now try a timed connection - TimedConnection conn; - conn.start(); - QVERIFY(server.waitForNewConnection(500)); - QVERIFY(server.hasPendingConnections()); - delete server.nextPendingConnection(); - } -} - -void tst_KLocalSocketServer::newConnection() -{ - KLocalSocketServer server; - QVERIFY(server.listen(QLatin1String(asocket))); - QVERIFY(!server.hasPendingConnections()); - - // catch the signal - QSignalSpy spy(&server, SIGNAL(newConnection())); - - KLocalSocket socket; - socket.connectToPath(QLatin1String(asocket)); - QVERIFY(socket.waitForConnected()); - - // let the events be processed - QTest::qWait(100); - - QVERIFY(spy.count() == 1); -} - -void tst_KLocalSocketServer::accept() -{ - KLocalSocketServer server; - QVERIFY(server.listen(QLatin1String(asocket))); - QVERIFY(!server.hasPendingConnections()); - - KLocalSocket socket; - socket.connectToPath(QLatin1String(asocket)); - QVERIFY(socket.waitForConnected()); - QVERIFY(server.waitForNewConnection()); - QVERIFY(server.hasPendingConnections()); - - KLocalSocket *socket2 = server.nextPendingConnection(); - QVERIFY(!server.hasPendingConnections()); - QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); - QCOMPARE(socket2->state(), QAbstractSocket::ConnectedState); - - delete socket2; -} - -void tst_KLocalSocketServer::state() -{ - KLocalSocketServer server; - - // sanity check of the initial state: - QVERIFY(!server.isListening()); - QVERIFY(server.localPath().isEmpty()); - QCOMPARE(int(server.localSocketType()), int(KLocalSocket::UnknownLocalSocketType)); - QVERIFY(!server.hasPendingConnections()); - QVERIFY(!server.nextPendingConnection()); - - // it's not connected, so it shouldn't change timedOut - bool timedOut = true; - QVERIFY(!server.waitForNewConnection(0, &timedOut)); - QVERIFY(timedOut); - timedOut = false; - QVERIFY(!server.waitForNewConnection(0, &timedOut)); - QVERIFY(!timedOut); - - // start listening: - QVERIFY(server.listen(QLatin1String(asocket))); - QVERIFY(server.isListening()); - QCOMPARE(server.localPath(), QString(QLatin1String(asocket))); - QCOMPARE(int(server.localSocketType()), int(KLocalSocket::UnixSocket)); - QVERIFY(!server.hasPendingConnections()); - QVERIFY(!server.nextPendingConnection()); - - // it must timeout now: - timedOut = false; - QVERIFY(!server.waitForNewConnection(0, &timedOut)); - QVERIFY(timedOut); - - // make a connection: - KLocalSocket socket; - socket.connectToPath(QLatin1String(asocket)); - QVERIFY(socket.waitForConnected()); - - // it mustn't time out now: - timedOut = true; - QVERIFY(server.waitForNewConnection(0, &timedOut)); - QVERIFY(!timedOut); - - QVERIFY(server.hasPendingConnections()); - KLocalSocket *socket2 = server.nextPendingConnection(); - QVERIFY(socket2); - delete socket2; - - // close: - server.close(); - - // verify state: - QVERIFY(!server.isListening()); - QVERIFY(server.localPath().isEmpty()); - QCOMPARE(int(server.localSocketType()), int(KLocalSocket::UnknownLocalSocketType)); - QVERIFY(!server.hasPendingConnections()); - QVERIFY(!server.nextPendingConnection()); -} - -void tst_KLocalSocketServer::setMaxPendingConnections() -{ - KLocalSocketServer server; - QVERIFY(server.listen(QLatin1String(asocket))); - QVERIFY(!server.hasPendingConnections()); - server.setMaxPendingConnections(0); // we don't want to receive - - // check if the event loop won't cause a connection to accepted - KLocalSocket socket; - socket.connectToPath(QLatin1String(asocket)); - QTest::qWait(100); // 100 ms doing absolutely nothing - QVERIFY(!server.hasPendingConnections()); - - // now check if we get that connection - server.setMaxPendingConnections(1); - QTest::qWait(100); - QVERIFY(server.hasPendingConnections()); - delete server.nextPendingConnection(); - QVERIFY(socket.waitForDisconnected()); - - // check if we receive only one of the two pending connections - KLocalSocket socket2; - socket.connectToPath(QLatin1String(asocket)); - socket2.connectToPath(QLatin1String(asocket)); - QTest::qWait(100); - - QVERIFY(server.hasPendingConnections()); - delete server.nextPendingConnection(); - QVERIFY(!server.hasPendingConnections()); - QVERIFY(!server.nextPendingConnection()); -} - -void tst_KLocalSocketServer::abstractUnixSocket_data() -{ -#ifndef Q_OS_LINUX - QSKIP("Abstract UNIX sockets are specific for Linux"); -#endif - QTest::addColumn("path"); - QTest::addColumn("success"); - - QTest::newRow("null") << QString() << false; - QTest::newRow("empty") << "" << false; -#if 0 - // apparently, we are allowed to put sockets there, even if we don't have permission to - QTest::newRow("a-dir") << "/tmp/" << false; - QTest::newRow("not-a-dir") << afile + QLatin1String("/foo") << false; - QTest::newRow("not-permitted") << "/root/foo" << false; -#endif - QTest::newRow("valid") << asocket << true; -} - -void tst_KLocalSocketServer::abstractUnixSocket() -{ - QFETCH(QString, path); - QFETCH(bool, success); - - if (success) { - QVERIFY(!QFile::exists(path)); - } - - KLocalSocketServer server; - QCOMPARE(server.listen(path, KLocalSocket::AbstractUnixSocket), success); - - if (success) { - // the socket must not exist in the filesystem - QVERIFY(!QFile::exists(path)); - - // now try to connect to it - KLocalSocket socket; - socket.connectToPath(path, KLocalSocket::AbstractUnixSocket); - QVERIFY(socket.waitForConnected(100)); - QVERIFY(server.waitForNewConnection(100)); - QVERIFY(server.hasPendingConnections()); - - // the socket must still not exist in the filesystem - QVERIFY(!QFile::exists(path)); - - // verify that they can exchange data too: - KLocalSocket *socket2 = server.nextPendingConnection(); - QByteArray data("Hello"); - socket2->write(data); - QVERIFY(socket2->bytesToWrite() == 0 || socket2->waitForBytesWritten(100)); - QVERIFY(socket.waitForReadyRead(100)); - QCOMPARE(socket.read(data.length()), data); - - socket.write(data); - QVERIFY(socket.bytesToWrite() == 0 || socket.waitForBytesWritten(100)); - QVERIFY(socket2->waitForReadyRead(100)); - QCOMPARE(socket2->read(data.length()), data); - - delete socket2; - QVERIFY(socket.waitForDisconnected(100)); - } -} - -QTEST_MAIN(tst_KLocalSocketServer) - -#include "klocalsocketservertest.moc" diff --git a/autotests/klocalsockettest.h b/autotests/klocalsockettest.h deleted file mode 100644 --- a/autotests/klocalsockettest.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#ifndef KLOCALSOCKETTEST_H -#define KLOCALSOCKETTEST_H - -#include - -class KLocalSocketServer; -class tst_KLocalSocket : public QObject -{ - Q_OBJECT -public: - KLocalSocketServer *server; - tst_KLocalSocket(); - ~tst_KLocalSocket(); - -private Q_SLOTS: - void initTestCase(); - void connection_data(); - void connection(); - void waitFor(); - - void reading(); - void writing(); - - void state(); - - void connected(); -}; - -#endif diff --git a/autotests/klocalsockettest.cpp b/autotests/klocalsockettest.cpp deleted file mode 100644 --- a/autotests/klocalsockettest.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "klocalsockettest.h" - -#include - -#include -#include -#include -#include "klocalsocket.h" - -static const char socketpath[] = "/tmp/testsocket"; - -tst_KLocalSocket::tst_KLocalSocket() -{ - server = nullptr; - QFile::remove(QFile::decodeName(socketpath)); -} - -tst_KLocalSocket::~tst_KLocalSocket() -{ - delete server; - QFile::remove(QFile::decodeName(socketpath)); -} - -#include - -class TimedTest: public QThread -{ - Q_OBJECT -public: - KLocalSocket *socket; - TimedTest(KLocalSocket *s) - : socket(s) - { } - ~TimedTest() - { - wait(1000); - } - - void run() override { - QThread::usleep(100000); - socket->write("Hello, World!", 13); - socket->waitForBytesWritten(); - QThread::usleep(100000); - socket->close(); - delete socket; - } -}; - -void tst_KLocalSocket::initTestCase() -{ - server = new KLocalSocketServer(this); - QVERIFY(server->listen(socketpath)); -} - -void tst_KLocalSocket::connection_data() -{ - QTest::addColumn("path"); - - QTest::newRow("null-path") << QString(); - QTest::newRow("empty-path") << ""; - QTest::newRow("directory") << "/tmp"; - QTest::newRow("directory2") << "/tmp/"; - QTest::newRow("non-existing") << "/tmp/nonexistingsocket"; - QTest::newRow("real") << socketpath; -} - -void tst_KLocalSocket::connection() -{ - QFETCH(QString, path); - KLocalSocket socket; - socket.connectToPath(path); - - bool shouldSucceed = path == socketpath; - QCOMPARE(socket.waitForConnected(1000), shouldSucceed); - if (shouldSucceed) { - QVERIFY(server->waitForNewConnection()); - delete server->nextPendingConnection(); - } else { - qDebug() << socket.errorString(); - } -} - -void tst_KLocalSocket::waitFor() -{ - KLocalSocket socket; - socket.connectToPath(socketpath); - QVERIFY(socket.waitForConnected(1000)); - QVERIFY(server->waitForNewConnection()); - - // now accept: - KLocalSocket *socket2 = server->nextPendingConnection(); - - // start thread: - TimedTest thr(socket2); - socket2->setParent(nullptr); - socket2->moveToThread(&thr); - thr.start(); - - QVERIFY(socket.waitForReadyRead(500)); - QByteArray data = socket.read(512); - - QVERIFY(socket.waitForDisconnected(500)); -} - -void tst_KLocalSocket::reading() -{ - static const char data1[] = "Hello ", - data2[] = "World"; - KLocalSocket socket; - socket.connectToPath(socketpath); - QVERIFY(socket.waitForConnected(1000)); - QVERIFY(server->waitForNewConnection()); - - // now accept and write something: - KLocalSocket *socket2 = server->nextPendingConnection(); - socket2->write(data1, sizeof data1 - 1); - QVERIFY(socket2->bytesToWrite() == 0 || socket2->waitForBytesWritten(200)); - - QVERIFY(socket.waitForReadyRead(200)); - QByteArray read = socket.read(sizeof data1 - 1); - QCOMPARE(read.length(), int(sizeof data1) - 1); - QCOMPARE(read.constData(), data1); - - // write data2 - socket2->write(data2, sizeof data2 - 1); - QVERIFY(socket2->bytesToWrite() == 0 || socket2->waitForBytesWritten(200)); - QVERIFY(socket.waitForReadyRead(200)); - read = socket.read(sizeof data2 - 1); - QCOMPARE(read.length(), int(sizeof data2) - 1); - QCOMPARE(read.constData(), data2); - - delete socket2; -} - -void tst_KLocalSocket::writing() -{ - static const char data1[] = "Hello ", - data2[] = "World"; - KLocalSocket socket; - socket.connectToPath(socketpath); - QVERIFY(socket.waitForConnected(1000)); - QVERIFY(server->waitForNewConnection()); - - // now accept and write something: - KLocalSocket *socket2 = server->nextPendingConnection(); - - QCOMPARE(socket.write(data1, sizeof data1 - 1), Q_INT64_C(sizeof data1 - 1)); - QVERIFY(socket.bytesToWrite() == 0 || socket.waitForBytesWritten(100)); - QVERIFY(socket2->waitForReadyRead()); - - QByteArray read = socket2->read(sizeof data1 - 1); - QCOMPARE(read.length(), int(sizeof data1) - 1); - QCOMPARE(read.constData(), data1); - - // write data2 - QCOMPARE(socket.write(data2, sizeof data2 - 1), Q_INT64_C(sizeof data2 - 1)); - QVERIFY(socket.bytesToWrite() == 0 || socket.waitForBytesWritten(100)); - QVERIFY(socket2->waitForReadyRead()); - read = socket2->read(sizeof data2 - 1); - QCOMPARE(read.length(), int(sizeof data2) - 1); - QCOMPARE(read.constData(), data2); - - delete socket2; -} - -void tst_KLocalSocket::state() -{ - KLocalSocket socket; - - // sanity check: - QCOMPARE(int(socket.localSocketType()), int(KLocalSocket::UnknownLocalSocketType)); - QVERIFY(socket.localPath().isEmpty()); - QVERIFY(socket.peerPath().isEmpty()); - QCOMPARE(int(socket.state()), int(QAbstractSocket::UnconnectedState)); - - // now connect and accept - socket.connectToPath(socketpath); - QVERIFY(socket.waitForConnected(1000)); - QVERIFY(server->waitForNewConnection()); - KLocalSocket *socket2 = server->nextPendingConnection(); - - QCOMPARE(socket.peerPath(), QString(socketpath)); - QCOMPARE(socket2->localPath(), QString(socketpath)); - QCOMPARE(int(socket.state()), int(QAbstractSocket::ConnectedState)); - QCOMPARE(int(socket2->state()), int(QAbstractSocket::ConnectedState)); - QCOMPARE(int(socket.localSocketType()), int(KLocalSocket::UnixSocket)); - QCOMPARE(int(socket2->localSocketType()), int(KLocalSocket::UnixSocket)); - - // now close one of the sockets: - socket.close(); - - // it must have reset its state: - QCOMPARE(int(socket.localSocketType()), int(KLocalSocket::UnknownLocalSocketType)); - QVERIFY(socket.peerPath().isEmpty()); - QCOMPARE(int(socket.state()), int(QAbstractSocket::UnconnectedState)); - - // but the other one mustn't have yet: - QCOMPARE(int(socket2->state()), int(QAbstractSocket::ConnectedState)); - QVERIFY(!socket2->localPath().isEmpty()); - QCOMPARE(int(socket2->localSocketType()), int(KLocalSocket::UnixSocket)); - - // wait for disconnected: - QVERIFY(socket2->waitForDisconnected()); - - // now it must have: - QCOMPARE(int(socket2->state()), int(QAbstractSocket::UnconnectedState)); - QVERIFY(socket2->localPath().isEmpty()); - QCOMPARE(int(socket2->localSocketType()), int(KLocalSocket::UnknownLocalSocketType)); - - delete socket2; -} - -void tst_KLocalSocket::connected() -{ - KLocalSocket socket; - socket.connectToPath(socketpath); - QEXPECT_FAIL("", "Will fix later", Continue); - QVERIFY(!socket.isOpen()); - - QSignalSpy spy(&socket, SIGNAL(connected())); - QTest::qWait(100); - - QEXPECT_FAIL("", "Will fix later", Continue); - QCOMPARE(spy.count(), 1); -} - -QTEST_MAIN(tst_KLocalSocket) - -#include "klocalsockettest.moc" diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -20,7 +20,6 @@ set(kiocore_SRCS idleslave.cpp - klocalsocket.cpp connectionbackend.cpp connection.cpp connectionserver.cpp @@ -129,13 +128,11 @@ if (UNIX) set(kiocore_SRCS ${kiocore_SRCS} - klocalsocket_unix.cpp kioglobal_p_unix.cpp ) endif() if (WIN32) set(kiocore_SRCS ${kiocore_SRCS} - klocalsocket_win.cpp kioglobal_p_win.cpp ) endif() diff --git a/src/core/connection.cpp b/src/core/connection.cpp --- a/src/core/connection.cpp +++ b/src/core/connection.cpp @@ -140,9 +140,7 @@ const QString scheme = address.scheme(); if (scheme == QLatin1String("local")) { - d->setBackend(new ConnectionBackend(ConnectionBackend::LocalSocketMode, this)); - } else if (scheme == QLatin1String("tcp")) { - d->setBackend(new ConnectionBackend(ConnectionBackend::TcpSocketMode, this)); + d->setBackend(new ConnectionBackend(this)); } else { qCWarning(KIO_CORE) << "Unknown protocol requested:" << scheme << "(" << address << ")"; Q_ASSERT(0); diff --git a/src/core/connectionbackend.cpp b/src/core/connectionbackend.cpp --- a/src/core/connectionbackend.cpp +++ b/src/core/connectionbackend.cpp @@ -21,38 +21,33 @@ #include "connectionbackend_p.h" #include -#include #include -#include "klocalsocket.h" #include #include #include #include #include #include +#include +#include #include "kiocoredebug.h" using namespace KIO; -ConnectionBackend::ConnectionBackend(Mode m, QObject *parent) +ConnectionBackend::ConnectionBackend(QObject *parent) : QObject(parent), state(Idle), socket(nullptr), len(-1), cmd(0), - signalEmitted(false), - mode(m) + signalEmitted(false) { localServer = nullptr; } ConnectionBackend::~ConnectionBackend() { - if (mode == LocalSocketMode && localServer && - localServer->localSocketType() == KLocalSocket::UnixSocket) { - QFile::remove(localServer->localPath()); - } } void ConnectionBackend::setSuspended(bool enable) @@ -93,31 +88,13 @@ Q_ASSERT(!socket); Q_ASSERT(!localServer); // !tcpServer as well - if (mode == LocalSocketMode) { - KLocalSocket *sock = new KLocalSocket(this); - QString path = url.path(); -#if 0 - // TODO: Activate once abstract socket support is implemented in Qt. - KLocalSocket::LocalSocketType type = KLocalSocket::UnixSocket; - - if (url.queryItem(QLatin1String("abstract")) == QLatin1Char('1')) { - type = KLocalSocket::AbstractUnixSocket; - } -#endif - sock->connectToPath(path); - socket = sock; - } else { - socket = new QTcpSocket(this); - socket->connectToHost(url.host(), url.port()); + QLocalSocket *sock = new QLocalSocket(this); + QString path = url.path(); + sock->connectToServer(path); + socket = sock; - if (!socket->waitForConnected(1000)) { - state = Idle; - qCDebug(KIO_CORE) << "could not connect to" << url; - return false; - } - } connect(socket, &QIODevice::readyRead, this, &ConnectionBackend::socketReadyRead); - connect(socket, &QAbstractSocket::disconnected, this, &ConnectionBackend::socketDisconnected); + connect(socket, &QLocalSocket::disconnected, this, &ConnectionBackend::socketDisconnected); state = Connected; return true; } @@ -134,56 +111,42 @@ Q_ASSERT(!socket); Q_ASSERT(!localServer); // !tcpServer as well - if (mode == LocalSocketMode) { - const QString prefix = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); - static QBasicAtomicInt s_socketCounter = Q_BASIC_ATOMIC_INITIALIZER(1); - QString appName = QCoreApplication::instance()->applicationName(); - appName.replace(QLatin1Char('/'), QLatin1Char('_')); // #357499 - QTemporaryFile socketfile(prefix + QLatin1Char('/') + appName + QStringLiteral("XXXXXX.%1.slave-socket").arg(s_socketCounter.fetchAndAddAcquire(1))); - if (!socketfile.open()) { - errorString = i18n("Unable to create io-slave: %1", QString::fromUtf8(strerror(errno))); - return false; - } - - QString sockname = socketfile.fileName(); - address.clear(); - address.setScheme(QStringLiteral("local")); - address.setPath(sockname); - socketfile.setAutoRemove(false); - socketfile.remove(); // can't bind if there is such a file - - localServer = new KLocalSocketServer(this); - if (!localServer->listen(sockname, KLocalSocket::UnixSocket)) { - errorString = localServer->errorString(); - delete localServer; - localServer = nullptr; - return false; - } - - connect(localServer, &KLocalSocketServer::newConnection, this, &ConnectionBackend::newConnection); - } else { - tcpServer = new QTcpServer(this); - tcpServer->listen(QHostAddress::LocalHost); - if (!tcpServer->isListening()) { - errorString = tcpServer->errorString(); - delete tcpServer; - tcpServer = nullptr; - return false; - } + const QString prefix = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); + static QBasicAtomicInt s_socketCounter = Q_BASIC_ATOMIC_INITIALIZER(1); + QString appName = QCoreApplication::instance()->applicationName(); + appName.replace(QLatin1Char('/'), QLatin1Char('_')); // #357499 + QTemporaryFile socketfile(prefix + QLatin1Char('/') + appName + QStringLiteral("XXXXXX.%1.slave-socket").arg(s_socketCounter.fetchAndAddAcquire(1))); + if (!socketfile.open()) { + errorString = i18n("Unable to create io-slave: %1", QString::fromUtf8(strerror(errno))); + return false; + } - address = QUrl(QLatin1String("tcp://127.0.0.1:") + QString::number(tcpServer->serverPort())); - connect(tcpServer, &QTcpServer::newConnection, this, &ConnectionBackend::newConnection); + QString sockname = socketfile.fileName(); + address.clear(); + address.setScheme(QStringLiteral("local")); + address.setPath(sockname); + socketfile.setAutoRemove(false); + socketfile.remove(); // can't bind if there is such a file + + localServer = new QLocalServer(this); + if (!localServer->listen(sockname)) { + errorString = localServer->errorString(); + delete localServer; + localServer = nullptr; + return false; } + connect(localServer, &QLocalServer::newConnection, this, &ConnectionBackend::newConnection); + state = Listening; return true; } bool ConnectionBackend::waitForIncomingTask(int ms) { Q_ASSERT(state == Connected); Q_ASSERT(socket); - if (socket->state() != QAbstractSocket::ConnectedState) { + if (socket->state() != QLocalSocket::LocalSocketState::ConnectedState) { state = Idle; return false; // socket has probably closed, what do we do? } @@ -200,16 +163,16 @@ QElapsedTimer timer; timer.start(); - while (socket->state() == QAbstractSocket::ConnectedState && !signalEmitted && + while (socket->state() == QLocalSocket::LocalSocketState::ConnectedState && !signalEmitted && (ms == -1 || timer.elapsed() < ms)) if (!socket->waitForReadyRead(ms == -1 ? -1 : ms - timer.elapsed())) { break; } if (signalEmitted) { return true; } - if (socket->state() != QAbstractSocket::ConnectedState) { + if (socket->state() != QLocalSocket::LocalSocketState::ConnectedState) { state = Idle; } return false; @@ -230,38 +193,33 @@ // << "bytes left to write )"; // blocking mode: - while (socket->bytesToWrite() > 0 && socket->state() == QAbstractSocket::ConnectedState) { + while (socket->bytesToWrite() > 0 && socket->state() == QLocalSocket::LocalSocketState::ConnectedState) { socket->waitForBytesWritten(-1); } - return socket->state() == QAbstractSocket::ConnectedState; + return socket->state() == QLocalSocket::LocalSocketState::ConnectedState; } ConnectionBackend *ConnectionBackend::nextPendingConnection() { Q_ASSERT(state == Listening); - Q_ASSERT(localServer || tcpServer); + Q_ASSERT(localServer); Q_ASSERT(!socket); //qCDebug(KIO_CORE) << "Got a new connection"; - QTcpSocket *newSocket; - if (mode == LocalSocketMode) { - newSocket = localServer->nextPendingConnection(); - } else { - newSocket = tcpServer->nextPendingConnection(); - } + QLocalSocket *newSocket = localServer->nextPendingConnection(); if (!newSocket) { return nullptr; // there was no connection... } - ConnectionBackend *result = new ConnectionBackend(Mode(mode)); + ConnectionBackend *result = new ConnectionBackend(); result->state = Connected; result->socket = newSocket; newSocket->setParent(result); connect(newSocket, &QIODevice::readyRead, result, &ConnectionBackend::socketReadyRead); - connect(newSocket, &QAbstractSocket::disconnected, result, &ConnectionBackend::socketDisconnected); + connect(newSocket, &QLocalSocket::disconnected, result, &ConnectionBackend::socketDisconnected); return result; } diff --git a/src/core/connectionbackend_p.h b/src/core/connectionbackend_p.h --- a/src/core/connectionbackend_p.h +++ b/src/core/connectionbackend_p.h @@ -22,9 +22,11 @@ #include #include -class KLocalSocketServer; + +class QLocalServer; +class QLocalSocket; + class QTcpServer; -class QTcpSocket; namespace KIO { @@ -40,17 +42,13 @@ public: enum { Idle, Listening, Connected } state; - enum Mode { LocalSocketMode, TcpSocketMode }; QUrl address; QString errorString; private: - QTcpSocket *socket; - union { - KLocalSocketServer *localServer; - QTcpServer *tcpServer; - }; + QLocalSocket *socket; + QLocalServer *localServer; long len; int cmd; int port; @@ -66,7 +64,7 @@ void newConnection(); public: - explicit ConnectionBackend(Mode m, QObject *parent = nullptr); + explicit ConnectionBackend(QObject *parent = nullptr); ~ConnectionBackend(); void setSuspended(bool enable); diff --git a/src/core/connectionserver.cpp b/src/core/connectionserver.cpp --- a/src/core/connectionserver.cpp +++ b/src/core/connectionserver.cpp @@ -48,11 +48,7 @@ void ConnectionServer::listenForRemote() { -#ifdef Q_OS_WIN - d->backend = new ConnectionBackend(ConnectionBackend::TcpSocketMode, this); -#else - d->backend = new ConnectionBackend(ConnectionBackend::LocalSocketMode, this); -#endif + d->backend = new ConnectionBackend(this); if (!d->backend->listenForRemote()) { delete d->backend; d->backend = nullptr; diff --git a/src/core/klocalsocket.h b/src/core/klocalsocket.h deleted file mode 100644 --- a/src/core/klocalsocket.h +++ /dev/null @@ -1,335 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef KLOCALSOCKET_H -#define KLOCALSOCKET_H - -#include "kiocore_export.h" -#include -#include -#include - -class KLocalSocketPrivate; -/** - * @class KLocalSocket - * @brief KLocalSocket allows one to create and use local (Unix) sockets - * - * On some platforms, local sockets are a kind of streaming socket - * that can be used to transmit and receive data just like Internet - * (TCP) streaming sockets. The difference is that they remain local - * to the host running them and cannot be accessed externally. They - * are also very fast and (in theory) consume less resources than - * standard TCP sockets. - * - * KLocalSocket supports two kinds of local socket types (see - * KLocalSocket::LocalSocketType): - * - Unix sockets (UnixSocket): standard Unix sockets whose names are - * file paths and obey filesystem restrictions - * - Abstract Unix sockets (AbstractUnixSocket): similar to Unix - * sockets, but they don't exist as entries in the filesystem and, - * thus, aren't restricted by its permissions - * - * @author Thiago Macieira - * @internal DO NOT USE. Only for KIO. - */ -class KIOCORE_EXPORT KLocalSocket : public QTcpSocket // Only exported for the unittest. Header not installed -{ - Q_OBJECT -public: - /** - * Defines the local socket type. See KLocalSocket for more - * information - */ - enum LocalSocketType { - UnixSocket, ///< Unix sockets - AbstractUnixSocket, ///< Abstract Unix sockets - UnknownLocalSocketType = -1 - }; - - /** - * Creates a KLocalSocket object with @p parent as the parent - * object. - * - * @param parent the parent object - */ - explicit KLocalSocket(QObject *parent = nullptr); - /** - * Destroys the KLocalSocket object and frees up any resources - * associated. If the socket is open, it will be closed. - */ - virtual ~KLocalSocket(); - - /** - * Opens a connection to a listening Unix socket at @p path. Use - * waitForConnection() to find out if the connection succeeded or - * not. - * - * @param path the Unix socket to connect to - * @param mode the mode to use when opening (see QIODevice::OpenMode) - */ - void connectToPath(const QString &path, OpenMode mode = ReadWrite); - /** - * @overload - * Opens a connection to a listening local socket at address @p - * path. Use waitForConnection() to find out if the connection - * succeeded or not. - * - * @param path the local socket address to connect to - * @param type the local socket type to use - * @param mode the mode to use when opening (see QIODevice::OpenMode) - */ - void connectToPath(const QString &path, LocalSocketType type, OpenMode mode = ReadWrite); - /** - * Disconnects the socket from its server. - */ - void disconnectFromPath(); - - /** - * Returns the socket type for this socket, when - * connected. Returns UnknownLocalSocketType if not - * connected. - */ - LocalSocketType localSocketType() const; - - /** - * Returns the local address of this socket, when - * connected. Returns QString() if not connected. - * - * Most of the time, the socket has no local address. - */ - QString localPath() const; - /** - * Returns the peer address of this socket. That is, the address - * that this socket connected to (see connectToPath). Returns - * QString() if not connected. - */ - QString peerPath() const; - -private: - using QAbstractSocket::connectToHost; - using QAbstractSocket::disconnectFromHost; - -protected Q_SLOTS: - /// @internal - void connectToHostImplementation(const QString &hostName, quint16 port, OpenMode mode); - void disconnectFromHostImplementation(); - -public: - void connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite) override - { - connectToHostImplementation(address.toString(), port, mode); - } - void connectToHost(const QString &hostName, quint16 port, OpenMode mode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol) override - { - Q_UNUSED(protocol) - connectToHostImplementation(hostName, port, mode); - } - void disconnectFromHost() override - { - disconnectFromHostImplementation(); - } - -private: - Q_DISABLE_COPY(KLocalSocket) - friend class KLocalSocketPrivate; - KLocalSocketPrivate *const d; -}; - -class KLocalSocketServerPrivate; -/** - * @class KLocalSocketServer - * @brief KLocalSocketServer allows one to create a listening local - * socket and accept incoming connections - * - * On some platforms, local sockets are a kind of streaming socket - * that can be used to transmit and receive data just like Internet - * (TCP) streaming sockets. The difference is that they remain local - * to the host running them and cannot be accessed externally. They - * are also very fast and (in theory) consume less resources than - * standard TCP sockets. - * - * KLocalSocketServer allows you to create the listening (i.e., - * passive) end of this local socket and accept incoming connections - * from users of KLocalSocket. It supports the same kind of socket - * types that KLocalSocket does (see KLocalSocket::LocalSocketType). - * - * @author Thiago Macieira - */ -class KIOCORE_EXPORT KLocalSocketServer : public QObject -{ - Q_OBJECT -public: - /** - * Creates a KLocalSocketServer object with @p parent as the - * parent object. The object is created without binding to any - * address. - * - * @param parent the parent object - */ - explicit KLocalSocketServer(QObject *parent = nullptr); - /** - * Destroys the KLocalSocketServer object and frees up any - * resource associated. If the socket is still listening, it's - * closed (see close()). - * - * The sockets that were accepted using this KLocalSocketServer - * object are not affected and will remain open. However, note - * that nextPendingConnection() returns objects that have this - * KLocalSocketServer as parents, so the QObject destruction will - * delete any objects that were not reparented. - */ - virtual ~KLocalSocketServer(); - - /** - * Binds this socket to the address @p path and starts listening - * there. - * - * If @p type is KLocalSocket::UnixSocket, @p path is - * treated as a Unix filesystem path and the calling user must - * have permission to create the named directory entry (that is, - * the user must have write permission to the parent directory, - * etc.) - * - * If @p type is KLocalSocket::AbstractUnixSocket, @p path is - * just a name that can be anything. It'll be converted to an - * 8-bit identifier just as if it were a file path, but - * filesystem restrictions do not apply. - * - * This function returns true if it succeeded in binding the - * socket to @p path and placing it in listen mode. It returns - * false otherwise. - * - * @param path the path to listen on - * @param type the local socket type - * @returns true on success, false otherwise - */ - bool listen(const QString &path, KLocalSocket::LocalSocketType type = KLocalSocket::UnixSocket); - - /** - * Closes the socket. No further connections will be accepted, - * but connections that were already pending can still be - * retrieved with nextPendingConnection(). - * - * Connections that were accepted and are already open will not - * be affected. - */ - void close(); - - /** - * Returns true if the socket is listening, false otherwise. - */ - bool isListening() const; - - /** - * Sets the maximum number of connections that KLocalSocketServer - * will accept on your behalf and keep queued, ready to be - * retrieved with nextPendingConnection(). If you set @p - * numConnections to 0, hasPendingConnections() will always - * return false. You can still use waitForNewConnection(), - * though. - * - * @param numConnections the number of connections to accept - * and keep queued. - */ - void setMaxPendingConnections(int numConnections); - /** - * Returns the value set with setMaxPendingConnections(). - */ - int maxPendingConnections() const; - - /** - * Returns the socket type that this socket is listening on. If it - * is not listening, returns QAbstractSocket::UnknownLocalSocketType. - */ - KLocalSocket::LocalSocketType localSocketType() const; - /** - * Returns the address of this socket if it is listening on, or - * QString() if it is not listening. - */ - QString localPath() const; - - /** - * Suspends the execution of the calling thread for at most @p - * msec milliseconds and wait for a new socket connection to be - * accepted (whichever comes first). If no new socket connection - * is received within @p msec milliseconds, consider this a - * time-out and set the boolean pointed by @p timedOut to false - * (if it's not 0). - * - * If @p msec is 0, this call will not block, but will simply poll - * the system to check if a new connection has been received in - * the background. - * - * Use @p msec value of -1 to block indefinitely. - * - * @param msec the time in milliseconds to block at most (-1 - * to block forever) - * @param timedOut points to a boolean that will be set to true - * if a timeout did occur - * @returns true if a new connection has been accepted or false if - * an error occurred or if the operation timed out. - */ - bool waitForNewConnection(int msec = 0, bool *timedOut = nullptr); - - /** - * Returns true if a new socket can be received with - * nextPendingConnection(). - */ - virtual bool hasPendingConnections() const; - /** - * Returns a new socket if one is available or @c nullptr if none is. - * - * Note that the objects returned by this function will have the - * current KLocalSocketServer object as its parent. You may want - * to reparent the accepted objects if you intend them to outlive - * the current object. - */ - virtual KLocalSocket *nextPendingConnection(); - - /** - * If an error occurred, return the error code. - */ - QAbstractSocket::SocketError serverError() const; - /** - * If an error occurred, return the error message. - */ - QString errorString() const; - -protected: - /// @internal - virtual void incomingConnection(int handle); - -Q_SIGNALS: - /** - * The newConnection() signal is emitted whenever a new connection - * is ready and has been accepted. Whenever it is emitted, calling - * nextPendingConnection() will return a valid object at least - * once. - */ - void newConnection(); - -private: - Q_PRIVATE_SLOT(d, void _k_newConnectionActivity()) - Q_DISABLE_COPY(KLocalSocketServer) - friend class KLocalSocketServerPrivate; - KLocalSocketServerPrivate *const d; -}; - -#endif diff --git a/src/core/klocalsocket.cpp b/src/core/klocalsocket.cpp deleted file mode 100644 --- a/src/core/klocalsocket.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "klocalsocket.h" -#include "klocalsocket_p.h" -#include "kiocoredebug.h" - -#include - -//#define LocalSocket (QAbstractSocket::SocketType(int(QAbstractSocket::UdpSocket) + 1)) - -void KLocalSocketPrivate::emitError(QAbstractSocket::SocketError error, const QString &errorString) -{ - q->setSocketState(QAbstractSocket::UnconnectedState); - q->setSocketError(error); - q->setErrorString(errorString); - emit q->stateChanged(QAbstractSocket::UnconnectedState); - emit q->error(error); -} - -void KLocalSocketServerPrivate::emitError(QAbstractSocket::SocketError an_error, const QString &an_errorString) -{ - error = an_error; - errorString = an_errorString; -} - -KLocalSocket::KLocalSocket(QObject *parent) - : QTcpSocket(parent), d(new KLocalSocketPrivate(this)) -{ -} - -KLocalSocket::~KLocalSocket() -{ - delete d; - // parent's destructor closes the socket -} - -void KLocalSocket::connectToPath(const QString &path, OpenMode mode) -{ - // cheat: - connectToHost(path, UnixSocket, mode); -} - -void KLocalSocket::connectToPath(const QString &path, LocalSocketType type, OpenMode mode) -{ - // cheat: - connectToHost(path, type, mode); -} - -void KLocalSocket::connectToHostImplementation(const QString &path, quint16 type, OpenMode mode) -{ - if (state() == ConnectedState || state() == ConnectingState) { - return; - } - - d->localPath.clear(); - d->peerPath.clear(); - - setSocketState(ConnectingState); - emit stateChanged(ConnectingState); - - d->connectToPath(path, LocalSocketType(type), mode); -} - -void KLocalSocket::disconnectFromHostImplementation() -{ - QTcpSocket::disconnectFromHost(); - - d->peerPath.clear(); - d->localPath.clear(); - d->type = UnknownLocalSocketType; -} - -void KLocalSocket::disconnectFromPath() -{ - // cheat: - disconnectFromHost(); -} - -KLocalSocket::LocalSocketType KLocalSocket::localSocketType() const -{ - return d->type; -} - -QString KLocalSocket::localPath() const -{ - return d->localPath; -} - -QString KLocalSocket::peerPath() const -{ - return d->peerPath; -} - -KLocalSocketServerPrivate::KLocalSocketServerPrivate(KLocalSocketServer *qq) - : q(qq), descriptor(-1), maxPendingConnections(30), - state(QAbstractSocket::UnconnectedState), - error(QAbstractSocket::UnknownSocketError), - type(KLocalSocket::UnknownLocalSocketType), - readNotifier(nullptr) -{ -} - -KLocalSocketServer::KLocalSocketServer(QObject *parent) - : QObject(parent), d(new KLocalSocketServerPrivate(this)) -{ -} - -KLocalSocketServer::~KLocalSocketServer() -{ - close(); - delete d; -} - -bool KLocalSocketServer::isListening() const -{ - return d->state == QAbstractSocket::ListeningState; -} - -bool KLocalSocketServer::listen(const QString &path, KLocalSocket::LocalSocketType type) -{ - if (d->state == QAbstractSocket::ListeningState) { - return false; // already created - } - - if (!d->listen(path, type)) { - // the private set the error code - return false; - } - - d->localPath = path; - return true; -} - -void KLocalSocketServer::close() -{ - d->close(); -} - -void KLocalSocketServer::setMaxPendingConnections(int numConnections) -{ - if (numConnections >= 0) { - d->maxPendingConnections = numConnections; - d->readNotifier->setEnabled(d->pendingConnections.size() < d->maxPendingConnections); - } else { - qCWarning(KIO_CORE, "KLocalSocketServer::setMaxPendingConnections: cannot set to a negative number"); - } -} - -int KLocalSocketServer::maxPendingConnections() const -{ - return d->maxPendingConnections; -} - -KLocalSocket::LocalSocketType KLocalSocketServer::localSocketType() const -{ - return d->type; -} - -QString KLocalSocketServer::localPath() const -{ - return d->localPath; -} - -bool KLocalSocketServer::waitForNewConnection(int msec, bool *timedOut) -{ - if (!isListening()) { - return false; // can't wait if we're not listening - } - - return d->waitForNewConnection(msec, timedOut); -} - -bool KLocalSocketServer::hasPendingConnections() const -{ - return !d->pendingConnections.isEmpty(); -} - -KLocalSocket *KLocalSocketServer::nextPendingConnection() -{ - if (hasPendingConnections()) { - d->readNotifier->setEnabled((d->pendingConnections.size() - 1) < d->maxPendingConnections); - return d->pendingConnections.dequeue(); - } - return nullptr; -} - -void KLocalSocketServer::incomingConnection(int descriptor) -{ - KLocalSocket *socket = new KLocalSocket(this); - KLocalSocketPrivate *socket_d = KLocalSocketPrivate::d(socket); - socket_d->localPath = d->localPath; - socket_d->type = d->type; - - socket->setSocketDescriptor(descriptor, QAbstractSocket::ConnectedState, QIODevice::ReadWrite); - d->pendingConnections.enqueue(socket); - - emit newConnection(); -} - -QAbstractSocket::SocketError KLocalSocketServer::serverError() const -{ - return d->error; -} - -QString KLocalSocketServer::errorString() const -{ - return d->errorString; -} - -#include "moc_klocalsocket.cpp" diff --git a/src/core/klocalsocket_p.h b/src/core/klocalsocket_p.h deleted file mode 100644 --- a/src/core/klocalsocket_p.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#ifndef KLOCALSOCKET_P_H -#define KLOCALSOCKET_P_H - -#include -#include -#include "klocalsocket.h" -#define MIN_SOCKADDR_UN_LEN (sizeof(quint16) + sizeof(char)) - -class QSocketNotifier; - -class KLocalSocketPrivate -{ -public: - KLocalSocket *const q; - explicit KLocalSocketPrivate(KLocalSocket *qq) - : q(qq), type(KLocalSocket::UnknownLocalSocketType) - { } - - QString localPath; - QString peerPath; - KLocalSocket::LocalSocketType type; - - void connectToPath(const QString &path, KLocalSocket::LocalSocketType type, - QAbstractSocket::OpenMode openMode); - - void emitError(QAbstractSocket::SocketError, const QString &errorString); - - static inline KLocalSocketPrivate *d(KLocalSocket *aq) - { - return aq->d; - } -}; - -class KLocalSocketServerPrivate -{ -public: - KLocalSocketServer *const q; - explicit KLocalSocketServerPrivate(KLocalSocketServer *qq); - - int descriptor; - int maxPendingConnections; - QAbstractSocket::SocketState state; - QAbstractSocket::SocketError error; - KLocalSocket::LocalSocketType type; - QString localPath; - QString errorString; - - QSocketNotifier *readNotifier; - QQueue pendingConnections; - - bool listen(const QString &path, KLocalSocket::LocalSocketType type); - void close(); - bool waitForNewConnection(int msec, bool *timedOut); - bool processSocketActivity(); - void _k_newConnectionActivity(); - void emitError(QAbstractSocket::SocketError, const QString &errorString); -}; - -#endif diff --git a/src/core/klocalsocket_unix.cpp b/src/core/klocalsocket_unix.cpp deleted file mode 100644 --- a/src/core/klocalsocket_unix.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#include // HAVE_STRUCT_SOCKADDR_SA_LEN - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "klocalizedstring.h" - -static inline int kSocket(int af, int socketype, int proto) -{ - int ret; - do { - ret = ::socket(af, socketype, proto); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static inline int kBind(int fd, const sockaddr *sa, int len) -{ - int ret; - do { - ret = ::bind(fd, sa, len); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static inline int kConnect(int fd, const sockaddr *sa, int len) -{ - int ret; - do { - ret = ::connect(fd, sa, len); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static inline int kListen(int fd, int backlog) -{ - int ret; - do { - ret = ::listen(fd, backlog); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static inline int kAccept(int fd) -{ - int ret; - sockaddr sa; - socklen_t len = sizeof(sa); - do { - ret = ::accept(fd, &sa, &len); - } while (ret == -1 && errno == EINTR); - return ret; -} - -#ifdef socket -#undef socket -#endif - -#ifdef bind -#undef bind -#endif - -#ifdef listen -#undef listen -#endif - -#ifdef connect -#undef connect -#endif - -#ifdef accept -#undef accept -#endif - -#include -#include -#include - -#include "klocalsocket.h" -#include "klocalsocket_p.h" - -#if !defined(AF_UNIX) && defined(AF_LOCAL) -# define AF_UNIX AF_LOCAL -#endif - -class KSockaddrUn -{ - int datalen; - QVarLengthArray data; -public: - KSockaddrUn(const QString &path, KLocalSocket::LocalSocketType type); - bool ok() const - { - return datalen; - } - int length() const - { - return datalen; - } - const sockaddr *address() - { - return reinterpret_cast(data.data()); - } -}; - -KSockaddrUn::KSockaddrUn(const QString &path, KLocalSocket::LocalSocketType type) - : datalen(0) -{ - if (path.isEmpty()) { - return; - } - - QString path2(path); - if (!path.startsWith(QLatin1Char('/'))) - // relative path; put everything in /tmp - { - path2.prepend(QLatin1String("/tmp/")); - } - - QByteArray encodedPath = QFile::encodeName(path2); - - datalen = MIN_SOCKADDR_UN_LEN + encodedPath.length(); - if (type == KLocalSocket::AbstractUnixSocket) { - ++datalen; - } - data.resize(datalen); - - sockaddr_un *saddr = reinterpret_cast(data.data()); - saddr->sun_family = AF_UNIX; -#if HAVE_STRUCT_SOCKADDR_SA_LEN - saddr->sun_len = datalen; -#endif - - if (type == KLocalSocket::UnixSocket) { - strcpy(saddr->sun_path, encodedPath.constData()); - } else if (type == KLocalSocket::AbstractUnixSocket) { - *saddr->sun_path = '\0'; - strcpy(saddr->sun_path + 1, encodedPath.constData()); - } else { - datalen = 0; // error - } -} - -static bool setNonBlocking(int fd) -{ - int fdflags = fcntl(fd, F_GETFL, 0); - if (fdflags == -1) { - return false; // error - } - - fdflags |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, fdflags) == -1) { - return false; // error - } - - return true; -} - -void KLocalSocketPrivate::connectToPath(const QString &path, KLocalSocket::LocalSocketType aType, - QAbstractSocket::OpenMode openMode) -{ - if (aType == KLocalSocket::UnixSocket || aType == KLocalSocket::AbstractUnixSocket) { - // connect to Unix socket - KSockaddrUn addr(path, aType); - if (!addr.ok()) { - emitError(QAbstractSocket::NetworkError, i18n("Specified socket path is invalid")); - return; - } - - // create the socket - int fd = kSocket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - // failed - emitError(QAbstractSocket::UnsupportedSocketOperationError, - i18n("The socket operation is not supported")); - return; - } - - // try to connect - // ### support non-blocking mode! - if (kConnect(fd, addr.address(), addr.length()) == -1) { - // failed - int error = errno; - ::close(fd); - - switch (error) { - case ECONNREFUSED: - emitError(QAbstractSocket::ConnectionRefusedError, i18n("Connection refused")); - return; - - case EACCES: - case EPERM: - emitError(QAbstractSocket::SocketAccessError, i18n("Permission denied")); - return; - - case ETIMEDOUT: - emitError(QAbstractSocket::SocketTimeoutError, i18n("Connection timed out")); - return; - - default: - emitError(QAbstractSocket::UnknownSocketError, i18n("Unknown error")); - return; - } - } - - // if we got here, we succeeded in connecting - if (!setNonBlocking(fd)) { - ::close(fd); - emitError(QAbstractSocket::UnknownSocketError, i18n("Could not set non-blocking mode")); - return; - } - - // all is good - peerPath = path; - type = aType; - - // setSocketDescriptor emits stateChanged - q->setSocketDescriptor(fd, QAbstractSocket::ConnectedState, openMode); - emit q->connected(); - } else { - emitError(QAbstractSocket::UnsupportedSocketOperationError, - i18n("The socket operation is not supported")); - } -} - -bool KLocalSocketServerPrivate::listen(const QString &path, KLocalSocket::LocalSocketType aType) -{ - qDeleteAll(pendingConnections); - pendingConnections.clear(); - - if (aType == KLocalSocket::UnixSocket || aType == KLocalSocket::AbstractUnixSocket) { - KSockaddrUn addr(path, aType); - if (!addr.ok()) { - emitError(QAbstractSocket::NetworkError, i18n("Specified socket path is invalid")); - return false; - } - - // create the socket - descriptor = kSocket(AF_UNIX, SOCK_STREAM, 0); - if (descriptor == -1) { - // failed - emitError(QAbstractSocket::UnsupportedSocketOperationError, - i18n("The socket operation is not supported")); - return false; - } - - // try to bind to the address - localPath = path; - if (kBind(descriptor, addr.address(), addr.length()) == -1 || - kListen(descriptor, 5) == -1) { - int error = errno; - close(); - - switch (error) { - case EACCES: - emitError(QAbstractSocket::SocketAccessError, i18n("Permission denied")); - return false; - - case EADDRINUSE: - emitError(QAbstractSocket::AddressInUseError, i18n("Address is already in use")); - return false; - - case ELOOP: - case ENAMETOOLONG: - emitError(QAbstractSocket::NetworkError, i18n("Path cannot be used")); - return false; - - case ENOENT: - emitError(QAbstractSocket::HostNotFoundError, i18n("No such file or directory")); - return false; - - case ENOTDIR: - emitError(QAbstractSocket::HostNotFoundError, i18n("Not a directory")); - return false; - - case EROFS: - emitError(QAbstractSocket::SocketResourceError, i18n("Read-only filesystem")); - return false; - - default: - emitError(QAbstractSocket::UnknownSocketError, i18n("Unknown error")); - return false; - } - } - - // if we got here, we succeeded in connecting - if (!setNonBlocking(descriptor)) { - close(); - emitError(QAbstractSocket::UnknownSocketError, i18n("Could not set non-blocking mode")); - return false; - } - - // done - state = QAbstractSocket::ListeningState; - type = aType; - readNotifier = new QSocketNotifier(descriptor, QSocketNotifier::Read, q); - readNotifier->setEnabled(maxPendingConnections > 0); - QObject::connect(readNotifier, SIGNAL(activated(int)), - q, SLOT(_k_newConnectionActivity())); - return true; - } - - return false; -} - -void KLocalSocketServerPrivate::close() -{ - if (descriptor != -1) { - ::close(descriptor); - } - descriptor = -1; - - delete readNotifier; - readNotifier = nullptr; - - if (type == KLocalSocket::UnixSocket) { - QFile::remove(localPath); - } - localPath.clear(); - type = KLocalSocket::UnknownLocalSocketType; - - state = QAbstractSocket::UnconnectedState; - error = QAbstractSocket::UnknownSocketError; - errorString.clear(); -} - -bool KLocalSocketServerPrivate::waitForNewConnection(int msec, bool *timedOut) -{ - timeval tv; - tv.tv_sec = msec / 1000; - tv.tv_usec = (msec % 1000) * 1000; - - fd_set readset; - FD_ZERO(&readset); - FD_SET(descriptor, &readset); - - while (descriptor != -1) { - int code = ::select(descriptor + 1, &readset, nullptr, nullptr, &tv); - if (code == -1 && errno == EINTR) { - // interrupted - continue; - } else if (code == -1) { - // error - emitError(QAbstractSocket::UnknownSocketError, i18n("Unknown socket error")); - close(); - return false; - } else if (code == 0) { - // timed out - if (timedOut) { - *timedOut = true; - } - return false; - } - - // we must've got a connection. At least, there's activity. - if (processSocketActivity()) { - if (timedOut) { - *timedOut = false; - } - return true; - } - } - return false; -} - -bool KLocalSocketServerPrivate::processSocketActivity() -{ - // we got a read notification in our socket - // see if we can accept anything - int newDescriptor = kAccept(descriptor); - if (newDescriptor == -1) { - switch (errno) { - case EAGAIN: - // shouldn't have happened, but it's ok - return false; // no new socket - - default: - emitError(QAbstractSocket::UnknownSocketError, i18n("Unknown socket error")); - // fall through - } - - close(); - return false; - } - - q->incomingConnection(newDescriptor); - readNotifier->setEnabled(pendingConnections.size() < maxPendingConnections); - return true; -} - -void KLocalSocketServerPrivate::_k_newConnectionActivity() -{ - if (descriptor == -1) { - return; - } - - processSocketActivity(); -} diff --git a/src/core/klocalsocket_win.cpp b/src/core/klocalsocket_win.cpp deleted file mode 100644 --- a/src/core/klocalsocket_win.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the KDE libraries - * Copyright (C) 2007 Thiago Macieira - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -// This file is a placeholder -// There is no Unix socket support on Windows - -#include "klocalsocket_p.h" - -#include "klocalizedstring.h" - -void KLocalSocketPrivate::connectToPath(const QString &path, KLocalSocket::LocalSocketType aType, - QAbstractSocket::OpenMode openMode) -{ - emitError(QAbstractSocket::UnsupportedSocketOperationError, i18n("Operation not supported")); -} - -bool KLocalSocketServerPrivate::listen(const QString &path, KLocalSocket::LocalSocketType aType) -{ - emitError(QAbstractSocket::UnsupportedSocketOperationError, i18n("Operation not supported")); - return false; -} - -void KLocalSocketServerPrivate::close() -{ -} - -bool KLocalSocketServerPrivate::waitForNewConnection(int, bool *) -{ - Q_ASSERT_X(false, "KLocalSocketServer::waitForNewConnection", - "This function should never have been called!"); - return false; -} - -void KLocalSocketServerPrivate::_k_newConnectionActivity() -{ -}