1/****************************************************************************
2**
3** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtSystems module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL21$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 or version 3 as published by the Free
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22** following information to ensure the GNU Lesser General Public License
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25**
26** As a special exception, The Qt Company gives you certain additional
27** rights. These rights are described in The Qt Company LGPL Exception
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29**
30** $QT_END_LICENSE$
31**
32****************************************************************************/
33
34#include "qservicedebuglog_p.h"
35#include <QDebug>
36#include <QTime>
37
38#include <QMutex>
39#include <QMutexLocker>
40#include <QCoreApplication>
41#include <QFileInfo>
42
43#ifdef QT_SFW_IPC_DEBUG
44#ifdef Q_OS_UNIX
45#include <signal.h>
46#include <errno.h>
47#endif
48#include <QNetworkInterface>
49#include <QUdpSocket>
50#endif
51
52QT_BEGIN_NAMESPACE
53
54QServiceDebugMessage::QServiceDebugMessage()
55{
56#ifdef QT_SFW_IPC_DEBUG
57 buffer = new QBuffer();
58 buffer->open(QIODevice::WriteOnly);
59 ds.setDevice(buffer);
60 QTime t = QTime::currentTime();
61 ds << (quint8)t.hour();
62 ds << (quint8)t.minute();
63 ds << (quint8)t.second();
64 ds << (quint16)t.msec();
65 ds << (quint32)(QCoreApplication::applicationPid());
66 QFileInfo fi(QCoreApplication::applicationFilePath());
67 QByteArray ba = fi.fileName().toLatin1();
68 ds.writeBytes(ba.constData(), ba.size());
69#endif
70}
71
72QServiceDebugMessage::~QServiceDebugMessage()
73{
74#ifdef QT_SFW_IPC_DEBUG
75 /* when we're destructed, we're ready to send! */
76 buffer->close();
77 QServiceDebugLog::instance()->logMessage(this);
78#endif
79}
80
81#ifdef QT_SFW_IPC_DEBUG
82#include <QHostAddress>
83const static QHostAddress _group_addr(QLatin1String("224.0.105.201"));
84#endif
85
86QServiceDebugLog::QServiceDebugLog()
87{
88 makeSockets();
89}
90
91#ifdef QT_SFW_IPC_DEBUG
92#include <fcntl.h>
93#endif
94
95void QServiceDebugLog::makeSockets()
96{
97#ifdef QT_SFW_IPC_DEBUG
98 if (sockets.size() > 0)
99 return;
100
101 QList<QNetworkInterface> ifs = QNetworkInterface::allInterfaces();
102 foreach (const QNetworkInterface &inf, ifs) {
103 /* avoid the loopback or any wireless interfaces
104 * (we probably don't want debug over those) */
105 if (inf.name().startsWith("wifi")
106 || inf.name().startsWith("wl") || inf.name().startsWith("ppp")
107 || inf.name().startsWith("tun") || inf.name().startsWith("tap"))
108 continue;
109
110 QUdpSocket *socket = new QUdpSocket();
111 if (!socket->bind(QHostAddress::AnyIPv4, 10520, QAbstractSocket::ShareAddress)) {
112 delete socket;
113 continue;
114 }
115 socket->setMulticastInterface(inf);
116 if (!socket->joinMulticastGroup(_group_addr, inf)) {
117 delete socket;
118 continue;
119 }
120
121 int fd = socket->socketDescriptor();
122 int flags = ::fcntl(fd, F_GETFL, 0);
123 if (flags < 0) {
124 delete socket;
125 continue;
126 }
127 flags |= O_NONBLOCK;
128 if (::fcntl(fd, F_SETFL, flags)) {
129 delete socket;
130 continue;
131 }
132
133 qDebug("SFW udp debug on interface %s", qPrintable(inf.name()));
134 sockets << socket;
135 }
136#endif
137}
138
139void QServiceDebugLog::logMessage(QServiceDebugMessage *msg)
140{
141#ifdef QT_SFW_IPC_DEBUG
142 QMutexLocker m(&socketLock);
143
144 if (sockets.size() == 0) {
145 makeSockets();
146
147 if (sockets.size() == 0) {
148 queue << msg->buffer;
149 return;
150 }
151 }
152
153 if (sockets.size() > 0) {
154 while (!queue.isEmpty()) {
155 foreach (QUdpSocket *socket, sockets) {
156 int ret = socket->writeDatagram(queue.front()->data(), _group_addr, 10520);
157 if (ret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
158 queue << msg->buffer;
159 return;
160 }
161 }
162 delete queue.front();
163 queue.pop_front();
164 }
165 foreach (QUdpSocket *socket, sockets) {
166 int ret = socket->writeDatagram(msg->buffer->data(), _group_addr, 10520);
167 if (ret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
168 queue << msg->buffer;
169 return;
170 }
171 }
172 delete msg->buffer;
173 }
174#else
175 Q_UNUSED(msg)
176#endif
177}
178
179QServiceDebugLog *QServiceDebugLog::instance()
180{
181 static QServiceDebugLog *dbg = 0;
182 static QMutex m;
183 QMutexLocker l(&m);
184
185 if (!dbg)
186 dbg = new QServiceDebugLog();
187 return dbg;
188}
189
190QT_END_NAMESPACE
191

source code of qtsystems/src/serviceframework/qservicedebuglog.cpp