Skip to content

Commit

Permalink
Merge branch 'ice'
Browse files Browse the repository at this point in the history
  • Loading branch information
altonen committed Apr 25, 2019
2 parents aa2d61d + 510e692 commit 2f0041a
Show file tree
Hide file tree
Showing 21 changed files with 1,070 additions and 464 deletions.
85 changes: 35 additions & 50 deletions src/connectiontester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
#include "stun.h"

ConnectionTester::ConnectionTester():
rtp_pair_(nullptr),
rtcp_pair_(nullptr),
pair_(nullptr),
controller_(false)
{
}
Expand All @@ -12,80 +11,66 @@ ConnectionTester::~ConnectionTester()
{
}

void ConnectionTester::setCandidatePair(ICEPair *rtp_pair, ICEPair *rtcp_pair)
void ConnectionTester::setCandidatePair(std::shared_ptr<ICEPair> pair)
{
rtp_pair_ = rtp_pair;
rtcp_pair_ = rtcp_pair;
pair_ = pair;
}

void ConnectionTester::isController(bool controller)
{
controller_ = controller;
}

void ConnectionTester::run()
void ConnectionTester::setStun(Stun *stun)
{
if (rtp_pair_ == nullptr || rtcp_pair_ == nullptr)
{
qDebug() << "Unable to test connection, RTP or RTCP candidate is NULL!";
return;
}

Stun stun;
stun_ = stun;

rtcp_pair_->state = PAIR_WAITING;
rtp_pair_->state = PAIR_IN_PROGRESS;

if (stun.sendBindingRequest(rtp_pair_, controller_))
{
rtp_pair_->state = PAIR_SUCCEEDED;
rtcp_pair_->state = PAIR_IN_PROGRESS;
QObject::connect(this, &ConnectionTester::stopTesting, stun, &Stun::stopTesting);
}

if (stun.sendBindingRequest(rtcp_pair_, controller_))
{
rtcp_pair_->state = PAIR_SUCCEEDED;
}
else
{
rtcp_pair_->state = PAIR_FAILED;
}
}
else
{
rtp_pair_->state = PAIR_FAILED;
}
void ConnectionTester::quit()
{
emit stopTesting();
QThread::quit();
}

/* remote did not respond to our binding requests -> terminate */
if (rtp_pair_->state == PAIR_FAILED || rtcp_pair_->state == PAIR_FAILED)
void ConnectionTester::run()
{
if (pair_ == nullptr)
{
qDebug() << "Unable to test connection, candidate is NULL!";
return;
}

// nomination is handled by the FlowController so if we're the controller,
// terminate connection testing
if (controller_)
pair_->state = PAIR_IN_PROGRESS;

if (!stun_->sendBindingRequest(pair_.get(), controller_))
{
emit testingDone(rtp_pair_, rtcp_pair_);
qDebug() << "Connectivity checks failed for"
<< pair_->local->address << pair_->local->port
<< pair_->remote->address << pair_->remote->port;
return;
}

// otherwise continue sending requests to remote to keep the hole in firewall open
if (!stun.sendNominationResponse(rtp_pair_))
pair_->state = PAIR_SUCCEEDED;

// controller performs the nomination process in FlowController so exit from ConnectionTester when this connection has been tested...
if (controller_)
{
qDebug() << "failed to receive nomination for RTP candidate:\n"
<< "\tlocal:" << rtp_pair_->local->address << ":" << rtcp_pair_->local->port << "\n"
<< "\tremote:" << rtp_pair_->remote->address << ":" << rtcp_pair_->remote->port;
qDebug() << "pair success" << pair_->local->address << pair_->local->port << pair_->remote->address << pair_->remote->port << pair_->local->component;
emit testingDone(pair_);
return;
}

if (!stun.sendNominationResponse(rtcp_pair_))
//... otherwise start waitin for nomination requests
if (!stun_->sendNominationResponse(pair_.get()))
{
qDebug() << "failed to receive nomination for RTCP!";
qDebug() << "failed to receive nomination for candidate:\n"
<< "\tlocal:" << pair_->local->address << ":" << pair_->local->port << "\n"
<< "\tremote:" << pair_->remote->address << ":" << pair_->remote->port;
pair_->state = PAIR_FAILED;
return;
}

rtp_pair_->state = PAIR_NOMINATED;
rtcp_pair_->state = PAIR_NOMINATED;

emit testingDone(rtp_pair_, rtcp_pair_);
emit testingDone(pair_);
}
28 changes: 20 additions & 8 deletions src/connectiontester.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#pragma once

#include <QThread>
#include <memory>

#include "icetypes.h"
#include "udpserver.h"
#include "stun.h"

