233 lines
6.1 KiB
C++
233 lines
6.1 KiB
C++
|
|
#include "rtc_bridge.h"
|
||
|
|
|
||
|
|
#include <rtc/rtc.h>
|
||
|
|
|
||
|
|
#include <cstring>
|
||
|
|
|
||
|
|
#ifdef _WIN32
|
||
|
|
#include <windows.h>
|
||
|
|
#include <bcrypt.h>
|
||
|
|
#else
|
||
|
|
#include <cstdio>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static std::mutex *g_rtc_mutex = new std::mutex;
|
||
|
|
static std::deque<RtcEvent> *g_rtc_events = new std::deque<RtcEvent>;
|
||
|
|
|
||
|
|
static void rtc_push(RtcEvent &&ev) {
|
||
|
|
std::lock_guard<std::mutex> lock(*g_rtc_mutex);
|
||
|
|
g_rtc_events->push_back(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
bool runt_rtc_poll_event(RtcEvent &out) {
|
||
|
|
std::lock_guard<std::mutex> lock(*g_rtc_mutex);
|
||
|
|
if (g_rtc_events->empty()) return false;
|
||
|
|
out = std::move(g_rtc_events->front());
|
||
|
|
g_rtc_events->pop_front();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_description_cb(int pc, const char *sdp, const char *type, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::LocalDescription;
|
||
|
|
ev.id = pc;
|
||
|
|
ev.s1 = sdp != nullptr ? sdp : "";
|
||
|
|
ev.s2 = type != nullptr ? type : "";
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_candidate_cb(int pc, const char *cand, const char *mid, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::LocalCandidate;
|
||
|
|
ev.id = pc;
|
||
|
|
ev.s1 = cand != nullptr ? cand : "";
|
||
|
|
ev.s2 = mid != nullptr ? mid : "";
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_open_cb(int id, void *ptr);
|
||
|
|
static void RTC_API rtc_closed_cb(int id, void *ptr);
|
||
|
|
static void RTC_API rtc_error_cb(int id, const char *error, void *ptr);
|
||
|
|
static void RTC_API rtc_message_cb(int id, const char *message, int size, void *ptr);
|
||
|
|
|
||
|
|
static void RTC_API rtc_state_cb(int pc, rtcState state, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::StateChange;
|
||
|
|
ev.id = pc;
|
||
|
|
ev.arg = (int)state;
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_gathering_cb(int pc, rtcGatheringState state, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::GatheringState;
|
||
|
|
ev.id = pc;
|
||
|
|
ev.arg = (int)state;
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void rtc_register_dc_callbacks(int dc) {
|
||
|
|
rtcSetOpenCallback(dc, rtc_open_cb);
|
||
|
|
rtcSetClosedCallback(dc, rtc_closed_cb);
|
||
|
|
rtcSetErrorCallback(dc, rtc_error_cb);
|
||
|
|
rtcSetMessageCallback(dc, rtc_message_cb);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_datachannel_cb(int pc, int dc, void *ptr) {
|
||
|
|
rtc_register_dc_callbacks(dc);
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::DataChannel;
|
||
|
|
ev.id = pc;
|
||
|
|
ev.arg = dc;
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_open_cb(int id, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::Open;
|
||
|
|
ev.id = id;
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_closed_cb(int id, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::Closed;
|
||
|
|
ev.id = id;
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_error_cb(int id, const char *error, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::Error;
|
||
|
|
ev.id = id;
|
||
|
|
ev.s1 = error != nullptr ? error : "";
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
static void RTC_API rtc_message_cb(int id, const char *message, int size, void *ptr) {
|
||
|
|
RtcEvent ev;
|
||
|
|
ev.type = RtcEventType::Message;
|
||
|
|
ev.id = id;
|
||
|
|
if (size < 0) {
|
||
|
|
ev.isString = true;
|
||
|
|
ev.s1 = message != nullptr ? message : "";
|
||
|
|
} else {
|
||
|
|
ev.data.assign(message, message + size);
|
||
|
|
}
|
||
|
|
rtc_push(std::move(ev));
|
||
|
|
}
|
||
|
|
|
||
|
|
int runt_rtc_init() {
|
||
|
|
return rtcPreload() ? 0 : -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void runt_rtc_cleanup() {
|
||
|
|
rtcCleanup();
|
||
|
|
}
|
||
|
|
|
||
|
|
int runt_rtc_create_peer_connection(const std::vector<std::string> &iceServers) {
|
||
|
|
rtcConfiguration conf;
|
||
|
|
memset(&conf, 0, sizeof(conf));
|
||
|
|
std::vector<const char *> servers(iceServers.size());
|
||
|
|
for (size_t i = 0; i < iceServers.size(); i++) {
|
||
|
|
servers[i] = iceServers[i].c_str();
|
||
|
|
}
|
||
|
|
conf.iceServers = servers.data();
|
||
|
|
conf.iceServersCount = (int)servers.size();
|
||
|
|
int pc = rtcCreatePeerConnection(&conf);
|
||
|
|
if (pc < 0) return pc;
|
||
|
|
rtcSetLocalDescriptionCallback(pc, rtc_description_cb);
|
||
|
|
rtcSetLocalCandidateCallback(pc, rtc_candidate_cb);
|
||
|
|
rtcSetStateChangeCallback(pc, rtc_state_cb);
|
||
|
|
rtcSetGatheringStateChangeCallback(pc, rtc_gathering_cb);
|
||
|
|
rtcSetDataChannelCallback(pc, rtc_datachannel_cb);
|
||
|
|
return pc;
|
||
|
|
}
|
||
|
|
|
||
|
|
void runt_rtc_close_peer_connection(int pc) {
|
||
|
|
rtcClosePeerConnection(pc);
|
||
|
|
}
|
||
|
|
|
||
|
|
void runt_rtc_delete_peer_connection(int pc) {
|
||
|
|
rtcDeletePeerConnection(pc);
|
||
|
|
}
|
||
|
|
|
||
|
|
void runt_rtc_set_local_description(int pc, const char *type) {
|
||
|
|
rtcSetLocalDescription(pc, type);
|
||
|
|
}
|
||
|
|
|
||
|
|
int runt_rtc_set_remote_description(int pc, const char *sdp, const char *type) {
|
||
|
|
return rtcSetRemoteDescription(pc, sdp, type);
|
||
|
|
}
|
||
|
|
|
||
|
|
int runt_rtc_add_remote_candidate(int pc, const char *cand, const char *mid) {
|
||
|
|
return rtcAddRemoteCandidate(pc, cand, mid);
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string runt_rtc_get_local_description(int pc) {
|
||
|
|
int size = rtcGetLocalDescription(pc, nullptr, 0);
|
||
|
|
if (size <= 0) return "";
|
||
|
|
std::string buf(size, '\0');
|
||
|
|
rtcGetLocalDescription(pc, buf.data(), size);
|
||
|
|
return std::string(buf.data(), strnlen(buf.data(), buf.size()));
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string runt_rtc_get_local_description_type(int pc) {
|
||
|
|
char buf[64];
|
||
|
|
int size = rtcGetLocalDescriptionType(pc, buf, sizeof(buf));
|
||
|
|
if (size <= 0) return "";
|
||
|
|
return std::string(buf, strnlen(buf, sizeof(buf)));
|
||
|
|
}
|
||
|
|
|
||
|
|
int runt_rtc_create_data_channel(int pc, const char *label, bool unordered,
|
||
|
|
int maxRetransmits) {
|
||
|
|
rtcDataChannelInit init;
|
||
|
|
memset(&init, 0, sizeof(init));
|
||
|
|
init.reliability.unordered = unordered;
|
||
|
|
init.reliability.unreliable = maxRetransmits >= 0;
|
||
|
|
init.reliability.maxRetransmits =
|
||
|
|
maxRetransmits >= 0 ? (unsigned int)maxRetransmits : 0;
|
||
|
|
int dc = rtcCreateDataChannelEx(pc, label, &init);
|
||
|
|
if (dc < 0) return dc;
|
||
|
|
rtc_register_dc_callbacks(dc);
|
||
|
|
return dc;
|
||
|
|
}
|
||
|
|
|
||
|
|
void runt_rtc_delete_data_channel(int dc) {
|
||
|
|
rtcDeleteDataChannel(dc);
|
||
|
|
}
|
||
|
|
|
||
|
|
int runt_rtc_send_message(int id, const char *data, int size) {
|
||
|
|
return rtcSendMessage(id, data, size);
|
||
|
|
}
|
||
|
|
|
||
|
|
void runt_rtc_close(int id) {
|
||
|
|
rtcClose(id);
|
||
|
|
}
|
||
|
|
|
||
|
|
void runt_rtc_delete(int id) {
|
||
|
|
rtcDelete(id);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool runt_rtc_is_open(int id) {
|
||
|
|
return rtcIsOpen(id);
|
||
|
|
}
|
||
|
|
|
||
|
|
int runt_rtc_get_buffered_amount(int id) {
|
||
|
|
return rtcGetBufferedAmount(id);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool runt_rtc_random_bytes(char *out, int len) {
|
||
|
|
#ifdef _WIN32
|
||
|
|
return BCryptGenRandom(nullptr, reinterpret_cast<PUCHAR>(out),
|
||
|
|
static_cast<ULONG>(len),
|
||
|
|
BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0;
|
||
|
|
#else
|
||
|
|
FILE *f = fopen("/dev/urandom", "rb");
|
||
|
|
if (f == nullptr) return false;
|
||
|
|
size_t n = fread(out, 1, static_cast<size_t>(len), f);
|
||
|
|
fclose(f);
|
||
|
|
return n == static_cast<size_t>(len);
|
||
|
|
#endif
|
||
|
|
}
|