Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::SL1Host Class Reference

#include <src/slic3r/Utils/OctoPrint.hpp>

+ Inheritance diagram for Slic3r::SL1Host:
+ Collaboration diagram for Slic3r::SL1Host:

Public Types

typedef Http::ProgressFn ProgressFn
 
typedef std::function< void(wxString)> ErrorFn
 
typedef std::function< void(wxString, wxString)> InfoFn
 

Public Member Functions

 SL1Host (DynamicPrintConfig *config)
 
 ~SL1Host () override=default
 
const char * get_name () const override
 
wxString get_test_ok_msg () const override
 
wxString get_test_failed_msg (wxString &msg) const override
 
PrintHostPostUploadActions get_post_upload_actions () const override
 
bool get_storage (wxArrayString &storage_path, wxArrayString &storage_name) const override
 
bool upload (PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override
 
bool has_auto_discovery () const override
 
bool can_test () const override
 
std::string get_host () const override
 
const std::string & get_apikey () const
 
const std::string & get_cafile () const
 
virtual bool supports_multiple_printers () const
 
virtual bool get_groups (wxArrayString &) const
 
virtual bool get_printers (wxArrayString &) const
 

Static Public Member Functions

static PrintHostget_print_host (DynamicPrintConfig *config)
 

Protected Member Functions

bool validate_version_text (const boost::optional< std::string > &version_text) const override
 
bool test (wxString &curl_msg) const override
 
bool upload_inner_with_host (PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override
 
void set_auth (Http &http) const override
 
virtual void set_http_post_header_args (Http &http, PrintHostPostUploadAction post_action) const
 
std::string make_url (const std::string &path) const
 
virtual wxString format_error (const std::string &body, const std::string &error, unsigned status) const
 

Protected Attributes

AuthorizationType m_authorization_type
 
std::string m_username
 
std::string m_password
 
std::string m_host
 
std::string m_apikey
 
std::string m_cafile
 
bool m_ssl_revoke_best_effort
 

Private Member Functions

bool test_with_method_check (wxString &curl_msg, bool &use_put) const
 
bool put_inner (PrintHostUpload upload_data, std::string url, const std::string &name, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const
 
bool post_inner (PrintHostUpload upload_data, std::string url, const std::string &name, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const
 

Private Attributes

bool m_show_after_message
 

Detailed Description

Member Typedef Documentation

◆ ErrorFn

typedef std::function<void(wxString )> Slic3r::PrintHost::ErrorFn
inherited

◆ InfoFn

typedef std::function<void(wxString , wxString )> Slic3r::PrintHost::InfoFn
inherited

◆ ProgressFn

Constructor & Destructor Documentation

◆ SL1Host()

Slic3r::SL1Host::SL1Host ( DynamicPrintConfig config)
541 : PrusaLink(config)
542{
543}

◆ ~SL1Host()

Slic3r::SL1Host::~SL1Host ( )
overridedefault

Member Function Documentation

◆ can_test()

bool Slic3r::OctoPrint::can_test ( ) const
inlineoverridevirtualinherited

Implements Slic3r::PrintHost.

31{ return true; }

◆ format_error()

wxString Slic3r::PrintHost::format_error ( const std::string &  body,
const std::string &  error,
unsigned  status 
) const
protectedvirtualinherited
67{
68 if (status != 0) {
69 auto wxbody = wxString::FromUTF8(body.data());
70 return wxString::Format("HTTP %u: %s", status, wxbody);
71 } else {
72 return wxString::FromUTF8(error.data());
73 }
74}
static char error[256]
Definition tga.cpp:50

References error.

Referenced by Slic3r::Duet::connect(), Slic3r::PrusaLink::post_inner(), Slic3r::PrusaLink::put_inner(), Slic3r::Duet::start_print(), Slic3r::AstroBox::test(), Slic3r::FlashAir::test(), Slic3r::Moonraker::test(), Slic3r::OctoPrint::test(), Slic3r::PrusaLink::test(), Slic3r::Repetier::test(), Slic3r::PrusaLink::test_with_method_check(), Slic3r::AstroBox::upload(), Slic3r::Duet::upload(), Slic3r::FlashAir::upload(), Slic3r::MKS::upload(), Slic3r::Moonraker::upload(), Slic3r::Repetier::upload(), and Slic3r::OctoPrint::upload_inner_with_host().

+ Here is the caller graph for this function:

◆ get_apikey()

const std::string & Slic3r::OctoPrint::get_apikey ( ) const
inlineinherited
34{ return m_apikey; }
std::string m_apikey
Definition OctoPrint.hpp:45

References Slic3r::OctoPrint::m_apikey.

Referenced by Slic3r::PrusaLink::set_auth().

+ Here is the caller graph for this function:

◆ get_cafile()

const std::string & Slic3r::OctoPrint::get_cafile ( ) const
inlineinherited
35{ return m_cafile; }
std::string m_cafile
Definition OctoPrint.hpp:46

References Slic3r::OctoPrint::m_cafile.

Referenced by Slic3r::PrusaLink::set_auth().

+ Here is the caller graph for this function:

◆ get_groups()

virtual bool Slic3r::PrintHost::get_groups ( wxArrayString &  ) const
inlinevirtualinherited

Reimplemented in Slic3r::Repetier.

65{ return false; }

◆ get_host()

std::string Slic3r::OctoPrint::get_host ( ) const
inlineoverridevirtualinherited

Implements Slic3r::PrintHost.

33{ return m_host; }
std::string m_host
Definition OctoPrint.hpp:44

References Slic3r::OctoPrint::m_host.

◆ get_name()

const char * Slic3r::SL1Host::get_name ( ) const
overridevirtual

Reimplemented from Slic3r::PrusaLink.

546{ return "SL1Host"; }

◆ get_post_upload_actions()

PrintHostPostUploadActions Slic3r::SL1Host::get_post_upload_actions ( ) const
inlineoverridevirtual

Reimplemented from Slic3r::PrusaLink.

130{ return {}; }

◆ get_print_host()

PrintHost * Slic3r::PrintHost::get_print_host ( DynamicPrintConfig config)
staticinherited
35{
37
38 {
39 const auto opt = config->option<ConfigOptionEnum<PrinterTechnology>>("printer_technology");
40 if (opt != nullptr) {
41 tech = opt->value;
42 }
43 }
44
45 if (tech == ptFFF) {
46 const auto opt = config->option<ConfigOptionEnum<PrintHostType>>("host_type");
47 const auto host_type = opt != nullptr ? opt->value : htOctoPrint;
48
49 switch (host_type) {
50 case htOctoPrint: return new OctoPrint(config);
51 case htDuet: return new Duet(config);
52 case htFlashAir: return new FlashAir(config);
53 case htAstroBox: return new AstroBox(config);
54 case htRepetier: return new Repetier(config);
55 case htPrusaLink: return new PrusaLink(config);
56 case htPrusaConnect: return new PrusaConnect(config);
57 case htMKS: return new MKS(config);
58 case htMoonraker: return new Moonraker(config);
59 default: return nullptr;
60 }
61 } else {
62 return new SL1Host(config);
63 }
64}
PrinterTechnology
Definition Config.hpp:205
@ ptFFF
Definition Config.hpp:207
@ htMoonraker
Definition PrintConfig.hpp:47
@ htPrusaLink
Definition PrintConfig.hpp:47
@ htRepetier
Definition PrintConfig.hpp:47
@ htMKS
Definition PrintConfig.hpp:47
@ htPrusaConnect
Definition PrintConfig.hpp:47
@ htDuet
Definition PrintConfig.hpp:47
@ htOctoPrint
Definition PrintConfig.hpp:47
@ htFlashAir
Definition PrintConfig.hpp:47
@ htAstroBox
Definition PrintConfig.hpp:47
ConfigOptionEnum< PrinterTechnology >
Definition PrintConfig.hpp:1079

References Slic3r::htAstroBox, Slic3r::htDuet, Slic3r::htFlashAir, Slic3r::htMKS, Slic3r::htMoonraker, Slic3r::htOctoPrint, Slic3r::htPrusaConnect, Slic3r::htPrusaLink, Slic3r::htRepetier, Slic3r::ConfigBase::option(), Slic3r::ptFFF, and Slic3r::ConfigOptionSingle< T >::value.

Referenced by Slic3r::GUI::PhysicalPrinterDialog::build_printhost_settings(), Slic3r::GUI::PhysicalPrinterDialog::update_printers(), and Slic3r::GUI::PhysicalPrinterDialog::update_printhost_buttons().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_printers()

virtual bool Slic3r::PrintHost::get_printers ( wxArrayString &  ) const
inlinevirtualinherited

Reimplemented in Slic3r::Repetier.

66{ return false; }

◆ get_storage()

bool Slic3r::PrusaLink::get_storage ( wxArrayString &  storage_path,
wxArrayString &  storage_name 
) const
overridevirtualinherited

Reimplemented from Slic3r::PrintHost.

690{
691 const char* name = get_name();
692
693 bool res = true;
694 auto url = make_url("api/v1/storage");
695 wxString error_msg;
696
697 struct StorageInfo {
698 wxString path;
699 wxString name;
700 bool read_only = false;
701 long long free_space = -1;
702 };
703 std::vector<StorageInfo> storage;
704
705 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get storage at: %2%") % name % url;
706
707 wxString wlang = GUI::wxGetApp().current_language_code();
708 std::string lang = GUI::format(wlang.SubString(0, 1));
709
710 auto http = Http::get(std::move(url));
711 set_auth(http);
712 http.header("Accept-Language", lang);
713 http.on_error([&](std::string body, std::string error, unsigned status) {
714 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting storage: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
715 error_msg = L"\n\n" + boost::nowide::widen(error);
716 res = false;
717 // If status is 0, the communication with the printer has failed completely (most likely a timeout), if the status is <= 400, it is an error returned by the pritner.
718 // If 0, we can show error to the user now, as we know the communication has failed. (res = true will do the trick.)
719 // if not 0, we must not show error, as not all printers support api/v1/storage endpoint.
720 // So we must be extra careful here, or we might be showing errors on perfectly fine communication.
721 if (status == 0)
722 res = true;
723
724 })
725 .on_complete([&](std::string body, unsigned) {
726 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got storage: %2%") % name % body;
727 try
728 {
729 std::stringstream ss(body);
730 pt::ptree ptree;
731 pt::read_json(ss, ptree);
732
733 // what if there is more structure added in the future? Enumerate all elements?
734 if (ptree.front().first != "storage_list") {
735 res = false;
736 return;
737 }
738 // each storage has own subtree of storage_list
739 for (const auto& section : ptree.front().second) {
740 const auto name = section.second.get_optional<std::string>("name");
741 const auto path = section.second.get_optional<std::string>("path");
742 const auto space = section.second.get_optional<std::string>("free_space");
743 const auto read_only = section.second.get_optional<bool>("read_only");
744 const auto ro = section.second.get_optional<bool>("ro"); // In PrusaLink 0.7.0RC2 "read_only" value is stored under "ro".
745 const auto available = section.second.get_optional<bool>("available");
746 if (path && (!available || *available)) {
747 StorageInfo si;
748 si.path = boost::nowide::widen(*path);
749 si.name = name ? boost::nowide::widen(*name) : wxString();
750 // If read_only is missing, assume it is NOT read only.
751 // si.read_only = read_only ? *read_only : false; // version without "ro"
752 si.read_only = (read_only ? *read_only : (ro ? *ro : false));
753 si.free_space = space ? std::stoll(*space) : 1; // If free_space is missing, assume there is free space.
754 storage.emplace_back(std::move(si));
755 }
756 }
757 }
758 catch (const std::exception&)
759 {
760 res = false;
761 }
762 })
763#ifdef WIN32
764 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
765
766#endif // WIN32
767 .perform_sync();
768
769 for (const auto& si : storage) {
770 if (!si.read_only && si.free_space > 0) {
771 storage_path.push_back(si.path);
772 storage_name.push_back(si.name);
773 }
774 }
775
776 if (res && storage_path.empty()) {
777 if (!storage.empty()) { // otherwise error_msg is already filled
778 error_msg = L"\n\n" + _L("Storages found") + L": \n";
779 for (const auto& si : storage) {
780 error_msg += GUI::format_wxstr(si.read_only ?
781 // TRN %1% = storage path
782 _L("%1% : read only") :
783 // TRN %1% = storage path
784 _L("%1% : no free space"), si.path) + L"\n";
785 }
786 }
787 // TRN %1% = host
788 std::string message = GUI::format(_L("Upload has failed. There is no suitable storage found at %1%."), m_host) + GUI::into_u8(error_msg);
789 BOOST_LOG_TRIVIAL(error) << message;
790 throw Slic3r::IOError(message);
791 }
792
793 return res;
794}
static Http get(std::string url)
Definition Http.cpp:607
bool m_ssl_revoke_best_effort
Definition OctoPrint.hpp:47
std::string make_url(const std::string &path) const
Definition OctoPrint.cpp:527
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:42
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:56
std::string into_u8(const wxString &str)
Definition GUI.cpp:442
wchar_t * widen(wchar_t *output, size_t output_size, char const *source)
Convert NULL terminated UTF source string to NULL terminated output string of size at most output_siz...
Definition convert.hpp:95
TPoint< P > front(const P &p)
Definition geometry_traits.hpp:872
#define L(s)
Definition I18N.hpp:18
#define _L(s)
Definition I18N.hpp:3

References _L, error, Slic3r::GUI::format(), Slic3r::GUI::format_wxstr(), Slic3r::Http::get(), Slic3r::PrusaLink::get_name(), Slic3r::GUI::into_u8(), L, Slic3r::OctoPrint::m_host, Slic3r::OctoPrint::m_ssl_revoke_best_effort, Slic3r::OctoPrint::make_url(), Slic3r::PrusaLink::set_auth(), and boost::nowide::widen().

+ Here is the call graph for this function:

◆ get_test_failed_msg()

wxString Slic3r::SL1Host::get_test_failed_msg ( wxString &  msg) const
overridevirtual

Reimplemented from Slic3r::PrusaLink.

554{
555 return GUI::format_wxstr("%s: %s", _L("Could not connect to Prusa SLA"), msg);
556}

References _L, and Slic3r::GUI::format_wxstr().

+ Here is the call graph for this function:

◆ get_test_ok_msg()

wxString Slic3r::SL1Host::get_test_ok_msg ( ) const
overridevirtual

Reimplemented from Slic3r::PrusaLink.

549{
550 return _(L("Connection to Prusa SL1 / SL1S works correctly."));
551}
#define _(msgid)
Definition getopt.c:87

References _, and L.

◆ has_auto_discovery()

bool Slic3r::OctoPrint::has_auto_discovery ( ) const
inlineoverridevirtualinherited

Implements Slic3r::PrintHost.

30{ return true; }

◆ make_url()

std::string Slic3r::OctoPrint::make_url ( const std::string &  path) const
protectedinherited
528{
529 if (m_host.find("http://") == 0 || m_host.find("https://") == 0) {
530 if (m_host.back() == '/') {
531 return (boost::format("%1%%2%") % m_host % path).str();
532 } else {
533 return (boost::format("%1%/%2%") % m_host % path).str();
534 }
535 } else {
536 return (boost::format("http://%1%/%2%") % m_host % path).str();
537 }
538}

References Slic3r::OctoPrint::m_host.

Referenced by Slic3r::PrusaLink::get_storage(), Slic3r::OctoPrint::test(), Slic3r::PrusaLink::test(), Slic3r::PrusaLink::test_with_method_check(), Slic3r::OctoPrint::upload_inner_with_host(), and Slic3r::PrusaLink::upload_inner_with_host().

+ Here is the caller graph for this function:

◆ post_inner()

bool Slic3r::PrusaLink::post_inner ( PrintHostUpload  upload_data,
std::string  url,
const std::string &  name,
ProgressFn  prorgess_fn,
ErrorFn  error_fn,
InfoFn  info_fn 
) const
privateinherited
1086{
1087 info_fn(L"set_complete_off", wxString());
1088 bool res = true;
1089 const auto upload_filename = upload_data.upload_path.filename();
1090 const auto upload_parent_path = upload_data.upload_path.parent_path();
1091
1092 Http http = Http::post(std::move(url));
1093#ifdef WIN32
1094 // "Host" header is necessary here. We have resolved IP address and subsituted it into "url" variable.
1095 // And when creating Http object above, libcurl automatically includes "Host" header from address it got.
1096 // Thus "Host" is set to the resolved IP instead of host filled by user. We need to change it back.
1097 // Not changing the host would work on the most cases (where there is 1 service on 1 hostname) but would break when f.e. reverse proxy is used (issue #9734).
1098 // https://www.rfc-editor.org/rfc/rfc7230#section-5.4
1099 std::string host = get_host_from_url(m_host);
1100 http.header("Host", host);
1101#endif // _WIN32
1102 set_auth(http);
1103 set_http_post_header_args(http, upload_data.post_action);
1104 http.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
1105 .form_add_file("file", upload_data.source_path.string(), upload_filename.string())
1106 .on_complete([&](std::string body, unsigned status) {
1108 // PrusaConnect message
1109 wxString widebody = wxString::FromUTF8(body);
1110 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % widebody;
1111 std::string message = m_show_after_message ? (boost::format("%1%") % widebody).str() : std::string();
1112 if (status == 202)
1113 info_fn(L"complete_with_warning", message);
1114 else
1115 info_fn(L"complete", message);
1116 } else {
1117 // PrusaLink
1118 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%") % name % status;
1119 info_fn(L"complete", wxString());
1120 }
1121
1122
1123 })
1124 .on_error([&](std::string body, std::string error, unsigned status) {
1125 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
1126 error_fn(format_error(body, error, status));
1127 res = false;
1128 })
1129 .on_progress([&](Http::Progress progress, bool& cancel) {
1130 prorgess_fn(std::move(progress), cancel);
1131 if (cancel) {
1132 // Upload was canceled
1133 BOOST_LOG_TRIVIAL(info) << "Octoprint: Upload canceled";
1134 res = false;
1135 }
1136 })
1137#ifdef WIN32
1138 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
1139#endif
1140 .perform_sync();
1141
1142 return res;
1143}
static Http post(std::string url)
Definition Http.cpp:612
virtual wxString format_error(const std::string &body, const std::string &error, unsigned status) const
Definition PrintHost.cpp:66
TOKEN * string(char *text)
Definition config.c:233
STL namespace.

References error, Slic3r::Http::form_add(), Slic3r::Http::form_add_file(), Slic3r::PrintHost::format_error(), Slic3r::Http::header(), L, Slic3r::OctoPrint::m_host, Slic3r::PrusaLink::m_show_after_message, Slic3r::OctoPrint::m_ssl_revoke_best_effort, Slic3r::Http::on_complete(), Slic3r::Http::perform_sync(), Slic3r::Http::post(), Slic3r::PrintHostUpload::post_action, Slic3r::PrusaLink::set_auth(), Slic3r::PrusaLink::set_http_post_header_args(), Slic3r::PrintHostUpload::source_path, and Slic3r::PrintHostUpload::upload_path.

Referenced by Slic3r::PrusaLink::upload_inner_with_host().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ put_inner()

bool Slic3r::PrusaLink::put_inner ( PrintHostUpload  upload_data,
std::string  url,
const std::string &  name,
ProgressFn  prorgess_fn,
ErrorFn  error_fn,
InfoFn  info_fn 
) const
privateinherited
1036{
1037 info_fn(L"set_complete_off", wxString());
1038
1039 bool res = true;
1040 // Percent escape all filenames in on path and add it to the url. This is different from POST.
1041 url += "/" + escape_path_by_element(upload_data.upload_path);
1042 Http http = Http::put(std::move(url));
1043#ifdef WIN32
1044 // "Host" header is necessary here. We have resolved IP address and subsituted it into "url" variable.
1045 // And when creating Http object above, libcurl automatically includes "Host" header from address it got.
1046 // Thus "Host" is set to the resolved IP instead of host filled by user. We need to change it back.
1047 // Not changing the host would work on the most cases (where there is 1 service on 1 hostname) but would break when f.e. reverse proxy is used (issue #9734).
1048 // https://www.rfc-editor.org/rfc/rfc7230#section-5.4
1049 std::string host = get_host_from_url(m_host);
1050 http.header("Host", host);
1051#endif // _WIN32
1052 set_auth(http);
1053 // This is ugly, but works. There was an error at PrusaLink side that accepts any string at Print-After-Upload as true, thus False was also triggering print after upload.
1054 if (upload_data.post_action == PrintHostPostUploadAction::StartPrint)
1055 http.header("Print-After-Upload", "?1");
1056 http.set_put_body(upload_data.source_path)
1057 .header("Content-Type", "text/x.gcode")
1058 .header("Overwrite", "?1")
1059 .on_complete([&](std::string body, unsigned status) {
1060 wxString widebody = wxString::FromUTF8(body);
1061 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % widebody;
1062 std::string message = m_show_after_message ? (boost::format("%1%") % widebody).str() : std::string();
1063 info_fn(L"complete", message);
1064 })
1065 .on_error([&](std::string body, std::string error, unsigned status) {
1066 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
1067 error_fn(format_error(body, error, status));
1068 res = false;
1069 })
1070 .on_progress([&](Http::Progress progress, bool& cancel) {
1071 prorgess_fn(std::move(progress), cancel);
1072 if (cancel) {
1073 // Upload was canceled
1074 BOOST_LOG_TRIVIAL(info) << "Octoprint: Upload canceled";
1075 res = false;
1076 }
1077 })
1078#ifdef WIN32
1079 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
1080#endif
1081 .perform_sync();
1082
1083 return res;
1084}
static Http put(std::string url)
Definition Http.cpp:619
std::string escape_path_by_element(const boost::filesystem::path &path)
Definition OctoPrint.cpp:146

References error, Slic3r::PrintHost::format_error(), Slic3r::Http::header(), L, Slic3r::OctoPrint::m_host, Slic3r::PrusaLink::m_show_after_message, Slic3r::OctoPrint::m_ssl_revoke_best_effort, Slic3r::Http::on_complete(), Slic3r::Http::perform_sync(), Slic3r::PrintHostUpload::post_action, Slic3r::Http::put(), Slic3r::PrusaLink::set_auth(), Slic3r::Http::set_put_body(), Slic3r::PrintHostUpload::source_path, Slic3r::StartPrint, and Slic3r::PrintHostUpload::upload_path.

Referenced by Slic3r::PrusaLink::upload_inner_with_host().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_auth()

void Slic3r::PrusaLink::set_auth ( Http http) const
overrideprotectedvirtualinherited

Reimplemented from Slic3r::OctoPrint.

591{
592 switch (m_authorization_type) {
593 case atKeyPassword:
594 http.header("X-Api-Key", get_apikey());
595 break;
596 case atUserPassword:
597 http.auth_digest(m_username, m_password);
598 break;
599 }
600
601 if (!get_cafile().empty()) {
602 http.ca_file(get_cafile());
603 }
604}
const std::string & get_cafile() const
Definition OctoPrint.hpp:35
const std::string & get_apikey() const
Definition OctoPrint.hpp:34
@ atUserPassword
Definition PrintConfig.hpp:51
@ atKeyPassword
Definition PrintConfig.hpp:51
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:229

References Slic3r::atKeyPassword, Slic3r::atUserPassword, Slic3r::Http::auth_digest(), Slic3r::Http::ca_file(), Slic3r::empty(), Slic3r::OctoPrint::get_apikey(), Slic3r::OctoPrint::get_cafile(), Slic3r::Http::header(), Slic3r::PrusaLink::m_authorization_type, Slic3r::PrusaLink::m_password, and Slic3r::PrusaLink::m_username.

Referenced by Slic3r::PrusaLink::get_storage(), Slic3r::PrusaLink::post_inner(), Slic3r::PrusaLink::put_inner(), Slic3r::PrusaLink::test(), and Slic3r::PrusaLink::test_with_method_check().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_http_post_header_args()

void Slic3r::PrusaLink::set_http_post_header_args ( Http http,
PrintHostPostUploadAction  post_action 
) const
protectedvirtualinherited

Reimplemented in Slic3r::PrusaConnect.

1146{
1147 http.form_add("print", post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false");
1148}

References Slic3r::Http::form_add(), and Slic3r::StartPrint.

Referenced by Slic3r::PrusaLink::post_inner().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ supports_multiple_printers()

virtual bool Slic3r::PrintHost::supports_multiple_printers ( ) const
inlinevirtualinherited

Reimplemented in Slic3r::Repetier.

60{ return false; }

◆ test()

bool Slic3r::PrusaLink::test ( wxString &  curl_msg) const
overrideprotectedvirtualinherited

Reimplemented from Slic3r::OctoPrint.

635{
636 // Since the request is performed synchronously here,
637 // it is ok to refer to `msg` from within the closure
638 const char* name = get_name();
639
640 bool res = true;
641 auto url = make_url("api/version");
642
643 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
644
645 auto http = Http::get(std::move(url));
646 set_auth(http);
647 http.on_error([&](std::string body, std::string error, unsigned status) {
648 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
649 res = false;
650 msg = format_error(body, error, status);
651 })
652 .on_complete([&, this](std::string body, unsigned) {
653 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body;
654
655 try {
656 std::stringstream ss(body);
657 pt::ptree ptree;
658 pt::read_json(ss, ptree);
659
660 if (!ptree.get_optional<std::string>("api")) {
661 res = false;
662 return;
663 }
664
665 const auto text = ptree.get_optional<std::string>("text");
666 res = validate_version_text(text);
667 if (!res) {
668 msg = GUI::format_wxstr(_L("Mismatched type of print host: %s"), (text ? *text : "OctoPrint"));
669 }
670 }
671 catch (const std::exception&) {
672 res = false;
673 msg = "Could not parse server response";
674 }
675 })
676#ifdef WIN32
677 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
678 .on_ip_resolve([&](std::string address) {
679 // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
680 // Remember resolved address to be reused at successive REST API call.
681 msg = GUI::from_u8(address);
682 })
683#endif // WIN32
684 .perform_sync();
685
686 return res;
687}
wxString from_u8(const std::string &str)
Definition GUI.cpp:437

References _L, error, Slic3r::PrintHost::format_error(), Slic3r::GUI::format_wxstr(), Slic3r::GUI::from_u8(), Slic3r::Http::get(), Slic3r::PrusaLink::get_name(), Slic3r::OctoPrint::m_ssl_revoke_best_effort, Slic3r::OctoPrint::make_url(), Slic3r::PrusaLink::set_auth(), and Slic3r::PrusaLink::validate_version_text().

+ Here is the call graph for this function:

◆ test_with_method_check()

bool Slic3r::PrusaLink::test_with_method_check ( wxString &  curl_msg,
bool &  use_put 
) const
privateinherited
797{
798 // Since the request is performed synchronously here,
799 // it is ok to refer to `msg` from within the closure
800
801 const char* name = get_name();
802
803 bool res = true;
804 auto url = make_url("api/version");
805
806 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
807 // Here we do not have to add custom "Host" header - the url contains host filled by user and libCurl will set the header by itself.
808 auto http = Http::get(std::move(url));
809 set_auth(http);
810 http.on_error([&](std::string body, std::string error, unsigned status) {
811 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
812 res = false;
813 msg = format_error(body, error, status);
814 })
815 .on_complete([&, this](std::string body, unsigned) {
816 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body;
817
818 try {
819 std::stringstream ss(body);
820 pt::ptree ptree;
821 pt::read_json(ss, ptree);
822
823 if (!ptree.get_optional<std::string>("api")) {
824 res = false;
825 return;
826 }
827
828 const auto text = ptree.get_optional<std::string>("text");
829 res = validate_version_text(text);
830 if (!res) {
831 msg = GUI::format_wxstr(_L("Mismatched type of print host: %s"), (text ? *text : "OctoPrint"));
832 use_put = false;
833 return;
834 }
835
836 // find capabilities subtree and read upload-by-put
837 for (const auto& section : ptree) {
838 if (section.first == "capabilities") {
839 const auto put_upload = section.second.get_optional<bool>("upload-by-put");
840 if (put_upload)
841 use_put = *put_upload;
842 break;
843 }
844 }
845
846 }
847 catch (const std::exception&) {
848 res = false;
849 msg = "Could not parse server response";
850 }
851 })
852#ifdef WIN32
853 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
854 .on_ip_resolve([&](std::string address) {
855 // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
856 // Remember resolved address to be reused at successive REST API call.
857 msg = GUI::from_u8(address);
858 })
859#endif // WIN32
860 .perform_sync();
861
862 return res;
863}

References _L, error, Slic3r::PrintHost::format_error(), Slic3r::GUI::format_wxstr(), Slic3r::GUI::from_u8(), Slic3r::Http::get(), Slic3r::PrusaLink::get_name(), Slic3r::OctoPrint::m_ssl_revoke_best_effort, Slic3r::OctoPrint::make_url(), Slic3r::PrusaLink::set_auth(), and Slic3r::PrusaLink::validate_version_text().

Referenced by Slic3r::PrusaLink::upload_inner_with_host().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ upload()

bool Slic3r::OctoPrint::upload ( PrintHostUpload  upload_data,
ProgressFn  prorgess_fn,
ErrorFn  error_fn,
InfoFn  info_fn 
) const
overridevirtualinherited

Implements Slic3r::PrintHost.

298{
299#ifndef WIN32
300 return upload_inner_with_host(std::move(upload_data), prorgess_fn, error_fn, info_fn);
301#else
302 std::string host = get_host_from_url(m_host);
303
304 // decide what to do based on m_host - resolve hostname or upload to ip
305 std::vector<boost::asio::ip::address> resolved_addr;
306 boost::system::error_code ec;
307 boost::asio::ip::address host_ip = boost::asio::ip::make_address(host, ec);
308 if (!ec) {
309 resolved_addr.push_back(host_ip);
310 } else if ( GUI::get_app_config()->get_bool("allow_ip_resolve") && boost::algorithm::ends_with(host, ".local")){
311 Bonjour("octoprint")
312 .set_hostname(host)
313 .set_retries(5) // number of rounds of queries send
314 .set_timeout(1) // after each timeout, if there is any answer, the resolving will stop
315 .on_resolve([&ra = resolved_addr](const std::vector<BonjourReply>& replies) {
316 for (const auto & rpl : replies) {
317 boost::asio::ip::address ip(rpl.ip);
318 ra.emplace_back(ip);
319 BOOST_LOG_TRIVIAL(info) << "Resolved IP address: " << rpl.ip;
320 }
321 })
322 .resolve_sync();
323 }
324 if (resolved_addr.empty()) {
325 // no resolved addresses - try system resolving
326 BOOST_LOG_TRIVIAL(error) << "PrusaSlicer failed to resolve hostname " << m_host << " into the IP address. Starting upload with system resolving.";
327 return upload_inner_with_host(std::move(upload_data), prorgess_fn, error_fn, info_fn);
328 } else if (resolved_addr.size() == 1) {
329 // one address resolved - upload there
330 return upload_inner_with_resolved_ip(std::move(upload_data), prorgess_fn, error_fn, info_fn, resolved_addr.front());
331 } else if (resolved_addr.size() == 2 && resolved_addr[0].is_v4() != resolved_addr[1].is_v4()) {
332 // there are just 2 addresses and 1 is ip_v4 and other is ip_v6
333 // try sending to both. (Then if both fail, show both error msg after second try)
334 wxString error_message;
335 if (!upload_inner_with_resolved_ip(std::move(upload_data), prorgess_fn
336 , [&msg = error_message, resolved_addr](wxString error) { msg = GUI::format_wxstr("%1%: %2%", resolved_addr.front(), error); }
337 , info_fn, resolved_addr.front())
338 &&
339 !upload_inner_with_resolved_ip(std::move(upload_data), prorgess_fn
340 , [&msg = error_message, resolved_addr](wxString error) { msg += GUI::format_wxstr("\n%1%: %2%", resolved_addr.back(), error); }
341 , info_fn, resolved_addr.back())
342 ) {
343
344 error_fn(error_message);
345 return false;
346 }
347 return true;
348 } else {
349 // There are multiple addresses - user needs to choose which to use.
350 size_t selected_index = resolved_addr.size();
351 IPListDialog dialog(nullptr, boost::nowide::widen(m_host), resolved_addr, selected_index);
352 if (dialog.ShowModal() == wxID_OK && selected_index < resolved_addr.size()) {
353 return upload_inner_with_resolved_ip(std::move(upload_data), prorgess_fn, error_fn, info_fn, resolved_addr[selected_index]);
354 }
355 }
356 return false;
357#endif // WIN32
358}
virtual bool upload_inner_with_host(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const
Definition OctoPrint.cpp:425
AppConfig * get_app_config()
Definition GUI.cpp:432

References error, Slic3r::GUI::format_wxstr(), Slic3r::GUI::get_app_config(), Slic3r::OctoPrint::m_host, Slic3r::Bonjour::on_resolve(), Slic3r::Bonjour::set_hostname(), Slic3r::Bonjour::set_retries(), Slic3r::Bonjour::set_timeout(), Slic3r::OctoPrint::upload_inner_with_host(), and boost::nowide::widen().

+ Here is the call graph for this function:

◆ upload_inner_with_host()

bool Slic3r::PrusaLink::upload_inner_with_host ( PrintHostUpload  upload_data,
ProgressFn  prorgess_fn,
ErrorFn  error_fn,
InfoFn  info_fn 
) const
overrideprotectedvirtualinherited

Reimplemented from Slic3r::OctoPrint.

980{
981 const char* name = get_name();
982
983 const auto upload_filename = upload_data.upload_path.filename();
984 const auto upload_parent_path = upload_data.upload_path.parent_path();
985
986 // If test fails, test_msg_or_host_ip contains the error message.
987 // Otherwise on Windows it contains the resolved IP address of the host.
988 wxString test_msg_or_host_ip;
989 bool use_put = false;
990 if (!test_with_method_check(test_msg_or_host_ip, use_put)) {
991 error_fn(std::move(test_msg_or_host_ip));
992 return false;
993 }
994
995 std::string url;
996 std::string storage_path = (use_put ? "api/v1/files" : "api/files");
997 storage_path += (upload_data.storage.empty() ? "/local" : upload_data.storage);
998#ifdef WIN32
999 // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
1000 if (m_host.find("https://") == 0 || test_msg_or_host_ip.empty() || !GUI::get_app_config()->get_bool("allow_ip_resolve"))
1001#endif // _WIN32
1002 {
1003 // If https is entered we assume signed ceritificate is being used
1004 // IP resolving will not happen - it could resolve into address not being specified in cert
1005 url = make_url(storage_path);
1006 }
1007#ifdef WIN32
1008 else {
1009 // Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
1010 // Curl uses easy_getinfo to get ip address of last successful transaction.
1011 // If it got the address use it instead of the stored in "host" variable.
1012 // This new address returns in "test_msg_or_host_ip" variable.
1013 // Solves troubles of uploades failing with name address.
1014 // in original address (m_host) replace host for resolved ip
1015 info_fn(L"resolve", test_msg_or_host_ip);
1016 url = substitute_host(make_url(storage_path), GUI::into_u8(test_msg_or_host_ip));
1017 BOOST_LOG_TRIVIAL(info) << "Upload address after ip resolve: " << url;
1018 }
1019#endif // _WIN32
1020
1021 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, method: %7%")
1022 % name
1023 % upload_data.source_path
1024 % url
1025 % upload_filename.string()
1026 % upload_parent_path.string()
1027 % (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
1028 % (use_put ? "PUT" : "POST");
1029
1030 if (use_put)
1031 return put_inner(std::move(upload_data), std::move(url), name, prorgess_fn, error_fn, info_fn);
1032 return post_inner(std::move(upload_data), std::move(url), name, prorgess_fn, error_fn, info_fn);
1033}
bool get_bool(const std::string &section, const std::string &key) const
Definition AppConfig.hpp:61

References Slic3r::GUI::get_app_config(), Slic3r::AppConfig::get_bool(), Slic3r::PrusaLink::get_name(), Slic3r::GUI::into_u8(), L, Slic3r::OctoPrint::m_host, Slic3r::OctoPrint::make_url(), Slic3r::PrintHostUpload::post_action, Slic3r::PrusaLink::post_inner(), Slic3r::PrusaLink::put_inner(), Slic3r::PrintHostUpload::source_path, Slic3r::StartPrint, Slic3r::PrintHostUpload::storage, Slic3r::PrusaLink::test_with_method_check(), and Slic3r::PrintHostUpload::upload_path.

+ Here is the call graph for this function:

◆ validate_version_text()

bool Slic3r::SL1Host::validate_version_text ( const boost::optional< std::string > &  version_text) const
overrideprotectedvirtual

Reimplemented from Slic3r::PrusaLink.

559{
560 return version_text ? boost::starts_with(*version_text, "Prusa SLA") : false;
561}

Member Data Documentation

◆ m_apikey

std::string Slic3r::OctoPrint::m_apikey
protectedinherited

◆ m_authorization_type

AuthorizationType Slic3r::PrusaLink::m_authorization_type
protectedinherited

◆ m_cafile

std::string Slic3r::OctoPrint::m_cafile
protectedinherited

◆ m_host

◆ m_password

std::string Slic3r::PrusaLink::m_password
protectedinherited

◆ m_show_after_message

bool Slic3r::PrusaLink::m_show_after_message
privateinherited

◆ m_ssl_revoke_best_effort

◆ m_username

std::string Slic3r::PrusaLink::m_username
protectedinherited

The documentation for this class was generated from the following files: