Skip to content

Commit 93e73be

Browse files
author
unknown
committed
Merge branch 'development' of https://git01.codeplex.com/forks/evanc/mshpccasablanca into evanc/mshpccasablanca
2 parents e5ba5ab + b519d0c commit 93e73be

File tree

9 files changed

+336
-45
lines changed

9 files changed

+336
-45
lines changed

Release/include/cpprest/asyncrt_utils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ namespace details
284284
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3)));
285285
}
286286

287+
template <typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4>
288+
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4) {
289+
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3), std::forward<_Arg4>(arg4)));
290+
}
291+
287292
/// <summary>
288293
/// Cross platform utility function for performing case insensitive string comparision.
289294
/// </summary>

Release/include/cpprest/details/http_server_asio.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#pragma clang diagnostic ignored "-Wconversion"
2020
#endif
2121
#include <boost/asio.hpp>
22+
#include <boost/asio/ssl.hpp>
2223
#if defined(__clang__)
2324
#pragma clang diagnostic pop
2425
#endif
@@ -57,6 +58,8 @@ class hostport_listener;
5758
class connection
5859
{
5960
private:
61+
typedef void (connection::*ResponseFuncPtr) (const http_response &response, const boost::system::error_code& ec);
62+
6063
std::unique_ptr<boost::asio::ip::tcp::socket> m_socket;
6164
boost::asio::streambuf m_request_buf;
6265
boost::asio::streambuf m_response_buf;
@@ -69,16 +72,28 @@ class connection
6972
bool m_chunked;
7073
std::atomic<int> m_refs; // track how many threads are still referring to this
7174

75+
std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>> m_ssl_stream;
76+
7277
public:
73-
connection(std::unique_ptr<boost::asio::ip::tcp::socket> socket, http_linux_server* server, hostport_listener* parent)
78+
connection(std::unique_ptr<boost::asio::ip::tcp::socket> socket, http_linux_server* server, hostport_listener* parent, bool is_https, const std::function<void(boost::asio::ssl::context&)>& ssl_context_callback)
7479
: m_socket(std::move(socket))
7580
, m_request_buf()
7681
, m_response_buf()
7782
, m_p_server(server)
7883
, m_p_parent(parent)
7984
, m_refs(1)
8085
{
81-
start_request_response();
86+
if (is_https)
87+
{
88+
boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23);
89+
ssl_context_callback(ssl_context);
90+
m_ssl_stream = utility::details::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>(*m_socket, ssl_context);
91+
m_ssl_stream->async_handshake(boost::asio::ssl::stream_base::server, [this](const boost::system::error_code&) { this->start_request_response(); });
92+
}
93+
else
94+
{
95+
start_request_response();
96+
}
8297
}
8398

8499
connection(const connection&) = delete;
@@ -95,6 +110,10 @@ class connection
95110
void handle_chunked_body(const boost::system::error_code& ec, int toWrite);
96111
void dispatch_request_to_listener();
97112
void do_response(bool bad_request);
113+
void async_write(ResponseFuncPtr response_func_ptr, const http_response &response);
114+
template <typename CompletionCondition, typename Handler>
115+
void async_read(CompletionCondition &&condition, Handler &&read_handler);
116+
void async_read_until();
98117
template <typename ReadHandler>
99118
void async_read_until_buffersize(size_t size, const ReadHandler &handler);
100119
void async_process_response(http_response response);
@@ -124,14 +143,19 @@ class hostport_listener
124143
std::string m_host;
125144
std::string m_port;
126145

146+
bool m_is_https;
147+
const std::function<void(boost::asio::ssl::context&)>& m_ssl_context_callback;
148+
127149
public:
128-
hostport_listener(http_linux_server* server, const std::string& hostport)
150+
hostport_listener(http_linux_server* server, const std::string& hostport, bool is_https, const http_listener_config& config)
129151
: m_acceptor()
130152
, m_listeners()
131153
, m_listeners_lock()
132154
, m_connections_lock()
133155
, m_connections()
134156
, m_p_server(server)
157+
, m_is_https(is_https)
158+
, m_ssl_context_callback(config.get_ssl_context_callback())
135159
{
136160
m_all_connections_complete.set();
137161

Release/include/cpprest/http_client.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ typedef void* native_handle;}}}
4242

4343
#include <memory>
4444
#include <limits>
45+
#if !defined(_WIN32) && !defined(__cplusplus_winrt)
46+
#include <boost/asio/ssl.hpp>
47+
#endif
4548

