Skip to content

Commit be7daab

Browse files
Connection manager (aws#18)
* HttpClientConnection manager and unit tests. * Updated Http tag. * Updated common version. * Updated aws-c-io tag. * HttpConnection can clean itself up * Added host resolver, updates to handle io changes, added test for host resolver.
1 parent 30f4fb0 commit be7daab

22 files changed

+1172
-4284
lines changed

aws-common-runtime/CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,25 @@ set(AWS_DEPS_DOWNLOAD_DIR "${AWS_DEPS_BUILD_DIR}/downloads" CACHE PATH "Dependen
1717

1818
message("install dir ${AWS_DEPS_INSTALL_DIR}")
1919
set(AWS_C_COMMON_URL "https://github.com/awslabs/aws-c-common.git")
20-
set(AWS_C_COMMON_SHA "v0.3.4")
20+
set(AWS_C_COMMON_SHA "v0.3.6")
2121
include(BuildAwsCCommon)
2222

2323
if (UNIX AND NOT APPLE)
2424
set(S2N_URL "https://github.com/awslabs/s2n.git")
25-
set(S2N_SHA "ff1a8b2187ded17ee5570fd54f15c58f2175ce51")
25+
set(S2N_SHA "db4fe111c6e64a206662524da31a5aba6b0932a8")
2626
include(BuildS2N)
2727
endif()
2828

2929
set(AWS_C_IO_URL "https://github.com/awslabs/aws-c-io.git")
30-
set(AWS_C_IO_SHA "v0.2.5")
30+
set(AWS_C_IO_SHA "v0.3.0")
3131
include(BuildAwsCIO)
3232

3333
set(AWS_C_HTTP_URL "https://github.com/awslabs/aws-c-http.git")
34-
set(AWS_C_HTTP_SHA "v0.1.0")
34+
set(AWS_C_HTTP_SHA "v0.2.1")
3535
include(BuildAwsCHttp)
3636

3737
set(AWS_C_MQTT_URL "https://github.com/awslabs/aws-c-mqtt.git")
38-
set(AWS_C_MQTT_SHA "v0.3.3")
38+
set(AWS_C_MQTT_SHA "v0.3.4")
3939
include(BuildAwsCMqtt)
4040

4141
set(AWS_C_CAL_URL "https://github.com/awslabs/aws-c-cal.git")

aws-common-runtime/cmake/BuildS2N.cmake

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ if("${TARGET_ARCH}" STREQUAL ANDROID)
1919
-DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME}
2020
-DANDROID_STANDALONE_TOOLCHAIN=${ANDROID_STANDALONE_TOOLCHAIN}
2121
-DANDROID_STL=${ANDROID_STL}
22-
-DENABLE_HW_OPTIMIZATION=OFF
2322
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
23+
-DBUILD_TESTING=OFF
24+
-DUSE_S2N_PQ_CRYPTO=OFF
2425
)
2526
else()
2627
ExternalProject_Add(S2N
@@ -37,5 +38,7 @@ else()
3738
-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}
3839
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
3940
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
41+
-DBUILD_TESTING=OFF
42+
-DUSE_S2N_PQ_CRYPTO=OFF
4043
)
4144
endif()

include/aws/crt/Types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <aws/io/socket.h>
2222
#include <aws/mqtt/mqtt.h>
2323

24+
#include <list>
2425
#include <map>
2526
#include <sstream>
2627
#include <string>
@@ -62,6 +63,7 @@ namespace Aws
6263
template <typename K, typename V>
6364
using MultiMap = std::multimap<K, V, std::less<K>, StlAllocator<std::pair<const K, V>>>;
6465
template <typename T> using Vector = std::vector<T, StlAllocator<T>>;
66+
template <typename T> using List = std::list<T, StlAllocator<T>>;
6567

6668
AWS_CRT_CPP_API Allocator *DefaultAllocator() noexcept;
6769
AWS_CRT_CPP_API ByteBuf ByteBufFromCString(const char *str) noexcept;

