mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-30 19:23:22 +02:00
291 lines
9.1 KiB
C++
291 lines
9.1 KiB
C++
//
|
|
// NetworkSocket.cpp
|
|
// libraries/networking/src/udt
|
|
//
|
|
// Created by David Rowe on 21 Jun 2021.
|
|
// Copyright 2021 Vircadia contributors.
|
|
//
|
|
|
|
#include "NetworkSocket.h"
|
|
|
|
#include "../NetworkLogging.h"
|
|
|
|
|
|
NetworkSocket::NetworkSocket(QObject* parent) :
|
|
QObject(parent),
|
|
_parent(parent),
|
|
_udpSocket(this)
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
,
|
|
_webrtcSocket(this)
|
|
#endif
|
|
{
|
|
connect(&_udpSocket, &QUdpSocket::readyRead, this, &NetworkSocket::readyRead);
|
|
connect(&_udpSocket, &QAbstractSocket::stateChanged, this, &NetworkSocket::onUDPStateChanged);
|
|
// Use old SIGNAL/SLOT mechanism for Android builds.
|
|
connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
|
|
this, SLOT(onUDPSocketError(QAbstractSocket::SocketError)));
|
|
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
connect(&_webrtcSocket, &WebRTCSocket::readyRead, this, &NetworkSocket::readyRead);
|
|
connect(&_webrtcSocket, &WebRTCSocket::stateChanged, this, &NetworkSocket::onWebRTCStateChanged);
|
|
// WEBRTC TODO: Add similar for errorOccurred
|
|
#endif
|
|
}
|
|
|
|
|
|
void NetworkSocket::setSocketOption(SocketType socketType, QAbstractSocket::SocketOption option, const QVariant& value) {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
_udpSocket.setSocketOption(option, value);
|
|
break;
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
_webrtcSocket.setSocketOption(option, value);
|
|
break;
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in setSocketOption()";
|
|
}
|
|
}
|
|
|
|
QVariant NetworkSocket::socketOption(SocketType socketType, QAbstractSocket::SocketOption option) {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
return _udpSocket.socketOption(option);
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.socketOption(option);
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in socketOption()";
|
|
return "";
|
|
}
|
|
}
|
|
|
|
|
|
void NetworkSocket::bind(SocketType socketType, const QHostAddress& address, quint16 port) {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
_udpSocket.bind(address, port);
|
|
break;
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
_webrtcSocket.bind(address, port);
|
|
break;
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in bind()";
|
|
}
|
|
}
|
|
|
|
void NetworkSocket::abort(SocketType socketType) {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
_udpSocket.abort();
|
|
break;
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
_webrtcSocket.abort();
|
|
break;
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in abort()";
|
|
}
|
|
}
|
|
|
|
|
|
quint16 NetworkSocket::localPort(SocketType socketType) const {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
return _udpSocket.localPort();
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.localPort();
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in localPort()";
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
qintptr NetworkSocket::socketDescriptor(SocketType socketType) const {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
return _udpSocket.socketDescriptor();
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.socketDescriptor();
|
|
return 0;
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in socketDescriptor()";
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
qint64 NetworkSocket::writeDatagram(const QByteArray& datagram, const SockAddr& sockAddr) {
|
|
switch (sockAddr.getSocketType()) {
|
|
case SocketType::UDP:
|
|
// WEBRTC TODO: The Qt documentation says that the following call shouldn't be used if the UDP socket is connected!!!
|
|
// https://doc.qt.io/qt-5/qudpsocket.html#writeDatagram
|
|
return _udpSocket.writeDatagram(datagram, sockAddr.getAddress(), sockAddr.getPort());
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.writeDatagram(datagram, sockAddr.getPort());
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in writeDatagram() address";
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
qint64 NetworkSocket::bytesToWrite(SocketType socketType, quint16 port) const {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
return _udpSocket.bytesToWrite();
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.bytesToWrite(port);
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in bytesToWrite()";
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
bool NetworkSocket::hasPendingDatagrams() const {
|
|
return
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
_webrtcSocket.hasPendingDatagrams() ||
|
|
#endif
|
|
_udpSocket.hasPendingDatagrams();
|
|
}
|
|
|
|
qint64 NetworkSocket::pendingDatagramSize() {
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
// Alternate socket types, remembering the socket type used so that the same socket type is used next readDatagram().
|
|
if (_lastSocketTypeRead == SocketType::UDP) {
|
|
if (_webrtcSocket.hasPendingDatagrams()) {
|
|
_pendingDatagramSizeSocketType = SocketType::WebRTC;
|
|
return _webrtcSocket.pendingDatagramSize();
|
|
} else {
|
|
_pendingDatagramSizeSocketType = SocketType::UDP;
|
|
return _udpSocket.pendingDatagramSize();
|
|
}
|
|
} else {
|
|
if (_udpSocket.hasPendingDatagrams()) {
|
|
_pendingDatagramSizeSocketType = SocketType::UDP;
|
|
return _udpSocket.pendingDatagramSize();
|
|
} else {
|
|
_pendingDatagramSizeSocketType = SocketType::WebRTC;
|
|
return _webrtcSocket.pendingDatagramSize();
|
|
}
|
|
}
|
|
#else
|
|
return _udpSocket.pendingDatagramSize();
|
|
#endif
|
|
}
|
|
|
|
qint64 NetworkSocket::readDatagram(char* data, qint64 maxSize, SockAddr* sockAddr) {
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
// Read per preceding pendingDatagramSize() if any, otherwise alternate socket types.
|
|
if (_pendingDatagramSizeSocketType == SocketType::UDP
|
|
|| _pendingDatagramSizeSocketType == SocketType::Unknown && _lastSocketTypeRead == SocketType::WebRTC) {
|
|
_lastSocketTypeRead = SocketType::UDP;
|
|
_pendingDatagramSizeSocketType = SocketType::Unknown;
|
|
if (sockAddr) {
|
|
sockAddr->setSocketType(SocketType::UDP);
|
|
return _udpSocket.readDatagram(data, maxSize, sockAddr->getAddressPointer(), sockAddr->getPortPointer());
|
|
} else {
|
|
return _udpSocket.readDatagram(data, maxSize);
|
|
}
|
|
} else {
|
|
_lastSocketTypeRead = SocketType::WebRTC;
|
|
_pendingDatagramSizeSocketType = SocketType::Unknown;
|
|
if (sockAddr) {
|
|
sockAddr->setSocketType(SocketType::WebRTC);
|
|
return _webrtcSocket.readDatagram(data, maxSize, sockAddr->getAddressPointer(), sockAddr->getPortPointer());
|
|
} else {
|
|
return _webrtcSocket.readDatagram(data, maxSize);
|
|
}
|
|
}
|
|
#else
|
|
if (sockAddr) {
|
|
sockAddr->setSocketType(SocketType::UDP);
|
|
return _udpSocket.readDatagram(data, maxSize, sockAddr->getAddressPointer(), sockAddr->getPortPointer());
|
|
} else {
|
|
return _udpSocket.readDatagram(data, maxSize);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
QAbstractSocket::SocketState NetworkSocket::state(SocketType socketType) const {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
return _udpSocket.state();
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.state();
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in state()";
|
|
return QAbstractSocket::SocketState::UnconnectedState;
|
|
}
|
|
}
|
|
|
|
|
|
QAbstractSocket::SocketError NetworkSocket::error(SocketType socketType) const {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
return _udpSocket.error();
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.error();
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in error()";
|
|
return QAbstractSocket::SocketError::UnknownSocketError;
|
|
}
|
|
}
|
|
|
|
QString NetworkSocket::errorString(SocketType socketType) const {
|
|
switch (socketType) {
|
|
case SocketType::UDP:
|
|
return _udpSocket.errorString();
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
case SocketType::WebRTC:
|
|
return _webrtcSocket.errorString();
|
|
#endif
|
|
default:
|
|
qCCritical(networking) << "Socket type not specified in errorString()";
|
|
return "";
|
|
}
|
|
}
|
|
|
|
|
|
#if defined(WEBRTC_DATA_CHANNELS)
|
|
const WebRTCSocket* NetworkSocket::getWebRTCSocket() {
|
|
return &_webrtcSocket;
|
|
}
|
|
#endif
|
|
|
|
|
|
void NetworkSocket::onUDPStateChanged(QAbstractSocket::SocketState socketState) {
|
|
emit stateChanged(SocketType::UDP, socketState);
|
|
}
|
|
|
|
void NetworkSocket::onWebRTCStateChanged(QAbstractSocket::SocketState socketState) {
|
|
emit stateChanged(SocketType::WebRTC, socketState);
|
|
}
|
|
|
|
void NetworkSocket::onUDPSocketError(QAbstractSocket::SocketError socketError) {
|
|
emit NetworkSocket::socketError(SocketType::UDP, socketError);
|
|
}
|
|
|
|
void NetworkSocket::onWebRTCSocketError(QAbstractSocket::SocketError socketError) {
|
|
emit NetworkSocket::socketError(SocketType::WebRTC, socketError);
|
|
}
|