Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique ptr for body stream #214

Merged
merged 27 commits into from
Jun 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ebf727c
change bodyStream to unique ptr
vhvb1989 Jun 24, 2020
8d0fc4f
stream ptr to unique_ptr
vhvb1989 Jun 24, 2020
a056962
updating storage to from bodyStream ptr to unique_ptr
vhvb1989 Jun 24, 2020
acab755
upload donwload to use unique ptr
vhvb1989 Jun 24, 2020
53ad030
checkpoint
vhvb1989 Jun 25, 2020
5134883
checkpoint
vhvb1989 Jun 25, 2020
2e08ba3
readChunked
vhvb1989 Jun 25, 2020
e3c30cb
reading chunk
vhvb1989 Jun 25, 2020
fba4e6c
storage tests fixes
vhvb1989 Jun 25, 2020
0be1cde
mac fixes
vhvb1989 Jun 25, 2020
c83807d
Fix build error on Mac and Windows
Jinming-Hu Jun 25, 2020
21d18f9
Blob service adapts to std::unique_ptr<BodyStream>
Jinming-Hu Jun 25, 2020
c7d3217
update test reading stream
vhvb1989 Jun 25, 2020
cb707b6
Merge branch 'unique-ptr-for-body-stream' of github.com:vhvb1989/azur…
vhvb1989 Jun 25, 2020
8afde21
Adding response body type enum to support reading strategies
vhvb1989 Jun 25, 2020
784a2a0
remove http.cpp with no code
vhvb1989 Jun 25, 2020
4d8ddeb
win86 fix
vhvb1989 Jun 25, 2020
a8cd90f
Merge branch 'master' of github.com:Azure/azure-sdk-for-cpp into uniq…
vhvb1989 Jun 25, 2020
c321fb3
Merge branch 'master' of github.com:Azure/azure-sdk-for-cpp into uniq…
vhvb1989 Jun 26, 2020
64af158
use BuildArgs for building in CI
vhvb1989 Jun 26, 2020
e51e173
revert
vhvb1989 Jun 26, 2020
bc92271
reduce stack usage on storage test
vhvb1989 Jun 26, 2020
12e85b1
x86 compilation fix
vhvb1989 Jun 26, 2020
d8497e8
x86 compile fix
vhvb1989 Jun 26, 2020
bd86ab6
remove parallel
vhvb1989 Jun 26, 2020
e775530
Merge branch 'master' of github.com:Azure/azure-sdk-for-cpp into uniq…
vhvb1989 Jun 29, 2020
22b0999
make credentials to use unique_ptr for request
vhvb1989 Jun 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion sdk/core/azure-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ add_library (
src/context.cpp
src/credentials/credentials.cpp
src/credentials/policy/policies.cpp
src/http/http.cpp
src/http/policy.cpp
src/http/request.cpp
src/http/response.cpp
Expand Down
42 changes: 35 additions & 7 deletions sdk/core/azure-core/inc/http/curl/curl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

namespace Azure { namespace Core { namespace Http {

constexpr auto UploadSstreamPageSize = 1024 * 64;
constexpr auto UploadStreamPageSize = 1024 * 64;
constexpr auto LibcurlReaderSize = 100;

/**
Expand Down Expand Up @@ -43,6 +43,18 @@ namespace Azure { namespace Core { namespace Http {
EndOfHeaders,
};

/**
* @brief Defines the strategy to read the body from an HTTP Response
*
*/
enum class ResponseBodyLengthType
{
ContentLength,
Chunked,
ReadToCloseConnection,
NoBody,
};

/**
* @brief stateful component used to read and parse a buffer to construct a valid HTTP Response.
*
Expand Down Expand Up @@ -212,6 +224,20 @@ namespace Azure { namespace Core { namespace Http {
*/
size_t m_bodyStartInBuffer;

/**
* @brief Control field to handle the number of bytes containing relevant data within the
* internal buffer. This is because internal buffer can be set to be size N but after writing
* from wire into it, it can be holding less then N bytes.
*
*/
size_t m_innerBufferSize;

/**
* @brief Defines the strategy to read a body from an HTTP Response
*
*/
ResponseBodyLengthType m_bodyLengthType;

/**
* @brief This is a copy of the value of an HTTP response header `content-length`. The value is
* received as string and parsed to size_t. This field avoid parsing the string header everytime
Expand Down Expand Up @@ -329,6 +355,7 @@ namespace Azure { namespace Core { namespace Http {
* requested.
*/
uint64_t ReadSocketToBuffer(uint8_t* buffer, size_t bufferSize);
uint64_t ReadChunkedBody(uint8_t* buffer, uint64_t bufferSize, uint64_t offset);

public:
/**
Expand All @@ -340,6 +367,7 @@ namespace Azure { namespace Core { namespace Http {
{
this->m_pCurl = curl_easy_init();
this->m_bodyStartInBuffer = 0;
this->m_innerBufferSize = LibcurlReaderSize;
}

/**
Expand Down Expand Up @@ -412,6 +440,8 @@ namespace Azure { namespace Core { namespace Http {
*/
uint64_t m_offset;

bool m_unknownSize;

public:
/**
* @brief Construct a new Curl Body Stream object.
Expand All @@ -425,12 +455,9 @@ namespace Azure { namespace Core { namespace Http {
{
}

~CurlBodyStream()
CurlBodyStream(CurlSession* curlSession)
: m_length(0), m_curlSession(curlSession), m_offset(0), m_unknownSize(true)
{
if (this->m_curlSession != nullptr)
{
delete this->m_curlSession; // Session Destructor will cleanup libcurl handle
}
}

/**
Expand All @@ -450,13 +477,14 @@ namespace Azure { namespace Core { namespace Http {
*/
uint64_t Read(uint8_t* buffer, uint64_t count) override
{
if (this->m_length == this->m_offset)
if (this->m_length == this->m_offset && !this->m_unknownSize)
{
return 0;
}
// Read bytes from curl into buffer. As max as the length of Stream is allowed
auto readCount = this->m_curlSession->ReadWithOffset(buffer, count, this->m_offset);
this->m_offset += readCount;

return readCount;
}

Expand Down
47 changes: 18 additions & 29 deletions sdk/core/azure-core/inc/http/http.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ namespace Azure { namespace Core { namespace Http {
std::map<std::string, std::string> m_retryHeaders;
std::map<std::string, std::string> m_retryQueryParameters;
// Work only with streams
BodyStream* m_bodyStream;
std::unique_ptr<BodyStream> m_bodyStream;

// flag to know where to insert header
bool m_retryModeEnabled;
Expand All @@ -233,25 +233,14 @@ namespace Azure { namespace Core { namespace Http {
std::string GetQueryString() const;

public:
Request(HttpMethod httpMethod, std::string const& url, BodyStream* bodyStream)
: m_method(std::move(httpMethod)), m_url(url), m_bodyStream(bodyStream),
Request(HttpMethod httpMethod, std::string const& url, std::unique_ptr<BodyStream> bodyStream)
: m_method(std::move(httpMethod)), m_url(url), m_bodyStream(std::move(bodyStream)),
m_retryModeEnabled(false)
{
}

// Typically used for GET with no request body.
Request(HttpMethod httpMethod, std::string const& url)
: Request(httpMethod, url, BodyStream::null)
{
}

~Request()
{
if (this->m_bodyStream != BodyStream::null)
{
delete this->m_bodyStream;
}
}
Request(HttpMethod httpMethod, std::string const& url) : Request(httpMethod, url, nullptr) {}

// Methods used to build HTTP request
void AppendPath(std::string const& path);
Expand Down Expand Up @@ -296,16 +285,16 @@ namespace Azure { namespace Core { namespace Http {
std::string m_reasonPhrase;
std::map<std::string, std::string> m_headers;

BodyStream* m_bodyStream;
std::unique_ptr<BodyStream> m_bodyStream;

Response(
int32_t majorVersion,
int32_t minorVersion,
HttpStatusCode statusCode,
std::string const& reasonPhrase,
BodyStream* const BodyStream)
std::unique_ptr<BodyStream> BodyStream)
: m_majorVersion(majorVersion), m_minorVersion(minorVersion), m_statusCode(statusCode),
m_reasonPhrase(reasonPhrase), m_bodyStream(BodyStream)
m_reasonPhrase(reasonPhrase), m_bodyStream(std::move(BodyStream))
{
}

Expand All @@ -315,23 +304,15 @@ namespace Azure { namespace Core { namespace Http {
int32_t minorVersion,
HttpStatusCode statusCode,
std::string const& reasonPhrase)
: Response(majorVersion, minorVersion, statusCode, reasonPhrase, BodyStream::null)
{
}

~Response()
: Response(majorVersion, minorVersion, statusCode, reasonPhrase, nullptr)
{
if (this->m_bodyStream != BodyStream::null)
{
delete this->m_bodyStream;
}
}

// Methods used to build HTTP response
void AddHeader(std::string const& name, std::string const& value);
// rfc form header-name: OWS header-value OWS
void AddHeader(std::string const& header);
void SetBodyStream(BodyStream* stream);
void SetBodyStream(std::unique_ptr<BodyStream> stream);

// adding getters for version and stream body. Clang will complain on Mac if we have unused
// fields in a class
Expand All @@ -340,7 +321,15 @@ namespace Azure { namespace Core { namespace Http {
HttpStatusCode GetStatusCode() const;
std::string const& GetReasonPhrase();
std::map<std::string, std::string> const& GetHeaders();
BodyStream* GetBodyStream() { return this->m_bodyStream; }
std::unique_ptr<BodyStream> GetBodyStream()
{
if (this->m_bodyStream == nullptr)
{
// Moved before or not yet created
return nullptr;
}
return std::move(this->m_bodyStream);
}

// Allocates a buffer in heap and reads and copy stream content into it.
// util for any API that needs to get the content from stream as a buffer
Expand Down
5 changes: 1 addition & 4 deletions sdk/core/azure-core/inc/http/stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Azure { namespace Core { namespace Http {
// BodyStream is used to read data to/from a service
class BodyStream {
public:
static BodyStream* null;
virtual ~BodyStream() = 0;

// Returns the length of the data; used with the HTTP Content-Length header
virtual uint64_t Length() const = 0;
Expand All @@ -33,9 +33,6 @@ namespace Azure { namespace Core { namespace Http {

// Closes the stream; typically called after all data read or if an error occurs.
virtual void Close() = 0;

// Desstructor. Enables derived classes to call its destructor
virtual ~BodyStream() = 0;
};

class MemoryBodyStream : public BodyStream {
Expand Down
6 changes: 3 additions & 3 deletions sdk/core/azure-core/src/credentials/credentials.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ AccessToken ClientSecretCredential::GetToken(

auto bodyStream = std::make_unique<Http::MemoryBodyStream>(bodyVec);

Http::Request request(Http::HttpMethod::Post, url.str(), bodyStream.get());
Http::Request request(Http::HttpMethod::Post, url.str(), std::move(bodyStream));
bodyStream.release();

request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
Expand Down Expand Up @@ -103,8 +103,8 @@ AccessToken ClientSecretCredential::GetToken(
{
std::ostringstream errorMsg;
errorMsg << errorMsgPrefix << "error response: "
<< static_cast<std::underlying_type<Http::HttpStatusCode>::type>(statusCode)
<< " " << response->GetReasonPhrase();
<< static_cast<std::underlying_type<Http::HttpStatusCode>::type>(statusCode) << " "
<< response->GetReasonPhrase();

throw AuthenticationException(errorMsg.str());
}
Expand Down
Loading