capi.cpp 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  1. /**
  2. * Copyright (c) 2019-2020 Paul-Louis Ageneau
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "rtc.h"
  19. #include "rtc.hpp"
  20. #include "plog/Formatters/FuncMessageFormatter.h"
  21. #include <chrono>
  22. #include <exception>
  23. #include <mutex>
  24. #include <type_traits>
  25. #include <unordered_map>
  26. #include <utility>
  27. #ifdef _WIN32
  28. #include <codecvt>
  29. #include <locale>
  30. #endif
  31. using namespace rtc;
  32. using std::chrono::milliseconds;
  33. namespace {
  34. std::unordered_map<int, shared_ptr<PeerConnection>> peerConnectionMap;
  35. std::unordered_map<int, shared_ptr<DataChannel>> dataChannelMap;
  36. std::unordered_map<int, shared_ptr<Track>> trackMap;
  37. #if RTC_ENABLE_MEDIA
  38. std::unordered_map<int, shared_ptr<MediaChainableHandler>> rtcpChainableHandlerMap;
  39. std::unordered_map<int, shared_ptr<RtcpSrReporter>> rtcpSrReporterMap;
  40. std::unordered_map<int, shared_ptr<RtpPacketizationConfig>> rtpConfigMap;
  41. #endif
  42. #if RTC_ENABLE_WEBSOCKET
  43. std::unordered_map<int, shared_ptr<WebSocket>> webSocketMap;
  44. #endif
  45. std::unordered_map<int, void *> userPointerMap;
  46. std::mutex mutex;
  47. int lastId = 0;
  48. optional<void *> getUserPointer(int id) {
  49. std::lock_guard lock(mutex);
  50. auto it = userPointerMap.find(id);
  51. return it != userPointerMap.end() ? std::make_optional(it->second) : nullopt;
  52. }
  53. void setUserPointer(int i, void *ptr) {
  54. std::lock_guard lock(mutex);
  55. userPointerMap[i] = ptr;
  56. }
  57. shared_ptr<PeerConnection> getPeerConnection(int id) {
  58. std::lock_guard lock(mutex);
  59. if (auto it = peerConnectionMap.find(id); it != peerConnectionMap.end())
  60. return it->second;
  61. else
  62. throw std::invalid_argument("PeerConnection ID does not exist");
  63. }
  64. shared_ptr<DataChannel> getDataChannel(int id) {
  65. std::lock_guard lock(mutex);
  66. if (auto it = dataChannelMap.find(id); it != dataChannelMap.end())
  67. return it->second;
  68. else
  69. throw std::invalid_argument("DataChannel ID does not exist");
  70. }
  71. shared_ptr<Track> getTrack(int id) {
  72. std::lock_guard lock(mutex);
  73. if (auto it = trackMap.find(id); it != trackMap.end())
  74. return it->second;
  75. else
  76. throw std::invalid_argument("Track ID does not exist");
  77. }
  78. int emplacePeerConnection(shared_ptr<PeerConnection> ptr) {
  79. std::lock_guard lock(mutex);
  80. int pc = ++lastId;
  81. peerConnectionMap.emplace(std::make_pair(pc, ptr));
  82. userPointerMap.emplace(std::make_pair(pc, nullptr));
  83. return pc;
  84. }
  85. int emplaceDataChannel(shared_ptr<DataChannel> ptr) {
  86. std::lock_guard lock(mutex);
  87. int dc = ++lastId;
  88. dataChannelMap.emplace(std::make_pair(dc, ptr));
  89. userPointerMap.emplace(std::make_pair(dc, nullptr));
  90. return dc;
  91. }
  92. int emplaceTrack(shared_ptr<Track> ptr) {
  93. std::lock_guard lock(mutex);
  94. int tr = ++lastId;
  95. trackMap.emplace(std::make_pair(tr, ptr));
  96. userPointerMap.emplace(std::make_pair(tr, nullptr));
  97. return tr;
  98. }
  99. void erasePeerConnection(int pc) {
  100. std::lock_guard lock(mutex);
  101. if (peerConnectionMap.erase(pc) == 0)
  102. throw std::invalid_argument("PeerConnection ID does not exist");
  103. userPointerMap.erase(pc);
  104. }
  105. void eraseDataChannel(int dc) {
  106. std::lock_guard lock(mutex);
  107. if (dataChannelMap.erase(dc) == 0)
  108. throw std::invalid_argument("DataChannel ID does not exist");
  109. userPointerMap.erase(dc);
  110. }
  111. void eraseTrack(int tr) {
  112. std::lock_guard lock(mutex);
  113. if (trackMap.erase(tr) == 0)
  114. throw std::invalid_argument("Track ID does not exist");
  115. #if RTC_ENABLE_MEDIA
  116. rtcpSrReporterMap.erase(tr);
  117. rtcpChainableHandlerMap.erase(tr);
  118. rtpConfigMap.erase(tr);
  119. #endif
  120. userPointerMap.erase(tr);
  121. }
  122. #if RTC_ENABLE_MEDIA
  123. shared_ptr<RtcpSrReporter> getRtcpSrReporter(int id) {
  124. std::lock_guard lock(mutex);
  125. if (auto it = rtcpSrReporterMap.find(id); it != rtcpSrReporterMap.end()) {
  126. return it->second;
  127. } else {
  128. throw std::invalid_argument("RtcpSRReporter ID does not exist");
  129. }
  130. }
  131. void emplaceRtcpSrReporter(shared_ptr<RtcpSrReporter> ptr, int tr) {
  132. std::lock_guard lock(mutex);
  133. rtcpSrReporterMap.emplace(std::make_pair(tr, ptr));
  134. }
  135. shared_ptr<MediaChainableHandler> getMediaChainableHandler(int id) {
  136. std::lock_guard lock(mutex);
  137. if (auto it = rtcpChainableHandlerMap.find(id); it != rtcpChainableHandlerMap.end()) {
  138. return it->second;
  139. } else {
  140. throw std::invalid_argument("RtcpChainableHandler ID does not exist");
  141. }
  142. }
  143. void emplaceMediaChainableHandler(shared_ptr<MediaChainableHandler> ptr, int tr) {
  144. std::lock_guard lock(mutex);
  145. rtcpChainableHandlerMap.emplace(std::make_pair(tr, ptr));
  146. }
  147. shared_ptr<RtpPacketizationConfig> getRTPConfig(int id) {
  148. std::lock_guard lock(mutex);
  149. if (auto it = rtpConfigMap.find(id); it != rtpConfigMap.end()) {
  150. return it->second;
  151. } else {
  152. throw std::invalid_argument("RTPConfiguration ID does not exist");
  153. }
  154. }
  155. void emplaceRTPConfig(shared_ptr<RtpPacketizationConfig> ptr, int tr) {
  156. std::lock_guard lock(mutex);
  157. rtpConfigMap.emplace(std::make_pair(tr, ptr));
  158. }
  159. Description::Direction rtcDirectionToDirection(rtcDirection direction) {
  160. switch (direction) {
  161. case RTC_DIRECTION_SENDONLY:
  162. return Description::Direction::SendOnly;
  163. case RTC_DIRECTION_RECVONLY:
  164. return Description::Direction::RecvOnly;
  165. case RTC_DIRECTION_SENDRECV:
  166. return Description::Direction::SendRecv;
  167. case RTC_DIRECTION_INACTIVE:
  168. return Description::Direction::Inactive;
  169. default:
  170. return Description::Direction::Unknown;
  171. }
  172. }
  173. shared_ptr<RtpPacketizationConfig>
  174. getNewRtpPacketizationConfig(uint32_t ssrc, const char *cname, uint8_t payloadType,
  175. uint32_t clockRate, uint16_t sequenceNumber, uint32_t timestamp) {
  176. if (!cname) {
  177. throw std::invalid_argument("Unexpected null pointer for cname");
  178. }
  179. return std::make_shared<RtpPacketizationConfig>(ssrc, cname, payloadType, clockRate,
  180. sequenceNumber, timestamp);
  181. }
  182. #endif // RTC_ENABLE_MEDIA
  183. #if RTC_ENABLE_WEBSOCKET
  184. shared_ptr<WebSocket> getWebSocket(int id) {
  185. std::lock_guard lock(mutex);
  186. if (auto it = webSocketMap.find(id); it != webSocketMap.end())
  187. return it->second;
  188. else
  189. throw std::invalid_argument("WebSocket ID does not exist");
  190. }
  191. int emplaceWebSocket(shared_ptr<WebSocket> ptr) {
  192. std::lock_guard lock(mutex);
  193. int ws = ++lastId;
  194. webSocketMap.emplace(std::make_pair(ws, ptr));
  195. userPointerMap.emplace(std::make_pair(ws, nullptr));
  196. return ws;
  197. }
  198. void eraseWebSocket(int ws) {
  199. std::lock_guard lock(mutex);
  200. if (webSocketMap.erase(ws) == 0)
  201. throw std::invalid_argument("WebSocket ID does not exist");
  202. userPointerMap.erase(ws);
  203. }
  204. #endif
  205. shared_ptr<Channel> getChannel(int id) {
  206. std::lock_guard lock(mutex);
  207. if (auto it = dataChannelMap.find(id); it != dataChannelMap.end())
  208. return it->second;
  209. if (auto it = trackMap.find(id); it != trackMap.end())
  210. return it->second;
  211. #if RTC_ENABLE_WEBSOCKET
  212. if (auto it = webSocketMap.find(id); it != webSocketMap.end())
  213. return it->second;
  214. #endif
  215. throw std::invalid_argument("DataChannel, Track, or WebSocket ID does not exist");
  216. }
  217. template <typename F> int wrap(F func) {
  218. try {
  219. return int(func());
  220. } catch (const std::invalid_argument &e) {
  221. PLOG_ERROR << e.what();
  222. return RTC_ERR_INVALID;
  223. } catch (const std::exception &e) {
  224. PLOG_ERROR << e.what();
  225. return RTC_ERR_FAILURE;
  226. }
  227. }
  228. int copyAndReturn(string s, char *buffer, int size) {
  229. if (!buffer)
  230. return int(s.size() + 1);
  231. if (size < int(s.size()))
  232. return RTC_ERR_TOO_SMALL;
  233. std::copy(s.begin(), s.end(), buffer);
  234. buffer[s.size()] = '\0';
  235. return int(s.size() + 1);
  236. }
  237. int copyAndReturn(binary b, char *buffer, int size) {
  238. if (!buffer)
  239. return int(b.size());
  240. if (size < int(b.size()))
  241. return RTC_ERR_TOO_SMALL;
  242. auto data = reinterpret_cast<const char *>(b.data());
  243. std::copy(data, data + b.size(), buffer);
  244. buffer[b.size()] = '\0';
  245. return int(b.size());
  246. }
  247. class plogAppender : public plog::IAppender {
  248. public:
  249. plogAppender(rtcLogCallbackFunc cb = nullptr) { setCallback(cb); }
  250. plogAppender(plogAppender &&appender) : callback(nullptr) {
  251. std::lock_guard lock(appender.callbackMutex);
  252. std::swap(appender.callback, callback);
  253. }
  254. void setCallback(rtcLogCallbackFunc cb) {
  255. std::lock_guard lock(callbackMutex);
  256. callback = cb;
  257. }
  258. void write(const plog::Record &record) override {
  259. plog::Severity severity = record.getSeverity();
  260. auto formatted = plog::FuncMessageFormatter::format(record);
  261. formatted.pop_back(); // remove newline
  262. #ifdef _WIN32
  263. using convert_type = std::codecvt_utf8<wchar_t>;
  264. std::wstring_convert<convert_type, wchar_t> converter;
  265. std::string str = converter.to_bytes(formatted);
  266. #else
  267. std::string str = formatted;
  268. #endif
  269. std::lock_guard lock(callbackMutex);
  270. if (callback)
  271. callback(static_cast<rtcLogLevel>(record.getSeverity()), str.c_str());
  272. else
  273. std::cout << plog::severityToString(severity) << " " << str << std::endl;
  274. }
  275. private:
  276. rtcLogCallbackFunc callback;
  277. std::mutex callbackMutex;
  278. };
  279. } // namespace
  280. void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb) {
  281. static optional<plogAppender> appender;
  282. const auto severity = static_cast<plog::Severity>(level);
  283. std::lock_guard lock(mutex);
  284. if (appender) {
  285. appender->setCallback(cb);
  286. InitLogger(severity, nullptr); // change the severity
  287. } else if (cb) {
  288. appender.emplace(plogAppender(cb));
  289. InitLogger(severity, &appender.value());
  290. } else {
  291. InitLogger(severity, nullptr); // log to stdout
  292. }
  293. }
  294. void rtcSetUserPointer(int i, void *ptr) { setUserPointer(i, ptr); }
  295. void *rtcGetUserPointer(int i) { return getUserPointer(i).value_or(nullptr); }
  296. int rtcCreatePeerConnection(const rtcConfiguration *config) {
  297. return wrap([config] {
  298. Configuration c;
  299. for (int i = 0; i < config->iceServersCount; ++i)
  300. c.iceServers.emplace_back(string(config->iceServers[i]));
  301. c.certificateType = static_cast<CertificateType>(config->certificateType);
  302. c.enableIceTcp = config->enableIceTcp;
  303. c.disableAutoNegotiation = config->disableAutoNegotiation;
  304. if (config->portRangeBegin > 0 || config->portRangeEnd > 0) {
  305. c.portRangeBegin = config->portRangeBegin;
  306. c.portRangeEnd = config->portRangeEnd;
  307. }
  308. if(config->mtu > 0)
  309. c.mtu = size_t(config->mtu);
  310. return emplacePeerConnection(std::make_shared<PeerConnection>(c));
  311. });
  312. }
  313. int rtcDeletePeerConnection(int pc) {
  314. return wrap([pc] {
  315. auto peerConnection = getPeerConnection(pc);
  316. peerConnection->onDataChannel(nullptr);
  317. peerConnection->onTrack(nullptr);
  318. peerConnection->onLocalDescription(nullptr);
  319. peerConnection->onLocalCandidate(nullptr);
  320. peerConnection->onStateChange(nullptr);
  321. peerConnection->onGatheringStateChange(nullptr);
  322. erasePeerConnection(pc);
  323. return RTC_ERR_SUCCESS;
  324. });
  325. }
  326. int rtcCreateDataChannel(int pc, const char *label) {
  327. return rtcCreateDataChannelEx(pc, label, nullptr);
  328. }
  329. int rtcCreateDataChannelEx(int pc, const char *label, const rtcDataChannelInit *init) {
  330. return wrap([&] {
  331. DataChannelInit dci = {};
  332. if (init) {
  333. auto *reliability = &init->reliability;
  334. dci.reliability.unordered = reliability->unordered;
  335. if (reliability->unreliable) {
  336. if (reliability->maxPacketLifeTime > 0) {
  337. dci.reliability.type = Reliability::Type::Timed;
  338. dci.reliability.rexmit = milliseconds(reliability->maxPacketLifeTime);
  339. } else {
  340. dci.reliability.type = Reliability::Type::Rexmit;
  341. dci.reliability.rexmit = reliability->maxRetransmits;
  342. }
  343. } else {
  344. dci.reliability.type = Reliability::Type::Reliable;
  345. }
  346. dci.negotiated = init->negotiated;
  347. dci.id = init->manualStream ? std::make_optional(init->stream) : nullopt;
  348. dci.protocol = init->protocol ? init->protocol : "";
  349. }
  350. auto peerConnection = getPeerConnection(pc);
  351. int dc = emplaceDataChannel(
  352. peerConnection->createDataChannel(string(label ? label : ""), std::move(dci)));
  353. if (auto ptr = getUserPointer(pc))
  354. rtcSetUserPointer(dc, *ptr);
  355. return dc;
  356. });
  357. }
  358. int rtcDeleteDataChannel(int dc) {
  359. return wrap([dc] {
  360. auto dataChannel = getDataChannel(dc);
  361. dataChannel->onOpen(nullptr);
  362. dataChannel->onClosed(nullptr);
  363. dataChannel->onError(nullptr);
  364. dataChannel->onMessage(nullptr);
  365. dataChannel->onBufferedAmountLow(nullptr);
  366. dataChannel->onAvailable(nullptr);
  367. eraseDataChannel(dc);
  368. return RTC_ERR_SUCCESS;
  369. });
  370. }
  371. #if RTC_ENABLE_MEDIA
  372. void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid,
  373. const char *_trackID) {
  374. optional<string> name = nullopt;
  375. if (_name) {
  376. name = string(_name);
  377. }
  378. optional<string> msid = nullopt;
  379. if (_msid) {
  380. msid = string(_msid);
  381. }
  382. optional<string> trackID = nullopt;
  383. if (_trackID) {
  384. trackID = string(_trackID);
  385. }
  386. description->addSSRC(ssrc, name, msid, trackID);
  387. }
  388. int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid,
  389. rtcDirection _direction, const char *_name, const char *_msid,
  390. const char *_trackID) {
  391. return wrap([&] {
  392. auto peerConnection = getPeerConnection(pc);
  393. auto direction = rtcDirectionToDirection(_direction);
  394. string mid = "video";
  395. switch (codec) {
  396. case RTC_CODEC_H264:
  397. case RTC_CODEC_VP8:
  398. case RTC_CODEC_VP9:
  399. mid = "video";
  400. break;
  401. case RTC_CODEC_OPUS:
  402. mid = "audio";
  403. break;
  404. }
  405. if (_mid) {
  406. mid = string(_mid);
  407. }
  408. optional<Description::Media> optDescription = nullopt;
  409. switch (codec) {
  410. case RTC_CODEC_H264:
  411. case RTC_CODEC_VP8:
  412. case RTC_CODEC_VP9: {
  413. auto desc = Description::Video(mid, direction);
  414. switch (codec) {
  415. case RTC_CODEC_H264:
  416. desc.addH264Codec(payloadType);
  417. break;
  418. case RTC_CODEC_VP8:
  419. desc.addVP8Codec(payloadType);
  420. break;
  421. case RTC_CODEC_VP9:
  422. desc.addVP8Codec(payloadType);
  423. break;
  424. default:
  425. break;
  426. }
  427. optDescription = desc;
  428. break;
  429. }
  430. case RTC_CODEC_OPUS: {
  431. auto desc = Description::Audio(mid, direction);
  432. switch (codec) {
  433. case RTC_CODEC_OPUS:
  434. desc.addOpusCodec(payloadType);
  435. break;
  436. default:
  437. break;
  438. }
  439. optDescription = desc;
  440. break;
  441. }
  442. default:
  443. break;
  444. }
  445. if (!optDescription.has_value()) {
  446. throw std::invalid_argument("Unexpected codec");
  447. } else {
  448. auto description = optDescription.value();
  449. setSSRC(&description, ssrc, _name, _msid, _trackID);
  450. int tr = emplaceTrack(peerConnection->addTrack(std::move(description)));
  451. if (auto ptr = getUserPointer(pc)) {
  452. rtcSetUserPointer(tr, *ptr);
  453. }
  454. return tr;
  455. }
  456. });
  457. }
  458. int rtcSetH264PacketizationHandler(int tr, uint32_t ssrc, const char *cname, uint8_t payloadType,
  459. uint32_t clockRate, uint16_t maxFragmentSize,
  460. uint16_t sequenceNumber, uint32_t timestamp) {
  461. return wrap([&] {
  462. auto track = getTrack(tr);
  463. // create RTP configuration
  464. auto rtpConfig = getNewRtpPacketizationConfig(ssrc, cname, payloadType, clockRate,
  465. sequenceNumber, timestamp);
  466. // create packetizer
  467. auto packetizer = std::make_shared<H264RtpPacketizer>(rtpConfig, maxFragmentSize);
  468. // create H264 handler
  469. auto h264Handler = std::make_shared<H264PacketizationHandler>(packetizer);
  470. emplaceMediaChainableHandler(h264Handler, tr);
  471. emplaceRTPConfig(rtpConfig, tr);
  472. // set handler
  473. track->setMediaHandler(h264Handler);
  474. return RTC_ERR_SUCCESS;
  475. });
  476. }
  477. int rtcSetOpusPacketizationHandler(int tr, uint32_t ssrc, const char *cname, uint8_t payloadType,
  478. uint32_t clockRate, uint16_t sequenceNumber,
  479. uint32_t timestamp) {
  480. return wrap([&] {
  481. auto track = getTrack(tr);
  482. // create RTP configuration
  483. auto rtpConfig = getNewRtpPacketizationConfig(ssrc, cname, payloadType, clockRate,
  484. sequenceNumber, timestamp);
  485. // create packetizer
  486. auto packetizer = std::make_shared<OpusRtpPacketizer>(rtpConfig);
  487. // create Opus handler
  488. auto opusHandler = std::make_shared<OpusPacketizationHandler>(packetizer);
  489. emplaceMediaChainableHandler(opusHandler, tr);
  490. emplaceRTPConfig(rtpConfig, tr);
  491. // set handler
  492. track->setMediaHandler(opusHandler);
  493. return RTC_ERR_SUCCESS;
  494. });
  495. }
  496. int rtcChainRtcpSrReporter(int tr) {
  497. return wrap([tr] {
  498. auto config = getRTPConfig(tr);
  499. auto reporter = std::make_shared<RtcpSrReporter>(config);
  500. emplaceRtcpSrReporter(reporter, tr);
  501. auto chainableHandler = getMediaChainableHandler(tr);
  502. chainableHandler->addToChain(reporter);
  503. return RTC_ERR_SUCCESS;
  504. });
  505. }
  506. int rtcChainRtcpNackResponder(int tr, unsigned maxStoredPacketsCount) {
  507. return wrap([tr, maxStoredPacketsCount] {
  508. auto responder = std::make_shared<RtcpNackResponder>(maxStoredPacketsCount);
  509. auto chainableHandler = getMediaChainableHandler(tr);
  510. chainableHandler->addToChain(responder);
  511. return RTC_ERR_SUCCESS;
  512. });
  513. }
  514. int rtcSetRtpConfigurationStartTime(int id, double startTime_s, bool timeIntervalSince1970,
  515. uint32_t timestamp) {
  516. return wrap([&] {
  517. auto config = getRTPConfig(id);
  518. auto epoch = RtpPacketizationConfig::EpochStart::T1900;
  519. if (timeIntervalSince1970) {
  520. epoch = RtpPacketizationConfig::EpochStart::T1970;
  521. }
  522. config->setStartTime(startTime_s, epoch, timestamp);
  523. return RTC_ERR_SUCCESS;
  524. });
  525. }
  526. int rtcStartRtcpSenderReporterRecording(int id) {
  527. return wrap([id] {
  528. auto sender = getRtcpSrReporter(id);
  529. sender->startRecording();
  530. return RTC_ERR_SUCCESS;
  531. });
  532. }
  533. int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp) {
  534. return wrap([&] {
  535. auto config = getRTPConfig(id);
  536. *timestamp = config->secondsToTimestamp(seconds);
  537. return RTC_ERR_SUCCESS;
  538. });
  539. }
  540. int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double *seconds) {
  541. return wrap([&] {
  542. auto config = getRTPConfig(id);
  543. *seconds = config->timestampToSeconds(timestamp);
  544. return RTC_ERR_SUCCESS;
  545. });
  546. }
  547. int rtcGetCurrentTrackTimestamp(int id, uint32_t *timestamp) {
  548. return wrap([&] {
  549. auto config = getRTPConfig(id);
  550. *timestamp = config->timestamp;
  551. return RTC_ERR_SUCCESS;
  552. });
  553. }
  554. int rtcGetTrackStartTimestamp(int id, uint32_t *timestamp) {
  555. return wrap([&] {
  556. auto config = getRTPConfig(id);
  557. *timestamp = config->startTimestamp;
  558. return RTC_ERR_SUCCESS;
  559. });
  560. }
  561. int rtcSetTrackRTPTimestamp(int id, uint32_t timestamp) {
  562. return wrap([&] {
  563. auto config = getRTPConfig(id);
  564. config->timestamp = timestamp;
  565. return RTC_ERR_SUCCESS;
  566. });
  567. }
  568. int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timestamp) {
  569. return wrap([&] {
  570. auto sender = getRtcpSrReporter(id);
  571. *timestamp = sender->previousReportedTimestamp;
  572. return RTC_ERR_SUCCESS;
  573. });
  574. }
  575. int rtcSetNeedsToSendRtcpSr(int id) {
  576. return wrap([id] {
  577. auto sender = getRtcpSrReporter(id);
  578. sender->setNeedsToReport();
  579. return RTC_ERR_SUCCESS;
  580. });
  581. }
  582. #endif // RTC_ENABLE_MEDIA
  583. int rtcAddTrack(int pc, const char *mediaDescriptionSdp) {
  584. return wrap([&] {
  585. if (!mediaDescriptionSdp)
  586. throw std::invalid_argument("Unexpected null pointer for track media description");
  587. auto peerConnection = getPeerConnection(pc);
  588. Description::Media media{string(mediaDescriptionSdp)};
  589. int tr = emplaceTrack(peerConnection->addTrack(std::move(media)));
  590. if (auto ptr = getUserPointer(pc))
  591. rtcSetUserPointer(tr, *ptr);
  592. return tr;
  593. });
  594. }
  595. int rtcDeleteTrack(int tr) {
  596. return wrap([&] {
  597. auto track = getTrack(tr);
  598. track->onOpen(nullptr);
  599. track->onClosed(nullptr);
  600. track->onError(nullptr);
  601. track->onMessage(nullptr);
  602. track->onBufferedAmountLow(nullptr);
  603. track->onAvailable(nullptr);
  604. eraseTrack(tr);
  605. return RTC_ERR_SUCCESS;
  606. });
  607. }
  608. int rtcGetTrackDescription(int tr, char *buffer, int size) {
  609. return wrap([&] {
  610. auto track = getTrack(tr);
  611. return copyAndReturn(track->description(), buffer, size);
  612. });
  613. }
  614. #if RTC_ENABLE_WEBSOCKET
  615. int rtcCreateWebSocket(const char *url) {
  616. return wrap([&] {
  617. auto ws = std::make_shared<WebSocket>();
  618. ws->open(url);
  619. return emplaceWebSocket(ws);
  620. });
  621. }
  622. int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config) {
  623. return wrap([&] {
  624. WebSocket::Configuration c;
  625. c.disableTlsVerification = config->disableTlsVerification;
  626. auto ws = std::make_shared<WebSocket>(c);
  627. ws->open(url);
  628. return emplaceWebSocket(ws);
  629. });
  630. }
  631. int rtcDeleteWebsocket(int ws) {
  632. return wrap([&] {
  633. auto webSocket = getWebSocket(ws);
  634. webSocket->onOpen(nullptr);
  635. webSocket->onClosed(nullptr);
  636. webSocket->onError(nullptr);
  637. webSocket->onMessage(nullptr);
  638. webSocket->onBufferedAmountLow(nullptr);
  639. webSocket->onAvailable(nullptr);
  640. eraseWebSocket(ws);
  641. return RTC_ERR_SUCCESS;
  642. });
  643. }
  644. #endif
  645. int rtcSetLocalDescriptionCallback(int pc, rtcDescriptionCallbackFunc cb) {
  646. return wrap([&] {
  647. auto peerConnection = getPeerConnection(pc);
  648. if (cb)
  649. peerConnection->onLocalDescription([pc, cb](Description desc) {
  650. if (auto ptr = getUserPointer(pc))
  651. cb(pc, string(desc).c_str(), desc.typeString().c_str(), *ptr);
  652. });
  653. else
  654. peerConnection->onLocalDescription(nullptr);
  655. return RTC_ERR_SUCCESS;
  656. });
  657. }
  658. int rtcSetLocalCandidateCallback(int pc, rtcCandidateCallbackFunc cb) {
  659. return wrap([&] {
  660. auto peerConnection = getPeerConnection(pc);
  661. if (cb)
  662. peerConnection->onLocalCandidate([pc, cb](Candidate cand) {
  663. if (auto ptr = getUserPointer(pc))
  664. cb(pc, cand.candidate().c_str(), cand.mid().c_str(), *ptr);
  665. });
  666. else
  667. peerConnection->onLocalCandidate(nullptr);
  668. return RTC_ERR_SUCCESS;
  669. });
  670. }
  671. int rtcSetStateChangeCallback(int pc, rtcStateChangeCallbackFunc cb) {
  672. return wrap([&] {
  673. auto peerConnection = getPeerConnection(pc);
  674. if (cb)
  675. peerConnection->onStateChange([pc, cb](PeerConnection::State state) {
  676. if (auto ptr = getUserPointer(pc))
  677. cb(pc, static_cast<rtcState>(state), *ptr);
  678. });
  679. else
  680. peerConnection->onStateChange(nullptr);
  681. return RTC_ERR_SUCCESS;
  682. });
  683. }
  684. int rtcSetGatheringStateChangeCallback(int pc, rtcGatheringStateCallbackFunc cb) {
  685. return wrap([&] {
  686. auto peerConnection = getPeerConnection(pc);
  687. if (cb)
  688. peerConnection->onGatheringStateChange([pc, cb](PeerConnection::GatheringState state) {
  689. if (auto ptr = getUserPointer(pc))
  690. cb(pc, static_cast<rtcGatheringState>(state), *ptr);
  691. });
  692. else
  693. peerConnection->onGatheringStateChange(nullptr);
  694. return RTC_ERR_SUCCESS;
  695. });
  696. }
  697. int rtcSetSignalingStateChangeCallback(int pc, rtcSignalingStateCallbackFunc cb) {
  698. return wrap([&] {
  699. auto peerConnection = getPeerConnection(pc);
  700. if (cb)
  701. peerConnection->onSignalingStateChange([pc, cb](PeerConnection::SignalingState state) {
  702. if (auto ptr = getUserPointer(pc))
  703. cb(pc, static_cast<rtcSignalingState>(state), *ptr);
  704. });
  705. else
  706. peerConnection->onGatheringStateChange(nullptr);
  707. return RTC_ERR_SUCCESS;
  708. });
  709. }
  710. int rtcSetDataChannelCallback(int pc, rtcDataChannelCallbackFunc cb) {
  711. return wrap([&] {
  712. auto peerConnection = getPeerConnection(pc);
  713. if (cb)
  714. peerConnection->onDataChannel([pc, cb](shared_ptr<DataChannel> dataChannel) {
  715. int dc = emplaceDataChannel(dataChannel);
  716. if (auto ptr = getUserPointer(pc)) {
  717. rtcSetUserPointer(dc, *ptr);
  718. cb(pc, dc, *ptr);
  719. }
  720. });
  721. else
  722. peerConnection->onDataChannel(nullptr);
  723. return RTC_ERR_SUCCESS;
  724. });
  725. }
  726. int rtcSetTrackCallback(int pc, rtcTrackCallbackFunc cb) {
  727. return wrap([&] {
  728. auto peerConnection = getPeerConnection(pc);
  729. if (cb)
  730. peerConnection->onTrack([pc, cb](shared_ptr<Track> track) {
  731. int tr = emplaceTrack(track);
  732. if (auto ptr = getUserPointer(pc)) {
  733. rtcSetUserPointer(tr, *ptr);
  734. cb(pc, tr, *ptr);
  735. }
  736. });
  737. else
  738. peerConnection->onTrack(nullptr);
  739. return RTC_ERR_SUCCESS;
  740. });
  741. }
  742. int rtcSetLocalDescription(int pc, const char *type) {
  743. return wrap([&] {
  744. auto peerConnection = getPeerConnection(pc);
  745. peerConnection->setLocalDescription(type ? Description::stringToType(type)
  746. : Description::Type::Unspec);
  747. return RTC_ERR_SUCCESS;
  748. });
  749. }
  750. int rtcSetRemoteDescription(int pc, const char *sdp, const char *type) {
  751. return wrap([&] {
  752. auto peerConnection = getPeerConnection(pc);
  753. if (!sdp)
  754. throw std::invalid_argument("Unexpected null pointer for remote description");
  755. peerConnection->setRemoteDescription({string(sdp), type ? string(type) : ""});
  756. return RTC_ERR_SUCCESS;
  757. });
  758. }
  759. int rtcAddRemoteCandidate(int pc, const char *cand, const char *mid) {
  760. return wrap([&] {
  761. auto peerConnection = getPeerConnection(pc);
  762. if (!cand)
  763. throw std::invalid_argument("Unexpected null pointer for remote candidate");
  764. peerConnection->addRemoteCandidate({string(cand), mid ? string(mid) : ""});
  765. return RTC_ERR_SUCCESS;
  766. });
  767. }
  768. int rtcGetLocalDescription(int pc, char *buffer, int size) {
  769. return wrap([&] {
  770. auto peerConnection = getPeerConnection(pc);
  771. if (auto desc = peerConnection->localDescription())
  772. return copyAndReturn(string(*desc), buffer, size);
  773. else
  774. return RTC_ERR_NOT_AVAIL;
  775. });
  776. }
  777. int rtcGetRemoteDescription(int pc, char *buffer, int size) {
  778. return wrap([&] {
  779. auto peerConnection = getPeerConnection(pc);
  780. if (auto desc = peerConnection->remoteDescription())
  781. return copyAndReturn(string(*desc), buffer, size);
  782. else
  783. return RTC_ERR_NOT_AVAIL;
  784. });
  785. }
  786. int rtcGetLocalDescriptionType(int pc, char *buffer, int size) {
  787. return wrap([&] {
  788. auto peerConnection = getPeerConnection(pc);
  789. if (auto desc = peerConnection->localDescription())
  790. return copyAndReturn(desc->typeString(), buffer, size);
  791. else
  792. return RTC_ERR_NOT_AVAIL;
  793. });
  794. }
  795. int rtcGetRemoteDescriptionType(int pc, char *buffer, int size) {
  796. return wrap([&] {
  797. auto peerConnection = getPeerConnection(pc);
  798. if (auto desc = peerConnection->remoteDescription())
  799. return copyAndReturn(desc->typeString(), buffer, size);
  800. else
  801. return RTC_ERR_NOT_AVAIL;
  802. });
  803. }
  804. int rtcGetLocalAddress(int pc, char *buffer, int size) {
  805. return wrap([&] {
  806. auto peerConnection = getPeerConnection(pc);
  807. if (auto addr = peerConnection->localAddress())
  808. return copyAndReturn(std::move(*addr), buffer, size);
  809. else
  810. return RTC_ERR_NOT_AVAIL;
  811. });
  812. }
  813. int rtcGetRemoteAddress(int pc, char *buffer, int size) {
  814. return wrap([&] {
  815. auto peerConnection = getPeerConnection(pc);
  816. if (auto addr = peerConnection->remoteAddress())
  817. return copyAndReturn(std::move(*addr), buffer, size);
  818. else
  819. return RTC_ERR_NOT_AVAIL;
  820. });
  821. }
  822. int rtcGetSelectedCandidatePair(int pc, char *local, int localSize, char *remote, int remoteSize) {
  823. return wrap([&] {
  824. auto peerConnection = getPeerConnection(pc);
  825. Candidate localCand;
  826. Candidate remoteCand;
  827. if (!peerConnection->getSelectedCandidatePair(&localCand, &remoteCand))
  828. return RTC_ERR_NOT_AVAIL;
  829. int localRet = copyAndReturn(string(localCand), local, localSize);
  830. if (localRet < 0)
  831. return localRet;
  832. int remoteRet = copyAndReturn(string(remoteCand), remote, remoteSize);
  833. if (remoteRet < 0)
  834. return remoteRet;
  835. return std::max(localRet, remoteRet);
  836. });
  837. }
  838. int rtcGetDataChannelStream(int dc) {
  839. return wrap([dc] {
  840. auto dataChannel = getDataChannel(dc);
  841. return int(dataChannel->id());
  842. });
  843. }
  844. int rtcGetDataChannelLabel(int dc, char *buffer, int size) {
  845. return wrap([&] {
  846. auto dataChannel = getDataChannel(dc);
  847. return copyAndReturn(dataChannel->label(), buffer, size);
  848. });
  849. }
  850. int rtcGetDataChannelProtocol(int dc, char *buffer, int size) {
  851. return wrap([&] {
  852. auto dataChannel = getDataChannel(dc);
  853. return copyAndReturn(dataChannel->protocol(), buffer, size);
  854. });
  855. }
  856. int rtcGetDataChannelReliability(int dc, rtcReliability *reliability) {
  857. return wrap([&] {
  858. auto dataChannel = getDataChannel(dc);
  859. if (!reliability)
  860. throw std::invalid_argument("Unexpected null pointer for reliability");
  861. Reliability dcr = dataChannel->reliability();
  862. std::memset(reliability, 0, sizeof(*reliability));
  863. reliability->unordered = dcr.unordered;
  864. if (dcr.type == Reliability::Type::Timed) {
  865. reliability->unreliable = true;
  866. reliability->maxPacketLifeTime = int(std::get<milliseconds>(dcr.rexmit).count());
  867. } else if (dcr.type == Reliability::Type::Rexmit) {
  868. reliability->unreliable = true;
  869. reliability->maxRetransmits = std::get<int>(dcr.rexmit);
  870. } else {
  871. reliability->unreliable = false;
  872. }
  873. return RTC_ERR_SUCCESS;
  874. });
  875. }
  876. int rtcSetOpenCallback(int id, rtcOpenCallbackFunc cb) {
  877. return wrap([&] {
  878. auto channel = getChannel(id);
  879. if (cb)
  880. channel->onOpen([id, cb]() {
  881. if (auto ptr = getUserPointer(id))
  882. cb(id, *ptr);
  883. });
  884. else
  885. channel->onOpen(nullptr);
  886. return RTC_ERR_SUCCESS;
  887. });
  888. }
  889. int rtcSetClosedCallback(int id, rtcClosedCallbackFunc cb) {
  890. return wrap([&] {
  891. auto channel = getChannel(id);
  892. if (cb)
  893. channel->onClosed([id, cb]() {
  894. if (auto ptr = getUserPointer(id))
  895. cb(id, *ptr);
  896. });
  897. else
  898. channel->onClosed(nullptr);
  899. return RTC_ERR_SUCCESS;
  900. });
  901. }
  902. int rtcSetErrorCallback(int id, rtcErrorCallbackFunc cb) {
  903. return wrap([&] {
  904. auto channel = getChannel(id);
  905. if (cb)
  906. channel->onError([id, cb](string error) {
  907. if (auto ptr = getUserPointer(id))
  908. cb(id, error.c_str(), *ptr);
  909. });
  910. else
  911. channel->onError(nullptr);
  912. return RTC_ERR_SUCCESS;
  913. });
  914. }
  915. int rtcSetMessageCallback(int id, rtcMessageCallbackFunc cb) {
  916. return wrap([&] {
  917. auto channel = getChannel(id);
  918. if (cb)
  919. channel->onMessage(
  920. [id, cb](binary b) {
  921. if (auto ptr = getUserPointer(id))
  922. cb(id, reinterpret_cast<const char *>(b.data()), int(b.size()), *ptr);
  923. },
  924. [id, cb](string s) {
  925. if (auto ptr = getUserPointer(id))
  926. cb(id, s.c_str(), -int(s.size() + 1), *ptr);
  927. });
  928. else
  929. channel->onMessage(nullptr);
  930. return RTC_ERR_SUCCESS;
  931. });
  932. }
  933. int rtcSendMessage(int id, const char *data, int size) {
  934. return wrap([&] {
  935. auto channel = getChannel(id);
  936. if (!data && size != 0)
  937. throw std::invalid_argument("Unexpected null pointer for data");
  938. if (size >= 0) {
  939. auto b = reinterpret_cast<const byte *>(data);
  940. channel->send(binary(b, b + size));
  941. return size;
  942. } else {
  943. string str(data);
  944. int len = int(str.size());
  945. channel->send(std::move(str));
  946. return len;
  947. }
  948. });
  949. }
  950. int rtcGetBufferedAmount(int id) {
  951. return wrap([id] {
  952. auto channel = getChannel(id);
  953. return int(channel->bufferedAmount());
  954. });
  955. }
  956. int rtcSetBufferedAmountLowThreshold(int id, int amount) {
  957. return wrap([&] {
  958. auto channel = getChannel(id);
  959. channel->setBufferedAmountLowThreshold(size_t(amount));
  960. return RTC_ERR_SUCCESS;
  961. });
  962. }
  963. int rtcSetBufferedAmountLowCallback(int id, rtcBufferedAmountLowCallbackFunc cb) {
  964. return wrap([&] {
  965. auto channel = getChannel(id);
  966. if (cb)
  967. channel->onBufferedAmountLow([id, cb]() {
  968. if (auto ptr = getUserPointer(id))
  969. cb(id, *ptr);
  970. });
  971. else
  972. channel->onBufferedAmountLow(nullptr);
  973. return RTC_ERR_SUCCESS;
  974. });
  975. }
  976. int rtcGetAvailableAmount(int id) {
  977. return wrap([id] { return int(getChannel(id)->availableAmount()); });
  978. }
  979. int rtcSetAvailableCallback(int id, rtcAvailableCallbackFunc cb) {
  980. return wrap([&] {
  981. auto channel = getChannel(id);
  982. if (cb)
  983. channel->onAvailable([id, cb]() {
  984. if (auto ptr = getUserPointer(id))
  985. cb(id, *ptr);
  986. });
  987. else
  988. channel->onAvailable(nullptr);
  989. return RTC_ERR_SUCCESS;
  990. });
  991. }
  992. int rtcReceiveMessage(int id, char *buffer, int *size) {
  993. return wrap([&] {
  994. auto channel = getChannel(id);
  995. if (!size)
  996. throw std::invalid_argument("Unexpected null pointer for size");
  997. *size = std::abs(*size);
  998. auto message = channel->peek();
  999. if (!message)
  1000. return RTC_ERR_NOT_AVAIL;
  1001. return std::visit( //
  1002. overloaded{
  1003. [&](binary b) {
  1004. int ret = copyAndReturn(std::move(b), buffer, *size);
  1005. if (ret >= 0) {
  1006. channel->receive(); // discard
  1007. *size = ret;
  1008. return RTC_ERR_SUCCESS;
  1009. } else {
  1010. *size = int(b.size());
  1011. return ret;
  1012. }
  1013. },
  1014. [&](string s) {
  1015. int ret = copyAndReturn(std::move(s), buffer, *size);
  1016. if (ret >= 0) {
  1017. channel->receive(); // discard
  1018. *size = -ret;
  1019. return RTC_ERR_SUCCESS;
  1020. } else {
  1021. *size = -int(s.size() + 1);
  1022. return ret;
  1023. }
  1024. },
  1025. },
  1026. *message);
  1027. });
  1028. }
  1029. void rtcPreload() { rtc::Preload(); }
  1030. void rtcCleanup() { rtc::Cleanup(); }