Skip to content

Commit aabcdea

Browse files
authored
Merge pull request #1469 from vircadia/webapp
Enable WebRTC connections to be made to the Domain, i.e., add Web client support.
2 parents 57167cd + 8764e6f commit aabcdea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2908
-224
lines changed

CODING_STANDARD.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ In an international environment English is the preferred language.
948948
949949
#### [4.3.2] Use // for all comments, including multi-line comments.
950950
951-
An exception to this rule applies for jsdoc or Doxygen comments.
951+
An exception to this rule applies to JSDoc and Doxygen comments.
952952
953953
```cpp
954954
// Comment spanning
@@ -1008,3 +1008,11 @@ These types of comments are explicitly not allowed. If you need to break up sect
10081008
//--------------------------------------------------------------------------------
10091009
```
10101010

1011+
#### [4.3.6] Doxygen comments should use "///"
1012+
1013+
Use the `///` style of [Doxygen](https://www.doxygen.nl/index.html) comments when documenting public interfaces.
1014+
1015+
Some editors can automatically create a Doxygen documentation stub if you type `///` in the line above the item to be
1016+
documented.
1017+
1018+
**Visual Studio:** To configure Visual Studio's Doxygen commenting behavior, search for "Doxygen" in Tools > Options.

assignment-client/src/AssignmentClient.cpp

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <assert.h>
1616

17+
#include <QJsonDocument>
1718
#include <QProcess>
1819
#include <QSharedMemory>
1920
#include <QThread>
@@ -84,7 +85,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
8485
_assignmentServerHostname = assignmentServerHostname;
8586
}
8687

87-
_assignmentServerSocket = SockAddr(_assignmentServerHostname, assignmentServerPort, true);
88+
_assignmentServerSocket = SockAddr(SocketType::UDP, _assignmentServerHostname, assignmentServerPort, true);
8889
if (_assignmentServerSocket.isNull()) {
8990
qCCritical(assignment_client) << "PAGE: Couldn't resolve domain server address" << _assignmentServerHostname;
9091
}
@@ -119,7 +120,8 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
119120

120121
// did we get an assignment-client monitor port?
121122
if (assignmentMonitorPort > 0) {
122-
_assignmentClientMonitorSocket = SockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort);
123+
_assignmentClientMonitorSocket = SockAddr(SocketType::UDP, DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME,
124+
assignmentMonitorPort);
123125
_assignmentClientMonitorSocket.setObjectName("AssignmentClientMonitor");
124126

125127
qCDebug(assignment_client) << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket;
@@ -132,6 +134,18 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
132134
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleCreateAssignmentPacket));
133135
packetReceiver.registerListener(PacketType::StopNode,
134136
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleStopNodePacket));
137+
138+
#if defined(WEBRTC_DATA_CHANNELS)
139+
auto webrtcSocket = nodeList->getWebRTCSocket();
140+
141+
// Route inbound WebRTC signaling messages from the Domain Server.
142+
packetReceiver.registerListener(PacketType::WebRTCSignaling,
143+
PacketReceiver::makeUnsourcedListenerReference<AssignmentClient>(this, &AssignmentClient::handleWebRTCSignalingPacket));
144+
connect(this, &AssignmentClient::webrtcSignalingMessageFromUserClient, webrtcSocket, &WebRTCSocket::onSignalingMessage);
145+
146+
// Route outbound WebRTC signaling messages via the Domain Server to the user client.
147+
connect(webrtcSocket, &WebRTCSocket::sendSignalingMessage, this, &AssignmentClient::sendSignalingMessageToUserClient);
148+
#endif
135149
}
136150

