Browse Source

Changed interface to pass objects rather than strings

Paul-Louis Ageneau 6 years ago
parent
commit
47b918d4a1
10 changed files with 114 additions and 81 deletions
  1. 8 4
      src/candidate.cpp
  2. 5 3
      src/candidate.hpp
  3. 6 1
      src/description.cpp
  4. 5 2
      src/description.hpp
  5. 10 6
      src/icetransport.cpp
  6. 10 10
      src/icetransport.hpp
  7. 2 0
      src/include.hpp
  8. 48 38
      src/peerconnection.cpp
  9. 16 13
      src/peerconnection.hpp
  10. 4 4
      test/main.cpp

+ 8 - 4
src/candidate.cpp

@@ -38,20 +38,20 @@ inline bool hasprefix(const string &str, const string &prefix) {
 
 
 namespace rtc {
 namespace rtc {
 
 
-Candidate::Candidate(string candidate, string mid) {
+Candidate::Candidate(string candidate, std::optional<string> mid) {
 	const string prefix{"candidate:"};
 	const string prefix{"candidate:"};
 	mCandidate =
 	mCandidate =
 	    hasprefix(candidate, prefix) ? candidate.substr(prefix.size()) : std::move(candidate);
 	    hasprefix(candidate, prefix) ? candidate.substr(prefix.size()) : std::move(candidate);
 	mMid = std::move(mid);
 	mMid = std::move(mid);
 
 
-	// See RFC 5245
+	// See RFC 5245 for format
 	std::stringstream ss(mCandidate);
 	std::stringstream ss(mCandidate);
 	int component{0}, priority{0};
 	int component{0}, priority{0};
 	string foundation, transport, node, service, typ_, type;
 	string foundation, transport, node, service, typ_, type;
 	if (ss >> foundation >> component >> transport >> priority &&
 	if (ss >> foundation >> component >> transport >> priority &&
 	    ss >> node >> service >> typ_ >> type && typ_ == "typ") {
 	    ss >> node >> service >> typ_ >> type && typ_ == "typ") {
 
 
-		// Try to resolv the node
+		// Try to resolve the node
 		struct addrinfo hints = {};
 		struct addrinfo hints = {};
 		hints.ai_family = AF_UNSPEC;
 		hints.ai_family = AF_UNSPEC;
 		hints.ai_flags = AI_ADDRCONFIG;
 		hints.ai_flags = AI_ADDRCONFIG;
@@ -88,9 +88,13 @@ Candidate::Candidate(string candidate, string mid) {
 
 
 string Candidate::candidate() const { return mCandidate; }
 string Candidate::candidate() const { return mCandidate; }
 
 
-string Candidate::mid() const { return mMid; }
+std::optional<string> Candidate::mid() const { return mMid; }
 
 
 Candidate::operator string() const { return mCandidate; }
 Candidate::operator string() const { return mCandidate; }
 
 
 } // namespace rtc
 } // namespace rtc
 
 
+std::ostream &operator<<(std::ostream &out, const rtc::Candidate &candidate) {
+	return out << std::string(candidate);
+}
+

+ 5 - 3
src/candidate.hpp

@@ -27,19 +27,21 @@ namespace rtc {
 
 
 class Candidate {
 class Candidate {
 public:
 public:
-	Candidate(string candidate, string mid);
+	Candidate(string candidate, std::optional<string> mid = nullopt);
 
 
 	string candidate() const;
 	string candidate() const;
-	string mid() const;
+	std::optional<string> mid() const;
 
 
 	operator string() const;
 	operator string() const;
 
 
 private:
 private:
 	string mCandidate;
 	string mCandidate;
-	string mMid;
+	std::optional<string> mMid;
 };
 };
 
 
 } // namespace rtc
 } // namespace rtc
 
 
+std::ostream &operator<<(std::ostream &out, const rtc::Candidate &candidate);
+
 #endif
 #endif
 
 

+ 6 - 1
src/description.cpp

@@ -44,7 +44,7 @@ inline void trim_end(string &str) {
 
 
 namespace rtc {
 namespace rtc {
 
 
-Description::Description(Role role, const string &sdp)
+Description::Description(const string &sdp, Role role)
     : mRole(role), mMid("0"), mIceUfrag("0"), mIcePwd("0") {
     : mRole(role), mMid("0"), mIceUfrag("0"), mIcePwd("0") {
 	auto seed = std::chrono::system_clock::now().time_since_epoch().count();
 	auto seed = std::chrono::system_clock::now().time_since_epoch().count();
 	std::default_random_engine generator(seed);
 	std::default_random_engine generator(seed);
@@ -138,3 +138,8 @@ Description::operator string() const {
 }
 }
 
 
 } // namespace rtc
 } // namespace rtc
+
+std::ostream &operator<<(std::ostream &out, const rtc::Description &description) {
+	return out << std::string(description);
+}
+

+ 5 - 2
src/description.hpp

@@ -22,6 +22,7 @@
 #include "candidate.hpp"
 #include "candidate.hpp"
 #include "include.hpp"
 #include "include.hpp"
 
 
+#include <iostream>
 #include <map>
 #include <map>
 #include <optional>
 #include <optional>
 #include <vector>
 #include <vector>
@@ -32,7 +33,7 @@ class Description {
 public:
 public:
 	enum class Role { Passive, Active, ActPass };
 	enum class Role { Passive, Active, ActPass };
 
 
-	Description(Role role, const string &sdp);
+	Description(const string &sdp, Role role = Role::ActPass);
 
 
 	Role role() const;
 	Role role() const;
 	std::optional<string> fingerprint() const;
 	std::optional<string> fingerprint() const;
@@ -45,7 +46,7 @@ public:
 	operator string() const;
 	operator string() const;
 
 
 private:
 private:
-	Role mRole = Role::Passive;
+	Role mRole;
 	string mSessionId;
 	string mSessionId;
 	string mMid;
 	string mMid;
 	string mIceUfrag, mIcePwd;
 	string mIceUfrag, mIcePwd;
@@ -57,4 +58,6 @@ private:
 
 
 } // namespace rtc
 } // namespace rtc
 
 
+std::ostream &operator<<(std::ostream &out, const rtc::Description &description);
+
 #endif
 #endif

+ 10 - 6
src/icetransport.cpp

@@ -33,10 +33,11 @@ namespace rtc {
 using std::shared_ptr;
 using std::shared_ptr;
 using std::weak_ptr;
 using std::weak_ptr;
 
 
-IceTransport::IceTransport(const IceConfiguration &config, Description::Role role,
-                           candidate_callback candidateCallback, ready_callback ready)
-    : mRole(role), mNiceAgent(nullptr, nullptr), mMainLoop(nullptr, nullptr),
-      mCandidateCallback(std::move(candidateCallback)), mReadyCallback(ready) {
+IceTransport::IceTransport(const IceConfiguration &config, candidate_callback candidateCallback,
+                           ready_callback ready)
+    : mRole(Description::Role::ActPass), mState(State::Disconnected), mNiceAgent(nullptr, nullptr),
+      mMainLoop(nullptr, nullptr), mCandidateCallback(std::move(candidateCallback)),
+      mReadyCallback(ready) {
 
 
 	auto logLevelFlags = GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION);
 	auto logLevelFlags = GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION);
 	g_log_set_handler(nullptr, logLevelFlags, LogCallback, this);
 	g_log_set_handler(nullptr, logLevelFlags, LogCallback, this);
@@ -132,10 +133,13 @@ IceTransport::State IceTransport::state() const { return mState; }
 Description IceTransport::getLocalDescription() const {
 Description IceTransport::getLocalDescription() const {
 	std::unique_ptr<gchar[], void (*)(void *)> sdp(nice_agent_generate_local_sdp(mNiceAgent.get()),
 	std::unique_ptr<gchar[], void (*)(void *)> sdp(nice_agent_generate_local_sdp(mNiceAgent.get()),
 	                                               g_free);
 	                                               g_free);
-	return Description(mRole, string(sdp.get()));
+	return Description(string(sdp.get()), mRole);
 }
 }
 
 
 void IceTransport::setRemoteDescription(const Description &description) {
 void IceTransport::setRemoteDescription(const Description &description) {
+	mRole = description.role() == Description::Role::Active ? Description::Role::Passive
+	                                                        : Description::Role::Active;
+
 	if (nice_agent_parse_remote_sdp(mNiceAgent.get(), string(description).c_str()))
 	if (nice_agent_parse_remote_sdp(mNiceAgent.get(), string(description).c_str()))
 		throw std::runtime_error("Unable to parse remote SDP");
 		throw std::runtime_error("Unable to parse remote SDP");
 }
 }
@@ -185,7 +189,7 @@ void IceTransport::processGatheringDone() { mCandidateCallback(nullopt); }
 
 
 void IceTransport::changeState(uint32_t state) {
 void IceTransport::changeState(uint32_t state) {
 	mState = static_cast<State>(state);
 	mState = static_cast<State>(state);
-	if (mState == State::READY) {
+	if (mState == State::Ready) {
 		mReadyCallback();
 		mReadyCallback();
 	}
 	}
 }
 }

+ 10 - 10
src/icetransport.hpp

@@ -39,19 +39,19 @@ namespace rtc {
 class IceTransport : public Transport {
 class IceTransport : public Transport {
 public:
 public:
 	enum class State : uint32_t {
 	enum class State : uint32_t {
-		DISCONNECTED = NICE_COMPONENT_STATE_DISCONNECTED,
-		GATHERING = NICE_COMPONENT_STATE_GATHERING,
-		CONNECTING = NICE_COMPONENT_STATE_CONNECTING,
-		CONNECTED = NICE_COMPONENT_STATE_CONNECTED,
-		READY = NICE_COMPONENT_STATE_READY,
-		FAILED = NICE_COMPONENT_STATE_FAILED
+		Disconnected = NICE_COMPONENT_STATE_DISCONNECTED,
+		Gathering = NICE_COMPONENT_STATE_GATHERING,
+		Connecting = NICE_COMPONENT_STATE_CONNECTING,
+		Connected = NICE_COMPONENT_STATE_CONNECTED,
+		Ready = NICE_COMPONENT_STATE_READY,
+		Failed = NICE_COMPONENT_STATE_FAILED
 	};
 	};
 
 
 	using candidate_callback = std::function<void(const std::optional<Candidate> &candidate)>;
 	using candidate_callback = std::function<void(const std::optional<Candidate> &candidate)>;
 	using ready_callback = std::function<void(void)>;
 	using ready_callback = std::function<void(void)>;
 
 
-	IceTransport(const IceConfiguration &config, Description::Role role,
-	             candidate_callback candidateCallback, ready_callback ready);
+	IceTransport(const IceConfiguration &config, candidate_callback candidateCallback,
+	             ready_callback ready);
 	~IceTransport();
 	~IceTransport();
 
 
 	Description::Role role() const;
 	Description::Role role() const;
@@ -74,8 +74,8 @@ private:
 	void processCandidate(const string &candidate);
 	void processCandidate(const string &candidate);
 	void processGatheringDone();
 	void processGatheringDone();
 
 
-	const Description::Role mRole;
-	State mState = State::DISCONNECTED;
+	Description::Role mRole;
+	State mState;
 
 
 	uint32_t mStreamId = 0;
 	uint32_t mStreamId = 0;
 	std::unique_ptr<NiceAgent, void (*)(gpointer)> mNiceAgent;
 	std::unique_ptr<NiceAgent, void (*)(gpointer)> mNiceAgent;

+ 2 - 0
src/include.hpp

@@ -39,6 +39,8 @@ using std::uint8_t;
 
 
 const size_t MAX_NUMERICNODE_LEN = 48; // Max IPv6 string representation length
 const size_t MAX_NUMERICNODE_LEN = 48; // Max IPv6 string representation length
 const size_t MAX_NUMERICSERV_LEN = 6;  // Max port string representation length
 const size_t MAX_NUMERICSERV_LEN = 6;  // Max port string representation length
+
+const uint16_t DEFAULT_SCTP_PORT = 5000; // SCTP port to use by default
 }
 }
 
 
 #endif
 #endif

+ 48 - 38
src/peerconnection.cpp

@@ -29,8 +29,7 @@ using std::function;
 using std::shared_ptr;
 using std::shared_ptr;
 
 
 PeerConnection::PeerConnection(const IceConfiguration &config)
 PeerConnection::PeerConnection(const IceConfiguration &config)
-    : mConfig(config), mCertificate(make_certificate("libdatachannel")), mMid("0"),
-      mSctpPort(5000) {}
+    : mConfig(config), mCertificate(make_certificate("libdatachannel")) {}
 
 
 PeerConnection::~PeerConnection() {}
 PeerConnection::~PeerConnection() {}
 
 
@@ -38,31 +37,29 @@ const IceConfiguration *PeerConnection::config() const { return &mConfig; }
 
 
 const Certificate *PeerConnection::certificate() const { return &mCertificate; }
 const Certificate *PeerConnection::certificate() const { return &mCertificate; }
 
 
-void PeerConnection::setRemoteDescription(const string &description) {
-	Description desc(Description::Role::ActPass, description);
+std::optional<Description> PeerConnection::localDescription() const { return mLocalDescription; }
 
 
-	if (auto fingerprint = desc.fingerprint())
-		mRemoteFingerprint.emplace(*fingerprint);
-
-	if (auto sctpPort = desc.sctpPort()) {
-		mSctpPort = *sctpPort;
-	}
+std::optional<Description> PeerConnection::remoteDescription() const { return mRemoteDescription; }
 
 
+void PeerConnection::setRemoteDescription(Description description) {
 	if (!mIceTransport) {
 	if (!mIceTransport) {
-		initIceTransport(Description::Role::ActPass);
-		mIceTransport->setRemoteDescription(desc);
-		triggerLocalDescription();
+		initIceTransport();
+		mIceTransport->setRemoteDescription(description);
+		processLocalDescription(mIceTransport->getLocalDescription());
 		mIceTransport->gatherLocalCandidates();
 		mIceTransport->gatherLocalCandidates();
 	} else {
 	} else {
-		mIceTransport->setRemoteDescription(desc);
+		mIceTransport->setRemoteDescription(description);
 	}
 	}
+
+	mRemoteDescription.emplace(std::move(description));
 }
 }
 
 
-void PeerConnection::setRemoteCandidate(const string &candidate) {
-	Candidate cand(candidate, mMid);
-	if (mIceTransport) {
-		mIceTransport->addRemoteCandidate(cand);
-	}
+void PeerConnection::setRemoteCandidate(Candidate candidate) {
+	if (!mRemoteDescription || !mIceTransport)
+		throw std::logic_error("Remote candidate set without remote description");
+
+	mIceTransport->addRemoteCandidate(candidate);
+	mRemoteDescription->addCandidate(std::move(candidate));
 }
 }
 
 
 shared_ptr<DataChannel> PeerConnection::createDataChannel(const string &label,
 shared_ptr<DataChannel> PeerConnection::createDataChannel(const string &label,
@@ -83,8 +80,8 @@ shared_ptr<DataChannel> PeerConnection::createDataChannel(const string &label,
 	mDataChannels.insert(std::make_pair(stream, channel));
 	mDataChannels.insert(std::make_pair(stream, channel));
 
 
 	if (!mIceTransport) {
 	if (!mIceTransport) {
-		initIceTransport(Description::Role::Active);
-		triggerLocalDescription();
+		initIceTransport();
+		processLocalDescription(mIceTransport->getLocalDescription());
 		mIceTransport->gatherLocalCandidates();
 		mIceTransport->gatherLocalCandidates();
 	} else if (mSctpTransport && mSctpTransport->isReady()) {
 	} else if (mSctpTransport && mSctpTransport->isReady()) {
 		channel->open(mSctpTransport);
 		channel->open(mSctpTransport);
@@ -97,18 +94,19 @@ void PeerConnection::onDataChannel(
 	mDataChannelCallback = callback;
 	mDataChannelCallback = callback;
 }
 }
 
 
-void PeerConnection::onLocalDescription(std::function<void(const string &description)> callback) {
+void PeerConnection::onLocalDescription(
+    std::function<void(const Description &description)> callback) {
 	mLocalDescriptionCallback = callback;
 	mLocalDescriptionCallback = callback;
 }
 }
 
 
 void PeerConnection::onLocalCandidate(
 void PeerConnection::onLocalCandidate(
-    std::function<void(const std::optional<string> &candidate)> callback) {
+    std::function<void(const std::optional<Candidate> &candidate)> callback) {
 	mLocalCandidateCallback = callback;
 	mLocalCandidateCallback = callback;
 }
 }
 
 
-void PeerConnection::initIceTransport(Description::Role role) {
+void PeerConnection::initIceTransport() {
 	mIceTransport = std::make_shared<IceTransport>(
 	mIceTransport = std::make_shared<IceTransport>(
-	    mConfig, role, std::bind(&PeerConnection::triggerLocalCandidate, this, _1),
+	    mConfig, std::bind(&PeerConnection::processLocalCandidate, this, _1),
 	    std::bind(&PeerConnection::initDtlsTransport, this));
 	    std::bind(&PeerConnection::initDtlsTransport, this));
 }
 }
 
 
@@ -119,13 +117,18 @@ void PeerConnection::initDtlsTransport() {
 }
 }
 
 
 void PeerConnection::initSctpTransport() {
 void PeerConnection::initSctpTransport() {
+	uint16_t sctpPort = mRemoteDescription->sctpPort().value_or(DEFAULT_SCTP_PORT);
 	mSctpTransport = std::make_shared<SctpTransport>(
 	mSctpTransport = std::make_shared<SctpTransport>(
-	    mDtlsTransport, mSctpPort, std::bind(&PeerConnection::openDataChannels, this),
+	    mDtlsTransport, sctpPort, std::bind(&PeerConnection::openDataChannels, this),
 	    std::bind(&PeerConnection::forwardMessage, this, _1));
 	    std::bind(&PeerConnection::forwardMessage, this, _1));
 }
 }
 
 
 bool PeerConnection::checkFingerprint(const std::string &fingerprint) const {
 bool PeerConnection::checkFingerprint(const std::string &fingerprint) const {
-	return mRemoteFingerprint && *mRemoteFingerprint == fingerprint;
+	if (auto expectedFingerprint =
+	        mRemoteDescription ? mRemoteDescription->fingerprint() : nullopt) {
+		return *expectedFingerprint == fingerprint;
+	}
+	return false;
 }
 }
 
 
 void PeerConnection::forwardMessage(message_ptr message) {
 void PeerConnection::forwardMessage(message_ptr message) {
@@ -158,19 +161,26 @@ void PeerConnection::openDataChannels(void) {
 		dataChannel->open(mSctpTransport);
 		dataChannel->open(mSctpTransport);
 }
 }
 
 
-void PeerConnection::triggerLocalDescription() {
-	if (mLocalDescriptionCallback && mIceTransport) {
-		Description desc{mIceTransport->getLocalDescription()};
-		desc.setFingerprint(mCertificate.fingerprint());
-		desc.setSctpPort(mSctpPort);
-		mLocalDescriptionCallback(string(desc));
-	}
+void PeerConnection::processLocalDescription(Description description) {
+	auto remoteSctpPort = mRemoteDescription ? mRemoteDescription->sctpPort() : nullopt;
+
+	description.setFingerprint(mCertificate.fingerprint());
+	description.setSctpPort(remoteSctpPort.value_or(DEFAULT_SCTP_PORT));
+	mLocalDescription.emplace(std::move(description));
+
+	if (mLocalDescriptionCallback)
+		mLocalDescriptionCallback(*mLocalDescription);
 }
 }
 
 
-void PeerConnection::triggerLocalCandidate(const std::optional<Candidate> &candidate) {
-	if (mLocalCandidateCallback) {
-		mLocalCandidateCallback(candidate ? std::make_optional(string(*candidate)) : nullopt);
-	}
+void PeerConnection::processLocalCandidate(std::optional<Candidate> candidate) {
+	if (!mLocalDescription)
+		throw std::logic_error("Got a local candidate without local description");
+
+	if (candidate)
+		mLocalDescription->addCandidate(*candidate);
+
+	if (mLocalCandidateCallback)
+		mLocalCandidateCallback(candidate);
 }
 }
 
 
 void PeerConnection::triggerDataChannel(std::shared_ptr<DataChannel> dataChannel) {
 void PeerConnection::triggerDataChannel(std::shared_ptr<DataChannel> dataChannel) {

+ 16 - 13
src/peerconnection.hpp

@@ -48,18 +48,21 @@ public:
 	const IceConfiguration *config() const;
 	const IceConfiguration *config() const;
 	const Certificate *certificate() const;
 	const Certificate *certificate() const;
 
 
-	void setRemoteDescription(const string &description);
-	void setRemoteCandidate(const string &candidate);
+	std::optional<Description> localDescription() const;
+	std::optional<Description> remoteDescription() const;
+
+	void setRemoteDescription(Description description);
+	void setRemoteCandidate(Candidate candidate);
 
 
 	std::shared_ptr<DataChannel> createDataChannel(const string &label, const string &protocol = "",
 	std::shared_ptr<DataChannel> createDataChannel(const string &label, const string &protocol = "",
 	                                               const Reliability &reliability = {});
 	                                               const Reliability &reliability = {});
 
 
 	void onDataChannel(std::function<void(std::shared_ptr<DataChannel> dataChannel)> callback);
 	void onDataChannel(std::function<void(std::shared_ptr<DataChannel> dataChannel)> callback);
-	void onLocalDescription(std::function<void(const string &description)> callback);
-	void onLocalCandidate(std::function<void(const std::optional<string> &candidate)> callback);
+	void onLocalDescription(std::function<void(const Description &description)> callback);
+	void onLocalCandidate(std::function<void(const std::optional<Candidate> &candidate)> callback);
 
 
 private:
 private:
-	void initIceTransport(Description::Role role);
+	void initIceTransport();
 	void initDtlsTransport();
 	void initDtlsTransport();
 	void initSctpTransport();
 	void initSctpTransport();
 
 
@@ -67,15 +70,15 @@ private:
 	void forwardMessage(message_ptr message);
 	void forwardMessage(message_ptr message);
 	void openDataChannels(void);
 	void openDataChannels(void);
 
 
-	void triggerLocalDescription();
-	void triggerLocalCandidate(const std::optional<Candidate> &candidate);
+	void processLocalDescription(Description description);
+	void processLocalCandidate(std::optional<Candidate> candidate);
 	void triggerDataChannel(std::shared_ptr<DataChannel> dataChannel);
 	void triggerDataChannel(std::shared_ptr<DataChannel> dataChannel);
 
 
 	const IceConfiguration mConfig;
 	const IceConfiguration mConfig;
-	Certificate mCertificate;
-	string mMid;
-	std::optional<string> mRemoteFingerprint;
-	uint16_t mSctpPort;
+	const Certificate mCertificate;
+
+	std::optional<Description> mLocalDescription;
+	std::optional<Description> mRemoteDescription;
 
 
 	std::shared_ptr<IceTransport> mIceTransport;
 	std::shared_ptr<IceTransport> mIceTransport;
 	std::shared_ptr<DtlsTransport> mDtlsTransport;
 	std::shared_ptr<DtlsTransport> mDtlsTransport;
@@ -84,8 +87,8 @@ private:
 	std::unordered_map<unsigned int, std::shared_ptr<DataChannel>> mDataChannels;
 	std::unordered_map<unsigned int, std::shared_ptr<DataChannel>> mDataChannels;
 
 
 	std::function<void(std::shared_ptr<DataChannel> dataChannel)> mDataChannelCallback;
 	std::function<void(std::shared_ptr<DataChannel> dataChannel)> mDataChannelCallback;
-	std::function<void(const string &description)> mLocalDescriptionCallback;
-	std::function<void(const std::optional<string> &candidate)> mLocalCandidateCallback;
+	std::function<void(const Description &description)> mLocalDescriptionCallback;
+	std::function<void(const std::optional<Candidate> &candidate)> mLocalCandidateCallback;
 };
 };
 
 
 } // namespace rtc
 } // namespace rtc

+ 4 - 4
test/main.cpp

@@ -32,24 +32,24 @@ int main(int argc, char **argv) {
 	auto pc1 = std::make_shared<PeerConnection>(config);
 	auto pc1 = std::make_shared<PeerConnection>(config);
 	auto pc2 = std::make_shared<PeerConnection>(config);
 	auto pc2 = std::make_shared<PeerConnection>(config);
 
 
-	pc1->onLocalDescription([pc2](const string &sdp) {
+	pc1->onLocalDescription([pc2](const Description &sdp) {
 		cout << "Description 1: " << sdp << endl;
 		cout << "Description 1: " << sdp << endl;
 		pc2->setRemoteDescription(sdp);
 		pc2->setRemoteDescription(sdp);
 	});
 	});
 
 
-	pc1->onLocalCandidate([pc2](const optional<string> &candidate) {
+	pc1->onLocalCandidate([pc2](const optional<Candidate> &candidate) {
 		if (candidate) {
 		if (candidate) {
 			cout << "Candidate 1: " << *candidate << endl;
 			cout << "Candidate 1: " << *candidate << endl;
 			pc2->setRemoteCandidate(*candidate);
 			pc2->setRemoteCandidate(*candidate);
 		}
 		}
 	});
 	});
 
 
-	pc2->onLocalDescription([pc1](const string &sdp) {
+	pc2->onLocalDescription([pc1](const Description &sdp) {
 		cout << "Description 2: " << sdp << endl;
 		cout << "Description 2: " << sdp << endl;
 		pc1->setRemoteDescription(sdp);
 		pc1->setRemoteDescription(sdp);
 	});
 	});
 
 
-	pc2->onLocalCandidate([pc1](const optional<string> &candidate) {
+	pc2->onLocalCandidate([pc1](const optional<Candidate> &candidate) {
 		if (candidate) {
 		if (candidate) {
 			cout << "Candidate 2: " << *candidate << endl;
 			cout << "Candidate 2: " << *candidate << endl;
 			pc1->setRemoteCandidate(*candidate);
 			pc1->setRemoteCandidate(*candidate);