"Fossies" - the Fresh Open Source Software Archive

Member "cb2bib-2.0.1/src/qtsingleapplication/src/qtlocalpeer.cpp" (12 Feb 2021, 6757 Bytes) of package /linux/privat/cb2bib-2.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "qtlocalpeer.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.9.9_vs_2.0.0.

    1 /****************************************************************************
    2 **
    3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
    4 ** Contact: http://www.qt-project.org/legal
    5 **
    6 ** This file is part of the Qt Solutions component.
    7 **
    8 ** $QT_BEGIN_LICENSE:BSD$
    9 ** You may use this file under the terms of the BSD license as follows:
   10 **
   11 ** "Redistribution and use in source and binary forms, with or without
   12 ** modification, are permitted provided that the following conditions are
   13 ** met:
   14 **   * Redistributions of source code must retain the above copyright
   15 **     notice, this list of conditions and the following disclaimer.
   16 **   * Redistributions in binary form must reproduce the above copyright
   17 **     notice, this list of conditions and the following disclaimer in
   18 **     the documentation and/or other materials provided with the
   19 **     distribution.
   20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
   21 **     of its contributors may be used to endorse or promote products derived
   22 **     from this software without specific prior written permission.
   23 **
   24 **
   25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
   36 **
   37 ** $QT_END_LICENSE$
   38 **
   39 ****************************************************************************/
   40 
   41 
   42 #include "qtlocalpeer.h"
   43 #include <QCoreApplication>
   44 #include <QDataStream>
   45 #include <QTime>
   46 
   47 #if defined(Q_OS_WIN)
   48 #include <QLibrary>
   49 #include <qt_windows.h>
   50 typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
   51 static PProcessIdToSessionId pProcessIdToSessionId = 0;
   52 #endif
   53 #if defined(Q_OS_UNIX)
   54 #include <sys/types.h>
   55 #include <time.h>
   56 #include <unistd.h>
   57 #endif
   58 
   59 namespace QtLP_Private
   60 {
   61 #include "qtlockedfile.cpp"
   62 #if defined(Q_OS_WIN)
   63 #include "qtlockedfile_win.cpp"
   64 #else
   65 #include "qtlockedfile_unix.cpp"
   66 #endif
   67 }
   68 
   69 const char* QtLocalPeer::ack = "ack";
   70 
   71 QtLocalPeer::QtLocalPeer(QObject* parento, const QString& appId)
   72     : QObject(parento), id(appId)
   73 {
   74     QString prefix = id;
   75     if (id.isEmpty())
   76     {
   77         id = QCoreApplication::applicationFilePath();
   78 #if defined(Q_OS_WIN)
   79         id = id.toLower();
   80 #endif
   81         prefix = id.section(QLatin1Char('/'), -1);
   82     }
   83     prefix.remove(QRegExp("[^a-zA-Z]"));
   84     prefix.truncate(6);
   85 
   86     QByteArray idc = id.toUtf8();
   87     quint16 idNum = qChecksum(idc.constData(), idc.size());
   88     socketName = QLatin1String("qtsingleapp-") + prefix
   89                  + QLatin1Char('-') + QString::number(idNum, 16);
   90 
   91 #if defined(Q_OS_WIN)
   92     if (!pProcessIdToSessionId)
   93     {
   94         QLibrary lib("kernel32");
   95         pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
   96     }
   97     if (pProcessIdToSessionId)
   98     {
   99         DWORD sessionId = 0;
  100         pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
  101         socketName += QLatin1Char('-') + QString::number(sessionId, 16);
  102     }
  103 #else
  104     socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
  105 #endif
  106 
  107     server = new QLocalServer(this);
  108     QString lockName = QDir(QDir::tempPath()).absolutePath()
  109                        + QLatin1Char('/') + socketName
  110                        + QLatin1String("-lockfile");
  111     lockFile.setFileName(lockName);
  112     lockFile.open(QIODevice::ReadWrite);
  113 }
  114 
  115 
  116 
  117 bool QtLocalPeer::isClient()
  118 {
  119     if (lockFile.isLocked())
  120         return false;
  121 
  122     if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
  123         return true;
  124 
  125     bool res = server->listen(socketName);
  126 #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
  127     // ### Workaround
  128     if (!res && server->serverError() == QAbstractSocket::AddressInUseError)
  129     {
  130         QFile::remove(QDir::cleanPath(QDir::tempPath()) + QLatin1Char('/') + socketName);
  131         res = server->listen(socketName);
  132     }
  133 #endif
  134     if (!res)
  135         qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
  136     QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
  137     return false;
  138 }
  139 
  140 
  141 bool QtLocalPeer::sendMessage(const QString& message, int timeout)
  142 {
  143     if (!isClient())
  144         return false;
  145 
  146     QLocalSocket socket;
  147     bool connOk = false;
  148     for (int i = 0; i < 2; i++)
  149     {
  150         // Try twice, in case the other instance is just starting up
  151         socket.connectToServer(socketName);
  152         connOk = socket.waitForConnected(timeout / 2);
  153         if (connOk || i)
  154             break;
  155         int ms = 250;
  156 #if defined(Q_OS_WIN)
  157         Sleep(DWORD(ms));
  158 #else
  159         struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
  160         nanosleep(&ts, NULL);
  161 #endif
  162     }
  163     if (!connOk)
  164         return false;
  165 
  166     QByteArray uMsg(message.toUtf8());
  167     QDataStream ds(&socket);
  168     ds.writeBytes(uMsg.constData(), uMsg.size());
  169     bool res = socket.waitForBytesWritten(timeout);
  170     if (res)
  171     {
  172         res &= socket.waitForReadyRead(timeout);   // wait for ack
  173         if (res)
  174             res &= (socket.read(qstrlen(ack)) == ack);
  175     }
  176     return res;
  177 }
  178 
  179 
  180 void QtLocalPeer::receiveConnection()
  181 {
  182     QLocalSocket* socket = server->nextPendingConnection();
  183     if (!socket)
  184         return;
  185 
  186     while (socket->bytesAvailable() < (int)sizeof(quint32))
  187         socket->waitForReadyRead();
  188     QDataStream ds(socket);
  189     QByteArray uMsg;
  190     quint32 remaining;
  191     ds >> remaining;
  192     uMsg.resize(remaining);
  193     int got = 0;
  194     char* uMsgBuf = uMsg.data();
  195     do
  196     {
  197         got = ds.readRawData(uMsgBuf, remaining);
  198         remaining -= got;
  199         uMsgBuf += got;
  200     }
  201     while (remaining && got >= 0 && socket->waitForReadyRead(2000));
  202     if (got < 0)
  203     {
  204         qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
  205         delete socket;
  206         return;
  207     }
  208     QString message(QString::fromUtf8(uMsg));
  209     socket->write(ack, qstrlen(ack));
  210     socket->waitForBytesWritten(1000);
  211     socket->waitForDisconnected(1000); // make sure client reads ack
  212     delete socket;
  213     emit messageReceived(message); //### (might take a long time to return)
  214 }