class ConnectionTester : public QThread
{
Expand All @@ -10,7 +14,8 @@ class ConnectionTester : public QThread
public:
ConnectionTester();
~ConnectionTester();
void setCandidatePair(ICEPair *pair_rtp, ICEPair *pair_rtcp);
void setStun(Stun *stun);
void setCandidatePair(std::shared_ptr<ICEPair> pair);

// controller_ defines the course of action after candiate pair has been validated.
// If the ConnectionTester belongs to FlowController it terminates immediately after
Expand All @@ -20,20 +25,27 @@ class ConnectionTester : public QThread
// requests after it has concluded the candidate verification
void isController(bool controller);

public slots:
// Because the Stun object used by ConnectionTester has it's own event loop, we must
// override the default quit function, call Stun::stopTesting() and then exit from ConnectionTester
void quit();

signals:
// testingDone() is emitted when the connection testing has ended
//
// if the tested candidate succeeded (remote responded to our requests),
// rtp and rtcp point to valid ICEPairs
//
// if something failed, rtp and rtcp are nullptr
void testingDone(ICEPair *rtp, ICEPair *rtcp);
// connection points to valid ICEPair, otherwise it's nullptr
void testingDone(std::shared_ptr<ICEPair> connection);

// send signal to Stun object that it should terminate testing the candidate
// (break from the event loop associated with testing)
void stopTesting();

protected:
void printMessage(QString message);
void run();

ICEPair *rtp_pair_;
ICEPair *rtcp_pair_;

std::shared_ptr<ICEPair> pair_;
bool controller_;
Stun *stun_;
};
83 changes: 46 additions & 37 deletions src/globalsdpstate.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#include "globalsdpstate.h"
#include <QDateTime>

const uint16_t MIN_SIP_PORT = 21500;
const uint16_t MAX_SIP_PORT = 22000;

const uint16_t MAX_PORTS = 42;

GlobalSDPState::GlobalSDPState():
localUsername_("")
{
ice_ = std::make_unique<ICE>();
parameters_.setPortRange(MIN_SIP_PORT, MAX_SIP_PORT, MAX_PORTS);
}

void GlobalSDPState::setLocalInfo(QString username)
Expand All @@ -15,11 +21,10 @@ void GlobalSDPState::setLocalInfo(QString username)
std::shared_ptr<SDPMessageInfo> GlobalSDPState::localSDPSuggestion(QHostAddress localAddress)
{
qDebug() << "Getting local SDP suggestion";
return generateSDP(localAddress, nullptr);
return generateSDP(localAddress);
}

std::shared_ptr<SDPMessageInfo>
GlobalSDPState::generateSDP(QHostAddress localAddress, QList<ICEInfo *> *remoteCandidates)
std::shared_ptr<SDPMessageInfo> GlobalSDPState::generateSDP(QHostAddress localAddress)
{
// TODO: This should ask media manager, what options it supports.
qDebug() << "Generating new SDP message with our address as:" << localAddress;
Expand Down Expand Up @@ -143,7 +148,7 @@ GlobalSDPState::localFinalSDP(SDPMessageInfo &remoteSDP, QHostAddress localAddre
// if we have not made a suggestion, then base our final SDP on their suggestion.
if(localSuggestion == nullptr)
{
sdp = generateSDP(localAddress, &remoteSDP.candidates);
sdp = generateSDP(localAddress);
sdp->sessionName = remoteSDP.sessionName;

qDebug() << "\n\n\nHELLO HERE AGAIN!!\n\n\n";
Expand All @@ -167,25 +172,19 @@ GlobalSDPState::localFinalSDP(SDPMessageInfo &remoteSDP, QHostAddress localAddre
return nullptr;
}

// getNominated() returns two (TODO: four!) valid candidate pairs if ICE succeeded
// (ie. ICE was not disabled and remote responded to our requests)
auto nominated = ice_->getNominated(sessionID);
ICEMediaInfo nominated = ice_->getNominated(sessionID);

if (nominated.first && nominated.second)
// first is RTP, second is RTCP
if (nominated.audio.first != nullptr && nominated.audio.second != nullptr)
{
// RTP
sdp->media[0].receivePort = nominated.first->local->port;
sdp->media[0].connection_address = nominated.first->local->address;

remoteSDP.media[0].receivePort = nominated.first->remote->port;
remoteSDP.media[0].connection_address = nominated.first->remote->address;

// RTCP
sdp->media[1].receivePort = nominated.second->local->port;
sdp->media[1].connection_address = nominated.second->local->address;
setMediaPair(sdp->media[0], nominated.audio.first->local);
setMediaPair(remoteSDP.media[0], nominated.audio.first->remote);
}

remoteSDP.media[1].receivePort = nominated.second->remote->port;
remoteSDP.media[1].connection_address = nominated.second->remote->address;
if (nominated.video.first != nullptr && nominated.video.second != nullptr)
{
setMediaPair(sdp->media[1], nominated.video.first->local);
setMediaPair(remoteSDP.media[1], nominated.video.first->remote);
}
}

Expand Down Expand Up @@ -259,31 +258,41 @@ void GlobalSDPState::endSession(std::shared_ptr<SDPMessageInfo> sessionSDP)
}
}