include/aws/crt/http/HttpConnection.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,14 +324,19 @@ namespace Aws
324324
*/
325325
std::shared_ptr<HttpClientStream> NewClientStream(const HttpRequestOptions &requestOptions) noexcept;
326326

327+
/**
328+
* Returns true unless the connection is closed or closing.
329+
*/
330+
bool IsOpen() const noexcept;
331+
327332
/**
328333
* Initiate a shutdown of the connection. Sometimes, connections are persistent and you want
329334
* to close them before shutting down your application or whatever is consuming this interface.
330335
*
331336
* Assuming `OnConnectionShutdown` has not already been invoked, it will be invoked as a result of this
332-
* call. It is safe to release your reference to this object after calling this function.
337+
* call.
333338
*/
334-
bool Close() noexcept;
339+
void Close() noexcept;
335340

336341
int LastError() const noexcept { return m_lastError; }
337342

@@ -359,8 +364,6 @@ namespace Aws
359364
struct aws_http_connection *connection,
360365
int error_code,
361366
void *user_data) noexcept;
362-
363-
friend class HttpClient;
364367
};
365368

366369
} // namespace Http
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#pragma once
2+
/*
3+
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License").
6+
* You may not use this file except in compliance with the License.
7+
* A copy of the License is located at
8+
*
9+
* http://aws.amazon.com/apache2.0
10+
*
11+
* or in the "license" file accompanying this file. This file is distributed
12+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13+
* express or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*/
16+
#include <aws/crt/http/HttpConnection.h>
17+
#include <condition_variable>
18+
#include <mutex>
19+
20+
namespace Aws
21+
{
22+
namespace Crt
23+
{
24+
namespace Http
25+
{
26+
/**
27+
* Invoked when a connection from the pool is available. If a connection was successfully obtained
28+
* the connection shared_ptr can be seated into your own copy of connection. If it failed, errorCode
29+
* will be non-zero. It is your responsibility to release the connection when you are finished with it.
30+
*/
31+
using OnClientConnectionAvailable =
32+
std::function<void(std::shared_ptr<HttpClientConnection> connection, int errorCode)>;
33+
34+
struct HttpClientConnectionManagerOptions
35+
{
36+
HttpClientConnectionManagerOptions();
37+
Io::ClientBootstrap *bootstrap;
38+
size_t initialWindowSize;
39+
Io::SocketOptions *socketOptions;
40+
Io::TlsConnectionOptions *tlsConnectionOptions;
41+
ByteCursor hostName;
42+
uint16_t port;
43+
size_t maxConnections;
44+
};
45+
46+
/**
47+
* Manages a pool of connections to a specific endpoint using the same socket and tls options.
48+
*/
49+
class HttpClientConnectionManager final : public std::enable_shared_from_this<HttpClientConnectionManager>
50+
{
51+
public:
52+
~HttpClientConnectionManager();
53+
54+
/**
55+
* Acquires a connection from the pool. onClientConnectionAvailable will be invoked upon an available
56+
* connection. Returns true if the connection request was successfully pooled, returns false if it
57+
* failed. On failure, onClientConnectionAvailable will not be invoked. After receiving a connection,
58+
* you must invoke ReleaseConnection().
59+
*/
60+
bool AcquireConnection(const OnClientConnectionAvailable &onClientConnectionAvailable) noexcept;
61+
62+
/**
63+
* Releases a connection back to the pool. This will cause queued consumers to be serviced, or the
64+
* connection will be pooled waiting on another call to AcquireConnection
65+
*/
66+
void ReleaseConnection(std::shared_ptr<HttpClientConnection> connection) noexcept;
67+
68+
int LastError() const noexcept { return m_lastError; }
69+
explicit operator bool() const noexcept { return m_good; }
70+
71+
static std::shared_ptr<HttpClientConnectionManager> NewClientConnectionManager(
72+
const HttpClientConnectionManagerOptions &connectionManagerOptions,
73+
Allocator *allocator = DefaultAllocator()) noexcept;
74+
75+
private:
76+
HttpClientConnectionManager(
77+
const HttpClientConnectionManagerOptions &connectionManagerOptions,
78+
Allocator *allocator = DefaultAllocator()) noexcept;
79+
80+
Vector<std::shared_ptr<HttpClientConnection>> m_connections;
81+
List<OnClientConnectionAvailable> m_pendingConnectionRequests;
82+
Allocator *m_allocator;
83+
Io::ClientBootstrap *m_bootstrap;
84+
size_t m_initialWindowSize;
85+
Io::SocketOptions m_socketOptions;
86+
Io::TlsConnectionOptions m_tlsConnOptions;
87+
String m_hostName;
88+
uint16_t m_port;
89+
bool m_good;
90+
int m_lastError;
91+
size_t m_maxSize;
92+
size_t m_outstandingVendedConnections;
93+
size_t m_pendingConnections;
94+
std::mutex m_connectionsLock;
95+
96+
void onConnectionSetup(const std::shared_ptr<HttpClientConnection> &connection, int errorCode) noexcept;
97+
void onConnectionShutdown(HttpClientConnection &connection, int errorCode) noexcept;
98+
bool createConnection() noexcept;
99+
void poolOrVendConnection(std::shared_ptr<HttpClientConnection> connection, bool isRelease) noexcept;
100+
};
101+
} // namespace Http
102+
} // namespace Crt
103+
} // namespace Aws

