4#include "Stroika/Frameworks/StroikaPreComp.h"
7#include "Stroika/Foundation/Characters/String2Int.h"
10#include "Stroika/Foundation/DataExchange/BadFormatException.h"
12#include "Stroika/Foundation/DataExchange/XML/WriterUtils.h"
13#include "Stroika/Foundation/Execution/Throw.h"
14#include "Stroika/Foundation/IO/Network/Transfer/Connection.h"
15#if qStroika_Foundation_DataExchange_XML_SupportDOM
16#include "Stroika/Foundation/DataExchange/XML/DOM.h"
25using namespace Stroika::Frameworks;
26using namespace Stroika::Frameworks::UPnP;
36 for (
const Argument& a : arguments) {
60 constexpr string_view kUPnPErrorNamespace_ =
"urn:schemas-upnp-org:control-1-0"sv;
63 String StandardDescription_ (
unsigned int errorCode)
67 return "Invalid Action"sv;
68 case ActionError::kInvalidArgs:
69 return "Invalid Args"sv;
70 case ActionError::kActionFailed:
71 return "Action Failed"sv;
72 case ActionError::kArgumentValueInvalid:
73 return "Argument Value Invalid"sv;
74 case ActionError::kArgumentValueOutOfRange:
75 return "Argument Value Out of Range"sv;
76 case ActionError::kOptionalActionNotImplemented:
77 return "Optional Action Not Implemented"sv;
78 case ActionError::kOutOfMemory:
79 return "Out of Memory"sv;
80 case ActionError::kHumanInterventionRequired:
81 return "Human Intervention Required"sv;
82 case ActionError::kStringArgumentTooLong:
83 return "String Argument Too Long"sv;
105 sb <<
", Action: "sv <<
fAction;
121 sb <<
", Action: "sv <<
fAction;
143 .fFaultString =
"UPnPError"sv,
144 .fDetail =
"<UPnPError xmlns=\"{}\"><errorCode>{}</errorCode><errorDescription>{}</errorDescription></UPnPError>"_f(
145 String{kUPnPErrorNamespace_},
fErrorCode, DataExchange::XML::QuoteForXMLW (fErrorDescription))};
150#if qStroika_Foundation_DataExchange_XML_SupportDOM
151 if (not fault.fDetail) {
154 using namespace DataExchange::XML::DOM;
156 Document::Ptr doc = Document::New (
"<detail>{}</detail>"_f(*fault.fDetail),
nullptr, options.fXMLOptions);
157 for (
const Element::Ptr& e : doc.GetRootElement ().GetChildElements ()) {
158 if (e.GetName ().fName ==
"UPnPError"sv) {
159 optional<String> code;
161 for (
const Element::Ptr& c : e.GetChildElements ()) {
162 if (c.GetName ().fName ==
"errorCode"sv) {
163 code = c.GetValue ().Trim ();
165 else if (c.GetName ().fName ==
"errorDescription"sv) {
166 result.fErrorDescription = c.GetValue ();
170 result.
fErrorCode = String2Int<unsigned int> (*code);
184 sb <<
", Error-Description: "sv << fErrorDescription;
195 : Execution::Exception<runtime_error>{
"UPnP error {}: {}"_f(error.
fErrorCode, error.fErrorDescription)}
219 UPnPWriting_ (options));
226 UPnPWriting_ (options));
283 GenericSOAP_::Request{.fNamespace = request.fServiceType, .fMethod = request.fAction, .fArguments = ToGeneric_ (request.fArguments)},
284 UPnPWriting_ (options));
307 Execution::Throw (ActionException{ActionError::kInvalidAction});
310 .fMethod = r.fMethod,
318 UPnPWriting_ (options));
328 return doAction (request);
336 Require (actions.
Keys ().All (
337 [&] (
const String& a) { return description.fActions.Any ([&] (const ServiceDescription::Action& d) { return d.fName == a; }); }));
340 m, serviceType, description,
342 if (optional<ActionHandler> h = actions.Lookup (request.
fAction)) {
343 return (*h) (request);
361 if (not lo or not hi) {
365 [&]<
typename T> (
const T& v) {
366 if constexpr (is_arithmetic_v<T> and not same_as<T, bool>) {
367 return get<T> (*lo) <= v and v <= get<T> (*hi);
380 optional<SD::Action> action = description.fActions.
First ([&] (
const SD::Action& a) {
return a.fName == request.
fAction; });
385 auto in = action->fArguments.Where ([] (
const SD::Argument& a) {
return a.fDirection == SD::Argument::Direction::eIn; });
390 for (
const SD::Argument& described : in) {
393 if (a.fKey != described.fName) {
396 optional<SD::StateVariable> v =
397 description.fStateVariables.First ([&] (
const SD::StateVariable& sv) {
return sv.fName == described.fRelatedStateVariable; });
406 if ((not v->fAllowedValues.empty () and not v->fAllowedValues.Contains (a.fValue)) or
407 (v->fAllowedValueRange and not InRange_ (*value, *v->fAllowedValueRange, *t))) {
#define RequireNotNull(p)
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
A Mapping uniquely associates two elements: a key and a value (use Assocation to allow multiple value...
nonvirtual Iterable< key_type > Keys() const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
nonvirtual optional< value_type > First() const
nonvirtual void Append(ArgByValueType< value_type > item)
nonvirtual size_t size() const
Returns the number of items contained.
nonvirtual Iterator< T > begin() const
Support for ranged for, and STL syntax in general.
An ActionError, thrown: Invoke throws the one a service answers with, and a HandleAction doAction thr...
ActionException(const ActionError &error)
A Fault, thrown: Invoke throws the one a server answers with, and a HandleRequest handler throws one ...
void Throw(T &&e2Throw)
like the builtin C++ 'throw', but stamps in the current Activity context and does helpful,...
variant< bool, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, Foundation::Characters::Character, String, Foundation::Time::Date, Foundation::Time::DateTime, Foundation::Time::TimeOfDay, Foundation::Memory::BLOB, Foundation::IO::Network::URI, Foundation::Common::GUID > Value
A value of any of UPnP's data types, as its C++ type (the table above) - for code that learns a value...
DataType
UPnP's data types - each named, as a service's description names it (Common::DefaultNames): ui2,...
optional< T > FromText(const String &text)
text read as UPnP reads it: as t, if given, else as T's default data type (the table above) - nullopt...
Foundation::Memory::BLOB Serialize(const ActionRequest &request, const WebService::SOAP::Options &options={})
The SOAP message - its XML, UTF-8 - which sends it: a request, a response, or an error (a SOAP fault)
ActionResponse Invoke(const URI &controlURL, const ActionRequest &request, const WebService::SOAP::Options &options={})
Ask the service at controlURL to do request's action - and return its answer. Throws ActionException ...
void DeSerialize(const Foundation::Memory::BLOB &b, ActionRequest *request, const WebService::SOAP::Options &options={})
The SOAP message read: what Serialize writes, and any other's. Throws DataExchange::BadFormatExceptio...
void CheckRequest(const ActionRequest &request, const ServiceDescription &description)
Throws the ActionException a service answers request with if its description - its actions,...
void HandleAction(WebServer::Message &m, const String &serviceType, const ActionHandler &doAction, const WebService::SOAP::Options &options={})
Answer a control request, at the controlURL's route of the service of type serviceType: doAction's ou...
function< Arguments(const ActionRequest &)> ActionHandler
What a service does for a request for one of its actions: the action's out arguments - or,...
void DeSerialize(const Memory::BLOB &b, Request *request, const Options &options={})
The SOAP message read: what Serialize writes, and any other's. Throws DataExchange::BadFormatExceptio...
Memory::BLOB Serialize(const Request &request, const Options &options={})
The SOAP message - its XML, UTF-8 - which sends it: a call, its answer, or a fault.
Response Invoke(const URI &url, const String &soapAction, const Request &request, const Options &options={})
Call a method: POST request to url, with soapAction (in quotes, as SOAPAction headers are: section 6....
void HandleRequest(WebServer::Message &m, const function< Response(const Request &)> &handler, const Options &options={})
Answer a call, at its URL's route: 415 (Unsupported Media Type) if its body is not text/xml; else its...
A service's answer to an ActionRequest, it having not done the action: why not (UPnP Device Architect...
nonvirtual String ToString() const
nonvirtual WebService::SOAP::Fault AsFault() const
As SOAP sends it: a Client fault, UPnPError, its detail a UPnPError element.
static constexpr unsigned int kInvalidAction
static optional< ActionError > FromFault(const WebService::SOAP::Fault &fault, const WebService::SOAP::Options &options={})
The UPnPError a SOAP fault's detail holds; nullopt if it holds none - the detail read with options' X...
A control point's request that a service do one of its actions.
nonvirtual String GetSOAPAction() const
nonvirtual String ToString() const
A service's answer to an ActionRequest, it having done the action: the action's out arguments.
nonvirtual String ToString() const
One of an action's arguments: its name, and its value as text, as UPnP writes it (DataTypes::ToText) ...
A service's description - its SCPD (UPnP Device Architecture 1.1, section 2.5): its actions,...
A call's answer, the method having not been done: why not (section 4.4) - sent in an HTTP response wh...
What SOAP must be told that has a sensible default - taken by Serialize and DeSerialize,...
EncodingStyleAttribute fEncodingStyleAttribute
Where Serialize writes encodingStyle - nowhere, the default, so what is written holds to SOAP's schem...
A call of a method (section 7.1): the Body's one element, named the method, in its namespace - its in...
A call's answer, the method having been done (section 7.1): the Body's one element,...