Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
ServiceDescription.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Frameworks_UPnP_ServiceDescription_h_
5#define _Stroika_Frameworks_UPnP_ServiceDescription_h_ 1
6
7#include "Stroika/Frameworks/StroikaPreComp.h"
8
10#include "Stroika/Foundation/Containers/Sequence.h"
14
15/**
16 * \file
17 *
18 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
19 */
20
21namespace Stroika::Frameworks::UPnP {
22
23 using Foundation::Characters::String;
24 using Foundation::Containers::Sequence;
25
26 /**
27 * \brief A service's description - its SCPD (UPnP Device Architecture 1.1, section 2.5): its actions, each with its
28 * arguments, and its state variables - what the SCPDURL in its device's description serves.
29 *
30 * Its standard - SwitchPower:1, say - gives a standard service's; a device serves that, and a control point reads it to
31 * learn what it can ask (SOAP::ActionRequest).
32 *
33 * \par Example Usage
34 * \code
35 * // SwitchPower:1's (https://upnp.org/specs/ha/UPnP-ha-SwitchPower-v1-Service.pdf), served at its SCPDURL
36 * using SD = ServiceDescription;
37 * const SD kSwitchPower{
38 * .fActions = {SD::Action{.fName = "SetTarget"sv, .fArguments = {{.fName = "newTargetValue"sv, .fRelatedStateVariable = "Target"sv}}},
39 * SD::Action{.fName = "GetStatus"sv,
40 * .fArguments = {{.fName = "ResultStatus"sv, .fDirection = SD::Argument::Direction::eOut,
41 * .fRelatedStateVariable = "Status"sv}}}},
42 * .fStateVariables = {SD::StateVariable{.fName = "Target"sv, .fDataType = "boolean"sv, .fDefaultValue = "0"sv, .fSendEvents = false},
43 * SD::StateVariable{.fName = "Status"sv, .fDataType = "boolean"sv, .fDefaultValue = "0"sv}}};
44 * ...
45 * response.write (Serialize (kSwitchPower));
46 * \endcode
47 */
49 /**
50 * One of an action's arguments: an in argument (sent in its request), or an out one (sent back in its response).
51 */
52 struct Argument {
53 String fName;
54 enum class Direction {
55 eIn,
56 eOut,
57 };
58 Direction fDirection{Direction::eIn};
59 /**
60 * An out argument only: it is the action's return value - at most one, which is its first out argument.
61 */
62 bool fRetval{false};
63 /**
64 * The state variable whose type it has - its name.
65 */
67
68 bool operator== (const Argument&) const = default;
69
70 /**
71 * @see Characters::ToString ();
72 */
73 nonvirtual String ToString () const;
74 };
75
76 /**
77 */
78 struct Action {
79 String fName;
80 /**
81 * In order - the order a request's and a response's arguments go in: its in arguments, then its out ones.
82 */
83 Sequence<Argument> fArguments;
84
85 bool operator== (const Action&) const = default;
86
87 /**
88 * @see Characters::ToString ();
89 */
90 nonvirtual String ToString () const;
91 };
92
93 /**
94 * The values a number state variable may take: minimum to maximum, in steps of fStep (if given).
95 */
97 String fMinimum;
98 String fMaximum;
99 optional<String> fStep;
100
101 bool operator== (const AllowedValueRange&) const = default;
102
103 /**
104 * @see Characters::ToString ();
105 */
106 nonvirtual String ToString () const;
107 };
108
109 /**
110 * A piece of the service's state: what an action's argument has the type of, and - if evented - what GENA tells each
111 * subscriber the changes of.
112 */
114 String fName;
115 /**
116 * Its type, as UPnP names it: boolean, ui4, string, ... (UPnP Device Architecture 1.1, section 2.5)
117 */
119 optional<String> fDefaultValue;
120 /**
121 * Evented: each change is told to each subscriber (GENA).
122 */
123 bool fSendEvents{true};
124 /**
125 * A string's values, if only these: empty, any.
126 */
128 /**
129 * A number's values, if only these.
130 */
131 optional<AllowedValueRange> fAllowedValueRange;
132
133 bool operator== (const StateVariable&) const = default;
134
135 /**
136 * @see Characters::ToString ();
137 */
138 nonvirtual String ToString () const;
139 };
140
141 Sequence<Action> fActions;
142 Sequence<StateVariable> fStateVariables;
143
144 /**
145 * \brief What Serialize and DeSerialize of an SCPD are told - defaulted, so a caller says only what it wants different.
146 * As DeviceDescription::Options, for the SCPD's own schema: by default what is written is checked, and what is
147 * read is not
148 */
149 struct Options {
150 /**
151 * \brief The XML provider that reads, and that checks what is written - by default, Stroika's default provider;
152 * nearly always left as is (@see XML::Options)
153 */
155
156 /**
157 * \brief Check an SCPD being read against this schema - ServiceDescriptionSchema - throwing where it does not
158 * hold; nullptr, the default, checks nothing
159 *
160 * Off by default, as for a device description: devices in the field are loose, and whether to see fewer of them
161 * is the application's choice, not the library's (@see DeviceDescription::Options::fValidateReadAgainst).
162 */
164
165 /**
166 * \brief Check what Serialize writes against ServiceDescriptionSchema, throwing BadFormatException where it does
167 * not hold - true, the default
168 *
169 * On by default, as for a device description (@see DeviceDescription::Options::fValidateWrite): an SCPD a device
170 * writes is its own, and one that does not hold - a state variable whose fDataType is not one of UPnP's (a
171 * vendor's own, or a misspelling), or no state variables at all, where service-1-0 requires one - is a mistake
172 * better found by its author than by its control points.
173 */
174 bool fValidateWrite{true};
175 };
176
177 bool operator== (const ServiceDescription&) const = default;
178
179 /**
180 * @see Characters::ToString ();
181 */
182 nonvirtual String ToString () const;
183 };
184
185 /**
186 * \brief The SCPD's XML: what its SCPDURL serves - as UPnP's XML (text/xml), UTF-8
187 *
188 * The text is written directly (Variant::XML::Writer); an XML parser only checks it, as by default it does - throwing
189 * BadFormatException where it does not hold (@see ServiceDescription::Options::fValidateWrite).
190 */
191 Foundation::Memory::BLOB Serialize (const ServiceDescription& sd, const ServiceDescription::Options& options = {});
192
193 /**
194 * \brief An SCPD read - what Serialize writes, and any other's, leniently: what it does not know - a vendor's own
195 * elements, say - is skipped, and an element given twice keeps its last. Throws if it is not XML, its document
196 * element is not <scpd>, or the build has no XML parser (qStroika_Foundation_DataExchange_XML_SupportParsing).
197 * @see Variant::XML::Reader::Options::fLenient
198 */
199 void DeSerialize (const Foundation::Memory::BLOB& b, ServiceDescription* sd, const ServiceDescription::Options& options = {});
200
201#if qStroika_Foundation_DataExchange_XML_SupportParsing and qStroika_Foundation_DataExchange_XML_SupportSchema and qStroika_Foundation_DataExchange_XML_SupportDOM
202 /**
203 * \brief UPnP's own SCPD schema, compiled by the provider o names - what Serialize checks what it writes against
204 * (ServiceDescription::Options::fValidateWrite), and what to give fValidateReadAgainst
205 *
206 * @see DeviceDescriptionSchema, which this matches in every other way.
207 *
208 * \note The schema is https://upnp.org/schemas/service-1-0.xsd as it stood 2026-10-13 - BUT WITH ONE CORRECTION: as
209 * published it restricts stateVariable's sendEvents and multicast to {"1", "0"}, where the specification it
210 * describes says sendEvents="yes"/"no" (UPnP Device Architecture 1.0: "non-evented state variables have
211 * sendEvents="no"; default is sendEvents="yes""), and every implementation writes both that way. Left as
212 * published it would refuse every real device, Stroika's own output included. The two enumerations are
213 * widened to accept yes and no as well; nothing else is touched. @see ServiceDescriptionSchema.cpp.
214 */
215 Foundation::DataExchange::XML::Schema::Ptr ServiceDescriptionSchema (const Foundation::DataExchange::XML::Options& o = {});
216#endif
217
218}
219
220#endif /*_Stroika_Frameworks_UPnP_ServiceDescription_h_*/
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
A generalization of a vector: a container whose elements are keyed by the natural numbers.
How XML is read and written - for now, with which provider - taken last by each XML function (DOM::Do...
What Serialize and DeSerialize of an SCPD are told - defaulted, so a caller says only what it wants d...
bool fValidateWrite
Check what Serialize writes against ServiceDescriptionSchema, throwing BadFormatException where it do...
Foundation::DataExchange::XML::Schema::Ptr fValidateReadAgainst
Check an SCPD being read against this schema - ServiceDescriptionSchema - throwing where it does not ...
Foundation::DataExchange::XML::Options fXMLOptions
The XML provider that reads, and that checks what is written - by default, Stroika's default provider...
A service's description - its SCPD (UPnP Device Architecture 1.1, section 2.5): its actions,...