include/aws/crt/io/Bootstrap.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
#include <aws/crt/Exports.h>
1818
#include <aws/crt/Types.h>
1919
#include <aws/crt/io/EventLoopGroup.h>
20+
#include <aws/crt/io/HostResolver.h>
2021

2122
#include <aws/io/channel_bootstrap.h>
23+
#include <aws/io/host_resolver.h>
2224

2325
namespace Aws
2426
{
@@ -29,12 +31,15 @@ namespace Aws
2931
class AWS_CRT_CPP_API ClientBootstrap final
3032
{
3133
public:
32-
ClientBootstrap(EventLoopGroup &elGroup, Allocator *allocator = DefaultAllocator()) noexcept;
34+
ClientBootstrap(
35+
EventLoopGroup &elGroup,
36+
HostResolver &resolver,
37+
Allocator *allocator = DefaultAllocator()) noexcept;
3338
~ClientBootstrap();
3439
ClientBootstrap(const ClientBootstrap &) = delete;
3540
ClientBootstrap &operator=(const ClientBootstrap &) = delete;
36-
ClientBootstrap(ClientBootstrap &&) noexcept;
37-
ClientBootstrap &operator=(ClientBootstrap &&) noexcept;
41+
ClientBootstrap(ClientBootstrap &&) = delete;
42+
ClientBootstrap &operator=(ClientBootstrap &&) = delete;
3843

3944
operator bool() const noexcept;
4045
int LastError() const noexcept;
@@ -47,4 +52,4 @@ namespace Aws
4752
};
4853
} // namespace Io
4954
} // namespace Crt
50-
} // namespace Aws
55+
} // namespace Aws

