Skip to content

Add WinHTTP Transport support to the SDK for windows clients as another HTTP Transport.#897

Merged
31 commits merged intoAzure:masterfrom
ahsonkhan:WinHttpTransport
Dec 10, 2020
Merged

Add WinHTTP Transport support to the SDK for windows clients as another HTTP Transport.#897
31 commits merged intoAzure:masterfrom
ahsonkhan:WinHttpTransport

Conversation

@ahsonkhan
Copy link
Copy Markdown
Contributor

Fixes #354

@ahsonkhan ahsonkhan added feature-request This issue requires a new behavior in the product in order be resolved. Azure.Core Client This issue points to a problem in the data-plane of the library. labels Nov 4, 2020
@ahsonkhan ahsonkhan added this to the [2020] November milestone Nov 4, 2020
@ahsonkhan ahsonkhan self-assigned this Nov 4, 2020
Comment thread sdk/core/azure-core/test/ut/transport_adapter.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Copy link
Copy Markdown
Member

@vhvb1989 vhvb1989 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Changelog
  • Readme docs about how to build and use

Really recommending to split the code from send() into multiple components. It is currently creating the handles, sending request , reading/parsing response and creating rawResponse.

  • The handles are copied to the bodyStream. Add a destructor for the bodyStream to clean the handles. Only the Send() method is caring about CleanupHandlesAndThrow, but if Read() fails or if the bodyStream is disposed, are we leaking?

Create an abstraction for writing/reading from the wire with an interface. Then create a derive class to implement the interface. This will let you create a mocked derived object to emulate the server's responses.

Comment thread cmake-modules/DefineTransportAdapter.cmake Outdated
Comment thread sdk/core/azure-core/CMakeLists.txt Outdated
Comment thread sdk/core/azure-core/CMakeLists.txt Outdated
Comment thread sdk/core/azure-core/inc/azure/core/http/http.hpp Outdated
Comment thread sdk/core/azure-core/inc/azure/core/http/winhttp/win_http_client.hpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
@ahsonkhan
Copy link
Copy Markdown
Contributor Author

ahsonkhan commented Nov 5, 2020

The handles are copied to the bodyStream. Add a destructor for the bodyStream to clean the handles. Only the Send() method is caring about CleanupHandlesAndThrow, but if Read() fails or if the bodyStream is disposed, are we leaking?

That is already happening. We are not leaking :)

See:

~WinHttpStream() override
{
WinHttpCloseHandle(this->m_requestHandle);
WinHttpCloseHandle(this->m_connectionHandle);
WinHttpCloseHandle(this->m_sessionHandle);
}

@check-enforcer
Copy link
Copy Markdown

check-enforcer Bot commented Dec 5, 2020

This pull request is protected by Check Enforcer.

What is Check Enforcer?

Check Enforcer helps ensure all pull requests are covered by at least one check-run (typically an Azure Pipeline). When all check-runs associated with this pull request pass then Check Enforcer itself will pass.

Why am I getting this message?

You are getting this message because Check Enforcer did not detect any check-runs being associated with this pull request within five minutes. This may indicate that your pull request is not covered by any pipelines and so Check Enforcer is correctly blocking the pull request being merged.

What should I do now?

If the check-enforcer check-run is not passing and all other check-runs associated with this PR are passing (excluding license-cla) then you could try telling Check Enforcer to evaluate your pull request again. You can do this by adding a comment to this pull request as follows:
/check-enforcer evaluate
Typically evaulation only takes a few seconds. If you know that your pull request is not covered by a pipeline and this is expected you can override Check Enforcer using the following command:
/check-enforcer override
Note that using the override command triggers alerts so that follow-up investigations can occur (PRs still need to be approved as normal).

What if I am onboarding a new service?

Often, new services do not have validation pipelines associated with them, in order to bootstrap pipelines for a new service, you can issue the following command as a pull request comment:
/azp run prepare-pipelines
This will run a pipeline that analyzes the source tree and creates the pipelines necessary to build and validate your pull request. Once the pipeline has been created you can trigger the pipeline using the following comment:
/azp run cpp - [service] - ci

@ahsonkhan
Copy link
Copy Markdown
Contributor Author

