From 7d7cba4dd2befbd9cb663d77544f42e497f90cd5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 31 Aug 2016 11:30:47 -0700 Subject: [PATCH] fix networking compile for android setsockopt --- libraries/networking/src/udt/Socket.cpp | 102 ++++++++++++------------ 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index b3ddc24914..a39100f8d1 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -11,6 +11,10 @@ #include "Socket.h" +#ifdef Q_OS_ANDROID +#include +#endif + #include #include @@ -30,10 +34,10 @@ Socket::Socket(QObject* parent) : _synTimer(new QTimer(this)) { connect(&_udpSocket, &QUdpSocket::readyRead, this, &Socket::readPendingDatagrams); - + // make sure our synchronization method is called every SYN interval connect(_synTimer, &QTimer::timeout, this, &Socket::rateControlSync); - + // start our timer for the synchronization time interval _synTimer->start(_synInterval); @@ -60,7 +64,7 @@ void Socket::bind(const QHostAddress& address, quint16 port) { void Socket::rebind() { quint16 oldPort = _udpSocket.localPort(); - + _udpSocket.close(); bind(QHostAddress::AnyIPv4, oldPort); } @@ -69,26 +73,26 @@ void Socket::setSystemBufferSizes() { for (int i = 0; i < 2; i++) { QAbstractSocket::SocketOption bufferOpt; QString bufferTypeString; - + int numBytes = 0; - + if (i == 0) { bufferOpt = QAbstractSocket::SendBufferSizeSocketOption; numBytes = udt::UDP_SEND_BUFFER_SIZE_BYTES; bufferTypeString = "send"; - + } else { bufferOpt = QAbstractSocket::ReceiveBufferSizeSocketOption; numBytes = udt::UDP_RECEIVE_BUFFER_SIZE_BYTES; bufferTypeString = "receive"; } - + int oldBufferSize = _udpSocket.socketOption(bufferOpt).toInt(); - + if (oldBufferSize < numBytes) { _udpSocket.setSocketOption(bufferOpt, QVariant(numBytes)); int newBufferSize = _udpSocket.socketOption(bufferOpt).toInt(); - + qCDebug(networking) << "Changed socket" << bufferTypeString << "buffer size from" << oldBufferSize << "to" << newBufferSize << "bytes"; } else { @@ -101,29 +105,29 @@ void Socket::setSystemBufferSizes() { qint64 Socket::writeBasePacket(const udt::BasePacket& packet, const HifiSockAddr &sockAddr) { // Since this is a base packet we have no way to know if this is reliable or not - we just fire it off - + // this should not be called with an instance of Packet Q_ASSERT_X(!dynamic_cast(&packet), "Socket::writeBasePacket", "Cannot send a Packet/NLPacket via writeBasePacket"); - + return writeDatagram(packet.getData(), packet.getDataSize(), sockAddr); } qint64 Socket::writePacket(const Packet& packet, const HifiSockAddr& sockAddr) { Q_ASSERT_X(!packet.isReliable(), "Socket::writePacket", "Cannot send a reliable packet unreliably"); - + // write the correct sequence number to the Packet here packet.writeSequenceNumber(++_unreliableSequenceNumbers[sockAddr]); - + return writeDatagram(packet.getData(), packet.getDataSize(), sockAddr); } qint64 Socket::writePacket(std::unique_ptr packet, const HifiSockAddr& sockAddr) { - + if (packet->isReliable()) { // hand this packet off to writeReliablePacket // because Qt can't invoke with the unique_ptr we have to release it here and re-construct in writeReliablePacket - + if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "writeReliablePacket", Qt::QueuedConnection, Q_ARG(Packet*, packet.release()), @@ -131,10 +135,10 @@ qint64 Socket::writePacket(std::unique_ptr packet, const HifiSockAddr& s } else { writeReliablePacket(packet.release(), sockAddr); } - + return 0; } - + return writePacket(*packet, sockAddr); } @@ -142,7 +146,7 @@ qint64 Socket::writePacketList(std::unique_ptr packetList, const Hif if (packetList->isReliable()) { // hand this packetList off to writeReliablePacketList // because Qt can't invoke with the unique_ptr we have to release it here and re-construct in writeReliablePacketList - + if (QThread::currentThread() != thread()) { auto ptr = packetList.release(); QMetaObject::invokeMethod(this, "writeReliablePacketList", Qt::AutoConnection, @@ -151,7 +155,7 @@ qint64 Socket::writePacketList(std::unique_ptr packetList, const Hif } else { writeReliablePacketList(packetList.release(), sockAddr); } - + return 0; } @@ -177,18 +181,18 @@ qint64 Socket::writeDatagram(const char* data, qint64 size, const HifiSockAddr& } qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& sockAddr) { - + qint64 bytesWritten = _udpSocket.writeDatagram(datagram, sockAddr.getAddress(), sockAddr.getPort()); - + if (bytesWritten < 0) { // when saturating a link this isn't an uncommon message - suppress it so it doesn't bomb the debug static const QString WRITE_ERROR_REGEX = "Socket::writeDatagram QAbstractSocket::NetworkError - Unable to send a message"; static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(WRITE_ERROR_REGEX); - + qCDebug(networking) << "Socket::writeDatagram" << _udpSocket.error() << "-" << qPrintable(_udpSocket.errorString()); } - + return bytesWritten; } @@ -199,17 +203,17 @@ Connection& Socket::findOrCreateConnection(const HifiSockAddr& sockAddr) { auto congestionControl = _ccFactory->create(); congestionControl->setMaxBandwidth(_maxBandwidth); auto connection = std::unique_ptr(new Connection(this, sockAddr, std::move(congestionControl))); - + // we queue the connection to cleanup connection in case it asks for it during its own rate control sync QObject::connect(connection.get(), &Connection::connectionInactive, this, &Socket::cleanupConnection); - + #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Creating new connection to" << sockAddr; #endif - + it = _connectionsHash.insert(it, std::make_pair(sockAddr, std::move(connection))); } - + return *it->second; } @@ -228,7 +232,7 @@ void Socket::clearConnections() { void Socket::cleanupConnection(HifiSockAddr sockAddr) { auto numErased = _connectionsHash.erase(sockAddr); - + if (numErased > 0) { #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "Socket::cleanupConnection called for UDT connection to" << sockAddr; @@ -253,10 +257,10 @@ void Socket::readPendingDatagrams() { while ((packetSizeWithHeader = _udpSocket.pendingDatagramSize()) != -1) { // setup a HifiSockAddr to read into HifiSockAddr senderSockAddr; - + // setup a buffer to read the packet into auto buffer = std::unique_ptr(new char[packetSizeWithHeader]); - + // pull the datagram auto sizeRead = _udpSocket.readDatagram(buffer.get(), packetSizeWithHeader, senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); @@ -266,34 +270,34 @@ void Socket::readPendingDatagrams() { // on windows even if there's not a packet available) continue; } - + auto it = _unfilteredHandlers.find(senderSockAddr); - + if (it != _unfilteredHandlers.end()) { // we have a registered unfiltered handler for this HifiSockAddr - call that and return if (it->second) { auto basePacket = BasePacket::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr); it->second(std::move(basePacket)); } - + continue; } - + // check if this was a control packet or a data packet bool isControlPacket = *reinterpret_cast(buffer.get()) & CONTROL_BIT_MASK; - + if (isControlPacket) { // setup a control packet from the data we just read auto controlPacket = ControlPacket::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr); - + // move this control packet to the matching connection auto& connection = findOrCreateConnection(senderSockAddr); connection.processControl(move(controlPacket)); - + } else { // setup a Packet from the data we just read auto packet = Packet::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr); - + // call our verification operator to see if this packet is verified if (!_packetFilterOperator || _packetFilterOperator(*packet)) { if (packet->isReliable()) { @@ -328,27 +332,27 @@ void Socket::connectToSendSignal(const HifiSockAddr& destinationAddr, QObject* r } void Socket::rateControlSync() { - + // enumerate our list of connections and ask each of them to send off periodic ACK packet for rate control - + // the way we do this is a little funny looking - we need to avoid the case where we call sync and // (because of our Qt direct connection to the Connection's signal that it has been deactivated) // an iterator on _connectionsHash would be invalidated by our own call to cleanupConnection - + // collect the sockets for all connections in a vector - + std::vector sockAddrVector; sockAddrVector.reserve(_connectionsHash.size()); - + for (auto& connection : _connectionsHash) { sockAddrVector.emplace_back(connection.first); } - + // enumerate that vector of HifiSockAddr objects for (auto& sockAddr : sockAddrVector) { // pull out the respective connection via a quick find on the unordered_map auto it = _connectionsHash.find(sockAddr); - + if (it != _connectionsHash.end()) { // if the connection is erased while calling sync since we are re-using the iterator that was invalidated // we're good to go @@ -356,7 +360,7 @@ void Socket::rateControlSync() { connection->sync(); } } - + if (_synTimer->interval() != _synInterval) { // if the _synTimer interval doesn't match the current _synInterval (changes when the CC factory is changed) // then restart it now with the right interval @@ -367,7 +371,7 @@ void Socket::rateControlSync() { void Socket::setCongestionControlFactory(std::unique_ptr ccFactory) { // swap the current unique_ptr for the new factory _ccFactory.swap(ccFactory); - + // update the _synInterval to the value from the factory _synInterval = _ccFactory->synInterval(); } @@ -402,10 +406,10 @@ Socket::StatsVector Socket::sampleStatsForAllConnections() { } -std::vector Socket::getConnectionSockAddrs() { +std::vector Socket::getConnectionSockAddrs() { std::vector addr; addr.reserve(_connectionsHash.size()); - + for (const auto& connectionPair : _connectionsHash) { addr.push_back(connectionPair.first); }