Skip to content

Commit

Permalink
feat: update current remote description with fingerprint
Browse files Browse the repository at this point in the history
Adds a `currentRemoteDescription` field to `PeerConnection` which
can be updated independently of `remoteDescription`, the idea being
the `remoteDescription` is the offer received from the remote peer
and the `currentRemoteDescription` is what has actually been
negotiated with them.

The `currentRemoteDescription` is initialised when the
`remoteDescription` is set.

Currently the `checkFingerprint` method updates the certificate
fingerprint used by the connection to the remote peer but I guess
other modifications may be useful.

Exposes the `currentRemoteDescription` via a getter similar to
`remoteDescription`.
  • Loading branch information
achingbrain committed Jun 7, 2024
1 parent 541d646 commit 96eb58b
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 9 deletions.
18 changes: 18 additions & 0 deletions DOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,24 @@ Return value: the length of the string copied in buffer (including the terminati

If `buffer` is `NULL`, the description is not copied but the size is still returned.

#### rtcGetCurrentRemoteDescription

```
int rtcGetCurrentRemoteDescription(int pc, char *buffer, int size)
```

Retrieves the currently negotiated remote description in SDP format.

Arguments:

- `pc`: the Peer Connection identifier
- `buffer`: a user-supplied buffer to store the description
- `size`: the size of `buffer`

Return value: the length of the string copied in buffer (including the terminating null character) or a negative error code

If `buffer` is `NULL`, the description is not copied but the size is still returned.

#### rtcGetLocalDescriptionType

```
Expand Down
1 change: 1 addition & 0 deletions include/rtc/peerconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class RTC_CPP_EXPORT PeerConnection final : CheshireCat<impl::PeerConnection> {
bool hasMedia() const;
optional<Description> localDescription() const;
optional<Description> remoteDescription() const;
optional<Description> currentRemoteDescription() const;
size_t remoteMaxMessageSize() const;
optional<string> localAddress() const;
optional<string> remoteAddress() const;
Expand Down
1 change: 1 addition & 0 deletions include/rtc/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ RTC_C_EXPORT int rtcAddRemoteCandidate(int pc, const char *cand, const char *mid

RTC_C_EXPORT int rtcGetLocalDescription(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetRemoteDescription(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetCurrentRemoteDescription(int pc, char *buffer, int size);

RTC_C_EXPORT int rtcGetLocalDescriptionType(int pc, char *buffer, int size);
RTC_C_EXPORT int rtcGetRemoteDescriptionType(int pc, char *buffer, int size);
Expand Down
11 changes: 11 additions & 0 deletions src/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,17 @@ int rtcGetRemoteDescription(int pc, char *buffer, int size) {
});
}

int rtcGetCurrentRemoteDescription(int pc, char *buffer, int size) {
return wrap([&] {
auto peerConnection = getPeerConnection(pc);

if (auto desc = peerConnection->currentRemoteDescription())
return copyAndReturn(string(*desc), buffer, size);
else
return RTC_ERR_NOT_AVAIL;
});
}

int rtcGetLocalDescriptionType(int pc, char *buffer, int size) {
return wrap([&] {
auto peerConnection = getPeerConnection(pc);
Expand Down
43 changes: 37 additions & 6 deletions src/impl/peerconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ optional<Description> PeerConnection::remoteDescription() const {
return mRemoteDescription;
}

optional<Description> PeerConnection::currentRemoteDescription() const {
std::lock_guard lock(mCurrentRemoteDescriptionMutex);
return mCurrentRemoteDescription;
}

size_t PeerConnection::remoteMaxMessageSize() const {
const size_t localMax = config.maxMessageSize.value_or(DEFAULT_LOCAL_MAX_MESSAGE_SIZE);

Expand Down Expand Up @@ -239,7 +244,7 @@ shared_ptr<DtlsTransport> PeerConnection::initDtlsTransport() {
throw std::logic_error("No underlying ICE transport for DTLS transport");

auto certificate = mCertificate.get();
auto verifierCallback = weak_bind(&PeerConnection::checkFingerprint, this, _1);
auto verifierCallback = weak_bind(&PeerConnection::checkFingerprint, this, _1, fingerprintAlgorithm);
auto dtlsStateChangeCallback =
[this, weak_this = weak_from_this()](DtlsTransport::State transportState) {
auto shared_this = weak_this.lock();
Expand Down Expand Up @@ -439,17 +444,21 @@ void PeerConnection::rollbackLocalDescription() {
}
}

bool PeerConnection::checkFingerprint(const std::string &fingerprint) const {
bool PeerConnection::checkFingerprint(const std::string &fingerprint, const CertificateFingerprint::Algorithm algorithm) {
std::lock_guard lock(mRemoteDescriptionMutex);
if (!mRemoteDescription || !mRemoteDescription->fingerprint())
return false;

if (config.disableFingerprintVerification)
return true;

auto expectedFingerprint = mRemoteDescription->fingerprint()->value;
if (expectedFingerprint == fingerprint) {
if (config.disableFingerprintVerification || expectedFingerprint == fingerprint) {
PLOG_VERBOSE << "Valid fingerprint \"" << fingerprint << "\"";

if (mCurrentRemoteDescription) {
std::lock_guard lock(mCurrentRemoteDescriptionMutex);
// update current remote description with incoming fingerprint
mCurrentRemoteDescription->setFingerprint(CertificateFingerprint{algorithm, fingerprint});
}

return true;
}

Expand Down Expand Up @@ -1078,6 +1087,20 @@ void PeerConnection::processLocalCandidate(Candidate candidate) {
&localCandidateCallback, std::move(candidate));
}

void PeerConnection::processCurrentRemoteDescription(Description description) {
{
// Set as current remote description
std::lock_guard lock(mCurrentRemoteDescriptionMutex);

std::vector<Candidate> existingCandidates;
if (mCurrentRemoteDescription)
existingCandidates = mCurrentRemoteDescription->extractCandidates();

mCurrentRemoteDescription.emplace(description);
mCurrentRemoteDescription->addCandidates(std::move(existingCandidates));
}
}

void PeerConnection::processRemoteDescription(Description description) {
// Update the SSRC cache for existing tracks
updateTrackSsrcCache(description);
Expand Down Expand Up @@ -1124,6 +1147,14 @@ void PeerConnection::processRemoteCandidate(Candidate candidate) {
candidate.resolve(Candidate::ResolveMode::Simple);
mRemoteDescription->addCandidate(candidate);
}
{
// Set as remote candidate on current remote description too
std::lock_guard lock(mCurrentRemoteDescriptionMutex);
if (mCurrentRemoteDescription->hasCandidate(candidate))
return; // already in description, ignore

mCurrentRemoteDescription->addCandidate(candidate);
}

if (candidate.isResolved()) {
iceTransport->addRemoteCandidate(std::move(candidate));
Expand Down
8 changes: 5 additions & 3 deletions src/impl/peerconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {

optional<Description> localDescription() const;
optional<Description> remoteDescription() const;
optional<Description> currentRemoteDescription() const;
size_t remoteMaxMessageSize() const;

shared_ptr<IceTransport> initIceTransport();
Expand All @@ -53,7 +54,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {

void endLocalCandidates();
void rollbackLocalDescription();
bool checkFingerprint(const std::string &fingerprint) const;
bool checkFingerprint(const std::string &fingerprint, const CertificateFingerprint::Algorithm algorithm);
void forwardMessage(message_ptr message);
void forwardMedia(message_ptr message);
void forwardBufferedAmount(uint16_t stream, size_t amount);
Expand All @@ -77,6 +78,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
void processLocalDescription(Description description);
void processLocalCandidate(Candidate candidate);
void processRemoteDescription(Description description);
void processCurrentRemoteDescription(Description description);
void processRemoteCandidate(Candidate candidate);
string localBundleMid() const;

Expand Down Expand Up @@ -135,8 +137,8 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {

Processor mProcessor;
optional<Description> mLocalDescription, mRemoteDescription;
optional<Description> mCurrentLocalDescription;
mutable std::mutex mLocalDescriptionMutex, mRemoteDescriptionMutex;
optional<Description> mCurrentLocalDescription, mCurrentRemoteDescription;
mutable std::mutex mLocalDescriptionMutex, mRemoteDescriptionMutex, mCurrentRemoteDescriptionMutex;

shared_ptr<MediaHandler> mMediaHandler;

Expand Down
5 changes: 5 additions & 0 deletions src/peerconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ optional<Description> PeerConnection::remoteDescription() const {
return impl()->remoteDescription();
}

optional<Description> PeerConnection::currentRemoteDescription() const {
return impl()->currentRemoteDescription();
}

size_t PeerConnection::remoteMaxMessageSize() const { return impl()->remoteMaxMessageSize(); }

bool PeerConnection::hasMedia() const {
Expand Down Expand Up @@ -243,6 +247,7 @@ void PeerConnection::setRemoteDescription(Description description) {
iceTransport->setRemoteDescription(description); // ICE transport might reject the description

impl()->processRemoteDescription(std::move(description));
impl()->processCurrentRemoteDescription(std::move(description));
impl()->changeSignalingState(newSignalingState);
signalingLock.unlock();

Expand Down

0 comments on commit 96eb58b

Please sign in to comment.