include/aws/crt/io/HostResolver.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#pragma once
2+
/*
3+
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License").
6+
* You may not use this file except in compliance with the License.
7+
* A copy of the License is located at
8+
*
9+
* http://aws.amazon.com/apache2.0
10+
*
11+
* or in the "license" file accompanying this file. This file is distributed
12+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13+
* express or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*/
16+
#include <aws/crt/Types.h>
17+
18+
#include <aws/io/host_resolver.h>
19+
20+
#include <functional>
21+
22+
namespace Aws
23+
{
24+
namespace Crt
25+
{
26+
namespace Io
27+
{
28+
class EventLoopGroup;
29+
class HostResolver;
30+
31+
using HostAddress = aws_host_address;
32+
33+
/**
34+
* Invoked upon resolution of an address. You do not own the memory pointed to in addresses, if you persist
35+
* the data, copy it first. If errorCode is AWS_ERROR_SUCCESS, the operation succeeded. Otherwise, the
36+
* operation failed.
37+
*/
38+
using OnHostResolved =
39+
std::function<void(HostResolver &resolver, const Vector<HostAddress> &addresses, int errorCode)>;
40+
41+
class HostResolver
42+
{
43+
public:
44+
virtual ~HostResolver();
45+
virtual bool ResolveHost(const String &host, const OnHostResolved &onResolved) noexcept = 0;
46+
virtual aws_host_resolver *GetUnderlyingHandle() noexcept = 0;
47+
virtual aws_host_resolution_config *GetConfig() noexcept = 0;
48+
};
49+
50+
class DefaultHostResolver final : public HostResolver
51+
{
52+
public:
53+
/**
54+
* Resolves DNS addresses. maxHosts is the number of unique hosts to maintain in the cache. maxTTL is
55+
* how long to keep an address in the cache before evicting it.
56+
*/
57+
DefaultHostResolver(
58+
EventLoopGroup &elGroup,
59+
size_t maxHosts,
60+
size_t maxTTL,
61+
Allocator *allocator = DefaultAllocator()) noexcept;
62+
~DefaultHostResolver();
63+
DefaultHostResolver(const DefaultHostResolver &) = delete;
64+
DefaultHostResolver &operator=(const DefaultHostResolver &) = delete;
65+
DefaultHostResolver(DefaultHostResolver &&) = delete;
66+
DefaultHostResolver &operator=(DefaultHostResolver &&) = delete;
67+
68+
operator bool() const noexcept { return m_initialized; }
69+
70+
/**
71+
* Kicks off an asynchronous resolution of host. onResolved will be invoked upon completion of the
72+
* resolution. If this returns false, the resolution was not attempted. On true, onResolved will be
73+
* called with the result.
74+
*/
75+
bool ResolveHost(const String &host, const OnHostResolved &onResolved) noexcept override;
76+
aws_host_resolver *GetUnderlyingHandle() noexcept override { return &m_resolver; }
77+
aws_host_resolution_config *GetConfig() noexcept override { return &m_config; }
78+
79+
private:
80+
aws_host_resolver m_resolver;
81+
aws_host_resolution_config m_config;
82+
Allocator *m_allocator;
83+
bool m_initialized;
84+
85+
static void s_onHostResolved(
86+
struct aws_host_resolver *resolver,
87+
const struct aws_string *host_name,
88+
int err_code,
89+
const struct aws_array_list *host_addresses,
90+
void *user_data);
91+
};
92+
} // namespace Io
93+
} // namespace Crt
94+
} // namespace Aws

samples/mqtt_pub_sub/main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,8 @@ int main(int argc, char *argv[])
159159
socketOptions.keep_alive_max_failed_probes = 1;
160160
socketOptions.keepalive = true;
161161

162-
Io::ClientBootstrap bootstrap(eventLoopGroup);
162+
Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 1, 5);
163+
Io::ClientBootstrap bootstrap(eventLoopGroup, defaultHostResolver);
163164

164165
if (!bootstrap)
165166
{

source/Api.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <aws/crt/external/cJSON.h>
1818
#include <aws/crt/io/TlsOptions.h>
1919

20+
#include <aws/http/http.h>
21+
2022
namespace Aws
2123
{
2224
namespace Crt
@@ -32,6 +34,7 @@ namespace Aws
3234
// sets up the StlAllocator for use.
3335
g_allocator = allocator;
3436
Io::InitTlsStaticState(allocator);
37+
aws_http_library_init(allocator);
3538

3639
cJSON_Hooks hooks;
3740
hooks.malloc_fn = s_cJSONAlloc;
@@ -42,6 +45,7 @@ namespace Aws
4245
static void s_cleanUpApi()
4346
{
4447
g_allocator = nullptr;
48+
aws_http_library_clean_up();
4549
Io::CleanUpTlsStaticState();
4650
}
4751

0 commit comments

Comments
 (0)