Skip to content

Commit 8d8e62e

Browse files
fusionfoxyThomas
andauthored
Sc3778 (#15)
* message transport uses explicit signaling messages instead of json * api ref documentation --------- Co-authored-by: Thomas <tfk@debian>
1 parent d1dc586 commit 8d8e62e

File tree

8 files changed

+337
-56
lines changed

8 files changed

+337
-56
lines changed

examples/libdatachannel/src/common/webrtc_connection/webrtc_connection.cpp

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ void WebrtcConnection::init() {
3333
auto self = shared_from_this();
3434

3535
messageTransport_->addMessageListener(
36-
[self](const nlohmann::json& msg) { self->handleMessage(msg); });
36+
[self](nabto::webrtc::util::WebrtcSignalingMessage& msg) {
37+
self->handleMessage(msg);
38+
});
3739

3840
messageTransport_->addSetupDoneListener(
3941
[self](const std::vector<nabto::webrtc::IceServer>& iceServers) {
@@ -60,16 +62,15 @@ void WebrtcConnection::init() {
6062
});
6163
}
6264

63-
void WebrtcConnection::handleMessage(const nlohmann::json& msg) {
65+
void WebrtcConnection::handleMessage(
66+
nabto::webrtc::util::WebrtcSignalingMessage& msg) {
6467
mutex_.lock();
6568
try {
66-
NPLOGI << "Webrtc got signaling message: " << msg.dump();
67-
auto type = msg.at("type").get<std::string>();
69+
NPLOGI << "Webrtc got signaling message";
6870

69-
if (type == "DESCRIPTION") {
70-
rtc::Description remDesc(
71-
msg.at("description").at("sdp").get<std::string>(),
72-
msg.at("description").at("type").get<std::string>());
71+
if (msg.isDescription()) {
72+
auto desc = msg.getDescription();
73+
rtc::Description remDesc(desc.sdp, desc.type);
7374

7475
bool offerCollision =
7576
remDesc.type() == rtc::Description::Type::Offer &&
@@ -93,13 +94,12 @@ void WebrtcConnection::handleMessage(const nlohmann::json& msg) {
9394
}
9495
return;
9596
}
96-
if (type == "CANDIDATE") {
97+
if (msg.isCandidate()) {
9798
std::shared_ptr<rtc::PeerConnection> pc = pc_;
9899
mutex_.unlock();
99100
try {
100-
rtc::Candidate cand(
101-
msg.at("candidate").at("candidate").get<std::string>(),
102-
msg.at("candidate").at("sdpMid").get<std::string>());
101+
auto sigCand = msg.getCandidate();
102+
rtc::Candidate cand(sigCand.candidate, sigCand.sdpMid);
103103
pc->addRemoteCandidate(cand);
104104
} catch (nlohmann::json::exception& ex) {
105105
NPLOGE << "handleIce json exception: " << ex.what();
@@ -114,10 +114,9 @@ void WebrtcConnection::handleMessage(const nlohmann::json& msg) {
114114
return;
115115
}
116116

117-
NPLOGE << "Got unknown message type: " << type;
117+
NPLOGE << "Got unknown message type";
118118
} catch (std::exception& ex) {
119-
NPLOGE << "Failed to handle message: " << msg.dump()
120-
<< " with: " << ex.what();
119+
NPLOGE << "Failed to handle message with: " << ex.what();
121120
}
122121
mutex_.unlock();
123122
}
@@ -231,15 +230,11 @@ void WebrtcConnection::handleSignalingStateChange(
231230
void WebrtcConnection::handleLocalCandidate(rtc::Candidate cand) {
232231
const std::lock_guard<std::mutex> lock(mutex_);
233232
if (canTrickle_) {
234-
nlohmann::json candidate = {{"sdpMid", cand.mid()},
235-
{"candidate", cand.candidate()}};
236-
237-
nlohmann::json msg = {
238-
{"type", "CANDIDATE"},
239-
{"candidate", candidate},
240-
};
233+
nabto::webrtc::util::SignalingCandidate candidate(cand.candidate());
234+
candidate.setSdpMid(cand.mid());
241235

242-
sendSignalingMessage(msg);
236+
sendSignalingMessage(
237+
nabto::webrtc::util::WebrtcSignalingMessage(candidate));
243238
}
244239
}
245240

@@ -305,15 +300,9 @@ void WebrtcConnection::sendDescription(
305300
NPLOGD << "SendDescription with: "
306301
<< (description.has_value() ? "true" : "false");
307302
if (description) {
308-
nlohmann::json message = {{"type", description->typeString()},
309-
{"sdp", std::string(description.value())}};
310-
311-
nlohmann::json msg = {
312-
{"type", "DESCRIPTION"},
313-
{"description", message},
314-
};
315-
316-
sendSignalingMessage(msg);
303+
nabto::webrtc::util::SignalingDescription desc(
304+
description->typeString(), std::string(description.value()));
305+
sendSignalingMessage(nabto::webrtc::util::WebrtcSignalingMessage(desc));
317306

318307
if (description->type() == rtc::Description::Type::Answer) {
319308
if (pc_->negotiationNeeded()) {
@@ -325,12 +314,12 @@ void WebrtcConnection::sendDescription(
325314
}
326315
}
327316

328-
void WebrtcConnection::sendSignalingMessage(const nlohmann::json& message) {
317+
void WebrtcConnection::sendSignalingMessage(
318+
const nabto::webrtc::util::WebrtcSignalingMessage& message) {
329319
try {
330320
messageTransport_->sendMessage(message);
331321
} catch (std::exception& e) {
332-
NPLOGE << "Failed to sign the message: " << message.dump()
333-
<< ", error: " << e.what();
322+
NPLOGE << "Failed to sign the message with error: " << e.what();
334323
}
335324
}
336325

examples/libdatachannel/src/common/webrtc_connection/webrtc_connection.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,30 +43,31 @@ class WebrtcConnection : public std::enable_shared_from_this<WebrtcConnection> {
4343

4444
std::vector<nlohmann::json> messageQueue_;
4545

46-
void handleMessage(const nlohmann::json& msg);
46+
void handleMessage(nabto::webrtc::util::WebrtcSignalingMessage& msg);
4747
void parseIceServers(
4848
const std::vector<struct nabto::webrtc::IceServer>& servers);
4949
void handleTransportError(const nabto::webrtc::SignalingError& error);
5050
void handleChannelStateChange(
5151
const nabto::webrtc::SignalingChannelState& state);
5252
void handleChannelError(const nabto::webrtc::SignalingError& error);
53-
54-
void init();
55-
void deinit();
56-
void createPeerConnection();
5753
void handleStateChange(const rtc::PeerConnection::State& state);
5854
void handleSignalingStateChange(rtc::PeerConnection::SignalingState state);
5955
void handleLocalCandidate(rtc::Candidate cand);
6056
void handleTrackEvent(std::shared_ptr<rtc::Track> track);
6157
void handleDatachannelEvent(std::shared_ptr<rtc::DataChannel> channel);
6258
void handleGatherinsStateChange(rtc::PeerConnection::GatheringState state);
6359

60+
void init();
61+
void deinit();
62+
void createPeerConnection();
63+
6464
void sendDescription(rtc::optional<rtc::Description> description);
6565
void sendCreateResponse(
6666
const std::vector<struct nabto::webrtc::IceServer>& iceServers);
6767
void requestIceServers();
6868

69-
void sendSignalingMessage(const nlohmann::json& message);
69+
void sendSignalingMessage(
70+
const nabto::webrtc::util::WebrtcSignalingMessage& message);
7071

7172
void addTrack();
7273

sdk/.clang-tidy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ HeaderFilterRegex: '.*'
2525

2626
CheckOptions:
2727
readability-function-cognitive-complexity.IgnoreMacros: true
28+
misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: true

sdk/src/signaling_util/message_transport/include/nabto/webrtc/util/message_transport.hpp

Lines changed: 175 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,171 @@ class MessageTransportFactory {
5858
nabto::webrtc::SignalingChannelPtr channel);
5959
};
6060

61+
/**
62+
* Class representing a WebRTC Description received or to be sent on the
63+
* MessageTransport.
64+
*/
65+
class SignalingDescription {
66+
public:
67+
/**
68+
* Construct a SignalingDescription object to send
69+
*
70+
* @param descType type of the description, typically "offer" or "answer"
71+
* @param descSdp SDP representation of the description.
72+
*/
73+
SignalingDescription(std::string descType, std::string descSdp);
74+
75+
/**
76+
* Convert the description to JSON format following the network protocol.
77+
*
78+
* @return The JSON document
79+
*/
80+
nlohmann::json toJson();
81+
82+
/**
83+
* The description type (typically "offer" or "answer")
84+
*/
85+
std::string type;
86+
87+
/**
88+
* SDP of the description.
89+
*/
90+
std::string sdp;
91+
};
92+
93+
/**
94+
* Class representing a WebRTC ICE Candidate received or to be sent on the
95+
* MessageTransport.
96+
*/
97+
class SignalingCandidate {
98+
public:
99+
/**
100+
* Construct a Candidate to be sent by the MessageTransport.
101+
*
102+
* @param cand The string representation of the candidate.
103+
*/
104+
explicit SignalingCandidate(std::string cand);
105+
106+
/**
107+
* Set the optional SDP MID value of a candidate.
108+
*
109+
* @param mid The MID to set.
110+
*/
111+
void setSdpMid(const std::string& mid);
112+
113+
/**
114+
* Set the optional SDP M Line Index of the candidate
115+
*
116+
* @param index The index to set.
117+
*/
118+
void setSdpMLineIndex(int index);
119+
120+
/**
121+
* Set the optional username fragment of the candidate
122+
*
123+
* @param ufrag The username fragment to set.
124+
*/
125+
void setUsernameFragment(const std::string& ufrag);
126+
127+
/**
128+
* Convert the description to JSON format following the network protocol.
129+
*
130+
* @return The JSON document
131+
*/
132+
nlohmann::json toJson();
133+
134+
/**
135+
* The string representation of the candidate
136+
*/
137+
std::string candidate;
138+
139+
/**
140+
* Optional SDP MID of the candidate. If this is empty, it means the value
141+
* does not exist.
142+
*/
143+
std::string sdpMid;
144+
145+
/**
146+
* Optional SDP M Line Index of the candidate. If this is `<0` it means the
147+
* value does not exist.
148+
*/
149+
int sdpMLineIndex{-1};
150+
151+
/**
152+
* Optional Username Fragment of the candidate. If this is empty, it means the
153+
* value does not exist.
154+
*/
155+
std::string usernameFragment;
156+
};
157+
158+
/**
159+
* Generalized WebRTC Signaling message to be sent/received by the
160+
* MessageTransport. This message can contain either a SignalingDescription or a
161+
* SignalingCandidate.
162+
*/
163+
class WebrtcSignalingMessage {
164+
public:
165+
/**
166+
* Construct a WebRTC Signaling message from the JSON format defined by the
167+
* protocol.
168+
*
169+
* If the JSON is invalid or not following the protocol, this will throw an
170+
* exception.
171+
*
172+
* @param jsonMessage The message to decode.
173+
* @return The created signaling message.
174+
*/
175+
static WebrtcSignalingMessage fromJson(nlohmann::json& jsonMessage);
176+
177+
/**
178+
* Construct a WebRTC Signaling message from a SignalingDescription.
179+
*
180+
* @param description The description to construct with.
181+
*/
182+
explicit WebrtcSignalingMessage(const SignalingDescription& description);
183+
184+
/**
185+
* Construct a WebRTC Signaling message from a SignalingCandidate.
186+
*
187+
* @param candidate The candidate to construct with.
188+
*/
189+
explicit WebrtcSignalingMessage(const SignalingCandidate& candidate);
190+
191+
/**
192+
* Check if the message is a SignalingDescription.
193+
*
194+
* @return True iff the message contains a description.
195+
*/
196+
bool isDescription() const;
197+
198+
/**
199+
* Check if the message is a SignalingCandidate.
200+
*
201+
* @return True iff the message contains a candidate.
202+
*/
203+
bool isCandidate() const;
204+
205+
/**
206+
* Get the SignalingDescription contained in this message if `isDescription()`
207+
* returns true. This must never be called if `isDescription()` returns false.
208+
*
209+
* @return The contained SignalingDescription object.
210+
*/
211+
SignalingDescription getDescription() const;
212+
213+
/**
214+
* Get the SignalingCandidate contained in this message if `isCandidate()`
215+
* returns true. This must never be called if `isCandidate()` returns false.
216+
*
217+
* @return The contained SignalingCandidate object.
218+
*/
219+
SignalingCandidate getCandidate() const;
220+
221+
private:
222+
std::unique_ptr<SignalingDescription> description_ = nullptr;
223+
std::unique_ptr<SignalingCandidate> candidate_ = nullptr;
224+
};
225+
61226
/**
62227
* Handler invoked when the MessageTransport has completed the setup phase of a
63228
* channel.
@@ -68,6 +233,14 @@ class MessageTransportFactory {
68233
using SetupDoneHandler = std::function<void(
69234
const std::vector<nabto::webrtc::IceServer>& iceServers)>;
70235

236+
/**
237+
* Handler invoked when a new message is available from the MessageTransport.
238+
*
239+
* @param message The new message.
240+
*/
241+
using MessageTransportMessageHandler =
242+
std::function<void(WebrtcSignalingMessage& message)>;
243+
71244
using SetupDoneListenerId = uint32_t;
72245
using TransportMessageListenerId = uint32_t;
73246
using TransportErrorListenerId = uint32_t;
@@ -108,7 +281,7 @@ class MessageTransport {
108281
* @return ID of the added handler to be used when removing it.
109282
*/
110283
virtual TransportMessageListenerId addMessageListener(
111-
nabto::webrtc::SignalingMessageHandler handler) = 0;
284+
MessageTransportMessageHandler handler) = 0;
112285

113286
/**
114287
* Remove message listener.
@@ -144,7 +317,7 @@ class MessageTransport {
144317
*
145318
* @param message The message to send.
146319
*/
147-
virtual void sendMessage(const nlohmann::json& message) = 0;
320+
virtual void sendMessage(const WebrtcSignalingMessage& message) = 0;
148321
};
149322

150323
} // namespace util

0 commit comments

Comments
 (0)