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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// Copyright (C) 2012 Research In Motion
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qqnxnavigatorpps.h"
#include <QDebug>
#include <QHash>
#include <QByteArray>
#include <private/qcore_unix_p.h>
QT_BEGIN_NAMESPACE
const char *QQnxNavigatorPps::navigatorControlPath = "/pps/services/navigator/control";
const size_t QQnxNavigatorPps::ppsBufferSize = 4096;
QQnxNavigatorPps::QQnxNavigatorPps(QObject *parent)
: QQnxAbstractNavigator(parent)
, m_fd(-1)
{
}
QQnxNavigatorPps::~QQnxNavigatorPps()
{
// close connection to navigator
if (m_fd != -1)
qt_safe_close(m_fd);
}
bool QQnxNavigatorPps::openPpsConnection()
{
if (m_fd != -1)
return true;
// open connection to navigator
errno = 0;
m_fd = qt_safe_open(navigatorControlPath, O_RDWR);
if (m_fd == -1) {
qWarning("QQNX: failed to open navigator pps, errno=%d", errno);
return false;
}
qCDebug(lcQpaQnxNavigator) << "successfully connected to Navigator. fd=" << m_fd;
return true;
}
bool QQnxNavigatorPps::requestInvokeUrl(const QByteArray &encodedUrl)
{
if (!openPpsConnection())
return false;
return sendPpsMessage("invoke", encodedUrl);
}
bool QQnxNavigatorPps::sendPpsMessage(const QByteArray &message, const QByteArray &data)
{
QByteArray ppsMessage = "msg::" + message;
if (!data.isEmpty())
ppsMessage += "\ndat::" + data;
ppsMessage += "\n";
qCDebug(lcQpaQnxNavigator) << "sending PPS message:\n" << ppsMessage;
// send pps message to navigator
errno = 0;
int bytes = qt_safe_write(m_fd, ppsMessage.constData(), ppsMessage.size());
if (Q_UNLIKELY(bytes == -1))
qFatal("QQNX: failed to write navigator pps, errno=%d", errno);
// allocate buffer for pps data
char buffer[ppsBufferSize];
// attempt to read pps data
do {
errno = 0;
bytes = qt_safe_read(m_fd, buffer, ppsBufferSize - 1);
if (Q_UNLIKELY(bytes == -1))
qFatal("QQNX: failed to read navigator pps, errno=%d", errno);
} while (bytes == 0);
// ensure data is null terminated
buffer[bytes] = '\0';
qCDebug(lcQpaQnxNavigator) << "received PPS message:\n" << buffer;
// process received message
QByteArray ppsData(buffer);
QHash<QByteArray, QByteArray> responseFields;
parsePPS(ppsData, responseFields);
if (responseFields.contains("res") && responseFields.value("res") == message) {
if (Q_UNLIKELY(responseFields.contains("err"))) {
qCritical() << "navigator responded with error: " << responseFields.value("err");
return false;
}
}
return true;
}
void QQnxNavigatorPps::parsePPS(const QByteArray &ppsData, QHash<QByteArray, QByteArray> &messageFields)
{
qCDebug(lcQpaQnxNavigator) << "data=" << ppsData;
// tokenize pps data into lines
QList<QByteArray> lines = ppsData.split('\n');
// validate pps object
if (Q_UNLIKELY(lines.empty() || lines.at(0) != "@control"))
qFatal("QQNX: unrecognized pps object, data=%s", ppsData.constData());
// parse pps object attributes and extract values
for (int i = 1; i < lines.size(); i++) {
// tokenize current attribute
const QByteArray &attr = lines.at(i);
qCDebug(lcQpaQnxNavigator) << "attr=" << attr;
int firstColon = attr.indexOf(':');
if (firstColon == -1) {
// abort - malformed attribute
continue;
}
int secondColon = attr.indexOf(':', firstColon + 1);
if (secondColon == -1) {
// abort - malformed attribute
continue;
}
QByteArray key = attr.left(firstColon);
QByteArray value = attr.mid(secondColon + 1);
qCDebug(lcQpaQnxNavigator) << "key=" << key << "value=" << value;
messageFields[key] = value;
}
}
QT_END_NAMESPACE
|