4649
#include "pplx/pplxtasks.h"
4750
#include "cpprest/http_msg.h"
@@ -88,6 +91,9 @@ class http_client_config
8891
, m_validate_certificates(true)
8992
#endif
9093
, m_set_user_nativehandle_options([](native_handle)->void{})
94+
#if !defined(_WIN32) && !defined(__cplusplus_winrt)
95+
, m_ssl_context_callback([](boost::asio::ssl::context&)->void{})
96+
#endif
9197
#if defined(_WIN32) && !defined(__cplusplus_winrt)
9298
, m_buffer_request(false)
9399
#endif
@@ -316,6 +322,25 @@ class http_client_config
316322
m_set_user_nativehandle_options(handle);
317323
}
318324

325+
#if !defined(_WIN32) && !defined(__cplusplus_winrt)
326+
/// <summary>
327+
/// Sets a callback to enable custom setting of the ssl context, at construction time.
328+
/// </summary>
329+
/// <param name="callback">A user callback allowing for customization of the ssl context at construction time.</param>
330+
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& callback)
331+
{
332+
m_ssl_context_callback = callback;
333+
}
334+
335+
/// <summary>
336+
/// Gets the user's callback to allow for customization of the ssl context.
337+
/// </summary>
338+
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
339+
{
340+
return m_ssl_context_callback;
341+
}
342+
#endif
343+
319344
private:
320345
#if !defined(CPPREST_TARGET_XP)
321346
std::shared_ptr<oauth1::experimental::oauth1_config> m_oauth1;
@@ -337,6 +362,9 @@ class http_client_config
337362

338363
std::function<void(native_handle)> m_set_user_nativehandle_options;
339364

365+
#if !defined(_WIN32) && !defined(__cplusplus_winrt)
366+
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
367+
#endif
340368
#if defined(_WIN32) && !defined(__cplusplus_winrt)
341369
bool m_buffer_request;
342370
#endif

Release/include/cpprest/http_listener.h

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
#include <limits>
3030
#include <functional>
3131

32+
#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt))
33+
#include <boost/asio/ssl.hpp>
34+
#endif
35+
3236
#include "cpprest/http_msg.h"
3337

3438
#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt))
@@ -64,6 +68,9 @@ class http_listener_config
6468
/// <param name="other">http_listener_config to copy.</param>
6569
http_listener_config(const http_listener_config &other)
6670
: m_timeout(other.m_timeout)
71+
#ifndef _WIN32
72+
, m_ssl_context_callback(other.m_ssl_context_callback)
73+
#endif
6774
{}
6875

6976
/// <summary>
@@ -72,6 +79,9 @@ class http_listener_config
7279
/// <param name="other">http_listener_config to move from.</param>
7380
http_listener_config(http_listener_config &&other)
7481
: m_timeout(std::move(other.m_timeout))
82+
#ifndef _WIN32
83+
, m_ssl_context_callback(std::move(other.m_ssl_context_callback))
84+
#endif
7585
{}
7686

7787
/// <summary>
@@ -83,6 +93,9 @@ class http_listener_config
8393
if(this != &rhs)
8494
{
8595
m_timeout = rhs.m_timeout;
96+
#ifndef _WIN32
97+
m_ssl_context_callback = rhs.m_ssl_context_callback;
98+
#endif
8699
}
87100
return *this;
88101
}
@@ -96,6 +109,9 @@ class http_listener_config
96109
if(this != &rhs)
97110
{
98111
m_timeout = std::move(rhs.m_timeout);
112+
#ifndef _WIN32
113+
m_ssl_context_callback = std::move(rhs.m_ssl_context_callback);
114+
#endif
99115
}
100116
return *this;
101117
}
@@ -118,9 +134,32 @@ class http_listener_config
118134
m_timeout = std::move(timeout);
119135
}
120136

137+
#ifndef _WIN32
138+
/// <summary>
139+
/// Get the callback of ssl context
140+
/// </summary>
141+
/// <returns>The function defined by the user of http_listener_config to configure a ssl context.</returns>
142+
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
143+
{
144+
return m_ssl_context_callback;
145+
}
146+
147+
/// <summary>
148+
/// Set the callback of ssl context
149+
/// </summary>
150+
/// <param name="ssl_context_callback">The function to configure a ssl context which will setup https connections.</param>
151+
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)> &ssl_context_callback)
152+
{
153+
m_ssl_context_callback = ssl_context_callback;
154+
}
155+
#endif
156+
121157
private:
122158

