Skip to content

Commit fcfcc4f

Browse files
Refactor API into an IceUdpMuxListener object
1 parent 4e0a5d8 commit fcfcc4f

8 files changed

+189
-64
lines changed

CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ set(LIBDATACHANNEL_SOURCES
6666
${CMAKE_CURRENT_SOURCE_DIR}/src/configuration.cpp
6767
${CMAKE_CURRENT_SOURCE_DIR}/src/datachannel.cpp
6868
${CMAKE_CURRENT_SOURCE_DIR}/src/description.cpp
69+
${CMAKE_CURRENT_SOURCE_DIR}/src/iceudpmuxlistener.cpp
6970
${CMAKE_CURRENT_SOURCE_DIR}/src/mediahandler.cpp
7071
${CMAKE_CURRENT_SOURCE_DIR}/src/global.cpp
7172
${CMAKE_CURRENT_SOURCE_DIR}/src/message.cpp
@@ -99,6 +100,7 @@ set(LIBDATACHANNEL_HEADERS
99100
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/configuration.hpp
100101
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/datachannel.hpp
101102
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/description.hpp
103+
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/iceudpmuxlistener.hpp
102104
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/mediahandler.hpp
103105
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/rtcpreceivingsession.hpp
104106
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/common.hpp
@@ -139,6 +141,7 @@ set(LIBDATACHANNEL_IMPL_SOURCES
139141
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlssrtptransport.cpp
140142
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlstransport.cpp
141143
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/icetransport.cpp
144+
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/iceudpmuxlistener.cpp
142145
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/init.cpp
143146
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/peerconnection.cpp
144147
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/logcounter.cpp
@@ -171,6 +174,7 @@ set(LIBDATACHANNEL_IMPL_HEADERS
171174
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlssrtptransport.hpp
172175
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlstransport.hpp
173176
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/icetransport.hpp
177+
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/iceudpmuxlistener.hpp
174178
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/init.hpp
175179
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/internals.hpp
176180
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/peerconnection.hpp

include/rtc/global.hpp

-11
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,6 @@ RTC_CPP_EXPORT void InitLogger(LogLevel level, LogCallback callback = nullptr);
3434
RTC_CPP_EXPORT void Preload();
3535
RTC_CPP_EXPORT std::shared_future<void> Cleanup();
3636

37-
struct IceUdpMuxRequest {
38-
std::string localUfrag;
39-
std::string remoteUfrag;
40-
std::string remoteHost;
41-
uint16_t remotePort;
42-
};
43-
44-
RTC_CPP_EXPORT typedef std::function<void(IceUdpMuxRequest request)> IceUdpMuxCallback;
45-
46-
RTC_CPP_EXPORT void ListenIceUdpMux (int port, IceUdpMuxCallback *callback, std::optional<std::string> bindAddress = nullptr);
47-
4837
struct SctpSettings {
4938
// For the following settings, not set means optimized default
5039
optional<size_t> recvBufferSize; // in bytes

include/rtc/iceudpmuxlistener.hpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Copyright (c) 2025 Alex Potsides
3+
* Copyright (c) 2025 Paul-Louis Ageneau
4+
*
5+
* This Source Code Form is subject to the terms of the Mozilla Public
6+
* License, v. 2.0. If a copy of the MPL was not distributed with this
7+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
8+
*/
9+
10+
#ifndef RTC_ICE_UDP_MUX_LISTENER_H
11+
#define RTC_ICE_UDP_MUX_LISTENER_H
12+
13+
#include "common.hpp"
14+
15+
namespace rtc {
16+
17+
namespace impl {
18+
19+
struct IceUdpMuxListener;
20+
21+
} // namespace impl
22+
23+
struct IceUdpMuxRequest { // TODO change name
24+
string localUfrag;
25+
string remoteUfrag;
26+
string remoteAddress;
27+
uint16_t remotePort;
28+
};
29+
30+
class RTC_CPP_EXPORT IceUdpMuxListener final : private CheshireCat<impl::IceUdpMuxListener> {
31+
public:
32+
IceUdpMuxListener(uint16_t port, optional<string> bindAddress = nullopt);
33+
~IceUdpMuxListener();
34+
35+
void stop();
36+
37+
uint16_t port() const;
38+
39+
void OnUnhandledStunRequest(std::function<void(IceUdpMuxRequest)> callback);
40+
41+
private:
42+
using CheshireCat<impl::IceUdpMuxListener>::impl;
43+
};
44+
45+
} // namespace rtc
46+
47+
#endif

include/rtc/rtc.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "datachannel.hpp"
1717
#include "peerconnection.hpp"
1818
#include "track.hpp"
19+
#include "iceudpmuxlistener.hpp"
1920

2021
#if RTC_ENABLE_WEBSOCKET
2122

src/global.cpp

+1-53
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@
1919
#include "impl/init.hpp"
2020

2121
#include <mutex>
22-
#include <map>
23-
24-
#if !USE_NICE
25-
#include <juice/juice.h>
26-
#endif
2722

2823
namespace {
2924

@@ -93,54 +88,7 @@ std::shared_future<void> Cleanup() { return impl::Init::Instance().cleanup(); }
9388

9489
void SetSctpSettings(SctpSettings s) { impl::Init::Instance().setSctpSettings(std::move(s)); }
9590

96-
#if !USE_NICE
97-
98-
void InvokeIceUdpMuxCallback (const juice_mux_binding_request *info, void *user_ptr) {
99-
PLOG_DEBUG << "Invoking ICE UDP mux callback";
100-
101-
IceUdpMuxCallback *callback = (IceUdpMuxCallback*)user_ptr;
102-
103-
if (callback) {
104-
(*callback)({
105-
std::string(info->local_ufrag),
106-
std::string(info->remote_ufrag),
107-
std::string(info->address),
108-
info->port
109-
});
110-
} else {
111-
PLOG_DEBUG << "No ICE UDP mux callback configured for port " << info->port;
112-
}
113-
}
114-
115-
#endif
116-
117-
void ListenIceUdpMux ([[maybe_unused]] int port, [[maybe_unused]] IceUdpMuxCallback *callback, [[maybe_unused]] std::optional<std::string> bindAddress) {
118-
#if USE_NICE
119-
PLOG_WARNING << "ListenIceUdpMux is not supported with libnice, please use libjuice";
120-
#else
121-
// NULL host binds to all available addresses
122-
const char *host = bindAddress.has_value() ? bindAddress.value().c_str() : NULL;
123-
124-
if (callback == NULL) {
125-
PLOG_DEBUG << "Removing ICE UDP mux callback for port " << port;
126-
127-
// call with NULL callback to remove the listener for the host/port
128-
if (juice_mux_listen(host, port, NULL, NULL) < 0) {
129-
throw std::runtime_error("Could not remove ICE UDP mux callback");
130-
}
131-
132-
return;
133-
}
134-
135-
PLOG_DEBUG << "Adding ICE UDP mux callback for port " << port;
136-
137-
if (juice_mux_listen(host, port, &InvokeIceUdpMuxCallback, callback) < 0) {
138-
throw std::invalid_argument("Could not add ICE UDP mux callback");
139-
}
140-
#endif
141-
}
142-
143-
RTC_CPP_EXPORT std::ostream &operator<<(std::ostream &out, LogLevel level) {
91+
std::ostream &operator<<(std::ostream &out, LogLevel level) {
14492
switch (level) {
14593
case LogLevel::Fatal:
14694
out << "fatal";

src/iceudpmuxlistener.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) 2025 Alex Potsides
3+
* Copyright (c) 2025 Paul-Louis Ageneau
4+
*
5+
* This Source Code Form is subject to the terms of the Mozilla Public
6+
* License, v. 2.0. If a copy of the MPL was not distributed with this
7+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
8+
*/
9+
10+
#include "iceudpmuxlistener.hpp"
11+
12+
#include "impl/iceudpmuxlistener.hpp"
13+
14+
namespace rtc {
15+
16+
IceUdpMuxListener::IceUdpMuxListener(uint16_t port, optional<string> bindAddress)
17+
: CheshireCat<impl::IceUdpMuxListener>(port, std::move(bindAddress)) {}
18+
19+
IceUdpMuxListener::~IceUdpMuxListener() {}
20+
21+
void IceUdpMuxListener::stop() { impl()->stop(); }
22+
23+
uint16_t IceUdpMuxListener::port() const { return impl()->port; }
24+
25+
void IceUdpMuxListener::OnUnhandledStunRequest(std::function<void(IceUdpMuxRequest)> callback) {
26+
impl()->unhandledStunRequestCallback = callback;
27+
}
28+
29+
} // namespace rtc

src/impl/iceudpmuxlistener.cpp

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Copyright (c) 2025 Alex Potsides
3+
* Copyright (c) 2025 Paul-Louis Ageneau
4+
*
5+
* This Source Code Form is subject to the terms of the Mozilla Public
6+
* License, v. 2.0. If a copy of the MPL was not distributed with this
7+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
8+
*/
9+
10+
#include "iceudpmuxlistener.hpp"
11+
#include "internals.hpp"
12+
13+
namespace rtc::impl {
14+
15+
#if !USE_NICE
16+
void IceUdpMuxListener::UnhandledStunRequestCallback(const juice_mux_binding_request *info,
17+
void *user_ptr) {
18+
auto listener = static_cast<IceUdpMuxListener *>(user_ptr);
19+
if (!listener)
20+
return;
21+
22+
IceUdpMuxRequest request;
23+
request.localUfrag = info->local_ufrag;
24+
request.remoteUfrag = info->remote_ufrag;
25+
request.remoteAddress = info->address;
26+
request.remotePort = info->port;
27+
listener->unhandledStunRequestCallback(std::move(request));
28+
}
29+
#endif
30+
31+
IceUdpMuxListener::IceUdpMuxListener(uint16_t port, optional<string> bindAddress) : port(port) {
32+
PLOG_VERBOSE << "Creating IceUdpMuxListener";
33+
34+
#if !USE_NICE
35+
PLOG_DEBUG << "Registering ICE UDP mux listener for port " << port;
36+
if (juice_mux_listen(bindAddress ? bindAddress->c_str() : NULL, port,
37+
IceUdpMuxListener::UnhandledStunRequestCallback, this) < 0) {
38+
throw std::runtime_error("Failed to register ICE UDP mux listener");
39+
}
40+
#else
41+
PLOG_WARNING << "ICE UDP mux is not available with libnice";
42+
#endif
43+
}
44+
45+
IceUdpMuxListener::~IceUdpMuxListener() {
46+
PLOG_VERBOSE << "Destroying IceUdpMuxListener";
47+
stop();
48+
}
49+
50+
void IceUdpMuxListener::stop() {
51+
if (mStopped.exchange(true))
52+
return;
53+
54+
#if !USE_NICE
55+
PLOG_DEBUG << "Unregistering ICE UDP mux listener for port " << port;
56+
if (juice_mux_listen(NULL, port, NULL, NULL) < 0) {
57+
PLOG_ERROR << "Failed to unregister ICE UDP mux listener";
58+
}
59+
#endif
60+
}
61+
62+
} // namespace rtc::impl

src/impl/iceudpmuxlistener.hpp

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright (c) 2025 Alex Potsides
3+
* Copyright (c) 2025 Paul-Louis Ageneau
4+
*
5+
* This Source Code Form is subject to the terms of the Mozilla Public
6+
* License, v. 2.0. If a copy of the MPL was not distributed with this
7+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
8+
*/
9+
10+
#ifndef RTC_IMPL_ICE_UDP_MUX_LISTENER_H
11+
#define RTC_IMPL_ICE_UDP_MUX_LISTENER_H
12+
13+
#include "common.hpp"
14+
15+
#include "rtc/iceudpmuxlistener.hpp"
16+
17+
#if !USE_NICE
18+
#include <juice/juice.h>
19+
#endif
20+
21+
#include <atomic>
22+
23+
namespace rtc::impl {
24+
25+
struct IceUdpMuxListener final {
26+
IceUdpMuxListener(uint16_t port, optional<string> bindAddress = nullopt);
27+
~IceUdpMuxListener();
28+
29+
void stop();
30+
31+
const uint16_t port;
32+
synchronized_callback<IceUdpMuxRequest> unhandledStunRequestCallback;
33+
34+
private:
35+
#if !USE_NICE
36+
static void UnhandledStunRequestCallback(const juice_mux_binding_request *info, void *user_ptr);
37+
#endif
38+
39+
std::atomic<bool> mStopped;
40+
};
41+
42+
}
43+
44+
#endif
45+

0 commit comments

Comments
 (0)