Skip to content

Commit 00ffc07

Browse files
Introduce createOffer() and createAnswer() methods
1 parent 815ea6e commit 00ffc07

6 files changed

+122
-92
lines changed

include/rtc/description.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ class RTC_CPP_EXPORT Description {
6666
bool ended() const;
6767

6868
void hintType(Type type);
69-
void setFingerprint(CertificateFingerprint f);
7069
void addIceOption(string option);
7170
void removeIceOption(const string &option);
71+
void setIceAttribute(string ufrag, string pwd);
72+
void setFingerprint(CertificateFingerprint f);
7273

7374
std::vector<string> attributes() const;
7475
void addAttribute(string attr);

include/rtc/peerconnection.hpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,13 @@ class RTC_CPP_EXPORT PeerConnection final : CheshireCat<impl::PeerConnection> {
9797
bool getSelectedCandidatePair(Candidate *local, Candidate *remote);
9898

9999
void setLocalDescription(Description::Type type = Description::Type::Unspec, LocalDescriptionInit init = {});
100+
void gatherLocalCandidates(std::vector<IceServer> additionalIceServers = {});
100101
void setRemoteDescription(Description description);
101102
void addRemoteCandidate(Candidate candidate);
102-
void gatherLocalCandidates(std::vector<IceServer> additionalIceServers = {});
103+
104+
// For specific use cases only
105+
Description createOffer();
106+
Description createAnswer();
103107

104108
void setMediaHandler(shared_ptr<MediaHandler> handler);
105109
shared_ptr<MediaHandler> getMediaHandler();

src/description.cpp

+15-10
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,21 @@ void Description::hintType(Type type) {
216216
mType = type;
217217
}
218218

219+
void Description::addIceOption(string option) {
220+
if (std::find(mIceOptions.begin(), mIceOptions.end(), option) == mIceOptions.end())
221+
mIceOptions.emplace_back(std::move(option));
222+
}
223+
224+
void Description::removeIceOption(const string &option) {
225+
mIceOptions.erase(std::remove(mIceOptions.begin(), mIceOptions.end(), option),
226+
mIceOptions.end());
227+
}
228+
229+
void Description::setIceAttribute(string ufrag, string pwd) {
230+
mIceUfrag = std::move(ufrag);
231+
mIcePwd = std::move(pwd);
232+
}
233+
219234
void Description::setFingerprint(CertificateFingerprint f) {
220235
if (!f.isValid())
221236
throw std::invalid_argument("Invalid " +
@@ -227,16 +242,6 @@ void Description::setFingerprint(CertificateFingerprint f) {
227242
mFingerprint = std::move(f);
228243
}
229244

230-
void Description::addIceOption(string option) {
231-
if (std::find(mIceOptions.begin(), mIceOptions.end(), option) == mIceOptions.end())
232-
mIceOptions.emplace_back(std::move(option));
233-
}
234-
235-
void Description::removeIceOption(const string &option) {
236-
mIceOptions.erase(std::remove(mIceOptions.begin(), mIceOptions.end(), option),
237-
mIceOptions.end());
238-
}
239-
240245
std::vector<string> Description::Entry::attributes() const { return mAttributes; }
241246

242247
void Description::Entry::addAttribute(string attr) {

src/impl/peerconnection.cpp

+67-74
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ void PeerConnection::validateRemoteDescription(const Description &description) {
925925
PLOG_VERBOSE << "Remote description looks valid";
926926
}
927927

928-
void PeerConnection::processLocalDescription(Description description) {
928+
void PeerConnection::populateLocalDescription(Description &description) const {
929929
const uint16_t localSctpPort = DEFAULT_SCTP_PORT;
930930
const size_t localMaxMessageSize =
931931
config.maxMessageSize.value_or(DEFAULT_LOCAL_MAX_MESSAGE_SIZE);
@@ -935,7 +935,7 @@ void PeerConnection::processLocalDescription(Description description) {
935935

936936
if (auto remote = remoteDescription()) {
937937
// Reciprocate remote description
938-
for (int i = 0; i < remote->mediaCount(); ++i)
938+
for (int i = 0; i < remote->mediaCount(); ++i) {
939939
std::visit( // reciprocate each media
940940
rtc::overloaded{
941941
[&](Description::Application *remoteApp) {
@@ -950,78 +950,46 @@ void PeerConnection::processLocalDescription(Description description) {
950950
<< app.mid() << "\"";
951951

952952
description.addMedia(std::move(app));
953-
return;
954-
}
955953

956-
auto reciprocated = remoteApp->reciprocate();
957-
reciprocated.hintSctpPort(localSctpPort);
958-
reciprocated.setMaxMessageSize(localMaxMessageSize);
954+
} else {
955+
auto reciprocated = remoteApp->reciprocate();
956+
reciprocated.hintSctpPort(localSctpPort);
957+
reciprocated.setMaxMessageSize(localMaxMessageSize);
959958

960-
PLOG_DEBUG << "Reciprocating application in local description, mid=\""
961-
<< reciprocated.mid() << "\"";
959+
PLOG_DEBUG << "Reciprocating application in local description, mid=\""
960+
<< reciprocated.mid() << "\"";
962961

963-
description.addMedia(std::move(reciprocated));
962+
description.addMedia(std::move(reciprocated));
963+
}
964964
},
965965
[&](Description::Media *remoteMedia) {
966-
std::unique_lock lock(mTracksMutex); // we may emplace a track
967-
if (auto it = mTracks.find(remoteMedia->mid()); it != mTracks.end()) {
968-
// Prefer local description
969-
if (auto track = it->second.lock()) {
970-
auto media = track->description();
971-
972-
PLOG_DEBUG << "Adding media to local description, mid=\""
973-
<< media.mid() << "\", removed=" << std::boolalpha
974-
<< media.isRemoved();
975-
976-
description.addMedia(std::move(media));
977-
978-
} else {
979-
auto reciprocated = remoteMedia->reciprocate();
980-
reciprocated.markRemoved();
966+
std::shared_lock lock(mTracksMutex);
967+
auto it = mTracks.find(remoteMedia->mid());
968+
auto track = it != mTracks.end() ? it->second.lock() : nullptr;
969+
if(track) {
970+
// Prefer local description
971+
auto media = track->description();
981972

982-
PLOG_DEBUG << "Adding media to local description, mid=\""
983-
<< reciprocated.mid()
984-
<< "\", removed=true (track is destroyed)";
985-
986-
description.addMedia(std::move(reciprocated));
987-
}
988-
return;
989-
}
990-
991-
auto reciprocated = remoteMedia->reciprocate();
992-
#if !RTC_ENABLE_MEDIA
993-
if (!reciprocated.isRemoved()) {
994-
// No media support, mark as removed
995-
PLOG_WARNING << "Rejecting track (not compiled with media support)";
996-
reciprocated.markRemoved();
997-
}
998-
#endif
973+
PLOG_DEBUG << "Adding media to local description, mid=\""
974+
<< media.mid() << "\", removed=" << std::boolalpha
975+
<< media.isRemoved();
999976

1000-
PLOG_DEBUG << "Reciprocating media in local description, mid=\""
1001-
<< reciprocated.mid() << "\", removed=" << std::boolalpha
1002-
<< reciprocated.isRemoved();
977+
description.addMedia(std::move(media));
1003978

1004-
// Create incoming track
1005-
auto track =
1006-
std::make_shared<Track>(weak_from_this(), std::move(reciprocated));
1007-
mTracks.emplace(std::make_pair(track->mid(), track));
1008-
mTrackLines.emplace_back(track);
1009-
triggerTrack(track); // The user may modify the track description
979+
} else {
980+
auto reciprocated = remoteMedia->reciprocate();
981+
reciprocated.markRemoved();
1010982

1011-
auto handler = getMediaHandler();
1012-
if (handler)
1013-
handler->media(track->description());
983+
PLOG_DEBUG << "Adding media to local description, mid=\""
984+
<< reciprocated.mid()
985+
<< "\", removed=true (track is destroyed)";
1014986

1015-
if (track->description().isRemoved())
1016-
track->close();
1017-
1018-
description.addMedia(track->description());
987+
description.addMedia(std::move(reciprocated));
988+
}
1019989
},
1020990
},
1021991
remote->media(i));
1022-
1023-
// We need to update the SSRC cache for newly-created incoming tracks
1024-
updateTrackSsrcCache(*remote);
992+
}
1025993
}
1026994

1027995
if (description.type() == Description::Type::Offer) {
@@ -1061,22 +1029,18 @@ void PeerConnection::processLocalDescription(Description description) {
10611029
description.addMedia(std::move(app));
10621030
}
10631031
}
1064-
1065-
// There might be no media at this point, for instance if the user deleted tracks
1066-
if (description.mediaCount() == 0)
1067-
throw std::runtime_error("No DataChannel or Track to negotiate");
10681032
}
10691033

10701034
// Set local fingerprint (wait for certificate if necessary)
10711035
description.setFingerprint(mCertificate.get()->fingerprint());
1036+
}
10721037

1038+
void PeerConnection::processLocalDescription(Description description) {
10731039
PLOG_VERBOSE << "Issuing local description: " << description;
10741040

10751041
if (description.mediaCount() == 0)
10761042
throw std::logic_error("Local description has no media line");
10771043

1078-
updateTrackSsrcCache(description);
1079-
10801044
{
10811045
// Set as local description
10821046
std::lock_guard lock(mLocalDescriptionMutex);
@@ -1093,11 +1057,6 @@ void PeerConnection::processLocalDescription(Description description) {
10931057

10941058
mProcessor.enqueue(&PeerConnection::trigger<Description>, shared_from_this(),
10951059
&localDescriptionCallback, std::move(description));
1096-
1097-
// Reciprocated tracks might need to be open
1098-
if (auto dtlsTransport = std::atomic_load(&mDtlsTransport);
1099-
dtlsTransport && dtlsTransport->state() == Transport::State::Connected)
1100-
mProcessor.enqueue(&PeerConnection::openTracks, shared_from_this());
11011060
}
11021061

11031062
void PeerConnection::processLocalCandidate(Candidate candidate) {
@@ -1121,6 +1080,40 @@ void PeerConnection::processLocalCandidate(Candidate candidate) {
11211080
}
11221081

11231082
void PeerConnection::processRemoteDescription(Description description) {
1083+
// Create tracks from remote description
1084+
for (int i = 0; i < description.mediaCount(); ++i) {
1085+
if (std::holds_alternative<Description::Media *>(description.media(i))) {
1086+
auto remoteMedia = std::get<Description::Media *>(description.media(i));
1087+
std::unique_lock lock(mTracksMutex); // we may emplace a track
1088+
if (auto it = mTracks.find(remoteMedia->mid()); it != mTracks.end())
1089+
continue;
1090+
1091+
PLOG_DEBUG << "New remote track, mid=\"" << remoteMedia->mid() << "\"";
1092+
1093+
auto reciprocated = remoteMedia->reciprocate();
1094+
#if !RTC_ENABLE_MEDIA
1095+
if (!reciprocated.isRemoved()) {
1096+
// No media support, mark as removed
1097+
PLOG_WARNING << "Rejecting track (not compiled with media support)";
1098+
reciprocated.markRemoved();
1099+
}
1100+
#endif
1101+
1102+
// Create incoming track
1103+
auto track = std::make_shared<Track>(weak_from_this(), std::move(reciprocated));
1104+
mTracks.emplace(std::make_pair(track->mid(), track));
1105+
mTrackLines.emplace_back(track);
1106+
triggerTrack(track); // The user may modify the track description
1107+
1108+
auto handler = getMediaHandler();
1109+
if (handler)
1110+
handler->media(track->description());
1111+
1112+
if (track->description().isRemoved())
1113+
track->close();
1114+
}
1115+
}
1116+
11241117
// Update the SSRC cache for existing tracks
11251118
updateTrackSsrcCache(description);
11261119

@@ -1146,9 +1139,9 @@ void PeerConnection::processRemoteDescription(Description description) {
11461139
mProcessor.enqueue(&PeerConnection::remoteCloseDataChannels, shared_from_this());
11471140
}
11481141

1142+
// Reciprocated tracks might need to be open
11491143
if (dtlsTransport && dtlsTransport->state() == Transport::State::Connected)
11501144
mProcessor.enqueue(&PeerConnection::openTracks, shared_from_this());
1151-
11521145
}
11531146

11541147
void PeerConnection::processRemoteCandidate(Candidate candidate) {
@@ -1238,7 +1231,7 @@ void PeerConnection::setMediaHandler(shared_ptr<MediaHandler> handler) {
12381231
mMediaHandler = handler;
12391232
}
12401233

1241-
shared_ptr<MediaHandler> PeerConnection::getMediaHandler() {
1234+
shared_ptr<MediaHandler> PeerConnection::getMediaHandler() const {
12421235
std::shared_lock lock(mMediaHandlerMutex);
12431236
return mMediaHandler;
12441237
}

src/impl/peerconnection.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
7575
void closeTracks();
7676

7777
void validateRemoteDescription(const Description &description);
78+
void populateLocalDescription(Description &description) const;
7879
void processLocalDescription(Description description);
7980
void processLocalCandidate(Candidate candidate);
8081
void processRemoteDescription(Description description);
@@ -84,7 +85,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
8485
bool negotiationNeeded() const;
8586

8687
void setMediaHandler(shared_ptr<MediaHandler> handler);
87-
shared_ptr<MediaHandler> getMediaHandler();
88+
shared_ptr<MediaHandler> getMediaHandler() const;
8889

8990
void triggerDataChannel(weak_ptr<DataChannel> weakDataChannel);
9091
void triggerTrack(weak_ptr<Track> weakTrack);

src/peerconnection.cpp

+31-5
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ void PeerConnection::setLocalDescription(Description::Type type, LocalDescriptio
8585
PLOG_VERBOSE << "Setting local description, type=" << Description::typeToString(type);
8686

8787
SignalingState signalingState = impl()->signalingState.load();
88+
8889
if (type == Description::Type::Rollback) {
8990
if (signalingState == SignalingState::HaveLocalOffer ||
9091
signalingState == SignalingState::HaveLocalPranswer) {
@@ -139,11 +140,17 @@ void PeerConnection::setLocalDescription(Description::Type type, LocalDescriptio
139140
return; // closed
140141

141142
if (init.iceUfrag && init.icePwd) {
142-
PLOG_DEBUG << "Using custom ICE attributes, ufrag=\"" << init.iceUfrag.value() << "\", pwd=\"" << init.icePwd.value() << "\"";
143-
iceTransport->setIceAttributes(init.iceUfrag.value(), init.icePwd.value());
143+
PLOG_DEBUG << "Setting custom ICE attributes, ufrag=\"" << *init.iceUfrag << "\", pwd=\"" << *init.icePwd << "\"";
144+
iceTransport->setIceAttributes(*init.iceUfrag, *init.icePwd);
144145
}
145146

146147
Description local = iceTransport->getLocalDescription(type);
148+
impl()->populateLocalDescription(local);
149+
150+
// There might be no media at this point, for instance if the user deleted tracks
151+
if (local.mediaCount() == 0)
152+
throw std::runtime_error("No DataChannel or Track to negotiate");
153+
147154
impl()->processLocalDescription(std::move(local));
148155

149156
impl()->changeSignalingState(newSignalingState);
@@ -162,9 +169,8 @@ void PeerConnection::setLocalDescription(Description::Type type, LocalDescriptio
162169

163170
void PeerConnection::gatherLocalCandidates(std::vector<IceServer> additionalIceServers) {
164171
auto iceTransport = impl()->getIceTransport();
165-
if (!iceTransport) {
166-
throw std::logic_error("No IceTransport. Local Description has not been set");
167-
}
172+
if (!iceTransport || !localDescription())
173+
throw std::logic_error("Local description has not been set before gathering");
168174

169175
if (impl()->gatheringState == GatheringState::New) {
170176
iceTransport->gatherLocalCandidates(impl()->localBundleMid(), additionalIceServers);
@@ -282,6 +288,26 @@ void PeerConnection::addRemoteCandidate(Candidate candidate) {
282288
impl()->processRemoteCandidate(std::move(candidate));
283289
}
284290

291+
Description PeerConnection::createOffer() {
292+
auto iceTransport = impl()->initIceTransport();
293+
if (!iceTransport)
294+
throw std::runtime_error("Peer connection is closed");
295+
296+
Description desc = iceTransport->getLocalDescription(rtc::Description::Type::Offer);
297+
impl()->populateLocalDescription(desc);
298+
return desc;
299+
}
300+
301+
Description PeerConnection::createAnswer() {
302+
auto iceTransport = impl()->initIceTransport();
303+
if (!iceTransport)
304+
throw std::runtime_error("Peer connection is closed");
305+
306+
Description desc = iceTransport->getLocalDescription(rtc::Description::Type::Answer);
307+
impl()->populateLocalDescription(desc);
308+
return desc;
309+
}
310+
285311
void PeerConnection::setMediaHandler(shared_ptr<MediaHandler> handler) {
286312
impl()->setMediaHandler(std::move(handler));
287313
};

0 commit comments

Comments
 (0)