Skip to content

H1b #56

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

Merged
merged 15 commits into from
Aug 28, 2019
Merged
2 changes: 1 addition & 1 deletion aws-common-runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ set(AWS_DEPS_DOWNLOAD_DIR "${AWS_DEPS_BUILD_DIR}/downloads" CACHE PATH "Dependen
message("install dir ${AWS_DEPS_INSTALL_DIR}")

set(AWS_CRT_CPP_URL "https://github.com/awslabs/aws-crt-cpp.git")
set(AWS_CRT_CPP_SHA "v0.4.6")
set(AWS_CRT_CPP_SHA "v0.5.3")
include(BuildAwsCrtCpp)
2 changes: 1 addition & 1 deletion codebuild/common-posix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fi

# build aws-crt-cpp
pushd $BUILD_PATH
git clone --branch v0.4.6 https://github.com/awslabs/aws-crt-cpp.git
git clone --branch v0.5.3 https://github.com/awslabs/aws-crt-cpp.git
cd aws-crt-cpp
cmake $CMAKE_ARGS -DBUILD_DEPS=ON ./
cmake --build . --target install
Expand Down
2 changes: 1 addition & 1 deletion codebuild/common-windows.bat
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mkdir %INSTALL_DIR%
@rem build aws-crt-cpp
mkdir %BUILDS_DIR%\aws-crt-cpp-build
cd %BUILDS_DIR%\aws-crt-cpp-build
git clone --branch v0.4.6 https://github.com/awslabs/aws-crt-cpp.git
git clone --branch v0.5.3 https://github.com/awslabs/aws-crt-cpp.git
cmake %CMAKE_ARGS% -DCMAKE_INSTALL_PREFIX="%INSTALL_DIR%" -DCMAKE_PREFIX_PATH="%INSTALL_DIR%" -DCMAKE_BUILD_TYPE="Release" -DBUILD_DEPS=ON aws-crt-cpp || goto error
cmake --build . --target install || goto error

Expand Down
62 changes: 51 additions & 11 deletions discovery/include/aws/discovery/DiscoveryClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,66 @@ namespace Aws
{
using OnDiscoverResponse = std::function<void(DiscoverResponse *, int errorCode, int httpResponseCode)>;

struct DiscoveryClientConfig
class AWS_DISCOVERY_API DiscoveryClientConfig
{
public:
DiscoveryClientConfig() noexcept;
Crt::Allocator *allocator;
Crt::Io::ClientBootstrap *bootstrap;
Crt::Io::TlsContext *tlsContext;
Crt::Io::SocketOptions *socketOptions;
Crt::String region;
size_t maxConnections;
// TODO: when supported add proxy configuration.
DiscoveryClientConfig(const DiscoveryClientConfig &rhs) = default;
DiscoveryClientConfig(DiscoveryClientConfig &&rhs) = default;

DiscoveryClientConfig &operator=(const DiscoveryClientConfig &rhs) = default;
DiscoveryClientConfig &operator=(DiscoveryClientConfig &&rhs) = default;

~DiscoveryClientConfig() = default;

/**
* The client bootstrap to use for setting up and tearing down connections.
* Required.
*/
Crt::Io::ClientBootstrap *Bootstrap;

/**
* The TLS options for all http connections made by this client.
* Optional.
*/
Crt::Optional<Crt::Io::TlsContext> TlsContext;

/**
* The socket options of the connections made by the client.
* Required.
*/
Crt::Io::SocketOptions SocketOptions;

/**
* The value of the Aws region to connect to.
* Required.
*/
Crt::String Region;

/**
* The maximum number of concurrent connections allowed
*/
size_t MaxConnections;

/**
* The proxy options for all http connections made by this client.
* Optional.
*/
Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> ProxyOptions;
};

class DiscoveryClient final
class AWS_DISCOVERY_API DiscoveryClient final
{
public:
DiscoveryClient(const DiscoveryClientConfig &) noexcept;

bool Discover(const Crt::String &thingName, const OnDiscoverResponse &onDiscoverResponse) noexcept;

static std::shared_ptr<DiscoveryClient> CreateClient(
const DiscoveryClientConfig &config,
Crt::Allocator *allocator = Crt::DefaultAllocator());

private:
DiscoveryClient(const DiscoveryClientConfig &config, Crt::Allocator *allocator) noexcept;

std::shared_ptr<Crt::Http::HttpClientConnectionManager> m_connectionManager;
Crt::String m_hostName;
Crt::Allocator *m_allocator;
Expand Down
180 changes: 107 additions & 73 deletions discovery/source/DiscoveryClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
*/
#include <aws/discovery/DiscoveryClient.h>

#include <aws/crt/Api.h>
#include <aws/crt/Types.h>
#include <aws/crt/http/HttpRequestResponse.h>
#include <aws/crt/io/TlsOptions.h>
#include <aws/crt/io/Uri.h>

Expand All @@ -22,23 +24,23 @@ namespace Aws
namespace Discovery
{
DiscoveryClientConfig::DiscoveryClientConfig() noexcept
: allocator(Crt::DefaultAllocator()), bootstrap(nullptr), tlsContext(nullptr), socketOptions(nullptr),
region("us-east-1"), maxConnections(2)
: Bootstrap(nullptr), TlsContext(), SocketOptions(), Region(), MaxConnections(2), ProxyOptions()
{
}

DiscoveryClient::DiscoveryClient(const Aws::Discovery::DiscoveryClientConfig &clientConfig) noexcept
DiscoveryClient::DiscoveryClient(
const Aws::Discovery::DiscoveryClientConfig &clientConfig,
Crt::Allocator *allocator) noexcept
{
AWS_ASSERT(clientConfig.tlsContext);
AWS_ASSERT(clientConfig.bootstrap);
AWS_ASSERT(clientConfig.socketOptions);
AWS_FATAL_ASSERT(clientConfig.TlsContext);
AWS_FATAL_ASSERT(clientConfig.Bootstrap);

m_allocator = clientConfig.allocator;
m_allocator = allocator;

Crt::StringStream ss;
ss << "greengrass-ats.iot." << clientConfig.region << ".amazonaws.com";
ss << "greengrass-ats.iot." << clientConfig.Region << ".amazonaws.com";

Crt::Io::TlsConnectionOptions tlsConnectionOptions = clientConfig.tlsContext->NewConnectionOptions();
Crt::Io::TlsConnectionOptions tlsConnectionOptions = clientConfig.TlsContext->NewConnectionOptions();
uint16_t port = 443;

if (Crt::Io::TlsContextOptions::IsAlpnSupported())
Expand All @@ -54,17 +56,38 @@ namespace Aws
Crt::ByteCursor serverName = Crt::ByteCursorFromCString(m_hostName.c_str());
tlsConnectionOptions.SetServerName(serverName);

Crt::Http::HttpClientConnectionOptions connectionOptions;
connectionOptions.SocketOptions = clientConfig.SocketOptions;
connectionOptions.Bootstrap = clientConfig.Bootstrap;
connectionOptions.TlsOptions = tlsConnectionOptions;
connectionOptions.HostName = Crt::String((const char *)serverName.ptr, serverName.len);
connectionOptions.Port = port;
if (clientConfig.ProxyOptions)
{
connectionOptions.ProxyOptions = *clientConfig.ProxyOptions;
}

Crt::Http::HttpClientConnectionManagerOptions connectionManagerOptions;
connectionManagerOptions.socketOptions = clientConfig.socketOptions;
connectionManagerOptions.bootstrap = clientConfig.bootstrap;
connectionManagerOptions.tlsConnectionOptions = &tlsConnectionOptions;
connectionManagerOptions.maxConnections = clientConfig.maxConnections;
connectionManagerOptions.initialWindowSize = SIZE_MAX;
connectionManagerOptions.hostName = serverName;
connectionManagerOptions.port = port;

m_connectionManager = Crt::Http::HttpClientConnectionManager::NewClientConnectionManager(
connectionManagerOptions, clientConfig.allocator);
connectionManagerOptions.ConnectionOptions = connectionOptions;
connectionManagerOptions.MaxConnections = clientConfig.MaxConnections;

m_connectionManager =
Crt::Http::HttpClientConnectionManager::NewClientConnectionManager(connectionManagerOptions, allocator);
}

std::shared_ptr<DiscoveryClient> DiscoveryClient::CreateClient(
const Aws::Discovery::DiscoveryClientConfig &clientConfig,
Crt::Allocator *allocator)
{
auto *toSeat = static_cast<DiscoveryClient *>(aws_mem_acquire(allocator, sizeof(DiscoveryClient)));
if (toSeat)
{
toSeat = new (toSeat) DiscoveryClient(clientConfig, allocator);
return std::shared_ptr<DiscoveryClient>(
toSeat, [allocator](DiscoveryClient *client) { Crt::Delete(client, allocator); });
}

return nullptr;
}

struct ClientCallbackContext
Expand All @@ -77,8 +100,7 @@ namespace Aws
const Crt::String &thingName,
const OnDiscoverResponse &onDiscoverResponse) noexcept
{

auto *callbackContext = Crt::New<ClientCallbackContext>(m_allocator);
auto callbackContext = Crt::MakeShared<ClientCallbackContext>(m_allocator);
if (!callbackContext)
{
return false;
Expand All @@ -89,69 +111,81 @@ namespace Aws
bool res = m_connectionManager->AcquireConnection(
[this, callbackContext, thingName, onDiscoverResponse](
std::shared_ptr<Crt::Http::HttpClientConnection> connection, int errorCode) {
if (!errorCode)
if (errorCode)
{
Crt::StringStream ss;
ss << "/greengrass/discover/thing/" << thingName;
Crt::String uriStr = ss.str();
Crt::Http::HttpRequestOptions requestOptions;
requestOptions.uri = Crt::ByteCursorFromCString(uriStr.c_str());
requestOptions.method = Crt::ByteCursorFromCString("GET");

Crt::Http::HttpHeader hostNameHeader;
hostNameHeader.name = Crt::ByteCursorFromCString("host");
hostNameHeader.value = Crt::ByteCursorFromCString(m_hostName.c_str());

requestOptions.headerArray = &hostNameHeader;
requestOptions.headerArrayLength = 1;

requestOptions.onStreamOutgoingBody = nullptr;
requestOptions.onIncomingHeaders =
[](Crt::Http::HttpStream &, const Crt::Http::HttpHeader *, std::size_t) {};
requestOptions.onIncomingHeadersBlockDone =
[callbackContext](Crt::Http::HttpStream &stream, bool) {
callbackContext->responseCode = stream.GetResponseStatusCode();
};
requestOptions.onIncomingBody =
[callbackContext](Crt::Http::HttpStream &, const Crt::ByteCursor &data, std::size_t &) {
callbackContext->ss.write(reinterpret_cast<const char *>(data.ptr), data.len);
};
requestOptions.onStreamComplete = [this, connection, callbackContext, onDiscoverResponse](
Crt::Http::HttpStream &stream, int errorCode) {
if (!errorCode && callbackContext->responseCode == 200)
{
Crt::JsonObject jsonObject(callbackContext->ss.str());
DiscoverResponse response(jsonObject.View());
onDiscoverResponse(&response, AWS_ERROR_SUCCESS, callbackContext->responseCode);
}
else
{
if (!errorCode)
{
errorCode = AWS_ERROR_UNKNOWN;
}
onDiscoverResponse(nullptr, errorCode, callbackContext->responseCode);
}
onDiscoverResponse(nullptr, errorCode, 0);
return;
}

Crt::Delete(callbackContext, m_allocator);
};
auto request = Aws::Crt::MakeShared<Crt::Http::HttpRequest>(m_allocator, m_allocator);
if (request == nullptr)
{
onDiscoverResponse(nullptr, Crt::LastErrorOrUnknown(), 0);
return;
}

if (!connection->NewClientStream(requestOptions))
{
onDiscoverResponse(nullptr, aws_last_error(), 0);
Crt::Delete(callbackContext, m_allocator);
}
Crt::StringStream ss;
ss << "/greengrass/discover/thing/" << thingName;
Crt::String uriStr = ss.str();
if (!request->SetMethod(Crt::ByteCursorFromCString("GET")))
{
onDiscoverResponse(nullptr, Crt::LastErrorOrUnknown(), 0);
return;
}

if (!request->SetPath(Crt::ByteCursorFromCString(uriStr.c_str())))
{
onDiscoverResponse(nullptr, Crt::LastErrorOrUnknown(), 0);
return;
}

Crt::Http::HttpHeader hostNameHeader;
hostNameHeader.name = Crt::ByteCursorFromCString("host");
hostNameHeader.value = Crt::ByteCursorFromCString(m_hostName.c_str());

if (!request->AddHeader(hostNameHeader))
{
onDiscoverResponse(nullptr, Crt::LastErrorOrUnknown(), 0);
return;
}

onDiscoverResponse(nullptr, errorCode, 0);
Crt::Delete(callbackContext, m_allocator);
Crt::Http::HttpRequestOptions requestOptions;
requestOptions.request = request.get();
requestOptions.onIncomingHeaders =
[](Crt::Http::HttpStream &, const Crt::Http::HttpHeader *, std::size_t) {};
requestOptions.onIncomingHeadersBlockDone = [callbackContext](Crt::Http::HttpStream &stream, bool) {
callbackContext->responseCode = stream.GetResponseStatusCode();
};
requestOptions.onIncomingBody =
[callbackContext](Crt::Http::HttpStream &, const Crt::ByteCursor &data) {
callbackContext->ss.write(reinterpret_cast<const char *>(data.ptr), data.len);
};
requestOptions.onStreamComplete = [request, connection, callbackContext, onDiscoverResponse](
Crt::Http::HttpStream &, int errorCode) {
if (!errorCode && callbackContext->responseCode == 200)
{
Crt::JsonObject jsonObject(callbackContext->ss.str());
DiscoverResponse response(jsonObject.View());
onDiscoverResponse(&response, AWS_ERROR_SUCCESS, callbackContext->responseCode);
}
else
{
if (!errorCode)
{
errorCode = AWS_ERROR_UNKNOWN;
}
onDiscoverResponse(nullptr, errorCode, callbackContext->responseCode);
}
};

if (!connection->NewClientStream(requestOptions))
{
onDiscoverResponse(nullptr, Crt::LastErrorOrUnknown(), 0);
}
});

if (!res)
{
Crt::Delete(callbackContext, m_allocator);
return false;
}

Expand Down
Loading