Loading [MathJax]/extensions/tex2jax.js
azure-core
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
curl_session_private.hpp
Go to the documentation of this file.
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
12#pragma once
13
17
18#include <memory>
19#include <string>
20
21#ifdef _azure_TESTING_BUILD
22// Define the class name that reads from ConnectionPool private members
23namespace Azure { namespace Core { namespace Test {
24 class CurlConnectionPool_connectionPoolTest_Test;
25 class SdkWithLibcurl_globalCleanUp_Test;
26}}} // namespace Azure::Core::Test
27#endif
28
29namespace Azure { namespace Core { namespace Http {
30
43#ifdef _azure_TESTING_BUILD
44 // Give access to private to this tests class
45 friend class Azure::Core::Test::CurlConnectionPool_connectionPoolTest_Test;
46 friend class Azure::Core::Test::SdkWithLibcurl_globalCleanUp_Test;
47#endif
48 private:
53 void ReadExpected(uint8_t expected, Context const& context);
54
60 void ReadCRLF(Context const& context);
61
72 enum class SessionState
73 {
74 PERFORM,
75 STREAMING
76 };
77
78 /*
79 * Enum used by ResponseBufferParser to control the parsing internal state while building
80 * the HTTP RawResponse
81 *
82 */
83 enum class ResponseParserState
84 {
85 StatusLine,
86 Headers,
87 EndOfHeaders,
88 };
89
102 class ResponseBufferParser final {
103 private:
108 ResponseParserState state = ResponseParserState::StatusLine;
115 std::unique_ptr<RawResponse> m_response;
121 bool m_parseCompleted = false;
122
123 bool m_delimiterStartInPrevPosition = false;
124
136 std::string m_internalBuffer;
137
150 size_t BuildStatusCode(uint8_t const* const buffer, size_t const bufferSize);
151
163 size_t BuildHeader(uint8_t const* const buffer, size_t const bufferSize);
164
165 public:
170 ResponseBufferParser() {}
171
188 size_t Parse(uint8_t const* const buffer, size_t const bufferSize);
189
195 bool IsParseCompleted() const { return m_parseCompleted; }
196
203 std::unique_ptr<RawResponse> ExtractResponse()
204 {
205 if (m_parseCompleted && m_response != nullptr)
206 {
207 return std::move(m_response);
208 }
209 return nullptr; // parse is not completed or response has been moved already.
210 }
211 };
212
221 SessionState m_sessionState = SessionState::PERFORM;
222
223 std::unique_ptr<CurlNetworkConnection> m_connection;
224
230 std::unique_ptr<RawResponse> m_response;
231
236 Request& m_request;
237
246 size_t m_bodyStartInBuffer = _detail::DefaultLibcurlReaderSize;
247
254 size_t m_innerBufferSize = _detail::DefaultLibcurlReaderSize;
255
256 bool m_isChunkedResponseType = false;
257
267 int64_t m_contentLength = 0;
268
274 size_t m_chunkSize = 0;
275
276 size_t m_sessionTotalRead = 0;
277
282 bool m_connectionUpgraded = false;
283
290 uint8_t m_readBuffer[_detail::DefaultLibcurlReaderSize]
291 = {0}; // to work with libcurl custom read.
292
301 CURLcode SendRawHttp(Context const& context);
302
310 CURLcode UploadBody(Context const& context);
311
321 CURLcode ReadStatusLineAndHeadersFromRawResponse(
322 Context const& context,
323 bool reuseInternalBuffer = false);
324
331 void ParseChunkSize(Context const& context);
332
340 Http::HttpStatusCode m_lastStatusCode = Http::HttpStatusCode::BadRequest;
341
347 bool m_httpKeepAlive = false;
348
353 bool IsEOF()
354 {
355 auto eof = m_isChunkedResponseType
356 ? m_chunkSize == 0
357 : static_cast<size_t>(m_contentLength) == m_sessionTotalRead;
358
359 // `IsEOF` is called before trying to move a connection back to the connection pool.
360 // If the session state is `PERFORM` it means the request could not complete an upload
361 // operation (might have throw while uploading).
362 // Connection should not be moved back to the connection pool on this scenario.
363 return eof && m_sessionState != SessionState::PERFORM;
364 }
365
375 bool m_keepAlive = true;
376
378 Azure::Nullable<std::string> m_httpProxyUser;
379 Azure::Nullable<std::string> m_httpProxyPassword;
380
390 size_t OnRead(uint8_t* buffer, size_t count, Azure::Core::Context const& context) override;
391
392 inline std::string GetHTTPMessagePreBody(Azure::Core::Http::Request const& request);
393 inline std::string GetHeadersAsString(Azure::Core::Http::Request const& request);
394 inline static void SetHeader(
396 std::string const& header);
397
398 public:
407 Request& request,
408 std::unique_ptr<CurlNetworkConnection> connection,
409 CurlTransportOptions curlOptions)
410 : m_connection(std::move(connection)), m_request(request),
411 m_keepAlive(curlOptions.HttpKeepAlive), m_httpProxy(curlOptions.Proxy),
412 m_httpProxyUser(curlOptions.ProxyUsername), m_httpProxyPassword(curlOptions.ProxyPassword)
413 {
414 }
415
416 ~CurlSession() override
417 {
418 // mark connection as reusable only if entire response was read
419 // If not, connection can't be reused because next Read will start from what it is currently
420 // in the wire.
421 // By not moving the connection back to the pool, it gets destroyed calling the connection
422 // destructor to clean libcurl handle and close the connection.
423 // IsEOF will also handle a connection that fail to complete an upload request.
424 if (IsEOF() && m_keepAlive && !m_connectionUpgraded)
425 {
426 _detail::CurlConnectionPool::g_curlConnectionPool.MoveConnectionBackToPool(
427 std::move(m_connection), m_httpKeepAlive);
428 }
429 }
430
438 CURLcode Perform(Context const& context);
439
446 std::unique_ptr<Azure::Core::Http::RawResponse> ExtractResponse();
447
453 int64_t Length() const override { return m_contentLength; }
454
460 std::unique_ptr<CurlNetworkConnection> ExtractConnection();
461 };
462
463}}} // namespace Azure::Core::Http
A context is a node within a unidirectional tree that represents deadlines and key/value pairs.
Definition context.hpp:72
Stateful component that controls sending an HTTP Request with libcurl over the wire.
Definition curl_session_private.hpp:42
std::unique_ptr< CurlNetworkConnection > ExtractConnection()
Return the network connection if the server indicated that the connection is upgraded.
Definition curl.cpp:521
CurlSession(Request &request, std::unique_ptr< CurlNetworkConnection > connection, CurlTransportOptions curlOptions)
Construct a new Curl Session object. Init internal libcurl handler.
Definition curl_session_private.hpp:406
int64_t Length() const override
Implement Azure::Core::IO::BodyStream length.
Definition curl_session_private.hpp:453
CURLcode Perform(Context const &context)
Function will use the HTTP request received in constructor to perform a network call based on the HTT...
Definition curl.cpp:401
std::unique_ptr< Azure::Core::Http::RawResponse > ExtractResponse()
Moved the ownership of the HTTP RawResponse out of the session.
Definition curl.cpp:1256
After receiving and interpreting a request message, a server responds with an HTTP response message.
Definition raw_response.hpp:24
A request message from a client to a server.
Definition http.hpp:183
Used to read data to/from a service.
Definition body_stream.hpp:32
Manages an optional contained value, i.e. a value that may or may not be present.
Definition nullable.hpp:30
The curl connection pool provides the utilities for creating a new curl connection and to keep a pool...
The libcurl connection keeps the curl handle and performs the data transfer to the network.
HTTP request and response functionality.
HttpStatusCode
Defines the possible HTTP status codes.
Definition http_status_code.hpp:18
Compute the hash value for the input binary data, using SHA256, SHA384 and SHA512.
Definition azure_assert.hpp:57
Set the libcurl connection options like a proxy and CA path.
Definition curl_transport.hpp:78