void GlobalSDPState::startICECandidateNegotiation(QList<ICEInfo *>& local, QList<ICEInfo *>& remote, uint32_t sessionID)
void GlobalSDPState::startICECandidateNegotiation(QList<std::shared_ptr<ICEInfo>>& local, QList<std::shared_ptr<ICEInfo>>& remote, uint32_t sessionID)
{
ice_->startNomination(local, remote, sessionID);
}

void GlobalSDPState::updateFinalSDPs(SDPMessageInfo& localSDP, SDPMessageInfo& remoteSDP, uint32_t sessionID)
void GlobalSDPState::setMediaPair(MediaInfo& media, std::shared_ptr<ICEInfo> mediaInfo)
{
auto nominated = ice_->getNominated(sessionID);

if (nominated.first && nominated.second)
if (mediaInfo == nullptr)
{
// local RTP
localSDP.media[0].connection_address = nominated.first->local->address;
localSDP.media[0].receivePort = nominated.first->local->port;
return;
}

// local RTCP
localSDP.media[1].connection_address = nominated.second->local->address;
localSDP.media[1].receivePort = nominated.second->local->port;
media.connection_address = mediaInfo->address;
media.receivePort = mediaInfo->port;
}

// remote RTP
remoteSDP.media[0].connection_address = nominated.first->remote->address;
remoteSDP.media[0].receivePort = nominated.first->remote->port;
void GlobalSDPState::updateFinalSDPs(SDPMessageInfo& localSDP, SDPMessageInfo& remoteSDP, uint32_t sessionID)
{
ICEMediaInfo nominated = ice_->getNominated(sessionID);

// first is RTP, second is RTCP
if (nominated.audio.first != nullptr && nominated.audio.second != nullptr)
{
setMediaPair(localSDP.media[0], nominated.audio.first->local);
setMediaPair(remoteSDP.media[0], nominated.audio.first->remote);
}

// remote RTCP
remoteSDP.media[1].connection_address = nominated.second->remote->address;
remoteSDP.media[1].receivePort = nominated.second->remote->port;
if (nominated.video.first != nullptr && nominated.video.second != nullptr)
{
setMediaPair(localSDP.media[1], nominated.video.first->local);
setMediaPair(remoteSDP.media[1], nominated.video.first->remote);
}
}

void GlobalSDPState::ICECleanup(uint32_t sessionID)
{
ice_->cleanupSession(sessionID);
}
9 changes: 7 additions & 2 deletions src/globalsdpstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class GlobalSDPState
// frees the ports when they are not needed in rest of the program
void endSession(std::shared_ptr<SDPMessageInfo> sessionSDP);

void startICECandidateNegotiation(QList<ICEInfo *>& local, QList<ICEInfo *>& remote, uint32_t sessionID);
void startICECandidateNegotiation(QList<std::shared_ptr<ICEInfo>>& local, QList<std::shared_ptr<ICEInfo>>& remote, uint32_t sessionID);

void ICECleanup(uint32_t sessionID);

// update the MediaInfo of remote and locals SDPs to include the nominated connections
void updateFinalSDPs(SDPMessageInfo& localSDP, SDPMessageInfo& remoteSDP, uint32_t sessionID);
Expand All @@ -49,13 +51,16 @@ class GlobalSDPState
private:

// TODO: This should be moved to MediaManager.
std::shared_ptr<SDPMessageInfo> generateSDP(QHostAddress localAddress, QList<ICEInfo *> *remoteCandidates);
std::shared_ptr<SDPMessageInfo> generateSDP(QHostAddress localAddress);

bool generateAudioMedia(MediaInfo &audio);
bool generateVideoMedia(MediaInfo &video);

bool checkSDPOffer(SDPMessageInfo& offer);

// update MediaInfo of SDP after ICE has finished
void setMediaPair(MediaInfo& media, std::shared_ptr<ICEInfo> mediaInfo);

QString localUsername_;

std::unique_ptr<ICE> ice_;
Expand Down
2 changes: 1 addition & 1 deletion src/gui/customsettings.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "customsettings.h"

#include "ui_customsettings.h"
#include "ui_customSettings.h"

#include <video/camerainfo.h>
#include "settingshelper.h"
Expand Down
Loading

0 comments on commit 2f0041a

Please sign in to comment.