Update PR

* Add libcurl check for websocket support
This commit is contained in:
abraunegg 2025-08-17 11:04:48 +10:00
commit 803c9d3cbd
3 changed files with 100 additions and 0 deletions

View file

@ -144,6 +144,10 @@ class ApplicationConfig {
bool fullScanTrueUpRequired = false;
bool suppressLoggingOutput = false;
// WebSocket Operations
bool curlSupportsWebSockets = false;
bool websocketsSupportCheckDone = false;
// Default number of concurrent threads when downloading and uploading data
ulong defaultConcurrentThreads = 8;

View file

@ -13,6 +13,10 @@ import std.stdio;
import std.range;
import core.memory;
import core.sys.posix.signal;
// Required for WebSocket Support
import core.stdc.stdlib : getenv;
import core.stdc.string : strcmp;
import core.sys.posix.dlfcn : dlopen, dlsym, dlclose, RTLD_NOW; // Posix elements
// What other modules that we have created do we need to import?
import log;
@ -21,11 +25,83 @@ import util;
// Shared pool of CurlEngine instances accessible across all threads
__gshared CurlEngine[] curlEnginePool; // __gshared is used to declare a variable that is shared across all threads
// WebSocket elements
enum CURL_WS_MIN_NUM = 0x075600; // 7.86.0 (version which WebSocket support was added to cURL)
// Flags (mirror curl/curl.h)
enum CURLWS_TEXT = 0x01u;
enum CURLWS_BINARY = 0x02u;
enum CURLWS_CONT = 0x10u;
enum CURLWS_CLOSE = 0x20u;
enum CURLWS_PING = 0x40u;
enum CURLWS_PONG = 0x80u;
extern (C) void sigpipeHandler(int signum) {
// Custom handler to ignore SIGPIPE signals
addLogEntry("ERROR: Handling a cURL SIGPIPE signal despite CURLOPT_NOSIGNAL being set (cURL Operational Bug) ...");
}
// Function pointer types matching libcurl WebSocket (WS) API
extern(C) struct curl_ws_frame {
uint age;
uint flags;
size_t len;
size_t offset;
size_t bytesleft;
}
// WebSocket alias
alias PFN_curl_ws_recv =
extern(C) CURLcode function(CURL*, void*, size_t, size_t*, const curl_ws_frame**);
alias PFN_curl_ws_send =
extern(C) CURLcode function(CURL*, const void*, size_t, size_t*, long /*curl_off_t*/, uint);
private __gshared {
void* _curlLib;
PFN_curl_ws_recv p_curl_ws_recv;
PFN_curl_ws_send p_curl_ws_send;
bool _wsSymbolsReady;
uint _wsProbeOnce; // 0=not run, 1=success, 2=fail
}
private void* loadCurlLib() {
// Respect LD_LIBRARY_PATH etc.
auto h = dlopen("libcurl.so.4", RTLD_NOW);
if (h is null) h = dlopen("libcurl.so", RTLD_NOW);
return h;
}
private void* findSymbol(const(char)* name) {
return dlsym(_curlLib, name);
}
private bool probeCurlWsSymbols() {
if (_wsProbeOnce == 1) return _wsSymbolsReady;
if (_wsProbeOnce == 2) return false;
// 1) libcurl version check
auto vi = curl_version_info(CURLVERSION_NOW);
if (vi is null || vi.version_num < CURL_WS_MIN_NUM) {
_wsProbeOnce = 2; _wsSymbolsReady = false; return false;
}
// 2) load libcurl and resolve symbols
_curlLib = loadCurlLib();
if (_curlLib is null) {
_wsProbeOnce = 2; _wsSymbolsReady = false; return false;
}
p_curl_ws_recv = cast(PFN_curl_ws_recv) findSymbol("curl_ws_recv");
p_curl_ws_send = cast(PFN_curl_ws_send) findSymbol("curl_ws_send");
_wsSymbolsReady = (p_curl_ws_recv !is null) && (p_curl_ws_send !is null);
_wsProbeOnce = _wsSymbolsReady ? 1 : 2;
return _wsSymbolsReady;
}
bool curlSupportsWebSockets() {
return probeCurlWsSymbols();
}
class CurlResponse {
HTTP.Method method;
const(char)[] url;

View file

@ -144,6 +144,26 @@ class OneDriveApi {
if (curlEngine is null) {
curlEngine = getCurlInstance();
curlEngine.initialise(appConfig.getValueLong("dns_timeout"), appConfig.getValueLong("connect_timeout"), appConfig.getValueLong("data_timeout"), appConfig.getValueLong("operation_timeout"), appConfig.defaultMaxRedirects, appConfig.getValueBool("debug_https"), appConfig.getValueString("user_agent"), appConfig.getValueBool("force_http_11"), appConfig.getValueLong("rate_limit"), appConfig.getValueLong("ip_protocol_version"), appConfig.getValueLong("max_curl_idle"), keepAlive);
// WebSocket capability available in OS cURL version
if (!appConfig.websocketsSupportCheckDone) {
// Check the underlying cURL capability to support websockets
if (debugLogging) {addLogEntry("Checking cURL Websocket support ...", ["debug"]);}
bool websocketSupport = curlSupportsWebSockets();
if (debugLogging) {addLogEntry("Checked cURL Websocket support = " ~ to!string(websocketSupport), ["debug"]);}
// Update appConfig flags
appConfig.curlSupportsWebSockets = websocketSupport;
appConfig.websocketsSupportCheckDone = true;
// Notify user if cURL vesion is too old to support websockets
if (!websocketSupport) {
addLogEntry();
addLogEntry("WARNING: Your libcurl is too old for WebSocket support. Please upgrade to libcurl 7.86.0 or newer.");
addLogEntry(" The near real-time processing of online changes cannot be enabled on your system.");
addLogEntry();
}
}
}
// Authorised value to return