123159
utility::seconds m_timeout;
160+
#ifndef _WIN32
161+
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
162+
#endif
124163
};
125164

126165
namespace details
@@ -311,4 +350,4 @@ class http_listener
311350
}}}}
312351

313352
#endif
314-
#endif
353+
#endif

Release/src/http/client/http_client_asio.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,19 @@ class asio_connection
6767
friend class asio_connection_pool;
6868
friend class asio_client;
6969
public:
70-
asio_connection(boost::asio::io_service& io_service, bool use_ssl) :
70+
asio_connection(boost::asio::io_service& io_service, bool use_ssl, const std::function<void(boost::asio::ssl::context&)>& ssl_context_callback) :
7171
m_socket(io_service),
7272
m_pool_timer(io_service),
7373
m_is_reused(false),
7474
m_keep_alive(true)
7575
{
7676
if (use_ssl)
7777
{
78-
boost::asio::ssl::context sslContext(boost::asio::ssl::context::sslv23);
79-
sslContext.set_default_verify_paths();
80-
sslContext.set_options(boost::asio::ssl::context::default_workarounds);
81-
m_ssl_stream = utility::details::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>>(m_socket, sslContext);
78+
boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23);
79+
ssl_context.set_default_verify_paths();
80+
ssl_context.set_options(boost::asio::ssl::context::default_workarounds);
81+
ssl_context_callback(ssl_context);
82+
m_ssl_stream = utility::details::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>>(m_socket, ssl_context);
8283

8384
}
8485
}
@@ -221,10 +222,11 @@ class asio_connection_pool
221222
{
222223
public:
223224

224-
asio_connection_pool(boost::asio::io_service& io_service, bool use_ssl, const std::chrono::seconds &idle_timeout) :
225+
asio_connection_pool(boost::asio::io_service& io_service, bool use_ssl, const std::chrono::seconds &idle_timeout, const std::function<void(boost::asio::ssl::context&)> &ssl_context_callback) :
225226
m_io_service(io_service),
226227
m_timeout_secs(static_cast<int>(idle_timeout.count())),
227-
m_use_ssl(use_ssl)
228+
m_use_ssl(use_ssl),
229+
m_ssl_context_callback(ssl_context_callback)
228230
{}
229231

230232
~asio_connection_pool()
@@ -260,7 +262,7 @@ class asio_connection_pool
260262
lock.unlock();
261263

262264
// No connections in pool => create a new connection instance.
263-
return std::make_shared<asio_connection>(m_io_service, m_use_ssl);
265+
return std::make_shared<asio_connection>(m_io_service, m_use_ssl, m_ssl_context_callback);
264266
}
265267
else
266268
{
@@ -297,6 +299,7 @@ class asio_connection_pool
297299
boost::asio::io_service& m_io_service;
298300
const int m_timeout_secs;
299301
const bool m_use_ssl;
302+
const std::function<void(boost::asio::ssl::context&)>& m_ssl_context_callback;
300303
std::vector<std::shared_ptr<asio_connection> > m_connections;
301304
std::mutex m_connections_mutex;
302305
};
@@ -308,7 +311,8 @@ class asio_client : public _http_client_communicator, public std::enable_shared_
308311
: _http_client_communicator(std::move(address), std::move(client_config))
309312
, m_pool(crossplat::threadpool::shared_instance().service(),
310313
base_uri().scheme() == "https",
311-
std::chrono::seconds(30)) // Unused sockets are kept in pool for 30 seconds.
314+
std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds.
315+
this->client_config().get_ssl_context_callback())
312316
, m_resolver(crossplat::threadpool::shared_instance().service())
313317
{}
314318

Release/src/http/listener/http_listener.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,11 @@ static void check_listener_uri(const http::uri &address)
4141
// Some things like proper URI schema are verified by the URI class.
4242
// We only need to check certain things specific to HTTP.
4343

44-
#ifdef _WIN32
4544
//HTTP Server API includes SSL support
4645
if(address.scheme() != U("http") && address.scheme() != U("https"))
4746
{
4847
throw std::invalid_argument("URI scheme must be 'http' or 'https'");
4948
}
50-
#else
51-
if(address.scheme() == U("https"))
52-
{
53-
throw std::invalid_argument("Listeners using 'https' are not yet supported");
54-
}
55-
56-
if(address.scheme() != U("http"))
57-
{
58-
throw std::invalid_argument("URI scheme must be 'http'");
59-
}
60-
#endif
6149

6250
if(address.host().empty())
6351
{

0 commit comments

Comments
 (0)