Skip to content

Commit e3690ab

Browse files
authored
Percolate TLS setup errors (aws#45)
1 parent 6e3a30c commit e3690ab

File tree

5 files changed

+103
-39
lines changed

5 files changed

+103
-39
lines changed

include/aws/crt/io/TlsOptions.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ namespace Aws
4444
TlsContextOptions(TlsContextOptions &&) noexcept;
4545
TlsContextOptions &operator=(TlsContextOptions &&) noexcept;
4646

47+
explicit operator bool() const noexcept { return m_isInit; }
48+
int LastError() const noexcept;
49+
4750
/**
4851
* Initializes TlsContextOptions with secure by default options, with
4952
* no client certificates.
@@ -92,7 +95,7 @@ namespace Aws
9295
* Sets the list of alpn protocols, delimited by ';'. This string must remain in memory
9396
* for the lifetime of this object.
9497
*/
95-
void SetAlpnList(const char *alpnList) noexcept;
98+
bool SetAlpnList(const char *alpnList) noexcept;
9699

97100
/**
98101
* In client mode, this turns off x.509 validation. Don't do this unless you're testing.
@@ -111,9 +114,9 @@ namespace Aws
111114
*
112115
* These strings must remain in memory for the lifetime of this object.
113116
*/
114-
void OverrideDefaultTrustStore(const char *caPath, const char *caFile) noexcept;
117+
bool OverrideDefaultTrustStore(const char *caPath, const char *caFile) noexcept;
115118

116-
void OverrideDefaultTrustStore(const ByteCursor &ca) noexcept;
119+
bool OverrideDefaultTrustStore(const ByteCursor &ca) noexcept;
117120

118121
private:
119122
aws_tls_ctx_options m_options;

include/aws/iot/MqttClient.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,24 @@ namespace Aws
2929
class AWS_CRT_CPP_API MqttClientConnectionConfig final
3030
{
3131
public:
32-
MqttClientConnectionConfig() noexcept;
32+
static MqttClientConnectionConfig CreateInvalid(int lastError) noexcept;
33+
3334
MqttClientConnectionConfig(
3435
const Crt::String &endpoint,
3536
uint16_t port,
3637
const Crt::Io::SocketOptions &socketOptions,
3738
Crt::Io::TlsContext &&tlsContext);
3839

3940
explicit operator bool() const noexcept { return m_context ? true : false; }
41+
int LastError() const noexcept { return m_lastError; }
4042

4143
private:
44+
MqttClientConnectionConfig(int lastError) noexcept;
4245
Crt::String m_endpoint;
4346
uint16_t m_port;
4447
Crt::Io::TlsContext m_context;
4548
Crt::Io::SocketOptions m_socketOptions;
49+
int m_lastError;
4650

4751
friend class MqttClient;
4852
};
@@ -127,12 +131,16 @@ namespace Aws
127131
*/
128132
MqttClientConnectionConfig Build() noexcept;
129133

134+
explicit operator bool() const noexcept { return m_lastError == 0; }
135+
int LastError() const noexcept { return m_lastError; }
136+
130137
private:
131138
Crt::Allocator *m_allocator;
132139
Crt::String m_endpoint;
133140
uint16_t m_portOverride;
134141
Crt::Io::SocketOptions m_socketOptions;
135142
Crt::Io::TlsContextOptions m_contextOptions;
143+
int m_lastError;
136144
};
137145

138146
/**
@@ -154,6 +162,7 @@ namespace Aws
154162

155163
private:
156164
Crt::Mqtt::MqttClient m_client;
165+
int m_lastError;
157166
};
158167
} // namespace Iot
159-
} // namespace Aws
168+
} // namespace Aws

samples/mqtt_pub_sub/main.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ int main(int argc, char *argv[])
124124

125125
if (!clientConfig)
126126
{
127-
fprintf(stderr, "Client Configuration initialization failed with error %s\n", ErrorDebugString(LastError()));
127+
fprintf(
128+
stderr,
129+
"Client Configuration initialization failed with error %s\n",
130+
ErrorDebugString(clientConfig.LastError()));
128131
exit(-1);
129132
}
130133

@@ -145,9 +148,9 @@ int main(int argc, char *argv[])
145148
*/
146149
auto connection = mqttClient.NewConnection(clientConfig);
147150

148-
if (!*connection)
151+
if (!connection)
149152
{
150-
fprintf(stderr, "MQTT Connection Creation failed with error %s\n", ErrorDebugString(connection->LastError()));
153+
fprintf(stderr, "MQTT Connection Creation failed with error %s\n", ErrorDebugString(mqttClient.LastError()));
151154
exit(-1);
152155
}
153156

