43#include <httpreadwrite.hpp>
52#include <umock/stdlib.hpp>
53#include <umock/stdio.hpp>
55#ifndef COMPA_INTERNAL_CONFIG_HPP
56#error "No or wrong config.hpp header file included."
59#ifndef COMPA_NET_HTTP_WEBSERVER_HPP
60#error "No or wrong webserver.hpp header file included."
105 CXmlAlias(){TRACE2(
this,
" Construct CXmlAlias()")}
110 TRACE2(
this,
" Executing CXmlAlias copy constructor()")
112 ::pthread_mutex_lock(&m_web_mutex);
113 this->m_name = that.m_name;
114 this->m_last_modified = that.m_last_modified;
115 if (that.m_doc.data() ==
nullptr) {
116 this->m_ct = that.m_ct;
117 this->m_doc = that.m_doc;
120 const size_t doc_len{that.m_doc.length()};
121 char* doc =
static_cast<char*
>(malloc(doc_len));
122 memcpy(doc, that.m_doc.data(), doc_len);
123 this->m_doc = std::string_view(doc, doc_len);
125 ::pthread_mutex_unlock(&m_web_mutex);
131 TRACE2(
this,
" Executing CXmlAlias assignment operator=")
135 std::swap(this->m_name, that.m_name);
136 std::swap(this->m_doc, that.m_doc);
137 std::swap(this->m_last_modified, that.m_last_modified);
138 std::swap(this->m_ct, that.m_ct);
147 TRACE2(
this,
" Destruct CXmlAlias()")
148 this->clear_private();
149 if (::pthread_mutex_destroy(&m_web_mutex) != 0)
151 "MSG1150")
"fails with EBUSY. The mutex is currently locked.\n";
164 int set(
const char* a_alias_name,
const char*& a_alias_content,
165 size_t& a_alias_content_length,
166 time_t a_last_modified = time(
nullptr)) {
167 TRACE2(
this,
" Executing CXmlAlias::set()")
168 ::pthread_mutex_lock(&m_web_mutex);
170 if (a_alias_name ==
nullptr) {
172 this->release_private();
173 ::pthread_mutex_unlock(&m_web_mutex);
176 if (a_alias_content ==
nullptr) {
177 ::pthread_mutex_unlock(&m_web_mutex);
180 this->release_private();
183 if (*a_alias_name !=
'/')
185 m_name += a_alias_name;
187 "MSG1133")
"attaching allocated document, take ownership.\n";
188 m_doc = std::string_view(a_alias_content, a_alias_content_length);
189 m_last_modified = a_last_modified;
190 a_alias_content =
nullptr;
191 a_alias_content_length = 0;
194 ::pthread_mutex_unlock(&m_web_mutex);
200 std::string_view
name()
const {
201 TRACE2(
this,
" Executing CXmlAlias::name()")
202 ::pthread_mutex_lock(&m_web_mutex);
203 std::string_view name = m_name;
204 ::pthread_mutex_unlock(&m_web_mutex);
210 std::string_view
doc()
const {
211 TRACE2(
this,
" Executing CXmlAlias::doc()")
212 ::pthread_mutex_lock(&m_web_mutex);
213 std::string_view doc = m_doc;
214 ::pthread_mutex_unlock(&m_web_mutex);
222 TRACE2(
this,
" Executing CXmlAlias::last_modified()")
223 ::pthread_mutex_lock(&m_web_mutex);
224 auto last_modified = m_last_modified;
225 ::pthread_mutex_unlock(&m_web_mutex);
226 return last_modified;
232 TRACE2(
this,
" Executing CXmlAlias::is_valid()")
233 ::pthread_mutex_lock(&m_web_mutex);
234 auto doc = m_doc.data();
235 ::pthread_mutex_unlock(&m_web_mutex);
236 return doc !=
nullptr;
242 TRACE2(
this,
" Executing CXmlAlias::release()")
243 ::pthread_mutex_lock(&m_web_mutex);
244 this->release_private();
245 ::pthread_mutex_unlock(&m_web_mutex);
251 TRACE2(
this,
" Executing CXmlAlias::clear()")
252 ::pthread_mutex_lock(&m_web_mutex);
253 this->clear_private();
254 ::pthread_mutex_unlock(&m_web_mutex);
259 mutable ::pthread_mutex_t m_web_mutex = PTHREAD_MUTEX_INITIALIZER;
265 std::string_view m_doc{std::string_view(
nullptr, 0)};
268 time_t m_last_modified{};
279 inline void release_private() {
284 this->clear_private();
290 inline void clear_private() {
296 if (m_doc.data() !=
nullptr) {
297 UPnPsdk_LOGINFO(
"MSG1118")
"freeing attached allocated document.\n";
298 ::free(
const_cast<char*
>(m_doc.data()));
299 m_doc = std::string_view(
nullptr, 0);
314#if defined(_WIN32) || defined(DOXYGEN_RUN)
319 if (tm == NULL || buf == NULL)
326#define web_server_asctime_r asctime_r
347 const char* a_extension,
348 const char** a_con_type,
349 const char** a_con_subtype
351 TRACE(
"Executing search_extension()")
356 if (filetype ==
nullptr) {
357 TRACE(
" search_extension: return with -1")
360 *a_con_type = filetype->
type.c_str();
361 *a_con_subtype = filetype->
subtype.c_str();
380 const char* filename,
388 const char* extension;
390 const char* subtype{};
398 extension = strrchr(filename,
'.');
399 if (extension != NULL) {
406 subtype =
"octet-stream";
408 length = strlen(type) + strlen(
"/") + strlen(subtype) + 1;
409 temp = (
char*)malloc(length);
412 rc = snprintf(temp, length,
"%s/%s", type, subtype);
413 if (rc < 0 || (
unsigned int)rc >= length) {
414 umock::stdlib_h.free(temp);
418 umock::stdlib_h.free(temp);
432 const char* filename,
442 time_t aux_LastModified;
448 umock::stdio_h.fopen_s(&fp, filename,
"r");
450 fp = umock::stdio_h.fopen(filename,
"r");
463 code = fstat(fd, &s);
468 umock::stdio_h.fclose(fp);
470 if (S_ISDIR(s.st_mode)) {
472 }
else if (S_ISREG(s.st_mode)) {
482 UPnPsdk_LOGINFO(
"MSG1108")
"webserver file info=\""
490 umock::stdio_h.fclose(fp);
507 const char* request_file,
513 int cmp = strcmp(alias->
name().data(), request_file);
516 static_cast<off_t
>(alias->
doc().length()));
536 const void** cookie) {
541 while (pCurVirtualDir != NULL) {
542 webDirLen = strlen(pCurVirtualDir->
dirName);
544 if (pCurVirtualDir->
dirName[webDirLen - 1] ==
'/') {
545 if (strncmp(pCurVirtualDir->
dirName, filePath, webDirLen) ==
548 *cookie = pCurVirtualDir->
cookie;
552 if (strncmp(pCurVirtualDir->
dirName, filePath, webDirLen) ==
554 (filePath[webDirLen] ==
'/' ||
555 filePath[webDirLen] ==
'\0' ||
556 filePath[webDirLen] ==
'?')) {
558 *cookie = pCurVirtualDir->
cookie;
563 pCurVirtualDir = pCurVirtualDir->
next;
576 *s =
static_cast<char>(std::toupper(
static_cast<unsigned char>(*s)));
604 Ptr = strstr(Str1, Str2);
608 ret = s1 + (Ptr - Str1);
610 umock::stdlib_h.free(Str2);
612 umock::stdlib_h.free(Str1);
632 TmpPtr = strstr(*Src, Del);
633 if (TmpPtr != NULL) {
635 *Src = TmpPtr + strlen(Del);
662 int Is_Suffix_byte_Range = 1;
664 if (*SrcRangeStr == NULL)
666 Tok =
StrTok(SrcRangeStr,
",");
667 if ((Ptr = strstr(Tok,
"-")) == NULL)
671 sscanf_s(Tok,
"%" SCNd64
"%" SCNd64, &F, &L);
673 sscanf(Tok,
"%" SCNd64
"%" SCNd64, &F, &L);
675 if (F == -1 || L == -1) {
677 for (i = 0; i < (int)strlen(Tok); i++) {
680 }
else if (isdigit(Tok[i])) {
681 Is_Suffix_byte_Range = 0;
685 if (Is_Suffix_byte_Range) {
686 *FirstByte = (off_t)L;
687 *LastByte = (off_t)F;
691 *FirstByte = (off_t)F;
692 *LastByte = (off_t)L;
709 char* ByteRangeSpecifier,
715 off_t FirstByte, LastByte;
722 if (!ByteRangeSpecifier)
723 return HTTP_BAD_REQUEST;
724 RangeInput = strdup(ByteRangeSpecifier);
726 return HTTP_INTERNAL_SERVER_ERROR;
728 if (
StrStr(RangeInput,
"bytes") == NULL ||
729 (Ptr =
StrStr(RangeInput,
"=")) == NULL) {
730 umock::stdlib_h.free(RangeInput);
732 return HTTP_BAD_REQUEST;
736 if (FileLength < 0) {
737 int ret = HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
738 if ((*Ptr ==
'0') && (*(Ptr + 1) ==
'-') && (*(Ptr + 2) ==
'\0')) {
742 umock::stdlib_h.free(RangeInput);
746 if (FileLength < FirstByte) {
747 umock::stdlib_h.free(RangeInput);
748 return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
750 if (FirstByte >= 0 && LastByte >= 0 && LastByte >= FirstByte) {
751 if (LastByte >= FileLength)
752 LastByte = FileLength - 1;
758 "CONTENT-RANGE: bytes %" PRId64
"-%" PRId64
"/%" PRId64
"\r\n",
759 (int64_t)FirstByte, (int64_t)LastByte, (int64_t)FileLength);
760 if (rc < 0 || (
unsigned int)rc >=
sizeof(Instr->
RangeHeader)) {
761 umock::stdlib_h.free(RangeInput);
762 return HTTP_INTERNAL_SERVER_ERROR;
764 }
else if (FirstByte >= 0 && LastByte == -1 && FirstByte < FileLength) {
768 "CONTENT-RANGE: bytes %" PRId64
"-%" PRId64
770 (int64_t)FirstByte, (int64_t)(FileLength - 1),
771 (int64_t)FileLength);
772 if (rc < 0 || (
unsigned int)rc >=
sizeof(Instr->
RangeHeader)) {
773 umock::stdlib_h.free(RangeInput);
774 return HTTP_INTERNAL_SERVER_ERROR;
776 }
else if (FirstByte == -1 && LastByte > 0) {
777 if (LastByte >= FileLength) {
781 "CONTENT-RANGE: bytes 0-%" PRId64
"/%" PRId64
783 (int64_t)(FileLength - 1), (int64_t)FileLength);
788 "CONTENT-RANGE: bytes %" PRId64
"-%" PRId64
790 (int64_t)(FileLength - LastByte),
791 (int64_t)FileLength - 1, (int64_t)FileLength);
793 if (rc < 0 || (
unsigned int)rc >=
sizeof(Instr->
RangeHeader)) {
794 umock::stdlib_h.free(RangeInput);
795 return HTTP_INTERNAL_SERVER_ERROR;
798 umock::stdlib_h.free(RangeInput);
799 return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
802 umock::stdlib_h.free(RangeInput);
803 return HTTP_REQUEST_RANGE_NOT_SATISFIABLE;
806 umock::stdlib_h.free(RangeInput);
833 int RetCode = HTTP_OK;
837 TmpBuf = (
char*)malloc(TmpBufSize);
839 return HTTP_INTERNAL_SERVER_ERROR;
841 while (node != NULL) {
853 umock::stdlib_h.free(TmpBuf);
855 TmpBuf = (
char*)malloc(TmpBufSize);
857 return HTTP_INTERNAL_SERVER_ERROR;
861 if (index != http_header_names_table.
npos) {
867 if (strlen(TmpBuf) > strlen(
"gzip")) {
869 if (
StrStr(TmpBuf,
"trailers") != NULL) {
881 if (RetCode != HTTP_OK) {
882 umock::stdlib_h.free(TmpBuf);
937 umock::stdlib_h.free(TmpBuf);
978 while (node != NULL) {
982 index = map_str_to_int((
const char*)header->
name.
buf,
989 if (index == http_header_names_table.
npos) {
993 return HTTP_INTERNAL_SERVER_ERROR;
1004 node =
ListNext(&Req->headers, node);
1043 char* request_doc{
nullptr};
1045 time_t aux_LastModified;
1046 bool alias_grabbed{
false};
1048 int using_virtual_dir{0};
1050 const char* temp_str;
1057 assert(req->
method == HTTPMETHOD_GET || req->
method == HTTPMETHOD_HEAD ||
1058 req->
method == HTTPMETHOD_POST ||
1059 req->
method == HTTPMETHOD_SIMPLEGET);
1061 memset(&finfo, 0,
sizeof(finfo));
1063 err_code = HTTP_INTERNAL_SERVER_ERROR;
1066 &resp_major, &resp_minor);
1071 if (request_doc == NULL) {
1080 err_code = HTTP_FORBIDDEN;
1083 if (*request_doc !=
'/') {
1085 err_code = HTTP_BAD_REQUEST;
1089 using_virtual_dir = 1;
1098 alias_grabbed =
true;
1099 using_alias =
get_alias(request_doc, a_alias, finfo);
1100 if (using_alias == 1) {
1102 "text/xml; charset=\"utf-8\"");
1109 if (using_virtual_dir) {
1110 if (req->
method != HTTPMETHOD_POST) {
1113 finfo))) != HTTP_OK) {
1128 err_code = HTTP_NOT_FOUND;
1133 if (filename->
buf[filename->
length - 1] ==
'/') {
1134 temp_str =
"index.html";
1136 temp_str =
"/index.html";
1143 filename->
buf, finfo, RespInstr->
Cookie,
1146 err_code = HTTP_NOT_FOUND;
1152 err_code = HTTP_FORBIDDEN;
1162 }
else if (!using_alias) {
1176 while (filename->
length > 0 &&
1177 filename->
buf[filename->
length - 1] ==
'/') {
1180 if (req->
method != HTTPMETHOD_POST) {
1183 err_code = HTTP_NOT_FOUND;
1188 if (filename->
buf[filename->
length - 1] ==
'/') {
1189 temp_str =
"index.html";
1191 temp_str =
"/index.html";
1199 err_code = HTTP_NOT_FOUND;
1205 err_code = HTTP_FORBIDDEN;
1222 if (code != HTTP_OK) {
1226 if (req->
method == HTTPMETHOD_POST) {
1233 if (using_virtual_dir &&
1236 if (resp_major == 1 && resp_minor == 1) {
1242 err_code = HTTP_NOT_ACCEPTABLE;
1252 headers, resp_major, resp_minor,
1260 HTTP_PARTIAL_CONTENT,
1272 headers, resp_major, resp_minor,
1281 HTTP_PARTIAL_CONTENT,
1294 headers, resp_major, resp_minor,
1313 headers, resp_major, resp_minor,
1332 headers, resp_major, resp_minor,
1349 if (req->
method == HTTPMETHOD_HEAD) {
1350 *rtype = RESP_HEADERS;
1351 }
else if (using_alias) {
1353 *rtype = RESP_XMLDOC;
1354 }
else if (using_virtual_dir) {
1355 *rtype = RESP_WEBDOC;
1358 *rtype = RESP_FILEDOC;
1362 if (req->
method == HTTPMETHOD_SIMPLEGET) {
1368 umock::stdlib_h.free(request_doc);
1372 if (err_code != HTTP_OK && alias_grabbed) {
1400 size_t Data_Buf_Size = 1024;
1405 int ok_on_close = 0;
1406 size_t entity_offset = 0;
1408 int ret_code = HTTP_OK;
1414 return HTTP_INTERNAL_SERVER_ERROR;
1416#ifdef UPNP_ENABLE_POST_WRITE
1417 Fp = umock::stdio_h.fopen(filename,
"wb");
1419 return HTTP_UNAUTHORIZED;
1421 return HTTP_NOT_FOUND;
1435 ret_code = HTTP_BAD_REQUEST;
1441 num_read =
sock_read(info, Buf,
sizeof(Buf), &Timeout);
1448 ret_code = HTTP_INTERNAL_SERVER_ERROR;
1458 ret_code = HTTP_BAD_REQUEST;
1461 }
else if (num_read == 0) {
1463 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
1465 "<<<\n%s\n-----------------\n",
1471 ret_code = HTTP_BAD_REQUEST;
1475 ret_code = HTTP_SERVICE_UNAVAILABLE;
1486 entity_offset += Data_Buf_Size;
1491 ret_code = HTTP_INTERNAL_SERVER_ERROR;
1495 size_t n = umock::stdio_h.fwrite(Buf, 1, Data_Buf_Size, Fp);
1496 if (n != Data_Buf_Size) {
1497 ret_code = HTTP_INTERNAL_SERVER_ERROR;
1507 umock::stdio_h.fclose(Fp);
1522 compa::gAliasDoc.clear();
1539 size_t a_alias_content_length,
1540 time_t a_last_modified) {
1541 TRACE(
"Executing web_server_set_alias()")
1542 return compa::gAliasDoc.set(a_alias_name, a_alias_content,
1543 a_alias_content_length, a_last_modified);
1547 TRACE(
"Executing web_server_set_root_dir()")
1548 if (root_dir ==
nullptr)
1578 compa::resp_type rtype{compa::RESP_UNSPEC};
1581 compa::CXmlAlias xmldoc;
1585 memset(&RespInstr, 0,
sizeof(RespInstr));
1591 ret = compa::process_request_in(a_info, a_req, &rtype, &headers, &filename,
1592 &xmldoc, &RespInstr);
1593 if (ret != HTTP_OK) {
1600 case compa::RESP_FILEDOC:
1604 case compa::RESP_XMLDOC:
1606 headers.
length, xmldoc.doc().data(),
1607 xmldoc.doc().length());
1610 case compa::RESP_WEBDOC:
1618 case compa::RESP_HEADERS:
1623 case compa::RESP_POST:
1625 ret = compa::http_RecvPostMessage(a_parser, a_info, filename.
buf,
1634 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
1635 "webserver: Invalid response type received.\n");
1639 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
1640 "webserver: request processed...\n");
1646 TRACE(
"Executing SetHTTPGetCallback()")
1654 compa::gAliasDoc.clear();
#define UPNP_USING_CHUNKED
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.
tm * http_gmtime_r(const time_t *clock, tm *result)
Portable gmtime_r for Microsoft Windows.
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.
void web_server_callback(http_parser_t *a_parser, http_message_t *a_req, SOCKINFO *a_info)
Main entry point into web server.
int web_server_set_root_dir(const char *root_dir)
Assign the path to the global Document root directory.
void SetHTTPGetCallback(MiniServerCallback callback)
Set HTTP Get Callback.
int web_server_set_cors(const char *cors_string)
Assign the Access-Control-Allow-Origin specfied by the input const char* cors_string parameterto the ...
int web_server_set_alias(const char *a_alias_name, const char *a_alias_content, size_t a_alias_content_length, time_t a_last_modified)
Replaces current alias with the given alias.
void web_server_destroy()
Release memory allocated for the global web server root directory and the global XML document.
void web_server_init()
Initilialize root directory for web server and different documents.
http_message_t msg
entire raw message
uri_type uri
Type of a uri, e.g. absolute, relative, etc.
constexpr std::array< const UPnPsdk::str_int_entry, 33 > Http_Header_Names
Assigns header-name id to its text representation.
http_method_t method
Http method of an outgoing request.
memptr name
Header name as a string.
int major_version
Http major version.
memptr entity
message body(entity).
#define HDR_ACCEPT_LANGUAGE
Header definition.
membuffer value
Raw-value; could be multi-lined; min-length = 0.
membuffer msg
entire raw message.
int http_error_code
read-only; in case of parse error, this contains the HTTP error code (4XX or 5XX).
parser_pos_t position
Private data – don't touch.
@ POS_COMPLETE
Position complete.
@ POS_ENTITY
Position entity.
#define HDR_USER_AGENT
Type of a HTTP header.
parse_status_t
Status of parsing.
@ PARSE_INCOMPLETE_ENTITY
LinkedList headers
List of headers.
int minor_version
Http minor version.
size_t entity_start_position
Offset in the raw message buffer, which contains the message body. preceding this are the headers of ...
#define HDR_TE
Header definition.
#define HDR_RANGE
Header definition.
#define HDR_CONTENT_LENGTH
Type of a HTTP header.
Structure of an HTTP parser object.
Structure of an HTTP message.
size_t size
Size of the buffer.
token pathquery
Member variable.
Represents a URI used in parse_uri and elsewhere.
membuffer gDocumentRootDir
#define X_USER_AGENT
Can be overwritten by configure CFLAGS argument.
off_t RangeOffset
member variable
long RecvWriteSize
Recv from the network and write into local file.
off_t ReadSendSize
Read from local source and send on the network.
const void * RequestCookie
Cookie associated with the request.
int IsRangeActive
member variable
const void * Cookie
Cookie associated with the virtualDir.
char AcceptLanguageHeader[200]
member variable
int IsTrailers
member variable
int IsVirtualFile
member variable
char RangeHeader[200]
member variable
int IsChunkActive
member variable
ListNode * ListNext(LinkedList *list, ListNode *node)
Returns the next item in the list.
ListNode * ListHead(LinkedList *list)
Returns the head of the list.
Linked list node. Stores generic item and pointers to next and prev.
Declarations to manage the builtin Webserver.
PUPNP_Api int UpnpFileInfo_set_LastModified(UpnpFileInfo *p, time_t n)
PUPNP_Api int UpnpFileInfo_set_CtrlPtIPAddr(UpnpFileInfo *p, const struct sockaddr_storage *buf)
PUPNP_Api time_t UpnpFileInfo_get_LastModified(const UpnpFileInfo *p)
PUPNP_Api const DOMString UpnpFileInfo_get_ContentType(const UpnpFileInfo *p)
PUPNP_Api int UpnpFileInfo_set_FileLength(UpnpFileInfo *p, off_t n)
PUPNP_Api off_t UpnpFileInfo_get_FileLength(const UpnpFileInfo *p)
PUPNP_Api int UpnpFileInfo_set_ContentType(UpnpFileInfo *p, const DOMString s)
PUPNP_Api const UpnpListHead * UpnpFileInfo_get_ExtraHeadersList(const UpnpFileInfo *p)
PUPNP_Api int UpnpFileInfo_strncpy_Os(UpnpFileInfo *p, const char *s, size_t n)
PUPNP_Api int UpnpFileInfo_get_IsReadable(const UpnpFileInfo *p)
PUPNP_Api int UpnpFileInfo_set_IsReadable(UpnpFileInfo *p, int n)
PUPNP_Api void UpnpFileInfo_delete(UpnpFileInfo *p)
PUPNP_Api int UpnpFileInfo_set_IsDirectory(UpnpFileInfo *p, int n)
PUPNP_Api int UpnpFileInfo_get_IsDirectory(const UpnpFileInfo *p)
PUPNP_Api UpnpFileInfo * UpnpFileInfo_new(void)
Printf format for integers.
VDCallback_GetInfo get_info
struct virtual_Dir_List * next
Table with C-strings mapped to an integer id.
static constexpr size_t npos
Value returned on error or when an index on a container is not found.
size_t index_of(const char *a_name, bool a_case_sensitive=false)
Match the given name with names from the entries in the table.
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 parser_parse_entity(http_parser_t *parser)
Determines method to read entity.
PUPNP_Api UpnpListIter UpnpListInsert(UpnpListHead *list, UpnpListIter pos, UpnpListHead *elt)
Insert element before pos, returns iterator pointing to inserted element.
PUPNP_Api UpnpListIter UpnpListEnd(UpnpListHead *list)
Return end of list sentinel iterator (not an element)
PUPNP_Api UpnpListIter UpnpListErase(UpnpListHead *list, UpnpListIter pos)
Erase element at pos, return next one, or end()
PUPNP_Api UpnpListIter UpnpListBegin(UpnpListHead *list)
Return iterator pointing to the first list element, or UpnpListEnd(list) if the list is empty.
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_assign_str(membuffer *m, const char *c_str)
Wrapper function for membuffer_assign().
int membuffer_append_str(membuffer *m, const char *c_str)
Invokes function to appends data from a constant string to the buffer.
void membuffer_delete(membuffer *m, size_t index, size_t num_bytes)
Shrink the size of the buffer depending on the current size of the buffer and the input parameters....
size_t length
length of buffer without terminating null byte (read-only).
char * buf
mem buffer; must not write beyond buf[length-1] (read/write).
size_t length
length of memory (read-only).
char * buf
start of memory (read/write).
pointer to a chunk of memory.
Maintains a block of dynamically allocated memory.
#define UPNP_E_INVALID_ARGUMENT
One or more of the parameters passed to a function is invalid.
#define UPNP_E_FILE_NOT_FOUND
The filename passed to one of the device registration functions was not found or was not accessible.
#define UPNP_E_SUCCESS
The operation completed successfully.
#define UPNP_E_OUTOF_MEMORY
Not enough resources are currently available to complete the operation.
void(* MiniServerCallback)(http_parser_t *parser, http_message_t *request, SOCKINFO *info)
For a miniserver callback function.
MiniServerCallback gGetCallback
HTTP server callback.
std::string subtype
file subtype
std::string type
file type
UPnPsdk_VIS const Document_meta * select_filetype(std::string_view a_extension)
Based on the extension, returns the content type and content subtype.
CXmlAlias gAliasDoc
Global XML document object.
const char * gMediaTypes[]
Media types.
char * web_server_asctime_r(const struct tm *tm, char *buf)
Multiplatform wrapper to make win32 asctime_s compatible to posix asctime_r.
constexpr size_t APPLICATION_INDEX
index to get media type of application from the media types table.
int process_request_in(SOCKINFO *info, http_message_t *req, enum resp_type *rtype, membuffer *headers, membuffer *filename, CXmlAlias *a_alias, SendInstruction *RespInstr)
Process a remote request and return the result.
int CheckOtherHTTPHeaders(http_message_t *Req, struct SendInstruction *RespInstr, off_t FileSize)
Get header id from the request parameter.
int search_extension(const char *a_extension, const char **a_con_type, const char **a_con_subtype)
Based on the extension, returns the content type and content subtype.
int get_file_info(const char *filename, UpnpFileInfo *info)
Get file information.
int GetNextRange(char **SrcRangeStr, off_t *FirstByte, off_t *LastByte)
Returns a range of integers from a string.
constexpr size_t ASCTIME_R_BUFFER_SIZE
Number of elements for asctime_s on win32, means buffer size.
char * StrTok(char **Src, const char *Del)
Finds next token in a string.
int isFileInVirtualDir(char *filePath, const void **cookie)
Compares filePath with paths from the list of virtual directory lists.
int http_RecvPostMessage(http_parser_t *parser, SOCKINFO *info, char *filename, struct SendInstruction *Instr)
Receives the HTTP post message.
int get_content_type(const char *filename, UpnpFileInfo *fileInfo)
Based on the extension of the filename, clones an XML string based on type and content subtype.
void FreeExtraHTTPHeaders(UpnpListHead *extraHeadersList)
Free extra HTTP headers.
char * StrStr(char *s1, const char *s2)
Finds a substring from a string in a case insensitive way.
int ExtraHTTPHeaders(http_message_t *Req, UpnpListHead *extraHeadersList)
Build an array of unrecognized headers.
int CreateHTTPRangeResponseHeader(char *ByteRangeSpecifier, off_t FileLength, struct SendInstruction *Instr)
Fills in the Offset, read size and contents to send out as an HTTP Range Response.
int get_alias(const char *request_file, CXmlAlias *alias, UpnpFileInfo *info)
Compare file names.
void ToUpperCase(char *s)
Converts C string in place to upper case.
Refactored pupnp program code that is compatible to the original pupnp code.
Specifications to be portable between different platforms.
int sock_read(SOCKINFO *info, char *buffer, size_t bufsize, int *timeoutSecs)
Reads data on socket in sockinfo.
sockaddr_storage foreign_sockaddr
Socket address of the remote node only filled in incoming requests.
Additional socket information for connections and ssl.
Manage "Step 1: Discovery" of the UPnP+™ specification with SSDP.
Alias directory structure on the webserver for an XML document.
void clear()
Clear the XML object.
std::string_view doc() const
Get the root udevice description XML document.
bool is_valid() const
Returns if the XML object contains a valid XML document.
std::string_view name() const
Get the name of the root udevice description XML document.
int set(const char *a_alias_name, const char *&a_alias_content, size_t &a_alias_content_length, time_t a_last_modified=time(nullptr))
Set an XML Document.
time_t last_modified() const
Get last modified date of the root udevice description XML document.
void release()
Release an XML document from the XML object.
Define macro for synced logging to the console for detailed info and debug.
struct VirtualDirCallbacks virtualDirCallback
This structure is for virtual directory callbacks.
virtualDirList * pVirtualDirList
Pointer to the virtual directory list.
membuffer gWebserverCorsString
WebServerState bWebServerState
Flag to indicate the state of web server.
Inititalize the compatible library before it can be used.
UPnPsdk_VIS void UpnpPrintf(Upnp_LogLevel DLevel, Dbg_Module Module, const char *DbgFileName, int DbgLineNo, const char *FmtStr,...)
Prints the debug statement.
int remove_dots(char *buf, size_t size)
Removes ".", and ".." from a path.
int remove_escaped_chars(char *in, size_t *size)
Removes http escaped characters such as: "%20" and replaces them with their character representation.