Files
LNXRNT/Sources/rtc_bridge.cpp

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
}