[cpp-sp] branch main updated: Windows: Add chunked transfer code to the WinHttpAgent
Rod Widdowson
rdw at steadingsoftware.com
Fri Feb 21 16:47:35 UTC 2025
This is an automated email from the git hooks/post-receive script.
rdw pushed a commit to branch main
in repository cpp-sp.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=0072c14516415ec91ea64d65421e16e3a8529a43
The following commit(s) were added to refs/heads/main by this push:
new 0072c145 Windows: Add chunked transfer code to the WinHttpAgent
0072c145 is described below
commit 0072c14516415ec91ea64d65421e16e3a8529a43
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Fri Feb 21 16:46:46 2025 +0000
Windows: Add chunked transfer code to the WinHttpAgent
Default it off for now (with a constexpr)
---
shibsp/remoting/impl/WinHTTPRemotingService.cpp | 94 +++++++++++++++++--------
1 file changed, 65 insertions(+), 29 deletions(-)
diff --git a/shibsp/remoting/impl/WinHTTPRemotingService.cpp b/shibsp/remoting/impl/WinHTTPRemotingService.cpp
index a85e34b5..0e7995dc 100644
--- a/shibsp/remoting/impl/WinHTTPRemotingService.cpp
+++ b/shibsp/remoting/impl/WinHTTPRemotingService.cpp
@@ -45,6 +45,8 @@ using namespace std;
# define strcasecmp _stricmp
#endif
+constexpr bool defaultChunking(false);
+
namespace {
class SHIBSP_DLLLOCAL WinHTTPRemotingService : public virtual AbstractHTTPRemotingService {
@@ -124,7 +126,7 @@ wstring WinHTTPRemotingService::utf8ToUtf16(const char* input) const {
return result;
}
-void WinHTTPRemotingService::handleCert(HINTERNET Handle) const
+void WinHTTPRemotingService::handleCert(HINTERNET Handle) const
{
PCCERT_CONTEXT pCert = NULL;
DWORD dwSize = sizeof(pCert);
@@ -145,7 +147,7 @@ void WinHTTPRemotingService::handleCert(HINTERNET Handle) const
m_log.debug("Checking certificate with subject %s", buffer);
//
// TODO check the certificate
- //
+ //
cout << "Subject name " << buffer << endl;
CertFreeCertificateContext(pCert);
}
@@ -169,7 +171,7 @@ WinHTTPRemotingService::WinHTTPRemotingService(ptree& pt)
: AbstractHTTPRemotingService(pt), AbstractRemotingService(pt),
m_log(Category::getInstance(SHIBSP_LOGCAT ".RemotingService.WinHTTP")),
m_winHTTPlog(Category::getInstance(SHIBSP_LOGCAT ".winHTTP")),
- m_init(false), m_chunked(true)
+ m_init(false), m_chunked(defaultChunking)
{
if (getUserAgent() == nullptr) {
string useragent = string(PACKAGE_NAME) + '/' + PACKAGE_VERSION + '/' + "WINHTTP";
@@ -182,7 +184,7 @@ WinHTTPRemotingService::WinHTTPRemotingService(ptree& pt)
BoostPropertySet props;
props.load(pt);
- m_chunked = props.getBool(CHUNKED_PROP_NAME, true);
+ m_chunked = props.getBool(CHUNKED_PROP_NAME, defaultChunking);
m_ciphers = props.getString(CIPHER_LIST_PROP_NAME, "");
m_username = utf8ToUtf16(getAgentID());
switch (getAuthMethod()) {
@@ -300,40 +302,74 @@ void WinHTTPRemotingService::send(const char* path, istream& input, ostream& out
}
}
- wstring headers(L"Content-Type: text/plain\nExpect:");
- if (m_chunked) {
- //
- // TODO Add the chunking headers. HttpRead (below) hides the chunking from us, HttpWrite, less so. See below
- //
- //headers += L"\nTransfer-Encoding: chunked";
- //
- // I think that in this case we send WinHttpSendRequest with length = WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH
- // and use WinHttpWriteData to write the buffer in the loop below.
- //
- }
- if (!WinHttpAddRequestHeaders(request, headers.c_str(), -1, WINHTTP_ADDREQ_FLAG_ADD)) {
+ wchar_t headers[]= L"Content-Type: text/plain\r\nExpect:";
+ //
+ // Add the headers.
+ //
+ if (!WinHttpAddRequestHeaders(request, headers, -1, WINHTTP_ADDREQ_FLAG_ADD)) {
m_log.crit("Send: Could not add request headers : %d", GetLastError());
throw RemotingException("send failed");
}
if (m_chunked) {
//
- // I think that in this case we send WinHttpSendRequest with length = WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH
- // and use WinHttpWriteData to write the buffer in the loop below.
- // We dont have to worry about the read since its all done for us regardless
+ // Send the request, then the chunked data
//
- }
+ m_log.debug("Sending chunked data to %s", path);
+ if (!WinHttpSendRequest(request, L"Transfer-Encoding: chunked", -1, WINHTTP_NO_REQUEST_DATA, 0, WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0)) {
+ m_log.crit("Send. Failed to send request to %s : %d", path, GetLastError());
+ throw RemotingException("send failed");
+ }
- string msg;
- while(input) {
- char buf[1024];
- input.read(buf, sizeof(buf));
- msg.append(buf, input.gcount());
+ DWORD written;
+ while (input) {
+ //
+ // This is a pain - we have to do the chunking by hand so we send the chunky bit, then the data, end the end of chucky bit
+ //
+ char buf[1024];
+ char chunkString[128];
+ input.read(buf, sizeof(buf));
+ int transferSize = static_cast<int>(input.gcount());
+ sprintf_s(chunkString, sizeof(chunkString), "%X\r\n", transferSize);
+ DWORD chunkStringLen = static_cast<DWORD>(strnlen_s(chunkString, sizeof(chunkString)));
+
+ m_log.debug("Sending chunk with %d bytes to %s", transferSize, path);
+ if (!WinHttpWriteData(request, chunkString, chunkStringLen, &written)) {
+ m_log.crit("Send. Failed to send chunk header to %s : %d", path, GetLastError());
+ throw RemotingException("send failed");
+ }
+ if (!WinHttpWriteData(request, buf, transferSize, &written)) {
+ m_log.crit("Send. Failed to send chunk data to %s : %d", path, GetLastError());
+ throw RemotingException("send failed");
+ }
+ if (!WinHttpWriteData(request, "\r\n", 2, &written)) {
+ m_log.crit("Send. Failed to send chunk trailer to %s : %d", path, GetLastError());
+ throw RemotingException("send failed");
+ }
+ }
+ //
+ // And when all gthe data is gone we say that the last chunk is zero long
+ //
+ if (!WinHttpWriteData(request, "0\r\n", 3, &written)) {
+ m_log.crit("Send. Failed to send chunk header to %s : %d", path, GetLastError());
+ throw RemotingException("send failed");
+ }
}
- m_log.debug("Sending %d bytes to %s", msg.length(), path);
- if (!WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, const_cast<char*>(msg.c_str()), static_cast<DWORD>(msg.length()), static_cast<DWORD>(msg.length()), 0)) {
- m_log.crit("Send. Failed to send request to %s : %d", path, GetLastError());
- throw RemotingException("send failed");
+ else {
+ //
+ // Just buffer up all the data and send it in a wunner
+ //
+ string msg;
+ while(input) {
+ char buf[1024];
+ input.read(buf, sizeof(buf));
+ msg.append(buf, input.gcount());
+ }
+ m_log.debug("Sending %d bytes to %s", msg.length(), path);
+ if (!WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, const_cast<char*>(msg.c_str()), static_cast<DWORD>(msg.length()), static_cast<DWORD>(msg.length()), 0)) {
+ m_log.crit("Send. Failed to send request to %s : %d", path, GetLastError());
+ throw RemotingException("send failed");
+ }
}
if (!WinHttpReceiveResponse(request, NULL)) {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list