File: connection.cpp

package info (click to toggle)
plasma-browser-integration 6.5.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,000 kB
  • sloc: cpp: 3,195; javascript: 2,553; xml: 127; python: 77; sh: 46; makefile: 16
file content (94 lines) | stat: -rw-r--r-- 2,518 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
    SPDX-FileCopyrightText: 2017 Kai Uwe Broulik <kde@privat.broulik.de>
    SPDX-FileCopyrightText: 2017 David Edmundson <davidedmundson@kde.org>

    SPDX-License-Identifier: MIT
*/

#include "connection.h"
#include <QCoreApplication>
#include <QJsonDocument>
#include <QSocketNotifier>

#include <QDebug>
#include <poll.h>
#include <unistd.h>

Connection::Connection()
    : QObject()
{
    // Make really sure no one but us, who uses the correct format, prints to stdout
    int newStdout = dup(STDOUT_FILENO);
    // redirect it to stderr so it's not just swallowed
    dup2(STDERR_FILENO, STDOUT_FILENO);
    m_stdOut.open(newStdout, QIODevice::WriteOnly);

    m_stdIn.open(STDIN_FILENO, QIODevice::ReadOnly | QIODevice::Unbuffered);

    auto notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this);
    connect(notifier, &QSocketNotifier::activated, this, &Connection::readData);
}

void Connection::sendData(const QJsonObject &data)
{
    const QByteArray rawData = QJsonDocument(data).toJson(QJsonDocument::Compact);
    // note, don't use QDataStream as we need to control the binary format used
    quint32 len = rawData.length();
    m_stdOut.write((char *)&len, sizeof(len));
    m_stdOut.write(rawData);
    m_stdOut.flush();
}

Connection *Connection::self()
{
    static Connection *s = nullptr;
    if (!s) {
        s = new Connection();
    }
    return s;
}

void Connection::readData()
{
    /* Qt does not recognize POLLHUP as an error and
     * as that flag never gets cleared, we enter an
     * infinite busy loop polling STDIN.
     * So we need to check for this condition ourselves
     * and exit. */

    struct pollfd poll_stdin = {};
    poll_stdin.fd = STDIN_FILENO;
    poll_stdin.events = POLLHUP;
    poll_stdin.revents = 0;

    if (poll(&poll_stdin, 1, 0) != 0) {
        // STDIN has HUP/ERR/NVAL condition
        qApp->exit(0);
        return;
    }

    m_stdIn.startTransaction();
    quint32 length = 0;
    auto rc = m_stdIn.read((char *)(&length), sizeof(quint32));
    if (rc == -1) {
        m_stdIn.rollbackTransaction();
        return;
    }

    QByteArray data = m_stdIn.read(length);
    if (data.length() != int(length)) {
        m_stdIn.rollbackTransaction();
        return;
    }

    if (data.isEmpty()) {
        m_stdIn.rollbackTransaction();
        return;
    }

    m_stdIn.commitTransaction();
    const QJsonObject json = QJsonDocument::fromJson(data).object();
    Q_EMIT dataReceived(json);
}

#include "moc_connection.cpp"