Add back 02.03.00 plugin to support debugging (#14966)

* Add back 02.03.00 plugin to support debugging
This commit is contained in:
SoftFever
2026-07-26 23:49:53 +08:00
committed by GitHub
parent d84a211b91
commit f60e0e776e
6 changed files with 347 additions and 124 deletions

View File

@@ -3708,13 +3708,13 @@ bool GUI_App::on_init_network(bool try_backup)
}
} else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll failed";
// A failed install can leave the config naming a build that never made it to
// disk (download_plugin() adopts the downloaded version up front so that
// install_plugin() can name the library after it). If the whitelisted latest
// is still installed, fall back to it instead of dropping the user into the
// re-download flow without networking.
// A failed install can leave the config naming a build that never made it to disk;
// fall back to the installed latest instead of dropping the user into the re-download
// flow. Only when the configured library is genuinely absent, though - a pinned series
// that is on disk but failed to load once must keep its pin, not be rewritten for good.
std::string latest = get_latest_network_version();
if (config_version != latest && BBLNetworkPlugin::versioned_library_exists(latest)) {
if (config_version != latest && !BBLNetworkPlugin::versioned_library_exists(config_version)
&& BBLNetworkPlugin::versioned_library_exists(latest)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": falling back to installed " << latest;
config_version = latest;
app_config->set_network_plugin_version(latest);
@@ -3818,7 +3818,14 @@ bool GUI_App::on_init_network(bool try_backup)
m_user_manager = new Slic3r::UserManager();
}
if (should_load_networking_plugin && m_networking_compatible && !use_legacy_network_plugin()) {
// A version pinned to something other than the latest series is a deliberate choice, so it
// is exempt from the upgrade prompt the same way the legacy pin already is - otherwise the
// dialog reappears on every launch for as long as the pin is held.
const std::string pinned_version = app_config->get_network_plugin_version();
const bool pinned_to_older_series = !pinned_version.empty() &&
network_plugin_series(pinned_version) != network_plugin_series(get_latest_network_version());
if (should_load_networking_plugin && m_networking_compatible && !pinned_to_older_series) {
app_config->clear_remind_network_update_later();
if (has_network_update_available()) {

View File

@@ -17,6 +17,20 @@ namespace Slic3r {
#define BAMBU_SOURCE_LIBRARY "BambuSource"
namespace {
// Named in the load log: the bound generation is what ties a crash report to an ABI choice.
// The label is the whitelist row's series, so it can never drift from the dispatch table.
const char* network_abi_name(NetworkAbi abi)
{
for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i)
if (AVAILABLE_NETWORK_VERSIONS[i].abi == abi)
return AVAILABLE_NETWORK_VERSIONS[i].version;
return "unsupported";
}
} // namespace
// ============================================================================
// Singleton Implementation
// ============================================================================
@@ -162,19 +176,20 @@ int BBLNetworkPlugin::initialize(bool using_backup, const std::string& version)
// Load all function pointers
load_all_function_pointers();
// Sync legacy network flag from loaded plugin
m_use_legacy_network = is_legacy_version(version);
// Key the generation on the library that actually loaded, not the version asked for:
// resolve_library_path() serves any same-series build. m_get_version is read directly, not
// via get_version(), which would substitute the "00.00.00.00" sentinel and pick no generation.
const std::string loaded_version = m_get_version ? m_get_version() : std::string();
m_network_abi = network_plugin_abi(loaded_version.empty() ? version : loaded_version);
std::string loaded_version;
if (m_get_version) {
loaded_version = m_get_version();
if (!loaded_version.empty()) {
m_use_legacy_network = is_legacy_version(loaded_version);
}
// A library reporting a series this build has no ABI for stays loaded but uncallable -
// check_networking_version() then reports it as incompatible and offers the update flow.
if (m_network_abi == NetworkAbi::Unsupported) {
BOOST_LOG_TRIVIAL(warning) << "BBLNetworkPlugin::initialize: no ABI for version "
<< (loaded_version.empty() ? version : loaded_version) << ", plug-in calls are disabled";
}
BOOST_LOG_TRIVIAL(info) << "BBLNetworkPlugin::initialize: legacy_mode="
<< (m_use_legacy_network ? "true" : "false")
BOOST_LOG_TRIVIAL(info) << "BBLNetworkPlugin::initialize: abi=" << network_abi_name(m_network_abi)
<< ", library=" << library
<< ", version=" << (loaded_version.empty() ? "unknown" : loaded_version)
<< ", send_message=" << (m_send_message ? "loaded" : "null")
@@ -217,7 +232,9 @@ int BBLNetworkPlugin::unload()
clear_all_function_pointers();
m_use_legacy_network = false;
// Safe to reset only because every pointer was nulled just above and every dispatcher is
// guarded on a non-null pointer, so no stale generation is reachable.
m_network_abi = NetworkAbi::Unsupported;
return 0;
}
@@ -520,7 +537,7 @@ void BBLNetworkPlugin::set_load_error(const std::string& message,
}
// ============================================================================
// Legacy Helper
// ABI Conversion Helpers
// ============================================================================
PrintParams_Legacy BBLNetworkPlugin::as_legacy(PrintParams& param)
@@ -564,6 +581,57 @@ PrintParams_Legacy BBLNetworkPlugin::as_legacy(PrintParams& param)
return l;
}
// Every PrintParams field except the four the 02.08.01 series added
// (task_timelapse_use_internal, extruder_cali_manual_mode, svc_context, slicer_uid).
PrintParams_0203 BBLNetworkPlugin::as_0203(PrintParams& param)
{
PrintParams_0203 p;
p.dev_id = std::move(param.dev_id);
p.task_name = std::move(param.task_name);
p.project_name = std::move(param.project_name);
p.preset_name = std::move(param.preset_name);
p.filename = std::move(param.filename);
p.config_filename = std::move(param.config_filename);
p.plate_index = param.plate_index;
p.ftp_folder = std::move(param.ftp_folder);
p.ftp_file = std::move(param.ftp_file);
p.ftp_file_md5 = std::move(param.ftp_file_md5);
p.nozzle_mapping = std::move(param.nozzle_mapping);
p.ams_mapping = std::move(param.ams_mapping);
p.ams_mapping2 = std::move(param.ams_mapping2);
p.ams_mapping_info = std::move(param.ams_mapping_info);
p.nozzles_info = std::move(param.nozzles_info);
p.connection_type = std::move(param.connection_type);
p.comments = std::move(param.comments);
p.origin_profile_id = param.origin_profile_id;
p.stl_design_id = param.stl_design_id;
p.origin_model_id = std::move(param.origin_model_id);
p.print_type = std::move(param.print_type);
p.dst_file = std::move(param.dst_file);
p.dev_name = std::move(param.dev_name);
p.dev_ip = std::move(param.dev_ip);
p.use_ssl_for_ftp = param.use_ssl_for_ftp;
p.use_ssl_for_mqtt = param.use_ssl_for_mqtt;
p.username = std::move(param.username);
p.password = std::move(param.password);
p.task_bed_leveling = param.task_bed_leveling;
p.task_flow_cali = param.task_flow_cali;
p.task_vibration_cali = param.task_vibration_cali;
p.task_layer_inspect = param.task_layer_inspect;
p.task_record_timelapse = param.task_record_timelapse;
p.task_use_ams = param.task_use_ams;
p.task_bed_type = std::move(param.task_bed_type);
p.extra_options = std::move(param.extra_options);
p.auto_bed_leveling = param.auto_bed_leveling;
p.auto_flow_cali = param.auto_flow_cali;
p.auto_offset_cali = param.auto_offset_cali;
p.task_ext_change_assist = param.task_ext_change_assist;
p.try_emmc_print = param.try_emmc_print;
return p;
}
// ============================================================================
// Function Pointer Loading
// ============================================================================
@@ -669,7 +737,8 @@ void BBLNetworkPlugin::load_all_function_pointers()
m_get_mw_user_preference = reinterpret_cast<func_get_mw_user_preference>(get_function("bambu_network_get_mw_user_preference"));
m_get_mw_user_4ulist = reinterpret_cast<func_get_mw_user_4ulist>(get_function("bambu_network_get_mw_user_4ulist"));
// Added by the 02.08.01.52 plugin ABI; resolve to null on older plugins so callers no-op.
// Bound late; anything a generation does not export resolves to null so callers no-op.
// See the typedefs for which generation introduced each of these.
m_set_on_user_login_fn = reinterpret_cast<func_set_on_user_login_fn>(get_function("bambu_network_set_on_user_login_fn"));
m_get_studio_info_url = reinterpret_cast<func_get_studio_info_url>(get_function("bambu_network_get_studio_info_url"));
m_report_consent = reinterpret_cast<func_report_consent>(get_function("bambu_network_report_consent"));

View File

@@ -119,7 +119,7 @@ typedef int (*func_get_model_mall_rating_result)(void *agent, int job_id, std::s
typedef int (*func_get_mw_user_preference)(void *agent, std::function<void(std::string)> callback);
typedef int (*func_get_mw_user_4ulist)(void *agent, int seed, int limit, std::function<void(std::string)> callback);
// Legacy function pointer types (for older DLL versions)
// Legacy function pointer types (for the 01.10.01 DLL)
typedef int (*func_start_print_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
typedef int (*func_start_local_print_with_record_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
typedef int (*func_start_send_gcode_to_sdcard_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
@@ -128,10 +128,25 @@ typedef int (*func_start_sdcard_print_legacy)(void* agent, PrintParams_Legacy pa
typedef int (*func_send_message_legacy)(void* agent, std::string dev_id, std::string json_str, int qos);
typedef int (*func_send_message_to_printer_legacy)(void* agent, std::string dev_id, std::string json_str, int qos);
// Added by the 02.08.01.52 plugin ABI (null on older plugins).
// 02.03.00 function pointer types. Only PrintParams differs from the current ABI; send_message
// and send_message_to_printer already take the flag argument in this series.
typedef int (*func_start_print_0203)(void *agent, PrintParams_0203 params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
typedef int (*func_start_local_print_with_record_0203)(void *agent, PrintParams_0203 params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
typedef int (*func_start_send_gcode_to_sdcard_0203)(void *agent, PrintParams_0203 params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
typedef int (*func_start_local_print_0203)(void *agent, PrintParams_0203 params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
typedef int (*func_start_sdcard_print_0203)(void* agent, PrintParams_0203 params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
// bind() gained dev_model in 02.08.01; the legacy and 02.03.00 series share the older form.
typedef int (*func_bind_pre0208)(void *agent, std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
// Exported by every supported generation, but only bound here.
typedef int (*func_set_on_user_login_fn)(void *agent, OnUserLoginFn fn);
typedef std::string (*func_get_studio_info_url)(void *agent);
// Present since 02.03.00, null on the legacy plugin.
typedef int (*func_report_consent)(void *agent, std::string expand);
// Added by the 02.08.01.52 plugin ABI (null on older plugins).
typedef int (*func_get_camera_url_for_golive)(void *agent, std::string dev_id, std::string sdev_id, std::function<void(std::string)> callback);
typedef int (*func_get_hms_snapshot)(void *agent, std::string& dev_id, std::string& file_name, std::function<void(std::string, int)> callback);
typedef int (*func_get_filament_spools)(void *agent, FilamentQueryParams params, std::string* http_body);
@@ -279,12 +294,13 @@ public:
const std::string& attempted_path);
// ========================================================================
// Legacy Network Flag
// Plug-in ABI Generation
// ========================================================================
static bool is_legacy_version(const std::string& version) { return version == BAMBU_NETWORK_AGENT_VERSION_LEGACY; }
bool use_legacy_network() const { return m_use_legacy_network; }
void set_use_legacy_network(bool legacy) { m_use_legacy_network = legacy; }
// The generation the loaded library speaks - what every call must dispatch on.
NetworkAbi network_abi() const { return m_network_abi; }
bool use_legacy_network() const { return m_network_abi == NetworkAbi::Legacy; }
// ========================================================================
// Function Pointer Accessors
@@ -401,10 +417,12 @@ public:
func_sync_ams_filaments get_sync_ams_filaments() const { return m_sync_ams_filaments; }
// ========================================================================
// Legacy Helper
// ABI Conversion Helpers
// ========================================================================
// Both move out of `param`, so convert only inside the branch that will actually run.
static PrintParams_Legacy as_legacy(PrintParams& param);
static PrintParams_0203 as_0203(PrintParams& param);
private:
// Singleton instance pointer (heap-allocated for explicit lifetime control)
@@ -431,8 +449,8 @@ private:
// Load error state
NetworkLibraryLoadError m_load_error;
// Legacy network compatibility flag
bool m_use_legacy_network{false};
// ABI generation of the currently loaded library
NetworkAbi m_network_abi{NetworkAbi::Unsupported};
// Function pointers
func_check_debug_consistent m_check_debug_consistent{nullptr};

View File

@@ -26,11 +26,19 @@ int BBLPrinterAgent::send_message(std::string dev_id, std::string json_str, int
auto agent = plugin.get_agent();
auto func = plugin.get_send_message();
if (func && agent) {
if (plugin.use_legacy_network()) {
// Only the legacy plug-in lacks `flag`; 02.03.00 already takes it, and routing that
// series through the legacy form would silently drop MessageFlag sign/encrypt.
switch (plugin.network_abi()) {
case NetworkAbi::Legacy: {
auto legacy_func = reinterpret_cast<func_send_message_legacy>(func);
return legacy_func(agent, dev_id, json_str, qos);
return legacy_func(agent, std::move(dev_id), std::move(json_str), qos);
}
case NetworkAbi::V0203:
case NetworkAbi::Current:
return func(agent, std::move(dev_id), std::move(json_str), qos, flag);
default:
return -1;
}
return func(agent, dev_id, json_str, qos, flag);
}
return -1;
}
@@ -63,11 +71,17 @@ int BBLPrinterAgent::send_message_to_printer(std::string dev_id, std::string jso
auto agent = plugin.get_agent();
auto func = plugin.get_send_message_to_printer();
if (func && agent) {
if (plugin.use_legacy_network()) {
switch (plugin.network_abi()) {
case NetworkAbi::Legacy: {
auto legacy_func = reinterpret_cast<func_send_message_to_printer_legacy>(func);
return legacy_func(agent, dev_id, json_str, qos);
return legacy_func(agent, std::move(dev_id), std::move(json_str), qos);
}
case NetworkAbi::V0203:
case NetworkAbi::Current:
return func(agent, std::move(dev_id), std::move(json_str), qos, flag);
default:
return -1;
}
return func(agent, dev_id, json_str, qos, flag);
}
return -1;
}
@@ -144,7 +158,19 @@ int BBLPrinterAgent::bind(std::string dev_ip, std::string dev_id, std::string de
auto agent = plugin.get_agent();
auto func = plugin.get_bind();
if (func && agent) {
return func(agent, dev_ip, dev_id, dev_model, sec_link, timezone, improved, update_fn);
// dev_model was added in 02.08.01. Passing it to a plug-in that takes the 7-argument
// form shifts every following argument, so the older generations get the older call.
switch (plugin.network_abi()) {
case NetworkAbi::Legacy:
case NetworkAbi::V0203: {
auto older_func = reinterpret_cast<func_bind_pre0208>(func);
return older_func(agent, dev_ip, dev_id, sec_link, timezone, improved, update_fn);
}
case NetworkAbi::Current:
return func(agent, dev_ip, dev_id, dev_model, sec_link, timezone, improved, update_fn);
default:
return -1;
}
}
return -1;
}
@@ -281,84 +307,62 @@ AgentInfo BBLPrinterAgent::get_agent_info_static()
// Print Job Operations
// ============================================================================
int BBLPrinterAgent::start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
namespace {
// Shared dispatcher for the start_* operations, whose params layout differs per generation.
// The per-generation typedefs are template arguments so a swapped pair fails to compile
// (each arm's converted params must match the casted signature). Each arm converts and calls
// in one step: as_legacy()/as_0203() move out of `params` and their prvalue result lands in
// the by-value ABI argument without another copy; the Current arm moves `params` outright.
template <typename LegacyFn, typename Fn0203, typename CurrentFn, typename... CallbackFns>
int dispatch_start(CurrentFn func, PrintParams& params, const CallbackFns&... callbacks)
{
auto& plugin = BBLNetworkPlugin::instance();
auto agent = plugin.get_agent();
auto func = plugin.get_start_print();
if (func && agent) {
if (plugin.use_legacy_network()) {
auto legacy_func = reinterpret_cast<func_start_print_legacy>(func);
auto legacy_params = BBLNetworkPlugin::as_legacy(params);
return legacy_func(agent, legacy_params, update_fn, cancel_fn, wait_fn);
}
return func(agent, params, update_fn, cancel_fn, wait_fn);
if (!func || !agent)
return -1;
switch (plugin.network_abi()) {
case NetworkAbi::Legacy:
return reinterpret_cast<LegacyFn>(func)(agent, BBLNetworkPlugin::as_legacy(params), callbacks...);
case NetworkAbi::V0203:
return reinterpret_cast<Fn0203>(func)(agent, BBLNetworkPlugin::as_0203(params), callbacks...);
case NetworkAbi::Current:
return func(agent, std::move(params), callbacks...);
default:
return -1;
}
return -1;
}
} // namespace
int BBLPrinterAgent::start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
{
return dispatch_start<func_start_print_legacy, func_start_print_0203>(
BBLNetworkPlugin::instance().get_start_print(), params, update_fn, cancel_fn, wait_fn);
}
int BBLPrinterAgent::start_local_print_with_record(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
{
auto& plugin = BBLNetworkPlugin::instance();
auto agent = plugin.get_agent();
auto func = plugin.get_start_local_print_with_record();
if (func && agent) {
if (plugin.use_legacy_network()) {
auto legacy_func = reinterpret_cast<func_start_local_print_with_record_legacy>(func);
auto legacy_params = BBLNetworkPlugin::as_legacy(params);
return legacy_func(agent, legacy_params, update_fn, cancel_fn, wait_fn);
}
return func(agent, params, update_fn, cancel_fn, wait_fn);
}
return -1;
return dispatch_start<func_start_local_print_with_record_legacy, func_start_local_print_with_record_0203>(
BBLNetworkPlugin::instance().get_start_local_print_with_record(), params, update_fn, cancel_fn, wait_fn);
}
int BBLPrinterAgent::start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
{
auto& plugin = BBLNetworkPlugin::instance();
auto agent = plugin.get_agent();
auto func = plugin.get_start_send_gcode_to_sdcard();
if (func && agent) {
if (plugin.use_legacy_network()) {
auto legacy_func = reinterpret_cast<func_start_send_gcode_to_sdcard_legacy>(func);
auto legacy_params = BBLNetworkPlugin::as_legacy(params);
return legacy_func(agent, legacy_params, update_fn, cancel_fn, wait_fn);
}
return func(agent, params, update_fn, cancel_fn, wait_fn);
}
return -1;
return dispatch_start<func_start_send_gcode_to_sdcard_legacy, func_start_send_gcode_to_sdcard_0203>(
BBLNetworkPlugin::instance().get_start_send_gcode_to_sdcard(), params, update_fn, cancel_fn, wait_fn);
}
int BBLPrinterAgent::start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
{
auto& plugin = BBLNetworkPlugin::instance();
auto agent = plugin.get_agent();
auto func = plugin.get_start_local_print();
if (func && agent) {
if (plugin.use_legacy_network()) {
auto legacy_func = reinterpret_cast<func_start_local_print_legacy>(func);
auto legacy_params = BBLNetworkPlugin::as_legacy(params);
return legacy_func(agent, legacy_params, update_fn, cancel_fn);
}
return func(agent, params, update_fn, cancel_fn);
}
return -1;
return dispatch_start<func_start_local_print_legacy, func_start_local_print_0203>(
BBLNetworkPlugin::instance().get_start_local_print(), params, update_fn, cancel_fn);
}
int BBLPrinterAgent::start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
{
auto& plugin = BBLNetworkPlugin::instance();
auto agent = plugin.get_agent();
auto func = plugin.get_start_sdcard_print();
if (func && agent) {
if (plugin.use_legacy_network()) {
auto legacy_func = reinterpret_cast<func_start_sdcard_print_legacy>(func);
auto legacy_params = BBLNetworkPlugin::as_legacy(params);
return legacy_func(agent, legacy_params, update_fn, cancel_fn);
}
return func(agent, params, update_fn, cancel_fn);
}
return -1;
return dispatch_start<func_start_sdcard_print_legacy, func_start_sdcard_print_0203>(
BBLNetworkPlugin::instance().get_start_sdcard_print(), params, update_fn, cancel_fn);
}
// ============================================================================

View File

@@ -230,6 +230,59 @@ struct PrintParams_Legacy {
std::string extra_options;
};
/* print job, as the 02.03.00 series expects it. The 02.08.01 series inserted
task_timelapse_use_internal, extruder_cali_manual_mode, svc_context and slicer_uid into
PrintParams; two of them sit mid-struct, so an older plug-in misreads every field from
task_use_ams onwards if handed the current layout. Rebuild it with as_0203() instead. */
struct PrintParams_0203 {
/* basic info */
std::string dev_id;
std::string task_name;
std::string project_name;
std::string preset_name;
std::string filename;
std::string config_filename;
int plate_index;
std::string ftp_folder;
std::string ftp_file;
std::string ftp_file_md5;
std::string nozzle_mapping;
std::string ams_mapping;
std::string ams_mapping2;
std::string ams_mapping_info;
std::string nozzles_info;
std::string connection_type;
std::string comments;
int origin_profile_id = 0;
int stl_design_id = 0;
std::string origin_model_id;
std::string print_type;
std::string dst_file;
std::string dev_name;
/* access options */
std::string dev_ip;
bool use_ssl_for_ftp;
bool use_ssl_for_mqtt;
std::string username;
std::string password;
/*user options */
bool task_bed_leveling; /* bed leveling of task */
bool task_flow_cali; /* flow calibration of task */
bool task_vibration_cali; /* vibration calibration of task */
bool task_layer_inspect; /* first layer inspection of task */
bool task_record_timelapse; /* record timelapse of task */
bool task_use_ams;
std::string task_bed_type;
std::string extra_options;
int auto_bed_leveling{ 0 };
int auto_flow_cali{ 0 };
int auto_offset_cali{ 0 };
bool task_ext_change_assist;
bool try_emmc_print;
};
/* print job*/
struct PrintParams {
/* basic info */
@@ -351,21 +404,34 @@ struct CertificateInformation {
std::string serial_number;
};
// The plug-in ABI generation a library speaks. Generations differ in by-value struct layouts and
// function signatures, so a call must go through the matching typedefs (see BBLPrinterAgent) -
// the wrong one corrupts the stack rather than failing cleanly.
enum class NetworkAbi {
Unsupported, // no generation in this build can call it - never dispatch through it
Legacy, // 01.10.01: PrintParams_Legacy; send_message/send_message_to_printer take no flag
V0203, // 02.03.00: PrintParams_0203; bind takes no dev_model
Current, // 02.08.01: the layouts and signatures this build declares directly
};
struct NetworkLibraryVersion {
const char* version;
const char* display_name;
const char* url_override;
bool is_latest;
const char* warning;
NetworkAbi abi;
};
// Only the latest series and the legacy build are offered/loadable: the host binds the
// modern ABI (by-value struct layouts, function signatures) of exactly one series, plus
// a dedicated shim for the legacy build. Older 02.0x series expect different layouts
// and must not be loaded - see is_supported_network_version().
// Every row names the generation that can call it, so a series can never be offered without a
// host-side ABI for it. Series with no generation - 02.01.01, 02.00.02 and older - must stay out;
// is_supported_network_version() is the gate that keeps them from loading.
static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = {
{"02.08.01", "02.08.01", nullptr, true, nullptr},
{BAMBU_NETWORK_AGENT_VERSION_LEGACY, BAMBU_NETWORK_AGENT_VERSION_LEGACY " (legacy)", nullptr, false, nullptr},
{"02.08.01", "02.08.01", nullptr, true, nullptr, NetworkAbi::Current},
{"02.03.00", "02.03.00", nullptr, false,
"An older plug-in series. Features that need newer plug-in support, such as print-failure "
"snapshots in the device error dialog, are unavailable.", NetworkAbi::V0203},
{BAMBU_NETWORK_AGENT_VERSION_LEGACY, BAMBU_NETWORK_AGENT_VERSION_LEGACY " (legacy)", nullptr, false, nullptr, NetworkAbi::Legacy},
};
static const size_t AVAILABLE_NETWORK_VERSIONS_COUNT = sizeof(AVAILABLE_NETWORK_VERSIONS) / sizeof(AVAILABLE_NETWORK_VERSIONS[0]);
@@ -378,23 +444,43 @@ inline const char* get_latest_network_version() {
return AVAILABLE_NETWORK_VERSIONS[0].version;
}
// True when the version can be loaded through the ABI this build was compiled against:
// an exact whitelist entry, or a build from the same AA.BB.CC series as a non-legacy
// whitelist entry (the plugin ABI is stable within a series, and the OTA sync only ever
// installs same-series updates). Anything else - in particular older 02.0x series a
// previous Orca release whitelisted - expects different by-value struct layouts and
// function signatures and must not be loaded.
inline bool is_supported_network_version(const std::string& version) {
// The AA.BB.CC series of a modern version string - the plug-in's stored identity. The 4th
// component is only which build of the series happens to be installed and is read live from
// the loaded plug-in for display. Legacy keeps its exact string (the shim matches exactly).
inline std::string network_plugin_series(const std::string& version) {
if (version.empty() || version == BAMBU_NETWORK_AGENT_VERSION_LEGACY)
return version;
return version.size() >= 8 ? version.substr(0, 8) : version;
}
// Index of the whitelist entry that can load this version: an exact match, or a build of the same
// AA.BB.CC series as a non-legacy entry (the ABI is stable within a series, and the OTA sync only
// installs same-series updates). Legacy matches exactly only - a sibling build of that series
// would come through the modern layout. AVAILABLE_NETWORK_VERSIONS_COUNT when nothing matches.
inline size_t find_network_version_index(const std::string& version) {
const std::string series = network_plugin_series(version);
for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) {
const std::string base = AVAILABLE_NETWORK_VERSIONS[i].version;
if (version == base)
return true;
return i;
if (base == BAMBU_NETWORK_AGENT_VERSION_LEGACY)
continue;
if (version.size() >= 8 && base.size() >= 8 && version.compare(0, 8, base, 0, 8) == 0)
return true;
if (series == base)
return i;
}
return false;
return AVAILABLE_NETWORK_VERSIONS_COUNT;
}
// True when a whitelisted series can load the version through an ABI this build implements.
inline bool is_supported_network_version(const std::string& version) {
return find_network_version_index(version) < AVAILABLE_NETWORK_VERSIONS_COUNT;
}
// The generation to call a loaded library through. Unsupported for anything the load gate rejects,
// so a mislabelled library reaches no plug-in call instead of a layout it does not share.
inline NetworkAbi network_plugin_abi(const std::string& version) {
const size_t i = find_network_version_index(version);
return i < AVAILABLE_NETWORK_VERSIONS_COUNT ? AVAILABLE_NETWORK_VERSIONS[i].abi : NetworkAbi::Unsupported;
}
struct NetworkLibraryVersionInfo {
@@ -441,15 +527,6 @@ inline std::string extract_suffix(const std::string& full_version) {
return (pos == std::string::npos) ? "" : full_version.substr(pos + 1);
}
// The AA.BB.CC series of a modern version string - the plug-in's stored identity. The 4th
// component is only which build of the series happens to be installed and is read live from
// the loaded plug-in for display. Legacy keeps its exact string (the shim matches exactly).
inline std::string network_plugin_series(const std::string& version) {
if (version.empty() || version == BAMBU_NETWORK_AGENT_VERSION_LEGACY)
return version;
return version.size() >= 8 ? version.substr(0, 8) : version;
}
// True when the version is a pure dotted-numeric build (AA.BB.CC or AA.BB.CC.DD) whose identity
// collapses to its series - the managed/OTA build. Legacy and any custom-named build
// (02.08.01_custom, 02.08.01.52-dev) are NOT managed: they are genuinely distinct files kept