webrtc.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "webrtc.h"
  3. #include "../server/web_client.h"
  4. #include "../server/web_client_cache.h"
  5. #ifdef HAVE_LIBDATACHANNEL
  6. #include "rtc/rtc.h"
  7. #define WEBRTC_OUR_MAX_MESSAGE_SIZE (5 * 1024 * 1024)
  8. #define WEBRTC_DEFAULT_REMOTE_MAX_MESSAGE_SIZE (65536)
  9. #define WEBRTC_COMPRESSED_HEADER_SIZE 200
  10. static void webrtc_log(rtcLogLevel level, const char *message) {
  11. switch(level) {
  12. case RTC_LOG_NONE:
  13. break;
  14. case RTC_LOG_WARNING:
  15. case RTC_LOG_ERROR:
  16. case RTC_LOG_FATAL:
  17. netdata_log_error("WEBRTC: %s", message);
  18. break;
  19. case RTC_LOG_INFO:
  20. netdata_log_info("WEBRTC: %s", message);
  21. break;
  22. default:
  23. case RTC_LOG_DEBUG:
  24. case RTC_LOG_VERBOSE:
  25. internal_error(true, "WEBRTC: %s", message);
  26. break;
  27. }
  28. }
  29. typedef struct webrtc_datachannel {
  30. int dc;
  31. char *label;
  32. struct webrtc_connection *conn;
  33. bool open; // atomic
  34. struct {
  35. struct webrtc_datachannel *prev;
  36. struct webrtc_datachannel *next;
  37. } link;
  38. } WEBRTC_DC;
  39. typedef struct webrtc_connection {
  40. int pc;
  41. rtcConfiguration config;
  42. rtcState state;
  43. rtcGatheringState gathering_state;
  44. size_t max_message_size;
  45. size_t local_max_message_size;
  46. size_t remote_max_message_size;
  47. struct {
  48. SPINLOCK spinlock;
  49. BUFFER *wb;
  50. bool sdp;
  51. bool candidates;
  52. } response;
  53. struct {
  54. SPINLOCK spinlock;
  55. WEBRTC_DC *head;
  56. } channels;
  57. struct {
  58. struct webrtc_connection *prev;
  59. struct webrtc_connection *next;
  60. } link;
  61. } WEBRTC_CONN;
  62. #define WEBRTC_MAX_ICE_SERVERS 100
  63. static struct {
  64. bool enabled;
  65. char *iceServers[WEBRTC_MAX_ICE_SERVERS];
  66. int iceServersCount;
  67. char *proxyServer;
  68. char *bindAddress;
  69. struct {
  70. SPINLOCK spinlock;
  71. WEBRTC_CONN *head;
  72. } unsafe;
  73. } webrtc_base = {
  74. #ifdef NETDATA_INTERNAL_CHECKS
  75. .enabled = true,
  76. #else
  77. .enabled = false,
  78. #endif
  79. .iceServers = {
  80. // Format:
  81. // [("stun"|"turn"|"turns") (":"|"://")][username ":" password "@"]hostname[":" port]["?transport=" ("udp"|"tcp"|"tls")]
  82. //
  83. // Note transports TCP and TLS are only available for a TURN server with libnice as ICE backend and govern only the
  84. // TURN control connection, meaning relaying is always performed over UDP.
  85. //
  86. // If the username or password of a URI contains reserved special characters, they must be percent-encoded.
  87. // In particular, ":" must be encoded as "%3A" and "@" must by encoded as "%40".
  88. "stun://stun.l.google.com:19302",
  89. NULL, // terminator
  90. },
  91. .iceServersCount = 1,
  92. .proxyServer = NULL, // [("http"|"socks5") (":"|"://")][username ":" password "@"]hostname[" :" port]
  93. .bindAddress = NULL,
  94. .unsafe = {
  95. .spinlock = NETDATA_SPINLOCK_INITIALIZER,
  96. .head = NULL,
  97. },
  98. };
  99. static inline bool webrtc_dc_is_open(WEBRTC_DC *chan) {
  100. return __atomic_load_n(&chan->open, __ATOMIC_RELAXED);
  101. }
  102. static void webrtc_config_ice_servers(void) {
  103. BUFFER *wb = buffer_create(0, NULL);
  104. int i;
  105. for(i = 0; i < WEBRTC_MAX_ICE_SERVERS ;i++) {
  106. if (webrtc_base.iceServers[i]) {
  107. if (buffer_strlen(wb))
  108. buffer_strcat(wb, " ");
  109. internal_error(true, "WEBRTC: default ice server No %d is: '%s'", i, webrtc_base.iceServers[i]);
  110. buffer_strcat(wb, webrtc_base.iceServers[i]);
  111. }
  112. else
  113. break;
  114. }
  115. webrtc_base.iceServersCount = i;
  116. internal_error(true, "WEBRTC: there are %d default ice servers: '%s'", webrtc_base.iceServersCount, buffer_tostring(wb));
  117. char *servers = config_get(CONFIG_SECTION_WEBRTC, "ice servers", buffer_tostring(wb));
  118. webrtc_base.iceServersCount = 0;
  119. char *s = servers, *e;
  120. while(*s) {
  121. if(isspace(*s))
  122. s++;
  123. e = s;
  124. while(*e && !isspace(*e))
  125. e++;
  126. if(s != e && webrtc_base.iceServersCount < WEBRTC_MAX_ICE_SERVERS) {
  127. char old = *e;
  128. *e = '\0';
  129. internal_error(true, "WEBRTC: ice server No %d is: '%s'", webrtc_base.iceServersCount, s);
  130. webrtc_base.iceServers[webrtc_base.iceServersCount++] = strdupz(s);
  131. *e = old;
  132. }
  133. if(*e)
  134. s = e + 1;
  135. else
  136. break;
  137. }
  138. buffer_free(wb);
  139. }
  140. void webrtc_initialize() {
  141. webrtc_base.enabled = config_get_boolean(CONFIG_SECTION_WEBRTC, "enabled", webrtc_base.enabled);
  142. internal_error(true, "WEBRTC: is %s", webrtc_base.enabled ? "enabled" : "disabled");
  143. webrtc_config_ice_servers();
  144. webrtc_base.proxyServer = config_get(CONFIG_SECTION_WEBRTC, "proxy server", webrtc_base.proxyServer ? webrtc_base.proxyServer : "");
  145. if(!webrtc_base.proxyServer || !*webrtc_base.proxyServer)
  146. webrtc_base.proxyServer = NULL;
  147. internal_error(true, "WEBRTC: proxy server is: '%s'", webrtc_base.proxyServer ? webrtc_base.proxyServer : "");
  148. webrtc_base.bindAddress = config_get(CONFIG_SECTION_WEBRTC, "bind address", webrtc_base.bindAddress ? webrtc_base.bindAddress : "");
  149. if(!webrtc_base.bindAddress || !*webrtc_base.bindAddress)
  150. webrtc_base.bindAddress = NULL;
  151. internal_error(true, "WEBRTC: bind address is: '%s'", webrtc_base.bindAddress ? webrtc_base.bindAddress : "");
  152. if(!webrtc_base.enabled)
  153. return;
  154. rtcLogLevel level;
  155. #ifdef NETDATA_INTERNAL_CHECKS
  156. level = RTC_LOG_INFO;
  157. #else
  158. level = RTC_LOG_WARNING;
  159. #endif
  160. rtcInitLogger(level, webrtc_log);
  161. rtcPreload();
  162. }
  163. void webrtc_close_all_connections() {
  164. if(!webrtc_base.enabled)
  165. return;
  166. rtcCleanup();
  167. }
  168. size_t find_max_message_size_in_sdp(const char *sdp) {
  169. char *s = strstr(sdp, "a=max-message-size:");
  170. if(s)
  171. return str2ul(&s[19]);
  172. return WEBRTC_DEFAULT_REMOTE_MAX_MESSAGE_SIZE;
  173. }
  174. // ----------------------------------------------------------------------------
  175. // execute web API requests
  176. static bool web_client_stop_callback(struct web_client *w __maybe_unused, void *data) {
  177. WEBRTC_DC *chan = data;
  178. return !webrtc_dc_is_open(chan);
  179. }
  180. static size_t webrtc_send_in_chunks(WEBRTC_DC *chan, const char *data, size_t size, int code, const char *message_type, HTTP_CONTENT_TYPE content_type, size_t max_message_size, bool binary) {
  181. size_t sent_bytes = 0;
  182. size_t chunk = 0;
  183. size_t total_chunks = size / max_message_size;
  184. if(total_chunks * max_message_size < size)
  185. total_chunks++;
  186. char *send_buffer = mallocz(chan->conn->max_message_size);
  187. char *s = (char *)data;
  188. size_t remaining = size;
  189. while(remaining > 0) {
  190. chunk++;
  191. size_t message_size = MIN(remaining, max_message_size);
  192. int len = snprintfz(send_buffer, WEBRTC_COMPRESSED_HEADER_SIZE, "%d %s %zu %zu %zu %s\r\n",
  193. code,
  194. message_type,
  195. message_size,
  196. chunk,
  197. total_chunks,
  198. web_content_type_to_string(content_type)
  199. );
  200. internal_fatal((size_t)len != strlen(send_buffer), "WEBRTC compressed header line mismatch");
  201. internal_fatal(len + message_size > chan->conn->max_message_size, "WEBRTC message exceeds max message size");
  202. memcpy(&send_buffer[len], s, message_size);
  203. int total_message_size = (int)(len + message_size);
  204. sent_bytes += total_message_size;
  205. if(!binary)
  206. total_message_size = -total_message_size;
  207. if(rtcSendMessage(chan->dc, send_buffer, total_message_size) != RTC_ERR_SUCCESS)
  208. netdata_log_error("WEBRTC[%d],DC[%d]: failed to send LZ4 chunk %zu of %zu", chan->conn->pc, chan->dc, chunk, total_chunks);
  209. else
  210. internal_error(true, "WEBRTC[%d],DC[%d]: sent chunk %zu of %zu, size %zu (total %d)",
  211. chan->conn->pc, chan->dc, chunk, total_chunks, message_size, total_message_size);
  212. s = s + message_size;
  213. remaining -= message_size;
  214. }
  215. internal_fatal(chunk != total_chunks, "WEBRTC number of compressed chunks mismatch");
  216. freez(send_buffer);
  217. return sent_bytes;
  218. }
  219. static void webrtc_execute_api_request(WEBRTC_DC *chan, const char *request, size_t size __maybe_unused, bool binary __maybe_unused) {
  220. struct timeval tv;
  221. internal_error(true, "WEBRTC[%d],DC[%d]: got request '%s' of size %zu and type %s.",
  222. chan->conn->pc, chan->dc, request, size, binary?"binary":"text");
  223. struct web_client *w = web_client_get_from_cache();
  224. w->statistics.received_bytes = size;
  225. w->interrupt.callback = web_client_stop_callback;
  226. w->interrupt.callback_data = chan;
  227. w->acl = WEB_CLIENT_ACL_WEBRTC;
  228. char *path = (char *)request;
  229. if(strncmp(request, "POST ", 5) == 0) {
  230. w->mode = WEB_CLIENT_MODE_POST;
  231. path += 10;
  232. }
  233. else if(strncmp(request, "GET ", 4) == 0) {
  234. w->mode = WEB_CLIENT_MODE_GET;
  235. path += 4;
  236. }
  237. web_client_timeout_checkpoint_set(w, 0);
  238. web_client_decode_path_and_query_string(w, path);
  239. path = (char *)buffer_tostring(w->url_path_decoded);
  240. w->response.code = (short)web_client_api_request_with_node_selection(localhost, w, path);
  241. web_client_timeout_checkpoint_response_ready(w, NULL);
  242. size_t sent_bytes = 0;
  243. size_t response_size = buffer_strlen(w->response.data);
  244. bool send_plain = true;
  245. int max_message_size = (int)chan->conn->max_message_size - WEBRTC_COMPRESSED_HEADER_SIZE;
  246. if(!webrtc_dc_is_open(chan)) {
  247. internal_error(true, "WEBRTC[%d],DC[%d]: ignoring API response on closed data channel.", chan->conn->pc, chan->dc);
  248. goto cleanup;
  249. }
  250. else {
  251. internal_error(true, "WEBRTC[%d],DC[%d]: prepared response with code %d, size %zu.",
  252. chan->conn->pc, chan->dc, w->response.code, response_size);
  253. }
  254. #if defined(ENABLE_LZ4)
  255. int max_compressed_size = LZ4_compressBound((int)response_size);
  256. char *compressed = mallocz(max_compressed_size);
  257. int compressed_size = LZ4_compress_default(buffer_tostring(w->response.data), compressed,
  258. (int)response_size, max_compressed_size);
  259. if(compressed_size > 0) {
  260. send_plain = false;
  261. sent_bytes = webrtc_send_in_chunks(chan, compressed, compressed_size,
  262. w->response.code, "LZ4", w->response.data->content_type,
  263. max_message_size, true);
  264. }
  265. freez(compressed);
  266. #endif
  267. if(send_plain)
  268. sent_bytes = webrtc_send_in_chunks(chan, buffer_tostring(w->response.data), buffer_strlen(w->response.data),
  269. w->response.code, "PLAIN", w->response.data->content_type,
  270. max_message_size, false);
  271. w->statistics.sent_bytes = sent_bytes;
  272. cleanup:
  273. now_monotonic_high_precision_timeval(&tv);
  274. netdata_log_access("%llu: %d '[RTC]:%d:%d' '%s' (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %d '%s'",
  275. w->id
  276. , gettid()
  277. , chan->conn->pc, chan->dc
  278. , "DATA"
  279. , sent_bytes
  280. , response_size
  281. , response_size > sent_bytes ? -(((double)(response_size - sent_bytes) / (double)response_size) * 100.0) : ((response_size > 0) ? (((sent_bytes - response_size) / (double)response_size) * 100.0) : 0.0)
  282. , dt_usec(&w->timings.tv_ready, &w->timings.tv_in) / 1000.0
  283. , dt_usec(&tv, &w->timings.tv_ready) / 1000.0
  284. , dt_usec(&tv, &w->timings.tv_in) / 1000.0
  285. , w->response.code
  286. , strip_control_characters((char *)buffer_tostring(w->url_as_received))
  287. );
  288. web_client_release_to_cache(w);
  289. }
  290. // ----------------------------------------------------------------------------
  291. // webrtc data channel
  292. static void myOpenCallback(int id __maybe_unused, void *user_ptr) {
  293. webrtc_set_thread_name();
  294. WEBRTC_DC *chan = user_ptr;
  295. internal_fatal(chan->dc != id, "WEBRTC[%d],DC[%d]: dc mismatch, expected %d, got %d", chan->conn->pc, chan->dc, chan->dc, id);
  296. netdata_log_access("WEBRTC[%d],DC[%d]: %d DATA CHANNEL '%s' OPEN", chan->conn->pc, chan->dc, gettid(), chan->label);
  297. internal_error(true, "WEBRTC[%d],DC[%d]: data channel opened.", chan->conn->pc, chan->dc);
  298. chan->open = true;
  299. }
  300. static void myClosedCallback(int id __maybe_unused, void *user_ptr) {
  301. webrtc_set_thread_name();
  302. WEBRTC_DC *chan = user_ptr;
  303. internal_fatal(chan->dc != id, "WEBRTC[%d],DC[%d]: dc mismatch, expected %d, got %d", chan->conn->pc, chan->dc, chan->dc, id);
  304. __atomic_store_n(&chan->open, false, __ATOMIC_RELAXED);
  305. internal_error(true, "WEBRTC[%d],DC[%d]: data channel closed.", chan->conn->pc, chan->dc);
  306. spinlock_lock(&chan->conn->channels.spinlock);
  307. DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(chan->conn->channels.head, chan, link.prev, link.next);
  308. spinlock_unlock(&chan->conn->channels.spinlock);
  309. netdata_log_access("WEBRTC[%d],DC[%d]: %d DATA CHANNEL '%s' CLOSED", chan->conn->pc, chan->dc, gettid(), chan->label);
  310. freez(chan->label);
  311. freez(chan);
  312. }
  313. static void myErrorCallback(int id __maybe_unused, const char *error, void *user_ptr) {
  314. webrtc_set_thread_name();
  315. WEBRTC_DC *chan = user_ptr;
  316. internal_fatal(chan->dc != id, "WEBRTC[%d],DC[%d]: dc mismatch, expected %d, got %d", chan->conn->pc, chan->dc, chan->dc, id);
  317. netdata_log_error("WEBRTC[%d],DC[%d]: ERROR: '%s'", chan->conn->pc, chan->dc, error);
  318. }
  319. static void myMessageCallback(int id __maybe_unused, const char *message, int size, void *user_ptr) {
  320. webrtc_set_thread_name();
  321. WEBRTC_DC *chan = user_ptr;
  322. internal_fatal(chan->dc != id, "WEBRTC[%d],DC[%d]: dc mismatch, expected %d, got %d", chan->conn->pc, chan->dc, chan->dc, id);
  323. internal_fatal(!webrtc_dc_is_open(chan), "WEBRTC[%d],DC[%d]: received message on closed channel", chan->conn->pc, chan->dc);
  324. bool binary = (size >= 0);
  325. if(size < 0)
  326. size = -size;
  327. webrtc_execute_api_request(chan, message, size, binary);
  328. }
  329. //#define WEBRTC_MAX_REQUEST_SIZE 65536
  330. //
  331. //static void myAvailableCallback(int id, void *user_ptr) {
  332. // webrtc_set_thread_name();
  333. //
  334. // WEBRTC_DC *chan = user_ptr;
  335. // internal_fatal(chan->dc != id, "WEBRTC[%d],DC[%d]: dc mismatch, expected %d, got %d", chan->conn->pc, chan->dc, chan->dc, id);
  336. //
  337. // internal_fatal(!chan->open, "WEBRTC[%d],DC[%d]: received message on closed channel", chan->conn->pc, chan->dc);
  338. //
  339. // int size = WEBRTC_MAX_REQUEST_SIZE;
  340. // char buffer[WEBRTC_MAX_REQUEST_SIZE];
  341. // while(rtcReceiveMessage(id, buffer, &size) == RTC_ERR_SUCCESS) {
  342. // bool binary = (size >= 0);
  343. // if(size < 0)
  344. // size = -size;
  345. //
  346. // webrtc_execute_api_request(chan, message, size, binary);
  347. // }
  348. //}
  349. static void myDataChannelCallback(int pc __maybe_unused, int dc, void *user_ptr) {
  350. webrtc_set_thread_name();
  351. WEBRTC_CONN *conn = user_ptr;
  352. internal_fatal(conn->pc != pc, "WEBRTC[%d]: pc mismatch, expected %d, got %d", conn->pc, conn->pc, pc);
  353. WEBRTC_DC *chan = callocz(1, sizeof(WEBRTC_DC));
  354. chan->dc = dc;
  355. chan->conn = conn;
  356. spinlock_lock(&conn->channels.spinlock);
  357. DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(conn->channels.head, chan, link.prev, link.next);
  358. spinlock_unlock(&conn->channels.spinlock);
  359. rtcSetUserPointer(dc, chan);
  360. char label[1024 + 1];
  361. rtcGetDataChannelLabel(dc, label, 1024);
  362. label[1024] = '\0';
  363. chan->label = strdupz(label);
  364. if(rtcSetOpenCallback(dc, myOpenCallback) != RTC_ERR_SUCCESS)
  365. netdata_log_error("WEBRTC[%d],DC[%d]: rtcSetOpenCallback() failed.", conn->pc, chan->dc);
  366. if(rtcSetClosedCallback(dc, myClosedCallback) != RTC_ERR_SUCCESS)
  367. netdata_log_error("WEBRTC[%d],DC[%d]: rtcSetClosedCallback() failed.", conn->pc, chan->dc);
  368. if(rtcSetErrorCallback(dc, myErrorCallback) != RTC_ERR_SUCCESS)
  369. netdata_log_error("WEBRTC[%d],DC[%d]: rtcSetErrorCallback() failed.", conn->pc, chan->dc);
  370. if(rtcSetMessageCallback(dc, myMessageCallback) != RTC_ERR_SUCCESS)
  371. netdata_log_error("WEBRTC[%d],DC[%d]: rtcSetMessageCallback() failed.", conn->pc, chan->dc);
  372. // if(rtcSetAvailableCallback(dc, myAvailableCallback) != RTC_ERR_SUCCESS)
  373. // netdata_log_error("WEBRTC[%d],DC[%d]: rtcSetAvailableCallback() failed.", conn->pc, chan->dc);
  374. internal_error(true, "WEBRTC[%d],DC[%d]: new data channel with label '%s'", chan->conn->pc, chan->dc, chan->label);
  375. }
  376. // ----------------------------------------------------------------------------
  377. // webrtc connection
  378. static inline void webrtc_destroy_connection_unsafe(WEBRTC_CONN *conn) {
  379. if(conn->state == RTC_CLOSED) {
  380. spinlock_lock(&conn->channels.spinlock);
  381. WEBRTC_DC *chan = conn->channels.head;
  382. spinlock_unlock(&conn->channels.spinlock);
  383. if(!chan) {
  384. internal_error(true, "WEBRTC[%d]: destroying connection", conn->pc);
  385. DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(webrtc_base.unsafe.head, conn, link.prev, link.next);
  386. freez(conn);
  387. }
  388. else {
  389. internal_error(true, "WEBRTC[%d]: not destroying closed connection because it has data channels running", conn->pc);
  390. }
  391. }
  392. }
  393. static void cleanupConnections() {
  394. spinlock_lock(&webrtc_base.unsafe.spinlock);
  395. WEBRTC_CONN *conn = webrtc_base.unsafe.head;
  396. while(conn) {
  397. WEBRTC_CONN *conn_next = conn->link.next;
  398. webrtc_destroy_connection_unsafe(conn);
  399. conn = conn_next;
  400. }
  401. spinlock_unlock(&webrtc_base.unsafe.spinlock);
  402. }
  403. static WEBRTC_CONN *webrtc_create_connection(void) {
  404. WEBRTC_CONN *conn = callocz(1, sizeof(WEBRTC_CONN));
  405. spinlock_init(&conn->response.spinlock);
  406. spinlock_init(&conn->channels.spinlock);
  407. spinlock_lock(&webrtc_base.unsafe.spinlock);
  408. DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(webrtc_base.unsafe.head, conn, link.prev, link.next);
  409. spinlock_unlock(&webrtc_base.unsafe.spinlock);
  410. return conn;
  411. }
  412. static void myDescriptionCallback(int pc __maybe_unused, const char *sdp, const char *type, void *user_ptr) {
  413. webrtc_set_thread_name();
  414. WEBRTC_CONN *conn = user_ptr;
  415. internal_fatal(conn->pc != pc, "WEBRTC[%d]: pc mismatch, expected %d, got %d", conn->pc, conn->pc, pc);
  416. internal_error(true, "WEBRTC[%d]: local description type '%s': %s", conn->pc, type, sdp);
  417. spinlock_lock(&conn->response.spinlock);
  418. if(!conn->response.candidates) {
  419. buffer_json_member_add_string(conn->response.wb, "sdp", sdp);
  420. buffer_json_member_add_string(conn->response.wb, "type", type);
  421. conn->response.sdp = true;
  422. }
  423. spinlock_unlock(&conn->response.spinlock);
  424. conn->local_max_message_size = find_max_message_size_in_sdp(sdp);
  425. }
  426. static void myCandidateCallback(int pc __maybe_unused, const char *cand, const char *mid __maybe_unused, void *user_ptr) {
  427. webrtc_set_thread_name();
  428. WEBRTC_CONN *conn = user_ptr;
  429. internal_fatal(conn->pc != pc, "WEBRTC[%d]: pc mismatch, expected %d, got %d", conn->pc, conn->pc, pc);
  430. spinlock_lock(&conn->response.spinlock);
  431. if(!conn->response.candidates) {
  432. buffer_json_member_add_array(conn->response.wb, "candidates");
  433. conn->response.candidates = true;
  434. }
  435. internal_error(true, "WEBRTC[%d]: local candidate '%s', mid '%s'", conn->pc, cand, mid);
  436. buffer_json_add_array_item_string(conn->response.wb, cand);
  437. spinlock_unlock(&conn->response.spinlock);
  438. }
  439. static void myStateChangeCallback(int pc __maybe_unused, rtcState state, void *user_ptr) {
  440. webrtc_set_thread_name();
  441. WEBRTC_CONN *conn = user_ptr;
  442. internal_fatal(conn->pc != pc, "WEBRTC[%d]: pc mismatch, expected %d, got %d", conn->pc, conn->pc, pc);
  443. conn->state = state;
  444. switch(state) {
  445. case RTC_NEW:
  446. internal_error(true, "WEBRTC[%d]: new connection...", conn->pc);
  447. break;
  448. case RTC_CONNECTING:
  449. netdata_log_access("WEBRTC[%d]: %d CONNECTING", conn->pc, gettid());
  450. internal_error(true, "WEBRTC[%d]: connecting...", conn->pc);
  451. break;
  452. case RTC_CONNECTED:
  453. netdata_log_access("WEBRTC[%d]: %d CONNECTED", conn->pc, gettid());
  454. internal_error(true, "WEBRTC[%d]: connected!", conn->pc);
  455. break;
  456. case RTC_DISCONNECTED:
  457. netdata_log_access("WEBRTC[%d]: %d DISCONNECTED", conn->pc, gettid());
  458. internal_error(true, "WEBRTC[%d]: disconnected.", conn->pc);
  459. break;
  460. case RTC_FAILED:
  461. netdata_log_access("WEBRTC[%d]: %d CONNECTION FAILED", conn->pc, gettid());
  462. internal_error(true, "WEBRTC[%d]: failed.", conn->pc);
  463. break;
  464. case RTC_CLOSED:
  465. netdata_log_access("WEBRTC[%d]: %d CONNECTION CLOSED", conn->pc, gettid());
  466. internal_error(true, "WEBRTC[%d]: closed.", conn->pc);
  467. spinlock_lock(&webrtc_base.unsafe.spinlock);
  468. webrtc_destroy_connection_unsafe(conn);
  469. spinlock_unlock(&webrtc_base.unsafe.spinlock);
  470. break;
  471. }
  472. }
  473. static void myGatheringStateCallback(int pc __maybe_unused, rtcGatheringState state, void *user_ptr) {
  474. webrtc_set_thread_name();
  475. WEBRTC_CONN *conn = user_ptr;
  476. internal_fatal(conn->pc != pc, "WEBRTC[%d]: pc mismatch, expected %d, got %d", conn->pc, conn->pc, pc);
  477. conn->gathering_state = state;
  478. switch(state) {
  479. case RTC_GATHERING_NEW:
  480. internal_error(true, "WEBRTC[%d]: gathering...", conn->pc);
  481. break;
  482. case RTC_GATHERING_INPROGRESS:
  483. internal_error(true, "WEBRTC[%d]: gathering in progress...", conn->pc);
  484. break;
  485. case RTC_GATHERING_COMPLETE:
  486. internal_error(true, "WEBRTC[%d]: gathering complete!", conn->pc);
  487. break;
  488. }
  489. }
  490. int webrtc_new_connection(const char *sdp, BUFFER *wb) {
  491. if(unlikely(!webrtc_base.enabled)) {
  492. buffer_flush(wb);
  493. buffer_strcat(wb, "WebRTC is not enabled on this agent.");
  494. wb->content_type = CT_TEXT_PLAIN;
  495. return HTTP_RESP_BAD_REQUEST;
  496. }
  497. cleanupConnections();
  498. if(unlikely(!sdp || !*sdp)) {
  499. buffer_flush(wb);
  500. buffer_strcat(wb, "No SDP message posted with the request");
  501. wb->content_type = CT_TEXT_PLAIN;
  502. return HTTP_RESP_BAD_REQUEST;
  503. }
  504. buffer_flush(wb);
  505. buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_DEFAULT);
  506. wb->content_type = CT_APPLICATION_JSON;
  507. WEBRTC_CONN *conn = webrtc_create_connection();
  508. conn->response.wb = wb;
  509. conn->max_message_size = WEBRTC_DEFAULT_REMOTE_MAX_MESSAGE_SIZE;
  510. conn->local_max_message_size = WEBRTC_OUR_MAX_MESSAGE_SIZE;
  511. conn->remote_max_message_size = find_max_message_size_in_sdp(sdp);
  512. conn->config.iceServers = (const char **)webrtc_base.iceServers;
  513. conn->config.iceServersCount = webrtc_base.iceServersCount;
  514. conn->config.proxyServer = webrtc_base.proxyServer;
  515. conn->config.bindAddress = webrtc_base.bindAddress;
  516. conn->config.certificateType = RTC_CERTIFICATE_DEFAULT;
  517. conn->config.iceTransportPolicy = RTC_TRANSPORT_POLICY_ALL;
  518. conn->config.enableIceTcp = true; // libnice only
  519. conn->config.enableIceUdpMux = true; // libjuice only
  520. conn->config.disableAutoNegotiation = false;
  521. conn->config.forceMediaTransport = false;
  522. conn->config.portRangeBegin = 0; // 0 means automatic
  523. conn->config.portRangeEnd = 0; // 0 means automatic
  524. conn->config.mtu = 0; // <= 0 means automatic
  525. conn->config.maxMessageSize = WEBRTC_OUR_MAX_MESSAGE_SIZE; // <= 0 means default
  526. conn->pc = rtcCreatePeerConnection(&conn->config);
  527. rtcSetUserPointer(conn->pc, conn);
  528. if(rtcSetLocalDescriptionCallback(conn->pc, myDescriptionCallback) != RTC_ERR_SUCCESS)
  529. netdata_log_error("WEBRTC[%d]: rtcSetLocalDescriptionCallback() failed", conn->pc);
  530. if(rtcSetLocalCandidateCallback(conn->pc, myCandidateCallback) != RTC_ERR_SUCCESS)
  531. netdata_log_error("WEBRTC[%d]: rtcSetLocalCandidateCallback() failed", conn->pc);
  532. if(rtcSetStateChangeCallback(conn->pc, myStateChangeCallback) != RTC_ERR_SUCCESS)
  533. netdata_log_error("WEBRTC[%d]: rtcSetStateChangeCallback() failed", conn->pc);
  534. if(rtcSetGatheringStateChangeCallback(conn->pc, myGatheringStateCallback) != RTC_ERR_SUCCESS)
  535. netdata_log_error("WEBRTC[%d]: rtcSetGatheringStateChangeCallback() failed", conn->pc);
  536. if(rtcSetDataChannelCallback(conn->pc, myDataChannelCallback) != RTC_ERR_SUCCESS)
  537. netdata_log_error("WEBRTC[%d]: rtcSetDataChannelCallback() failed", conn->pc);
  538. // initialize the handshake
  539. internal_error(true, "WEBRTC[%d]: setting remote sdp: %s", conn->pc, sdp);
  540. if(rtcSetRemoteDescription(conn->pc, sdp, "offer") != RTC_ERR_SUCCESS)
  541. netdata_log_error("WEBRTC[%d]: rtcSetRemoteDescription() failed", conn->pc);
  542. // initiate the handshake process
  543. if(conn->config.disableAutoNegotiation) {
  544. if(rtcSetLocalDescription(conn->pc, NULL) != RTC_ERR_SUCCESS)
  545. netdata_log_error("WEBRTC[%d]: rtcSetLocalDescription() failed", conn->pc);
  546. }
  547. bool logged = false;
  548. while(conn->gathering_state != RTC_GATHERING_COMPLETE) {
  549. if(!logged) {
  550. logged = true;
  551. internal_error(true, "WEBRTC[%d]: Waiting for gathering to complete", conn->pc);
  552. }
  553. usleep(1000);
  554. }
  555. if(logged)
  556. internal_error(true, "WEBRTC[%d]: Gathering finished, our answer is ready", conn->pc);
  557. internal_fatal(!conn->response.sdp, "WEBRTC[%d]: response does not have an SDP: %s", conn->pc, buffer_tostring(conn->response.wb));
  558. internal_fatal(!conn->response.candidates, "WEBRTC[%d]: response does not have candidates: %s", conn->pc, buffer_tostring(conn->response.wb));
  559. conn->max_message_size = MIN(conn->local_max_message_size, conn->remote_max_message_size);
  560. if(conn->max_message_size < WEBRTC_COMPRESSED_HEADER_SIZE)
  561. conn->max_message_size = WEBRTC_COMPRESSED_HEADER_SIZE;
  562. buffer_json_finalize(wb);
  563. return HTTP_RESP_OK;
  564. }
  565. #else // ! HAVE_LIBDATACHANNEL
  566. void webrtc_initialize() {
  567. ;
  568. }
  569. int webrtc_new_connection(const char *sdp __maybe_unused, BUFFER *wb) {
  570. buffer_flush(wb);
  571. buffer_strcat(wb, "WEBRTC is not available on this server");
  572. wb->content_type = CT_TEXT_PLAIN;
  573. return HTTP_RESP_BAD_REQUEST;
  574. }
  575. void webrtc_close_all_connections() {
  576. ;
  577. }
  578. #endif // ! HAVE_LIBDATACHANNEL