source/io/TlsOptions.cpp

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ namespace Aws
2222
{
2323
namespace Io
2424
{
25+
int TlsContextOptions::LastError() const noexcept { return aws_last_error(); }
26+
2527
TlsContextOptions::~TlsContextOptions()
2628
{
2729
if (m_isInit)
@@ -115,36 +117,28 @@ namespace Aws
115117

116118
bool TlsContextOptions::IsAlpnSupported() noexcept { return aws_tls_is_alpn_available(); }
117119

118-
void TlsContextOptions::SetAlpnList(const char *alpn_list) noexcept
120+
bool TlsContextOptions::SetAlpnList(const char *alpn_list) noexcept
119121
{
120-
if (m_isInit)
121-
{
122-
aws_tls_ctx_options_set_alpn_list(&m_options, alpn_list);
123-
}
122+
AWS_ASSERT(m_isInit);
123+
return aws_tls_ctx_options_set_alpn_list(&m_options, alpn_list) == 0;
124124
}
125125

126126
void TlsContextOptions::SetVerifyPeer(bool verify_peer) noexcept
127127
{
128-
if (m_isInit)
129-
{
130-
aws_tls_ctx_options_set_verify_peer(&m_options, verify_peer);
131-
}
128+
AWS_ASSERT(m_isInit);
129+
aws_tls_ctx_options_set_verify_peer(&m_options, verify_peer);
132130
}
133131

134-
void TlsContextOptions::OverrideDefaultTrustStore(const char *caPath, const char *caFile) noexcept
132+
bool TlsContextOptions::OverrideDefaultTrustStore(const char *caPath, const char *caFile) noexcept
135133
{
136-
if (m_isInit)
137-
{
138-
aws_tls_ctx_options_override_default_trust_store_from_path(&m_options, caPath, caFile);
139-
}
134+
AWS_ASSERT(m_isInit);
135+
return aws_tls_ctx_options_override_default_trust_store_from_path(&m_options, caPath, caFile) == 0;
140136
}
141137

142-
void TlsContextOptions::OverrideDefaultTrustStore(const ByteCursor &ca) noexcept
138+
bool TlsContextOptions::OverrideDefaultTrustStore(const ByteCursor &ca) noexcept
143139
{
144-
if (m_isInit)
145-
{
146-
aws_tls_ctx_options_override_default_trust_store(&m_options, const_cast<ByteCursor *>(&ca));
147-
}
140+
AWS_ASSERT(m_isInit);
141+
return aws_tls_ctx_options_override_default_trust_store(&m_options, const_cast<ByteCursor *>(&ca)) == 0;
148142
}
149143

150144
void InitTlsStaticState(Aws::Crt::Allocator *alloc) noexcept { aws_tls_init_static_state(alloc); }

source/iot/MqttClient.cpp

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,40 +20,58 @@ namespace Aws
2020
{
2121
namespace Iot
2222
{
23-
MqttClientConnectionConfig::MqttClientConnectionConfig() noexcept : m_port(0)
23+
MqttClientConnectionConfig::MqttClientConnectionConfig(int lastError) noexcept
24+
: m_port(0), m_lastError(lastError)
2425
{
2526
AWS_ZERO_STRUCT(m_socketOptions);
2627
}
2728

29+
MqttClientConnectionConfig MqttClientConnectionConfig::CreateInvalid(int lastError) noexcept
30+
{
31+
return MqttClientConnectionConfig(lastError);
32+
}
33+
2834
MqttClientConnectionConfig::MqttClientConnectionConfig(
2935
const Crt::String &endpoint,
3036
uint16_t port,
3137
const Crt::Io::SocketOptions &socketOptions,
3238
Crt::Io::TlsContext &&tlsContext)
3339
: m_endpoint(endpoint), m_port(port), m_context(std::move(tlsContext)), m_socketOptions(socketOptions)
3440
{
41+
if (!m_context)
42+
{
43+
m_lastError = m_context.LastError();
44+
}
3545
}
3646

3747
MqttClientConnectionConfigBuilder::MqttClientConnectionConfigBuilder(
3848
const char *certPath,
3949
const char *pkeyPath,
4050
Crt::Allocator *allocator) noexcept
41-
: m_allocator(allocator), m_portOverride(0)
51+
: m_allocator(allocator), m_portOverride(0), m_lastError(0)
4252
{
43-
m_contextOptions = Crt::Io::TlsContextOptions::InitClientWithMtls(certPath, pkeyPath, allocator);
4453
AWS_ZERO_STRUCT(m_socketOptions);
4554
m_socketOptions.connect_timeout_ms = 3000;
55+
m_contextOptions = Crt::Io::TlsContextOptions::InitClientWithMtls(certPath, pkeyPath, allocator);
56+
if (!m_contextOptions)
57+
{
58+
m_lastError = m_contextOptions.LastError();
59+
}
4660
}
4761

4862
MqttClientConnectionConfigBuilder::MqttClientConnectionConfigBuilder(
4963
const Crt::ByteCursor &cert,
5064
const Crt::ByteCursor &pkey,
5165
Crt::Allocator *allocator) noexcept
52-
: m_allocator(allocator), m_portOverride(0)
66+
: m_allocator(allocator), m_portOverride(0), m_lastError(0)
5367
{
54-
m_contextOptions = Crt::Io::TlsContextOptions::InitClientWithMtls(cert, pkey, allocator);
5568
AWS_ZERO_STRUCT(m_socketOptions);
5669
m_socketOptions.connect_timeout_ms = 3000;
70+
m_contextOptions = Crt::Io::TlsContextOptions::InitClientWithMtls(cert, pkey, allocator);
71+
if (!m_contextOptions)
72+
{
73+
m_lastError = m_contextOptions.LastError();
74+
}
5775
}
5876

5977
MqttClientConnectionConfigBuilder &MqttClientConnectionConfigBuilder::WithEndpoint(const Crt::String &endpoint)
@@ -77,14 +95,26 @@ namespace Aws
7795
MqttClientConnectionConfigBuilder &MqttClientConnectionConfigBuilder::WithCertificateAuthority(
7896
const char *caPath) noexcept
7997
{
80-
m_contextOptions.OverrideDefaultTrustStore(nullptr, caPath);
98+
if (m_contextOptions)
99+
{
100+
if (!m_contextOptions.OverrideDefaultTrustStore(nullptr, caPath))
101+
{
102+
m_lastError = m_contextOptions.LastError();
103+
}
104+
}
81105
return *this;
82106
}
83107

84108
MqttClientConnectionConfigBuilder &MqttClientConnectionConfigBuilder::WithCertificateAuthority(
85109
const Crt::ByteCursor &cert) noexcept
86110
{
87-
m_contextOptions.OverrideDefaultTrustStore(cert);
111+
if (m_contextOptions)
112+
{
113+
if (!m_contextOptions.OverrideDefaultTrustStore(cert))
114+
{
115+
m_lastError = m_contextOptions.LastError();
116+
}
117+
}
88118
return *this;
89119
}
90120

@@ -123,6 +153,11 @@ namespace Aws
123153

124154
MqttClientConnectionConfig MqttClientConnectionConfigBuilder::Build() noexcept
125155
{
156+
if (m_lastError)
157+
{
158+
return MqttClientConnectionConfig::CreateInvalid(m_lastError);
159+
}
160+
126161
uint16_t port = m_portOverride;
127162

128163
if (!m_portOverride)
@@ -137,7 +172,10 @@ namespace Aws
137172

138173
if (port == 443 && Crt::Io::TlsContextOptions::IsAlpnSupported())
139174
{
140-
m_contextOptions.SetAlpnList("x-amzn-mqtt-ca");
175+
if (!m_contextOptions.SetAlpnList("x-amzn-mqtt-ca"))
176+
{
177+
return MqttClientConnectionConfig::CreateInvalid(m_contextOptions.LastError());
178+
}
141179
}
142180

143181
return MqttClientConnectionConfig(
@@ -148,25 +186,42 @@ namespace Aws
148186
}
149187

150188
MqttClient::MqttClient(Crt::Io::ClientBootstrap &bootstrap, Crt::Allocator *allocator) noexcept
151-
: m_client(bootstrap, allocator)
189+
: m_client(bootstrap, allocator), m_lastError(0)
152190
{
191+
if (!m_client)
192+
{
193+
m_lastError = m_client.LastError();
194+
}
153195
}
154196

155197
std::shared_ptr<Crt::Mqtt::MqttConnection> MqttClient::NewConnection(
156198
const MqttClientConnectionConfig &config) noexcept
157199
{
200+
if (!config)
201+
{
202+
m_lastError = config.LastError();
203+
return nullptr;
204+
}
205+
158206
auto newConnection = m_client.NewConnection(
159207
config.m_endpoint.c_str(),
160208
config.m_port,
161209
config.m_socketOptions,
162210
config.m_context.NewConnectionOptions());
163211

164-
if (newConnection && newConnection->SetLogin("?SDK=CPPv2&Version=" AWS_CRT_CPP_VERSION, nullptr))
212+
if (!newConnection)
213+
{
214+
m_lastError = m_client.LastError();
215+
return nullptr;
216+
}
217+
218+
if (!(*newConnection) || !newConnection->SetLogin("?SDK=CPPv2&Version=" AWS_CRT_CPP_VERSION, nullptr))
165219
{
166-
return newConnection;
220+
m_lastError = newConnection->LastError();
221+
return nullptr;
167222
}
168223

169-
return nullptr;
224+
return newConnection;
170225
}
171226
} // namespace Iot
172227
} // namespace Aws

0 commit comments

Comments
 (0)