UPnPsdk 0.1
Universal Plug and Play +, Software Development Kit
 
Loading...
Searching...
No Matches
soap_ctrlpt.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 *
3 * Copyright (c) 2000-2003 Intel Corporation
4 * All rights reserved.
5 * Copyright (C) 2022+ GPL 3 and higher by Ingo Höft, <Ingo@Hoeft-online.de>
6 * Redistribution only with this Copyright remark. Last modified: 2024-02-28
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 * - Neither name of Intel Corporation nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 ******************************************************************************/
33// Last compare with ./pupnp source file on 2024-02-14, ver 1.14.18
42#include <soap_common.hpp>
43#include <soap_ctrlpt.hpp>
44
45#include <httpreadwrite.hpp>
46#include <parsetools.hpp>
47#include <statcodes.hpp>
48#include <upnpapi.hpp>
49
50#ifndef COMPA_INTERNAL_CONFIG_HPP
51#error "No or wrong config.hpp header file included."
52#endif
53
55#include <cassert>
56#include <cctype>
57#include <cstdarg>
58#include <cstdio>
59#include <cstdlib>
61
62
63namespace {
64
69constexpr int SOAP_ACTION_RESP{1};
70constexpr int SOAP_VAR_RESP{2};
71/*#define SOAP_ERROR_RESP 3*/
72constexpr int SOAP_ACTION_RESP_ERROR{3};
73constexpr int SOAP_VAR_RESP_ERROR{4};
76
77
89 /* [in] lookup name. */
90 const char* name,
91 /* [in] xml node. */
92 IXML_Node* node) {
93 const DOMString node_name = NULL;
94 memptr nameptr;
95 memptr dummy;
96 int ret_code;
97
98 assert(name);
99 assert(node);
100
101 node_name = ixmlNode_getNodeName(node);
102 if (node_name == NULL)
103 return UPNP_E_OUTOF_MEMORY;
104 if (strcmp(name, node_name) == 0)
105 ret_code = 0;
106 else if (matchstr((char*)node_name, strlen(node_name), "%s:%s%0", &dummy,
107 &nameptr) == PARSE_OK &&
108 strcmp(nameptr.buf, name) == 0)
109 ret_code = 0;
110 else
111 /* names are not the same */
112 ret_code = 1;
113
114 return ret_code;
115}
116
126 /* [in] name of the node. */
127 const char* node_name,
128 /* [in] complete xml node. */
129 IXML_Node* start_node,
130 /* [out] matched node. */
131 IXML_Node** matching_node) {
132 IXML_Node* node;
133
134 /* invalid args */
135 if (!node_name || !start_node)
136 return UPNP_E_NOT_FOUND;
137 node = ixmlNode_getFirstChild(start_node);
138 while (node != NULL) {
139 /* match name */
140 if (dom_cmp_name(node_name, node) == 0) {
141 *matching_node = node;
142 return UPNP_E_SUCCESS;
143 }
144 /* free and next node */
145 node = ixmlNode_getNextSibling(node);
146 }
147
148 return UPNP_E_NOT_FOUND;
149}
150
159 /* [in] array of names. */
160 const char* names[],
161 /* [in] size of array. */
162 int num_names,
163 /* [in] Node from where it should be searched. */
164 IXML_Node* start_node,
165 /* [out] Node that matches the last name of the array. */
166 IXML_Node** matching_node) {
167 int i;
168 IXML_Node* node;
169 IXML_Node* match_node;
170
171 assert(num_names > 0);
172
173 node = start_node;
174 if (dom_cmp_name(names[0], start_node) == 0) {
175 if (num_names == 1) {
176 *matching_node = start_node;
177 return UPNP_E_SUCCESS;
178 }
179 }
180 for (i = 1; i < num_names; i++) {
181 if (dom_find_node(names[i], node, &match_node) != UPNP_E_SUCCESS)
182 return UPNP_E_NOT_FOUND;
183 if (i == num_names - 1) {
184 *matching_node = match_node;
185 return UPNP_E_SUCCESS;
186 }
187 /* try again */
188 node = match_node;
189 }
190
191 /* this line not reached */
192 return UPNP_E_NOT_FOUND;
193}
194
202 IXML_Node* node
203) {
204 IXML_Node* text_node = NULL;
205 const DOMString text_value = NULL;
206
207 text_node = ixmlNode_getFirstChild(node);
208 if (text_node == NULL) {
209 return NULL;
210 }
211
212 text_value = ixmlNode_getNodeValue(text_node);
213 return text_value;
214}
215
223inline int get_host_and_path( //
224 char* ctrl_url,
225 const memptr* host,
226 const memptr* path,
227 uri_type* url
228) {
229 if (parse_uri(ctrl_url, strlen(ctrl_url), url) != HTTP_SUCCESS) {
230 return -1;
231 }
232 /* This is done to ensure that the buffer is kept const */
233 ((memptr*)host)->buf = (char*)url->hostport.text.buff;
234 ((memptr*)host)->length = url->hostport.text.size;
235
236 ((memptr*)path)->buf = (char*)url->pathquery.buff;
237 ((memptr*)path)->length = url->pathquery.size;
238
239 return 0;
240}
241
249inline int get_action_name( //
250 char* action,
251 memptr* name
252) {
253 memptr dummy;
254 int ret_code;
255
256 ret_code = matchstr(action, strlen(action), " <%s:%s", &dummy, name);
257
258 return ret_code == PARSE_OK ? 0 : -1;
259}
260
268inline int add_man_header(
269 /* [in,out] HTTP header. */
270 membuffer* headers) {
271 size_t n;
272 char* soap_action_hdr;
273 const char* man_hdr =
274 "MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; ns=01\r\n01-";
275
276 /* change POST to M-POST */
277 if (membuffer_insert(headers, "M-", 2, 0) != 0)
278 return UPNP_E_OUTOF_MEMORY;
279 soap_action_hdr = strstr(headers->buf, "SOAPACTION:");
280 /* can't fail */
281 assert(soap_action_hdr != NULL);
282 /* insert MAN header */
283 n = (size_t)(soap_action_hdr - headers->buf);
284 if (membuffer_insert(headers, man_hdr, strlen(man_hdr), n))
285 return UPNP_E_OUTOF_MEMORY;
286
287 return 0;
288}
289
306 membuffer* request,
307 uri_type* destination_url,
308 http_parser_t* response
309) {
310 int ret_code;
311
312 ret_code =
313 http_RequestAndResponse(destination_url, request->buf, request->length,
314 SOAPMETHOD_POST, UPNP_TIMEOUT, response);
315 if (ret_code != 0) {
316 httpmsg_destroy(&response->msg);
317 return ret_code;
318 }
319 /* method-not-allowed error */
320 if (response->msg.status_code == HTTP_METHOD_NOT_ALLOWED) {
321 ret_code = add_man_header(request); /* change to M-POST msg */
322 if (ret_code != 0) {
323 return ret_code;
324 }
325
326 httpmsg_destroy(&response->msg); /* about to reuse response */
327
328 /* try again */
329 ret_code = http_RequestAndResponse(destination_url, request->buf,
330 request->length, HTTPMETHOD_MPOST,
331 UPNP_TIMEOUT, response);
332 if (ret_code != 0) {
333 httpmsg_destroy(&response->msg);
334 }
335 }
336
337 return ret_code;
338}
339
357 http_message_t* hmsg,
358 int code,
359 char* name,
360 int* upnp_error_code,
361 IXML_Node** action_value,
362 DOMString* str_value
364) {
365 IXML_Node* node = NULL;
366 IXML_Node* root_node = NULL;
367 IXML_Node* error_node = NULL;
368 IXML_Document* doc = NULL;
369 char* node_str = NULL;
370 const char* temp_str = NULL;
371 DOMString error_node_str = NULL;
372 int err_code = UPNP_E_BAD_RESPONSE; /* default error */
373 int done = 0;
374 const char* names[5];
375 const DOMString nodeValue;
376
377 /* only 200 and 500 status codes are relevant */
378 if ((hmsg->status_code != HTTP_OK &&
379 hmsg->status_code != HTTP_INTERNAL_SERVER_ERROR) ||
381 goto error_handler;
382 if (ixmlParseBufferEx(hmsg->entity.buf, &doc) != IXML_SUCCESS)
383 goto error_handler;
384 root_node = ixmlNode_getFirstChild((IXML_Node*)doc);
385 if (root_node == NULL)
386 goto error_handler;
387 if (code == SOAP_ACTION_RESP) {
388 /* try reading soap action response */
389 assert(action_value != NULL);
390
391 *action_value = NULL;
392 names[0] = "Envelope";
393 names[1] = "Body";
394 names[2] = name;
395 if (dom_find_deep_node(names, 3, root_node, &node) == UPNP_E_SUCCESS) {
396 node_str = ixmlPrintNode(node);
397 if (node_str == NULL) {
398 err_code = UPNP_E_OUTOF_MEMORY;
399 goto error_handler;
400 }
401 if (ixmlParseBufferEx(node_str, (IXML_Document**)action_value) !=
402 IXML_SUCCESS) {
403 err_code = UPNP_E_BAD_RESPONSE;
404 goto error_handler;
405 }
406 err_code = SOAP_ACTION_RESP;
407 done = 1;
408 }
409 } else if (code == SOAP_VAR_RESP) {
410 /* try reading var response */
411 assert(str_value != NULL);
412
413 *str_value = NULL;
414 names[0] = "Envelope";
415 names[1] = "Body";
416 names[2] = "QueryStateVariableResponse";
417 names[3] = "return";
418 if (dom_find_deep_node(names, 4, root_node, &node) == UPNP_E_SUCCESS) {
419 nodeValue = get_node_value(node);
420 if (nodeValue == NULL)
421 goto error_handler;
422 *str_value = ixmlCloneDOMString(nodeValue);
423 err_code = SOAP_VAR_RESP;
424 done = 1;
425 }
426 }
427 if (!done) {
428 /* not action or var resp; read error code and description */
429 *str_value = NULL;
430 names[0] = "Envelope";
431 names[1] = "Body";
432 names[2] = "Fault";
433 names[3] = "detail";
434 names[4] = "UPnPError";
435 if (dom_find_deep_node(names, 5, root_node, &error_node) !=
437 goto error_handler;
438 if (dom_find_node("errorCode", error_node, &node) != UPNP_E_SUCCESS)
439 goto error_handler;
440 temp_str = get_node_value(node);
441 if (!temp_str)
442 goto error_handler;
443 *upnp_error_code = atoi(temp_str);
444 if (*upnp_error_code > 400) {
445 err_code = *upnp_error_code;
446 goto error_handler; /* bad SOAP error code */
447 }
448 if (code == SOAP_VAR_RESP) {
449 if (dom_find_node("errorDescription", error_node, &node) !=
451 goto error_handler;
452 }
453 nodeValue = get_node_value(node);
454 if (nodeValue == NULL) {
455 goto error_handler;
456 }
457 *str_value = ixmlCloneDOMString(nodeValue);
458 if (*str_value == NULL) {
459 goto error_handler;
460 }
461 err_code = SOAP_VAR_RESP_ERROR;
462 } else if (code == SOAP_ACTION_RESP) {
463 error_node_str = ixmlPrintNode(error_node);
464 if (error_node_str == NULL) {
465 err_code = UPNP_E_OUTOF_MEMORY;
466 goto error_handler;
467 }
468 if (ixmlParseBufferEx(error_node_str,
469 (IXML_Document**)action_value) !=
470 IXML_SUCCESS) {
471 err_code = UPNP_E_BAD_RESPONSE;
472
473 goto error_handler;
474 }
475 err_code = SOAP_ACTION_RESP_ERROR;
476 }
477 }
478
479error_handler:
481 ixmlFreeDOMString(node_str);
482 ixmlFreeDOMString(error_node_str);
483 return err_code;
484}
485
487} // anonymous namespace
488
489
490int SoapSendAction(char* action_url, char* service_type,
491 IXML_Document* action_node, IXML_Document** response_node) {
492 char* action_str = NULL;
493 memptr name;
494 membuffer request;
495 membuffer responsename;
496 int err_code;
497 int ret_code;
498 http_parser_t response;
499 uri_type url;
500 int upnp_error_code;
501 char* upnp_error_str;
502 int got_response = 0;
503
504 off_t content_length;
505 const char* xml_start =
506 "<s:Envelope "
507 "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
508 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
509 "<s:Body>";
510 const char* xml_end = "</s:Body>\r\n"
511 "</s:Envelope>\r\n\r\n";
512 size_t xml_start_len;
513 size_t xml_end_len;
514 size_t action_str_len;
515
516 *response_node = NULL; /* init */
517
518 err_code = UPNP_E_OUTOF_MEMORY; /* default error */
519
520 UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__, "Inside SoapSendAction():");
521 /* init */
522 membuffer_init(&request);
523 membuffer_init(&responsename);
524
525 /* print action */
526 action_str = ixmlPrintNode((IXML_Node*)action_node);
527 if (action_str == NULL) {
528 goto error_handler;
529 }
530 /* get action name */
531 if (get_action_name(action_str, &name) != 0) {
532 err_code = UPNP_E_INVALID_ACTION;
533 goto error_handler;
534 }
535 /* parse url */
536 if (http_FixStrUrl(action_url, strlen(action_url), &url) != 0) {
537 err_code = UPNP_E_INVALID_URL;
538 goto error_handler;
539 }
540
541 UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
542 "path=%.*s, hostport=%.*s\n", (int)url.pathquery.size,
543 url.pathquery.buff, (int)url.hostport.text.size,
544 url.hostport.text.buff);
545
546 xml_start_len = strlen(xml_start);
547 xml_end_len = strlen(xml_end);
548 action_str_len = strlen(action_str);
549
550 /* make request msg */
551 request.size_inc = 50;
552 content_length = (off_t)(xml_start_len + action_str_len + xml_end_len);
553 if (http_MakeMessage(&request, 1, 1,
554 "q"
555 "N"
556 "s"
557 "sssbsc"
558 "Uc"
559 "b"
560 "b"
561 "b",
562 SOAPMETHOD_POST, &url, content_length,
563 ContentTypeHeader, "SOAPACTION: \"", service_type, "#",
564 name.buf, name.length, "\"", xml_start, xml_start_len,
565 action_str, action_str_len, xml_end,
566 xml_end_len) != 0) {
567 goto error_handler;
568 }
569
570 ret_code = soap_request_and_response(&request, &url, &response);
571 got_response = 1;
572 if (ret_code != UPNP_E_SUCCESS) {
573 err_code = ret_code;
574 goto error_handler;
575 }
576
577 if (membuffer_append(&responsename, name.buf, name.length) != 0 ||
578 membuffer_append_str(&responsename, "Response") != 0) {
579 goto error_handler;
580 }
581 /* get action node from the response */
582 ret_code = get_response_value(&response.msg, SOAP_ACTION_RESP,
583 responsename.buf, &upnp_error_code,
584 (IXML_Node**)response_node, &upnp_error_str);
585
586 if (ret_code == SOAP_ACTION_RESP) {
587 err_code = UPNP_E_SUCCESS;
588 } else if (ret_code == SOAP_ACTION_RESP_ERROR) {
589 err_code = upnp_error_code;
590 } else {
591 err_code = ret_code;
592 }
593
594error_handler:
595 ixmlFreeDOMString(action_str);
596 membuffer_destroy(&request);
597 membuffer_destroy(&responsename);
598 if (got_response) {
599 httpmsg_destroy(&response.msg);
600 }
601
602 return err_code;
603}
604
605int SoapSendActionEx(char* action_url, char* service_type,
606 IXML_Document* header, IXML_Document* action_node,
607 IXML_Document** response_node) {
608 char* xml_header_str = NULL;
609 char* action_str = NULL;
610 memptr name;
611 membuffer request;
612 membuffer responsename;
613 int err_code;
614 int ret_code;
615 http_parser_t response;
616 uri_type url;
617 int upnp_error_code;
618 char* upnp_error_str;
619 int got_response = 0;
620 const char* xml_start =
621 "<s:Envelope "
622 "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
623 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n";
624 const char* xml_header_start = "<s:Header>\r\n";
625 const char* xml_header_end = "</s:Header>\r\n";
626 const char* xml_body_start = "<s:Body>";
627 const char* xml_end = "</s:Body>\r\n"
628 "</s:Envelope>\r\n";
629 size_t xml_start_len;
630 size_t xml_header_start_len;
631 size_t xml_header_str_len;
632 size_t xml_header_end_len;
633 size_t xml_body_start_len;
634 size_t action_str_len;
635 size_t xml_end_len;
636 off_t content_length;
637
638 *response_node = NULL; /* init */
639
640 err_code = UPNP_E_OUTOF_MEMORY; /* default error */
641
642 UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
643 "Inside SoapSendActionEx():");
644 /* init */
645 membuffer_init(&request);
646 membuffer_init(&responsename);
647
648 /* header string */
649 xml_header_str = ixmlPrintNode((IXML_Node*)header);
650 if (xml_header_str == NULL) {
651 goto error_handler;
652 }
653 /* print action */
654 action_str = ixmlPrintNode((IXML_Node*)action_node);
655 if (action_str == NULL) {
656 goto error_handler;
657 }
658 /* get action name */
659 if (get_action_name(action_str, &name) != 0) {
660 err_code = UPNP_E_INVALID_ACTION;
661 goto error_handler;
662 }
663 /* parse url */
664 if (http_FixStrUrl(action_url, strlen(action_url), &url) != 0) {
665 err_code = UPNP_E_INVALID_URL;
666 goto error_handler;
667 }
668
669 UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
670 "path=%.*s, hostport=%.*s\n", (int)url.pathquery.size,
671 url.pathquery.buff, (int)url.hostport.text.size,
672 url.hostport.text.buff);
673
674 xml_start_len = strlen(xml_start);
675 xml_body_start_len = strlen(xml_body_start);
676 xml_end_len = strlen(xml_end);
677 action_str_len = strlen(action_str);
678
679 xml_header_start_len = strlen(xml_header_start);
680 xml_header_end_len = strlen(xml_header_end);
681 xml_header_str_len = strlen(xml_header_str);
682
683 /* make request msg */
684 request.size_inc = 50;
685 content_length = (off_t)(xml_start_len + xml_header_start_len +
686 xml_header_str_len + xml_header_end_len +
687 xml_body_start_len + action_str_len + xml_end_len);
688 if (http_MakeMessage(&request, 1, 1,
689 "q"
690 "N"
691 "s"
692 "sssbsc"
693 "Uc"
694 "b"
695 "b"
696 "b"
697 "b"
698 "b"
699 "b"
700 "b",
701 SOAPMETHOD_POST, &url, content_length,
702 ContentTypeHeader, "SOAPACTION: \"", service_type, "#",
703 name.buf, name.length, "\"", xml_start, xml_start_len,
704 xml_header_start, xml_header_start_len, xml_header_str,
705 xml_header_str_len, xml_header_end, xml_header_end_len,
706 xml_body_start, xml_body_start_len, action_str,
707 action_str_len, xml_end, xml_end_len) != 0) {
708 goto error_handler;
709 }
710
711 ret_code = soap_request_and_response(&request, &url, &response);
712 got_response = 1;
713 if (ret_code != UPNP_E_SUCCESS) {
714 err_code = ret_code;
715 goto error_handler;
716 }
717
718 if (membuffer_append(&responsename, name.buf, name.length) != 0 ||
719 membuffer_append_str(&responsename, "Response") != 0) {
720 goto error_handler;
721 }
722 /* get action node from the response */
723 ret_code = get_response_value(&response.msg, SOAP_ACTION_RESP,
724 responsename.buf, &upnp_error_code,
725 (IXML_Node**)response_node, &upnp_error_str);
726
727 if (ret_code == SOAP_ACTION_RESP) {
728 err_code = UPNP_E_SUCCESS;
729 } else if (ret_code == SOAP_ACTION_RESP_ERROR) {
730 err_code = upnp_error_code;
731 } else {
732 err_code = ret_code;
733 }
734
735error_handler:
736
737 ixmlFreeDOMString(action_str);
738 ixmlFreeDOMString(xml_header_str);
739 membuffer_destroy(&request);
740 membuffer_destroy(&responsename);
741 if (got_response) {
742 httpmsg_destroy(&response.msg);
743 }
744
745 return err_code;
746}
747
748int SoapGetServiceVarStatus(char* action_url, DOMString var_name,
749 DOMString* var_value) {
751#ifdef UPNPLIB_PUPNP_BUG
752 // Error old code: uninitialized 'const host|path' [-fpermissive]. Need to
753 // fix it here otherwise it will not compile. --Ingo
754 const memptr host; /* value for HOST header */
755 const memptr path; /* ctrl path in first line in msg */
756#else
757 const memptr host{}; /* value for HOST header */
758 const memptr path{}; /* ctrl path in first line in msg */
759#endif
760 uri_type url;
761 membuffer request;
762 int ret_code;
763 http_parser_t response;
764 int upnp_error_code;
765 off_t content_length;
766 const char* xml_start =
767 "<s:Envelope "
768 "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
769 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
770 "<s:Body>\r\n"
771 "<u:QueryStateVariable "
772 "xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\r\n"
773 "<u:varName>";
774 const char* xml_end = "</u:varName>\r\n"
775 "</u:QueryStateVariable>\r\n"
776 "</s:Body>\r\n"
777 "</s:Envelope>\r\n";
778
779 *var_value = NULL; /* return NULL in case of an error */
780 membuffer_init(&request);
781 /* get host hdr and url path */
782 if (get_host_and_path(action_url, &host, &path, &url) == -1) {
783 return UPNP_E_INVALID_URL;
784 }
785 /* make headers */
786 request.size_inc = 50;
787 content_length =
788 (off_t)(strlen(xml_start) + strlen(var_name) + strlen(xml_end));
790 &request, 1, 1,
791 "Q"
792 "sbc"
793 "N"
794 "s"
795 "sc"
796 "Ucc"
797 "sss",
798 SOAPMETHOD_POST, path.buf, path.length, "HOST: ", host.buf,
799 host.length, content_length, ContentTypeHeader,
800 "SOAPACTION: "
801 "\"urn:schemas-upnp-org:control-1-0#QueryStateVariable\"",
802 xml_start, var_name, xml_end) != 0) {
803 return UPNP_E_OUTOF_MEMORY;
804 }
805 /* send msg and get reply */
806 ret_code = soap_request_and_response(&request, &url, &response);
807 membuffer_destroy(&request);
808 if (ret_code != UPNP_E_SUCCESS) {
809 return ret_code;
810 }
811 /* get variable value from the response */
812 ret_code = get_response_value(&response.msg, SOAP_VAR_RESP, NULL,
813 &upnp_error_code, NULL, var_value);
814 httpmsg_destroy(&response.msg);
815 if (ret_code == SOAP_VAR_RESP) {
816 return UPNP_E_SUCCESS;
817 } else if (ret_code == SOAP_VAR_RESP_ERROR) {
818 return upnp_error_code;
819 } else {
820 return ret_code;
821 }
822}
int http_RequestAndResponse(uri_type *destination, const char *request, size_t request_length, http_method_t req_method, int timeout_secs, http_parser_t *response)
Initiates socket, connects to the remote host, sends a request and waits for the response from the re...
int http_FixStrUrl(const char *urlstr, size_t urlstrlen, uri_type *fixed_url)
Parses URL and then validates URL.
int http_MakeMessage(membuffer *buf, int http_major_version, int http_minor_version, const char *fmt,...)
Generate an HTTP message based on the format that is specified in the input parameters.
http_message_t msg
entire raw message
memptr entity
message body(entity).
@ PARSE_OK
Structure of an HTTP parser object.
Structure of an HTTP message.
hostport_type hostport
Member variable.
Definition uri.hpp:100
size_t size
Size of the buffer.
Definition uri.hpp:78
const char * buff
Buffer.
Definition uri.hpp:77
token pathquery
Member variable.
Definition uri.hpp:98
constexpr int HTTP_SUCCESS
Yet another success code.
Definition uri.hpp:70
token text
Pointing to the full host:port string representation.
Definition uri.hpp:85
Represents a URI used in parse_uri and elsewhere.
Definition uri.hpp:92
Data structure common to all types of nodes.
Definition ixml.hpp:132
Data structure representing the DOM Document.
Definition ixml.hpp:155
PUPNP_Api DOMString ixmlPrintNode(IXML_Node *doc)
Renders a Node and all sub-elements into an XML text representation.
Definition ixml.cpp:338
PUPNP_Api int ixmlParseBufferEx(const char *buffer, IXML_Document **doc)
Parses an XML text buffer converting it into an IXML DOM representation.
Definition ixml.cpp:390
#define DOMString
The type of DOM strings.
Definition ixml.hpp:47
PUPNP_Api IXML_Node * ixmlNode_getNextSibling(IXML_Node *nodeptr)
Retrieves the sibling Node immediately following this Node.
Definition node.cpp:375
PUPNP_Api const DOMString ixmlNode_getNodeValue(IXML_Node *nodeptr)
Returns the value of the Node as a string.
Definition node.cpp:296
PUPNP_Api const DOMString ixmlNode_getNodeName(IXML_Node *nodeptr)
Returns the name of the Node, depending on what type of Node it is, in a read-only string.
Definition node.cpp:179
PUPNP_Api void ixmlFreeDOMString(DOMString buf)
Frees a DOMString.
Definition ixml.cpp:418
PUPNP_Api DOMString ixmlCloneDOMString(const DOMString src)
Clones an existing DOMString.
Definition ixml.cpp:410
PUPNP_Api IXML_Node * ixmlNode_getFirstChild(IXML_Node *nodeptr)
Retrieves the first child Node of a Node.
Definition node.cpp:342
PUPNP_Api void ixmlDocument_free(IXML_Document *doc)
Frees a Document object and all Nodes associated with it.
Definition document.cpp:47
void httpmsg_destroy(http_message_t *msg)
Free memory allocated for the http message.
parse_status_t matchstr(char *str, size_t slen, const char *fmt,...)
Matches a variable parameter list with a string and takes actions based on the data type specified.
void membuffer_destroy(membuffer *m)
Free's memory allocated for membuffer* m.
void membuffer_init(membuffer *m)
Wrapper to membuffer_initialize().
int membuffer_append(membuffer *m, const void *buf, size_t buf_len)
Invokes function to appends data from a constant buffer to the buffer.
int membuffer_append_str(membuffer *m, const char *c_str)
Invokes function to appends data from a constant string to the buffer.
int membuffer_insert(membuffer *m, const void *buf, size_t buf_len, size_t index)
Allocates memory for the new data to be inserted. Does memory management by moving the data from the ...
size_t size_inc
used to increase size; MUST be > 0; (read/write).
Definition membuffer.hpp:69
size_t length
length of buffer without terminating null byte (read-only).
Definition membuffer.hpp:65
char * buf
mem buffer; must not write beyond buf[length-1] (read/write).
Definition membuffer.hpp:63
size_t length
length of memory (read-only).
Definition membuffer.hpp:54
char * buf
start of memory (read/write).
Definition membuffer.hpp:52
pointer to a chunk of memory.
Definition membuffer.hpp:50
Maintains a block of dynamically allocated memory.
Definition membuffer.hpp:61
#define UPNP_E_NOT_FOUND
The response to a SOAP request did not contain the required XML constructs.
Definition messages.hpp:313
#define UPNP_E_SUCCESS
The operation completed successfully.
Definition messages.hpp:27
#define UPNP_E_OUTOF_MEMORY
Not enough resources are currently available to complete the operation.
Definition messages.hpp:57
#define UPNP_E_INVALID_URL
An URL passed into the function is invalid.
Definition messages.hpp:83
#define UPNP_E_INVALID_ACTION
The SOAP action message is invalid.
Definition messages.hpp:113
#define UPNP_E_BAD_RESPONSE
The response received from the remote side of a connection is not correct for the protocol.
Definition messages.hpp:103
int get_response_value(http_message_t *hmsg, int code, char *name, int *upnp_error_code, IXML_Node **action_value, DOMString *str_value)
This function handles the response coming back from the device.
int soap_request_and_response(membuffer *request, uri_type *destination_url, http_parser_t *response)
This function sends the control point's request to the device and receives a response from it.
int add_man_header(membuffer *headers)
Adds "MAN" field in the HTTP header.
int dom_find_deep_node(const char *names[], int num_names, IXML_Node *start_node, IXML_Node **matching_node)
Searches for the node specifed by the last name in the 'name' array.
constexpr int SOAP_VAR_RESP
Control point SOAP status.
int dom_cmp_name(const char *name, IXML_Node *node)
Compares 'name' and node's name.
int dom_find_node(const char *node_name, IXML_Node *start_node, IXML_Node **matching_node)
Goes thru each child of 'start_node' looking for a node having the name 'node_name'.
constexpr int SOAP_ACTION_RESP
Control point SOAP status.
constexpr int SOAP_VAR_RESP_ERROR
Control point SOAP status.
int get_host_and_path(char *ctrl_url, const memptr *host, const memptr *path, uri_type *url)
This function retrives the host and path from the control URL.
constexpr int SOAP_ACTION_RESP_ERROR
Control point SOAP status.
const DOMString get_node_value(IXML_Node *node)
This function returns the value of the text node.
int get_action_name(char *action, memptr *name)
This function retrives the action name in the buffer.
int has_xml_content_type(http_message_t *hmsg)
Find the header from the HTTP message and match the header for xml data.
Function to extract header information from an http message and match the data with XML data.
Common SOAP declarations used for SOAP Devices and SOAP Control Points.
constexpr char ContentTypeHeader[]
Common SOAP constant string specifying the content type header.
int SoapSendActionEx(char *action_url, char *service_type, IXML_Document *header, IXML_Document *action_node, IXML_Document **response_node)
This extended function is called by UPnP API to send the SOAP action request.
int SoapGetServiceVarStatus(char *action_url, DOMString var_name, DOMString *var_value)
This function creates a status variable query message send it to the specified URL....
int SoapSendAction(char *action_url, char *service_type, IXML_Document *action_node, IXML_Document **response_node)
This function is called by UPnP API to send the SOAP action request.
SOAP declarations for Control Points using SOAP.
HTTP status codes.
Inititalize the compatible library before it can be used.
#define UPNP_TIMEOUT
UPNP_TIMEOUT.
Definition upnpapi.hpp:71
UPnPsdk_VIS void UpnpPrintf(Upnp_LogLevel DLevel, Dbg_Module Module, const char *DbgFileName, int DbgLineNo, const char *FmtStr,...)
Prints the debug statement.
int parse_uri(const char *in, size_t max, uri_type *out)
Parses a uri as defined in RFC 2396 (explaining URIs).
Definition uri.cpp:733