Skip to content
Open
6 changes: 4 additions & 2 deletions src/Camera/VehicleCameraControl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1817,7 +1817,8 @@ void VehicleCameraControl::setCurrentStream(int stream)
if (stream != _currentStream && stream >= 0 && stream < _streamLabels.count()) {
QGCVideoStreamInfo* pInfo = currentStreamInstance();
if(pInfo) {
qCDebug(VehicleCameraControlLog) << "Stopping stream:" << pInfo->uri();
qCDebug(VehicleCameraControlLog)
<< "Stopping stream:" << QGCNetworkHelper::redactedUrlForLogging(pInfo->uri());
//-- Stop current stream
_vehicle->sendMavCommand(
_compID, // Target component
Expand All @@ -1829,7 +1830,8 @@ void VehicleCameraControl::setCurrentStream(int stream)
pInfo = currentStreamInstance();
if(pInfo) {
//-- Start new stream
qCDebug(VehicleCameraControlLog) << "Starting stream:" << pInfo->uri();
qCDebug(VehicleCameraControlLog)
<< "Starting stream:" << QGCNetworkHelper::redactedUrlForLogging(pInfo->uri());
_vehicle->sendMavCommand(
_compID, // Target component
MAV_CMD_VIDEO_START_STREAMING, // Command id
Expand Down
25 changes: 17 additions & 8 deletions src/Settings/VideoSettings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "VideoManager.h"

#include "QGCLoggingCategory.h"
#include "QGCNetworkHelper.h"
#include <QtCore/QSettings>
#include <QtCore/QVariantList>

Expand Down Expand Up @@ -243,23 +244,31 @@ bool VideoSettings::streamConfigured(void)
}
//-- If UDP, check for URL
if(vSource == videoSourceUDPH264 || vSource == videoSourceUDPH265) {
qCDebug(VideoSettingsLog) << "Testing configuration for UDP Stream:" << udpUrl()->rawValue().toString();
return !udpUrl()->rawValue().toString().isEmpty();
const QString url = udpUrl()->rawValue().toString();
qCDebug(VideoSettingsLog) << "Testing configuration for UDP Stream:"
<< QGCNetworkHelper::redactedUrlForLogging(url);
return !url.isEmpty();
}
//-- If RTSP, check for URL
if(vSource == videoSourceRTSP) {
qCDebug(VideoSettingsLog) << "Testing configuration for RTSP Stream:" << rtspUrl()->rawValue().toString();
return !rtspUrl()->rawValue().toString().isEmpty();
const QString url = rtspUrl()->rawValue().toString();
qCDebug(VideoSettingsLog) << "Testing configuration for RTSP Stream:"
<< QGCNetworkHelper::redactedUrlForLogging(url);
return !url.isEmpty();
}
//-- If TCP, check for URL
if(vSource == videoSourceTCP) {
qCDebug(VideoSettingsLog) << "Testing configuration for TCP Stream:" << tcpUrl()->rawValue().toString();
return !tcpUrl()->rawValue().toString().isEmpty();
const QString url = tcpUrl()->rawValue().toString();
qCDebug(VideoSettingsLog) << "Testing configuration for TCP Stream:"
<< QGCNetworkHelper::redactedUrlForLogging(url);
return !url.isEmpty();
}
//-- If MPEG-TS, check for URL
if(vSource == videoSourceMPEGTS) {
qCDebug(VideoSettingsLog) << "Testing configuration for MPEG-TS Stream:" << udpUrl()->rawValue().toString();
return !udpUrl()->rawValue().toString().isEmpty();
const QString url = udpUrl()->rawValue().toString();
qCDebug(VideoSettingsLog) << "Testing configuration for MPEG-TS Stream:"
<< QGCNetworkHelper::redactedUrlForLogging(url);
return !url.isEmpty();
}
//-- If Herelink Air unit, good to go
if(vSource == videoSourceHerelinkAirUnit) {
Expand Down
53 changes: 53 additions & 0 deletions src/Utilities/Network/QGCNetworkHelper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <QtCore/QFile>
#include <QtCore/QIODevice>
#include <QtCore/QJsonDocument>
#include <QtCore/QRegularExpression>
#include <QtCore/QUrlQuery>
#include <QtNetwork/QHttpHeaders>
#include <QtNetwork/QHttpPart>
Expand Down Expand Up @@ -342,6 +343,58 @@ QUrl urlWithoutQuery(const QUrl& url)
return url.adjusted(QUrl::RemoveQuery | QUrl::RemoveFragment);
}

namespace {
bool isHostPortForLogging(const QString& value)
{
static const QRegularExpression pattern(QStringLiteral(R"(^[^/@?#\s]+:\d{1,5}$)"));
return pattern.match(value).hasMatch();
Comment on lines +349 to +350
}
} // namespace

QString redactedUrlForLogging(const QUrl& url)
{
if (url.isEmpty()) {
return QStringLiteral("<empty-url>");
}
if (!url.isValid()) {
if (url.scheme().isEmpty() && isHostPortForLogging(url.path())) {
return url.path();
}
return QStringLiteral("<invalid-url>");
}

QUrl redactedUrl = url.adjusted(QUrl::RemoveUserInfo);
if (redactedUrl.hasQuery()) {
const auto queryItems = QUrlQuery(redactedUrl).queryItems(QUrl::FullyDecoded);
QUrlQuery redactedQuery;
for (const auto& queryItem : queryItems) {
redactedQuery.addQueryItem(queryItem.first, QStringLiteral("REDACTED"));
}
if (queryItems.isEmpty()) {
redactedUrl.setQuery(QString());
} else {
redactedUrl.setQuery(redactedQuery);
}
}
if (redactedUrl.hasFragment()) {
redactedUrl.setFragment(QStringLiteral("REDACTED"));
}

return redactedUrl.toDisplayString(QUrl::FullyEncoded);
}

QString redactedUrlForLogging(const QString& url)
{
if (isHostPortForLogging(url)) {
return url;
}
const QUrl parsedUrl(url);
if (!url.isEmpty() && !parsedUrl.isValid()) {
return QStringLiteral("<invalid-url length=%1>").arg(url.size());
}
return redactedUrlForLogging(parsedUrl);
}

// ============================================================================
// Request Configuration
// ============================================================================
Expand Down
5 changes: 5 additions & 0 deletions src/Utilities/Network/QGCNetworkHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ QUrl buildUrl(const QString& baseUrl, const QList<QPair<QString, QString>>& para
/// Get URL without query string and fragment
QUrl urlWithoutQuery(const QUrl& url);

/// Return a URL suitable for diagnostics. Stream identity is preserved while user info,
/// query values, and fragment content are redacted.
QString redactedUrlForLogging(const QUrl& url);
QString redactedUrlForLogging(const QString& url);

// ============================================================================
// Request Configuration
// ============================================================================
Expand Down
13 changes: 9 additions & 4 deletions src/VideoManager/VideoManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "QGCCameraManager.h"
#include "QGCCorePlugin.h"
#include "QGCLoggingCategory.h"
#include "QGCNetworkHelper.h"
#include "QGCVideoStreamInfo.h"
#include "SettingsManager.h"
#include "SubtitleWriter.h"
Expand Down Expand Up @@ -593,7 +594,8 @@ bool VideoManager::_updateAutoStream(VideoReceiver *receiver)
return false;
}

qCDebug(VideoManagerLog) << QString("Configure stream (%1):").arg(receiver->name()) << pInfo->uri();
qCDebug(VideoManagerLog) << QString("Configure stream (%1):").arg(receiver->name())
<< QGCNetworkHelper::redactedUrlForLogging(pInfo->uri());

QString source, url;
switch (pInfo->type()) {
Expand Down Expand Up @@ -651,7 +653,7 @@ bool VideoManager::_updateVideoUri(VideoReceiver *receiver, const QString &uri)
return false;
}

qCDebug(VideoManagerLog) << "New Video URI" << uri;
qCDebug(VideoManagerLog) << "New Video URI" << QGCNetworkHelper::redactedUrlForLogging(uri);

receiver->setUri(uri);

Expand Down Expand Up @@ -899,13 +901,16 @@ void VideoManager::_initVideoReceiver(VideoReceiver *receiver, QQuickWindow *win
});

(void) connect(receiver, &VideoReceiver::onStopComplete, this, [this, receiver](VideoReceiver::STATUS status) {
qCDebug(VideoManagerLog) << "Stop complete" << receiver->name() << receiver->uri() << ", status:" << status;
qCDebug(VideoManagerLog) << "Stop complete" << receiver->name()
<< QGCNetworkHelper::redactedUrlForLogging(receiver->uri())
<< ", status:" << status;
receiver->setStarted(false);
if (status == VideoReceiver::STATUS_INVALID_URL) {
qCDebug(VideoManagerLog) << "Invalid video URL. Not restarting";
} else {
QTimer::singleShot(1000, receiver, [this, receiver]() {
qCDebug(VideoManagerLog) << "Restarting video receiver" << receiver->name() << receiver->uri();
qCDebug(VideoManagerLog) << "Restarting video receiver" << receiver->name()
<< QGCNetworkHelper::redactedUrlForLogging(receiver->uri());
_startReceiver(receiver);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ QString writePipelineDot(GstElement* pipeline, const char* tag)
QFile::remove(existing.takeFirst().absoluteFilePath());
}

gchar* data = gst_debug_bin_to_dot_data(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL);
gchar* data = gst_debug_bin_to_dot_data(GST_BIN(pipeline), kDiagnosticDotGraphDetails);
if (!data)
return {};
const QString fileName = QStringLiteral("%1-%2.dot")
Expand Down
4 changes: 4 additions & 0 deletions src/VideoManager/VideoReceiver/GStreamer/GStreamerHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include "GStreamer.h" // VideoDecoderOptions

namespace GStreamer {
/// Automatic field-report graphs omit element properties because source properties can contain credentials.
inline constexpr GstDebugGraphDetails kDiagnosticDotGraphDetails = static_cast<GstDebugGraphDetails>(
GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS | GST_DEBUG_GRAPH_SHOW_STATES);
Comment on lines +12 to +14

bool isValidRtspUri(const gchar* uri_str);

/// Dump @p pipeline's graph as a rotating .dot under CacheLocation/qgc-pipeline-dot/ for field reports.
Expand Down
15 changes: 10 additions & 5 deletions src/VideoManager/VideoReceiver/GStreamer/GstSourceFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "GStreamerHelpers.h"
#include "QGCLoggingCategory.h"
#include "QGCNetworkHelper.h"

QGC_LOGGING_CATEGORY(GstSourceFactoryLog, "Video.GStreamer.GstSourceFactory")

Expand Down Expand Up @@ -273,7 +274,7 @@ void linkPad(GstElement* element, GstPad* pad, gpointer data)
GstElement* buildRtspSource(const QString& uri, const QUrl& sourceUrl, const Config& config, guint latencyMs)
{
if (!GStreamer::isValidRtspUri(uri.toUtf8().constData())) {
qCCritical(GstSourceFactoryLog) << "Invalid RTSP URI:" << sourceUrl.toDisplayString(QUrl::RemoveUserInfo);
qCWarning(GstSourceFactoryLog) << "Invalid RTSP URI:" << QGCNetworkHelper::redactedUrlForLogging(sourceUrl);
return nullptr;
}

Expand Down Expand Up @@ -313,12 +314,14 @@ GstElement* buildTcpSource(const QUrl& sourceUrl)
{
const int port = sourceUrl.port();
if (!validPort(port)) {
qCCritical(GstSourceFactoryLog) << "Invalid TCP port" << port << "in" << sourceUrl.toDisplayString(QUrl::RemoveUserInfo);
qCWarning(GstSourceFactoryLog) << "Invalid TCP port" << port << "in"
<< QGCNetworkHelper::redactedUrlForLogging(sourceUrl);
return nullptr;
}
const QString host = sourceUrl.host();
if (host.isEmpty()) {
qCCritical(GstSourceFactoryLog) << "Missing host in TCP URI" << sourceUrl.toDisplayString(QUrl::RemoveUserInfo);
qCWarning(GstSourceFactoryLog) << "Missing host in TCP URI"
<< QGCNetworkHelper::redactedUrlForLogging(sourceUrl);
return nullptr;
}

Expand All @@ -336,7 +339,8 @@ GstElement* buildUdpSource(const QUrl& sourceUrl, bool isUdpH264, bool isUdpH265
{
const int port = sourceUrl.port();
if (!validPort(port)) {
qCCritical(GstSourceFactoryLog) << "Invalid UDP port" << port << "in" << sourceUrl.toDisplayString(QUrl::RemoveUserInfo);
qCWarning(GstSourceFactoryLog) << "Invalid UDP port" << port << "in"
<< QGCNetworkHelper::redactedUrlForLogging(sourceUrl);
return nullptr;
}

Expand Down Expand Up @@ -505,7 +509,8 @@ GstElement* create(const QString& uri, const Config& config)
const bool isTcpMPEGTS = (scheme == QLatin1String("tcp"));

if (!isRtsp && !isUdpH264 && !isUdpH265 && !isUdpMPEGTS && !isTcpMPEGTS) {
qCWarning(GstSourceFactoryLog) << "Unsupported URI scheme:" << scheme << "in" << sourceUrl.toDisplayString(QUrl::RemoveUserInfo);
qCWarning(GstSourceFactoryLog) << "Unsupported URI scheme:" << scheme << "in"
<< QGCNetworkHelper::redactedUrlForLogging(sourceUrl);
return nullptr;
}

Expand Down
Loading
Loading