/azp run cpp - storage

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Member

@vhvb1989 vhvb1989 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a few comments.

Feel free to create issues to address those things in the future if you are ready to merge.

Comment thread CMakeSettings.json
Comment thread sdk/core/azure-core/CHANGELOG.md
Comment thread sdk/core/azure-core/inc/azure/core/http/winhttp/win_http_client.hpp
Comment thread sdk/core/azure-core/inc/azure/core/http/winhttp/win_http_client.hpp Outdated
private:
WinHttpTransportOptions m_options;

void GetSessionHandle(std::unique_ptr<Details::HandleManager>& handleManager);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it would just better to use a pointer here like Details::HandleManager const* const or Details::HandleManager * const.
The main purpose of using the unique_ptr is to handle the ownership and ensure only only owner. My recommendation is to change this signatures to a raw pointer. We can still keep a unique_ptr wherever it's need, We can get the raw pointer from the unique_ptr by calling .get().
@antkmsft , I would like to hear from you here since you know better understanding of this

Comment on lines +558 to +566
GetSessionHandle(handleManager);
GetConnectionHandle(handleManager);
GetRequestHandle(handleManager);

SendRequest(handleManager);

ReceiveResponse(handleManager);

return GetRawResponse(handleManager, request.GetMethod());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these methods dont's need to get a unique_ptr.
Instead, they can just take a referece or a raw pointer to HandleManager.

The benefit, if it just a reference, is that you never worry about null argument exception.
See, I made this example on how to pass a reference from a unique_ptr, I recommend following this approach here
https://godbolt.org/z/71G7nd

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this is an implementation detail and seems somewhat subjective, I am inclined to leave it as is for now.

One thing I need is the destructor of handleManager to be called whenever we throw. Would passing them as raw pointers or a reference still let that happen?

Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp
Comment thread sdk/core/azure-core/test/ut/CMakeLists.txt
@ahsonkhan
Copy link
Copy Markdown
Contributor Author

/azp run cpp - storage

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@ahsonkhan
Copy link
Copy Markdown
Contributor Author

/azp run cpp - storage

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Member

@vhvb1989 vhvb1989 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding some responses

Also mentioning an issue with the unique_ptr that needs to be fixed before merging.
The WinHttpBodyStream is currently stealing the handleManager ownership instead of expecting to become the owner

Comment thread CMakeSettings.json
// Specify an HTTP server.
// Uses port 80 for HTTP and port 443 for HTTPS.
// This function always operates synchronously.
handleManager->m_connectionHandle = WinHttpConnect(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not managing anything. It is acting just as a container or bag. But any name you decide is up to up as the author.

Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp
Comment thread sdk/core/azure-core/inc/azure/core/http/winhttp/win_http_client.hpp Outdated
Comment thread sdk/core/azure-core/inc/azure/core/http/winhttp/win_http_client.hpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
Comment thread sdk/core/azure-core/src/http/winhttp/win_http_transport.cpp Outdated
@ahsonkhan
Copy link
Copy Markdown
Contributor Author

/azp run cpp - storage

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@ghost
Copy link
Copy Markdown

ghost commented Dec 10, 2020

Hello @ahsonkhan!

Because this pull request has the auto-merge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ahsonkhan
Copy link
Copy Markdown
Contributor Author

Thanks for the great and detailed feedback @vhvb1989. Appreciate it!

If anyone else has any other pressing feedback or wants me to change something, please review it and let me know and I will address it separately. In the interest of time, given the duration and size of this PR and conversation, I am going to merge this as-is, once CI is green (again).

@ghost ghost merged commit 0f854ff into Azure:master Dec 10, 2020
@ahsonkhan ahsonkhan deleted the WinHttpTransport branch December 10, 2020 22:47
@ahsonkhan
Copy link
Copy Markdown
Contributor Author

@Jinming-Hu can't wait for you to share the performance numbers on Windows. I have some optimizations in mind that I suspect can get us some improvements, but wanted to see the change first to get a sense of order-of-magnitude. Thanks!

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Azure.Core Client This issue points to a problem in the data-plane of the library. feature-request This issue requires a new behavior in the product in order be resolved.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WinHttp transport implementation

3 participants