Add SSL error handling and user notification dialog
- Implemented a new function `ssl_error_dialog_show` to display SSL connection errors to users in both English and German. - Integrated SSL error handling in API calls and webhook functionality, ensuring users are informed of potential connection issues. - Updated relevant files to include the new error handling logic and dialog display.
This commit is contained in:
@@ -431,3 +431,36 @@ extern "C" void forced_update_show(const char *new_version, const char *locale)
|
|||||||
obf_dash_downloads_path());
|
obf_dash_downloads_path());
|
||||||
open_url(url);
|
open_url(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void ssl_error_dialog_show(const char *detail, const char *locale)
|
||||||
|
{
|
||||||
|
bool is_de = locale && (strncmp(locale, "de", 2) == 0);
|
||||||
|
|
||||||
|
QWidget *parent = (QWidget *)obs_frontend_get_main_window();
|
||||||
|
|
||||||
|
QString title = is_de ? "Verbindungsfehler"
|
||||||
|
: "Connection Error";
|
||||||
|
|
||||||
|
QString text = is_de
|
||||||
|
? QString::fromUtf8(
|
||||||
|
"Easy IRL Stream konnte keine sichere Verbindung "
|
||||||
|
"zu stools.cc herstellen.\n\n"
|
||||||
|
"M\xc3\xb6""gliche Ursachen:\n"
|
||||||
|
"\xe2\x80\xa2 Antivirus-Software blockiert die Verbindung "
|
||||||
|
"(HTTPS-Scanning / SSL-Inspektion deaktivieren)\n"
|
||||||
|
"\xe2\x80\xa2 Firewall oder Proxy blockiert stools.cc\n"
|
||||||
|
"\xe2\x80\xa2 VPN-Verbindung aktiv\n\n"
|
||||||
|
"Fehler: %1")
|
||||||
|
.arg(detail && detail[0] ? detail : "SSL connect error")
|
||||||
|
: QString("Easy IRL Stream could not establish a secure "
|
||||||
|
"connection to stools.cc.\n\n"
|
||||||
|
"Possible causes:\n"
|
||||||
|
"\xe2\x80\xa2 Antivirus software blocking the connection "
|
||||||
|
"(disable HTTPS scanning / SSL inspection)\n"
|
||||||
|
"\xe2\x80\xa2 Firewall or proxy blocking stools.cc\n"
|
||||||
|
"\xe2\x80\xa2 VPN connection active\n\n"
|
||||||
|
"Error: %1")
|
||||||
|
.arg(detail && detail[0] ? detail : "SSL connect error");
|
||||||
|
|
||||||
|
QMessageBox::warning(parent, title, text, QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ void help_dialog_show(const char *local_ip, const char *external_ip,
|
|||||||
|
|
||||||
void update_dialog_show(const char *new_version, const char *locale);
|
void update_dialog_show(const char *new_version, const char *locale);
|
||||||
void forced_update_show(const char *new_version, const char *locale);
|
void forced_update_show(const char *new_version, const char *locale);
|
||||||
|
void ssl_error_dialog_show(const char *detail, const char *locale);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -313,21 +313,30 @@ static bool check_update_blocking(void)
|
|||||||
if (!curl) return false;
|
if (!curl) return false;
|
||||||
|
|
||||||
struct update_mem_buf buf = {NULL, 0};
|
struct update_mem_buf buf = {NULL, 0};
|
||||||
|
char errbuf[CURL_ERROR_SIZE] = "";
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, update_write_cb);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, update_write_cb);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
|
||||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
||||||
#ifdef CURLSSLOPT_NATIVE_CA
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NATIVE_CA);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
#endif
|
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
|
|
||||||
CURLcode res = curl_easy_perform(curl);
|
CURLcode res = curl_easy_perform(curl);
|
||||||
long http_code = 0;
|
long http_code = 0;
|
||||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
blog(LOG_WARNING, "[%s] Update check failed: %s (%s)",
|
||||||
|
PLUGIN_NAME, curl_easy_strerror(res),
|
||||||
|
errbuf[0] ? errbuf : "no details");
|
||||||
|
}
|
||||||
|
|
||||||
if (res != CURLE_OK || http_code != 200 || !buf.data) {
|
if (res != CURLE_OK || http_code != 200 || !buf.data) {
|
||||||
free(buf.data);
|
free(buf.data);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+50
-10
@@ -14,6 +14,37 @@
|
|||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
#include "help-dialog.hpp"
|
||||||
|
|
||||||
|
/* ---- SSL error dialog (shown once per session) ---- */
|
||||||
|
|
||||||
|
static volatile bool g_ssl_error_shown = false;
|
||||||
|
|
||||||
|
struct ssl_error_ctx {
|
||||||
|
char detail[CURL_ERROR_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void task_show_ssl_error(void *param)
|
||||||
|
{
|
||||||
|
struct ssl_error_ctx *ctx = param;
|
||||||
|
ssl_error_dialog_show(ctx->detail, obs_get_locale());
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void maybe_show_ssl_error(CURLcode res, const char *errbuf)
|
||||||
|
{
|
||||||
|
if (res != CURLE_SSL_CONNECT_ERROR || g_ssl_error_shown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_ssl_error_shown = true;
|
||||||
|
struct ssl_error_ctx *ctx = malloc(sizeof(*ctx));
|
||||||
|
if (ctx) {
|
||||||
|
snprintf(ctx->detail, sizeof(ctx->detail), "%s",
|
||||||
|
errbuf && errbuf[0] ? errbuf : "SSL connect error");
|
||||||
|
obs_queue_task(OBS_TASK_UI, task_show_ssl_error, ctx, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- cURL helpers ---- */
|
/* ---- cURL helpers ---- */
|
||||||
|
|
||||||
struct mem_buf {
|
struct mem_buf {
|
||||||
@@ -53,6 +84,7 @@ static char *api_get(const char *path, const char *token)
|
|||||||
snprintf(ua, sizeof(ua), "%s%s", obf_ua_prefix(), PLUGIN_VERSION);
|
snprintf(ua, sizeof(ua), "%s%s", obf_ua_prefix(), PLUGIN_VERSION);
|
||||||
|
|
||||||
struct mem_buf buf = {NULL, 0};
|
struct mem_buf buf = {NULL, 0};
|
||||||
|
char errbuf[CURL_ERROR_SIZE] = "";
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
@@ -60,9 +92,10 @@ static char *api_get(const char *path, const char *token)
|
|||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buf);
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
||||||
#ifdef CURLSSLOPT_NATIVE_CA
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NATIVE_CA);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
#endif
|
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
|
|
||||||
CURLcode res = curl_easy_perform(curl);
|
CURLcode res = curl_easy_perform(curl);
|
||||||
long http_code = 0;
|
long http_code = 0;
|
||||||
@@ -71,8 +104,10 @@ static char *api_get(const char *path, const char *token)
|
|||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
blog(LOG_WARNING, "[%s] API GET %s failed: %s",
|
blog(LOG_WARNING, "[%s] API GET %s failed: %s (%s)",
|
||||||
PLUGIN_NAME, path, curl_easy_strerror(res));
|
PLUGIN_NAME, path, curl_easy_strerror(res),
|
||||||
|
errbuf[0] ? errbuf : "no details");
|
||||||
|
maybe_show_ssl_error(res, errbuf);
|
||||||
free(buf.data);
|
free(buf.data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -105,14 +140,17 @@ static bool api_post(const char *path, const char *token, const char *json_body)
|
|||||||
char ua[128];
|
char ua[128];
|
||||||
snprintf(ua, sizeof(ua), "%s%s", obf_ua_prefix(), PLUGIN_VERSION);
|
snprintf(ua, sizeof(ua), "%s%s", obf_ua_prefix(), PLUGIN_VERSION);
|
||||||
|
|
||||||
|
char errbuf[CURL_ERROR_SIZE] = "";
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_body);
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_body);
|
||||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, ua);
|
||||||
#ifdef CURLSSLOPT_NATIVE_CA
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NATIVE_CA);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
#endif
|
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
|
|
||||||
CURLcode res = curl_easy_perform(curl);
|
CURLcode res = curl_easy_perform(curl);
|
||||||
long http_code = 0;
|
long http_code = 0;
|
||||||
@@ -121,8 +159,10 @@ static bool api_post(const char *path, const char *token, const char *json_body)
|
|||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
blog(LOG_WARNING, "[%s] API POST %s failed: %s",
|
blog(LOG_WARNING, "[%s] API POST %s failed: %s (%s)",
|
||||||
PLUGIN_NAME, path, curl_easy_strerror(res));
|
PLUGIN_NAME, path, curl_easy_strerror(res),
|
||||||
|
errbuf[0] ? errbuf : "no details");
|
||||||
|
maybe_show_ssl_error(res, errbuf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (http_code != 200) {
|
if (http_code != 200) {
|
||||||
|
|||||||
+9
-5
@@ -37,6 +37,8 @@ static void webhook_do_send(const char *url, const char *json_body)
|
|||||||
struct curl_slist *headers = NULL;
|
struct curl_slist *headers = NULL;
|
||||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||||
|
|
||||||
|
char errbuf[CURL_ERROR_SIZE] = "";
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_body);
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_body);
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
@@ -44,14 +46,16 @@ static void webhook_do_send(const char *url, const char *json_body)
|
|||||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
|
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, discard_response);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, discard_response);
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "easy-irl-stream-webhook/1.0");
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "easy-irl-stream-webhook/1.0");
|
||||||
#ifdef CURLSSLOPT_NATIVE_CA
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_NATIVE_CA);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
#endif
|
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
|
|
||||||
CURLcode res = curl_easy_perform(curl);
|
CURLcode res = curl_easy_perform(curl);
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
blog(LOG_WARNING, "[%s] Webhook failed (%s): %s",
|
blog(LOG_WARNING, "[%s] Webhook failed (%s): %s (%s)",
|
||||||
"Easy IRL Stream", url, curl_easy_strerror(res));
|
"Easy IRL Stream", url, curl_easy_strerror(res),
|
||||||
|
errbuf[0] ? errbuf : "no details");
|
||||||
} else {
|
} else {
|
||||||
long http_code = 0;
|
long http_code = 0;
|
||||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||||
|
|||||||
Reference in New Issue
Block a user