242 lines · 6.7 KB · C++
RawDownload
////  NetworkPeer.cpp//  libraries/networking/src////  Created by Stephen Birarda on 2014-10-02.//  Copyright 2014 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "NetworkPeer.h" #include <QtCore/QDateTime>#include <QtCore/QDebug> #include <SharedUtil.h>#include <UUID.h> #include "NetworkLogging.h" #include "BandwidthRecorder.h" NetworkPeer::NetworkPeer(QObject* parent) :    QObject(parent),    _uuid(),    _publicSocket(),    _localSocket(),    _symmetricSocket(),    _activeSocket(NULL),    _wakeTimestamp(QDateTime::currentMSecsSinceEpoch()),    _lastHeardMicrostamp(usecTimestampNow()),    _connectionAttempts(0){ } NetworkPeer::NetworkPeer(const QUuid& uuid, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, QObject* parent) :    QObject(parent),    _uuid(uuid),    _publicSocket(publicSocket),    _localSocket(localSocket),    _symmetricSocket(),    _activeSocket(NULL),    _wakeTimestamp(QDateTime::currentMSecsSinceEpoch()),    _lastHeardMicrostamp(usecTimestampNow()),    _connectionAttempts(0){ } void NetworkPeer::setPublicSocket(const HifiSockAddr& publicSocket) {    if (publicSocket != _publicSocket) {        if (_activeSocket == &_publicSocket) {            // if the active socket was the public socket then reset it to NULL            _activeSocket = NULL;        }         if (!_publicSocket.isNull()) {            qCDebug(networking) << "Public socket change for node" << *this;        }         _publicSocket = publicSocket;    }} void NetworkPeer::setLocalSocket(const HifiSockAddr& localSocket) {    if (localSocket != _localSocket) {        if (_activeSocket == &_localSocket) {            // if the active socket was the local socket then reset it to NULL            _activeSocket = NULL;        }         if (!_localSocket.isNull()) {            qCDebug(networking) << "Local socket change for node" << *this;        }         _localSocket = localSocket;    }} void NetworkPeer::setSymmetricSocket(const HifiSockAddr& symmetricSocket) {    if (symmetricSocket != _symmetricSocket) {        if (_activeSocket == &_symmetricSocket) {            // if the active socket was the symmetric socket then reset it to NULL            _activeSocket = NULL;        }         if (!_symmetricSocket.isNull()) {            qCDebug(networking) << "Symmetric socket change for node" << *this;        }         _symmetricSocket = symmetricSocket;    }} void NetworkPeer::setActiveSocket(HifiSockAddr* discoveredSocket) {    _activeSocket = discoveredSocket;     // we have an active socket, stop our ping timer    stopPingTimer();     // we're now considered connected to this peer - reset the number of connection attemps    resetConnectionAttempts();} void NetworkPeer::activateLocalSocket() {    if (_activeSocket != &_localSocket) {        qCDebug(networking) << "Activating local socket for network peer with ID" << uuidStringWithoutCurlyBraces(_uuid);        setActiveSocket(&_localSocket);    }} void NetworkPeer::activatePublicSocket() {    if (_activeSocket != &_publicSocket) {        qCDebug(networking) << "Activating public socket for network peer with ID" << uuidStringWithoutCurlyBraces(_uuid);        setActiveSocket(&_publicSocket);    }} void NetworkPeer::activateSymmetricSocket() {    if (_activeSocket != &_symmetricSocket) {        qCDebug(networking) << "Activating symmetric socket for network peer with ID" << uuidStringWithoutCurlyBraces(_uuid);        setActiveSocket(&_symmetricSocket);    }} void NetworkPeer::activateMatchingOrNewSymmetricSocket(const HifiSockAddr& matchableSockAddr) {    if (matchableSockAddr == _publicSocket) {        activatePublicSocket();    } else if (matchableSockAddr == _localSocket) {        activateLocalSocket();    } else {        // set the Node's symmetric socket to the passed socket        setSymmetricSocket(matchableSockAddr);        activateSymmetricSocket();    }} void NetworkPeer::softReset() {    // a soft reset should clear the sockets and reset the number of connection attempts    _localSocket.clear();    _publicSocket.clear();    _symmetricSocket.clear();    _activeSocket = NULL;     // stop our ping timer since we don't have sockets to ping anymore anyways    stopPingTimer();     _connectionAttempts = 0;} void NetworkPeer::reset() {    softReset();     _uuid = QUuid();    _wakeTimestamp = QDateTime::currentMSecsSinceEpoch();    _lastHeardMicrostamp = usecTimestampNow();} QByteArray NetworkPeer::toByteArray() const {    QByteArray peerByteArray;     QDataStream peerStream(&peerByteArray, QIODevice::Append);    peerStream << *this;     return peerByteArray;} void NetworkPeer::startPingTimer() {    if (!_pingTimer) {        _pingTimer = new QTimer(this);         connect(_pingTimer, &QTimer::timeout, this, &NetworkPeer::pingTimerTimeout);         _pingTimer->start(UDP_PUNCH_PING_INTERVAL_MS);    }} void NetworkPeer::stopPingTimer() {    if (_pingTimer) {        _pingTimer->stop();        _pingTimer->deleteLater();        _pingTimer = NULL;    }} QDataStream& operator<<(QDataStream& out, const NetworkPeer& peer) {    out << peer._uuid;    out << peer._publicSocket;    out << peer._localSocket;     return out;} QDataStream& operator>>(QDataStream& in, NetworkPeer& peer) {    in >> peer._uuid;    in >> peer._publicSocket;    in >> peer._localSocket;     return in;} QDebug operator<<(QDebug debug, const NetworkPeer &peer) {    debug << uuidStringWithoutCurlyBraces(peer.getUUID())        << "- public:" << peer.getPublicSocket()        << "- local:" << peer.getLocalSocket();    return debug;}  // FIXME this is a temporary implementation to determine if this is the right approach.// If so, migrate the BandwidthRecorder into the NetworkPeer classusing BandwidthRecorderPtr = QSharedPointer<BandwidthRecorder>;static QHash<QUuid, BandwidthRecorderPtr> PEER_BANDWIDTH; BandwidthRecorder& getBandwidthRecorder(const QUuid & uuid) {    if (!PEER_BANDWIDTH.count(uuid)) {        PEER_BANDWIDTH.insert(uuid, BandwidthRecorderPtr(new BandwidthRecorder()));    }    return *PEER_BANDWIDTH[uuid].data();} void NetworkPeer::recordBytesSent(int count) {    auto& bw = getBandwidthRecorder(_uuid);    bw.updateOutboundData(0, count);} void NetworkPeer::recordBytesReceived(int count) {    auto& bw = getBandwidthRecorder(_uuid);    bw.updateInboundData(0, count);} float NetworkPeer::getOutboundBandwidth() {    auto& bw = getBandwidthRecorder(_uuid);    return bw.getAverageOutputKilobitsPerSecond(0);} float NetworkPeer::getInboundBandwidth() {    auto& bw = getBandwidthRecorder(_uuid);    return bw.getAverageInputKilobitsPerSecond(0);}