UPnPsdk 0.1
Universal Plug and Play +, Software Development Kit
 
Loading...
Searching...
No Matches
soap_device.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 *
3 * Copyright (c) 2000-2003 Intel Corporation
4 * All rights reserved.
5 * Copyright (c) 2012 France Telecom All rights reserved.
6 * Copyright (C) 2022+ GPL 3 and higher by Ingo Höft, <Ingo@Hoeft-online.de>
7 * Redistribution only with this Copyright remark. Last modified: 2024-10-26
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * - Neither name of Intel Corporation nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 ******************************************************************************/
34// Last compare with ./pupnp source file on 2024-10-26, ver 1.14.20
43#include <soap_common.hpp>
44#include <soap_device.hpp>
45
46#include <httpreadwrite.hpp>
47#include <parsetools.hpp>
48#include <ssdp_common.hpp>
49#include <statcodes.hpp>
50#include <upnpapi.hpp>
52#include <webserver.hpp>
53
54#ifndef COMPA_INTERNAL_CONFIG_HPP
55#error "No or wrong config.hpp header file included."
56#endif
57
59#include <cassert>
60#include <cstring>
62
63namespace {
64
70constexpr int SREQ_HDR_NOT_FOUND{-1};
71constexpr int SREQ_BAD_HDR_FORMAT{-2};
72constexpr int SREQ_NOT_EXTENDED{-3};
73
74constexpr int SOAP_INVALID_ACTION{401};
75// constexpr int SOAP_INVALID_ARGS{402};
76// constexpr int SOAP_OUT_OF_SYNC{403};
77constexpr int SOAP_INVALID_VAR{404};
78constexpr int SOAP_ACTION_FAILED{501};
79constexpr int SOAP_MEMORY_OUT{603};
81
84constexpr char SOAP_BODY[]{"Body"};
85constexpr char SOAP_URN[]{"http://schemas.xmlsoap.org/soap/envelope/"};
86constexpr char QUERY_STATE_VAR_URN[]{"urn:schemas-upnp-org:control-1-0"};
87
88constexpr char Soap_Invalid_Action[]{"Invalid Action"};
89// constexpr char Soap_Invalid_Args[]{"Invalid Args"};
90constexpr char Soap_Action_Failed[]{"Action Failed"};
91constexpr char Soap_Invalid_Var[]{"Invalid Var"};
92constexpr char Soap_Memory_out[]{"Out of Memory"};
94
96
102 char dev_udn[NAME_SIZE];
103 char service_type[NAME_SIZE];
104 char service_id[NAME_SIZE];
105 memptr action_name;
106 Upnp_FunPtr callback;
107 void* cookie;
108};
109
111
116void namecopy(char dest[NAME_SIZE], const char* src) {
117 strncpy(dest, src, NAME_SIZE - (size_t)1);
118 /* null-terminate if len(src) >= NAME_SIZE. */
119 dest[NAME_SIZE - 1] = '\0';
120}
121
127 SOCKINFO* info,
129 int error_code,
131 const char* err_msg,
133 http_message_t* hmsg) {
134 off_t content_length;
135 int timeout_secs = UPNP_TIMEOUT;
136 int major;
137 int minor;
138 const char* start_body =
139 /* "<?xml version=\"1.0\"?>\n" required?? */
140 "<s:Envelope "
141 "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
142 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/"
143 "\">\n"
144 "<s:Body>\n"
145 "<s:Fault>\n"
146 "<faultcode>s:Client</faultcode>\n"
147 "<faultstring>UPnPError</faultstring>\n"
148 "<detail>\n"
149 "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"
150 "<errorCode>";
151 const char* mid_body = "</errorCode>\n"
152 "<errorDescription>";
153 const char* end_body = "</errorDescription>\n"
154 "</UPnPError>\n"
155 "</detail>\n"
156 "</s:Fault>\n"
157 "</s:Body>\n"
158 "</s:Envelope>\n";
159 char err_code_str[30];
160 membuffer headers;
161
162 memset(err_code_str, 0, sizeof(err_code_str));
163 snprintf(err_code_str, sizeof(err_code_str), "%d", error_code);
164 /* calc body len */
165 content_length =
166 (off_t)(strlen(start_body) + strlen(err_code_str) + strlen(mid_body) +
167 strlen(err_msg) + strlen(end_body));
169 &minor);
170 /* make headers */
171 membuffer_init(&headers);
172 if (http_MakeMessage(&headers, major, minor,
173 "RNsDsSXcc"
174 "sssss",
175 500, content_length, ContentTypeHeader, "EXT:\r\n",
176 X_USER_AGENT, start_body, err_code_str, mid_body,
177 err_msg, end_body) != 0) {
178 membuffer_destroy(&headers);
179 /* out of mem */
180 return;
181 }
182 /* send err msg */
183 http_SendMessage(info, &timeout_secs, "b", headers.buf, headers.length);
184 membuffer_destroy(&headers);
185}
186
192 SOCKINFO* info,
194 const char* var_value,
196 http_message_t* hmsg) {
197 off_t content_length;
198 int timeout_secs = UPNP_TIMEOUT;
199 int major;
200 int minor;
201 const char* start_body =
202 "<s:Envelope "
203 "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
204 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/"
205 "\">\n"
206 "<s:Body>\n"
207 "<u:QueryStateVariableResponse "
208 "xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n"
209 "<return>";
210 const char* end_body = "</return>\n"
211 "</u:QueryStateVariableResponse>\n"
212 "</s:Body>\n"
213 "</s:Envelope>\n";
214 membuffer response;
215
217 &minor);
218 content_length =
219 (off_t)(strlen(start_body) + strlen(var_value) + strlen(end_body));
220 /* make headers */
221 membuffer_init(&response);
222 if (http_MakeMessage(&response, major, minor,
223 "RNsDsSXcc"
224 "sss",
225 HTTP_OK, content_length, ContentTypeHeader, "EXT:\r\n",
226 X_USER_AGENT, start_body, var_value, end_body) != 0) {
227 membuffer_destroy(&response);
228 /* out of mem */
229 return;
230 }
231 /* send msg */
232 http_SendMessage(info, &timeout_secs, "b", response.buf, response.length);
233 membuffer_destroy(&response);
234}
235
241 SOCKINFO* info,
243 IXML_Document* action_resp,
245 http_message_t* request) {
246 char* xml_response = NULL;
247 membuffer headers;
248 int major, minor;
249 int err_code;
250 off_t content_length;
251 int ret_code;
252 int timeout_secs = UPNP_TIMEOUT;
253 static const char* start_body =
254 /*"<?xml version=\"1.0\"?>" required?? */
255 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap."
256 "org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap."
257 "org/soap/encoding/\"><s:Body>\n";
258 static const char* end_body = "</s:Body> </s:Envelope>";
259
260 /* init */
262 &major, &minor);
263 membuffer_init(&headers);
264 err_code = UPNP_E_OUTOF_MEMORY; /* one error only */
265 /* get xml */
266 xml_response = ixmlPrintNode((IXML_Node*)action_resp);
267 if (!xml_response)
268 goto error_handler;
269 content_length =
270 (off_t)(strlen(start_body) + strlen(xml_response) + strlen(end_body));
271 /* make headers */
273 &headers, major, minor, "RNsDsSXcc", HTTP_OK, /* status code */
274 content_length, ContentTypeHeader, "EXT:\r\n", X_USER_AGENT) != 0) {
275 goto error_handler;
276 }
277 /* send whole msg */
278 ret_code = http_SendMessage(info, &timeout_secs, "bbbb", headers.buf,
279 headers.length, start_body, strlen(start_body),
280 xml_response, strlen(xml_response), end_body,
281 strlen(end_body));
282 if (ret_code != 0) {
283 UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
284 "Failed to send response: err code = %d\n", ret_code);
285 }
286 err_code = 0;
287
288error_handler:
289 ixmlFreeDOMString(xml_response);
290 membuffer_destroy(&headers);
291 if (err_code != 0) {
292 /* only one type of error to worry about - out of mem */
293 send_error_response(info, SOAP_ACTION_FAILED, "Out of memory", request);
294 }
295}
296
304 SOCKINFO* info,
306 http_message_t* request,
308 soap_devserv_t* soap_info,
310 IXML_Node* req_node) {
312 const char* err_str;
313 int err_code;
314 const DOMString var_name;
315
316 /* set default error */
317 err_code = SOAP_INVALID_VAR;
318 err_str = Soap_Invalid_Var;
319
320 if (variable == NULL) {
321 err_code = SOAP_MEMORY_OUT;
322 err_str = Soap_Memory_out;
323 goto error_handler;
324 }
325
327 UpnpStateVarRequest_strcpy_DevUDN(variable, soap_info->dev_udn);
328 UpnpStateVarRequest_strcpy_ServiceID(variable, soap_info->service_id);
329 var_name = ixmlNode_getNodeValue(req_node);
330 UpnpStateVarRequest_strcpy_StateVarName(variable, var_name);
332
333 /* send event */
334 soap_info->callback(UPNP_CONTROL_GET_VAR_REQUEST, variable,
335 soap_info->cookie);
336 UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
337 "Return from callback for var request\n");
338 /* validate, and handle result */
339 if (UpnpStateVarRequest_get_CurrentVal(variable) == NULL)
340 goto error_handler;
343 0) {
344 err_code = UpnpStateVarRequest_get_ErrCode(variable);
345 err_str = UpnpStateVarRequest_get_ErrStr_cstr(variable);
346 }
347 goto error_handler;
348 }
349 /* send response */
351 request);
352 err_code = 0;
353
354 /* error handling and cleanup */
355error_handler:
357 if (err_code != 0)
358 send_error_response(info, err_code, err_str, request);
359}
360
366 SOCKINFO* info,
368 http_message_t* request,
370 soap_devserv_t* soap_info,
372 IXML_Node* req_node) {
373 char save_char;
375 IXML_Document* actionRequestDoc = NULL;
376 IXML_Document* actionResultDoc = NULL;
377 int err_code;
378 const char* err_str{};
379 memptr action_name;
380 DOMString act_node = NULL;
381 memptr hdr_value;
382
383 /* null-terminate */
384 action_name = soap_info->action_name;
385 save_char = action_name.buf[action_name.length];
386 action_name.buf[action_name.length] = '\0';
387 /* get action node */
388 act_node = ixmlPrintNode(req_node);
389 if (!act_node) {
390 err_code = SOAP_MEMORY_OUT;
391 err_str = Soap_Memory_out;
392 goto error_handler;
393 }
394 err_code = ixmlParseBufferEx(act_node, &actionRequestDoc);
395 if (err_code != IXML_SUCCESS) {
396 if (IXML_INSUFFICIENT_MEMORY == err_code) {
397 err_code = SOAP_MEMORY_OUT;
398 err_str = Soap_Memory_out;
399 } else {
400 err_code = SOAP_INVALID_ACTION;
401 err_str = Soap_Invalid_Action;
402 }
403 goto error_handler;
404 }
406 UpnpActionRequest_strcpy_ActionName(action, action_name.buf);
407 UpnpActionRequest_strcpy_DevUDN(action, soap_info->dev_udn);
408 UpnpActionRequest_strcpy_ServiceID(action, soap_info->service_id);
409 UpnpActionRequest_set_ActionRequest(action, actionRequestDoc);
412
413 if (httpmsg_find_hdr(request, HDR_USER_AGENT, &hdr_value) != NULL) {
414 UpnpActionRequest_strncpy_Os(action, hdr_value.buf, hdr_value.length);
415 }
416
417 UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__, "Calling Callback\n");
418 soap_info->callback(UPNP_CONTROL_ACTION_REQUEST, action, soap_info->cookie);
419 err_code = UpnpActionRequest_get_ErrCode(action);
420 if (err_code != UPNP_E_SUCCESS) {
421 err_str = UpnpActionRequest_get_ErrStr_cstr(action);
422 if (strlen(err_str) <= 0) {
423 err_code = SOAP_ACTION_FAILED;
424 err_str = Soap_Action_Failed;
425 }
426 goto error_handler;
427 }
428 /* validate, and handle action error */
429 actionResultDoc = UpnpActionRequest_get_ActionResult(action);
430 if (actionResultDoc == NULL) {
431 err_code = SOAP_ACTION_FAILED;
432 err_str = Soap_Action_Failed;
433 goto error_handler;
434 }
435 /* send response */
436 send_action_response(info, actionResultDoc, request);
437 err_code = 0;
438
439 /* error handling and cleanup */
440error_handler:
441 ixmlDocument_free(actionResultDoc);
442 ixmlDocument_free(actionRequestDoc);
443 ixmlFreeDOMString(act_node);
444 /* restore */
445 action_name.buf[action_name.length] = save_char;
446 if (err_code != 0)
447 send_error_response(info, err_code, err_str, request);
449}
450
463 http_message_t* request,
465 int AddressFamily,
467 soap_devserv_t* soap_info) {
468 struct Handle_Info* device_info;
469 int device_hnd;
470 service_info* serv_info;
471 char save_char;
472 /* error by default */
473 int ret_code = -1;
474 const char* control_url;
475
476 /* null-terminate pathquery of url */
477 control_url = request->uri.pathquery.buff;
478 save_char = control_url[request->uri.pathquery.size];
479 ((char*)control_url)[request->uri.pathquery.size] = '\0';
480
482
483 if (GetDeviceHandleInfoForPath(control_url, AddressFamily, &device_hnd,
484 &device_info, &serv_info) != HND_DEVICE)
485 goto error_handler;
486 if (!serv_info)
487 goto error_handler;
488
489 namecopy(soap_info->dev_udn, serv_info->UDN);
490 namecopy(soap_info->service_type, serv_info->serviceType);
491 namecopy(soap_info->service_id, serv_info->serviceId);
492 soap_info->callback = device_info->Callback;
493 soap_info->cookie = device_info->Cookie;
494 ret_code = 0;
495
496error_handler:
497 /* restore */
498 ((char*)control_url)[request->uri.pathquery.size] = save_char;
499 HandleUnlock();
500 return ret_code;
501}
502
515 http_message_t* request,
517 memptr* val) {
518 http_header_t* hdr;
519 memptr ns_value, dummy_quote, value;
520 membuffer soap_action_name;
521
522 assert(HTTPMETHOD_MPOST == request->method);
523 hdr = httpmsg_find_hdr(request, HDR_MAN, &value);
524 if (NULL == hdr)
525 return SREQ_NOT_EXTENDED;
526 if (matchstr(value.buf, value.length, "%q%i ; ns = %s", &dummy_quote,
527 &ns_value) != PARSE_OK)
528 return SREQ_NOT_EXTENDED;
529 /* create soapaction name header */
530 membuffer_init(&soap_action_name);
531 if (membuffer_assign(&soap_action_name, ns_value.buf, ns_value.length) ==
533 membuffer_append_str(&soap_action_name, "-SOAPACTION") ==
535 membuffer_destroy(&soap_action_name);
536 return UPNP_E_OUTOF_MEMORY;
537 }
538 hdr = httpmsg_find_hdr_str(request, soap_action_name.buf);
539 membuffer_destroy(&soap_action_name);
540 if (NULL == hdr)
541 return SREQ_HDR_NOT_FOUND;
542 val->buf = hdr->value.buf;
543 val->length = hdr->value.length;
544 return UPNP_E_SUCCESS;
545}
546
563 http_message_t* request,
565 soap_devserv_t* soap_info) {
566 memptr value;
567 char save_char;
568 char* hash_pos = NULL;
569 char *col_pos1, *col_pos2, *serv_type;
570 size_t cp1_diff;
571 int ret_code;
572
573 /* find SOAPACTION header */
574 if (SOAPMETHOD_POST == request->method) {
575 if (!httpmsg_find_hdr(request, HDR_SOAPACTION, &value))
576 return SREQ_HDR_NOT_FOUND;
577 } else {
578 ret_code = get_mpost_acton_hdrval(request, &value);
579 if (ret_code != UPNP_E_SUCCESS) {
580 return ret_code;
581 }
582 }
583
584 /* error by default */
585 ret_code = SREQ_BAD_HDR_FORMAT;
586 /* get action name*/
587 save_char = value.buf[value.length];
588 value.buf[value.length] = '\0';
589 hash_pos = strchr(value.buf, '#');
590 if (NULL == hash_pos) {
591 goto error_handler;
592 }
593 *hash_pos = '\0';
594 if (matchstr(hash_pos + 1,
595 value.length - (size_t)(hash_pos + 1 - value.buf), "%s",
596 &soap_info->action_name) != PARSE_OK) {
597 goto error_handler;
598 }
599
600 /* check service type */
601 if (value.buf[0] != '\"') {
602 serv_type = &value.buf[0];
603 } else {
604 serv_type = &value.buf[1];
605 }
606 col_pos1 = strrchr(serv_type, ':');
607 if (NULL == col_pos1) {
608 goto error_handler;
609 }
610 col_pos2 = strrchr(soap_info->service_type, ':');
611 /* XXX: this should be checked when service list is generated */
612 assert(col_pos2 != NULL);
613 cp1_diff = (size_t)(col_pos1 - serv_type);
614 if (col_pos2 - soap_info->service_type == col_pos1 - serv_type &&
615 strncmp(soap_info->service_type, serv_type, cp1_diff) == 0) {
616 /* for action invocation, update the version information */
617 namecopy(soap_info->service_type, serv_type);
618 } else if (strcmp(serv_type, QUERY_STATE_VAR_URN) == 0 &&
619 memptr_cmp(&soap_info->action_name, "QueryStateVariable") == 0) {
620 /* query variable */
621 soap_info->action_name.buf = NULL;
622 soap_info->action_name.length = 0;
623 } else {
624 goto error_handler;
625 }
626 ret_code = UPNP_E_SUCCESS;
627
628error_handler:
629 if (hash_pos != NULL) {
630 *hash_pos = '#';
631 }
632 value.buf[value.length] = save_char;
633 return ret_code;
634}
635
645 soap_devserv_t* soap_info,
647 IXML_Document* xml_doc,
649 IXML_Node** req_node) {
650 IXML_Node* envp_node = NULL;
651 IXML_Node* body_node = NULL;
652 IXML_Node* action_node = NULL;
653 const DOMString local_name = NULL;
654 const DOMString ns_uri = NULL;
655 int ret_val = -1;
656
657 /* Got the Envelop node here */
658 envp_node = ixmlNode_getFirstChild((IXML_Node*)xml_doc);
659 if (NULL == envp_node) {
660 goto error_handler;
661 }
662 ns_uri = ixmlNode_getNamespaceURI(envp_node);
663 if (NULL == ns_uri || strcmp(ns_uri, SOAP_URN) != 0) {
664 goto error_handler;
665 }
666 /* Got Body here */
667 body_node = ixmlNode_getFirstChild(envp_node);
668 if (NULL == body_node) {
669 goto error_handler;
670 }
671 local_name = ixmlNode_getLocalName(body_node);
672 if (NULL == local_name || strcmp(local_name, SOAP_BODY) != 0) {
673 goto error_handler;
674 }
675 /* Got action node here */
676 action_node = ixmlNode_getFirstChild(body_node);
677 if (NULL == action_node) {
678 goto error_handler;
679 }
680 /* check local name and namespace of action node */
681 ns_uri = ixmlNode_getNamespaceURI(action_node);
682 if (NULL == ns_uri) {
683 goto error_handler;
684 }
685 local_name = ixmlNode_getLocalName(action_node);
686 if (NULL == local_name) {
687 goto error_handler;
688 }
689 if (NULL == soap_info->action_name.buf) {
690 IXML_Node* varname_node = NULL;
691 IXML_Node* nametxt_node = NULL;
692 if (strcmp(ns_uri, QUERY_STATE_VAR_URN) != 0 ||
693 strcmp(local_name, "QueryStateVariable") != 0) {
694 goto error_handler;
695 }
696 varname_node = ixmlNode_getFirstChild(action_node);
697 if (NULL == varname_node) {
698 goto error_handler;
699 }
700 local_name = ixmlNode_getLocalName(varname_node);
701 if (strcmp(local_name, "varName") != 0) {
702 goto error_handler;
703 }
704 nametxt_node = ixmlNode_getFirstChild(varname_node);
705 if (NULL == nametxt_node ||
706 ixmlNode_getNodeType(nametxt_node) != eTEXT_NODE) {
707 goto error_handler;
708 }
709 *req_node = nametxt_node;
710 } else {
711 /* check service type against SOAPACTION header */
712 if (strcmp(soap_info->service_type, ns_uri) != 0 ||
713 memptr_cmp(&soap_info->action_name, local_name) != 0) {
714 goto error_handler;
715 }
716 *req_node = action_node;
717 }
718 /* success */
719 ret_val = 0;
720
721error_handler:
722 return ret_val;
723}
724
726} // anonymous namespace
727
728
737 http_parser_t* parser,
739 http_message_t* request,
741 SOCKINFO* info) {
742 int err_code;
743 IXML_Document* xml_doc = NULL;
744 soap_devserv_t* soap_info = NULL;
745 IXML_Node* req_node = NULL;
746 (void)parser;
747
748 /* get device/service identified by the request-URI */
749 soap_info = (soap_devserv_t*)malloc(sizeof(soap_devserv_t));
750 if (NULL == soap_info) {
751 err_code = HTTP_INTERNAL_SERVER_ERROR;
752 goto error_handler;
753 }
754 if (get_dev_service(request, info->foreign_sockaddr.ss_family, soap_info) <
755 0) {
756 err_code = HTTP_NOT_FOUND;
757 goto error_handler;
758 }
759 /* validate: content-type == text/xml */
760 if (!has_xml_content_type(request)) {
761 err_code = HTTP_UNSUPPORTED_MEDIA_TYPE;
762 goto error_handler;
763 }
764 /* check SOAPACTION HTTP header */
765 err_code = check_soapaction_hdr(request, soap_info);
766 if (err_code != UPNP_E_SUCCESS) {
767 switch (err_code) {
769 err_code = HTTP_NOT_EXTENDED;
770 break;
772 err_code = HTTP_INTERNAL_SERVER_ERROR;
773 break;
774 default:
775 err_code = HTTP_BAD_REQUEST;
776 break;
777 }
778 goto error_handler;
779 }
780 /* parse XML */
781 err_code = ixmlParseBufferEx(request->entity.buf, &xml_doc);
782 if (err_code != IXML_SUCCESS) {
783 if (IXML_INSUFFICIENT_MEMORY == err_code)
784 err_code = HTTP_INTERNAL_SERVER_ERROR;
785 else
786 err_code = HTTP_BAD_REQUEST;
787 goto error_handler;
788 }
789 /* check SOAP body */
790 if (check_soap_request(soap_info, xml_doc, &req_node) < 0) {
791 err_code = HTTP_BAD_REQUEST;
792 goto error_handler;
793 }
794 /* process SOAP request */
795 if (NULL == soap_info->action_name.buf)
796 /* query var */
797 handle_query_variable(info, request, soap_info, req_node);
798 else
799 /* invoke action */
800 handle_invoke_action(info, request, soap_info, req_node);
801
802 err_code = HTTP_OK;
803
804error_handler:
805 ixmlDocument_free(xml_doc);
806 free(soap_info);
807 if (err_code != HTTP_OK) {
808 http_SendStatusResponse(info, err_code, request->major_version,
809 request->minor_version);
810 }
811 return;
812}
@ UPNP_CONTROL_GET_VAR_REQUEST
Definition Callback.hpp:39
@ UPNP_CONTROL_ACTION_REQUEST
Definition Callback.hpp:28
int(* Upnp_FunPtr)(Upnp_EventType EventType, const void *Event, void *Cookie)
Definition Callback.hpp:143
#define NAME_SIZE
Definition API.hpp:46
int http_SendMessage(SOCKINFO *info, int *TimeOut, const char *fmt,...)
Sends a message to the destination based on the format parameter.
void http_CalcResponseVersion(int request_major_vers, int request_minor_vers, int *response_major_vers, int *response_minor_vers)
Calculate HTTP response versions based on the request versions.
int http_SendStatusResponse(SOCKINFO *info, int http_status_code, int request_major_version, int request_minor_version)
Generate a response message for the status query and send the status response.
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.
uri_type uri
Type of a uri, e.g. absolute, relative, etc.
http_method_t method
Http method of an outgoing request.
int major_version
Http major version.
memptr entity
message body(entity).
membuffer value
Raw-value; could be multi-lined; min-length = 0.
#define HDR_MAN
Type of a HTTP header.
#define HDR_USER_AGENT
Type of a HTTP header.
@ PARSE_OK
#define HDR_SOAPACTION
Type of a HTTP header.
int minor_version
Http minor version.
Structure of an HTTP parser object.
Structure of an HTTP message.
Structure of an HTTP header object.
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
#define X_USER_AGENT
Can be overwritten by configure CFLAGS argument.
Definition webserver.hpp:87
s_UpnpActionRequest
PUPNP_Api int UpnpActionRequest_get_ErrCode(const UpnpActionRequest *p)
PUPNP_Api int UpnpActionRequest_strncpy_Os(UpnpActionRequest *p, const char *s, size_t n)
PUPNP_Api void UpnpActionRequest_delete(UpnpActionRequest *p)
PUPNP_Api IXML_Document * UpnpActionRequest_get_ActionResult(const UpnpActionRequest *p)
PUPNP_Api int UpnpActionRequest_strcpy_ServiceID(UpnpActionRequest *p, const char *s)
PUPNP_Api int UpnpActionRequest_strcpy_DevUDN(UpnpActionRequest *p, const char *s)
PUPNP_Api const char * UpnpActionRequest_get_ErrStr_cstr(const UpnpActionRequest *p)
PUPNP_Api int UpnpActionRequest_set_ActionRequest(UpnpActionRequest *p, IXML_Document *n)
PUPNP_Api UpnpActionRequest * UpnpActionRequest_new(void)
PUPNP_Api int UpnpActionRequest_set_ErrCode(UpnpActionRequest *p, int n)
PUPNP_Api int UpnpActionRequest_set_ActionResult(UpnpActionRequest *p, IXML_Document *n)
PUPNP_Api int UpnpActionRequest_strcpy_ActionName(UpnpActionRequest *p, const char *s)
PUPNP_Api int UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, const struct sockaddr_storage *buf)
With header typedef "protected" s_UpnpStateVarRequest.
Header file for UpnpStateVarRequest methods.
PUPNP_Api int UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, const struct sockaddr_storage *buf)
PUPNP_Api const char * UpnpStateVarRequest_get_ErrStr_cstr(const UpnpStateVarRequest *p)
PUPNP_Api int UpnpStateVarRequest_set_ErrCode(UpnpStateVarRequest *p, int n)
PUPNP_Api UpnpStateVarRequest * UpnpStateVarRequest_new(void)
PUPNP_Api int UpnpStateVarRequest_get_ErrCode(const UpnpStateVarRequest *p)
PUPNP_Api const UpnpString * UpnpStateVarRequest_get_ErrStr(const UpnpStateVarRequest *p)
PUPNP_Api int UpnpStateVarRequest_strcpy_DevUDN(UpnpStateVarRequest *p, const char *s)
PUPNP_Api int UpnpStateVarRequest_strcpy_ServiceID(UpnpStateVarRequest *p, const char *s)
PUPNP_Api int UpnpStateVarRequest_strcpy_StateVarName(UpnpStateVarRequest *p, const char *s)
PUPNP_Api void UpnpStateVarRequest_delete(UpnpStateVarRequest *p)
PUPNP_Api const DOMString UpnpStateVarRequest_get_CurrentVal(const UpnpStateVarRequest *p)
PUPNP_Api size_t UpnpString_get_Length(const UpnpString *p)
Returns the length of the string.
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 unsigned short ixmlNode_getNodeType(IXML_Node *nodeptr)
Retrieves the type of a Node. Note that not all possible return values are actually implemented.
Definition node.cpp:326
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 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_getLocalName(IXML_Node *nodeptr)
Retrieves the local name of a Node, if present.
Definition node.cpp:187
PUPNP_Api void ixmlFreeDOMString(DOMString buf)
Frees a DOMString.
Definition ixml.cpp:418
PUPNP_Api const DOMString ixmlNode_getNamespaceURI(IXML_Node *nodeptr)
Retrieves the namespace URI for a Node as a DOMString.
Definition node.cpp:276
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
http_header_t * httpmsg_find_hdr_str(http_message_t *msg, const char *header_name)
Compares the header name with the header names stored in the linked list of messages.
http_header_t * httpmsg_find_hdr(http_message_t *msg, int header_name_id, memptr *value)
Finds header from a list, with the given 'name_id'.
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.
int memptr_cmp(memptr *m, const char *s)
Compares characters of strings passed for number of bytes. If equal for the number of bytes,...
Definition membuffer.cpp:70
void membuffer_destroy(membuffer *m)
Free's memory allocated for membuffer* m.
void membuffer_init(membuffer *m)
Wrapper to membuffer_initialize().
int membuffer_append_str(membuffer *m, const char *c_str)
Invokes function to appends data from a constant string to the buffer.
int membuffer_assign(membuffer *m, const void *buf, size_t buf_len)
Allocate memory to membuffer *m and copy the contents of the in parameter const void *buf.
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_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
void send_action_response(SOCKINFO *info, IXML_Document *action_resp, http_message_t *request)
Sends the SOAP action response.
int get_dev_service(http_message_t *request, int AddressFamily, soap_devserv_t *soap_info)
Retrieve SOAP device/service information associated with request-URI.
constexpr char Soap_Invalid_Action[]
UPnP Device SOAP strings.
constexpr char Soap_Memory_out[]
UPnP Device SOAP strings.
constexpr char QUERY_STATE_VAR_URN[]
UPnP Device SOAP strings.
constexpr int SOAP_MEMORY_OUT
UPnP Device SOAP status.
int get_mpost_acton_hdrval(http_message_t *request, memptr *val)
Get the SOAPACTION header value for M-POST request.
constexpr int SOAP_INVALID_ACTION
UPnP Device SOAP status.
constexpr int SREQ_HDR_NOT_FOUND
UPnP Device SOAP status.
constexpr char SOAP_URN[]
UPnP Device SOAP strings.
int check_soapaction_hdr(http_message_t *request, soap_devserv_t *soap_info)
Check header validity, get action name and version of service.
constexpr int SREQ_NOT_EXTENDED
UPnP Device SOAP status.
int check_soap_request(soap_devserv_t *soap_info, IXML_Document *xml_doc, IXML_Node **req_node)
Check validity of the SOAP request per UPnP specification.
void namecopy(char dest[NAME_SIZE], const char *src)
Copy string with length NAME_SIZE and terminate with '\0'.
constexpr char SOAP_BODY[]
UPnP Device SOAP strings.
constexpr int SREQ_BAD_HDR_FORMAT
UPnP Device SOAP status.
constexpr char Soap_Invalid_Var[]
UPnP Device SOAP strings.
void send_var_query_response(SOCKINFO *info, const char *var_value, http_message_t *hmsg)
Sends response of get var status.
constexpr char Soap_Action_Failed[]
UPnP Device SOAP strings.
void handle_query_variable(SOCKINFO *info, http_message_t *request, soap_devserv_t *soap_info, IXML_Node *req_node)
Handles the SOAP requests to querry the state variables.
constexpr int SOAP_ACTION_FAILED
UPnP Device SOAP status.
void handle_invoke_action(SOCKINFO *info, http_message_t *request, soap_devserv_t *soap_info, IXML_Node *req_node)
Handles the SOAP action request.
void send_error_response(SOCKINFO *info, int error_code, const char *err_msg, http_message_t *hmsg)
Sends SOAP error response.
constexpr int SOAP_INVALID_VAR
UPnP Device SOAP status.
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.
DOMString UDN
Part of Service information.
DOMString serviceId
Part of Service information.
DOMString serviceType
Part of Service information.
-brief Service information
Common SOAP declarations used for SOAP Devices and SOAP Control Points.
constexpr char ContentTypeHeader[]
Common SOAP constant string specifying the content type header.
void soap_device_callback(http_parser_t *parser, http_message_t *request, SOCKINFO *info)
This is a callback called by minisever after receiving the request from the control point.
SOAP declarations for UPnP Devices using SOAP.
sockaddr_storage foreign_sockaddr
Socket address of the remote node only filled in incoming requests.
Definition sock.hpp:69
Additional socket information for connections and ssl.
Definition sock.hpp:65
Manage "Step 1: Discovery" of the UPnP+™ specification with SSDP.
HTTP status codes.
Upnp_Handle_Type GetDeviceHandleInfoForPath(const char *path, int AddressFamily, UpnpDevice_Handle *device_handle_out, struct Handle_Info **HndInfo, service_info **serv_info)
Retrieves the device handle and information of the first device of the address family specified,...
Definition upnpapi.cpp:3305
Inititalize the compatible library before it can be used.
#define UPNP_TIMEOUT
UPNP_TIMEOUT.
Definition upnpapi.hpp:71
#define HandleUnlock()
HandleUnlock.
Definition upnpapi.hpp:147
char * Cookie
???
Definition upnpapi.hpp:87
Upnp_FunPtr Callback
Callback function pointer.
Definition upnpapi.hpp:86
#define HandleReadLock()
HandleReadLock.
Definition upnpapi.hpp:144
Data to be stored in handle table for Handle Info.
Definition upnpapi.hpp:84
UPnPsdk_VIS void UpnpPrintf(Upnp_LogLevel DLevel, Dbg_Module Module, const char *DbgFileName, int DbgLineNo, const char *FmtStr,...)
Prints the debug statement.