blob: e4be7a220d5818a0f3858a5b6545e700dbfacc5b [file] [log] [blame]
James Kuszmaul4a42b182021-01-17 11:32:46 -08001#include "common.h"
2#include <rawrtc.h>
3#include <rawrtcc.h>
4#include <rawrtcdc.h>
5#include <re.h>
6#include <stdlib.h> // exit
7#include <string.h> // strerror
8
9#define DEBUG_MODULE "helper-common"
10#define DEBUG_LEVEL 7
11#include <re_dbg.h>
12
13/*
14 * Ignore success code list.
15 */
16enum rawrtc_code const ignore_success[] = {RAWRTC_CODE_SUCCESS};
17size_t const ignore_success_length = ARRAY_SIZE(ignore_success);
18
19/*
20 * Function to be called before exiting.
21 */
22void before_exit(void) {
23 // Close
24 rawrtc_close(true);
25
26 // Check memory leaks
27 tmr_debug();
28 mem_debug();
29}
30
31/*
32 * Exit on error code.
33 */
34void exit_on_error(
35 enum rawrtc_code const code,
36 enum rawrtc_code const ignore[],
37 size_t const n_ignore,
38 char const* const file,
39 uint32_t const line) {
40 size_t i;
41
42 // Ignore?
43 for (i = 0; i < n_ignore; ++i) {
44 if (code == ignore[i]) {
45 return;
46 }
47 }
48
49 // Handle
50 switch (code) {
51 case RAWRTC_CODE_SUCCESS:
52 return;
53 case RAWRTC_CODE_NOT_IMPLEMENTED:
54 DEBUG_WARNING("Not implemented in %s %" PRIu32 "\n", file, line);
55 return;
56 default:
57 DEBUG_WARNING(
58 "Error in %s %" PRIu32 " (%d): %s\n", file, line, code, rawrtc_code_to_str(code));
59 before_exit();
60 exit((int) code);
61 }
62}
63
64/*
65 * Exit on POSIX error code.
66 */
67void exit_on_posix_error(int code, char const* const file, uint32_t line) {
68 if (code != 0) {
69 DEBUG_WARNING("Error in %s %" PRIu32 " (%d): %s\n", file, line, code, strerror(code));
70 before_exit();
71 exit(code);
72 }
73}
74
75/*
76 * Exit with a custom error message.
77 */
78void exit_with_error(char const* const file, uint32_t line, char const* const formatter, ...) {
79 char* message;
80
81 // Format message
82 va_list ap;
83 va_start(ap, formatter);
84 re_vsdprintf(&message, formatter, ap);
85 va_end(ap);
86
87 // Print message
88 DEBUG_WARNING("%s %" PRIu32 ": %s\n", file, line, message);
89
90 // Un-reference & bye
91 mem_deref(message);
92 before_exit();
93 exit(1);
94}
95
96/*
97 * Check if the ICE candidate type is enabled.
98 */
99bool ice_candidate_type_enabled(
100 struct client* const client, enum rawrtc_ice_candidate_type const type) {
101 char const* const type_str = rawrtc_ice_candidate_type_to_str(type);
102 size_t i;
103
104 // All enabled?
105 if (client->n_ice_candidate_types == 0) {
106 return true;
107 }
108
109 // Specifically enabled?
110 for (i = 0; i < client->n_ice_candidate_types; ++i) {
111 if (str_cmp(client->ice_candidate_types[i], type_str) == 0) {
112 return true;
113 }
114 }
115
116 // Nope
117 return false;
118}
119
120/*
121 * Print ICE candidate information.
122 */
123void print_ice_candidate(
124 struct rawrtc_ice_candidate* const candidate,
125 char const* const url, // read-only
126 struct rawrtc_peer_connection_ice_candidate* const pc_candidate, // nullable
127 struct client* const client) {
128 if (candidate) {
129 enum rawrtc_code const ignore[] = {RAWRTC_CODE_NO_VALUE};
130 enum rawrtc_code error;
131 char* foundation;
132 enum rawrtc_ice_protocol protocol;
133 uint32_t priority;
134 char* ip;
135 uint16_t port;
136 enum rawrtc_ice_candidate_type type;
137 enum rawrtc_ice_tcp_candidate_type tcp_type;
138 char const* tcp_type_str = "n/a";
139 char* related_address = NULL;
140 uint16_t related_port = 0;
141 char* mid = NULL;
142 uint8_t media_line_index = UINT8_MAX;
143 char* media_line_index_str = NULL;
144 char* username_fragment = NULL;
145 bool is_enabled;
146 int level;
147
148 // Get candidate information
149 EOE(rawrtc_ice_candidate_get_foundation(&foundation, candidate));
150 EOE(rawrtc_ice_candidate_get_protocol(&protocol, candidate));
151 EOE(rawrtc_ice_candidate_get_priority(&priority, candidate));
152 EOE(rawrtc_ice_candidate_get_ip(&ip, candidate));
153 EOE(rawrtc_ice_candidate_get_port(&port, candidate));
154 EOE(rawrtc_ice_candidate_get_type(&type, candidate));
155 error = rawrtc_ice_candidate_get_tcp_type(&tcp_type, candidate);
156 switch (error) {
157 case RAWRTC_CODE_SUCCESS:
158 tcp_type_str = rawrtc_ice_tcp_candidate_type_to_str(tcp_type);
159 break;
160 case RAWRTC_CODE_NO_VALUE:
161 break;
162 default:
163 EOE(error);
164 break;
165 }
166 EOEIGN(rawrtc_ice_candidate_get_related_address(&related_address, candidate), ignore);
167 EOEIGN(rawrtc_ice_candidate_get_related_port(&related_port, candidate), ignore);
168 if (pc_candidate) {
169 EOEIGN(rawrtc_peer_connection_ice_candidate_get_sdp_mid(&mid, pc_candidate), ignore);
170 error = rawrtc_peer_connection_ice_candidate_get_sdp_media_line_index(
171 &media_line_index, pc_candidate);
172 switch (error) {
173 case RAWRTC_CODE_SUCCESS:
174 EOE(rawrtc_sdprintf(&media_line_index_str, "%" PRIu8, media_line_index));
175 break;
176 case RAWRTC_CODE_NO_VALUE:
177 break;
178 default:
179 EOE(error);
180 break;
181 }
182 EOEIGN(
183 rawrtc_peer_connection_ice_candidate_get_username_fragment(
184 &username_fragment, pc_candidate),
185 ignore);
186 }
187 is_enabled = ice_candidate_type_enabled(client, type);
188
189 // Print candidate (meh, lot's of repeated code... feel free to suggest an alternative)
190 level = is_enabled ? DBG_INFO : DBG_DEBUG;
191 if (!pc_candidate) {
192 dbg_printf(
193 level,
194 "(%s) ICE candidate: foundation=%s, protocol=%s"
195 ", priority=%" PRIu32 ", ip=%s, port=%" PRIu16 ", type=%s, tcp-type=%s"
196 ", related-address=%s, related-port=%" PRIu16 "; URL: %s; %s\n",
197 client->name, foundation, rawrtc_ice_protocol_to_str(protocol), priority, ip, port,
198 rawrtc_ice_candidate_type_to_str(type), tcp_type_str,
199 related_address ? related_address : "n/a", related_port, url ? url : "n/a",
200 is_enabled ? "enabled" : "disabled");
201 } else {
202 dbg_printf(
203 level,
204 "(%s) ICE candidate: foundation=%s, protocol=%s"
205 ", priority=%" PRIu32 ", ip=%s, port=%" PRIu16 ", type=%s, tcp-type=%s"
206 ", related-address=%s, related-port=%" PRIu16 "; URL: %s"
207 "; mid=%s, media_line_index=%s, username_fragment=%s; %s\n",
208 client->name, foundation, rawrtc_ice_protocol_to_str(protocol), priority, ip, port,
209 rawrtc_ice_candidate_type_to_str(type), tcp_type_str,
210 related_address ? related_address : "n/a", related_port, url ? url : "n/a",
211 mid ? mid : "n/a", media_line_index_str ? media_line_index_str : "n/a",
212 username_fragment ? username_fragment : "n/a", is_enabled ? "enabled" : "disabled");
213 }
214
215 // Unreference
216 mem_deref(username_fragment);
217 mem_deref(media_line_index_str);
218 mem_deref(mid);
219 mem_deref(related_address);
220 mem_deref(ip);
221 mem_deref(foundation);
222 } else {
223 DEBUG_INFO("(%s) ICE gatherer last local candidate\n", client->name);
224 }
225}