137151
void AssignmentClient::stopAssignmentClient() {
@@ -340,3 +354,45 @@ void AssignmentClient::assignmentCompleted() {
340354

341355
_isAssigned = false;
342356
}
357+
358+
#if defined(WEBRTC_DATA_CHANNELS)
359+
360+
void AssignmentClient::handleWebRTCSignalingPacket(QSharedPointer<ReceivedMessage> message) {
361+
auto messageString = message->readString();
362+
auto json = QJsonDocument::fromJson(messageString.toUtf8()).object();
363+
if (json.keys().contains("echo")) {
364+
// Echo message back to sender.
365+
366+
if (!json.keys().contains("to") || !json.keys().contains("from")) {
367+
qCDebug(assignment_client) << "Invalid WebRTC signaling echo message received.";
368+
return;
369+
}
370+
371+
// Swap to/from.
372+
auto to = json.value("to");
373+
json.insert("to", json.value("from"));
374+
json.insert("from", to);
375+
376+
// Send back to sender via the Domain Server.
377+
auto packetList = NLPacketList::create(PacketType::WebRTCSignaling, QByteArray(), true, true);
378+
packetList->writeString(QJsonDocument(json).toJson(QJsonDocument::Compact));
379+
auto nodeList = DependencyManager::get<NodeList>();
380+
auto domainServerAddress = nodeList->getDomainHandler().getSockAddr();
381+
nodeList->sendPacketList(std::move(packetList), domainServerAddress);
382+
383+
} else {
384+
// WebRTC signaling message.
385+
emit webrtcSignalingMessageFromUserClient(json);
386+
}
387+
}
388+
389+
// Sends a signaling message from the assignment client to the user client via the Domain Server.
390+
void AssignmentClient::sendSignalingMessageToUserClient(const QJsonObject& json) {
391+
auto packetList = NLPacketList::create(PacketType::WebRTCSignaling, QByteArray(), true, true);
392+
packetList->writeString(QJsonDocument(json).toJson(QJsonDocument::Compact));
393+
auto nodeList = DependencyManager::get<NodeList>();
394+
auto domainServerAddress = nodeList->getDomainHandler().getSockAddr();
395+
nodeList->sendPacketList(std::move(packetList), domainServerAddress);
396+
}
397+
398+
#endif

assignment-client/src/AssignmentClient.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <QtCore/QPointer>
1818
#include <QtCore/QSharedPointer>
1919

20+
#include <shared/WebRTC.h>
21+
2022
#include "ThreadedAssignment.h"
2123

2224
class QSharedMemory;
@@ -30,19 +32,26 @@ class AssignmentClient : public QObject {
3032
bool disableDomainPortAutoDiscovery);
3133
~AssignmentClient();
3234

35+
public slots:
36+
void aboutToQuit();
37+
3338
private slots:
3439
void sendAssignmentRequest();
3540
void assignmentCompleted();
3641
void handleAuthenticationRequest();
3742
void sendStatusPacketToACM();
3843
void stopAssignmentClient();
39-
40-
public slots:
41-
void aboutToQuit();
42-
43-
private slots:
4444
void handleCreateAssignmentPacket(QSharedPointer<ReceivedMessage> message);
4545
void handleStopNodePacket(QSharedPointer<ReceivedMessage> message);
46+
#if defined(WEBRTC_DATA_CHANNELS)
47+
void handleWebRTCSignalingPacket(QSharedPointer<ReceivedMessage> message);
48+
void sendSignalingMessageToUserClient(const QJsonObject& json);
49+
#endif
50+
51+
signals:
52+
#if defined(WEBRTC_DATA_CHANNELS)
53+
void webrtcSignalingMessageFromUserClient(const QJsonObject& json);
54+
#endif
4655

4756
private:
4857
void setUpStatusToMonitor();

cmake/ports/webrtc/CONTROL

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
Source: webrtc
2-
Version: 20190626
2+
Version: 20210105
33
Description: WebRTC

cmake/ports/webrtc/README.md

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# WebRTC
2+
3+
WebRTC Information:
4+
- https://webrtc.org/
5+
- https://webrtc.googlesource.com/src
6+
- https://webrtc.googlesource.com/src/+/refs/heads/master/docs/native-code/index.md
7+
- https://webrtc.googlesource.com/src/+/refs/heads/master/docs/native-code/development/prerequisite-sw/index.md
8+
- https://webrtc.googlesource.com/src/+/refs/heads/master/docs/native-code/development/index.md
9+
- https://www.chromium.org/developers/calendar
10+
- https://github.com/microsoft/winrtc
11+
- https://docs.microsoft.com/en-us/winrtc/getting-started
12+
- https://groups.google.com/g/discuss-webrtc \
13+
See "PSA" posts for release information.
14+
- https://bugs.chromium.org/p/webrtc/issues/list
15+
- https://stackoverflow.com/questions/27809193/webrtc-not-building-for-windows
16+
- https://github.com/aisouard/libwebrtc/issues/57
17+
18+
## Windows - M84
19+
20+
WebRTC's M84 release is currently used because it corresponded to Microsoft's latest WinRTC release at the time of development,
21+
and WinRTC is a source of potentially useful patches.
22+
23+
The following notes document how the M84-based Windows VCPKG was created, using Visual Studio 2019.
24+
25+
### Set Up depot_tools
26+
27+
Install Google's depot_tools.
28+
- Download depot_tools.zip.
29+
- Extract somewhere.
30+
- Add the extracted directory to the start of the system `PATH` environment variable.
31+
32+
Configure depot_tools.
33+
- Set an environment variable `DEPOT_TOOLS_WIN_TOOLCHAIN=0`
34+
- Set an environment variable `GYP_MSVS_VERSION=2019`
35+
36+
Initialize depot_tools.
37+
- VS2019 developer command prompt in the directory where the source tree will be created.
38+
- `gclient`
39+
40+
### Get the Code
41+
42+
Fetch the code into a *\src* subdirectory. This may take some time!
43+
- `fetch --nohooks webrtc`
44+
45+
Switch to the M84 branch.
46+
- `cd src`
47+
- `git checkout branch-heads/4147`
48+
49+
Fetch all the subrepositories.
50+
- `gclient sync -D -r branch-heads/4147`
51+
52+
### Patch the Code
53+
54+
#### Modify compiler switches
55+
- Edit *build\config\win\BUILD.gn*:
56+
- Change all `/MT` to `/MD`, and `/MTd` to `/MDd`.
57+
- Change all `cflags = [ "/MDd" ]` to `[ "/MDd", "-D_ITERATOR_DEBUG_LEVEL=2", "-D_HAS_ITERATOR_DEBUGGING=1" ]`.
58+
- Edit *build\config\compiler\BUILD.gn*:\
59+
Change:
60+
```
61+
if (is_win) {
62+
if (is_clang) {
63+
cflags = [ "/Z7" ] # Debug information in the .obj files.
64+
} else {
65+
cflags = [ "/Zi" ] # Produce PDB file, no edit and continue.
66+
}
67+
```
68+
to:
69+
```
70+
if (is_win) {
71+
if (is_clang) {
72+
cflags = [ "/Z7", "/std:c++17", "/Zc:__cplusplus" ] # Debug information in the .obj files.
73+
} else {
74+
cflags = [ "/Zi", "/std:c++17", "/Zc:__cplusplus" ] # Produce PDB file, no edit and continue.
75+
}
76+
```
77+
78+
#### H265 Codec Fixes
79+
https://bugs.webrtc.org/9213#c13
80+
- Edit the following files:
81+
- *modules\video_coding\codecs\h264\h264_color_space.h*
82+
- *modules\video_coding\codecs\h264\h264_decoder_impl.h*
83+
- *modules\video_coding\codecs\h264\h264_encoder_impl.h*
84+
In each, comment out the following lines:
85+
```
86+
#if defined(WEBRTC_WIN) && !defined(__clang__)
87+
#error "See: bugs.webrtc.org/9213#c13."
88+
#endif
89+
```
90+
- Edit *third_party\ffmpeg\libavcodec\fft_template.c*:\
91+
Comment out all of `ff_fft_init` except the fail clause at the end.
92+
- Edit *third_party\ffmpeg\libavcodec\pcm.c*:\
93+
Comment out last line, containing `PCM Archimedes VIDC`.
94+
- Edit *third_party\ffmpeg\libavutil\x86\imgutils_init.c*:\
95+
Add the following method to the end of the file:
96+
```
97+
void avpriv_emms_asm(void) {} // Fix missing symbol in FFMPEG.
98+
```
99+
100+
#### Exclude BoringSSL
101+
A separate OpenSSL VCPKG is used for building Vircadia.
102+
The following patches are needed even though SSL is excluded in the `gn gen` build commands.
103+
- Rename *third_party\boringssl* to *third_party\boringssl-NO*.
104+
- Edit *third_party\libsrtp\BUILD.gn:\
105+
Change:
106+
```
107+
public_deps = [
108+
"//third_party/boringssl:boringssl",
109+
]
110+
```
111+
To:
112+
```
113+
public_deps = [
114+
# "//third_party/boringssl:boringssl",
115+
]
116+
```
117+
118+
- Edit *third_party\usrsctp\BUILD.gn*:\
119+
Change:
120+
```
121+
deps = [ "//third_party/boringssl" ]
122+
```
123+
To:
124+
```
125+
deps = [
126+
# "//third_party/boringssl"
127+
]
128+
```
129+
- Edit *base\BUILD.gn*:\
130+
In the code under:
131+
```
132+
# Use the base implementation of hash functions when building for
133+
# NaCl. Otherwise, use boringssl.
134+
```
135+
Change:
136+
```
137+
if (is_nacl) {
138+
```
139+
To:
140+
```
141+
# if (is_nacl) {
142+
if (true) {
143+
```
144+
- Edit *rtc_base\BUILD.gn*:\
145+
Change:
146+
```
147+
if (rtc_build_ssl) {
148+
deps += [ "//third_party/boringssl" ]
149+
} else {
150+
```
151+
To:
152+
```
153+
if (rtc_build_ssl) {
154+
# deps += [ "//third_party/boringssl" ]
155+
} else {
156+
```
157+
158+
### Set Up OpenSSL
159+
160+
Do one of the following to provide OpenSSL for building against:
161+
a. If you have built Vircadia, find the **HIFI_VCPKG_BASE** subdirectory used in your build and make note of the path to and
162+
including the *installed\x64-windows\include* directory (which includes an *openssl* directory).
163+
a. Follow https://github.com/vircadia/vcpkg to install *vcpkg* and then *openssl*. Make note of the path to and including the
164+
*packages\openssl-windows_x64-windows\include* directory (which includes an *openssl* directory).
165+
166+
Copy the *\<path\>\openssl* directory to the following locations (i.e., add as *openssl* subdirectories):
167+
- *third_party\libsrtp\crypto\include*
168+
- *third_party\usrsctp\usrsctplib\usrsctplib*
169+
170+
Also use the path in the `gn gen` commands, below, making sure to escape `\`s as `\\`s.
171+
172+
### Build and Package
173+
174+
Use a VS2019 developer command prompt in the *src* directory.
175+
176+
Create a release build of the WebRTC library:
177+
- `gn gen --ide=vs2019 out\Release --filters=//:webrtc "--args=is_debug=false is_clang=false use_custom_libcxx=false libcxx_is_shared=true symbol_level=2 use_lld=false rtc_include_tests=false rtc_build_tools=false rtc_build_examples=false proprietary_codecs=true rtc_use_h264=true enable_libaom=false rtc_enable_protobuf=false rtc_build_ssl=false rtc_ssl_root=\"<path>\""`
178+
- `ninja -C out\Release`
179+
180+
Create a debug build of the WebRTC library:
181+
- `gn gen --ide=vs2019 out\Debug --filters=//:webrtc "--args=is_debug=true is_clang=false use_custom_libcxx=false libcxx_is_shared=true enable_iterator_debugging=true use_lld=false rtc_include_tests=false rtc_build_tools=false rtc_build_examples=false proprietary_codecs=true rtc_use_h264=true enable_libaom=false rtc_enable_protobuf=false rtc_build_ssl=false rtc_ssl_root=\"<path>\""`
182+
- `ninja -C out\Debug`
183+
184+
Create VCPKG file:
185+
- Assemble files in VCPKG directory structure: Use the *copy-VCPKG-files-win.cmd* batch file per instructions in it.
186+
`cd ..`\
187+
`copy-VCPKG-files-win`
188+
- Zip up the VCPKG *webrtc* directory created by the batch file.
189+
`cd vcpkg`\
190+
`7z a -tzip webrtc-m84-yyyymmdd-windows.zip webrtc`
191+
- Calculate the SHA512 of the zip file. E.g., using a Windows PowerShell command window:\
192+
`Get-FileHash <filename> -Algorithm SHA512 | Format-List`
193+
- Convert the SHA512 to lower case. E.g., using Microsoft Word, select the SHA512 text and use Shift-F3 to change the case.
194+
- Host the zip file on the Web.
195+
- Update *CONTROL* and *portfile.cmake* with version number (revision date), zip file Web URL, and SHA512.
196+
197+
### Tidying up
198+
199+
Disable the depot_tools:
200+
- Rename the *depot_tools* directory so that these tools don't interfere with the rest of your development environment for
201+
other work.
202+
203+
204+
## Linux - M81
205+
206+
The original, High Fidelity-provided WebRTC VCPKG library is used for AEC (audio echo cancellation) only.
207+
208+
**TODO:** Update to M84 and include WebRTC components per Windows WebRTC.
209+
210+
211+
## MacOS - M78
212+
213+
The original, High Fidelity-provided WebRTC VCPKG library is used for AEC (audio echo cancellation) only.
214+
215+
**TODO:** Update to M84 and include WebRTC components per Windows WebRTC.

0 commit comments

Comments
 (0)