Envelope.h
Go to the documentation of this file.
1 /****
2  * Envelope.h
3  *
4  * Copyright 2019 mikee47 <mike@sillyhouse.net>
5  *
6  * This file is part of the Sming UPnP Library
7  *
8  * This library is free software: you can redistribute it and/or modify it under the terms of the
9  * GNU General Public License as published by the Free Software Foundation, version 3 or later.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with this library.
16  * If not, see <https://www.gnu.org/licenses/>.
17  *
18  ****/
19 
20 #pragma once
21 
22 #include <RapidXML.h>
23 #include "Error.h"
24 #include "ErrorCode.h"
25 #include "Base64.h"
26 
27 namespace UPnP
28 {
29 using Error = UPnP::Error;
30 class Service;
31 
35 class Envelope
36 {
37 public:
38  enum class ContentType {
39  none,
40  fault,
41  request,
42  response,
43  };
44 
45  class Fault
46  {
47  public:
48  Fault(Envelope& envelope) : envelope(envelope)
49  {
50  }
51 
52  explicit operator bool() const
53  {
54  return envelope.isFault();
55  }
56 
57  String faultCode() const;
58  String faultString() const;
59  ErrorCode errorCode() const;
60  String errorDescription() const;
61 
62  size_t printTo(Print& p) const;
63 
64  private:
65  Envelope& envelope;
66  XML::Node* detail() const;
67  XML::Node* error() const;
68  };
69 
71  {
72  }
73 
77  void clear();
78 
79  bool isEmpty() const
80  {
81  return type == ContentType::none;
82  }
83 
84  bool isFault() const
85  {
86  return type == ContentType::fault;
87  }
88 
95  Error load(String&& content);
96 
97  Error load(const FlashString& content);
103  String serialize(bool pretty)
104  {
105  prepareResponse();
106  return XML::serialize(doc, pretty);
107  }
108 
112  size_t serialize(Print& p, bool pretty)
113  {
114  prepareResponse();
115  return XML::serialize(doc, p, pretty);
116  }
117 
121  ContentType contentType() const
122  {
123  return type;
124  }
125 
130  {
131  return name;
132  }
133 
138 
143 
147  void convertToResponse()
148  {
149  if(type == ContentType::request) {
150  type = ContentType::response;
151  responsePrepared = false;
152  }
153  }
154 
159  void prepareResponse()
160  {
161  if(type == Envelope::ContentType::response && !responsePrepared) {
163  }
164  }
165 
169  Fault createFault(ErrorCode error);
170 
175  Fault fault()
176  {
177  return Fault(*this);
178  }
179 
180  const Fault fault() const
181  {
182  return Fault(*const_cast<Envelope*>(this));
183  }
184 
191  const char* getArgValue(const String& name) const
192  {
193  auto node = XML::getNode(content, name, "");
194  return node ? node->value() : nullptr;
195  }
196 
197  String getArg(const String& name) const
198  {
199  return XML::getValue(content, name, "");
200  }
201 
202  bool getArg(const String& name, char& value, char defaultValue = '?')
203  {
204  auto s = getArgValue(name);
205  if(s == nullptr) {
206  value = defaultValue;
207  return false;
208  }
209 
210  value = *s;
211  return true;
212  }
213 
214  bool getArg(const String& name, String& value)
215  {
216  value = getArg(name);
217  return bool(value);
218  }
219 
220  template <typename T>
221  typename std::enable_if<std::is_unsigned<T>::value && !std::is_floating_point<T>::value, bool>::type
222  getArg(const String& name, T& value, T defaultValue = T{})
223  {
224  uint32_t n;
225  if(!getArg(name, n, defaultValue)) {
226  value = defaultValue;
227  return false;
228  }
229 
230  value = n;
231  return true;
232  }
233 
234  template <typename T>
235  typename std::enable_if<std::is_signed<T>::value && !std::is_floating_point<T>::value, bool>::type
236  getArg(const String& name, T& value, T defaultValue = T{})
237  {
238  int32_t n;
239  if(!getArg(name, n, defaultValue)) {
240  value = defaultValue;
241  return false;
242  }
243 
244  value = n;
245  return true;
246  }
247 
248  bool getArg(const String& name, bool& value, bool defaultValue = false);
249  bool getArg(const String& name, uint32_t& value, uint32_t defaultValue = 0);
250  bool getArg(const String& name, int32_t& value, int32_t defaultValue = 0);
251  bool getArg(const String& name, float& value, float defaultValue = 0.0);
252  bool getArg(const String& name, double& value, double defaultValue = 0.0);
253 
254  bool getArg(const String& name, Base64& value)
255  {
256  value = getArgValue(name);
257  return bool(value);
258  }
259 
266  bool addArg(const String& name, const String& value)
267  {
268  prepareResponse();
269  assert(type == ContentType::request || type == ContentType::response);
270  XML::appendNode(content, name, value);
271  return true;
272  }
273 
274  bool addArg(const String& name, const char* value)
275  {
276  return addArg(name, String(value));
277  }
278 
279  bool addArg(const String& name, bool value)
280  {
281  return addArg(name, value ? "1" : "0");
282  }
283 
284  bool addArg(const String& name, const Base64& value)
285  {
286  return addArg(name, value.encode());
287  }
288 
289  template <typename T> bool addArg(const String& name, T value)
290  {
291  return addArg(name, String(value));
292  }
293 
297 
298  const Service& service;
299 
300 private:
301  Error parseBody();
302  Error verifyObjectType(const String& objectType) const;
303  XML::Node* initialise(ContentType contentType);
304 
305  XML::Document doc;
306  String buffer;
307  String name;
308  XML::Node* content{nullptr};
309  ContentType type{};
310  Error lastError{};
311  bool responsePrepared{false};
312 };
313 
314 } // namespace UPnP
Error load(String &&content)
Load a SOAP document.
String getArg(const String &name) const
Definition: Envelope.h:214
Envelope & createResponse(const String &actionName)
Initialise the envelope as a response.
Node * getNode(Node *node, const char *path, const char *ns, size_t ns_len=0)
describes a counted string stored in flash memory
Definition: String.hpp:173
String faultCode() const
rapidxml::xml_node< char > Node
Definition: RapidXML.h:37
String serialize(bool pretty)
Obtain content as XML string.
Definition: Envelope.h:120
The String class.
Definition: WString.h:136
Definition: MPU6050.h:3440
String soapAction() const
Class to manage a SOAP envelope for service request/response.
Definition: Envelope.h:52
bool addArg(const String &name, const char *value)
Definition: Envelope.h:291
ErrorCode errorCode() const
std::enable_if< std::is_unsigned< T >::value &&!std::is_floating_point< T >::value, bool >::type getArg(const String &name, T &value, T defaultValue=T{})
Definition: Envelope.h:239
Fault createFault(ErrorCode error)
Initialise the envelope as a fault.
Error
Definition: Libraries/UPnP/src/include/Network/UPnP/Error.h:45
ContentType contentType() const
Get the current envelope content type.
Definition: Envelope.h:138
Fault fault()
Definition: Envelope.h:192
Represents any kind of device, including a root device.
Definition: UPnP/src/include/Network/UPnP/Service.h:46
Definition: Base64.h:44
String getValue(const Node *node, const char *name, size_t name_size, const char *ns=nullptr, size_t ns_size=0)
String errorDescription() const
bool isFault() const
Definition: Envelope.h:101
bool isEmpty() const
Definition: Envelope.h:96
void prepareResponse()
If Response is required but hasn't been prepared yet, do it now. This wipes out the incoming request.
Definition: Envelope.h:176
const char * getArgValue(const String &name) const
Definition: Envelope.h:208
Definition: WebConstants.h:71
String faultString() const
bool addArg(const String &name, const String &value)
Definition: Envelope.h:283
Definition: ActionRequest.h:24
size_t serialize(const Node &node, String &buffer, bool pretty=false)
Serialize XML text and append to string buffer.
Fault(Envelope &envelope)
Definition: Envelope.h:65
void clear()
Wipe the envelope contents.
Provides formatted output to stream.
Definition: Print.h:36
Node * appendNode(Node *parent, const char *name, const char *value=nullptr, size_t name_size=0, size_t value_size=0)
Append a child element with optional value.
String actionName() const
Get the action name.
Definition: Envelope.h:146
size_t printTo(Print &p) const
ErrorCode
Definition: ErrorCode.h:58
rapidxml::xml_document< char > Document
Definition: RapidXML.h:36
Definition: Envelope.h:62
void convertToResponse()
Set a flag that this should be converted to Response on next setArg() call.
Definition: Envelope.h:164
Envelope & createRequest(const String &actionName)
Initialise the envelope as a request.
Envelope(const Service &service)
Definition: Envelope.h:87
const Service & service
Definition: Envelope.h:315
String encode() const
Definition: Base64.h:92