43#include <httpreadwrite.hpp>
51#include <webserver.hpp>
62#include <sys/utsname.h>
65#if defined(__ANDROID__) && \
66 (!defined(__USE_FILE_OFFSET64) || __ANDROID_API__ < 24)
72#include <umock/pupnp_sock.hpp>
73#include <umock/pupnp_httprw.hpp>
74#include <umock/stdio.hpp>
75#include <umock/sys_socket.hpp>
76#include <umock/winsock2.hpp>
77#include <umock/sysinfo.hpp>
110 const int connect_res
113 TRACE(
"Executing Check_Connect_And_Wait_Connection()")
115 if (connect_res == 0)
118 if (umock::winsock2_h.WSAGetLastError() != WSAEWOULDBLOCK)
121 if (errno != EINPROGRESS)
127 FD_SET(a_sock, &fdSet);
129 int result{SOCKET_ERROR};
132 umock::sys_socket_h.select(a_sock + 1, NULL, &fdSet, NULL, &tmvTimeout);
141 socklen_t len{
sizeof(valopt)};
142 if (umock::sys_socket_h.getsockopt(a_sock, SOL_SOCKET, SO_ERROR,
143 (
void*)&valopt, &len) < 0)
159#ifdef COMPA_ENABLE_BLOCKING_TCP_CONNECTIONS
160bool unblock_tcp_connections{
false};
162bool unblock_tcp_connections{
true};
183 TRACE(
"Executing get_hoststr()")
190 if (strlen(url_str) < 2)
193 start = strstr(url_str,
"//");
198 finish = strchr(start,
'/');
200 *hostlen =
static_cast<size_t>(finish - start);
202 *hostlen = strlen(start);
223 UpnpHttpHeader *header;
230 header = UpnpHttpHeader_new();
231 UpnpHttpHeader_strncpy_Name(
235 UpnpHttpHeader_strncpy_Value(
252 const char* contentType,
const UpnpString* headers) {
257 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
"URL: %s method: %d\n",
272 ret_code =
get_hoststr(url_str, &hoststr, &hostlen);
275 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
276 "HOSTNAME : %s Length : %" PRIzu
"\n", hoststr, hostlen);
280 "HOST: ", hoststr, hostlen);
285 if (ret_code == 0 && contentType) {
290 if (contentLength >= 0)
301 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
302 "HTTP Makemessage failed\n");
306 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
308 "----------END--------\n",
345 int* http_error_code) {
366 num_read =
sock_read(info, buf,
sizeof(buf), timeout_secs);
388 }
else if (num_read == 0) {
390 *http_error_code = HTTP_BAD_REQUEST;
408 num_read =
sock_read(info, buf,
sizeof(buf), timeout_secs);
427 }
else if (num_read == 0) {
429 *http_error_code = HTTP_BAD_REQUEST;
451 url_str_len = strlen(url_str);
453 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
"DOWNLOAD URL : %s\n",
461 ret_code =
get_hoststr(url_str, &hoststr, &hostlen);
465 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
466 "HOSTNAME : %s Length : %" PRIzu
"\n", hoststr, hostlen);
474 hostlen, pRangeSpecifier);
476 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
477 "HTTP Makemessage failed\n");
482 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
484 "----------END--------\n",
508 const sockaddr*
const
510 const socklen_t addrlen
512 TRACE(
"Executing private_connect(), blocking " +
513 std::string(unblock_tcp_connections ?
"false" :
"true"))
515 if (unblock_tcp_connections) {
519 int ret{SOCKET_ERROR};
521 ret = umock::pupnp_sock.sock_make_no_blocking(sockfd);
525 ret = umock::sys_socket_h.connect(sockfd, serv_addr, addrlen);
531 ret = ret | umock::pupnp_sock.sock_make_blocking(sockfd);
534 return ret == 0 ? 0 : SOCKET_ERROR;
539 if (umock::sys_socket_h.connect(sockfd, serv_addr, addrlen) != 0) {
541 UPnPsdk_LOGERR(
"MSG1020")
"failed to connect() socket("
542 << sockfd <<
"): " << serrObj.
error_str() <<
"\n";
552#if defined(_WIN32) || defined(DOXYGEN_RUN)
554 if (clock == NULL || *clock < 0 || result == NULL)
558 gmtime_s(result, clock);
564 const char* temp_path =
"/";
567#ifdef UPnPsdk_HAVE_OPENSSL
601 socklen_t sockaddr_len;
609 if (connfd == INVALID_SOCKET) {
613 ?
sizeof(
struct sockaddr_in6)
614 :
sizeof(
struct sockaddr_in));
615 ret_connect = umock::pupnp_httprw.private_connect(
617 if (ret_connect == -1) {
619 UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
620 "connect error: %d\n", umock::winsock2_h.WSAGetLastError());
622 if (umock::sys_socket_h.shutdown(connfd, SD_BOTH) == -1) {
623 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
624 "Error in shutdown: %s\n", std::strerror(errno));
626 umock::unistd_h.CLOSE_SOCKET_P(connfd);
635 int* http_error_code) {
636 TRACE(
"Executing http_RecvMessage()")
643 size_t buf_len{1024};
645 *http_error_code = HTTP_INTERNAL_SERVER_ERROR;
646 buf = (
char*)malloc(buf_len);
661 if ((
size_t)num_read >= buf_len) {
663 buf_len = 2 * buf_len;
664 buf = (
char*)malloc(buf_len);
670 num_read =
sock_read(info, buf, buf_len, timeout_secs);
676 UPnPsdk_LOGINFO(
"MSG1031")
"<<< (RECVD) <<<\n"
677 << parser->
msg.
msg.
buf <<
"UPnPsdk -----------------\n";
680 *http_error_code = HTTP_REQ_ENTITY_TOO_LARGE;
706 }
else if (num_read == 0) {
707 UPnPsdk_LOGINFO(
"MSG1047")
"<<< (RECVD) <<<\n"
708 << parser->
msg.
msg.
buf <<
"\n-----------------\n";
714 *http_error_code = HTTP_BAD_REQUEST;
716 UPnPsdk_LOGERR(
"MSG1005")
"Line " << line
717 <<
": partial message.\n";
732 UPnPsdk_LOGERR(
"MSG1048")
"error "
733 << ret <<
" on line " << line
734 <<
", http_error_code=" << *http_error_code <<
".\n";
741 TRACE(
"Executing http_SendMessage()")
742#ifdef COMPA_HAVE_WEBSERVER
744 char* file_buf{
nullptr};
745 char* ChunkBuf{
nullptr};
748 off_t amount_to_be_read{};
750 int I_fmt_processed = 0;
760 }
catch (
const std::exception& ex) {
761 UPnPsdk_LOGCATCH(
"MSG1086")
"catched next line...\n" << ex.what();
771 while ((c = *fmt++) !=
'\0') {
772#ifdef COMPA_HAVE_WEBSERVER
773 if (c ==
'I' && !I_fmt_processed) {
776 if (Instr->ReadSendSize >= 0) {
777 amount_to_be_read = Instr->ReadSendSize;
779 amount_to_be_read = (off_t)Data_Buf_Size;
782 Data_Buf_Size = (
size_t)amount_to_be_read;
783 ChunkBuf = (
char*)malloc(
791 }
else if (c ==
'f') {
793 char* filename = va_arg(argp,
char*);
796 if (Instr && Instr->IsVirtualFile)
798 filename, UPNP_READ, Instr->Cookie, Instr->RequestCookie);
802 if (umock::stdio_h.fopen_s(&Fp, filename,
"rb") != 0)
805 Fp = umock::stdio_h.fopen(filename,
"rb");
811 if (Instr && Instr->IsRangeActive && Instr->IsVirtualFile) {
814 Instr->RequestCookie) != 0) {
818 }
else if (Instr && Instr->IsRangeActive) {
819 if (fseeko(Fp, Instr->RangeOffset, SEEK_CUR) != 0) {
824 while (amount_to_be_read) {
826 size_t n = amount_to_be_read >= (off_t)Data_Buf_Size
828 : (size_t)amount_to_be_read;
829 if (Instr->IsVirtualFile) {
832 Instr->RequestCookie);
838 num_read =
static_cast<size_t>(nr);
840 num_read = umock::stdio_h.fread(file_buf, 1u, n, Fp);
841 if (umock::stdio_h.ferror(Fp)) {
843 umock::stdio_h.clearerr(Fp);
847 amount_to_be_read -= (off_t)num_read;
848 if (Instr->ReadSendSize < 0) {
850 amount_to_be_read = (off_t)Data_Buf_Size;
853 num_read = umock::stdio_h.fread(file_buf, (
size_t)1,
855 if (umock::stdio_h.ferror(Fp)) {
857 umock::stdio_h.clearerr(Fp);
862 if (num_read == 0u) {
864 if (Instr && Instr->IsChunkActive) {
865 const char* str =
"0\r\n\r\n";
866 num_write =
sock_write(info, str, strlen(str), TimeOut);
873 if (Instr && Instr->IsChunkActive) {
875 memcpy(file_buf + num_read,
"\r\n", (
size_t)2);
878 int rc = snprintf(Chunk_Header,
sizeof(Chunk_Header),
879 "%" PRIzx
"\r\n", num_read);
881 static_cast<unsigned int>(rc) >=
sizeof(Chunk_Header)) {
886 memcpy(file_buf - strlen(Chunk_Header), Chunk_Header,
887 strlen(Chunk_Header));
894 info, file_buf - strlen(Chunk_Header),
895 num_read + strlen(Chunk_Header) + 2u, TimeOut);
896 size_t num_written =
static_cast<size_t>(num_write);
897 if (num_write <= 0 ||
898 num_written != num_read + strlen(Chunk_Header) + 2u)
903 num_write =
sock_write(info, file_buf, num_read, TimeOut);
906 "MSG1104")
">>> (SENT) >>> UDevice response_out "
909 <<
"\" to (\"HOST:\" in following message) ...\n"
910 << std::string(file_buf,
static_cast<size_t>(num_write))
911 <<
"\nUPnPsdk num_written=" << num_write
912 <<
".\nUPnPsdk ------------\n";
915 size_t num_written =
static_cast<size_t>(num_write);
916 if (num_write <= 0 || num_written != num_read) {
923 if (Instr && Instr->IsVirtualFile) {
925 Instr->RequestCookie);
927 umock::stdio_h.fclose(Fp);
935 char* buf = va_arg(argp,
char*);
936 size_t buf_length = va_arg(argp,
size_t);
937 if (buf_length > 0u) {
939 int num_write =
sock_write(info, buf, buf_length, TimeOut);
942 "MSG1105")
">>> (SENT) >>> UDevice response_out "
945 <<
"\" to (\"HOST:\" in following message) ...\n"
946 << std::string(buf, buf_length)
947 <<
"\nUPnPsdk buf_length=" << buf_length
948 <<
", num_written=" << num_write
949 <<
".\nUPnPsdk ------------\n";
958 if (
static_cast<size_t>(num_write) != buf_length) {
968#ifdef COMPA_HAVE_WEBSERVER
978 TRACE(
"Executing http_RequestAndResponse()")
979 SOCKET tcp_connection;
981 socklen_t sockaddr_len;
984 tcp_connection = umock::sys_socket_h.
socket(
986 if (tcp_connection == INVALID_SOCKET) {
997 ?
sizeof(sockaddr_in6)
998 :
sizeof(sockaddr_in);
999 ret_code = umock::pupnp_httprw.private_connect(
1002 if (ret_code == -1) {
1010 if (ret_code != 0) {
1015 int http_error_code;
1028 size_t* doc_length,
char* content_type) {
1029 TRACE(
"Executing http_Download()")
1040 size_t url_str_len = strlen(url_str);
1042 UPnPsdk_LOGINFO(
"MSG1098")
"UDevice DOWNLOAD URL=\"" << url_str
1053 const char* hoststr;
1055 ret_code =
get_hoststr(url_str, &hoststr, &hostlen);
1069 if (ret_code != 0) {
1070 UPnPsdk_LOGERR(
"MSG1100")
"HTTP MakeMessage failed.\n";
1074 UPnPsdk_LOGINFO(
"MSG1101")
"Ctrlpnt send request_out HTTP Buffer...\n"
1075 << request_out.
buf <<
"UPnPsdk ----------END--------\n";
1080 HTTPMETHOD_GET, timeout_secs, &response_in);
1083 if (ret_code != 0) {
1088 UPnPsdk_LOGINFO(
"MSG1102")
"Response_in...\n";
1094 *content_type =
'\0';
1101 memcpy(content_type, ctype.
buf, copy_len);
1102 content_type[copy_len] =
'\0';
1117 memmove(msg_start, entity_start, *doc_length + (
size_t)1);
1120 (
char*)realloc(msg_start, *doc_length + (
size_t)1);
1124 assert(msg_length > *doc_length);
1125 assert(*document != NULL);
1126 if (msg_length <= *doc_length || *document == NULL)
1127 UPnPsdk_LOGINFO(
"MSG1103")
"msg_length("
1128 << msg_length <<
") <= *doc_length(" << *doc_length
1129 <<
") or document is NULL.\n";
1144 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1146 if (!handle || !length || !total) {
1149 *length = handle->response.msg.entity.length;
1150 *total = handle->response.content_length;
1156 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1166 [[maybe_unused]]
int timeout) {
1167 TRACE(
"Executing http_OpenHttpConnection()")
1169 size_t sockaddr_len;
1170 SOCKET tcp_connection;
1171 http_connection_handle_t* handle =
nullptr;
1175 if (!url_str || !Handle)
1184 (http_connection_handle_t*)malloc(
sizeof(http_connection_handle_t));
1188 handle->requestStarted = 0;
1189 memset(&handle->response, 0,
sizeof(handle->response));
1191 tcp_connection = umock::sys_socket_h.socket(
1193 if (tcp_connection == INVALID_SOCKET) {
1194 handle->sock_info.socket = INVALID_SOCKET;
1204 ?
sizeof(
struct sockaddr_in6)
1205 : sizeof(struct sockaddr_in);
1207 handle->sock_info.socket, (struct sockaddr*)&(url.hostport.IPaddress),
1208 (socklen_t)sockaddr_len);
1209 if (ret_code == -1) {
1214#ifdef UPnPsdk_HAVE_OPENSSL
1231 const char* contentType,
int contentLength,
1235 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1237 if (!url_str || !Handle)
1239 if (handle->requestStarted) {
1243 handle->requestStarted = 1;
1246 &url, contentLength, contentType, headers);
1259 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1260 char* tempbuf = NULL;
1261 size_t tempbufSize = 0;
1262 int freeTempbuf = 0;
1265 if (!handle || !size || !buf) {
1272 size_t tempSize = 0;
1274 tempbuf = (
char*)malloc(tempbuf_len);
1278 snprintf(tempbuf, tempbuf_len,
"%zx\r\n", *size);
1279 tempSize = strlen(tempbuf);
1280 memcpy(tempbuf + tempSize, buf, *size);
1281 memcpy(tempbuf + tempSize + *size,
"\r\n", 2);
1283 tempbufSize = tempSize + *size + 2;
1288 tempbufSize = *size;
1290 numWritten =
sock_write(&handle->sock_info, tempbuf, tempbufSize, &timeout);
1293 if (numWritten < 0) {
1297 *size = (size_t)numWritten;
1304 const char* zcrlf =
"0\r\n\r\n";
1305 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1308 if (!handle->requestStarted) {
1311 handle->requestStarted = 0;
1314 retc =
sock_write(&handle->sock_info, zcrlf, strlen(zcrlf), &timeout);
1320 int* contentLength,
int* httpStatus,
int timeout) {
1322 int http_error_code;
1324 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1328 &handle->sock_info, &handle->response, &timeout, &http_error_code);
1344 *httpStatus = handle->response.msg.status_code;
1349 *contentType = NULL;
1351 *contentType = ctype.
buf;
1353 if (contentLength) {
1359 *contentLength = (int)handle->response.content_length;
1375 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1378 int ok_on_close = 0;
1379 char tempbuf[2 * 1024];
1382 if (!handle || !size || (*size > 0 && !buf)) {
1402 while (handle->response.msg.amount_discarded + *size >
1403 handle->response.msg.entity.length &&
1404 !handle->cancel && handle->response.position !=
POS_COMPLETE) {
1406 sock_read(&handle->sock_info, tempbuf,
sizeof(tempbuf), &timeout);
1411 if (ret_code != 0) {
1413 handle->response.http_error_code = HTTP_INTERNAL_SERVER_ERROR;
1428 }
else if (num_read == 0) {
1430 UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
1432 "<<<\n%s\n-----------------\n",
1433 handle->response.msg.msg.buf);
1438 handle->response.http_error_code =
1447 if (handle->cancel) {
1451 if (handle->response.msg.amount_discarded + *size >
1452 handle->response.msg.entity.length)
1453 *size = handle->response.msg.entity.length -
1454 handle->response.msg.amount_discarded;
1458 &handle->response.msg.msg
1459 .buf[handle->response.entity_start_position],
1462 handle->response.entity_start_position, *size);
1464 handle->response.scanner.cursor -= *size;
1466 handle->response.msg.amount_discarded += *size;
1473 http_connection_handle_t* handle = (http_connection_handle_t*)Handle;
1484 int request_major_version,
1485 int request_minor_version) {
1486 int response_major, response_minor;
1492 &response_major, &response_minor);
1497 http_status_code, http_status_code);
1513 int http_minor_version,
const char* fmt, ...) {
1516 TRACE(
"Executing http_MakeMessage()")
1524 struct tm date_storage;
1526 const char* start_str;
1527 const char* end_str;
1529 const char* status_msg;
1531 const char* method_str;
1532 const char* url_str;
1533 const char* temp_str;
1539 const char* weekday_str =
"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat";
1540 const char* month_str =
"Jan\0Feb\0Mar\0Apr\0May\0Jun\0"
1541 "Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
1544 memset(tempbuf, 0,
sizeof(tempbuf));
1545 va_start(argp, fmt);
1546 while ((c = *fmt++) != 0) {
1567 }
else if (c ==
's') {
1569 s = (
char*)va_arg(argp,
char*);
1571 UpnpPrintf(UPNP_ALL, HTTP, __FILE__, __LINE__,
1572 "Adding a string : %s\n", s);
1575 }
else if (c ==
'K') {
1579 }
else if (c ==
'A') {
1587 strcmp(
static_cast<const char*
>(RespInstr->
CorsHeader),
"") &&
1589 "ssc",
"Access-Control-Allow-Origin: ",
1592 }
else if (c ==
'G') {
1602 }
else if (c ==
'b') {
1604 s = (
char*)va_arg(argp,
char*);
1605 UpnpPrintf(UPNP_ALL, HTTP, __FILE__, __LINE__,
1606 "Adding a char Buffer starting with: %c\n", (
int)s[0]);
1608 length = (size_t)va_arg(argp,
size_t);
1611 }
else if (c ==
'c') {
1615 }
else if (c ==
'd') {
1617 num = (size_t)va_arg(argp,
int);
1618 rc = snprintf(tempbuf,
sizeof(tempbuf),
"%" PRIzu, num);
1619 if (rc < 0 || (
unsigned int)rc >=
sizeof(tempbuf) ||
1622 }
else if (c ==
'h') {
1624 bignum = (off_t)va_arg(argp, off_t);
1626 snprintf(tempbuf,
sizeof(tempbuf),
"%" PRId64, (int64_t)bignum);
1627 if (rc < 0 || (
unsigned int)rc >=
sizeof(tempbuf) ||
1630 }
else if (c ==
't' || c ==
'D') {
1634 start_str =
"DATE: ";
1636 curr_time = umock::sysinfo.time(NULL);
1637 loc_time = &curr_time;
1640 start_str = end_str =
"";
1641 loc_time = (time_t*)va_arg(argp, time_t*);
1647 rc = snprintf(tempbuf,
sizeof(tempbuf),
1648 "%s%s, %02d %s %d %02d:%02d:%02d GMT%s", start_str,
1649 &weekday_str[date->tm_wday * 4], date->tm_mday,
1650 &month_str[date->tm_mon * 4], date->tm_year + 1900,
1651 date->tm_hour, date->tm_min, date->tm_sec, end_str);
1652 if (rc < 0 || (
unsigned int)rc >=
sizeof(tempbuf) ||
1655 }
else if (c ==
'L') {
1665 !web_server_content_language.empty() &&
1667 buf, http_major_version, http_minor_version,
"ssc",
1668 "CONTENT-LANGUAGE: ",
1669 web_server_content_language.c_str()) != 0)
1671 }
else if (c ==
'C') {
1672 if ((http_major_version > 1) ||
1673 (http_major_version == 1 && http_minor_version == 1)) {
1678 }
else if (c ==
'N') {
1680 bignum = (off_t)va_arg(argp, off_t);
1681 assert(bignum >= 0);
1683 "shc",
"CONTENT-LENGTH: ", bignum) != 0)
1687 "sc",
"Accept-Ranges: bytes") != 0)
1689 }
else if (c ==
'S' || c ==
'U') {
1691 temp_str = (c ==
'S') ?
"SERVER: " :
"USER-AGENT: ";
1694 "ss", temp_str, tempbuf) != 0)
1696 }
else if (c ==
'X') {
1698 s = (
char*)va_arg(argp,
char*);
1704 }
else if (c ==
'R') {
1707 status_code = (int)va_arg(argp,
int);
1708 assert(status_code > 0);
1709 rc = snprintf(tempbuf,
sizeof(tempbuf),
"HTTP/%d.%d %d ",
1710 http_major_version, http_minor_version, status_code);
1713 if (rc < 0 || (
unsigned int)rc >=
sizeof(tempbuf) ||
1715 "ssc", tempbuf, status_msg) != 0)
1717 }
else if (c ==
'B') {
1719 status_code = (int)va_arg(argp,
int);
1720 rc = snprintf(tempbuf,
sizeof(tempbuf),
"%s%d %s%s",
1721 "<html><body><h1>", status_code,
1723 "</h1></body></html>");
1724 if (rc < 0 || (
unsigned int)rc >=
sizeof(tempbuf))
1726 bignum = (off_t)strlen(tempbuf);
1733 }
else if (c ==
'Q') {
1738 url_str = (
const char*)va_arg(argp,
const char*);
1739 num = (size_t)va_arg(argp,
size_t);
1741 "ssbsdsdc", method_str,
1743 " HTTP/", http_major_version,
".",
1744 http_minor_version) != 0)
1746 }
else if (c ==
'q') {
1762 }
else if (c ==
'T') {
1764 temp_str = (
const char*)va_arg(
1767 "ssc",
"CONTENT-TYPE: ", temp_str) != 0)
1787 int* response_major_vers,
1788 int* response_minor_vers) {
1789 if ((request_major_vers > 1) ||
1790 (request_major_vers == 1 && request_minor_vers >= 1)) {
1791 *response_major_vers = 1;
1792 *response_minor_vers = 1;
1794 *response_major_vers = request_major_vers;
1795 *response_minor_vers = request_minor_vers;
1801 int* contentLength,
int* httpStatus,
int lowRange,
1802 int highRange,
int timeout) {
1803 int http_error_code;
1805 SOCKET tcp_connection;
1806 size_t sockaddr_len;
1808 http_connection_handle_t* handle = NULL;
1819 if (!url_str || !Handle || !contentType || !httpStatus) {
1826 *contentType = NULL;
1828 if (lowRange > highRange) {
1832 memset(&rangeBuf, 0,
sizeof(rangeBuf));
1834 "Range: bytes=%d-%d\r\n", lowRange, highRange);
1835 if (rc < 0 || (
unsigned int)rc >=
sizeof(rangeBuf.
RangeHeader))
1842 (http_connection_handle_t*)malloc(
sizeof(http_connection_handle_t));
1847 memset(handle, 0,
sizeof(*handle));
1849 tcp_connection = umock::sys_socket_h.socket(
1851 if (tcp_connection == INVALID_SOCKET) {
1863 ?
sizeof(
struct sockaddr_in6)
1864 : sizeof(struct sockaddr_in);
1866 handle->sock_info.socket,
1867 (struct sockaddr*)&(url.hostport.IPaddress),
1868 (socklen_t)sockaddr_len);
1869 if (errCode == -1) {
1885 &http_error_code) != (
int)
PARSE_OK) {
1897 *httpStatus = handle->response.msg.status_code;
1902 *contentType = NULL;
1904 *contentType = ctype.
buf;
1910 *contentLength = (int)handle->response.content_length;
1923 TRACE(
"Executing get_sdk_info().")
1924#ifdef UPNP_ENABLE_UNSPECIFIED_SERVER
1925 snprintf(info, infoSize,
"Unspecified, UPnP/1.0, Unspecified\r\n");
1928 snprintf(info, infoSize,
1929 "UPnP/1.0, Portable SDK for UPnP devices/" PUPNP_VERSION
1932 struct utsname sys_info;
1934 int ret_code = umock::sysinfo.uname(&sys_info);
1936 snprintf(info, infoSize,
1937 "Unspecified, UPnP/1.0, Portable SDK for UPnP "
1938 "devices/" PUPNP_VERSION
"\r\n");
1940 snprintf(info, infoSize,
1941 "%s/%s, UPnP/1.0, Portable SDK for UPnP "
1942 "devices/" PUPNP_VERSION
"\r\n",
1943 sys_info.sysname, sys_info.release);
#define UPNP_E_OUTOF_BOUNDS
The operation completed successfully.
#define UPNP_USING_CHUNKED
int http_ReadHttpResponse(void *Handle, char *buf, size_t *size, int timeout)
Reads the content of a response using a connection previously created by UpnpOpenHttpConnection().
int http_OpenHttpConnection(const char *url_str, void **Handle, int timeout)
Opens a connection to the server.
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_CloseHttpConnection(void *Handle)
Closes the connection created with UpnpOpenHttpConnection() and frees any memory associated with the ...
int http_FixStrUrl(const char *urlstr, size_t urlstrlen, uri_type *fixed_url)
Parses URL and then validates URL.
int http_SendMessage(SOCKINFO *info, int *TimeOut, const char *fmt,...)
Sends a message to the destination based on the format parameter.
SOCKET http_Connect(uri_type *destination_url, uri_type *url)
Gets destination address from URL and then connects to the remote end.
void get_sdk_info(char *info, size_t infoSize)
Returns the server information for the operating system.
int http_Download(const char *url_str, int timeout_secs, char **document, size_t *doc_length, char *content_type)
Download the document message and extract the document from the message.
int http_FixUrl(uri_type *url, uri_type *fixed_url)
Validates URL.
int http_CancelHttpGet(void *Handle)
Set the cancel flag of the HttpGet handle.
int http_WriteHttpRequest(void *Handle, char *buf, size_t *size, int timeout)
Writes the content of a HTTP request initiated by a UpnpMakeHttpRequest() call. The end of the conten...
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.
static int private_connect(const SOCKET sockfd, const sockaddr *const serv_addr, const socklen_t addrlen)
Initiate a connection on a socket.
int http_EndHttpRequest(void *Handle, int timeout)
Indicates the end of a HTTP request previously made by UpnpMakeHttpRequest().
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_OpenHttpGetEx(const char *url_str, void **Handle, char **contentType, int *contentLength, int *httpStatus, int lowRange, int highRange, int timeout)
Makes the HTTP GET message, connects to the peer, sends the HTTP GET request, gets the response and p...
int http_GetHttpResponse(void *Handle, UpnpString *headers, char **contentType, int *contentLength, int *httpStatus, int timeout)
Gets the response from the server using a connection previously created by UpnpOpenHttpConnection().
int http_MakeHttpRequest(Upnp_HttpMethod method, const char *url_str, void *Handle, UpnpString *headers, const char *contentType, int contentLength, int timeout)
Makes a HTTP request using a connection previously created by UpnpOpenHttpConnection().
int http_RecvMessage(SOCKINFO *info, http_parser_t *parser, http_method_t request_method, int *timeout_secs, int *http_error_code)
Get the data on the socket and take actions based on the read data to modify the parser objects buffe...
int http_HttpGetProgress(void *Handle, size_t *length, size_t *total)
Extracts information from the Handle to the HTTP get object.
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
http_method_t
Method in a HTTP request.
memptr name
Header name as a string.
memptr entity
message body(entity).
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.
parser_pos_t
Type of a parser position.
@ POS_COMPLETE
Position complete.
@ POS_ENTITY
Position entity.
parse_status_t
Status of parsing.
@ PARSE_INCOMPLETE_ENTITY
unsigned int content_length
Private data – don't touch.
#define ENTREAD_USING_CHUNKED
Defines read method.
#define HDR_CONTENT_TYPE
Type of a HTTP header.
#define ENTREAD_USING_CLEN
Defines read method.
#define ENTREAD_UNTIL_CLOSE
Defines read method.
Structure of an HTTP parser object.
#define HTTP_DEFAULT_TIMEOUT
token scheme
Member variable.
hostport_type hostport
Member variable.
size_t size
Size of the buffer.
token pathquery
Member variable.
sockaddr_storage IPaddress
Network socket address.
constexpr int HTTP_SUCCESS
Yet another success code.
token text
Pointing to the full host:port string representation.
Represents a URI used in parse_uri and elsewhere.
char AcceptLanguageHeader[200]
member variable
char RangeHeader[200]
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.
int ListInit(LinkedList *list, cmp_routine cmp_func, free_function free_func)
Initializes LinkedList. Must be called first and only once for List.
void(* free_function)(void *arg)
Function for freeing list items.
Linked list node. Stores generic item and pointers to next and prev.
Linked list (no protection).
Printf format for integers.
Class for portable handling of network socket errors.
void catch_error()
Catch error for later use.
std::string error_str() const
Get human readable error description of the catched error.
Get information from a raw network socket file descriptor.
bool local_saddr(SSockaddr *a_saddr=nullptr) const
Get the local socket address the socket is bound to.
void load()
Load the raw socket file descriptor specified with the constructor into the object.
#define WEB_SERVER_CONTENT_LANGUAGE
This configuration parameter sets the value of the Content-Language header for the webserver....
#define WEB_SERVER_BUF_SIZE
This configuration parameter sets the maximum buffer size for the webserver. The default value is 1MB...
Internal implementation of the class UpnpString.
PUPNP_Api const char * UpnpString_get_String(const UpnpString *p)
Returns the pointer to char.
#define DOMString
The type of DOM strings.
Upnp_HttpMethod
Different HTTP methods.
parse_status_t parser_parse_headers(http_parser_t *parser)
Get HTTP Method, URL location and version information.
void parser_request_init(http_parser_t *parser)
Initializes parser object for a request.
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.
void parser_response_init(http_parser_t *parser, http_method_t request_method)
Initializes parser object for a response.
parse_status_t parser_parse_responseline(http_parser_t *parser)
Get HTTP Method, URL location and version information.
void httpmsg_destroy(http_message_t *msg)
Free memory allocated for the http message.
parse_status_t parser_get_entity_read_method(http_parser_t *parser)
Determines method to read entity.
parse_status_t parser_append(http_parser_t *parser, const char *buf, size_t buf_length)
Append date to HTTP parser, and do the parsing.
const char * method_to_str(http_method_t method)
A wrapper function that maps a method id to a method.
PUPNP_Api UpnpListIter UpnpListEnd(UpnpListHead *list)
Return end of list sentinel iterator (not an element)
PUPNP_Api UpnpListIter UpnpListBegin(UpnpListHead *list)
Return iterator pointing to the first list element, or UpnpListEnd(list) if the list is empty.
PUPNP_Api UpnpListIter UpnpListNext(UpnpListHead *list, UpnpListIter pos)
Return iterator pointing to element after pos, or end()
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.
char * membuffer_detach(membuffer *m)
Detaches current buffer and returns it. The caller must free the returned buffer using free()....
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 size_inc
used to increase size; MUST be > 0; (read/write).
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_SOCKET_CONNECT
The SDK had a problem connecting to a remote host.
#define UPNP_E_SOCKET_ERROR
Generic socket error code for conditions not covered by other error codes.
#define UPNP_E_FILE_READ_ERROR
An error happened while reading a file.
#define UPNP_E_BAD_HTTPMSG
The HTTP message contains invalid message headers.
#define UPNP_E_SUCCESS
The operation completed successfully.
#define UPNP_E_OUTOF_SOCKET
The SDK cannot create any more sockets.
#define UPNP_E_OUTOF_MEMORY
Not enough resources are currently available to complete the operation.
#define UPNP_E_INVALID_URL
An URL passed into the function is invalid.
#define UPNP_E_SOCKET_WRITE
An error happened while writing to a socket.
#define UPNP_E_CANCELED
The operation was canceled.
#define UPNP_E_INVALID_PARAM
One or more of the parameters passed to the function is not valid.
#define UPNP_E_INTERNAL_ERROR
Generic error code for internal conditions not covered by other error codes.
#define UPNP_E_BAD_RESPONSE
The response received from the remote side of a connection is not correct for the protocol.
UPnPsdk_EXTERN bool g_dbug
Switch to enable verbose (debug) output.
int MakeGetMessageEx(const char *url_str, membuffer *request, uri_type *url, SendInstruction *pRangeSpecifier)
Make extended GetMessage.
constexpr time_t DEFAULT_TCP_CONNECT_TIMEOUT
Default TCP connection timeout.
constexpr size_t CHUNK_TAIL_SIZE
???
int Check_Connect_And_Wait_Connection(const SOCKET a_sock, const int connect_res)
Checks socket connection and wait if it is not connected.
void copy_msg_headers(LinkedList *msgHeaders, UpnpString *headers)
Dummy function. It do nothing since years. Do we need it?
int MakeGenericMessage(http_method_t method, const char *url_str, membuffer *request, uri_type *url, int contentLength, const char *contentType, const UpnpString *headers)
Make a generic message, what ever this mean.
int get_hoststr(const char *url_str, const char **hoststr, size_t *hostlen)
Point to the hostname within a URL C-string.
int ReadResponseLineAndHeaders(SOCKINFO *info, http_parser_t *parser, int *timeout_secs, int *http_error_code)
Parses already exiting data.
constexpr size_t CHUNK_HEADER_SIZE
???
int sock_ssl_connect(SOCKINFO *info)
Associates an SSL object with the socket and begins the client-side SSL/TLS handshake.
int sock_destroy(SOCKINFO *info, int ShutdownMethod)
Shutsdown the socket using the ShutdownMethod to indicate whether sends and receives on the socket wi...
int sock_read(SOCKINFO *info, char *buffer, size_t bufsize, int *timeoutSecs)
Reads data on socket in sockinfo.
int sock_write(SOCKINFO *info, const char *buffer, size_t bufsize, int *timeoutSecs)
Writes data on the socket in sockinfo.
int sock_init(SOCKINFO *info, SOCKET sockfd)
Assign the passed in socket descriptor to socket descriptor in the SOCKINFO structure.
SOCKET socket
Handle/descriptor to a socket.
Additional socket information for connections and ssl.
Declaration of the Sockaddr class and some free helper functions.
const char * http_get_code_text(int statusCode)
Return the right status message based on the passed in int statusCode input parameter.
Trivial ::sockaddr structures enhanced with methods.
const std::string netaddrp() noexcept
Get the assosiated netaddress with port.
Define macro for synced logging to the console for detailed info and debug.
struct VirtualDirCallbacks virtualDirCallback
This structure is for virtual directory callbacks.
size_t g_maxContentLength
Maximum content-length (in bytes) that the SDK will process on an incoming packet.
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 token_string_casecmp(token *in1, const char *in2)
Compares buffer in the token object with the buffer in in2 case insensitive.
int parse_uri(const char *in, size_t max, uri_type *out)
Parses a uri as defined in RFC 2396 (explaining URIs).