From 35a64f5facfbb1c244d4bffd8c2d3519562cc7a6 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 1 Oct 2015 22:54:08 -0700 Subject: [PATCH 001/609] Added CMake macro to disable websockets functionality on Windows --- Release/CMakeLists.txt | 15 ++++++++++++--- Release/src/CMakeLists.txt | 5 ++++- Release/tests/common/TestRunner/CMakeLists.txt | 5 ++--- .../tests/functional/http/client/CMakeLists.txt | 2 +- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 2938285f0e..d46a5f8a4c 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -101,6 +101,7 @@ elseif(WIN32) option(BUILD_SHARED_LIBS "Build shared Libraries." ON) option(BUILD_TESTS "Build tests." ON) option(BUILD_SAMPLES "Build samples." ON) + option(CPPREST_EXCLUDE_WEBSOCKETS "Exclude websockets functionality." OFF) option(Boost_USE_STATIC_LIBS ON) add_definitions(-DUNICODE -D_UNICODE) @@ -114,8 +115,12 @@ elseif(WIN32) endif() add_definitions(${Casablanca_DEFINITIONS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -DWIN32) - find_package(Boost 1.55 REQUIRED COMPONENTS random system thread filesystem chrono atomic) - find_package(OpenSSL 1.0 REQUIRED) + if (CPPREST_EXCLUDE_WEBSOCKETS) + add_definitions(-DCPPREST_EXCLUDE_WEBSOCKETS=1) + else() + find_package(Boost 1.55 REQUIRED COMPONENTS random system thread filesystem chrono atomic) + find_package(OpenSSL 1.0 REQUIRED) + endif() else() message(FATAL_ERROR "-- Unsupported Build Platform.") endif() @@ -165,7 +170,11 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) # These settings can be used by the test targets set(Casablanca_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) -set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${Boost_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp) +if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${Boost_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp) +else() + set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) +endif() set(Casablanca_LIBRARY ${LIB}cpprest) set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} ${Boost_LIBRARIES} ${Boost_FRAMEWORK}) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 766e4964bd..f6a000478d 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -1,4 +1,7 @@ -include_directories(../include pch ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}) +include_directories(../include pch) +if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + include_directories(${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}) +endif() set(SOURCES_COMMON http/client/http_client_msg.cpp diff --git a/Release/tests/common/TestRunner/CMakeLists.txt b/Release/tests/common/TestRunner/CMakeLists.txt index 2a00f35431..57e63348b9 100644 --- a/Release/tests/common/TestRunner/CMakeLists.txt +++ b/Release/tests/common/TestRunner/CMakeLists.txt @@ -1,6 +1,5 @@ -include_directories(${Casablanca_INCLUDE_DIR} +include_directories(${Casablanca_INCLUDE_DIRS} ../UnitTestpp - ${Boost_INCLUDE_DIR} ) set(TR_SOURCES @@ -100,4 +99,4 @@ if(NOT IOS AND NOT ANDROID) ) endif() endif() -endif() +endif() diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 97083a20a7..dd9a2b89d0 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -1,7 +1,7 @@ include_directories( ../utilities/include ../utilities/testlistener/include - ${OPENSSL_INCLUDE_DIR} + ${Casablanca_INCLUDE_DIRS} ) set(SOURCES From 6e07ff3db7533a6ef813a9c2c5bc54c06d8c7d8f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 1 Oct 2015 22:54:24 -0700 Subject: [PATCH 002/609] Only use PCH when using MSBuild --- Release/src/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index f6a000478d..bf652bc227 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -70,8 +70,12 @@ elseif(WIN32) httpapi.lib Winhttp.lib ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} /Yustdafx.h /Zm200") - set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS}") + if (${CMAKE_GENERATOR} MATCHES "Visual Studio .*") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Yustdafx.h /Zm200") + set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + endif() + if (BUILD_SHARED_LIBS) add_definitions(-D_ASYNCRT_EXPORT -D_PPLX_EXPORT -D_USRDLL) endif() From 1dc9934d093db7353158f0376cac2f8689042d4e Mon Sep 17 00:00:00 2001 From: Gergely Lukacsy Date: Tue, 10 Nov 2015 14:52:23 +0000 Subject: [PATCH 003/609] Add unsolicited pong support with integration tests --- Release/include/cpprest/ws_msg.h | 17 ++++++++++ .../src/websockets/client/ws_client_wspp.cpp | 11 ++++-- .../websockets/client/send_msg_tests.cpp | 34 +++++++++++++++++++ .../utilities/test_websocket_server.cpp | 19 +++++++++-- .../utilities/test_websocket_server.h | 3 +- 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/Release/include/cpprest/ws_msg.h b/Release/include/cpprest/ws_msg.h index 9b3fe713a7..171234edf0 100644 --- a/Release/include/cpprest/ws_msg.h +++ b/Release/include/cpprest/ws_msg.h @@ -73,6 +73,15 @@ class websocket_outgoing_message { public: + /// + /// Sets a the outgoing message to be an unsolicited pong message. + /// This is useful when the client side wants to check whether the server is alive. + /// + void set_pong_message() + { + this->set_message_pong(); + } + /// /// Sets a UTF-8 message as the message body. /// @@ -152,6 +161,14 @@ class websocket_outgoing_message const pplx::task_completion_event & body_sent() const { return m_body_sent; } + void set_message_pong() + { + concurrency::streams::container_buffer buffer(""); + m_msg_type = websocket_message_type::pong; + m_length = static_cast(buffer.size()); + m_body = buffer; + } + void set_message(const concurrency::streams::container_buffer &buffer) { m_msg_type = websocket_message_type::text_message; diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 1e53f69e39..bd17af922e 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -373,13 +373,14 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: { case websocket_message_type::text_message: case websocket_message_type::binary_message: + case websocket_message_type::pong: break; default: return pplx::task_from_exception(websocket_exception("Invalid message type")); } const auto length = msg.m_length; - if (length == 0) + if (length == 0 && msg.m_msg_type != websocket_message_type::pong) { return pplx::task_from_exception(websocket_exception("Cannot send empty message.")); } @@ -639,13 +640,19 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: ec); break; case websocket_message_type::binary_message: - client.send( + client.send( this_client->m_con, sp_allocated.get(), length, websocketpp::frame::opcode::binary, ec); break; + case websocket_message_type::pong: + client.pong( + this_client->m_con, + "", + ec); + break; default: // This case should have already been filtered above. std::abort(); diff --git a/Release/tests/functional/websockets/client/send_msg_tests.cpp b/Release/tests/functional/websockets/client/send_msg_tests.cpp index f0cd3ea82a..1303207a0e 100644 --- a/Release/tests/functional/websockets/client/send_msg_tests.cpp +++ b/Release/tests/functional/websockets/client/send_msg_tests.cpp @@ -103,6 +103,21 @@ pplx::task send_text_msg_helper(SocketClientClass& client, web::uri uri, t return client.send(msg); } +template +pplx::task send_pong_msg_helper(SocketClientClass& client, web::uri uri, test_websocket_server& server) +{ + server.next_message([](test_websocket_msg msg) // Handler to verify the message sent by the client. + { + websocket_asserts::assert_message_equals(msg, "", test_websocket_message_type::WEB_SOCKET_PONG_TYPE); + }); + + client.connect(uri).wait(); + + websocket_outgoing_message msg; + msg.set_pong_message(); + return client.send(msg); +} + pplx::task send_msg_from_stream(websocket_client& client, test_websocket_server& server, web::uri uri, @@ -456,6 +471,25 @@ TEST_FIXTURE(uri_address, send_stream_binary_msg_no_length) client.close().wait(); } +// Send an unsolicited pong message to the server +TEST_FIXTURE(uri_address, send_pong_msg) +{ + test_websocket_server server; + websocket_client client; + send_pong_msg_helper(client, m_uri, server).wait(); + client.close().wait(); +} + +// Send an unsolicited pong message to the server with websocket_callback_client +TEST_FIXTURE(uri_address, send_pong_msg_callback_client) +{ + test_websocket_server server; + websocket_callback_client client; + send_pong_msg_helper(client, m_uri, server).wait(); + client.close().wait(); +} + + } // SUITE(send_msg_tests) }}}} diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp index c1377ee4ec..4485e93f86 100644 --- a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp +++ b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp @@ -134,6 +134,19 @@ namespace utilities { m_server_connected.set_exception(std::runtime_error("Connection attempt failed.")); }); + m_srv.set_pong_handler([this](websocketpp::connection_hdl hdl, std::string input) + { + auto fn = m_test_srv->get_next_message_handler(); + assert(fn); + + test_websocket_msg wsmsg; + + wsmsg.set_data(std::vector(input.begin(), input.end())); + + wsmsg.set_msg_type(WEB_SOCKET_PONG_TYPE); + fn(wsmsg); + }); + m_srv.set_message_handler([this](websocketpp::connection_hdl hdl, server::message_ptr msg) { auto pay = msg->get_payload(); @@ -151,12 +164,12 @@ namespace utilities { wsmsg.set_msg_type(utilities::WEB_SOCKET_BINARY_MESSAGE_TYPE); break; case websocketpp::frame::opcode::text: - wsmsg.set_msg_type(utilities::WEB_SOCKET_UTF8_MESSAGE_TYPE); + wsmsg.set_msg_type(utilities::WEB_SOCKET_UTF8_MESSAGE_TYPE); break; case websocketpp::frame::opcode::close: wsmsg.set_msg_type(utilities::WEB_SOCKET_CLOSE_TYPE); break; - default: + default: // Websocketspp does not currently support explicit fragmentation. We should not get here. std::abort(); } @@ -262,7 +275,7 @@ namespace utilities { case test_websocket_message_type::WEB_SOCKET_CLOSE_TYPE: flags = websocketpp::frame::opcode::close; // WebSocket::FRAME_OP_CLOSE; break; - case test_websocket_message_type::WEB_SOCKET_UTF8_FRAGMENT_TYPE: + case test_websocket_message_type::WEB_SOCKET_UTF8_FRAGMENT_TYPE: case test_websocket_message_type::WEB_SOCKET_BINARY_FRAGMENT_TYPE: default: throw std::runtime_error("invalid message type"); diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.h b/Release/tests/functional/websockets/utilities/test_websocket_server.h index b5440068b2..5126c8281d 100644 --- a/Release/tests/functional/websockets/utilities/test_websocket_server.h +++ b/Release/tests/functional/websockets/utilities/test_websocket_server.h @@ -50,7 +50,8 @@ enum test_websocket_message_type WEB_SOCKET_BINARY_FRAGMENT_TYPE, WEB_SOCKET_UTF8_MESSAGE_TYPE, WEB_SOCKET_UTF8_FRAGMENT_TYPE, - WEB_SOCKET_CLOSE_TYPE + WEB_SOCKET_CLOSE_TYPE, + WEB_SOCKET_PONG_TYPE }; // Interface containing details about the HTTP handshake request received by the test server. From 0292c7c34d12875af0774a1fe9f46190625698d2 Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Thu, 12 Nov 2015 19:45:44 +1100 Subject: [PATCH 004/609] Refactor the response handling in http_server_httpsys to fix some issues where error replies didn't get sent, and cyclic references weren't cleaned up --- .../cpprest/details/http_server_httpsys.h | 3 + .../src/http/listener/http_listener_msg.cpp | 2 +- .../src/http/listener/http_server_httpsys.cpp | 115 ++++++++++++------ 3 files changed, 79 insertions(+), 41 deletions(-) diff --git a/Release/include/cpprest/details/http_server_httpsys.h b/Release/include/cpprest/details/http_server_httpsys.h index 0de4934cf1..261aa7ad44 100644 --- a/Release/include/cpprest/details/http_server_httpsys.h +++ b/Release/include/cpprest/details/http_server_httpsys.h @@ -99,6 +99,9 @@ struct windows_request_context : http::details::_http_server_context // Dispatch request to the provided http_listener. void dispatch_request_to_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener); + // Initialise the response task callbacks + void do_response(bool bad_request); + // Read in a portion of the request body. void read_request_body_chunk(); diff --git a/Release/src/http/listener/http_listener_msg.cpp b/Release/src/http/listener/http_listener_msg.cpp index bbfbdc99ff..15c6af57ec 100644 --- a/Release/src/http/listener/http_listener_msg.cpp +++ b/Release/src/http/listener/http_listener_msg.cpp @@ -47,7 +47,7 @@ pplx::task details::_http_request::_reply_impl(http_response response) { // Add a task-based continuation so no exceptions thrown from the task go 'unobserved'. response._set_server_context(std::move(m_server_context)); - response_completed = experimental::details::http_server_api::server_api()->respond(response); + response_completed = server_api->respond(response); response_completed.then([](pplx::task t) { try { t.wait(); } catch(...) {} diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 21284f2c9e..f389d5fed7 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -494,6 +494,12 @@ windows_request_context::~windows_request_context() // the lock then setting of the event has completed. std::unique_lock lock(m_responseCompletedLock); + // Add a task-based continuation so no exceptions thrown from the task go 'unobserved'. + pplx::create_task(m_response_completed).then([](pplx::task t) + { + try { t.wait(); } catch(...) {} + }); + auto *pServer = static_cast(http_server_api::server_api()); if(--pServer->m_numOutstandingRequests == 0) { @@ -530,6 +536,7 @@ void windows_request_context::async_process_request(HTTP_REQUEST_ID request_id, { CancelThreadpoolIo(pServer->m_threadpool_io); m_msg.reply(status_codes::InternalError); + do_response(true); } } @@ -541,6 +548,7 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD if(error_code != NO_ERROR) { m_msg.reply(status_codes::InternalError); + do_response(true); } else { @@ -574,6 +582,7 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD else { m_msg.reply(status_codes::BadRequest, badRequestMsg); + do_response(true); } } } @@ -614,6 +623,7 @@ void windows_request_context::read_request_body_chunk() else { m_msg._get_impl()->_complete(0, std::make_exception_ptr(http_exception(error_code))); + m_msg._reply_if_not_already(status_codes::InternalError); } } } @@ -639,6 +649,7 @@ void windows_request_context::read_body_io_completion(DWORD error_code, DWORD by { request_body_buf.commit(0); m_msg._get_impl()->_complete(0, std::make_exception_ptr(http_exception(error_code))); + m_msg._reply_if_not_already(status_codes::InternalError); } } @@ -649,46 +660,7 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper // Save http_request copy to dispatch to user's handler in case content_ready() completes before. http_request request = m_msg; - // Wait until the content download finished before replying. - request.content_ready().then([=](pplx::task requestBody) - { - // If an exception occurred while processing the body then there is no reason - // to even try sending the response, just re-surface the same exception. - try - { - requestBody.wait(); - } - catch (...) - { - m_msg = http_request(); - cancel_request(std::current_exception()); - return; - } - - // At this point the user entirely controls the lifetime of the http_request. - m_msg = http_request(); - - request.get_response().then([this](pplx::task responseTask) - { - // Don't let an exception from sending the response bring down the server. - try - { - m_response = responseTask.get(); - } - catch (const pplx::task_canceled &) - { - // This means the user didn't respond to the request, allowing the - // http_request instance to be destroyed. There is nothing to do then - // so don't send a response. - return; - } - catch (...) - { - m_response = http::http_response(status_codes::InternalError); - } - async_process_response(); - }); - }); + do_response(false); // Look up the lock for the http_listener. auto *pServer = static_cast(http_server_api::server_api()); @@ -721,6 +693,69 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper } } +void windows_request_context::do_response(bool bad_request) +{ + // Use a proxy event so we're not causing a circular reference between the http_request and the response task + pplx::task_completion_event proxy_content_ready; + + auto content_ready_task = m_msg.content_ready(); + auto get_response_task = m_msg.get_response(); + + content_ready_task.then([this, proxy_content_ready](pplx::task requestBody) + { + // If an exception occurred while processing the body then there is no reason + // to even try sending the response, just re-surface the same exception. + try + { + requestBody.wait(); + } + catch (...) + { + m_msg = http_request(); + proxy_content_ready.set_exception(std::current_exception()); + cancel_request(std::current_exception()); + return; + } + + // At this point the user entirely controls the lifetime of the http_request. + m_msg = http_request(); + proxy_content_ready.set(); + }); + + get_response_task.then([this, bad_request, proxy_content_ready](pplx::task responseTask) + { + // Don't let an exception from sending the response bring down the server. + try + { + m_response = responseTask.get(); + } + catch (const pplx::task_canceled &) + { + // This means the user didn't respond to the request, allowing the + // http_request instance to be destroyed. There is nothing to do then + // so don't send a response. + return; + } + catch (...) + { + m_response = http::http_response(status_codes::InternalError); + } + + if (bad_request) + { + async_process_response(); + } + else + { + // Wait until the content download finished before replying. + pplx::create_task(proxy_content_ready).then([this](pplx::task requestBody) + { + async_process_response(); + }); + } + }); +} + void windows_request_context::async_process_response() { auto *pServer = static_cast(http_server_api::server_api()); From 94ab4048c44dc9760dd7c4687ccbb2aab6ba771d Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Fri, 13 Nov 2015 12:15:30 +1100 Subject: [PATCH 005/609] Fix a couple of race conditions, and use enum instead of bool --- .../cpprest/details/http_server_httpsys.h | 9 ++++- .../src/http/listener/http_server_httpsys.cpp | 40 +++++++++++-------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Release/include/cpprest/details/http_server_httpsys.h b/Release/include/cpprest/details/http_server_httpsys.h index 261aa7ad44..a97a461a8e 100644 --- a/Release/include/cpprest/details/http_server_httpsys.h +++ b/Release/include/cpprest/details/http_server_httpsys.h @@ -99,8 +99,13 @@ struct windows_request_context : http::details::_http_server_context // Dispatch request to the provided http_listener. void dispatch_request_to_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener); - // Initialise the response task callbacks - void do_response(bool bad_request); + enum ShouldWaitForBody + { + WaitForBody, + DontWaitForBody + }; + // Initialise the response task callbacks. If the body has been requested, we should wait for it to avoid race conditions. + void init_response_callbacks(ShouldWaitForBody shouldWait); // Read in a portion of the request body. void read_request_body_chunk(); diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index f389d5fed7..a366641ae0 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -536,7 +536,7 @@ void windows_request_context::async_process_request(HTTP_REQUEST_ID request_id, { CancelThreadpoolIo(pServer->m_threadpool_io); m_msg.reply(status_codes::InternalError); - do_response(true); + init_response_callbacks(DontWaitForBody); } } @@ -548,7 +548,7 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD if(error_code != NO_ERROR) { m_msg.reply(status_codes::InternalError); - do_response(true); + init_response_callbacks(DontWaitForBody); } else { @@ -582,7 +582,9 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD else { m_msg.reply(status_codes::BadRequest, badRequestMsg); - do_response(true); + + // Even though we have a bad request, we should wait for the body otherwise we risk racing over m_overlapped + init_response_callbacks(WaitForBody); } } } @@ -623,7 +625,6 @@ void windows_request_context::read_request_body_chunk() else { m_msg._get_impl()->_complete(0, std::make_exception_ptr(http_exception(error_code))); - m_msg._reply_if_not_already(status_codes::InternalError); } } } @@ -649,7 +650,6 @@ void windows_request_context::read_body_io_completion(DWORD error_code, DWORD by { request_body_buf.commit(0); m_msg._get_impl()->_complete(0, std::make_exception_ptr(http_exception(error_code))); - m_msg._reply_if_not_already(status_codes::InternalError); } } @@ -660,7 +660,7 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper // Save http_request copy to dispatch to user's handler in case content_ready() completes before. http_request request = m_msg; - do_response(false); + init_response_callbacks(WaitForBody); // Look up the lock for the http_listener. auto *pServer = static_cast(http_server_api::server_api()); @@ -693,7 +693,7 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper } } -void windows_request_context::do_response(bool bad_request) +void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWait) { // Use a proxy event so we're not causing a circular reference between the http_request and the response task pplx::task_completion_event proxy_content_ready; @@ -722,7 +722,7 @@ void windows_request_context::do_response(bool bad_request) proxy_content_ready.set(); }); - get_response_task.then([this, bad_request, proxy_content_ready](pplx::task responseTask) + get_response_task.then([this, proxy_content_ready](pplx::task responseTask) { // Don't let an exception from sending the response bring down the server. try @@ -741,19 +741,25 @@ void windows_request_context::do_response(bool bad_request) m_response = http::http_response(status_codes::InternalError); } - if (bad_request) - { - async_process_response(); - } - else + // Wait until the content download finished before replying because m_overlapped is reused, + // and we don't want to delete 'this' if the body is still downloading + pplx::create_task(proxy_content_ready).then([this](pplx::task t) { - // Wait until the content download finished before replying. - pplx::create_task(proxy_content_ready).then([this](pplx::task requestBody) + try { + t.wait(); async_process_response(); - }); - } + } + catch (...) + { + } + }).wait(); }); + + if (shouldWait == DontWaitForBody) + { + proxy_content_ready.set(); + } } void windows_request_context::async_process_response() From a1c52e57695fd61d189b379d96d5a3c720e3b6de Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Fri, 13 Nov 2015 13:52:09 +1100 Subject: [PATCH 006/609] Avoid another unobserved exception handler situation, and add an assert in an error case that looks problematic --- Release/src/http/listener/http_server_httpsys.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index a366641ae0..acfbb4f6d6 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -734,10 +734,18 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa // This means the user didn't respond to the request, allowing the // http_request instance to be destroyed. There is nothing to do then // so don't send a response. + // Avoid unobserved exception handler + pplx::create_task(proxy_content_ready).then([this](pplx::task t) + { + try { t.wait(); } catch(...) {} + }); return; } catch (...) { + // Should never get here, if we do there's a chance that a circular reference will cause leaks, + // or worse, undefined behaviour as we don't know who owns 'this' anymore + _ASSERTE(false); m_response = http::http_response(status_codes::InternalError); } From 11fa3ee5cb8a7664742af889a53057d5aec7a41d Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Fri, 13 Nov 2015 18:07:21 +1100 Subject: [PATCH 007/609] Move the callback that breaks the http_response circular reference so that it can't fire before the response claims ownership of the circular reference --- .../src/http/listener/http_server_httpsys.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index acfbb4f6d6..915a5ea0cc 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -465,13 +465,7 @@ void http_windows_server::receive_requests() pplx::task http_windows_server::respond(http::http_response response) { windows_request_context * p_context = static_cast(response._get_server_context()); - return pplx::create_task(p_context->m_response_completed).then([p_context](::pplx::task t) - { - // After response is sent, break circular reference between http_response and the request context. - // Otherwise http_listener::close() can hang. - p_context->m_response._get_impl()->_set_server_context(nullptr); - t.get(); - }); + return pplx::create_task(p_context->m_response_completed); } windows_request_context::windows_request_context() @@ -711,6 +705,8 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa } catch (...) { + // Copy the request reference in case it's the last + http_request request = m_msg; m_msg = http_request(); proxy_content_ready.set_exception(std::current_exception()); cancel_request(std::current_exception()); @@ -749,6 +745,13 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa m_response = http::http_response(status_codes::InternalError); } + pplx::create_task(m_response_completed).then([this](::pplx::task t) + { + // After response is sent, break circular reference between http_response and the request context. + // Otherwise http_listener::close() can hang. + m_response._get_impl()->_set_server_context(nullptr); + }); + // Wait until the content download finished before replying because m_overlapped is reused, // and we don't want to delete 'this' if the body is still downloading pplx::create_task(proxy_content_ready).then([this](pplx::task t) From 0685728fd5934b86d259df21af16c341b9a71424 Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Fri, 13 Nov 2015 18:47:38 +1100 Subject: [PATCH 008/609] Work around leak of http_request when _complete is never called --- Release/src/http/listener/http_server_httpsys.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 915a5ea0cc..37762d58a3 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -769,7 +769,8 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa if (shouldWait == DontWaitForBody) { - proxy_content_ready.set(); + // Fake a body completion so the content_ready() task doesn't keep the http_request alive forever + m_msg._get_impl()->_complete(0); } } From 90ebeb43f0dd1ceaa233fdbc375bb4b143737cba Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Fri, 13 Nov 2015 18:52:15 +1100 Subject: [PATCH 009/609] Fix accidental tab --- Release/src/http/listener/http_server_httpsys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 37762d58a3..e0ceaa840f 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -706,7 +706,7 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa catch (...) { // Copy the request reference in case it's the last - http_request request = m_msg; + http_request request = m_msg; m_msg = http_request(); proxy_content_ready.set_exception(std::current_exception()); cancel_request(std::current_exception()); From 3cb4da799a068daf1c9d436027fe49be3a958dd1 Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Thu, 19 Nov 2015 10:28:58 +1100 Subject: [PATCH 010/609] Fix another accidental tab indent --- Release/src/http/listener/http_server_httpsys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index e0ceaa840f..be5f50b0e3 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -690,7 +690,7 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWait) { // Use a proxy event so we're not causing a circular reference between the http_request and the response task - pplx::task_completion_event proxy_content_ready; + pplx::task_completion_event proxy_content_ready; auto content_ready_task = m_msg.content_ready(); auto get_response_task = m_msg.get_response(); From 6c82566f047bbf37ec91354e46ed07c66922dff5 Mon Sep 17 00:00:00 2001 From: Tim Boundy Date: Wed, 25 Nov 2015 22:09:31 +1100 Subject: [PATCH 011/609] Update CONTRIBUTORS.txt --- CONTRIBUTORS.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index c1aa02bd51..a368135804 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -34,3 +34,6 @@ Cisco Systems Gergely Lukacsy (glukacsy) thomasschaub + +Trimble +Tim Boundy (gigaplex) \ No newline at end of file From 6a3617ab1901fdd5a18161f77497e3443b11334d Mon Sep 17 00:00:00 2001 From: Rino Seminara Date: Thu, 26 Nov 2015 09:57:41 +0100 Subject: [PATCH 012/609] Added "-Wno-error" and "-Wno-unused-local-typedefs" to the clang suppression list. It solves build problems on iOS. --- Release/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index dd2272f420..99f706f460 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -134,7 +134,7 @@ elseif((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR IOS) message("-- Setting clang options") set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") - set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder") + set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-error -Wno-unused-local-typedefs") set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") From cabb753f9102c74e98b0841440320641d636d910 Mon Sep 17 00:00:00 2001 From: Simon Ferquel Date: Fri, 27 Nov 2015 14:53:18 +0100 Subject: [PATCH 013/609] Static lib for uwp --- .../cpprestsdk140.uwp.staticlib.vcxproj | 110 ++++++++++++++++++ cpprestsdk140.sln | 31 ++++- 2 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj diff --git a/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj b/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj new file mode 100644 index 0000000000..475ec343f2 --- /dev/null +++ b/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj @@ -0,0 +1,110 @@ + + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {47A5CFDC-C244-45A6-9830-38CB303CB495} + StaticLibrary + en-US + 14.0 + true + Windows Store + 8.2 + cpprestsdk140.uwp.staticlib + v140 + StaticLibrary + $(OutDir)\$(MsBuildProjectName) + 10.0.10240.0 + 10.0.10240.0 + + + + + + + + + + + + + + + + d + + + $(CppRestBaseFileName)140$(DebugFileSuffix)_uwp_$(CppRestSDKVersionFileSuffix) + + + + + false + false + + + + _NO_ASYNCRTIMP;_NO_PPLXIMP;_USRDLL;%(PreprocessorDefinitions); + Use + true + $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) + Use + stdafx.h + -Zm250 /bigobj %(AdditionalOptions) + true + + + Console + false + UseLinkTimeCodeGeneration + false + + + + + + copy /Y $(OutDir)\* $(OutDir)..\ + exit 0 + Copying $(TargetName).winrt binaries to OutDir and removing appcontainer flag + + + MachineX86 + + + MachineX86 + + + MachineX64 + + + MachineX64 + + + + + \ No newline at end of file diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln index 9e5c64dd78..472cbc5730 100644 --- a/cpprestsdk140.sln +++ b/cpprestsdk140.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22815.1 +VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14\casablanca140.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" EndProject @@ -47,18 +47,22 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.wod", "Releas EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.vcxproj", "{36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp.staticlib", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.staticlib.vcxproj", "{47A5CFDC-C244-45A6-9830-38CB303CB495}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - Release\src\build\common.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 + Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 @@ -204,6 +208,22 @@ Global {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.Build.0 = Release|x64 {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.ActiveCfg = Release|Win32 {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.Build.0 = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|ARM.ActiveCfg = Debug|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|ARM.Build.0 = Debug|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|Win32.ActiveCfg = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|Win32.Build.0 = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x64.ActiveCfg = Debug|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x64.Build.0 = Debug|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x86.ActiveCfg = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x86.Build.0 = Debug|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|ARM.ActiveCfg = Release|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|ARM.Build.0 = Release|ARM + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|Win32.ActiveCfg = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|Win32.Build.0 = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x64.ActiveCfg = Release|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x64.Build.0 = Release|x64 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.ActiveCfg = Release|Win32 + {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -229,5 +249,6 @@ Global {AFB49019-965B-4C10-BAFF-C86C16D58010} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {3A584D9C-1A98-4046-B7D3-B7171EF42D34} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {47A5CFDC-C244-45A6-9830-38CB303CB495} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} EndGlobalSection EndGlobal From 32d4a4c8270372291cd8ac9b1fd79413957db268 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Wed, 2 Dec 2015 12:54:57 -0800 Subject: [PATCH 014/609] Do not expose set_pong_message on WinRT --- Release/include/cpprest/ws_msg.h | 22 +++++++++++-------- .../websockets/client/send_msg_tests.cpp | 19 ++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Release/include/cpprest/ws_msg.h b/Release/include/cpprest/ws_msg.h index 171234edf0..b22ecad058 100644 --- a/Release/include/cpprest/ws_msg.h +++ b/Release/include/cpprest/ws_msg.h @@ -73,14 +73,16 @@ class websocket_outgoing_message { public: - /// - /// Sets a the outgoing message to be an unsolicited pong message. - /// This is useful when the client side wants to check whether the server is alive. - /// - void set_pong_message() - { - this->set_message_pong(); - } +#if !defined(__cplusplus_winrt) + /// + /// Sets a the outgoing message to be an unsolicited pong message. + /// This is useful when the client side wants to check whether the server is alive. + /// + void set_pong_message() + { + this->set_message_pong(); + } +#endif /// /// Sets a UTF-8 message as the message body. @@ -161,13 +163,15 @@ class websocket_outgoing_message const pplx::task_completion_event & body_sent() const { return m_body_sent; } +#if !defined(__cplusplus_winrt) void set_message_pong() { - concurrency::streams::container_buffer buffer(""); + concurrency::streams::container_buffer buffer(""); m_msg_type = websocket_message_type::pong; m_length = static_cast(buffer.size()); m_body = buffer; } +#endif void set_message(const concurrency::streams::container_buffer &buffer) { diff --git a/Release/tests/functional/websockets/client/send_msg_tests.cpp b/Release/tests/functional/websockets/client/send_msg_tests.cpp index 1303207a0e..263dc1eb0b 100644 --- a/Release/tests/functional/websockets/client/send_msg_tests.cpp +++ b/Release/tests/functional/websockets/client/send_msg_tests.cpp @@ -471,24 +471,25 @@ TEST_FIXTURE(uri_address, send_stream_binary_msg_no_length) client.close().wait(); } +#if !defined(__cplusplus_winrt) // Send an unsolicited pong message to the server TEST_FIXTURE(uri_address, send_pong_msg) { - test_websocket_server server; - websocket_client client; - send_pong_msg_helper(client, m_uri, server).wait(); - client.close().wait(); + test_websocket_server server; + websocket_client client; + send_pong_msg_helper(client, m_uri, server).wait(); + client.close().wait(); } // Send an unsolicited pong message to the server with websocket_callback_client TEST_FIXTURE(uri_address, send_pong_msg_callback_client) { - test_websocket_server server; - websocket_callback_client client; - send_pong_msg_helper(client, m_uri, server).wait(); - client.close().wait(); + test_websocket_server server; + websocket_callback_client client; + send_pong_msg_helper(client, m_uri, server).wait(); + client.close().wait(); } - +#endif } // SUITE(send_msg_tests) From 725c941d7af5564ded24fde12ffc63f288631d8a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 2 Dec 2015 17:55:53 -0800 Subject: [PATCH 015/609] Enum classes are preferred to avoid implicit conversions --- Release/include/cpprest/details/http_server_httpsys.h | 6 +++--- Release/src/http/listener/http_server_httpsys.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Release/include/cpprest/details/http_server_httpsys.h b/Release/include/cpprest/details/http_server_httpsys.h index a97a461a8e..6ae9cc1e85 100644 --- a/Release/include/cpprest/details/http_server_httpsys.h +++ b/Release/include/cpprest/details/http_server_httpsys.h @@ -99,10 +99,10 @@ struct windows_request_context : http::details::_http_server_context // Dispatch request to the provided http_listener. void dispatch_request_to_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener); - enum ShouldWaitForBody + enum class ShouldWaitForBody { - WaitForBody, - DontWaitForBody + Wait, + DontWait }; // Initialise the response task callbacks. If the body has been requested, we should wait for it to avoid race conditions. void init_response_callbacks(ShouldWaitForBody shouldWait); diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index be5f50b0e3..73b7f7ba6a 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -530,7 +530,7 @@ void windows_request_context::async_process_request(HTTP_REQUEST_ID request_id, { CancelThreadpoolIo(pServer->m_threadpool_io); m_msg.reply(status_codes::InternalError); - init_response_callbacks(DontWaitForBody); + init_response_callbacks(ShouldWaitForBody::DontWait); } } @@ -542,7 +542,7 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD if(error_code != NO_ERROR) { m_msg.reply(status_codes::InternalError); - init_response_callbacks(DontWaitForBody); + init_response_callbacks(ShouldWaitForBody::DontWait); } else { @@ -578,7 +578,7 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD m_msg.reply(status_codes::BadRequest, badRequestMsg); // Even though we have a bad request, we should wait for the body otherwise we risk racing over m_overlapped - init_response_callbacks(WaitForBody); + init_response_callbacks(ShouldWaitForBody::Wait); } } } @@ -654,7 +654,7 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper // Save http_request copy to dispatch to user's handler in case content_ready() completes before. http_request request = m_msg; - init_response_callbacks(WaitForBody); + init_response_callbacks(ShouldWaitForBody::Wait); // Look up the lock for the http_listener. auto *pServer = static_cast(http_server_api::server_api()); @@ -767,7 +767,7 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa }).wait(); }); - if (shouldWait == DontWaitForBody) + if (shouldWait == ShouldWaitForBody::DontWait) { // Fake a body completion so the content_ready() task doesn't keep the http_request alive forever m_msg._get_impl()->_complete(0); From c966484b7e2683b3756153bfdc62679980376b06 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 2 Dec 2015 17:57:59 -0800 Subject: [PATCH 016/609] Minor cleanup --- Release/src/http/listener/http_server_httpsys.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 73b7f7ba6a..72f7b1c069 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -708,8 +708,9 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa // Copy the request reference in case it's the last http_request request = m_msg; m_msg = http_request(); - proxy_content_ready.set_exception(std::current_exception()); - cancel_request(std::current_exception()); + auto exc = std::current_exception(); + proxy_content_ready.set_exception(exc); + cancel_request(exc); return; } @@ -731,9 +732,9 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa // http_request instance to be destroyed. There is nothing to do then // so don't send a response. // Avoid unobserved exception handler - pplx::create_task(proxy_content_ready).then([this](pplx::task t) + pplx::create_task(proxy_content_ready).then([](pplx::task t) { - try { t.wait(); } catch(...) {} + try { t.wait(); } catch (...) {} }); return; } @@ -745,7 +746,7 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa m_response = http::http_response(status_codes::InternalError); } - pplx::create_task(m_response_completed).then([this](::pplx::task t) + pplx::create_task(m_response_completed).then([this](pplx::task t) { // After response is sent, break circular reference between http_response and the request context. // Otherwise http_listener::close() can hang. From abfe6a35d000ed993e67ad0c4c3f5bb3148a0f75 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Thu, 3 Dec 2015 10:02:59 -0800 Subject: [PATCH 017/609] --Wno-error is not required, remove it. --- Release/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 99f706f460..bd64c460c5 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -134,7 +134,7 @@ elseif((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR IOS) message("-- Setting clang options") set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") - set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-error -Wno-unused-local-typedefs") + set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs") set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") From dad24c1def16df6cb2a01e80150529dd21365004 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Mon, 7 Dec 2015 11:28:14 -0800 Subject: [PATCH 018/609] Change the cpprest140_uwp static lib name to libcpprest140..lib --- Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj b/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj index 475ec343f2..2918824b65 100644 --- a/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj +++ b/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj @@ -59,7 +59,7 @@ d - $(CppRestBaseFileName)140$(DebugFileSuffix)_uwp_$(CppRestSDKVersionFileSuffix) + lib$(CppRestBaseFileName)140$(DebugFileSuffix)_uwp_$(CppRestSDKVersionFileSuffix) From 61d14bf7c5b84364d98e427262b75e3a51de0bb0 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 9 Dec 2015 09:41:23 -0800 Subject: [PATCH 019/609] Remove use of boost in tests if on windows and excluding websockets --- Release/tests/functional/streams/stdstream_tests.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Release/tests/functional/streams/stdstream_tests.cpp b/Release/tests/functional/streams/stdstream_tests.cpp index 8904f3ee08..a100492fd0 100644 --- a/Release/tests/functional/streams/stdstream_tests.cpp +++ b/Release/tests/functional/streams/stdstream_tests.cpp @@ -26,7 +26,9 @@ #include "cpprest/filestream.h" #include "cpprest/producerconsumerstream.h" +#if !defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS) #include +#endif #if defined(__cplusplus_winrt) using namespace Windows::Storage; @@ -787,6 +789,7 @@ TEST(sync_on_async_close_with_exception) } } +#if !defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS) TEST(ostream_full_throw_exception) { char tgt_buffer[5]; @@ -806,6 +809,7 @@ TEST(ostream_full_throw_exception) VERIFY_THROWS(astream.read_to_end(os_streambuf).get(), std::exception); } +#endif } }}} From fa9f01538e98ab611f12192fac7fb013a35eef53 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 9 Dec 2015 09:41:39 -0800 Subject: [PATCH 020/609] Do not build websocket tests if excluding websockets --- .../websockets/client/CMakeLists.txt | 26 +++++++------- .../websockets/utilities/CMakeLists.txt | 34 +++++++++++-------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/Release/tests/functional/websockets/client/CMakeLists.txt b/Release/tests/functional/websockets/client/CMakeLists.txt index 53df487947..e4bd7a3625 100644 --- a/Release/tests/functional/websockets/client/CMakeLists.txt +++ b/Release/tests/functional/websockets/client/CMakeLists.txt @@ -1,13 +1,15 @@ -include_directories(../utilities) +if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + include_directories(../utilities) + + set(SOURCES + authentication_tests.cpp + client_construction.cpp + close_tests.cpp + error_tests.cpp + receive_msg_tests.cpp + send_msg_tests.cpp + ) -set(SOURCES - authentication_tests.cpp - client_construction.cpp - close_tests.cpp - error_tests.cpp - receive_msg_tests.cpp - send_msg_tests.cpp -) - -add_casablanca_test(${LIB}websocketclient_test SOURCES) -target_link_libraries(${LIB}websocketclient_test ${LIB}websockettest_utilities) \ No newline at end of file + add_casablanca_test(${LIB}websocketclient_test SOURCES) + target_link_libraries(${LIB}websocketclient_test ${LIB}websockettest_utilities) +endif() \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/CMakeLists.txt b/Release/tests/functional/websockets/utilities/CMakeLists.txt index 31f51c37b9..e1c5b1edba 100644 --- a/Release/tests/functional/websockets/utilities/CMakeLists.txt +++ b/Release/tests/functional/websockets/utilities/CMakeLists.txt @@ -1,17 +1,21 @@ -include_directories(include) +if (NOT CPPREST_EXCLUDE_WEBSOCKETS) -if(WIN32) - add_definitions(-DWEBSOCKETTESTUTILITY_EXPORTS) -endif() + include_directories(include) + + if(WIN32) + add_definitions(-DWEBSOCKETTESTUTILITY_EXPORTS) + endif() + + set(SOURCES + test_websocket_server.cpp + ) + + add_library(${LIB}websockettest_utilities ${SOURCES}) + target_link_libraries(${LIB}websockettest_utilities + ${LIB}unittestpp + ${LIB}common_utilities + ${BOOST_LIBRARIES} + ${Casablanca_LIBRARIES} + ) -set(SOURCES - test_websocket_server.cpp -) - -add_library(${LIB}websockettest_utilities ${SOURCES}) -target_link_libraries(${LIB}websockettest_utilities - ${LIB}unittestpp - ${LIB}common_utilities - ${BOOST_LIBRARIES} - ${Casablanca_LIBRARIES} -) +endif() \ No newline at end of file From 47e2bf030f1c2f9cca7273e5d539c7db4440e8a8 Mon Sep 17 00:00:00 2001 From: hs3180 Date: Sat, 19 Dec 2015 10:58:32 +0800 Subject: [PATCH 021/609] Fix #34, Ignore warning C4592 --- Release/src/build/vs14/casablanca140.vcxproj | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Release/src/build/vs14/casablanca140.vcxproj b/Release/src/build/vs14/casablanca140.vcxproj index c5a3c41aff..cca6328ef9 100644 --- a/Release/src/build/vs14/casablanca140.vcxproj +++ b/Release/src/build/vs14/casablanca140.vcxproj @@ -52,12 +52,13 @@ MultiThreadedDLL true - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) + + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) From a7e22d61641b81f6f71a490399c151f5e9ca8fc8 Mon Sep 17 00:00:00 2001 From: George Malayil Date: Mon, 21 Dec 2015 15:29:01 +0530 Subject: [PATCH 022/609] Adding include to cpprest/details/web_utilities.h to bring in web_proxy definition. --- Release/include/cpprest/oauth2.h | 1164 +++++++++++++++++------------- 1 file changed, 663 insertions(+), 501 deletions(-) diff --git a/Release/include/cpprest/oauth2.h b/Release/include/cpprest/oauth2.h index 202d1520e9..f146990e9b 100644 --- a/Release/include/cpprest/oauth2.h +++ b/Release/include/cpprest/oauth2.h @@ -18,7 +18,8 @@ * * HTTP Library: Oauth 2.0 * -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk +* For the latest on this and related APIs, please see: +*https://github.com/Microsoft/cpprestsdk * * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ @@ -28,516 +29,677 @@ #define _CASA_OAUTH2_H #include "cpprest/http_msg.h" +#include "cpprest/details/web_utilities.h" -namespace web -{ -namespace http -{ -namespace client -{ - // Forward declaration to avoid circular include dependency. - class http_client_config; -} +namespace web { +namespace http { + namespace client { + // Forward declaration to avoid circular include dependency. + class http_client_config; + } -/// oAuth 2.0 library. -namespace oauth2 -{ -namespace details -{ + /// oAuth 2.0 library. + namespace oauth2 { + namespace details { -class oauth2_handler; + class oauth2_handler; -// Constant strings for OAuth 2.0. -typedef utility::string_t oauth2_string; -class oauth2_strings -{ -public: + // Constant strings for OAuth 2.0. + typedef utility::string_t oauth2_string; + class oauth2_strings { + public: #define _OAUTH2_STRINGS #define DAT(a_, b_) _ASYNCRTIMP static const oauth2_string a_; #include "cpprest/details/http_constants.dat" #undef _OAUTH2_STRINGS #undef DAT -}; - -} // namespace web::http::oauth2::details - -/// oAuth functionality is currently in beta. -namespace experimental -{ - -/// -/// Exception type for OAuth 2.0 errors. -/// -class oauth2_exception : public std::exception -{ -public: - oauth2_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {} - ~oauth2_exception() CPPREST_NOEXCEPT {} - const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); } - -private: - std::string m_msg; -}; - -/// -/// OAuth 2.0 token and associated information. -/// -class oauth2_token -{ -public: - - /// - /// Value for undefined expiration time in expires_in(). - /// - enum { undefined_expiration = -1 }; - - oauth2_token(utility::string_t access_token=utility::string_t()) : - m_access_token(std::move(access_token)), - m_expires_in(undefined_expiration) - {} - - /// - /// Get access token validity state. - /// If true, access token is a valid. - /// - /// Access token validity state. - bool is_valid_access_token() const { return !access_token().empty(); } - - /// - /// Get access token. - /// - /// Access token string. - const utility::string_t& access_token() const { return m_access_token; } - /// - /// Set access token. - /// - /// Access token string to set. - void set_access_token(utility::string_t access_token) { m_access_token = std::move(access_token); } - - /// - /// Get refresh token. - /// - /// Refresh token string. - const utility::string_t& refresh_token() const { return m_refresh_token; } - /// - /// Set refresh token. - /// - /// Refresh token string to set. - void set_refresh_token(utility::string_t refresh_token) { m_refresh_token = std::move(refresh_token); } - - /// - /// Get token type. - /// - /// Token type string. - const utility::string_t& token_type() const { return m_token_type; } - /// - /// Set token type. - /// - /// Token type string to set. - void set_token_type(utility::string_t token_type) { m_token_type = std::move(token_type); } - - /// - /// Get token scope. - /// - /// Token scope string. - const utility::string_t& scope() const { return m_scope; } - /// - /// Set token scope. - /// - /// Token scope string to set. - void set_scope(utility::string_t scope) { m_scope = std::move(scope); } - - /// - /// Get the lifetime of the access token in seconds. - /// For example, 3600 means the access token will expire in one hour from - /// the time when access token response was generated by the authorization server. - /// Value of undefined_expiration means expiration time is either - /// unset or that it was not returned by the server with the access token. - /// - /// Lifetime of the access token in seconds or undefined_expiration if not set. - int64_t expires_in() const { return m_expires_in; } - /// - /// Set lifetime of access token (in seconds). - /// - /// Lifetime of access token in seconds. - void set_expires_in(int64_t expires_in) { m_expires_in = expires_in; } - -private: - utility::string_t m_access_token; - utility::string_t m_refresh_token; - utility::string_t m_token_type; - utility::string_t m_scope; - int64_t m_expires_in; -}; - -/// -/// OAuth 2.0 configuration. -/// -/// Encapsulates functionality for: -/// - Authenticating requests with an access token. -/// - Performing the OAuth 2.0 authorization code grant authorization flow. -/// See: http://tools.ietf.org/html/rfc6749#section-4.1 -/// - Performing the OAuth 2.0 implicit grant authorization flow. -/// See: http://tools.ietf.org/html/rfc6749#section-4.2 -/// -/// Performing OAuth 2.0 authorization: -/// 1. Set service and client/app parameters: -/// - Client/app key & secret (as provided by the service). -/// - The service authorization endpoint and token endpoint. -/// - Your client/app redirect URI. -/// - Use set_state() to assign a unique state string for the authorization -/// session (default: ""). -/// - If needed, use set_bearer_auth() to control bearer token passing in either -/// query or header (default: header). See: http://tools.ietf.org/html/rfc6750#section-2 -/// - If needed, use set_access_token_key() to set "non-standard" access token -/// key (default: "access_token"). -/// - If needed, use set_implicit_grant() to enable implicit grant flow. -/// 2. Build authorization URI with build_authorization_uri() and open this in web browser/control. -/// 3. The resource owner should then clicks "Yes" to authorize your client/app, and -/// as a result the web browser/control is redirected to redirect_uri(). -/// 5. Capture the redirected URI either in web control or by HTTP listener. -/// 6. Pass the redirected URI to token_from_redirected_uri() to obtain access token. -/// - The method ensures redirected URI contains same state() as set in step 1. -/// - In implicit_grant() is false, this will create HTTP request to fetch access token -/// from the service. Otherwise access token is already included in the redirected URI. -/// -/// Usage for issuing authenticated requests: -/// 1. Perform authorization as above to obtain the access token or use an existing token. -/// - Some services provide option to generate access tokens for testing purposes. -/// 2. Pass the resulting oauth2_config with the access token to http_client_config::set_oauth2(). -/// 3. Construct http_client with this http_client_config. As a result, all HTTP requests -/// by that client will be OAuth 2.0 authenticated. -/// -/// -class oauth2_config -{ -public: - - oauth2_config(utility::string_t client_key, utility::string_t client_secret, - utility::string_t auth_endpoint, utility::string_t token_endpoint, - utility::string_t redirect_uri, utility::string_t scope=utility::string_t()) : - m_client_key(std::move(client_key)), - m_client_secret(std::move(client_secret)), - m_auth_endpoint(std::move(auth_endpoint)), - m_token_endpoint(std::move(token_endpoint)), - m_redirect_uri(std::move(redirect_uri)), - m_scope(std::move(scope)), - m_implicit_grant(false), - m_bearer_auth(true), - m_http_basic_auth(true), - m_access_token_key(details::oauth2_strings::access_token) - {} - - /// - /// Builds an authorization URI to be loaded in the web browser/view. - /// The URI is built with auth_endpoint() as basis. - /// The implicit_grant() affects the built URI by selecting - /// either authorization code or implicit grant flow. - /// You can set generate_state to generate a new random state string. - /// - /// If true, a new random state() string is generated - /// which replaces the current state(). If false, state() is unchanged and used as-is. - /// Authorization URI string. - _ASYNCRTIMP utility::string_t build_authorization_uri(bool generate_state); - - /// - /// Fetch an access token (and possibly a refresh token) based on redirected URI. - /// Behavior depends on the implicit_grant() setting. - /// If implicit_grant() is false, the URI is parsed for 'code' - /// parameter, and then token_from_code() is called with this code. - /// See: http://tools.ietf.org/html/rfc6749#section-4.1 - /// Otherwise, redirect URI fragment part is parsed for 'access_token' - /// parameter, which directly contains the token(s). - /// See: http://tools.ietf.org/html/rfc6749#section-4.2 - /// In both cases, the 'state' parameter is parsed and is verified to match state(). - /// - /// The URI where web browser/view was redirected after resource owner's authorization. - /// Task that fetches the token(s) based on redirected URI. - _ASYNCRTIMP pplx::task token_from_redirected_uri(const web::http::uri& redirected_uri); - - /// - /// Fetches an access token (and possibly a refresh token) from the token endpoint. - /// The task creates an HTTP request to the token_endpoint() which exchanges - /// the authorization code for the token(s). - /// This also sets the refresh token if one was returned. - /// See: http://tools.ietf.org/html/rfc6749#section-4.1.3 - /// - /// Code received via redirect upon successful authorization. - /// Task that fetches token(s) based on the authorization code. - pplx::task token_from_code(utility::string_t authorization_code) - { - uri_builder ub; - ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::authorization_code, false); - ub.append_query(details::oauth2_strings::code, uri::encode_data_string(std::move(authorization_code)), false); - ub.append_query(details::oauth2_strings::redirect_uri, uri::encode_data_string(redirect_uri()), false); - return _request_token(ub); - } - - /// - /// Fetches a new access token (and possibly a new refresh token) using the refresh token. - /// The task creates a HTTP request to the token_endpoint(). - /// If successful, resulting access token is set as active via set_token(). - /// See: http://tools.ietf.org/html/rfc6749#section-6 - /// This also sets a new refresh token if one was returned. - /// - /// Task that fetches the token(s) using the refresh token. - pplx::task token_from_refresh() - { - uri_builder ub; - ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::refresh_token, false); - ub.append_query(details::oauth2_strings::refresh_token, uri::encode_data_string(token().refresh_token()), false); - return _request_token(ub); - } - - /// - /// Returns enabled state of the configuration. - /// The oauth2_handler will perform OAuth 2.0 authentication only if - /// this method returns true. - /// Return value is true if access token is valid (=fetched or manually set). - /// - /// The configuration enabled state. - bool is_enabled() const { return token().is_valid_access_token(); } - - /// - /// Get client key. - /// - /// Client key string. - const utility::string_t& client_key() const { return m_client_key; } - /// - /// Set client key. - /// - /// Client key string to set. - void set_client_key(utility::string_t client_key) { m_client_key = std::move(client_key); } - - /// - /// Get client secret. - /// - /// Client secret string. - const utility::string_t& client_secret() const { return m_client_secret; } - /// - /// Set client secret. - /// - /// Client secret string to set. - void set_client_secret(utility::string_t client_secret) { m_client_secret = std::move(client_secret); } - - /// - /// Get authorization endpoint URI string. - /// - /// Authorization endpoint URI string. - const utility::string_t& auth_endpoint() const { return m_auth_endpoint; } - /// - /// Set authorization endpoint URI string. - /// - /// Authorization endpoint URI string to set. - void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); } - - /// - /// Get token endpoint URI string. - /// - /// Token endpoint URI string. - const utility::string_t& token_endpoint() const { return m_token_endpoint; } - /// - /// Set token endpoint URI string. - /// - /// Token endpoint URI string to set. - void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); } - - /// - /// Get redirect URI string. - /// - /// Redirect URI string. - const utility::string_t& redirect_uri() const { return m_redirect_uri; } - /// - /// Set redirect URI string. - /// - /// Redirect URI string to set. - void set_redirect_uri(utility::string_t redirect_uri) { m_redirect_uri = std::move(redirect_uri); } - - /// - /// Get scope used in authorization for token. - /// - /// Scope string used in authorization. - const utility::string_t& scope() const { return m_scope; } - /// - /// Set scope for authorization for token. - /// - /// Scope string for authorization for token. - void set_scope(utility::string_t scope) { m_scope = std::move(scope); } - - /// - /// Get client state string used in authorization. - /// - /// Client state string used in authorization. - const utility::string_t& state() { return m_state; } - /// - /// Set client state string for authorization for token. - /// The state string is used in authorization for security reasons - /// (to uniquely identify authorization sessions). - /// If desired, suitably secure state string can be automatically generated - /// by build_authorization_uri(). - /// A good state string consist of 30 or more random alphanumeric characters. - /// - /// Client authorization state string to set. - void set_state(utility::string_t state) { m_state = std::move(state); } - - /// - /// Get token. - /// - /// Token. - const oauth2_token& token() const { return m_token; } - /// - /// Set token. - /// - /// Token to set. - void set_token(oauth2_token token) { m_token = std::move(token); } - - /// - /// Get implicit grant setting for authorization. - /// - /// Implicit grant setting for authorization. - bool implicit_grant() const { return m_implicit_grant; } - /// - /// Set implicit grant setting for authorization. - /// False means authorization code grant is used for authorization. - /// True means implicit grant is used. - /// Default: False. - /// - /// The implicit grant setting to set. - void set_implicit_grant(bool implicit_grant) { m_implicit_grant = implicit_grant; } - - /// - /// Get bearer token authentication setting. - /// - /// Bearer token authentication setting. - bool bearer_auth() const { return m_bearer_auth; } - /// - /// Set bearer token authentication setting. - /// This must be selected based on what the service accepts. - /// True means access token is passed in the request header. (http://tools.ietf.org/html/rfc6750#section-2.1) - /// False means access token in passed in the query parameters. (http://tools.ietf.org/html/rfc6750#section-2.3) - /// Default: True. - /// - /// The bearer token authentication setting to set. - void set_bearer_auth(bool bearer_auth) { m_bearer_auth = bearer_auth; } - - /// - /// Get HTTP Basic authentication setting for token endpoint. - /// - /// HTTP Basic authentication setting for token endpoint. - bool http_basic_auth() const { return m_http_basic_auth; } - /// - /// Set HTTP Basic authentication setting for token endpoint. - /// This setting must be selected based on what the service accepts. - /// True means HTTP Basic authentication is used for the token endpoint. - /// False means client key & secret are passed in the HTTP request body. - /// Default: True. - /// - /// The HTTP Basic authentication setting to set. - void set_http_basic_auth(bool http_basic_auth) { m_http_basic_auth = http_basic_auth; } - - /// - /// Get access token key. - /// - /// Access token key string. - const utility::string_t& access_token_key() const { return m_access_token_key; } - /// - /// Set access token key. - /// If the service requires a "non-standard" key you must set it here. - /// Default: "access_token". - /// - void set_access_token_key(utility::string_t access_token_key) { m_access_token_key = std::move(access_token_key); } - - /// - /// Get the web proxy object - /// - /// A reference to the web proxy object. - const web_proxy& proxy() const - { - return m_proxy; - } - - /// - /// Set the web proxy object that will be used by token_from_code and token_from_refresh - /// - /// A reference to the web proxy object. - void set_proxy(const web_proxy& proxy) - { - m_proxy = proxy; - } - -private: - friend class web::http::client::http_client_config; - friend class web::http::oauth2::details::oauth2_handler; - - oauth2_config() : - m_implicit_grant(false), - m_bearer_auth(true), - m_http_basic_auth(true) - {} - - _ASYNCRTIMP pplx::task _request_token(uri_builder& request_body); - - oauth2_token _parse_token_from_json(const json::value& token_json); - - void _authenticate_request(http_request &req) const - { - if (bearer_auth()) - { - req.headers().add(header_names::authorization, _XPLATSTR("Bearer ") + token().access_token()); - } - else - { - uri_builder ub(req.request_uri()); - ub.append_query(access_token_key(), token().access_token()); - req.set_request_uri(ub.to_uri()); - } - } - - utility::string_t m_client_key; - utility::string_t m_client_secret; - utility::string_t m_auth_endpoint; - utility::string_t m_token_endpoint; - utility::string_t m_redirect_uri; - utility::string_t m_scope; - utility::string_t m_state; - - web::web_proxy m_proxy; - - bool m_implicit_grant; - bool m_bearer_auth; - bool m_http_basic_auth; - utility::string_t m_access_token_key; - - oauth2_token m_token; - - utility::nonce_generator m_state_generator; -}; - -} // namespace web::http::oauth2::experimental - -namespace details -{ - -class oauth2_handler : public http_pipeline_stage -{ -public: - oauth2_handler(std::shared_ptr cfg) : - m_config(std::move(cfg)) - {} - - virtual pplx::task propagate(http_request request) override - { - if (m_config) - { - m_config->_authenticate_request(request); + }; + + } // namespace web::http::oauth2::details + + /// oAuth functionality is currently in beta. + namespace experimental { + + /// + /// Exception type for OAuth 2.0 errors. + /// + class oauth2_exception : public std::exception { + public: + oauth2_exception(utility::string_t msg) + : m_msg(utility::conversions::to_utf8string(std::move(msg))) + { + } + ~oauth2_exception() CPPREST_NOEXCEPT {} + const char* what() const CPPREST_NOEXCEPT + { + return m_msg.c_str(); + } + + private: + std::string m_msg; + }; + + /// + /// OAuth 2.0 token and associated information. + /// + class oauth2_token { + public: + /// + /// Value for undefined expiration time in expires_in(). + /// + enum { undefined_expiration = -1 }; + + oauth2_token( + utility::string_t access_token = utility::string_t()) + : m_access_token(std::move(access_token)) + , m_expires_in(undefined_expiration) + { + } + + /// + /// Get access token validity state. + /// If true, access token is a valid. + /// + /// Access token validity state. + bool is_valid_access_token() const + { + return !access_token().empty(); + } + + /// + /// Get access token. + /// + /// Access token string. + const utility::string_t& access_token() const + { + return m_access_token; + } + /// + /// Set access token. + /// + /// Access token string to + /// set. + void set_access_token(utility::string_t access_token) + { + m_access_token = std::move(access_token); + } + + /// + /// Get refresh token. + /// + /// Refresh token string. + const utility::string_t& refresh_token() const + { + return m_refresh_token; + } + /// + /// Set refresh token. + /// + /// Refresh token string to + /// set. + void set_refresh_token(utility::string_t refresh_token) + { + m_refresh_token = std::move(refresh_token); + } + + /// + /// Get token type. + /// + /// Token type string. + const utility::string_t& token_type() const + { + return m_token_type; + } + /// + /// Set token type. + /// + /// Token type string to set. + void set_token_type(utility::string_t token_type) + { + m_token_type = std::move(token_type); + } + + /// + /// Get token scope. + /// + /// Token scope string. + const utility::string_t& scope() const { return m_scope; } + /// + /// Set token scope. + /// + /// Token scope string to set. + void set_scope(utility::string_t scope) + { + m_scope = std::move(scope); + } + + /// + /// Get the lifetime of the access token in seconds. + /// For example, 3600 means the access token will expire in one + /// hour from + /// the time when access token response was generated by the + /// authorization server. + /// Value of undefined_expiration means expiration time is + /// either + /// unset or that it was not returned by the server with the + /// access token. + /// + /// Lifetime of the access token in seconds or + /// undefined_expiration if not set. + int64_t expires_in() const { return m_expires_in; } + /// + /// Set lifetime of access token (in seconds). + /// + /// Lifetime of access token in + /// seconds. + void set_expires_in(int64_t expires_in) + { + m_expires_in = expires_in; + } + + private: + utility::string_t m_access_token; + utility::string_t m_refresh_token; + utility::string_t m_token_type; + utility::string_t m_scope; + int64_t m_expires_in; + }; + + /// + /// OAuth 2.0 configuration. + /// + /// Encapsulates functionality for: + /// - Authenticating requests with an access token. + /// - Performing the OAuth 2.0 authorization code grant + /// authorization flow. + /// See: http://tools.ietf.org/html/rfc6749#section-4.1 + /// - Performing the OAuth 2.0 implicit grant authorization flow. + /// See: http://tools.ietf.org/html/rfc6749#section-4.2 + /// + /// Performing OAuth 2.0 authorization: + /// 1. Set service and client/app parameters: + /// - Client/app key & secret (as provided by the service). + /// - The service authorization endpoint and token endpoint. + /// - Your client/app redirect URI. + /// - Use set_state() to assign a unique state string for the + /// authorization + /// session (default: ""). + /// - If needed, use set_bearer_auth() to control bearer token + /// passing in either + /// query or header (default: header). See: + /// http://tools.ietf.org/html/rfc6750#section-2 + /// - If needed, use set_access_token_key() to set "non-standard" + /// access token + /// key (default: "access_token"). + /// - If needed, use set_implicit_grant() to enable implicit grant + /// flow. + /// 2. Build authorization URI with build_authorization_uri() and + /// open this in web browser/control. + /// 3. The resource owner should then clicks "Yes" to authorize your + /// client/app, and + /// as a result the web browser/control is redirected to + /// redirect_uri(). + /// 5. Capture the redirected URI either in web control or by HTTP + /// listener. + /// 6. Pass the redirected URI to token_from_redirected_uri() to + /// obtain access token. + /// - The method ensures redirected URI contains same state() as + /// set in step 1. + /// - In implicit_grant() is false, this will create HTTP request + /// to fetch access token + /// from the service. Otherwise access token is already included + /// in the redirected URI. + /// + /// Usage for issuing authenticated requests: + /// 1. Perform authorization as above to obtain the access token or + /// use an existing token. + /// - Some services provide option to generate access tokens for + /// testing purposes. + /// 2. Pass the resulting oauth2_config with the access token to + /// http_client_config::set_oauth2(). + /// 3. Construct http_client with this http_client_config. As a + /// result, all HTTP requests + /// by that client will be OAuth 2.0 authenticated. + /// + /// + class oauth2_config { + public: + oauth2_config(utility::string_t client_key, + utility::string_t client_secret, + utility::string_t auth_endpoint, + utility::string_t token_endpoint, + utility::string_t redirect_uri, + utility::string_t scope = utility::string_t()) + : m_client_key(std::move(client_key)) + , m_client_secret(std::move(client_secret)) + , m_auth_endpoint(std::move(auth_endpoint)) + , m_token_endpoint(std::move(token_endpoint)) + , m_redirect_uri(std::move(redirect_uri)) + , m_scope(std::move(scope)) + , m_implicit_grant(false) + , m_bearer_auth(true) + , m_http_basic_auth(true) + , m_access_token_key(details::oauth2_strings::access_token) + { + } + + /// + /// Builds an authorization URI to be loaded in the web + /// browser/view. + /// The URI is built with auth_endpoint() as basis. + /// The implicit_grant() affects the built URI by selecting + /// either authorization code or implicit grant flow. + /// You can set generate_state to generate a new random state + /// string. + /// + /// If true, a new random state() + /// string is generated + /// which replaces the current state(). If false, state() is + /// unchanged and used as-is. + /// Authorization URI string. + _ASYNCRTIMP utility::string_t build_authorization_uri( + bool generate_state); + + /// + /// Fetch an access token (and possibly a refresh token) based + /// on redirected URI. + /// Behavior depends on the implicit_grant() setting. + /// If implicit_grant() is false, the URI is parsed for 'code' + /// parameter, and then token_from_code() is called with this + /// code. + /// See: http://tools.ietf.org/html/rfc6749#section-4.1 + /// Otherwise, redirect URI fragment part is parsed for + /// 'access_token' + /// parameter, which directly contains the token(s). + /// See: http://tools.ietf.org/html/rfc6749#section-4.2 + /// In both cases, the 'state' parameter is parsed and is + /// verified to match state(). + /// + /// The URI where web browser/view + /// was redirected after resource owner's authorization. + /// Task that fetches the token(s) based on redirected + /// URI. + _ASYNCRTIMP pplx::task token_from_redirected_uri( + const web::http::uri& redirected_uri); + + /// + /// Fetches an access token (and possibly a refresh token) from + /// the token endpoint. + /// The task creates an HTTP request to the token_endpoint() + /// which exchanges + /// the authorization code for the token(s). + /// This also sets the refresh token if one was returned. + /// See: http://tools.ietf.org/html/rfc6749#section-4.1.3 + /// + /// Code received via redirect + /// upon successful authorization. + /// Task that fetches token(s) based on the + /// authorization code. + pplx::task token_from_code( + utility::string_t authorization_code) + { + uri_builder ub; + ub.append_query(details::oauth2_strings::grant_type, + details::oauth2_strings::authorization_code, false); + ub.append_query(details::oauth2_strings::code, + uri::encode_data_string(std::move(authorization_code)), + false); + ub.append_query(details::oauth2_strings::redirect_uri, + uri::encode_data_string(redirect_uri()), false); + return _request_token(ub); + } + + /// + /// Fetches a new access token (and possibly a new refresh + /// token) using the refresh token. + /// The task creates a HTTP request to the token_endpoint(). + /// If successful, resulting access token is set as active via + /// set_token(). + /// See: http://tools.ietf.org/html/rfc6749#section-6 + /// This also sets a new refresh token if one was returned. + /// + /// Task that fetches the token(s) using the refresh + /// token. + pplx::task token_from_refresh() + { + uri_builder ub; + ub.append_query(details::oauth2_strings::grant_type, + details::oauth2_strings::refresh_token, false); + ub.append_query(details::oauth2_strings::refresh_token, + uri::encode_data_string(token().refresh_token()), + false); + return _request_token(ub); + } + + /// + /// Returns enabled state of the configuration. + /// The oauth2_handler will perform OAuth 2.0 authentication + /// only if + /// this method returns true. + /// Return value is true if access token is valid (=fetched or + /// manually set). + /// + /// The configuration enabled state. + bool is_enabled() const + { + return token().is_valid_access_token(); + } + + /// + /// Get client key. + /// + /// Client key string. + const utility::string_t& client_key() const + { + return m_client_key; + } + /// + /// Set client key. + /// + /// Client key string to set. + void set_client_key(utility::string_t client_key) + { + m_client_key = std::move(client_key); + } + + /// + /// Get client secret. + /// + /// Client secret string. + const utility::string_t& client_secret() const + { + return m_client_secret; + } + /// + /// Set client secret. + /// + /// Client secret string to + /// set. + void set_client_secret(utility::string_t client_secret) + { + m_client_secret = std::move(client_secret); + } + + /// + /// Get authorization endpoint URI string. + /// + /// Authorization endpoint URI string. + const utility::string_t& auth_endpoint() const + { + return m_auth_endpoint; + } + /// + /// Set authorization endpoint URI string. + /// + /// Authorization endpoint URI + /// string to set. + void set_auth_endpoint(utility::string_t auth_endpoint) + { + m_auth_endpoint = std::move(auth_endpoint); + } + + /// + /// Get token endpoint URI string. + /// + /// Token endpoint URI string. + const utility::string_t& token_endpoint() const + { + return m_token_endpoint; + } + /// + /// Set token endpoint URI string. + /// + /// Token endpoint URI string to + /// set. + void set_token_endpoint(utility::string_t token_endpoint) + { + m_token_endpoint = std::move(token_endpoint); + } + + /// + /// Get redirect URI string. + /// + /// Redirect URI string. + const utility::string_t& redirect_uri() const + { + return m_redirect_uri; + } + /// + /// Set redirect URI string. + /// + /// Redirect URI string to + /// set. + void set_redirect_uri(utility::string_t redirect_uri) + { + m_redirect_uri = std::move(redirect_uri); + } + + /// + /// Get scope used in authorization for token. + /// + /// Scope string used in authorization. + const utility::string_t& scope() const { return m_scope; } + /// + /// Set scope for authorization for token. + /// + /// Scope string for authorization for + /// token. + void set_scope(utility::string_t scope) + { + m_scope = std::move(scope); + } + + /// + /// Get client state string used in authorization. + /// + /// Client state string used in + /// authorization. + const utility::string_t& state() { return m_state; } + /// + /// Set client state string for authorization for token. + /// The state string is used in authorization for security + /// reasons + /// (to uniquely identify authorization sessions). + /// If desired, suitably secure state string can be + /// automatically generated + /// by build_authorization_uri(). + /// A good state string consist of 30 or more random + /// alphanumeric characters. + /// + /// Client authorization state string to + /// set. + void set_state(utility::string_t state) + { + m_state = std::move(state); + } + + /// + /// Get token. + /// + /// Token. + const oauth2_token& token() const { return m_token; } + /// + /// Set token. + /// + /// Token to set. + void set_token(oauth2_token token) + { + m_token = std::move(token); + } + + /// + /// Get implicit grant setting for authorization. + /// + /// Implicit grant setting for authorization. + bool implicit_grant() const { return m_implicit_grant; } + /// + /// Set implicit grant setting for authorization. + /// False means authorization code grant is used for + /// authorization. + /// True means implicit grant is used. + /// Default: False. + /// + /// The implicit grant setting to + /// set. + void set_implicit_grant(bool implicit_grant) + { + m_implicit_grant = implicit_grant; + } + + /// + /// Get bearer token authentication setting. + /// + /// Bearer token authentication setting. + bool bearer_auth() const { return m_bearer_auth; } + /// + /// Set bearer token authentication setting. + /// This must be selected based on what the service accepts. + /// True means access token is passed in the request header. + /// (http://tools.ietf.org/html/rfc6750#section-2.1) + /// False means access token in passed in the query parameters. + /// (http://tools.ietf.org/html/rfc6750#section-2.3) + /// Default: True. + /// + /// The bearer token authentication + /// setting to set. + void set_bearer_auth(bool bearer_auth) + { + m_bearer_auth = bearer_auth; + } + + /// + /// Get HTTP Basic authentication setting for token endpoint. + /// + /// HTTP Basic authentication setting for token + /// endpoint. + bool http_basic_auth() const { return m_http_basic_auth; } + /// + /// Set HTTP Basic authentication setting for token endpoint. + /// This setting must be selected based on what the service + /// accepts. + /// True means HTTP Basic authentication is used for the token + /// endpoint. + /// False means client key & secret are passed in the HTTP + /// request body. + /// Default: True. + /// + /// The HTTP Basic authentication + /// setting to set. + void set_http_basic_auth(bool http_basic_auth) + { + m_http_basic_auth = http_basic_auth; + } + + /// + /// Get access token key. + /// + /// Access token key string. + const utility::string_t& access_token_key() const + { + return m_access_token_key; + } + /// + /// Set access token key. + /// If the service requires a "non-standard" key you must set it + /// here. + /// Default: "access_token". + /// + void set_access_token_key(utility::string_t access_token_key) + { + m_access_token_key = std::move(access_token_key); + } + + /// + /// Get the web proxy object + /// + /// A reference to the web proxy object. + const web_proxy& proxy() const { return m_proxy; } + + /// + /// Set the web proxy object that will be used by + /// token_from_code and token_from_refresh + /// + /// A reference to the web proxy + /// object. + void set_proxy(const web_proxy& proxy) { m_proxy = proxy; } + + private: + friend class web::http::client::http_client_config; + friend class web::http::oauth2::details::oauth2_handler; + + oauth2_config() + : m_implicit_grant(false) + , m_bearer_auth(true) + , m_http_basic_auth(true) + { + } + + _ASYNCRTIMP pplx::task _request_token( + uri_builder& request_body); + + oauth2_token _parse_token_from_json( + const json::value& token_json); + + void _authenticate_request(http_request& req) const + { + if (bearer_auth()) { + req.headers().add(header_names::authorization, + _XPLATSTR("Bearer ") + token().access_token()); + } + else { + uri_builder ub(req.request_uri()); + ub.append_query( + access_token_key(), token().access_token()); + req.set_request_uri(ub.to_uri()); + } + } + + utility::string_t m_client_key; + utility::string_t m_client_secret; + utility::string_t m_auth_endpoint; + utility::string_t m_token_endpoint; + utility::string_t m_redirect_uri; + utility::string_t m_scope; + utility::string_t m_state; + + web::web_proxy m_proxy; + + bool m_implicit_grant; + bool m_bearer_auth; + bool m_http_basic_auth; + utility::string_t m_access_token_key; + + oauth2_token m_token; + + utility::nonce_generator m_state_generator; + }; + + } // namespace web::http::oauth2::experimental + + namespace details { + + class oauth2_handler : public http_pipeline_stage { + public: + oauth2_handler(std::shared_ptr cfg) + : m_config(std::move(cfg)) + { + } + + virtual pplx::task propagate( + http_request request) override + { + if (m_config) { + m_config->_authenticate_request(request); + } + return next_stage()->propagate(request); + } + + private: + std::shared_ptr m_config; + }; } - return next_stage()->propagate(request); } - -private: - std::shared_ptr m_config; -}; - -}}}} +} +} #endif From 948ce4f0f85a4e5734e997b22b26454cdfe4d336 Mon Sep 17 00:00:00 2001 From: megaposer Date: Mon, 21 Dec 2015 11:56:37 +0100 Subject: [PATCH 023/609] Add TLS extension SNI for boost asio based http_client - adds the TLS server name indication extension during handshake (ClientHello) - enabled by default as most virtual host environments require it nowadays - note: setting the extension could potentially fail (i.e. if TLS would be disabled on the stream altogether), but other SSL stream options are not "guarded" either --- CONTRIBUTORS.txt | 3 +++ Release/include/cpprest/http_client.h | 21 ++++++++++++++++++++ Release/src/http/client/http_client_asio.cpp | 9 +++++++++ 3 files changed, 33 insertions(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e53f210625..230d1fb14e 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -35,4 +35,7 @@ Gery Vessere (gery@vessere.com) Cisco Systems Gergely Lukacsy (glukacsy) +Ocedo GmbH +Henning Pfeiffer (megaposer) + thomasschaub diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 86e314feca..7823a6b1c1 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -101,6 +101,7 @@ class http_client_config , m_set_user_nativehandle_options([](native_handle)->void{}) #if !defined(_WIN32) && !defined(__cplusplus_winrt) , m_ssl_context_callback([](boost::asio::ssl::context&)->void{}) + , m_tlsext_host_name(true) #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) , m_buffer_request(false) @@ -347,6 +348,25 @@ class http_client_config { return m_ssl_context_callback; } + + /// + /// Gets the TLS server name indication (SNI) property. + /// + /// True if TLS server name indication is enabled, false otherwise. + bool tlsext_host_name() const + { + return m_tlsext_host_name; + } + + /// + /// Sets the TLS server name indication (SNI) property. + /// + /// False to disable the TLS (ClientHello) extension for server name indication, true otherwise. + /// Note: This setting is required in most virtual hosting scenarios. + void set_tlsext_host_name(bool tlsext_host_name) + { + m_tlsext_host_name = tlsext_host_name; + } #endif private: @@ -372,6 +392,7 @@ class http_client_config #if !defined(_WIN32) && !defined(__cplusplus_winrt) std::function m_ssl_context_callback; + bool m_tlsext_host_name; #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) bool m_buffer_request; diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index bff2ff4843..ed4a448d3a 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -136,6 +136,7 @@ class asio_connection template void async_handshake(boost::asio::ssl::stream_base::handshake_type type, const http_client_config &config, + const utility::string_t &host_name, const HandshakeHandler &handshake_handler, const CertificateHandler &cert_handler) { @@ -152,6 +153,13 @@ class asio_connection { m_ssl_stream->set_verify_mode(boost::asio::ssl::context::verify_none); } + + // Check to set host name for Server Name Indication (SNI) + if (config.tlsext_host_name()) + { + SSL_set_tlsext_host_name(m_ssl_stream->native_handle(), const_cast(host_name.data())); + } + m_ssl_stream->async_handshake(type, handshake_handler); } @@ -561,6 +569,7 @@ class asio_context : public request_context, public std::enable_shared_from_this const auto weakCtx = std::weak_ptr(shared_from_this()); m_connection->async_handshake(boost::asio::ssl::stream_base::client, m_http_client->client_config(), + m_http_client->base_uri().host(), boost::bind(&asio_context::handle_handshake, shared_from_this(), boost::asio::placeholders::error), // Use a weak_ptr since the verify_callback is stored until the connection is destroyed. From e254a62bf6f2783380ff12a7c8f35b6fd3d7d8f2 Mon Sep 17 00:00:00 2001 From: George Malayil Date: Mon, 21 Dec 2015 17:08:26 +0530 Subject: [PATCH 024/609] Adding the ability to overwrite the http host header --- Release/include/cpprest/details/http_client_impl.h | 5 +++++ Release/src/http/client/http_client_asio.cpp | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/details/http_client_impl.h b/Release/include/cpprest/details/http_client_impl.h index 2f88472a50..3e1d246c02 100644 --- a/Release/include/cpprest/details/http_client_impl.h +++ b/Release/include/cpprest/details/http_client_impl.h @@ -57,6 +57,11 @@ static utility::string_t flatten_http_headers(const http_headers &headers) utility::string_t flattened_headers; for(auto iter = headers.begin(); iter != headers.end(); ++iter) { + utility::string_t header_name = iter->first; + http_headers::_case_insensitive_cmp cmp; + if (!cmp(header_name, "host") && !cmp("host", header_name)) { + continue; + } flattened_headers.append(iter->first); flattened_headers.push_back(':'); flattened_headers.append(iter->second); diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index bff2ff4843..694e961976 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -394,14 +394,21 @@ class asio_context : public request_context, public std::enable_shared_from_this std::ostream request_stream(&m_body_buf); request_stream.imbue(std::locale::classic()); - request_stream << method << " " << encoded_resource << " " << "HTTP/1.1" << CRLF << "Host: " << host; + request_stream << method << " " << encoded_resource << " " << "HTTP/1.1" << CRLF; + request_stream << "Host: "; int port = base_uri.port(); if (base_uri.is_port_default()) { port = (m_connection->is_ssl() ? 443 : 80); } - request_stream << ":" << port << CRLF; + + std::string specified_host_header; + if (m_request.headers().match(header_names::host, specified_host_header)) { + request_stream << specified_host_header << CRLF; + } else { + request_stream << host << ":" << port << CRLF; + } // Extra request headers are constructed here. utility::string_t extra_headers; From ac76f07be6cc74fde98c76e8ccfd428f82cfa5bd Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Mon, 21 Dec 2015 11:47:57 +0000 Subject: [PATCH 025/609] Implementing HTTP and HTTPS client proxy support for non-Windows platforms. Fixing whitespace --- .../cpprest/details/http_client_impl.h | 5 +- .../include/cpprest/details/web_utilities.h | 2 + Release/src/http/client/http_client_asio.cpp | 438 ++++++++++++++---- .../functional/http/client/proxy_tests.cpp | 2 +- 4 files changed, 358 insertions(+), 89 deletions(-) diff --git a/Release/include/cpprest/details/http_client_impl.h b/Release/include/cpprest/details/http_client_impl.h index 2f88472a50..e83c672c83 100644 --- a/Release/include/cpprest/details/http_client_impl.h +++ b/Release/include/cpprest/details/http_client_impl.h @@ -296,9 +296,10 @@ class _http_client_communicator // URI to connect to. const http::uri m_uri; -private: - http_client_config m_client_config; + http_client_config m_client_config; + +private: bool m_opened; diff --git a/Release/include/cpprest/details/web_utilities.h b/Release/include/cpprest/details/web_utilities.h index 9224b72f54..0fe97193bb 100644 --- a/Release/include/cpprest/details/web_utilities.h +++ b/Release/include/cpprest/details/web_utilities.h @@ -30,6 +30,7 @@ namespace web namespace http { namespace client { namespace details { class winhttp_client; class winrt_client; +class asio_context; }}} namespace websockets { namespace client { namespace details { class winrt_callback_client; @@ -124,6 +125,7 @@ class credentials private: friend class http::client::details::winhttp_client; friend class http::client::details::winrt_client; + friend class http::client::details::asio_context; friend class websockets::client::details::winrt_callback_client; friend class websockets::client::details::wspp_callback_client; diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index bff2ff4843..3f6b70cbb7 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -74,20 +74,16 @@ class asio_connection friend class asio_connection_pool; friend class asio_client; public: - asio_connection(boost::asio::io_service& io_service, bool use_ssl, const std::function& ssl_context_callback) : + asio_connection(boost::asio::io_service& io_service, bool start_with_ssl, const std::function& ssl_context_callback) : m_socket(io_service), m_pool_timer(io_service), m_is_reused(false), - m_keep_alive(true) + m_keep_alive(true), + m_ssl_context_callback(ssl_context_callback) { - if (use_ssl) + if (start_with_ssl) { - boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23); - ssl_context.set_default_verify_paths(); - ssl_context.set_options(boost::asio::ssl::context::default_workarounds); - ssl_context_callback(ssl_context); - m_ssl_stream = utility::details::make_unique>(m_socket, ssl_context); - + upgrade_to_ssl(); } } @@ -96,6 +92,18 @@ class asio_connection close(); } + // This simply instantiates the internal state to support ssl. It does not perform the handshake. + void upgrade_to_ssl() + { + std::lock_guard lock(m_socket_lock); + assert(!is_ssl()); + boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23); + ssl_context.set_default_verify_paths(); + ssl_context.set_options(boost::asio::ssl::context::default_workarounds); + m_ssl_context_callback(ssl_context); + m_ssl_stream = utility::details::make_unique>(m_socket, ssl_context); + } + void close() { std::lock_guard lock(m_socket_lock); @@ -220,6 +228,8 @@ class asio_connection tcp::socket m_socket; std::unique_ptr > m_ssl_stream; + std::function m_ssl_context_callback; + boost::asio::deadline_timer m_pool_timer; bool m_is_reused; bool m_keep_alive; @@ -229,10 +239,10 @@ class asio_connection_pool { public: - asio_connection_pool(boost::asio::io_service& io_service, bool use_ssl, const std::chrono::seconds &idle_timeout, const std::function &ssl_context_callback) : + asio_connection_pool(boost::asio::io_service& io_service, bool start_with_ssl, const std::chrono::seconds &idle_timeout, const std::function &ssl_context_callback) : m_io_service(io_service), m_timeout_secs(static_cast(idle_timeout.count())), - m_use_ssl(use_ssl), + m_start_with_ssl(start_with_ssl), m_ssl_context_callback(ssl_context_callback) {} @@ -269,7 +279,7 @@ class asio_connection_pool lock.unlock(); // No connections in pool => create a new connection instance. - return std::make_shared(m_io_service, m_use_ssl, m_ssl_context_callback); + return std::make_shared(m_io_service, m_start_with_ssl, m_ssl_context_callback); } else { @@ -305,19 +315,21 @@ class asio_connection_pool boost::asio::io_service& m_io_service; const int m_timeout_secs; - const bool m_use_ssl; + const bool m_start_with_ssl; const std::function& m_ssl_context_callback; std::vector > m_connections; std::mutex m_connections_mutex; }; + + class asio_client : public _http_client_communicator, public std::enable_shared_from_this { public: asio_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) , m_pool(crossplat::threadpool::shared_instance().service(), - base_uri().scheme() == "https", + base_uri().scheme() == "https" && !m_client_config.proxy().is_specified(), std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. this->client_config().get_ssl_context_callback()) , m_resolver(crossplat::threadpool::shared_instance().service()) @@ -363,102 +375,331 @@ class asio_context : public request_context, public std::enable_shared_from_this ctx->m_timer.set_ctx(std::weak_ptr(ctx)); return ctx; } - - void start_request() + + class ssl_proxy_tunnel : public std::enable_shared_from_this { - if (m_request._cancellation_token().is_canceled()) + public: + ssl_proxy_tunnel(std::shared_ptr context, std::function)> ssl_tunnel_established) + : m_ssl_tunnel_established(ssl_tunnel_established), m_context(context) + {} + + void start_proxy_connect() { - request_context::report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user."); - return; - } + auto proxy = m_context->m_http_client->client_config().proxy(); + auto proxy_uri = proxy.address(); - const auto &base_uri = m_http_client->base_uri(); - auto encoded_resource = uri_builder(base_uri).append(m_request.relative_uri()).to_uri().resource().to_string(); - if (encoded_resource == "") - { - encoded_resource = "/"; - } + utility::string_t proxy_host = proxy_uri.host(); + int proxy_port = proxy_uri.port() == -1 ? 8080 : proxy_uri.port(); - const auto &method = m_request.method(); + const auto &base_uri = m_context->m_http_client->base_uri(); + const auto &host = base_uri.host(); - // stop injection of headers via method - // resource should be ok, since it's been encoded - // and host won't resolve - if (!::web::http::details::validate_method(method)) - { - report_exception(http_exception("The method string is invalid.")); - return; - } + std::ostream request_stream(&request_); + request_stream.imbue(std::locale::classic()); - const auto &host = base_uri.host(); - std::ostream request_stream(&m_body_buf); - request_stream.imbue(std::locale::classic()); + request_stream << "CONNECT " << host << ":" << 443 << " HTTP/1.1" << CRLF; + request_stream << "Host: " << host << ":" << 443 << CRLF; + request_stream << "Proxy-Connection: Keep-Alive" << CRLF; - request_stream << method << " " << encoded_resource << " " << "HTTP/1.1" << CRLF << "Host: " << host; + if(!m_context->m_http_client->client_config().proxy().credentials().username().empty()) + { + request_stream << m_context->generate_basic_proxy_auth_header() << CRLF; + } - int port = base_uri.port(); - if (base_uri.is_port_default()) - { - port = (m_connection->is_ssl() ? 443 : 80); - } - request_stream << ":" << port << CRLF; + request_stream << CRLF; - // Extra request headers are constructed here. - utility::string_t extra_headers; + m_context->m_timer.start(); - // Check user specified transfer-encoding. - std::string transferencoding; - if (m_request.headers().match(header_names::transfer_encoding, transferencoding) && transferencoding == "chunked") - { - m_needChunked = true; + tcp::resolver::query query(proxy_host, utility::conversions::print_string(proxy_port, std::locale::classic())); + + auto client = std::static_pointer_cast(m_context->m_http_client); + client->m_resolver.async_resolve(query, boost::bind(&ssl_proxy_tunnel::handle_resolve, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } - else if (!m_request.headers().match(header_names::content_length, m_content_length)) + + private: + void handle_resolve(const boost::system::error_code& ec, tcp::resolver::iterator endpoints) { - // Stream without content length is the signal of requiring transfer encoding chunked. - if (m_request.body()) + if (ec) + { + m_context->report_error("Error resolving proxy address", ec, httpclient_errorcode_context::connect); + } + else { - m_needChunked = true; - extra_headers.append(header_names::transfer_encoding); - extra_headers.append(":chunked" + CRLF); + m_context->m_timer.reset(); + auto endpoint = *endpoints; + m_context->m_connection->async_connect(endpoint, boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); } } - request_stream << flatten_http_headers(m_request.headers()); - request_stream << extra_headers; - // Enforce HTTP connection keep alive (even for the old HTTP/1.0 protocol). - request_stream << "Connection: Keep-Alive" << CRLF << CRLF; + void handle_tcp_connect(const boost::system::error_code& ec, tcp::resolver::iterator endpoints) + { + if (!ec) + { + m_context->m_timer.reset(); + m_context->m_connection->async_write(request_, boost::bind(&ssl_proxy_tunnel::handle_write_request, shared_from_this(), boost::asio::placeholders::error)); + } + else if (endpoints == tcp::resolver::iterator()) + { + m_context->report_error("Failed to connect to any resolved proxy endpoint", ec, httpclient_errorcode_context::connect); + } + else + { + m_context->m_timer.reset(); + //// Replace the connection. This causes old connection object to go out of scope. + auto client = std::static_pointer_cast(m_context->m_http_client); + m_context->m_connection = client->m_pool.obtain(); - // Start connection timeout timer. - m_timer.start(); + auto endpoint = *endpoints; + m_context->m_connection->async_connect(endpoint, boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); + } - if (m_connection->is_reused()) - { - // If socket is a reused connection, try to write the request directly. - write_request(); } - else + + void handle_write_request(const boost::system::error_code& err) { - // If the connection is new (unresolved and unconnected socket), then start async - // call to resolve first, leading eventually to request write. - tcp::resolver::query query(host, utility::conversions::print_string(port, std::locale::classic())); - auto client = std::static_pointer_cast(m_http_client); - client->m_resolver.async_resolve(query, boost::bind(&asio_context::handle_resolve, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::iterator)); + if (!err) + { + m_context->m_timer.reset(); + m_context->m_connection->async_read_until(response_, CRLF + CRLF, boost::bind(&ssl_proxy_tunnel::handle_status_line, shared_from_this(), boost::asio::placeholders::error)); + } + else + { + m_context->report_error("Failed to send connect request to proxy.", err, httpclient_errorcode_context::writebody); + } + } + + void handle_status_line(const boost::system::error_code& ec) + { + if (!ec) + { + m_context->m_timer.reset(); + std::istream response_stream(&response_); + response_stream.imbue(std::locale::classic()); + std::string http_version; + response_stream >> http_version; + status_code status_code; + response_stream >> status_code; + + if (!response_stream || http_version.substr(0, 5) != "HTTP/") + { + m_context->report_error("Invalid HTTP status line during proxy connection", ec, httpclient_errorcode_context::readheader); + return; + } + + if (status_code != 200) + { + utility::stringstream_t err_ss; + err_ss << U("Expected a 200 response from proxy, received: ") << status_code; + m_context->report_error(err_ss.str(), ec, httpclient_errorcode_context::readheader); + return; + } + + m_context->m_connection->upgrade_to_ssl(); + + m_ssl_tunnel_established(m_context); + } + else + { + // These errors tell if connection was closed. + const bool socket_was_closed((boost::asio::error::eof == ec) + || (boost::asio::error::connection_reset == ec) + || (boost::asio::error::connection_aborted == ec)); + if (socket_was_closed && m_context->m_connection->is_reused()) + { + // Failed to write to socket because connection was already closed while it was in the pool. + // close() here ensures socket is closed in a robust way and prevents the connection from being put to the pool again. + m_context->m_connection->close(); + + // Create a new context and copy the request object, completion event and + // cancellation registration to maintain the old state. + // This also obtains a new connection from pool. + auto new_ctx = m_context->create_request_context(m_context->m_http_client, m_context->m_request); + new_ctx->m_request_completion = m_context->m_request_completion; + new_ctx->m_cancellationRegistration = m_context->m_cancellationRegistration; + + auto client = std::static_pointer_cast(m_context->m_http_client); + // Resend the request using the new context. + client->send_request(new_ctx); + } + else + { + m_context->report_error("Failed to read HTTP status line from proxy", ec, httpclient_errorcode_context::readheader); + } + } } + + std::function)> m_ssl_tunnel_established; + std::shared_ptr m_context; + + boost::asio::streambuf request_; + boost::asio::streambuf response_; + }; + + + enum class http_proxy_type + { + none, + http, + ssl_tunnel + }; - // Register for notification on cancellation to abort this request. - if(m_request._cancellation_token() != pplx::cancellation_token::none()) + void start_request() + { + if (m_request._cancellation_token().is_canceled()) + { + request_context::report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user."); + return; + } + + http_proxy_type proxy_type = http_proxy_type::none; + utility::string_t proxy_host; + int proxy_port = -1; + + // There is no support for auto-detection of proxies on non-windows platforms, it must be specified explicitly from the client code. + if (m_http_client->client_config().proxy().is_specified()) + { + proxy_type = m_http_client->base_uri().scheme() == U("https") ? http_proxy_type::ssl_tunnel : http_proxy_type::http; + auto proxy = m_http_client->client_config().proxy(); + auto proxy_uri = proxy.address(); + proxy_port = proxy_uri.port() == -1 ? 8080 : proxy_uri.port(); + proxy_host = proxy_uri.host(); + } + + auto start_http_request_flow = [proxy_type, proxy_host, proxy_port](std::shared_ptr ctx) { - // weak_ptr prevents lambda from taking shared ownership of the context. - // Otherwise context replacement in the handle_status_line() would leak the objects. - std::weak_ptr ctx_weak(shared_from_this()); - m_cancellationRegistration = m_request._cancellation_token().register_callback([ctx_weak]() + if (ctx->m_request._cancellation_token().is_canceled()) { - if (auto ctx_lock = ctx_weak.lock()) + ctx->request_context::report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user."); + return; + } + + const auto &base_uri = ctx->m_http_client->base_uri(); + const auto full_uri = uri_builder(base_uri).append(ctx->m_request.relative_uri()).to_uri(); + + // For a normal http proxy, we need to specify the full request uri, otherwise just specify the resource + auto encoded_resource = proxy_type == http_proxy_type::http ? full_uri.to_string() : full_uri.resource().to_string(); + + if (encoded_resource == "") + { + encoded_resource = "/"; + } + + const auto &method = ctx->m_request.method(); + + // stop injection of headers via method + // resource should be ok, since it's been encoded + // and host won't resolve + if (!::web::http::details::validate_method(method)) + { + ctx->report_exception(http_exception("The method string is invalid.")); + return; + } + + std::ostream request_stream(&ctx->m_body_buf); + request_stream.imbue(std::locale::classic()); + const auto &host = base_uri.host(); + + request_stream << method << " " << encoded_resource << " " << "HTTP/1.1" << CRLF << "Host: " << host; + + int port = base_uri.port(); + + if (base_uri.is_port_default()) + { + port = (ctx->m_connection->is_ssl() ? 443 : 80); + } + + request_stream << ":" << port << CRLF; + + // Extra request headers are constructed here. + utility::string_t extra_headers; + + // Add header for basic proxy authentication + if (proxy_type == http_proxy_type::http && !ctx->m_http_client->client_config().proxy().credentials().username().empty()) + { + extra_headers.append(ctx->generate_basic_proxy_auth_header()); + } + + // Check user specified transfer-encoding. + std::string transferencoding; + if (ctx->m_request.headers().match(header_names::transfer_encoding, transferencoding) && transferencoding == "chunked") + { + ctx->m_needChunked = true; + } + else if (!ctx->m_request.headers().match(header_names::content_length, ctx->m_content_length)) + { + // Stream without content length is the signal of requiring transfer encoding chunked. + if (ctx->m_request.body()) { - // Shut down transmissions, close the socket and prevent connection from being pooled. - ctx_lock->m_connection->close(); + ctx->m_needChunked = true; + extra_headers.append(header_names::transfer_encoding); + extra_headers.append(":chunked" + CRLF); } - }); + } + + if (proxy_type == http_proxy_type::http) + { + extra_headers.append(header_names::cache_control); + extra_headers.append(": no-store, no-cache" + CRLF); + extra_headers.append(header_names::pragma); + extra_headers.append(": no-cache" + CRLF); + } + + request_stream << flatten_http_headers(ctx->m_request.headers()); + request_stream << extra_headers; + // Enforce HTTP connection keep alive (even for the old HTTP/1.0 protocol). + request_stream << "Connection: Keep-Alive" << CRLF << CRLF; + + // Start connection timeout timer. + if (!ctx->m_timer.has_started()) + { + ctx->m_timer.start(); + } + + if (ctx->m_connection->is_reused() || proxy_type == http_proxy_type::ssl_tunnel) + { + // If socket is a reused connection or we're connected via an ssl-tunneling proxy, try to write the request directly. In both cases we have already established a tcp connection. + ctx->write_request(); + } + else + { + // If the connection is new (unresolved and unconnected socket), then start async + // call to resolve first, leading eventually to request write. + + // For normal http proxies, we want to connect directly to the proxy server. It will relay our request. + auto tcp_host = proxy_type == http_proxy_type::http ? proxy_host : host; + auto tcp_port = proxy_type == http_proxy_type::http ? proxy_port : port; + + tcp::resolver::query query(tcp_host, utility::conversions::print_string(tcp_port, std::locale::classic())); + auto client = std::static_pointer_cast(ctx->m_http_client); + client->m_resolver.async_resolve(query, boost::bind(&asio_context::handle_resolve, ctx, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); + } + + // Register for notification on cancellation to abort this request. + if (ctx->m_request._cancellation_token() != pplx::cancellation_token::none()) + { + // weak_ptr prevents lambda from taking shared ownership of the context. + // Otherwise context replacement in the handle_status_line() would leak the objects. + std::weak_ptr ctx_weak(ctx); + ctx->m_cancellationRegistration = ctx->m_request._cancellation_token().register_callback([ctx_weak]() + { + if (auto ctx_lock = ctx_weak.lock()) + { + // Shut down transmissions, close the socket and prevent connection from being pooled. + ctx_lock->m_connection->close(); + } + }); + } + }; + + if (proxy_type == http_proxy_type::ssl_tunnel) + { + // The ssl_tunnel_proxy keeps the context alive and then calls back once the ssl tunnel is established via 'start_http_request_flow' + std::shared_ptr ssl_tunnel = std::make_shared(shared_from_this(), start_http_request_flow); + ssl_tunnel->start_proxy_connect(); + } + else + { + start_http_request_flow(shared_from_this()); } } @@ -477,6 +718,24 @@ class asio_context : public request_context, public std::enable_shared_from_this private: + utility::string_t generate_basic_proxy_auth_header() + { + utility::string_t header; + + header.append(header_names::proxy_authorization); + header.append(": Basic "); + + auto credential_str = web::details::plaintext_string(new ::utility::string_t(m_http_client->client_config().proxy().credentials().username())); + credential_str->append(":"); + credential_str->append(*m_http_client->client_config().proxy().credentials().decrypt()); + + std::vector credentials_buffer(credential_str->begin(), credential_str->end()); + + header.append(utility::conversions::to_base64(credentials_buffer)); + header.append(CRLF); + return header; + } + void report_error(const utility::string_t &message, const boost::system::error_code &ec, httpclient_errorcode_context context = httpclient_errorcode_context::none) { // By default, errorcodeValue don't need to converted @@ -519,6 +778,7 @@ class asio_context : public request_context, public std::enable_shared_from_this void handle_connect(const boost::system::error_code& ec, tcp::resolver::iterator endpoints) { + m_timer.reset(); if (!ec) { @@ -640,6 +900,7 @@ class asio_context : public request_context, public std::enable_shared_from_this } } + void handle_write_chunked_body(const boost::system::error_code& ec) { if (ec) @@ -705,7 +966,7 @@ class asio_context : public request_context, public std::enable_shared_from_this // Reuse error handling. return handle_write_body(ec); } - + m_timer.reset(); const auto &progress = m_request._get_impl()->_progress_handler(); if (progress) @@ -786,7 +1047,7 @@ class asio_context : public request_context, public std::enable_shared_from_this response_stream >> http_version; status_code status_code; response_stream >> status_code; - + std::string status_message; std::getline(response_stream, status_message); @@ -1114,6 +1375,8 @@ class asio_context : public request_context, public std::enable_shared_from_this bool has_timedout() const { return m_state == timedout; } + bool has_started() const { return m_state == started; } + void stop() { m_state = stopped; @@ -1135,6 +1398,7 @@ class asio_context : public request_context, public std::enable_shared_from_this } } + private: enum timer_state { created, @@ -1164,6 +1428,8 @@ class asio_context : public request_context, public std::enable_shared_from_this #endif }; + + http_network_handler::http_network_handler(const uri &base_uri, const http_client_config &client_config) : m_http_client_impl(std::make_shared(base_uri, client_config)) {} diff --git a/Release/tests/functional/http/client/proxy_tests.cpp b/Release/tests/functional/http/client/proxy_tests.cpp index 1d73fa5cb7..e7b9d1cfb0 100644 --- a/Release/tests/functional/http/client/proxy_tests.cpp +++ b/Release/tests/functional/http/client/proxy_tests.cpp @@ -90,7 +90,7 @@ TEST_FIXTURE(uri_address, no_proxy_options_on_winrt) #ifndef __cplusplus_winrt // Can't specify a proxy with WinRT implementation. -TEST_FIXTURE(uri_address, proxy_with_credentials, "Ignore:Linux", "NYI", "Ignore:Apple", "NYI", "Ignore:Android", "NYI") +TEST_FIXTURE(uri_address, proxy_with_credentials) { uri u(U("http://netproxy.redmond.corp.microsoft.com")); From f41a04bdff6078dd6ef403e6ccb6d5a579740a09 Mon Sep 17 00:00:00 2001 From: George Malayil Date: Tue, 22 Dec 2015 01:32:25 +0530 Subject: [PATCH 026/609] Switching from hard-coded string 'host' to reference from header_names --- Release/include/cpprest/details/http_client_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/details/http_client_impl.h b/Release/include/cpprest/details/http_client_impl.h index 3e1d246c02..bccdd83acf 100644 --- a/Release/include/cpprest/details/http_client_impl.h +++ b/Release/include/cpprest/details/http_client_impl.h @@ -59,7 +59,7 @@ static utility::string_t flatten_http_headers(const http_headers &headers) { utility::string_t header_name = iter->first; http_headers::_case_insensitive_cmp cmp; - if (!cmp(header_name, "host") && !cmp("host", header_name)) { + if (!cmp(header_name, header_names::host) && !cmp(header_names::host, header_name)) { continue; } flattened_headers.append(iter->first); From a20b66910611c55baddd4759516846df7a5feca7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Dec 2015 19:20:13 +0000 Subject: [PATCH 027/609] Updating contributors.txt --- CONTRIBUTORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e53f210625..0e4c99aea0 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -34,5 +34,6 @@ Gery Vessere (gery@vessere.com) Cisco Systems Gergely Lukacsy (glukacsy) +Chris Deering (deeringc) thomasschaub From e4de345156427b67b0d7dd5eb70e4cdcc9eb68c9 Mon Sep 17 00:00:00 2001 From: AnyCPU Date: Tue, 22 Dec 2015 22:10:08 +0000 Subject: [PATCH 028/609] (freebsd) compilation fix #1 --- Release/include/pplx/pplxcancellation_token.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Release/include/pplx/pplxcancellation_token.h b/Release/include/pplx/pplxcancellation_token.h index f75da6099d..a191a93607 100644 --- a/Release/include/pplx/pplxcancellation_token.h +++ b/Release/include/pplx/pplxcancellation_token.h @@ -34,6 +34,7 @@ #error This file must not be included for Visual Studio 12 or later #endif +#include #include #include "pplx/pplxinterface.h" From fff0b91621a8d361cd60c33454ad8c9da051429e Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Thu, 31 Dec 2015 17:40:12 -0800 Subject: [PATCH 029/609] Fix indentation in oauth2.h --- Release/include/cpprest/oauth2.h | 1163 +++++++++++++----------------- 1 file changed, 501 insertions(+), 662 deletions(-) diff --git a/Release/include/cpprest/oauth2.h b/Release/include/cpprest/oauth2.h index f146990e9b..69c8dbcca6 100644 --- a/Release/include/cpprest/oauth2.h +++ b/Release/include/cpprest/oauth2.h @@ -18,8 +18,7 @@ * * HTTP Library: Oauth 2.0 * -* For the latest on this and related APIs, please see: -*https://github.com/Microsoft/cpprestsdk +* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk * * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ @@ -31,675 +30,515 @@ #include "cpprest/http_msg.h" #include "cpprest/details/web_utilities.h" -namespace web { -namespace http { - namespace client { - // Forward declaration to avoid circular include dependency. - class http_client_config; - } +namespace web +{ +namespace http +{ +namespace client +{ + // Forward declaration to avoid circular include dependency. + class http_client_config; +} - /// oAuth 2.0 library. - namespace oauth2 { - namespace details { +/// oAuth 2.0 library. +namespace oauth2 +{ +namespace details +{ - class oauth2_handler; +class oauth2_handler; - // Constant strings for OAuth 2.0. - typedef utility::string_t oauth2_string; - class oauth2_strings { - public: +// Constant strings for OAuth 2.0. +typedef utility::string_t oauth2_string; +class oauth2_strings +{ +public: #define _OAUTH2_STRINGS #define DAT(a_, b_) _ASYNCRTIMP static const oauth2_string a_; #include "cpprest/details/http_constants.dat" #undef _OAUTH2_STRINGS #undef DAT - }; - - } // namespace web::http::oauth2::details - - /// oAuth functionality is currently in beta. - namespace experimental { - - /// - /// Exception type for OAuth 2.0 errors. - /// - class oauth2_exception : public std::exception { - public: - oauth2_exception(utility::string_t msg) - : m_msg(utility::conversions::to_utf8string(std::move(msg))) - { - } - ~oauth2_exception() CPPREST_NOEXCEPT {} - const char* what() const CPPREST_NOEXCEPT - { - return m_msg.c_str(); - } - - private: - std::string m_msg; - }; - - /// - /// OAuth 2.0 token and associated information. - /// - class oauth2_token { - public: - /// - /// Value for undefined expiration time in expires_in(). - /// - enum { undefined_expiration = -1 }; - - oauth2_token( - utility::string_t access_token = utility::string_t()) - : m_access_token(std::move(access_token)) - , m_expires_in(undefined_expiration) - { - } - - /// - /// Get access token validity state. - /// If true, access token is a valid. - /// - /// Access token validity state. - bool is_valid_access_token() const - { - return !access_token().empty(); - } - - /// - /// Get access token. - /// - /// Access token string. - const utility::string_t& access_token() const - { - return m_access_token; - } - /// - /// Set access token. - /// - /// Access token string to - /// set. - void set_access_token(utility::string_t access_token) - { - m_access_token = std::move(access_token); - } - - /// - /// Get refresh token. - /// - /// Refresh token string. - const utility::string_t& refresh_token() const - { - return m_refresh_token; - } - /// - /// Set refresh token. - /// - /// Refresh token string to - /// set. - void set_refresh_token(utility::string_t refresh_token) - { - m_refresh_token = std::move(refresh_token); - } - - /// - /// Get token type. - /// - /// Token type string. - const utility::string_t& token_type() const - { - return m_token_type; - } - /// - /// Set token type. - /// - /// Token type string to set. - void set_token_type(utility::string_t token_type) - { - m_token_type = std::move(token_type); - } - - /// - /// Get token scope. - /// - /// Token scope string. - const utility::string_t& scope() const { return m_scope; } - /// - /// Set token scope. - /// - /// Token scope string to set. - void set_scope(utility::string_t scope) - { - m_scope = std::move(scope); - } - - /// - /// Get the lifetime of the access token in seconds. - /// For example, 3600 means the access token will expire in one - /// hour from - /// the time when access token response was generated by the - /// authorization server. - /// Value of undefined_expiration means expiration time is - /// either - /// unset or that it was not returned by the server with the - /// access token. - /// - /// Lifetime of the access token in seconds or - /// undefined_expiration if not set. - int64_t expires_in() const { return m_expires_in; } - /// - /// Set lifetime of access token (in seconds). - /// - /// Lifetime of access token in - /// seconds. - void set_expires_in(int64_t expires_in) - { - m_expires_in = expires_in; - } - - private: - utility::string_t m_access_token; - utility::string_t m_refresh_token; - utility::string_t m_token_type; - utility::string_t m_scope; - int64_t m_expires_in; - }; - - /// - /// OAuth 2.0 configuration. - /// - /// Encapsulates functionality for: - /// - Authenticating requests with an access token. - /// - Performing the OAuth 2.0 authorization code grant - /// authorization flow. - /// See: http://tools.ietf.org/html/rfc6749#section-4.1 - /// - Performing the OAuth 2.0 implicit grant authorization flow. - /// See: http://tools.ietf.org/html/rfc6749#section-4.2 - /// - /// Performing OAuth 2.0 authorization: - /// 1. Set service and client/app parameters: - /// - Client/app key & secret (as provided by the service). - /// - The service authorization endpoint and token endpoint. - /// - Your client/app redirect URI. - /// - Use set_state() to assign a unique state string for the - /// authorization - /// session (default: ""). - /// - If needed, use set_bearer_auth() to control bearer token - /// passing in either - /// query or header (default: header). See: - /// http://tools.ietf.org/html/rfc6750#section-2 - /// - If needed, use set_access_token_key() to set "non-standard" - /// access token - /// key (default: "access_token"). - /// - If needed, use set_implicit_grant() to enable implicit grant - /// flow. - /// 2. Build authorization URI with build_authorization_uri() and - /// open this in web browser/control. - /// 3. The resource owner should then clicks "Yes" to authorize your - /// client/app, and - /// as a result the web browser/control is redirected to - /// redirect_uri(). - /// 5. Capture the redirected URI either in web control or by HTTP - /// listener. - /// 6. Pass the redirected URI to token_from_redirected_uri() to - /// obtain access token. - /// - The method ensures redirected URI contains same state() as - /// set in step 1. - /// - In implicit_grant() is false, this will create HTTP request - /// to fetch access token - /// from the service. Otherwise access token is already included - /// in the redirected URI. - /// - /// Usage for issuing authenticated requests: - /// 1. Perform authorization as above to obtain the access token or - /// use an existing token. - /// - Some services provide option to generate access tokens for - /// testing purposes. - /// 2. Pass the resulting oauth2_config with the access token to - /// http_client_config::set_oauth2(). - /// 3. Construct http_client with this http_client_config. As a - /// result, all HTTP requests - /// by that client will be OAuth 2.0 authenticated. - /// - /// - class oauth2_config { - public: - oauth2_config(utility::string_t client_key, - utility::string_t client_secret, - utility::string_t auth_endpoint, - utility::string_t token_endpoint, - utility::string_t redirect_uri, - utility::string_t scope = utility::string_t()) - : m_client_key(std::move(client_key)) - , m_client_secret(std::move(client_secret)) - , m_auth_endpoint(std::move(auth_endpoint)) - , m_token_endpoint(std::move(token_endpoint)) - , m_redirect_uri(std::move(redirect_uri)) - , m_scope(std::move(scope)) - , m_implicit_grant(false) - , m_bearer_auth(true) - , m_http_basic_auth(true) - , m_access_token_key(details::oauth2_strings::access_token) - { - } - - /// - /// Builds an authorization URI to be loaded in the web - /// browser/view. - /// The URI is built with auth_endpoint() as basis. - /// The implicit_grant() affects the built URI by selecting - /// either authorization code or implicit grant flow. - /// You can set generate_state to generate a new random state - /// string. - /// - /// If true, a new random state() - /// string is generated - /// which replaces the current state(). If false, state() is - /// unchanged and used as-is. - /// Authorization URI string. - _ASYNCRTIMP utility::string_t build_authorization_uri( - bool generate_state); - - /// - /// Fetch an access token (and possibly a refresh token) based - /// on redirected URI. - /// Behavior depends on the implicit_grant() setting. - /// If implicit_grant() is false, the URI is parsed for 'code' - /// parameter, and then token_from_code() is called with this - /// code. - /// See: http://tools.ietf.org/html/rfc6749#section-4.1 - /// Otherwise, redirect URI fragment part is parsed for - /// 'access_token' - /// parameter, which directly contains the token(s). - /// See: http://tools.ietf.org/html/rfc6749#section-4.2 - /// In both cases, the 'state' parameter is parsed and is - /// verified to match state(). - /// - /// The URI where web browser/view - /// was redirected after resource owner's authorization. - /// Task that fetches the token(s) based on redirected - /// URI. - _ASYNCRTIMP pplx::task token_from_redirected_uri( - const web::http::uri& redirected_uri); - - /// - /// Fetches an access token (and possibly a refresh token) from - /// the token endpoint. - /// The task creates an HTTP request to the token_endpoint() - /// which exchanges - /// the authorization code for the token(s). - /// This also sets the refresh token if one was returned. - /// See: http://tools.ietf.org/html/rfc6749#section-4.1.3 - /// - /// Code received via redirect - /// upon successful authorization. - /// Task that fetches token(s) based on the - /// authorization code. - pplx::task token_from_code( - utility::string_t authorization_code) - { - uri_builder ub; - ub.append_query(details::oauth2_strings::grant_type, - details::oauth2_strings::authorization_code, false); - ub.append_query(details::oauth2_strings::code, - uri::encode_data_string(std::move(authorization_code)), - false); - ub.append_query(details::oauth2_strings::redirect_uri, - uri::encode_data_string(redirect_uri()), false); - return _request_token(ub); - } - - /// - /// Fetches a new access token (and possibly a new refresh - /// token) using the refresh token. - /// The task creates a HTTP request to the token_endpoint(). - /// If successful, resulting access token is set as active via - /// set_token(). - /// See: http://tools.ietf.org/html/rfc6749#section-6 - /// This also sets a new refresh token if one was returned. - /// - /// Task that fetches the token(s) using the refresh - /// token. - pplx::task token_from_refresh() - { - uri_builder ub; - ub.append_query(details::oauth2_strings::grant_type, - details::oauth2_strings::refresh_token, false); - ub.append_query(details::oauth2_strings::refresh_token, - uri::encode_data_string(token().refresh_token()), - false); - return _request_token(ub); - } - - /// - /// Returns enabled state of the configuration. - /// The oauth2_handler will perform OAuth 2.0 authentication - /// only if - /// this method returns true. - /// Return value is true if access token is valid (=fetched or - /// manually set). - /// - /// The configuration enabled state. - bool is_enabled() const - { - return token().is_valid_access_token(); - } - - /// - /// Get client key. - /// - /// Client key string. - const utility::string_t& client_key() const - { - return m_client_key; - } - /// - /// Set client key. - /// - /// Client key string to set. - void set_client_key(utility::string_t client_key) - { - m_client_key = std::move(client_key); - } - - /// - /// Get client secret. - /// - /// Client secret string. - const utility::string_t& client_secret() const - { - return m_client_secret; - } - /// - /// Set client secret. - /// - /// Client secret string to - /// set. - void set_client_secret(utility::string_t client_secret) - { - m_client_secret = std::move(client_secret); - } - - /// - /// Get authorization endpoint URI string. - /// - /// Authorization endpoint URI string. - const utility::string_t& auth_endpoint() const - { - return m_auth_endpoint; - } - /// - /// Set authorization endpoint URI string. - /// - /// Authorization endpoint URI - /// string to set. - void set_auth_endpoint(utility::string_t auth_endpoint) - { - m_auth_endpoint = std::move(auth_endpoint); - } - - /// - /// Get token endpoint URI string. - /// - /// Token endpoint URI string. - const utility::string_t& token_endpoint() const - { - return m_token_endpoint; - } - /// - /// Set token endpoint URI string. - /// - /// Token endpoint URI string to - /// set. - void set_token_endpoint(utility::string_t token_endpoint) - { - m_token_endpoint = std::move(token_endpoint); - } - - /// - /// Get redirect URI string. - /// - /// Redirect URI string. - const utility::string_t& redirect_uri() const - { - return m_redirect_uri; - } - /// - /// Set redirect URI string. - /// - /// Redirect URI string to - /// set. - void set_redirect_uri(utility::string_t redirect_uri) - { - m_redirect_uri = std::move(redirect_uri); - } - - /// - /// Get scope used in authorization for token. - /// - /// Scope string used in authorization. - const utility::string_t& scope() const { return m_scope; } - /// - /// Set scope for authorization for token. - /// - /// Scope string for authorization for - /// token. - void set_scope(utility::string_t scope) - { - m_scope = std::move(scope); - } - - /// - /// Get client state string used in authorization. - /// - /// Client state string used in - /// authorization. - const utility::string_t& state() { return m_state; } - /// - /// Set client state string for authorization for token. - /// The state string is used in authorization for security - /// reasons - /// (to uniquely identify authorization sessions). - /// If desired, suitably secure state string can be - /// automatically generated - /// by build_authorization_uri(). - /// A good state string consist of 30 or more random - /// alphanumeric characters. - /// - /// Client authorization state string to - /// set. - void set_state(utility::string_t state) - { - m_state = std::move(state); - } - - /// - /// Get token. - /// - /// Token. - const oauth2_token& token() const { return m_token; } - /// - /// Set token. - /// - /// Token to set. - void set_token(oauth2_token token) - { - m_token = std::move(token); - } - - /// - /// Get implicit grant setting for authorization. - /// - /// Implicit grant setting for authorization. - bool implicit_grant() const { return m_implicit_grant; } - /// - /// Set implicit grant setting for authorization. - /// False means authorization code grant is used for - /// authorization. - /// True means implicit grant is used. - /// Default: False. - /// - /// The implicit grant setting to - /// set. - void set_implicit_grant(bool implicit_grant) - { - m_implicit_grant = implicit_grant; - } - - /// - /// Get bearer token authentication setting. - /// - /// Bearer token authentication setting. - bool bearer_auth() const { return m_bearer_auth; } - /// - /// Set bearer token authentication setting. - /// This must be selected based on what the service accepts. - /// True means access token is passed in the request header. - /// (http://tools.ietf.org/html/rfc6750#section-2.1) - /// False means access token in passed in the query parameters. - /// (http://tools.ietf.org/html/rfc6750#section-2.3) - /// Default: True. - /// - /// The bearer token authentication - /// setting to set. - void set_bearer_auth(bool bearer_auth) - { - m_bearer_auth = bearer_auth; - } - - /// - /// Get HTTP Basic authentication setting for token endpoint. - /// - /// HTTP Basic authentication setting for token - /// endpoint. - bool http_basic_auth() const { return m_http_basic_auth; } - /// - /// Set HTTP Basic authentication setting for token endpoint. - /// This setting must be selected based on what the service - /// accepts. - /// True means HTTP Basic authentication is used for the token - /// endpoint. - /// False means client key & secret are passed in the HTTP - /// request body. - /// Default: True. - /// - /// The HTTP Basic authentication - /// setting to set. - void set_http_basic_auth(bool http_basic_auth) - { - m_http_basic_auth = http_basic_auth; - } - - /// - /// Get access token key. - /// - /// Access token key string. - const utility::string_t& access_token_key() const - { - return m_access_token_key; - } - /// - /// Set access token key. - /// If the service requires a "non-standard" key you must set it - /// here. - /// Default: "access_token". - /// - void set_access_token_key(utility::string_t access_token_key) - { - m_access_token_key = std::move(access_token_key); - } - - /// - /// Get the web proxy object - /// - /// A reference to the web proxy object. - const web_proxy& proxy() const { return m_proxy; } - - /// - /// Set the web proxy object that will be used by - /// token_from_code and token_from_refresh - /// - /// A reference to the web proxy - /// object. - void set_proxy(const web_proxy& proxy) { m_proxy = proxy; } - - private: - friend class web::http::client::http_client_config; - friend class web::http::oauth2::details::oauth2_handler; - - oauth2_config() - : m_implicit_grant(false) - , m_bearer_auth(true) - , m_http_basic_auth(true) - { - } - - _ASYNCRTIMP pplx::task _request_token( - uri_builder& request_body); - - oauth2_token _parse_token_from_json( - const json::value& token_json); - - void _authenticate_request(http_request& req) const - { - if (bearer_auth()) { - req.headers().add(header_names::authorization, - _XPLATSTR("Bearer ") + token().access_token()); - } - else { - uri_builder ub(req.request_uri()); - ub.append_query( - access_token_key(), token().access_token()); - req.set_request_uri(ub.to_uri()); - } - } - - utility::string_t m_client_key; - utility::string_t m_client_secret; - utility::string_t m_auth_endpoint; - utility::string_t m_token_endpoint; - utility::string_t m_redirect_uri; - utility::string_t m_scope; - utility::string_t m_state; - - web::web_proxy m_proxy; - - bool m_implicit_grant; - bool m_bearer_auth; - bool m_http_basic_auth; - utility::string_t m_access_token_key; - - oauth2_token m_token; - - utility::nonce_generator m_state_generator; - }; - - } // namespace web::http::oauth2::experimental - - namespace details { - - class oauth2_handler : public http_pipeline_stage { - public: - oauth2_handler(std::shared_ptr cfg) - : m_config(std::move(cfg)) - { - } - - virtual pplx::task propagate( - http_request request) override - { - if (m_config) { - m_config->_authenticate_request(request); - } - return next_stage()->propagate(request); - } - - private: - std::shared_ptr m_config; - }; +}; + +} // namespace web::http::oauth2::details + +/// oAuth functionality is currently in beta. +namespace experimental +{ + +/// +/// Exception type for OAuth 2.0 errors. +/// +class oauth2_exception : public std::exception +{ +public: + oauth2_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {} + ~oauth2_exception() CPPREST_NOEXCEPT {} + const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); } + +private: + std::string m_msg; +}; + +/// +/// OAuth 2.0 token and associated information. +/// +class oauth2_token +{ +public: + + /// + /// Value for undefined expiration time in expires_in(). + /// + enum { undefined_expiration = -1 }; + + oauth2_token(utility::string_t access_token=utility::string_t()) : + m_access_token(std::move(access_token)), + m_expires_in(undefined_expiration) + {} + + /// + /// Get access token validity state. + /// If true, access token is a valid. + /// + /// Access token validity state. + bool is_valid_access_token() const { return !access_token().empty(); } + + /// + /// Get access token. + /// + /// Access token string. + const utility::string_t& access_token() const { return m_access_token; } + /// + /// Set access token. + /// + /// Access token string to set. + void set_access_token(utility::string_t access_token) { m_access_token = std::move(access_token); } + + /// + /// Get refresh token. + /// + /// Refresh token string. + const utility::string_t& refresh_token() const { return m_refresh_token; } + /// + /// Set refresh token. + /// + /// Refresh token string to set. + void set_refresh_token(utility::string_t refresh_token) { m_refresh_token = std::move(refresh_token); } + + /// + /// Get token type. + /// + /// Token type string. + const utility::string_t& token_type() const { return m_token_type; } + /// + /// Set token type. + /// + /// Token type string to set. + void set_token_type(utility::string_t token_type) { m_token_type = std::move(token_type); } + + /// + /// Get token scope. + /// + /// Token scope string. + const utility::string_t& scope() const { return m_scope; } + /// + /// Set token scope. + /// + /// Token scope string to set. + void set_scope(utility::string_t scope) { m_scope = std::move(scope); } + + /// + /// Get the lifetime of the access token in seconds. + /// For example, 3600 means the access token will expire in one hour from + /// the time when access token response was generated by the authorization server. + /// Value of undefined_expiration means expiration time is either + /// unset or that it was not returned by the server with the access token. + /// + /// Lifetime of the access token in seconds or undefined_expiration if not set. + int64_t expires_in() const { return m_expires_in; } + /// + /// Set lifetime of access token (in seconds). + /// + /// Lifetime of access token in seconds. + void set_expires_in(int64_t expires_in) { m_expires_in = expires_in; } + +private: + utility::string_t m_access_token; + utility::string_t m_refresh_token; + utility::string_t m_token_type; + utility::string_t m_scope; + int64_t m_expires_in; +}; + +/// +/// OAuth 2.0 configuration. +/// +/// Encapsulates functionality for: +/// - Authenticating requests with an access token. +/// - Performing the OAuth 2.0 authorization code grant authorization flow. +/// See: http://tools.ietf.org/html/rfc6749#section-4.1 +/// - Performing the OAuth 2.0 implicit grant authorization flow. +/// See: http://tools.ietf.org/html/rfc6749#section-4.2 +/// +/// Performing OAuth 2.0 authorization: +/// 1. Set service and client/app parameters: +/// - Client/app key & secret (as provided by the service). +/// - The service authorization endpoint and token endpoint. +/// - Your client/app redirect URI. +/// - Use set_state() to assign a unique state string for the authorization +/// session (default: ""). +/// - If needed, use set_bearer_auth() to control bearer token passing in either +/// query or header (default: header). See: http://tools.ietf.org/html/rfc6750#section-2 +/// - If needed, use set_access_token_key() to set "non-standard" access token +/// key (default: "access_token"). +/// - If needed, use set_implicit_grant() to enable implicit grant flow. +/// 2. Build authorization URI with build_authorization_uri() and open this in web browser/control. +/// 3. The resource owner should then clicks "Yes" to authorize your client/app, and +/// as a result the web browser/control is redirected to redirect_uri(). +/// 5. Capture the redirected URI either in web control or by HTTP listener. +/// 6. Pass the redirected URI to token_from_redirected_uri() to obtain access token. +/// - The method ensures redirected URI contains same state() as set in step 1. +/// - In implicit_grant() is false, this will create HTTP request to fetch access token +/// from the service. Otherwise access token is already included in the redirected URI. +/// +/// Usage for issuing authenticated requests: +/// 1. Perform authorization as above to obtain the access token or use an existing token. +/// - Some services provide option to generate access tokens for testing purposes. +/// 2. Pass the resulting oauth2_config with the access token to http_client_config::set_oauth2(). +/// 3. Construct http_client with this http_client_config. As a result, all HTTP requests +/// by that client will be OAuth 2.0 authenticated. +/// +/// +class oauth2_config +{ +public: + + oauth2_config(utility::string_t client_key, utility::string_t client_secret, + utility::string_t auth_endpoint, utility::string_t token_endpoint, + utility::string_t redirect_uri, utility::string_t scope=utility::string_t()) : + m_client_key(std::move(client_key)), + m_client_secret(std::move(client_secret)), + m_auth_endpoint(std::move(auth_endpoint)), + m_token_endpoint(std::move(token_endpoint)), + m_redirect_uri(std::move(redirect_uri)), + m_scope(std::move(scope)), + m_implicit_grant(false), + m_bearer_auth(true), + m_http_basic_auth(true), + m_access_token_key(details::oauth2_strings::access_token) + {} + + /// + /// Builds an authorization URI to be loaded in the web browser/view. + /// The URI is built with auth_endpoint() as basis. + /// The implicit_grant() affects the built URI by selecting + /// either authorization code or implicit grant flow. + /// You can set generate_state to generate a new random state string. + /// + /// If true, a new random state() string is generated + /// which replaces the current state(). If false, state() is unchanged and used as-is. + /// Authorization URI string. + _ASYNCRTIMP utility::string_t build_authorization_uri(bool generate_state); + + /// + /// Fetch an access token (and possibly a refresh token) based on redirected URI. + /// Behavior depends on the implicit_grant() setting. + /// If implicit_grant() is false, the URI is parsed for 'code' + /// parameter, and then token_from_code() is called with this code. + /// See: http://tools.ietf.org/html/rfc6749#section-4.1 + /// Otherwise, redirect URI fragment part is parsed for 'access_token' + /// parameter, which directly contains the token(s). + /// See: http://tools.ietf.org/html/rfc6749#section-4.2 + /// In both cases, the 'state' parameter is parsed and is verified to match state(). + /// + /// The URI where web browser/view was redirected after resource owner's authorization. + /// Task that fetches the token(s) based on redirected URI. + _ASYNCRTIMP pplx::task token_from_redirected_uri(const web::http::uri& redirected_uri); + + /// + /// Fetches an access token (and possibly a refresh token) from the token endpoint. + /// The task creates an HTTP request to the token_endpoint() which exchanges + /// the authorization code for the token(s). + /// This also sets the refresh token if one was returned. + /// See: http://tools.ietf.org/html/rfc6749#section-4.1.3 + /// + /// Code received via redirect upon successful authorization. + /// Task that fetches token(s) based on the authorization code. + pplx::task token_from_code(utility::string_t authorization_code) + { + uri_builder ub; + ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::authorization_code, false); + ub.append_query(details::oauth2_strings::code, uri::encode_data_string(std::move(authorization_code)), false); + ub.append_query(details::oauth2_strings::redirect_uri, uri::encode_data_string(redirect_uri()), false); + return _request_token(ub); + } + + /// + /// Fetches a new access token (and possibly a new refresh token) using the refresh token. + /// The task creates a HTTP request to the token_endpoint(). + /// If successful, resulting access token is set as active via set_token(). + /// See: http://tools.ietf.org/html/rfc6749#section-6 + /// This also sets a new refresh token if one was returned. + /// + /// Task that fetches the token(s) using the refresh token. + pplx::task token_from_refresh() + { + uri_builder ub; + ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::refresh_token, false); + ub.append_query(details::oauth2_strings::refresh_token, uri::encode_data_string(token().refresh_token()), false); + return _request_token(ub); + } + + /// + /// Returns enabled state of the configuration. + /// The oauth2_handler will perform OAuth 2.0 authentication only if + /// this method returns true. + /// Return value is true if access token is valid (=fetched or manually set). + /// + /// The configuration enabled state. + bool is_enabled() const { return token().is_valid_access_token(); } + + /// + /// Get client key. + /// + /// Client key string. + const utility::string_t& client_key() const { return m_client_key; } + /// + /// Set client key. + /// + /// Client key string to set. + void set_client_key(utility::string_t client_key) { m_client_key = std::move(client_key); } + + /// + /// Get client secret. + /// + /// Client secret string. + const utility::string_t& client_secret() const { return m_client_secret; } + /// + /// Set client secret. + /// + /// Client secret string to set. + void set_client_secret(utility::string_t client_secret) { m_client_secret = std::move(client_secret); } + + /// + /// Get authorization endpoint URI string. + /// + /// Authorization endpoint URI string. + const utility::string_t& auth_endpoint() const { return m_auth_endpoint; } + /// + /// Set authorization endpoint URI string. + /// + /// Authorization endpoint URI string to set. + void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); } + + /// + /// Get token endpoint URI string. + /// + /// Token endpoint URI string. + const utility::string_t& token_endpoint() const { return m_token_endpoint; } + /// + /// Set token endpoint URI string. + /// + /// Token endpoint URI string to set. + void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); } + + /// + /// Get redirect URI string. + /// + /// Redirect URI string. + const utility::string_t& redirect_uri() const { return m_redirect_uri; } + /// + /// Set redirect URI string. + /// + /// Redirect URI string to set. + void set_redirect_uri(utility::string_t redirect_uri) { m_redirect_uri = std::move(redirect_uri); } + + /// + /// Get scope used in authorization for token. + /// + /// Scope string used in authorization. + const utility::string_t& scope() const { return m_scope; } + /// + /// Set scope for authorization for token. + /// + /// Scope string for authorization for token. + void set_scope(utility::string_t scope) { m_scope = std::move(scope); } + + /// + /// Get client state string used in authorization. + /// + /// Client state string used in authorization. + const utility::string_t& state() { return m_state; } + /// + /// Set client state string for authorization for token. + /// The state string is used in authorization for security reasons + /// (to uniquely identify authorization sessions). + /// If desired, suitably secure state string can be automatically generated + /// by build_authorization_uri(). + /// A good state string consist of 30 or more random alphanumeric characters. + /// + /// Client authorization state string to set. + void set_state(utility::string_t state) { m_state = std::move(state); } + + /// + /// Get token. + /// + /// Token. + const oauth2_token& token() const { return m_token; } + /// + /// Set token. + /// + /// Token to set. + void set_token(oauth2_token token) { m_token = std::move(token); } + + /// + /// Get implicit grant setting for authorization. + /// + /// Implicit grant setting for authorization. + bool implicit_grant() const { return m_implicit_grant; } + /// + /// Set implicit grant setting for authorization. + /// False means authorization code grant is used for authorization. + /// True means implicit grant is used. + /// Default: False. + /// + /// The implicit grant setting to set. + void set_implicit_grant(bool implicit_grant) { m_implicit_grant = implicit_grant; } + + /// + /// Get bearer token authentication setting. + /// + /// Bearer token authentication setting. + bool bearer_auth() const { return m_bearer_auth; } + /// + /// Set bearer token authentication setting. + /// This must be selected based on what the service accepts. + /// True means access token is passed in the request header. (http://tools.ietf.org/html/rfc6750#section-2.1) + /// False means access token in passed in the query parameters. (http://tools.ietf.org/html/rfc6750#section-2.3) + /// Default: True. + /// + /// The bearer token authentication setting to set. + void set_bearer_auth(bool bearer_auth) { m_bearer_auth = bearer_auth; } + + /// + /// Get HTTP Basic authentication setting for token endpoint. + /// + /// HTTP Basic authentication setting for token endpoint. + bool http_basic_auth() const { return m_http_basic_auth; } + /// + /// Set HTTP Basic authentication setting for token endpoint. + /// This setting must be selected based on what the service accepts. + /// True means HTTP Basic authentication is used for the token endpoint. + /// False means client key & secret are passed in the HTTP request body. + /// Default: True. + /// + /// The HTTP Basic authentication setting to set. + void set_http_basic_auth(bool http_basic_auth) { m_http_basic_auth = http_basic_auth; } + + /// + /// Get access token key. + /// + /// Access token key string. + const utility::string_t& access_token_key() const { return m_access_token_key; } + /// + /// Set access token key. + /// If the service requires a "non-standard" key you must set it here. + /// Default: "access_token". + /// + void set_access_token_key(utility::string_t access_token_key) { m_access_token_key = std::move(access_token_key); } + + /// + /// Get the web proxy object + /// + /// A reference to the web proxy object. + const web_proxy& proxy() const + { + return m_proxy; + } + + /// + /// Set the web proxy object that will be used by token_from_code and token_from_refresh + /// + /// A reference to the web proxy object. + void set_proxy(const web_proxy& proxy) + { + m_proxy = proxy; + } + +private: + friend class web::http::client::http_client_config; + friend class web::http::oauth2::details::oauth2_handler; + + oauth2_config() : + m_implicit_grant(false), + m_bearer_auth(true), + m_http_basic_auth(true) + {} + + _ASYNCRTIMP pplx::task _request_token(uri_builder& request_body); + + oauth2_token _parse_token_from_json(const json::value& token_json); + + void _authenticate_request(http_request &req) const + { + if (bearer_auth()) + { + req.headers().add(header_names::authorization, _XPLATSTR("Bearer ") + token().access_token()); + } + else + { + uri_builder ub(req.request_uri()); + ub.append_query(access_token_key(), token().access_token()); + req.set_request_uri(ub.to_uri()); } } -} -} + + utility::string_t m_client_key; + utility::string_t m_client_secret; + utility::string_t m_auth_endpoint; + utility::string_t m_token_endpoint; + utility::string_t m_redirect_uri; + utility::string_t m_scope; + utility::string_t m_state; + + web::web_proxy m_proxy; + + bool m_implicit_grant; + bool m_bearer_auth; + bool m_http_basic_auth; + utility::string_t m_access_token_key; + + oauth2_token m_token; + + utility::nonce_generator m_state_generator; +}; + +} // namespace web::http::oauth2::experimental + +namespace details +{ + +class oauth2_handler : public http_pipeline_stage +{ +public: + oauth2_handler(std::shared_ptr cfg) : + m_config(std::move(cfg)) + {} + + virtual pplx::task propagate(http_request request) override + { + if (m_config) + { + m_config->_authenticate_request(request); + } + return next_stage()->propagate(request); + } + +private: + std::shared_ptr m_config; +}; + +}}}} #endif From 57c2e9e10d239648e8dfbfa52b55cdad6054102c Mon Sep 17 00:00:00 2001 From: megaposer Date: Mon, 4 Jan 2016 08:49:08 +0100 Subject: [PATCH 030/609] Rename methods and variable names / incorrporate feedback from #39 review --- Release/include/cpprest/http_client.h | 20 ++++++++++---------- Release/src/http/client/http_client_asio.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 7823a6b1c1..1e0ce8b73f 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -101,7 +101,7 @@ class http_client_config , m_set_user_nativehandle_options([](native_handle)->void{}) #if !defined(_WIN32) && !defined(__cplusplus_winrt) , m_ssl_context_callback([](boost::asio::ssl::context&)->void{}) - , m_tlsext_host_name(true) + , m_tlsext_sni_enabled(true) #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) , m_buffer_request(false) @@ -350,22 +350,22 @@ class http_client_config } /// - /// Gets the TLS server name indication (SNI) property. + /// Gets the TLS extension server name indication (SNI) status. /// /// True if TLS server name indication is enabled, false otherwise. - bool tlsext_host_name() const + bool is_tlsext_sni_enabled() const { - return m_tlsext_host_name; + return m_tlsext_sni_enabled; } /// - /// Sets the TLS server name indication (SNI) property. + /// Sets the TLS extension server name indication (SNI) status. /// - /// False to disable the TLS (ClientHello) extension for server name indication, true otherwise. - /// Note: This setting is required in most virtual hosting scenarios. - void set_tlsext_host_name(bool tlsext_host_name) + /// False to disable the TLS (ClientHello) extension for server name indication, true otherwise. + /// Note: This setting is enabled by default as it is required in most virtual hosting scenarios. + void set_tlsext_sni_enabled(bool tlsext_sni_enabled) { - m_tlsext_host_name = tlsext_host_name; + m_tlsext_sni_enabled = tlsext_sni_enabled; } #endif @@ -392,7 +392,7 @@ class http_client_config #if !defined(_WIN32) && !defined(__cplusplus_winrt) std::function m_ssl_context_callback; - bool m_tlsext_host_name; + bool m_tlsext_sni_enabled; #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) bool m_buffer_request; diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index ed4a448d3a..9a4b5314f0 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -155,7 +155,7 @@ class asio_connection } // Check to set host name for Server Name Indication (SNI) - if (config.tlsext_host_name()) + if (config.is_tlsext_sni_enabled()) { SSL_set_tlsext_host_name(m_ssl_stream->native_handle(), const_cast(host_name.data())); } From 9eebbd3deebbc640aaff26160dd10ab3ace2a505 Mon Sep 17 00:00:00 2001 From: George Malayil Date: Mon, 4 Jan 2016 15:16:40 +0530 Subject: [PATCH 031/609] 1. Switched to utility::details::str_icmp() to do header value comparisons 2. Added test case to test overwriting the host header --- .../cpprest/details/http_client_impl.h | 3 +- .../functional/http/client/header_tests.cpp | 33 ++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/details/http_client_impl.h b/Release/include/cpprest/details/http_client_impl.h index bccdd83acf..bb351526a1 100644 --- a/Release/include/cpprest/details/http_client_impl.h +++ b/Release/include/cpprest/details/http_client_impl.h @@ -58,8 +58,7 @@ static utility::string_t flatten_http_headers(const http_headers &headers) for(auto iter = headers.begin(); iter != headers.end(); ++iter) { utility::string_t header_name = iter->first; - http_headers::_case_insensitive_cmp cmp; - if (!cmp(header_name, header_names::host) && !cmp(header_names::host, header_name)) { + if (utility::details::str_icmp(header_name, header_names::host)) { continue; } flattened_headers.append(iter->first); diff --git a/Release/tests/functional/http/client/header_tests.cpp b/Release/tests/functional/http/client/header_tests.cpp index 83bee7cab5..697bc8173c 100644 --- a/Release/tests/functional/http/client/header_tests.cpp +++ b/Release/tests/functional/http/client/header_tests.cpp @@ -382,6 +382,37 @@ TEST_FIXTURE(uri_address, parsing_content_type_redundantsemicolon_string) auto resp = client.request(methods::GET).get(); VERIFY_ARE_EQUAL(resp.extract_string().get(), utility::conversions::to_string_t(body)); } + +TEST_FIXTURE(uri_address, overwrite_http_header) +{ + test_http_server::scoped_server scoped(m_uri); + http_client client(m_uri); + + // Test default case of cpprestsdk setting host header as host:port + auto& host = m_uri.host(); + int port = m_uri.port(); + utility::string_t expected_default_header = host + ":" + std::to_string(port); + http_request default_host_headers_request(methods::GET); + scoped.server()->next_request().then([&](test_request *p_request) + { + auto headers = p_request->m_headers; + VERIFY_ARE_EQUAL(expected_default_header, headers[header_names::host]); + p_request->reply(200); + }); + + client.request(default_host_headers_request).get(); + + // Test case where we overwrite the host header + http_request overwritten_host_headers_request(methods::GET); + overwritten_host_headers_request.headers().add("Host", host); + scoped.server()->next_request().then([&](test_request *p_request) + { + auto headers = p_request->m_headers; + VERIFY_ARE_EQUAL(host, headers[header_names::host]); + p_request->reply(200); + }); + client.request(overwritten_host_headers_request).get(); +} } // SUITE(header_tests) -}}}} \ No newline at end of file +}}}} From d7c9e7c1a55c53d55fc7ea8402b9f43cc3ea7be7 Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Tue, 5 Jan 2016 12:40:15 +0000 Subject: [PATCH 032/609] Updates from code review. Adding new manual test cases for http_proxy and https_proxy --- .../cpprest/details/http_client_impl.h | 5 +-- Release/src/http/client/http_client_asio.cpp | 18 ++++---- .../functional/http/client/proxy_tests.cpp | 43 ++++++++++++++++++- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/Release/include/cpprest/details/http_client_impl.h b/Release/include/cpprest/details/http_client_impl.h index e83c672c83..2f88472a50 100644 --- a/Release/include/cpprest/details/http_client_impl.h +++ b/Release/include/cpprest/details/http_client_impl.h @@ -296,11 +296,10 @@ class _http_client_communicator // URI to connect to. const http::uri m_uri; - - http_client_config m_client_config; - private: + http_client_config m_client_config; + bool m_opened; pplx::extensibility::critical_section_t m_open_lock; diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 3f6b70cbb7..8fcfe120e9 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -329,7 +329,7 @@ class asio_client : public _http_client_communicator, public std::enable_shared_ asio_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) , m_pool(crossplat::threadpool::shared_instance().service(), - base_uri().scheme() == "https" && !m_client_config.proxy().is_specified(), + base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. this->client_config().get_ssl_context_callback()) , m_resolver(crossplat::threadpool::shared_instance().service()) @@ -394,14 +394,14 @@ class asio_context : public request_context, public std::enable_shared_from_this const auto &base_uri = m_context->m_http_client->base_uri(); const auto &host = base_uri.host(); - std::ostream request_stream(&request_); + std::ostream request_stream(&m_request); request_stream.imbue(std::locale::classic()); request_stream << "CONNECT " << host << ":" << 443 << " HTTP/1.1" << CRLF; request_stream << "Host: " << host << ":" << 443 << CRLF; request_stream << "Proxy-Connection: Keep-Alive" << CRLF; - if(!m_context->m_http_client->client_config().proxy().credentials().username().empty()) + if(m_context->m_http_client->client_config().proxy().credentials().is_set()) { request_stream << m_context->generate_basic_proxy_auth_header() << CRLF; } @@ -436,7 +436,7 @@ class asio_context : public request_context, public std::enable_shared_from_this if (!ec) { m_context->m_timer.reset(); - m_context->m_connection->async_write(request_, boost::bind(&ssl_proxy_tunnel::handle_write_request, shared_from_this(), boost::asio::placeholders::error)); + m_context->m_connection->async_write(m_request, boost::bind(&ssl_proxy_tunnel::handle_write_request, shared_from_this(), boost::asio::placeholders::error)); } else if (endpoints == tcp::resolver::iterator()) { @@ -460,7 +460,7 @@ class asio_context : public request_context, public std::enable_shared_from_this if (!err) { m_context->m_timer.reset(); - m_context->m_connection->async_read_until(response_, CRLF + CRLF, boost::bind(&ssl_proxy_tunnel::handle_status_line, shared_from_this(), boost::asio::placeholders::error)); + m_context->m_connection->async_read_until(m_response, CRLF + CRLF, boost::bind(&ssl_proxy_tunnel::handle_status_line, shared_from_this(), boost::asio::placeholders::error)); } else { @@ -473,7 +473,7 @@ class asio_context : public request_context, public std::enable_shared_from_this if (!ec) { m_context->m_timer.reset(); - std::istream response_stream(&response_); + std::istream response_stream(&m_response); response_stream.imbue(std::locale::classic()); std::string http_version; response_stream >> http_version; @@ -531,8 +531,8 @@ class asio_context : public request_context, public std::enable_shared_from_this std::function)> m_ssl_tunnel_established; std::shared_ptr m_context; - boost::asio::streambuf request_; - boost::asio::streambuf response_; + boost::asio::streambuf m_request; + boost::asio::streambuf m_response; }; @@ -614,7 +614,7 @@ class asio_context : public request_context, public std::enable_shared_from_this utility::string_t extra_headers; // Add header for basic proxy authentication - if (proxy_type == http_proxy_type::http && !ctx->m_http_client->client_config().proxy().credentials().username().empty()) + if (proxy_type == http_proxy_type::http && ctx->m_http_client->client_config().proxy().credentials().is_set()) { extra_headers.append(ctx->generate_basic_proxy_auth_header()); } diff --git a/Release/tests/functional/http/client/proxy_tests.cpp b/Release/tests/functional/http/client/proxy_tests.cpp index e7b9d1cfb0..115d39f5e3 100644 --- a/Release/tests/functional/http/client/proxy_tests.cpp +++ b/Release/tests/functional/http/client/proxy_tests.cpp @@ -90,7 +90,7 @@ TEST_FIXTURE(uri_address, no_proxy_options_on_winrt) #ifndef __cplusplus_winrt // Can't specify a proxy with WinRT implementation. -TEST_FIXTURE(uri_address, proxy_with_credentials) +TEST_FIXTURE(uri_address, http_proxy_with_credentials) { uri u(U("http://netproxy.redmond.corp.microsoft.com")); @@ -124,6 +124,47 @@ TEST_FIXTURE(uri_address, proxy_with_credentials) throw; } } + +TEST_FIXTURE(uri_address, http_proxy, "Ignore", "Manual") +{ + // In order to run this test, replace this proxy uri with one that you have access to. + uri u(U("http://netproxy.redmond.corp.microsoft.com")); + + web_proxy proxy(u); + VERIFY_IS_TRUE(proxy.is_specified()); + VERIFY_ARE_EQUAL(u, proxy.address()); + + http_client_config config; + config.set_proxy(proxy); + + http_client client(U("http://httpbin.org"), config); + + http_response response = client.request(methods::GET).get(); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); + response.content_ready().wait(); +} + + +TEST_FIXTURE(uri_address, https_proxy, "Ignore", "Manual") +{ + // In order to run this test, replace this proxy uri with one that you have access to. + uri u(U("http://netproxy.redmond.corp.microsoft.com")); + + web_proxy proxy(u); + VERIFY_IS_TRUE(proxy.is_specified()); + VERIFY_ARE_EQUAL(u, proxy.address()); + + http_client_config config; + config.set_proxy(proxy); + + http_client client(U("https://httpbin.org"), config); + + http_response response = client.request(methods::GET).get(); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); + response.content_ready().wait(); +} + + #endif } // SUITE(proxy_tests) From e708c1a9d7304633fa204a1baf3abfd419a0cccd Mon Sep 17 00:00:00 2001 From: AntonBikineev Date: Wed, 6 Jan 2016 04:02:31 +0300 Subject: [PATCH 033/609] Fixing .then to work with movable-only types --- Release/include/pplx/pplxtasks.h | 82 ++++++++++++++----- .../pplx/pplx_test/pplxtask_tests.cpp | 15 ++++ 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index e82a14e17e..6145fe08f3 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -3093,6 +3093,45 @@ namespace details template static std::false_type _IsValidCreateAsync(_Ty _Param, ...); #endif /* defined (__cplusplus_winrt) */ + +/// +/// A helper class template that makes only movable functions be able to be passed to std::function +/// + template + struct _NonCopyableFunctorWrapper + { + template + _NonCopyableFunctorWrapper(_Tx&& f) + : _M_functor{std::make_shared<_Ty>(std::forward<_Tx>(f))} + {} + + template + auto operator()(_Args&&... args) -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...)) + { + return _M_functor->operator()(std::forward<_Args>(args)...); + } + + template + auto operator()(_Args&&... args) const -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...)) + { + return _M_functor->operator()(std::forward<_Args>(args)...); + } + + std::shared_ptr<_Ty> _M_functor; + }; + + template + struct _CopyableFunctor + { + typedef _Ty _Type; + }; + + template + struct _CopyableFunctor<_Ty, typename std::enable_if< + std::is_move_constructible<_Ty>::value && !std::is_copy_constructible<_Ty>::value>::type> + { + typedef _NonCopyableFunctorWrapper<_Ty> _Type; + }; } /// /// A helper class template that transforms a continuation lambda that either takes or returns void, or both, into a lambda that takes and returns a @@ -3424,11 +3463,11 @@ class task /**/ template __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result - auto then(const _Function& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType + auto then(_Function&& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType { task_options _TaskOptions; details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK()); - return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions); + return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions); } /// @@ -3457,10 +3496,10 @@ class task /**/ template __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result - auto then(const _Function& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType + auto then(_Function&& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType { details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK()); - return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions); + return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions); } /// @@ -3493,11 +3532,11 @@ class task /**/ template __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result - auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType + auto then(_Function&& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType { task_options _TaskOptions(_CancellationToken, _ContinuationContext); details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK()); - return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions); + return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions); } /// @@ -3682,13 +3721,13 @@ class task /// This function is Used for runtime internal continuations only. /// template - auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState, + auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState, details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType { // inherit from antecedent auto _Scheduler = _GetImpl()->_GetScheduler(); - return _ThenImpl<_ReturnType, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode); + return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode); } private: @@ -3801,16 +3840,17 @@ class task typedef typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type _NormalizedContinuationReturnType; typename details::_Task_ptr<_ReturnType>::_Type _M_ancestorTaskImpl; - _Function _M_function; + typename details::_CopyableFunctor<_Function>::_Type _M_function; + template _ContinuationTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type & _AncestorImpl, const typename details::_Task_ptr<_NormalizedContinuationReturnType>::_Type & _ContinuationImpl, - const _Function & _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode) + _ForwardedFunction&& _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode) : details::_PPLTaskHandle::_Type, _ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase> ::_PPLTaskHandle(_ContinuationImpl) , _M_ancestorTaskImpl(_AncestorImpl) - , _M_function(_Func) + , _M_function(std::forward<_ForwardedFunction>(_Func)) { this->_M_isTaskBasedContinuation = _IsTaskBased::value; this->_M_continuationContext = _Context; @@ -4095,7 +4135,7 @@ class task } template - auto _ThenImpl(const _Function& _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType + auto _ThenImpl(_Function&& _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType { if (!_M_Impl) { @@ -4105,14 +4145,14 @@ class task details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr; auto _Scheduler = _TaskOptions.has_scheduler() ? _TaskOptions.get_scheduler() : _GetImpl()->_GetScheduler(); auto _CreationStack = details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : details::_TaskCreationCallstack(); - return _ThenImpl<_InternalReturnType, _Function>(_Func, _PTokenState, _TaskOptions.get_continuation_context(), _Scheduler, _CreationStack); + return _ThenImpl<_InternalReturnType, _Function>(std::forward<_Function>(_Func), _PTokenState, _TaskOptions.get_continuation_context(), _Scheduler, _CreationStack); } /// /// The one and only implementation of then for void and non-void tasks. /// template - auto _ThenImpl(const _Function& _Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack, + auto _ThenImpl(_Function&& _Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack, details::_TaskInliningMode_t _InliningMode = details::_NoInline) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType { if (!_M_Impl) @@ -4149,7 +4189,7 @@ class task _ContinuationTask._SetTaskCreationCallstack(_CreationStack); _GetImpl()->_ScheduleContinuation(new _ContinuationTaskHandle<_InternalReturnType, _TaskType, _Function, typename _Function_type_traits::_Takes_task, typename _Async_type_traits::_AsyncKind>( - _GetImpl(), _ContinuationTask._GetImpl(), _Func, _ContinuationContext, _InliningMode)); + _GetImpl(), _ContinuationTask._GetImpl(), std::forward<_Function>(_Func), _ContinuationContext, _InliningMode)); return _ContinuationTask; } @@ -4371,10 +4411,10 @@ class task /**/ template __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result - auto then(const _Function& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType + auto then(_Function&& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType { details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK()); - return _M_unitTask._ThenImpl(_Func, _TaskOptions); + return _M_unitTask._ThenImpl(std::forward<_Function>(_Func), _TaskOptions); } /// @@ -4407,11 +4447,11 @@ class task /**/ template __declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result - auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType + auto then(_Function&& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType { task_options _TaskOptions(_CancellationToken, _ContinuationContext); details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK()); - return _M_unitTask._ThenImpl(_Func, _TaskOptions); + return _M_unitTask._ThenImpl(std::forward<_Function>(_Func), _TaskOptions); } /// @@ -4555,13 +4595,13 @@ class task /// An internal version of then that takes additional flags and executes the continuation inline. Used for runtime internal continuations only. /// template - auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState, + auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState, details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType { // inherit from antecedent auto _Scheduler = _GetImpl()->_GetScheduler(); - return _M_unitTask._ThenImpl(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode); + return _M_unitTask._ThenImpl(std::forward<_Function>(_Func), _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode); } private: diff --git a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp index e0d3596e18..a6ea601ed7 100644 --- a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp +++ b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp @@ -304,6 +304,21 @@ TEST(TestTasks_void_tasks_default_construction) } } +TEST(TestTasks_movable_then) +{ + struct A + { + A() = default; + A(A&&) = default; + A& operator=(A&&) = default; + } a; + + task task = create_task([]{ return 2; }); + auto f = task.then([a = std::move(a)](int) { return 'c'; }); + + IsTrue(f.get() == 'c', L".then should be able to work with movable functors"); +} + TEST(TestTasks_constant_this) { #ifdef _MSC_VER From 95478a4c83a6b02456deede288c2496f813e7d9d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Jan 2016 14:58:42 -0800 Subject: [PATCH 034/609] Address warnings in Ubuntu 15.10 --- Release/CMakeLists.txt | 10 +++++++++- Release/src/http/client/http_client_asio.cpp | 4 ++-- Release/src/websockets/client/ws_client_wspp.cpp | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 24e93de5c0..d99fa5c877 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -189,7 +189,15 @@ else() endif() set(Casablanca_LIBRARY ${LIB}cpprest) -set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} ${Boost_LIBRARIES} ${Boost_FRAMEWORK}) +set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_ATOMIC_LIBRARY} + ${Boost_CHRONO_LIBRARY} + ${Boost_RANDOM_LIBRARY} + ${Boost_REGEX_LIBRARY} + ${Boost_FRAMEWORK}) # Everything in the project needs access to the casablanca include directories include_directories(${Casablanca_INCLUDE_DIRS}) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index ead627be92..2e2ac61554 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -76,10 +76,10 @@ class asio_connection public: asio_connection(boost::asio::io_service& io_service, bool start_with_ssl, const std::function& ssl_context_callback) : m_socket(io_service), + m_ssl_context_callback(ssl_context_callback), m_pool_timer(io_service), m_is_reused(false), - m_keep_alive(true), - m_ssl_context_callback(ssl_context_callback) + m_keep_alive(true) { if (start_with_ssl) { diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index bd17af922e..e8f5d2edbe 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -35,6 +35,7 @@ #pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wignored-qualifiers" +#pragma GCC diagnostic ignored "-Wcast-qual" #include #include #include @@ -774,4 +775,4 @@ websocket_callback_client::websocket_callback_client(websocket_client_config con }}} -#endif \ No newline at end of file +#endif From f8a0225863fe2c36bbaab7b8a7e8702a4224be19 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Jan 2016 14:58:42 -0800 Subject: [PATCH 035/609] Disable http_proxy_with_credentials test on non-windows. TODO: reenable --- Release/tests/functional/http/client/proxy_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/client/proxy_tests.cpp b/Release/tests/functional/http/client/proxy_tests.cpp index 115d39f5e3..d309c957e2 100644 --- a/Release/tests/functional/http/client/proxy_tests.cpp +++ b/Release/tests/functional/http/client/proxy_tests.cpp @@ -90,7 +90,7 @@ TEST_FIXTURE(uri_address, no_proxy_options_on_winrt) #ifndef __cplusplus_winrt // Can't specify a proxy with WinRT implementation. -TEST_FIXTURE(uri_address, http_proxy_with_credentials) + TEST_FIXTURE(uri_address, http_proxy_with_credentials, "Ignore:Linux", "Github 53", "Ignore:Apple", "Github 53", "Ignore:Android", "Github 53", "Ignore:IOS", "Github 53") { uri u(U("http://netproxy.redmond.corp.microsoft.com")); @@ -169,4 +169,4 @@ TEST_FIXTURE(uri_address, https_proxy, "Ignore", "Manual") } // SUITE(proxy_tests) -}}}} \ No newline at end of file +}}}} From 2321e84906414aaf92830645113a1fd644e71659 Mon Sep 17 00:00:00 2001 From: Thomas Schaub Date: Thu, 14 Jan 2016 12:28:35 +0100 Subject: [PATCH 036/609] Add test to expose http_client_asio bug --- .../http/client/connections_and_errors.cpp | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Release/tests/functional/http/client/connections_and_errors.cpp b/Release/tests/functional/http/client/connections_and_errors.cpp index bd57390f3a..813cb5e8ff 100644 --- a/Release/tests/functional/http/client/connections_and_errors.cpp +++ b/Release/tests/functional/http/client/connections_and_errors.cpp @@ -27,6 +27,9 @@ #include "cpprest/http_listener.h" #endif +#include +#include + using namespace web; using namespace utility; using namespace concurrency; @@ -400,6 +403,36 @@ TEST_FIXTURE(uri_address, cancel_while_downloading_data) } #endif +// Try to connect to a server on a closed port and cancel the operation. +TEST_FIXTURE(uri_address, cancel_bad_port) +{ + // http_client_asio has a bug where, when canceled, it will cancel only the + // current connection but then go and try the next address from the list of + // resolved addresses, i.e., it won't actually cancel as long as there are + // more addresses to try. Consequently, it will not report the task as being + // canceled. This is easiest to observe when trying to connect to a server + // that does not respond on a certain port, otherwise the timing might be + // tricky. + + // We need to connect to a URI for which there are multiple addresses + // associated (i.e., multiple A records). + web::http::uri uri(U("https://microsoft.com:442/")); + + // Send request. + http_client c(uri); + web::http::http_request r; + auto cts = pplx::cancellation_token_source(); + auto ct = cts.get_token(); + auto t = c.request(r, ct); + + // Make sure that the client already finished resolving before canceling, + // otherwise the bug might not be triggered. + std::this_thread::sleep_for(std::chrono::seconds(1)); + cts.cancel(); + + VERIFY_THROWS_HTTP_ERROR_CODE(t.get(), std::errc::operation_canceled); +} + } // SUITE(connections_and_errors) }}}} From 124609d0bf5325ca17fa0dd064102cf2e0fd9d52 Mon Sep 17 00:00:00 2001 From: Thomas Schaub Date: Thu, 14 Jan 2016 12:37:21 +0100 Subject: [PATCH 037/609] Fix http_client_asio cancel bug --- Release/src/http/client/http_client_asio.cpp | 4 ++++ .../http/client/connections_and_errors.cpp | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index ead627be92..54d27dadc2 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -792,6 +792,10 @@ class asio_context : public request_context, public std::enable_shared_from_this { write_request(); } + else if (ec.value() == boost::system::errc::operation_canceled) + { + request_context::report_error(ec.value(), "Request canceled by user."); + } else if (endpoints == tcp::resolver::iterator()) { report_error("Failed to connect to any resolved endpoint", ec, httpclient_errorcode_context::connect); diff --git a/Release/tests/functional/http/client/connections_and_errors.cpp b/Release/tests/functional/http/client/connections_and_errors.cpp index 813cb5e8ff..99a689ea20 100644 --- a/Release/tests/functional/http/client/connections_and_errors.cpp +++ b/Release/tests/functional/http/client/connections_and_errors.cpp @@ -406,13 +406,13 @@ TEST_FIXTURE(uri_address, cancel_while_downloading_data) // Try to connect to a server on a closed port and cancel the operation. TEST_FIXTURE(uri_address, cancel_bad_port) { - // http_client_asio has a bug where, when canceled, it will cancel only the + // http_client_asio had a bug where, when canceled, it would cancel only the // current connection but then go and try the next address from the list of - // resolved addresses, i.e., it won't actually cancel as long as there are - // more addresses to try. Consequently, it will not report the task as being - // canceled. This is easiest to observe when trying to connect to a server - // that does not respond on a certain port, otherwise the timing might be - // tricky. + // resolved addresses, i.e., it wouldn't actually cancel as long as there + // are more addresses to try. Consequently, it would not report the task as + // being canceled. This was easiest to observe when trying to connect to a + // server that does not respond on a certain port, otherwise the timing + // might be tricky. // We need to connect to a URI for which there are multiple addresses // associated (i.e., multiple A records). From 42881d22d562920c7b86a0c5334435f7467f8a9b Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Tue, 19 Jan 2016 14:08:11 -0800 Subject: [PATCH 038/609] The change in flatten_http_headers to omit adding Host header wasbreaking windows clients. Instead, skip adding the host header when user has already specified one in the boost asio based clients without modifying flatten_http_headers. --- Release/include/cpprest/details/http_client_impl.h | 4 ---- Release/src/http/client/http_client_asio.cpp | 10 ++++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Release/include/cpprest/details/http_client_impl.h b/Release/include/cpprest/details/http_client_impl.h index bb351526a1..2f88472a50 100644 --- a/Release/include/cpprest/details/http_client_impl.h +++ b/Release/include/cpprest/details/http_client_impl.h @@ -57,10 +57,6 @@ static utility::string_t flatten_http_headers(const http_headers &headers) utility::string_t flattened_headers; for(auto iter = headers.begin(); iter != headers.end(); ++iter) { - utility::string_t header_name = iter->first; - if (utility::details::str_icmp(header_name, header_names::host)) { - continue; - } flattened_headers.append(iter->first); flattened_headers.push_back(':'); flattened_headers.append(iter->second); diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 694e961976..02c5ea1f8d 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -395,7 +395,6 @@ class asio_context : public request_context, public std::enable_shared_from_this request_stream.imbue(std::locale::classic()); request_stream << method << " " << encoded_resource << " " << "HTTP/1.1" << CRLF; - request_stream << "Host: "; int port = base_uri.port(); if (base_uri.is_port_default()) @@ -403,11 +402,10 @@ class asio_context : public request_context, public std::enable_shared_from_this port = (m_connection->is_ssl() ? 443 : 80); } - std::string specified_host_header; - if (m_request.headers().match(header_names::host, specified_host_header)) { - request_stream << specified_host_header << CRLF; - } else { - request_stream << host << ":" << port << CRLF; + // Add the Host header if user has not specified it explicitly + if (!m_request.headers().has(header_names::host)) + { + request_stream << "Host: " << host << ":" << port << CRLF; } // Extra request headers are constructed here. From 545c25d578f93b04fcf1ef6c7139128de8243490 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Tue, 19 Jan 2016 14:31:29 -0800 Subject: [PATCH 039/609] Fix build break in http_client_asio.cpp after the merge. --- Release/src/http/client/http_client_asio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 31315dcf0f..44296040e0 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -617,7 +617,7 @@ class asio_context : public request_context, public std::enable_shared_from_this } // Add the Host header if user has not specified it explicitly - if (!m_request.headers().has(header_names::host)) + if (!ctx->m_request.headers().has(header_names::host)) { request_stream << "Host: " << host << ":" << port << CRLF; } From de8671baa2de647071a9085faf7d65447eb5e86f Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Tue, 19 Jan 2016 14:46:25 -0800 Subject: [PATCH 040/609] testcase overwrite_http_header fails on winrt. It is by design. --- Release/tests/functional/http/client/header_tests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Release/tests/functional/http/client/header_tests.cpp b/Release/tests/functional/http/client/header_tests.cpp index 87e07941cb..e0223784f2 100644 --- a/Release/tests/functional/http/client/header_tests.cpp +++ b/Release/tests/functional/http/client/header_tests.cpp @@ -402,6 +402,7 @@ TEST_FIXTURE(uri_address, overwrite_http_header) client.request(default_host_headers_request).get(); +#ifndef __cplusplus_winrt // Test case where we overwrite the host header http_request overwritten_host_headers_request(methods::GET); overwritten_host_headers_request.headers().add(U("Host"), host); @@ -412,6 +413,7 @@ TEST_FIXTURE(uri_address, overwrite_http_header) p_request->reply(200); }); client.request(overwritten_host_headers_request).get(); +#endif } } // SUITE(header_tests) From 9e5c60a2c4ed542a42d5be427a580858016e1fe0 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 1 Feb 2016 18:16:57 -0800 Subject: [PATCH 041/609] Undefine the max macro --- .../functional/streams/istream_tests.cpp | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Release/tests/functional/streams/istream_tests.cpp b/Release/tests/functional/streams/istream_tests.cpp index 69548d1881..5d8508b8f3 100644 --- a/Release/tests/functional/streams/istream_tests.cpp +++ b/Release/tests/functional/streams/istream_tests.cpp @@ -25,6 +25,10 @@ #include +#ifdef max +#undef max +#endif + #if defined(__cplusplus_winrt) using namespace Windows::Storage; #endif @@ -90,7 +94,7 @@ void fill_file_w(const utility::string_t &name, size_t repetitions = 1) for (size_t i = 0; i < repetitions; i++) for (wchar_t ch = L'a'; ch <= L'z'; ++ch) fwrite(&ch, sizeof(wchar_t), 1, stream); - + fclose(stream); } #pragma warning (pop) @@ -372,7 +376,7 @@ TEST(stream_read_5) VERIFY_ARE_EQUAL(len, rbuf.putn_nocopy(text, len).get()); istream stream(rbuf); - + VERIFY_IS_FALSE(stream.is_eof()); VERIFY_ARE_EQUAL(26u, stream.read_to_delim(trg, '\n').get()); VERIFY_IS_FALSE(stream.is_eof()); @@ -725,7 +729,7 @@ TEST(fstream_read_to_end_3) pplx::details::do_while([=]()-> pplx::task { return stream.read().then(lambda1); }).wait(); - + auto& target = sbuf.collection(); VERIFY_ARE_EQUAL(26, target.size()); VERIFY_IS_TRUE(stream.is_eof()); @@ -1174,7 +1178,7 @@ TEST(istream_extract_bool_from_number) { producer_consumer_buffer rbuf; const char *text = " 1 0 NOT_OK"; - + size_t len = strlen(text); rbuf.putn_nocopy(text, len).wait(); rbuf.close(std::ios_base::out).get(); @@ -1212,7 +1216,7 @@ TEST(istream_extract_bool_from_number_w) { producer_consumer_buffer rbuf; const wchar_t *text = L" 1 0 NOT_OK"; - + size_t len = wcslen(text); rbuf.putn_nocopy(text, len).wait(); rbuf.close(std::ios_base::out).get(); @@ -1343,10 +1347,10 @@ TEST(extract_floating_point) { double expected = 0; std_istream >> expected; - + const auto actual = istream_double.extract().get(); compare_double(expected, actual); - + if (actual <= std::numeric_limits::max()) compare_float(float(expected), istream_float.extract().get()); else @@ -1360,7 +1364,7 @@ TEST(extract_floating_point) TEST(extract_floating_point_with_exceptions) { - std::vector> tests; + std::vector> tests; tests.push_back(std::pair("a", "Invalid character 'a'")); tests.push_back(std::pair("x", "Invalid character 'x'")); tests.push_back(std::pair("e", "Invalid character 'e'")); @@ -1412,7 +1416,7 @@ TEST(extract_floating_point_with_exceptions) TEST(streambuf_read_delim) { producer_consumer_buffer rbuf; - std::string s("Hello World"); // there are 2 spaces here + std::string s("Hello World"); // there are 2 spaces here streams::stringstreambuf data; @@ -1423,7 +1427,7 @@ TEST(streambuf_read_delim) std::string r("Hello"); VERIFY_ARE_EQUAL(size, r.size()); VERIFY_IS_FALSE(is.is_eof()); - + auto& s2 = data.collection(); VERIFY_ARE_EQUAL(s2, r); return is.read_to_delim(data, ' '); @@ -1465,7 +1469,7 @@ TEST(uninitialized_streambuf) // All operations should throw uint8_t * ptr = nullptr; size_t count = 0; - + VERIFY_THROWS(strbuf.acquire(ptr, count), std::invalid_argument); VERIFY_THROWS(strbuf.release(ptr, count), std::invalid_argument); From 8b6f83250dfd6ddfe3ae548c01fdd0be7ab25963 Mon Sep 17 00:00:00 2001 From: Sergei Nikulov Date: Tue, 2 Feb 2016 12:41:20 +0300 Subject: [PATCH 042/609] fix for build on Linux --- Release/CMakeLists.txt | 13 ++++--------- Release/src/CMakeLists.txt | 6 +++++- Release/tests/common/TestRunner/CMakeLists.txt | 12 +++--------- .../tests/functional/http/client/proxy_tests.cpp | 8 ++++---- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index d99fa5c877..e229106951 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -7,6 +7,8 @@ enable_testing() set(WARNINGS) set(ANDROID_STL_FLAGS) +option(WERROR "Threat Warnings as Errors" ON) + # Platform (not compiler) specific settings if(IOS) set(IOS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Build_iOS") @@ -73,7 +75,7 @@ elseif(ANDROID) set(BUILD_SAMPLES OFF) option(BUILD_TESTS "Build tests." ON) elseif(UNIX) # This includes OSX - find_package(Boost REQUIRED COMPONENTS random chrono system thread regex filesystem) + find_package(Boost 1.54 REQUIRED COMPONENTS random chrono system thread regex filesystem) find_package(Threads REQUIRED) if(APPLE AND NOT OPENSSL_ROOT_DIR) # Prefer a homebrew version of OpenSSL over the one in /usr/lib @@ -190,14 +192,7 @@ endif() set(Casablanca_LIBRARY ${LIB}cpprest) set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} - ${Boost_SYSTEM_LIBRARY} - ${Boost_THREAD_LIBRARY} - ${Boost_ATOMIC_LIBRARY} - ${Boost_CHRONO_LIBRARY} - ${Boost_RANDOM_LIBRARY} - ${Boost_REGEX_LIBRARY} - ${Boost_FRAMEWORK}) + ${Boost_LIBRARIES}) # Everything in the project needs access to the casablanca include directories include_directories(${Casablanca_INCLUDE_DIRS}) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 5aef95cf76..f247806adf 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -53,7 +53,11 @@ if(UNIX) else() list(APPEND SOURCES pplx/pplxlinux.cpp) endif() - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + + if(WERROR) + set(WARNINGS "${WARNINGS} -Werror") + endif() + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -pedantic") elseif(WIN32) set(SOURCES ${SOURCES_COMMON} diff --git a/Release/tests/common/TestRunner/CMakeLists.txt b/Release/tests/common/TestRunner/CMakeLists.txt index 57e63348b9..19bd2162aa 100644 --- a/Release/tests/common/TestRunner/CMakeLists.txt +++ b/Release/tests/common/TestRunner/CMakeLists.txt @@ -17,9 +17,7 @@ if(NOT IOS AND NOT ANDROID) ) target_link_libraries(test_runner - ${Boost_FRAMEWORK} - ${Boost_SYSTEM_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} + ${Boost_LIBRARIES} ${LIB}unittestpp ${CMAKE_DL_LIBS} ) @@ -31,9 +29,7 @@ if(NOT IOS AND NOT ANDROID) ) target_link_libraries(test_runner - ${Boost_FRAMEWORK} - ${Boost_SYSTEM_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} + ${Boost_LIBRARIES} ${LIB}unittestpp ${CMAKE_DL_LIBS} -Wl,-force_load @@ -64,9 +60,7 @@ if(NOT IOS AND NOT ANDROID) ) target_link_libraries(test_runner - ${Boost_FRAMEWORK} - ${Boost_SYSTEM_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} + ${Boost_LIBRARIES} ${LIB}unittestpp ${CMAKE_DL_LIBS} -Wl,--whole-archive diff --git a/Release/tests/functional/http/client/proxy_tests.cpp b/Release/tests/functional/http/client/proxy_tests.cpp index d309c957e2..895d7c9518 100644 --- a/Release/tests/functional/http/client/proxy_tests.cpp +++ b/Release/tests/functional/http/client/proxy_tests.cpp @@ -46,7 +46,7 @@ TEST_FIXTURE(uri_address, auto_discovery_proxy) p_request->reply(200); }); http_client_config config; - + config.set_proxy(web_proxy::use_auto_discovery); VERIFY_IS_FALSE(config.proxy().is_disabled()); VERIFY_IS_FALSE(config.proxy().is_specified()); @@ -63,7 +63,7 @@ TEST_FIXTURE(uri_address, disabled_proxy) http_asserts::assert_test_request_equals(p_request, methods::PUT, U("/"), U("text/plain"), U("sample data")); p_request->reply(status_codes::OK); }); - + http_client_config config; config.set_proxy(web_proxy(web_proxy::disabled)); VERIFY_IS_TRUE(config.proxy().is_disabled()); @@ -97,13 +97,13 @@ TEST_FIXTURE(uri_address, no_proxy_options_on_winrt) web_proxy proxy(u); VERIFY_IS_TRUE(proxy.is_specified()); VERIFY_ARE_EQUAL(u, proxy.address()); - credentials cred(U("artur"), U("fred")); // relax, this is not my real password + web::credentials cred(U("artur"), U("fred")); // relax, this is not my real password proxy.set_credentials(cred); http_client_config config; config.set_proxy(proxy); - // Access to this server will succeed because the first request will not be challenged and hence + // Access to this server will succeed because the first request will not be challenged and hence // my bogus credentials will not be supplied. http_client client(U("http://www.microsoft.com"), config); From 1b190fcdaff2a5db1e854322e2b905603709bc64 Mon Sep 17 00:00:00 2001 From: Michael Yang Date: Wed, 3 Feb 2016 08:39:59 +0800 Subject: [PATCH 043/609] Add proxy support for oauth1_config class --- Release/include/cpprest/oauth1.h | 21 +++++++++++++++++++++ Release/src/http/oauth/oauth1.cpp | 9 ++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) mode change 100644 => 100755 Release/include/cpprest/oauth1.h mode change 100644 => 100755 Release/src/http/oauth/oauth1.cpp diff --git a/Release/include/cpprest/oauth1.h b/Release/include/cpprest/oauth1.h old mode 100644 new mode 100755 index 1bf1f7fe7c..f464da0f06 --- a/Release/include/cpprest/oauth1.h +++ b/Release/include/cpprest/oauth1.h @@ -28,6 +28,7 @@ #define _CASA_OAUTH1_H #include "cpprest/http_msg.h" +#include "cpprest/details/web_utilities.h" namespace web { @@ -479,6 +480,24 @@ class oauth1_config /// void clear_parameters() { m_parameters_to_sign.clear(); } + /// + /// Get the web proxy object + /// + /// A reference to the web proxy object. + const web_proxy& proxy() const + { + return m_proxy; + } + + /// + /// Set the web proxy object that will be used by token_from_code and token_from_refresh + /// + /// A reference to the web proxy object. + void set_proxy(const web_proxy& proxy) + { + m_proxy = proxy; + } + private: friend class web::http::client::http_client_config; friend class web::http::oauth1::details::oauth1_handler; @@ -532,6 +551,8 @@ class oauth1_config std::map m_parameters_to_sign; + web::web_proxy m_proxy; + utility::nonce_generator m_nonce_generator; bool m_is_authorization_completed; }; diff --git a/Release/src/http/oauth/oauth1.cpp b/Release/src/http/oauth/oauth1.cpp old mode 100644 new mode 100755 index 23af2d9952..176d27666e --- a/Release/src/http/oauth/oauth1.cpp +++ b/Release/src/http/oauth/oauth1.cpp @@ -29,6 +29,7 @@ using namespace utility; using web::http::client::http_client; +using web::http::client::http_client_config; using web::http::oauth1::details::oauth1_state; using web::http::oauth1::details::oauth1_strings; @@ -281,7 +282,13 @@ pplx::task oauth1_config::_request_token(oauth1_state state, bool is_temp_ req._set_base_uri(endpoint); _authenticate_request(req, std::move(state)); - http_client client(endpoint); + + // configure proxy + http_client_config config; + config.set_proxy(m_proxy); + + http_client client(endpoint, config); + return client.request(req) .then([](http_response resp) { From fc16fcd559ae455629a0ca12ace62eb8556420cc Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 2 Feb 2016 18:03:27 -0800 Subject: [PATCH 044/609] Suppress warning C4592 in websocket++ --- .../websocketpp/websocketpp/connection.hpp | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/Release/libs/websocketpp/websocketpp/connection.hpp b/Release/libs/websocketpp/websocketpp/connection.hpp index 954683279d..45fa6f92b1 100644 --- a/Release/libs/websocketpp/websocketpp/connection.hpp +++ b/Release/libs/websocketpp/websocketpp/connection.hpp @@ -161,7 +161,10 @@ typedef lib::function write_frame_handler; * @todo Move this to configs to allow compile/runtime disabling or enabling * of protocol versions */ +#pragma warning(push) +#pragma warning(disable : 4592) static std::vector const versions_supported = {0,7,8,13}; +#pragma warning(pop) #else /// Helper array to get around lack of initializer lists pre C++11 static int const helper[] = {0,7,8,13}; @@ -534,7 +537,7 @@ class connection /// Get maximum message size /** - * Get maximum message size. Maximum message size determines the point at + * Get maximum message size. Maximum message size determines the point at * which the connection will fail with the message_too_big protocol error. * * The default is set by the endpoint that creates the connection. @@ -544,11 +547,11 @@ class connection size_t get_max_message_size() const { return m_max_message_size; } - + /// Set maximum message size /** - * Set maximum message size. Maximum message size determines the point at - * which the connection will fail with the message_too_big protocol error. + * Set maximum message size. Maximum message size determines the point at + * which the connection will fail with the message_too_big protocol error. * This value may be changed during the connection. * * The default is set by the endpoint that creates the connection. @@ -563,7 +566,7 @@ class connection m_processor->set_max_message_size(new_value); } } - + /// Get maximum HTTP message body size /** * Get maximum HTTP message body size. Maximum message body size determines @@ -579,7 +582,7 @@ class connection size_t get_max_http_body_size() const { return m_request.get_max_body_size(); } - + /// Set maximum HTTP message body size /** * Set maximum HTTP message body size. Maximum message body size determines @@ -683,14 +686,14 @@ class connection * @return An error code */ lib::error_code interrupt(); - + /// Transport inturrupt callback void handle_interrupt(); - + /// Pause reading of new data /** - * Signals to the connection to halt reading of new data. While reading is paused, - * the connection will stop reading from its associated socket. In turn this will + * Signals to the connection to halt reading of new data. While reading is paused, + * the connection will stop reading from its associated socket. In turn this will * result in TCP based flow control kicking in and slowing data flow from the remote * endpoint. * @@ -702,7 +705,7 @@ class connection * * If supported by the transport this is done asynchronously. As such reading may not * stop until the current read operation completes. Typically you can expect to - * receive no more bytes after initiating a read pause than the size of the read + * receive no more bytes after initiating a read pause than the size of the read * buffer. * * If reading is paused for this connection already nothing is changed. @@ -1357,7 +1360,7 @@ class connection * Includes: error code and message for why it was failed */ void log_fail_result(); - + /// Prints information about HTTP connections /** * Includes: TODO @@ -1506,7 +1509,7 @@ class connection /// Detailed internal error code lib::error_code m_ec; - + /// A flag that gets set once it is determined that the connection is an /// HTTP connection and not a WebSocket one. bool m_is_http; From d71191ec8db6a239cd3188472ac200b7cf52c810 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 2 Feb 2016 19:29:05 -0800 Subject: [PATCH 045/609] Fix unknown pragma warning for non-MSVC compilers --- Release/libs/websocketpp/websocketpp/connection.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Release/libs/websocketpp/websocketpp/connection.hpp b/Release/libs/websocketpp/websocketpp/connection.hpp index 45fa6f92b1..8fd1ae1e2f 100644 --- a/Release/libs/websocketpp/websocketpp/connection.hpp +++ b/Release/libs/websocketpp/websocketpp/connection.hpp @@ -161,10 +161,12 @@ typedef lib::function write_frame_handler; * @todo Move this to configs to allow compile/runtime disabling or enabling * of protocol versions */ +#if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4592) static std::vector const versions_supported = {0,7,8,13}; #pragma warning(pop) +#endif #else /// Helper array to get around lack of initializer lists pre C++11 static int const helper[] = {0,7,8,13}; From 8e3e0410f60cfe51077aa6fcaa5b66b5c88b0a88 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 3 Feb 2016 14:08:04 -0800 Subject: [PATCH 046/609] Fixup previous fix, the definition of versions_supported needs to exist on non-windows. --- Release/libs/websocketpp/websocketpp/connection.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Release/libs/websocketpp/websocketpp/connection.hpp b/Release/libs/websocketpp/websocketpp/connection.hpp index 8fd1ae1e2f..e28536a6f9 100644 --- a/Release/libs/websocketpp/websocketpp/connection.hpp +++ b/Release/libs/websocketpp/websocketpp/connection.hpp @@ -164,7 +164,9 @@ typedef lib::function write_frame_handler; #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4592) +#endif static std::vector const versions_supported = {0,7,8,13}; +#if defined(_MSC_VER) #pragma warning(pop) #endif #else From 2b62c4b651f628a335a7df4bfbe64c66cb64614e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 3 Feb 2016 15:49:44 -0800 Subject: [PATCH 047/609] Removed wod projects from the main build. They can still be built using msbuild directly on the project files. --- Release/src/dirs.proj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Release/src/dirs.proj b/Release/src/dirs.proj index adee7dd7d3..d94b26bb6b 100644 --- a/Release/src/dirs.proj +++ b/Release/src/dirs.proj @@ -5,7 +5,6 @@ - @@ -19,10 +18,9 @@ - - + From 01e3effe38903723e00423a02e6e3d2de4dcb43e Mon Sep 17 00:00:00 2001 From: Leigh Smith Date: Mon, 8 Feb 2016 22:10:31 -0500 Subject: [PATCH 048/609] Added prefix to credentials to avoid compilation errors on Linux confusing with krb5.h struct credentials declaration --- Release/tests/functional/http/client/proxy_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/tests/functional/http/client/proxy_tests.cpp b/Release/tests/functional/http/client/proxy_tests.cpp index d309c957e2..2d7ca22b27 100644 --- a/Release/tests/functional/http/client/proxy_tests.cpp +++ b/Release/tests/functional/http/client/proxy_tests.cpp @@ -97,7 +97,7 @@ TEST_FIXTURE(uri_address, no_proxy_options_on_winrt) web_proxy proxy(u); VERIFY_IS_TRUE(proxy.is_specified()); VERIFY_ARE_EQUAL(u, proxy.address()); - credentials cred(U("artur"), U("fred")); // relax, this is not my real password + web::credentials cred(U("artur"), U("fred")); // relax, this is not my real password proxy.set_credentials(cred); http_client_config config; From 58c1a645f0033324627528adfe17824a6a661e3a Mon Sep 17 00:00:00 2001 From: Justin Marshall Date: Tue, 9 Feb 2016 17:21:50 +0100 Subject: [PATCH 049/609] Add a project for compiling as a static lib --- .../vs14.static/casablanca140.static.vcxproj | 84 +++++++++++++++++++ Release/src/build/vs14.static/packages.config | 11 +++ cpprestsdk140.sln | 23 ++++- 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Release/src/build/vs14.static/casablanca140.static.vcxproj create mode 100644 Release/src/build/vs14.static/packages.config diff --git a/Release/src/build/vs14.static/casablanca140.static.vcxproj b/Release/src/build/vs14.static/casablanca140.static.vcxproj new file mode 100644 index 0000000000..5795f27671 --- /dev/null +++ b/Release/src/build/vs14.static/casablanca140.static.vcxproj @@ -0,0 +1,84 @@ + + + + + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A} + Win32Proj + SAK + SAK + SAK + SAK + StaticLibrary + v140 + false + false + cpprestsdk140.static + 8.1 + + + + + + + + + + + + + + + + + + + d + + + $(CppRestBaseFileName)140$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) + + + + Designer + + + + + _NO_ASYNCRTIMP;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + Use + stdafx.h + -Zm300 /bigobj %(AdditionalOptions) + MultiThreadedDebugDLL + MultiThreadedDLL + true + + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + false + false + false + false + false + false + + + Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) + UseLinkTimeCodeGeneration + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Release/src/build/vs14.static/packages.config b/Release/src/build/vs14.static/packages.config new file mode 100644 index 0000000000..21a51fdf83 --- /dev/null +++ b/Release/src/build/vs14.static/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln index 1041525211..e575ad5e71 100644 --- a/cpprestsdk140.sln +++ b/cpprestsdk140.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23207.2 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14\casablanca140.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" EndProject @@ -49,6 +49,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp", "Releas EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRunner.android.NativeActivity", "Release\tests\common\TestRunner\vs14.android\TestRunner.android.NativeActivity\TestRunner.android.NativeActivity.vcxproj", "{D1060D0A-A10E-444D-9F6B-9676EA453F9A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14.static\casablanca140.static.vcxproj", "{79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Release\src\build\win32.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 @@ -61,6 +63,8 @@ Global Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 @@ -220,6 +224,22 @@ Global {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x64.ActiveCfg = Release|x86 {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.ActiveCfg = Release|x86 {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.Build.0 = Release|x86 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.ActiveCfg = Debug|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.Build.0 = Debug|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|Win32.ActiveCfg = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|Win32.Build.0 = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x64.ActiveCfg = Debug|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x64.Build.0 = Debug|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x86.ActiveCfg = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x86.Build.0 = Debug|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|ARM.ActiveCfg = Release|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|ARM.Build.0 = Release|ARM + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|Win32.ActiveCfg = Release|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|Win32.Build.0 = Release|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x64.ActiveCfg = Release|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x64.Build.0 = Release|x64 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x86.ActiveCfg = Release|Win32 + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -245,5 +265,6 @@ Global {AFB49019-965B-4C10-BAFF-C86C16D58010} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {3A584D9C-1A98-4046-B7D3-B7171EF42D34} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} EndGlobalSection EndGlobal From a075fb2b203485baea48433587df0ec9628e3951 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 11 Feb 2016 02:30:11 -0800 Subject: [PATCH 050/609] Fix for 'fatal error C1041: cannot open program database' which should enable multicore MSBuild --- Build/Common.Build.settings | 1 + Build/Release.Product.settings | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Build/Common.Build.settings b/Build/Common.Build.settings index 30147c9f87..16ba09aa54 100644 --- a/Build/Common.Build.settings +++ b/Build/Common.Build.settings @@ -36,6 +36,7 @@ $(BuildRoot)\Binaries\$(Platform)\$(Configuration)\ $(OutputPath) + $(BuildRoot)\Intermediate\$(MSBuildProjectName)\$(Platform)\$(Configuration)\ $(BuildRoot)\Release\Tests $(BuildRoot)\Release\src $(BuildRoot)\Release\Resource diff --git a/Build/Release.Product.settings b/Build/Release.Product.settings index b4bc14c8a2..30d0bc9a4f 100644 --- a/Build/Release.Product.settings +++ b/Build/Release.Product.settings @@ -32,7 +32,6 @@ $(CasablancaIncludeDir) - $(BuildRoot)\Intermediate\$(MSBuildProjectName)\$(Platform)\$(Configuration)\ From 115f7aebbf8b17ff3426d9b0ea1b34a261f6dae9 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 11 Feb 2016 02:30:44 -0800 Subject: [PATCH 051/609] Fix for [aapt] warning : AndroidManifest.xml already defines debuggable --- .../TestRunner.android.Packaging/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml index eebac18117..711b77cda6 100644 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml +++ b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml @@ -11,7 +11,7 @@ - + From 46baef93fdc88d18e5c220a7d405bb36030248f0 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 11 Feb 2016 02:31:16 -0800 Subject: [PATCH 052/609] Remove TestUnitTestpp from default build --- Release/tests/common/UnitTestpp/dirs.proj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/common/UnitTestpp/dirs.proj b/Release/tests/common/UnitTestpp/dirs.proj index d4f28240a6..20495a4cf3 100644 --- a/Release/tests/common/UnitTestpp/dirs.proj +++ b/Release/tests/common/UnitTestpp/dirs.proj @@ -4,7 +4,7 @@ - + @@ -14,7 +14,7 @@ - + From 41e3ff890783ac241a86d13d35334be9e2b44129 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 11 Feb 2016 18:01:39 -0800 Subject: [PATCH 053/609] Enable common test settings for AuthListener120.csproj --- .../http/client/AuthListener/vs12/AuthListener120.csproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj b/Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj index 2035f91aca..e34311d956 100644 --- a/Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj +++ b/Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj @@ -1,6 +1,8 @@  + + Debug AnyCPU @@ -17,7 +19,7 @@ true full false - bin\Debug\ + DEBUG;TRACE prompt 4 @@ -26,7 +28,7 @@ AnyCPU pdbonly true - bin\Release\ + TRACE prompt 4 From d7c92210463045f5731459f4d0bb050fea44293e Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 12 Feb 2016 13:07:16 -0800 Subject: [PATCH 054/609] Fix packages.config for android --- .../websockets/utilities/vs14.android/packages.config | 5 +++++ .../websockets_test_utilities140.android.vcxproj | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 Release/tests/functional/websockets/utilities/vs14.android/packages.config diff --git a/Release/tests/functional/websockets/utilities/vs14.android/packages.config b/Release/tests/functional/websockets/utilities/vs14.android/packages.config new file mode 100644 index 0000000000..299115366f --- /dev/null +++ b/Release/tests/functional/websockets/utilities/vs14.android/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj index a45f20f492..c04a6bbe46 100644 --- a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj +++ b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj @@ -33,7 +33,7 @@ - + From de610baae395de56979d77b86d76ce6231179577 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Fri, 12 Feb 2016 13:19:38 -0800 Subject: [PATCH 055/609] Remove unused packages.config --- Release/src/build/vs12.winrt/packages.config | 3 --- Release/src/build/vs12.wp81/packages.config | 3 --- Release/src/build/vs12.wps81/packages.config | 3 --- 3 files changed, 9 deletions(-) delete mode 100644 Release/src/build/vs12.winrt/packages.config delete mode 100644 Release/src/build/vs12.wp81/packages.config delete mode 100644 Release/src/build/vs12.wps81/packages.config diff --git a/Release/src/build/vs12.winrt/packages.config b/Release/src/build/vs12.winrt/packages.config deleted file mode 100644 index 6b8deb9c96..0000000000 --- a/Release/src/build/vs12.winrt/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/Release/src/build/vs12.wp81/packages.config b/Release/src/build/vs12.wp81/packages.config deleted file mode 100644 index 6b8deb9c96..0000000000 --- a/Release/src/build/vs12.wp81/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/Release/src/build/vs12.wps81/packages.config b/Release/src/build/vs12.wps81/packages.config deleted file mode 100644 index 6b8deb9c96..0000000000 --- a/Release/src/build/vs12.wps81/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file From c9ca1743ba1646934298510ddec0cf1ab1aa06b1 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Mon, 22 Feb 2016 15:47:07 -0800 Subject: [PATCH 056/609] Bump version number for 2.8 release --- Build/version.props | 2 +- Release/include/cpprest/version.h | 2 +- Release/src/CMakeLists.txt | 2 +- Release/src/build/init.ps1 | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Build/version.props b/Build/version.props index ffc7238858..c74165e925 100644 --- a/Build/version.props +++ b/Build/version.props @@ -3,7 +3,7 @@ cpprest 2 - 7 + 8 0 $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index 924307aad2..642dd48568 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -16,7 +16,7 @@ * ==--== */ #define CPPREST_VERSION_REVISION 0 -#define CPPREST_VERSION_MINOR 7 +#define CPPREST_VERSION_MINOR 8 #define CPPREST_VERSION_MAJOR 2 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 5aef95cf76..fd1df86e40 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -99,7 +99,7 @@ target_link_libraries(${Casablanca_LIBRARY} # Portions specific to cpprest binary versioning. set (CPPREST_VERSION_MAJOR 2) -set (CPPREST_VERSION_MINOR 7) +set (CPPREST_VERSION_MINOR 8) set (CPPREST_VERSION_REVISION 0) if(WIN32) diff --git a/Release/src/build/init.ps1 b/Release/src/build/init.ps1 index 45ae72ab74..68a35fbc13 100644 --- a/Release/src/build/init.ps1 +++ b/Release/src/build/init.ps1 @@ -5,7 +5,7 @@ function Copy-Natvis($DestFolder) if ((Test-Path $DestFolder) -eq $True) { # Update casablanca version for each release here. - $DestFile = Join-Path -path $DestFolder -childpath "cpprest2_7.natvis"; + $DestFile = Join-Path -path $DestFolder -childpath "cpprest2_8.natvis"; # Check to see if cpp rest natvis file for this version already exists # if not, then copy into user profile for Visual Studio to pick up From 3070ca21ed665a5aeb7d0cfe28f7f21d6c062a92 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 25 Feb 2016 19:25:47 -0800 Subject: [PATCH 057/609] Adapt configure.sh to the new way that the OpenSSL-for-iPhone project produces openssl binaries Signed-off-by: Alexander Karatarakis --- Build_iOS/configure.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Build_iOS/configure.sh b/Build_iOS/configure.sh index cbc68baab5..8c9c9eafd7 100755 --- a/Build_iOS/configure.sh +++ b/Build_iOS/configure.sh @@ -12,9 +12,11 @@ git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git pushd OpenSSL-for-iPhone ./build-libssl.sh popd -mkdir openssl -mv OpenSSL-for-iPhone/include openssl -mv OpenSSL-for-iPhone/lib openssl +mkdir -p openssl/lib +cp -r OpenSSL-for-iPhone/bin/iPhoneOS8.2-armv7.sdk/include openssl +cp OpenSSL-for-iPhone/include/LICENSE openssl +lipo -create -output openssl/lib/libssl.a OpenSSL-for-iPhone/bin/iPhone*/lib/libssl.a +lipo -create -output openssl/lib/libcrypto.a OpenSSL-for-iPhone/bin/iPhone*/lib/libcrypto.a git clone https://github.com/cristeab/ios-cmake.git pushd ios-cmake From 2320e0c94b75474cf6d1af8e4bdf639ac13d8486 Mon Sep 17 00:00:00 2001 From: AntonBikineev Date: Sat, 27 Feb 2016 22:08:26 +0300 Subject: [PATCH 058/609] Changing use of C++14 capture initialization to usual functor in pplxtask_tests.hpp --- .../functional/pplx/pplx_test/pplxtask_tests.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp index a6ea601ed7..c6f39e815d 100644 --- a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp +++ b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp @@ -306,15 +306,25 @@ TEST(TestTasks_void_tasks_default_construction) TEST(TestTasks_movable_then) { + // create movable only type struct A { A() = default; A(A&&) = default; A& operator=(A&&) = default; + + // explicitly delete copy functions + A(const A&) = delete; + A& operator=(const A&) = delete; + + char operator()(int) + { + return 'c'; + } } a; task task = create_task([]{ return 2; }); - auto f = task.then([a = std::move(a)](int) { return 'c'; }); + auto f = task.then(std::move(a)); IsTrue(f.get() == 'c', L".then should be able to work with movable functors"); } From ff4f31157deac23173150f5ab48243b810f336bf Mon Sep 17 00:00:00 2001 From: AntonBikineev Date: Sun, 28 Feb 2016 03:04:12 +0300 Subject: [PATCH 059/609] Disabling movable_then test on Windows --- Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp index c6f39e815d..e38398f854 100644 --- a/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp +++ b/Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp @@ -306,6 +306,7 @@ TEST(TestTasks_void_tasks_default_construction) TEST(TestTasks_movable_then) { +#ifndef _MSC_VER // create movable only type struct A { @@ -327,6 +328,7 @@ TEST(TestTasks_movable_then) auto f = task.then(std::move(a)); IsTrue(f.get() == 'c', L".then should be able to work with movable functors"); +#endif // _MSC_VER } TEST(TestTasks_constant_this) From cd9714182ed4b928553e51272713c391babc5f78 Mon Sep 17 00:00:00 2001 From: AntonBikineev Date: Tue, 1 Mar 2016 08:29:20 -0600 Subject: [PATCH 060/609] Fixing noncopyablewrapper ctor --- Release/include/pplx/pplxtasks.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index 6145fe08f3..bda98e46d4 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -3100,8 +3100,10 @@ namespace details template struct _NonCopyableFunctorWrapper { - template - _NonCopyableFunctorWrapper(_Tx&& f) + template, + typename std::decay<_Tx>::type>::value>::type> + explicit _NonCopyableFunctorWrapper(_Tx&& f) : _M_functor{std::make_shared<_Ty>(std::forward<_Tx>(f))} {} From 2e23b2adf1aad9508bba14b6e48647d41690d971 Mon Sep 17 00:00:00 2001 From: AntonBikineev Date: Wed, 2 Mar 2016 03:56:16 -0600 Subject: [PATCH 061/609] Adding decay to noncopyablefunctorwrapper --- Release/include/pplx/pplxtasks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index bda98e46d4..760a614538 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -3842,7 +3842,7 @@ class task typedef typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type _NormalizedContinuationReturnType; typename details::_Task_ptr<_ReturnType>::_Type _M_ancestorTaskImpl; - typename details::_CopyableFunctor<_Function>::_Type _M_function; + typename details::_CopyableFunctor::type >::_Type _M_function; template _ContinuationTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type & _AncestorImpl, From 2bf31b7f75a86a1d97e356f61235dae1e623a937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Do=C4=9Fukan=20=C3=87a=C4=9Fatay?= Date: Thu, 3 Mar 2016 16:27:51 +0200 Subject: [PATCH 062/609] Fixed ambiguous call to begin when using with boost library. --- Release/include/cpprest/containerstream.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/containerstream.h b/Release/include/cpprest/containerstream.h index 89ad1bff6d..12c1af2fe9 100644 --- a/Release/include/cpprest/containerstream.h +++ b/Release/include/cpprest/containerstream.h @@ -439,8 +439,8 @@ namespace Concurrency { namespace streams { size_t newPos = m_current_position + read_size; - auto readBegin = begin(m_data) + m_current_position; - auto readEnd = begin(m_data) + newPos; + auto readBegin = std::begin(m_data) + m_current_position; + auto readEnd = std::begin(m_data) + newPos; #ifdef _WIN32 // Avoid warning C4996: Use checked iterators under SECURE_SCL @@ -470,7 +470,7 @@ namespace Concurrency { namespace streams { resize_for_write(newSize); // Copy the data - std::copy(ptr, ptr + count, begin(m_data) + m_current_position); + std::copy(ptr, ptr + count, std::begin(m_data) + m_current_position); // Update write head and satisfy pending reads if any update_current_position(newSize); From ef8e748a2b16a6eecece4b69d3033f3285cdd971 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 4 Mar 2016 16:16:16 -0800 Subject: [PATCH 063/609] Fix use after free in HTTPS listener on non-windows. The boost examples for ssl::stream all use stack allocated contexts and streams; considering that the ssl::context is noncopyable, it seems that its lifetime must exceed any streams. --- Release/include/cpprest/details/http_server_asio.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/details/http_server_asio.h b/Release/include/cpprest/details/http_server_asio.h index 4ab7c38e90..bf4695a213 100644 --- a/Release/include/cpprest/details/http_server_asio.h +++ b/Release/include/cpprest/details/http_server_asio.h @@ -72,6 +72,7 @@ class connection bool m_chunked; std::atomic m_refs; // track how many threads are still referring to this + std::unique_ptr m_ssl_context; std::unique_ptr> m_ssl_stream; public: @@ -85,9 +86,11 @@ class connection { if (is_https) { - boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23); - ssl_context_callback(ssl_context); - m_ssl_stream = utility::details::make_unique>(*m_socket, ssl_context); + m_ssl_context = utility::details::make_unique(boost::asio::ssl::context::sslv23); + ssl_context_callback(*m_ssl_context); + m_ssl_stream = utility::details::make_unique>(*m_socket, *m_ssl_context); + m_ssl_stream = utility::details::make_unique>(*m_socket, *m_ssl_context); + m_ssl_stream->async_handshake(boost::asio::ssl::stream_base::server, [this](const boost::system::error_code&) { this->start_request_response(); }); } else From 0d615a18d51526c819db939c55495ca2a424ce38 Mon Sep 17 00:00:00 2001 From: Senthil Date: Wed, 9 Mar 2016 01:11:10 -0800 Subject: [PATCH 064/609] Fix obtaining raw string_t pointer from temporary --- Release/src/json/json_parsing.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index ea7ee52e89..13e3d59006 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -63,7 +63,8 @@ void CreateException(const Token &tk, const utility::string_t &message) { utility::ostringstream_t os; os << _XPLATSTR("* Line ") << tk.start.m_line << _XPLATSTR(", Column ") << tk.start.m_column << _XPLATSTR(" Syntax error: ") << message; - throw web::json::json_exception(os.str().c_str()); + utility::string_t osStr = os.str(); + throw web::json::json_exception(osStr.c_str()); } template From 2b7b52f97a43ce0b587756f827a6d156039e7e2b Mon Sep 17 00:00:00 2001 From: Gianfranco Costamagna Date: Thu, 17 Mar 2016 08:32:42 +0100 Subject: [PATCH 065/609] Fix typo hexidecimal/hexadecimal Spotted by debian lintian checks --- Release/src/uri/uri.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index e9647bb276..104719c81d 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -226,7 +226,7 @@ static int hex_char_digit_to_decimal_char(int hex) } else { - throw uri_exception("Invalid hexidecimal digit"); + throw uri_exception("Invalid hexadecimal digit"); } return decimal; } @@ -240,12 +240,12 @@ utility::string_t uri::decode(const utility::string_t &encoded) { if(++iter == encoded.end()) { - throw uri_exception("Invalid URI string, two hexidecimal digits must follow '%'"); + throw uri_exception("Invalid URI string, two hexadecimal digits must follow '%'"); } int decimal_value = hex_char_digit_to_decimal_char(static_cast(*iter)) << 4; if(++iter == encoded.end()) { - throw uri_exception("Invalid URI string, two hexidecimal digits must follow '%'"); + throw uri_exception("Invalid URI string, two hexadecimal digits must follow '%'"); } decimal_value += hex_char_digit_to_decimal_char(static_cast(*iter)); From d6b882a6d8c947e245b2ed8b1ecbe2a9e4954de5 Mon Sep 17 00:00:00 2001 From: "hyotak.yun" Date: Wed, 23 Mar 2016 19:56:47 +0900 Subject: [PATCH 066/609] Added websocket_client_config option for ssl verify mode --- Release/include/cpprest/ws_client.h | 26 ++++++++++++++++++- .../src/websockets/client/ws_client_wspp.cpp | 9 ++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/ws_client.h b/Release/include/cpprest/ws_client.h index b6d00b805d..18a2ba28b1 100644 --- a/Release/include/cpprest/ws_client.h +++ b/Release/include/cpprest/ws_client.h @@ -84,7 +84,11 @@ class websocket_client_config /// /// Creates a websocket client configuration with default settings. /// - websocket_client_config() : m_sni_enabled(true) {} + websocket_client_config() : + m_sni_enabled(true), + m_validate_certificates(true) + { + } /// /// Get the web proxy object @@ -187,6 +191,25 @@ class websocket_client_config /// If you want all the subprotocols in a comma separated string /// they can be directly looked up in the headers using 'Sec-WebSocket-Protocol'. _ASYNCRTIMP std::vector<::utility::string_t> subprotocols() const; + + /// + /// Gets the server certificate validation property. + /// + /// True if certificates are to be verified, false otherwise. + bool validate_certificates() const + { + return m_validate_certificates; + } + + /// + /// Sets the server certificate validation property. + /// + /// False to turn ignore all server certificate validation errors, true otherwise. + /// Note ignoring certificate errors can be dangerous and should be done with caution. + void set_validate_certificates(bool validate_certs) + { + m_validate_certificates = validate_certs; + } private: web::web_proxy m_proxy; @@ -194,6 +217,7 @@ class websocket_client_config web::http::http_headers m_headers; bool m_sni_enabled; utf8string m_sni_hostname; + bool m_validate_certificates; }; /// diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index e8f5d2edbe..03d7dc17cf 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -159,7 +159,14 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: auto sslContext = websocketpp::lib::shared_ptr(new boost::asio::ssl::context(boost::asio::ssl::context::sslv23)); sslContext->set_default_verify_paths(); sslContext->set_options(boost::asio::ssl::context::default_workarounds); - sslContext->set_verify_mode(boost::asio::ssl::context::verify_peer); + if (m_config.validate_certificates()) + { + sslContext->set_verify_mode(boost::asio::ssl::context::verify_peer); + } + else + { + sslContext->set_verify_mode(boost::asio::ssl::context::verify_none); + } #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || defined(_WIN32) m_openssl_failed = false; From 525db49e7855fe6de3d6e4ab25c84a5110f6d60c Mon Sep 17 00:00:00 2001 From: "hyotak.yun" Date: Wed, 23 Mar 2016 20:01:56 +0900 Subject: [PATCH 067/609] . --- Release/include/cpprest/ws_client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/ws_client.h b/Release/include/cpprest/ws_client.h index 18a2ba28b1..6ce052342e 100644 --- a/Release/include/cpprest/ws_client.h +++ b/Release/include/cpprest/ws_client.h @@ -217,7 +217,7 @@ class websocket_client_config web::http::http_headers m_headers; bool m_sni_enabled; utf8string m_sni_hostname; - bool m_validate_certificates; + bool m_validate_certificates; }; /// From c7c044f7a10bcf59ce793976e4a1328d398005e9 Mon Sep 17 00:00:00 2001 From: feelapi Date: Wed, 30 Mar 2016 16:36:21 +0800 Subject: [PATCH 068/609] add static library for windows xp --- .../casablanca120.xp.static.vcxproj | 109 ++++++++++++++++++ .../src/build/vs12.xp.static/packages.config | 13 +++ cpprestsdk120.sln | 31 +++-- 3 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj create mode 100644 Release/src/build/vs12.xp.static/packages.config diff --git a/Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj b/Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj new file mode 100644 index 0000000000..91a91c3134 --- /dev/null +++ b/Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj @@ -0,0 +1,109 @@ + + + + + + DebugStatic + ARM + + + DebugStatic + Win32 + + + DebugStatic + x64 + + + ReleaseStatic + ARM + + + ReleaseStatic + Win32 + + + ReleaseStatic + x64 + + + + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3} + Win32Proj + SAK + SAK + SAK + SAK + StaticLibrary + v120_xp + false + true + cpprestsdk120.xp.static + + + + + + + + true + true + true + true + + + + + + + + + + + + + + + d + + + $(CppRestBaseFileName)120$(DebugFileSuffix)_xp_$(CppRestSDKVersionFileSuffix) + 58b07c0c + + + + + + + _NO_ASYNCRTIMP;_WINSOCK_DEPRECATED_NO_WARNINGS;CPPREST_TARGET_XP;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + Use + stdafx.h + -Zm160 /bigobj %(AdditionalOptions) + MultiThreadedDebugDLL + MultiThreadedDLL + true + + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + + + Winhttp.lib;crypt32.lib;%(AdditionalDependencies) + UseLinkTimeCodeGeneration + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Release/src/build/vs12.xp.static/packages.config b/Release/src/build/vs12.xp.static/packages.config new file mode 100644 index 0000000000..7b1dc6aac0 --- /dev/null +++ b/Release/src/build/vs12.xp.static/packages.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/cpprestsdk120.sln b/cpprestsdk120.sln index 362892d2e5..59fc89bf4c 100644 --- a/cpprestsdk120.sln +++ b/cpprestsdk120.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop +# Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" @@ -65,23 +65,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FacebookDemo120", "Release\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.wod", "Release\src\build\vs12.wod\casablanca120.wod.vcxproj", "{BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.xp.static", "Release\src\build\vs12.xp.static\casablanca120.xp.static.vcxproj", "{CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - Release\src\build\common.vcxitems*{c5d88d15-f9f5-48e2-9ef2-be0b645b9c0d}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{c5d88d15-f9f5-48e2-9ef2-be0b645b9c0d}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{cf74448d-fe99-4e3c-afa6-a50f3145baf3}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{cf74448d-fe99-4e3c-afa6-a50f3145baf3}*SharedItemsImports = 4 Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{15f3b200-1aed-4b57-af37-b21cd67914b1}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{15f3b200-1aed-4b57-af37-b21cd67914b1}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{9ad285a2-301e-47a0-a299-14ad5d4f2758}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{9ad285a2-301e-47a0-a299-14ad5d4f2758}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{01a76234-e6e8-4332-9fe2-1e12c34621be}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{15f3b200-1aed-4b57-af37-b21cd67914b1}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{01a76234-e6e8-4332-9fe2-1e12c34621be}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{ba4f15a0-6f9c-4ed6-a132-d6f7d0e08d6a}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{01a76234-e6e8-4332-9fe2-1e12c34621be}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{ba4f15a0-6f9c-4ed6-a132-d6f7d0e08d6a}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{ba4f15a0-6f9c-4ed6-a132-d6f7d0e08d6a}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{e5f8a2f0-f713-4673-a42f-2cc4e8fb171b}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{e5f8a2f0-f713-4673-a42f-2cc4e8fb171b}*SharedItemsImports = 4 Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 EndGlobalSection @@ -272,6 +270,18 @@ Global {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|Win32.Build.0 = Release|Win32 {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|x64.ActiveCfg = Release|x64 {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|x64.Build.0 = Release|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|ARM.ActiveCfg = DebugStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|ARM.Build.0 = DebugStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|Win32.ActiveCfg = DebugStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|Win32.Build.0 = DebugStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|x64.ActiveCfg = DebugStatic|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|x64.Build.0 = DebugStatic|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|ARM.ActiveCfg = ReleaseStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|ARM.Build.0 = ReleaseStatic|ARM + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|Win32.ActiveCfg = ReleaseStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|Win32.Build.0 = ReleaseStatic|Win32 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|x64.ActiveCfg = ReleaseStatic|x64 + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|x64.Build.0 = ReleaseStatic|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -306,5 +316,6 @@ Global {3E5DF179-3668-49DA-9B6D-38C0632D8F28} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} = {3E5DF179-3668-49DA-9B6D-38C0632D8F28} {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} + {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} EndGlobalSection EndGlobal From f0637654fc0e6752d60f483138cbc8aef4ff0b75 Mon Sep 17 00:00:00 2001 From: Leigh Smith Date: Wed, 30 Mar 2016 16:50:08 -0400 Subject: [PATCH 069/609] Removed redundant std::move() that was causing errors on Xcode 7.3 gcc --- Release/src/http/common/http_helpers.cpp | 6 +++--- Release/src/utilities/asyncrt_utils.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index a80f2ad1bf..1424dbe382 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -272,7 +272,7 @@ utf16string convert_utf16_to_utf16(utf16string src) { case little_endian: src.erase(0, 1); - return std::move(src); + return src; case big_endian: return convert_utf16be_to_utf16le(std::move(src), true); case unknown: @@ -313,7 +313,7 @@ static utf16string big_endian_to_little_endian(utf16string src, bool erase_bom) } if (src.empty()) { - return std::move(src); + return src; } const size_t size = src.size(); @@ -324,7 +324,7 @@ static utf16string big_endian_to_little_endian(utf16string src, bool erase_bom) src[i] = static_cast(src[i] | ch >> 8); } - return std::move(src); + return src; } utility::string_t convert_utf16be_to_string_t(utf16string src, bool erase_bom) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index cb7a329487..ada58bada5 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -486,13 +486,13 @@ utility::string_t __cdecl conversions::to_string_t(const std::string &s) #endif } -std::string __cdecl conversions::to_utf8string(std::string value) { return std::move(value); } +std::string __cdecl conversions::to_utf8string(std::string value) { return value; } std::string __cdecl conversions::to_utf8string(const utf16string &value) { return utf16_to_utf8(value); } utf16string __cdecl conversions::to_utf16string(const std::string &value) { return utf8_to_utf16(value); } -utf16string __cdecl conversions::to_utf16string(utf16string value) { return std::move(value); } +utf16string __cdecl conversions::to_utf16string(utf16string value) { return value; } #ifndef WIN32 datetime datetime::timeval_to_datetime(const timeval &time) From 356639d5e2599bd33f745552deb0331c8943e4ae Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 30 Mar 2016 17:26:26 -0700 Subject: [PATCH 070/609] Adding 'lib' prefix to v140 static lib to prevent collision with import lib name --- Release/src/build/vs14.static/casablanca140.static.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/build/vs14.static/casablanca140.static.vcxproj b/Release/src/build/vs14.static/casablanca140.static.vcxproj index 5795f27671..cda12db6a7 100644 --- a/Release/src/build/vs14.static/casablanca140.static.vcxproj +++ b/Release/src/build/vs14.static/casablanca140.static.vcxproj @@ -35,7 +35,7 @@ d - $(CppRestBaseFileName)140$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) + lib$(CppRestBaseFileName)140$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) From 2d26f0aa5c27785d25dfd6437b2a5f2ca0605b42 Mon Sep 17 00:00:00 2001 From: Rami Abughazaleh Date: Wed, 30 Mar 2016 15:01:22 -0700 Subject: [PATCH 071/609] Added projects which target v140_xp to resolve https://github.com/Microsoft/cpprestsdk/issues/113 --- CONTRIBUTORS.txt | 2 + .../BingRequest140.xp.vcxproj | 133 ++++++++++++++ .../BingRequest140.xp.vcxproj.filters | 13 ++ .../build/vs14.xp/casablanca140.xp.vcxproj | 86 +++++++++ Release/src/build/vs14.xp/packages.config | 11 ++ Release/src/dirs.proj | 1 + Release/tests/common/utilities/dirs.proj | 13 +- .../vs14.xp/CommonUtilities140.xp.vcxproj | 150 ++++++++++++++++ Release/tests/functional/json/dirs.proj | 13 +- .../json/vs14.xp/JSON140_test.xp.vcxproj | 151 ++++++++++++++++ .../tests/functional/pplx/pplx_test/dirs.proj | 11 +- .../pplx_test/vs14.xp/pplx140_test.xp.vcxproj | 158 +++++++++++++++++ Release/tests/functional/streams/dirs.proj | 17 +- .../vs14.xp/streams140_test.xp.vcxproj | 163 ++++++++++++++++++ Release/tests/functional/uri/dirs.proj | 13 +- .../uri/vs14.xp/Uri140_test.xp.vcxproj | 155 +++++++++++++++++ Release/tests/functional/utils/dirs.proj | 15 +- .../utils/vs14.xp/Utils140_test.xp.vcxproj | 151 ++++++++++++++++ .../functional/websockets/client/dirs.proj | 1 + .../websocketsclient140_test.xp.vcxproj | 123 +++++++++++++ .../functional/websockets/utilities/dirs.proj | 1 + .../websockets_test_utilities140.xp.vcxproj | 132 ++++++++++++++ cpprestsdk140.sln | 40 ++++- 23 files changed, 1514 insertions(+), 39 deletions(-) create mode 100644 Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj create mode 100644 Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters create mode 100644 Release/src/build/vs14.xp/casablanca140.xp.vcxproj create mode 100644 Release/src/build/vs14.xp/packages.config create mode 100644 Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj create mode 100644 Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj create mode 100644 Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj create mode 100644 Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj create mode 100644 Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj create mode 100644 Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj create mode 100644 Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj create mode 100644 Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 98b12d748f..ca43881905 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -43,3 +43,5 @@ thomasschaub Trimble Tim Boundy (gigaplex) + +Rami Abughazaleh (icnocop) \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj new file mode 100644 index 0000000000..d8b4faa9c0 --- /dev/null +++ b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj @@ -0,0 +1,133 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} + SAK + SAK + SAK + SAK + Win32Proj + $(VCTargetsPath14) + + + + Application + true + NotSet + v140_xp + + + Application + true + NotSet + v140_xp + + + Application + false + true + NotSet + v140_xp + + + Application + false + true + NotSet + v140_xp + + + + + + + /bigobj %(AdditionalOptions) + NotUsing + Disabled + CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + Disabled + CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + MaxSpeed + true + true + CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + MaxSpeed + true + true + CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + + + + {15f3b200-1aed-4b57-af37-b21cd67914b1} + + + + \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters new file mode 100644 index 0000000000..cee450afc2 --- /dev/null +++ b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {786631e0-badc-4b3f-bd98-9b13e6a8e5f8} + + + + + Source Files + + + \ No newline at end of file diff --git a/Release/src/build/vs14.xp/casablanca140.xp.vcxproj b/Release/src/build/vs14.xp/casablanca140.xp.vcxproj new file mode 100644 index 0000000000..4a1b3661a9 --- /dev/null +++ b/Release/src/build/vs14.xp/casablanca140.xp.vcxproj @@ -0,0 +1,86 @@ + + + + + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9} + Win32Proj + SAK + SAK + SAK + SAK + DynamicLibrary + v140_xp + false + true + cpprestsdk140.xp + + + + + + + + true + true + true + true + + + + + + + + + + + + + + + d + + + $(CppRestBaseFileName)140$(DebugFileSuffix)_xp_$(CppRestSDKVersionFileSuffix) + eec97f90 + + + + Designer + + + + + CPPREST_TARGET_XP;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + Use + stdafx.h + -Zm300 /bigobj %(AdditionalOptions) + MultiThreadedDebugDLL + MultiThreadedDLL + true + + + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + + + Winhttp.lib;crypt32.lib;%(AdditionalDependencies) + UseLinkTimeCodeGeneration + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Release/src/build/vs14.xp/packages.config b/Release/src/build/vs14.xp/packages.config new file mode 100644 index 0000000000..21a51fdf83 --- /dev/null +++ b/Release/src/build/vs14.xp/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Release/src/dirs.proj b/Release/src/dirs.proj index d94b26bb6b..96b0b6fc94 100644 --- a/Release/src/dirs.proj +++ b/Release/src/dirs.proj @@ -18,6 +18,7 @@ + diff --git a/Release/tests/common/utilities/dirs.proj b/Release/tests/common/utilities/dirs.proj index 4b919954b1..953e655a6e 100644 --- a/Release/tests/common/utilities/dirs.proj +++ b/Release/tests/common/utilities/dirs.proj @@ -3,20 +3,21 @@ - - + + - + - + + - + - + diff --git a/Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj b/Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj new file mode 100644 index 0000000000..202e5daf98 --- /dev/null +++ b/Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {5AD81270-B089-4E1B-8741-6486F39DE273} + Win32Proj + CommonUtilities140 + SAK + SAK + SAK + SAK + $(VCTargetsPath14) + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + + Create + Create + Create + Create + + + + + + + + + + + {75885703-7f3d-4086-8e60-c60b9b126f7e} + + + {6490c580-dd4a-4f2d-a345-732c5148349f} + + + {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} + + + + + + \ No newline at end of file diff --git a/Release/tests/functional/json/dirs.proj b/Release/tests/functional/json/dirs.proj index 30f6c1118c..14b704700e 100644 --- a/Release/tests/functional/json/dirs.proj +++ b/Release/tests/functional/json/dirs.proj @@ -3,23 +3,24 @@ - - + + - + - + + - + - + diff --git a/Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj b/Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj new file mode 100644 index 0000000000..6b4e8ee881 --- /dev/null +++ b/Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {ABA69F91-45D4-41D8-991A-10A6319E42C3} + SAK + SAK + SAK + SAK + Win32Proj + $(VCTargetsPath14) + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CommonTestIncludeDir) + + + Console + true + $(OutDir)%(AdditionalLibraryDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CommonTestIncludeDir) + + + Console + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CommonTestIncludeDir) + + + Console + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CommonTestIncludeDir) + + + Console + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} + + + {75885703-7f3d-4086-8e60-c60b9b126f7e} + + + {5AD81270-B089-4E1B-8741-6486F39DE273} + + + + + + \ No newline at end of file diff --git a/Release/tests/functional/pplx/pplx_test/dirs.proj b/Release/tests/functional/pplx/pplx_test/dirs.proj index 1f1f538dde..559175d100 100644 --- a/Release/tests/functional/pplx/pplx_test/dirs.proj +++ b/Release/tests/functional/pplx/pplx_test/dirs.proj @@ -3,21 +3,22 @@ - - + + + - + - + - + diff --git a/Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj new file mode 100644 index 0000000000..bedd4efee8 --- /dev/null +++ b/Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {EB4A3750-CA93-4968-89D7-3ED467DB2C59} + Win32Proj + HttpTests + SAK + SAK + SAK + SAK + $(VCTargetsPath14) + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) + + + + + Level4 + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Level4 + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Level4 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Level4 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + + + + + + + + Create + Create + Create + Create + + + + + {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} + + + {5ad81270-b089-4e1b-8741-6486f39de273} + + + {75885703-7F3D-4086-8E60-C60B9B126F7E} + + + + + + \ No newline at end of file diff --git a/Release/tests/functional/streams/dirs.proj b/Release/tests/functional/streams/dirs.proj index c496ac99e5..1740e6d983 100644 --- a/Release/tests/functional/streams/dirs.proj +++ b/Release/tests/functional/streams/dirs.proj @@ -1,23 +1,24 @@ - + - - + + - + - + - + + - + - + diff --git a/Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj b/Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj new file mode 100644 index 0000000000..cdd4ff6820 --- /dev/null +++ b/Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F279F1ED-8AFF-478D-9A20-DDCAD8CBA336} + Win32Proj + HttpTests + SAK + SAK + SAK + SAK + $(VCTargetsPath14) + 2276c549 + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) + /bigobj %(AdditionalOptions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} + + + {75885703-7f3d-4086-8e60-c60b9b126f7e} + + + {5ad81270-b089-4e1b-8741-6486f39de273} + + + + + + + + + + \ No newline at end of file diff --git a/Release/tests/functional/uri/dirs.proj b/Release/tests/functional/uri/dirs.proj index 74d3ea4028..fcaf28aa55 100644 --- a/Release/tests/functional/uri/dirs.proj +++ b/Release/tests/functional/uri/dirs.proj @@ -3,23 +3,24 @@ - - + + - + - + - + + - + diff --git a/Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj b/Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj new file mode 100644 index 0000000000..988d387b15 --- /dev/null +++ b/Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {66B6D1E2-A91C-4DA3-8568-B7457FA7ED6D} + SAK + SAK + SAK + SAK + Win32Proj + $(VCTargetsPath14) + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} + + + {75885703-7f3d-4086-8e60-c60b9b126f7e} + + + {5ad81270-b089-4e1b-8741-6486f39de273} + + + + + + \ No newline at end of file diff --git a/Release/tests/functional/utils/dirs.proj b/Release/tests/functional/utils/dirs.proj index 7efe26d2cb..f01337a94f 100644 --- a/Release/tests/functional/utils/dirs.proj +++ b/Release/tests/functional/utils/dirs.proj @@ -3,21 +3,22 @@ - - + + - + - + + - + - + - + diff --git a/Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj b/Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj new file mode 100644 index 0000000000..45ee435b2b --- /dev/null +++ b/Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E9E26CDB-4CE3-4B0E-AAF8-D32F57E48856} + SAK + SAK + SAK + SAK + Win32Proj + $(VCTargetsPath14) + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + Windows + true + true + true + $(OutDir);%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} + + + {75885703-7f3d-4086-8e60-c60b9b126f7e} + + + {5ad81270-b089-4e1b-8741-6486f39de273} + + + + + + \ No newline at end of file diff --git a/Release/tests/functional/websockets/client/dirs.proj b/Release/tests/functional/websockets/client/dirs.proj index 38d0fd629e..15d6dbc4dd 100644 --- a/Release/tests/functional/websockets/client/dirs.proj +++ b/Release/tests/functional/websockets/client/dirs.proj @@ -14,6 +14,7 @@ + diff --git a/Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj b/Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj new file mode 100644 index 0000000000..9791f3d90c --- /dev/null +++ b/Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj @@ -0,0 +1,123 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + WebsocketTests + SAK + SAK + SAK + SAK + websocketsclient140_test.xp + {BBE711C0-568C-48E5-A9EB-2F3741D0687B} + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + Use + $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities;%(AdditionalIncludeDirectories) + + + Windows + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Disabled + CPPREST_TARGET_XP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + + + MaxSpeed + true + true + CPPREST_TARGET_XP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + + true + true + + + + + {75885703-7f3d-4086-8e60-c60b9b126f7e} + + + {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} + + + {5AD81270-B089-4E1B-8741-6486F39DE273} + + + {3803246A-F31E-44EC-BCA9-87DF68C5EB8D} + + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + diff --git a/Release/tests/functional/websockets/utilities/dirs.proj b/Release/tests/functional/websockets/utilities/dirs.proj index 09467840c5..e063f42b24 100644 --- a/Release/tests/functional/websockets/utilities/dirs.proj +++ b/Release/tests/functional/websockets/utilities/dirs.proj @@ -13,6 +13,7 @@ + diff --git a/Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj b/Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj new file mode 100644 index 0000000000..c1410e701a --- /dev/null +++ b/Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj @@ -0,0 +1,132 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + SAK + SAK + SAK + SAK + Win32Proj + en-US + 11.0 + tests::common::websockets_test_utilities + websockets_test_utilities140.xp + {3803246A-F31E-44EC-BCA9-87DF68C5EB8D} + + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + DynamicLibrary + false + true + Unicode + v140 + + + + + + Use + $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories) + + + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + 4503;%(DisableSpecificWarnings) + + + Windows + $(OutDir);%(AdditionalLibraryDirectories) + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) + + + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) + + + true + true + + + + + + Create + Create + Create + Create + + + + + + + + + {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} + + + {75885703-7f3d-4086-8e60-c60b9b126f7e} + + + {5AD81270-B089-4E1B-8741-6486F39DE273} + + + + + + + + + + + + + diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln index 36c7cb8da0..940d77dc51 100644 --- a/cpprestsdk140.sln +++ b/cpprestsdk140.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23207.2 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14\casablanca140.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" EndProject @@ -51,6 +51,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp.staticlib EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRunner.android.NativeActivity", "Release\tests\common\TestRunner\vs14.android\TestRunner.android.NativeActivity\TestRunner.android.NativeActivity.vcxproj", "{D1060D0A-A10E-444D-9F6B-9676EA453F9A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.xp", "Release\src\build\vs14.xp\casablanca140.xp.vcxproj", "{39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest140.xp", "Release\samples\BingRequest\BingRequest140.xp\BingRequest140.xp.vcxproj", "{7009BCBE-D67C-4B54-BEFC-A44E62656CF1}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Release\src\build\win32.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 @@ -65,6 +69,8 @@ Global Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 @@ -240,6 +246,36 @@ Global {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x64.ActiveCfg = Release|x86 {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.ActiveCfg = Release|x86 {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.Build.0 = Release|x86 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|ARM.ActiveCfg = Debug|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|ARM.Build.0 = Debug|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|Win32.ActiveCfg = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|Win32.Build.0 = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x64.ActiveCfg = Debug|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x64.Build.0 = Debug|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x86.ActiveCfg = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x86.Build.0 = Debug|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|ARM.ActiveCfg = Release|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|ARM.Build.0 = Release|ARM + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|Win32.ActiveCfg = Release|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|Win32.Build.0 = Release|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x64.ActiveCfg = Release|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x64.Build.0 = Release|x64 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x86.ActiveCfg = Release|Win32 + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x86.Build.0 = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|ARM.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.Build.0 = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.ActiveCfg = Debug|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.Build.0 = Debug|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x86.ActiveCfg = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x86.Build.0 = Debug|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|ARM.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.Build.0 = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.ActiveCfg = Release|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.Build.0 = Release|x64 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.ActiveCfg = Release|Win32 + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -266,5 +302,7 @@ Global {3A584D9C-1A98-4046-B7D3-B7171EF42D34} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {47A5CFDC-C244-45A6-9830-38CB303CB495} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} + {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} = {00EF03C1-74A9-4832-B26B-E6478C2A96AC} EndGlobalSection EndGlobal From 5d84d4c1b0926f4d3cec9404e2a76a28d5dd717e Mon Sep 17 00:00:00 2001 From: pp555 Date: Wed, 23 Mar 2016 16:12:46 +0100 Subject: [PATCH 072/609] Fixing latin1 to UTF-16 convertion --- Release/src/utilities/asyncrt_utils.cpp | 2 +- Release/tests/functional/utils/strings.cpp | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index ada58bada5..d1af12b8dd 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -440,7 +440,7 @@ utf16string __cdecl conversions::latin1_to_utf16(const std::string &s) dest.resize(s.size()); for (size_t i = 0; i < s.size(); ++i) { - dest[i] = utf16char(s[i]); + dest[i] = utf16char(static_cast(s[i])); } return dest; } diff --git a/Release/tests/functional/utils/strings.cpp b/Release/tests/functional/utils/strings.cpp index d6a88c70a9..3142ba45db 100644 --- a/Release/tests/functional/utils/strings.cpp +++ b/Release/tests/functional/utils/strings.cpp @@ -278,13 +278,22 @@ TEST(utf8_to_utf16_errors) TEST(latin1_to_utf16) { - // TODO: find some string that actually uses something unique to the Latin1 code page. - std::string str_latin1("This is a test"); - utf16string str_utf16 = utility::conversions::latin1_to_utf16(str_latin1); - - for (size_t i = 0; i < str_latin1.size(); ++i) + char in[256] = { 0 }; + char16_t expectedResult[256] = { 0 }; + for (size_t i = 0; i < 256; ++i) + { + in[i] = static_cast(i); + expectedResult[i] = static_cast(i); + } + + std::string str_latin1(in, 256); + + auto actualResult = utility::conversions::latin1_to_utf16(str_latin1); + + VERIFY_ARE_EQUAL(str_latin1.size(), actualResult.size()); + for (size_t i = 0; i < actualResult.size(); ++i) { - VERIFY_ARE_EQUAL((utf16char)str_latin1[i], str_utf16[i]); + VERIFY_ARE_EQUAL(expectedResult[i], actualResult[i]); } } From a148540720aa645306807d8a2eb2f901b88f153e Mon Sep 17 00:00:00 2001 From: Simon Lepasteur Date: Thu, 31 Mar 2016 16:36:20 +0200 Subject: [PATCH 073/609] Fix header reading on linux listener using HTTPS. The first asynchronous read of the stream was stopping at the first CRLF (after the HTTP version) instead of reading until CRLFCRLF (the end of the header). This bug was not always noticeable because, as stated in the boost documentation: "After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter. An application will typically leave that data in the streambuf for a subsequent async_read_until operation to examine." Therefore the bug appeared only when trying to read the body of the request and the streambuf filled by async_read_until did not contain the complete header. --- Release/src/http/listener/http_server_asio.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 14f3383b8e..63ea41f749 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -38,6 +38,7 @@ using namespace boost::asio; using namespace boost::asio::ip; #define CRLF std::string("\r\n") +#define CRLFCRLF std::string("\r\n\r\n") namespace web { @@ -144,7 +145,7 @@ struct crlf_nonascii_searcher_t } return std::make_pair(excluded, false); } -} crlf_nonascii_searcher; +} crlfcrlf_nonascii_searcher; }}}}} namespace boost @@ -205,14 +206,14 @@ void connection::start_request_response() if (m_ssl_stream) { - boost::asio::async_read_until(*m_ssl_stream, m_request_buf, CRLF, [this](const boost::system::error_code& ec, std::size_t) + boost::asio::async_read_until(*m_ssl_stream, m_request_buf, CRLFCRLF, [this](const boost::system::error_code& ec, std::size_t) { this->handle_http_line(ec); }); } else { - boost::asio::async_read_until(*m_socket, m_request_buf, crlf_nonascii_searcher, [this](const boost::system::error_code& ec, std::size_t) + boost::asio::async_read_until(*m_socket, m_request_buf, crlfcrlf_nonascii_searcher, [this](const boost::system::error_code& ec, std::size_t) { this->handle_http_line(ec); }); From 11a53dac6710e6fdd89933e76f032f5c204b1f2d Mon Sep 17 00:00:00 2001 From: Simon Lepasteur Date: Tue, 5 Apr 2016 11:36:08 +0200 Subject: [PATCH 074/609] Modify create_https_listener_get test to check that headers and body are retrieved correctly. --- .../src/http/listener/http_server_asio.cpp | 4 +- .../listener/listener_construction_tests.cpp | 51 ++++++++++++++++++- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 63ea41f749..9454aa5175 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -58,7 +58,7 @@ namespace details // This is used as part of the async_read_until call below; see the // following for more details: // http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/async_read_until/overload4.html -struct crlf_nonascii_searcher_t +struct crlfcrlf_nonascii_searcher_t { enum class State { @@ -152,7 +152,7 @@ namespace boost { namespace asio { -template <> struct is_match_condition : public boost::true_type {}; +template <> struct is_match_condition : public boost::true_type {}; }} namespace web diff --git a/Release/tests/functional/http/listener/listener_construction_tests.cpp b/Release/tests/functional/http/listener/listener_construction_tests.cpp index c5d3aa6274..8e30a2b488 100644 --- a/Release/tests/functional/http/listener/listener_construction_tests.cpp +++ b/Release/tests/functional/http/listener/listener_construction_tests.cpp @@ -488,6 +488,42 @@ AvLsTlswO+wDLXM1DoKxzFBZL5o8927niqW+vZpzyGc1uPmC1MG7+MDKdZsR+e+9 XzJTD4slrGSJrcpLt/g/Jqqdjg== -----END PRIVATE KEY----- )"; + + auto body = utility::string_t{U("body content")}; + http_headers all_headers; + all_headers.add(U("Accept"), U("text/plain")); + all_headers.add(U("Accept-Charset"), U("utf-8")); + all_headers.add(U("Accept-Encoding"), U("gzip, deflate")); + all_headers.add(U("Accept-Language"), U("en-US")); + all_headers.add(U("Accept-Datetime"), U("Thu, 31 May 2007 20:35:00 GMT")); + all_headers.add(U("Authorization"), U("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==")); + all_headers.add(U("Cache-Control"), U("no-cache")); + all_headers.add(U("Cookie"), U("$Version=1; Skin=new;")); + all_headers.add(U("Content-Length"), body.size()); + all_headers.add(U("Content-MD5"), U("Q2hlY2sgSW50ZWdyaXR5IQ==")); + all_headers.add(U("Content-Type"), U("application/x-www-form-urlencoded")); + all_headers.add(U("Date"), U("Tue, 15 Nov 1994 08:12:31 GMT")); + all_headers.add(U("Expect"), U("100-continue")); + all_headers.add(U("Forwarded"), U("for=192.0.2.60;proto=http;by=203.0.113.43Forwarded: for=192.0.2.43, for=198.51.100.17")); + all_headers.add(U("From"), U("user@example.com")); + all_headers.add(U("Host"), U("en.wikipedia.org")); + all_headers.add(U("If-Match"), U("\"737060cd8c284d8af7ad3082f209582d\"")); + all_headers.add(U("If-Modified-Since"), U("Sat, 29 Oct 1994 19:43:31 GMT")); + all_headers.add(U("If-None-Match"), U("\"737060cd8c284d8af7ad3082f209582d\"")); + all_headers.add(U("If-Range"), U("\"737060cd8c284d8af7ad3082f209582d\"")); + all_headers.add(U("If-Unmodified-Since"), U("Sat, 29 Oct 1994 19:43:31 GMT")); + all_headers.add(U("Max-Forwards"), U("10")); + all_headers.add(U("Origin"), U("http://www.example-social-network.com")); + all_headers.add(U("Pragma"), U("no-cache")); + all_headers.add(U("Proxy-Authorization"), U("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==")); + all_headers.add(U("Range"), U("bytes=500-999")); + all_headers.add(U("Referer"), U("http://en.wikipedia.org/wiki/Main_Page")); + all_headers.add(U("TE"), U("trailers, deflate")); + all_headers.add(U("User-Agent"), U("Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0")); + all_headers.add(U("Upgrade"), U("HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11")); + all_headers.add(U("Via"), U("1.0 fred, 1.1 example.com (Apache/1.1)")); + all_headers.add(U("Warning"), U("199 Miscellaneous warning")); + boost::asio::const_buffer cert(self_signed_cert, std::strlen(self_signed_cert)); boost::asio::const_buffer key(private_key, std::strlen(private_key)); @@ -503,9 +539,19 @@ XzJTD4slrGSJrcpLt/g/Jqqdjg== http_listener listener(m_secure_uri, server_config); listener.support(methods::GET, - [](http_request request) + [&](http_request request) { http_asserts::assert_request_equals(request, methods::GET, U("/")); + + for (auto&& h : all_headers) + { + std::cout << "HEADER - " << h.first << ": " << h.second << std::endl; + VERIFY_IS_TRUE(request.headers().has(h.first)); + VERIFY_ARE_EQUAL(h.second, request.headers().find(h.first)->second); + } + + VERIFY_ARE_EQUAL(body, request.extract_string(true).get()); + request.reply(status_codes::OK); }); @@ -522,6 +568,9 @@ XzJTD4slrGSJrcpLt/g/Jqqdjg== http_request msg(methods::GET); msg.set_request_uri(U("/")); + msg.headers() = all_headers; + msg.set_body(body); + http_asserts::assert_response_equals(client.request(msg).get(), status_codes::OK); listener.close().wait(); From dac2c165d899a0b99789accb19b3818f815329fc Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Apr 2016 19:07:14 -0700 Subject: [PATCH 075/609] Consolidate x509's into a single file. No need to have a file per (mutually exclusive) function. --- Release/src/CMakeLists.txt | 3 - Release/src/build/android.vcxitems | 1 - Release/src/build/android.vcxitems.filters | 3 - Release/src/build/other.vcxitems | 1 - Release/src/build/other.vcxitems.filters | 3 - Release/src/build/win32.vcxitems | 1 - Release/src/build/win32.vcxitems.filters | 3 - .../src/http/client/x509_cert_utilities.cpp | 391 +++++++++++++++++- .../client/x509_cert_utilities_android.cpp | 236 ----------- .../http/client/x509_cert_utilities_apple.cpp | 126 ------ .../http/client/x509_cert_utilities_win32.cpp | 105 ----- .../src/websockets/client/ws_client_wspp.cpp | 3 +- 12 files changed, 392 insertions(+), 484 deletions(-) delete mode 100644 Release/src/http/client/x509_cert_utilities_android.cpp delete mode 100644 Release/src/http/client/x509_cert_utilities_apple.cpp delete mode 100644 Release/src/http/client/x509_cert_utilities_win32.cpp diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index ade7c93b5b..0afb3b88df 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -40,14 +40,12 @@ if(UNIX) if(APPLE) list(APPEND SOURCES pplx/pplxapple.cpp - http/client/x509_cert_utilities_apple.cpp ) find_library(COREFOUNDATION CoreFoundation "/") find_library(SECURITY Security "/") set(EXTRALINKS ${COREFOUNDATION} ${SECURITY}) elseif(ANDROID) list(APPEND SOURCES - http/client/x509_cert_utilities_android.cpp pplx/pplxlinux.cpp ) else() @@ -62,7 +60,6 @@ elseif(WIN32) set(SOURCES ${SOURCES_COMMON} http/client/http_client_winhttp.cpp - http/client/x509_cert_utilities_win32.cpp http/listener/http_server_httpsys.cpp pplx/pplxwin.cpp streams/fileio_win32.cpp diff --git a/Release/src/build/android.vcxitems b/Release/src/build/android.vcxitems index e6febf2f9e..b838706244 100644 --- a/Release/src/build/android.vcxitems +++ b/Release/src/build/android.vcxitems @@ -15,7 +15,6 @@ - diff --git a/Release/src/build/android.vcxitems.filters b/Release/src/build/android.vcxitems.filters index 28951ec63a..a79b9de949 100644 --- a/Release/src/build/android.vcxitems.filters +++ b/Release/src/build/android.vcxitems.filters @@ -19,9 +19,6 @@ Source Files - - Source Files - diff --git a/Release/src/build/other.vcxitems b/Release/src/build/other.vcxitems index ff29aaf2bb..2199600b11 100644 --- a/Release/src/build/other.vcxitems +++ b/Release/src/build/other.vcxitems @@ -14,7 +14,6 @@ - diff --git a/Release/src/build/other.vcxitems.filters b/Release/src/build/other.vcxitems.filters index 486bba9f26..caa96f0b2a 100644 --- a/Release/src/build/other.vcxitems.filters +++ b/Release/src/build/other.vcxitems.filters @@ -12,8 +12,5 @@ Source Files - - Source Files - \ No newline at end of file diff --git a/Release/src/build/win32.vcxitems b/Release/src/build/win32.vcxitems index 5de0ce00ad..0d9e515317 100644 --- a/Release/src/build/win32.vcxitems +++ b/Release/src/build/win32.vcxitems @@ -15,7 +15,6 @@ - diff --git a/Release/src/build/win32.vcxitems.filters b/Release/src/build/win32.vcxitems.filters index 10063c1013..f32d09f1d2 100644 --- a/Release/src/build/win32.vcxitems.filters +++ b/Release/src/build/win32.vcxitems.filters @@ -13,9 +13,6 @@ Source Files - - Source Files - Source Files diff --git a/Release/src/http/client/x509_cert_utilities.cpp b/Release/src/http/client/x509_cert_utilities.cpp index fed486dcc2..fb1496125e 100644 --- a/Release/src/http/client/x509_cert_utilities.cpp +++ b/Release/src/http/client/x509_cert_utilities.cpp @@ -25,11 +25,29 @@ #include "stdafx.h" +#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) + #include "cpprest/details/x509_cert_utilities.h" +#if defined(ANDROID) || defined(__ANDROID__) +#include +#endif + +#if defined(__APPLE__) +#include +#include +#include +#include +#include +#endif + +#if defined(_WIN32) +#include +#include +#endif + namespace web { namespace http { namespace client { namespace details { -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verifyCtx, const std::string &hostName) { X509_STORE_CTX *storeContext = verifyCtx.native_handle(); @@ -83,6 +101,377 @@ bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verif #endif return verify_result; } + +#if defined(ANDROID) || defined(__ANDROID__) +/// +/// Helper function to check return value and see if any exceptions +/// occurred when calling a JNI function. +/// +/// true if JNI call failed, false otherwise. +static bool jni_failed(JNIEnv *env) +{ + if(env->ExceptionOccurred()) + { + // Clear exception otherwise no other JNI functions can be called. + // In the future if we improve error reporting the exception message + // can be retrieved from here. + env->ExceptionClear(); + return true; + } + return false; +} +template +static bool jni_failed(JNIEnv *env, const java_local_ref &result) +{ + if(jni_failed(env) || !result) + { + return true; + } + return false; +} +static bool jni_failed(JNIEnv *env, const jmethodID &result) +{ + if(jni_failed(env) || result == nullptr) + { + return true; + } + return false; +} +#define CHECK_JREF(env, obj) if(jni_failed(env, obj)) return false; +#define CHECK_JMID(env, mid) if(jni_failed(env, mid)) return false; +#define CHECK_JNI(env) if(jni_failed(env)) return false; + +bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName) +{ + JNIEnv* env = get_jvm_env(); + + // Possible performance improvement: + // In the future we could gain performance by turning all the jclass local + // references into global references. Then we could lazy initialize and + // save them globally. If this is done I'm not exactly sure where the release + // should be. + + // ByteArrayInputStream + java_local_ref byteArrayInputStreamClass(env->FindClass("java/io/ByteArrayInputStream")); + CHECK_JREF(env, byteArrayInputStreamClass); + jmethodID byteArrayInputStreamConstructorMethod = env->GetMethodID( + byteArrayInputStreamClass.get(), + "", + "([B)V"); + CHECK_JMID(env, byteArrayInputStreamConstructorMethod); + + // CertificateFactory + java_local_ref certificateFactoryClass(env->FindClass("java/security/cert/CertificateFactory")); + CHECK_JREF(env, certificateFactoryClass); + jmethodID certificateFactoryGetInstanceMethod = env->GetStaticMethodID( + certificateFactoryClass.get(), + "getInstance", + "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); + CHECK_JMID(env, certificateFactoryGetInstanceMethod); + jmethodID generateCertificateMethod = env->GetMethodID( + certificateFactoryClass.get(), + "generateCertificate", + "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); + CHECK_JMID(env, generateCertificateMethod); + + // X509Certificate + java_local_ref X509CertificateClass(env->FindClass("java/security/cert/X509Certificate")); + CHECK_JREF(env, X509CertificateClass); + + // TrustManagerFactory + java_local_ref trustManagerFactoryClass(env->FindClass("javax/net/ssl/TrustManagerFactory")); + CHECK_JREF(env, trustManagerFactoryClass); + jmethodID trustManagerFactoryGetInstanceMethod = env->GetStaticMethodID( + trustManagerFactoryClass.get(), + "getInstance", + "(Ljava/lang/String;)Ljavax/net/ssl/TrustManagerFactory;"); + CHECK_JMID(env, trustManagerFactoryGetInstanceMethod); + jmethodID trustManagerFactoryInitMethod = env->GetMethodID( + trustManagerFactoryClass.get(), + "init", + "(Ljava/security/KeyStore;)V"); + CHECK_JMID(env, trustManagerFactoryInitMethod); + jmethodID trustManagerFactoryGetTrustManagersMethod = env->GetMethodID( + trustManagerFactoryClass.get(), + "getTrustManagers", + "()[Ljavax/net/ssl/TrustManager;"); + CHECK_JMID(env, trustManagerFactoryGetTrustManagersMethod); + + // X509TrustManager + java_local_ref X509TrustManagerClass(env->FindClass("javax/net/ssl/X509TrustManager")); + CHECK_JREF(env, X509TrustManagerClass); + jmethodID X509TrustManagerCheckServerTrustedMethod = env->GetMethodID( + X509TrustManagerClass.get(), + "checkServerTrusted", + "([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V"); + CHECK_JMID(env, X509TrustManagerCheckServerTrustedMethod); + + // StrictHostnameVerifier + java_local_ref strictHostnameVerifierClass(env->FindClass("org/apache/http/conn/ssl/StrictHostnameVerifier")); + CHECK_JREF(env, strictHostnameVerifierClass); + jmethodID strictHostnameVerifierConstructorMethod = env->GetMethodID(strictHostnameVerifierClass.get(), "", "()V"); + CHECK_JMID(env, strictHostnameVerifierConstructorMethod); + jmethodID strictHostnameVerifierVerifyMethod = env->GetMethodID( + strictHostnameVerifierClass.get(), + "verify", + "(Ljava/lang/String;Ljava/security/cert/X509Certificate;)V"); + CHECK_JMID(env, strictHostnameVerifierVerifyMethod); + + // Create CertificateFactory + java_local_ref XDot509String(env->NewStringUTF("X.509")); + CHECK_JREF(env, XDot509String); + java_local_ref certificateFactory(env->CallStaticObjectMethod( + certificateFactoryClass.get(), + certificateFactoryGetInstanceMethod, + XDot509String.get())); + CHECK_JREF(env, certificateFactory); + + // Create Java array to store all the certs in. + java_local_ref certsArray(env->NewObjectArray(certChain.size(), X509CertificateClass.get(), nullptr)); + CHECK_JREF(env, certsArray); + + // For each certificate perform the following steps: + // 1. Create ByteArrayInputStream backed by DER certificate bytes + // 2. Create Certificate using CertificateFactory.generateCertificate + // 3. Add Certificate to array + int i = 0; + for(const auto &certData : certChain) + { + java_local_ref byteArray(env->NewByteArray(certData.size())); + CHECK_JREF(env, byteArray); + env->SetByteArrayRegion(byteArray.get(), 0, certData.size(), reinterpret_cast(certData.c_str())); + CHECK_JNI(env); + java_local_ref byteArrayInputStream(env->NewObject( + byteArrayInputStreamClass.get(), + byteArrayInputStreamConstructorMethod, + byteArray.get())); + CHECK_JREF(env, byteArrayInputStream); + + java_local_ref cert(env->CallObjectMethod( + certificateFactory.get(), + generateCertificateMethod, + byteArrayInputStream.get())); + CHECK_JREF(env, cert); + + env->SetObjectArrayElement(certsArray.get(), i, cert.get()); + CHECK_JNI(env); + ++i; + } + + // Create TrustManagerFactory, init with Android system certs + java_local_ref X509String(env->NewStringUTF("X509")); + CHECK_JREF(env, X509String); + java_local_ref trustFactoryManager(env->CallStaticObjectMethod( + trustManagerFactoryClass.get(), + trustManagerFactoryGetInstanceMethod, + X509String.get())); + CHECK_JREF(env, trustFactoryManager); + env->CallVoidMethod(trustFactoryManager.get(), trustManagerFactoryInitMethod, nullptr); + CHECK_JNI(env); + + // Get TrustManager + java_local_ref trustManagerArray(static_cast( + env->CallObjectMethod(trustFactoryManager.get(), trustManagerFactoryGetTrustManagersMethod))); + CHECK_JREF(env, trustManagerArray); + java_local_ref trustManager(env->GetObjectArrayElement(trustManagerArray.get(), 0)); + CHECK_JREF(env, trustManager); + + // Validate certificate chain. + java_local_ref RSAString(env->NewStringUTF("RSA")); + CHECK_JREF(env, RSAString); + env->CallVoidMethod( + trustManager.get(), + X509TrustManagerCheckServerTrustedMethod, + certsArray.get(), + RSAString.get()); + CHECK_JNI(env); + + // Verify hostname on certificate according to RFC 2818. + java_local_ref hostnameVerifier(env->NewObject( + strictHostnameVerifierClass.get(), strictHostnameVerifierConstructorMethod)); + CHECK_JREF(env, hostnameVerifier); + java_local_ref hostNameString(env->NewStringUTF(hostName.c_str())); + CHECK_JREF(env, hostNameString); + java_local_ref cert(env->GetObjectArrayElement(certsArray.get(), 0)); + CHECK_JREF(env, cert); + env->CallVoidMethod( + hostnameVerifier.get(), + strictHostnameVerifierVerifyMethod, + hostNameString.get(), + cert.get()); + CHECK_JNI(env); + + return true; +} +#endif + +#if defined(__APPLE__) +namespace { + // Simple RAII pattern wrapper to perform CFRelease on objects. + template + class cf_ref + { + public: + cf_ref(T v) : value(v) + { + static_assert(sizeof(cf_ref) == sizeof(T), "Code assumes just a wrapper, see usage in CFArrayCreate below."); + } + cf_ref() : value(nullptr) {} + cf_ref(cf_ref &&other) : value(other.value) { other.value = nullptr; } + + ~cf_ref() + { + if(value != nullptr) + { + CFRelease(value); + } + } + + T & get() + { + return value; + } + private: + cf_ref(const cf_ref &); + cf_ref & operator=(const cf_ref &); + T value; + }; +} + +bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName) +{ + // Build up CFArrayRef with all the certificates. + // All this code is basically just to get into the correct structures for the Apple APIs. + // Copies are avoided whenever possible. + std::vector> certs; + for(const auto & certBuf : certChain) + { + cf_ref certDataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + reinterpret_cast(certBuf.c_str()), + certBuf.size(), + kCFAllocatorNull); + if(certDataRef.get() == nullptr) + { + return false; + } + + cf_ref certObj = SecCertificateCreateWithData(nullptr, certDataRef.get()); + if(certObj.get() == nullptr) + { + return false; + } + certs.push_back(std::move(certObj)); + } + cf_ref certsArray = CFArrayCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&certs[0])), certs.size(), nullptr); + if(certsArray.get() == nullptr) + { + return false; + } + + // Create trust management object with certificates and SSL policy. + // Note: SecTrustCreateWithCertificates expects the certificate to be + // verified is the first element. + cf_ref cfHostName = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, + hostName.c_str(), + kCFStringEncodingASCII, + kCFAllocatorNull); + if(cfHostName.get() == nullptr) + { + return false; + } + cf_ref policy = SecPolicyCreateSSL(true /* client side */, cfHostName.get()); + cf_ref trust; + OSStatus status = SecTrustCreateWithCertificates(certsArray.get(), policy.get(), &trust.get()); + if(status == noErr) + { + // Perform actual certificate verification. + SecTrustResultType trustResult; + status = SecTrustEvaluate(trust.get(), &trustResult); + if(status == noErr && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) + { + return true; + } + } + + return false; +} #endif +#if defined(_WIN32) +namespace { + // Helper RAII unique_ptrs to free Windows structures. + struct cert_free_certificate_context + { + void operator()(const CERT_CONTEXT *ctx) const + { + CertFreeCertificateContext(ctx); + } + }; + typedef std::unique_ptr cert_context; + struct cert_free_certificate_chain + { + void operator()(const CERT_CHAIN_CONTEXT *chain) const + { + CertFreeCertificateChain(chain); + } + }; + typedef std::unique_ptr chain_context; +} + +bool verify_X509_cert_chain(const std::vector &certChain, const std::string &) +{ + // Create certificate context from server certificate. + cert_context cert(CertCreateCertificateContext( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + reinterpret_cast(certChain[0].c_str()), + static_cast(certChain[0].size()))); + if (cert == nullptr) + { + return false; + } + + // Let the OS build a certificate chain from the server certificate. + CERT_CHAIN_PARA params; + ZeroMemory(¶ms, sizeof(params)); + params.cbSize = sizeof(CERT_CHAIN_PARA); + params.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; + LPSTR usages [] = + { + szOID_PKIX_KP_SERVER_AUTH, + + // For older servers and to match IE. + szOID_SERVER_GATED_CRYPTO, + szOID_SGC_NETSCAPE + }; + params.RequestedUsage.Usage.cUsageIdentifier = std::extent::value; + params.RequestedUsage.Usage.rgpszUsageIdentifier = usages; + PCCERT_CHAIN_CONTEXT chainContext; + chain_context chain; + if (!CertGetCertificateChain( + nullptr, + cert.get(), + nullptr, + nullptr, + ¶ms, + CERT_CHAIN_REVOCATION_CHECK_CHAIN, + nullptr, + &chainContext)) + { + return false; + } + chain.reset(chainContext); + + // Check to see if the certificate chain is actually trusted. + if (chain->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) + { + return false; + } + + return true; +} +#endif + + }}}} + +#endif diff --git a/Release/src/http/client/x509_cert_utilities_android.cpp b/Release/src/http/client/x509_cert_utilities_android.cpp deleted file mode 100644 index 916582b222..0000000000 --- a/Release/src/http/client/x509_cert_utilities_android.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/*** -* ==++== -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* Contains utility functions for helping to verify server certificates on Android. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#include "stdafx.h" - -#include "cpprest/details/x509_cert_utilities.h" - -#include -using namespace crossplat; - -namespace web { namespace http { namespace client { namespace details { - -/// -/// Helper function to check return value and see if any exceptions -/// occurred when calling a JNI function. -/// -/// true if JNI call failed, false otherwise. -bool jni_failed(JNIEnv *env) -{ - if(env->ExceptionOccurred()) - { - // Clear exception otherwise no other JNI functions can be called. - // In the future if we improve error reporting the exception message - // can be retrieved from here. - env->ExceptionClear(); - return true; - } - return false; -} -template -bool jni_failed(JNIEnv *env, const java_local_ref &result) -{ - if(jni_failed(env) || !result) - { - return true; - } - return false; -} -bool jni_failed(JNIEnv *env, const jmethodID &result) -{ - if(jni_failed(env) || result == nullptr) - { - return true; - } - return false; -} -#define CHECK_JREF(env, obj) if(jni_failed(env, obj)) return false; -#define CHECK_JMID(env, mid) if(jni_failed(env, mid)) return false; -#define CHECK_JNI(env) if(jni_failed(env)) return false; - -bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName) -{ - JNIEnv* env = get_jvm_env(); - - // Possible performance improvement: - // In the future we could gain performance by turning all the jclass local - // references into global references. Then we could lazy initialize and - // save them globally. If this is done I'm not exactly sure where the release - // should be. - - // ByteArrayInputStream - java_local_ref byteArrayInputStreamClass(env->FindClass("java/io/ByteArrayInputStream")); - CHECK_JREF(env, byteArrayInputStreamClass); - jmethodID byteArrayInputStreamConstructorMethod = env->GetMethodID( - byteArrayInputStreamClass.get(), - "", - "([B)V"); - CHECK_JMID(env, byteArrayInputStreamConstructorMethod); - - // CertificateFactory - java_local_ref certificateFactoryClass(env->FindClass("java/security/cert/CertificateFactory")); - CHECK_JREF(env, certificateFactoryClass); - jmethodID certificateFactoryGetInstanceMethod = env->GetStaticMethodID( - certificateFactoryClass.get(), - "getInstance", - "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); - CHECK_JMID(env, certificateFactoryGetInstanceMethod); - jmethodID generateCertificateMethod = env->GetMethodID( - certificateFactoryClass.get(), - "generateCertificate", - "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); - CHECK_JMID(env, generateCertificateMethod); - - // X509Certificate - java_local_ref X509CertificateClass(env->FindClass("java/security/cert/X509Certificate")); - CHECK_JREF(env, X509CertificateClass); - - // TrustManagerFactory - java_local_ref trustManagerFactoryClass(env->FindClass("javax/net/ssl/TrustManagerFactory")); - CHECK_JREF(env, trustManagerFactoryClass); - jmethodID trustManagerFactoryGetInstanceMethod = env->GetStaticMethodID( - trustManagerFactoryClass.get(), - "getInstance", - "(Ljava/lang/String;)Ljavax/net/ssl/TrustManagerFactory;"); - CHECK_JMID(env, trustManagerFactoryGetInstanceMethod); - jmethodID trustManagerFactoryInitMethod = env->GetMethodID( - trustManagerFactoryClass.get(), - "init", - "(Ljava/security/KeyStore;)V"); - CHECK_JMID(env, trustManagerFactoryInitMethod); - jmethodID trustManagerFactoryGetTrustManagersMethod = env->GetMethodID( - trustManagerFactoryClass.get(), - "getTrustManagers", - "()[Ljavax/net/ssl/TrustManager;"); - CHECK_JMID(env, trustManagerFactoryGetTrustManagersMethod); - - // X509TrustManager - java_local_ref X509TrustManagerClass(env->FindClass("javax/net/ssl/X509TrustManager")); - CHECK_JREF(env, X509TrustManagerClass); - jmethodID X509TrustManagerCheckServerTrustedMethod = env->GetMethodID( - X509TrustManagerClass.get(), - "checkServerTrusted", - "([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V"); - CHECK_JMID(env, X509TrustManagerCheckServerTrustedMethod); - - // StrictHostnameVerifier - java_local_ref strictHostnameVerifierClass(env->FindClass("org/apache/http/conn/ssl/StrictHostnameVerifier")); - CHECK_JREF(env, strictHostnameVerifierClass); - jmethodID strictHostnameVerifierConstructorMethod = env->GetMethodID(strictHostnameVerifierClass.get(), "", "()V"); - CHECK_JMID(env, strictHostnameVerifierConstructorMethod); - jmethodID strictHostnameVerifierVerifyMethod = env->GetMethodID( - strictHostnameVerifierClass.get(), - "verify", - "(Ljava/lang/String;Ljava/security/cert/X509Certificate;)V"); - CHECK_JMID(env, strictHostnameVerifierVerifyMethod); - - // Create CertificateFactory - java_local_ref XDot509String(env->NewStringUTF("X.509")); - CHECK_JREF(env, XDot509String); - java_local_ref certificateFactory(env->CallStaticObjectMethod( - certificateFactoryClass.get(), - certificateFactoryGetInstanceMethod, - XDot509String.get())); - CHECK_JREF(env, certificateFactory); - - // Create Java array to store all the certs in. - java_local_ref certsArray(env->NewObjectArray(certChain.size(), X509CertificateClass.get(), nullptr)); - CHECK_JREF(env, certsArray); - - // For each certificate perform the following steps: - // 1. Create ByteArrayInputStream backed by DER certificate bytes - // 2. Create Certificate using CertificateFactory.generateCertificate - // 3. Add Certificate to array - int i = 0; - for(const auto &certData : certChain) - { - java_local_ref byteArray(env->NewByteArray(certData.size())); - CHECK_JREF(env, byteArray); - env->SetByteArrayRegion(byteArray.get(), 0, certData.size(), reinterpret_cast(certData.c_str())); - CHECK_JNI(env); - java_local_ref byteArrayInputStream(env->NewObject( - byteArrayInputStreamClass.get(), - byteArrayInputStreamConstructorMethod, - byteArray.get())); - CHECK_JREF(env, byteArrayInputStream); - - java_local_ref cert(env->CallObjectMethod( - certificateFactory.get(), - generateCertificateMethod, - byteArrayInputStream.get())); - CHECK_JREF(env, cert); - - env->SetObjectArrayElement(certsArray.get(), i, cert.get()); - CHECK_JNI(env); - ++i; - } - - // Create TrustManagerFactory, init with Android system certs - java_local_ref X509String(env->NewStringUTF("X509")); - CHECK_JREF(env, X509String); - java_local_ref trustFactoryManager(env->CallStaticObjectMethod( - trustManagerFactoryClass.get(), - trustManagerFactoryGetInstanceMethod, - X509String.get())); - CHECK_JREF(env, trustFactoryManager); - env->CallVoidMethod(trustFactoryManager.get(), trustManagerFactoryInitMethod, nullptr); - CHECK_JNI(env); - - // Get TrustManager - java_local_ref trustManagerArray(static_cast( - env->CallObjectMethod(trustFactoryManager.get(), trustManagerFactoryGetTrustManagersMethod))); - CHECK_JREF(env, trustManagerArray); - java_local_ref trustManager(env->GetObjectArrayElement(trustManagerArray.get(), 0)); - CHECK_JREF(env, trustManager); - - // Validate certificate chain. - java_local_ref RSAString(env->NewStringUTF("RSA")); - CHECK_JREF(env, RSAString); - env->CallVoidMethod( - trustManager.get(), - X509TrustManagerCheckServerTrustedMethod, - certsArray.get(), - RSAString.get()); - CHECK_JNI(env); - - // Verify hostname on certificate according to RFC 2818. - java_local_ref hostnameVerifier(env->NewObject( - strictHostnameVerifierClass.get(), strictHostnameVerifierConstructorMethod)); - CHECK_JREF(env, hostnameVerifier); - java_local_ref hostNameString(env->NewStringUTF(hostName.c_str())); - CHECK_JREF(env, hostNameString); - java_local_ref cert(env->GetObjectArrayElement(certsArray.get(), 0)); - CHECK_JREF(env, cert); - env->CallVoidMethod( - hostnameVerifier.get(), - strictHostnameVerifierVerifyMethod, - hostNameString.get(), - cert.get()); - CHECK_JNI(env); - - return true; -} - -}}}} \ No newline at end of file diff --git a/Release/src/http/client/x509_cert_utilities_apple.cpp b/Release/src/http/client/x509_cert_utilities_apple.cpp deleted file mode 100644 index c311144d56..0000000000 --- a/Release/src/http/client/x509_cert_utilities_apple.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/*** -* ==++== -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* Contains utility functions for helping to verify server certificates on OSX/iOS. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#include "stdafx.h" - -#include "cpprest/details/x509_cert_utilities.h" - -#include -#include -#include -#include -#include - -namespace web { namespace http { namespace client { namespace details { - -// Simple RAII pattern wrapper to perform CFRelease on objects. -template -class cf_ref -{ -public: - cf_ref(T v) : value(v) - { - static_assert(sizeof(cf_ref) == sizeof(T), "Code assumes just a wrapper, see usage in CFArrayCreate below."); - } - cf_ref() : value(nullptr) {} - cf_ref(cf_ref &&other) : value(other.value) { other.value = nullptr; } - - ~cf_ref() - { - if(value != nullptr) - { - CFRelease(value); - } - } - - T & get() - { - return value; - } -private: - cf_ref(const cf_ref &); - cf_ref & operator=(const cf_ref &); - T value; -}; - -bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName) -{ - // Build up CFArrayRef with all the certificates. - // All this code is basically just to get into the correct structures for the Apple APIs. - // Copies are avoided whenever possible. - std::vector> certs; - for(const auto & certBuf : certChain) - { - cf_ref certDataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, - reinterpret_cast(certBuf.c_str()), - certBuf.size(), - kCFAllocatorNull); - if(certDataRef.get() == nullptr) - { - return false; - } - - cf_ref certObj = SecCertificateCreateWithData(nullptr, certDataRef.get()); - if(certObj.get() == nullptr) - { - return false; - } - certs.push_back(std::move(certObj)); - } - cf_ref certsArray = CFArrayCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&certs[0])), certs.size(), nullptr); - if(certsArray.get() == nullptr) - { - return false; - } - - // Create trust management object with certificates and SSL policy. - // Note: SecTrustCreateWithCertificates expects the certificate to be - // verified is the first element. - cf_ref cfHostName = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, - hostName.c_str(), - kCFStringEncodingASCII, - kCFAllocatorNull); - if(cfHostName.get() == nullptr) - { - return false; - } - cf_ref policy = SecPolicyCreateSSL(true /* client side */, cfHostName.get()); - cf_ref trust; - OSStatus status = SecTrustCreateWithCertificates(certsArray.get(), policy.get(), &trust.get()); - if(status == noErr) - { - // Perform actual certificate verification. - SecTrustResultType trustResult; - status = SecTrustEvaluate(trust.get(), &trustResult); - if(status == noErr && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) - { - return true; - } - } - - return false; -} - -}}}} \ No newline at end of file diff --git a/Release/src/http/client/x509_cert_utilities_win32.cpp b/Release/src/http/client/x509_cert_utilities_win32.cpp deleted file mode 100644 index cd2b671424..0000000000 --- a/Release/src/http/client/x509_cert_utilities_win32.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/*** -* ==++== -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* Contains utility functions for helping to verify server certificates on Windows desktop. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#include "stdafx.h" - -#include "cpprest/details/x509_cert_utilities.h" - -#include -#include - -namespace web { namespace http { namespace client { namespace details { - -// Helper RAII unique_ptrs to free Windows structures. -struct cert_free_certificate_context -{ - void operator()(const CERT_CONTEXT *ctx) const - { - CertFreeCertificateContext(ctx); - } -}; -typedef std::unique_ptr cert_context; -struct cert_free_certificate_chain -{ - void operator()(const CERT_CHAIN_CONTEXT *chain) const - { - CertFreeCertificateChain(chain); - } -}; -typedef std::unique_ptr chain_context; - -bool verify_X509_cert_chain(const std::vector &certChain, const std::string &) -{ - // Create certificate context from server certificate. - cert_context cert(CertCreateCertificateContext( - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - reinterpret_cast(certChain[0].c_str()), - static_cast(certChain[0].size()))); - if (cert == nullptr) - { - return false; - } - - // Let the OS build a certificate chain from the server certificate. - CERT_CHAIN_PARA params; - ZeroMemory(¶ms, sizeof(params)); - params.cbSize = sizeof(CERT_CHAIN_PARA); - params.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; - LPSTR usages [] = - { - szOID_PKIX_KP_SERVER_AUTH, - - // For older servers and to match IE. - szOID_SERVER_GATED_CRYPTO, - szOID_SGC_NETSCAPE - }; - params.RequestedUsage.Usage.cUsageIdentifier = std::extent::value; - params.RequestedUsage.Usage.rgpszUsageIdentifier = usages; - PCCERT_CHAIN_CONTEXT chainContext; - chain_context chain; - if (!CertGetCertificateChain( - nullptr, - cert.get(), - nullptr, - nullptr, - ¶ms, - CERT_CHAIN_REVOCATION_CHECK_CHAIN, - nullptr, - &chainContext)) - { - return false; - } - chain.reset(chainContext); - - // Check to see if the certificate chain is actually trusted. - if (chain->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) - { - return false; - } - - return true; -} - -}}}} \ No newline at end of file diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index e8f5d2edbe..81512bc89f 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -24,10 +24,11 @@ ****/ #include "stdafx.h" -#include "cpprest/details/x509_cert_utilities.h" #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) +#include "cpprest/details/x509_cert_utilities.h" + // Force websocketpp to use C++ std::error_code instead of Boost. #define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_ #if defined(__GNUC__) From 2b79bd325e902d0ba371f9495f691269d30e741f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Apr 2016 19:10:36 -0700 Subject: [PATCH 076/609] Declaration for verify_x509_cert_chain does not need external linkage. --- Release/include/cpprest/details/x509_cert_utilities.h | 5 +---- Release/src/http/client/x509_cert_utilities.cpp | 3 +++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Release/include/cpprest/details/x509_cert_utilities.h b/Release/include/cpprest/details/x509_cert_utilities.h index b9e60df880..5cfa561be5 100644 --- a/Release/include/cpprest/details/x509_cert_utilities.h +++ b/Release/include/cpprest/details/x509_cert_utilities.h @@ -25,7 +25,6 @@ #pragma once -#include #include #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) @@ -52,13 +51,11 @@ namespace web { namespace http { namespace client { namespace details { /// Using platform specific APIs verifies server certificate. /// Currently implemented to work on iOS, Android, and OS X. /// -/// Boost.ASIO context get certificate chain from. +/// Boost.ASIO context to get certificate chain from. /// Host name from the URI. /// True if verification passed and server can be trusted, false otherwise. bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verifyCtx, const std::string &hostName); -bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName); - }}}} #endif \ No newline at end of file diff --git a/Release/src/http/client/x509_cert_utilities.cpp b/Release/src/http/client/x509_cert_utilities.cpp index fb1496125e..8f92bfa103 100644 --- a/Release/src/http/client/x509_cert_utilities.cpp +++ b/Release/src/http/client/x509_cert_utilities.cpp @@ -28,6 +28,7 @@ #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) #include "cpprest/details/x509_cert_utilities.h" +#include #if defined(ANDROID) || defined(__ANDROID__) #include @@ -48,6 +49,8 @@ namespace web { namespace http { namespace client { namespace details { +static bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName); + bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verifyCtx, const std::string &hostName) { X509_STORE_CTX *storeContext = verifyCtx.native_handle(); From 6f5f815ddf7ff69743af2ee7b0e9b11e7038bec2 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Apr 2016 19:42:33 -0700 Subject: [PATCH 077/609] Move definitions from http_helpers into http_msg, removing external declarations --- .../include/cpprest/details/http_helpers.h | 21 --- Release/src/http/common/http_helpers.cpp | 139 ---------------- Release/src/http/common/http_msg.cpp | 157 +++++++++++++++++- 3 files changed, 156 insertions(+), 161 deletions(-) diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 3e231f5871..0cd1ae344e 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -60,27 +60,6 @@ namespace details #undef DAT }; - /// - /// Determines whether or not the given content type is 'textual' according the feature specifications. - /// - bool is_content_type_textual(const utility::string_t &content_type); - - /// - /// Determines whether or not the given content type is JSON according the feature specifications. - /// - bool is_content_type_json(const utility::string_t &content_type); - - /// - /// Parses the given Content-Type header value to get out actual content type and charset. - /// If the charset isn't specified the default charset for the content type will be set. - /// - void parse_content_type_and_charset(const utility::string_t &content_type, utility::string_t &content, utility::string_t &charset); - - /// - /// Gets the default charset for given content type. If the MIME type is not textual or recognized Latin1 will be returned. - /// - utility::string_t get_default_charset(const utility::string_t &content_type); - /// /// Helper function to get the default HTTP reason phrase for a status code. /// diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index a80f2ad1bf..00cefeffd2 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -34,145 +34,6 @@ namespace web { namespace http namespace details { -bool is_content_type_one_of(const utility::string_t *first, const utility::string_t *last, const utility::string_t &value) -{ - while (first != last) - { - if (utility::details::str_icmp(*first, value)) - { - return true; - } - ++first; - } - return false; -} - -// Remove once VS 2013 is no longer supported. -#if defined(_WIN32) && _MSC_VER < 1900 -// Not referring to mime_types to avoid static initialization order fiasco. -static const utility::string_t textual_types [] = { - U("message/http"), - U("application/json"), - U("application/xml"), - U("application/atom+xml"), - U("application/http"), - U("application/x-www-form-urlencoded") -}; -#endif -bool is_content_type_textual(const utility::string_t &content_type) -{ -#if !defined(_WIN32) || _MSC_VER >= 1900 - static const utility::string_t textual_types [] = { - mime_types::message_http, - mime_types::application_json, - mime_types::application_xml, - mime_types::application_atom_xml, - mime_types::application_http, - mime_types::application_x_www_form_urlencoded - }; -#endif - - if (content_type.size() >= 4 && utility::details::str_icmp(content_type.substr(0, 4), _XPLATSTR("text"))) - { - return true; - } - return (is_content_type_one_of(std::begin(textual_types), std::end(textual_types), content_type)); -} - -// Remove once VS 2013 is no longer supported. -#if defined(_WIN32) && _MSC_VER < 1900 -// Not referring to mime_types to avoid static initialization order fiasco. -static const utility::string_t json_types [] = { - U("application/json"), - U("application/x-json"), - U("text/json"), - U("text/x-json"), - U("text/javascript"), - U("text/x-javascript"), - U("application/javascript"), - U("application/x-javascript") -}; -#endif -bool is_content_type_json(const utility::string_t &content_type) -{ -#if !defined(_WIN32) || _MSC_VER >= 1900 - static const utility::string_t json_types [] = { - mime_types::application_json, - mime_types::application_xjson, - mime_types::text_json, - mime_types::text_xjson, - mime_types::text_javascript, - mime_types::text_xjavascript, - mime_types::application_javascript, - mime_types::application_xjavascript - }; -#endif - - return (is_content_type_one_of(std::begin(json_types), std::end(json_types), content_type)); -} - -void parse_content_type_and_charset(const utility::string_t &content_type, utility::string_t &content, utility::string_t &charset) -{ - const size_t semi_colon_index = content_type.find_first_of(_XPLATSTR(";")); - - // No charset specified. - if (semi_colon_index == utility::string_t::npos) - { - content = content_type; - trim_whitespace(content); - charset = get_default_charset(content); - return; - } - - // Split into content type and second part which could be charset. - content = content_type.substr(0, semi_colon_index); - trim_whitespace(content); - utility::string_t possible_charset = content_type.substr(semi_colon_index + 1); - trim_whitespace(possible_charset); - const size_t equals_index = possible_charset.find_first_of(_XPLATSTR("=")); - - // No charset specified. - if (equals_index == utility::string_t::npos) - { - charset = get_default_charset(content); - return; - } - - // Split and make sure 'charset' - utility::string_t charset_key = possible_charset.substr(0, equals_index); - trim_whitespace(charset_key); - if (!utility::details::str_icmp(charset_key, _XPLATSTR("charset"))) - { - charset = get_default_charset(content); - return; - } - charset = possible_charset.substr(equals_index + 1); - // Remove the redundant ';' at the end of charset. - while (charset.back() == ';') - { - charset.pop_back(); - } - trim_whitespace(charset); - if (charset.front() == _XPLATSTR('"') && charset.back() == _XPLATSTR('"')) - { - charset = charset.substr(1, charset.size() - 2); - trim_whitespace(charset); - } -} - -utility::string_t get_default_charset(const utility::string_t &content_type) -{ - // We are defaulting everything to Latin1 except JSON which is utf-8. - if (is_content_type_json(content_type)) - { - return charset_types::utf8; - } - else - { - return charset_types::latin1; - } -} - // Remove once VS 2013 is no longer supported. #if defined(_WIN32) && _MSC_VER < 1900 static const http_status_to_phrase idToPhraseMap [] = { diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index c655f7a989..331db12b28 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -218,13 +218,168 @@ void http_msg_base::_complete(utility::size64_t body_size, const std::exception_ } } +static bool is_content_type_one_of(const utility::string_t *first, const utility::string_t *last, const utility::string_t &value) +{ + while (first != last) + { + if (utility::details::str_icmp(*first, value)) + { + return true; + } + ++first; + } + return false; +} + +// Remove once VS 2013 is no longer supported. +#if defined(_WIN32) && _MSC_VER < 1900 +// Not referring to mime_types to avoid static initialization order fiasco. +static const utility::string_t textual_types [] = { + U("message/http"), + U("application/json"), + U("application/xml"), + U("application/atom+xml"), + U("application/http"), + U("application/x-www-form-urlencoded") +}; +#endif + +/// +/// Determines whether or not the given content type is 'textual' according the feature specifications. +/// +static bool is_content_type_textual(const utility::string_t &content_type) +{ +#if !defined(_WIN32) || _MSC_VER >= 1900 + static const utility::string_t textual_types [] = { + mime_types::message_http, + mime_types::application_json, + mime_types::application_xml, + mime_types::application_atom_xml, + mime_types::application_http, + mime_types::application_x_www_form_urlencoded + }; +#endif + + if (content_type.size() >= 4 && utility::details::str_icmp(content_type.substr(0, 4), _XPLATSTR("text"))) + { + return true; + } + return (is_content_type_one_of(std::begin(textual_types), std::end(textual_types), content_type)); +} + +// Remove once VS 2013 is no longer supported. +#if defined(_WIN32) && _MSC_VER < 1900 +// Not referring to mime_types to avoid static initialization order fiasco. +static const utility::string_t json_types [] = { + U("application/json"), + U("application/x-json"), + U("text/json"), + U("text/x-json"), + U("text/javascript"), + U("text/x-javascript"), + U("application/javascript"), + U("application/x-javascript") +}; +#endif + +/// +/// Determines whether or not the given content type is JSON according the feature specifications. +/// +static bool is_content_type_json(const utility::string_t &content_type) +{ +#if !defined(_WIN32) || _MSC_VER >= 1900 + static const utility::string_t json_types [] = { + mime_types::application_json, + mime_types::application_xjson, + mime_types::text_json, + mime_types::text_xjson, + mime_types::text_javascript, + mime_types::text_xjavascript, + mime_types::application_javascript, + mime_types::application_xjavascript + }; +#endif + + return (is_content_type_one_of(std::begin(json_types), std::end(json_types), content_type)); +} + +/// +/// Gets the default charset for given content type. If the MIME type is not textual or recognized Latin1 will be returned. +/// +static utility::string_t get_default_charset(const utility::string_t &content_type) +{ + // We are defaulting everything to Latin1 except JSON which is utf-8. + if (is_content_type_json(content_type)) + { + return charset_types::utf8; + } + else + { + return charset_types::latin1; + } +} + + +/// +/// Parses the given Content-Type header value to get out actual content type and charset. +/// If the charset isn't specified the default charset for the content type will be set. +/// +static void parse_content_type_and_charset(const utility::string_t &content_type, utility::string_t &content, utility::string_t &charset) +{ + const size_t semi_colon_index = content_type.find_first_of(_XPLATSTR(";")); + + // No charset specified. + if (semi_colon_index == utility::string_t::npos) + { + content = content_type; + trim_whitespace(content); + charset = get_default_charset(content); + return; + } + + // Split into content type and second part which could be charset. + content = content_type.substr(0, semi_colon_index); + trim_whitespace(content); + utility::string_t possible_charset = content_type.substr(semi_colon_index + 1); + trim_whitespace(possible_charset); + const size_t equals_index = possible_charset.find_first_of(_XPLATSTR("=")); + + // No charset specified. + if (equals_index == utility::string_t::npos) + { + charset = get_default_charset(content); + return; + } + + // Split and make sure 'charset' + utility::string_t charset_key = possible_charset.substr(0, equals_index); + trim_whitespace(charset_key); + if (!utility::details::str_icmp(charset_key, _XPLATSTR("charset"))) + { + charset = get_default_charset(content); + return; + } + charset = possible_charset.substr(equals_index + 1); + // Remove the redundant ';' at the end of charset. + while (charset.back() == ';') + { + charset.pop_back(); + } + trim_whitespace(charset); + if (charset.front() == _XPLATSTR('"') && charset.back() == _XPLATSTR('"')) + { + charset = charset.substr(1, charset.size() - 2); + trim_whitespace(charset); + } +} + utility::string_t details::http_msg_base::parse_and_check_content_type(bool ignore_content_type, const std::function &check_content_type) { if (!instream()) { throw http_exception(stream_was_set_explicitly); } - + utility::string_t content, charset = charset_types::utf8; if (!ignore_content_type) { From 986946214d951671382cdf008373c5265d0aa039 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Apr 2016 19:50:33 -0700 Subject: [PATCH 078/609] Localized conversion functions from http_helpers.h to http_msg.cpp --- .../include/cpprest/details/http_helpers.h | 13 -- Release/src/http/common/http_helpers.cpp | 135 ----------------- Release/src/http/common/http_msg.cpp | 140 ++++++++++++++++++ 3 files changed, 140 insertions(+), 148 deletions(-) diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 0cd1ae344e..fd6c3c1ffa 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -65,19 +65,6 @@ namespace details /// utility::string_t get_default_reason_phrase(status_code code); - /// - /// Helper functions to convert a series of bytes from a charset to utf-8 or utf-16. - /// These APIs deal with checking for and handling byte order marker (BOM). - /// - utility::string_t convert_utf16_to_string_t(utf16string src); - utf16string convert_utf16_to_utf16(utf16string src); - std::string convert_utf16_to_utf8(utf16string src); - utility::string_t convert_utf16le_to_string_t(utf16string src, bool erase_bom); - std::string convert_utf16le_to_utf8(utf16string src, bool erase_bom); - utility::string_t convert_utf16be_to_string_t(utf16string src, bool erase_bom); - std::string convert_utf16be_to_utf8(utf16string src, bool erase_bom); - utf16string convert_utf16be_to_utf16le(utf16string src, bool erase_bom); - // simple helper functions to trim whitespace. _ASYNCRTIMP void __cdecl ltrim_whitespace(utility::string_t &str); _ASYNCRTIMP void __cdecl rtrim_whitespace(utility::string_t &str); diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index 00cefeffd2..a5baccf976 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -71,141 +71,6 @@ utility::string_t get_default_reason_phrase(status_code code) return phrase; } -// Helper function to determine byte order mark. -enum endian_ness -{ - little_endian, - big_endian, - unknown -}; -static endian_ness check_byte_order_mark(const utf16string &str) -{ - if (str.empty()) - { - return unknown; - } - const unsigned char *src = (const unsigned char *) &str[0]; - - // little endian - if (src[0] == 0xFF && src[1] == 0xFE) - { - return little_endian; - } - - // big endian - else if (src[0] == 0xFE && src[1] == 0xFF) - { - return big_endian; - } - - return unknown; -} - -utility::string_t convert_utf16_to_string_t(utf16string src) -{ -#ifdef _UTF16_STRINGS - return convert_utf16_to_utf16(std::move(src)); -#else - return convert_utf16_to_utf8(std::move(src)); -#endif -} - -std::string convert_utf16_to_utf8(utf16string src) -{ - const endian_ness endian = check_byte_order_mark(src); - switch (endian) - { - case little_endian: - return convert_utf16le_to_utf8(std::move(src), true); - case big_endian: - return convert_utf16be_to_utf8(std::move(src), true); - case unknown: - // unknown defaults to big endian. - return convert_utf16be_to_utf8(std::move(src), false); - } - __assume(0); -} - -utf16string convert_utf16_to_utf16(utf16string src) -{ - const endian_ness endian = check_byte_order_mark(src); - switch (endian) - { - case little_endian: - src.erase(0, 1); - return std::move(src); - case big_endian: - return convert_utf16be_to_utf16le(std::move(src), true); - case unknown: - // unknown defaults to big endian. - return convert_utf16be_to_utf16le(std::move(src), false); - } - __assume(0); -} - -std::string convert_utf16le_to_utf8(utf16string src, bool erase_bom) -{ - if (erase_bom && !src.empty()) - { - src.erase(0, 1); - } - return utf16_to_utf8(std::move(src)); -} - -utility::string_t convert_utf16le_to_string_t(utf16string src, bool erase_bom) -{ - if (erase_bom && !src.empty()) - { - src.erase(0, 1); - } -#ifdef _UTF16_STRINGS - return std::move(src); -#else - return utf16_to_utf8(std::move(src)); -#endif -} - -// Helper function to change endian ness from big endian to little endian -static utf16string big_endian_to_little_endian(utf16string src, bool erase_bom) -{ - if (erase_bom && !src.empty()) - { - src.erase(0, 1); - } - if (src.empty()) - { - return std::move(src); - } - - const size_t size = src.size(); - for (size_t i = 0; i < size; ++i) - { - utf16char ch = src[i]; - src[i] = static_cast(ch << 8); - src[i] = static_cast(src[i] | ch >> 8); - } - - return std::move(src); -} - -utility::string_t convert_utf16be_to_string_t(utf16string src, bool erase_bom) -{ -#ifdef _UTF16_STRINGS - return convert_utf16be_to_utf16le(std::move(src), erase_bom); -#else - return convert_utf16be_to_utf8(std::move(src), erase_bom); -#endif -} - -std::string convert_utf16be_to_utf8(utf16string src, bool erase_bom) -{ - return utf16_to_utf8(big_endian_to_little_endian(std::move(src), erase_bom)); -} - -utf16string convert_utf16be_to_utf16le(utf16string src, bool erase_bom) -{ - return big_endian_to_little_endian(std::move(src), erase_bom); -} void ltrim_whitespace(utility::string_t &str) { diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 331db12b28..615f640907 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -42,6 +42,146 @@ utility::string_t http_headers::content_type() const return result; } + + +/// Helper functions to convert a series of bytes from a charset to utf-8 or utf-16. +/// These APIs deal with checking for and handling byte order marker (BOM). +namespace { + enum endian_ness + { + little_endian, + big_endian, + unknown + }; + endian_ness check_byte_order_mark(const utf16string &str) + { + if (str.empty()) + { + return unknown; + } + const unsigned char *src = (const unsigned char *) &str[0]; + + // little endian + if (src[0] == 0xFF && src[1] == 0xFE) + { + return little_endian; + } + + // big endian + else if (src[0] == 0xFE && src[1] == 0xFF) + { + return big_endian; + } + + return unknown; + } + + std::string convert_utf16le_to_utf8(utf16string src, bool erase_bom) + { + if (erase_bom && !src.empty()) + { + src.erase(0, 1); + } + return utf16_to_utf8(std::move(src)); + } + + utility::string_t convert_utf16le_to_string_t(utf16string src, bool erase_bom) + { + if (erase_bom && !src.empty()) + { + src.erase(0, 1); + } + #ifdef _UTF16_STRINGS + return std::move(src); + #else + return utf16_to_utf8(std::move(src)); + #endif + } + + // Helper function to change endian ness from big endian to little endian + utf16string big_endian_to_little_endian(utf16string src, bool erase_bom) + { + if (erase_bom && !src.empty()) + { + src.erase(0, 1); + } + if (src.empty()) + { + return std::move(src); + } + + const size_t size = src.size(); + for (size_t i = 0; i < size; ++i) + { + utf16char ch = src[i]; + src[i] = static_cast(ch << 8); + src[i] = static_cast(src[i] | ch >> 8); + } + + return std::move(src); + } + + std::string convert_utf16be_to_utf8(utf16string src, bool erase_bom) + { + return utf16_to_utf8(big_endian_to_little_endian(std::move(src), erase_bom)); + } + + utf16string convert_utf16be_to_utf16le(utf16string src, bool erase_bom) + { + return big_endian_to_little_endian(std::move(src), erase_bom); + } + + utility::string_t convert_utf16be_to_string_t(utf16string src, bool erase_bom) + { + #ifdef _UTF16_STRINGS + return convert_utf16be_to_utf16le(std::move(src), erase_bom); + #else + return convert_utf16be_to_utf8(std::move(src), erase_bom); + #endif + } + + std::string convert_utf16_to_utf8(utf16string src) + { + const endian_ness endian = check_byte_order_mark(src); + switch (endian) + { + case little_endian: + return convert_utf16le_to_utf8(std::move(src), true); + case big_endian: + return convert_utf16be_to_utf8(std::move(src), true); + case unknown: + // unknown defaults to big endian. + return convert_utf16be_to_utf8(std::move(src), false); + } + __assume(0); + } + + utf16string convert_utf16_to_utf16(utf16string src) + { + const endian_ness endian = check_byte_order_mark(src); + switch (endian) + { + case little_endian: + src.erase(0, 1); + return std::move(src); + case big_endian: + return convert_utf16be_to_utf16le(std::move(src), true); + case unknown: + // unknown defaults to big endian. + return convert_utf16be_to_utf16le(std::move(src), false); + } + __assume(0); + } + utility::string_t convert_utf16_to_string_t(utf16string src) + { + #ifdef _UTF16_STRINGS + return convert_utf16_to_utf16(std::move(src)); + #else + return convert_utf16_to_utf8(std::move(src)); + #endif + } +} + void http_headers::set_content_type(utility::string_t type) { m_headers[http::header_names::content_type] = std::move(type); From 9b5ecb1301fd583c42841cd117a68dff654a2cf4 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Apr 2016 19:58:53 -0700 Subject: [PATCH 079/609] Move mime_types and charset_types to the header matching the defining cpp --- .../include/cpprest/details/http_helpers.h | 29 ------------------ Release/include/cpprest/http_msg.h | 30 +++++++++++++++++++ Release/src/http/common/http_helpers.cpp | 4 +-- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index fd6c3c1ffa..a7c589b996 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -34,45 +34,16 @@ namespace web { namespace http namespace details { - /// - /// Constants for MIME types. - /// - class mime_types - { - public: - #define _MIME_TYPES - #define DAT(a,b) _ASYNCRTIMP const static utility::string_t a; - #include "cpprest/details/http_constants.dat" - #undef _MIME_TYPES - #undef DAT - }; - - /// - /// Constants for charset types. - /// - class charset_types - { - public: - #define _CHARSET_TYPES - #define DAT(a,b) _ASYNCRTIMP const static utility::string_t a; - #include "cpprest/details/http_constants.dat" - #undef _CHARSET_TYPES - #undef DAT - }; - /// /// Helper function to get the default HTTP reason phrase for a status code. /// utility::string_t get_default_reason_phrase(status_code code); // simple helper functions to trim whitespace. - _ASYNCRTIMP void __cdecl ltrim_whitespace(utility::string_t &str); - _ASYNCRTIMP void __cdecl rtrim_whitespace(utility::string_t &str); _ASYNCRTIMP void __cdecl trim_whitespace(utility::string_t &str); bool validate_method(const utility::string_t& method); - namespace chunked_encoding { // Transfer-Encoding: chunked support diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 9ad32d937b..90669accc4 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -89,6 +89,36 @@ class status_codes #undef DAT }; +namespace details { + +/// +/// Constants for MIME types. +/// +class mime_types +{ +public: +#define _MIME_TYPES +#define DAT(a,b) _ASYNCRTIMP const static utility::string_t a; +#include "cpprest/details/http_constants.dat" +#undef _MIME_TYPES +#undef DAT +}; + +/// +/// Constants for charset types. +/// +class charset_types +{ +public: +#define _CHARSET_TYPES +#define DAT(a,b) _ASYNCRTIMP const static utility::string_t a; +#include "cpprest/details/http_constants.dat" +#undef _CHARSET_TYPES +#undef DAT +}; + +} + /// Message direction namespace message_direction { diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index a5baccf976..75ef626820 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -72,13 +72,13 @@ utility::string_t get_default_reason_phrase(status_code code) } -void ltrim_whitespace(utility::string_t &str) +static void ltrim_whitespace(utility::string_t &str) { size_t index; for (index = 0; index < str.size() && isspace(str[index]); ++index); str.erase(0, index); } -void rtrim_whitespace(utility::string_t &str) +static void rtrim_whitespace(utility::string_t &str) { size_t index; for (index = str.size(); index > 0 && isspace(str[index - 1]); --index); From d3391c8b503db3963fe06bf0126338203457ba06 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Apr 2016 19:59:47 -0700 Subject: [PATCH 080/609] http_helpers only uses string_t. --- Release/include/cpprest/details/http_helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index a7c589b996..0ef034b606 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -27,7 +27,7 @@ ****/ #pragma once -#include "cpprest/http_msg.h" +#include "cpprest/details/basic_types.h" namespace web { namespace http { From a0a0f8dbc606c54cf9c34a9f843b3ad8285e255d Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Apr 2016 22:11:24 -0700 Subject: [PATCH 081/609] Refactor http_client_impl.h to be internal. --- .../cpprest/details/http_client_impl.h | 466 ------------------ Release/include/cpprest/http_client.h | 24 +- Release/include/cpprest/http_headers.h | 14 + Release/src/CMakeLists.txt | 1 + Release/src/build/common.vcxitems | 5 +- Release/src/build/common.vcxitems.filters | 12 +- Release/src/http/client/http_client.cpp | 335 +++++++++++++ Release/src/http/client/http_client_asio.cpp | 2 +- Release/src/http/client/http_client_impl.h | 168 +++++++ .../src/http/client/http_client_winhttp.cpp | 19 +- Release/src/http/client/http_client_winrt.cpp | 6 +- Release/src/http/common/http_msg.cpp | 43 ++ 12 files changed, 604 insertions(+), 491 deletions(-) delete mode 100644 Release/include/cpprest/details/http_client_impl.h create mode 100644 Release/src/http/client/http_client.cpp create mode 100644 Release/src/http/client/http_client_impl.h diff --git a/Release/include/cpprest/details/http_client_impl.h b/Release/include/cpprest/details/http_client_impl.h deleted file mode 100644 index 2f88472a50..0000000000 --- a/Release/include/cpprest/details/http_client_impl.h +++ /dev/null @@ -1,466 +0,0 @@ -/*** -* ==++== -* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* HTTP Library: Client-side APIs, non-public declarations used in the implementation. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ -#pragma once - -#include "cpprest/details/basic_types.h" -#include "cpprest/details/http_helpers.h" - -#ifdef _WIN32 -# define CRLF _XPLATSTR("\r\n") -#else -# define CRLF std::string("\r\n") -#endif - -namespace web { namespace http { namespace client { namespace details -{ - -#ifdef _WIN32 -static const utility::char_t * get_with_body = _XPLATSTR("A GET or HEAD request should not have an entity body."); - -// Helper function to trim leading and trailing null characters from a string. -static void trim_nulls(utility::string_t &str) -{ - size_t index; - for(index = 0; index < str.size() && str[index] == 0; ++index); - str.erase(0, index); - for(index = str.size(); index > 0 && str[index - 1] == 0; --index); - str.erase(index); -} - -#endif - -// Flatten the http_headers into a name:value pairs separated by a carriage return and line feed. -static utility::string_t flatten_http_headers(const http_headers &headers) -{ - utility::string_t flattened_headers; - for(auto iter = headers.begin(); iter != headers.end(); ++iter) - { - flattened_headers.append(iter->first); - flattened_headers.push_back(':'); - flattened_headers.append(iter->second); - flattened_headers.append(CRLF); - } - return flattened_headers; -} - -#ifdef _WIN32 -/// -/// Parses a string containing Http headers. -/// -static void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers) -{ - utf16char *context = nullptr; - utf16char *line = wcstok_s(headersStr, CRLF, &context); - while(line != nullptr) - { - const utility::string_t header_line(line); - const size_t colonIndex = header_line.find_first_of(_XPLATSTR(":")); - if(colonIndex != utility::string_t::npos) - { - utility::string_t key = header_line.substr(0, colonIndex); - utility::string_t value = header_line.substr(colonIndex + 1, header_line.length() - colonIndex - 1); - http::details::trim_whitespace(key); - http::details::trim_whitespace(value); - headers.add(key, value); - } - line = wcstok_s(nullptr, CRLF, &context); - } -} -#endif - -class _http_client_communicator; - -// Request context encapsulating everything necessary for creating and responding to a request. -class request_context -{ -public: - - // Destructor to clean up any held resources. - virtual ~request_context() - { - } - - void complete_headers() - { - // We have already read (and transmitted) the request body. Should we explicitly close the stream? - // Well, there are test cases that assumes that the istream is valid when t receives the response! - // For now, we will drop our reference which will close the stream if the user doesn't have one. - m_request.set_body(Concurrency::streams::istream()); - m_request_completion.set(m_response); - } - - /// - /// Completes this request, setting the underlying task completion event, and cleaning up the handles - /// - void complete_request(utility::size64_t body_size) - { - m_response._get_impl()->_complete(body_size); - - finish(); - } - - void report_error(unsigned long error_code, const std::string &errorMessage) - { - report_exception(http_exception(static_cast(error_code), errorMessage)); - } - -#ifdef _WIN32 - void report_error(unsigned long error_code, const std::wstring &errorMessage) - { - report_exception(http_exception(static_cast(error_code), errorMessage)); - } -#endif - - template - void report_exception(const _ExceptionType &e) - { - report_exception(std::make_exception_ptr(e)); - } - - virtual void report_exception(std::exception_ptr exceptionPtr) - { - auto response_impl = m_response._get_impl(); - - // If cancellation has been triggered then ignore any errors. - if(m_request._cancellation_token().is_canceled()) - { - exceptionPtr = std::make_exception_ptr(http_exception((int)std::errc::operation_canceled, std::generic_category())); - } - - // First try to complete the headers with an exception. - if(m_request_completion.set_exception(exceptionPtr)) - { - // Complete the request with no msg body. The exception - // should only be propagated to one of the tce. - response_impl->_complete(0); - } - else - { - // Complete the request with an exception - response_impl->_complete(0, exceptionPtr); - } - - finish(); - } - - virtual concurrency::streams::streambuf _get_readbuffer() - { - auto instream = m_request.body(); - - _ASSERTE((bool)instream); - return instream.streambuf(); - } - - concurrency::streams::streambuf _get_writebuffer() - { - auto outstream = m_response._get_impl()->outstream(); - - _ASSERTE((bool)outstream); - return outstream.streambuf(); - } - - // Reference to the http_client implementation. - std::shared_ptr<_http_client_communicator> m_http_client; - - // request/response pair. - http_request m_request; - http_response m_response; - - utility::size64_t m_uploaded; - utility::size64_t m_downloaded; - - // task completion event to signal request is completed. - pplx::task_completion_event m_request_completion; - - // Registration for cancellation notification if enabled. - pplx::cancellation_token_registration m_cancellationRegistration; - -protected: - - request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request) - : m_http_client(client), - m_request(request), - m_uploaded(0), - m_downloaded(0) - { - auto responseImpl = m_response._get_impl(); - - // Copy the user specified output stream over to the response - responseImpl->set_outstream(request._get_impl()->_response_stream(), false); - - // Prepare for receiving data from the network. Ideally, this should be done after - // we receive the headers and determine that there is a response body. We will do it here - // since it is not immediately apparent where that would be in the callback handler - responseImpl->_prepare_to_receive_data(); - } - - virtual void finish(); -}; - -// -// Interface used by client implementations. Concrete implementations are responsible for -// sending HTTP requests and receiving the responses. -// -class _http_client_communicator -{ -public: - - // Destructor to clean up any held resources. - virtual ~_http_client_communicator() {} - - // Asynchronously send a HTTP request and process the response. - void async_send_request(const std::shared_ptr &request) - { - if(m_client_config.guarantee_order()) - { - // Send to call block to be processed. - push_request(request); - } - else - { - // Schedule a task to start sending. - pplx::create_task([this, request] - { - open_and_send_request(request); - }); - } - } - - void finish_request() - { - // If guarantee order is specified we don't need to do anything. - if(m_client_config.guarantee_order()) - { - pplx::extensibility::scoped_critical_section_t l(m_open_lock); - - --m_scheduled; - - if( !m_requests_queue.empty()) - { - auto request = m_requests_queue.front(); - m_requests_queue.pop(); - - // Schedule a task to start sending. - pplx::create_task([this, request] - { - open_and_send_request(request); - }); - } - } - } - - const http_client_config& client_config() const - { - return m_client_config; - } - - const uri & base_uri() const - { - return m_uri; - } - -protected: - _http_client_communicator(http::uri address, http_client_config client_config) - : m_uri(std::move(address)), m_client_config(std::move(client_config)), m_opened(false), m_scheduled(0) - { - } - - // Method to open client. - virtual unsigned long open() = 0; - - // HTTP client implementations must implement send_request. - virtual void send_request(_In_ const std::shared_ptr &request) = 0; - - // URI to connect to. - const http::uri m_uri; - -private: - - http_client_config m_client_config; - - bool m_opened; - - pplx::extensibility::critical_section_t m_open_lock; - - // Wraps opening the client around sending a request. - void open_and_send_request(const std::shared_ptr &request) - { - // First see if client needs to be opened. - auto error = open_if_required(); - - if (error != 0) - { - // Failed to open - request->report_error(error, _XPLATSTR("Open failed")); - - // DO NOT TOUCH the this pointer after completing the request - // This object could be freed along with the request as it could - // be the last reference to this object - return; - } - - send_request(request); - } - - unsigned long open_if_required() - { - unsigned long error = 0; - - if(!m_opened) - { - pplx::extensibility::scoped_critical_section_t l(m_open_lock); - - // Check again with the lock held - if (!m_opened) - { - error = open(); - - if (error == 0) - { - m_opened = true; - } - } - } - - return error; - } - - void push_request(const std::shared_ptr &request) - { - pplx::extensibility::scoped_critical_section_t l(m_open_lock); - - if(++m_scheduled == 1) - { - // Schedule a task to start sending. - pplx::create_task([this, request]() - { - open_and_send_request(request); - }); - } - else - { - m_requests_queue.push(request); - } - } - - // Queue used to guarantee ordering of requests, when applicable. - std::queue> m_requests_queue; - int m_scheduled; -}; - -inline void request_context::finish() -{ - // If cancellation is enabled and registration was performed, unregister. - if(m_cancellationRegistration != pplx::cancellation_token_registration()) - { - _ASSERTE(m_request._cancellation_token() != pplx::cancellation_token::none()); - m_request._cancellation_token().deregister_callback(m_cancellationRegistration); - } - - m_http_client->finish_request(); -} - -class http_network_handler : public http_pipeline_stage -{ -public: - http_network_handler(const uri &base_uri, const http_client_config &client_config); - - virtual pplx::task propagate(http_request request); - - const std::shared_ptr& http_client_impl() const - { - return m_http_client_impl; - } - -private: - std::shared_ptr<_http_client_communicator> m_http_client_impl; -}; - -// Helper function to check to make sure the uri is valid. -void verify_uri(const uri &uri) -{ - // Some things like proper URI schema are verified by the URI class. - // We only need to check certain things specific to HTTP. - if (uri.scheme() != _XPLATSTR("http") && uri.scheme() != _XPLATSTR("https")) - { - throw std::invalid_argument("URI scheme must be 'http' or 'https'"); - } - - if(uri.host().empty()) - { - throw std::invalid_argument("URI must contain a hostname."); - } -} - -} // namespace details - -http_client::http_client(const uri &base_uri) -{ - build_pipeline(base_uri, http_client_config()); -} - -http_client::http_client(const uri &base_uri, const http_client_config &client_config) -{ - build_pipeline(base_uri, client_config); -} - -void http_client::build_pipeline(const uri &base_uri, const http_client_config &client_config) -{ - if (base_uri.scheme().empty()) - { - auto uribuilder = uri_builder(base_uri); - uribuilder.set_scheme(_XPLATSTR("http")); - uri uriWithScheme = uribuilder.to_uri(); - details::verify_uri(uriWithScheme); - m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared(uriWithScheme, client_config)); - } - else - { - details::verify_uri(base_uri); - m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared(base_uri, client_config)); - } - -#if !defined(CPPREST_TARGET_XP) - add_handler(std::static_pointer_cast( - std::make_shared(client_config.oauth1()))); -#endif - - add_handler(std::static_pointer_cast( - std::make_shared(client_config.oauth2()))); -} - -const http_client_config & http_client::client_config() const -{ - auto ph = std::static_pointer_cast(m_pipeline->last_stage()); - return ph->http_client_impl()->client_config(); -} - -const uri & http_client::base_uri() const -{ - auto ph = std::static_pointer_cast(m_pipeline->last_stage()); - return ph->http_client_impl()->base_uri(); -} - -}}} // namespaces diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 1e0ce8b73f..577f57785f 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -280,8 +280,7 @@ class http_client_config } #endif -#ifdef _WIN32 -#if !defined(__cplusplus_winrt) +#if defined(_WIN32) && !defined(__cplusplus_winrt) /// /// Checks if request data buffering is turned on, the default is off. /// @@ -302,7 +301,6 @@ class http_client_config { m_buffer_request = buffer_request; } -#endif #endif /// @@ -422,7 +420,7 @@ class http_client /// Note the destructor doesn't necessarily close the connection and release resources. /// The connection is reference counted with the http_responses. /// - ~http_client() CPPREST_NOEXCEPT {} + _ASYNCRTIMP ~http_client() CPPREST_NOEXCEPT; /// /// Gets the base URI. @@ -442,19 +440,14 @@ class http_client /// Adds an HTTP pipeline stage to the client. /// /// A function object representing the pipeline stage. - void add_handler(const std::function(http_request, std::shared_ptr)> &handler) - { - m_pipeline->append(std::make_shared<::web::http::details::function_pipeline_wrapper>(handler)); - } + _ASYNCRTIMP void add_handler(const std::function(http_request, std::shared_ptr)> &handler); + /// /// Adds an HTTP pipeline stage to the client. /// /// A shared pointer to a pipeline stage. - void add_handler(const std::shared_ptr &stage) - { - m_pipeline->append(stage); - } + _ASYNCRTIMP void add_handler(const std::shared_ptr &stage); /// /// Asynchronously sends an HTTP request. @@ -732,6 +725,13 @@ class http_client std::shared_ptr<::web::http::http_pipeline> m_pipeline; }; +namespace details { +#if defined(_WIN32) +extern const utility::char_t * get_with_body_err_msg; +#endif + +} + }}} #endif diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 8228d7cccb..388fb4bd1c 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -328,4 +328,18 @@ class http_headers std::map m_headers; }; +namespace details { + + /// + /// Serialize the http_headers into name:value pairs separated by a carriage return and line feed. + /// + utility::string_t flatten_http_headers(const http_headers &headers); +#if defined(_WIN32) + /// + /// Parses a string containing Http headers. + /// + void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers); +#endif +} + }} \ No newline at end of file diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 0afb3b88df..eba83b2cc3 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -4,6 +4,7 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) endif() set(SOURCES_COMMON + http/client/http_client.cpp http/client/http_client_msg.cpp http/client/x509_cert_utilities.cpp http/common/http_helpers.cpp diff --git a/Release/src/build/common.vcxitems b/Release/src/build/common.vcxitems index 28702632db..eec185f2ee 100644 --- a/Release/src/build/common.vcxitems +++ b/Release/src/build/common.vcxitems @@ -15,6 +15,7 @@ + @@ -51,12 +52,11 @@ - - + @@ -83,6 +83,7 @@ + diff --git a/Release/src/build/common.vcxitems.filters b/Release/src/build/common.vcxitems.filters index 4133dbbe93..35cf8139d2 100644 --- a/Release/src/build/common.vcxitems.filters +++ b/Release/src/build/common.vcxitems.filters @@ -67,6 +67,9 @@ Source Files + + Source Files + @@ -87,6 +90,9 @@ {1c12997c-5bf5-4b60-853e-a5f9c8303760} + + {97da7aee-41c8-4948-bb0e-c31cec1bfb16} + @@ -152,9 +158,6 @@ Header Files\cpprest\details - - Header Files\cpprest\details - Header Files\cpprest\details @@ -209,6 +212,9 @@ Header Files\cpprest\details + + Header Files\private + diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp new file mode 100644 index 0000000000..fb666128d3 --- /dev/null +++ b/Release/src/http/client/http_client.cpp @@ -0,0 +1,335 @@ +/*** +* ==++== +* +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* ==--== +* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +* +* HTTP Library: Client-side APIs. +* +* This file contains shared code across all http_client implementations. +* +* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk +* +* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +****/ + +#include "stdafx.h" + +#include "http_client_impl.h" + +namespace web { namespace http { namespace client { + +// Helper function to check to make sure the uri is valid. +static void verify_uri(const uri &uri) +{ + // Some things like proper URI schema are verified by the URI class. + // We only need to check certain things specific to HTTP. + if (uri.scheme() != _XPLATSTR("http") && uri.scheme() != _XPLATSTR("https")) + { + throw std::invalid_argument("URI scheme must be 'http' or 'https'"); + } + + if (uri.host().empty()) + { + throw std::invalid_argument("URI must contain a hostname."); + } +} + +namespace details +{ + +#if defined(_WIN32) + const utility::char_t * get_with_body_err_msg = _XPLATSTR("A GET or HEAD request should not have an entity body."); +#endif + +void request_context::complete_headers() +{ + // We have already read (and transmitted) the request body. Should we explicitly close the stream? + // Well, there are test cases that assumes that the istream is valid when t receives the response! + // For now, we will drop our reference which will close the stream if the user doesn't have one. + m_request.set_body(Concurrency::streams::istream()); + m_request_completion.set(m_response); +} + +void request_context::complete_request(utility::size64_t body_size) +{ + m_response._get_impl()->_complete(body_size); + + finish(); +} + +void request_context::report_error(unsigned long error_code, const std::string &errorMessage) +{ + report_exception(http_exception(static_cast(error_code), errorMessage)); +} + +#if defined(_WIN32) +void request_context::report_error(unsigned long error_code, const std::wstring &errorMessage) +{ + report_exception(http_exception(static_cast(error_code), errorMessage)); +} +#endif + +void request_context::report_exception(std::exception_ptr exceptionPtr) +{ + auto response_impl = m_response._get_impl(); + + // If cancellation has been triggered then ignore any errors. + if (m_request._cancellation_token().is_canceled()) + { + exceptionPtr = std::make_exception_ptr(http_exception((int)std::errc::operation_canceled, std::generic_category())); + } + + // First try to complete the headers with an exception. + if (m_request_completion.set_exception(exceptionPtr)) + { + // Complete the request with no msg body. The exception + // should only be propagated to one of the tce. + response_impl->_complete(0); + } + else + { + // Complete the request with an exception + response_impl->_complete(0, exceptionPtr); + } + + finish(); +} + +concurrency::streams::streambuf request_context::_get_readbuffer() +{ + auto instream = m_request.body(); + + _ASSERTE((bool)instream); + return instream.streambuf(); +} + +concurrency::streams::streambuf request_context::_get_writebuffer() +{ + auto outstream = m_response._get_impl()->outstream(); + + _ASSERTE((bool)outstream); + return outstream.streambuf(); +} + +request_context::request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request) + : m_http_client(client), + m_request(request), + m_uploaded(0), + m_downloaded(0) +{ + auto responseImpl = m_response._get_impl(); + + // Copy the user specified output stream over to the response + responseImpl->set_outstream(request._get_impl()->_response_stream(), false); + + // Prepare for receiving data from the network. Ideally, this should be done after + // we receive the headers and determine that there is a response body. We will do it here + // since it is not immediately apparent where that would be in the callback handler + responseImpl->_prepare_to_receive_data(); +} + +void _http_client_communicator::async_send_request(const std::shared_ptr &request) +{ + if (m_client_config.guarantee_order()) + { + // Send to call block to be processed. + push_request(request); + } + else + { + // Schedule a task to start sending. + pplx::create_task([this, request] + { + open_and_send_request(request); + }); + } +} + +void _http_client_communicator::finish_request() +{ + // If guarantee order is specified we don't need to do anything. + if (m_client_config.guarantee_order()) + { + pplx::extensibility::scoped_critical_section_t l(m_open_lock); + + --m_scheduled; + + if (!m_requests_queue.empty()) + { + auto request = m_requests_queue.front(); + m_requests_queue.pop(); + + // Schedule a task to start sending. + pplx::create_task([this, request] + { + open_and_send_request(request); + }); + } + } +} + +const http_client_config& _http_client_communicator::client_config() const +{ + return m_client_config; +} + +const uri & _http_client_communicator::base_uri() const +{ + return m_uri; +} + +_http_client_communicator::_http_client_communicator(http::uri address, http_client_config client_config) + : m_uri(std::move(address)), m_client_config(std::move(client_config)), m_opened(false), m_scheduled(0) +{ +} + +// Wraps opening the client around sending a request. +void _http_client_communicator::open_and_send_request(const std::shared_ptr &request) +{ + // First see if client needs to be opened. + auto error = open_if_required(); + + if (error != 0) + { + // Failed to open + request->report_error(error, _XPLATSTR("Open failed")); + + // DO NOT TOUCH the this pointer after completing the request + // This object could be freed along with the request as it could + // be the last reference to this object + return; + } + + send_request(request); +} + +unsigned long _http_client_communicator::open_if_required() +{ + unsigned long error = 0; + + if (!m_opened) + { + pplx::extensibility::scoped_critical_section_t l(m_open_lock); + + // Check again with the lock held + if (!m_opened) + { + error = open(); + + if (error == 0) + { + m_opened = true; + } + } + } + + return error; +} + +void _http_client_communicator::push_request(const std::shared_ptr &request) +{ + pplx::extensibility::scoped_critical_section_t l(m_open_lock); + + if (++m_scheduled == 1) + { + // Schedule a task to start sending. + pplx::create_task([this, request]() + { + open_and_send_request(request); + }); + } + else + { + m_requests_queue.push(request); + } +} + +inline void request_context::finish() +{ + // If cancellation is enabled and registration was performed, unregister. + if (m_cancellationRegistration != pplx::cancellation_token_registration()) + { + _ASSERTE(m_request._cancellation_token() != pplx::cancellation_token::none()); + m_request._cancellation_token().deregister_callback(m_cancellationRegistration); + } + + m_http_client->finish_request(); +} + +} // namespace details + + +void http_client::add_handler(const std::function(http_request, std::shared_ptr)> &handler) +{ + m_pipeline->append(std::make_shared<::web::http::details::function_pipeline_wrapper>(handler)); +} + +void http_client::add_handler(const std::shared_ptr &stage) +{ + m_pipeline->append(stage); +} + +http_client::http_client(const uri &base_uri) +{ + build_pipeline(base_uri, http_client_config()); +} + +http_client::http_client(const uri &base_uri, const http_client_config &client_config) +{ + build_pipeline(base_uri, client_config); +} + +http_client::~http_client() CPPREST_NOEXCEPT {} + +void http_client::build_pipeline(const uri &base_uri, const http_client_config &client_config) +{ + if (base_uri.scheme().empty()) + { + auto uribuilder = uri_builder(base_uri); + uribuilder.set_scheme(_XPLATSTR("http")); + uri uriWithScheme = uribuilder.to_uri(); + verify_uri(uriWithScheme); + m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared(uriWithScheme, client_config)); + } + else + { + verify_uri(base_uri); + m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared(base_uri, client_config)); + } + +#if !defined(CPPREST_TARGET_XP) + add_handler(std::static_pointer_cast( + std::make_shared(client_config.oauth1()))); +#endif + + add_handler(std::static_pointer_cast( + std::make_shared(client_config.oauth2()))); +} + +const http_client_config & http_client::client_config() const +{ + auto ph = std::static_pointer_cast(m_pipeline->last_stage()); + return ph->http_client_impl()->client_config(); +} + +const uri & http_client::base_uri() const +{ + auto ph = std::static_pointer_cast(m_pipeline->last_stage()); + return ph->http_client_impl()->base_uri(); +} + + +}}} \ No newline at end of file diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 44296040e0..0b70f6889d 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -43,7 +43,7 @@ #error "Cpp rest SDK requires c++11 smart pointer support from boost" #endif -#include "cpprest/details/http_client_impl.h" +#include "http_client_impl.h" #include "cpprest/details/x509_cert_utilities.h" #include diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h new file mode 100644 index 0000000000..7dcb1f8c62 --- /dev/null +++ b/Release/src/http/client/http_client_impl.h @@ -0,0 +1,168 @@ +/*** +* ==++== +* +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* ==--== +* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +* +* HTTP Library: Client-side APIs. +* +* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk +* +* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +****/ +#pragma once + +#include "cpprest/details/basic_types.h" +#include "cpprest/astreambuf.h" +#include "cpprest/http_client.h" +#include "cpprest/http_msg.h" +#include +#include +#include + +namespace web { namespace http { namespace client { namespace details { + +class _http_client_communicator; + +// Request context encapsulating everything necessary for creating and responding to a request. +class request_context +{ +public: + + // Destructor to clean up any held resources. + virtual ~request_context() {} + + virtual void report_exception(std::exception_ptr exceptionPtr); + + virtual concurrency::streams::streambuf _get_readbuffer(); + + void complete_headers(); + + /// + /// Completes this request, setting the underlying task completion event, and cleaning up the handles + /// + void complete_request(utility::size64_t body_size); + + void report_error(unsigned long error_code, const std::string &errorMessage); + +#ifdef _WIN32 + void report_error(unsigned long error_code, const std::wstring &errorMessage); +#endif + + template + void report_exception(const _ExceptionType &e) + { + report_exception(std::make_exception_ptr(e)); + } + + concurrency::streams::streambuf _get_writebuffer(); + + // Reference to the http_client implementation. + std::shared_ptr<_http_client_communicator> m_http_client; + + // request/response pair. + http_request m_request; + http_response m_response; + + utility::size64_t m_uploaded; + utility::size64_t m_downloaded; + + // task completion event to signal request is completed. + pplx::task_completion_event m_request_completion; + + // Registration for cancellation notification if enabled. + pplx::cancellation_token_registration m_cancellationRegistration; + +protected: + + request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request); + + virtual void finish(); +}; + +// +// Interface used by client implementations. Concrete implementations are responsible for +// sending HTTP requests and receiving the responses. +// +class _http_client_communicator +{ +public: + + virtual ~_http_client_communicator() {} + + // Asynchronously send a HTTP request and process the response. + void async_send_request(const std::shared_ptr &request); + + void finish_request(); + + const http_client_config& client_config() const; + + const uri & base_uri() const; + +protected: + _http_client_communicator(http::uri address, http_client_config client_config); + + // Method to open client. + virtual unsigned long open() = 0; + + // HTTP client implementations must implement send_request. + virtual void send_request(_In_ const std::shared_ptr &request) = 0; + + // URI to connect to. + const http::uri m_uri; + +private: + + http_client_config m_client_config; + + bool m_opened; + + pplx::extensibility::critical_section_t m_open_lock; + + // Wraps opening the client around sending a request. + void open_and_send_request(const std::shared_ptr &request); + + unsigned long open_if_required(); + + void push_request(const std::shared_ptr &request); + + // Queue used to guarantee ordering of requests, when applicable. + std::queue> m_requests_queue; + int m_scheduled; +}; + +class http_network_handler : public http_pipeline_stage +{ +public: + /// + /// The constructor is separately defined by each subsystem (winhttp, winrt, asio) to create the platform-specific _http_client_communicator. + /// + http_network_handler(const uri &base_uri, const http_client_config &client_config); + + /// + /// This method is separately defined by each subsystem (winhttp, winrt, asio) to enable the platform-specific handling behavior. + /// + virtual pplx::task propagate(http_request request) override; + + const std::shared_ptr& http_client_impl() const + { + return m_http_client_impl; + } + +private: + std::shared_ptr<_http_client_communicator> m_http_client_impl; +}; + +}}}} \ No newline at end of file diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 36f596b937..79cb2501d3 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -26,7 +26,8 @@ ****/ #include "stdafx.h" -#include "cpprest/details/http_client_impl.h" +#include "cpprest/http_headers.h" +#include "http_client_impl.h" namespace web { @@ -66,6 +67,16 @@ static http::status_code parse_status_code(HINTERNET request_handle) return (unsigned short)_wtoi(buffer.c_str()); } +// Helper function to trim leading and trailing null characters from a string. +static void trim_nulls(utility::string_t &str) +{ + size_t index; + for (index = 0; index < str.size() && str[index] == 0; ++index); + str.erase(0, index); + for (index = str.size(); index > 0 && str[index - 1] == 0; --index); + str.erase(index); +} + // Helper function to get the reason phrase from a WinHTTP response. static utility::string_t parse_reason_phrase(HINTERNET request_handle) { @@ -98,7 +109,7 @@ static void parse_winhttp_headers(HINTERNET request_handle, _In_z_ utf16char *he response.set_status_code(parse_status_code(request_handle)); response.set_reason_phrase(parse_reason_phrase(request_handle)); - parse_headers_string(headersStr, response.headers()); + web::http::details::parse_headers_string(headersStr, response.headers()); } // Helper function to build error messages. @@ -568,7 +579,7 @@ class winhttp_client : public _http_client_communicator { if ( msg.method() == http::methods::GET || msg.method() == http::methods::HEAD ) { - request->report_exception(http_exception(get_with_body)); + request->report_exception(http_exception(get_with_body_err_msg)); return; } @@ -590,7 +601,7 @@ class winhttp_client : public _http_client_communicator // Add headers. if(!msg.headers().empty()) { - const utility::string_t flattened_headers = flatten_http_headers(msg.headers()); + const utility::string_t flattened_headers = web::http::details::flatten_http_headers(msg.headers()); if(!WinHttpAddRequestHeaders( winhttp_context->m_request_handle, flattened_headers.c_str(), diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index d2b5a58cc4..693a083089 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -26,7 +26,7 @@ ****/ #include "stdafx.h" -#include "cpprest/details/http_client_impl.h" +#include "http_client_impl.h" #include // Important for WP8 @@ -109,7 +109,7 @@ class HttpRequestCallback : } } - parse_headers_string(hdrStr, response.headers()); + web::http::details::parse_headers_string(hdrStr, response.headers()); m_request->complete_headers(); return S_OK; @@ -516,7 +516,7 @@ class winrt_client : public _http_client_communicator { if ( msg.method() == http::methods::GET || msg.method() == http::methods::HEAD ) { - request->report_exception(http_exception(get_with_body)); + request->report_exception(http_exception(get_with_body_err_msg)); return; } diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 615f640907..ed3a309e83 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -223,6 +223,49 @@ void http_headers::set_content_length(utility::size64_t length) m_headers[http::header_names::content_length] = utility::conversions::print_string(length, std::locale::classic()); } +namespace details { + +#ifdef _WIN32 +# define CRLF _XPLATSTR("\r\n") +#else +# define CRLF std::string("\r\n") +#endif + +utility::string_t flatten_http_headers(const http_headers &headers) +{ + utility::string_t flattened_headers; + for (auto iter = headers.begin(); iter != headers.end(); ++iter) + { + flattened_headers.append(iter->first); + flattened_headers.push_back(':'); + flattened_headers.append(iter->second); + flattened_headers.append(CRLF); + } + return flattened_headers; +} + +void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers) +{ + utf16char *context = nullptr; + utf16char *line = wcstok_s(headersStr, CRLF, &context); + while (line != nullptr) + { + const utility::string_t header_line(line); + const size_t colonIndex = header_line.find_first_of(_XPLATSTR(":")); + if (colonIndex != utility::string_t::npos) + { + utility::string_t key = header_line.substr(0, colonIndex); + utility::string_t value = header_line.substr(colonIndex + 1, header_line.length() - colonIndex - 1); + http::details::trim_whitespace(key); + http::details::trim_whitespace(value); + headers.add(key, value); + } + line = wcstok_s(nullptr, CRLF, &context); + } +} + +} + static const utility::char_t * stream_was_set_explicitly = _XPLATSTR("A stream was set on the message and extraction is not possible"); static const utility::char_t * unsupported_charset = _XPLATSTR("Charset must be iso-8859-1, utf-8, utf-16, utf-16le, or utf-16be to be extracted."); From aff4a1a7d8502ab94fb00acfcdb3235bcc452fb6 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 3 Apr 2016 01:11:28 -0700 Subject: [PATCH 082/609] Refactor to remove web::http::details::http_network_handler. --- Release/CMakeLists.txt | 1 + Release/include/cpprest/http_client.h | 2 - Release/src/http/client/http_client.cpp | 27 +++++------- Release/src/http/client/http_client_asio.cpp | 42 ++++++++++--------- Release/src/http/client/http_client_impl.h | 27 +++--------- .../src/http/client/http_client_winhttp.cpp | 40 ++++++++++-------- Release/src/http/client/http_client_winrt.cpp | 35 ++++++++-------- 7 files changed, 79 insertions(+), 95 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index e229106951..3467977980 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -160,6 +160,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") message("-- Setting msvc options") set(WARNINGS) + add_compile_options(/bigobj) else() message("-- Unknown compiler, success is doubtful.") message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}") diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 577f57785f..f515e2cea6 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -720,8 +720,6 @@ class http_client private: - void build_pipeline(const uri &base_uri, const http_client_config &client_config); - std::shared_ptr<::web::http::http_pipeline> m_pipeline; }; diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index fb666128d3..70b540ccd0 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -282,19 +282,10 @@ void http_client::add_handler(const std::shared_ptr & m_pipeline->append(stage); } -http_client::http_client(const uri &base_uri) -{ - build_pipeline(base_uri, http_client_config()); -} +http_client::http_client(const uri &base_uri) : http_client(base_uri, http_client_config()) +{} http_client::http_client(const uri &base_uri, const http_client_config &client_config) -{ - build_pipeline(base_uri, client_config); -} - -http_client::~http_client() CPPREST_NOEXCEPT {} - -void http_client::build_pipeline(const uri &base_uri, const http_client_config &client_config) { if (base_uri.scheme().empty()) { @@ -302,12 +293,12 @@ void http_client::build_pipeline(const uri &base_uri, const http_client_config & uribuilder.set_scheme(_XPLATSTR("http")); uri uriWithScheme = uribuilder.to_uri(); verify_uri(uriWithScheme); - m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared(uriWithScheme, client_config)); + m_pipeline = ::web::http::http_pipeline::create_pipeline(details::create_platform_final_pipeline_stage(uriWithScheme, client_config)); } else { verify_uri(base_uri); - m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared(base_uri, client_config)); + m_pipeline = ::web::http::http_pipeline::create_pipeline(details::create_platform_final_pipeline_stage(base_uri, client_config)); } #if !defined(CPPREST_TARGET_XP) @@ -319,16 +310,18 @@ void http_client::build_pipeline(const uri &base_uri, const http_client_config & std::make_shared(client_config.oauth2()))); } +http_client::~http_client() CPPREST_NOEXCEPT {} + const http_client_config & http_client::client_config() const { - auto ph = std::static_pointer_cast(m_pipeline->last_stage()); - return ph->http_client_impl()->client_config(); + auto ph = std::static_pointer_cast(m_pipeline->last_stage()); + return ph->client_config(); } const uri & http_client::base_uri() const { - auto ph = std::static_pointer_cast(m_pipeline->last_stage()); - return ph->http_client_impl()->base_uri(); + auto ph = std::static_pointer_cast(m_pipeline->last_stage()); + return ph->base_uri(); } diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 0b70f6889d..72eeb0d8df 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -44,11 +44,14 @@ #endif #include "http_client_impl.h" +#include "cpprest/base_uri.h" #include "cpprest/details/x509_cert_utilities.h" #include using boost::asio::ip::tcp; +#define CRLF std::string("\r\n") + namespace web { namespace http { namespace client @@ -227,8 +230,6 @@ class asio_connection m_is_reused = true; } - void handle_pool_timer(const boost::system::error_code& ec); - // Guards concurrent access to socket/ssl::stream. This is necessary // because timeouts and cancellation can touch the socket at the same time // as normal message processing. @@ -331,7 +332,7 @@ class asio_connection_pool -class asio_client : public _http_client_communicator, public std::enable_shared_from_this +class asio_client : public _http_client_communicator { public: asio_client(http::uri address, http_client_config client_config) @@ -347,6 +348,8 @@ class asio_client : public _http_client_communicator, public std::enable_shared_ unsigned long open() override { return 0; } + virtual pplx::task propagate(http_request request) override; + asio_connection_pool m_pool; tcp::resolver m_resolver; }; @@ -656,7 +659,7 @@ class asio_context : public request_context, public std::enable_shared_from_this extra_headers.append(": no-cache" + CRLF); } - request_stream << flatten_http_headers(ctx->m_request.headers()); + request_stream << ::web::http::details::flatten_http_headers(ctx->m_request.headers()); request_stream << extra_headers; // Enforce HTTP connection keep alive (even for the old HTTP/1.0 protocol). request_stream << "Connection: Keep-Alive" << CRLF << CRLF; @@ -1446,22 +1449,9 @@ class asio_context : public request_context, public std::enable_shared_from_this }; - -http_network_handler::http_network_handler(const uri &base_uri, const http_client_config &client_config) : - m_http_client_impl(std::make_shared(base_uri, client_config)) -{} - -pplx::task http_network_handler::propagate(http_request request) +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) { - auto context = details::asio_context::create_request_context(m_http_client_impl, request); - - // Use a task to externally signal the final result and completion of the task. - auto result_task = pplx::create_task(context->m_request_completion); - - // Asynchronously send the response with the HTTP client implementation. - m_http_client_impl->async_send_request(context); - - return result_task; + return std::make_shared(base_uri, client_config); } void asio_client::send_request(const std::shared_ptr &request_ctx) @@ -1488,4 +1478,18 @@ void asio_client::send_request(const std::shared_ptr &request_c ctx->start_request(); } +pplx::task asio_client::propagate(http_request request) +{ + auto self = std::static_pointer_cast<_http_client_communicator>(shared_from_this()); + auto context = details::asio_context::create_request_context(self, request); + + // Use a task to externally signal the final result and completion of the task. + auto result_task = pplx::create_task(context->m_request_completion); + + // Asynchronously send the response with the HTTP client implementation. + this->async_send_request(context); + + return result_task; +} + }}}} // namespaces diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h index 7dcb1f8c62..ac0ae81ce1 100644 --- a/Release/src/http/client/http_client_impl.h +++ b/Release/src/http/client/http_client_impl.h @@ -96,7 +96,7 @@ class request_context // Interface used by client implementations. Concrete implementations are responsible for // sending HTTP requests and receiving the responses. // -class _http_client_communicator +class _http_client_communicator : public http_pipeline_stage { public: @@ -143,26 +143,9 @@ class _http_client_communicator int m_scheduled; }; -class http_network_handler : public http_pipeline_stage -{ -public: - /// - /// The constructor is separately defined by each subsystem (winhttp, winrt, asio) to create the platform-specific _http_client_communicator. - /// - http_network_handler(const uri &base_uri, const http_client_config &client_config); - - /// - /// This method is separately defined by each subsystem (winhttp, winrt, asio) to enable the platform-specific handling behavior. - /// - virtual pplx::task propagate(http_request request) override; - - const std::shared_ptr& http_client_impl() const - { - return m_http_client_impl; - } - -private: - std::shared_ptr<_http_client_communicator> m_http_client_impl; -}; +/// +/// Factory function implemented by the separate platforms to construct their subclasses of _http_client_communicator +/// +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config); }}}} \ No newline at end of file diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 79cb2501d3..ce1f27205d 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -312,7 +312,10 @@ class winhttp_client : public _http_client_communicator { public: winhttp_client(http::uri address, http_client_config client_config) - : _http_client_communicator(std::move(address), std::move(client_config)), m_secure(m_uri.scheme() == _XPLATSTR("https")), m_hSession(nullptr), m_hConnection(nullptr) { } + : _http_client_communicator(std::move(address), std::move(client_config)) + , m_secure(m_uri.scheme() == _XPLATSTR("https")) + , m_hSession(nullptr) + , m_hConnection(nullptr) { } // Closes session. ~winhttp_client() @@ -335,6 +338,20 @@ class winhttp_client : public _http_client_communicator } } + virtual pplx::task propagate(http_request request) override + { + auto self = std::static_pointer_cast<_http_client_communicator>(shared_from_this()); + auto context = details::winhttp_request_context::create_request_context(self, request); + + // Use a task to externally signal the final result and completion of the task. + auto result_task = pplx::create_task(context->m_request_completion); + + // Asynchronously send the response with the HTTP client implementation. + this->async_send_request(context); + + return result_task; + } + protected: unsigned long report_failure(const utility::string_t& errorMessage) @@ -1274,26 +1291,13 @@ class winhttp_client : public _http_client_communicator bool m_secure; // No copy or assignment. - winhttp_client(const winhttp_client&); - winhttp_client &operator=(const winhttp_client&); + winhttp_client(const winhttp_client&) = delete; + winhttp_client &operator=(const winhttp_client&) = delete; }; -http_network_handler::http_network_handler(const uri &base_uri, const http_client_config &client_config) : - m_http_client_impl(std::make_shared(base_uri, client_config)) +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) { -} - -pplx::task http_network_handler::propagate(http_request request) -{ - auto context = details::winhttp_request_context::create_request_context(m_http_client_impl, request); - - // Use a task to externally signal the final result and completion of the task. - auto result_task = pplx::create_task(context->m_request_completion); - - // Asynchronously send the response with the HTTP client implementation. - m_http_client_impl->async_send_request(context); - - return result_task; + return std::make_shared(std::move(base_uri), client_config); } }}}} diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 693a083089..44196a6412 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -359,6 +359,20 @@ class winrt_client : public _http_client_communicator winrt_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) { } + virtual pplx::task propagate(http_request request) override + { + auto self = std::static_pointer_cast<_http_client_communicator>(shared_from_this()); + auto context = details::winrt_request_context::create_request_context(self, request); + + // Use a task to externally signal the final result and completion of the task. + auto result_task = pplx::create_task(context->m_request_completion); + + // Asynchronously send the response with the HTTP client implementation. + this->async_send_request(context); + + return result_task; + } + protected: // Method to open client. @@ -545,26 +559,13 @@ class winrt_client : public _http_client_communicator private: // No copy or assignment. - winrt_client(const winrt_client&); - winrt_client &operator=(const winrt_client&); + winrt_client(const winrt_client&) = delete; + winrt_client &operator=(const winrt_client&) = delete; }; -http_network_handler::http_network_handler(const uri &base_uri, const http_client_config &client_config) : - m_http_client_impl(std::make_shared(base_uri, client_config)) +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) { -} - -pplx::task http_network_handler::propagate(http_request request) -{ - auto context = details::winrt_request_context::create_request_context(m_http_client_impl, request); - - // Use a task to externally signal the final result and completion of the task. - auto result_task = pplx::create_task(context->m_request_completion); - - // Asynchronously send the response with the HTTP client implementation. - m_http_client_impl->async_send_request(context); - - return result_task; + return std::make_shared(std::move(base_uri), client_config); } }}}} From 7c9189ef92622b9cf54b0248cec5996431aa08d7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 4 Apr 2016 20:22:58 -0700 Subject: [PATCH 083/609] Fix android build after refactor. --- Release/src/http/client/x509_cert_utilities.cpp | 2 ++ Release/src/http/common/http_msg.cpp | 8 ++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Release/src/http/client/x509_cert_utilities.cpp b/Release/src/http/client/x509_cert_utilities.cpp index 8f92bfa103..20eef9812f 100644 --- a/Release/src/http/client/x509_cert_utilities.cpp +++ b/Release/src/http/client/x509_cert_utilities.cpp @@ -106,6 +106,8 @@ bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verif } #if defined(ANDROID) || defined(__ANDROID__) +using namespace crossplat; + /// /// Helper function to check return value and see if any exceptions /// occurred when calling a JNI function. diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index ed3a309e83..d8d2cf84a5 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -225,12 +225,6 @@ void http_headers::set_content_length(utility::size64_t length) namespace details { -#ifdef _WIN32 -# define CRLF _XPLATSTR("\r\n") -#else -# define CRLF std::string("\r\n") -#endif - utility::string_t flatten_http_headers(const http_headers &headers) { utility::string_t flattened_headers; @@ -244,6 +238,7 @@ utility::string_t flatten_http_headers(const http_headers &headers) return flattened_headers; } +#if defined(_WIN32) void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers) { utf16char *context = nullptr; @@ -263,6 +258,7 @@ void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers line = wcstok_s(nullptr, CRLF, &context); } } +#endif } From fde3e9a07f9cd469fb181c3542b42860f11ab395 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Apr 2016 20:17:57 -0700 Subject: [PATCH 084/609] Update tests to account for outside site fixing bad certificate. --- Release/tests/functional/http/client/outside_tests.cpp | 2 +- .../tests/functional/websockets/client/authentication_tests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index e0f4498923..dfdacfb2bd 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -140,7 +140,7 @@ TEST(server_selfsigned_cert) }); } -TEST(server_hostname_mismatch) +TEST(server_hostname_mismatch, "Ignore", "Site fixed certificate. Improve test (new site or alternate method).") { handle_timeout([] { diff --git a/Release/tests/functional/websockets/client/authentication_tests.cpp b/Release/tests/functional/websockets/client/authentication_tests.cpp index 363835d7ad..148655fd66 100644 --- a/Release/tests/functional/websockets/client/authentication_tests.cpp +++ b/Release/tests/functional/websockets/client/authentication_tests.cpp @@ -234,7 +234,7 @@ TEST(self_signed_cert) handshake_error_test_impl(U("wss://www.pcwebshop.co.uk/")); } -TEST(hostname_mismatch) +TEST(hostname_mismatch, "Ignore", "Site fixed certificate. Improve test (new site or alternate method).") { handshake_error_test_impl(U("wss://swordsoftruth.com/")); } From 98320fe944c0eb2f7d5a548ffa57594e6d618fc6 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Apr 2016 23:11:31 -0700 Subject: [PATCH 085/609] Hide definition of http_pipeline. --- Release/include/cpprest/http_client.h | 2 + Release/include/cpprest/http_msg.h | 126 ++---------------- Release/src/http/client/http_client.cpp | 106 ++++++++++++++- Release/src/http/client/http_client_msg.cpp | 17 --- .../http/client/pipeline_stage_tests.cpp | 2 +- 5 files changed, 113 insertions(+), 140 deletions(-) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index f515e2cea6..0c8d7e9f8c 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -397,6 +397,8 @@ class http_client_config #endif }; +class http_pipeline; + /// /// HTTP client class, used to maintain a connection to an HTTP service for an extended session. /// diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 90669accc4..c88e51ab1c 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -1318,6 +1318,10 @@ class http_request std::shared_ptr _m_impl; }; +namespace client { +class http_pipeline; +} + /// /// HTTP client handler class, used to represent an HTTP pipeline stage. /// @@ -1333,6 +1337,11 @@ class http_pipeline_stage : public std::enable_shared_from_this /// Gets the next stage in the pipeline. /// @@ -1363,13 +1368,14 @@ class http_pipeline_stage : public std::enable_shared_from_this /// A shared pointer to a pipeline stage. + CASABLANCA_DEPRECATED("This api is redundant. Use 'shared_from_this()' directly instead.") std::shared_ptr current_stage() { return this->shared_from_this(); } private: - friend class http_pipeline; + friend class ::web::http::client::http_pipeline; void set_next_stage(const std::shared_ptr &next) { @@ -1378,116 +1384,6 @@ class http_pipeline_stage : public std::enable_shared_from_this m_next_stage; - // No copy or assignment. - http_pipeline_stage & operator=(const http_pipeline_stage &); - http_pipeline_stage(const http_pipeline_stage &); -}; - -namespace details { - -class function_pipeline_wrapper : public http::http_pipeline_stage -{ -public: - function_pipeline_wrapper(std::function(http_request, std::shared_ptr)> handler) : m_handler(handler) - { - } - - virtual pplx::task propagate(http_request request) override - { - return m_handler(request, next_stage()); - } -private: - - std::function(http_request, std::shared_ptr)> m_handler; -}; - -} // namespace details - -/// -/// -/// -class http_pipeline -{ -public: - - /// - /// Create an http pipeline that consists of a linear chain of stages - /// - /// The final stage - static std::shared_ptr create_pipeline(const std::shared_ptr &last) - { - return std::shared_ptr(new http_pipeline(last)); - } - - /// - /// Initiate an http request into the pipeline - /// - /// Http request - pplx::task propagate(http_request request) - { - std::shared_ptr first; - { - pplx::extensibility::scoped_recursive_lock_t l(m_lock); - first = (m_stages.size() > 0) ? m_stages[0] : m_last_stage; - } - return first->propagate(request); - } - - /// - /// Adds an HTTP pipeline stage to the pipeline. - /// - /// A pipeline stage. - void append(const std::shared_ptr &stage) - { - pplx::extensibility::scoped_recursive_lock_t l(m_lock); - - if (m_stages.size() > 0) - { - std::shared_ptr penultimate = m_stages[m_stages.size()-1]; - penultimate->set_next_stage(stage); - } - stage->set_next_stage(m_last_stage); - - m_stages.push_back(stage); - } - - /// - /// Sets the last stage of the pipeline. - /// - /// Shared pointer to pipeline stage to set as the last. - void set_last_stage(const std::shared_ptr &last) - { - m_last_stage = last; - } - - /// - /// Retrieves the last stage in this pipeline. - /// - /// A shared pointer to last stage. - const std::shared_ptr& last_stage() const - { - return m_last_stage; - } - -private: - - http_pipeline(const std::shared_ptr &last) : m_last_stage(last) - { - } - - // The vector of pipeline stages. - std::vector> m_stages; - - // The last stage is always set up by the client or listener and cannot - // be changed. All application-defined stages are executed before the - // last stage, which is typically a send or dispatch. - std::shared_ptr m_last_stage; - - pplx::extensibility::recursive_lock_t m_lock; - - // No copy or assignment. - http_pipeline & operator=(const http_pipeline &); - http_pipeline(const http_pipeline &); }; }} diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 70b540ccd0..ece552932c 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -271,10 +271,83 @@ inline void request_context::finish() } // namespace details +/// +/// Private implementation of http_client. Manages the http request processing pipeline. +/// +class http_pipeline +{ +public: + http_pipeline(std::shared_ptr last) : m_last_stage(std::move(last)) + {} + + // No copy or assignment. + http_pipeline & operator=(const http_pipeline &) = delete; + http_pipeline(const http_pipeline &) = delete; + + /// + /// Initiate an http request into the pipeline + /// + /// Http request + pplx::task propagate(http_request request) + { + std::shared_ptr first; + { + pplx::extensibility::scoped_recursive_lock_t l(m_lock); + first = (m_stages.size() > 0) ? m_stages[0] : m_last_stage; + } + return first->propagate(request); + } + + /// + /// Adds an HTTP pipeline stage to the pipeline. + /// + /// A pipeline stage. + void append(const std::shared_ptr &stage) + { + pplx::extensibility::scoped_recursive_lock_t l(m_lock); + + if (m_stages.size() > 0) + { + std::shared_ptr penultimate = m_stages[m_stages.size() - 1]; + penultimate->set_next_stage(stage); + } + stage->set_next_stage(m_last_stage); + + m_stages.push_back(stage); + } + + // The last stage is always set up by the client or listener and cannot + // be changed. All application-defined stages are executed before the + // last stage, which is typically a send or dispatch. + const std::shared_ptr m_last_stage; + +private: + + // The vector of pipeline stages. + std::vector> m_stages; + + pplx::extensibility::recursive_lock_t m_lock; +}; void http_client::add_handler(const std::function(http_request, std::shared_ptr)> &handler) { - m_pipeline->append(std::make_shared<::web::http::details::function_pipeline_wrapper>(handler)); + class function_pipeline_wrapper : public http::http_pipeline_stage + { + public: + function_pipeline_wrapper(const std::function(http_request, std::shared_ptr)> &handler) : m_handler(handler) + { + } + + virtual pplx::task propagate(http_request request) override + { + return m_handler(std::move(request), next_stage()); + } + private: + + std::function(http_request, std::shared_ptr)> m_handler; + }; + + m_pipeline->append(std::make_shared(handler)); } void http_client::add_handler(const std::shared_ptr &stage) @@ -287,20 +360,24 @@ http_client::http_client(const uri &base_uri) : http_client(base_uri, http_clien http_client::http_client(const uri &base_uri, const http_client_config &client_config) { + std::shared_ptr final_pipeline_stage; + if (base_uri.scheme().empty()) { auto uribuilder = uri_builder(base_uri); uribuilder.set_scheme(_XPLATSTR("http")); uri uriWithScheme = uribuilder.to_uri(); verify_uri(uriWithScheme); - m_pipeline = ::web::http::http_pipeline::create_pipeline(details::create_platform_final_pipeline_stage(uriWithScheme, client_config)); + final_pipeline_stage = details::create_platform_final_pipeline_stage(uriWithScheme, client_config); } else { verify_uri(base_uri); - m_pipeline = ::web::http::http_pipeline::create_pipeline(details::create_platform_final_pipeline_stage(base_uri, client_config)); + final_pipeline_stage = details::create_platform_final_pipeline_stage(base_uri, client_config); } + m_pipeline = std::make_shared(std::move(final_pipeline_stage)); + #if !defined(CPPREST_TARGET_XP) add_handler(std::static_pointer_cast( std::make_shared(client_config.oauth1()))); @@ -314,14 +391,29 @@ http_client::~http_client() CPPREST_NOEXCEPT {} const http_client_config & http_client::client_config() const { - auto ph = std::static_pointer_cast(m_pipeline->last_stage()); - return ph->client_config(); + return m_pipeline->m_last_stage->client_config(); } const uri & http_client::base_uri() const { - auto ph = std::static_pointer_cast(m_pipeline->last_stage()); - return ph->base_uri(); + return m_pipeline->m_last_stage->base_uri(); +} + +// Macros to help build string at compile time and avoid overhead. +#define STRINGIFY(x) _XPLATSTR(#x) +#define TOSTRING(x) STRINGIFY(x) +#define USERAGENT _XPLATSTR("cpprestsdk/") TOSTRING(CPPREST_VERSION_MAJOR) _XPLATSTR(".") TOSTRING(CPPREST_VERSION_MINOR) _XPLATSTR(".") TOSTRING(CPPREST_VERSION_REVISION) + +pplx::task http_client::request(http_request request, const pplx::cancellation_token &token) +{ + if (!request.headers().has(header_names::user_agent)) + { + request.headers().add(header_names::user_agent, USERAGENT); + } + + request._set_base_uri(base_uri()); + request._set_cancellation_token(token); + return m_pipeline->propagate(request); } diff --git a/Release/src/http/client/http_client_msg.cpp b/Release/src/http/client/http_client_msg.cpp index 0a73670a47..dd89d8fffa 100644 --- a/Release/src/http/client/http_client_msg.cpp +++ b/Release/src/http/client/http_client_msg.cpp @@ -97,21 +97,4 @@ utility::string_t details::_http_response::to_string() const return buffer.str(); } -// Macros to help build string at compile time and avoid overhead. -#define STRINGIFY(x) _XPLATSTR(#x) -#define TOSTRING(x) STRINGIFY(x) -#define USERAGENT _XPLATSTR("cpprestsdk/") TOSTRING(CPPREST_VERSION_MAJOR) _XPLATSTR(".") TOSTRING(CPPREST_VERSION_MINOR) _XPLATSTR(".") TOSTRING(CPPREST_VERSION_REVISION) - -pplx::task client::http_client::request(http_request request, const pplx::cancellation_token &token) -{ - if(!request.headers().has(header_names::user_agent)) - { - request.headers().add(header_names::user_agent, USERAGENT); - } - - request._set_base_uri(base_uri()); - request._set_cancellation_token(token); - return m_pipeline->propagate(request); -} - }} // namespace web::http diff --git a/Release/tests/functional/http/client/pipeline_stage_tests.cpp b/Release/tests/functional/http/client/pipeline_stage_tests.cpp index 4e166e26f7..e276a013b2 100644 --- a/Release/tests/functional/http/client/pipeline_stage_tests.cpp +++ b/Release/tests/functional/http/client/pipeline_stage_tests.cpp @@ -244,7 +244,7 @@ class modify_count_responses_stage : public http_pipeline_stage { request.headers().set_content_type(U("modified content type")); - auto currentStage = current_stage(); + auto currentStage = this->shared_from_this(); return next_stage()->propagate(request).then([currentStage](http_response response) -> http_response { From baa8c9bdcd8ea4f19603d6d261e3790316127023 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 3 Apr 2016 03:17:52 -0700 Subject: [PATCH 086/609] Add final for internal types. Fix docs. --- Release/include/cpprest/http_msg.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index c88e51ab1c..002a59e2f3 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -376,7 +376,7 @@ class _http_server_context /// /// Internal representation of an HTTP response. /// -class _http_response : public http::details::http_msg_base +class _http_response final : public http::details::http_msg_base { public: _http_response() : m_status_code((std::numeric_limits::max)()) { } @@ -488,7 +488,7 @@ class http_response /// Extracts the body of the response message as a string value, checking that the content type is a MIME text type. /// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out. /// - /// If true, ignores the Content-Type header and assumes UTF-8. + /// If true, ignores the Content-Type header and assumes text. /// String containing body of the message. pplx::task extract_string(bool ignore_content_type = false) const { @@ -500,7 +500,7 @@ class http_response /// Extracts the body of the response message as a UTF-8 string value, checking that the content type is a MIME text type. /// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out. /// - /// If true, ignores the Content-Type header and assumes UTF-8. + /// If true, ignores the Content-Type header and assumes text. /// String containing body of the message. pplx::task extract_utf8string(bool ignore_content_type = false) const { @@ -512,7 +512,7 @@ class http_response /// Extracts the body of the response message as a UTF-16 string value, checking that the content type is a MIME text type. /// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out. /// - /// If true, ignores the Content-Type header and assumes UTF-16. + /// If true, ignores the Content-Type header and assumes text. /// String containing body of the message. pplx::task extract_utf16string(bool ignore_content_type = false) const { @@ -524,7 +524,7 @@ class http_response /// Extracts the body of the response message into a json value, checking that the content type is application/json. /// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out. /// - /// If true, ignores the Content-Type header and assumes UTF-8. + /// If true, ignores the Content-Type header and assumes json. /// JSON value from the body of this message. pplx::task extract_json(bool ignore_content_type = false) const { @@ -707,7 +707,7 @@ namespace details { /// /// Internal representation of an HTTP request message. /// -class _http_request : public http::details::http_msg_base, public std::enable_shared_from_this<_http_request> +class _http_request final : public http::details::http_msg_base, public std::enable_shared_from_this<_http_request> { public: From ba2adb3f103604de8ec5e1223ab2ff0753d68bd7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 4 Apr 2016 18:38:49 -0700 Subject: [PATCH 087/609] http_pipeline does not have correct semantics under move. --- Release/src/http/client/http_client.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index ece552932c..6c69634f93 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -280,9 +280,11 @@ class http_pipeline http_pipeline(std::shared_ptr last) : m_last_stage(std::move(last)) {} - // No copy or assignment. - http_pipeline & operator=(const http_pipeline &) = delete; + // pplx::extensibility::recursive_lock_t does not support move/copy, but does not delete the functions either. http_pipeline(const http_pipeline &) = delete; + http_pipeline(http_pipeline &&) = delete; + http_pipeline & operator=(const http_pipeline &) = delete; + http_pipeline & operator=(http_pipeline &&) = delete; /// /// Initiate an http request into the pipeline From 479ebe78345d9e399db571aede694d9acadb8e56 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 12 Apr 2016 10:49:42 -0700 Subject: [PATCH 088/609] Code review comments for 952a0e22 Conflicts: Release/src/http/client/http_client.cpp --- Release/include/cpprest/http_msg.h | 6 ++---- Release/src/http/client/http_client.cpp | 2 +- Release/src/http/client/http_client_winhttp.cpp | 7 +++---- Release/src/http/client/http_client_winrt.cpp | 9 +++------ Release/src/http/common/http_msg.cpp | 10 +++++----- 5 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 002a59e2f3..b2721f9ebc 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -1337,14 +1337,12 @@ class http_pipeline_stage : public std::enable_shared_from_this /// Runs this stage against the given request and passes onto the next stage. diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 6c69634f93..d9676024ee 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -51,7 +51,7 @@ namespace details { #if defined(_WIN32) - const utility::char_t * get_with_body_err_msg = _XPLATSTR("A GET or HEAD request should not have an entity body."); + extern const utility::char_t * get_with_body_err_msg = _XPLATSTR("A GET or HEAD request should not have an entity body."); #endif void request_context::complete_headers() diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index ce1f27205d..e4d19042b2 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -317,6 +317,9 @@ class winhttp_client : public _http_client_communicator , m_hSession(nullptr) , m_hConnection(nullptr) { } + winhttp_client(const winhttp_client&) = delete; + winhttp_client &operator=(const winhttp_client&) = delete; + // Closes session. ~winhttp_client() { @@ -1289,10 +1292,6 @@ class winhttp_client : public _http_client_communicator HINTERNET m_hSession; HINTERNET m_hConnection; bool m_secure; - - // No copy or assignment. - winhttp_client(const winhttp_client&) = delete; - winhttp_client &operator=(const winhttp_client&) = delete; }; std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 44196a6412..5ae4a8ec52 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -359,6 +359,9 @@ class winrt_client : public _http_client_communicator winrt_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) { } + winrt_client(const winrt_client&) = delete; + winrt_client &operator=(const winrt_client&) = delete; + virtual pplx::task propagate(http_request request) override { auto self = std::static_pointer_cast<_http_client_communicator>(shared_from_this()); @@ -555,12 +558,6 @@ class winrt_client : public _http_client_communicator }); } } - -private: - - // No copy or assignment. - winrt_client(const winrt_client&) = delete; - winrt_client &operator=(const winrt_client&) = delete; }; std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index d8d2cf84a5..c9ab6ae7f0 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -47,19 +47,19 @@ utility::string_t http_headers::content_type() const /// Helper functions to convert a series of bytes from a charset to utf-8 or utf-16. /// These APIs deal with checking for and handling byte order marker (BOM). namespace { - enum endian_ness + enum endianness { little_endian, big_endian, unknown }; - endian_ness check_byte_order_mark(const utf16string &str) + endianness check_byte_order_mark(const utf16string &str) { if (str.empty()) { return unknown; } - const unsigned char *src = (const unsigned char *) &str[0]; + const unsigned char *src = reinterpret_cast(str.data()); // little endian if (src[0] == 0xFF && src[1] == 0xFE) @@ -142,7 +142,7 @@ namespace { std::string convert_utf16_to_utf8(utf16string src) { - const endian_ness endian = check_byte_order_mark(src); + const endianness endian = check_byte_order_mark(src); switch (endian) { case little_endian: @@ -158,7 +158,7 @@ namespace { utf16string convert_utf16_to_utf16(utf16string src) { - const endian_ness endian = check_byte_order_mark(src); + const endianness endian = check_byte_order_mark(src); switch (endian) { case little_endian: From b3325915bb42078cb16c03b7d9cae24ebeabd9fe Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 13 Apr 2016 23:37:56 -0700 Subject: [PATCH 089/609] Fix move of http_pipeline into web::http::client namespace --- Release/include/cpprest/http_client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 0c8d7e9f8c..a908c48de3 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -722,7 +722,7 @@ class http_client private: - std::shared_ptr<::web::http::http_pipeline> m_pipeline; + std::shared_ptr<::web::http::client::http_pipeline> m_pipeline; }; namespace details { From 54d7fcdac2a2e4621d6af5c42140c0986c8d8334 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 14 Apr 2016 00:39:04 -0700 Subject: [PATCH 090/609] Mark add_handler std::function argument as requiring __cdecl to guard against compiler options --- Release/include/cpprest/http_client.h | 2 +- Release/src/http/client/http_client.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index a908c48de3..8f9e0f9f8a 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -442,7 +442,7 @@ class http_client /// Adds an HTTP pipeline stage to the client. /// /// A function object representing the pipeline stage. - _ASYNCRTIMP void add_handler(const std::function(http_request, std::shared_ptr)> &handler); + _ASYNCRTIMP void add_handler(const std::function __cdecl(http_request, std::shared_ptr)> &handler); /// diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index d9676024ee..9f71603d85 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -331,12 +331,12 @@ class http_pipeline pplx::extensibility::recursive_lock_t m_lock; }; -void http_client::add_handler(const std::function(http_request, std::shared_ptr)> &handler) +void http_client::add_handler(const std::function __cdecl(http_request, std::shared_ptr)> &handler) { class function_pipeline_wrapper : public http::http_pipeline_stage { public: - function_pipeline_wrapper(const std::function(http_request, std::shared_ptr)> &handler) : m_handler(handler) + function_pipeline_wrapper(const std::function __cdecl(http_request, std::shared_ptr)> &handler) : m_handler(handler) { } From 834491eebc5222ec4d5a54b29c0f7afac46e59ec Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 12 Apr 2016 15:45:17 -0700 Subject: [PATCH 091/609] Improve CMake support for windows. Added experimental support for building UWP. Added support for accessing NuGet packages. Renamed project to 'cpprest'. Removed superfluous ${LIB} prefix on all libs. Enabled MultiToolTask for android build. Added header files to the cpprest library, improving IDE support. --- .gitignore | 4 +- Release/CMakeLists.txt | 61 ++++++++++---- Release/samples/BingRequest/CMakeLists.txt | 6 +- Release/samples/BlackJack/CMakeLists.txt | 8 +- Release/samples/Oauth1Client/CMakeLists.txt | 15 ++-- Release/samples/Oauth2Client/CMakeLists.txt | 13 +-- Release/samples/SearchFile/CMakeLists.txt | 6 +- Release/src/CMakeLists.txt | 83 +++++++++++++------ .../casablanca140.android.vcxproj | 8 ++ .../tests/common/TestRunner/CMakeLists.txt | 73 +++++++++------- .../tests/common/UnitTestpp/CMakeLists.txt | 8 +- Release/tests/common/utilities/CMakeLists.txt | 6 +- .../functional/http/client/CMakeLists.txt | 2 +- .../functional/http/listener/CMakeLists.txt | 42 +++++----- .../functional/http/utilities/CMakeLists.txt | 8 +- Release/tests/functional/json/CMakeLists.txt | 6 +- .../functional/pplx/pplx_test/CMakeLists.txt | 2 +- .../tests/functional/streams/CMakeLists.txt | 11 ++- .../functional/websockets/CMakeLists.txt | 23 ++++- .../websockets/client/CMakeLists.txt | 6 +- .../websockets/utilities/CMakeLists.txt | 21 ----- 21 files changed, 258 insertions(+), 154 deletions(-) delete mode 100644 Release/tests/functional/websockets/utilities/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 8cba58c6d3..d0ff65b0ac 100644 --- a/.gitignore +++ b/.gitignore @@ -63,4 +63,6 @@ Intermediate/ **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ - +.vs/ +# Ignore cmake building directories +build.*/ diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index e229106951..cbe840b663 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -1,6 +1,6 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0) cmake_minimum_required(VERSION 2.6) -project(casablanca) +project(cpprest) enable_testing() @@ -8,6 +8,8 @@ set(WARNINGS) set(ANDROID_STL_FLAGS) option(WERROR "Threat Warnings as Errors" ON) +option(BUILD_TESTS "Build tests." ON) +option(CPPREST_EXCLUDE_WEBSOCKETS "Exclude websockets functionality." OFF) # Platform (not compiler) specific settings if(IOS) @@ -27,7 +29,6 @@ if(IOS) set(BUILD_SHARED_LIBS OFF) set(BUILD_SAMPLES OFF) - option(BUILD_TESTS "Build tests." ON) elseif(ANDROID) set(Boost_COMPILER "-clang") set(Boost_USE_STATIC_LIBS ON) @@ -73,7 +74,6 @@ elseif(ANDROID) option(BUILD_SHARED_LIBS "Build shared Libraries." OFF) set(BUILD_SAMPLES OFF) - option(BUILD_TESTS "Build tests." ON) elseif(UNIX) # This includes OSX find_package(Boost 1.54 REQUIRED COMPONENTS random chrono system thread regex filesystem) find_package(Threads REQUIRED) @@ -88,7 +88,6 @@ elseif(UNIX) # This includes OSX find_package(OpenSSL 1.0.0 REQUIRED) option(BUILD_SHARED_LIBS "Build shared Libraries." ON) - option(BUILD_TESTS "Build tests." ON) option(BUILD_SAMPLES "Build samples." ON) option(CASA_INSTALL_HEADERS "Install header files." ON) if(CASA_INSTALL_HEADERS) @@ -101,9 +100,7 @@ elseif(UNIX) # This includes OSX endif() elseif(WIN32) option(BUILD_SHARED_LIBS "Build shared Libraries." ON) - option(BUILD_TESTS "Build tests." ON) option(BUILD_SAMPLES "Build samples." ON) - option(CPPREST_EXCLUDE_WEBSOCKETS "Exclude websockets functionality." OFF) option(Boost_USE_STATIC_LIBS ON) add_definitions(-DUNICODE -D_UNICODE) @@ -117,11 +114,31 @@ elseif(WIN32) endif() add_definitions(${Casablanca_DEFINITIONS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -DWIN32) - if (CPPREST_EXCLUDE_WEBSOCKETS) - add_definitions(-DCPPREST_EXCLUDE_WEBSOCKETS=1) - else() - find_package(Boost 1.55 REQUIRED COMPONENTS random system thread filesystem chrono atomic) - find_package(OpenSSL 1.0 REQUIRED) + if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + set(NUGET_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../packages") + set(PACKAGE_PATHS) + list(APPEND PACKAGE_PATHS "${NUGET_PATH}/boost.1.58.0.0/") + list(APPEND PACKAGE_PATHS "${NUGET_PATH}/boost_system-vc140.1.58.0-vs140rc/") + list(APPEND PACKAGE_PATHS "${NUGET_PATH}/boost_date_time-vc140.1.58.0-vs140rc/") + list(APPEND PACKAGE_PATHS "${NUGET_PATH}/boost_regex-vc140.1.58.0-vs140rc/") + list(APPEND PACKAGE_PATHS "${NUGET_PATH}/openssl.v140.windesktop.msvcstl.static.rt-dyn.x64.1.0.2.1/") + list(APPEND PACKAGE_PATHS "${NUGET_PATH}/zlib.v140.windesktop.msvcstl.static.rt-dyn.1.2.8.8/") + + if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + find_library(Boost_SYSTEM_LIBRARY libboost_system-vc140-mt-gd-1_58.lib PATHS ${PACKAGE_PATHS} PATH_SUFFIXES lib/native/address-model-64/lib) + find_library(Boost_DATE_TIME_LIBRARY libboost_date_time-vc140-mt-gd-1_58.lib PATHS ${PACKAGE_PATHS} PATH_SUFFIXES lib/native/address-model-64/lib) + find_library(Boost_REGEX_LIBRARY libboost_regex-vc140-mt-gd-1_58.lib PATHS ${PACKAGE_PATHS} PATH_SUFFIXES lib/native/address-model-64/lib) + set(Boost_LIBRARIES ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY}) + + find_library(OpenSSL_libeay_LIBRARY libeay32.lib PATHS ${PACKAGE_PATHS} PATH_SUFFIXES lib/native/v140/windesktop/msvcstl/static/rt-dyn/x64/debug) + find_library(OpenSSL_ssleay_LIBRARY ssleay32.lib PATHS ${PACKAGE_PATHS} PATH_SUFFIXES lib/native/v140/windesktop/msvcstl/static/rt-dyn/x64/debug) + find_library(ZLIB_LIBRARY zlibstaticd.lib PATHS ${PACKAGE_PATHS} PATH_SUFFIXES lib/native/v140/windesktop/msvcstl/static/rt-dyn/x64/debug) + set(OPENSSL_LIBRARIES ${OpenSSL_ssleay_LIBRARY} ${OpenSSL_libeay_LIBRARY} ${ZLIB_LIBRARY}) + + set(OPENSSL_INCLUDE_DIR "${NUGET_PATH}/openssl.v140.windesktop.msvcstl.static.rt-dyn.x64.1.0.2.1/build/native/include") + endif() + + set(Boost_INCLUDE_DIR "${NUGET_PATH}/boost.1.58.0.0/lib/native/include") endif() else() message(FATAL_ERROR "-- Unsupported Build Platform.") @@ -160,11 +177,20 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") message("-- Setting msvc options") set(WARNINGS) + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4264") + add_compile_options(/bigobj) + if (WINDOWS_STORE OR WINDOWS_PHONE) + add_compile_options(/ZW) + endif() else() message("-- Unknown compiler, success is doubtful.") message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}") endif() +if (CPPREST_EXCLUDE_WEBSOCKETS) + add_definitions(-DCPPREST_EXCLUDE_WEBSOCKETS=1) +endif() + # Reconfigure final output directory set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) @@ -190,9 +216,8 @@ else() set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) endif() -set(Casablanca_LIBRARY ${LIB}cpprest) -set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} - ${Boost_LIBRARIES}) +set(Casablanca_LIBRARY cpprest) +set(Casablanca_LIBRARIES cpprest ${Boost_LIBRARIES}) # Everything in the project needs access to the casablanca include directories include_directories(${Casablanca_INCLUDE_DIRS}) @@ -203,16 +228,16 @@ function(add_casablanca_test NAME SOURCES_VAR) message("-- Added test library ${NAME}") if (NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") target_link_libraries(${NAME} - ${LIB}httptest_utilities - ${LIB}common_utilities - ${LIB}unittestpp + httptest_utilities + common_utilities + unittestpp ${Casablanca_LIBRARIES} ${ANDROID_STL_FLAGS} ) if (BUILD_SHARED_LIBS) add_test(NAME ${NAME} WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMAND test_runner lib${NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} + COMMAND test_runner $ ) endif() endif() diff --git a/Release/samples/BingRequest/CMakeLists.txt b/Release/samples/BingRequest/CMakeLists.txt index f4de12f102..261078cb76 100644 --- a/Release/samples/BingRequest/CMakeLists.txt +++ b/Release/samples/BingRequest/CMakeLists.txt @@ -1,2 +1,4 @@ -add_executable(BingRequest bingrequest.cpp) -target_link_libraries(BingRequest ${Casablanca_LIBRARIES}) \ No newline at end of file +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + add_executable(BingRequest bingrequest.cpp) + target_link_libraries(BingRequest ${Casablanca_LIBRARIES}) +endif() \ No newline at end of file diff --git a/Release/samples/BlackJack/CMakeLists.txt b/Release/samples/BlackJack/CMakeLists.txt index be0ea12e9e..422ec4c4cc 100644 --- a/Release/samples/BlackJack/CMakeLists.txt +++ b/Release/samples/BlackJack/CMakeLists.txt @@ -1,2 +1,6 @@ -add_subdirectory(BlackJack_Server) -add_subdirectory(BlackJack_Client) +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + add_subdirectory(BlackJack_Server) + add_subdirectory(BlackJack_Client) +else() + # TODO: add BlackJack_UIClient +endif() diff --git a/Release/samples/Oauth1Client/CMakeLists.txt b/Release/samples/Oauth1Client/CMakeLists.txt index a67ab7f547..ee8c82f2dc 100644 --- a/Release/samples/Oauth1Client/CMakeLists.txt +++ b/Release/samples/Oauth1Client/CMakeLists.txt @@ -1,7 +1,8 @@ - -add_executable(oauth1client - Oauth1Client.cpp - stdafx.cpp - ) - -target_link_libraries(oauth1client ${Casablanca_LIBRARIES}) +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + add_executable(oauth1client + Oauth1Client.cpp + stdafx.cpp + ) + + target_link_libraries(oauth1client ${Casablanca_LIBRARIES}) +endif() \ No newline at end of file diff --git a/Release/samples/Oauth2Client/CMakeLists.txt b/Release/samples/Oauth2Client/CMakeLists.txt index 0ed8385cf6..212afb2001 100644 --- a/Release/samples/Oauth2Client/CMakeLists.txt +++ b/Release/samples/Oauth2Client/CMakeLists.txt @@ -1,7 +1,8 @@ +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + add_executable(oauth2client + Oauth2Client.cpp + stdafx.cpp + ) -add_executable(oauth2client - Oauth2Client.cpp - stdafx.cpp - ) - -target_link_libraries(oauth2client ${Casablanca_LIBRARIES}) + target_link_libraries(oauth2client ${Casablanca_LIBRARIES}) +endif() \ No newline at end of file diff --git a/Release/samples/SearchFile/CMakeLists.txt b/Release/samples/SearchFile/CMakeLists.txt index e1313e6405..d933df6781 100644 --- a/Release/samples/SearchFile/CMakeLists.txt +++ b/Release/samples/SearchFile/CMakeLists.txt @@ -1,2 +1,4 @@ -add_executable(SearchFile searchfile.cpp) -target_link_libraries(SearchFile ${Casablanca_LIBRARIES}) +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + add_executable(SearchFile searchfile.cpp) + target_link_libraries(SearchFile ${Casablanca_LIBRARIES}) +endif() diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index ade7c93b5b..51ea088418 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -3,8 +3,21 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) include_directories(${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}) endif() +add_definitions(${WARNINGS}) + +file(GLOB SOURCES_CPPREST "../include/cpprest/*.h") +file(GLOB SOURCES_PPLX "../include/pplx/*.h") +file(GLOB SOURCES_DETAILS "../include/cpprest/details/*.h") +source_group("Header Files\\cpprest" FILES ${SOURCES_CPPREST}) +source_group("Header Files\\pplx" FILES ${SOURCES_PPLX}) +source_group("Header Files\\cpprest\\details" FILES ${SOURCES_DETAILS}) set(SOURCES_COMMON + ${SOURCES_CPPREST} + ${SOURCES_PPLX} + ${SOURCES_DETAILS} + http/client/http_client.cpp http/client/http_client_msg.cpp + http/client/http_client_impl.h http/client/x509_cert_utilities.cpp http/common/http_helpers.cpp http/common/http_msg.cpp @@ -25,7 +38,6 @@ set(SOURCES_COMMON utilities/web_utilities.cpp websockets/client/ws_msg.cpp websockets/client/ws_client.cpp - websockets/client/ws_client_wspp.cpp ) # THE ORDER OF FILES IS VERY /VERY/ IMPORTANT @@ -37,6 +49,9 @@ if(UNIX) http/client/http_client_asio.cpp http/listener/http_server_asio.cpp ) + if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + list(APPEND SOURCES websockets/client/ws_client_wspp.cpp) + endif() if(APPLE) list(APPEND SOURCES pplx/pplxapple.cpp @@ -55,45 +70,61 @@ if(UNIX) endif() if(WERROR) - set(WARNINGS "${WARNINGS} -Werror") + add_compile_options(-Werror) endif() - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -pedantic") + add_compile_options(-pedantic) elseif(WIN32) - set(SOURCES - ${SOURCES_COMMON} - http/client/http_client_winhttp.cpp - http/client/x509_cert_utilities_win32.cpp - http/listener/http_server_httpsys.cpp + set(SOURCES ${SOURCES_COMMON} pplx/pplxwin.cpp - streams/fileio_win32.cpp - pch/stdafx.cpp ) - set(EXTRALINKS - bcrypt.lib - crypt32.lib - httpapi.lib - Winhttp.lib - ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS}") - if (${CMAKE_GENERATOR} MATCHES "Visual Studio .*") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Yustdafx.h /Zm200") - set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + if (WINDOWS_PHONE OR WINDOWS_STORE) + list(APPEND SOURCES + http/client/http_client_winrt.cpp + streams/fileio_winrt.cpp + websockets/client/ws_client_winrt.cpp + ) + else() + list(APPEND SOURCES + http/client/http_client_winhttp.cpp + http/listener/http_server_httpsys.cpp + streams/fileio_win32.cpp + ) + if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + list(APPEND SOURCES websockets/client/ws_client_wspp.cpp) + endif() + set(EXTRALINKS + bcrypt.lib + crypt32.lib + httpapi.lib + Winhttp.lib + ) endif() + add_compile_options(/Yustdafx.h /Zm200) + set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + + if (NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio .*") + set_property(SOURCE pch/stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${SOURCES} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + list(APPEND SOURCES pch/stdafx.cpp pch/stdafx.h) if (BUILD_SHARED_LIBS) add_definitions(-D_ASYNCRT_EXPORT -D_PPLX_EXPORT -D_USRDLL) endif() endif() -add_library(${Casablanca_LIBRARY} ${SOURCES}) +add_library(cpprest ${SOURCES}) -target_link_libraries(${Casablanca_LIBRARY} +target_link_libraries(cpprest ${CMAKE_THREAD_LIBS_INIT} ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_ATOMIC_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_RANDOM_LIBRARY} + ${Boost_REGEX_LIBRARY} + ${Boost_DATE_TIME_LIBRARY} ${EXTRALINKS} ${Boost_FRAMEWORK} ${OPENSSL_LIBRARIES} @@ -107,17 +138,17 @@ set (CPPREST_VERSION_MINOR 8) set (CPPREST_VERSION_REVISION 0) if(WIN32) - set_target_properties(${Casablanca_LIBRARY} PROPERTIES - OUTPUT_NAME "${Casablanca_LIBRARY}_${CPPREST_VERSION_MAJOR}_${CPPREST_VERSION_MINOR}") + set_target_properties(cpprest PROPERTIES + OUTPUT_NAME "cpprest_${CPPREST_VERSION_MAJOR}_${CPPREST_VERSION_MINOR}") elseif(ANDROID) # Do not use SOVERSION on android. It is completely unsupported (and causes problems). # Perhaps revisit in the future? (NDK r9d, 8/7/14) else() - set_target_properties(${Casablanca_LIBRARY} PROPERTIES + set_target_properties(cpprest PROPERTIES SOVERSION ${CPPREST_VERSION_MAJOR}.${CPPREST_VERSION_MINOR}) install( - TARGETS ${Casablanca_LIBRARY} + TARGETS cpprest LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) diff --git a/Release/src/build/vs14.android/casablanca140.android.vcxproj b/Release/src/build/vs14.android/casablanca140.android.vcxproj index 72b51b7e3f..6e7d82feaf 100644 --- a/Release/src/build/vs14.android/casablanca140.android.vcxproj +++ b/Release/src/build/vs14.android/casablanca140.android.vcxproj @@ -60,8 +60,10 @@ + true + true @@ -113,6 +115,12 @@ $(CppRestBaseFileName)140$(DebugFileSuffix)_android_$(CppRestSDKVersionFileSuffix) + + true + + + true + diff --git a/Release/tests/common/TestRunner/CMakeLists.txt b/Release/tests/common/TestRunner/CMakeLists.txt index 19bd2162aa..29669d277a 100644 --- a/Release/tests/common/TestRunner/CMakeLists.txt +++ b/Release/tests/common/TestRunner/CMakeLists.txt @@ -7,7 +7,13 @@ set(TR_SOURCES test_module_loader.cpp ) -add_definitions(-DDESKTOP_TEST_RUNNER) +if (WIN32) + if (WINDOWS_STORE OR WINDOWS_PHONE) + add_definitions(-DWINRT_TEST_RUNNER -D_CONSOLE) + else() + add_definitions(-DDESKTOP_TEST_RUNNER) + endif() +endif() if(NOT IOS AND NOT ANDROID) if(BUILD_SHARED_LIBS) @@ -18,7 +24,7 @@ if(NOT IOS AND NOT ANDROID) target_link_libraries(test_runner ${Boost_LIBRARIES} - ${LIB}unittestpp + unittestpp ${CMAKE_DL_LIBS} ) else() @@ -30,28 +36,28 @@ if(NOT IOS AND NOT ANDROID) target_link_libraries(test_runner ${Boost_LIBRARIES} - ${LIB}unittestpp + unittestpp ${CMAKE_DL_LIBS} -Wl,-force_load - ${LIB}httpclient_test + httpclient_test -Wl,-force_load - ${LIB}json_test + json_test -Wl,-force_load - ${LIB}uri_test + uri_test -Wl,-force_load - ${LIB}pplx_test + pplx_test -Wl,-force_load - ${LIB}httplistener_test + httplistener_test -Wl,-force_load - ${LIB}streams_test + streams_test -Wl,-force_load - ${LIB}utils_test + utils_test ) elseif(UNIX) add_executable(test_runner @@ -61,36 +67,47 @@ if(NOT IOS AND NOT ANDROID) target_link_libraries(test_runner ${Boost_LIBRARIES} - ${LIB}unittestpp + unittestpp ${CMAKE_DL_LIBS} -Wl,--whole-archive - ${LIB}httpclient_test - ${LIB}json_test - ${LIB}uri_test - ${LIB}pplx_test - ${LIB}httplistener_test - ${LIB}streams_test - ${LIB}utils_test + httpclient_test + json_test + uri_test + pplx_test + httplistener_test + streams_test + utils_test -Wl,--no-whole-archive ) else() # In order to achieve --whole-archive on windows, we link all the test files into the test_runner directly # This means that the tests themselves must be created as "OBJECT" libraries - add_executable(test_runner + set(SOURCES test_runner.cpp - test_module_loader.cpp - $ - $ - $ - $ - $ - $ - $ + $ + $ + $ + $ + $ + $ + ) + if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + list(APPEND SOURCES + test_module_loader.cpp + $ ) + endif() + add_executable(test_runner ${SOURCES}) target_link_libraries(test_runner - ${LIB}unittestpp + unittestpp + common_utilities + httptest_utilities + cpprest ${CMAKE_DL_LIBS} ) + if (WINDOWS_STORE) + target_link_libraries(test_runner ucrtd.lib vcruntimed.lib vccorlibd.lib msvcrtd.lib msvcprtd.lib concrtd.lib RuntimeObject.lib) + endif() endif() endif() endif() diff --git a/Release/tests/common/UnitTestpp/CMakeLists.txt b/Release/tests/common/UnitTestpp/CMakeLists.txt index c8e229dd7e..2c8205aa13 100644 --- a/Release/tests/common/UnitTestpp/CMakeLists.txt +++ b/Release/tests/common/UnitTestpp/CMakeLists.txt @@ -38,15 +38,15 @@ set(TEST_SOURCES ) if(UNIX) - set(UT_SOURCES ${UT_SOURCES} + list(APPEND UT_SOURCES src/Posix/SignalTranslator.cpp src/Posix/TimeHelpers.cpp ) elseif(WIN32) - set(UT_SOURCES ${UT_SOURCES} src/Win32/TimeHelpers.cpp) + list(APPEND UT_SOURCES src/Win32/TimeHelpers.cpp) add_definitions(-DWIN32 -D_USRDLL -D_CRT_SECURE_NO_DEPRECATE -DUNITTEST_DLL_EXPORT) endif() -add_library(${LIB}unittestpp ${UT_SOURCES}) -target_link_libraries(${LIB}unittestpp ${ANDROID_STL_FLAGS}) \ No newline at end of file +add_library(unittestpp ${UT_SOURCES}) +target_link_libraries(unittestpp ${ANDROID_STL_FLAGS}) \ No newline at end of file diff --git a/Release/tests/common/utilities/CMakeLists.txt b/Release/tests/common/utilities/CMakeLists.txt index 0b5996c834..6ff564f84e 100644 --- a/Release/tests/common/utilities/CMakeLists.txt +++ b/Release/tests/common/utilities/CMakeLists.txt @@ -4,14 +4,14 @@ if(WIN32) add_definitions(-DCOMMONUTILITIES_EXPORTS) endif() -add_library(${LIB}common_utilities +add_library(common_utilities os_utilities.cpp stdafx.cpp ) -target_link_libraries(${LIB}common_utilities +target_link_libraries(common_utilities ${Casablanca_LIBRARY} - ${LIB}unittestpp + unittestpp ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ) diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index dd9a2b89d0..d18060894f 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -29,4 +29,4 @@ set(SOURCES http_client_fuzz_tests.cpp ) -add_casablanca_test(${LIB}httpclient_test SOURCES) +add_casablanca_test(httpclient_test SOURCES) diff --git a/Release/tests/functional/http/listener/CMakeLists.txt b/Release/tests/functional/http/listener/CMakeLists.txt index 209e4026d8..270b89de25 100644 --- a/Release/tests/functional/http/listener/CMakeLists.txt +++ b/Release/tests/functional/http/listener/CMakeLists.txt @@ -1,20 +1,22 @@ -include_directories (../utilities/include) - -set (SOURCES - building_response_tests.cpp - connections_and_errors.cpp - header_tests.cpp - listener_construction_tests.cpp - reply_helper_tests.cpp - request_extract_tests.cpp - request_handler_tests.cpp - request_relative_uri_tests.cpp - request_stream_tests.cpp - requests_tests.cpp - response_stream_tests.cpp - status_code_reason_phrase_tests.cpp - to_string_tests.cpp - stdafx.cpp -) - -add_casablanca_test(${LIB}httplistener_test SOURCES) +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + include_directories (../utilities/include) + + set (SOURCES + building_response_tests.cpp + connections_and_errors.cpp + header_tests.cpp + listener_construction_tests.cpp + reply_helper_tests.cpp + request_extract_tests.cpp + request_handler_tests.cpp + request_relative_uri_tests.cpp + request_stream_tests.cpp + requests_tests.cpp + response_stream_tests.cpp + status_code_reason_phrase_tests.cpp + to_string_tests.cpp + stdafx.cpp + ) + + add_casablanca_test(httplistener_test SOURCES) +endif () \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/CMakeLists.txt b/Release/tests/functional/http/utilities/CMakeLists.txt index 08f6bcf351..a36e9614e3 100644 --- a/Release/tests/functional/http/utilities/CMakeLists.txt +++ b/Release/tests/functional/http/utilities/CMakeLists.txt @@ -11,10 +11,10 @@ set(SOURCES test_server_utilities.cpp ) -add_library(${LIB}httptest_utilities ${SOURCES}) -target_link_libraries(${LIB}httptest_utilities - ${LIB}unittestpp - ${LIB}common_utilities +add_library(httptest_utilities ${SOURCES}) +target_link_libraries(httptest_utilities + unittestpp + common_utilities ${BOOST_LIBRARIES} ${Casablanca_LIBRARIES} ) diff --git a/Release/tests/functional/json/CMakeLists.txt b/Release/tests/functional/json/CMakeLists.txt index c83741c940..f6d6ff7587 100644 --- a/Release/tests/functional/json/CMakeLists.txt +++ b/Release/tests/functional/json/CMakeLists.txt @@ -3,9 +3,11 @@ set (SOURCES negative_parsing_tests.cpp parsing_tests.cpp to_as_and_operators_tests.cpp - fuzz_tests.cpp iterator_tests.cpp json_numbers_tests.cpp ) +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + list(APPEND SOURCES fuzz_tests.cpp) +endif() -add_casablanca_test(${LIB}json_test SOURCES) +add_casablanca_test(json_test SOURCES) diff --git a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt index 000442f7ab..01c56f7522 100644 --- a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt +++ b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt @@ -5,4 +5,4 @@ set(SOURCES stdafx.cpp ) -add_casablanca_test(${LIB}pplx_test SOURCES) +add_casablanca_test(pplx_test SOURCES) diff --git a/Release/tests/functional/streams/CMakeLists.txt b/Release/tests/functional/streams/CMakeLists.txt index 72ce8177dd..c7e1147966 100644 --- a/Release/tests/functional/streams/CMakeLists.txt +++ b/Release/tests/functional/streams/CMakeLists.txt @@ -4,6 +4,13 @@ set(SOURCES memstream_tests.cpp ostream_tests.cpp stdstream_tests.cpp - fuzz_tests.cpp ) -add_casablanca_test(${LIB}streams_test SOURCES) +if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + list(APPEND SOURCES fuzz_tests.cpp) + if (WIN32) + list(APPEND SOURCES CppSparseFile.cpp) + endif () +else () + list(APPEND SOURCES winrt_interop_tests.cpp) +endif () +add_casablanca_test(streams_test SOURCES) diff --git a/Release/tests/functional/websockets/CMakeLists.txt b/Release/tests/functional/websockets/CMakeLists.txt index 415f5510fb..cd373a50d5 100644 --- a/Release/tests/functional/websockets/CMakeLists.txt +++ b/Release/tests/functional/websockets/CMakeLists.txt @@ -1,2 +1,21 @@ -add_subdirectory(client) -add_subdirectory(utilities) +if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + + include_directories(utilities/include) + + set(SOURCES + utilities/test_websocket_server.cpp + ) + + add_library(websockettest_utilities ${TEST_LIBRARY_TARGET_TYPE} ${SOURCES}) + target_compile_definitions(websockettest_utilities PRIVATE -DWEBSOCKETTESTUTILITY_EXPORTS) + if (NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") + target_link_libraries(websockettest_utilities + unittestpp + common_utilities + ${BOOST_LIBRARIES} + ${Casablanca_LIBRARIES} + ) + endif() + + add_subdirectory(client) +endif() diff --git a/Release/tests/functional/websockets/client/CMakeLists.txt b/Release/tests/functional/websockets/client/CMakeLists.txt index e4bd7a3625..9cb347ebb5 100644 --- a/Release/tests/functional/websockets/client/CMakeLists.txt +++ b/Release/tests/functional/websockets/client/CMakeLists.txt @@ -10,6 +10,8 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) send_msg_tests.cpp ) - add_casablanca_test(${LIB}websocketclient_test SOURCES) - target_link_libraries(${LIB}websocketclient_test ${LIB}websockettest_utilities) + add_casablanca_test(websocketclient_test SOURCES) + if (NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") + target_link_libraries(websocketclient_test websockettest_utilities) + endif() endif() \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/CMakeLists.txt b/Release/tests/functional/websockets/utilities/CMakeLists.txt deleted file mode 100644 index e1c5b1edba..0000000000 --- a/Release/tests/functional/websockets/utilities/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -if (NOT CPPREST_EXCLUDE_WEBSOCKETS) - - include_directories(include) - - if(WIN32) - add_definitions(-DWEBSOCKETTESTUTILITY_EXPORTS) - endif() - - set(SOURCES - test_websocket_server.cpp - ) - - add_library(${LIB}websockettest_utilities ${SOURCES}) - target_link_libraries(${LIB}websockettest_utilities - ${LIB}unittestpp - ${LIB}common_utilities - ${BOOST_LIBRARIES} - ${Casablanca_LIBRARIES} - ) - -endif() \ No newline at end of file From 45ff2f624667441d6dc214df19cd7839f4514cdd Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 14 Apr 2016 16:35:00 -0700 Subject: [PATCH 092/609] Remove extraneous allocation of boost::asio::ssl::stream --- Release/include/cpprest/details/http_server_asio.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Release/include/cpprest/details/http_server_asio.h b/Release/include/cpprest/details/http_server_asio.h index bf4695a213..95c1745083 100644 --- a/Release/include/cpprest/details/http_server_asio.h +++ b/Release/include/cpprest/details/http_server_asio.h @@ -89,7 +89,6 @@ class connection m_ssl_context = utility::details::make_unique(boost::asio::ssl::context::sslv23); ssl_context_callback(*m_ssl_context); m_ssl_stream = utility::details::make_unique>(*m_socket, *m_ssl_context); - m_ssl_stream = utility::details::make_unique>(*m_socket, *m_ssl_context); m_ssl_stream->async_handshake(boost::asio::ssl::stream_base::server, [this](const boost::system::error_code&) { this->start_request_response(); }); } From 7ff0685f5c30c77d4a0db24be9e1e3a3c7661ec0 Mon Sep 17 00:00:00 2001 From: Jason Ng Date: Sun, 17 Apr 2016 15:14:13 -0700 Subject: [PATCH 093/609] Update to include access control allow origin added DAT(access_control_allow_origin, "Access-Control-Allow-Origin") as a list of header items. --- Release/include/cpprest/details/http_constants.dat | 1 + 1 file changed, 1 insertion(+) diff --git a/Release/include/cpprest/details/http_constants.dat b/Release/include/cpprest/details/http_constants.dat index a36e931a7d..c408556b19 100644 --- a/Release/include/cpprest/details/http_constants.dat +++ b/Release/include/cpprest/details/http_constants.dat @@ -60,6 +60,7 @@ DAT(accept_charset, "Accept-Charset") DAT(accept_encoding, "Accept-Encoding") DAT(accept_language, "Accept-Language") DAT(accept_ranges, "Accept-Ranges") +DAT(access_control_allow_origin, "Access-Control-Allow-Origin") DAT(age, "Age") DAT(allow, "Allow") DAT(authorization, "Authorization") From 1e0b5c5d6e769b690ccb54cf156931577c81a337 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 20 Apr 2016 18:16:55 -0700 Subject: [PATCH 094/609] Remove Windows-On-Devices and android test runner from the default solution file. --- cpprestsdk140.sln | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln index c025ca9d0a..2392954c0a 100644 --- a/cpprestsdk140.sln +++ b/cpprestsdk140.sln @@ -43,20 +43,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile140", "Release\sa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.android", "Release\src\build\vs14.android\casablanca140.android.vcxproj", "{AFB49019-965B-4C10-BAFF-C86C16D58010}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.wod", "Release\src\build\vs14.wod\casablanca140.wod.vcxproj", "{3A584D9C-1A98-4046-B7D3-B7171EF42D34}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.vcxproj", "{36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp.staticlib", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.staticlib.vcxproj", "{47A5CFDC-C244-45A6-9830-38CB303CB495}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRunner.android.NativeActivity", "Release\tests\common\TestRunner\vs14.android\TestRunner.android.NativeActivity\TestRunner.android.NativeActivity.vcxproj", "{D1060D0A-A10E-444D-9F6B-9676EA453F9A}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.static", "Release\src\build\vs14.static\casablanca140.static.vcxproj", "{79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}" EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - Release\src\build\win32.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 @@ -182,22 +176,6 @@ Global {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x64.ActiveCfg = Release|x86 {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.ActiveCfg = Release|x86 {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.Build.0 = Release|x86 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|ARM.ActiveCfg = Debug|ARM - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|ARM.Build.0 = Debug|ARM - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|Win32.ActiveCfg = Debug|Win32 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|Win32.Build.0 = Debug|Win32 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|x64.ActiveCfg = Debug|x64 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|x64.Build.0 = Debug|x64 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|x86.ActiveCfg = Debug|Win32 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Debug|x86.Build.0 = Debug|Win32 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|ARM.ActiveCfg = Release|ARM - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|ARM.Build.0 = Release|ARM - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|Win32.ActiveCfg = Release|Win32 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|Win32.Build.0 = Release|Win32 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|x64.ActiveCfg = Release|x64 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|x64.Build.0 = Release|x64 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|x86.ActiveCfg = Release|Win32 - {3A584D9C-1A98-4046-B7D3-B7171EF42D34}.Release|x86.Build.0 = Release|Win32 {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.ActiveCfg = Debug|ARM {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.Build.0 = Debug|ARM {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -230,20 +208,6 @@ Global {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x64.Build.0 = Release|x64 {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.ActiveCfg = Release|Win32 {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.Build.0 = Release|Win32 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|ARM.ActiveCfg = Debug|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|ARM.Build.0 = Debug|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|Win32.ActiveCfg = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|Win32.Build.0 = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x64.ActiveCfg = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x86.ActiveCfg = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x86.Build.0 = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|ARM.ActiveCfg = Release|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|ARM.Build.0 = Release|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|Win32.ActiveCfg = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|Win32.Build.0 = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x64.ActiveCfg = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.ActiveCfg = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.Build.0 = Release|x86 {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.ActiveCfg = Debug|ARM {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.Build.0 = Debug|ARM {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -283,7 +247,6 @@ Global {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} = {76FA5645-FF99-44C0-87DB-B96AFAC2F800} {F03BEE03-BEFB-4B17-A774-D9C8246530D4} = {22309B46-EE6F-45D0-A993-2F45D98DEF22} {AFB49019-965B-4C10-BAFF-C86C16D58010} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {3A584D9C-1A98-4046-B7D3-B7171EF42D34} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {47A5CFDC-C244-45A6-9830-38CB303CB495} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} From d5afb5c0da9929313cc4b0f950555ebff9d13450 Mon Sep 17 00:00:00 2001 From: Deniz Turkoglu Date: Sun, 24 Apr 2016 10:21:31 +0200 Subject: [PATCH 095/609] Fix android build script for linux The build no longer uses libiconv but there were traces left. Also boost patch had a typo for x86. With these changes, the build script should work as expected. --- Build_android/boost-for-android-x86.patch | 18 ++------- Build_android/boost-for-android.patch | 16 +------- Build_android/configure.sh | 47 +++-------------------- 3 files changed, 10 insertions(+), 71 deletions(-) diff --git a/Build_android/boost-for-android-x86.patch b/Build_android/boost-for-android-x86.patch index 663c7befc1..8e3f2edcf9 100644 --- a/Build_android/boost-for-android-x86.patch +++ b/Build_android/boost-for-android-x86.patch @@ -13,29 +13,17 @@ index 40453f7..7ffc050 100755 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e + ;; -+ "10e-rc4 (64-bit)") ++ "10e-rc4 (64-bit)"|"10e (64-bit)") + TOOLCHAIN=llvm-3.6 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e ;; *) echo "Undefined or not supported Android NDK version!" -@@ -392,6 +397,7 @@ echo "Building boost for android" - export PATH=$AndroidBinariesPath:$PATH - export AndroidNDKRoot - export NO_BZIP2=1 -+ export ICONV_PATH="`pwd`/../../libiconv/x86" - - cxxflags="" - for flag in $CXXFLAGS; do cxxflags="$cxxflags cxxflags=$flag"; done -@@ -404,8 +410,12 @@ echo "Building boost for android" +@@ -404,8 +409,8 @@ echo "Building boost for android" threading=multi \ --layout=versioned \ --prefix="./../$BUILD_DIR/" \ -+ boost.locale.posix=off \ -+ boost.locale.std=on \ -+ boost.locale.iconv=on \ -+ boost.locale.icu=off \ $LIBRARIES \ - install 2>&1 \ + release debug install 2>&1 \ @@ -98,7 +86,7 @@ index 666d4c8..762753e 100644 +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-x86 # @Moss - Above are the 'oficial' android flags -arm -+#i686 ++i686 -fvisibility=hidden -fvisibility-inlines-hidden -fdata-sections diff --git a/Build_android/boost-for-android.patch b/Build_android/boost-for-android.patch index 4ed156f551..d37c923862 100644 --- a/Build_android/boost-for-android.patch +++ b/Build_android/boost-for-android.patch @@ -13,29 +13,17 @@ index 40453f7..ad78ddf 100755 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e + ;; -+ "10e-rc4 (64-bit)") ++ "10e-rc4 (64-bit)"|"10e (64-bit)") + TOOLCHAIN=llvm-3.6 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e ;; *) echo "Undefined or not supported Android NDK version!" -@@ -392,6 +397,7 @@ echo "Building boost for android" - export PATH=$AndroidBinariesPath:$PATH - export AndroidNDKRoot - export NO_BZIP2=1 -+ export ICONV_PATH="`pwd`/../../libiconv/armeabi-v7a" - - cxxflags="" - for flag in $CXXFLAGS; do cxxflags="$cxxflags cxxflags=$flag"; done -@@ -404,8 +410,12 @@ echo "Building boost for android" +@@ -404,8 +409,8 @@ echo "Building boost for android" threading=multi \ --layout=versioned \ --prefix="./../$BUILD_DIR/" \ -+ boost.locale.posix=off \ -+ boost.locale.std=on \ -+ boost.locale.iconv=on \ -+ boost.locale.icu=off \ $LIBRARIES \ - install 2>&1 \ + release debug install 2>&1 \ diff --git a/Build_android/configure.sh b/Build_android/configure.sh index 47e7d65897..5cef31364f 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -34,17 +34,15 @@ set -e # Parse args # ----------------- -DO_LIBICONV=1 DO_BOOST=1 DO_OPENSSL=1 DO_CPPRESTSDK=1 function usage { - echo "Usage: $0 [--skip-boost] [--skip-openssl] [--skip-libiconv] [--skip-cpprestsdk] [-h] [--ndk ]" + echo "Usage: $0 [--skip-boost] [--skip-openssl] [--skip-cpprestsdk] [-h] [--ndk ]" echo "" echo " --skip-boost Skip fetching and compiling boost" echo " --skip-openssl Skip fetching and compiling openssl" - echo " --skip-libiconv Skip fetching and compiling libiconv" echo " --skip-cpprestsdk Skip compiling cpprestsdk" echo " -h,--help,-? Display this information" echo " --ndk If specified, overrides the ANDROID_NDK environment variable" @@ -59,9 +57,6 @@ do "--skip-openssl") DO_OPENSSL=0 ;; - "--skip-libiconv") - DO_LIBICONV=0 - ;; "--skip-cpprestsdk") DO_CPPRESTSDK=0 ;; @@ -131,40 +126,6 @@ then ) fi -# -------- -# libiconv -# -------- - -# This steps are based on the blog post -# http://danilogiulianelli.blogspot.com/2012/12/how-to-cross-compile-libiconv-for.html -if [ "${DO_LIBICONV}" == "1" ] -then -( - if [ ! -e "libiconv-1.13.1.tar.gz" ] - then - wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz - fi - rm -rf libiconv - mkdir libiconv - cd libiconv - tar xzf ../libiconv-1.13.1.tar.gz - patch -b -p0 < "$DIR/libiconv/libiconv.patch" - cd libiconv-1.13.1 - ./configure - cp -r "$DIR/libiconv/jni" .. - cd ../jni - "${NDK_DIR}/ndk-build" || exit 1 - cd .. - mkdir -p armeabi-v7a/include - mkdir -p armeabi-v7a/lib - mkdir -p x86/include - mkdir -p x86/lib - cp libiconv-1.13.1/include/iconv.h armeabi-v7a/include/ - cp libiconv-1.13.1/include/iconv.h x86/include/ - cp obj/local/x86/libiconv.a x86/lib/ - cp obj/local/armeabi-v7a/libiconv.a armeabi-v7a/lib/ -) -fi # ----- # Boost @@ -187,7 +148,8 @@ then git apply "$DIR/boost-for-android.patch" touch cpprestsdk.patched.stamp fi - PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.55.0 --with-libraries=locale,random,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 + + PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.55.0 --with-libraries=random,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 ) ( @@ -204,7 +166,8 @@ then ln -s ../Boost-for-Android/boost_1_55_0.tar.bz2 . touch cpprestsdk.patched.stamp fi - PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.55.0 --with-libraries=locale,random,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 + + PATH="$PATH:$NDK_DIR" ./build-android.sh --boost=1.55.0 --with-libraries=atomic,random,date_time,filesystem,system,thread,chrono "${NDK_DIR}" || exit 1 ) ) fi From dad1c14df755973b2c0ddfb783f872481043e410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deniz=20T=C3=BCrkoglu?= Date: Wed, 27 Apr 2016 09:10:00 +0200 Subject: [PATCH 096/609] Enable builds on OSX Remove hardcoded platform strings with variables and fix scripts to work on both OSX and Linux. --- Build_android/boost-for-android-x86.patch | 24 ++++++++++++++++------- Build_android/boost-for-android.patch | 23 ++++++++++++++++------ Build_android/openssl/Makefile | 4 ++-- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/Build_android/boost-for-android-x86.patch b/Build_android/boost-for-android-x86.patch index 8e3f2edcf9..be0957dd3b 100644 --- a/Build_android/boost-for-android-x86.patch +++ b/Build_android/boost-for-android-x86.patch @@ -20,8 +20,15 @@ index 40453f7..7ffc050 100755 ;; *) echo "Undefined or not supported Android NDK version!" -@@ -404,8 +409,8 @@ echo "Building boost for android" - threading=multi \ +@@ -391,6 +396,7 @@ echo "Building boost for android" + export AndroidBinariesPath=`dirname $CXXPATH` + export PATH=$AndroidBinariesPath:$PATH + export AndroidNDKRoot ++ export PlatformOS + export NO_BZIP2=1 + + cxxflags="" +@@ -405,7 +411,7 @@ echo "Building boost for android" --layout=versioned \ --prefix="./../$BUILD_DIR/" \ $LIBRARIES \ @@ -31,11 +38,14 @@ index 40453f7..7ffc050 100755 } | tee -a $PROGDIR/build.log diff --git a/configs/user-config-boost-1_55_0.jam b/configs/user-config-boost-1_55_0.jam -index 666d4c8..762753e 100644 +index 666d4c8..4cd3441 100644 --- a/configs/user-config-boost-1_55_0.jam +++ b/configs/user-config-boost-1_55_0.jam -@@ -41,91 +41,44 @@ import os ; +@@ -39,93 +39,47 @@ + + import os ; local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; ++local PlatformOS = [ os.environ PlatformOS ] ; # -------------------------------------------------------------------- -# Is same for 8b, 8c and 8d @@ -43,10 +53,10 @@ index 666d4c8..762753e 100644 +using clang : androidR8e : -arm-linux-androideabi-g++ -+$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/linux-x86_64/bin/clang++ ++$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/$(PlatformOS)-x86_64/bin/clang++ : -arm-linux-androideabi-ar -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/linux-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/$(PlatformOS)-x86_64" -fexceptions -frtti -fpic @@ -82,7 +92,7 @@ index 666d4c8..762753e 100644 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/include +--target=i686-none-linux-android -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/linux-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/$(PlatformOS)-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-x86 # @Moss - Above are the 'oficial' android flags -arm diff --git a/Build_android/boost-for-android.patch b/Build_android/boost-for-android.patch index d37c923862..0b941435e3 100644 --- a/Build_android/boost-for-android.patch +++ b/Build_android/boost-for-android.patch @@ -20,7 +20,15 @@ index 40453f7..ad78ddf 100755 ;; *) echo "Undefined or not supported Android NDK version!" -@@ -404,8 +409,8 @@ echo "Building boost for android" +@@ -391,6 +396,7 @@ echo "Building boost for android" + export AndroidBinariesPath=`dirname $CXXPATH` + export PATH=$AndroidBinariesPath:$PATH + export AndroidNDKRoot ++ export PlatformOS + export NO_BZIP2=1 + + cxxflags="" +@@ -405,7 +411,7 @@ echo "Building boost for android" threading=multi \ --layout=versioned \ --prefix="./../$BUILD_DIR/" \ @@ -34,19 +42,22 @@ diff --git a/configs/user-config-boost-1_55_0.jam b/configs/user-config-boost-1_ index 666d4c8..df597f6 100644 --- a/configs/user-config-boost-1_55_0.jam +++ b/configs/user-config-boost-1_55_0.jam -@@ -41,82 +41,41 @@ import os ; +@@ -39,84 +39,44 @@ + + import os ; local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; - ++local PlatformOS = [ os.environ PlatformOS ] ; + # -------------------------------------------------------------------- -# Is same for 8b, 8c and 8d -using gcc : androidR8b +using clang : androidR8e : -arm-linux-androideabi-g++ -+$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/linux-x86_64/bin/clang++ ++$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/$(PlatformOS)-x86_64/bin/clang++ : -arm-linux-androideabi-ar -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/$(PlatformOS)-x86_64" -fexceptions -frtti -fpic @@ -126,7 +137,7 @@ index 666d4c8..df597f6 100644 +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include +-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi/include +--target=armv7-none-linux-androideabi -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/$(PlatformOS)-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-arm # @Moss - Above are the 'oficial' android flags arm diff --git a/Build_android/openssl/Makefile b/Build_android/openssl/Makefile index fbb5b84b64..f0bc60591d 100644 --- a/Build_android/openssl/Makefile +++ b/Build_android/openssl/Makefile @@ -16,8 +16,8 @@ setenv-android.sh: setenv-android-x86.sh: setenv-android.sh cp setenv-android.sh setenv-android-x86.sh.tmp - sed -i 's/_ANDROID_EABI="arm-linux-androideabi-4.8"/_ANDROID_EABI="x86-4.8"/g' setenv-android-x86.sh.tmp - sed -i 's/_ANDROID_ARCH=arch-arm/_ANDROID_ARCH=arch-x86/g' setenv-android-x86.sh.tmp + sed -i -e 's/_ANDROID_EABI="arm-linux-androideabi-4.8"/_ANDROID_EABI="x86-4.8"/g' setenv-android-x86.sh.tmp + sed -i -e 's/_ANDROID_ARCH=arch-arm/_ANDROID_ARCH=arch-x86/g' setenv-android-x86.sh.tmp mv setenv-android-x86.sh.tmp setenv-android-x86.sh $(OPENSSL_VER).tar.gz: From 12619af30abdd64bac08a16ec4d4683735331bb4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 6 May 2016 23:27:19 +0200 Subject: [PATCH 097/609] Work around SSL compression methods memory leak in ASIO Call SSL_COMP_free_compression_methods() because ASIO itself doesn't, even though it should, because it calls SSL_library_init() which allocates memory for the compression methods. Closes https://github.com/Microsoft/cpprestsdk/issues/67 --- .../src/websockets/client/ws_client_wspp.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 81512bc89f..6b5971e481 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -62,6 +62,26 @@ #endif /* __GNUC__ */ +// This is a hack to avoid memory leak reports from the debug MSVC CRT for all +// programs using the library: ASIO calls SSL_library_init() which calls +// SSL_COMP_get_compression_methods(), which allocates some heap memory and the +// only way to free it later is to call SSL_COMP_free_compression_methods(), +// but this function is unaccessible from the application code as OpenSSL is +// statically linked into the C++ REST SDK DLL. So, just to be nice, call it +// here ourselves -- even if the real problem is in ASIO (up to v1.60.0). +#if defined(_WIN32) && !defined(NDEBUG) + +#include +static struct ASIO_SSL_memory_leak_suppress +{ + ~ASIO_SSL_memory_leak_suppress() + { + ::SSL_COMP_free_compression_methods(); + } +} ASIO_SSL_memory_leak_suppressor; + +#endif /* _WIN32 && !NDEBUG */ + using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_2; using websocketpp::lib::bind; From 5df687f16908a76d211d6a04bc8051aefc8dfc74 Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Wed, 4 May 2016 08:48:22 +0000 Subject: [PATCH 098/609] some perf improvements for uri related code --- Release/include/cpprest/asyncrt_utils.h | 10 ++++++++++ Release/include/cpprest/base_uri.h | 6 ++++++ Release/include/cpprest/http_headers.h | 2 +- Release/include/cpprest/uri_builder.h | 2 +- Release/src/uri/uri.cpp | 24 ++++++++++++------------ Release/src/uri/uri_builder.cpp | 2 +- Release/src/uri/uri_parser.cpp | 4 ++-- 7 files changed, 33 insertions(+), 17 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 3d7f3ee5e0..73b6f5b97e 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -197,6 +197,11 @@ namespace conversions return print_string(val, std::locale()); } + inline utility::string_t print_string(const utility::string_t &val) + { + return val; + } + template Target scan_string(const utility::string_t &str, const std::locale &loc) { @@ -216,6 +221,11 @@ namespace conversions { return scan_string(str, std::locale()); } + + inline utility::string_t scan_string(const utility::string_t &str) + { + return str; + } } namespace details diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index ee24fb453e..5f354fa5ad 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -223,6 +223,12 @@ namespace web { /// uri() { m_uri = _XPLATSTR("/");}; + /// + /// Creates a URI from the given URI components. + /// + /// A URI components object to create the URI instance. + _ASYNCRTIMP uri(const details::uri_components &components) : m_components(components) { m_uri = m_components.join(); } + /// /// Creates a URI from the given encoded string. This will throw an exception if the string /// does not contain a valid URI. Use uri::validate if processing user-input. diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 8228d7cccb..e0c4526def 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -159,7 +159,7 @@ class http_headers { if (has(name)) { - m_headers[name] = m_headers[name].append(_XPLATSTR(", ") + utility::conversions::print_string(value)); + m_headers[name] = m_headers[name].append(_XPLATSTR(", ")).append(utility::conversions::print_string(value)); } else { diff --git a/Release/include/cpprest/uri_builder.h b/Release/include/cpprest/uri_builder.h index e4fb2024fd..1537063e5a 100644 --- a/Release/include/cpprest/uri_builder.h +++ b/Release/include/cpprest/uri_builder.h @@ -238,7 +238,7 @@ namespace web uri_builder &append_query(const utility::string_t &name, const T &value, bool do_encoding = true) { auto encodedName = name; - auto encodedValue = ::utility::conversions::print_string(value, std::locale::classic()); + auto encodedValue = ::utility::conversions::print_string(value); if (do_encoding) { diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index e9647bb276..b5d12af772 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -53,28 +53,27 @@ utility::string_t uri_components::join() m_path.insert(m_path.begin(), 1, _XPLATSTR('/')); } - utility::ostringstream_t os; - os.imbue(std::locale::classic()); + utility::string_t ret; if (!m_scheme.empty()) { - os << m_scheme << _XPLATSTR(':'); + ret.append(m_scheme).append({ _XPLATSTR(':') }); } if (!m_host.empty()) { - os << _XPLATSTR("//"); + ret.append(_XPLATSTR("//")); if (!m_user_info.empty()) { - os << m_user_info << _XPLATSTR('@'); + ret.append(m_user_info).append({ _XPLATSTR('@') }); } - os << m_host; + ret.append(m_host); if (m_port > 0) { - os << _XPLATSTR(':') << m_port; + ret.append({ _XPLATSTR(':') }).append(utility::conversions::print_string(m_port)); } } @@ -83,22 +82,23 @@ utility::string_t uri_components::join() // only add the leading slash when the host is present if (!m_host.empty() && m_path.front() != _XPLATSTR('/')) { - os << _XPLATSTR('/'); + ret.append({ _XPLATSTR('/') }); } - os << m_path; + + ret.append(m_path); } if (!m_query.empty()) { - os << _XPLATSTR('?') << m_query; + ret.append({ _XPLATSTR('?') }).append(m_query); } if (!m_fragment.empty()) { - os << _XPLATSTR('#') << m_fragment; + ret.append({ _XPLATSTR('#') }).append(m_fragment); } - return os.str(); + return ret; } } diff --git a/Release/src/uri/uri_builder.cpp b/Release/src/uri/uri_builder.cpp index a94a22eb9b..28085161c0 100644 --- a/Release/src/uri/uri_builder.cpp +++ b/Release/src/uri/uri_builder.cpp @@ -110,7 +110,7 @@ utility::string_t uri_builder::to_string() uri uri_builder::to_uri() { - return uri(m_uri.join()); + return uri(m_uri); } bool uri_builder::is_valid() diff --git a/Release/src/uri/uri_parser.cpp b/Release/src/uri/uri_parser.cpp index 1d4f7e33e7..75bf73f273 100644 --- a/Release/src/uri/uri_parser.cpp +++ b/Release/src/uri/uri_parser.cpp @@ -100,7 +100,7 @@ bool parse(const utility::string_t &encoded_string, uri_components &components) // convert scheme to lowercase std::transform(components.m_scheme.begin(), components.m_scheme.end(), components.m_scheme.begin(), [](utility::char_t c) { - return std::tolower(c, std::locale::classic()); + return (utility::char_t)tolower(c); }); } else @@ -119,7 +119,7 @@ bool parse(const utility::string_t &encoded_string, uri_components &components) // convert host to lowercase std::transform(components.m_host.begin(), components.m_host.end(), components.m_host.begin(), [](utility::char_t c) { - return std::tolower(c, std::locale::classic()); + return (utility::char_t)tolower(c); }); } else From 5f0b315b06230ea9acff14af0aec279c112be897 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 12 May 2016 12:20:31 -0700 Subject: [PATCH 099/609] Fix renamed argument under CPPREST_STDLIB_UNICODE_CONVERSIONS. Fixes #153. --- Release/src/utilities/asyncrt_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index d1af12b8dd..ab502ac5c5 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -284,7 +284,7 @@ utf16string __cdecl conversions::utf8_to_utf16(const std::string &s) { #if defined(CPPREST_STDLIB_UNICODE_CONVERSIONS) std::wstring_convert, utf16char> conversion; - return conversion.from_bytes(src); + return conversion.from_bytes(s); #else utf16string dest; // Save repeated heap allocations, use less than source string size assuming some From 6e23e697813541d19e5b2dbcd7b6ec0895c53dbb Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Thu, 12 May 2016 05:58:48 +0000 Subject: [PATCH 100/609] add host based connection pool map --- Release/include/pplx/threadpool.h | 20 +++++++++ Release/src/http/client/http_client_asio.cpp | 45 ++++++++++++++------ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index c778040737..f28c51ea31 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -42,6 +42,10 @@ #include "pplx/pplx.h" #endif +namespace web { namespace http { namespace client { namespace details { + class asio_connection_pool; +}}}} + namespace crossplat { #if (defined(ANDROID) || defined(__ANDROID__)) @@ -97,6 +101,19 @@ class threadpool return m_service; } + std::shared_ptr obtain_connection_pool(const std::string &base_uri, std::function()> connection_pool_generator) + { + std::lock_guard lg(m_connection_pool_map_mutex); + + auto &pool = m_connection_pool_map[base_uri]; + if (!pool) + { + pool = connection_pool_generator(); + } + + return pool; + } + private: struct _cancel_thread { }; @@ -156,6 +173,9 @@ class threadpool std::vector m_threads; boost::asio::io_service m_service; boost::asio::io_service::work m_work; + + std::mutex m_connection_pool_map_mutex; + std::map> m_connection_pool_map; }; } diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 72eeb0d8df..f9b1747c52 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -325,24 +325,45 @@ class asio_connection_pool boost::asio::io_service& m_io_service; const int m_timeout_secs; const bool m_start_with_ssl; - const std::function& m_ssl_context_callback; + std::function m_ssl_context_callback; std::vector > m_connections; std::mutex m_connections_mutex; }; - class asio_client : public _http_client_communicator { public: asio_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) - , m_pool(crossplat::threadpool::shared_instance().service(), - base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), - std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. - this->client_config().get_ssl_context_callback()) , m_resolver(crossplat::threadpool::shared_instance().service()) - {} + { + std::string host = base_uri().to_string(); + + auto &credentials = _http_client_communicator::client_config().credentials(); + if (credentials.is_set()) + { + host.append(credentials.username()); + } + + auto &proxy = _http_client_communicator::client_config().proxy(); + if (proxy.is_specified()) + { + host.append(proxy.address().to_string()); + if (proxy.credentials().is_set()) + { + host.append(proxy.credentials().username()); + } + } + + m_pool = crossplat::threadpool::shared_instance().obtain_connection_pool(host, [this]() + { + return std::make_shared(crossplat::threadpool::shared_instance().service(), + base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), + std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. + this->client_config().get_ssl_context_callback()); + }); + } void send_request(const std::shared_ptr &request_ctx) override; @@ -350,7 +371,7 @@ class asio_client : public _http_client_communicator virtual pplx::task propagate(http_request request) override; - asio_connection_pool m_pool; + std::shared_ptr m_pool; tcp::resolver m_resolver; }; @@ -375,13 +396,13 @@ class asio_context : public request_context, public std::enable_shared_from_this { m_timer.stop(); // Release connection back to the pool. If connection was not closed, it will be put to the pool for reuse. - std::static_pointer_cast(m_http_client)->m_pool.release(m_connection); + std::static_pointer_cast(m_http_client)->m_pool->release(m_connection); } static std::shared_ptr create_request_context(std::shared_ptr<_http_client_communicator> &client, http_request &request) { auto client_cast(std::static_pointer_cast(client)); - auto connection(client_cast->m_pool.obtain()); + auto connection(client_cast->m_pool->obtain()); auto ctx = std::make_shared(client, request, connection); ctx->m_timer.set_ctx(std::weak_ptr(ctx)); return ctx; @@ -458,7 +479,7 @@ class asio_context : public request_context, public std::enable_shared_from_this m_context->m_timer.reset(); //// Replace the connection. This causes old connection object to go out of scope. auto client = std::static_pointer_cast(m_context->m_http_client); - m_context->m_connection = client->m_pool.obtain(); + m_context->m_connection = client->m_pool->obtain(); auto endpoint = *endpoints; m_context->m_connection->async_connect(endpoint, boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); @@ -811,7 +832,7 @@ class asio_context : public request_context, public std::enable_shared_from_this { // Replace the connection. This causes old connection object to go out of scope. auto client = std::static_pointer_cast(m_http_client); - m_connection = client->m_pool.obtain(); + m_connection = client->m_pool->obtain(); auto endpoint = *endpoints; m_connection->async_connect(endpoint, boost::bind(&asio_context::handle_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); From 8e09ae6ae391c272c1a5b0f8217508c39d771d12 Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Wed, 18 May 2016 03:45:46 +0000 Subject: [PATCH 101/609] fixed 2 unit tests uri_builder_tests:to_string_invalid_uri uri_builder_tests:append_query_locale --- Release/include/cpprest/base_uri.h | 2 +- Release/include/cpprest/http_headers.h | 2 +- Release/include/cpprest/uri_builder.h | 2 +- Release/src/uri/uri.cpp | 11 ++++++++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index 5f354fa5ad..e6428e3e5c 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -227,7 +227,7 @@ namespace web { /// Creates a URI from the given URI components. /// /// A URI components object to create the URI instance. - _ASYNCRTIMP uri(const details::uri_components &components) : m_components(components) { m_uri = m_components.join(); } + _ASYNCRTIMP uri(const details::uri_components &components); /// /// Creates a URI from the given encoded string. This will throw an exception if the string diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 06d0b2cb68..0d318cbee4 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -159,7 +159,7 @@ class http_headers { if (has(name)) { - m_headers[name] = m_headers[name].append(_XPLATSTR(", ")).append(utility::conversions::print_string(value)); + m_headers[name].append(_XPLATSTR(", ")).append(utility::conversions::print_string(value)); } else { diff --git a/Release/include/cpprest/uri_builder.h b/Release/include/cpprest/uri_builder.h index 1537063e5a..e4fb2024fd 100644 --- a/Release/include/cpprest/uri_builder.h +++ b/Release/include/cpprest/uri_builder.h @@ -238,7 +238,7 @@ namespace web uri_builder &append_query(const utility::string_t &name, const T &value, bool do_encoding = true) { auto encodedName = name; - auto encodedValue = ::utility::conversions::print_string(value); + auto encodedValue = ::utility::conversions::print_string(value, std::locale::classic()); if (do_encoding) { diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index 2e71fa516b..d161a5d924 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -73,7 +73,7 @@ utility::string_t uri_components::join() if (m_port > 0) { - ret.append({ _XPLATSTR(':') }).append(utility::conversions::print_string(m_port)); + ret.append({ _XPLATSTR(':') }).append(utility::conversions::print_string(m_port, std::locale::classic())); } } @@ -104,6 +104,15 @@ utility::string_t uri_components::join() using namespace details; +uri::uri(const details::uri_components &components) : m_components(components) +{ + m_uri = m_components.join(); + if (!details::uri_parser::validate(m_uri)) + { + throw uri_exception("provided uri is invalid: " + utility::conversions::to_utf8string(m_uri)); + } +} + uri::uri(const utility::string_t &uri_string) { if (!details::uri_parser::parse(uri_string, m_components)) From 02b8718225f2909d58c4a0b8749bb1f1925ed649 Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Wed, 18 May 2016 05:42:41 +0000 Subject: [PATCH 102/609] if ssl_context_callback is used, then the pool is not added to the map --- Release/src/http/client/http_client_asio.cpp | 49 ++++++++++++-------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index f9b1747c52..0b1d30dce6 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -338,31 +338,42 @@ class asio_client : public _http_client_communicator : _http_client_communicator(std::move(address), std::move(client_config)) , m_resolver(crossplat::threadpool::shared_instance().service()) { - std::string host = base_uri().to_string(); - - auto &credentials = _http_client_communicator::client_config().credentials(); - if (credentials.is_set()) + if (this->client_config().get_ssl_context_callback()) { - host.append(credentials.username()); + // The pool is not added to the map because there is no better approaches to compare callback functors. + m_pool = std::make_shared(crossplat::threadpool::shared_instance().service(), + base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), + std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. + this->client_config().get_ssl_context_callback()); } - - auto &proxy = _http_client_communicator::client_config().proxy(); - if (proxy.is_specified()) + else { - host.append(proxy.address().to_string()); - if (proxy.credentials().is_set()) + std::string host = base_uri().to_string(); + + auto &credentials = _http_client_communicator::client_config().credentials(); + if (credentials.is_set()) { - host.append(proxy.credentials().username()); + host.append(credentials.username()); } - } - m_pool = crossplat::threadpool::shared_instance().obtain_connection_pool(host, [this]() - { - return std::make_shared(crossplat::threadpool::shared_instance().service(), - base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), - std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. - this->client_config().get_ssl_context_callback()); - }); + auto &proxy = _http_client_communicator::client_config().proxy(); + if (proxy.is_specified()) + { + host.append(proxy.address().to_string()); + if (proxy.credentials().is_set()) + { + host.append(proxy.credentials().username()); + } + } + + m_pool = crossplat::threadpool::shared_instance().obtain_connection_pool(host, [this]() + { + return std::make_shared(crossplat::threadpool::shared_instance().service(), + base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), + std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. + this->client_config().get_ssl_context_callback()); + }); + } } void send_request(const std::shared_ptr &request_ctx) override; From b6f20378eecb834ad55e334b0c09624857c7c4e6 Mon Sep 17 00:00:00 2001 From: Stewart Bright Date: Wed, 18 May 2016 15:54:30 -0400 Subject: [PATCH 103/609] Header parsing assumes whitespace after colon RFC7230 (HTTP 1.1) 3.2 "Header fields" specifies that whitespace between colon and value is optional, but http_client_asio::read_headers started reading the value at one after the colon, assuming there would always be exactly one space. --- Release/src/http/client/http_client_asio.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 44296040e0..a5967127c1 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1123,7 +1123,6 @@ class asio_context : public request_context, public std::enable_shared_from_this if (colon != std::string::npos) { auto name = header.substr(0, colon); - auto value = header.substr(colon + 2, header.size() - (colon + 3)); // also exclude '\r' boost::algorithm::trim(name); boost::algorithm::trim(value); From 4f9a55088742568ba58da8ca1d83e5123f0af790 Mon Sep 17 00:00:00 2001 From: Stewart Bright Date: Wed, 18 May 2016 20:57:55 -0400 Subject: [PATCH 104/609] Header parsing assumes whitespace after colon Not sure how, but fix line was deleted rather than committed. --- Release/src/http/client/http_client_asio.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index a5967127c1..a884099032 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1123,6 +1123,7 @@ class asio_context : public request_context, public std::enable_shared_from_this if (colon != std::string::npos) { auto name = header.substr(0, colon); + auto value = header.substr(colon + 1, header.size() - colon - 2); boost::algorithm::trim(name); boost::algorithm::trim(value); From 944daa78f76d110d3a2bec5ab8b2a4cae26bf027 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Thu, 2 Jun 2016 18:45:59 -0700 Subject: [PATCH 105/609] Add nullcheck to eliminate warning with Code Analysis --- Release/src/utilities/asyncrt_utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index ab502ac5c5..fac7787d49 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -63,7 +63,7 @@ scoped_c_thread_locale::xplat_locale scoped_c_thread_locale::c_locale() scoped_c_thread_locale::xplat_locale *clocale = new scoped_c_thread_locale::xplat_locale(); #ifdef _WIN32 *clocale = _create_locale(LC_ALL, "C"); - if (*clocale == nullptr) + if (clocale == nullptr || *clocale == nullptr) { throw std::runtime_error("Unable to create 'C' locale."); } @@ -74,7 +74,7 @@ scoped_c_thread_locale::xplat_locale scoped_c_thread_locale::c_locale() }; #else *clocale = newlocale(LC_ALL, "C", nullptr); - if (*clocale == nullptr) + if (clocale == nullptr || *clocale == nullptr) { throw std::runtime_error("Unable to create 'C' locale."); } From 943c4d89d6eb96e27137fe6d1e1baa17853c7b4a Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Mon, 13 Jun 2016 09:11:45 +0000 Subject: [PATCH 106/609] add pool timer to clean connection pool --- .../cpprest/details/http_server_asio.h | 5 +- Release/include/cpprest/http_client.h | 1 - Release/include/pplx/threadpool.h | 18 +++- Release/src/http/client/http_client_asio.cpp | 98 +++++++++++++++---- Release/src/pplx/threadpool.cpp | 9 ++ 5 files changed, 105 insertions(+), 26 deletions(-) diff --git a/Release/include/cpprest/details/http_server_asio.h b/Release/include/cpprest/details/http_server_asio.h index 95c1745083..e34435d09c 100644 --- a/Release/include/cpprest/details/http_server_asio.h +++ b/Release/include/cpprest/details/http_server_asio.h @@ -87,7 +87,10 @@ class connection if (is_https) { m_ssl_context = utility::details::make_unique(boost::asio::ssl::context::sslv23); - ssl_context_callback(*m_ssl_context); + if (ssl_context_callback) + { + ssl_context_callback(*m_ssl_context); + } m_ssl_stream = utility::details::make_unique>(*m_socket, *m_ssl_context); m_ssl_stream->async_handshake(boost::asio::ssl::stream_base::server, [this](const boost::system::error_code&) { this->start_request_response(); }); diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 8f9e0f9f8a..e5d2f3677a 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -100,7 +100,6 @@ class http_client_config #endif , m_set_user_nativehandle_options([](native_handle)->void{}) #if !defined(_WIN32) && !defined(__cplusplus_winrt) - , m_ssl_context_callback([](boost::asio::ssl::context&)->void{}) , m_tlsext_sni_enabled(true) #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index f28c51ea31..5ec939ddf5 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -101,19 +101,31 @@ class threadpool return m_service; } - std::shared_ptr obtain_connection_pool(const std::string &base_uri, std::function()> connection_pool_generator) + template + std::shared_ptr obtain_connection_pool(const std::string &key, PoolGenerator pool_generator) { std::lock_guard lg(m_connection_pool_map_mutex); - auto &pool = m_connection_pool_map[base_uri]; + auto &pool = m_connection_pool_map[key]; if (!pool) { - pool = connection_pool_generator(); + pool = pool_generator(); } return pool; } + template + void release_connection_pool(const std::string &key, PoolReleaseHandler handler) + { + std::lock_guard lg(m_connection_pool_map_mutex); + + auto pool = m_connection_pool_map[key]; + handler(pool); + } + + void free_connection_pool(const boost::system::error_code &ec, const std::string &key); + private: struct _cancel_thread { }; diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 0b1d30dce6..613b18de46 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -80,7 +80,7 @@ class asio_connection asio_connection(boost::asio::io_service& io_service, bool start_with_ssl, const std::function& ssl_context_callback) : m_socket(io_service), m_ssl_context_callback(ssl_context_callback), - m_pool_timer(io_service), + m_connection_timer(io_service), m_is_reused(false), m_keep_alive(true) { @@ -103,7 +103,10 @@ class asio_connection boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23); ssl_context.set_default_verify_paths(); ssl_context.set_options(boost::asio::ssl::context::default_workarounds); - m_ssl_context_callback(ssl_context); + if (m_ssl_context_callback) + { + m_ssl_context_callback(ssl_context); + } m_ssl_stream = utility::details::make_unique>(m_socket, ssl_context); } @@ -127,9 +130,9 @@ class asio_connection return error; } - void cancel_pool_timer() + void cancel_connection_timer() { - m_pool_timer.cancel(); + m_connection_timer.cancel(); } bool is_reused() const { return m_is_reused; } @@ -218,15 +221,15 @@ class asio_connection private: template - void start_pool_timer(int timeout_secs, const TimeoutHandler &handler) + void start_connection_timer(int timeout_secs, const TimeoutHandler &handler) { - m_pool_timer.expires_from_now(boost::posix_time::milliseconds(timeout_secs * 1000)); - m_pool_timer.async_wait(handler); + m_connection_timer.expires_from_now(boost::posix_time::milliseconds(timeout_secs * 1000)); + m_connection_timer.async_wait(handler); } void start_reuse() { - cancel_pool_timer(); + cancel_connection_timer(); m_is_reused = true; } @@ -239,7 +242,7 @@ class asio_connection std::function m_ssl_context_callback; - boost::asio::deadline_timer m_pool_timer; + boost::asio::deadline_timer m_connection_timer; bool m_is_reused; bool m_keep_alive; }; @@ -252,7 +255,10 @@ class asio_connection_pool m_io_service(io_service), m_timeout_secs(static_cast(idle_timeout.count())), m_start_with_ssl(start_with_ssl), - m_ssl_context_callback(ssl_context_callback) + m_ssl_context_callback(ssl_context_callback), + m_pool_timeout_secs(60), // Clean this connection pool 60 secs after the last asio_client release it. + m_pool_timer(io_service), + m_use_count(0) {} ~asio_connection_pool() @@ -261,10 +267,24 @@ class asio_connection_pool // Cancel the pool timer for all connections. for (auto& connection : m_connections) { - connection->cancel_pool_timer(); + connection->cancel_connection_timer(); } } + template + void start_pool_timer(const TimeoutHandler &handler) + { + //std::lock_guard lg(m_pool_timer_mutex); + m_pool_timer.expires_from_now(boost::posix_time::milliseconds(m_pool_timeout_secs * 1000)); + m_pool_timer.async_wait(handler); + } + + void cancel_pool_timer() + { + //std::lock_guard lg(m_pool_timer_mutex); + m_pool_timer.cancel(); + } + void release(const std::shared_ptr &connection) { if (connection->keep_alive() && (m_timeout_secs > 0)) @@ -274,7 +294,7 @@ class asio_connection_pool std::lock_guard lock(m_connections_mutex); // This will destroy and remove the connection from pool after the set timeout. // We use 'this' because async calls to timer handler only occur while the pool exists. - connection->start_pool_timer(m_timeout_secs, boost::bind(&asio_connection_pool::handle_pool_timer, this, boost::asio::placeholders::error, connection)); + connection->start_connection_timer(m_timeout_secs, boost::bind(&asio_connection_pool::handle_connection_timer, this, boost::asio::placeholders::error, connection)); m_connections.push_back(connection); } // Otherwise connection is not put to the pool and it will go out of scope. @@ -302,10 +322,15 @@ class asio_connection_pool } } + int &use_count() + { + return m_use_count; + } + private: // Using weak_ptr here ensures bind() to this handler will not prevent the connection object from going out of scope. - void handle_pool_timer(const boost::system::error_code& ec, const std::weak_ptr &connection) + void handle_connection_timer(const boost::system::error_code& ec, const std::weak_ptr &connection) { if (!ec) { @@ -328,6 +353,12 @@ class asio_connection_pool std::function m_ssl_context_callback; std::vector > m_connections; std::mutex m_connections_mutex; + + const int m_pool_timeout_secs; + std::mutex m_pool_timer_mutex; + boost::asio::deadline_timer m_pool_timer; + //std::atomic m_use_count; + int m_use_count; }; @@ -348,32 +379,56 @@ class asio_client : public _http_client_communicator } else { - std::string host = base_uri().to_string(); + m_pool_key = base_uri().to_string(); auto &credentials = _http_client_communicator::client_config().credentials(); if (credentials.is_set()) { - host.append(credentials.username()); + m_pool_key.append(credentials.username()); } auto &proxy = _http_client_communicator::client_config().proxy(); if (proxy.is_specified()) { - host.append(proxy.address().to_string()); + m_pool_key.append(proxy.address().to_string()); if (proxy.credentials().is_set()) { - host.append(proxy.credentials().username()); + m_pool_key.append(proxy.credentials().username()); } } - m_pool = crossplat::threadpool::shared_instance().obtain_connection_pool(host, [this]() + m_pool = crossplat::threadpool::shared_instance().obtain_connection_pool(m_pool_key, [this]() { return std::make_shared(crossplat::threadpool::shared_instance().service(), base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. - this->client_config().get_ssl_context_callback()); + nullptr); + }); + + if (m_pool->use_count() == 0) + { + m_pool->cancel_pool_timer(); + } + ++m_pool->use_count(); + } + } + + ~asio_client() + { + if (!m_pool_key.empty()) + { + crossplat::threadpool::shared_instance().release_connection_pool(m_pool_key, [this](std::shared_ptr pool) + { + if (pool) + { + --pool->use_count(); + if (pool->use_count() == 0) + { + pool->start_pool_timer(boost::bind(&crossplat::threadpool::free_connection_pool, &crossplat::threadpool::shared_instance(), boost::asio::placeholders::error, m_pool_key)); + } + } }); - } + } } void send_request(const std::shared_ptr &request_ctx) override; @@ -384,6 +439,7 @@ class asio_client : public _http_client_communicator std::shared_ptr m_pool; tcp::resolver m_resolver; + std::string m_pool_key; }; class asio_context : public request_context, public std::enable_shared_from_this @@ -509,7 +565,7 @@ class asio_context : public request_context, public std::enable_shared_from_this { m_context->report_error("Failed to send connect request to proxy.", err, httpclient_errorcode_context::writebody); } - } + } void handle_status_line(const boost::system::error_code& ec) { diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index 729dae85d9..16c1bfbce9 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -67,6 +67,15 @@ threadpool& threadpool::shared_instance() return s_shared; } +void threadpool::free_connection_pool(const boost::system::error_code &ec, const std::string &key) +{ + if (!ec) + { + std::lock_guard lg(m_connection_pool_map_mutex); + m_connection_pool_map.erase(key); + } +} + #endif } From ca5cf696aac3a4da22c8498f34fdf51eec63b632 Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Mon, 13 Jun 2016 16:58:07 +0000 Subject: [PATCH 107/609] remove unnecessary lock --- Release/src/http/client/http_client_asio.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 82cdad30c3..e7d807e94b 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -274,14 +274,12 @@ class asio_connection_pool template void start_pool_timer(const TimeoutHandler &handler) { - //std::lock_guard lg(m_pool_timer_mutex); m_pool_timer.expires_from_now(boost::posix_time::milliseconds(m_pool_timeout_secs * 1000)); m_pool_timer.async_wait(handler); } void cancel_pool_timer() { - //std::lock_guard lg(m_pool_timer_mutex); m_pool_timer.cancel(); } @@ -355,9 +353,7 @@ class asio_connection_pool std::mutex m_connections_mutex; const int m_pool_timeout_secs; - std::mutex m_pool_timer_mutex; boost::asio::deadline_timer m_pool_timer; - //std::atomic m_use_count; int m_use_count; }; From 5caac19dadf36166b6020a1b9c2b3bc106c1d806 Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Tue, 14 Jun 2016 08:50:37 +0000 Subject: [PATCH 108/609] move connection_pool_map related functions from threadpool to http_client_asio --- Release/include/pplx/threadpool.h | 32 ------ Release/src/http/client/http_client_asio.cpp | 109 ++++++++++++------- Release/src/pplx/threadpool.cpp | 9 -- 3 files changed, 72 insertions(+), 78 deletions(-) diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index 5ec939ddf5..c778040737 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -42,10 +42,6 @@ #include "pplx/pplx.h" #endif -namespace web { namespace http { namespace client { namespace details { - class asio_connection_pool; -}}}} - namespace crossplat { #if (defined(ANDROID) || defined(__ANDROID__)) @@ -101,31 +97,6 @@ class threadpool return m_service; } - template - std::shared_ptr obtain_connection_pool(const std::string &key, PoolGenerator pool_generator) - { - std::lock_guard lg(m_connection_pool_map_mutex); - - auto &pool = m_connection_pool_map[key]; - if (!pool) - { - pool = pool_generator(); - } - - return pool; - } - - template - void release_connection_pool(const std::string &key, PoolReleaseHandler handler) - { - std::lock_guard lg(m_connection_pool_map_mutex); - - auto pool = m_connection_pool_map[key]; - handler(pool); - } - - void free_connection_pool(const boost::system::error_code &ec, const std::string &key); - private: struct _cancel_thread { }; @@ -185,9 +156,6 @@ class threadpool std::vector m_threads; boost::asio::io_service m_service; boost::asio::io_service::work m_work; - - std::mutex m_connection_pool_map_mutex; - std::map> m_connection_pool_map; }; } diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index e7d807e94b..e8b9ea396a 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -72,6 +72,28 @@ enum class httpclient_errorcode_context }; class asio_connection_pool; + +class asio_connection_pool_map +{ +public: + static asio_connection_pool_map &instance(); + + std::shared_ptr obtain_connection_pool(const std::string &pool_key, bool start_with_ssl, std::chrono::seconds idle_timeout); + + void release_connection_pool(const std::string &pool_key); + + void free_connection_pool(const boost::system::error_code &ec, const std::string &pool_key); + +private: + asio_connection_pool_map() + : m_threadpool(crossplat::threadpool::shared_instance()) + {} + + crossplat::threadpool &m_threadpool; + std::mutex m_connection_pool_map_mutex; + std::map> m_connection_pool_map; +}; + class asio_connection { friend class asio_connection_pool; @@ -257,8 +279,7 @@ class asio_connection_pool m_start_with_ssl(start_with_ssl), m_ssl_context_callback(ssl_context_callback), m_pool_timeout_secs(60), // Clean this connection pool 60 secs after the last asio_client release it. - m_pool_timer(io_service), - m_use_count(0) + m_pool_timer(io_service) {} ~asio_connection_pool() @@ -320,11 +341,6 @@ class asio_connection_pool } } - int &use_count() - { - return m_use_count; - } - private: // Using weak_ptr here ensures bind() to this handler will not prevent the connection object from going out of scope. @@ -354,9 +370,49 @@ class asio_connection_pool const int m_pool_timeout_secs; boost::asio::deadline_timer m_pool_timer; - int m_use_count; }; +asio_connection_pool_map &asio_connection_pool_map::instance() +{ + static asio_connection_pool_map s_instance; + return s_instance; +} + +std::shared_ptr asio_connection_pool_map::obtain_connection_pool(const std::string &pool_key, bool start_with_ssl, std::chrono::seconds idle_timeout) +{ + std::lock_guard lg(m_connection_pool_map_mutex); + auto &pool = m_connection_pool_map[pool_key]; + if (!pool) + { + pool = std::make_shared(crossplat::threadpool::shared_instance().service(), start_with_ssl, idle_timeout, nullptr); + } + + pool->cancel_pool_timer(); + return pool; +} + +void asio_connection_pool_map::release_connection_pool(const std::string &pool_key) +{ + std::lock_guard lg(m_connection_pool_map_mutex); + auto &pool = m_connection_pool_map[pool_key]; + if (pool) + { + pool->start_pool_timer(boost::bind(&asio_connection_pool_map::free_connection_pool, this, boost::asio::placeholders::error, pool_key)); + } +} + +void asio_connection_pool_map::free_connection_pool(const boost::system::error_code &ec, const std::string &pool_key) +{ + if (!ec) + { + std::lock_guard lg(m_connection_pool_map_mutex); + auto &pool = m_connection_pool_map[pool_key]; + if (pool && pool.use_count() == 1) + { + m_connection_pool_map.erase(pool_key); + } + } +} class asio_client : public _http_client_communicator { @@ -365,13 +421,14 @@ class asio_client : public _http_client_communicator : _http_client_communicator(std::move(address), std::move(client_config)) , m_resolver(crossplat::threadpool::shared_instance().service()) { - if (this->client_config().get_ssl_context_callback()) + bool start_with_ssl = base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(); + const std::chrono::seconds idle_timeout(30); // Unused sockets are kept in pool for 30 seconds. + auto ssl_context_callback = this->client_config().get_ssl_context_callback(); + + if (ssl_context_callback) { // The pool is not added to the map because there is no better approaches to compare callback functors. - m_pool = std::make_shared(crossplat::threadpool::shared_instance().service(), - base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), - std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. - this->client_config().get_ssl_context_callback()); + m_pool = std::make_shared(crossplat::threadpool::shared_instance().service(), start_with_ssl, idle_timeout, ssl_context_callback); } else { @@ -393,19 +450,7 @@ class asio_client : public _http_client_communicator } } - m_pool = crossplat::threadpool::shared_instance().obtain_connection_pool(m_pool_key, [this]() - { - return std::make_shared(crossplat::threadpool::shared_instance().service(), - base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(), - std::chrono::seconds(30), // Unused sockets are kept in pool for 30 seconds. - nullptr); - }); - - if (m_pool->use_count() == 0) - { - m_pool->cancel_pool_timer(); - } - ++m_pool->use_count(); + m_pool = asio_connection_pool_map::instance().obtain_connection_pool(m_pool_key, start_with_ssl, idle_timeout); } } @@ -413,17 +458,7 @@ class asio_client : public _http_client_communicator { if (!m_pool_key.empty()) { - crossplat::threadpool::shared_instance().release_connection_pool(m_pool_key, [this](std::shared_ptr pool) - { - if (pool) - { - --pool->use_count(); - if (pool->use_count() == 0) - { - pool->start_pool_timer(boost::bind(&crossplat::threadpool::free_connection_pool, &crossplat::threadpool::shared_instance(), boost::asio::placeholders::error, m_pool_key)); - } - } - }); + asio_connection_pool_map::instance().release_connection_pool(m_pool_key); } } diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index 16c1bfbce9..729dae85d9 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -67,15 +67,6 @@ threadpool& threadpool::shared_instance() return s_shared; } -void threadpool::free_connection_pool(const boost::system::error_code &ec, const std::string &key) -{ - if (!ec) - { - std::lock_guard lg(m_connection_pool_map_mutex); - m_connection_pool_map.erase(key); - } -} - #endif } From e29426d258cb88bc81f35a206587d459fde24fd8 Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Fri, 17 Jun 2016 08:19:37 +0000 Subject: [PATCH 109/609] use iterator in free_connection_pool --- Release/src/http/client/http_client_asio.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index e8b9ea396a..fbd4de1eed 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -406,10 +406,10 @@ void asio_connection_pool_map::free_connection_pool(const boost::system::error_c if (!ec) { std::lock_guard lg(m_connection_pool_map_mutex); - auto &pool = m_connection_pool_map[pool_key]; - if (pool && pool.use_count() == 1) + auto it = m_connection_pool_map.find(pool_key); + if (it != m_connection_pool_map.end() && it->second.use_count() == 1) { - m_connection_pool_map.erase(pool_key); + m_connection_pool_map.erase(it); } } } From e9667dbf2a031fbbdbce64aa4e8abb72c2120d7c Mon Sep 17 00:00:00 2001 From: Han Zhu Date: Fri, 24 Jun 2016 05:46:04 +0000 Subject: [PATCH 110/609] remove pool_map, use multimap in global connection_pool --- Release/src/http/client/http_client_asio.cpp | 302 +++++++++---------- 1 file changed, 151 insertions(+), 151 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index fbd4de1eed..4de483afeb 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -72,28 +72,6 @@ enum class httpclient_errorcode_context }; class asio_connection_pool; - -class asio_connection_pool_map -{ -public: - static asio_connection_pool_map &instance(); - - std::shared_ptr obtain_connection_pool(const std::string &pool_key, bool start_with_ssl, std::chrono::seconds idle_timeout); - - void release_connection_pool(const std::string &pool_key); - - void free_connection_pool(const boost::system::error_code &ec, const std::string &pool_key); - -private: - asio_connection_pool_map() - : m_threadpool(crossplat::threadpool::shared_instance()) - {} - - crossplat::threadpool &m_threadpool; - std::mutex m_connection_pool_map_mutex; - std::map> m_connection_pool_map; -}; - class asio_connection { friend class asio_connection_pool; @@ -102,7 +80,7 @@ class asio_connection asio_connection(boost::asio::io_service& io_service, bool start_with_ssl, const std::function& ssl_context_callback) : m_socket(io_service), m_ssl_context_callback(ssl_context_callback), - m_connection_timer(io_service), + m_pool_timer(io_service), m_is_reused(false), m_keep_alive(true) { @@ -112,6 +90,12 @@ class asio_connection } } + asio_connection(boost::asio::io_service& io_service, const std::string &pool_key, bool start_with_ssl, const std::function& ssl_context_callback) : + asio_connection(io_service, start_with_ssl, ssl_context_callback) + { + m_pool_key = pool_key; + } + ~asio_connection() { close(); @@ -152,15 +136,18 @@ class asio_connection return error; } - void cancel_connection_timer() + void cancel_pool_timer() { - m_connection_timer.cancel(); + m_pool_timer.cancel(); } bool is_reused() const { return m_is_reused; } void set_keep_alive(bool keep_alive) { m_keep_alive = keep_alive; } bool keep_alive() const { return m_keep_alive; } bool is_ssl() const { return m_ssl_stream ? true : false; } + const std::string &pool_key() const { return m_pool_key; } + const std::string &nonce() const { return m_nonce; } + void generate_nonce() { m_nonce = m_nonce_generator.generate(); } template void async_connect(const Iterator &begin, const Handler &handler) @@ -243,16 +230,17 @@ class asio_connection private: template - void start_connection_timer(int timeout_secs, const TimeoutHandler &handler) + void start_pool_timer(int timeout_secs, const TimeoutHandler &handler) { - m_connection_timer.expires_from_now(boost::posix_time::milliseconds(timeout_secs * 1000)); - m_connection_timer.async_wait(handler); + m_pool_timer.expires_from_now(boost::posix_time::milliseconds(timeout_secs * 1000)); + m_pool_timer.async_wait(handler); } void start_reuse() { - cancel_connection_timer(); + cancel_pool_timer(); m_is_reused = true; + generate_nonce(); } // Guards concurrent access to socket/ssl::stream. This is necessary @@ -264,22 +252,22 @@ class asio_connection std::function m_ssl_context_callback; - boost::asio::deadline_timer m_connection_timer; + boost::asio::deadline_timer m_pool_timer; bool m_is_reused; bool m_keep_alive; + std::string m_pool_key; + std::string m_nonce; + utility::nonce_generator m_nonce_generator; }; class asio_connection_pool { public: - asio_connection_pool(boost::asio::io_service& io_service, bool start_with_ssl, const std::chrono::seconds &idle_timeout, const std::function &ssl_context_callback) : + asio_connection_pool(boost::asio::io_service& io_service, const std::chrono::seconds &idle_timeout, bool is_shared) : m_io_service(io_service), m_timeout_secs(static_cast(idle_timeout.count())), - m_start_with_ssl(start_with_ssl), - m_ssl_context_callback(ssl_context_callback), - m_pool_timeout_secs(60), // Clean this connection pool 60 secs after the last asio_client release it. - m_pool_timer(io_service) + m_is_shared(is_shared) {} ~asio_connection_pool() @@ -288,130 +276,135 @@ class asio_connection_pool // Cancel the pool timer for all connections. for (auto& connection : m_connections) { - connection->cancel_connection_timer(); + connection->cancel_pool_timer(); } } - template - void start_pool_timer(const TimeoutHandler &handler) - { - m_pool_timer.expires_from_now(boost::posix_time::milliseconds(m_pool_timeout_secs * 1000)); - m_pool_timer.async_wait(handler); - } - - void cancel_pool_timer() - { - m_pool_timer.cancel(); - } - void release(const std::shared_ptr &connection) { if (connection->keep_alive() && (m_timeout_secs > 0)) { connection->cancel(); - std::lock_guard lock(m_connections_mutex); - // This will destroy and remove the connection from pool after the set timeout. - // We use 'this' because async calls to timer handler only occur while the pool exists. - connection->start_connection_timer(m_timeout_secs, boost::bind(&asio_connection_pool::handle_connection_timer, this, boost::asio::placeholders::error, connection)); - m_connections.push_back(connection); + if (m_is_shared) + { + std::lock_guard lock(m_connections_mutex); + auto it = m_shared_connections.insert(std::make_pair(connection->pool_key(), connection)); + // This will destroy and remove the connection from pool after the set timeout. + // We use 'this' because async calls to timer handler only occur while the pool exists. + connection->start_pool_timer(m_timeout_secs, boost::bind(&asio_connection_pool::free_shared_connection, this, boost::asio::placeholders::error, it, std::weak_ptr(connection), connection->nonce())); + } + else + { + std::lock_guard lock(m_connections_mutex); + auto pair = m_connections.insert(connection); + if (pair.second) + { + // This will destroy and remove the connection from pool after the set timeout. + // We use 'this' because async calls to timer handler only occur while the pool exists. + connection->start_pool_timer(m_timeout_secs, boost::bind(&asio_connection_pool::free_connection, this, boost::asio::placeholders::error, pair.first, std::weak_ptr(connection), connection->nonce())); + } + } } // Otherwise connection is not put to the pool and it will go out of scope. } - std::shared_ptr obtain() + std::shared_ptr obtain(const std::string &pool_key, bool start_with_ssl, const std::function& ssl_context_callback) { - std::unique_lock lock(m_connections_mutex); - if (m_connections.empty()) + if (m_is_shared) { - lock.unlock(); + std::unique_lock lock(m_connections_mutex); + auto it = m_shared_connections.find(pool_key); + if (it == m_shared_connections.end()) + { + lock.unlock(); + + // No connections in pool => create a new connection instance. + return std::make_shared(m_io_service, pool_key, start_with_ssl, ssl_context_callback); + } + else + { + // Reuse connection from pool. + auto connection = it->second; + m_shared_connections.erase(it); + connection->start_reuse(); + lock.unlock(); - // No connections in pool => create a new connection instance. - return std::make_shared(m_io_service, m_start_with_ssl, m_ssl_context_callback); + return connection; + } } else { - // Reuse connection from pool. - auto connection = m_connections.back(); - m_connections.pop_back(); - lock.unlock(); + std::unique_lock lock(m_connections_mutex); + if (m_connections.empty()) + { + lock.unlock(); - connection->start_reuse(); - return connection; + // No connections in pool => create a new connection instance. + return std::make_shared(m_io_service, start_with_ssl, ssl_context_callback); + } + else + { + // Reuse connection from pool. + auto it = m_connections.begin(); + auto connection = *it; + m_connections.erase(it); + connection->start_reuse(); + lock.unlock(); + + return connection; + } } } + static std::shared_ptr shared_instance(); + private: // Using weak_ptr here ensures bind() to this handler will not prevent the connection object from going out of scope. - void handle_connection_timer(const boost::system::error_code& ec, const std::weak_ptr &connection) + void free_shared_connection(const boost::system::error_code& ec, std::multimap>::iterator it, const std::weak_ptr &connection, const std::string &nonce) { if (!ec) { auto connection_shared = connection.lock(); - if (connection_shared) + // Compare nonce here to ensure the iterator is valid, the connection not been reused. + if (connection_shared && (connection_shared->nonce() == nonce)) { std::lock_guard lock(m_connections_mutex); - const auto &iter = std::find(m_connections.begin(), m_connections.end(), connection_shared); - if (iter != m_connections.end()) - { - m_connections.erase(iter); - } + m_shared_connections.erase(it); + } + } + } + + // Using weak_ptr here ensures bind() to this handler will not prevent the connection object from going out of scope. + void free_connection(const boost::system::error_code& ec, std::set>::iterator it, const std::weak_ptr &connection, const std::string &nonce) + { + if (!ec) + { + auto connection_shared = connection.lock(); + // Compare nonce here to ensure the iterator is valid, the connection not been reused. + if (connection_shared && (connection_shared->nonce() == nonce)) + { + std::lock_guard lock(m_connections_mutex); + m_connections.erase(it); } } } boost::asio::io_service& m_io_service; const int m_timeout_secs; - const bool m_start_with_ssl; - std::function m_ssl_context_callback; - std::vector > m_connections; + bool m_is_shared; + std::multimap> m_shared_connections; + std::set> m_connections; std::mutex m_connections_mutex; - - const int m_pool_timeout_secs; - boost::asio::deadline_timer m_pool_timer; }; -asio_connection_pool_map &asio_connection_pool_map::instance() -{ - static asio_connection_pool_map s_instance; - return s_instance; -} - -std::shared_ptr asio_connection_pool_map::obtain_connection_pool(const std::string &pool_key, bool start_with_ssl, std::chrono::seconds idle_timeout) -{ - std::lock_guard lg(m_connection_pool_map_mutex); - auto &pool = m_connection_pool_map[pool_key]; - if (!pool) - { - pool = std::make_shared(crossplat::threadpool::shared_instance().service(), start_with_ssl, idle_timeout, nullptr); - } - - pool->cancel_pool_timer(); - return pool; -} - -void asio_connection_pool_map::release_connection_pool(const std::string &pool_key) +std::shared_ptr asio_connection_pool::shared_instance() { - std::lock_guard lg(m_connection_pool_map_mutex); - auto &pool = m_connection_pool_map[pool_key]; - if (pool) - { - pool->start_pool_timer(boost::bind(&asio_connection_pool_map::free_connection_pool, this, boost::asio::placeholders::error, pool_key)); - } -} + const std::chrono::seconds idle_timeout(30); // Unused sockets are kept in pool for 30 seconds. + static std::shared_ptr s_instance = std::make_shared(crossplat::threadpool::shared_instance().service(), idle_timeout, true); -void asio_connection_pool_map::free_connection_pool(const boost::system::error_code &ec, const std::string &pool_key) -{ - if (!ec) - { - std::lock_guard lg(m_connection_pool_map_mutex); - auto it = m_connection_pool_map.find(pool_key); - if (it != m_connection_pool_map.end() && it->second.use_count() == 1) - { - m_connection_pool_map.erase(it); - } - } + return s_instance; } class asio_client : public _http_client_communicator @@ -421,44 +414,19 @@ class asio_client : public _http_client_communicator : _http_client_communicator(std::move(address), std::move(client_config)) , m_resolver(crossplat::threadpool::shared_instance().service()) { - bool start_with_ssl = base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(); + m_start_with_ssl = base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(); + m_ssl_context_callback = this->client_config().get_ssl_context_callback(); const std::chrono::seconds idle_timeout(30); // Unused sockets are kept in pool for 30 seconds. - auto ssl_context_callback = this->client_config().get_ssl_context_callback(); - if (ssl_context_callback) + if (m_ssl_context_callback) { - // The pool is not added to the map because there is no better approaches to compare callback functors. - m_pool = std::make_shared(crossplat::threadpool::shared_instance().service(), start_with_ssl, idle_timeout, ssl_context_callback); + // We will use a private connection pool because there is no better approaches to compare callback functors. + m_pool = std::make_shared(crossplat::threadpool::shared_instance().service(), idle_timeout, false); } else { - m_pool_key = base_uri().to_string(); - - auto &credentials = _http_client_communicator::client_config().credentials(); - if (credentials.is_set()) - { - m_pool_key.append(credentials.username()); - } - - auto &proxy = _http_client_communicator::client_config().proxy(); - if (proxy.is_specified()) - { - m_pool_key.append(proxy.address().to_string()); - if (proxy.credentials().is_set()) - { - m_pool_key.append(proxy.credentials().username()); - } - } - - m_pool = asio_connection_pool_map::instance().obtain_connection_pool(m_pool_key, start_with_ssl, idle_timeout); - } - } - - ~asio_client() - { - if (!m_pool_key.empty()) - { - asio_connection_pool_map::instance().release_connection_pool(m_pool_key); + init_pool_key(); + m_pool = asio_connection_pool::shared_instance(); } } @@ -468,11 +436,43 @@ class asio_client : public _http_client_communicator virtual pplx::task propagate(http_request request) override; + void init_pool_key(); + + std::shared_ptr obtain_connection(); + std::shared_ptr m_pool; tcp::resolver m_resolver; + bool m_start_with_ssl; + std::function m_ssl_context_callback; std::string m_pool_key; }; +void asio_client::init_pool_key() +{ + m_pool_key = base_uri().to_string(); + + auto &credentials = _http_client_communicator::client_config().credentials(); + if (credentials.is_set()) + { + m_pool_key.append(credentials.username()); + } + + auto &proxy = _http_client_communicator::client_config().proxy(); + if (proxy.is_specified()) + { + m_pool_key.append(proxy.address().to_string()); + if (proxy.credentials().is_set()) + { + m_pool_key.append(proxy.credentials().username()); + } + } +} + +std::shared_ptr asio_client::obtain_connection() +{ + return m_pool->obtain(m_pool_key, m_start_with_ssl, m_ssl_context_callback); +} + class asio_context : public request_context, public std::enable_shared_from_this { friend class asio_client; @@ -500,7 +500,7 @@ class asio_context : public request_context, public std::enable_shared_from_this static std::shared_ptr create_request_context(std::shared_ptr<_http_client_communicator> &client, http_request &request) { auto client_cast(std::static_pointer_cast(client)); - auto connection(client_cast->m_pool->obtain()); + auto connection(client_cast->obtain_connection()); auto ctx = std::make_shared(client, request, connection); ctx->m_timer.set_ctx(std::weak_ptr(ctx)); return ctx; @@ -577,7 +577,7 @@ class asio_context : public request_context, public std::enable_shared_from_this m_context->m_timer.reset(); //// Replace the connection. This causes old connection object to go out of scope. auto client = std::static_pointer_cast(m_context->m_http_client); - m_context->m_connection = client->m_pool->obtain(); + m_context->m_connection = client->obtain_connection(); auto endpoint = *endpoints; m_context->m_connection->async_connect(endpoint, boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); @@ -930,7 +930,7 @@ class asio_context : public request_context, public std::enable_shared_from_this { // Replace the connection. This causes old connection object to go out of scope. auto client = std::static_pointer_cast(m_http_client); - m_connection = client->m_pool->obtain(); + m_connection = client->obtain_connection(); auto endpoint = *endpoints; m_connection->async_connect(endpoint, boost::bind(&asio_context::handle_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); From a3b71652090278db7db0c40ee616a7191d22efe3 Mon Sep 17 00:00:00 2001 From: Ritesh Khadgaray Date: Sun, 26 Jun 2016 11:24:57 +0530 Subject: [PATCH 111/609] add support for basic authentication --- Release/src/http/client/http_client_asio.cpp | 24 +++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 0e294851b6..85a26000c0 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -633,7 +633,12 @@ class asio_context : public request_context, public std::enable_shared_from_this { extra_headers.append(ctx->generate_basic_proxy_auth_header()); } - + + if (ctx->m_http_client->client_config().credentials().is_set()) + { + extra_headers.append(ctx->generate_basic_auth_header()); + } + // Check user specified transfer-encoding. std::string transferencoding; if (ctx->m_request.headers().match(header_names::transfer_encoding, transferencoding) && transferencoding == "chunked") @@ -732,6 +737,23 @@ class asio_context : public request_context, public std::enable_shared_from_this } private: + utility::string_t generate_basic_auth_header() + { + utility::string_t header; + + header.append(header_names::authorization); + header.append(": Basic "); + + auto credential_str = web::details::plaintext_string(new ::utility::string_t(m_http_client->client_config().credentials().username())); + credential_str->append(":"); + credential_str->append(*m_http_client->client_config().credentials().decrypt()); + + std::vector credentials_buffer(credential_str->begin(), credential_str->end()); + + header.append(utility::conversions::to_base64(credentials_buffer)); + header.append(CRLF); + return header; + } utility::string_t generate_basic_proxy_auth_header() { From 526e99714f7cf0b3a1b0550ba4c3e1fed69438ca Mon Sep 17 00:00:00 2001 From: Ritesh Khadgaray Date: Sun, 26 Jun 2016 13:58:09 +0530 Subject: [PATCH 112/609] asio basic auth support: test case --- .../http/client/authentication_tests.cpp | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Release/tests/functional/http/client/authentication_tests.cpp b/Release/tests/functional/http/client/authentication_tests.cpp index f339c64477..d5cdd4605a 100644 --- a/Release/tests/functional/http/client/authentication_tests.cpp +++ b/Release/tests/functional/http/client/authentication_tests.cpp @@ -620,6 +620,37 @@ TEST_FIXTURE(uri_address, failed_authentication_attempt, "Ignore:Linux", "89", " #if !defined(_WIN32) +// http_server does not support auth +void auth_test_impl(bool fail) +{ + std::string user("user1"), password("user1"); + auto return_code = status_codes::NotFound; // return 404 if successful auth + + if (fail) + { + password = "invalid"; + return_code = status_codes::Unauthorized; + } + + http_client_config client_config; + web::credentials cred(U(user), U(password)); + client_config.set_credentials(cred); + http_client client(U("http://test.webdav.org/auth-basic/"), client_config); + + http_response response = client.request(methods::GET).get(); + VERIFY_ARE_EQUAL(return_code, response.status_code()); +} + +TEST(auth_no_data) +{ + auth_test_impl(false); +} + +TEST(unsuccessful_auth_with_basic_cred) +{ + auth_test_impl(true); +} + TEST_FIXTURE(uri_address, set_user_options_asio_http) { test_http_server::scoped_server scoped(m_uri); From 89c20ddaf2c4b72fd105f127304d68b950ebea93 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 28 Jun 2016 18:23:23 -0700 Subject: [PATCH 113/609] WIP --- Release/src/http/client/http_client_asio.cpp | 151 ++++++++++++------- 1 file changed, 98 insertions(+), 53 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 4de483afeb..b7231831cc 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -77,12 +77,18 @@ class asio_connection friend class asio_connection_pool; friend class asio_client; public: - asio_connection(boost::asio::io_service& io_service, bool start_with_ssl, const std::function& ssl_context_callback) : - m_socket(io_service), - m_ssl_context_callback(ssl_context_callback), - m_pool_timer(io_service), - m_is_reused(false), - m_keep_alive(true) + asio_connection( + boost::asio::io_service& io_service, + const std::string &pool_key, + bool start_with_ssl, + const std::function& ssl_context_callback) + : m_socket(io_service), + m_ssl_context_callback(ssl_context_callback), + m_pool_timer(io_service), + m_is_reused(false), + m_keep_alive(true), + m_pool_key(pool_key), + m_epoch(0) { if (start_with_ssl) { @@ -90,12 +96,6 @@ class asio_connection } } - asio_connection(boost::asio::io_service& io_service, const std::string &pool_key, bool start_with_ssl, const std::function& ssl_context_callback) : - asio_connection(io_service, start_with_ssl, ssl_context_callback) - { - m_pool_key = pool_key; - } - ~asio_connection() { close(); @@ -146,8 +146,7 @@ class asio_connection bool keep_alive() const { return m_keep_alive; } bool is_ssl() const { return m_ssl_stream ? true : false; } const std::string &pool_key() const { return m_pool_key; } - const std::string &nonce() const { return m_nonce; } - void generate_nonce() { m_nonce = m_nonce_generator.generate(); } + uint32_t epoch() const { return m_epoch; } template void async_connect(const Iterator &begin, const Handler &handler) @@ -240,7 +239,7 @@ class asio_connection { cancel_pool_timer(); m_is_reused = true; - generate_nonce(); + m_epoch++; } // Guards concurrent access to socket/ssl::stream. This is necessary @@ -256,18 +255,71 @@ class asio_connection bool m_is_reused; bool m_keep_alive; std::string m_pool_key; - std::string m_nonce; - utility::nonce_generator m_nonce_generator; + uint32_t m_epoch; +}; + +class asio_shared_connection_pool +{ +public: + asio_shared_connection_pool(boost::asio::io_service& io_service) : + m_io_service(io_service) + {} + + ~asio_shared_connection_pool() + { + std::lock_guard lock(m_connections_mutex); + // Cancel the pool timer for all connections. + for (auto& connection : m_connections) + { + connection.second->cancel_pool_timer(); + } + } + + void release(const std::shared_ptr& connection) + { + if (connection->keep_alive() && (m_timeout_secs > 0)) + { + connection->cancel(); + + std::lock_guard lock(m_connections_mutex); + auto it = m_connections.insert(std::make_pair(connection->pool_key(), connection)); + + // This will destroy and remove the connection from pool after the set timeout. + // We use 'this' because async calls to timer handler only occur while the pool exists. + auto connection_weak = std::weak_ptr(connection); + auto epoch = connection->epoch(); + connection->start_pool_timer(m_timeout_secs, [this, connection_weak, epoch](const boost::error_code& ec) { + this->free_shared_connection(ec, connection_weak, epoch); + }); + } + } + +private: + void free_connection(const boost::system::error_code& ec, const std::weak_ptr &connection, unsigned int epoch) + { + auto connection_shared = connection.lock(); + if (!connection_shared) + return; + + std::lock_guard lock(m_connections_mutex); + auto it = m_connections.find(connection_shared); + if (it == m_connections.end()) + // The connection was acquired while this callback was firing + return; + + // The epoch is used to ensure the connection was not quickly acquired and released while this callback was firing. + // Every acquisition increments the epoch. + if (epoch != (*it)->epoch()) + m_connections.erase(it); + } }; class asio_connection_pool { public: - asio_connection_pool(boost::asio::io_service& io_service, const std::chrono::seconds &idle_timeout, bool is_shared) : - m_io_service(io_service), - m_timeout_secs(static_cast(idle_timeout.count())), - m_is_shared(is_shared) + asio_connection_pool(boost::asio::io_service& io_service) : + m_io_service(io_service) {} ~asio_connection_pool() @@ -282,29 +334,15 @@ class asio_connection_pool void release(const std::shared_ptr &connection) { - if (connection->keep_alive() && (m_timeout_secs > 0)) - { - connection->cancel(); + connection->cancel(); - if (m_is_shared) - { - std::lock_guard lock(m_connections_mutex); - auto it = m_shared_connections.insert(std::make_pair(connection->pool_key(), connection)); - // This will destroy and remove the connection from pool after the set timeout. - // We use 'this' because async calls to timer handler only occur while the pool exists. - connection->start_pool_timer(m_timeout_secs, boost::bind(&asio_connection_pool::free_shared_connection, this, boost::asio::placeholders::error, it, std::weak_ptr(connection), connection->nonce())); - } - else - { - std::lock_guard lock(m_connections_mutex); - auto pair = m_connections.insert(connection); - if (pair.second) - { - // This will destroy and remove the connection from pool after the set timeout. - // We use 'this' because async calls to timer handler only occur while the pool exists. - connection->start_pool_timer(m_timeout_secs, boost::bind(&asio_connection_pool::free_connection, this, boost::asio::placeholders::error, pair.first, std::weak_ptr(connection), connection->nonce())); - } - } + if (connection->keep_alive()) + { + std::lock_guard lock(m_connections_mutex); + // This will destroy and remove the connection from pool after the set timeout. + // We use 'this' because async calls to timer handler only occur while the pool exists. + connection->start_pool_timer(s_timeout_secs.count(), boost::bind(&asio_connection_pool::free_connection, this, boost::asio::placeholders::error, pair.first, std::weak_ptr(connection), connection->nonce())); + m_connections.push_back(connection); } // Otherwise connection is not put to the pool and it will go out of scope. } @@ -377,26 +415,33 @@ class asio_connection_pool } // Using weak_ptr here ensures bind() to this handler will not prevent the connection object from going out of scope. - void free_connection(const boost::system::error_code& ec, std::set>::iterator it, const std::weak_ptr &connection, const std::string &nonce) + void free_connection(const boost::system::error_code& ec, const std::weak_ptr &connection, uint32_t epoch) { if (!ec) { auto connection_shared = connection.lock(); - // Compare nonce here to ensure the iterator is valid, the connection not been reused. - if (connection_shared && (connection_shared->nonce() == nonce)) - { - std::lock_guard lock(m_connections_mutex); + if (!connection_shared) + return; + + std::lock_guard lock(m_connections_mutex); + auto it = m_connections.find(connection_shared); + if (it == m_connections.end()) + // The connection was acquired while this callback was firing + return; + + // The epoch is used to ensure the connection was not quickly acquired and released while this callback was firing. + // Every acquisition increments the epoch. + if (epoch != (*it)->epoch()) m_connections.erase(it); - } } } boost::asio::io_service& m_io_service; - const int m_timeout_secs; - bool m_is_shared; - std::multimap> m_shared_connections; - std::set> m_connections; + std::mutex m_connections_mutex; + std::set> m_connections; + + static const std::chrono::seconds s_timeout_secs = 30; }; std::shared_ptr asio_connection_pool::shared_instance() From 0b7fd428748848331adf01f363aa3458cb761ac7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 30 Jun 2016 02:54:10 -0700 Subject: [PATCH 114/609] Merged connection deadline_timers, reverted solution back to pool of pools approach --- Release/src/http/client/http_client_asio.cpp | 408 ++++++++----------- 1 file changed, 169 insertions(+), 239 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index b7231831cc..49376dc882 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -71,30 +71,15 @@ enum class httpclient_errorcode_context close }; -class asio_connection_pool; -class asio_connection +class asio_connection : public std::enable_shared_from_this { - friend class asio_connection_pool; friend class asio_client; public: - asio_connection( - boost::asio::io_service& io_service, - const std::string &pool_key, - bool start_with_ssl, - const std::function& ssl_context_callback) - : m_socket(io_service), - m_ssl_context_callback(ssl_context_callback), - m_pool_timer(io_service), + asio_connection(boost::asio::io_service& io_service) + : m_socket(io_service), m_is_reused(false), - m_keep_alive(true), - m_pool_key(pool_key), - m_epoch(0) - { - if (start_with_ssl) - { - upgrade_to_ssl(); - } - } + m_keep_alive(true) + {} ~asio_connection() { @@ -102,16 +87,16 @@ class asio_connection } // This simply instantiates the internal state to support ssl. It does not perform the handshake. - void upgrade_to_ssl() + void upgrade_to_ssl(const std::function& ssl_context_callback) { std::lock_guard lock(m_socket_lock); assert(!is_ssl()); boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23); ssl_context.set_default_verify_paths(); ssl_context.set_options(boost::asio::ssl::context::default_workarounds); - if (m_ssl_context_callback) + if (ssl_context_callback) { - m_ssl_context_callback(ssl_context); + ssl_context_callback(ssl_context); } m_ssl_stream = utility::details::make_unique>(m_socket, ssl_context); } @@ -136,17 +121,10 @@ class asio_connection return error; } - void cancel_pool_timer() - { - m_pool_timer.cancel(); - } - bool is_reused() const { return m_is_reused; } void set_keep_alive(bool keep_alive) { m_keep_alive = keep_alive; } bool keep_alive() const { return m_keep_alive; } bool is_ssl() const { return m_ssl_stream ? true : false; } - const std::string &pool_key() const { return m_pool_key; } - uint32_t epoch() const { return m_epoch; } template void async_connect(const Iterator &begin, const Handler &handler) @@ -227,21 +205,12 @@ class asio_connection } } -private: - template - void start_pool_timer(int timeout_secs, const TimeoutHandler &handler) - { - m_pool_timer.expires_from_now(boost::posix_time::milliseconds(timeout_secs * 1000)); - m_pool_timer.async_wait(handler); - } - void start_reuse() { - cancel_pool_timer(); m_is_reused = true; - m_epoch++; } +private: // Guards concurrent access to socket/ssl::stream. This is necessary // because timeouts and cancellation can touch the socket at the same time // as normal message processing. @@ -249,229 +218,177 @@ class asio_connection tcp::socket m_socket; std::unique_ptr > m_ssl_stream; - std::function m_ssl_context_callback; - - boost::asio::deadline_timer m_pool_timer; bool m_is_reused; bool m_keep_alive; - std::string m_pool_key; - uint32_t m_epoch; }; -class asio_shared_connection_pool +/// Implements a connection pool with adaptive connection removal and callback notification on idle +/// +/// The timeout mechanism is based on the `uint64_t m_epoch` member. Every 30 seconds, +/// the lambda in `start_epoch_interval` fires, triggering the cleanup of any +/// connections that have resided in the pool since the last cleanup phase's epoch. +/// +/// This works because the `m_connections` member functions is used in LIFO order. +/// LIFO usage guarantees that the elements remain sorted based on epoch number, +/// since the highest epoch is always removed and on insertion the next monotonically +/// increasing epoch is used. +/// +/// During the cleanup phase, connections are removed starting with the oldest. This +/// ensures that if a high intensity workload is followed by a low intensity workload, +/// the connection pool will correctly adapt to the current workload. Specifically, +/// the following code will eventually result in a maximum of one pooled connection +/// regardless of the initial number of pooled connections: +/// +/// while(1) +/// { +/// auto conn = pool.acquire(); +/// if (!conn) conn = new_conn(); +/// pool.release(conn); +/// } +/// +/// +/// Additionally, idle notification is only triggered when two cleanup phases have +/// occurred with no calls to `acquire()` between them. This prevents a race +/// condition where the cleanup might occur when the pool happens to be +/// instantaneously empty but still under heavy load. +/// +class asio_connection_pool : public std::enable_shared_from_this { public: - asio_shared_connection_pool(boost::asio::io_service& io_service) : - m_io_service(io_service) - {} - - ~asio_shared_connection_pool() + asio_connection_pool(const std::function& m_cb = {}) + : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()), + m_parent_pool_cb(m_cb) { - std::lock_guard lock(m_connections_mutex); - // Cancel the pool timer for all connections. - for (auto& connection : m_connections) - { - connection.second->cancel_pool_timer(); - } + start_epoch_interval(shared_from_this()); } - void release(const std::shared_ptr& connection) + std::shared_ptr acquire() { - if (connection->keep_alive() && (m_timeout_secs > 0)) - { - connection->cancel(); + std::lock_guard lock(m_lock); - std::lock_guard lock(m_connections_mutex); - auto it = m_connections.insert(std::make_pair(connection->pool_key(), connection)); + if (m_connections.empty()) + return nullptr; - // This will destroy and remove the connection from pool after the set timeout. - // We use 'this' because async calls to timer handler only occur while the pool exists. - auto connection_weak = std::weak_ptr(connection); - auto epoch = connection->epoch(); - connection->start_pool_timer(m_timeout_secs, [this, connection_weak, epoch](const boost::error_code& ec) { - this->free_shared_connection(ec, connection_weak, epoch); - }); - } + auto conn = std::move(m_connections.back().second); + m_connections.pop_back(); + conn->start_reuse(); + return conn; } -private: - void free_connection(const boost::system::error_code& ec, const std::weak_ptr &connection, unsigned int epoch) + void release(const std::shared_ptr& connection) { - auto connection_shared = connection.lock(); - if (!connection_shared) - return; + connection->cancel(); - std::lock_guard lock(m_connections_mutex); - auto it = m_connections.find(connection_shared); - if (it == m_connections.end()) - // The connection was acquired while this callback was firing + if (!connection->keep_alive()) return; - // The epoch is used to ensure the connection was not quickly acquired and released while this callback was firing. - // Every acquisition increments the epoch. - if (epoch != (*it)->epoch()) - m_connections.erase(it); - } -}; - -class asio_connection_pool -{ -public: - - asio_connection_pool(boost::asio::io_service& io_service) : - m_io_service(io_service) - {} - - ~asio_connection_pool() - { - std::lock_guard lock(m_connections_mutex); - // Cancel the pool timer for all connections. - for (auto& connection : m_connections) - { - connection->cancel_pool_timer(); - } + std::lock_guard lock(m_lock); + m_epoch++; + m_connections.emplace_back(m_epoch, connection); } - void release(const std::shared_ptr &connection) - { - connection->cancel(); +private: + static void start_epoch_interval(const std::shared_ptr& pool) { + std::weak_ptr weak_pool = pool; + auto prev_epoch = pool->m_epoch; + pool->m_pool_epoch_timer.expires_from_now(boost::posix_time::seconds(30)); + pool->m_pool_epoch_timer.async_wait([prev_epoch, weak_pool](const boost::system::error_code& ec) { + if (ec) + return; - if (connection->keep_alive()) - { - std::lock_guard lock(m_connections_mutex); - // This will destroy and remove the connection from pool after the set timeout. - // We use 'this' because async calls to timer handler only occur while the pool exists. - connection->start_pool_timer(s_timeout_secs.count(), boost::bind(&asio_connection_pool::free_connection, this, boost::asio::placeholders::error, pair.first, std::weak_ptr(connection), connection->nonce())); - m_connections.push_back(connection); - } - // Otherwise connection is not put to the pool and it will go out of scope. - } + auto pool = weak_pool.lock(); + if (!pool) + return; - std::shared_ptr obtain(const std::string &pool_key, bool start_with_ssl, const std::function& ssl_context_callback) - { - if (m_is_shared) - { - std::unique_lock lock(m_connections_mutex); - auto it = m_shared_connections.find(pool_key); - if (it == m_shared_connections.end()) + std::lock_guard lock(pool->m_lock); + if (prev_epoch == pool->m_epoch && pool->m_parent_pool_cb) { - lock.unlock(); - - // No connections in pool => create a new connection instance. - return std::make_shared(m_io_service, pool_key, start_with_ssl, ssl_context_callback); + assert(pool->m_connections.empty()); + pool->m_parent_pool_cb(pool.get()); } else { - // Reuse connection from pool. - auto connection = it->second; - m_shared_connections.erase(it); - connection->start_reuse(); - lock.unlock(); - - return connection; - } - } - else - { - std::unique_lock lock(m_connections_mutex); - if (m_connections.empty()) - { - lock.unlock(); + auto erase_end = std::find_if(pool->m_connections.begin(), pool->m_connections.end(), [prev_epoch](std::pair>& p) + { + return p.first > prev_epoch; + }); - // No connections in pool => create a new connection instance. - return std::make_shared(m_io_service, start_with_ssl, ssl_context_callback); + pool->m_connections.erase(pool->m_connections.begin(), erase_end); } - else - { - // Reuse connection from pool. - auto it = m_connections.begin(); - auto connection = *it; - m_connections.erase(it); - connection->start_reuse(); - lock.unlock(); - - return connection; - } - } + start_epoch_interval(pool); + }); } - static std::shared_ptr shared_instance(); + std::mutex m_lock; + boost::asio::deadline_timer m_pool_epoch_timer; + std::deque>> m_connections; + uint64_t m_epoch = 0; -private: + const std::function m_parent_pool_cb; +}; - // Using weak_ptr here ensures bind() to this handler will not prevent the connection object from going out of scope. - void free_shared_connection(const boost::system::error_code& ec, std::multimap>::iterator it, const std::weak_ptr &connection, const std::string &nonce) +class asio_shared_connection_pool : public std::enable_shared_from_this +{ +public: + std::shared_ptr obtain(const std::string &pool_key) { - if (!ec) + std::shared_ptr ret; + + std::lock_guard lock(m_lock); + auto it = m_pools.find(pool_key); + if (it == m_pools.end()) { - auto connection_shared = connection.lock(); - // Compare nonce here to ensure the iterator is valid, the connection not been reused. - if (connection_shared && (connection_shared->nonce() == nonce)) + std::weak_ptr weak_this = shared_from_this(); + ret = std::make_shared([pool_key, weak_this](asio_connection_pool* inner_pool_ptr) { - std::lock_guard lock(m_connections_mutex); - m_shared_connections.erase(it); - } - } - } + auto self = weak_this.lock(); + if (!self) + return; - // Using weak_ptr here ensures bind() to this handler will not prevent the connection object from going out of scope. - void free_connection(const boost::system::error_code& ec, const std::weak_ptr &connection, uint32_t epoch) - { - if (!ec) + std::lock_guard lock(self->m_lock); + auto it = self->m_pools.find(pool_key); + if (it != self->m_pools.end() && it->second.get() == inner_pool_ptr) + self->m_pools.erase(it); + }); + m_pools.emplace(pool_key, ret); + } + else { - auto connection_shared = connection.lock(); - if (!connection_shared) - return; - - std::lock_guard lock(m_connections_mutex); - auto it = m_connections.find(connection_shared); - if (it == m_connections.end()) - // The connection was acquired while this callback was firing - return; - - // The epoch is used to ensure the connection was not quickly acquired and released while this callback was firing. - // Every acquisition increments the epoch. - if (epoch != (*it)->epoch()) - m_connections.erase(it); + ret = it->second; } + assert(ret != nullptr); + return ret; } - boost::asio::io_service& m_io_service; + static std::shared_ptr& shared_instance() + { + static std::shared_ptr s_instance = std::make_shared(); - std::mutex m_connections_mutex; - std::set> m_connections; + return s_instance; + } - static const std::chrono::seconds s_timeout_secs = 30; +private: + std::mutex m_lock; + std::unordered_map> m_pools; }; -std::shared_ptr asio_connection_pool::shared_instance() -{ - const std::chrono::seconds idle_timeout(30); // Unused sockets are kept in pool for 30 seconds. - static std::shared_ptr s_instance = std::make_shared(crossplat::threadpool::shared_instance().service(), idle_timeout, true); - - return s_instance; -} - -class asio_client : public _http_client_communicator +class asio_client final : public _http_client_communicator { public: asio_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) , m_resolver(crossplat::threadpool::shared_instance().service()) { - m_start_with_ssl = base_uri().scheme() == "https" && !_http_client_communicator::client_config().proxy().is_specified(); - m_ssl_context_callback = this->client_config().get_ssl_context_callback(); - const std::chrono::seconds idle_timeout(30); // Unused sockets are kept in pool for 30 seconds. + m_start_with_ssl = base_uri().scheme() == "https" && !this->client_config().proxy().is_specified(); - if (m_ssl_context_callback) + if (this->client_config().get_ssl_context_callback()) { // We will use a private connection pool because there is no better approaches to compare callback functors. - m_pool = std::make_shared(crossplat::threadpool::shared_instance().service(), idle_timeout, false); + m_pool = std::make_shared(); } else { - init_pool_key(); - m_pool = asio_connection_pool::shared_instance(); + m_pool = asio_shared_connection_pool::shared_instance()->obtain(get_pool_key()); } } @@ -479,44 +396,57 @@ class asio_client : public _http_client_communicator unsigned long open() override { return 0; } - virtual pplx::task propagate(http_request request) override; - - void init_pool_key(); + void release_connection(std::shared_ptr& conn) + { + m_pool->release(conn); + } + std::shared_ptr obtain_connection() + { + std::shared_ptr conn = m_pool->acquire(); - std::shared_ptr obtain_connection(); + if (conn == nullptr) + { + // Pool was empty. Create a new connection + conn = std::make_shared(crossplat::threadpool::shared_instance().service()); + if (m_start_with_ssl) + conn->upgrade_to_ssl(this->client_config().get_ssl_context_callback()); + } - std::shared_ptr m_pool; - tcp::resolver m_resolver; - bool m_start_with_ssl; - std::function m_ssl_context_callback; - std::string m_pool_key; -}; + return conn; + } -void asio_client::init_pool_key() -{ - m_pool_key = base_uri().to_string(); + virtual pplx::task propagate(http_request request) override; - auto &credentials = _http_client_communicator::client_config().credentials(); - if (credentials.is_set()) +private: + std::string get_pool_key() const { - m_pool_key.append(credentials.username()); - } + auto pool_key = base_uri().to_string(); - auto &proxy = _http_client_communicator::client_config().proxy(); - if (proxy.is_specified()) - { - m_pool_key.append(proxy.address().to_string()); - if (proxy.credentials().is_set()) + auto &credentials = _http_client_communicator::client_config().credentials(); + if (credentials.is_set()) { - m_pool_key.append(proxy.credentials().username()); + pool_key.append(credentials.username()); } + + auto &proxy = _http_client_communicator::client_config().proxy(); + if (proxy.is_specified()) + { + pool_key.append(proxy.address().to_string()); + if (proxy.credentials().is_set()) + { + pool_key.append(proxy.credentials().username()); + } + } + + return pool_key; } -} -std::shared_ptr asio_client::obtain_connection() -{ - return m_pool->obtain(m_pool_key, m_start_with_ssl, m_ssl_context_callback); -} + std::shared_ptr m_pool; +public: + tcp::resolver m_resolver; +private: + bool m_start_with_ssl; +}; class asio_context : public request_context, public std::enable_shared_from_this { @@ -539,7 +469,7 @@ class asio_context : public request_context, public std::enable_shared_from_this { m_timer.stop(); // Release connection back to the pool. If connection was not closed, it will be put to the pool for reuse. - std::static_pointer_cast(m_http_client)->m_pool->release(m_connection); + std::static_pointer_cast(m_http_client)->release_connection(m_connection); } static std::shared_ptr create_request_context(std::shared_ptr<_http_client_communicator> &client, http_request &request) @@ -668,9 +598,9 @@ class asio_context : public request_context, public std::enable_shared_from_this m_context->report_error(err_ss.str(), ec, httpclient_errorcode_context::readheader); return; } - - m_context->m_connection->upgrade_to_ssl(); - + + m_context->m_connection->upgrade_to_ssl(m_context->m_http_client->client_config().get_ssl_context_callback()); + m_ssl_tunnel_established(m_context); } else From eaacac4aa8a147b5180cd04037d04ad133982b57 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 5 Jul 2016 15:45:37 -0700 Subject: [PATCH 115/609] Improved asio connection pooling implementation. Removed asio_connection inherits from enable_shared_from_this. Replaced asio_connection_pool::m_parent_pool_cb with a self-referencing shared_ptr. Added asio_shared_connection_pool::m_timer to periodically clear out expired connection pools. --- Release/src/http/client/http_client_asio.cpp | 121 +++++++++++++------ 1 file changed, 84 insertions(+), 37 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 49376dc882..560eac68d0 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -71,7 +71,7 @@ enum class httpclient_errorcode_context close }; -class asio_connection : public std::enable_shared_from_this +class asio_connection { friend class asio_client; public: @@ -222,7 +222,7 @@ class asio_connection : public std::enable_shared_from_this bool m_keep_alive; }; -/// Implements a connection pool with adaptive connection removal and callback notification on idle +/// Implements a connection pool with adaptive connection removal /// /// The timeout mechanism is based on the `uint64_t m_epoch` member. Every 30 seconds, /// the lambda in `start_epoch_interval` fires, triggering the cleanup of any @@ -247,20 +247,18 @@ class asio_connection : public std::enable_shared_from_this /// } /// /// -/// Additionally, idle notification is only triggered when two cleanup phases have -/// occurred with no calls to `acquire()` between them. This prevents a race -/// condition where the cleanup might occur when the pool happens to be -/// instantaneously empty but still under heavy load. +/// Additionally, when two cleanup phases have occurred with no calls to `release()` +/// between them, the internal self-reference is cleared. If there are no active +/// `http_client`s keeping the pool alive, this will cause the pool to expire upon +/// cleanup handler termination. Whenever a new call to `release()` arrives, the self +/// reference is re-applied to keep the pool alive. /// class asio_connection_pool : public std::enable_shared_from_this { public: - asio_connection_pool(const std::function& m_cb = {}) - : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()), - m_parent_pool_cb(m_cb) - { - start_epoch_interval(shared_from_this()); - } + asio_connection_pool() + : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) + {} std::shared_ptr acquire() { @@ -283,39 +281,56 @@ class asio_connection_pool : public std::enable_shared_from_this lock(m_lock); + if (m_self_reference == nullptr) + { + auto sptr = this->shared_from_this(); + m_self_reference = sptr; + start_epoch_interval(sptr); + } + m_epoch++; m_connections.emplace_back(m_epoch, connection); } private: + // Note: must be called under m_lock static void start_epoch_interval(const std::shared_ptr& pool) { + _ASSERTE(pool.get() != nullptr); + _ASSERTE(pool->m_self_reference != nullptr); + + auto& self = *pool; std::weak_ptr weak_pool = pool; - auto prev_epoch = pool->m_epoch; + + self.m_prev_epoch = self.m_epoch; pool->m_pool_epoch_timer.expires_from_now(boost::posix_time::seconds(30)); - pool->m_pool_epoch_timer.async_wait([prev_epoch, weak_pool](const boost::system::error_code& ec) { + pool->m_pool_epoch_timer.async_wait([weak_pool](const boost::system::error_code& ec) { if (ec) return; auto pool = weak_pool.lock(); if (!pool) return; + auto& self = *pool; - std::lock_guard lock(pool->m_lock); - if (prev_epoch == pool->m_epoch && pool->m_parent_pool_cb) + std::lock_guard lock(self.m_lock); + _ASSERTE(self.m_self_reference != nullptr); + if (self.m_prev_epoch == self.m_epoch) { - assert(pool->m_connections.empty()); - pool->m_parent_pool_cb(pool.get()); + assert(self.m_connections.empty()); + self.m_self_reference = nullptr; } else { - auto erase_end = std::find_if(pool->m_connections.begin(), pool->m_connections.end(), [prev_epoch](std::pair>& p) + auto prev_epoch = self.m_prev_epoch; + auto erase_end = std::find_if(self.m_connections.begin(), self.m_connections.end(), + [prev_epoch](std::pair>& p) { return p.first > prev_epoch; }); - pool->m_connections.erase(pool->m_connections.begin(), erase_end); + self.m_connections.erase(self.m_connections.begin(), erase_end); + start_epoch_interval(pool); } - start_epoch_interval(pool); }); } @@ -323,8 +338,9 @@ class asio_connection_pool : public std::enable_shared_from_this>> m_connections; uint64_t m_epoch = 0; + uint64_t m_prev_epoch = 0; - const std::function m_parent_pool_cb; + std::shared_ptr m_self_reference; }; class asio_shared_connection_pool : public std::enable_shared_from_this @@ -336,26 +352,27 @@ class asio_shared_connection_pool : public std::enable_shared_from_this lock(m_lock); auto it = m_pools.find(pool_key); - if (it == m_pools.end()) + if (it != m_pools.end()) { - std::weak_ptr weak_this = shared_from_this(); - ret = std::make_shared([pool_key, weak_this](asio_connection_pool* inner_pool_ptr) + ret = it->second.lock(); + if (ret == nullptr) { - auto self = weak_this.lock(); - if (!self) - return; - - std::lock_guard lock(self->m_lock); - auto it = self->m_pools.find(pool_key); - if (it != self->m_pools.end() && it->second.get() == inner_pool_ptr) - self->m_pools.erase(it); - }); - m_pools.emplace(pool_key, ret); + // Previous pool expired + ret = std::make_shared(); + it->second = ret; + } } else { - ret = it->second; + if (m_pools.empty()) + { + // If transitioning from empty to having a single element, restart the timer. + start_timer(shared_from_this()); + } + ret = std::make_shared(); + m_pools.emplace(pool_key, ret); } + assert(ret != nullptr); return ret; } @@ -367,9 +384,39 @@ class asio_shared_connection_pool : public std::enable_shared_from_this& self) + { + self->m_timer.expires_from_now(boost::posix_time::seconds(60)); + std::weak_ptr weak_this = self; + self->m_timer.async_wait([weak_this](const boost::system::error_code& ec) + { + if (ec) + return; + auto strong_this = weak_this.lock(); + if (!strong_this) + return; + + std::lock_guard lock(strong_this->m_lock); + auto b = strong_this->m_pools.begin(); + auto e = strong_this->m_pools.end(); + for (; b != e;) + { + if (b->second.expired()) + b = strong_this->m_pools.erase(b); + else + ++b; + } + if (!strong_this->m_pools.empty()) + start_timer(strong_this); + }); + } + + boost::asio::deadline_timer m_timer; std::mutex m_lock; - std::unordered_map> m_pools; + std::unordered_map> m_pools; }; class asio_client final : public _http_client_communicator From 943aa0b16bfab03ce19e5889522f78ac7a2f9026 Mon Sep 17 00:00:00 2001 From: ajneu Date: Tue, 19 Jul 2016 20:30:04 +0200 Subject: [PATCH 116/609] include_directories with SYSTEM for system-headers such as boost, to avoid warnings-checking on those 3rd party headers --- Release/CMakeLists.txt | 13 ++++++------- Release/libs/websocketpp/CMakeLists.txt | 2 +- Release/src/CMakeLists.txt | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index cbe840b663..1274102599 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -149,7 +149,7 @@ if(ANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith") - include_directories( + include_directories(SYSTEM "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include" "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include" "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include/backward" @@ -197,7 +197,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) # These settings can be used by the test targets -set(Casablanca_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) +set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) if (NOT CPPREST_EXCLUDE_WEBSOCKETS) find_path(WEBSOCKETPP_CONFIG websocketpp-config.cmake HINTS /usr/lib/cmake/websocketpp) @@ -207,20 +207,19 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) include(${WEBSOCKETPP_CONFIG}/websocketpp-config.cmake) include(${WEBSOCKETPP_CONFIG}/websocketpp-configVersion.cmake) message("-- Found websocketpp version " ${PACKAGE_VERSION} " on system") - set(Casablanca_INCLUDE_DIRS ${Casablanca_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${WEBSOCKETPP_INCLUDE_DIR}) + set(Casablanca_SYSTEM_INCLUDE_DIRS ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${WEBSOCKETPP_INCLUDE_DIR}) else(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) - set(Casablanca_INCLUDE_DIRS ${Casablanca_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp) + set(Casablanca_SYSTEM_INCLUDE_DIRS ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp) message("-- websocketpp not found, using the embedded version") endif(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) -else() - set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) endif() set(Casablanca_LIBRARY cpprest) set(Casablanca_LIBRARIES cpprest ${Boost_LIBRARIES}) # Everything in the project needs access to the casablanca include directories -include_directories(${Casablanca_INCLUDE_DIRS}) +include_directories( ${Casablanca_INCLUDE_DIRS}) +include_directories(SYSTEM ${Casablanca_SYSTEM_INCLUDE_DIRS}) # Finally, the tests all use the same style declaration to build themselves, so we use a function function(add_casablanca_test NAME SOURCES_VAR) diff --git a/Release/libs/websocketpp/CMakeLists.txt b/Release/libs/websocketpp/CMakeLists.txt index 8279156029..b30a0ed464 100644 --- a/Release/libs/websocketpp/CMakeLists.txt +++ b/Release/libs/websocketpp/CMakeLists.txt @@ -190,7 +190,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES) if (Boost_FOUND) # Boost is a project wide global dependency. - include_directories (${Boost_INCLUDE_DIRS}) + include_directories (SYSTEM ${Boost_INCLUDE_DIRS}) link_directories (${Boost_LIBRARY_DIRS}) # Pretty print status diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index cf086ed47e..3c98d8a22e 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(../include pch) if (NOT CPPREST_EXCLUDE_WEBSOCKETS) - include_directories(${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}) + include_directories(SYSTEM ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}) endif() add_definitions(${WARNINGS}) From 02119a190a0c694446248ca0c5729909e6d003d0 Mon Sep 17 00:00:00 2001 From: ajneu Date: Tue, 19 Jul 2016 20:31:06 +0200 Subject: [PATCH 117/609] have BingRequest honour http_proxy environment variable --- Release/samples/BingRequest/bingrequest.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Release/samples/BingRequest/bingrequest.cpp b/Release/samples/BingRequest/bingrequest.cpp index bf1e749817..16c630865a 100644 --- a/Release/samples/BingRequest/bingrequest.cpp +++ b/Release/samples/BingRequest/bingrequest.cpp @@ -30,6 +30,23 @@ using namespace web::http; using namespace web::http::client; using namespace concurrency::streams; +/* Can pass proxy information via environment variable http_proxy. + Example: + Linux: export http_proxy=http://192.1.8.1:8080 + */ +web::http::client::http_client_config client_config_for_proxy() +{ + web::http::client::http_client_config client_config; + + if(const char* env_http_proxy = std::getenv("http_proxy")) { + web::web_proxy proxy(env_http_proxy); + client_config.set_proxy(proxy); + } + + return client_config; +} + + #ifdef _WIN32 int wmain(int argc, wchar_t *args[]) #else @@ -52,7 +69,7 @@ int main(int argc, char *args[]) // Create an HTTP request. // Encode the URI query since it could contain special characters like spaces. - http_client client(U("http://www.bing.com/")); + http_client client(U("http://www.bing.com/"), client_config_for_proxy()); return client.request(methods::GET, uri_builder(U("/search")).append_query(U("q"), searchTerm).to_string()); }) @@ -74,4 +91,4 @@ int main(int argc, char *args[]) .wait(); return 0; -} \ No newline at end of file +} From 08f59008c45388654ba4a107cdee881360ef3604 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 25 Jul 2016 15:10:25 -0700 Subject: [PATCH 118/609] When the epoch has not increased since the last cleanup cycle, it means we can clear the pool, not that the pool is empty. --- Release/src/http/client/http_client_asio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 560eac68d0..b0b7a4ce18 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -316,7 +316,7 @@ class asio_connection_pool : public std::enable_shared_from_this Date: Tue, 26 Jul 2016 16:47:16 -0700 Subject: [PATCH 119/609] Adopt the Microsoft Open Source Code of Conduct --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ca0f662b12..9b68329ab1 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,5 @@ We'd love to get your review score, whether good or bad, but even more than that * [Documentation](https://github.com/Microsoft/cpprestsdk/wiki) * [Issue Tracker](https://github.com/Microsoft/cpprestsdk/issues) * Directly contact us: + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. \ No newline at end of file From 9e9bcbe94c5f13726d63f1920acbe120a5785b28 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Wed, 27 Jul 2016 15:14:28 -0700 Subject: [PATCH 120/609] Fix compile errors on windows --- .../BingRequest140.xp/BingRequest140.xp.vcxproj | 8 ++++---- .../BingRequest/BingRequest140/BingRequest140.vcxproj | 11 ++++++----- Release/samples/BingRequest/bingrequest.cpp | 3 ++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj index 2c799b7326..56afcd81b3 100644 --- a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj +++ b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj @@ -62,7 +62,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -76,7 +76,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -92,7 +92,7 @@ MaxSpeed true true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -110,7 +110,7 @@ MaxSpeed true true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async diff --git a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj b/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj index 12fd07f59d..b10a107dbc 100644 --- a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj +++ b/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj @@ -40,7 +40,8 @@ NotSet v140 - + Application false true @@ -70,7 +71,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -84,7 +85,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -100,7 +101,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -118,7 +119,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async diff --git a/Release/samples/BingRequest/bingrequest.cpp b/Release/samples/BingRequest/bingrequest.cpp index 16c630865a..256faa9826 100644 --- a/Release/samples/BingRequest/bingrequest.cpp +++ b/Release/samples/BingRequest/bingrequest.cpp @@ -39,7 +39,8 @@ web::http::client::http_client_config client_config_for_proxy() web::http::client::http_client_config client_config; if(const char* env_http_proxy = std::getenv("http_proxy")) { - web::web_proxy proxy(env_http_proxy); + uri proxy_uri(utility::conversions::utf8_to_utf16(env_http_proxy)); + web::web_proxy proxy(proxy_uri); client_config.set_proxy(proxy); } From 0bed9f957dd9227e2e3403c567dfa528e99e7289 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Thu, 28 Jul 2016 11:21:59 -0700 Subject: [PATCH 121/609] Disable create_https_listener_get testcase --- .../functional/http/listener/listener_construction_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/listener/listener_construction_tests.cpp b/Release/tests/functional/http/listener/listener_construction_tests.cpp index 8e30a2b488..7feecda31c 100644 --- a/Release/tests/functional/http/listener/listener_construction_tests.cpp +++ b/Release/tests/functional/http/listener/listener_construction_tests.cpp @@ -1,4 +1,4 @@ -/*** +/*** * ==++== * * Copyright (c) Microsoft Corporation. All rights reserved. @@ -432,7 +432,7 @@ TEST_FIXTURE(uri_address, listener_config_creation) #if !defined(_WIN32) && !defined(__cplusplus_winrt) -TEST_FIXTURE(uri_address, create_https_listener_get) +TEST_FIXTURE(uri_address, create_https_listener_get, "Ignore", "github 209") { const char * self_signed_cert = R"( -----BEGIN CERTIFICATE----- From ad9150b6967c19424148833c9244d0f06e73f868 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Thu, 28 Jul 2016 13:00:41 -0700 Subject: [PATCH 122/609] Fix bingrequest build break on osx and linux --- Release/samples/BingRequest/bingrequest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/samples/BingRequest/bingrequest.cpp b/Release/samples/BingRequest/bingrequest.cpp index 256faa9826..671690abc3 100644 --- a/Release/samples/BingRequest/bingrequest.cpp +++ b/Release/samples/BingRequest/bingrequest.cpp @@ -39,7 +39,7 @@ web::http::client::http_client_config client_config_for_proxy() web::http::client::http_client_config client_config; if(const char* env_http_proxy = std::getenv("http_proxy")) { - uri proxy_uri(utility::conversions::utf8_to_utf16(env_http_proxy)); + uri proxy_uri(utility::conversions::to_string_t(env_http_proxy)); web::web_proxy proxy(proxy_uri); client_config.set_proxy(proxy); } From 16582a56482fbea4946402b380b9ce6119f855b4 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Thu, 28 Jul 2016 13:05:16 -0700 Subject: [PATCH 123/609] Fix warning 4996 for get_env for 120 samples --- .../BingRequest120.xp/BingRequest120.xp.vcxproj | 8 ++++---- .../BingRequest/BingRequest120/BingRequest120.vcxproj | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj b/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj index d4e878ee46..67d605f1f9 100644 --- a/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj +++ b/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj @@ -62,7 +62,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -76,7 +76,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -92,7 +92,7 @@ MaxSpeed true true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -110,7 +110,7 @@ MaxSpeed true true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async diff --git a/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj b/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj index 1bf0f1287c..981088f76d 100644 --- a/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj +++ b/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj @@ -72,7 +72,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -86,7 +86,7 @@ /bigobj %(AdditionalOptions) NotUsing Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -102,7 +102,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async @@ -120,7 +120,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) $(CasablancaIncludeDir) Async From 5b7bfd4927157a7c1c26467fab33f6da9d4ab40e Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Thu, 28 Jul 2016 13:17:35 -0700 Subject: [PATCH 124/609] Fix a typo error from previous commit --- .../samples/BingRequest/BingRequest140/BingRequest140.vcxproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj b/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj index b10a107dbc..bf9a63acc9 100644 --- a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj +++ b/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj @@ -40,8 +40,7 @@ NotSet v140 - + Application false true From e8347d041ed810a6423bd2552de66f56acab7ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deniz=20T=C3=BCrkoglu?= Date: Fri, 29 Jul 2016 20:13:23 +0200 Subject: [PATCH 125/609] ifndef BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION This can be defined elsewhere and can raise an error. --- Release/include/cpprest/details/cpprest_compat.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Release/include/cpprest/details/cpprest_compat.h b/Release/include/cpprest/details/cpprest_compat.h index 240a338995..8ad309950d 100644 --- a/Release/include/cpprest/details/cpprest_compat.h +++ b/Release/include/cpprest/details/cpprest_compat.h @@ -68,8 +68,10 @@ // without this macro defined, it will create references to __tls_get_addr // which (while able to link) will not be available at runtime and prevent // the .so from loading. +#if not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION #define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION #endif +#endif #ifdef __clang__ #include From 211fdeaa5f594e7b93b99caf56e735715991e748 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Fri, 29 Jul 2016 16:00:38 -0700 Subject: [PATCH 126/609] Fix websocket tests. jabbr.net certificate is not valid anymore. swordsoftruth.com certificate has been fixed. so interchange the sites in the tests. --- .../websockets/client/authentication_tests.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Release/tests/functional/websockets/client/authentication_tests.cpp b/Release/tests/functional/websockets/client/authentication_tests.cpp index 148655fd66..fde6c837c6 100644 --- a/Release/tests/functional/websockets/client/authentication_tests.cpp +++ b/Release/tests/functional/websockets/client/authentication_tests.cpp @@ -142,7 +142,7 @@ void sni_test_impl(websocket_client &client) { try { - client.connect(U("wss://jabbr.net")).wait(); + client.connect(U("wss://swordsoftruth.com")).wait(); // Should never be reached. VERIFY_IS_TRUE(false); @@ -182,7 +182,7 @@ TEST(disable_sni) try { - client.connect(U("wss://jabbr.net")).wait(); + client.connect(U("wss://swordsoftruth.com")).wait(); // Should never be reached. VERIFY_IS_TRUE(false); @@ -202,7 +202,7 @@ TEST(disable_sni) TEST(sni_explicit_hostname) { websocket_client_config config; - const auto &name = utf8string("jabbr.net"); + const auto &name = utf8string("swordsoftruth.com"); config.set_server_name(name); VERIFY_ARE_EQUAL(name, config.server_name()); websocket_client client(config); @@ -234,9 +234,9 @@ TEST(self_signed_cert) handshake_error_test_impl(U("wss://www.pcwebshop.co.uk/")); } -TEST(hostname_mismatch, "Ignore", "Site fixed certificate. Improve test (new site or alternate method).") +TEST(hostname_mismatch) { - handshake_error_test_impl(U("wss://swordsoftruth.com/")); + handshake_error_test_impl(U("wss://jabbr.net")); } TEST(cert_expired) From b6cff6e28ba795d0a707374aa9686e371b85c726 Mon Sep 17 00:00:00 2001 From: Gopalakrishna Palem Date: Sat, 30 Jul 2016 14:21:28 +0530 Subject: [PATCH 127/609] Adding PARENT_SCOPE To make it possible to include as sub-project from external projects. This lets the variable `Casablanca_LIBRARIES` be accessible from the parent project --- Release/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index d99fa5c877..37c652e0dd 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -197,7 +197,7 @@ set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_RANDOM_LIBRARY} ${Boost_REGEX_LIBRARY} - ${Boost_FRAMEWORK}) + ${Boost_FRAMEWORK} PARENT_SCOPE) # Everything in the project needs access to the casablanca include directories include_directories(${Casablanca_INCLUDE_DIRS}) From 6cd63923500f37fc012dede318f2520352686530 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 2 Aug 2016 00:46:54 -0700 Subject: [PATCH 128/609] Revert global connection pool, but leave improved individual pools. Pools no longer need to self-reference and are destroyed with the owning http_client. --- Release/src/http/client/http_client.cpp | 6 +- Release/src/http/client/http_client_asio.cpp | 172 +++--------------- Release/src/http/client/http_client_impl.h | 6 +- .../src/http/client/http_client_winhttp.cpp | 4 +- Release/src/http/client/http_client_winrt.cpp | 6 +- 5 files changed, 39 insertions(+), 155 deletions(-) diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 9f71603d85..8dbfb9c1f4 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -191,7 +191,7 @@ const uri & _http_client_communicator::base_uri() const return m_uri; } -_http_client_communicator::_http_client_communicator(http::uri address, http_client_config client_config) +_http_client_communicator::_http_client_communicator(http::uri&& address, http_client_config&& client_config) : m_uri(std::move(address)), m_client_config(std::move(client_config)), m_opened(false), m_scheduled(0) { } @@ -370,12 +370,12 @@ http_client::http_client(const uri &base_uri, const http_client_config &client_c uribuilder.set_scheme(_XPLATSTR("http")); uri uriWithScheme = uribuilder.to_uri(); verify_uri(uriWithScheme); - final_pipeline_stage = details::create_platform_final_pipeline_stage(uriWithScheme, client_config); + final_pipeline_stage = details::create_platform_final_pipeline_stage(std::move(uriWithScheme), http_client_config(client_config)); } else { verify_uri(base_uri); - final_pipeline_stage = details::create_platform_final_pipeline_stage(base_uri, client_config); + final_pipeline_stage = details::create_platform_final_pipeline_stage(uri(base_uri), http_client_config(client_config)); } m_pipeline = std::make_shared(std::move(final_pipeline_stage)); diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 9bd085ab69..f928e18e46 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -235,9 +235,10 @@ class asio_connection /// /// During the cleanup phase, connections are removed starting with the oldest. This /// ensures that if a high intensity workload is followed by a low intensity workload, -/// the connection pool will correctly adapt to the current workload. Specifically, -/// the following code will eventually result in a maximum of one pooled connection -/// regardless of the initial number of pooled connections: +/// the connection pool will correctly adapt to the low intensity workload. +/// +/// Specifically, the following code will eventually result in a maximum of one pooled +/// connection regardless of the initial number of pooled connections: /// /// while(1) /// { @@ -246,18 +247,11 @@ class asio_connection /// pool.release(conn); /// } /// -/// -/// Additionally, when two cleanup phases have occurred with no calls to `release()` -/// between them, the internal self-reference is cleared. If there are no active -/// `http_client`s keeping the pool alive, this will cause the pool to expire upon -/// cleanup handler termination. Whenever a new call to `release()` arrives, the self -/// reference is re-applied to keep the pool alive. /// class asio_connection_pool : public std::enable_shared_from_this { public: - asio_connection_pool() - : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) + asio_connection_pool() : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) {} std::shared_ptr acquire() @@ -281,29 +275,29 @@ class asio_connection_pool : public std::enable_shared_from_this lock(m_lock); - if (m_self_reference == nullptr) + if (!is_timer_running) { - auto sptr = this->shared_from_this(); - m_self_reference = sptr; - start_epoch_interval(sptr); + start_epoch_interval(shared_from_this()); + is_timer_running = true; } m_epoch++; - m_connections.emplace_back(m_epoch, connection); + m_connections.emplace_back(m_epoch, std::move(connection)); } private: // Note: must be called under m_lock - static void start_epoch_interval(const std::shared_ptr& pool) { + static void start_epoch_interval(const std::shared_ptr& pool) + { _ASSERTE(pool.get() != nullptr); - _ASSERTE(pool->m_self_reference != nullptr); auto& self = *pool; std::weak_ptr weak_pool = pool; self.m_prev_epoch = self.m_epoch; pool->m_pool_epoch_timer.expires_from_now(boost::posix_time::seconds(30)); - pool->m_pool_epoch_timer.async_wait([weak_pool](const boost::system::error_code& ec) { + pool->m_pool_epoch_timer.async_wait([weak_pool](const boost::system::error_code& ec) + { if (ec) return; @@ -313,11 +307,11 @@ class asio_connection_pool : public std::enable_shared_from_this lock(self.m_lock); - _ASSERTE(self.m_self_reference != nullptr); if (self.m_prev_epoch == self.m_epoch) { self.m_connections.clear(); - self.m_self_reference = nullptr; + self.is_timer_running = false; + return; } else { @@ -335,109 +329,23 @@ class asio_connection_pool : public std::enable_shared_from_this>> m_connections; + uint64_t m_epoch = 0; uint64_t m_prev_epoch = 0; - - std::shared_ptr m_self_reference; -}; - -class asio_shared_connection_pool : public std::enable_shared_from_this -{ -public: - std::shared_ptr obtain(const std::string &pool_key) - { - std::shared_ptr ret; - - std::lock_guard lock(m_lock); - auto it = m_pools.find(pool_key); - if (it != m_pools.end()) - { - ret = it->second.lock(); - if (ret == nullptr) - { - // Previous pool expired - ret = std::make_shared(); - it->second = ret; - } - } - else - { - if (m_pools.empty()) - { - // If transitioning from empty to having a single element, restart the timer. - start_timer(shared_from_this()); - } - ret = std::make_shared(); - m_pools.emplace(pool_key, ret); - } - - assert(ret != nullptr); - return ret; - } - - static std::shared_ptr& shared_instance() - { - static std::shared_ptr s_instance = std::make_shared(); - - return s_instance; - } - - asio_shared_connection_pool() : m_timer(crossplat::threadpool::shared_instance().service()) {} - -private: - static void start_timer(const std::shared_ptr& self) - { - self->m_timer.expires_from_now(boost::posix_time::seconds(60)); - std::weak_ptr weak_this = self; - self->m_timer.async_wait([weak_this](const boost::system::error_code& ec) - { - if (ec) - return; - auto strong_this = weak_this.lock(); - if (!strong_this) - return; - - std::lock_guard lock(strong_this->m_lock); - auto b = strong_this->m_pools.begin(); - auto e = strong_this->m_pools.end(); - for (; b != e;) - { - if (b->second.expired()) - b = strong_this->m_pools.erase(b); - else - ++b; - } - if (!strong_this->m_pools.empty()) - start_timer(strong_this); - }); - } - - boost::asio::deadline_timer m_timer; - std::mutex m_lock; - std::unordered_map> m_pools; + bool is_timer_running = false; + boost::asio::deadline_timer m_pool_epoch_timer; }; class asio_client final : public _http_client_communicator { public: - asio_client(http::uri address, http_client_config client_config) - : _http_client_communicator(std::move(address), std::move(client_config)) - , m_resolver(crossplat::threadpool::shared_instance().service()) - { - m_start_with_ssl = base_uri().scheme() == "https" && !this->client_config().proxy().is_specified(); - - if (this->client_config().get_ssl_context_callback()) - { - // We will use a private connection pool because there is no better approaches to compare callback functors. - m_pool = std::make_shared(); - } - else - { - m_pool = asio_shared_connection_pool::shared_instance()->obtain(get_pool_key()); - } - } + asio_client(http::uri&& address, http_client_config&& client_config) + : _http_client_communicator(std::move(address), std::move(client_config)) + , m_resolver(crossplat::threadpool::shared_instance().service()) + , m_pool(std::make_shared()) + , m_start_with_ssl(base_uri().scheme() == "https" && !this->client_config().proxy().is_specified()) + {} void send_request(const std::shared_ptr &request_ctx) override; @@ -464,35 +372,11 @@ class asio_client final : public _http_client_communicator virtual pplx::task propagate(http_request request) override; -private: - std::string get_pool_key() const - { - auto pool_key = base_uri().to_string(); - - auto &credentials = _http_client_communicator::client_config().credentials(); - if (credentials.is_set()) - { - pool_key.append(credentials.username()); - } - - auto &proxy = _http_client_communicator::client_config().proxy(); - if (proxy.is_specified()) - { - pool_key.append(proxy.address().to_string()); - if (proxy.credentials().is_set()) - { - pool_key.append(proxy.credentials().username()); - } - } - - return pool_key; - } - - std::shared_ptr m_pool; public: tcp::resolver m_resolver; private: - bool m_start_with_ssl; + const std::shared_ptr m_pool; + const bool m_start_with_ssl; }; class asio_context : public request_context, public std::enable_shared_from_this @@ -1612,9 +1496,9 @@ class asio_context : public request_context, public std::enable_shared_from_this }; -std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config) { - return std::make_shared(base_uri, client_config); + return std::make_shared(std::move(base_uri), std::move(client_config)); } void asio_client::send_request(const std::shared_ptr &request_ctx) diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h index ac0ae81ce1..eacf64c83b 100644 --- a/Release/src/http/client/http_client_impl.h +++ b/Release/src/http/client/http_client_impl.h @@ -100,7 +100,7 @@ class _http_client_communicator : public http_pipeline_stage { public: - virtual ~_http_client_communicator() {} + virtual ~_http_client_communicator() override = default; // Asynchronously send a HTTP request and process the response. void async_send_request(const std::shared_ptr &request); @@ -112,7 +112,7 @@ class _http_client_communicator : public http_pipeline_stage const uri & base_uri() const; protected: - _http_client_communicator(http::uri address, http_client_config client_config); + _http_client_communicator(http::uri&& address, http_client_config&& client_config); // Method to open client. virtual unsigned long open() = 0; @@ -146,6 +146,6 @@ class _http_client_communicator : public http_pipeline_stage /// /// Factory function implemented by the separate platforms to construct their subclasses of _http_client_communicator /// -std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config); +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config); }}}} \ No newline at end of file diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index e4d19042b2..db0bb9e340 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -1294,9 +1294,9 @@ class winhttp_client : public _http_client_communicator bool m_secure; }; -std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config) { - return std::make_shared(std::move(base_uri), client_config); + return std::make_shared(std::move(base_uri), std::move(client_config)); } }}}} diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 5ae4a8ec52..639bbc3da8 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -356,7 +356,7 @@ class IResponseStream class winrt_client : public _http_client_communicator { public: - winrt_client(http::uri address, http_client_config client_config) + winrt_client(http::uri&& address, http_client_config&& client_config) : _http_client_communicator(std::move(address), std::move(client_config)) { } winrt_client(const winrt_client&) = delete; @@ -560,9 +560,9 @@ class winrt_client : public _http_client_communicator } }; -std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri base_uri, const http_client_config& client_config) +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config) { - return std::make_shared(std::move(base_uri), client_config); + return std::make_shared(std::move(base_uri), std::move(client_config)); } }}}} From c800ab2d04bb6c6d5e6a5617137f358a8f3d91ea Mon Sep 17 00:00:00 2001 From: daniuk-microsoft Date: Tue, 2 Aug 2016 11:38:02 -0700 Subject: [PATCH 129/609] Fixed race condition in Casablanca ws_client_winrt.cpp Fixed race condition in Casablanca ws_client_winrt.cpp - Simplified message queuing logic to always use the outgoing queue - Removed m_num_sends member variable --- .../src/websockets/client/ws_client_winrt.cpp | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/Release/src/websockets/client/ws_client_winrt.cpp b/Release/src/websockets/client/ws_client_winrt.cpp index a35f269adf..035f9b02cd 100644 --- a/Release/src/websockets/client/ws_client_winrt.cpp +++ b/Release/src/websockets/client/ws_client_winrt.cpp @@ -85,8 +85,7 @@ class winrt_callback_client : public websocket_client_callback_impl, public std: public: winrt_callback_client(websocket_client_config config) : websocket_client_callback_impl(std::move(config)), - m_connected(false), - m_num_sends(0) + m_connected(false) { m_msg_websocket = ref new MessageWebSocket(); @@ -243,17 +242,24 @@ class winrt_callback_client : public websocket_client_callback_impl, public std: return pplx::task_from_exception(websocket_exception("Message size too large. Ensure message length is less than UINT_MAX.")); } - if (++m_num_sends == 1) // No sends in progress + bool msg_pending = false; { - // Start sending the message - send_msg(msg); - } - else - { - // Only actually have to take the lock if touching the queue. std::lock_guard lock(m_send_lock); + if (m_outgoing_msg_queue.size() > 0) + { + msg_pending = true; + } + m_outgoing_msg_queue.push(msg); } + + // No sends in progress + if (msg_pending == false) + { + // Start sending the message + send_msg(msg); + } + return pplx::create_task(msg.body_sent()); } @@ -385,15 +391,24 @@ class winrt_callback_client : public websocket_client_callback_impl, public std: msg.signal_body_sent(); } - if (--this_client->m_num_sends > 0) + bool msg_pending = false; + websocket_outgoing_message next_msg; { // Only hold the lock when actually touching the queue. - websocket_outgoing_message next_msg; + std::lock_guard lock(this_client->m_send_lock); + + // First message in queue has been sent + this_client->m_outgoing_msg_queue.pop(); + + if (this_client->m_outgoing_msg_queue.size() > 0) { - std::lock_guard lock(this_client->m_send_lock); next_msg = this_client->m_outgoing_msg_queue.front(); - this_client->m_outgoing_msg_queue.pop(); + msg_pending = true; } + } + + if (msg_pending) + { this_client->send_msg(next_msg); } }); @@ -443,11 +458,8 @@ class winrt_callback_client : public websocket_client_callback_impl, public std: // The implementation has to ensure ordering of send requests std::mutex m_send_lock; - // Queue to order the sends + // Queue to track pending sends std::queue m_outgoing_msg_queue; - - // Number of sends in progress and queued up. - std::atomic m_num_sends; }; void ReceiveContext::OnReceive(MessageWebSocket^ sender, MessageWebSocketMessageReceivedEventArgs^ args) From 4b24cedc16f06b0672cd11586f56fe94358af2d2 Mon Sep 17 00:00:00 2001 From: daniuk-microsoft Date: Wed, 3 Aug 2016 11:24:19 -0700 Subject: [PATCH 130/609] Fixed mem leak in HttpRequestCallback::OnHeadersAvailable() IXMLHTTPRequest2::GetAllResponseHeaders() allocates memory that is returned via hdrStr. Changed to make sure this gets cleaned up. --- Release/src/http/client/http_client_winrt.cpp | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 5ae4a8ec52..42390b0ae2 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -94,25 +94,33 @@ class HttpRequestCallback : utf16char *hdrStr = nullptr; HRESULT hr = xmlReq->GetAllResponseHeaders(&hdrStr); - if(hr != S_OK) + if (SUCCEEDED(hr)) { - return hr; - } + try + { + auto progress = m_request->m_request._get_impl()->_progress_handler(); + if (progress && m_request->m_uploaded == 0) + { + (*progress)(message_direction::upload, 0); + } - auto progress = m_request->m_request._get_impl()->_progress_handler(); - if (progress && m_request->m_uploaded == 0) - { - try { (*progress)(message_direction::upload, 0); } catch(...) + parse_headers_string(hdrStr, response.headers()); + m_request->complete_headers(); + } + catch (...) { m_request->m_exceptionPtr = std::current_exception(); - return ERROR_UNHANDLED_EXCEPTION; + hr = ERROR_UNHANDLED_EXCEPTION; } } - web::http::details::parse_headers_string(hdrStr, response.headers()); - m_request->complete_headers(); + if (hdrStr != nullptr) + { + ::CoTaskMemFree(hdrStr); + hdrStr = nullptr; + } - return S_OK; + return hr; } // Called when a portion of the entity body has been received. From 2e99d108fd9a4dd0a67fc8e9e12c6abb217c7a71 Mon Sep 17 00:00:00 2001 From: Casablanca Team Date: Thu, 4 Aug 2016 14:40:37 -0700 Subject: [PATCH 131/609] During timeout, there is a race to determine the exact error code. To ensure timeouts always result in std::errc::timed_out, we trigger entirely off of the timer's state instead of considering the error code. --- Release/src/http/client/http_client_asio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index f928e18e46..b9dc0153db 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -804,7 +804,7 @@ class asio_context : public request_context, public std::enable_shared_from_this long errorcodeValue = ec.value(); // map timer cancellation to time_out - if (ec == boost::system::errc::operation_canceled && m_timer.has_timedout()) + if (m_timer.has_timedout()) { errorcodeValue = make_error_code(std::errc::timed_out).value(); } From abc2753ca41bad53d3d425316a1884ab2b21fd85 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 5 Aug 2016 15:11:11 -0700 Subject: [PATCH 132/609] Reduce size of race condition in asio_client. In the future, the entire timeout interaction needs to be reworked to remove it entirely. --- Release/src/http/client/http_client_asio.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index b9dc0153db..6963aee43d 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -464,6 +464,12 @@ class asio_context : public request_context, public std::enable_shared_from_this m_context->m_timer.reset(); auto endpoint = *endpoints; m_context->m_connection->async_connect(endpoint, boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); + + // TODO: refactor all interactions with the timeout_timer to avoid racing + if (m_context->m_timer.has_timedout()) + { + m_context->m_connection->close(); + } } } @@ -876,6 +882,12 @@ class asio_context : public request_context, public std::enable_shared_from_this m_timer.reset(); auto endpoint = *endpoints; m_connection->async_connect(endpoint, boost::bind(&asio_context::handle_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); + + // TODO: refactor all interactions with the timeout_timer to avoid racing + if (m_timer.has_timedout()) + { + m_connection->close(); + } } } @@ -1479,7 +1491,7 @@ class asio_context : public request_context, public std::enable_shared_from_this #else std::chrono::microseconds m_duration; #endif - timer_state m_state; + std::atomic m_state; std::weak_ptr m_ctx; boost::asio::steady_timer m_timer; }; From edfb941eb5e7fac60c3783159147bc36d3a40da9 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Thu, 25 Aug 2016 18:13:42 -0700 Subject: [PATCH 133/609] Bump version to 2.9 --- Build/version.props | 2 +- Release/include/cpprest/version.h | 2 +- Release/src/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Build/version.props b/Build/version.props index c74165e925..b5eb1517da 100644 --- a/Build/version.props +++ b/Build/version.props @@ -3,7 +3,7 @@ cpprest 2 - 8 + 9 0 $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index 642dd48568..11afd6b90d 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -16,7 +16,7 @@ * ==--== */ #define CPPREST_VERSION_REVISION 0 -#define CPPREST_VERSION_MINOR 8 +#define CPPREST_VERSION_MINOR 9 #define CPPREST_VERSION_MAJOR 2 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 3c98d8a22e..4074905ac2 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -132,7 +132,7 @@ target_link_libraries(cpprest # Portions specific to cpprest binary versioning. set (CPPREST_VERSION_MAJOR 2) -set (CPPREST_VERSION_MINOR 8) +set (CPPREST_VERSION_MINOR 9) set (CPPREST_VERSION_REVISION 0) if(WIN32) From 3514688f4e24cfc8d6612191f1c022feb18a18dc Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 2 Sep 2016 15:54:44 +0200 Subject: [PATCH 134/609] replace boost::this_thread::yield with std::this_thread::yield --- Release/src/pplx/pplxlinux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/pplx/pplxlinux.cpp b/Release/src/pplx/pplxlinux.cpp index 73e07bd350..a50237d47a 100644 --- a/Release/src/pplx/pplxlinux.cpp +++ b/Release/src/pplx/pplxlinux.cpp @@ -46,7 +46,7 @@ namespace details { _PPLXIMP void YieldExecution() { - boost::this_thread::yield(); + std::this_thread::yield(); } } From 3f876bd6ccb830a55be5b054c6e5c5d8938ec201 Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Wed, 7 Sep 2016 15:40:18 +0100 Subject: [PATCH 135/609] Initial implementation of HTTP compression for Windows --- .../include/cpprest/details/http_helpers.h | 83 +++++ Release/include/cpprest/http_client.h | 23 ++ .../build/vs14.wod/casablanca140.wod.vcxproj | 11 +- .../src/http/client/http_client_winhttp.cpp | 74 ++++- Release/src/http/common/http_helpers.cpp | 312 ++++++++++++++++++ .../functional/http/client/outside_tests.cpp | 19 ++ .../http/client/request_helper_tests.cpp | 50 +++ cpprestsdk140.sln | 14 +- 8 files changed, 573 insertions(+), 13 deletions(-) diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 3e231f5871..bf9dc7486e 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -27,6 +27,11 @@ ****/ #pragma once +// CPPREST_EXCLUDE_WEBSOCKETS is a flag that now essentially means "no external dependencies". TODO: Rename +#if defined(_WIN32) && !defined(CPPREST_EXCLUDE_WEBSOCKETS) +#define CPPREST_HTTP_COMPRESSION +#endif + #include "cpprest/http_msg.h" namespace web { namespace http @@ -124,4 +129,82 @@ namespace details _ASYNCRTIMP size_t __cdecl add_chunked_delimiters(_Out_writes_(buffer_size) uint8_t *data, _In_ size_t buffer_size, size_t bytes_read); } + namespace compression + { + enum class compression_algorithm : int + { + deflate = 15, + gzip = 31, + invalid = 9999 + }; + + using data_buffer = std::vector; + + class stream_decompressor + { + public: + + static compression_algorithm to_compression_algorithm(const utility::string_t& alg) + { + if (U("gzip") == alg) + { + return compression_algorithm::gzip; + } + else if (U("deflate") == alg) + { + return compression_algorithm::deflate; + } + + return compression_algorithm::invalid; + } + + static bool is_supported() + { +#if !defined(CPPREST_HTTP_COMPRESSION) + return false; +#else + return true; +#endif + } + + _ASYNCRTIMP stream_decompressor(compression_algorithm alg); + + _ASYNCRTIMP data_buffer decompress(const data_buffer& input); + + _ASYNCRTIMP data_buffer decompress(const uint8_t* input, size_t input_size); + + _ASYNCRTIMP bool has_error() const; + + private: + class stream_decompressor_impl; + std::shared_ptr m_pimpl; + }; + + class stream_compressor + { + public: + + static bool is_supported() + { +#if !defined(CPPREST_HTTP_COMPRESSION) + return false; +#else + return true; +#endif + } + + _ASYNCRTIMP stream_compressor(compression_algorithm alg); + + _ASYNCRTIMP data_buffer compress(const data_buffer& input, bool finish); + + _ASYNCRTIMP data_buffer compress(const uint8_t* input, size_t input_size, bool finish); + + _ASYNCRTIMP bool has_error() const; + + private: + class stream_compressor_impl; + std::shared_ptr m_pimpl; + }; + + } }}} diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 86e314feca..d5ffad015e 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -104,6 +104,7 @@ class http_client_config #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) , m_buffer_request(false) + , m_request_compressed(false) #endif { } @@ -301,6 +302,27 @@ class http_client_config { m_buffer_request = buffer_request; } + + /// + /// Checks if requesting a compressed response is turned on, the default is off. + /// + /// True if compressed response is enabled, false otherwise + bool request_compressed_response() const + { + return m_request_compressed; + } + + /// + /// Request that the server responds with a compressed body. + /// If true, in cases where the server does not support compression, this will have no effect. + /// The response body is internally decompressed before the consumer receives the data. + /// + /// True to turn on response body compression, false otherwise. + /// Please note there is a performance cost due to copying the request data. + void set_request_compressed_response(bool request_compressed) + { + m_request_compressed = request_compressed; + } #endif #endif @@ -375,6 +397,7 @@ class http_client_config #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) bool m_buffer_request; + bool m_request_compressed; #endif }; diff --git a/Release/src/build/vs14.wod/casablanca140.wod.vcxproj b/Release/src/build/vs14.wod/casablanca140.wod.vcxproj index 24d0a9088d..25e0bbd9db 100644 --- a/Release/src/build/vs14.wod/casablanca140.wod.vcxproj +++ b/Release/src/build/vs14.wod/casablanca140.wod.vcxproj @@ -21,14 +21,17 @@ + d $(CppRestBaseFileName)140$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix).wod - 57c5697d + + + CPPREST_EXCLUDE_WEBSOCKETS;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) @@ -47,4 +50,10 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 36f596b937..a779a4d36a 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -238,6 +238,8 @@ class winhttp_request_context : public request_context memory_holder m_body_data; + std::unique_ptr decompressor; + virtual void cleanup() { if(m_request_handle != nullptr) @@ -587,6 +589,11 @@ class winhttp_client : public _http_client_communicator } } + if(web::http::details::compression::stream_decompressor::is_supported() && client_config().request_compressed_response()) + { + msg.headers().add(web::http::header_names::accept_encoding, U("deflate, gzip")); + } + // Add headers. if(!msg.headers().empty()) { @@ -1135,6 +1142,24 @@ class winhttp_client : public _http_client_communicator } } + // If the response body is compressed we will read the encoding header and create a decompressor object which will later decompress the body + utility::string_t encoding; + if (web::http::details::compression::stream_decompressor::is_supported() && response.headers().match(web::http::header_names::content_encoding, encoding)) + { + auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(encoding); + + if (alg != web::http::details::compression::compression_algorithm::invalid) + { + p_request_context->decompressor = std::make_unique(alg); + } + else + { + utility::string_t error = U("Unsupported compression algorithm in the Content Encoding header: "); + error += encoding; + p_request_context->report_exception(http_exception(error)); + } + } + // Signal that the headers are available. p_request_context->complete_headers(); @@ -1159,12 +1184,21 @@ class winhttp_client : public _http_client_communicator case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE : { // Status information contains pointer to DWORD containing number of bytes available. - DWORD num_bytes = *(PDWORD)statusInfo; + const DWORD num_bytes = *(PDWORD)statusInfo; if(num_bytes > 0) { - auto writebuf = p_request_context->_get_writebuffer(); - p_request_context->allocate_reply_space(writebuf.alloc(num_bytes), num_bytes); + if (p_request_context->decompressor) + { + // Decompression is too slow to reliably do on this callback. Therefore we need to store it now in order to decompress it at a later stage in the flow. + // However, we want to eventually use the writebuf to store the decompressed body. Therefore we'll store the compressed body as an internal allocation in the request_context + p_request_context->allocate_reply_space(nullptr, num_bytes); + } + else + { + auto writebuf = p_request_context->_get_writebuffer(); + p_request_context->allocate_reply_space(writebuf.alloc(num_bytes), num_bytes); + } // Read in body all at once. if(!WinHttpReadData( @@ -1198,7 +1232,7 @@ class winhttp_client : public _http_client_communicator case WINHTTP_CALLBACK_STATUS_READ_COMPLETE : { // Status information length contains the number of bytes read. - const DWORD bytesRead = statusInfoLength; + DWORD bytesRead = statusInfoLength; // Report progress about downloaded bytes. auto progress = p_request_context->m_request._get_impl()->_progress_handler(); @@ -1220,9 +1254,39 @@ class winhttp_client : public _http_client_communicator break; } + auto writebuf = p_request_context->_get_writebuffer(); + + // If we have compressed data it is stored in the local allocation of the p_request_context. We will store the decompressed buffer in the external allocation of the p_request_context. + if (p_request_context->decompressor) + { + web::http::details::compression::data_buffer decompressed = p_request_context->decompressor->decompress(p_request_context->m_body_data.get(), bytesRead); + + if (p_request_context->decompressor->has_error()) + { + p_request_context->report_exception(std::runtime_error("Failed to decompress the response body")); + return; + } + + // We've decompressed this chunk of the body, need to now store it in the writebuffer. + auto decompressed_size = decompressed.size(); + + if (decompressed_size > 0) + { + auto p = writebuf.alloc(decompressed_size); + p_request_context->allocate_reply_space(p, decompressed_size); + std::memcpy(p_request_context->m_body_data.get(), &decompressed[0], decompressed_size); + + bytesRead = decompressed_size; + } + else + { + p_request_context->report_exception(std::runtime_error("Failed to decompress the response body, empty decompression result")); + return; + } + } + // If the data was allocated directly from the buffer then commit, otherwise we still // need to write to the response stream buffer. - auto writebuf = p_request_context->_get_writebuffer(); if (p_request_context->is_externally_allocated()) { writebuf.commit(bytesRead); diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index a80f2ad1bf..55a5cfb400 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -25,6 +25,10 @@ #include "stdafx.h" +#if defined(CPPREST_HTTP_COMPRESSION) +#include +#endif + using namespace web; using namespace utility; using namespace utility::conversions; @@ -427,5 +431,313 @@ bool validate_method(const utility::string_t& method) } #endif +namespace compression +{ +#if defined(CPPREST_HTTP_COMPRESSION) + + class compression_base_impl + { + public: + compression_base_impl(compression_algorithm alg) : m_alg(alg), m_zLibState(Z_OK) + { + memset(&m_zLibStream, 0, sizeof(m_zLibStream)); + } + + size_t read_output(size_t input_offset, size_t available_input, size_t total_out_before, uint8_t* temp_buffer, data_buffer& output) + { + input_offset += (available_input - stream().avail_in); + auto out_length = stream().total_out - total_out_before; + output.insert(output.end(), temp_buffer, temp_buffer + out_length); + + return input_offset; + } + + bool is_complete() const + { + return state() == Z_STREAM_END; + } + + bool has_error() const + { + return !is_complete() && state() != Z_OK; + } + + int state() const + { + return m_zLibState; + } + + void set_state(int state) + { + m_zLibState = state; + } + + compression_algorithm algorithm() const + { + return m_alg; + } + + z_stream& stream() + { + return m_zLibStream; + } + + int to_zlib_alg(compression_algorithm alg) + { + return static_cast(alg); + } + + private: + const compression_algorithm m_alg; + + std::atomic m_zLibState{ Z_OK }; + z_stream m_zLibStream; + }; + + class stream_decompressor::stream_decompressor_impl : public compression_base_impl + { + public: + stream_decompressor_impl(compression_algorithm alg) : compression_base_impl(alg) + { + set_state(inflateInit2(&stream(), to_zlib_alg(alg))); + } + + ~stream_decompressor_impl() + { + inflateEnd(&stream()); + } + + data_buffer decompress(const uint8_t* input, size_t input_size) + { + if (input == nullptr || input_size == 0) + { + set_state(Z_BUF_ERROR); + return data_buffer(); + } + + // Need to guard against attempting to decompress when we're already finished or encountered an error! + if (is_complete() || has_error()) + { + set_state(Z_STREAM_ERROR); + return data_buffer(); + } + + const size_t BUFFER_SIZE = 1024; + unsigned char temp_buffer[BUFFER_SIZE]; + + data_buffer output; + output.reserve(input_size * 3); + + size_t input_offset{ 0 }; + + while (state() == Z_OK && input_offset < input_size) + { + auto total_out_before = stream().total_out; + + auto available_input = input_size - input_offset; + stream().next_in = const_cast(&input[input_offset]); + stream().avail_in = static_cast(available_input); + stream().next_out = temp_buffer; + stream().avail_out = BUFFER_SIZE; + + set_state(inflate(&stream(), Z_PARTIAL_FLUSH)); + + if (has_error()) + { + return data_buffer(); + } + + input_offset = read_output(input_offset, available_input, total_out_before, temp_buffer, output); + } + + return output; + } + }; + + class stream_compressor::stream_compressor_impl : public compression_base_impl + { + public: + stream_compressor_impl(compression_algorithm alg) : compression_base_impl(alg) + { + const int level = Z_DEFAULT_COMPRESSION; + if (alg == compression_algorithm::gzip) + { + const auto windowBits = 15; + const auto gzip_encoding = 16; + + set_state(deflateInit2(&stream(), level, Z_DEFLATED, to_zlib_alg(alg), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)); + } + else if (alg == compression_algorithm::deflate) + { + set_state(deflateInit(&stream(), level)); + } + } + + web::http::details::compression::data_buffer compress(const uint8_t* input, size_t input_size, bool finish) + { + if (input == nullptr || input_size == 0) + { + set_state(Z_BUF_ERROR); + return data_buffer(); + } + + if (state() != Z_OK) + { + set_state(Z_STREAM_ERROR); + return data_buffer(); + } + + data_buffer output; + output.reserve(input_size); + + const size_t BUFFER_SIZE = 1024; + uint8_t temp_buffer[BUFFER_SIZE]; + + size_t input_offset{ 0 }; + auto flush = Z_NO_FLUSH; + + while (flush == Z_NO_FLUSH) + { + auto total_out_before = stream().total_out; + auto available_input = input_size - input_offset; + + if (available_input == 0) + { + flush = finish ? Z_FINISH : Z_PARTIAL_FLUSH; + } + else + { + stream().avail_in = static_cast(available_input); + stream().next_in = const_cast(&input[input_offset]); + } + + do + { + stream().next_out = temp_buffer; + stream().avail_out = BUFFER_SIZE; + + set_state(deflate(&stream(), flush)); + + if (has_error()) + { + return data_buffer(); + } + + input_offset = read_output(input_offset, available_input, total_out_before, temp_buffer, output); + + } while (stream().avail_out == 0); + } + + return output; + } + + ~stream_compressor_impl() + { + deflateEnd(&stream()); + } + }; +#else // Stub impl for when compression is not supported + + class compression_base_impl + { + public: + bool has_error() const + { + return false; + } + }; + + class stream_compressor::stream_compressor_impl : public compression_base_impl + { + public: + stream_compressor::stream_compressor_impl(compression_algorithm) {} + compression::data_buffer compress(const uint8_t*, size_t, bool) + { + return compression::data_buffer(); + } + }; + + class stream_decompressor::stream_decompressor_impl : public compression_base_impl + { + public: + stream_decompressor::stream_decompressor_impl(compression_algorithm) {} + compression::data_buffer decompress(const uint8_t*, size_t) { + return compression::data_buffer(); + } + }; +#endif + + stream_decompressor::stream_decompressor(compression_algorithm alg) + : m_pimpl(std::make_shared(alg)) + { + } + + compression::data_buffer stream_decompressor::decompress(const data_buffer& input) + { + if (input.empty() || !m_pimpl) + { + return data_buffer(); + } + + return m_pimpl->decompress(&input[0], input.size()); + } + + web::http::details::compression::data_buffer stream_decompressor::decompress(const uint8_t* input, size_t input_size) + { + if (!m_pimpl) + { + return data_buffer(); + } + + return m_pimpl->decompress(input, input_size); + } + + bool stream_decompressor::has_error() const + { + if (!m_pimpl) + { + return true; + } + + return m_pimpl->has_error(); + } + + stream_compressor::stream_compressor(compression_algorithm alg) + : m_pimpl(std::make_shared(alg)) + { + + } + + compression::data_buffer stream_compressor::compress(const data_buffer& input, bool finish) + { + if (input.empty() || !m_pimpl) + { + return compression::data_buffer(); + } + + return m_pimpl->compress(&input[0], input.size(), finish); + } + + web::http::details::compression::data_buffer stream_compressor::compress(const uint8_t* input, size_t input_size, bool finish) + { + if (!m_pimpl) + { + return compression::data_buffer(); + } + + return m_pimpl->compress(input, input_size, finish); + } + + bool stream_compressor::has_error() const + { + if (!m_pimpl) + { + return true; + } + + return m_pimpl->has_error(); + } + +} // namespace compression } // namespace details }} // namespace web::http diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index e0f4498923..ac3610c920 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -63,6 +63,25 @@ TEST_FIXTURE(uri_address, outside_cnn_dot_com) }); } +TEST_FIXTURE(uri_address, outside_google_dot_com_compressed_http_response) +{ + http_client_config config; + config.set_request_compressed_response(true); + + http_client client(U("http://www.google.com"), config); + http_request httpRequest(methods::GET); + + http_response response = client.request(httpRequest).get(); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); + response.content_ready().wait(); + + auto s = response.extract_utf8string().get(); + + std::wstring encoding; + response.headers().match(web::http::header_names::content_encoding, encoding); + VERIFY_ARE_EQUAL(encoding, U("gzip")); +} + TEST_FIXTURE(uri_address, outside_google_dot_com) { http_client client(U("http://www.google.com")); diff --git a/Release/tests/functional/http/client/request_helper_tests.cpp b/Release/tests/functional/http/client/request_helper_tests.cpp index 0e153852ed..aeabf096a9 100644 --- a/Release/tests/functional/http/client/request_helper_tests.cpp +++ b/Release/tests/functional/http/client/request_helper_tests.cpp @@ -28,6 +28,7 @@ #include #include "cpprest/version.h" +#include "cpprest/details/http_helpers.h" using namespace web; using namespace utility; @@ -41,6 +42,55 @@ namespace tests { namespace functional { namespace http { namespace client { SUITE(request_helper_tests) { +TEST_FIXTURE(uri_address, compress_and_decompress) +{ + if (web::http::details::compression::stream_compressor::is_supported()) + { + auto compress_and_decompress = [](web::http::details::compression::compression_algorithm alg) + { + auto compressor = std::make_shared(alg); + auto decompressor = std::make_shared(alg); + + const size_t buffer_size = 100; + const size_t split_pos = buffer_size / 2; + + web::http::details::compression::data_buffer input_buffer; + input_buffer.reserve(buffer_size); + + for (size_t i = 0; i < buffer_size; ++i) + { + input_buffer.push_back(static_cast(i)); + } + + web::http::details::compression::data_buffer buffer1(input_buffer.begin(), input_buffer.begin() + split_pos); + web::http::details::compression::data_buffer buffer2(input_buffer.begin() + split_pos, input_buffer.end()); + + auto compressed_data1 = compressor->compress(buffer1, false); + VERIFY_IS_FALSE(compressed_data1.empty()); + VERIFY_IS_FALSE(compressor->has_error()); + + auto compressed_data2 = compressor->compress(buffer2, true); + VERIFY_IS_FALSE(compressed_data2.empty()); + VERIFY_IS_FALSE(compressor->has_error()); + + auto decompressed_data1 = decompressor->decompress(compressed_data1); + VERIFY_IS_FALSE(decompressed_data1.empty()); + VERIFY_IS_FALSE(decompressor->has_error()); + + auto decompressed_data2 = decompressor->decompress(compressed_data2); + VERIFY_IS_FALSE(decompressed_data2.empty()); + VERIFY_IS_FALSE(decompressor->has_error()); + + decompressed_data1.insert(decompressed_data1.end(), decompressed_data2.begin(), decompressed_data2.end()); + + VERIFY_ARE_EQUAL(input_buffer, decompressed_data1); + }; + + compress_and_decompress(web::http::details::compression::compression_algorithm::gzip); + compress_and_decompress(web::http::details::compression::compression_algorithm::deflate); + } +} + TEST_FIXTURE(uri_address, non_rvalue_bodies) { test_http_server::scoped_server scoped(m_uri); diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln index 1041525211..887d1df119 100644 --- a/cpprestsdk140.sln +++ b/cpprestsdk140.sln @@ -51,19 +51,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRunner.android.NativeAc EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - Release\src\build\win32.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 - Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{3a584d9c-1a98-4046-b7d3-b7171ef42d34}*SharedItemsImports = 4 + Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 + Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 - Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM From f3d03e69a3073e1ce84d8c965e4a293304f4558f Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Wed, 7 Sep 2016 16:25:29 +0100 Subject: [PATCH 136/609] Moving request_compressed_response in http config out of win compile flag --- Release/include/cpprest/http_client.h | 49 ++++++++++--------- .../functional/http/client/outside_tests.cpp | 1 + 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index ebbbe1741e..993d2e4e75 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -94,7 +94,8 @@ class http_client_config http_client_config() : m_guarantee_order(false), m_timeout(std::chrono::seconds(30)), - m_chunksize(0) + m_chunksize(0), + m_request_compressed(false) #if !defined(__cplusplus_winrt) , m_validate_certificates(true) #endif @@ -105,8 +106,8 @@ class http_client_config #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) , m_buffer_request(false) - , m_request_compressed(false) #endif + { } @@ -260,6 +261,27 @@ class http_client_config return m_chunksize == 0; } + /// + /// Checks if requesting a compressed response is turned on, the default is off. + /// + /// True if compressed response is enabled, false otherwise + bool request_compressed_response() const + { + return m_request_compressed; + } + + /// + /// Request that the server responds with a compressed body. + /// If true, in cases where the server does not support compression, this will have no effect. + /// The response body is internally decompressed before the consumer receives the data. + /// + /// True to turn on response body compression, false otherwise. + /// Please note there is a performance cost due to copying the request data. Currently only supported on Windows. + void set_request_compressed_response(bool request_compressed) + { + m_request_compressed = request_compressed; + } + #if !defined(__cplusplus_winrt) /// /// Gets the server certificate validation property. @@ -303,27 +325,6 @@ class http_client_config { m_buffer_request = buffer_request; } - - /// - /// Checks if requesting a compressed response is turned on, the default is off. - /// - /// True if compressed response is enabled, false otherwise - bool request_compressed_response() const - { - return m_request_compressed; - } - - /// - /// Request that the server responds with a compressed body. - /// If true, in cases where the server does not support compression, this will have no effect. - /// The response body is internally decompressed before the consumer receives the data. - /// - /// True to turn on response body compression, false otherwise. - /// Please note there is a performance cost due to copying the request data. - void set_request_compressed_response(bool request_compressed) - { - m_request_compressed = request_compressed; - } #endif #endif @@ -404,6 +405,7 @@ class http_client_config std::chrono::microseconds m_timeout; size_t m_chunksize; + bool m_request_compressed; #if !defined(__cplusplus_winrt) // IXmlHttpRequest2 doesn't allow configuration of certificate verification. @@ -418,7 +420,6 @@ class http_client_config #endif #if defined(_WIN32) && !defined(__cplusplus_winrt) bool m_buffer_request; - bool m_request_compressed; #endif }; diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index ac3610c920..86d2257bdb 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -76,6 +76,7 @@ TEST_FIXTURE(uri_address, outside_google_dot_com_compressed_http_response) response.content_ready().wait(); auto s = response.extract_utf8string().get(); + VERIFY_IS_FALSE(s.empty()); std::wstring encoding; response.headers().match(web::http::header_names::content_encoding, encoding); From ae792c762c6c0a5f6f936d4c6f6896e36bbfe13f Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Mon, 12 Sep 2016 12:55:01 +0100 Subject: [PATCH 137/609] Adding support for HTTP compression on OSX --- Release/CMakeLists.txt | 483 +++++++++--------- .../include/cpprest/details/http_helpers.h | 7 +- Release/include/cpprest/http_client.h | 4 +- Release/src/CMakeLists.txt | 1 + Release/src/http/client/http_client_asio.cpp | 115 ++++- .../src/http/client/http_client_winhttp.cpp | 11 +- Release/src/http/common/http_helpers.cpp | 42 +- .../functional/http/client/outside_tests.cpp | 9 +- 8 files changed, 378 insertions(+), 294 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index d99fa5c877..a6020e89ef 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -1,234 +1,249 @@ -set(CMAKE_LEGACY_CYGWIN_WIN32 0) -cmake_minimum_required(VERSION 2.6) -project(casablanca) - -enable_testing() - -set(WARNINGS) -set(ANDROID_STL_FLAGS) - -# Platform (not compiler) specific settings -if(IOS) - set(IOS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Build_iOS") - set(Boost_FRAMEWORK "-F ${IOS_SOURCE_DIR} -framework boost") - set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers") - - set(OPENSSL_FOUND 1) - set(OPENSSL_INCLUDE_DIR "${IOS_SOURCE_DIR}/openssl/include") - set(OPENSSL_LIBRARIES - "${IOS_SOURCE_DIR}/openssl/lib/libcrypto.a" - "${IOS_SOURCE_DIR}/openssl/lib/libssl.a" - ) - - # The cxx_flags must be reset here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag. - set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden") - - set(BUILD_SHARED_LIBS OFF) - set(BUILD_SAMPLES OFF) - option(BUILD_TESTS "Build tests." ON) -elseif(ANDROID) - set(Boost_COMPILER "-clang") - set(Boost_USE_STATIC_LIBS ON) - if(ARM) - set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android/build") - set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/lib") - else() - set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build") - set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build/lib") - endif() - find_host_package(Boost 1.55 EXACT REQUIRED COMPONENTS random system thread filesystem chrono atomic) - - set(OPENSSL_FOUND 1) - if(ARM) - set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/include") - set(OPENSSL_LIBRARIES - "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libssl.a" - "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libcrypto.a" - ) - else() - set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/x86/include") - set(OPENSSL_LIBRARIES - "${CMAKE_BINARY_DIR}/../openssl/x86/lib/libssl.a" - "${CMAKE_BINARY_DIR}/../openssl/x86/lib/libcrypto.a" - ) - endif() - - if(ARM) - set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/thumb/libgnustl_static.a") - else() - set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/libgnustl_static.a") - endif() - # These are used in the shared library case - set(ANDROID_STL_FLAGS - ${LIBCXX_STL} - atomic - dl - gcc - c - m - -nodefaultlibs - ) - - option(BUILD_SHARED_LIBS "Build shared Libraries." OFF) - set(BUILD_SAMPLES OFF) - option(BUILD_TESTS "Build tests." ON) -elseif(UNIX) # This includes OSX - find_package(Boost REQUIRED COMPONENTS random chrono system thread regex filesystem) - find_package(Threads REQUIRED) - if(APPLE AND NOT OPENSSL_ROOT_DIR) - # Prefer a homebrew version of OpenSSL over the one in /usr/lib - file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl/*) - # Prefer the latest (make the latest one first) - list(REVERSE OPENSSL_ROOT_DIR) - endif() - # This should prevent linking against the system provided 0.9.8y - set(_OPENSSL_VERSION "") - find_package(OpenSSL 1.0.0 REQUIRED) - - option(BUILD_SHARED_LIBS "Build shared Libraries." ON) - option(BUILD_TESTS "Build tests." ON) - option(BUILD_SAMPLES "Build samples." ON) - option(CASA_INSTALL_HEADERS "Install header files." ON) - if(CASA_INSTALL_HEADERS) - file(GLOB CASA_HEADERS_CPPREST include/cpprest/*.hpp include/cpprest/*.h include/cpprest/*.dat) - install(FILES ${CASA_HEADERS_CPPREST} DESTINATION include/cpprest) - file(GLOB CASA_HEADERS_PPLX include/pplx/*.hpp include/pplx/*.h) - install(FILES ${CASA_HEADERS_PPLX} DESTINATION include/pplx) - file(GLOB CASA_HEADERS_DETAILS include/cpprest/details/*.hpp include/cpprest/details/*.h include/cpprest/details/*.dat) - install(FILES ${CASA_HEADERS_DETAILS} DESTINATION include/cpprest/details) - endif() -elseif(WIN32) - option(BUILD_SHARED_LIBS "Build shared Libraries." ON) - option(BUILD_TESTS "Build tests." ON) - option(BUILD_SAMPLES "Build samples." ON) - option(CPPREST_EXCLUDE_WEBSOCKETS "Exclude websockets functionality." OFF) - option(Boost_USE_STATIC_LIBS ON) - - add_definitions(-DUNICODE -D_UNICODE) - - if(NOT BUILD_SHARED_LIBS) - # This causes cmake to not link the test libraries separately, but instead hold onto their object files. - set(TEST_LIBRARY_TARGET_TYPE OBJECT) - set(Casablanca_DEFINITIONS -D_NO_ASYNCRTIMP -D_NO_PPLXIMP CACHE INTERNAL "Definitions for consume casablanca library") - else() - set(Casablanca_DEFINITIONS "" CACHE INTERNAL "Definitions for consume casablanca library") - endif() - add_definitions(${Casablanca_DEFINITIONS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -DWIN32) - - if (CPPREST_EXCLUDE_WEBSOCKETS) - add_definitions(-DCPPREST_EXCLUDE_WEBSOCKETS=1) - else() - find_package(Boost 1.55 REQUIRED COMPONENTS random system thread filesystem chrono atomic) - find_package(OpenSSL 1.0 REQUIRED) - endif() -else() - message(FATAL_ERROR "-- Unsupported Build Platform.") -endif() - -# Compiler (not platform) specific settings -if(ANDROID) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith") - include_directories( - "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include" - "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include" - "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include/backward" - ) -elseif((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR IOS) - message("-- Setting clang options") - - set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") - set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs") - set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") - set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") - set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") -elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - message("-- Setting gcc options") - - set(WARNINGS "-Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code") - - set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") -elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - message("-- Setting msvc options") - set(WARNINGS) -else() - message("-- Unknown compiler, success is doubtful.") - message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}") -endif() - -# Reconfigure final output directory -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) - -# These settings can be used by the test targets -set(Casablanca_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) -if (NOT CPPREST_EXCLUDE_WEBSOCKETS) - find_path(WEBSOCKETPP_CONFIG websocketpp-config.cmake - HINTS /usr/lib/cmake/websocketpp) - find_path(WEBSOCKETPP_CONFIG_VERSION websocketpp-configVersion.cmake - HINTS /usr/lib/cmake/websocketpp) - if(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) - include(${WEBSOCKETPP_CONFIG}/websocketpp-config.cmake) - include(${WEBSOCKETPP_CONFIG}/websocketpp-configVersion.cmake) - message("-- Found websocketpp version " ${PACKAGE_VERSION} " on system") - set(Casablanca_INCLUDE_DIRS ${Casablanca_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${WEBSOCKETPP_INCLUDE_DIR}) - else(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) - set(Casablanca_INCLUDE_DIRS ${Casablanca_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp) - message("-- websocketpp not found, using the embedded version") - endif(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) -else() - set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) -endif() - -set(Casablanca_LIBRARY ${LIB}cpprest) -set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} - ${Boost_SYSTEM_LIBRARY} - ${Boost_THREAD_LIBRARY} - ${Boost_ATOMIC_LIBRARY} - ${Boost_CHRONO_LIBRARY} - ${Boost_RANDOM_LIBRARY} - ${Boost_REGEX_LIBRARY} - ${Boost_FRAMEWORK}) - -# Everything in the project needs access to the casablanca include directories -include_directories(${Casablanca_INCLUDE_DIRS}) - -# Finally, the tests all use the same style declaration to build themselves, so we use a function -function(add_casablanca_test NAME SOURCES_VAR) - add_library(${NAME} ${TEST_LIBRARY_TARGET_TYPE} ${${SOURCES_VAR}}) - message("-- Added test library ${NAME}") - if (NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") - target_link_libraries(${NAME} - ${LIB}httptest_utilities - ${LIB}common_utilities - ${LIB}unittestpp - ${Casablanca_LIBRARIES} - ${ANDROID_STL_FLAGS} - ) - if (BUILD_SHARED_LIBS) - add_test(NAME ${NAME} - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - COMMAND test_runner lib${NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} - ) - endif() - endif() -endfunction() - -add_subdirectory(src) - -if(BUILD_TESTS) - add_subdirectory(tests) -endif() - -if(BUILD_SAMPLES) - add_subdirectory(samples) -endif() +set(CMAKE_LEGACY_CYGWIN_WIN32 0) +cmake_minimum_required(VERSION 2.6) +project(casablanca) + +enable_testing() + +set(WARNINGS) +set(ANDROID_STL_FLAGS) + +# Platform (not compiler) specific settings +if(IOS) + set(IOS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Build_iOS") + set(Boost_FRAMEWORK "-F ${IOS_SOURCE_DIR} -framework boost") + set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers") + + set(OPENSSL_FOUND 1) + set(OPENSSL_INCLUDE_DIR "${IOS_SOURCE_DIR}/openssl/include") + set(OPENSSL_LIBRARIES + "${IOS_SOURCE_DIR}/openssl/lib/libcrypto.a" + "${IOS_SOURCE_DIR}/openssl/lib/libssl.a" + ) + + # The cxx_flags must be reset here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag. + set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden") + + set(BUILD_SHARED_LIBS OFF) + set(BUILD_SAMPLES OFF) + option(BUILD_TESTS "Build tests." ON) +elseif(ANDROID) + set(Boost_COMPILER "-clang") + set(Boost_USE_STATIC_LIBS ON) + if(ARM) + set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android/build") + set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/lib") + else() + set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build") + set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build/lib") + endif() + find_host_package(Boost 1.55 EXACT REQUIRED COMPONENTS random system thread filesystem chrono atomic) + + set(OPENSSL_FOUND 1) + if(ARM) + set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/include") + set(OPENSSL_LIBRARIES + "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libssl.a" + "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libcrypto.a" + ) + else() + set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/x86/include") + set(OPENSSL_LIBRARIES + "${CMAKE_BINARY_DIR}/../openssl/x86/lib/libssl.a" + "${CMAKE_BINARY_DIR}/../openssl/x86/lib/libcrypto.a" + ) + endif() + + if(ARM) + set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/thumb/libgnustl_static.a") + else() + set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/libgnustl_static.a") + endif() + # These are used in the shared library case + set(ANDROID_STL_FLAGS + ${LIBCXX_STL} + atomic + dl + gcc + c + m + -nodefaultlibs + ) + + option(BUILD_SHARED_LIBS "Build shared Libraries." OFF) + set(BUILD_SAMPLES OFF) + option(BUILD_TESTS "Build tests." ON) +elseif(UNIX) # This includes OSX + find_package(Boost REQUIRED COMPONENTS random chrono system thread regex filesystem) + + find_package(Threads REQUIRED) + if(APPLE AND NOT OPENSSL_ROOT_DIR) + # Prefer a homebrew version of OpenSSL over the one in /usr/lib + file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl/*) + # Prefer the latest (make the latest one first) + list(REVERSE OPENSSL_ROOT_DIR) + endif() + # This should prevent linking against the system provided 0.9.8y + set(_OPENSSL_VERSION "") + find_package(OpenSSL 1.0.0 REQUIRED) + + option(BUILD_SHARED_LIBS "Build shared Libraries." ON) + + # Prefer the homebrew version of zlib + find_library(ZLIB_LIBRARIES NAMES libz.a PATHS /usr/local/Cellar/zlib/1.2.8/lib NO_DEFAULT_PATH) + find_path(ZLIB_INCLUDE_DIRS NAMES zlib.h PATHS /usr/local/Cellar/zlib/1.2.8/include NO_DEFAULT_PATH) + + if(NOT ZLIB_LIBRARIES OR NOT ZLIB_INCLUDE_DIRS) + find_package(ZLib) + if(NOT ZLIB_FOUND) + option(CPPREST_EXCLUDE_COMPRESSION "Exclude compression functionality." ON) + endif() + endif() + + option(BUILD_TESTS "Build tests." ON) + option(BUILD_SAMPLES "Build samples." ON) + option(CASA_INSTALL_HEADERS "Install header files." ON) + if(CASA_INSTALL_HEADERS) + file(GLOB CASA_HEADERS_CPPREST include/cpprest/*.hpp include/cpprest/*.h include/cpprest/*.dat) + install(FILES ${CASA_HEADERS_CPPREST} DESTINATION include/cpprest) + file(GLOB CASA_HEADERS_PPLX include/pplx/*.hpp include/pplx/*.h) + install(FILES ${CASA_HEADERS_PPLX} DESTINATION include/pplx) + file(GLOB CASA_HEADERS_DETAILS include/cpprest/details/*.hpp include/cpprest/details/*.h include/cpprest/details/*.dat) + install(FILES ${CASA_HEADERS_DETAILS} DESTINATION include/cpprest/details) + endif() +elseif(WIN32) + option(BUILD_SHARED_LIBS "Build shared Libraries." ON) + option(BUILD_TESTS "Build tests." ON) + option(BUILD_SAMPLES "Build samples." ON) + option(CPPREST_EXCLUDE_WEBSOCKETS "Exclude websockets functionality." OFF) + option(Boost_USE_STATIC_LIBS ON) + + add_definitions(-DUNICODE -D_UNICODE) + + if(NOT BUILD_SHARED_LIBS) + # This causes cmake to not link the test libraries separately, but instead hold onto their object files. + set(TEST_LIBRARY_TARGET_TYPE OBJECT) + set(Casablanca_DEFINITIONS -D_NO_ASYNCRTIMP -D_NO_PPLXIMP CACHE INTERNAL "Definitions for consume casablanca library") + else() + set(Casablanca_DEFINITIONS "" CACHE INTERNAL "Definitions for consume casablanca library") + endif() + add_definitions(${Casablanca_DEFINITIONS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -DWIN32) + + if (CPPREST_EXCLUDE_WEBSOCKETS) + add_definitions(-DCPPREST_EXCLUDE_WEBSOCKETS=1) + else() + find_package(Boost 1.55 REQUIRED COMPONENTS random system thread filesystem chrono atomic) + find_package(OpenSSL 1.0 REQUIRED) + endif() +else() + message(FATAL_ERROR "-- Unsupported Build Platform.") +endif() + +# Compiler (not platform) specific settings +if(ANDROID) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith") + include_directories( + "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include" + "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include" + "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include/backward" + ) +elseif((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR IOS) + message("-- Setting clang options") + + set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") + set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs") + set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + message("-- Setting gcc options") + + set(WARNINGS "-Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code") + + set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") +elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + message("-- Setting msvc options") + set(WARNINGS) +else() + message("-- Unknown compiler, success is doubtful.") + message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}") +endif() + +# Reconfigure final output directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) + +# These settings can be used by the test targets +set(Casablanca_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) +if (NOT CPPREST_EXCLUDE_WEBSOCKETS) + find_path(WEBSOCKETPP_CONFIG websocketpp-config.cmake + HINTS /usr/lib/cmake/websocketpp) + find_path(WEBSOCKETPP_CONFIG_VERSION websocketpp-configVersion.cmake + HINTS /usr/lib/cmake/websocketpp) + if(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) + include(${WEBSOCKETPP_CONFIG}/websocketpp-config.cmake) + include(${WEBSOCKETPP_CONFIG}/websocketpp-configVersion.cmake) + message("-- Found websocketpp version " ${PACKAGE_VERSION} " on system") + set(Casablanca_INCLUDE_DIRS ${Casablanca_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${WEBSOCKETPP_INCLUDE_DIR}) + else(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) + set(Casablanca_INCLUDE_DIRS ${Casablanca_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp) + message("-- websocketpp not found, using the embedded version") + endif(WEBSOCKETPP_CONFIG AND WEBSOCKETPP_CONFIG_VERSION) +else() + set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) +endif() + +set(Casablanca_LIBRARY ${LIB}cpprest) +set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_ATOMIC_LIBRARY} + ${Boost_CHRONO_LIBRARY} + ${Boost_RANDOM_LIBRARY} + ${Boost_REGEX_LIBRARY} + ${Boost_FRAMEWORK} + ${ZLIB_LIBRARIES} + ) + +# Everything in the project needs access to the casablanca include directories +include_directories(${Casablanca_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS}) + +# Finally, the tests all use the same style declaration to build themselves, so we use a function +function(add_casablanca_test NAME SOURCES_VAR) + add_library(${NAME} ${TEST_LIBRARY_TARGET_TYPE} ${${SOURCES_VAR}}) + message("-- Added test library ${NAME}") + if (NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") + target_link_libraries(${NAME} + ${LIB}httptest_utilities + ${LIB}common_utilities + ${LIB}unittestpp + ${Casablanca_LIBRARIES} + ${ANDROID_STL_FLAGS} + ) + if (BUILD_SHARED_LIBS) + add_test(NAME ${NAME} + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMAND test_runner lib${NAME}${CMAKE_SHARED_LIBRARY_SUFFIX} + ) + endif() + endif() +endfunction() + +add_subdirectory(src) + +if(BUILD_TESTS) + add_subdirectory(tests) +endif() + +if(BUILD_SAMPLES) + add_subdirectory(samples) +endif() diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index bf9dc7486e..a19daedb24 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -27,8 +27,13 @@ ****/ #pragma once +#if __APPLE__ + #include "TargetConditionals.h" +#endif + +// CPPREST_EXCLUDE_COMPRESSION is set if we're on a platform that supports compression but we want to explicitly disable it. // CPPREST_EXCLUDE_WEBSOCKETS is a flag that now essentially means "no external dependencies". TODO: Rename -#if defined(_WIN32) && !defined(CPPREST_EXCLUDE_WEBSOCKETS) +#if (defined(_WIN32) || defined(TARGET_OS_MAC)) && !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) #define CPPREST_HTTP_COMPRESSION #endif diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 993d2e4e75..e86c99e5db 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -275,8 +275,8 @@ class http_client_config /// If true, in cases where the server does not support compression, this will have no effect. /// The response body is internally decompressed before the consumer receives the data. /// - /// True to turn on response body compression, false otherwise. - /// Please note there is a performance cost due to copying the request data. Currently only supported on Windows. + /// True to turn on response body compression, false otherwise. + /// Please note there is a performance cost due to copying the request data. Currently only supported on Windows and OSX. void set_request_compressed_response(bool request_compressed) { m_request_compressed = request_compressed; diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index fd1df86e40..eabad87002 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -95,6 +95,7 @@ target_link_libraries(${Casablanca_LIBRARY} ${OPENSSL_LIBRARIES} ${COREFOUNDATION} ${ANDROID_STL_FLAGS} + ${ZLIB_LIBRARIES} ) # Portions specific to cpprest binary versioning. diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 44296040e0..abc629d808 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -45,7 +45,9 @@ #include "cpprest/details/http_client_impl.h" #include "cpprest/details/x509_cert_utilities.h" +#include "cpprest/details/http_helpers.h" #include +#include using boost::asio::ip::tcp; @@ -630,6 +632,17 @@ class asio_context : public request_context, public std::enable_shared_from_this { extra_headers.append(ctx->generate_basic_proxy_auth_header()); } + + // Add the header needed to request a compressed response if supported on this platform and it has been specified in the config + if (web::http::details::compression::stream_decompressor::is_supported() && ctx->m_http_client->client_config().request_compressed_response()) + { + utility::string_t accept_encoding_header; + accept_encoding_header.append(header_names::accept_encoding); + accept_encoding_header.append(": deflate, gzip"); + accept_encoding_header.append(CRLF); + + extra_headers.append(accept_encoding_header); + } // Check user specified transfer-encoding. std::string transferencoding; @@ -1140,7 +1153,7 @@ class asio_context : public request_context, public std::enable_shared_from_this // to respond using 'Connection: Keep-Alive' every time. m_connection->set_keep_alive(!boost::iequals(value, U("close"))); } - + m_response.headers().add(std::move(name), std::move(value)); } } @@ -1148,6 +1161,23 @@ class asio_context : public request_context, public std::enable_shared_from_this m_content_length = std::numeric_limits::max(); // Without Content-Length header, size should be same as TCP stream - set it size_t max. m_response.headers().match(header_names::content_length, m_content_length); + + utility::string_t content_encoding; + if(m_response.headers().match(header_names::content_encoding, content_encoding)) + { + auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(content_encoding); + + if (alg != web::http::details::compression::compression_algorithm::invalid) + { + m_decompressor = utility::details::make_unique(alg); + } + else + { + utility::string_t error = U("Unsupported compression algorithm in the Content Encoding header: "); + error += content_encoding; + report_exception(std::runtime_error(error)); + } + } // note: need to check for 'chunked' here as well, azure storage sends both // transfer-encoding:chunked and content-length:0 (although HTTP says not to) @@ -1316,25 +1346,78 @@ class asio_context : public request_context, public std::enable_shared_from_this { // more data need to be read const auto this_request = shared_from_this(); - writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), - static_cast(std::min(static_cast(m_body_buf.size()), m_content_length - m_downloaded))) - .then([this_request](pplx::task op) + + auto read_size = static_cast(std::min(static_cast(m_body_buf.size()), m_content_length - m_downloaded)); + + if(m_decompressor) { - size_t writtenSize = 0; - try + auto decompressed = m_decompressor->decompress(boost::asio::buffer_cast(m_body_buf.data()), read_size); + + if (m_decompressor->has_error()) { - writtenSize = op.get(); - this_request->m_downloaded += static_cast(writtenSize); - this_request->m_body_buf.consume(writtenSize); - this_request->async_read_until_buffersize(static_cast(std::min(static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), - boost::bind(&asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); + this_request->report_exception(std::runtime_error("Failed to decompress the response body")); + return; } - catch (...) + + // It is valid for the decompressor to sometimes return an empty output for a given chunk, the data will be flushed when the next chunk is received + if (decompressed.empty()) { - this_request->report_exception(std::current_exception()); - return; + try + { + this_request->m_downloaded += static_cast(read_size); + + this_request->async_read_until_buffersize(static_cast(std::min(static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), + boost::bind(&asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } + } + else + { + writeBuffer.putn(&decompressed[0], decompressed.size()) + .then([this_request, read_size](pplx::task op) + { + size_t writtenSize = 0; + try + { + writtenSize = op.get(); + this_request->m_downloaded += static_cast(read_size); + this_request->m_body_buf.consume(writtenSize); + this_request->async_read_until_buffersize(static_cast(std::min(static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), + boost::bind(&asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } + }); } - }); + } + else + { + writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), read_size) + .then([this_request](pplx::task op) + { + size_t writtenSize = 0; + try + { + writtenSize = op.get(); + this_request->m_downloaded += static_cast(writtenSize); + this_request->m_body_buf.consume(writtenSize); + this_request->async_read_until_buffersize(static_cast(std::min(static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), + boost::bind(&asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } + }); + } } else { @@ -1439,6 +1522,8 @@ class asio_context : public request_context, public std::enable_shared_from_this timeout_timer m_timer; boost::asio::streambuf m_body_buf; std::shared_ptr m_connection; + + std::unique_ptr m_decompressor; #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) bool m_openssl_failed; diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index a779a4d36a..9ca40c4313 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -1275,14 +1275,11 @@ class winhttp_client : public _http_client_communicator auto p = writebuf.alloc(decompressed_size); p_request_context->allocate_reply_space(p, decompressed_size); std::memcpy(p_request_context->m_body_data.get(), &decompressed[0], decompressed_size); - - bytesRead = decompressed_size; - } - else - { - p_request_context->report_exception(std::runtime_error("Failed to decompress the response body, empty decompression result")); - return; } + // Note, some servers seem to send a first chunk of body data that decompresses to nothing but initializes the zlib decryption state. This produces no decompressed output. + // Subsequent chunks will then begin emmiting decompressed body data. + + bytesRead = decompressed_size; } // If the data was allocated directly from the buffer then commit, otherwise we still diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index 55a5cfb400..763b2146ba 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -26,7 +26,9 @@ #include "stdafx.h" #if defined(CPPREST_HTTP_COMPRESSION) + #include + #endif using namespace web; @@ -562,9 +564,6 @@ namespace compression const int level = Z_DEFAULT_COMPRESSION; if (alg == compression_algorithm::gzip) { - const auto windowBits = 15; - const auto gzip_encoding = 16; - set_state(deflateInit2(&stream(), level, Z_DEFLATED, to_zlib_alg(alg), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)); } else if (alg == compression_algorithm::deflate) @@ -643,26 +642,27 @@ namespace compression public: bool has_error() const { - return false; + throw std::runtime_error("Compression/Decompression has not been implemented or configured on this platform"); } }; class stream_compressor::stream_compressor_impl : public compression_base_impl { public: - stream_compressor::stream_compressor_impl(compression_algorithm) {} + stream_compressor_impl(compression_algorithm) {} compression::data_buffer compress(const uint8_t*, size_t, bool) { - return compression::data_buffer(); + throw std::runtime_error("Compression is not implemented or configured on this platform"); } }; class stream_decompressor::stream_decompressor_impl : public compression_base_impl { public: - stream_decompressor::stream_decompressor_impl(compression_algorithm) {} - compression::data_buffer decompress(const uint8_t*, size_t) { - return compression::data_buffer(); + stream_decompressor_impl(compression_algorithm) {} + compression::data_buffer decompress(const uint8_t*, size_t) + { + throw std::runtime_error("Decompression is not implemented or configured on this platform"); } }; #endif @@ -674,7 +674,7 @@ namespace compression compression::data_buffer stream_decompressor::decompress(const data_buffer& input) { - if (input.empty() || !m_pimpl) + if (input.empty()) { return data_buffer(); } @@ -684,21 +684,11 @@ namespace compression web::http::details::compression::data_buffer stream_decompressor::decompress(const uint8_t* input, size_t input_size) { - if (!m_pimpl) - { - return data_buffer(); - } - return m_pimpl->decompress(input, input_size); } bool stream_decompressor::has_error() const { - if (!m_pimpl) - { - return true; - } - return m_pimpl->has_error(); } @@ -710,7 +700,7 @@ namespace compression compression::data_buffer stream_compressor::compress(const data_buffer& input, bool finish) { - if (input.empty() || !m_pimpl) + if (input.empty()) { return compression::data_buffer(); } @@ -720,21 +710,11 @@ namespace compression web::http::details::compression::data_buffer stream_compressor::compress(const uint8_t* input, size_t input_size, bool finish) { - if (!m_pimpl) - { - return compression::data_buffer(); - } - return m_pimpl->compress(input, input_size, finish); } bool stream_compressor::has_error() const { - if (!m_pimpl) - { - return true; - } - return m_pimpl->has_error(); } diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 86d2257bdb..89ccadf320 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -63,12 +63,12 @@ TEST_FIXTURE(uri_address, outside_cnn_dot_com) }); } -TEST_FIXTURE(uri_address, outside_google_dot_com_compressed_http_response) +TEST_FIXTURE(uri_address, outside_wikipedia_compressed_http_response) { http_client_config config; config.set_request_compressed_response(true); - http_client client(U("http://www.google.com"), config); + http_client client(U("https://en.wikipedia.org/wiki/HTTP_compression"), config); http_request httpRequest(methods::GET); http_response response = client.request(httpRequest).get(); @@ -77,9 +77,10 @@ TEST_FIXTURE(uri_address, outside_google_dot_com_compressed_http_response) auto s = response.extract_utf8string().get(); VERIFY_IS_FALSE(s.empty()); + + utility::string_t encoding; + VERIFY_IS_TRUE(response.headers().match(web::http::header_names::content_encoding, encoding)); - std::wstring encoding; - response.headers().match(web::http::header_names::content_encoding, encoding); VERIFY_ARE_EQUAL(encoding, U("gzip")); } From 6b70c3f7afa875d955cf520e49e37d7ca8e7eb13 Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Tue, 13 Sep 2016 12:04:35 +0100 Subject: [PATCH 138/609] Fix issue where link time code generation was detecting dead code. --- Release/src/http/common/http_helpers.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index 763b2146ba..b54e3db373 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -642,7 +642,8 @@ namespace compression public: bool has_error() const { - throw std::runtime_error("Compression/Decompression has not been implemented or configured on this platform"); + assert(false); //Compression/Decompression has not been implemented or configured on this platform + return true; } }; @@ -652,7 +653,8 @@ namespace compression stream_compressor_impl(compression_algorithm) {} compression::data_buffer compress(const uint8_t*, size_t, bool) { - throw std::runtime_error("Compression is not implemented or configured on this platform"); + assert(false); //Compression is not implemented or configured on this platform + return{}; } }; @@ -662,7 +664,8 @@ namespace compression stream_decompressor_impl(compression_algorithm) {} compression::data_buffer decompress(const uint8_t*, size_t) { - throw std::runtime_error("Decompression is not implemented or configured on this platform"); + assert(false); //Decompression is not implemented or configured on this platform + return{}; } }; #endif From b0027074d8e4a4ba16b361960e58e88491383b74 Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Tue, 13 Sep 2016 12:17:29 +0100 Subject: [PATCH 139/609] Fix 64bit compile issue --- Release/src/http/client/http_client_winhttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 9ca40c4313..65a9008ea8 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -1279,7 +1279,7 @@ class winhttp_client : public _http_client_communicator // Note, some servers seem to send a first chunk of body data that decompresses to nothing but initializes the zlib decryption state. This produces no decompressed output. // Subsequent chunks will then begin emmiting decompressed body data. - bytesRead = decompressed_size; + bytesRead = static_cast(decompressed_size); } // If the data was allocated directly from the buffer then commit, otherwise we still From 3bcc8ebb73706f8932b1185c1b2b72bbb15716bb Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Thu, 15 Sep 2016 12:19:05 +0100 Subject: [PATCH 140/609] Adding decompression support for chunked encoding on OSX --- Release/src/http/client/http_client_asio.cpp | 64 ++++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index abc629d808..5cc0553da8 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -70,6 +70,7 @@ enum class httpclient_errorcode_context close }; + class asio_connection_pool; class asio_connection { @@ -1163,7 +1164,7 @@ class asio_context : public request_context, public std::enable_shared_from_this m_response.headers().match(header_names::content_length, m_content_length); utility::string_t content_encoding; - if(m_response.headers().match(header_names::content_encoding, content_encoding)) + if(web::http::details::compression::stream_decompressor::is_supported() && m_response.headers().match(header_names::content_encoding, content_encoding)) { auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(content_encoding); @@ -1286,22 +1287,62 @@ class asio_context : public request_context, public std::enable_shared_from_this } else { - auto writeBuffer = _get_writebuffer(); const auto this_request = shared_from_this(); - writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read).then([this_request, to_read](pplx::task op) + auto writeBuffer = _get_writebuffer(); + if(m_decompressor) { - try + + auto decompressed = m_decompressor->decompress(boost::asio::buffer_cast(m_body_buf.data()), to_read); + + if (m_decompressor->has_error()) { - op.wait(); + + report_exception(std::runtime_error("Failed to decompress the response body")); + return; } - catch (...) + + // It is valid for the decompressor to sometimes return an empty output for a given chunk, the data will be flushed when the next chunk is received + if (decompressed.empty()) { - this_request->report_exception(std::current_exception()); - return; + m_body_buf.consume(to_read + CRLF.size()); // consume crlf + m_connection->async_read_until(m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); } - this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf - this_request->m_connection->async_read_until(this_request->m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); - }); + else + { + + writeBuffer.putn(&decompressed[0], decompressed.size()) + .then([this_request, to_read](pplx::task op) + { + try + { + this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf + this_request->m_connection->async_read_until(this_request->m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } + }); + } + } + else + { + writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read).then([this_request, to_read](pplx::task op) + { + try + { + op.wait(); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } + this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf + this_request->m_connection->async_read_until(this_request->m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); + }); + } } } else @@ -1314,6 +1355,7 @@ class asio_context : public request_context, public std::enable_shared_from_this { auto writeBuffer = _get_writebuffer(); + if (ec) { if (ec == boost::asio::error::eof && m_content_length == std::numeric_limits::max()) From 7e6145d8b450c2ac74fd76749db165f80de393d8 Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Thu, 15 Sep 2016 14:53:31 +0100 Subject: [PATCH 141/609] On platforms where compression is not supported, trying to use a compressor or decompressor will throw an exception --- Release/src/http/common/http_helpers.cpp | 28 ++++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index b54e3db373..a83573c146 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -642,7 +642,11 @@ namespace compression public: bool has_error() const { - assert(false); //Compression/Decompression has not been implemented or configured on this platform + //Compression/Decompression has not been implemented or configured on this platform + if (!stream_compressor::is_supported()) + { + throw std::exception(); + } return true; } }; @@ -651,10 +655,15 @@ namespace compression { public: stream_compressor_impl(compression_algorithm) {} - compression::data_buffer compress(const uint8_t*, size_t, bool) + compression::data_buffer compress(const uint8_t* data, size_t size, bool) { - assert(false); //Compression is not implemented or configured on this platform - return{}; + //Compression is not implemented or configured on this platform + if (!stream_compressor::is_supported()) + { + throw std::exception(); + } + + return data_buffer(data, data + size); } }; @@ -662,10 +671,15 @@ namespace compression { public: stream_decompressor_impl(compression_algorithm) {} - compression::data_buffer decompress(const uint8_t*, size_t) + compression::data_buffer decompress(const uint8_t* data, size_t size) { - assert(false); //Decompression is not implemented or configured on this platform - return{}; + //Decompression is not implemented or configured on this platform + if (!stream_decompressor::is_supported()) + { + throw std::exception(); + } + + return data_buffer(data, data + size); } }; #endif From 655dd46f0b7d23a75205fd1ad949f2e30212e39d Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Thu, 15 Sep 2016 14:57:02 +0100 Subject: [PATCH 142/609] Updating exceptions to give an error message --- Release/src/http/common/http_helpers.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index a83573c146..685845949a 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -642,10 +642,9 @@ namespace compression public: bool has_error() const { - //Compression/Decompression has not been implemented or configured on this platform if (!stream_compressor::is_supported()) { - throw std::exception(); + throw std::runtime_error("Compression/Decompression has not been implemented or configured on this platform"); } return true; } @@ -657,10 +656,9 @@ namespace compression stream_compressor_impl(compression_algorithm) {} compression::data_buffer compress(const uint8_t* data, size_t size, bool) { - //Compression is not implemented or configured on this platform if (!stream_compressor::is_supported()) { - throw std::exception(); + throw std::runtime_error("Compression is not implemented or configured on this platform"); } return data_buffer(data, data + size); @@ -673,10 +671,9 @@ namespace compression stream_decompressor_impl(compression_algorithm) {} compression::data_buffer decompress(const uint8_t* data, size_t size) { - //Decompression is not implemented or configured on this platform if (!stream_decompressor::is_supported()) { - throw std::exception(); + throw std::runtime_error("Decompression is not implemented or configured on this platform"); } return data_buffer(data, data + size); From 36713d0dd58d51ae3ea915d40359fe4ae72eb8fb Mon Sep 17 00:00:00 2001 From: Robert Bennett Date: Tue, 20 Sep 2016 01:03:29 -0500 Subject: [PATCH 143/609] =?UTF-8?q?Enable=20TLS=201.1=20and=201.2=20?= =?UTF-8?q?=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default only SSL3 and TLS1 are enabled in Windows 7 and Windows 8. By default only SSL3, TLS1.0, TLS1.1, and TLS1.2 are enabled in Windows 8.1 and Windows 10. https://msdn.microsoft.com/en-us/library/windows/desktop/aa384066 --- Release/src/http/client/http_client_winhttp.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 36f596b937..572803d2cc 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -427,6 +427,14 @@ class winhttp_client : public _http_client_communicator } } #endif + //Enable TLS 1.1 and 1.2 + HRESULT result(S_OK); + BOOL win32_result(FALSE); + + DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2); + win32_result = ::WinHttpSetOption(m_hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols)); + if(FALSE == win32_result){ result = HRESULT_FROM_WIN32(::GetLastError()); } + // Register asynchronous callback. if(WINHTTP_INVALID_STATUS_CALLBACK == WinHttpSetStatusCallback( m_hSession, From 26bf780b4528ebf07f34e65e292a97a9fb7d2de3 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Mon, 26 Sep 2016 10:07:31 -0700 Subject: [PATCH 144/609] Fixes to build with clang 3_8 --- Release/src/build/package_info.xml | 8 ++-- .../casablanca140.android.vcxproj | 12 +++--- .../src/build/vs14.android/packages.config | 14 +++---- .../UnitTestpp140.android.vcxproj | 8 ++-- .../CommonUtilities140.android.vcxproj | 8 ++-- .../HttpClient140_test.android.vcxproj | 8 ++-- .../HttpListener140_test.android.vcxproj | 8 ++-- .../HttpTestUtilities140.android.vcxproj | 8 ++-- .../vs14.android/JSON140_test.android.vcxproj | 8 ++-- .../vs14.android/pplx140_test.android.vcxproj | 8 ++-- .../streams140_test.android.vcxproj | 8 ++-- .../vs14.android/Uri140_test.android.vcxproj | 8 ++-- .../Utils140_test.android.vcxproj | 8 ++-- .../websocketsclient140_test.android.vcxproj | 8 ++-- ...bsockets_test_utilities140.android.vcxproj | 8 ++-- cpprestsdk140.sln | 40 +++++++++++++------ 16 files changed, 93 insertions(+), 77 deletions(-) diff --git a/Release/src/build/package_info.xml b/Release/src/build/package_info.xml index fc3b1d002c..a2f9550b13 100644 --- a/Release/src/build/package_info.xml +++ b/Release/src/build/package_info.xml @@ -1,7 +1,7 @@ cpprestsdk - 2.7.0 + 2.9.0 casablancacore Microsoft, Visual C++ http://www.apache.org/licenses/LICENSE-2.0 @@ -10,7 +10,7 @@ false The C++ REST SDK is a cross-platform, modern, and asynchronous library that enables developers to access and author connected applications. The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services. - https://github.com/Microsoft/cpprestsdk/releases/tag/v2.7.0 + https://github.com/Microsoft/cpprestsdk/releases/tag/v2.9.0 Copyright 2015 cpprestsdk Casablanca REST JSON HTTP URI WebSockets @@ -28,10 +28,10 @@ /d2notypeopt %(AdditionalOptions) CPPREST_TARGET_XP;%(PreprocessorDefinitions) - -funwind-tables %(AdditionalOptions) + -funwind-tables %(AdditionalOptions) - m;%(LibraryDependencies) + m;%(LibraryDependencies) diff --git a/Release/src/build/vs14.android/casablanca140.android.vcxproj b/Release/src/build/vs14.android/casablanca140.android.vcxproj index 6e7d82feaf..6f5ec43ce7 100644 --- a/Release/src/build/vs14.android/casablanca140.android.vcxproj +++ b/Release/src/build/vs14.android/casablanca140.android.vcxproj @@ -34,25 +34,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static @@ -125,14 +125,14 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/src/build/vs14.android/packages.config b/Release/src/build/vs14.android/packages.config index ad9ec48240..746b7f61a2 100644 --- a/Release/src/build/vs14.android/packages.config +++ b/Release/src/build/vs14.android/packages.config @@ -1,11 +1,11 @@  - - - - - - - + + + + + + + \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj index d994188a6f..3804df5f49 100644 --- a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj +++ b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj @@ -103,25 +103,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj index 5ee0a1acc8..984cd33475 100644 --- a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj +++ b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj @@ -54,25 +54,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj index 0ff16c0a20..3b5e3aa321 100644 --- a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj +++ b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj @@ -72,25 +72,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj index 0bae47f684..fbe9edd033 100644 --- a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj +++ b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj @@ -64,25 +64,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj index 4f8db665d9..444640f84d 100644 --- a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj +++ b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj @@ -60,25 +60,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj index a771d56274..6bf397496b 100644 --- a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj +++ b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj @@ -58,25 +58,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj index c6a34bc9e0..e761c8a654 100644 --- a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj +++ b/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj @@ -53,25 +53,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj index 035631cf2b..95390f07ca 100644 --- a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj +++ b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj @@ -57,25 +57,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj index 22c087567d..072c51d13a 100644 --- a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj +++ b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj @@ -60,25 +60,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj index 1a2bb5e255..cb4f653878 100644 --- a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj +++ b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj @@ -56,25 +56,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj b/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj index 52c27223e4..1292bf6f1d 100644 --- a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj +++ b/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj @@ -58,25 +58,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj index c04a6bbe46..1ae22dc009 100644 --- a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj +++ b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj @@ -52,25 +52,25 @@ StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary true - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static StaticLibrary false - Clang_3_6 + Clang_3_8 gnustl_static diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln index 4a9087e936..e183a8be02 100644 --- a/cpprestsdk140.sln +++ b/cpprestsdk140.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14\casablanca140.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" EndProject @@ -53,25 +53,27 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.xp", "Release EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest140.xp", "Release\samples\BingRequest\BingRequest140.xp\BingRequest140.xp.vcxproj", "{7009BCBE-D67C-4B54-BEFC-A44E62656CF1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRunner.android.NativeActivity", "Release\tests\common\TestRunner\vs14.android\TestRunner.android.NativeActivity\TestRunner.android.NativeActivity.vcxproj", "{D1060D0A-A10E-444D-9F6B-9676EA453F9A}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 - Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 - Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 + Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 + Release\src\build\win32.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 + Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 + Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -260,6 +262,20 @@ Global {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.Build.0 = Release|x64 {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.ActiveCfg = Release|Win32 {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.Build.0 = Release|Win32 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|ARM.ActiveCfg = Debug|ARM + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|ARM.Build.0 = Debug|ARM + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|Win32.ActiveCfg = Debug|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|Win32.Build.0 = Debug|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x64.ActiveCfg = Debug|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x86.ActiveCfg = Debug|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x86.Build.0 = Debug|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|ARM.ActiveCfg = Release|ARM + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|ARM.Build.0 = Release|ARM + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|Win32.ActiveCfg = Release|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|Win32.Build.0 = Release|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x64.ActiveCfg = Release|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.ActiveCfg = Release|x86 + {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 435d69cf60b149d01adf6e4095b0c4ed20e47a6a Mon Sep 17 00:00:00 2001 From: Jason Yang Date: Tue, 27 Sep 2016 15:26:22 +0800 Subject: [PATCH 145/609] Use index instead of iterator for utf16_to_utf8, performance improvement. --- Release/src/utilities/asyncrt_utils.cpp | 28 +++++++++++++------------ 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index fac7787d49..fba168f81a 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -370,17 +370,19 @@ std::string __cdecl conversions::utf16_to_utf8(const utf16string &w) #else std::string dest; dest.reserve(w.size()); - for (auto src = w.begin(); src != w.end(); ++src) + + for (size_t index = 0; index < w.size(); ++index) { + auto src = w[index]; // Check for high surrogate. - if (*src >= H_SURROGATE_START && *src <= H_SURROGATE_END) + if (src >= H_SURROGATE_START && src <= H_SURROGATE_END) { - const auto highSurrogate = *src++; - if (src == w.end()) + const auto highSurrogate = w[++index]; + if (index == w.size()) { throw std::range_error("UTF-16 string is missing low surrogate"); } - const auto lowSurrogate = *src; + const auto lowSurrogate = src; if (lowSurrogate < L_SURROGATE_START || lowSurrogate > L_SURROGATE_END) { throw std::range_error("UTF-16 string has invalid low surrogate"); @@ -404,20 +406,20 @@ std::string __cdecl conversions::utf16_to_utf8(const utf16string &w) } else { - if (*src <= 0x7F) // single byte character + if (src <= 0x7F) // single byte character { - dest.push_back(static_cast(*src)); + dest.push_back(static_cast(src)); } - else if (*src <= 0x7FF) // 2 bytes needed (11 bits used) + else if (src <= 0x7FF) // 2 bytes needed (11 bits used) { - dest.push_back(char((*src >> 6) | 0xC0)); // leading 5 bits - dest.push_back(char((*src & LOW_6BITS) | BIT8)); // trailing 6 bits + dest.push_back(char((src >> 6) | 0xC0)); // leading 5 bits + dest.push_back(char((src & LOW_6BITS) | BIT8)); // trailing 6 bits } else // 3 bytes needed (16 bits used) { - dest.push_back(char((*src >> 12) | 0xE0)); // leading 4 bits - dest.push_back(char(((*src >> 6) & LOW_6BITS) | BIT8)); // middle 6 bits - dest.push_back(char((*src & LOW_6BITS) | BIT8)); // trailing 6 bits + dest.push_back(char((src >> 12) | 0xE0)); // leading 4 bits + dest.push_back(char(((src >> 6) & LOW_6BITS) | BIT8)); // middle 6 bits + dest.push_back(char((src & LOW_6BITS) | BIT8)); // trailing 6 bits } } } From b2aadf60d1ef563bb566c1360bf2af2f88c9885a Mon Sep 17 00:00:00 2001 From: Jason Yang Date: Tue, 27 Sep 2016 16:05:41 +0800 Subject: [PATCH 146/609] Fix the order of highSurrogate and lowSurrogate. --- Release/src/utilities/asyncrt_utils.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index fba168f81a..afa81729cd 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -377,12 +377,13 @@ std::string __cdecl conversions::utf16_to_utf8(const utf16string &w) // Check for high surrogate. if (src >= H_SURROGATE_START && src <= H_SURROGATE_END) { - const auto highSurrogate = w[++index]; + const auto highSurrogate = src; + ++index; if (index == w.size()) { throw std::range_error("UTF-16 string is missing low surrogate"); } - const auto lowSurrogate = src; + const auto lowSurrogate = w[index]; if (lowSurrogate < L_SURROGATE_START || lowSurrogate > L_SURROGATE_END) { throw std::range_error("UTF-16 string has invalid low surrogate"); From f9d32dfc2d61c30c765f8c70850e61e5026d044f Mon Sep 17 00:00:00 2001 From: Jason Yang Date: Thu, 29 Sep 2016 13:55:24 +0800 Subject: [PATCH 147/609] use pointers instead of operator[], extend to utf8_to_utf16 --- Release/src/utilities/asyncrt_utils.cpp | 274 ++++++++++++++++-------- 1 file changed, 186 insertions(+), 88 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index afa81729cd..6565ba8d62 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -280,147 +280,245 @@ const std::error_category & __cdecl linux_category() #define H_SURROGATE_END 0xDBFF #define SURROGATE_PAIR_START 0x10000 -utf16string __cdecl conversions::utf8_to_utf16(const std::string &s) +inline size_t count_utf8_to_utf16(const std::string& s) { -#if defined(CPPREST_STDLIB_UNICODE_CONVERSIONS) - std::wstring_convert, utf16char> conversion; - return conversion.from_bytes(s); -#else - utf16string dest; - // Save repeated heap allocations, use less than source string size assuming some - // of the characters are not just ASCII and collapse. - dest.reserve(static_cast(static_cast(s.size()) * .70)); - - for (auto src = s.begin(); src != s.end(); ++src) + const size_t sSize = s.size(); + const char* const sData = s.data(); + size_t result{ sSize }; + for (size_t index = 0; index < sSize;) { - if ((*src & BIT8) == 0) // single byte character, 0x0 to 0x7F + const char c{ sData[index++] }; + if ((c & BIT8) == 0) { - dest.push_back(utf16string::value_type(*src)); + continue; } - else + + if ((c & BIT7) == 0) { - unsigned char numContBytes = 0; - uint32_t codePoint; - if ((*src & BIT7) == 0) + throw std::range_error("UTF-8 string character can never start with 10xxxxxx"); + } + else if ((c & BIT6) == 0) // 2 byte character, 0x80 to 0x7FF + { + if (index == sSize) { - throw std::range_error("UTF-8 string character can never start with 10xxxxxx"); + throw std::range_error("UTF-8 string is missing bytes in character"); } - else if ((*src & BIT6) == 0) // 2 byte character, 0x80 to 0x7FF + + const char c2{ sData[index++] }; + if ((c2 & 0xC0) != BIT8) { - codePoint = *src & LOW_5BITS; - numContBytes = 1; + throw std::range_error("UTF-8 continuation byte is missing leading byte"); } - else if ((*src & BIT5) == 0) // 3 byte character, 0x800 to 0xFFFF + + // can't require surrogates for 7FF + --result; + } + else if ((c & BIT5) == 0) // 3 byte character, 0x800 to 0xFFFF + { + if (sSize - index < 2) { - codePoint = *src & LOW_4BITS; - numContBytes = 2; + throw std::range_error("UTF-8 string is missing bytes in character"); } - else if ((*src & BIT4) == 0) // 4 byte character, 0x10000 to 0x10FFFF + + const char c2{ sData[index++] }; + const char c3{ sData[index++] }; + if (((c2 | c3) & 0xC0) != BIT8) { - codePoint = *src & LOW_3BITS; - numContBytes = 3; + throw std::range_error("UTF-8 continuation byte is missing leading byte"); } - else + + result -= 2; + } + else if ((c & BIT4) == 0) // 4 byte character, 0x10000 to 0x10FFFF + { + if (sSize - index < 3) { - throw std::range_error("UTF-8 string has invalid Unicode code point"); + throw std::range_error("UTF-8 string is missing bytes in character"); } - for (unsigned char i = 0; i < numContBytes; ++i) + const char c2{ sData[index++] }; + const char c3{ sData[index++] }; + const char c4{ sData[index++] }; + if (((c2 | c3 | c4) & 0xC0) != BIT8) { - if (++src == s.end()) + throw std::range_error("UTF-8 continuation byte is missing leading byte"); + } + + const uint32_t codePoint = ((c & LOW_3BITS) << 18) | ((c2 & LOW_6BITS) << 12) | ((c3 & LOW_6BITS) << 6) | (c4 & LOW_6BITS); + result -= (3 - (codePoint >= SURROGATE_PAIR_START)); + } + else + { + throw std::range_error("UTF-8 string has invalid Unicode code point"); + } + } + + return result; +} + +utf16string __cdecl conversions::utf8_to_utf16(const std::string &s) +{ +#if defined(CPPREST_STDLIB_UNICODE_CONVERSIONS) + std::wstring_convert, utf16char> conversion; + return conversion.from_bytes(s); +#else + // Save repeated heap allocations, use the length of resulting sequence. + const size_t srcSize = s.size(); + const std::string::value_type* const srcData = &s[0]; + utf16string dest(count_utf8_to_utf16(s), L'\0'); + utf16string::value_type* const destData = &dest[0]; + size_t destIndex = 0; + + for (size_t index = 0; index < srcSize; ++index) + { + std::string::value_type src = srcData[index]; + switch (src & 0xF0) + { + case 0xF0: // 4 byte character, 0x10000 to 0x10FFFF + { + const char c2{ srcData[++index] }; + const char c3{ srcData[++index] }; + const char c4{ srcData[++index] }; + uint32_t codePoint = ((src & LOW_3BITS) << 18) | ((c2 & LOW_6BITS) << 12) | ((c3 & LOW_6BITS) << 6) | (c4 & LOW_6BITS); + if (codePoint >= SURROGATE_PAIR_START) { - throw std::range_error("UTF-8 string is missing bytes in character"); + // In UTF-16 U+10000 to U+10FFFF are represented as two 16-bit code units, surrogate pairs. + // - 0x10000 is subtracted from the code point + // - high surrogate is 0xD800 added to the top ten bits + // - low surrogate is 0xDC00 added to the low ten bits + codePoint -= SURROGATE_PAIR_START; + destData[destIndex++] = static_cast((codePoint >> 10) | H_SURROGATE_START); + destData[destIndex++] = static_cast((codePoint & 0x3FF) | L_SURROGATE_START); } - if ((*src & BIT8) == 0 || (*src & BIT7) != 0) + else { - throw std::range_error("UTF-8 continuation byte is missing leading byte"); + // In UTF-16 U+0000 to U+D7FF and U+E000 to U+FFFF are represented exactly as the Unicode code point value. + // U+D800 to U+DFFF are not valid characters, for simplicity we assume they are not present but will encode + // them if encountered. + destData[destIndex++] = static_cast(codePoint); } - codePoint <<= 6; - codePoint |= *src & LOW_6BITS; } - - if (codePoint >= SURROGATE_PAIR_START) + break; + case 0xE0: // 3 byte character, 0x800 to 0xFFFF { - // In UTF-16 U+10000 to U+10FFFF are represented as two 16-bit code units, surrogate pairs. - // - 0x10000 is subtracted from the code point - // - high surrogate is 0xD800 added to the top ten bits - // - low surrogate is 0xDC00 added to the low ten bits - codePoint -= SURROGATE_PAIR_START; - dest.push_back(utf16string::value_type((codePoint >> 10) | H_SURROGATE_START)); - dest.push_back(utf16string::value_type((codePoint & 0x3FF) | L_SURROGATE_START)); + const char c2{ srcData[++index] }; + const char c3{ srcData[++index] }; + destData[destIndex++] = ((src & LOW_4BITS) << 12) | ((c2 & LOW_6BITS) << 6) | (c3 & LOW_6BITS); } - else + break; + case 0xD0: // 2 byte character, 0x80 to 0x7FF + case 0xC0: { - // In UTF-16 U+0000 to U+D7FF and U+E000 to U+FFFF are represented exactly as the Unicode code point value. - // U+D800 to U+DFFF are not valid characters, for simplicity we assume they are not present but will encode - // them if encountered. - dest.push_back(utf16string::value_type(codePoint)); + const char c2{ srcData[++index] }; + destData[destIndex++] = static_cast(((src & LOW_5BITS) << 6) | (c2 & LOW_6BITS)); } + break; + default: // single byte character, 0x0 to 0x7F + destData[destIndex++] = static_cast(src); } } return dest; #endif } -std::string __cdecl conversions::utf16_to_utf8(const utf16string &w) -{ - #if defined(CPPREST_STDLIB_UNICODE_CONVERSIONS) - std::wstring_convert, utf16char> conversion; - return conversion.to_bytes(w); - #else - std::string dest; - dest.reserve(w.size()); - for (size_t index = 0; index < w.size(); ++index) +inline size_t count_utf16_to_utf8(const utf16string &w) +{ + const utf16string::value_type * const srcData = &w[0]; + const size_t srcSize = w.size(); + size_t destSize(srcSize); + for (size_t index = 0; index < srcSize; ++index) { - auto src = w[index]; + const utf16string::value_type ch(srcData[index]); + if (ch <= 0x7FF) + { + if (ch > 0x7F) // 2 bytes needed (11 bits used) + { + ++destSize; + } + } // Check for high surrogate. - if (src >= H_SURROGATE_START && src <= H_SURROGATE_END) + else if (ch >= H_SURROGATE_START && ch <= H_SURROGATE_END) // 4 bytes need using 21 bits { - const auto highSurrogate = src; - ++index; - if (index == w.size()) + ++index; + if (index == srcSize) { throw std::range_error("UTF-16 string is missing low surrogate"); } - const auto lowSurrogate = w[index]; + + const auto lowSurrogate = srcData[index]; if (lowSurrogate < L_SURROGATE_START || lowSurrogate > L_SURROGATE_END) { throw std::range_error("UTF-16 string has invalid low surrogate"); } - // To get from surrogate pair to Unicode code point: - // - subract 0xD800 from high surrogate, this forms top ten bits - // - subract 0xDC00 from low surrogate, this forms low ten bits - // - add 0x10000 - // Leaves a code point in U+10000 to U+10FFFF range. - uint32_t codePoint = highSurrogate - H_SURROGATE_START; - codePoint <<= 10; - codePoint |= lowSurrogate - L_SURROGATE_START; - codePoint += SURROGATE_PAIR_START; - - // 4 bytes need using 21 bits - dest.push_back(char((codePoint >> 18) | 0xF0)); // leading 3 bits - dest.push_back(char(((codePoint >> 12) & LOW_6BITS) | BIT8)); // next 6 bits - dest.push_back(char(((codePoint >> 6) & LOW_6BITS) | BIT8)); // next 6 bits - dest.push_back(char((codePoint & LOW_6BITS) | BIT8)); // trailing 6 bits + destSize += 2; } - else + else // 3 bytes needed (16 bits used) + { + destSize += 2; + } + } + + return destSize; +} + +std::string __cdecl conversions::utf16_to_utf8(const utf16string &w) +{ + #if defined(CPPREST_STDLIB_UNICODE_CONVERSIONS) + std::wstring_convert, utf16char> conversion; + return conversion.to_bytes(w); + #else + const size_t srcSize = w.size(); + const utf16string::value_type* const srcData = &w[0]; + std::string dest(count_utf16_to_utf8(w), '\0'); + std::string::value_type* const destData = &dest[0]; + size_t destIndex(0); + + for (size_t index = 0; index < srcSize; ++index) + { + const utf16string::value_type src{ srcData[index] }; + if (src <= 0x7FF) { if (src <= 0x7F) // single byte character { - dest.push_back(static_cast(src)); + destData[destIndex++] = static_cast(src); } - else if (src <= 0x7FF) // 2 bytes needed (11 bits used) + else // 2 bytes needed (11 bits used) + { + destData[destIndex++] = static_cast(char((src >> 6) | 0xC0)); // leading 5 bits + destData[destIndex++] = static_cast(char((src & LOW_6BITS) | BIT8)); // trailing 6 bits + } + } + else + { + // Check for high surrogate. + if (src >= H_SURROGATE_START && src <= H_SURROGATE_END) { - dest.push_back(char((src >> 6) | 0xC0)); // leading 5 bits - dest.push_back(char((src & LOW_6BITS) | BIT8)); // trailing 6 bits + const auto highSurrogate{ src }; + const auto lowSurrogate{ srcData[++index] }; + + // To get from surrogate pair to Unicode code point: + // - subract 0xD800 from high surrogate, this forms top ten bits + // - subract 0xDC00 from low surrogate, this forms low ten bits + // - add 0x10000 + // Leaves a code point in U+10000 to U+10FFFF range. + uint32_t codePoint = highSurrogate - H_SURROGATE_START; + codePoint <<= 10; + codePoint |= lowSurrogate - L_SURROGATE_START; + codePoint += SURROGATE_PAIR_START; + + // 4 bytes need using 21 bits + destData[destIndex++] = static_cast((codePoint >> 18) | 0xF0); // leading 3 bits + destData[destIndex++] = static_cast(((codePoint >> 12) & LOW_6BITS) | BIT8); // next 6 bits + destData[destIndex++] = static_cast(((codePoint >> 6) & LOW_6BITS) | BIT8); // next 6 bits + destData[destIndex++] = static_cast((codePoint & LOW_6BITS) | BIT8); // trailing 6 bits } else // 3 bytes needed (16 bits used) { - dest.push_back(char((src >> 12) | 0xE0)); // leading 4 bits - dest.push_back(char(((src >> 6) & LOW_6BITS) | BIT8)); // middle 6 bits - dest.push_back(char((src & LOW_6BITS) | BIT8)); // trailing 6 bits + destData[destIndex++] = static_cast((src >> 12) | 0xE0); // leading 4 bits + destData[destIndex++] = static_cast(((src >> 6) & LOW_6BITS) | BIT8); // middle 6 bits + destData[destIndex++] = static_cast((src & LOW_6BITS) | BIT8); // trailing 6 bits } } } From 2902b293f553cbfcd077a84bd4bcda7c50634ac9 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Tue, 4 Oct 2016 16:10:18 -0700 Subject: [PATCH 148/609] Android build script updates to use NDK 11 and clang 3.8 --- Build_android/boost-for-android-x86.patch | 44 ++++++++++++++------ Build_android/boost-for-android.patch | 49 ++++++++++++++++------- Build_android/configure.sh | 10 ++--- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/Build_android/boost-for-android-x86.patch b/Build_android/boost-for-android-x86.patch index be0957dd3b..4e24b988e3 100644 --- a/Build_android/boost-for-android-x86.patch +++ b/Build_android/boost-for-android-x86.patch @@ -1,8 +1,22 @@ diff --git a/build-android.sh b/build-android.sh -index 40453f7..7ffc050 100755 +index 40453f7..5902fe2 100755 --- a/build-android.sh +++ b/build-android.sh -@@ -258,9 +258,14 @@ case "$NDK_RN" in +@@ -195,8 +195,12 @@ case "$HOST_OS" in + PlatformOS=linux + esac + ++NDK_SOURCE_PROPERTIES=$AndroidNDKRoot"/source.properties" + NDK_RELEASE_FILE=$AndroidNDKRoot"/RELEASE.TXT" +-if [ -f "${NDK_RELEASE_FILE}" ]; then ++if [ -f "${NDK_SOURCE_PROPERTIES}" ]; then ++ version=$(grep -i '^Pkg.Revision =' $NDK_SOURCE_PROPERTIES | cut -f2- -d=) ++ NDK_RN=$(echo $version | awk -F. '{print $1}') ++elif [ -f "${NDK_RELEASE_FILE}" ]; then + NDK_RN=`cat $NDK_RELEASE_FILE | sed 's/^r\(.*\)$/\1/g'` + elif [ -n "${AndroidSourcesDetected}" ]; then + if [ -f "${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" ]; then +@@ -258,10 +262,20 @@ case "$NDK_RN" in TOOLSET=gcc-androidR8e ;; "10 (64-bit)") @@ -18,17 +32,23 @@ index 40453f7..7ffc050 100755 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e ;; ++ 11) ++ TOOLCHAIN=llvm ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e ++ ;; *) echo "Undefined or not supported Android NDK version!" -@@ -391,6 +396,7 @@ echo "Building boost for android" + exit 1 +@@ -391,6 +405,7 @@ echo "Building boost for android" export AndroidBinariesPath=`dirname $CXXPATH` export PATH=$AndroidBinariesPath:$PATH export AndroidNDKRoot + export PlatformOS export NO_BZIP2=1 - + cxxflags="" -@@ -405,7 +411,7 @@ echo "Building boost for android" +@@ -405,7 +420,7 @@ echo "Building boost for android" --layout=versioned \ --prefix="./../$BUILD_DIR/" \ $LIBRARIES \ @@ -38,11 +58,11 @@ index 40453f7..7ffc050 100755 } | tee -a $PROGDIR/build.log diff --git a/configs/user-config-boost-1_55_0.jam b/configs/user-config-boost-1_55_0.jam -index 666d4c8..4cd3441 100644 +index 666d4c8..93aba68 100644 --- a/configs/user-config-boost-1_55_0.jam +++ b/configs/user-config-boost-1_55_0.jam @@ -39,93 +39,47 @@ - + import os ; local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; +local PlatformOS = [ os.environ PlatformOS ] ; @@ -53,10 +73,10 @@ index 666d4c8..4cd3441 100644 +using clang : androidR8e : -arm-linux-androideabi-g++ -+$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/$(PlatformOS)-x86_64/bin/clang++ ++$(AndroidNDKRoot)/toolchains/llvm/prebuilt/$(PlatformOS)-x86_64/bin/clang++ : -arm-linux-androideabi-ar -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/$(PlatformOS)-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.9/prebuilt/$(PlatformOS)-x86_64" -fexceptions -frtti -fpic @@ -89,10 +109,10 @@ index 666d4c8..4cd3441 100644 -g --I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include --I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include -+-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include -+-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/libs/x86/include +--target=i686-none-linux-android -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.8/prebuilt/$(PlatformOS)-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/x86-4.9/prebuilt/$(PlatformOS)-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-x86 # @Moss - Above are the 'oficial' android flags -arm diff --git a/Build_android/boost-for-android.patch b/Build_android/boost-for-android.patch index 0b941435e3..2b86e8f833 100644 --- a/Build_android/boost-for-android.patch +++ b/Build_android/boost-for-android.patch @@ -1,8 +1,22 @@ diff --git a/build-android.sh b/build-android.sh -index 40453f7..ad78ddf 100755 +index 40453f7..5902fe2 100755 --- a/build-android.sh +++ b/build-android.sh -@@ -258,9 +258,14 @@ case "$NDK_RN" in +@@ -195,8 +195,12 @@ case "$HOST_OS" in + PlatformOS=linux + esac + ++NDK_SOURCE_PROPERTIES=$AndroidNDKRoot"/source.properties" + NDK_RELEASE_FILE=$AndroidNDKRoot"/RELEASE.TXT" +-if [ -f "${NDK_RELEASE_FILE}" ]; then ++if [ -f "${NDK_SOURCE_PROPERTIES}" ]; then ++ version=$(grep -i '^Pkg.Revision =' $NDK_SOURCE_PROPERTIES | cut -f2- -d=) ++ NDK_RN=$(echo $version | awk -F. '{print $1}') ++elif [ -f "${NDK_RELEASE_FILE}" ]; then + NDK_RN=`cat $NDK_RELEASE_FILE | sed 's/^r\(.*\)$/\1/g'` + elif [ -n "${AndroidSourcesDetected}" ]; then + if [ -f "${ANDROID_BUILD_TOP}/ndk/docs/CHANGES.html" ]; then +@@ -258,10 +262,20 @@ case "$NDK_RN" in TOOLSET=gcc-androidR8e ;; "10 (64-bit)") @@ -18,18 +32,23 @@ index 40453f7..ad78ddf 100755 + CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ + TOOLSET=clang-androidR8e ;; ++ 11) ++ TOOLCHAIN=llvm ++ CXXPATH=$AndroidNDKRoot/toolchains/${TOOLCHAIN}/prebuilt/${PlatformOS}-x86_64/bin/clang++ ++ TOOLSET=clang-androidR8e ++ ;; *) echo "Undefined or not supported Android NDK version!" -@@ -391,6 +396,7 @@ echo "Building boost for android" + exit 1 +@@ -391,6 +405,7 @@ echo "Building boost for android" export AndroidBinariesPath=`dirname $CXXPATH` export PATH=$AndroidBinariesPath:$PATH export AndroidNDKRoot + export PlatformOS export NO_BZIP2=1 - + cxxflags="" -@@ -405,7 +411,7 @@ echo "Building boost for android" - threading=multi \ +@@ -405,7 +420,7 @@ echo "Building boost for android" --layout=versioned \ --prefix="./../$BUILD_DIR/" \ $LIBRARIES \ @@ -39,25 +58,25 @@ index 40453f7..ad78ddf 100755 } | tee -a $PROGDIR/build.log diff --git a/configs/user-config-boost-1_55_0.jam b/configs/user-config-boost-1_55_0.jam -index 666d4c8..df597f6 100644 +index 666d4c8..cdab118 100644 --- a/configs/user-config-boost-1_55_0.jam +++ b/configs/user-config-boost-1_55_0.jam @@ -39,84 +39,44 @@ - + import os ; local AndroidNDKRoot = [ os.environ AndroidNDKRoot ] ; +local PlatformOS = [ os.environ PlatformOS ] ; - + # -------------------------------------------------------------------- -# Is same for 8b, 8c and 8d -using gcc : androidR8b +using clang : androidR8e : -arm-linux-androideabi-g++ -+$(AndroidNDKRoot)/toolchains/llvm-3.6/prebuilt/$(PlatformOS)-x86_64/bin/clang++ ++$(AndroidNDKRoot)/toolchains/llvm/prebuilt/$(PlatformOS)-x86_64/bin/clang++ : -arm-linux-androideabi-ar -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/$(PlatformOS)-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.9/prebuilt/$(PlatformOS)-x86_64" -fexceptions -frtti -fpic @@ -134,15 +153,15 @@ index 666d4c8..df597f6 100644 -g --I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/include --I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include -+-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/include -+-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/include ++-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include +--target=armv7-none-linux-androideabi -+--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.8/prebuilt/$(PlatformOS)-x86_64" ++--gcc-toolchain="$(AndroidNDKRoot)/toolchains/arm-linux-androideabi-4.9/prebuilt/$(PlatformOS)-x86_64" +--sysroot=$(AndroidNDKRoot)/platforms/android-9/arch-arm # @Moss - Above are the 'oficial' android flags arm -fvisibility=hidden -@@ -125,9 +84,11 @@ arm-linux-androideabi-g++ +@@ -125,9 +85,11 @@ arm-linux-androideabi-g++ -D__arm__ -D_REENTRANT -D_GLIBCXX__PTHREADS diff --git a/Build_android/configure.sh b/Build_android/configure.sh index 5cef31364f..75697672a6 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -193,7 +193,7 @@ then cmake "$DIR/../Release/" \ -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ -DANDROID_ABI=armeabi-v7a \ - -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.6 \ + -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.8 \ -DANDROID_STL=none \ -DANDROID_STL_FORCE_FEATURES=ON \ -DANDROID_NATIVE_API_LEVEL=android-9 \ @@ -209,7 +209,7 @@ then cmake "$DIR/../Release/" \ -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ -DANDROID_ABI=armeabi-v7a \ - -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.6 \ + -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang3.8 \ -DANDROID_STL=none \ -DANDROID_STL_FORCE_FEATURES=ON \ -DANDROID_NDK="${ANDROID_NDK}" \ @@ -225,7 +225,7 @@ then cmake "$DIR/../Release/" \ -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ -DANDROID_ABI=x86 \ - -DANDROID_TOOLCHAIN_NAME=x86-clang3.6 \ + -DANDROID_TOOLCHAIN_NAME=x86-clang3.8 \ -DANDROID_STL=none \ -DANDROID_STL_FORCE_FEATURES=ON \ -DANDROID_NATIVE_API_LEVEL=android-9 \ @@ -241,7 +241,7 @@ then cmake "$DIR/../Release/" \ -DCMAKE_TOOLCHAIN_FILE=../android-cmake/android.toolchain.cmake \ -DANDROID_ABI=x86 \ - -DANDROID_TOOLCHAIN_NAME=x86-clang3.6 \ + -DANDROID_TOOLCHAIN_NAME=x86-clang3.8 \ -DANDROID_STL=none \ -DANDROID_STL_FORCE_FEATURES=ON \ -DANDROID_NDK="${ANDROID_NDK}" \ @@ -251,4 +251,4 @@ then make -j 1 ) ) -fi \ No newline at end of file +fi From d1337468f584ab06e1a969c7b63dfbccc5051bef Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Wed, 5 Oct 2016 10:13:12 -0700 Subject: [PATCH 149/609] Some fixes to build with clang 3_8. Ignore the -Winfinite-recursion warning. This has been fixed in the next boost versions. --- .../cpprest/details/http_server_asio.h | 1 + Release/include/pplx/threadpool.h | 1 + Release/src/http/client/http_client_asio.cpp | 1 + Release/src/pch/stdafx.h | 1 + .../TestRunner.android.NativeActivity.vcxproj | 42 ++++++++++--------- .../packages.config | 16 +++---- .../http/client/authentication_tests.cpp | 7 ++++ .../utilities/test_websocket_server.cpp | 9 ++++ 8 files changed, 51 insertions(+), 27 deletions(-) diff --git a/Release/include/cpprest/details/http_server_asio.h b/Release/include/cpprest/details/http_server_asio.h index e34435d09c..c9ed53b006 100644 --- a/Release/include/cpprest/details/http_server_asio.h +++ b/Release/include/cpprest/details/http_server_asio.h @@ -20,6 +20,7 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Winfinite-recursion" #endif #include #include diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index c778040737..4a88a75c44 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -30,6 +30,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wunreachable-code" +#pragma clang diagnostic ignored "-Winfinite-recursion" #endif #include "boost/asio.hpp" #if defined(__clang__) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 6963aee43d..10984ebff7 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -30,6 +30,7 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-local-typedef" +#pragma clang diagnostic ignored "-Winfinite-recursion" #endif #include #include diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index f177ad5004..432f9e7449 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -28,6 +28,7 @@ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-local-typedef" +#pragma clang diagnostic ignored "-Winfinite-recursion" #endif #include "cpprest/details/cpprest_compat.h" diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj index 8a3b63bb63..42f9f5b673 100644 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj +++ b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -26,28 +26,32 @@ en-US 14.0 Android - 1.0 + 2.0 DynamicLibrary true gnustl_static + Clang_3_8 DynamicLibrary true gnustl_static + Clang_3_8 DynamicLibrary false gnustl_static + Clang_3_8 DynamicLibrary false gnustl_static + Clang_3_8 @@ -253,28 +257,28 @@ - + - - - - - - - + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - - - - - - - + + + + + + + - + \ No newline at end of file diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config index 5eea3261b9..c99b35a84e 100644 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config +++ b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config @@ -1,12 +1,12 @@  - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/Release/tests/functional/http/client/authentication_tests.cpp b/Release/tests/functional/http/client/authentication_tests.cpp index d5cdd4605a..31ecea7cfa 100644 --- a/Release/tests/functional/http/client/authentication_tests.cpp +++ b/Release/tests/functional/http/client/authentication_tests.cpp @@ -38,8 +38,15 @@ #endif #if !defined(_WIN32) +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winfinite-recursion" +#endif #include #include +#if defined(__clang__) +#pragma clang diagnostic pop +#endif #endif using namespace web; diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp index 4485e93f86..c091100fba 100644 --- a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp +++ b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp @@ -39,9 +39,18 @@ #endif #endif /* _WIN32 */ +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winfinite-recursion" +#endif + #include #include +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + #ifdef _WIN32 #pragma warning( pop ) #endif From 0cc46e8b6bcee53b26f63e5ddab2612e6bdc2341 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Wed, 5 Oct 2016 10:22:13 -0700 Subject: [PATCH 150/609] Update the Nuget package paths to use the android packages built with clang 3_8 --- .../UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj | 4 ++-- .../utilities/vs14.android/CommonUtilities140.android.vcxproj | 4 ++-- .../client/vs14.android/HttpClient140_test.android.vcxproj | 4 ++-- .../vs14.android/HttpListener140_test.android.vcxproj | 4 ++-- .../vs14.android/HttpTestUtilities140.android.vcxproj | 4 ++-- .../functional/json/vs14.android/JSON140_test.android.vcxproj | 4 ++-- .../pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj | 4 ++-- .../streams/vs14.android/streams140_test.android.vcxproj | 4 ++-- .../functional/uri/vs14.android/Uri140_test.android.vcxproj | 4 ++-- .../utils/vs14.android/Utils140_test.android.vcxproj | 4 ++-- .../vs14.android/websocketsclient140_test.android.vcxproj | 4 ++-- .../vs14.android/websockets_test_utilities140.android.vcxproj | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj index 3804df5f49..c90d265794 100644 --- a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj +++ b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj @@ -187,13 +187,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj index 984cd33475..461f9237b7 100644 --- a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj +++ b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj @@ -136,13 +136,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj index 3b5e3aa321..9858725a15 100644 --- a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj +++ b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj @@ -156,13 +156,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj index fbe9edd033..26c52a2ba3 100644 --- a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj +++ b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj @@ -148,13 +148,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj index 444640f84d..b59dba2585 100644 --- a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj +++ b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj @@ -144,13 +144,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj index 6bf397496b..b2790fed9e 100644 --- a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj +++ b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj @@ -142,13 +142,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj index e761c8a654..e0963274a6 100644 --- a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj +++ b/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj @@ -137,13 +137,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj index 95390f07ca..07add08cd8 100644 --- a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj +++ b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj @@ -141,13 +141,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj index 072c51d13a..edcd45196c 100644 --- a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj +++ b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj @@ -144,13 +144,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj index cb4f653878..e1cd173286 100644 --- a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj +++ b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj @@ -140,13 +140,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj b/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj index 1292bf6f1d..78a5386065 100644 --- a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj +++ b/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj @@ -142,13 +142,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj index 1ae22dc009..837df5c8e2 100644 --- a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj +++ b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj @@ -136,13 +136,13 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + From 5214d5e735e5d629a1108713a06a443778ade347 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Wed, 5 Oct 2016 11:40:47 -0700 Subject: [PATCH 151/609] Change ApplicationTypeRevision=2.0 for VS Update3 to use the clang 3_8 toolset. --- Release/src/build/vs14.android/casablanca140.android.vcxproj | 2 +- .../TestRunner.android.NativeActivity.vcxproj | 4 ++-- .../UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj | 2 +- .../utilities/vs14.android/CommonUtilities140.android.vcxproj | 2 +- .../client/vs14.android/HttpClient140_test.android.vcxproj | 2 +- .../tests/functional/http/client/vs14.android/packages.config | 2 +- .../vs14.android/HttpListener140_test.android.vcxproj | 2 +- .../vs14.android/HttpTestUtilities140.android.vcxproj | 2 +- .../functional/json/vs14.android/JSON140_test.android.vcxproj | 2 +- .../pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj | 2 +- .../streams/vs14.android/streams140_test.android.vcxproj | 2 +- .../functional/uri/vs14.android/Uri140_test.android.vcxproj | 2 +- .../utils/vs14.android/Utils140_test.android.vcxproj | 2 +- .../vs14.android/websocketsclient140_test.android.vcxproj | 2 +- .../websockets/utilities/vs14.android/packages.config | 2 +- .../vs14.android/websockets_test_utilities140.android.vcxproj | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Release/src/build/vs14.android/casablanca140.android.vcxproj b/Release/src/build/vs14.android/casablanca140.android.vcxproj index 6f5ec43ce7..038f56b125 100644 --- a/Release/src/build/vs14.android/casablanca140.android.vcxproj +++ b/Release/src/build/vs14.android/casablanca140.android.vcxproj @@ -26,7 +26,7 @@ {AFB49019-965B-4C10-BAFF-C86C16D58010} Android Android - 1.0 + 2.0 cpprestsdk140.android diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj index 42f9f5b673..d798ca823d 100644 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj +++ b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj @@ -257,7 +257,7 @@ - + @@ -271,7 +271,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj index c90d265794..c7b52f072b 100644 --- a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj +++ b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj @@ -95,7 +95,7 @@ {3EFD8540-A54D-4900-887E-F856162535A0} Android Android - 1.0 + 2.0 UnitTestpp140.android diff --git a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj index 461f9237b7..53592625d0 100644 --- a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj +++ b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj @@ -46,7 +46,7 @@ {7C4E6E33-42E2-4472-9319-DDE7564F3DAE} Android Android - 1.0 + 2.0 CommonUtilities140.android diff --git a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj index 9858725a15..9d4978a9af 100644 --- a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj +++ b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj @@ -64,7 +64,7 @@ {0EE481DA-A97F-4831-9119-C65EB2D7B4DA} Android Android - 1.0 + 2.0 HttpClient140_test.android diff --git a/Release/tests/functional/http/client/vs14.android/packages.config b/Release/tests/functional/http/client/vs14.android/packages.config index 299115366f..4bd0fd80ad 100644 --- a/Release/tests/functional/http/client/vs14.android/packages.config +++ b/Release/tests/functional/http/client/vs14.android/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj index 26c52a2ba3..2bb8421046 100644 --- a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj +++ b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj @@ -56,7 +56,7 @@ {2B00D1C0-1A93-4A32-8932-C3CC43ACFF45} Android Android - 1.0 + 2.0 HttpListener140_test.android diff --git a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj index b59dba2585..62a0cf8a5a 100644 --- a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj +++ b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj @@ -52,7 +52,7 @@ {B444EE47-1340-4A74-820D-CDD55F9F22F7} Android Android - 1.0 + 2.0 HttpTestUtilities140.android diff --git a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj index b2790fed9e..16dd72d5bc 100644 --- a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj +++ b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj @@ -50,7 +50,7 @@ {169555EF-8A80-405E-A815-CFE70028CA45} Android Android - 1.0 + 2.0 JSON140_test.android diff --git a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj index e0963274a6..7fd3c7b631 100644 --- a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj +++ b/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj @@ -45,7 +45,7 @@ {DF670B4E-692C-424E-BCFD-F63D34FE5CD3} Android Android - 1.0 + 2.0 pplx140_test.android diff --git a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj index 07add08cd8..81ff3ad878 100644 --- a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj +++ b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj @@ -49,7 +49,7 @@ {B9DA540F-95F7-485E-ADF4-C94A17BFA1EB} Android Android - 1.0 + 2.0 streams140_test.android diff --git a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj index edcd45196c..bf66be6210 100644 --- a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj +++ b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj @@ -52,7 +52,7 @@ {63569C1A-A168-442A-B160-76D0256803AF} Android Android - 1.0 + 2.0 Uri140_test.android diff --git a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj index e1cd173286..3bffb9f385 100644 --- a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj +++ b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj @@ -48,7 +48,7 @@ {423FCE6D-7400-4C09-9038-4438FBB089D4} Android Android - 1.0 + 2.0 Utils140_test.android diff --git a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj b/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj index 78a5386065..230810860b 100644 --- a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj +++ b/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj @@ -50,7 +50,7 @@ {3E8466B1-7CBC-489D-8E6B-5E45BAB4D627} Android Android - 1.0 + 2.0 websocketsclient140_test.android diff --git a/Release/tests/functional/websockets/utilities/vs14.android/packages.config b/Release/tests/functional/websockets/utilities/vs14.android/packages.config index 299115366f..4bd0fd80ad 100644 --- a/Release/tests/functional/websockets/utilities/vs14.android/packages.config +++ b/Release/tests/functional/websockets/utilities/vs14.android/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj index 837df5c8e2..3962040a52 100644 --- a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj +++ b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj @@ -44,7 +44,7 @@ {0149E1C2-FBF3-48B6-9996-D6753F689DFB} Android Android - 1.0 + 2.0 websockets_test_utilities140.android From c873d633c2876ca16fb5b9f34e0e37d583422ad5 Mon Sep 17 00:00:00 2001 From: Kavya Kotacherry Date: Wed, 5 Oct 2016 12:07:01 -0700 Subject: [PATCH 152/609] Revert temporary changes from cpprestsdk140.sln --- cpprestsdk140.sln | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln index e183a8be02..4a9087e936 100644 --- a/cpprestsdk140.sln +++ b/cpprestsdk140.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14\casablanca140.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" EndProject @@ -53,27 +53,25 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.xp", "Release EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest140.xp", "Release\samples\BingRequest\BingRequest140.xp\BingRequest140.xp.vcxproj", "{7009BCBE-D67C-4B54-BEFC-A44E62656CF1}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestRunner.android.NativeActivity", "Release\tests\common\TestRunner\vs14.android\TestRunner.android.NativeActivity\TestRunner.android.NativeActivity.vcxproj", "{D1060D0A-A10E-444D-9F6B-9676EA453F9A}" -EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 + Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 + Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 - Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 - Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 + Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -262,20 +260,6 @@ Global {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.Build.0 = Release|x64 {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.ActiveCfg = Release|Win32 {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.Build.0 = Release|Win32 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|ARM.ActiveCfg = Debug|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|ARM.Build.0 = Debug|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|Win32.ActiveCfg = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|Win32.Build.0 = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x64.ActiveCfg = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x86.ActiveCfg = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Debug|x86.Build.0 = Debug|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|ARM.ActiveCfg = Release|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|ARM.Build.0 = Release|ARM - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|Win32.ActiveCfg = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|Win32.Build.0 = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x64.ActiveCfg = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.ActiveCfg = Release|x86 - {D1060D0A-A10E-444D-9F6B-9676EA453F9A}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From b8f518ff429faeae29d758b4ed1f6a8298f510e2 Mon Sep 17 00:00:00 2001 From: John Paul Date: Thu, 6 Oct 2016 16:44:26 -0400 Subject: [PATCH 153/609] fix for bug: m_close getting initialised in handle_headers wipes out the value assigned to it in handle_http_line. This could cause some connection objects to not get released soon, for example if the request is HTTP1.0. --- Release/include/cpprest/details/http_server_asio.h | 1 + Release/src/http/listener/http_server_asio.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Release/include/cpprest/details/http_server_asio.h b/Release/include/cpprest/details/http_server_asio.h index e34435d09c..0d9a984895 100644 --- a/Release/include/cpprest/details/http_server_asio.h +++ b/Release/include/cpprest/details/http_server_asio.h @@ -82,6 +82,7 @@ class connection , m_response_buf() , m_p_server(server) , m_p_parent(parent) + , m_close(false) , m_refs(1) { if (is_https) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 9454aa5175..dcead5f938 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -362,7 +362,7 @@ void connection::handle_headers() } } - m_close = m_chunked = false; + m_chunked = false; utility::string_t name; // check if the client has requested we close the connection if (m_request.headers().match(header_names::connection, name)) From 1ee9d64f7fcc8607d1e48f7da815ca54f2cc5dfc Mon Sep 17 00:00:00 2001 From: John Paul Date: Thu, 6 Oct 2016 20:43:53 -0400 Subject: [PATCH 154/609] ECONNRESET must be used instead of ECONNABORTED. fix for bug: when client does not perform an orderly shutdown of the connection during recv() or read() the error code returned is 'connection reset by peer' or 'connection timed out' according to the opengroup specification (also linux specification). It is not 'operation aborted' which the current code assumes. 'operation aborted' happens during accept(). This fix was needed on RHEL 7 server. References: http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html https://linux.die.net/man/3/recv --- Release/src/http/listener/http_server_asio.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 9454aa5175..a145a5487f 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -249,7 +249,12 @@ void connection::handle_http_line(const boost::system::error_code& ec) if (ec) { // client closed connection - if (ec == boost::asio::error::eof || ec == boost::asio::error::operation_aborted) + if ( + ec == boost::asio::error::eof || // peer has performed an orderly shutdown + ec == boost::asio::error::operation_aborted || // this can be removed. ECONNABORTED happens only for accept() + ec == boost::asio::error::connection_reset || // connection reset by peer + ec == boost::asio::error::timed_out // connection timed out + ) { finish_request_response(); } From 1d03de5b491ca2e4057c98e35870ddd9cd9a45dd Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 18 Oct 2016 12:27:38 -0700 Subject: [PATCH 155/609] Update license to MIT --- license.txt | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/license.txt b/license.txt index 29d1339a81..fb805d9757 100644 --- a/license.txt +++ b/license.txt @@ -1,15 +1,25 @@ - ==++== - - Copyright (c) Microsoft Corporation. All rights reserved. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - ==--== +C++ REST SDK + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From eee6beacdd1d5c425fef2827b3be4e78311bde63 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 18 Oct 2016 12:30:28 -0700 Subject: [PATCH 156/609] Update ThirdPartyNotices.txt to only cover websocketpp, since boost and openssl are not checked in --- ThirdPartyNotices.txt | 184 ++++++++++++++++++++++++++++-------------- 1 file changed, 125 insertions(+), 59 deletions(-) diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index f9922ccb8a..dab0d36764 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -1,45 +1,17 @@ + THIRD-PARTY SOFTWARE NOTICES AND INFORMATION Do Not Translate or Localize -Microsoft is offering you a license to use the following components with C++ REST SDK subject to their original license terms. - -1. OpenSSL version 1.0.1i (http://www.openssl.org/) -2. Websocket++ version 0.3.0 (http://www.zaphoyd.com/websocketpp/) -3. Boost version 1.55 (http://www.boost.org/) - -%% OpenSSL NOTICES, INFORMATION, AND LICENSE BEGIN HERE -========================================= -OpenSSL License -Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - -4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org. - -5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. +C++ REST SDK incorporates third party material from the projects listed below. The original copyright notice and the license under which Microsoft received such third party material are set forth below. Microsoft reserves all other rights not expressly granted, whether by implication, estoppel or otherwise. -6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" - -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). -========================================= -END OF OpenSSL NOTICES, INFORMATION, AND LICENSE +1. Websocket++ (http://www.zaphoyd.com/websocketpp/) %% Websocket++ NOTICES, INFORMATION, AND LICENSE BEGIN HERE ========================================= -WebSocket++ -Copyright (c) 2013, Peter Thorson. All rights reserved. -http://www.zaphoyd.com/websocketpp/ +Main Library: + +Copyright (c) 2014, Peter Thorson. All rights reserved. -BSD License -==================================================================== Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright @@ -61,33 +33,127 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -========================================= -END OF Websocket++ NOTICES, INFORMATION, AND LICENSE -%% Boost NOTICES, INFORMATION, AND LICENSE BEGIN HERE -========================================= -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. +Bundled Libraries: + +****** Base 64 Library (base64/base64.hpp) ****** +base64.hpp is a repackaging of the base64.cpp and base64.h files into a +single header suitable for use as a header only library. This conversion was +done by Peter Thorson (webmaster@zaphoyd.com) in 2012. All modifications to +the code are redistributed under the same license as the original, which is +listed below. + +base64.cpp and base64.h + +Copyright (C) 2004-2008 Ren Nyffenegger + +This source code is provided 'as-is', without any express or implied +warranty. In no event will the author be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + +3. This notice may not be removed or altered from any source distribution. + +Ren Nyffenegger rene.nyffenegger@adp-gmbh.ch + +****** SHA1 Library (sha1/sha1.hpp) ****** +sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1 +library (http://code.google.com/p/smallsha1/) into a single header suitable for +use as a header only library. This conversion was done by Peter Thorson +(webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed +under the same license as the original, which is listed below. + + Copyright (c) 2011, Micael Hildenborg + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Micael Hildenborg nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +****** MD5 Library (common/md5.hpp) ****** +md5.hpp is a reformulation of the md5.h and md5.c code from +http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to +function as a component of a header only library. This conversion was done by +Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The +changes are released under the same license as the original (listed below) + +Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +L. Peter Deutsch +ghost@aladdin.com + +****** UTF8 Validation logic (utf8_validation.hpp) ****** +utf8_validation.hpp is adapted from code originally written by Bjoern Hoehrmann +. See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for +details. + +The original license: + +Copyright (c) 2008-2009 Bjoern Hoehrmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. ========================================= -END OF Boost NOTICES, INFORMATION, AND LICENSE +END OF Websocket++ NOTICES, INFORMATION, AND LICENSE + + From 41520ca9a409967f7f395001afde64b60eeb8e77 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 21 Oct 2016 14:14:10 -0700 Subject: [PATCH 157/609] Fix regression introduced in PR #214 --- Release/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 4daa480ea0..ad474bf486 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -215,7 +215,8 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) endif() set(Casablanca_LIBRARY cpprest) -set(Casablanca_LIBRARIES cpprest ${Boost_LIBRARIES} PARENT_SCOPE) +set(Casablanca_LIBRARIES cpprest ${Boost_LIBRARIES}) +set(Casablanca_LIBRARIES ${Casablanca_LIBRARIES} PARENT_SCOPE) # Everything in the project needs access to the casablanca include directories include_directories( ${Casablanca_INCLUDE_DIRS}) From 6ca83ac4ecfc53cddaaa583357abb11bff13a5ca Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Oct 2016 15:59:36 -0700 Subject: [PATCH 158/609] Skip compression test on platforms that do not claim to support compression. --- Release/tests/functional/http/client/outside_tests.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index b06f69e641..d78e9c6b1f 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -28,6 +28,7 @@ #include #endif #include "cpprest/rawptrstream.h" +#include "cpprest/details/http_helpers.h" #include "os_utilities.h" #include @@ -65,6 +66,11 @@ TEST_FIXTURE(uri_address, outside_cnn_dot_com) TEST_FIXTURE(uri_address, outside_wikipedia_compressed_http_response) { + if (web::http::details::compression::stream_decompressor::is_supported() == false) + { + // On platforms which do not support compressed http, nothing to check. + return; + } http_client_config config; config.set_request_compressed_response(true); From 29b9082033fb655cb90bfce52999f3bccd1a0632 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Oct 2016 17:12:21 -0700 Subject: [PATCH 159/609] Revert throwing exceptions when compression is not compiled in. --- Release/src/http/common/http_helpers.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index 43f0e15e24..f4ed764be5 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -367,10 +367,6 @@ namespace compression public: bool has_error() const { - if (!stream_compressor::is_supported()) - { - throw std::runtime_error("Compression/Decompression has not been implemented or configured on this platform"); - } return true; } }; @@ -381,11 +377,6 @@ namespace compression stream_compressor_impl(compression_algorithm) {} compression::data_buffer compress(const uint8_t* data, size_t size, bool) { - if (!stream_compressor::is_supported()) - { - throw std::runtime_error("Compression is not implemented or configured on this platform"); - } - return data_buffer(data, data + size); } }; @@ -396,11 +387,6 @@ namespace compression stream_decompressor_impl(compression_algorithm) {} compression::data_buffer decompress(const uint8_t* data, size_t size) { - if (!stream_decompressor::is_supported()) - { - throw std::runtime_error("Decompression is not implemented or configured on this platform"); - } - return data_buffer(data, data + size); } }; From cc16407cdae1ca6a82d809643682131c0bbafaf4 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Oct 2016 17:54:11 -0700 Subject: [PATCH 160/609] Add check to disable CPPREST_HTTP_COMPRESSION on WinRT/UWP platforms --- Release/include/cpprest/details/http_helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 3b6ae4c4c5..897aded527 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -35,7 +35,7 @@ // CPPREST_EXCLUDE_COMPRESSION is set if we're on a platform that supports compression but we want to explicitly disable it. // CPPREST_EXCLUDE_WEBSOCKETS is a flag that now essentially means "no external dependencies". TODO: Rename -#if (defined(_WIN32) || defined(TARGET_OS_MAC)) && !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) +#if ((defined(_WIN32) && (!defined(WINAPI_FAMILY_SYSTEM) || (WINAPI_PARTITION_DESKTOP == 1))) || defined(TARGET_OS_MAC)) && !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) #define CPPREST_HTTP_COMPRESSION #endif From ec83ac4bb2908b14dc3d0593fd0ff3be41bfc340 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 26 Oct 2016 17:58:51 -0700 Subject: [PATCH 161/609] Removed WOD projects; in the future, see IoT Core. --- .../build/vs12.wod/casablanca120.wod.vcxproj | 52 ---------------- .../build/vs14.wod/casablanca140.wod.vcxproj | 59 ------------------- 2 files changed, 111 deletions(-) delete mode 100644 Release/src/build/vs12.wod/casablanca120.wod.vcxproj delete mode 100644 Release/src/build/vs14.wod/casablanca140.wod.vcxproj diff --git a/Release/src/build/vs12.wod/casablanca120.wod.vcxproj b/Release/src/build/vs12.wod/casablanca120.wod.vcxproj deleted file mode 100644 index 8d2759ac44..0000000000 --- a/Release/src/build/vs12.wod/casablanca120.wod.vcxproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A} - Win32Proj - SAK - SAK - SAK - SAK - DynamicLibrary - v120 - false - false - cpprestsdk120.wod - Unicode - - - - - - - d - - - $(CppRestBaseFileName)120$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix).wod - 45d9db9f - - - - Designer - - - - - CPPREST_EXCLUDE_WEBSOCKETS;_WINSOCK_DEPRECATED_NO_WARNINGS;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm160 /bigobj /d2nolock %(AdditionalOptions) - NoExtensions - true - - - Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14.wod/casablanca140.wod.vcxproj b/Release/src/build/vs14.wod/casablanca140.wod.vcxproj deleted file mode 100644 index 25e0bbd9db..0000000000 --- a/Release/src/build/vs14.wod/casablanca140.wod.vcxproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - - {3A584D9C-1A98-4046-B7D3-B7171EF42D34} - Win32Proj - SAK - SAK - SAK - SAK - DynamicLibrary - v140 - false - false - cpprestsdk140.wod - Unicode - - - - - - - - - - - d - - - $(CppRestBaseFileName)140$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix).wod - - - - - - - CPPREST_EXCLUDE_WEBSOCKETS;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm300 /bigobj /d2nolock %(AdditionalOptions) - NoExtensions - true - - - Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file From aecf8f1712203b119f58a7ff157c16f66885adcb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 28 Oct 2016 12:20:12 -0700 Subject: [PATCH 162/609] Update all embedded licenses to MIT --- Build_android/configure.sh | 17 ++--------------- Release/include/cpprest/astreambuf.h | 16 ++-------------- Release/include/cpprest/asyncrt_utils.h | 16 ++-------------- Release/include/cpprest/base_uri.h | 16 ++-------------- Release/include/cpprest/containerstream.h | 16 ++-------------- Release/include/cpprest/details/basic_types.h | 16 ++-------------- .../include/cpprest/details/cpprest_compat.h | 16 ++-------------- Release/include/cpprest/details/fileio.h | 16 ++-------------- Release/include/cpprest/details/http_helpers.h | 16 ++-------------- Release/include/cpprest/details/http_server.h | 17 ++--------------- .../include/cpprest/details/http_server_api.h | 16 ++-------------- .../include/cpprest/details/http_server_asio.h | 17 ++++------------- .../cpprest/details/http_server_httpsys.h | 16 ++-------------- Release/include/cpprest/details/nosal.h | 16 ++-------------- Release/include/cpprest/details/uri_parser.h | 16 ++-------------- .../include/cpprest/details/web_utilities.h | 16 ++-------------- .../cpprest/details/x509_cert_utilities.h | 16 ++-------------- Release/include/cpprest/filestream.h | 16 ++-------------- Release/include/cpprest/http_client.h | 16 ++-------------- Release/include/cpprest/http_headers.h | 16 ++-------------- Release/include/cpprest/http_listener.h | 17 ++--------------- Release/include/cpprest/http_msg.h | 16 ++-------------- Release/include/cpprest/interopstream.h | 16 ++-------------- Release/include/cpprest/json.h | 16 ++-------------- Release/include/cpprest/oauth1.h | 16 ++-------------- Release/include/cpprest/oauth2.h | 16 ++-------------- .../include/cpprest/producerconsumerstream.h | 16 ++-------------- Release/include/cpprest/rawptrstream.h | 16 ++-------------- Release/include/cpprest/streams.h | 16 ++-------------- Release/include/cpprest/uri.h | 16 ++-------------- Release/include/cpprest/uri_builder.h | 16 ++-------------- Release/include/cpprest/version.h | 16 ++-------------- Release/include/cpprest/ws_client.h | 16 ++-------------- Release/include/cpprest/ws_msg.h | 16 ++-------------- Release/include/pplx/pplx.h | 16 ++-------------- Release/include/pplx/pplxcancellation_token.h | 16 ++-------------- Release/include/pplx/pplxconv.h | 16 ++-------------- Release/include/pplx/pplxinterface.h | 16 ++-------------- Release/include/pplx/pplxlinux.h | 16 ++-------------- Release/include/pplx/pplxtasks.h | 16 ++-------------- Release/include/pplx/pplxwin.h | 16 ++-------------- Release/include/pplx/threadpool.h | 16 ++-------------- Release/samples/BingRequest/bingrequest.cpp | 16 ++-------------- .../BlackJack_Client/BlackJackClient.cpp | 16 ++-------------- .../BlackJack/BlackJack_Client/stdafx.cpp | 16 ++-------------- .../BlackJack/BlackJack_Client/stdafx.h | 16 ++-------------- .../BlackJack/BlackJack_Client/targetver.h | 16 ++-------------- .../BlackJack_Server/BlackJack_Server.cpp | 16 ++-------------- .../BlackJack/BlackJack_Server/Dealer.cpp | 16 ++-------------- .../BlackJack/BlackJack_Server/Table.cpp | 16 ++-------------- .../samples/BlackJack/BlackJack_Server/Table.h | 16 ++-------------- .../BlackJack/BlackJack_Server/messagetypes.h | 16 ++-------------- .../BlackJack/BlackJack_Server/stdafx.cpp | 16 ++-------------- .../BlackJack/BlackJack_Server/stdafx.h | 16 ++-------------- .../BlackJack/BlackJack_UIClient/App.xaml.cpp | 18 +++--------------- .../BlackJack/BlackJack_UIClient/App.xaml.h | 18 +++--------------- .../BlackJack_UIClient/CardShape.xaml.cpp | 18 +++--------------- .../BlackJack_UIClient/CardShape.xaml.h | 18 +++--------------- .../BlackJack_UIClient/Player.xaml.cpp | 18 +++--------------- .../BlackJack/BlackJack_UIClient/Player.xaml.h | 18 +++--------------- .../BlackJack_UIClient/PlayingTable.xaml.cpp | 18 +++--------------- .../BlackJack_UIClient/PlayingTable.xaml.h | 18 +++--------------- .../BlackJack_UIClient/messagetypes.h | 16 ++-------------- .../BlackJack/BlackJack_UIClient/pch.cpp | 18 +++--------------- .../samples/BlackJack/BlackJack_UIClient/pch.h | 18 +++--------------- Release/samples/CasaLens/casalens.cpp | 16 ++-------------- Release/samples/CasaLens/casalens.h | 16 ++-------------- Release/samples/CasaLens/datafetcher.cpp | 16 ++-------------- Release/samples/CasaLens/stdafx.cpp | 16 ++-------------- Release/samples/CasaLens/stdafx.h | 16 ++-------------- Release/samples/FacebookDemo/App.xaml | 15 +++------------ Release/samples/FacebookDemo/App.xaml.cpp | 18 +++--------------- Release/samples/FacebookDemo/App.xaml.h | 18 +++--------------- .../FacebookDemo/Common/StandardStyles.xaml | 15 +++------------ Release/samples/FacebookDemo/Facebook.cpp | 16 ++-------------- Release/samples/FacebookDemo/Facebook.h | 16 ++-------------- Release/samples/FacebookDemo/MainPage.xaml | 15 +++------------ Release/samples/FacebookDemo/MainPage.xaml.cpp | 18 +++--------------- Release/samples/FacebookDemo/MainPage.xaml.h | 18 +++--------------- Release/samples/FacebookDemo/pch.cpp | 18 +++--------------- Release/samples/FacebookDemo/pch.h | 18 +++--------------- Release/samples/OAuth2Live/pch.h | 17 +++-------------- Release/samples/Oauth1Client/Oauth1Client.cpp | 16 ++-------------- Release/samples/Oauth1Client/stdafx.cpp | 16 ++-------------- Release/samples/Oauth1Client/stdafx.h | 16 ++-------------- Release/samples/Oauth2Client/Oauth2Client.cpp | 16 ++-------------- Release/samples/Oauth2Client/stdafx.cpp | 16 ++-------------- Release/samples/Oauth2Client/stdafx.h | 16 ++-------------- Release/samples/SearchFile/searchfile.cpp | 16 ++-------------- Release/samples/WindowsLiveAuth/App.xaml.cpp | 18 +++--------------- Release/samples/WindowsLiveAuth/App.xaml.h | 18 +++--------------- .../samples/WindowsLiveAuth/MainPage.xaml.cpp | 18 +++--------------- .../samples/WindowsLiveAuth/MainPage.xaml.h | 18 +++--------------- Release/samples/WindowsLiveAuth/live_connect.h | 16 ++-------------- Release/samples/WindowsLiveAuth/pch.cpp | 18 +++--------------- Release/samples/WindowsLiveAuth/pch.h | 18 +++--------------- Release/src/http/client/http_client.cpp | 16 ++-------------- Release/src/http/client/http_client_asio.cpp | 16 ++-------------- Release/src/http/client/http_client_impl.h | 16 ++-------------- Release/src/http/client/http_client_msg.cpp | 16 ++-------------- .../src/http/client/http_client_winhttp.cpp | 16 ++-------------- Release/src/http/client/http_client_winrt.cpp | 16 ++-------------- .../src/http/client/x509_cert_utilities.cpp | 16 ++-------------- Release/src/http/common/http_helpers.cpp | 16 ++-------------- Release/src/http/common/http_msg.cpp | 16 ++-------------- Release/src/http/listener/http_listener.cpp | 16 ++-------------- .../src/http/listener/http_listener_msg.cpp | 16 ++-------------- Release/src/http/listener/http_server_api.cpp | 16 ++-------------- Release/src/http/listener/http_server_asio.cpp | 16 ++-------------- .../src/http/listener/http_server_httpsys.cpp | 16 ++-------------- Release/src/http/oauth/oauth1.cpp | 16 ++-------------- Release/src/http/oauth/oauth2.cpp | 16 ++-------------- Release/src/json/json.cpp | 16 ++-------------- Release/src/json/json_parsing.cpp | 16 ++-------------- Release/src/json/json_serialization.cpp | 16 ++-------------- Release/src/pch/stdafx.cpp | 16 ++-------------- Release/src/pch/stdafx.h | 16 ++-------------- Release/src/pplx/pplx.cpp | 16 ++-------------- Release/src/pplx/pplxapple.cpp | 18 +++--------------- Release/src/pplx/pplxlinux.cpp | 16 ++-------------- Release/src/pplx/pplxwin.cpp | 16 ++-------------- Release/src/pplx/threadpool.cpp | 16 ++-------------- Release/src/streams/fileio_posix.cpp | 16 ++-------------- Release/src/streams/fileio_win32.cpp | 16 ++-------------- Release/src/streams/fileio_winrt.cpp | 16 ++-------------- Release/src/uri/uri.cpp | 16 ++-------------- Release/src/uri/uri_builder.cpp | 16 ++-------------- Release/src/uri/uri_parser.cpp | 16 ++-------------- Release/src/utilities/asyncrt_utils.cpp | 16 ++-------------- Release/src/utilities/base64.cpp | 16 ++-------------- Release/src/utilities/web_utilities.cpp | 16 ++-------------- Release/src/websockets/client/ws_client.cpp | 16 ++-------------- .../src/websockets/client/ws_client_winrt.cpp | 16 ++-------------- .../src/websockets/client/ws_client_wspp.cpp | 16 ++-------------- Release/src/websockets/client/ws_msg.cpp | 16 ++-------------- .../ios/ios_runnerTests/ios_runnerTests.mm | 15 ++------------- .../common/TestRunner/test_module_loader.cpp | 16 ++-------------- .../common/TestRunner/test_module_loader.h | 16 ++-------------- .../tests/common/TestRunner/test_runner.cpp | 16 ++-------------- .../include/common_utilities_public.h | 16 ++-------------- .../common/utilities/include/locale_guard.h | 16 ++-------------- .../common/utilities/include/os_utilities.h | 16 ++-------------- .../tests/common/utilities/os_utilities.cpp | 16 ++-------------- Release/tests/common/utilities/stdafx.cpp | 16 ++-------------- Release/tests/common/utilities/stdafx.h | 16 ++-------------- Release/tests/common/utilities/targetver.h | 16 ++-------------- .../http/client/authentication_tests.cpp | 16 ++-------------- .../http/client/building_request_tests.cpp | 16 ++-------------- .../http/client/client_construction.cpp | 16 ++-------------- .../http/client/connections_and_errors.cpp | 16 ++-------------- .../functional/http/client/header_tests.cpp | 16 ++-------------- .../http/client/http_client_fuzz_tests.cpp | 16 ++-------------- .../http/client/http_client_tests.cpp | 16 ++-------------- .../functional/http/client/http_client_tests.h | 16 ++-------------- .../http/client/http_methods_tests.cpp | 16 ++-------------- .../http/client/multiple_requests.cpp | 16 ++-------------- .../functional/http/client/oauth1_tests.cpp | 16 ++-------------- .../functional/http/client/oauth2_tests.cpp | 16 ++-------------- .../functional/http/client/outside_tests.cpp | 16 ++-------------- .../http/client/pipeline_stage_tests.cpp | 16 ++-------------- .../http/client/progress_handler_tests.cpp | 16 ++-------------- .../functional/http/client/proxy_tests.cpp | 17 +++-------------- .../http/client/request_helper_tests.cpp | 16 ++-------------- .../http/client/request_stream_tests.cpp | 16 ++-------------- .../http/client/request_uri_tests.cpp | 16 ++-------------- .../http/client/response_extract_tests.cpp | 16 ++-------------- .../http/client/response_stream_tests.cpp | 16 ++-------------- .../client/status_code_reason_phrase_tests.cpp | 16 ++-------------- .../tests/functional/http/client/stdafx.cpp | 16 ++-------------- Release/tests/functional/http/client/stdafx.h | 16 ++-------------- .../functional/http/client/timeout_handler.h | 16 ++-------------- .../functional/http/client/to_string_tests.cpp | 16 ++-------------- .../listener/listener_construction_tests.cpp | 2 +- .../http/listener/request_handler_tests.cpp | 16 ++-------------- .../functional/http/utilities/http_asserts.cpp | 16 ++-------------- .../http/utilities/include/http_asserts.h | 16 ++-------------- .../utilities/include/http_test_utilities.h | 16 ++-------------- .../include/http_test_utilities_public.h | 16 ++-------------- .../http/utilities/include/test_http_client.h | 16 ++-------------- .../http/utilities/include/test_http_server.h | 16 ++-------------- .../utilities/include/test_server_utilities.h | 16 ++-------------- .../tests/functional/http/utilities/stdafx.cpp | 16 ++-------------- .../tests/functional/http/utilities/stdafx.h | 17 ++--------------- .../http/utilities/test_http_client.cpp | 16 ++-------------- .../http/utilities/test_http_server.cpp | 16 ++-------------- .../http/utilities/test_server_utilities.cpp | 16 ++-------------- .../functional/json/construction_tests.cpp | 18 +++--------------- Release/tests/functional/json/fuzz_tests.cpp | 16 ++-------------- .../tests/functional/json/iterator_tests.cpp | 16 ++-------------- .../functional/json/json_numbers_tests.cpp | 16 ++-------------- Release/tests/functional/json/json_tests.h | 16 ++-------------- .../functional/json/negative_parsing_tests.cpp | 16 ++-------------- .../tests/functional/json/parsing_tests.cpp | 16 ++-------------- Release/tests/functional/json/stdafx.cpp | 16 ++-------------- Release/tests/functional/json/stdafx.h | 16 ++-------------- .../json/to_as_and_operators_tests.cpp | 16 ++-------------- .../misc/atl_headers/header_test1.cpp | 16 ++-------------- .../misc/atl_headers/header_test2.cpp | 16 ++-------------- .../tests/functional/misc/version/version.cpp | 16 ++-------------- .../functional/pplx/pplx_test/pplx_op_test.cpp | 16 ++-------------- .../pplx/pplx_test/pplx_task_options.cpp | 16 ++-------------- .../pplx/pplx_test/pplxtask_tests.cpp | 16 ++-------------- .../tests/functional/pplx/pplx_test/stdafx.cpp | 16 ++-------------- .../tests/functional/pplx/pplx_test/stdafx.h | 16 ++-------------- .../tests/functional/streams/CppSparseFile.h | 16 ++-------------- .../functional/streams/fstreambuf_tests.cpp | 16 ++-------------- .../tests/functional/streams/fuzz_tests.cpp | 16 ++-------------- .../tests/functional/streams/istream_tests.cpp | 16 ++-------------- .../functional/streams/memstream_tests.cpp | 16 ++-------------- .../tests/functional/streams/ostream_tests.cpp | 16 ++-------------- Release/tests/functional/streams/prefix.h | 16 ++-------------- Release/tests/functional/streams/stdafx.cpp | 16 ++-------------- Release/tests/functional/streams/stdafx.h | 16 ++-------------- .../functional/streams/stdstream_tests.cpp | 16 ++-------------- .../tests/functional/streams/streams_tests.h | 16 ++-------------- .../functional/streams/winrt_interop_tests.cpp | 16 ++-------------- .../tests/functional/uri/accessor_tests.cpp | 16 ++-------------- .../tests/functional/uri/combining_tests.cpp | 16 ++-------------- .../tests/functional/uri/constructor_tests.cpp | 16 ++-------------- .../tests/functional/uri/conversions_tests.cpp | 16 ++-------------- .../tests/functional/uri/diagnostic_tests.cpp | 16 ++-------------- .../tests/functional/uri/encoding_tests.cpp | 18 +++--------------- .../tests/functional/uri/operator_tests.cpp | 16 ++-------------- .../tests/functional/uri/splitting_tests.cpp | 16 ++-------------- Release/tests/functional/uri/stdafx.cpp | 16 ++-------------- Release/tests/functional/uri/stdafx.h | 16 ++-------------- .../tests/functional/uri/uri_builder_tests.cpp | 16 ++-------------- Release/tests/functional/uri/uri_tests.h | 16 ++-------------- Release/tests/functional/utils/base64.cpp | 16 ++-------------- Release/tests/functional/utils/datetime.cpp | 16 ++-------------- Release/tests/functional/utils/macro_test.cpp | 16 ++-------------- .../functional/utils/nonce_generator_tests.cpp | 16 ++-------------- Release/tests/functional/utils/stdafx.cpp | 16 ++-------------- Release/tests/functional/utils/stdafx.h | 16 ++-------------- Release/tests/functional/utils/strings.cpp | 18 +++--------------- Release/tests/functional/utils/utils_tests.h | 16 ++-------------- .../websockets/client/authentication_tests.cpp | 16 ++-------------- .../websockets/client/client_construction.cpp | 16 ++-------------- .../websockets/client/close_tests.cpp | 16 ++-------------- .../websockets/client/error_tests.cpp | 18 +++--------------- .../websockets/client/proxy_tests.cpp | 16 ++-------------- .../websockets/client/receive_msg_tests.cpp | 16 ++-------------- .../websockets/client/send_msg_tests.cpp | 16 ++-------------- .../functional/websockets/client/stdafx.cpp | 16 ++-------------- .../functional/websockets/client/stdafx.h | 16 ++-------------- .../websockets/client/websocket_client_tests.h | 16 ++-------------- .../functional/websockets/utilities/stdafx.cpp | 16 ++-------------- .../functional/websockets/utilities/stdafx.h | 17 ++--------------- .../utilities/test_websocket_server.cpp | 16 ++-------------- .../utilities/test_websocket_server.h | 16 ++-------------- 250 files changed, 533 insertions(+), 3511 deletions(-) diff --git a/Build_android/configure.sh b/Build_android/configure.sh index 75697672a6..fd17fb7007 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -1,19 +1,6 @@ #!/bin/bash -# ==++== -# -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ==--== +# Copyright (C) Microsoft. All rights reserved. +# Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. # =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ # # configure.sh diff --git a/Release/include/cpprest/astreambuf.h b/Release/include/cpprest/astreambuf.h index 7b431fcde4..cf75ebaff9 100644 --- a/Release/include/cpprest/astreambuf.h +++ b/Release/include/cpprest/astreambuf.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Asynchronous I/O: stream buffer. This is an extension to the PPL concurrency features and therefore diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 73b6f5b97e..1c3bba979a 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Various common utilities. diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index e6428e3e5c..a8b0f54ff4 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Protocol independent support for URIs. diff --git a/Release/include/cpprest/containerstream.h b/Release/include/cpprest/containerstream.h index 12c1af2fe9..63ead19f9b 100644 --- a/Release/include/cpprest/containerstream.h +++ b/Release/include/cpprest/containerstream.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * This file defines a basic STL-container-based stream buffer. Reading from the buffer will not remove any data diff --git a/Release/include/cpprest/details/basic_types.h b/Release/include/cpprest/details/basic_types.h index ea28f8260f..36aad71b98 100644 --- a/Release/include/cpprest/details/basic_types.h +++ b/Release/include/cpprest/details/basic_types.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Platform-dependent type definitions diff --git a/Release/include/cpprest/details/cpprest_compat.h b/Release/include/cpprest/details/cpprest_compat.h index 240a338995..ebd1c935ec 100644 --- a/Release/include/cpprest/details/cpprest_compat.h +++ b/Release/include/cpprest/details/cpprest_compat.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Standard macros and definitions. diff --git a/Release/include/cpprest/details/fileio.h b/Release/include/cpprest/details/fileio.h index 47186412d6..f60947daf1 100644 --- a/Release/include/cpprest/details/fileio.h +++ b/Release/include/cpprest/details/fileio.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * fileio.h diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 0ef034b606..35d1e053d2 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Implementation Details of the http.h layer of messaging diff --git a/Release/include/cpprest/details/http_server.h b/Release/include/cpprest/details/http_server.h index 558374254a..0a94b0361b 100644 --- a/Release/include/cpprest/details/http_server.h +++ b/Release/include/cpprest/details/http_server.h @@ -1,20 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: interface to implement HTTP server to service http_listeners. diff --git a/Release/include/cpprest/details/http_server_api.h b/Release/include/cpprest/details/http_server_api.h index 492f1f7b79..e44e104f02 100644 --- a/Release/include/cpprest/details/http_server_api.h +++ b/Release/include/cpprest/details/http_server_api.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: exposes the entry points to the http server transport apis. diff --git a/Release/include/cpprest/details/http_server_asio.h b/Release/include/cpprest/details/http_server_asio.h index c9ed53b006..3471282dd7 100644 --- a/Release/include/cpprest/details/http_server_asio.h +++ b/Release/include/cpprest/details/http_server_asio.h @@ -1,16 +1,7 @@ -/* -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +****/ #pragma once diff --git a/Release/include/cpprest/details/http_server_httpsys.h b/Release/include/cpprest/details/http_server_httpsys.h index 6ae9cc1e85..2523d62e4e 100644 --- a/Release/include/cpprest/details/http_server_httpsys.h +++ b/Release/include/cpprest/details/http_server_httpsys.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: implementation of HTTP server API built on Windows HTTP Server APIs. diff --git a/Release/include/cpprest/details/nosal.h b/Release/include/cpprest/details/nosal.h index 4d7e583a7c..7aeeec03de 100644 --- a/Release/include/cpprest/details/nosal.h +++ b/Release/include/cpprest/details/nosal.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk * diff --git a/Release/include/cpprest/details/uri_parser.h b/Release/include/cpprest/details/uri_parser.h index af458c49bb..6cf023126c 100644 --- a/Release/include/cpprest/details/uri_parser.h +++ b/Release/include/cpprest/details/uri_parser.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * URI parsing implementation diff --git a/Release/include/cpprest/details/web_utilities.h b/Release/include/cpprest/details/web_utilities.h index 0fe97193bb..b7bf2276bd 100644 --- a/Release/include/cpprest/details/web_utilities.h +++ b/Release/include/cpprest/details/web_utilities.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * utility classes used by the different web:: clients diff --git a/Release/include/cpprest/details/x509_cert_utilities.h b/Release/include/cpprest/details/x509_cert_utilities.h index 5cfa561be5..cc40d9ccfb 100644 --- a/Release/include/cpprest/details/x509_cert_utilities.h +++ b/Release/include/cpprest/details/x509_cert_utilities.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Contains utility functions for helping to verify server certificates in OS X/iOS and Android. diff --git a/Release/include/cpprest/filestream.h b/Release/include/cpprest/filestream.h index 3e0864b950..2e60732b05 100644 --- a/Release/include/cpprest/filestream.h +++ b/Release/include/cpprest/filestream.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Asynchronous File streams diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index e5d2f3677a..b874247f4e 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: Client-side APIs. diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 0d318cbee4..c352b49bb7 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk diff --git a/Release/include/cpprest/http_listener.h b/Release/include/cpprest/http_listener.h index 329a2f1c06..1ff260bbfc 100644 --- a/Release/include/cpprest/http_listener.h +++ b/Release/include/cpprest/http_listener.h @@ -1,20 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: HTTP listener (server-side) APIs diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index b2721f9ebc..5740569922 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: Request and reply message definitions. diff --git a/Release/include/cpprest/interopstream.h b/Release/include/cpprest/interopstream.h index b1fc150ff1..5cf575aa0e 100644 --- a/Release/include/cpprest/interopstream.h +++ b/Release/include/cpprest/interopstream.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Adapter classes for async and STD stream buffers, used to connect std-based and async-based APIs. diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 704cbfad91..5f614c80f6 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: JSON parser and writer diff --git a/Release/include/cpprest/oauth1.h b/Release/include/cpprest/oauth1.h index f464da0f06..1dc790b2e2 100755 --- a/Release/include/cpprest/oauth1.h +++ b/Release/include/cpprest/oauth1.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: Oauth 1.0 diff --git a/Release/include/cpprest/oauth2.h b/Release/include/cpprest/oauth2.h index 69c8dbcca6..39b77e643c 100644 --- a/Release/include/cpprest/oauth2.h +++ b/Release/include/cpprest/oauth2.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * HTTP Library: Oauth 2.0 diff --git a/Release/include/cpprest/producerconsumerstream.h b/Release/include/cpprest/producerconsumerstream.h index 2d33d4f584..4e10872f45 100644 --- a/Release/include/cpprest/producerconsumerstream.h +++ b/Release/include/cpprest/producerconsumerstream.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * This file defines a basic memory-based stream buffer, which allows consumer / producer pairs to communicate diff --git a/Release/include/cpprest/rawptrstream.h b/Release/include/cpprest/rawptrstream.h index 402a65102b..3fdbb99cb3 100644 --- a/Release/include/cpprest/rawptrstream.h +++ b/Release/include/cpprest/rawptrstream.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * This file defines a stream buffer that is based on a raw pointer and block size. Unlike a vector-based diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 45ae22e03b..7e4128984b 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Asynchronous I/O: streams API, used for formatted input and output, based on unformatted I/O using stream buffers diff --git a/Release/include/cpprest/uri.h b/Release/include/cpprest/uri.h index f61fa4b034..a26618cf89 100644 --- a/Release/include/cpprest/uri.h +++ b/Release/include/cpprest/uri.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Protocol independent support for URIs. diff --git a/Release/include/cpprest/uri_builder.h b/Release/include/cpprest/uri_builder.h index e4fb2024fd..564a22a592 100644 --- a/Release/include/cpprest/uri_builder.h +++ b/Release/include/cpprest/uri_builder.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Builder style class for creating URIs. diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index 11afd6b90d..e197de4118 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== */ #define CPPREST_VERSION_REVISION 0 #define CPPREST_VERSION_MINOR 9 diff --git a/Release/include/cpprest/ws_client.h b/Release/include/cpprest/ws_client.h index 6ce052342e..9c9e5d818d 100644 --- a/Release/include/cpprest/ws_client.h +++ b/Release/include/cpprest/ws_client.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Websocket client side implementation diff --git a/Release/include/cpprest/ws_msg.h b/Release/include/cpprest/ws_msg.h index b22ecad058..326541c7a1 100644 --- a/Release/include/cpprest/ws_msg.h +++ b/Release/include/cpprest/ws_msg.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Websocket incoming and outgoing message definitions. diff --git a/Release/include/pplx/pplx.h b/Release/include/pplx/pplx.h index 68c36cd764..5a7c970319 100644 --- a/Release/include/pplx/pplx.h +++ b/Release/include/pplx/pplx.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Parallel Patterns Library diff --git a/Release/include/pplx/pplxcancellation_token.h b/Release/include/pplx/pplxcancellation_token.h index a191a93607..634e4fafb3 100644 --- a/Release/include/pplx/pplxcancellation_token.h +++ b/Release/include/pplx/pplxcancellation_token.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Parallel Patterns Library : cancellation_token diff --git a/Release/include/pplx/pplxconv.h b/Release/include/pplx/pplxconv.h index 9acf946b0b..9023064aed 100644 --- a/Release/include/pplx/pplxconv.h +++ b/Release/include/pplx/pplxconv.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Utilities to convert between PPL tasks and PPLX tasks diff --git a/Release/include/pplx/pplxinterface.h b/Release/include/pplx/pplxinterface.h index d652d2c9a8..5df5777182 100644 --- a/Release/include/pplx/pplxinterface.h +++ b/Release/include/pplx/pplxinterface.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * PPL interfaces diff --git a/Release/include/pplx/pplxlinux.h b/Release/include/pplx/pplxlinux.h index 908c1aa2df..6aa1ba352e 100644 --- a/Release/include/pplx/pplxlinux.h +++ b/Release/include/pplx/pplxlinux.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Linux specific pplx implementations diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index 760a614538..516a10d4f7 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Parallel Patterns Library - PPLx Tasks diff --git a/Release/include/pplx/pplxwin.h b/Release/include/pplx/pplxwin.h index c60ff9090f..ba9ebd8b92 100644 --- a/Release/include/pplx/pplxwin.h +++ b/Release/include/pplx/pplxwin.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Windows specific pplx implementations diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index 4a88a75c44..1b25eb3871 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * * Simple Linux implementation of a static thread pool. * diff --git a/Release/samples/BingRequest/bingrequest.cpp b/Release/samples/BingRequest/bingrequest.cpp index 671690abc3..f6b1ae980d 100644 --- a/Release/samples/BingRequest/bingrequest.cpp +++ b/Release/samples/BingRequest/bingrequest.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * bingrequest.cpp - Simple cmd line application that makes an HTTP GET request to bing searching and outputting diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp index c9ab0f5a52..0e84d14d69 100644 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp +++ b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * BlackJackClient.cpp : Defines the entry point for the console application diff --git a/Release/samples/BlackJack/BlackJack_Client/stdafx.cpp b/Release/samples/BlackJack/BlackJack_Client/stdafx.cpp index 26c94a4565..cd389fa0d6 100644 --- a/Release/samples/BlackJack/BlackJack_Client/stdafx.cpp +++ b/Release/samples/BlackJack/BlackJack_Client/stdafx.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * stdafx.cpp : source file that includes just the standard includes diff --git a/Release/samples/BlackJack/BlackJack_Client/stdafx.h b/Release/samples/BlackJack/BlackJack_Client/stdafx.h index 3a1bd72ac8..82b776702a 100644 --- a/Release/samples/BlackJack/BlackJack_Client/stdafx.h +++ b/Release/samples/BlackJack/BlackJack_Client/stdafx.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * stdafx.h : include file for standard system include files, diff --git a/Release/samples/BlackJack/BlackJack_Client/targetver.h b/Release/samples/BlackJack/BlackJack_Client/targetver.h index 45a9dabfac..951583c45d 100644 --- a/Release/samples/BlackJack/BlackJack_Client/targetver.h +++ b/Release/samples/BlackJack/BlackJack_Client/targetver.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * targetver.h diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server.cpp b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server.cpp index f327b9ba90..351d3dc65c 100644 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server.cpp +++ b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * BlackJack_Servr.cpp - Simple server application for blackjack diff --git a/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp b/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp index cbfb0b6a83..b03cab9e26 100644 --- a/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp +++ b/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Dealer.cpp : Contains the main logic of the black jack dealer diff --git a/Release/samples/BlackJack/BlackJack_Server/Table.cpp b/Release/samples/BlackJack/BlackJack_Server/Table.cpp index 387e5bb4dd..9473b37945 100644 --- a/Release/samples/BlackJack/BlackJack_Server/Table.cpp +++ b/Release/samples/BlackJack/BlackJack_Server/Table.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Table.cpp : Contains the main logic of game diff --git a/Release/samples/BlackJack/BlackJack_Server/Table.h b/Release/samples/BlackJack/BlackJack_Server/Table.h index da109e095c..856a27c5f0 100644 --- a/Release/samples/BlackJack/BlackJack_Server/Table.h +++ b/Release/samples/BlackJack/BlackJack_Server/Table.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Table.h diff --git a/Release/samples/BlackJack/BlackJack_Server/messagetypes.h b/Release/samples/BlackJack/BlackJack_Server/messagetypes.h index a00167f384..b48fcfde0d 100644 --- a/Release/samples/BlackJack/BlackJack_Server/messagetypes.h +++ b/Release/samples/BlackJack/BlackJack_Server/messagetypes.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * messagetypes.h diff --git a/Release/samples/BlackJack/BlackJack_Server/stdafx.cpp b/Release/samples/BlackJack/BlackJack_Server/stdafx.cpp index 523a51f47b..283f636882 100644 --- a/Release/samples/BlackJack/BlackJack_Server/stdafx.cpp +++ b/Release/samples/BlackJack/BlackJack_Server/stdafx.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * stdafx.cpp : source file that includes just the standard includes diff --git a/Release/samples/BlackJack/BlackJack_Server/stdafx.h b/Release/samples/BlackJack/BlackJack_Server/stdafx.h index 18966e36c6..15f4ceb58f 100644 --- a/Release/samples/BlackJack/BlackJack_Server/stdafx.h +++ b/Release/samples/BlackJack/BlackJack_Server/stdafx.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * stdafx.h : include file for standard system include files, diff --git a/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.cpp b/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.cpp index 704671df33..7ec9f8da64 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.cpp @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * App.xaml.cpp - Implementation of the App class. diff --git a/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.h b/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.h index 0e68d4354e..f5492ebfcb 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/App.xaml.h @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * App.xaml.h - Declaration of the App class. diff --git a/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.cpp b/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.cpp index 5e40e37122..3e20598bb7 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.cpp @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * CardShape.xaml.cpp - Implementation of the CardShape class diff --git a/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.h b/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.h index 7de62f4ee8..8a54c43d33 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/CardShape.xaml.h @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * CardShape.xaml.h - Declaration of the CardShape class diff --git a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp index df4ffe6aaf..5245c22749 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Player.xaml.cpp: Implementation of the Player class. diff --git a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h index f3a326f121..a8d4fdb3fc 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Player.xaml.h: Declaration of the Player class. diff --git a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp index 562d0bb181..809fa4b180 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Table.xaml.cpp: Implementation of the Table.xaml class. diff --git a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h index 3cdfe3189a..f1fe3e28be 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * Table.xaml.h: Declaration of the Table.xaml class. diff --git a/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h b/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h index e56f6f3023..cea826c559 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * messagetypes.h diff --git a/Release/samples/BlackJack/BlackJack_UIClient/pch.cpp b/Release/samples/BlackJack/BlackJack_UIClient/pch.cpp index 3de5c74e6f..dfd959aa19 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/pch.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/pch.cpp @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * pch.cpp: Include the standard header and generate the precompiled header. diff --git a/Release/samples/BlackJack/BlackJack_UIClient/pch.h b/Release/samples/BlackJack/BlackJack_UIClient/pch.h index f467376252..65fb42f8fc 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/pch.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/pch.h @@ -1,19 +1,7 @@ -/*** -* ==++== +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * pch.h: Header for standard system include files. diff --git a/Release/samples/CasaLens/casalens.cpp b/Release/samples/CasaLens/casalens.cpp index d2dde0a6e3..6b436c5cab 100644 --- a/Release/samples/CasaLens/casalens.cpp +++ b/Release/samples/CasaLens/casalens.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * casalens.cpp: Listener code: Given a location/postal code, the listener queries different services diff --git a/Release/samples/CasaLens/casalens.h b/Release/samples/CasaLens/casalens.h index a296698336..7d75f14cae 100644 --- a/Release/samples/CasaLens/casalens.h +++ b/Release/samples/CasaLens/casalens.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * casalens.h: Listener code: Given a location/postal code, the listener queries different services diff --git a/Release/samples/CasaLens/datafetcher.cpp b/Release/samples/CasaLens/datafetcher.cpp index 6039a7e1a9..b3e41ada00 100644 --- a/Release/samples/CasaLens/datafetcher.cpp +++ b/Release/samples/CasaLens/datafetcher.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * datafetcher.cpp: Listener code: Given a location/postal code, the listener queries different services diff --git a/Release/samples/CasaLens/stdafx.cpp b/Release/samples/CasaLens/stdafx.cpp index 5398581b84..96f92dea02 100644 --- a/Release/samples/CasaLens/stdafx.cpp +++ b/Release/samples/CasaLens/stdafx.cpp @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * stdafx.cpp diff --git a/Release/samples/CasaLens/stdafx.h b/Release/samples/CasaLens/stdafx.h index cdac77bed8..7b1debc1db 100644 --- a/Release/samples/CasaLens/stdafx.h +++ b/Release/samples/CasaLens/stdafx.h @@ -1,19 +1,7 @@ /*** -* ==++== +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* ==--== * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * * stdafx.h : include file for standard system include files, diff --git a/Release/samples/FacebookDemo/App.xaml b/Release/samples/FacebookDemo/App.xaml index 8aba49f654..fa7eb1060b 100644 --- a/Release/samples/FacebookDemo/App.xaml +++ b/Release/samples/FacebookDemo/App.xaml @@ -1,15 +1,6 @@ - + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root)) + $(BuildRoot)\Binaries\$(Platform)\$(Configuration)\ + $(OutputPath) + $(BuildRoot)\Release\src + $(BuildRoot)\Release\include + + + + + /bigobj %(AdditionalOptions) + NotUsing + Disabled + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + Disabled + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + + + + + + + \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj.filters b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj.filters new file mode 100644 index 0000000000..bb6411f159 --- /dev/null +++ b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj.filters @@ -0,0 +1,12 @@ + + + + + + + + + Source Files + + + \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj new file mode 100644 index 0000000000..f06fd04ff8 --- /dev/null +++ b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {830b6e2f-9224-41d1-b9c7-a51fc78b00c7} + Win32Proj + BlackJack_Client + SAK + SAK + SAK + SAK + $(VCTargetsPath12) + + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + + + + + + Create + Create + Create + Create + + + + + + + + \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj.filters new file mode 100644 index 0000000000..d19e3a56d0 --- /dev/null +++ b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + h;hpp;hxx;hm;inl;inc;xsd + + + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj new file mode 100644 index 0000000000..928d64e91c --- /dev/null +++ b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {84350cd1-d406-4a4f-9571-261ca46d77c5} + Win32Proj + BlackJack_Server + SAK + SAK + SAK + $(VCTargetsPath12) + SAK + + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj.filters new file mode 100644 index 0000000000..a13f88916c --- /dev/null +++ b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + h;hpp;hxx;hm;inl;inc;xsd + + + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj index 97459a28e4..00535c0cdb 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj +++ b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj @@ -138,7 +138,7 @@ - + Designer diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj index d38005e2cf..2a0c920c4b 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj +++ b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj @@ -43,35 +43,35 @@ Application true - v120 + v140 Application true - v120 + v140 Application true - v120 + v140 Application false true - v120 + v140 Application false true - v120 + v140 Application false true - v120 + v140 @@ -138,7 +138,7 @@ - + Designer diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj new file mode 100644 index 0000000000..2479ddea21 --- /dev/null +++ b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj @@ -0,0 +1,185 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {b8d3f85b-da71-4aca-87ba-10fed681dc79} + BlackJack_UIClient + en-US + 14.0 + true + SAK + SAK + SAK + SAK + Windows Store + 10.0 + 10.0.10240.0 + 10.0.10240.0 + + + + Application + true + v141 + + + Application + true + v141 + + + Application + true + v141 + + + Application + false + true + v141 + + + Application + false + true + v141 + + + Application + false + true + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + BlackJack_UIClient_TemporaryKey.pfx + + + + pch.h + WIN32;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);%(AdditionalIncludeDirectories) + 4100;4267;4450;4453;4702;%(DisableSpecificWarnings) + + + + $(OutDir)\$(MSBuildProjectName)\ + 5C945ED108BF1723994A90F9BAA4B7D93FBE0E47 + + + + CardShape.xaml + + + + App.xaml + + + Player.xaml + + + PlayingTable.xaml + + + + + Designer + + + + Designer + + + + + + + + + + + + + + + + + App.xaml + + + CardShape.xaml + + + Create + Create + Create + Create + Create + Create + + + Player.xaml + + + PlayingTable.xaml + + + + + {198ED804-2655-4D92-8104-C220E3EA9452} + + + + + Designer + + + + \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_UIClient/Package120.appxmanifest b/Release/samples/BlackJack/BlackJack_UIClient/Package.appxmanifest similarity index 100% rename from Release/samples/BlackJack/BlackJack_UIClient/Package120.appxmanifest rename to Release/samples/BlackJack/BlackJack_UIClient/Package.appxmanifest diff --git a/Release/samples/BlackJack/BlackJack_UIClient/Package.uwp.appxmanifest b/Release/samples/BlackJack/BlackJack_UIClient/Package.uwp.appxmanifest new file mode 100644 index 0000000000..0ed116553c --- /dev/null +++ b/Release/samples/BlackJack/BlackJack_UIClient/Package.uwp.appxmanifest @@ -0,0 +1,34 @@ + + + + + Blackjack Client + Andy + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_UIClient/Package140.appxmanifest b/Release/samples/BlackJack/BlackJack_UIClient/Package140.appxmanifest deleted file mode 100644 index 45057a76b0..0000000000 --- a/Release/samples/BlackJack/BlackJack_UIClient/Package140.appxmanifest +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Blackjack Client - Microsoft Corporation - Assets\StoreLogo.png - - - 6.2.1 - 6.2.1 - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp index 809fa4b180..a6bd90995e 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp @@ -43,7 +43,7 @@ PlayingTable::PlayingTable() : m_dealerResource(L"dealer"), m_alreadyInsured(fal this->serverAddress->Text = ref new Platform::String(L"http://localhost:34568/blackjack/"); - this->playerName->Text = Windows::System::UserProfile::UserInformation::GetDisplayNameAsync()->GetResults(); + this->playerName->Text = L"Player"; size_t players = 5; diff --git a/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h b/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h index cea826c559..325b915c2f 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/messagetypes.h @@ -108,9 +108,9 @@ struct BJHand NumericHandValues GetNumericValues() { - NumericHandValues result; - result.low = 0; - result.low = 0; + NumericHandValues r; + r.low = 0; + r.low = 0; bool hasAces = false; @@ -118,17 +118,17 @@ struct BJHand { if ( iter->value == CV_Ace ) hasAces = true; - result.low += (iter->value < 10) ? iter->value : 10; + r.low += (iter->value < 10) ? iter->value : 10; } - result.high = hasAces ? result.low + 10 : result.low; - return result; + r.high = hasAces ? r.low + 10 : r.low; + return r; } BJHand(web::json::value object) { - web::json::value cards = object[CARDS]; + web::json::value l_cards = object[CARDS]; - for (auto iter = cards.as_array().begin(); iter != cards.as_array().end(); ++iter) + for (auto iter = l_cards.as_array().begin(); iter != l_cards.as_array().end(); ++iter) { if ( !iter->is_null() ) { diff --git a/Release/samples/CasaLens/CasaLens141/AppCode.html b/Release/samples/CasaLens/CasaLens141/AppCode.html new file mode 100644 index 0000000000..60ab734521 --- /dev/null +++ b/Release/samples/CasaLens/CasaLens141/AppCode.html @@ -0,0 +1,157 @@ + + + + Casa Lens | Casablana Test App + + + + + + + + + + +
+
+ +
+
+
+ +
+ + + + diff --git a/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj b/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj new file mode 100644 index 0000000000..bc93468518 --- /dev/null +++ b/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj @@ -0,0 +1,167 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} + SAK + SAK + SAK + SAK + Win32Proj + $(VCTargetsPath12) + + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + + + + + /bigobj -Zm140 %(AdditionalOptions) + Use + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj -Zm140 %(AdditionalOptions) + Use + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj -Zm140 %(AdditionalOptions) + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + /bigobj -Zm140 %(AdditionalOptions) + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Release/samples/CasaLens/CasaLens141/css/default.css b/Release/samples/CasaLens/CasaLens141/css/default.css new file mode 100644 index 0000000000..65809e84fd --- /dev/null +++ b/Release/samples/CasaLens/CasaLens141/css/default.css @@ -0,0 +1,97 @@ +body +{ + width: 100%; + height: 100%; + font-family: Calibri; + background-image: linear-gradient(20deg, white, #DDE6DF 62.6%, #24507C); + background-repeat: no-repeat; + background-size: 100% 100%; +} + +h4 { + height:25px; + text-align: center; +} + +.Logo { + width: 105.59px; + height: 103.64px; +} + +.searchBox { +} + +.textclass +{ + width: 46%; + font-family: "segoe ui"; +} + +.tftextbtn +{ + color: #fff; + display: inline-block; + background-color: rgb(230, 100, 0); + font-family: "segoe ui"; +} + +.PictureGallery { +} + +.mainPic { +} + +.thumbnailPic { +} + +.CurrentTemperature { + vertical-align:middle; + text-align: center; + font-size: 75px; +} + +.WeatherData { +} + +.EventTitle { + font-size: large; +} + +.EventDescription { + font-family:Helvetica; + word-wrap:break-word; + font-size:small; +} + +a:link {text-decoration:none;} +td +{ + vertical-align:top; + valign:top; +} + +.verticalLine { + border-left: thick solid #ff0000; +} + +.wrap-words { + word-wrap:break-word; +} + +.eventful-badge, +.eventful-badge * { + margin: 0 !important; + padding: 0 !important; + border: 0 !important; + text-align: center !important; + color: #CCC !important; + font-family: Arial !important; + text-decoration: none !important; +} + +.eventful-medium { + position: relative !important; + width: 100px !important; + font-size: 12px !important; + line-height: 13px !important; +} \ No newline at end of file diff --git a/Release/samples/CasaLens/CasaLens141/image/bing-logo.jpg b/Release/samples/CasaLens/CasaLens141/image/bing-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..22a2dbe521f7ca245a9652dc679d9d2235f86f88 GIT binary patch literal 6264 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 Ag#Z8m literal 0 HcmV?d00001 diff --git a/Release/samples/CasaLens/CasaLens141/image/logo.png b/Release/samples/CasaLens/CasaLens141/image/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1ba6835b106e61b45ef6d577554300cba86846c4 GIT binary patch literal 3923 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

PS{hmg26{$T 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⋘pF_=#!XHsoBu_o`VV%AXCp;=DSYI%0 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 z z;oldF01hj|e=pj}?lO5z-ZFnLAO-}@v(a2^6ac|1Gop2-FA$AWHY^H#y|O$`(tAKz zC8Ld-rWh$C@y45yaC~T`8mJFa4CFL$o5>!y8M8;6KVN$E%qVJ~66Aydxl`gAiYPLh zA=NkHi*qL2e*$*TZAv1DMjqzBFcA5>KY5>X-D3UxHZz;YOypcgP;l{SEy4tLph9qb zT*MUMw%>eA8#4JniJP>_*)w-iwdDj9NR`;g{XdCk`if?*vo}X7eC%2pZ-J>Mpxurc z>zt}vh>r*=^1R9*$0Q=i!u>iKgcnWdXR*f{q9i4I7@cyQrNq7~V$K{s!Qrni-bJGI zv{#%C?$CrNi`sH`35@tcT=IWIe)ElzvSrJ0k*P8~5S4LA->PKOKY#FptRwD>?^Osf z4?&Z>M45D8)!yNKVxwhwdIo7a<@9dFx+8-=Xw-!E z0%NAIMlI{<{AWmp=;UxzoE?P(sbujpTbu`G<{t)~q!e$Ro?3lN0>gx{gwMN9;m%SHUS=*sX&Bu6n$OdD;0ZCVbs7K_QY>`%=@@MdSC((vAg;!!^BXek}TG`wr7+4h2y)uA70gGkI0j%O+K1_BX1QdR;7@>w23!; zt6Um3>>>(kdx}6{{P|m0RaOHi3?J(JCvn7`xt@~rYdu2E`sb*rZyMdp0NmE7xy|y@ z!zYYWOj4{@y><`#qIsSWv4y#cCx>myLQ8moxq$tNxgr zthkpspeKDhf|?er7<+M1FfK9LW*YgAB93bu0zmnMK6{&(X^PX#RoWY00VVf@ea~M} zrMn5Lfl1q|6v0eu>9Z=^8g~;Brc$kUJ51)%^SRpVFyiUQOB`j9v`cNS9diwPpZ2Ij zhxZdweFiS7YO$dIo7+8Z0cm4~9qm1&HjEwF2VFe4W<%5GwfDV!ho#EWwKXgsRvtVb z#uT$pP8#W)r2s4lciMe$A|>rQFblqP@GjZD{&jVxfB~p3qh3a0SS_};z7($T8kKMj zxs9TDbQV9fCO=WZ^|0cyO zC5**Gh=|F!d!|vP*BC;l16^qszA39mZ%^kVPKCN#8UpLz`X+y&(TTP{27b?HqkIs} zt&-QC_GV7IVJB>82Ro$d&P@;J)Z6yw^T)5VPYog2tV4`_!1e&hnXf=`5rrAZm5C-D z!OLCAA@^A3Ox+VN2NWIA$qq(aSHcC<+ia%jH6DswjuDZfMZ*Lc8NE z;^m25x}Acd!#X_YSL4@gN-Q>?t{6yMB5ELeZ-7EEb)q>9e=X-Vxn~VpwjQ8jo_xX0 zQGjP@Y0_V2KVj8b@v(`>-vz~RqG6Qm>i0xH0j)hwrsjxv7c9}Qw4SAB50ZSCI-%@J zAX;b3q|G*e%7<}j3F>oTG9??JfPa0X;X6oDYdXLl_2G+{WV2a?GWdPRmjFzBfoZ>J zlfY5|2RFk1h_sYKl7%M*)>zv(P2W&SUm3?A@Xgu zaVAK7Xbe@HT~jkm8)5!!#?A+uqe%@C>a;$!rjKp&YnT`y41Q(a8?{T%D9I=G3&AiF zHxV9X9YF(^oM>@E=iZ{cR4)rNPf%V?X4Ss4wB_1#~U0``^M zYc}&{g-_#WP@E$2sx!~;M1yr(HMb*!V9_ZoEPBkm6wFwF!lkf!13AUKAqc# z8=*roLaA~}H&biArMv=I&e!|xlJ^&SuOfhnMxzRJLLS6g{HH+GoRE5hZ7B86wbFFX zDHcB#CgYP{IZDvjkMh#J449g@esWyS|C~WzqL@H9#(V_qwlff}vy&G&XwIf zd|Ga#p>s|n22VmaV_kOel5nmJGT zPEOGpei7SP{;_u}fL3_rwt=9%6%lv?jya7y-75dc0`>iOtQ2Gc1lw90XZownfFwhX zsWUiP57g*Uw=;5jzGee$Q?}hCoaA~K9GKR!q_DO8mf^xlh;{(uiCIhin@1>_Caly2 z`1l;GY90yI*MB~Vm67N{bOF#*M#+z#FzThnKuL>D{`qW_OOtgA*y9It{dT}~i)QMM z=m7#>DPPT*myT#YqkgW_I5lS$S?JDnjDv+uuiYv;n&{FgFH03Ppx}5c(ndEPwG^EZrKSe zyX}&X@op6vfsOM!>G#BjC7L-AUoct{l6#XHcI3|+dvn<(`u!a{fLyQs`V%WjIRy&= zO#<-og0`6t4~9iWXoWezTFJYC1*!p~1~ugm<&lIP!@UYY9ilbI&Bt@^fo@j0#r>7~ zdkMgT2tVSkw9jipYL~3>08bHU+Y{FATL{bldSWgm7}%CcgQVkf8^jB=qc48&f1P8O zXW7!9#u;}mQ8`0^;}~fKW-rIRGj7be7#vMUoi~fx9Kjt%c6|X9CfFanl!FVq{`855 z3qXaBcs2MoR}!?RP@PPG0JvhxdS4rMn%;CiU)6;v-_XGF>HAGS6!1n#=I(20&nl?{nbcHhPCPBHY zp6!?EX4VYS&`!8yLqvRiDm;w&lH#560%D+$JPB(4*0M9#{5+ol?E{-MKPF@Qy}j;+ zMxp?=Non<3k5QNKzA+3z1fm_@^2PF*7Y@!HNNS3&PQDB!?4b5{R4zb~lzZ2Q*wq`Uh&hMmf@!758X4=>_V2;?YwqTyTrTfp&NammkpTSJhp|)xLK3sX7?Br{%EYDn6vO;P93ZsPxOVEk(9nK;i+K^6xb$;fl`R3Bd)EhLbFmYknX*&)e1?l!%reWZxf!UZ%EL7bpdMt%-U=2MSvk;#-T&(uat;6U z(j=A?IuB~}`iiRXCj;U`UF1t!&8B}gg-xw8H!E4oGRkdm!!5HXm4?^!9|D<>k9`5! zeXM2mAHQ03>;|X(E42P1*)Xzhdr-^0J9UQ!7brGx$~!EXnRTXT996oxGVFgm!A|* zn*A#;k=~EBsf&1O)^1-J^uDOqD0U8z_;MPGr}8qq`gjPh^M1t=t{zFlaUMlxkp*jM zsdtoK%GwFd7TW9qEVoOqe`UNKlZ4^`YneT&I}>KukuV%%5@1` zAmQFF6)=cEWVq7sjItdvuQ(qR%GP#bcRKZch#aiQt2=7m0O4om*8L~3&p@Y>c}7qt z(N`)e0pvsAI#=Gz^?f_3K$6hwvMrq}RsYk?^B)_;lx zT4udwEapvnGy0xL;PEFIJzR~RfkoC&HN4pqG4*mndq1xnqjF!%wp_E4Z2t6&e7+zV zWSo-KJ$&a^V?{$ChDmU1I!^zYZQ7<>UM9~RtpRn}gOSYX*~LbXeD}q6=eISzuJ;}t z%O*c##=N>lz8`gc|NZ?gVSeAKkg6xf1{hn|0K~!%0AnFzYru^P{8s((;vtn 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 literal 0 HcmV?d00001 diff --git a/Release/samples/CasaLens/CasaLens141/js/default.js b/Release/samples/CasaLens/CasaLens141/js/default.js new file mode 100644 index 0000000000..b7e1ea2339 --- /dev/null +++ b/Release/samples/CasaLens/CasaLens141/js/default.js @@ -0,0 +1,173 @@ +function formatAMPM(date) { + var hours = date.getHours(); + var minutes = date.getMinutes(); + var ampm = hours >= 12 ? 'pm' : 'am'; + hours = hours % 12; + hours = hours ? hours : 12; // the hour '0' should be '12' + minutes = minutes < 10 ? '0' + minutes : minutes; + var strTime = hours + ':' + minutes + ' ' + ampm; + return strTime; +} + +function formatEventTime(dateTimeStr) { + dateTimeStr = dateTimeStr.substr(0, dateTimeStr.lastIndexOf(":")).split(" ").join("T") + var dateObj = new Date(dateTimeStr); + if (!dateObj) { + return ""; + } + var dateStr = dateObj.toDateString(); + dateStr = dateStr.substring(0, dateStr.length - 5); + return dateStr + "
" + formatAMPM(dateObj); +} + +function ClearText() { + location_ip.value = ""; +} + +function TrimText(text, maxLength) { + if (text.length < maxLength) { + return text; + } else { + var i = maxLength; + while (i < text.length) { + + if (text[i] == " " || text[i] == "," || text[i] == "." || text[i] == "\r" || text[i] == "\n") { + break; + } + i++; + } + return text.substr(0, i); + } +} + +function populateEvents(events) { + + var tempDiv = document.createElement("div"); + + var currentChildNodes = eventsTable.childNodes; + var defaultChildrenCount = 2; + for (var i = defaultChildrenCount; i < currentChildNodes.length; i++) { + currentChildNodes[i].parentNode.removeChild(currentChildNodes[i]); + } + for (var i = 0; i < events.length; i++) { + var dataObj = events[i]; + + tempDiv.innerHTML = dataObj.description; + var description = TrimText(tempDiv.innerText, 150); + var innerHtml = eventTemplate.innerHTML; + innerHtml = innerHtml.replace("%eventtitle%", TrimText(dataObj.title, 30)); + innerHtml = innerHtml.replace("%eventstarttime%", formatEventTime(dataObj.starttime)); + innerHtml = innerHtml.replace("%eventdescription%", description); + innerHtml = innerHtml.replace("%eventlink1%", dataObj.url); + innerHtml = innerHtml.replace("%eventlink2%", dataObj.url); + innerHtml = innerHtml.replace("%eventvenue%", dataObj.venue_address); + var obj = document.createElement("tr"); + obj.innerHTML = window.toStaticHTML(innerHtml); + + eventsTable.appendChild(obj); + } +} + +function populateWeather(weather) { + + var currentChildNodes = weatherData.childNodes; + var defaultChildrenCount = 5; + for (var i = defaultChildrenCount; i < currentChildNodes.length; i++) { + currentChildNodes[i].parentNode.removeChild(currentChildNodes[i]); + } + + var weatherElement = weatherTemplate.cloneNode(true); + weatherElement.style.display = "inherit"; + var innerHtml = weatherElement.innerHTML; + innerHtml = innerHtml.replace("%wt%", weather.temperature); + innerHtml = innerHtml.replace("%wp%", weather.pressure); + innerHtml = innerHtml.replace("%wtmin%", weather.temp_min); + innerHtml = innerHtml.replace("%wtmax%", weather.temp_max); + innerHtml = innerHtml.replace("%wdesc%", weather.description); + innerHtml = innerHtml.replace("%wimg%", weather.image); + weatherElement.innerHTML = window.toStaticHTML(innerHtml); + weatherData.appendChild(weatherElement); +} + +function populateMovies(movies) { + + var currentChildNodes = movieTemplateToHide.childNodes; + var defaultChildrenCount = 3; + for (var i = defaultChildrenCount; i < currentChildNodes.length; i++) { + currentChildNodes[i].parentNode.removeChild(currentChildNodes[i]); + } + + var showtimes = ""; + for (var i = 0; i < movies.length; i++) { + var innerHtml = movieTemplate.innerHTML; + var dataObj = movies[i]; + + var theatrename; + for (var j = 0; j < dataObj.theatre.length; j++) { + + showtimes += dataObj.theatre[j].name; + showtimes += "
"; + var showtimelist = dataObj.theatre[j].datetime; + for (var k = 0; k < showtimelist.length; k++) { + var dateObj = new Date(showtimelist[k]); + if (dateObj) { + showtimes += formatAMPM(dateObj) + " | "; + } + } + showtimes = showtimes.substr(0, showtimes.length - 2); + showtimes += "

"; + } + innerHtml = innerHtml.replace("%mtitle%", dataObj.title); + innerHtml = innerHtml.replace("%mtheater%", showtimes); + innerHtml = innerHtml.replace("%mposter%", dataObj.poster); + + var obj = document.createElement("div"); + obj.innerHTML = window.toStaticHTML(innerHtml); + movieTemplateToHide.appendChild(obj); + } +} + +function populateImages(images) { + if (images.length == 4) { + var mainimg = document.getElementById('mainPic1'); + mainimg.src = images[0]; + + var img1 = document.getElementById('thumbnailPic1'); + img1.src = images[1]; + + var img2 = document.getElementById('thumbnailPic2'); + img2.src = images[2]; + + var img3 = document.getElementById('thumbnailPic3'); + img3.src = images[3]; + } +} + +function FetchData() { + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function (e) { + // The request finished and response is ready + if (xhr.readyState == 4) { + var searchbar = document.getElementById('searchBar'); + searchbar.style.display = 'none'; + + if (xhr.status == 200) { + var replydata = JSON.parse(xhr.responseText); + populateImages(replydata.images); + populateEvents(replydata.events); + populateMovies(replydata.movies); + populateWeather(replydata.weather); + + defaultData.style.display = "none"; + cityData.style.display = 'inherit'; + } + else { + defaultData.style.display = "none"; + errorData.style.display = 'inherit'; + } + } + } + xhr.open("POST", document.URL, true); + xhr.setRequestHeader("Content-type", 'text/html'); + xhr.send(location_ip.value); +} diff --git a/Release/samples/CasaLens/casalens.cpp b/Release/samples/CasaLens/casalens.cpp index 6b436c5cab..4caac60d46 100644 --- a/Release/samples/CasaLens/casalens.cpp +++ b/Release/samples/CasaLens/casalens.cpp @@ -94,7 +94,7 @@ void CasaLens::handle_get(http_request message) concurrency::streams::fstream::open_istream(file_name, std::ios::in).then([=](concurrency::streams::istream is) { message.reply(status_codes::OK, is, content_type).then([](pplx::task t) { handle_error(t); }); - }).then([=](pplx::task& t) + }).then([=](pplx::task t) { try { diff --git a/Release/samples/CasaLens/datafetcher.cpp b/Release/samples/CasaLens/datafetcher.cpp index b3e41ada00..7f5c55d1c5 100644 --- a/Release/samples/CasaLens/datafetcher.cpp +++ b/Release/samples/CasaLens/datafetcher.cpp @@ -408,7 +408,7 @@ void CasaLens::get_data(http_request message, const std::wstring& input_text) bing_client.request(methods::GET, s).then([=](http_response resp) { return resp.extract_json(); - }).then([=](json::value& maps_result) mutable + }).then([=](json::value maps_result) mutable { auto coordinates = maps_result[U("resourceSets")][0][U("resources")][0][U("point")]; auto lattitude = coordinates[U("coordinates")][0].serialize(); @@ -420,10 +420,10 @@ void CasaLens::get_data(http_request message, const std::wstring& input_text) }).then([](http_response resp) { return resp.extract_json(); - }).then([=](json::value& maps_result) + }).then([=](json::value maps_result) { auto postal_code = maps_result[U("resourceSets")][0][U("resources")][0][U("address")][U("postalCode")].as_string(); - fetch_data(message, postal_code, input_text); + fetch_data(message, postal_code, input_text); }).then([=](pplx::task t) { try diff --git a/Release/samples/FacebookDemo/FacebookDemo120.vcxproj b/Release/samples/FacebookDemo/FacebookDemo120.vcxproj index 8a5e649a0e..c09ba7fb72 100644 --- a/Release/samples/FacebookDemo/FacebookDemo120.vcxproj +++ b/Release/samples/FacebookDemo/FacebookDemo120.vcxproj @@ -144,7 +144,7 @@ - + Designer diff --git a/Release/samples/FacebookDemo/FacebookDemo140.vcxproj b/Release/samples/FacebookDemo/FacebookDemo140.vcxproj index 25ee7d2c3d..bd249ff292 100644 --- a/Release/samples/FacebookDemo/FacebookDemo140.vcxproj +++ b/Release/samples/FacebookDemo/FacebookDemo140.vcxproj @@ -143,7 +143,7 @@ - + Designer diff --git a/Release/samples/FacebookDemo/FacebookDemo141.vcxproj b/Release/samples/FacebookDemo/FacebookDemo141.vcxproj new file mode 100644 index 0000000000..af5715d233 --- /dev/null +++ b/Release/samples/FacebookDemo/FacebookDemo141.vcxproj @@ -0,0 +1,184 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} + FacebookDemo + en-US + 14.0 + true + Windows Store + 10.0.10240.0 + 10.0.10240.0 + 10.0 + + + + Application + true + v141 + + + Application + true + v141 + + + Application + true + v141 + + + Application + false + true + v141 + + + Application + false + true + v141 + + + Application + false + true + v141 + + + + + + + FacebookDemo_TemporaryKey.pfx + + + $(OutDir)\$(MSBuildProjectName)\ + + + + /bigobj %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + + /bigobj %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + + /bigobj /Zm137 %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + + /bigobj %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + + /bigobj %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + + /bigobj %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + + + + App.xaml + + + MainPage.xaml + + + + + Designer + + + Designer + + + Designer + + + + + Designer + + + + + + + + + + + + App.xaml + + + + MainPage.xaml + + + Create + Create + Create + Create + Create + Create + + + + + {198ed804-2655-4d92-8104-c220e3ea9452} + + + + + + \ No newline at end of file diff --git a/Release/samples/FacebookDemo/Package120.appxmanifest b/Release/samples/FacebookDemo/Package.appxmanifest similarity index 93% rename from Release/samples/FacebookDemo/Package120.appxmanifest rename to Release/samples/FacebookDemo/Package.appxmanifest index 51de7429ba..10e0fb86ab 100644 --- a/Release/samples/FacebookDemo/Package120.appxmanifest +++ b/Release/samples/FacebookDemo/Package.appxmanifest @@ -7,8 +7,8 @@ Assets\StoreLogo.png - 6.2.1 - 6.2.1 + 10.0 + 10.0 diff --git a/Release/samples/FacebookDemo/Package.uwp.appxmanifest b/Release/samples/FacebookDemo/Package.uwp.appxmanifest new file mode 100644 index 0000000000..2c22a5313a --- /dev/null +++ b/Release/samples/FacebookDemo/Package.uwp.appxmanifest @@ -0,0 +1,34 @@ + + + + + FacebookDemo + Andy + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Release/samples/FacebookDemo/Package110.appxmanifest b/Release/samples/FacebookDemo/Package110.appxmanifest deleted file mode 100644 index 92b3781c45..0000000000 --- a/Release/samples/FacebookDemo/Package110.appxmanifest +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - FacebookDemo - Andy - Assets\StoreLogo.png - - - - 6.2.1 - 6.2.1 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/FacebookDemo/Package140.appxmanifest b/Release/samples/FacebookDemo/Package140.appxmanifest deleted file mode 100644 index 92b3781c45..0000000000 --- a/Release/samples/FacebookDemo/Package140.appxmanifest +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - FacebookDemo - Andy - Assets\StoreLogo.png - - - - 6.2.1 - 6.2.1 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/OAuth2Live/OAuth2Live120.vcxproj b/Release/samples/OAuth2Live/OAuth2Live120.vcxproj index ba5f229042..505d507611 100644 --- a/Release/samples/OAuth2Live/OAuth2Live120.vcxproj +++ b/Release/samples/OAuth2Live/OAuth2Live120.vcxproj @@ -150,7 +150,7 @@ - + Designer diff --git a/Release/samples/OAuth2Live/OAuth2Live140.vcxproj b/Release/samples/OAuth2Live/OAuth2Live140.vcxproj index 536709ab38..6671f9c227 100644 --- a/Release/samples/OAuth2Live/OAuth2Live140.vcxproj +++ b/Release/samples/OAuth2Live/OAuth2Live140.vcxproj @@ -150,7 +150,7 @@ - + Designer diff --git a/Release/samples/OAuth2Live/OAuth2Live141.vcxproj b/Release/samples/OAuth2Live/OAuth2Live141.vcxproj new file mode 100644 index 0000000000..4607d183a0 --- /dev/null +++ b/Release/samples/OAuth2Live/OAuth2Live141.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {2887A786-B818-4B3D-94EF-21EFD6AFDC22} + OAuth2Live + en-US + 14.0 + true + Windows Store + 10.0.10240.0 + 10.0.10240.0 + 10.0 + + + + Application + true + v141 + + + Application + true + v141 + + + Application + true + v141 + + + Application + false + true + v141 + + + Application + false + true + v141 + + + Application + false + true + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /bigobj /Zm200 %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + $(OutDir)\$(MSBuildProjectName)\ + + + OAuth2Live_TemporaryKey.pfx + + + + + App.xaml + + + MainPage.xaml + + + + + Designer + + + Designer + + + Designer + + + + + Designer + + + + + + + + + + + + App.xaml + + + MainPage.xaml + + + Create + Create + Create + Create + Create + Create + + + + + {198ed804-2655-4d92-8104-c220e3ea9452} + + + + + + \ No newline at end of file diff --git a/Release/samples/OAuth2Live/Package120.appxmanifest b/Release/samples/OAuth2Live/Package.appxmanifest similarity index 100% rename from Release/samples/OAuth2Live/Package120.appxmanifest rename to Release/samples/OAuth2Live/Package.appxmanifest diff --git a/Release/samples/OAuth2Live/Package.uwp.appxmanifest b/Release/samples/OAuth2Live/Package.uwp.appxmanifest new file mode 100644 index 0000000000..1c43d54562 --- /dev/null +++ b/Release/samples/OAuth2Live/Package.uwp.appxmanifest @@ -0,0 +1,34 @@ + + + + + OAuth2Live + Andy + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Release/samples/OAuth2Live/Package110.appxmanifest b/Release/samples/OAuth2Live/Package110.appxmanifest deleted file mode 100644 index d43e5de92a..0000000000 --- a/Release/samples/OAuth2Live/Package110.appxmanifest +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - OAuth2Live - symbiouser - Assets\StoreLogo.png - - - - 6.2.1 - 6.2.1 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/OAuth2Live/Package140.appxmanifest b/Release/samples/OAuth2Live/Package140.appxmanifest deleted file mode 100644 index fc1171601e..0000000000 --- a/Release/samples/OAuth2Live/Package140.appxmanifest +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - OAuth2Live - Microsoft Corporation - Assets\StoreLogo.png - - - - 6.2.1 - 6.2.1 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj new file mode 100644 index 0000000000..9dff0e2207 --- /dev/null +++ b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj @@ -0,0 +1,204 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {850CCB95-CFA8-4E41-9D1D-387C0C186740} + Win32Proj + Oauth1Client + SAK + SAK + SAK + SAK + $(VCTargetsPath12) + + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + + + + \ No newline at end of file diff --git a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj.filters b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj.filters new file mode 100644 index 0000000000..48d2ebae5f --- /dev/null +++ b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj new file mode 100644 index 0000000000..a0d3d0fdeb --- /dev/null +++ b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj @@ -0,0 +1,205 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654} + Win32Proj + Oauth2Client + SAK + SAK + SAK + SAK + $(VCTargetsPath12) + + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + -Zm140 %(AdditionalOptions) + + + Console + true + true + true + + + + + + + + + + Create + Create + Create + Create + Create + Create + + + + + {1014c621-bc2d-4813-b8c1-6d83ad6f9249} + + + + \ No newline at end of file diff --git a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj.filters b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj.filters new file mode 100644 index 0000000000..d11e5aec8b --- /dev/null +++ b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj new file mode 100644 index 0000000000..7fa2bd5235 --- /dev/null +++ b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj @@ -0,0 +1,146 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {F03BEE03-BEFB-4B17-A774-D9C8246530D4} + SAK + SAK + SAK + SAK + Win32Proj + $(VCTargetsPath12) + + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + Application + false + true + NotSet + v141 + + + + + + + /bigobj %(AdditionalOptions) + NotUsing + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + /bigobj %(AdditionalOptions) + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(CasablancaIncludeDir) + Async + + + Console + true + true + true + + + + + {1014c621-bc2d-4813-b8c1-6d83ad6f9249} + + + + + + + \ No newline at end of file diff --git a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj.filters b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj.filters new file mode 100644 index 0000000000..2794140178 --- /dev/null +++ b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj.filters @@ -0,0 +1,13 @@ + + + + + {bc214923-f806-44a3-abd4-08a1aa1a9b3b} + + + + + Source Files + + + \ No newline at end of file diff --git a/Release/samples/WindowsLiveAuth/Package120.appxmanifest b/Release/samples/WindowsLiveAuth/Package.appxmanifest similarity index 100% rename from Release/samples/WindowsLiveAuth/Package120.appxmanifest rename to Release/samples/WindowsLiveAuth/Package.appxmanifest diff --git a/Release/samples/WindowsLiveAuth/Package140.appxmanifest b/Release/samples/WindowsLiveAuth/Package140.appxmanifest deleted file mode 100644 index c3bed31403..0000000000 --- a/Release/samples/WindowsLiveAuth/Package140.appxmanifest +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - WindowsLiveAuth - Microsoft Corporation - Assets\StoreLogo.png - - - - 6.2.1 - 6.2.1 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj b/Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj index 4befa38ebd..2efbe5d141 100644 --- a/Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj +++ b/Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj @@ -152,7 +152,7 @@ - + Designer diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj b/Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj index 7a04658c9a..7be6b6dda1 100644 --- a/Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj +++ b/Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj @@ -151,7 +151,7 @@ - + Designer diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj b/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj new file mode 100644 index 0000000000..3983220d9e --- /dev/null +++ b/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj @@ -0,0 +1,191 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {1c20f771-3131-46e8-805f-aa1fe44165c0} + WindowsLiveAuth + en-US + 14.0 + true + Windows Store + 10.0.10240.0 + 10.0.10240.0 + 10.0 + + + + Application + true + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + Application + false + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /bigobj /Zm200 %(AdditionalOptions) + 4453 + $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) + + + + $(OutDir)\$(MSBuildProjectName)\ + + + WindowsLiveAuth_TemporaryKey.pfx + + + + + + App.xaml + + + MainPage.xaml + + + + + Designer + + + Designer + + + Designer + + + + + Designer + + + + + + + + + + + + App.xaml + + + MainPage.xaml + + + Create + Create + Create + Create + Create + Create + + + + + {198ed804-2655-4d92-8104-c220e3ea9452} + + + + + + \ No newline at end of file diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 9391da3cc8..1c460684ab 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -249,7 +249,7 @@ endif() # Portions specific to cpprest binary versioning. set (CPPREST_VERSION_MAJOR 2) -set (CPPREST_VERSION_MINOR 9) +set (CPPREST_VERSION_MINOR 10) set (CPPREST_VERSION_REVISION 0) if(WIN32) diff --git a/Release/src/build/common.vcxitems b/Release/src/build/common.vcxitems index 96e64635fb..8e9142fa9a 100644 --- a/Release/src/build/common.vcxitems +++ b/Release/src/build/common.vcxitems @@ -1,100 +1,95 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 248F659F-DAC5-46E8-AC09-60EC9FC95053 - true - b19fa703-0bf0-4e1f-8927-b0eaeb6aa823 - {594dcb5f-07e3-4084-a2ce-268611fa629f} - common - common - - - - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - - - - - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + 248F659F-DAC5-46E8-AC09-60EC9FC95053 + true + b19fa703-0bf0-4e1f-8927-b0eaeb6aa823 + {594dcb5f-07e3-4084-a2ce-268611fa629f} + common + common + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Release/src/build/common.vcxitems.filters b/Release/src/build/common.vcxitems.filters index 055bff167f..437868082e 100644 --- a/Release/src/build/common.vcxitems.filters +++ b/Release/src/build/common.vcxitems.filters @@ -1,236 +1,233 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {3bdf9ddb-6199-4b83-84cd-e8617e78294e} - - - {42f86193-fcdc-443d-8ede-8fd31abe6643} - - - {ed89d519-15d6-47d9-90cb-e6c25bcaa323} - - - {e5ecd256-178a-403a-9249-5d15463ad051} - - - {d32b3879-7333-4ab4-8ef2-dd72aed7b5dc} - - - {1c12997c-5bf5-4b60-853e-a5f9c8303760} - - - {97da7aee-41c8-4948-bb0e-c31cec1bfb16} - - - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\pch - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest - - - Header Files\cpprest\details - - - Header Files\private - - - Header Files\private - - - Header Files\private - - - Header Files\private - - - - - Header Files\cpprest\details - - - - - + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + {3bdf9ddb-6199-4b83-84cd-e8617e78294e} + + + {42f86193-fcdc-443d-8ede-8fd31abe6643} + + + {ed89d519-15d6-47d9-90cb-e6c25bcaa323} + + + {e5ecd256-178a-403a-9249-5d15463ad051} + + + {d32b3879-7333-4ab4-8ef2-dd72aed7b5dc} + + + {1c12997c-5bf5-4b60-853e-a5f9c8303760} + + + {97da7aee-41c8-4948-bb0e-c31cec1bfb16} + + + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\pch + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest + + + Header Files\cpprest\details + + + Header Files\private + + + Header Files\private + + + Header Files\private + + + Header Files\private + + + + + Header Files\cpprest\details + + \ No newline at end of file diff --git a/Release/src/build/init.ps1 b/Release/src/build/init.ps1 index 68a35fbc13..595baeaaa9 100644 --- a/Release/src/build/init.ps1 +++ b/Release/src/build/init.ps1 @@ -5,7 +5,7 @@ function Copy-Natvis($DestFolder) if ((Test-Path $DestFolder) -eq $True) { # Update casablanca version for each release here. - $DestFile = Join-Path -path $DestFolder -childpath "cpprest2_8.natvis"; + $DestFile = Join-Path -path $DestFolder -childpath "cpprest2_10.natvis"; # Check to see if cpp rest natvis file for this version already exists # if not, then copy into user profile for Visual Studio to pick up diff --git a/Release/src/build/package_info.xml b/Release/src/build/package_info.xml deleted file mode 100644 index a2f9550b13..0000000000 --- a/Release/src/build/package_info.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - cpprestsdk - 2.9.0 - casablancacore - Microsoft, Visual C++ - http://www.apache.org/licenses/LICENSE-2.0 - https://github.com/Microsoft/cpprestsdk/ - https://download-codeplex.sec.s-msft.com/Download?ProjectName=casablanca&DownloadId=630102&Build=20425 - false -

The C++ REST SDK is a cross-platform, modern, and asynchronous library that enables developers to access and author connected applications. - The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services. - https://github.com/Microsoft/cpprestsdk/releases/tag/v2.9.0 - Copyright 2015 - cpprestsdk Casablanca REST JSON HTTP URI WebSockets - - ..\..\include - - - - - - - - - - - /d2notypeopt %(AdditionalOptions) - CPPREST_TARGET_XP;%(PreprocessorDefinitions) - - -funwind-tables %(AdditionalOptions) - - - m;%(LibraryDependencies) - - - - \ No newline at end of file diff --git a/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj b/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj new file mode 100644 index 0000000000..874315ee1f --- /dev/null +++ b/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj @@ -0,0 +1,91 @@ + + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} + DynamicLibrary + en-US + 14.0 + true + Windows Store + 10.0.10240.0 + 10.0.10240.0 + 10.0 + cpprest141.uwp + v141 + DynamicLibrary + $(OutDir)\$(MsBuildProjectName) + + + + + + + + + + + + + + + + d + + + $(CppRestBaseFileName)141$(DebugFileSuffix)_uwp_$(CppRestSDKVersionFileSuffix) + + + + + false + false + + + + _ASYNCRT_EXPORT;_PPLX_EXPORT;_USRDLL;%(PreprocessorDefinitions); + Use + true + $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) + Use + stdafx.h + -Zm250 /bigobj %(AdditionalOptions) + true + + + Console + false + UseLinkTimeCodeGeneration + false + + + + + + \ No newline at end of file diff --git a/Release/src/build/vs141/cpprest141.vcxproj b/Release/src/build/vs141/cpprest141.vcxproj new file mode 100644 index 0000000000..323553b4cc --- /dev/null +++ b/Release/src/build/vs141/cpprest141.vcxproj @@ -0,0 +1,78 @@ + + + + + {1014C621-BC2D-4813-B8C1-6D83AD6F9249} + Win32Proj + SAK + SAK + SAK + SAK + DynamicLibrary + v141 + false + false + cpprest141 + + + + + + + + + + + + + + + + + + + d + + + $(CppRestBaseFileName)141$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) + + + + Designer + + + + + _ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) + $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + Use + stdafx.h + -Zm300 /bigobj %(AdditionalOptions) + MultiThreadedDebugDLL + MultiThreadedDLL + true + + + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + 4503;4592;%(DisableSpecificWarnings) + + + Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) + UseLinkTimeCodeGeneration + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Release/src/build/vs141/packages.config b/Release/src/build/vs141/packages.config new file mode 100644 index 0000000000..21a51fdf83 --- /dev/null +++ b/Release/src/build/vs141/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/cpprestsdk141.sln b/cpprestsdk141.sln new file mode 100644 index 0000000000..1d0d59b04c --- /dev/null +++ b/cpprestsdk141.sln @@ -0,0 +1,243 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27016.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "Release\src\build\common.vcxitems", "{594DCB5F-07E3-4084-A2CE-268611FA629F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "other", "Release\src\build\other.vcxitems", "{3D5908F7-7673-4229-BC46-2007A7AF9CAE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32", "Release\src\build\win32.vcxitems", "{F40F4804-50F9-4257-8D74-B9CBB19AC4C3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrt", "Release\src\build\winrt.vcxitems", "{0A9BA181-7876-4B3D-A5E0-EE673FA51C05}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{92944FCF-7E50-41FD-8A99-DD6869F9AEA5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprest141", "Release\src\build\vs141\cpprest141.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprest141.uwp", "Release\src\build\vs141.uwp\cpprest141.uwp.vcxproj", "{36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{EF775754-D70A-4611-A00C-F49F224FD236}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile141", "Release\samples\SearchFile\SearchFile141\SearchFile141.vcxproj", "{F03BEE03-BEFB-4B17-A774-D9C8246530D4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OAuth2Live141", "Release\samples\OAuth2Live\OAuth2Live141.vcxproj", "{2887A786-B818-4B3D-94EF-21EFD6AFDC22}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Oauth2Client141", "Release\samples\Oauth2Client\Oauth2Client141\Oauth2Client141.vcxproj", "{35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Oauth1Client141", "Release\samples\Oauth1Client\Oauth1Client141\Oauth1Client141.vcxproj", "{850CCB95-CFA8-4E41-9D1D-387C0C186740}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FacebookDemo141", "Release\samples\FacebookDemo\FacebookDemo141.vcxproj", "{43DE4DF3-ACAA-429E-B260-CC6D4FE82658}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CasaLens141", "Release\samples\CasaLens\CasaLens141\CasaLens141.vcxproj", "{FFBFD6C1-B525-4D35-AB64-A2FE9460B147}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_UIClient141", "Release\samples\BlackJack\BlackJack_UIClient\BlackJack_UIClient141.vcxproj", "{B8D3F85B-DA71-4ACA-87BA-10FED681DC79}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Server141", "Release\samples\BlackJack\BlackJack_Server\BlackJack_Server141\BlackJack_Server141.vcxproj", "{84350CD1-D406-4A4F-9571-261CA46D77C5}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Client141", "Release\samples\BlackJack\BlackJack_Client\BlackJack_Client141\BlackJack_Client141.vcxproj", "{830B6E2F-9224-41D1-B9C7-A51FC78B00C7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest141", "Release\samples\BingRequest\BingRequest141\BingRequest141.vcxproj", "{2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 + Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 + Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 + Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 + Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 + Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|ARM.ActiveCfg = Debug|ARM + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|ARM.Build.0 = Debug|ARM + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.ActiveCfg = Debug|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.Build.0 = Debug|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.ActiveCfg = Debug|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.Build.0 = Debug|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|ARM.ActiveCfg = Release|ARM + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|ARM.Build.0 = Release|ARM + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.ActiveCfg = Release|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.Build.0 = Release|x64 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.ActiveCfg = Release|Win32 + {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.Build.0 = Release|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.ActiveCfg = Debug|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.Build.0 = Debug|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.ActiveCfg = Debug|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.Build.0 = Debug|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.ActiveCfg = Debug|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.Build.0 = Debug|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.ActiveCfg = Release|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.Build.0 = Release|ARM + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.ActiveCfg = Release|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.Build.0 = Release|x64 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.ActiveCfg = Release|Win32 + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.Build.0 = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|ARM.ActiveCfg = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.ActiveCfg = Debug|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.Build.0 = Debug|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.ActiveCfg = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.Build.0 = Debug|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|ARM.ActiveCfg = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.ActiveCfg = Release|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.Build.0 = Release|x64 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.ActiveCfg = Release|Win32 + {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.Build.0 = Release|Win32 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|ARM.ActiveCfg = Debug|ARM + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|ARM.Build.0 = Debug|ARM + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|ARM.Deploy.0 = Debug|ARM + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x64.ActiveCfg = Debug|x64 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x64.Build.0 = Debug|x64 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x64.Deploy.0 = Debug|x64 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x86.ActiveCfg = Debug|Win32 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x86.Build.0 = Debug|Win32 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x86.Deploy.0 = Debug|Win32 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|ARM.ActiveCfg = Release|ARM + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|ARM.Build.0 = Release|ARM + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|ARM.Deploy.0 = Release|ARM + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x64.ActiveCfg = Release|x64 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x64.Build.0 = Release|x64 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x64.Deploy.0 = Release|x64 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x86.ActiveCfg = Release|Win32 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x86.Build.0 = Release|Win32 + {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x86.Deploy.0 = Release|Win32 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|ARM.ActiveCfg = Debug|ARM + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|ARM.Build.0 = Debug|ARM + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x64.ActiveCfg = Debug|x64 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x64.Build.0 = Debug|x64 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x86.ActiveCfg = Debug|Win32 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x86.Build.0 = Debug|Win32 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|ARM.ActiveCfg = Release|ARM + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|ARM.Build.0 = Release|ARM + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x64.ActiveCfg = Release|x64 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x64.Build.0 = Release|x64 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x86.ActiveCfg = Release|Win32 + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x86.Build.0 = Release|Win32 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|ARM.ActiveCfg = Debug|ARM + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|ARM.Build.0 = Debug|ARM + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x64.ActiveCfg = Debug|x64 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x64.Build.0 = Debug|x64 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x86.ActiveCfg = Debug|Win32 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x86.Build.0 = Debug|Win32 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|ARM.ActiveCfg = Release|ARM + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|ARM.Build.0 = Release|ARM + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x64.ActiveCfg = Release|x64 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x64.Build.0 = Release|x64 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x86.ActiveCfg = Release|Win32 + {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x86.Build.0 = Release|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.ActiveCfg = Debug|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Build.0 = Debug|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Deploy.0 = Debug|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.ActiveCfg = Debug|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Build.0 = Debug|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Deploy.0 = Debug|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x86.ActiveCfg = Debug|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x86.Build.0 = Debug|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x86.Deploy.0 = Debug|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.ActiveCfg = Release|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Build.0 = Release|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Deploy.0 = Release|ARM + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.ActiveCfg = Release|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Build.0 = Release|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Deploy.0 = Release|x64 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x86.ActiveCfg = Release|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x86.Build.0 = Release|Win32 + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x86.Deploy.0 = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|ARM.ActiveCfg = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.ActiveCfg = Debug|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.Build.0 = Debug|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.ActiveCfg = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.Build.0 = Debug|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|ARM.ActiveCfg = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.ActiveCfg = Release|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.Build.0 = Release|x64 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.ActiveCfg = Release|Win32 + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.Build.0 = Release|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.ActiveCfg = Debug|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Build.0 = Debug|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Deploy.0 = Debug|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.ActiveCfg = Debug|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Build.0 = Debug|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Deploy.0 = Debug|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x86.ActiveCfg = Debug|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x86.Build.0 = Debug|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x86.Deploy.0 = Debug|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.ActiveCfg = Release|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Build.0 = Release|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Deploy.0 = Release|ARM + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.ActiveCfg = Release|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Build.0 = Release|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Deploy.0 = Release|x64 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x86.ActiveCfg = Release|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x86.Build.0 = Release|Win32 + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x86.Deploy.0 = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|ARM.ActiveCfg = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.ActiveCfg = Debug|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.Build.0 = Debug|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.ActiveCfg = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.Build.0 = Debug|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|ARM.ActiveCfg = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.ActiveCfg = Release|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.Build.0 = Release|x64 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.ActiveCfg = Release|Win32 + {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.Build.0 = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|ARM.ActiveCfg = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.ActiveCfg = Debug|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.Build.0 = Debug|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.ActiveCfg = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.Build.0 = Debug|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|ARM.ActiveCfg = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.ActiveCfg = Release|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.Build.0 = Release|x64 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.ActiveCfg = Release|Win32 + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.Build.0 = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|ARM.ActiveCfg = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.ActiveCfg = Debug|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.Build.0 = Debug|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.ActiveCfg = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.Build.0 = Debug|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|ARM.ActiveCfg = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.ActiveCfg = Release|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.Build.0 = Release|x64 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.ActiveCfg = Release|Win32 + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {65951C40-A332-4B54-89C2-7CDAF30D5F66} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} + {594DCB5F-07E3-4084-A2CE-268611FA629F} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} + {3D5908F7-7673-4229-BC46-2007A7AF9CAE} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} + {F40F4804-50F9-4257-8D74-B9CBB19AC4C3} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} + {0A9BA181-7876-4B3D-A5E0-EE673FA51C05} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} + {1014C621-BC2D-4813-B8C1-6D83AD6F9249} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} + {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} + {F03BEE03-BEFB-4B17-A774-D9C8246530D4} = {EF775754-D70A-4611-A00C-F49F224FD236} + {2887A786-B818-4B3D-94EF-21EFD6AFDC22} = {EF775754-D70A-4611-A00C-F49F224FD236} + {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654} = {EF775754-D70A-4611-A00C-F49F224FD236} + {850CCB95-CFA8-4E41-9D1D-387C0C186740} = {EF775754-D70A-4611-A00C-F49F224FD236} + {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} = {EF775754-D70A-4611-A00C-F49F224FD236} + {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} = {EF775754-D70A-4611-A00C-F49F224FD236} + {B8D3F85B-DA71-4ACA-87BA-10FED681DC79} = {EF775754-D70A-4611-A00C-F49F224FD236} + {84350CD1-D406-4A4F-9571-261CA46D77C5} = {EF775754-D70A-4611-A00C-F49F224FD236} + {830B6E2F-9224-41D1-B9C7-A51FC78B00C7} = {EF775754-D70A-4611-A00C-F49F224FD236} + {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} = {EF775754-D70A-4611-A00C-F49F224FD236} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5782CB9E-B335-4D07-A195-717BF4093536} + EndGlobalSection +EndGlobal From 801943b888c8f3d8c167fec749c1a36ddfaf05ad Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 18 Oct 2017 23:06:37 -0700 Subject: [PATCH 298/609] Add Generated Files to gitignore. Normalize BingRequest141. --- .gitignore | 2 ++ .../BingRequest/BingRequest141/BingRequest141.vcxproj | 10 +--------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index cbc754231e..49f694a391 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,5 @@ build.*/ docs/ # ignore NuGet artifacts .nuget/ + +Generated Files/ \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj index 215c686f1e..04ca9dee54 100644 --- a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj +++ b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj @@ -55,15 +55,7 @@ v141 - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root)) - $(BuildRoot)\Binaries\$(Platform)\$(Configuration)\ - $(OutputPath) - $(BuildRoot)\Release\src - $(BuildRoot)\Release\include - + From 6f291dd16b244e9d02e54a903f7082f462505fd7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 18 Oct 2017 23:15:47 -0700 Subject: [PATCH 299/609] Remove v120 MSBuild files. Use CMake instead. --- Release/dirs.proj | 16 - .../BingRequest120.xp.vcxproj | 133 -------- .../BingRequest120.xp.vcxproj.filters | 13 - .../BingRequest120/BingRequest120.vcxproj | 143 -------- .../BingRequest120.vcxproj.filters | 13 - Release/samples/BingRequest/dirs.proj | 15 - .../BlackJack_Client120.vcxproj | 148 -------- .../BlackJack_Client120.vcxproj.filters | 33 -- .../BlackJack/BlackJack_Client/dirs.proj | 11 - .../BlackJack_Server120.vcxproj | 154 --------- .../BlackJack_Server120.vcxproj.filters | 41 --- .../BlackJack/BlackJack_Server/dirs.proj | 11 - .../BlackJack_UIClient120.vcxproj | 182 ---------- Release/samples/BlackJack/dirs.proj | 16 - .../CasaLens/CasaLens120/CasaLens120.vcxproj | 168 --------- .../CasaLens120/CasaLens120.vcxproj.filters | 33 -- Release/samples/CasaLens/dirs.proj | 11 - .../FacebookDemo/FacebookDemo120.vcxproj | 184 ---------- Release/samples/FacebookDemo/dirs.proj | 11 - .../samples/OAuth2Live/OAuth2Live120.vcxproj | 188 ---------- Release/samples/OAuth2Live/dirs.proj | 11 - .../Oauth1Client120/Oauth1Client120.vcxproj | 205 ----------- .../Oauth1Client120.vcxproj.filters | 33 -- Release/samples/Oauth1Client/dirs.proj | 11 - .../Oauth2Client120/Oauth2Client120.sln | 34 -- .../Oauth2Client120/Oauth2Client120.vcxproj | 205 ----------- .../Oauth2Client120.vcxproj.filters | 33 -- Release/samples/Oauth2Client/dirs.proj | 11 - .../SearchFile120/SearchFile120.vcxproj | 133 -------- .../SearchFile120.vcxproj.filters | 13 - Release/samples/SearchFile/dirs.proj | 11 - .../WindowsLiveAuth120.vcxproj | 190 ----------- Release/samples/WindowsLiveAuth/dirs.proj | 15 - Release/samples/dirs.proj | 24 -- .../vs12.winrt/casablanca120.winrt.vcxproj | 68 ---- .../vs12.wp81/casablanca120.wp81.vcxproj | 68 ---- .../vs12.wps81/casablanca120.wps81.vcxproj | 66 ---- .../casablanca120.xp.static.vcxproj | 109 ------ .../src/build/vs12.xp.static/packages.config | 13 - .../build/vs12.xp/casablanca120.xp.vcxproj | 83 ----- Release/src/build/vs12.xp/packages.config | 13 - Release/src/build/vs12/casablanca120.vcxproj | 79 ----- Release/src/build/vs12/packages.config | 13 - Release/src/dirs.proj | 31 -- Release/tests/common/TestRunner/dirs.proj | 25 -- .../vs12.winrt/TestRunner120.winrt.vcxproj | 250 -------------- .../TestRunner120.winrt.vcxproj.filters | 24 -- .../TestRunner/vs12/TestRunner120.vcxproj | 250 -------------- .../vs12/TestRunner120.vcxproj.filters | 24 -- Release/tests/common/UnitTestpp/dirs.proj | 26 -- .../vs12.winrt/UnitTestpp120.winrt.vcxproj | 263 -------------- .../UnitTestpp120.winrt.vcxproj.filters | 159 --------- .../UnitTestpp/vs12/TestUnitTestpp120.vcxproj | 202 ----------- .../vs12/TestUnitTestpp120.vcxproj.filters | 72 ---- .../UnitTestpp/vs12/UnitTestpp120.vcxproj | 228 ------------- .../vs12/UnitTestpp120.vcxproj.filters | 159 --------- Release/tests/common/dirs.proj | 13 - Release/tests/common/utilities/dirs.proj | 25 -- .../CommonUtilities120.winrt.vcxproj | 274 --------------- .../CommonUtilities120.winrt.vcxproj.filters | 33 -- .../vs12.xp/CommonUtilities120.xp.vcxproj | 150 -------- .../utilities/vs12/CommonUtilities120.vcxproj | 203 ----------- .../vs12/CommonUtilities120.vcxproj.filters | 33 -- Release/tests/dirs.proj | 12 - Release/tests/functional/dirs.proj | 18 - .../http/client/AuthListener/App.config | 6 - .../http/client/AuthListener/Program.cs | 146 -------- .../AuthListener/Properties/AssemblyInfo.cs | 36 -- .../http/client/AuthListener/dirs.proj | 15 - .../AuthListener/vs12/AuthListener120.csproj | 60 ---- .../tests/functional/http/client/dirs.proj | 22 -- .../HttpClient120_test.winrt.vcxproj | 257 -------------- .../HttpClient120_test.winrt.vcxproj.filters | 87 ----- .../client/vs12/HttpClient120_test.vcxproj | 234 ------------- .../vs12/HttpClient120_test.vcxproj.filters | 88 ----- Release/tests/functional/http/dirs.proj | 13 - .../tests/functional/http/listener/dirs.proj | 15 - .../vs12/HttpListener120_test.vcxproj | 236 ------------- .../vs12/HttpListener120_test.vcxproj.filters | 66 ---- .../tests/functional/http/utilities/dirs.proj | 24 -- .../HttpTestUtilities120.winrt.vcxproj | 246 -------------- ...HttpTestUtilities120.winrt.vcxproj.filters | 51 --- .../vs12/HttpTestUtilities120.vcxproj | 218 ------------ .../vs12/HttpTestUtilities120.vcxproj.filters | 51 --- Release/tests/functional/json/dirs.proj | 26 -- .../vs12.winrt/JSON120_test.winrt.vcxproj | 234 ------------- .../JSON120_test.winrt.vcxproj.filters | 42 --- .../json/vs12.xp/JSON120_test.xp.vcxproj | 151 -------- .../functional/json/vs12/JSON120_test.vcxproj | 207 ----------- .../json/vs12/JSON120_test.vcxproj.filters | 44 --- .../functional/misc/atl_headers/dirs.proj | 10 - .../atl_headers/vs12/header_test120.vcxproj | 173 ---------- .../vs12/header_test120.vcxproj.filters | 32 -- Release/tests/functional/misc/dirs.proj | 16 - .../tests/functional/misc/version/dirs.proj | 11 - Release/tests/functional/pplx/dirs.proj | 11 - .../tests/functional/pplx/pplx_test/dirs.proj | 26 -- .../vs12.winrt/pplx120_test.winrt.vcxproj | 228 ------------- .../pplx_test/vs12.xp/pplx120_test.xp.vcxproj | 158 --------- .../pplx/pplx_test/vs12/pplx120_test.vcxproj | 216 ------------ Release/tests/functional/streams/dirs.proj | 26 -- .../vs12.winrt/streams120_test.winrt.vcxproj | 246 -------------- .../streams120_test.winrt.vcxproj.filters | 45 --- .../vs12.xp/streams120_test.xp.vcxproj | 163 --------- .../streams/vs12/streams120_test.vcxproj | 216 ------------ .../vs12/streams120_test.vcxproj.filters | 43 --- Release/tests/functional/uri/dirs.proj | 26 -- .../URI120_test.winrt.vcxproj.filters | 57 ---- .../uri/vs12.winrt/Uri120_test.winrt.vcxproj | 234 ------------- .../uri/vs12.xp/Uri120_test.xp.vcxproj | 155 --------- .../functional/uri/vs12/Uri120_test.vcxproj | 208 ------------ .../uri/vs12/Uri120_test.vcxproj.filters | 59 ---- Release/tests/functional/utils/dirs.proj | 26 -- .../vs12.winrt/Utils120_test.winrt.vcxproj | 229 ------------- .../Utils120_test.winrt.vcxproj.filters | 36 -- .../utils/vs12.xp/Utils120_test.xp.vcxproj | 151 -------- .../utils/vs12/Utils120_test.vcxproj | 202 ----------- .../utils/vs12/Utils120_test.vcxproj.filters | 38 --- .../functional/websockets/client/dirs.proj | 26 -- .../websocketsclient120_test.winrt.vcxproj | 179 ---------- .../websocketsclient120_test.xp.vcxproj | 123 ------- .../vs12/websocketsclient120_test.vcxproj | 129 ------- Release/tests/functional/websockets/dirs.proj | 12 - .../functional/websockets/utilities/dirs.proj | 26 -- ...websockets_test_utilities120.winrt.vcxproj | 178 ---------- .../websockets_test_utilities120.xp.vcxproj | 132 ------- .../websockets/utilities/vs12/packages.config | 7 - .../vs12/websockets_test_utilities120.vcxproj | 157 --------- cpprestsdk120.sln | 321 ------------------ setup_ps_env_VS2013.ps1 | 22 -- setup_ps_env_VS2015.ps1 | 17 - 131 files changed, 12384 deletions(-) delete mode 100644 Release/dirs.proj delete mode 100644 Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj delete mode 100644 Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj.filters delete mode 100644 Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj delete mode 100644 Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj.filters delete mode 100644 Release/samples/BingRequest/dirs.proj delete mode 100644 Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj.filters delete mode 100644 Release/samples/BlackJack/BlackJack_Client/dirs.proj delete mode 100644 Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj.filters delete mode 100644 Release/samples/BlackJack/BlackJack_Server/dirs.proj delete mode 100644 Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj delete mode 100644 Release/samples/BlackJack/dirs.proj delete mode 100644 Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj delete mode 100644 Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj.filters delete mode 100644 Release/samples/CasaLens/dirs.proj delete mode 100644 Release/samples/FacebookDemo/FacebookDemo120.vcxproj delete mode 100644 Release/samples/FacebookDemo/dirs.proj delete mode 100644 Release/samples/OAuth2Live/OAuth2Live120.vcxproj delete mode 100644 Release/samples/OAuth2Live/dirs.proj delete mode 100644 Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj delete mode 100644 Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj.filters delete mode 100644 Release/samples/Oauth1Client/dirs.proj delete mode 100644 Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.sln delete mode 100644 Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj delete mode 100644 Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj.filters delete mode 100644 Release/samples/Oauth2Client/dirs.proj delete mode 100644 Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj delete mode 100644 Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj.filters delete mode 100644 Release/samples/SearchFile/dirs.proj delete mode 100644 Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj delete mode 100644 Release/samples/WindowsLiveAuth/dirs.proj delete mode 100644 Release/samples/dirs.proj delete mode 100644 Release/src/build/vs12.winrt/casablanca120.winrt.vcxproj delete mode 100644 Release/src/build/vs12.wp81/casablanca120.wp81.vcxproj delete mode 100644 Release/src/build/vs12.wps81/casablanca120.wps81.vcxproj delete mode 100644 Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj delete mode 100644 Release/src/build/vs12.xp.static/packages.config delete mode 100644 Release/src/build/vs12.xp/casablanca120.xp.vcxproj delete mode 100644 Release/src/build/vs12.xp/packages.config delete mode 100644 Release/src/build/vs12/casablanca120.vcxproj delete mode 100644 Release/src/build/vs12/packages.config delete mode 100644 Release/src/dirs.proj delete mode 100644 Release/tests/common/TestRunner/dirs.proj delete mode 100644 Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj delete mode 100644 Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj.filters delete mode 100644 Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj delete mode 100644 Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj.filters delete mode 100644 Release/tests/common/UnitTestpp/dirs.proj delete mode 100644 Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj delete mode 100644 Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj.filters delete mode 100644 Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj delete mode 100644 Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj.filters delete mode 100644 Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj delete mode 100644 Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj.filters delete mode 100644 Release/tests/common/dirs.proj delete mode 100644 Release/tests/common/utilities/dirs.proj delete mode 100644 Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj delete mode 100644 Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj.filters delete mode 100644 Release/tests/common/utilities/vs12.xp/CommonUtilities120.xp.vcxproj delete mode 100644 Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj delete mode 100644 Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj.filters delete mode 100644 Release/tests/dirs.proj delete mode 100644 Release/tests/functional/dirs.proj delete mode 100644 Release/tests/functional/http/client/AuthListener/App.config delete mode 100644 Release/tests/functional/http/client/AuthListener/Program.cs delete mode 100644 Release/tests/functional/http/client/AuthListener/Properties/AssemblyInfo.cs delete mode 100644 Release/tests/functional/http/client/AuthListener/dirs.proj delete mode 100644 Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj delete mode 100644 Release/tests/functional/http/client/dirs.proj delete mode 100644 Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj delete mode 100644 Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj.filters delete mode 100644 Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj delete mode 100644 Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj.filters delete mode 100644 Release/tests/functional/http/dirs.proj delete mode 100644 Release/tests/functional/http/listener/dirs.proj delete mode 100644 Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj delete mode 100644 Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj.filters delete mode 100644 Release/tests/functional/http/utilities/dirs.proj delete mode 100644 Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj delete mode 100644 Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj.filters delete mode 100644 Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj delete mode 100644 Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj.filters delete mode 100644 Release/tests/functional/json/dirs.proj delete mode 100644 Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj delete mode 100644 Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj.filters delete mode 100644 Release/tests/functional/json/vs12.xp/JSON120_test.xp.vcxproj delete mode 100644 Release/tests/functional/json/vs12/JSON120_test.vcxproj delete mode 100644 Release/tests/functional/json/vs12/JSON120_test.vcxproj.filters delete mode 100644 Release/tests/functional/misc/atl_headers/dirs.proj delete mode 100644 Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj delete mode 100644 Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj.filters delete mode 100644 Release/tests/functional/misc/dirs.proj delete mode 100644 Release/tests/functional/misc/version/dirs.proj delete mode 100644 Release/tests/functional/pplx/dirs.proj delete mode 100644 Release/tests/functional/pplx/pplx_test/dirs.proj delete mode 100644 Release/tests/functional/pplx/pplx_test/vs12.winrt/pplx120_test.winrt.vcxproj delete mode 100644 Release/tests/functional/pplx/pplx_test/vs12.xp/pplx120_test.xp.vcxproj delete mode 100644 Release/tests/functional/pplx/pplx_test/vs12/pplx120_test.vcxproj delete mode 100644 Release/tests/functional/streams/dirs.proj delete mode 100644 Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj delete mode 100644 Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj.filters delete mode 100644 Release/tests/functional/streams/vs12.xp/streams120_test.xp.vcxproj delete mode 100644 Release/tests/functional/streams/vs12/streams120_test.vcxproj delete mode 100644 Release/tests/functional/streams/vs12/streams120_test.vcxproj.filters delete mode 100644 Release/tests/functional/uri/dirs.proj delete mode 100644 Release/tests/functional/uri/vs12.winrt/URI120_test.winrt.vcxproj.filters delete mode 100644 Release/tests/functional/uri/vs12.winrt/Uri120_test.winrt.vcxproj delete mode 100644 Release/tests/functional/uri/vs12.xp/Uri120_test.xp.vcxproj delete mode 100644 Release/tests/functional/uri/vs12/Uri120_test.vcxproj delete mode 100644 Release/tests/functional/uri/vs12/Uri120_test.vcxproj.filters delete mode 100644 Release/tests/functional/utils/dirs.proj delete mode 100644 Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj delete mode 100644 Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj.filters delete mode 100644 Release/tests/functional/utils/vs12.xp/Utils120_test.xp.vcxproj delete mode 100644 Release/tests/functional/utils/vs12/Utils120_test.vcxproj delete mode 100644 Release/tests/functional/utils/vs12/Utils120_test.vcxproj.filters delete mode 100644 Release/tests/functional/websockets/client/dirs.proj delete mode 100644 Release/tests/functional/websockets/client/vs12.winrt/websocketsclient120_test.winrt.vcxproj delete mode 100644 Release/tests/functional/websockets/client/vs12.xp/websocketsclient120_test.xp.vcxproj delete mode 100644 Release/tests/functional/websockets/client/vs12/websocketsclient120_test.vcxproj delete mode 100644 Release/tests/functional/websockets/dirs.proj delete mode 100644 Release/tests/functional/websockets/utilities/dirs.proj delete mode 100644 Release/tests/functional/websockets/utilities/vs12.winrt/websockets_test_utilities120.winrt.vcxproj delete mode 100644 Release/tests/functional/websockets/utilities/vs12.xp/websockets_test_utilities120.xp.vcxproj delete mode 100644 Release/tests/functional/websockets/utilities/vs12/packages.config delete mode 100644 Release/tests/functional/websockets/utilities/vs12/websockets_test_utilities120.vcxproj delete mode 100644 cpprestsdk120.sln delete mode 100644 setup_ps_env_VS2013.ps1 delete mode 100644 setup_ps_env_VS2015.ps1 diff --git a/Release/dirs.proj b/Release/dirs.proj deleted file mode 100644 index bdbd321a8d..0000000000 --- a/Release/dirs.proj +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj b/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj deleted file mode 100644 index 67d605f1f9..0000000000 --- a/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - Application - true - NotSet - v120_xp - - - Application - true - NotSet - v120_xp - - - Application - false - true - NotSet - v120_xp - - - Application - false - true - NotSet - v120_xp - - - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - - - - {15f3b200-1aed-4b57-af37-b21cd67914b1} - - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj.filters b/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj.filters deleted file mode 100644 index cee450afc2..0000000000 --- a/Release/samples/BingRequest/BingRequest120.xp/BingRequest120.xp.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {786631e0-badc-4b3f-bd98-9b13e6a8e5f8} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj b/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj deleted file mode 100644 index 981088f76d..0000000000 --- a/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj +++ /dev/null @@ -1,143 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root)) - $(BuildRoot)\Binaries\$(Platform)\$(Configuration)\ - $(OutputPath) - $(BuildRoot)\Release\src - $(BuildRoot)\Release\include - - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj.filters b/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj.filters deleted file mode 100644 index b78f1994bb..0000000000 --- a/Release/samples/BingRequest/BingRequest120/BingRequest120.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {bc214923-f806-44a3-abd4-08a1aa1a9b3b} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/dirs.proj b/Release/samples/BingRequest/dirs.proj deleted file mode 100644 index 41aac664db..0000000000 --- a/Release/samples/BingRequest/dirs.proj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj deleted file mode 100644 index 004ac5e463..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {830b6e2f-9224-41d1-b9c7-a51fc78b00c7} - Win32Proj - BlackJack_Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj.filters deleted file mode 100644 index 127018be70..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client120/BlackJack_Client120.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/dirs.proj b/Release/samples/BlackJack/BlackJack_Client/dirs.proj deleted file mode 100644 index 873f38e386..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj deleted file mode 100644 index 87ec496b5e..0000000000 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj +++ /dev/null @@ -1,154 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {84350cd1-d406-4a4f-9571-261ca46d77c5} - Win32Proj - BlackJack_Server - SAK - SAK - SAK - $(VCTargetsPath12) - SAK - - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj.filters deleted file mode 100644 index a0eae4c8d1..0000000000 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server120/BlackJack_Server120.vcxproj.filters +++ /dev/null @@ -1,41 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/dirs.proj b/Release/samples/BlackJack/BlackJack_Server/dirs.proj deleted file mode 100644 index 2514717ba1..0000000000 --- a/Release/samples/BlackJack/BlackJack_Server/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj deleted file mode 100644 index 00535c0cdb..0000000000 --- a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient120.vcxproj +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {b8d3f85b-da71-4aca-87ba-10fed681dc79} - BlackJack_UIClient - en-US - 12.0 - true - SAK - SAK - SAK - SAK - Windows Store - 8.1 - - - - Application - true - v120 - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - BlackJack_UIClient_TemporaryKey.pfx - - - - pch.h - WIN32;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - 4100;4267;4450;4453;4702;%(DisableSpecificWarnings) - - - - $(OutDir)\$(MSBuildProjectName)\ - F21E91BD711D606106CD99CE5C2E090FD822956F - - - - CardShape.xaml - - - - App.xaml - - - Player.xaml - - - PlayingTable.xaml - - - - - Designer - - - - Designer - - - - - - - Designer - - - - - - - - - - - - - - App.xaml - - - CardShape.xaml - - - Create - Create - Create - Create - Create - Create - - - Player.xaml - - - PlayingTable.xaml - - - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/dirs.proj b/Release/samples/BlackJack/dirs.proj deleted file mode 100644 index 01cd2b9ca6..0000000000 --- a/Release/samples/BlackJack/dirs.proj +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj b/Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj deleted file mode 100644 index 695a518dfb..0000000000 --- a/Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj +++ /dev/null @@ -1,168 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj.filters b/Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj.filters deleted file mode 100644 index 3f96e58d5b..0000000000 --- a/Release/samples/CasaLens/CasaLens120/CasaLens120.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - - - - - - {d774ca0e-abc2-480d-a95a-c748cc85c9a3} - - - {35af6514-c88d-44e5-9e0f-97a7e4d93fb6} - - - \ No newline at end of file diff --git a/Release/samples/CasaLens/dirs.proj b/Release/samples/CasaLens/dirs.proj deleted file mode 100644 index 46ff276f1e..0000000000 --- a/Release/samples/CasaLens/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/FacebookDemo/FacebookDemo120.vcxproj b/Release/samples/FacebookDemo/FacebookDemo120.vcxproj deleted file mode 100644 index c09ba7fb72..0000000000 --- a/Release/samples/FacebookDemo/FacebookDemo120.vcxproj +++ /dev/null @@ -1,184 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} - FacebookDemo - en-US - 12.0 - true - Windows Store - 8.1 - - - - Application - true - v120 - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - - - - - FacebookDemo_TemporaryKey.pfx - - - $(OutDir)\$(MSBuildProjectName)\ - A2EB87D9E8F458456834BA935C38BCD7C389022E - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj /Zm137 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - - App.xaml - - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {198ed804-2655-4d92-8104-c220e3ea9452} - - - - - - \ No newline at end of file diff --git a/Release/samples/FacebookDemo/dirs.proj b/Release/samples/FacebookDemo/dirs.proj deleted file mode 100644 index 4f05c7d418..0000000000 --- a/Release/samples/FacebookDemo/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/OAuth2Live/OAuth2Live120.vcxproj b/Release/samples/OAuth2Live/OAuth2Live120.vcxproj deleted file mode 100644 index 505d507611..0000000000 --- a/Release/samples/OAuth2Live/OAuth2Live120.vcxproj +++ /dev/null @@ -1,188 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {2887A786-B818-4B3D-94EF-21EFD6AFDC22} - OAuth2Live - en-US - 12.0 - true - Windows Store - 8.1 - - - - Application - true - v120 - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /bigobj /Zm200 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - $(OutDir)\$(MSBuildProjectName)\ - - - OAuth2Live_TemporaryKey.pfx - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {198ed804-2655-4d92-8104-c220e3ea9452} - - - - - - \ No newline at end of file diff --git a/Release/samples/OAuth2Live/dirs.proj b/Release/samples/OAuth2Live/dirs.proj deleted file mode 100644 index 1f8a5de3cf..0000000000 --- a/Release/samples/OAuth2Live/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj b/Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj deleted file mode 100644 index 220d05bd85..0000000000 --- a/Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj +++ /dev/null @@ -1,205 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {0AA87B6D-FEDD-4435-A68A-789D7C582591} - Win32Proj - Oauth1Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - \ No newline at end of file diff --git a/Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj.filters b/Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj.filters deleted file mode 100644 index 48d2ebae5f..0000000000 --- a/Release/samples/Oauth1Client/Oauth1Client120/Oauth1Client120.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/Oauth1Client/dirs.proj b/Release/samples/Oauth1Client/dirs.proj deleted file mode 100644 index c82273b693..0000000000 --- a/Release/samples/Oauth1Client/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.sln b/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.sln deleted file mode 100644 index 5d2a398e85..0000000000 --- a/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.sln +++ /dev/null @@ -1,34 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30110.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Oauth2Client120", "Oauth2Client120.vcxproj", "{62CF690F-9B67-4A86-9CF4-E7CD07D1A342}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|ARM = Release|ARM - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Debug|ARM.ActiveCfg = Debug|ARM - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Debug|ARM.Build.0 = Debug|ARM - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Debug|Win32.ActiveCfg = Debug|Win32 - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Debug|Win32.Build.0 = Debug|Win32 - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Debug|x64.ActiveCfg = Debug|x64 - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Debug|x64.Build.0 = Debug|x64 - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Release|ARM.ActiveCfg = Release|ARM - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Release|ARM.Build.0 = Release|ARM - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Release|Win32.ActiveCfg = Release|Win32 - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Release|Win32.Build.0 = Release|Win32 - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Release|x64.ActiveCfg = Release|x64 - {62CF690F-9B67-4A86-9CF4-E7CD07D1A342}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj b/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj deleted file mode 100644 index 0376c0243a..0000000000 --- a/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj +++ /dev/null @@ -1,205 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {09E24B3F-FE75-4FDA-B75B-8CE3C65C8D8A} - Win32Proj - Oauth2Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - \ No newline at end of file diff --git a/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj.filters b/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj.filters deleted file mode 100644 index d11e5aec8b..0000000000 --- a/Release/samples/Oauth2Client/Oauth2Client120/Oauth2Client120.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/Oauth2Client/dirs.proj b/Release/samples/Oauth2Client/dirs.proj deleted file mode 100644 index 484537a0e5..0000000000 --- a/Release/samples/Oauth2Client/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj b/Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj deleted file mode 100644 index 6c747ed8e1..0000000000 --- a/Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {F03BEE03-BEFB-4B17-A774-D9C8246530D4} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - Application - true - NotSet - v120 - - - Application - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - Application - false - true - NotSet - v120 - - - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - - \ No newline at end of file diff --git a/Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj.filters b/Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj.filters deleted file mode 100644 index 2794140178..0000000000 --- a/Release/samples/SearchFile/SearchFile120/SearchFile120.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {bc214923-f806-44a3-abd4-08a1aa1a9b3b} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/SearchFile/dirs.proj b/Release/samples/SearchFile/dirs.proj deleted file mode 100644 index 8f7ae1654b..0000000000 --- a/Release/samples/SearchFile/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj b/Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj deleted file mode 100644 index 2efbe5d141..0000000000 --- a/Release/samples/WindowsLiveAuth/WindowsLiveAuth120.vcxproj +++ /dev/null @@ -1,190 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {1c20f771-3131-46e8-805f-aa1fe44165c0} - WindowsLiveAuth - en-US - 12.0 - true - Windows Store - 8.1 - - - - Application - true - v120 - - - Application - true - v120 - - - Application - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - Application - false - true - v120 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /bigobj /Zm200 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - $(OutDir)\$(MSBuildProjectName)\ - - - WindowsLiveAuth_TemporaryKey.pfx - D3342DAE1EC703934903364490A80C5BB06C929A - - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {198ed804-2655-4d92-8104-c220e3ea9452} - - - - - - \ No newline at end of file diff --git a/Release/samples/WindowsLiveAuth/dirs.proj b/Release/samples/WindowsLiveAuth/dirs.proj deleted file mode 100644 index 7060c7e4f1..0000000000 --- a/Release/samples/WindowsLiveAuth/dirs.proj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/Release/samples/dirs.proj b/Release/samples/dirs.proj deleted file mode 100644 index 4abd4ec473..0000000000 --- a/Release/samples/dirs.proj +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/Release/src/build/vs12.winrt/casablanca120.winrt.vcxproj b/Release/src/build/vs12.winrt/casablanca120.winrt.vcxproj deleted file mode 100644 index c7bebcbdea..0000000000 --- a/Release/src/build/vs12.winrt/casablanca120.winrt.vcxproj +++ /dev/null @@ -1,68 +0,0 @@ - - - - - {9AD285A2-301E-47A0-A299-14AD5D4F2758} - Win32Proj - casablanca - en-US - 12.0 - SAK - SAK - SAK - SAK - true - true - DynamicLibrary - v120 - true - false - - $(OutDir)\$(MsBuildProjectName) - Windows Store - 8.1 - cpprestsdk120.winrt - - - - - - - - - - d - - - $(CppRestBaseFileName)120$(DebugFileSuffix)_app_$(CppRestSDKVersionFileSuffix) - - - - WINAPI_FAMILY=WINAPI_PARTITION_APP;_ASYNCRT_EXPORT;_PPLX_EXPORT;_USRDLL;%(PreprocessorDefinitions); - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm250 /bigobj %(AdditionalOptions) - true - - - msxml6.lib;kernel32.lib;user32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - false - - - - - - - - - copy /Y $(OutDir)\* $(OutDir)..\ - link /edit /appcontainer:no $(OutDir)..\$(TargetName).dll - exit 0 - Copying $(TargetName).winrt binaries to OutDir and removing appcontainer flag - - - \ No newline at end of file diff --git a/Release/src/build/vs12.wp81/casablanca120.wp81.vcxproj b/Release/src/build/vs12.wp81/casablanca120.wp81.vcxproj deleted file mode 100644 index 8123760fa6..0000000000 --- a/Release/src/build/vs12.wp81/casablanca120.wp81.vcxproj +++ /dev/null @@ -1,68 +0,0 @@ - - - - - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B} - Win32Proj - casablanca - en-US - 12.0 - SAK - SAK - SAK - SAK - true - true - DynamicLibrary - v120_wp81 - true - false - - $(OutDir)\$(MsBuildProjectName) - Windows Phone - 8.1 - cpprestsdk120.wp81 - - - - - - - - - - d - - - $(CppRestBaseFileName)120$(DebugFileSuffix)_wp81_$(CppRestSDKVersionFileSuffix) - - - - WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP;_ASYNCRT_EXPORT;_PPLX_EXPORT;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm250 %(AdditionalOptions) - true - - - msxml6.lib;WindowsPhoneCore.lib;RuntimeObject.lib;PhoneAppModelHost.lib;%(AdditionalDependencies) - false - UseLinkTimeCodeGeneration - - - - - - - - - copy /Y $(OutDir)\* $(OutDir)..\ - link /edit /appcontainer:no $(OutDir)..\$(TargetName).dll - exit 0 - Copying $(TargetName).winrt binaries to OutDir and removing appcontainer flag - - - \ No newline at end of file diff --git a/Release/src/build/vs12.wps81/casablanca120.wps81.vcxproj b/Release/src/build/vs12.wps81/casablanca120.wps81.vcxproj deleted file mode 100644 index 7d6d0172a4..0000000000 --- a/Release/src/build/vs12.wps81/casablanca120.wps81.vcxproj +++ /dev/null @@ -1,66 +0,0 @@ - - - - - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D} - Win32Proj - en-US - 12.0 - SAK - SAK - SAK - SAK - true - true - DynamicLibrary - v120 - true - false - - $(OutDir)\$(MsBuildProjectName) - Windows Phone Silverlight - 8.1 - cpprestsdk120.wps81 - - - - - - - - - - d - - - $(CppRestBaseFileName)120$(DebugFileSuffix)_wps81_$(CppRestSDKVersionFileSuffix) - - - - CPPREST_EXCLUDE_WEBSOCKETS;WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP;_ASYNCRT_EXPORT;_PPLX_EXPORT;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm250 %(AdditionalOptions) - true - - - msxml6.lib;WindowsPhoneCore.lib;RuntimeObject.lib;PhoneAppModelHost.lib;%(AdditionalDependencies) - false - UseLinkTimeCodeGeneration - - - - - - - - copy /Y $(OutDir)\* $(OutDir)..\ - link /edit /appcontainer:no $(OutDir)..\$(TargetName).dll - exit 0 - Copying $(TargetName).winrt binaries to OutDir and removing appcontainer flag - - - \ No newline at end of file diff --git a/Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj b/Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj deleted file mode 100644 index 91a91c3134..0000000000 --- a/Release/src/build/vs12.xp.static/casablanca120.xp.static.vcxproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - DebugStatic - ARM - - - DebugStatic - Win32 - - - DebugStatic - x64 - - - ReleaseStatic - ARM - - - ReleaseStatic - Win32 - - - ReleaseStatic - x64 - - - - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3} - Win32Proj - SAK - SAK - SAK - SAK - StaticLibrary - v120_xp - false - true - cpprestsdk120.xp.static - - - - - - - - true - true - true - true - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)120$(DebugFileSuffix)_xp_$(CppRestSDKVersionFileSuffix) - 58b07c0c - - - - - - - _NO_ASYNCRTIMP;_WINSOCK_DEPRECATED_NO_WARNINGS;CPPREST_TARGET_XP;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm160 /bigobj %(AdditionalOptions) - MultiThreadedDebugDLL - MultiThreadedDLL - true - - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - - - Winhttp.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs12.xp.static/packages.config b/Release/src/build/vs12.xp.static/packages.config deleted file mode 100644 index 7b1dc6aac0..0000000000 --- a/Release/src/build/vs12.xp.static/packages.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs12.xp/casablanca120.xp.vcxproj b/Release/src/build/vs12.xp/casablanca120.xp.vcxproj deleted file mode 100644 index 037e2a439a..0000000000 --- a/Release/src/build/vs12.xp/casablanca120.xp.vcxproj +++ /dev/null @@ -1,83 +0,0 @@ - - - - - {15F3B200-1AED-4B57-AF37-B21CD67914B1} - Win32Proj - SAK - SAK - SAK - SAK - DynamicLibrary - v120_xp - false - true - cpprestsdk120.xp - - - - - - - - true - true - true - true - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)120$(DebugFileSuffix)_xp_$(CppRestSDKVersionFileSuffix) - 58b07c0c - - - - - - - _WINSOCK_DEPRECATED_NO_WARNINGS;CPPREST_TARGET_XP;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm160 /bigobj %(AdditionalOptions) - MultiThreadedDebugDLL - MultiThreadedDLL - true - - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - - - Winhttp.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs12.xp/packages.config b/Release/src/build/vs12.xp/packages.config deleted file mode 100644 index 7b1dc6aac0..0000000000 --- a/Release/src/build/vs12.xp/packages.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs12/casablanca120.vcxproj b/Release/src/build/vs12/casablanca120.vcxproj deleted file mode 100644 index 5140823890..0000000000 --- a/Release/src/build/vs12/casablanca120.vcxproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - {01A76234-E6E8-4332-9FE2-1E12C34621BE} - Win32Proj - SAK - SAK - SAK - SAK - DynamicLibrary - v120 - false - false - cpprestsdk120 - - - - - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)120$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) - 1af61e94 - Unicode - - - - Designer - - - - - _WINSOCK_DEPRECATED_NO_WARNINGS;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm160 /bigobj %(AdditionalOptions) - MultiThreadedDebugDLL - MultiThreadedDLL - true - - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - - - Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs12/packages.config b/Release/src/build/vs12/packages.config deleted file mode 100644 index 7b1dc6aac0..0000000000 --- a/Release/src/build/vs12/packages.config +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/dirs.proj b/Release/src/dirs.proj deleted file mode 100644 index 96b0b6fc94..0000000000 --- a/Release/src/dirs.proj +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/TestRunner/dirs.proj b/Release/tests/common/TestRunner/dirs.proj deleted file mode 100644 index b8119ce4e7..0000000000 --- a/Release/tests/common/TestRunner/dirs.proj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj b/Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj deleted file mode 100644 index cd7e87d376..0000000000 --- a/Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj +++ /dev/null @@ -1,250 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {26009642-9C25-441F-B138-395E14DF2FB6} - Win32Proj - TestRunner - $(VCTargetsPath12) - SAK - SAK - SAK - SAK - - - - Application - true - Unicode - v120 - - - Application - true - Unicode - v120 - - - Application - true - Unicode - v120 - - - Application - false - true - Unicode - v120 - - - Application - false - true - Unicode - v120 - - - Application - false - true - Unicode - v120 - - - - - - - - - - - - - - - - - - - - - - - TestRunner.winrt - - - TestRunner.winrt - - - TestRunner.winrt - - - false - TestRunner.winrt - - - false - TestRunner.winrt - - - false - TestRunner.winrt - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - - NotUsing - Disabled - WINRT_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - Disabled - WINRT_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - Disabled - WINRT_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - WINRT_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - WINRT_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - WINRT_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - - - - diff --git a/Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj.filters b/Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj.filters deleted file mode 100644 index f9fa6c25ca..0000000000 --- a/Release/tests/common/TestRunner/vs12.winrt/TestRunner120.winrt.vcxproj.filters +++ /dev/null @@ -1,24 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - {5e4d32c8-a472-4388-b880-920a7a546fa3} - - - {f05a925c-282c-4424-ae9a-10fe7f88fe47} - - - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj b/Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj deleted file mode 100644 index e4479c83cc..0000000000 --- a/Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj +++ /dev/null @@ -1,250 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {6490C580-DD4A-4F2D-A345-732C5148349F} - Win32Proj - TestRunner - $(VCTargetsPath12) - SAK - SAK - SAK - SAK - - - - Application - true - Unicode - v120 - - - Application - true - Unicode - v120 - - - Application - true - Unicode - v120 - - - Application - false - true - Unicode - v120 - - - Application - false - true - Unicode - v120 - - - Application - false - true - Unicode - v120 - - - - - - - - - - - - - - - - - - - - - - - TestRunner - - - TestRunner - - - TestRunner - - - false - TestRunner - - - false - TestRunner - - - false - TestRunner - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - - NotUsing - Disabled - DESKTOP_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - Disabled - DESKTOP_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - Disabled - DESKTOP_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - DESKTOP_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - DESKTOP_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - DESKTOP_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - - - - diff --git a/Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj.filters b/Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj.filters deleted file mode 100644 index f9fa6c25ca..0000000000 --- a/Release/tests/common/TestRunner/vs12/TestRunner120.vcxproj.filters +++ /dev/null @@ -1,24 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - {5e4d32c8-a472-4388-b880-920a7a546fa3} - - - {f05a925c-282c-4424-ae9a-10fe7f88fe47} - - - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/dirs.proj b/Release/tests/common/UnitTestpp/dirs.proj deleted file mode 100644 index 20495a4cf3..0000000000 --- a/Release/tests/common/UnitTestpp/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj b/Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj deleted file mode 100644 index 11967444c9..0000000000 --- a/Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj +++ /dev/null @@ -1,263 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - Win32Proj - UnitTest - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories); - Use - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store;%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store\arm;%(AdditionalLibraryDirectories); - uuid.lib;ole32.lib;msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store\amd64;%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store;%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store\arm;%(AdditionalLibraryDirectories); - uuid.lib;ole32.lib;msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store\amd64;%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj.filters b/Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj.filters deleted file mode 100644 index 6fd73f9e3b..0000000000 --- a/Release/tests/common/UnitTestpp/vs12.winrt/UnitTestpp120.winrt.vcxproj.filters +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {640fb93d-0deb-4bc4-a035-5d44d5c2af4b} - - - {b883825b-c6c4-4545-806e-dfe105753ac8} - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj b/Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj deleted file mode 100644 index c77c6b7430..0000000000 --- a/Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj +++ /dev/null @@ -1,202 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {E715BBE6-743D-47C2-8F43-92AA18F6ED19} - Win32Proj - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - TestUnitTestpp120 - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);%(AdditionalIncludeDirectories); - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - MaxSpeed - NotUsing - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - - - - diff --git a/Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj.filters b/Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj.filters deleted file mode 100644 index 44e0743ad6..0000000000 --- a/Release/tests/common/UnitTestpp/vs12/TestUnitTestpp120.vcxproj.filters +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - - - {420b7d9f-7900-40f3-8aa7-3c800278bc98} - - - {7ddca59d-156c-46f2-af93-4a03f915bbcb} - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj b/Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj deleted file mode 100644 index 1c60278851..0000000000 --- a/Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - Win32Proj - UnitTest - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - UnitTestpp120 - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories); - Use - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj.filters b/Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj.filters deleted file mode 100644 index 6fd73f9e3b..0000000000 --- a/Release/tests/common/UnitTestpp/vs12/UnitTestpp120.vcxproj.filters +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {640fb93d-0deb-4bc4-a035-5d44d5c2af4b} - - - {b883825b-c6c4-4545-806e-dfe105753ac8} - - - \ No newline at end of file diff --git a/Release/tests/common/dirs.proj b/Release/tests/common/dirs.proj deleted file mode 100644 index 51622a29de..0000000000 --- a/Release/tests/common/dirs.proj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/Release/tests/common/utilities/dirs.proj b/Release/tests/common/utilities/dirs.proj deleted file mode 100644 index 953e655a6e..0000000000 --- a/Release/tests/common/utilities/dirs.proj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj b/Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj deleted file mode 100644 index 98a3534883..0000000000 --- a/Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj +++ /dev/null @@ -1,274 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - Win32Proj - CommonUtilities120 - SAK - SAK - SAK - SAK - en-US - 12.0 - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store\arm;$(OutDir);%(AdditionalLibraryDirectories); - uuid.lib;ole32.lib;msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store\arm;$(OutDir);%(AdditionalLibraryDirectories); - uuid.lib;ole32.lib;msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;%(AdditionalDependencies) - true - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {26009642-9C25-441F-B138-395E14DF2FB6} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj.filters b/Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj.filters deleted file mode 100644 index 1325242b47..0000000000 --- a/Release/tests/common/utilities/vs12.winrt/CommonUtilities120.winrt.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {24e13f0e-e0f6-4fe0-922a-5cf7cbe823f4} - - - {ef18a939-f1a3-4e9e-b93a-05826fbae7f6} - - - \ No newline at end of file diff --git a/Release/tests/common/utilities/vs12.xp/CommonUtilities120.xp.vcxproj b/Release/tests/common/utilities/vs12.xp/CommonUtilities120.xp.vcxproj deleted file mode 100644 index 5073a3d364..0000000000 --- a/Release/tests/common/utilities/vs12.xp/CommonUtilities120.xp.vcxproj +++ /dev/null @@ -1,150 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - Win32Proj - CommonUtilities120 - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Create - Create - Create - Create - - - - - - - - - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {6490c580-dd4a-4f2d-a345-732c5148349f} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - - - - \ No newline at end of file diff --git a/Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj b/Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj deleted file mode 100644 index ae0cf1656c..0000000000 --- a/Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj +++ /dev/null @@ -1,203 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - Win32Proj - CommonUtilities120 - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Advapi32.lib;kernel32.lib;user32.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Advapi32.lib;kernel32.lib;user32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {6490C580-DD4A-4F2D-A345-732C5148349F} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - diff --git a/Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj.filters b/Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj.filters deleted file mode 100644 index 1325242b47..0000000000 --- a/Release/tests/common/utilities/vs12/CommonUtilities120.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {24e13f0e-e0f6-4fe0-922a-5cf7cbe823f4} - - - {ef18a939-f1a3-4e9e-b93a-05826fbae7f6} - - - \ No newline at end of file diff --git a/Release/tests/dirs.proj b/Release/tests/dirs.proj deleted file mode 100644 index 93af424583..0000000000 --- a/Release/tests/dirs.proj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/Release/tests/functional/dirs.proj b/Release/tests/functional/dirs.proj deleted file mode 100644 index 7c81a4e0a5..0000000000 --- a/Release/tests/functional/dirs.proj +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/client/AuthListener/App.config b/Release/tests/functional/http/client/AuthListener/App.config deleted file mode 100644 index 8e15646352..0000000000 --- a/Release/tests/functional/http/client/AuthListener/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/AuthListener/Program.cs b/Release/tests/functional/http/client/AuthListener/Program.cs deleted file mode 100644 index eabc9c4844..0000000000 --- a/Release/tests/functional/http/client/AuthListener/Program.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System; -using System.Collections; -using System.Collections.Specialized; -using System.IO; -using System.Net; -using System.Reflection; -using System.Text; -using System.Threading; - -class Program -{ - /// - /// Checks if the appropriate authentication scheme was used. - /// - /// - /// - /// True if verification was successful, false otherwise. - public static bool VerifyAuthenticationScheme(AuthenticationSchemes listenerAuthScheme, HttpListenerContext requestContext) - { - System.Security.Principal.IIdentity id = null; - if (requestContext.User != null) - { - id = requestContext.User.Identity; - Console.WriteLine("IsAuthenticated:{0}", id.IsAuthenticated); - Console.WriteLine("AuthenticationType:{0}", id.AuthenticationType); - Console.WriteLine("Name:{0}", id.Name); - - if (requestContext.Request.Headers.AllKeys.Contains("UserName")) - { - if (string.Compare(requestContext.Request.Headers["UserName"], id.Name, true) != 0) - { - return false; - } - } - } - - switch (listenerAuthScheme) - { - case AuthenticationSchemes.Anonymous: - if (id != null) - { - return false; - } - break; - case AuthenticationSchemes.Basic: - if (!id.IsAuthenticated || id.AuthenticationType != "Basic") - { - return false; - } - HttpListenerBasicIdentity basicId = (HttpListenerBasicIdentity)id; - if (string.Compare(basicId.Password, requestContext.Request.Headers["Password"], true) != 0) - { - return false; - } - break; - case AuthenticationSchemes.Digest: - if (!id.IsAuthenticated || id.AuthenticationType != "Digest") - { - return false; - } - break; - case AuthenticationSchemes.Ntlm: - if (!id.IsAuthenticated || id.AuthenticationType != "NTLM") - { - return false; - } - break; - case AuthenticationSchemes.Negotiate: - if (!id.IsAuthenticated || id.AuthenticationType != "NTLM") - { - return false; - } - break; - case AuthenticationSchemes.IntegratedWindowsAuthentication: - if (!id.IsAuthenticated || id.AuthenticationType != "NTLM") - { - return false; - } - break; - default: - return false; - } - return true; - } - - static void Main(string []args) - { - if(args.Length != 2) - { - Console.WriteLine("Error: please specify URI to listen on and Authentication type to use:\nAuthListener.exe ServerURI AuthenticationScheme"); - return; - } - string serverUri = args[0]; - AuthenticationSchemes authScheme; - switch(args[1].ToLower()) - { - case "none": - authScheme = AuthenticationSchemes.None; - break; - case "anonymous": - authScheme = AuthenticationSchemes.Anonymous; - break; - case "basic": - authScheme = AuthenticationSchemes.Basic; - break; - case "digest": - authScheme = AuthenticationSchemes.Digest; - break; - case "ntlm": - authScheme = AuthenticationSchemes.Ntlm; - break; - case "negotiate": - authScheme = AuthenticationSchemes.Negotiate; - break; - case "integrated": - authScheme = AuthenticationSchemes.IntegratedWindowsAuthentication; - break; - default: - Console.WriteLine("Error: unrecognized AuthenticationScheme:{0}", args[1]); - return; - } - - HttpListener listener = new HttpListener(); - listener.Prefixes.Add(serverUri); - listener.AuthenticationSchemes = authScheme; - - listener.Start(); - Console.WriteLine("Listening..."); - - HttpListenerContext context = listener.GetContext(); - Console.WriteLine("Received request..."); - StreamWriter writer = new StreamWriter(context.Response.OutputStream); - - // Verify correct authentication scheme was used. - if (!VerifyAuthenticationScheme(listener.AuthenticationSchemes, context)) - { - context.Response.StatusCode = (int)HttpStatusCode.ExpectationFailed; - writer.Write("Error authentication validation failed"); - } - - context.Response.Close(); - } -} \ No newline at end of file diff --git a/Release/tests/functional/http/client/AuthListener/Properties/AssemblyInfo.cs b/Release/tests/functional/http/client/AuthListener/Properties/AssemblyInfo.cs deleted file mode 100644 index c6467dfbe7..0000000000 --- a/Release/tests/functional/http/client/AuthListener/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("AuthListner")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("AuthListner")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("91128a88-2401-47d2-aef5-c0d72dc55426")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Release/tests/functional/http/client/AuthListener/dirs.proj b/Release/tests/functional/http/client/AuthListener/dirs.proj deleted file mode 100644 index 277f6ee4ec..0000000000 --- a/Release/tests/functional/http/client/AuthListener/dirs.proj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj b/Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj deleted file mode 100644 index e34311d956..0000000000 --- a/Release/tests/functional/http/client/AuthListener/vs12/AuthListener120.csproj +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - Debug - AnyCPU - {3052AD81-465E-4A2E-B278-DF5FC4BB604C} - Exe - Properties - AuthListener - AuthListener120 - v4.5 - 512 - - - AnyCPU - true - full - false - - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/dirs.proj b/Release/tests/functional/http/client/dirs.proj deleted file mode 100644 index 56056487eb..0000000000 --- a/Release/tests/functional/http/client/dirs.proj +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj b/Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj deleted file mode 100644 index ccbcd17b16..0000000000 --- a/Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj +++ /dev/null @@ -1,257 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {e66e4531-ac9c-459b-a4ca-87592eb0eeb8} - HttpTests - SAK - SAK - SAK - SAK - en-US - 12.0 - true - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities\include;%(AdditionalIncludeDirectories) - - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;%(AdditionalUsingDirectories) - true - false - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;%(AdditionalUsingDirectories) - true - false - -Zm350 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;%(AdditionalUsingDirectories) - true - false - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;%(AdditionalUsingDirectories) - true - false - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;%(AdditionalUsingDirectories) - true - false - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;%(AdditionalUsingDirectories) - true - false - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {06F4E6FA-152F-4AA7-B8D0-F3EBC5F11F81} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj.filters b/Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj.filters deleted file mode 100644 index a8536ce996..0000000000 --- a/Release/tests/functional/http/client/vs12.winrt/HttpClient120_test.winrt.vcxproj.filters +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - - - {fadb7f38-3d0c-4a31-af39-6364be0d9793} - - - {ee68ca67-bbcf-4196-89c7-fbf59083ac16} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj b/Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj deleted file mode 100644 index f0294802c5..0000000000 --- a/Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj +++ /dev/null @@ -1,234 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {dc215f97-c43c-47f5-9784-711908a24ae3} - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities\include;%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - {6837625b-c0db-4fd0-aee2-19699031b76e} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - diff --git a/Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj.filters b/Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj.filters deleted file mode 100644 index 6a577a5662..0000000000 --- a/Release/tests/functional/http/client/vs12/HttpClient120_test.vcxproj.filters +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - Source Files - - - - - Header Files - - - Header Files - - - - - {fadb7f38-3d0c-4a31-af39-6364be0d9793} - - - {ee68ca67-bbcf-4196-89c7-fbf59083ac16} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/dirs.proj b/Release/tests/functional/http/dirs.proj deleted file mode 100644 index bce0f05b62..0000000000 --- a/Release/tests/functional/http/dirs.proj +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/listener/dirs.proj b/Release/tests/functional/http/listener/dirs.proj deleted file mode 100644 index 160e1126af..0000000000 --- a/Release/tests/functional/http/listener/dirs.proj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj b/Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj deleted file mode 100644 index 166fc078ec..0000000000 --- a/Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj +++ /dev/null @@ -1,236 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {2853ec0b-1b8e-4d9d-8436-4ef6dded5378} - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - - - - - - - - - - - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {6837625b-c0db-4fd0-aee2-19699031b76e} - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - diff --git a/Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj.filters b/Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj.filters deleted file mode 100644 index 8275b21007..0000000000 --- a/Release/tests/functional/http/listener/vs12/HttpListener120_test.vcxproj.filters +++ /dev/null @@ -1,66 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - - - {3de7d3df-7d70-4ea1-a460-bc378ed266c2} - - - {4ac74123-f940-4347-9a8e-d9e35ba7c7ac} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/dirs.proj b/Release/tests/functional/http/utilities/dirs.proj deleted file mode 100644 index c71ce6f396..0000000000 --- a/Release/tests/functional/http/utilities/dirs.proj +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj b/Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj deleted file mode 100644 index f871c60361..0000000000 --- a/Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj +++ /dev/null @@ -1,246 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {06F4E6FA-152F-4AA7-B8D0-F3EBC5F11F81} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 12.0 - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - true - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - true - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store\arm;$(OutDir);%(AdditionalLibraryDirectories); - uuid.lib;ole32.lib;msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store\arm;$(OutDir);%(AdditionalLibraryDirectories); - uuid.lib;ole32.lib;msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - true - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj.filters b/Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj.filters deleted file mode 100644 index c965e9cb22..0000000000 --- a/Release/tests/functional/http/utilities/vs12.winrt/HttpTestUtilities120.winrt.vcxproj.filters +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {96f6b99e-76ae-4ace-801c-39bb8d308125} - - - {d4ba757b-dfdc-4d61-a9bd-19e957c5a09c} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj b/Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj deleted file mode 100644 index ff4a1656e9..0000000000 --- a/Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj +++ /dev/null @@ -1,218 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {6837625b-c0db-4fd0-aee2-19699031b76e} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include;%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm140 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm140 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj.filters b/Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj.filters deleted file mode 100644 index 1e583ce8ed..0000000000 --- a/Release/tests/functional/http/utilities/vs12/HttpTestUtilities120.vcxproj.filters +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {d0052d1d-10e0-42da-9df6-72be473a8ebe} - - - {a4317631-da2e-4508-982f-e689f8d4a039} - - - \ No newline at end of file diff --git a/Release/tests/functional/json/dirs.proj b/Release/tests/functional/json/dirs.proj deleted file mode 100644 index 14b704700e..0000000000 --- a/Release/tests/functional/json/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj b/Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj deleted file mode 100644 index 151a7e5be7..0000000000 --- a/Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj +++ /dev/null @@ -1,234 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {D398DF71-8642-4BC4-940F-9AE2B0AE1CE4} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 12.0 - $(VCTargetsPath12) - true - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj.filters b/Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj.filters deleted file mode 100644 index ae62883eba..0000000000 --- a/Release/tests/functional/json/vs12.winrt/JSON120_test.winrt.vcxproj.filters +++ /dev/null @@ -1,42 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {db714d7a-c017-4d4f-99ab-f1f195ba360c} - - - {3ea4dfd5-d8b3-4370-adda-ea04dcaf401b} - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs12.xp/JSON120_test.xp.vcxproj b/Release/tests/functional/json/vs12.xp/JSON120_test.xp.vcxproj deleted file mode 100644 index 2681aa86e2..0000000000 --- a/Release/tests/functional/json/vs12.xp/JSON120_test.xp.vcxproj +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {ABA69F91-45D4-41D8-991A-10A6319E42C3} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - $(OutDir)%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs12/JSON120_test.vcxproj b/Release/tests/functional/json/vs12/JSON120_test.vcxproj deleted file mode 100644 index 2290a41c53..0000000000 --- a/Release/tests/functional/json/vs12/JSON120_test.vcxproj +++ /dev/null @@ -1,207 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {6f026328-4d10-4ef1-bd6c-8fd3cbe0f530} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - - - Console - true - $(OutDir)%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - diff --git a/Release/tests/functional/json/vs12/JSON120_test.vcxproj.filters b/Release/tests/functional/json/vs12/JSON120_test.vcxproj.filters deleted file mode 100644 index 8ee98cfa77..0000000000 --- a/Release/tests/functional/json/vs12/JSON120_test.vcxproj.filters +++ /dev/null @@ -1,44 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/misc/atl_headers/dirs.proj b/Release/tests/functional/misc/atl_headers/dirs.proj deleted file mode 100644 index 93cc367da8..0000000000 --- a/Release/tests/functional/misc/atl_headers/dirs.proj +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj b/Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj deleted file mode 100644 index b7efae465f..0000000000 --- a/Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj +++ /dev/null @@ -1,173 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {32DB3115-2918-477F-B00A-DAC6277EEFAB} - Win32Proj - header_test100 - SAK - SAK - SAK - SAK - atl_header120 - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - Dynamic - Dynamic - v120 - - - DynamicLibrary - true - Unicode - Dynamic - Dynamic - v120 - - - DynamicLibrary - false - true - Unicode - Dynamic - v120 - - - DynamicLibrary - false - true - Unicode - Dynamic - v120 - - - - - - - - - - - - - - - - - - - - - false - - - false - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HEADER_TEST_EXPORTS;%(PreprocessorDefinitions);_AFXDLL - $(CommonTestIncludeDir);$(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - MultiThreadedDebugDLL - - - Windows - true - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HEADER_TEST_EXPORTS;%(PreprocessorDefinitions);_AFXDLL - $(CommonTestIncludeDir);$(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - MultiThreadedDebugDLL - - - Windows - true - - - - - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HEADER_TEST_EXPORTS;%(PreprocessorDefinitions);_AFXDLL - $(CommonTestIncludeDir);$(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - MultiThreadedDLL - - - Windows - true - true - true - - - - - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HEADER_TEST_EXPORTS;%(PreprocessorDefinitions);_AFXDLL - $(CommonTestIncludeDir);$(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - MultiThreadedDLL - - - Windows - true - true - true - - - - - - - - - - - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj.filters b/Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj.filters deleted file mode 100644 index 1adba0e43f..0000000000 --- a/Release/tests/functional/misc/atl_headers/vs12/header_test120.vcxproj.filters +++ /dev/null @@ -1,32 +0,0 @@ - - - - - Source FIles - - - Source FIles - - - - - {e9450d87-ef77-4303-b158-baa118a801f2} - - - {aaa56f3f-2db2-4047-a0b4-3b3ba827fef9} - - - {b5ccd6e9-b76b-4fd9-8492-c978dd95f5a3} - - - - - Header Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/Release/tests/functional/misc/dirs.proj b/Release/tests/functional/misc/dirs.proj deleted file mode 100644 index 43af01e15e..0000000000 --- a/Release/tests/functional/misc/dirs.proj +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - diff --git a/Release/tests/functional/misc/version/dirs.proj b/Release/tests/functional/misc/version/dirs.proj deleted file mode 100644 index f3f76d4aac..0000000000 --- a/Release/tests/functional/misc/version/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/pplx/dirs.proj b/Release/tests/functional/pplx/dirs.proj deleted file mode 100644 index 1ce745ee07..0000000000 --- a/Release/tests/functional/pplx/dirs.proj +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/Release/tests/functional/pplx/pplx_test/dirs.proj b/Release/tests/functional/pplx/pplx_test/dirs.proj deleted file mode 100644 index 559175d100..0000000000 --- a/Release/tests/functional/pplx/pplx_test/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/pplx/pplx_test/vs12.winrt/pplx120_test.winrt.vcxproj b/Release/tests/functional/pplx/pplx_test/vs12.winrt/pplx120_test.winrt.vcxproj deleted file mode 100644 index 4c8d4314a3..0000000000 --- a/Release/tests/functional/pplx/pplx_test/vs12.winrt/pplx120_test.winrt.vcxproj +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {23A43AC2-1E04-4589-B0A9-0295962755DC} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - en-US - 12.0 - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - /bigobj %(AdditionalOptions) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - /bigobj %(AdditionalOptions) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - /bigobj %(AdditionalOptions) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - /bigobj %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - /bigobj %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - /bigobj %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/pplx/pplx_test/vs12.xp/pplx120_test.xp.vcxproj b/Release/tests/functional/pplx/pplx_test/vs12.xp/pplx120_test.xp.vcxproj deleted file mode 100644 index 04ec221801..0000000000 --- a/Release/tests/functional/pplx/pplx_test/vs12.xp/pplx120_test.xp.vcxproj +++ /dev/null @@ -1,158 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {EB4A3750-CA93-4968-89D7-3ED467DB2C59} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Level4 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level4 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level4 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level4 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - {75885703-7F3D-4086-8E60-C60B9B126F7E} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/pplx/pplx_test/vs12/pplx120_test.vcxproj b/Release/tests/functional/pplx/pplx_test/vs12/pplx120_test.vcxproj deleted file mode 100644 index 2d391753e2..0000000000 --- a/Release/tests/functional/pplx/pplx_test/vs12/pplx120_test.vcxproj +++ /dev/null @@ -1,216 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {5115840e-a5a8-4044-b595-cda05c2d65d0} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - - Level3 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/dirs.proj b/Release/tests/functional/streams/dirs.proj deleted file mode 100644 index 1740e6d983..0000000000 --- a/Release/tests/functional/streams/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj b/Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj deleted file mode 100644 index 1eac7a67bd..0000000000 --- a/Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj +++ /dev/null @@ -1,246 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {337E0660-2300-4DC6-883E-283D5A7281B5} - Win32Proj - SAK - SAK - SAK - SAK - en-US - 12.0 - true - $(VCTargetsPath12) - e13f21ed - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - Unicode - v120 - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm160 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm160 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm160 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm160 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm160 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm160 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj.filters b/Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj.filters deleted file mode 100644 index 86b36e3575..0000000000 --- a/Release/tests/functional/streams/vs12.winrt/streams120_test.winrt.vcxproj.filters +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {274676f3-573c-4a10-adbb-0421159c8a2a} - - - {dd303bf1-0c87-4079-a035-c16d23cf129d} - - - - - Header Files - - - Header Files - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs12.xp/streams120_test.xp.vcxproj b/Release/tests/functional/streams/vs12.xp/streams120_test.xp.vcxproj deleted file mode 100644 index 3ced480633..0000000000 --- a/Release/tests/functional/streams/vs12.xp/streams120_test.xp.vcxproj +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {F279F1ED-8AFF-478D-9A20-DDCAD8CBA336} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - 2276c549 - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs12/streams120_test.vcxproj b/Release/tests/functional/streams/vs12/streams120_test.vcxproj deleted file mode 100644 index 04c97f0915..0000000000 --- a/Release/tests/functional/streams/vs12/streams120_test.vcxproj +++ /dev/null @@ -1,216 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {181ccb80-9ae8-4ed7-8b7d-4c0cbc80eedd} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - 84fd5b75 - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - ARM;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - ARM;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - - - - - diff --git a/Release/tests/functional/streams/vs12/streams120_test.vcxproj.filters b/Release/tests/functional/streams/vs12/streams120_test.vcxproj.filters deleted file mode 100644 index fec2efca0f..0000000000 --- a/Release/tests/functional/streams/vs12/streams120_test.vcxproj.filters +++ /dev/null @@ -1,43 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - - {1de3a9ce-57af-48bd-8125-3af4f406be26} - - - {3c2936bc-8d1e-4a33-96c9-5cfb3d83b30d} - - - - - Header Files - - - Header Files - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/dirs.proj b/Release/tests/functional/uri/dirs.proj deleted file mode 100644 index fcaf28aa55..0000000000 --- a/Release/tests/functional/uri/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/uri/vs12.winrt/URI120_test.winrt.vcxproj.filters b/Release/tests/functional/uri/vs12.winrt/URI120_test.winrt.vcxproj.filters deleted file mode 100644 index fd4f136ea8..0000000000 --- a/Release/tests/functional/uri/vs12.winrt/URI120_test.winrt.vcxproj.filters +++ /dev/null @@ -1,57 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {e30fa8ae-3cb4-4a63-870b-a7e85088a9ad} - - - {e7f8af98-2e23-4c57-93e1-2936a3f0ac84} - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/vs12.winrt/Uri120_test.winrt.vcxproj b/Release/tests/functional/uri/vs12.winrt/Uri120_test.winrt.vcxproj deleted file mode 100644 index 52abbff812..0000000000 --- a/Release/tests/functional/uri/vs12.winrt/Uri120_test.winrt.vcxproj +++ /dev/null @@ -1,234 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {9169C20C-B98A-46C6-A138-A107C458E8DD} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 12.0 - true - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - - - - - - - - - diff --git a/Release/tests/functional/uri/vs12.xp/Uri120_test.xp.vcxproj b/Release/tests/functional/uri/vs12.xp/Uri120_test.xp.vcxproj deleted file mode 100644 index 201dae39c4..0000000000 --- a/Release/tests/functional/uri/vs12.xp/Uri120_test.xp.vcxproj +++ /dev/null @@ -1,155 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {66B6D1E2-A91C-4DA3-8568-B7457FA7ED6D} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/vs12/Uri120_test.vcxproj b/Release/tests/functional/uri/vs12/Uri120_test.vcxproj deleted file mode 100644 index bc0e8c5861..0000000000 --- a/Release/tests/functional/uri/vs12/Uri120_test.vcxproj +++ /dev/null @@ -1,208 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {3d9c3f25-1736-4d39-a31f-6b2de34e20cf} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - diff --git a/Release/tests/functional/uri/vs12/Uri120_test.vcxproj.filters b/Release/tests/functional/uri/vs12/Uri120_test.vcxproj.filters deleted file mode 100644 index 8c9f65a853..0000000000 --- a/Release/tests/functional/uri/vs12/Uri120_test.vcxproj.filters +++ /dev/null @@ -1,59 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/dirs.proj b/Release/tests/functional/utils/dirs.proj deleted file mode 100644 index f01337a94f..0000000000 --- a/Release/tests/functional/utils/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj b/Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj deleted file mode 100644 index 30335ca23c..0000000000 --- a/Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj +++ /dev/null @@ -1,229 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {4fddc511-5cfd-48a0-b373-43b13a43fb45} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 12.0 - true - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - - - - - - - - diff --git a/Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj.filters b/Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj.filters deleted file mode 100644 index a2199f62fb..0000000000 --- a/Release/tests/functional/utils/vs12.winrt/Utils120_test.winrt.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {e30fa8ae-3cb4-4a63-870b-a7e85088a9ad} - - - {e7f8af98-2e23-4c57-93e1-2936a3f0ac84} - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/vs12.xp/Utils120_test.xp.vcxproj b/Release/tests/functional/utils/vs12.xp/Utils120_test.xp.vcxproj deleted file mode 100644 index 2067371412..0000000000 --- a/Release/tests/functional/utils/vs12.xp/Utils120_test.xp.vcxproj +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {E9E26CDB-4CE3-4B0E-AAF8-D32F57E48856} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/vs12/Utils120_test.vcxproj b/Release/tests/functional/utils/vs12/Utils120_test.vcxproj deleted file mode 100644 index 620d770a0f..0000000000 --- a/Release/tests/functional/utils/vs12/Utils120_test.vcxproj +++ /dev/null @@ -1,202 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {50386698-0180-4ebc-8827-f2c36561f6b4} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - diff --git a/Release/tests/functional/utils/vs12/Utils120_test.vcxproj.filters b/Release/tests/functional/utils/vs12/Utils120_test.vcxproj.filters deleted file mode 100644 index dfa7b86991..0000000000 --- a/Release/tests/functional/utils/vs12/Utils120_test.vcxproj.filters +++ /dev/null @@ -1,38 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/client/dirs.proj b/Release/tests/functional/websockets/client/dirs.proj deleted file mode 100644 index 15d6dbc4dd..0000000000 --- a/Release/tests/functional/websockets/client/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/websockets/client/vs12.winrt/websocketsclient120_test.winrt.vcxproj b/Release/tests/functional/websockets/client/vs12.winrt/websocketsclient120_test.winrt.vcxproj deleted file mode 100644 index 6ca0b5efeb..0000000000 --- a/Release/tests/functional/websockets/client/vs12.winrt/websocketsclient120_test.winrt.vcxproj +++ /dev/null @@ -1,179 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {8E3772EF-7807-40DA-8932-F37DB0C1CB44} - SAK - SAK - SAK - SAK - en-US - 12.0 - true - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities; - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm200 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm200 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm200 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WINAPI_FAMILY=WINAPI_PARTITION_APP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - -Zm200 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - {D422311C-1C3A-4083-A564-6474EA60FFC7} - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/client/vs12.xp/websocketsclient120_test.xp.vcxproj b/Release/tests/functional/websockets/client/vs12.xp/websocketsclient120_test.xp.vcxproj deleted file mode 100644 index e2bd01c665..0000000000 --- a/Release/tests/functional/websockets/client/vs12.xp/websocketsclient120_test.xp.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - WebsocketTests - SAK - SAK - SAK - SAK - websocketsclient120_test.xp - {BBE711C0-568C-48E5-A9EB-2F3741D0687B} - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities;%(AdditionalIncludeDirectories) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - - - MaxSpeed - true - true - CPPREST_TARGET_XP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - true - true - - - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - - - {3803246A-F31E-44EC-BCA9-87DF68C5EB8D} - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - diff --git a/Release/tests/functional/websockets/client/vs12/websocketsclient120_test.vcxproj b/Release/tests/functional/websockets/client/vs12/websocketsclient120_test.vcxproj deleted file mode 100644 index 8d02565a3c..0000000000 --- a/Release/tests/functional/websockets/client/vs12/websocketsclient120_test.vcxproj +++ /dev/null @@ -1,129 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9A23F9D2-4876-423B-9393-A604764601B0} - WebsocketTests - SAK - SAK - SAK - SAK - websocketsclient120_test - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities;%(AdditionalIncludeDirectories) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - StdCall - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - StdCall - - - true - true - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {14f7b7a0-a057-4e15-8ec4-12baf00b0f64} - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/dirs.proj b/Release/tests/functional/websockets/dirs.proj deleted file mode 100644 index 2c3829d5b2..0000000000 --- a/Release/tests/functional/websockets/dirs.proj +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/Release/tests/functional/websockets/utilities/dirs.proj b/Release/tests/functional/websockets/utilities/dirs.proj deleted file mode 100644 index e063f42b24..0000000000 --- a/Release/tests/functional/websockets/utilities/dirs.proj +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/functional/websockets/utilities/vs12.winrt/websockets_test_utilities120.winrt.vcxproj b/Release/tests/functional/websockets/utilities/vs12.winrt/websockets_test_utilities120.winrt.vcxproj deleted file mode 100644 index 9de41c333e..0000000000 --- a/Release/tests/functional/websockets/utilities/vs12.winrt/websockets_test_utilities120.winrt.vcxproj +++ /dev/null @@ -1,178 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {D422311C-1C3A-4083-A564-6474EA60FFC7} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 12.0 - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;Ws2_32.lib;Mswsock.lib;libboost_system-vc120-mt-gd-1_58.lib;%(AdditionalDependencies) - true - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - msvcrtd.lib;msvcprtd.lib;vccorlibd.lib;RuntimeObject.lib;Ws2_32.lib;Mswsock.lib;libboost_system-vc120-mt-gd-1_58.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;Ws2_32.lib;Mswsock.lib;libboost_system-vc120-mt-1_58.lib;%(AdditionalDependencies) - true - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);..\include - $(WindowsSDKDir)\References\CommonConfiguration\Neutral;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - - - Windows - true - true - true - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - msvcrt.lib;msvcprt.lib;vccorlib.lib;RuntimeObject.lib;Ws2_32.lib;Mswsock.lib;libboost_system-vc120-mt-1_58.lib;%(AdditionalDependencies) - true - - - - - {ea2d69a1-55c8-4c15-805e-de7e85872484} - - - {B341AA9C-F38B-4D59-B6B7-8F22491090B7} - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs12.xp/websockets_test_utilities120.xp.vcxproj b/Release/tests/functional/websockets/utilities/vs12.xp/websockets_test_utilities120.xp.vcxproj deleted file mode 100644 index 52a10dfef0..0000000000 --- a/Release/tests/functional/websockets/utilities/vs12.xp/websockets_test_utilities120.xp.vcxproj +++ /dev/null @@ -1,132 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - SAK - SAK - SAK - SAK - Win32Proj - en-US - 11.0 - tests::common::websockets_test_utilities - websockets_test_utilities120.xp - {3803246A-F31E-44EC-BCA9-87DF68C5EB8D} - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories) - - - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - true - true - - - - - - Create - Create - Create - Create - - - - - - - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - - - - - - - - - - - - - diff --git a/Release/tests/functional/websockets/utilities/vs12/packages.config b/Release/tests/functional/websockets/utilities/vs12/packages.config deleted file mode 100644 index b1cabf8f3a..0000000000 --- a/Release/tests/functional/websockets/utilities/vs12/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs12/websockets_test_utilities120.vcxproj b/Release/tests/functional/websockets/utilities/vs12/websockets_test_utilities120.vcxproj deleted file mode 100644 index c1a2a04c09..0000000000 --- a/Release/tests/functional/websockets/utilities/vs12/websockets_test_utilities120.vcxproj +++ /dev/null @@ -1,157 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {14F7B7A0-A057-4E15-8EC4-12BAF00B0F64} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 11.0 - tests::common::websockets_test_utilities - websockets_test_utilities120 - - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - DynamicLibrary - false - true - Unicode - v120 - - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories) - - - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - - - MaxSpeed - true - true - NDEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - true - true - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - - - - - - - - - - - - - diff --git a/cpprestsdk120.sln b/cpprestsdk120.sln deleted file mode 100644 index 59fc89bf4c..0000000000 --- a/cpprestsdk120.sln +++ /dev/null @@ -1,321 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "Release\src\build\common.vcxitems", "{594DCB5F-07E3-4084-A2CE-268611FA629F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "other", "Release\src\build\other.vcxitems", "{3D5908F7-7673-4229-BC46-2007A7AF9CAE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32", "Release\src\build\win32.vcxitems", "{F40F4804-50F9-4257-8D74-B9CBB19AC4C3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrt", "Release\src\build\winrt.vcxitems", "{0A9BA181-7876-4B3D-A5E0-EE673FA51C05}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120", "Release\src\build\vs12\casablanca120.vcxproj", "{01A76234-E6E8-4332-9FE2-1E12C34621BE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.winrt", "Release\src\build\vs12.winrt\casablanca120.winrt.vcxproj", "{9AD285A2-301E-47A0-A299-14AD5D4F2758}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.xp", "Release\src\build\vs12.xp\casablanca120.xp.vcxproj", "{15F3B200-1AED-4B57-AF37-B21CD67914B1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.wps81", "Release\src\build\vs12.wps81\casablanca120.wps81.vcxproj", "{C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.wp81", "Release\src\build\vs12.wp81\casablanca120.wp81.vcxproj", "{E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B27A3D67-1423-48D8-9F6D-D8FD7E682EC7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BingRequest", "BingRequest", "{06A71AA7-132E-4A1B-A353-C36B2779331F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest120", "Release\samples\BingRequest\BingRequest120\BingRequest120.vcxproj", "{2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest120.xp", "Release\samples\BingRequest\BingRequest120.xp\BingRequest120.xp.vcxproj", "{7009BCBE-D67C-4B54-BEFC-A44E62656CF1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SearchFile", "SearchFile", "{CA4D2B5D-D78C-4165-B8E6-0126FF584FCB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile120", "Release\samples\SearchFile\SearchFile120\SearchFile120.vcxproj", "{F03BEE03-BEFB-4B17-A774-D9C8246530D4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CasaLens", "CasaLens", "{BBB2B70F-1D96-4597-96B0-75EA9BE3CA2A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CasaLens120", "Release\samples\CasaLens\CasaLens120\CasaLens120.vcxproj", "{FFBFD6C1-B525-4D35-AB64-A2FE9460B147}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BlackJack", "BlackJack", "{843B16ED-DE6A-4541-B700-D65B384D43A0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{E442BD21-6B65-4D0E-A96C-623F605A9517}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{3D3149CF-B1FF-40C0-BD59-1B41FC3522F0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Client120", "Release\samples\BlackJack\BlackJack_Client\BlackJack_Client120\BlackJack_Client120.vcxproj", "{830B6E2F-9224-41D1-B9C7-A51FC78B00C7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Server120", "Release\samples\BlackJack\BlackJack_Server\BlackJack_Server120\BlackJack_Server120.vcxproj", "{84350CD1-D406-4A4F-9571-261CA46D77C5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WindowsLiveAuth", "WindowsLiveAuth", "{052831C4-6B41-4A52-A740-4228EB79CF3B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsLiveAuth120", "Release\samples\WindowsLiveAuth\WindowsLiveAuth120.vcxproj", "{1C20F771-3131-46E8-805F-AA1FE44165C0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UIClient", "UIClient", "{11041CA3-4C29-41E4-9C76-36AF06268C19}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_UIClient120", "Release\samples\BlackJack\BlackJack_UIClient\BlackJack_UIClient120.vcxproj", "{B8D3F85B-DA71-4ACA-87BA-10FED681DC79}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Facebook", "Facebook", "{3E5DF179-3668-49DA-9B6D-38C0632D8F28}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FacebookDemo120", "Release\samples\FacebookDemo\FacebookDemo120.vcxproj", "{43DE4DF3-ACAA-429E-B260-CC6D4FE82658}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.wod", "Release\src\build\vs12.wod\casablanca120.wod.vcxproj", "{BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk120.xp.static", "Release\src\build\vs12.xp.static\casablanca120.xp.static.vcxproj", "{CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}" -EndProject -Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - Release\src\build\win32.vcxitems*{cf74448d-fe99-4e3c-afa6-a50f3145baf3}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{cf74448d-fe99-4e3c-afa6-a50f3145baf3}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 - Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\win32.vcxitems*{15f3b200-1aed-4b57-af37-b21cd67914b1}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{15f3b200-1aed-4b57-af37-b21cd67914b1}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{01a76234-e6e8-4332-9fe2-1e12c34621be}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{01a76234-e6e8-4332-9fe2-1e12c34621be}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{ba4f15a0-6f9c-4ed6-a132-d6f7d0e08d6a}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{ba4f15a0-6f9c-4ed6-a132-d6f7d0e08d6a}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 - Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|ARM = Release|ARM - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|ARM.ActiveCfg = Debug|ARM - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|Win32.Build.0 = Debug|Win32 - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|x64.ActiveCfg = Debug|x64 - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Debug|x64.Build.0 = Debug|x64 - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|ARM.ActiveCfg = Release|ARM - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|Win32.ActiveCfg = Release|Win32 - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|Win32.Build.0 = Release|Win32 - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|x64.ActiveCfg = Release|x64 - {01A76234-E6E8-4332-9FE2-1E12C34621BE}.Release|x64.Build.0 = Release|x64 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|ARM.ActiveCfg = Debug|ARM - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|ARM.Build.0 = Debug|ARM - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|Win32.ActiveCfg = Debug|Win32 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|Win32.Build.0 = Debug|Win32 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x64.ActiveCfg = Debug|x64 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Debug|x64.Build.0 = Debug|x64 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|ARM.ActiveCfg = Release|ARM - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|ARM.Build.0 = Release|ARM - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|Win32.ActiveCfg = Release|Win32 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|Win32.Build.0 = Release|Win32 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x64.ActiveCfg = Release|x64 - {9AD285A2-301E-47A0-A299-14AD5D4F2758}.Release|x64.Build.0 = Release|x64 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|ARM.ActiveCfg = Debug|ARM - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|Win32.ActiveCfg = Debug|Win32 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|Win32.Build.0 = Debug|Win32 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|x64.ActiveCfg = Debug|x64 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Debug|x64.Build.0 = Debug|x64 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|ARM.ActiveCfg = Release|ARM - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|Win32.ActiveCfg = Release|Win32 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|Win32.Build.0 = Release|Win32 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|x64.ActiveCfg = Release|x64 - {15F3B200-1AED-4B57-AF37-B21CD67914B1}.Release|x64.Build.0 = Release|x64 - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|ARM.ActiveCfg = Debug|ARM - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|ARM.Build.0 = Debug|ARM - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|Win32.ActiveCfg = Debug|Win32 - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|Win32.Build.0 = Debug|Win32 - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Debug|x64.ActiveCfg = Debug|x64 - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|ARM.ActiveCfg = Release|ARM - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|ARM.Build.0 = Release|ARM - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|Win32.ActiveCfg = Release|Win32 - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|Win32.Build.0 = Release|Win32 - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D}.Release|x64.ActiveCfg = Release|x64 - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|ARM.ActiveCfg = Debug|ARM - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|ARM.Build.0 = Debug|ARM - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|Win32.ActiveCfg = Debug|Win32 - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|Win32.Build.0 = Debug|Win32 - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Debug|x64.ActiveCfg = Debug|x64 - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|ARM.ActiveCfg = Release|ARM - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|ARM.Build.0 = Release|ARM - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|Win32.ActiveCfg = Release|Win32 - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|Win32.Build.0 = Release|Win32 - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B}.Release|x64.ActiveCfg = Release|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|ARM.ActiveCfg = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.ActiveCfg = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.Build.0 = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.ActiveCfg = Debug|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.Build.0 = Debug|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|ARM.ActiveCfg = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.ActiveCfg = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.Build.0 = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.ActiveCfg = Release|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.Build.0 = Release|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|ARM.ActiveCfg = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.ActiveCfg = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.Build.0 = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.ActiveCfg = Debug|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.Build.0 = Debug|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|ARM.ActiveCfg = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.ActiveCfg = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.Build.0 = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.ActiveCfg = Release|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.Build.0 = Release|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|ARM.ActiveCfg = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.Build.0 = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.ActiveCfg = Debug|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.Build.0 = Debug|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|ARM.ActiveCfg = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.ActiveCfg = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.Build.0 = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.ActiveCfg = Release|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.Build.0 = Release|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|ARM.ActiveCfg = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.ActiveCfg = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.Build.0 = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.ActiveCfg = Debug|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.Build.0 = Debug|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|ARM.ActiveCfg = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.ActiveCfg = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.Build.0 = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.ActiveCfg = Release|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.Build.0 = Release|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|ARM.ActiveCfg = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.ActiveCfg = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.Build.0 = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.ActiveCfg = Debug|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.Build.0 = Debug|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|ARM.ActiveCfg = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.ActiveCfg = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.Build.0 = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.ActiveCfg = Release|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.Build.0 = Release|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|ARM.ActiveCfg = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.ActiveCfg = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.Build.0 = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.ActiveCfg = Debug|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.Build.0 = Debug|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|ARM.ActiveCfg = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.ActiveCfg = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.Build.0 = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.ActiveCfg = Release|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.Build.0 = Release|x64 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|ARM.ActiveCfg = Debug|ARM - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|ARM.Build.0 = Debug|ARM - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|ARM.Deploy.0 = Debug|ARM - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|Win32.ActiveCfg = Debug|Win32 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|Win32.Build.0 = Debug|Win32 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|Win32.Deploy.0 = Debug|Win32 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|x64.ActiveCfg = Debug|x64 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|x64.Build.0 = Debug|x64 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Debug|x64.Deploy.0 = Debug|x64 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|ARM.ActiveCfg = Release|ARM - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|ARM.Build.0 = Release|ARM - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|ARM.Deploy.0 = Release|ARM - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|Win32.ActiveCfg = Release|Win32 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|Win32.Build.0 = Release|Win32 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|Win32.Deploy.0 = Release|Win32 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|x64.ActiveCfg = Release|x64 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|x64.Build.0 = Release|x64 - {1C20F771-3131-46E8-805F-AA1FE44165C0}.Release|x64.Deploy.0 = Release|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.ActiveCfg = Debug|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Build.0 = Debug|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Deploy.0 = Debug|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|Win32.ActiveCfg = Debug|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|Win32.Build.0 = Debug|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|Win32.Deploy.0 = Debug|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.ActiveCfg = Debug|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Build.0 = Debug|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Deploy.0 = Debug|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.ActiveCfg = Release|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Build.0 = Release|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Deploy.0 = Release|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|Win32.ActiveCfg = Release|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|Win32.Build.0 = Release|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|Win32.Deploy.0 = Release|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.ActiveCfg = Release|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Build.0 = Release|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Deploy.0 = Release|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.ActiveCfg = Debug|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Build.0 = Debug|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Deploy.0 = Debug|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|Win32.ActiveCfg = Debug|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|Win32.Build.0 = Debug|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|Win32.Deploy.0 = Debug|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.ActiveCfg = Debug|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Build.0 = Debug|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Deploy.0 = Debug|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.ActiveCfg = Release|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Build.0 = Release|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Deploy.0 = Release|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|Win32.ActiveCfg = Release|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|Win32.Build.0 = Release|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|Win32.Deploy.0 = Release|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.ActiveCfg = Release|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Build.0 = Release|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Deploy.0 = Release|x64 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|ARM.ActiveCfg = Debug|ARM - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|ARM.Build.0 = Debug|ARM - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|Win32.ActiveCfg = Debug|Win32 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|Win32.Build.0 = Debug|Win32 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|x64.ActiveCfg = Debug|x64 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Debug|x64.Build.0 = Debug|x64 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|ARM.ActiveCfg = Release|ARM - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|ARM.Build.0 = Release|ARM - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|Win32.ActiveCfg = Release|Win32 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|Win32.Build.0 = Release|Win32 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|x64.ActiveCfg = Release|x64 - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A}.Release|x64.Build.0 = Release|x64 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|ARM.ActiveCfg = DebugStatic|ARM - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|ARM.Build.0 = DebugStatic|ARM - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|Win32.ActiveCfg = DebugStatic|Win32 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|Win32.Build.0 = DebugStatic|Win32 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|x64.ActiveCfg = DebugStatic|x64 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Debug|x64.Build.0 = DebugStatic|x64 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|ARM.ActiveCfg = ReleaseStatic|ARM - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|ARM.Build.0 = ReleaseStatic|ARM - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|Win32.ActiveCfg = ReleaseStatic|Win32 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|Win32.Build.0 = ReleaseStatic|Win32 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|x64.ActiveCfg = ReleaseStatic|x64 - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3}.Release|x64.Build.0 = ReleaseStatic|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {65951C40-A332-4B54-89C2-7CDAF30D5F66} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {594DCB5F-07E3-4084-A2CE-268611FA629F} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {3D5908F7-7673-4229-BC46-2007A7AF9CAE} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {F40F4804-50F9-4257-8D74-B9CBB19AC4C3} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {0A9BA181-7876-4B3D-A5E0-EE673FA51C05} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {01A76234-E6E8-4332-9FE2-1E12C34621BE} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {9AD285A2-301E-47A0-A299-14AD5D4F2758} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {15F3B200-1AED-4B57-AF37-B21CD67914B1} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {C5D88D15-F9F5-48E2-9EF2-BE0B645B9C0D} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {E5F8A2F0-F713-4673-A42F-2CC4E8FB171B} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {06A71AA7-132E-4A1B-A353-C36B2779331F} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} = {06A71AA7-132E-4A1B-A353-C36B2779331F} - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} = {06A71AA7-132E-4A1B-A353-C36B2779331F} - {CA4D2B5D-D78C-4165-B8E6-0126FF584FCB} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} - {F03BEE03-BEFB-4B17-A774-D9C8246530D4} = {CA4D2B5D-D78C-4165-B8E6-0126FF584FCB} - {BBB2B70F-1D96-4597-96B0-75EA9BE3CA2A} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} = {BBB2B70F-1D96-4597-96B0-75EA9BE3CA2A} - {843B16ED-DE6A-4541-B700-D65B384D43A0} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} - {E442BD21-6B65-4D0E-A96C-623F605A9517} = {843B16ED-DE6A-4541-B700-D65B384D43A0} - {3D3149CF-B1FF-40C0-BD59-1B41FC3522F0} = {843B16ED-DE6A-4541-B700-D65B384D43A0} - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7} = {E442BD21-6B65-4D0E-A96C-623F605A9517} - {84350CD1-D406-4A4F-9571-261CA46D77C5} = {3D3149CF-B1FF-40C0-BD59-1B41FC3522F0} - {052831C4-6B41-4A52-A740-4228EB79CF3B} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} - {1C20F771-3131-46E8-805F-AA1FE44165C0} = {052831C4-6B41-4A52-A740-4228EB79CF3B} - {11041CA3-4C29-41E4-9C76-36AF06268C19} = {843B16ED-DE6A-4541-B700-D65B384D43A0} - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79} = {11041CA3-4C29-41E4-9C76-36AF06268C19} - {3E5DF179-3668-49DA-9B6D-38C0632D8F28} = {B27A3D67-1423-48D8-9F6D-D8FD7E682EC7} - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} = {3E5DF179-3668-49DA-9B6D-38C0632D8F28} - {BA4F15A0-6F9C-4ED6-A132-D6F7D0E08D6A} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - {CF74448D-FE99-4E3C-AFA6-A50F3145BAF3} = {E25A1A01-9AB0-41C5-A03B-F6B83F5E66B9} - EndGlobalSection -EndGlobal diff --git a/setup_ps_env_VS2013.ps1 b/setup_ps_env_VS2013.ps1 deleted file mode 100644 index 085175864f..0000000000 --- a/setup_ps_env_VS2013.ps1 +++ /dev/null @@ -1,22 +0,0 @@ -function Get-Batchfile ($file) { - $cmd = "`"$file`" & set" - cmd /c $cmd | Foreach-Object { - $p, $v = $_.split('=') - Set-Item -path env:$p -value $v - } -} - -function VsVars32() -{ - $vs120comntools = (Get-ChildItem env:VS120COMNTOOLS).Value - $batchFile = [System.IO.Path]::Combine($vs120comntools, "vsvars32.bat") - Get-Batchfile $BatchFile -} - -"Initializing C++ REST SDK Powershell VS2013 Environment" - -# get VS tools -VsVars32 - -$Env:VisualStudioVersion = "12.0" -$Env:DevToolsVersion = "120" diff --git a/setup_ps_env_VS2015.ps1 b/setup_ps_env_VS2015.ps1 deleted file mode 100644 index 297f210e32..0000000000 --- a/setup_ps_env_VS2015.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -"Initializing C++ REST SDK Powershell VS2015 Environment" - -# Add MSBuild to the path. -if (Test-Path "Env:ProgramFiles(x86)") -{ - $msbuildLocation = (Get-ChildItem "Env:ProgramFiles(x86)").Value -} -else -{ - $msbuildLocation = (Get-ChildItem "Env:ProgramFiles").Value -} - -$msbuildLocation = [System.IO.Path]::Combine($msbuildLocation, "MSBuild", "14.0", "Bin") -$Env:Path += ";" + $msbuildLocation - -$Env:VisualStudioVersion = "14.0" -$Env:DevToolsVersion = "140" From 11bc9f0697741e50cc2616a9684eb91062eb4985 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 18 Oct 2017 23:51:06 -0700 Subject: [PATCH 300/609] Remove debug message. --- Release/cmake/cpprest_find_boost.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/Release/cmake/cpprest_find_boost.cmake b/Release/cmake/cpprest_find_boost.cmake index 9e8db2948a..69b07964c5 100644 --- a/Release/cmake/cpprest_find_boost.cmake +++ b/Release/cmake/cpprest_find_boost.cmake @@ -42,7 +42,6 @@ function(cpprest_find_boost) endif() set(_prev "${_lib}") endforeach() - message(STATUS "_libs: ${_libs}") target_link_libraries(cpprestsdk_boost_internal INTERFACE "$") else() From c1a4067d82f07a218a9f71fb68badac05afff9e8 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 18 Oct 2017 23:51:21 -0700 Subject: [PATCH 301/609] Fix _do_while patch on Linux. --- Release/include/cpprest/astreambuf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/astreambuf.h b/Release/include/cpprest/astreambuf.h index d4769f7aa9..cca1abc9cb 100644 --- a/Release/include/cpprest/astreambuf.h +++ b/Release/include/cpprest/astreambuf.h @@ -27,10 +27,10 @@ namespace Concurrency namespace details { template - task _do_while(std::function(void)> func) + pplx::task _do_while(std::function(void)> func) { - task first = func(); - return first.then([=](bool guard) -> task { + pplx::task first = func(); + return first.then([=](bool guard) -> pplx::task { if (guard) return Concurrency::details::_do_while(func); else From e5350bac8904286c5b309139cf39c5b543e12e2e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 18 Oct 2017 23:54:36 -0700 Subject: [PATCH 302/609] Always add CMAKE_DL_LIBS to test_runner. --- Release/tests/common/TestRunner/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Release/tests/common/TestRunner/CMakeLists.txt b/Release/tests/common/TestRunner/CMakeLists.txt index a39f76800a..ec74598dee 100644 --- a/Release/tests/common/TestRunner/CMakeLists.txt +++ b/Release/tests/common/TestRunner/CMakeLists.txt @@ -7,10 +7,9 @@ if (WIN32) endif() add_executable(test_runner test_runner.cpp test_module_loader.cpp) -target_link_libraries(test_runner PRIVATE unittestpp) +target_link_libraries(test_runner PRIVATE unittestpp ${CMAKE_DL_LIBS}) if(BUILD_SHARED_LIBS) - target_link_libraries(test_runner PRIVATE ${CMAKE_DL_LIBS}) elseif(APPLE) target_link_libraries(test_runner PRIVATE -Wl,-force_load httpclient_test @@ -22,7 +21,7 @@ elseif(APPLE) -Wl,-force_load utils_test ) elseif(UNIX) - target_link_libraries(test_runner PRIVATE ${CMAKE_DL_LIBS} + target_link_libraries(test_runner PRIVATE -Wl,--whole-archive httpclient_test json_test From 6c8f948e4d63bcd014f0ea6e6d5cc35713916ef9 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 01:34:23 -0700 Subject: [PATCH 303/609] Fix outside tests to use the more stable badssl.com --- Release/tests/functional/http/client/outside_tests.cpp | 9 +++++---- .../websockets/client/authentication_tests.cpp | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 4ac5a23632..56825fa00d 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -151,6 +151,7 @@ TEST_FIXTURE(uri_address, no_transfer_encoding_content_length) } // Note additional sites for testing can be found at: +// https://badssl.com/ // https://www.ssllabs.com/ssltest/ // http://www.internetsociety.org/deploy360/resources/dane-test-sites/ // https://onlinessl.netlock.hu/# @@ -158,17 +159,17 @@ TEST(server_selfsigned_cert) { handle_timeout([] { - http_client client(U("https://www.pcwebshop.co.uk/")); + http_client client(U("https://self-signed.badssl.com/")); auto requestTask = client.request(methods::GET); VERIFY_THROWS(requestTask.get(), http_exception); }); } -TEST(server_hostname_mismatch, "Ignore", "Site fixed certificate. Improve test (new site or alternate method).") +TEST(server_hostname_mismatch) { handle_timeout([] { - http_client client(U("https://swordsoftruth.com/")); + http_client client(U("https://wrong.host.badssl.com/")); auto requestTask = client.request(methods::GET); VERIFY_THROWS(requestTask.get(), http_exception); }); @@ -180,7 +181,7 @@ TEST(server_cert_expired) { http_client_config config; config.set_timeout(std::chrono::seconds(1)); - http_client client(U("https://tv.eurosport.com/"), config); + http_client client(U("https://expired.badssl.com/"), config); auto requestTask = client.request(methods::GET); VERIFY_THROWS(requestTask.get(), http_exception); }); diff --git a/Release/tests/functional/websockets/client/authentication_tests.cpp b/Release/tests/functional/websockets/client/authentication_tests.cpp index c04a90e1e0..5db5207697 100644 --- a/Release/tests/functional/websockets/client/authentication_tests.cpp +++ b/Release/tests/functional/websockets/client/authentication_tests.cpp @@ -219,17 +219,17 @@ void handshake_error_test_impl(const ::utility::string_t &host) TEST(self_signed_cert) { - handshake_error_test_impl(U("wss://www.pcwebshop.co.uk/")); + handshake_error_test_impl(U("wss://self-signed.badssl.com/")); } TEST(hostname_mismatch) { - handshake_error_test_impl(U("wss://jabbr.net")); + handshake_error_test_impl(U("wss://wrong.host.badssl.com/")); } TEST(cert_expired) { - handshake_error_test_impl(U("wss://tv.eurosport.com/")); + handshake_error_test_impl(U("wss://expired.badssl.com/")); } #endif From 272fa31defbfead731a3067d015dc6768f051e13 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 02:19:21 -0700 Subject: [PATCH 304/609] Fix use-after-free race condition in winhttp. Essentially, the request_context could call ->finish() (and free itself) before the final WinHttp callback completed. The fix, without changing lifetime semantics, is to use a heap-allocated weak_ptr as the context. This weak_ptr will be freed by the callback function when called with WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING. --- .../src/http/client/http_client_winhttp.cpp | 579 ++++++++++-------- Release/src/pch/stdafx.h | 1 + 2 files changed, 311 insertions(+), 269 deletions(-) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 0054b8f839..60a4d060d5 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -187,10 +187,9 @@ class winhttp_request_context : public request_context // Factory function to create requests on the heap. static std::shared_ptr create_request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request) { - // With WinHttp we have to pass the request context to the callback through a raw pointer. - // The lifetime of this object is delete once complete or report_error/report_exception is called. - auto pContext = new winhttp_request_context(client, request); - return std::shared_ptr(pContext, [](winhttp_request_context *){}); + std::shared_ptr ret(new winhttp_request_context(client, request)); + ret->m_self_reference = ret; + return std::move(ret); } ~winhttp_request_context() @@ -220,6 +219,7 @@ class winhttp_request_context : public request_context } HINTERNET m_request_handle; + std::weak_ptr* m_request_context; bool m_proxy_authentication_tried; bool m_server_authentication_tried; @@ -239,8 +239,9 @@ class winhttp_request_context : public request_context return m_readStream.streambuf(); } + // This self reference will keep us alive until finish() is called. + std::shared_ptr m_self_reference; memory_holder m_body_data; - std::unique_ptr decompressor; virtual void cleanup() @@ -258,7 +259,9 @@ class winhttp_request_context : public request_context virtual void finish() { request_context::finish(); - delete this; + assert(m_self_reference != nullptr); + auto dereference_self = std::move(m_self_reference); + // As the stack frame cleans up, this will be deleted if no other references exist. } private: @@ -267,6 +270,7 @@ class winhttp_request_context : public request_context winhttp_request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request) : request_context(client, request), m_request_handle(nullptr), + m_request_context(nullptr), m_bodyType(no_body), m_startingPosition(std::char_traits::eof()), m_body_data(), @@ -572,7 +576,8 @@ class winhttp_client : public _http_client_communicator void send_request(_In_ const std::shared_ptr &request) { http_request &msg = request->m_request; - winhttp_request_context * winhttp_context = static_cast(request.get()); + std::shared_ptr winhttp_context = std::static_pointer_cast(request); + std::weak_ptr weak_winhttp_context = winhttp_context; proxy_info info; bool proxy_info_required = false; @@ -747,11 +752,13 @@ class winhttp_client : public _http_client_communicator if(msg._cancellation_token() != pplx::cancellation_token::none()) { // cancellation callback is unregistered when request is completed. - winhttp_context->m_cancellationRegistration = msg._cancellation_token().register_callback([winhttp_context]() + winhttp_context->m_cancellationRegistration = msg._cancellation_token().register_callback([weak_winhttp_context]() { // Call the WinHttpSendRequest API after WinHttpCloseHandle will give invalid handle error and we throw this exception. // Call the cleanup to make the m_request_handle as nullptr, otherwise, Application Verifier will give AV exception on m_request_handle. - winhttp_context->cleanup(); + auto lock = weak_winhttp_context.lock(); + if (!lock) return; + lock->cleanup(); }); } @@ -779,8 +786,16 @@ class winhttp_client : public _http_client_communicator private: - void _start_request_send(_In_ winhttp_request_context * winhttp_context, size_t content_length) + void _start_request_send(const std::shared_ptr& winhttp_context, size_t content_length) { + // WinHttp takes a context object as a void*. We therefore heap allocate a std::weak_ptr to the request context which will be destroyed during the final callback. + std::unique_ptr> weak_context_holder; + if (winhttp_context->m_request_context == nullptr) + { + weak_context_holder = std::make_unique>(winhttp_context); + winhttp_context->m_request_context = weak_context_holder.get(); + } + if (winhttp_context->m_bodyType == no_body) { if(!WinHttpSendRequest( @@ -790,11 +805,19 @@ class winhttp_client : public _http_client_communicator nullptr, 0, 0, - (DWORD_PTR)winhttp_context)) + (DWORD_PTR)winhttp_context->m_request_context)) { + if (weak_context_holder) + winhttp_context->m_request_context = nullptr; + auto errorCode = GetLastError(); winhttp_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpSendRequest")); } + else + { + // Ownership of the weak_context_holder was accepted by the callback, so release the pointer without freeing. + weak_context_holder.release(); + } return; } @@ -815,11 +838,19 @@ class winhttp_client : public _http_client_communicator nullptr, 0, winhttp_context->m_bodyType == content_length_chunked ? (DWORD)content_length : WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, - (DWORD_PTR)winhttp_context)) + (DWORD_PTR)winhttp_context->m_request_context)) { + if (weak_context_holder) + winhttp_context->m_request_context = nullptr; + auto errorCode = GetLastError(); winhttp_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpSendRequest chunked")); } + else + { + // Ownership of the weak_context_holder was accepted by the callback, so release the pointer without freeing. + weak_context_holder.release(); + } } // Helper function to query/read next part of response data from winhttp. @@ -1011,7 +1042,7 @@ class winhttp_client : public _http_client_communicator // or false if we fail to handle. static bool handle_authentication_failure( HINTERNET hRequestHandle, - _In_ winhttp_request_context * p_request_context, + const std::shared_ptr& p_request_context, _In_ DWORD error = 0) { http_request & request = p_request_context->m_request; @@ -1132,261 +1163,250 @@ class winhttp_client : public _http_client_communicator { CASABLANCA_UNREFERENCED_PARAMETER(statusInfoLength); - if ( statusCode == WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING ) + std::weak_ptr* p_weak_request_context = reinterpret_cast *>(context); + + if (p_weak_request_context == nullptr) return; - winhttp_request_context * p_request_context = reinterpret_cast(context); + if (statusCode == WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING) + { + // This callback is responsible for freeing the type-erased context. + // This particular status code indicates that this is the final callback call, suitable for context destruction. + delete p_weak_request_context; + return; + } - if(p_request_context != nullptr) + auto p_request_context = p_weak_request_context->lock(); + if (!p_request_context) + // The request context was already released, probably due to cancellation + return; + + switch (statusCode) { - switch (statusCode) + case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR : { - case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR : + WINHTTP_ASYNC_RESULT *error_result = reinterpret_cast(statusInfo); + const DWORD errorCode = error_result->dwError; + + // Some authentication schemes require multiple transactions. + // When ERROR_WINHTTP_RESEND_REQUEST is encountered, + // we should continue to resend the request until a response is received that does not contain a 401 or 407 status code. + if (errorCode == ERROR_WINHTTP_RESEND_REQUEST) { - WINHTTP_ASYNC_RESULT *error_result = reinterpret_cast(statusInfo); - const DWORD errorCode = error_result->dwError; + bool resending = handle_authentication_failure(hRequestHandle, p_request_context, errorCode); + if(resending) + { + // The request is resending. Wait until we get a new response. + return; + } + } - // Some authentication schemes require multiple transactions. - // When ERROR_WINHTTP_RESEND_REQUEST is encountered, - // we should continue to resend the request until a response is received that does not contain a 401 or 407 status code. - if (errorCode == ERROR_WINHTTP_RESEND_REQUEST) + p_request_context->report_error(errorCode, build_error_msg(error_result)); + break; + } + case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE : + { + if (!p_request_context->m_request.body()) + { + // Report progress finished uploading with no message body. + auto progress = p_request_context->m_request._get_impl()->_progress_handler(); + if ( progress ) { - bool resending = handle_authentication_failure(hRequestHandle, p_request_context, errorCode); - if(resending) + try { (*progress)(message_direction::upload, 0); } catch(...) { - // The request is resending. Wait until we get a new response. + p_request_context->report_exception(std::current_exception()); return; } } + } - p_request_context->report_error(errorCode, build_error_msg(error_result)); - break; + if ( p_request_context->m_bodyType == transfer_encoding_chunked ) + { + _transfer_encoding_chunked_write_data(p_request_context.get()); } - case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE : + else if ( p_request_context->m_bodyType == content_length_chunked ) { - if (!p_request_context->m_request.body()) + _multiple_segment_write_data(p_request_context.get()); + } + else + { + if(!WinHttpReceiveResponse(hRequestHandle, nullptr)) { - // Report progress finished uploading with no message body. - auto progress = p_request_context->m_request._get_impl()->_progress_handler(); - if ( progress ) - { - try { (*progress)(message_direction::upload, 0); } catch(...) - { - p_request_context->report_exception(std::current_exception()); - return; - } - } + auto errorCode = GetLastError(); + p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReceiveResponse")); } + } + break; + } + case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: + { + auto *flagsPtr = reinterpret_cast(statusInfo); + auto flags = *flagsPtr; + + std::string err = "SSL error: "; + if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED failed to check revocation status. "; + if (flags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT) err += "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT SSL certificate is invalid. "; + if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED SSL certificate was revoked. "; + if (flags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) err += "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA SSL invalid CA. "; + if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID SSL common name does not match. "; + if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID SLL certificate is expired. "; + if (flags & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR) err += "WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR internal error. "; + + p_request_context->report_exception(web::http::http_exception(std::move(err))); + break; + } + case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE : + { + DWORD bytesWritten = *((DWORD *)statusInfo); + _ASSERTE(statusInfoLength == sizeof(DWORD)); - if ( p_request_context->m_bodyType == transfer_encoding_chunked ) - { - _transfer_encoding_chunked_write_data(p_request_context); - } - else if ( p_request_context->m_bodyType == content_length_chunked ) - { - _multiple_segment_write_data(p_request_context); - } - else + if ( bytesWritten > 0 ) + { + auto progress = p_request_context->m_request._get_impl()->_progress_handler(); + if ( progress ) { - if(!WinHttpReceiveResponse(hRequestHandle, nullptr)) + p_request_context->m_uploaded += bytesWritten; + try { (*progress)(message_direction::upload, p_request_context->m_uploaded); } catch(...) { - auto errorCode = GetLastError(); - p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReceiveResponse")); + p_request_context->report_exception(std::current_exception()); + return; } } - break; } - case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: - { - auto *flagsPtr = reinterpret_cast(statusInfo); - auto flags = *flagsPtr; - - std::string err = "SSL error: "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED failed to check revocation status. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT) err += "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT SSL certificate is invalid. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED SSL certificate was revoked. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) err += "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA SSL invalid CA. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID SSL common name does not match. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID SLL certificate is expired. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR) err += "WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR internal error. "; - - p_request_context->report_exception(std::runtime_error(err)); - break; - } - case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE : + + if ( p_request_context->is_externally_allocated() ) { - DWORD bytesWritten = *((DWORD *)statusInfo); - _ASSERTE(statusInfoLength == sizeof(DWORD)); + p_request_context->_get_readbuffer().release(p_request_context->m_body_data.get(), bytesWritten); + } - if ( bytesWritten > 0 ) + if ( p_request_context->m_bodyType == transfer_encoding_chunked ) + { + _transfer_encoding_chunked_write_data(p_request_context.get()); + } + else if ( p_request_context->m_bodyType == content_length_chunked ) + { + _multiple_segment_write_data(p_request_context.get()); + } + else + { + if(!WinHttpReceiveResponse(hRequestHandle, nullptr)) { - auto progress = p_request_context->m_request._get_impl()->_progress_handler(); - if ( progress ) - { - p_request_context->m_uploaded += bytesWritten; - try { (*progress)(message_direction::upload, p_request_context->m_uploaded); } catch(...) - { - p_request_context->report_exception(std::current_exception()); - return; - } - } + auto errorCode = GetLastError(); + p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReceiveResponse")); } + } + break; + } + case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE : + { + // First need to query to see what the headers size is. + DWORD headerBufferLength = 0; + query_header_length(hRequestHandle, WINHTTP_QUERY_RAW_HEADERS_CRLF, headerBufferLength); + + // Now allocate buffer for headers and query for them. + std::vector header_raw_buffer; + header_raw_buffer.resize(headerBufferLength); + utf16char * header_buffer = reinterpret_cast(&header_raw_buffer[0]); + if(!WinHttpQueryHeaders( + hRequestHandle, + WINHTTP_QUERY_RAW_HEADERS_CRLF, + WINHTTP_HEADER_NAME_BY_INDEX, + header_buffer, + &headerBufferLength, + WINHTTP_NO_HEADER_INDEX)) + { + auto errorCode = GetLastError(); + p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpQueryHeaders"));; + return; + } - if ( p_request_context->is_externally_allocated() ) - { - p_request_context->_get_readbuffer().release(p_request_context->m_body_data.get(), bytesWritten); - } + http_response & response = p_request_context->m_response; + parse_winhttp_headers(hRequestHandle, header_buffer, response); - if ( p_request_context->m_bodyType == transfer_encoding_chunked ) - { - _transfer_encoding_chunked_write_data(p_request_context); - } - else if ( p_request_context->m_bodyType == content_length_chunked ) - { - _multiple_segment_write_data(p_request_context); - } - else - { - if(!WinHttpReceiveResponse(hRequestHandle, nullptr)) - { - auto errorCode = GetLastError(); - p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReceiveResponse")); - } - } - break; - } - case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE : + if(response.status_code() == status_codes::Unauthorized /*401*/ || + response.status_code() == status_codes::ProxyAuthRequired /*407*/) { - // First need to query to see what the headers size is. - DWORD headerBufferLength = 0; - query_header_length(hRequestHandle, WINHTTP_QUERY_RAW_HEADERS_CRLF, headerBufferLength); - - // Now allocate buffer for headers and query for them. - std::vector header_raw_buffer; - header_raw_buffer.resize(headerBufferLength); - utf16char * header_buffer = reinterpret_cast(&header_raw_buffer[0]); - if(!WinHttpQueryHeaders( - hRequestHandle, - WINHTTP_QUERY_RAW_HEADERS_CRLF, - WINHTTP_HEADER_NAME_BY_INDEX, - header_buffer, - &headerBufferLength, - WINHTTP_NO_HEADER_INDEX)) + bool resending = handle_authentication_failure(hRequestHandle, p_request_context); + if(resending) { - auto errorCode = GetLastError(); - p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpQueryHeaders"));; + // The request was not completed but resent with credentials. Wait until we get a new response return; } + } - http_response & response = p_request_context->m_response; - parse_winhttp_headers(hRequestHandle, header_buffer, response); + // If the response body is compressed we will read the encoding header and create a decompressor object which will later decompress the body + utility::string_t encoding; + if (web::http::details::compression::stream_decompressor::is_supported() && response.headers().match(web::http::header_names::content_encoding, encoding)) + { + auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(encoding); - if(response.status_code() == status_codes::Unauthorized /*401*/ || - response.status_code() == status_codes::ProxyAuthRequired /*407*/) + if (alg != web::http::details::compression::compression_algorithm::invalid) { - bool resending = handle_authentication_failure(hRequestHandle, p_request_context); - if(resending) - { - // The request was not completed but resent with credentials. Wait until we get a new response - return; - } + p_request_context->decompressor = std::make_unique(alg); } - - // If the response body is compressed we will read the encoding header and create a decompressor object which will later decompress the body - utility::string_t encoding; - if (web::http::details::compression::stream_decompressor::is_supported() && response.headers().match(web::http::header_names::content_encoding, encoding)) + else { - auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(encoding); - - if (alg != web::http::details::compression::compression_algorithm::invalid) - { - p_request_context->decompressor = std::make_unique(alg); - } - else - { - utility::string_t error = U("Unsupported compression algorithm in the Content Encoding header: "); - error += encoding; - p_request_context->report_exception(http_exception(error)); - } + utility::string_t error = U("Unsupported compression algorithm in the Content Encoding header: "); + error += encoding; + p_request_context->report_exception(http_exception(error)); } + } - // Signal that the headers are available. - p_request_context->complete_headers(); + // Signal that the headers are available. + p_request_context->complete_headers(); - // If the method was 'HEAD,' the body of the message is by definition empty. No need to - // read it. Any headers that suggest the presence of a body can safely be ignored. - if (p_request_context->m_request.method() == methods::HEAD ) - { - p_request_context->allocate_request_space(nullptr, 0); - p_request_context->complete_request(0); - return; - } + // If the method was 'HEAD,' the body of the message is by definition empty. No need to + // read it. Any headers that suggest the presence of a body can safely be ignored. + if (p_request_context->m_request.method() == methods::HEAD ) + { + p_request_context->allocate_request_space(nullptr, 0); + p_request_context->complete_request(0); + return; + } - // HTTP Specification states: - // If a message is received with both a Transfer-Encoding header field - // and a Content-Length header field, the latter MUST be ignored. - // If none of them is specified, the message length should be determined by the server closing the connection. - // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 + // HTTP Specification states: + // If a message is received with both a Transfer-Encoding header field + // and a Content-Length header field, the latter MUST be ignored. + // If none of them is specified, the message length should be determined by the server closing the connection. + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 - read_next_response_chunk(p_request_context, 0, true); - break; - } - case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE : - { - // Status information contains pointer to DWORD containing number of bytes available. - const DWORD num_bytes = *(PDWORD)statusInfo; + read_next_response_chunk(p_request_context.get(), 0, true); + break; + } + case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE : + { + // Status information contains pointer to DWORD containing number of bytes available. + const DWORD num_bytes = *(PDWORD)statusInfo; - if(num_bytes > 0) + if(num_bytes > 0) + { + if (p_request_context->decompressor) { - if (p_request_context->decompressor) - { - // Decompression is too slow to reliably do on this callback. Therefore we need to store it now in order to decompress it at a later stage in the flow. - // However, we want to eventually use the writebuf to store the decompressed body. Therefore we'll store the compressed body as an internal allocation in the request_context - p_request_context->allocate_reply_space(nullptr, num_bytes); - } - else - { - auto writebuf = p_request_context->_get_writebuffer(); - p_request_context->allocate_reply_space(writebuf.alloc(num_bytes), num_bytes); - } - - // Read in body all at once. - if(!WinHttpReadData( - hRequestHandle, - p_request_context->m_body_data.get(), - num_bytes, - nullptr)) - { - auto errorCode = GetLastError(); - p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReadData")); - } + // Decompression is too slow to reliably do on this callback. Therefore we need to store it now in order to decompress it at a later stage in the flow. + // However, we want to eventually use the writebuf to store the decompressed body. Therefore we'll store the compressed body as an internal allocation in the request_context + p_request_context->allocate_reply_space(nullptr, num_bytes); } else { - // No more data available, complete the request. - auto progress = p_request_context->m_request._get_impl()->_progress_handler(); - if (progress) - { - try { (*progress)(message_direction::download, p_request_context->m_downloaded); } - catch (...) - { - p_request_context->report_exception(std::current_exception()); - return; - } - } + auto writebuf = p_request_context->_get_writebuffer(); + p_request_context->allocate_reply_space(writebuf.alloc(num_bytes), num_bytes); + } - p_request_context->complete_request(p_request_context->m_downloaded); + // Read in body all at once. + if(!WinHttpReadData( + hRequestHandle, + p_request_context->m_body_data.get(), + num_bytes, + nullptr)) + { + auto errorCode = GetLastError(); + p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReadData")); } - break; } - case WINHTTP_CALLBACK_STATUS_READ_COMPLETE : + else { - // Status information length contains the number of bytes read. - DWORD bytesRead = statusInfoLength; - - // Report progress about downloaded bytes. + // No more data available, complete the request. auto progress = p_request_context->m_request._get_impl()->_progress_handler(); - p_request_context->m_downloaded += statusInfoLength; if (progress) { try { (*progress)(message_direction::download, p_request_context->m_downloaded); } @@ -1397,75 +1417,96 @@ class winhttp_client : public _http_client_communicator } } - // If no bytes have been read, then this is the end of the response. - if (bytesRead == 0) + p_request_context->complete_request(p_request_context->m_downloaded); + } + break; + } + case WINHTTP_CALLBACK_STATUS_READ_COMPLETE : + { + // Status information length contains the number of bytes read. + DWORD bytesRead = statusInfoLength; + + // Report progress about downloaded bytes. + auto progress = p_request_context->m_request._get_impl()->_progress_handler(); + p_request_context->m_downloaded += statusInfoLength; + if (progress) + { + try { (*progress)(message_direction::download, p_request_context->m_downloaded); } + catch (...) { - p_request_context->complete_request(p_request_context->m_downloaded); - break; + p_request_context->report_exception(std::current_exception()); + return; } + } - auto writebuf = p_request_context->_get_writebuffer(); + // If no bytes have been read, then this is the end of the response. + if (bytesRead == 0) + { + p_request_context->complete_request(p_request_context->m_downloaded); + break; + } - // If we have compressed data it is stored in the local allocation of the p_request_context. We will store the decompressed buffer in the external allocation of the p_request_context. - if (p_request_context->decompressor) + auto writebuf = p_request_context->_get_writebuffer(); + + // If we have compressed data it is stored in the local allocation of the p_request_context. We will store the decompressed buffer in the external allocation of the p_request_context. + if (p_request_context->decompressor) + { + web::http::details::compression::data_buffer decompressed = p_request_context->decompressor->decompress(p_request_context->m_body_data.get(), bytesRead); + + if (p_request_context->decompressor->has_error()) + { + p_request_context->report_exception(std::runtime_error("Failed to decompress the response body")); + return; + } + + // We've decompressed this chunk of the body, need to now store it in the writebuffer. + auto decompressed_size = decompressed.size(); + + if (decompressed_size > 0) { - web::http::details::compression::data_buffer decompressed = p_request_context->decompressor->decompress(p_request_context->m_body_data.get(), bytesRead); + auto p = writebuf.alloc(decompressed_size); + p_request_context->allocate_reply_space(p, decompressed_size); + std::memcpy(p_request_context->m_body_data.get(), &decompressed[0], decompressed_size); + } + // Note, some servers seem to send a first chunk of body data that decompresses to nothing but initializes the zlib decryption state. This produces no decompressed output. + // Subsequent chunks will then begin emmiting decompressed body data. + + bytesRead = static_cast(decompressed_size); + } - if (p_request_context->decompressor->has_error()) + // If the data was allocated directly from the buffer then commit, otherwise we still + // need to write to the response stream buffer. + if (p_request_context->is_externally_allocated()) + { + writebuf.commit(bytesRead); + read_next_response_chunk(p_request_context.get(), bytesRead); + } + else + { + writebuf.putn_nocopy(p_request_context->m_body_data.get(), bytesRead).then( + [hRequestHandle, p_request_context, bytesRead] (pplx::task op) + { + size_t written = 0; + try { written = op.get(); } + catch (...) { - p_request_context->report_exception(std::runtime_error("Failed to decompress the response body")); + p_request_context->report_exception(std::current_exception()); return; } - // We've decompressed this chunk of the body, need to now store it in the writebuffer. - auto decompressed_size = decompressed.size(); - - if (decompressed_size > 0) + // If we couldn't write everything, it's time to exit. + if (written != bytesRead) { - auto p = writebuf.alloc(decompressed_size); - p_request_context->allocate_reply_space(p, decompressed_size); - std::memcpy(p_request_context->m_body_data.get(), &decompressed[0], decompressed_size); + p_request_context->report_exception(std::runtime_error("response stream unexpectedly failed to write the requested number of bytes")); + return; } - // Note, some servers seem to send a first chunk of body data that decompresses to nothing but initializes the zlib decryption state. This produces no decompressed output. - // Subsequent chunks will then begin emmiting decompressed body data. - bytesRead = static_cast(decompressed_size); - } - - // If the data was allocated directly from the buffer then commit, otherwise we still - // need to write to the response stream buffer. - if (p_request_context->is_externally_allocated()) - { - writebuf.commit(bytesRead); - read_next_response_chunk(p_request_context, bytesRead); - } - else - { - writebuf.putn_nocopy(p_request_context->m_body_data.get(), bytesRead).then( - [hRequestHandle, p_request_context, bytesRead] (pplx::task op) - { - size_t written = 0; - try { written = op.get(); } - catch (...) - { - p_request_context->report_exception(std::current_exception()); - return; - } - - // If we couldn't write everything, it's time to exit. - if (written != bytesRead) - { - p_request_context->report_exception(std::runtime_error("response stream unexpectedly failed to write the requested number of bytes")); - return; - } - - read_next_response_chunk(p_request_context, bytesRead); - }); - } - break; + read_next_response_chunk(p_request_context.get(), bytesRead); + }); } + break; } - } + } } // WinHTTP session and connection diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index 155b50b096..05a004dec4 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -88,6 +88,7 @@ #include #include #include +#include #include #include #include From 6e8d910e5839dea136f46ee7226f233378d5c3d9 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 04:55:21 -0700 Subject: [PATCH 305/609] Fix auth_no_data test on linux. --- Release/tests/functional/http/client/authentication_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/client/authentication_tests.cpp b/Release/tests/functional/http/client/authentication_tests.cpp index 37b6177cc2..c58ca1c90c 100644 --- a/Release/tests/functional/http/client/authentication_tests.cpp +++ b/Release/tests/functional/http/client/authentication_tests.cpp @@ -646,7 +646,7 @@ TEST_FIXTURE(uri_address, failed_authentication_attempt, "Ignore:Linux", "89", " void auth_test_impl(bool fail) { std::string user("user1"), password("user1"); - auto return_code = status_codes::NotFound; // return 404 if successful auth + auto return_code = status_codes::OK; if (fail) { @@ -657,7 +657,7 @@ void auth_test_impl(bool fail) http_client_config client_config; web::credentials cred(U(user), U(password)); client_config.set_credentials(cred); - http_client client(U("http://test.webdav.org/auth-basic/"), client_config); + http_client client(U("http://httpbin.org/basic-auth/user1/user1"), client_config); http_response response = client.request(methods::GET).get(); VERIFY_ARE_EQUAL(return_code, response.status_code()); From 2b53b1b5e8c813d74279a5900c7b84dff5d44b6b Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 04:55:42 -0700 Subject: [PATCH 306/609] Improve error diagnostics for VERIFY_THROWS_HTTP_ERROR_CODE --- .../http/utilities/include/http_asserts.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Release/tests/functional/http/utilities/include/http_asserts.h b/Release/tests/functional/http/utilities/include/http_asserts.h index 02eb702b0a..9291a936ce 100644 --- a/Release/tests/functional/http/utilities/include/http_asserts.h +++ b/Release/tests/functional/http/utilities/include/http_asserts.h @@ -202,7 +202,7 @@ class http_asserts #define HTTP_ERROR_CHECK_IMPL(__code) VERIFY_ARE_EQUAL(static_cast(__code), _exc.error_code().default_error_condition().value()); #endif #else -#define HTTP_ERROR_CHECK_IMPL(__code) if(__code != _exc.error_code()) { VERIFY_IS_TRUE(false, "Unexpected error code encountered."); } +#define HTTP_ERROR_CHECK_IMPL(__code) VERIFY_ARE_EQUAL(_exc.error_code(), __code, "Unexpected error code encountered.") #endif @@ -212,17 +212,20 @@ class http_asserts try \ { \ __expression; \ - VERIFY_IS_TRUE(false, "Expected http_exception not thrown"); \ + UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), "Expected exception: \"web::http::http_exception\" not thrown"); \ } \ catch (const web::http::http_exception& _exc) \ { \ VERIFY_IS_TRUE(std::string(_exc.what()).size() > 0); \ HTTP_ERROR_CHECK_IMPL(__code); \ - } \ - catch(...) \ - { \ - VERIFY_IS_TRUE(false, "Exception other than http_exception thrown"); \ - } \ + } catch(const std::exception & _exc) { \ + std::string _msg("(" #__expression ") threw exception: "); \ + _msg.append(_exc.what()); \ + UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), _msg.c_str()); \ + } catch (...) { \ + std::string _msg("(" #__expression ") threw exception: <...>"); \ + UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), _msg.c_str()); \ + } \ UNITTEST_MULTILINE_MACRO_END }}}} From 8b186cb76f223d4108cc3648419bae2a40c927b7 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 04:59:31 -0700 Subject: [PATCH 307/609] Loosen tests because error codes can't be consistently reproduced on Linux. --- .../tests/functional/http/client/connections_and_errors.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/client/connections_and_errors.cpp b/Release/tests/functional/http/client/connections_and_errors.cpp index b535dc5a64..24e452f023 100644 --- a/Release/tests/functional/http/client/connections_and_errors.cpp +++ b/Release/tests/functional/http/client/connections_and_errors.cpp @@ -91,7 +91,7 @@ TEST_FIXTURE(uri_address, server_doesnt_exist) http_client_config config; config.set_timeout(std::chrono::seconds(1)); http_client client(m_uri, config); - VERIFY_THROWS_HTTP_ERROR_CODE(client.request(methods::GET).wait(), std::errc::host_unreachable); + VERIFY_THROWS(client.request(methods::GET).wait(), web::http::http_exception); } TEST_FIXTURE(uri_address, open_failure) @@ -125,7 +125,7 @@ TEST_FIXTURE(uri_address, server_close_without_responding) VERIFY_THROWS_HTTP_ERROR_CODE(response.wait(), std::errc::connection_aborted); // Try sending another request. - VERIFY_THROWS_HTTP_ERROR_CODE(client.request(methods::GET).wait(), std::errc::host_unreachable); + VERIFY_THROWS(client.request(methods::GET).wait(), web::http::http_exception); } TEST_FIXTURE(uri_address, request_timeout) From f08dd84c51a14686f2345a15f79705cefd28604e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 06:31:03 -0700 Subject: [PATCH 308/609] Add missing begin-quotes to http constants --- Release/include/cpprest/details/http_constants.dat | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Release/include/cpprest/details/http_constants.dat b/Release/include/cpprest/details/http_constants.dat index f3d051f236..c3b1a53cb6 100644 --- a/Release/include/cpprest/details/http_constants.dat +++ b/Release/include/cpprest/details/http_constants.dat @@ -51,11 +51,11 @@ DAT(UnsupportedMediaType, 415, _XPLATSTR("Unsupported Media Type")) DAT(RangeNotSatisfiable, 416, _XPLATSTR("Requested range not satisfiable")) DAT(ExpectationFailed, 417, _XPLATSTR("Expectation Failed")) DAT(MisdirectedRequest, 421, _XPLATSTR("Misdirected Request")) -DAT(UnprocessableEntity, 422, _XPLATSTR(Unprocessable Entity")) -DAT(Locked, 423, _XPLATSTR(Locked")) -DAT(FailedDependency, 424, _XPLATSTR(Failed Dependency")) -DAT(UpgradeRequired, 426, _XPLATSTR(Upgrade Required")) -DAT(PreconditionRequired, 428, _XPLATSTR(Precondition Required")) +DAT(UnprocessableEntity, 422, _XPLATSTR("Unprocessable Entity")) +DAT(Locked, 423, _XPLATSTR("Locked")) +DAT(FailedDependency, 424, _XPLATSTR("Failed Dependency")) +DAT(UpgradeRequired, 426, _XPLATSTR("Upgrade Required")) +DAT(PreconditionRequired, 428, _XPLATSTR("Precondition Required")) DAT(TooManyRequests, 429, _XPLATSTR("Too Many Requests")) DAT(RequestHeaderFieldsTooLarge, 431, _XPLATSTR("Request Header Fields Too Large")) DAT(UnavailableForLegalReasons, 451, _XPLATSTR("Unavailable For Legal Reasons")) From d305566190b927fe401b509eee9ec71c1f9790d1 Mon Sep 17 00:00:00 2001 From: Chris Deering Date: Thu, 19 Oct 2017 22:52:16 +0100 Subject: [PATCH 309/609] Fix an issue where requests sent via authenticated proxies could not be successfully redirected from one domain to another --- .../src/http/client/http_client_winhttp.cpp | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 60a4d060d5..5f1c5d2e90 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -1038,6 +1038,25 @@ class winhttp_client : public _http_client_communicator } } + static utility::string_t get_request_url(HINTERNET hRequestHandle) + { + DWORD urlSize{ 0 }; + if(FALSE == WinHttpQueryOption(hRequestHandle, WINHTTP_OPTION_URL, nullptr, &urlSize) || urlSize == 0) + { + return U(""); + } + + auto urlwchar = new WCHAR[urlSize / sizeof(WCHAR)]; + + WinHttpQueryOption(hRequestHandle, WINHTTP_OPTION_URL, (void*)urlwchar, &urlSize); + + utility::string_t url(urlwchar); + + delete[] urlwchar; + + return url; + } + // Returns true if we handle successfully and resending the request // or false if we fail to handle. static bool handle_authentication_failure( @@ -1094,10 +1113,22 @@ class winhttp_client : public _http_client_communicator cred = p_request_context->m_http_client->client_config().credentials(); p_request_context->m_server_authentication_tried = true; } - else if (dwAuthTarget == WINHTTP_AUTH_TARGET_PROXY && !p_request_context->m_proxy_authentication_tried) + else if (dwAuthTarget == WINHTTP_AUTH_TARGET_PROXY) { - cred = p_request_context->m_http_client->client_config().proxy().credentials(); - p_request_context->m_proxy_authentication_tried = true; + bool is_redirect = false; + try + { + web::uri current_uri(get_request_url(hRequestHandle)); + is_redirect = p_request_context->m_request.absolute_uri().to_string() != current_uri.to_string(); + } + catch (const std::exception&) {} + + // If we have been redirected, then WinHttp needs the proxy credentials again to make the next request leg (which may be on a different server) + if (is_redirect || !p_request_context->m_proxy_authentication_tried) + { + cred = p_request_context->m_http_client->client_config().proxy().credentials(); + p_request_context->m_proxy_authentication_tried = true; + } } // No credentials found so can't resend. From facb5c29ee1cc4ee1433f1e73847816e2c484f20 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 19 Oct 2017 18:25:33 -0700 Subject: [PATCH 310/609] Add android project for vs2017. --- .../vs141.android/cpprest141.android.vcxproj | 138 ++++++++++++++++++ .../src/build/vs141.android/packages.config | 11 ++ cpprestsdk141.sln | 17 ++- 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 Release/src/build/vs141.android/cpprest141.android.vcxproj create mode 100644 Release/src/build/vs141.android/packages.config diff --git a/Release/src/build/vs141.android/cpprest141.android.vcxproj b/Release/src/build/vs141.android/cpprest141.android.vcxproj new file mode 100644 index 0000000000..e70534ecfc --- /dev/null +++ b/Release/src/build/vs141.android/cpprest141.android.vcxproj @@ -0,0 +1,138 @@ + + + + + + Debug + ARM + + + Debug + x86 + + + Release + ARM + + + Release + x86 + + + + + + + {AFB49019-965B-4C10-BAFF-C86C16D58010} + Android + Android + 2.0 + cpprest141.android + + + + + StaticLibrary + true + Clang_3_8 + gnustl_static + + + StaticLibrary + true + Clang_3_8 + gnustl_static + + + StaticLibrary + false + Clang_3_8 + gnustl_static + + + StaticLibrary + false + Clang_3_8 + gnustl_static + + + + + + + true + + + true + + + + EnableAllWarnings + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + Enabled + c++11 + true + true + -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) + + + + + EnableAllWarnings + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) + c++11 + Enabled + true + true + -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) + + + + + EnableAllWarnings + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + c++11 + Enabled + true + true + -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) + + + + + EnableAllWarnings + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + c++11 + Enabled + true + true + -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) + + + + d + + + $(CppRestBaseFileName)141$(DebugFileSuffix)_android_$(CppRestSDKVersionFileSuffix) + + + true + + + true + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + diff --git a/Release/src/build/vs141.android/packages.config b/Release/src/build/vs141.android/packages.config new file mode 100644 index 0000000000..746b7f61a2 --- /dev/null +++ b/Release/src/build/vs141.android/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/cpprestsdk141.sln b/cpprestsdk141.sln index 1d0d59b04c..f4ed2d2d51 100644 --- a/cpprestsdk141.sln +++ b/cpprestsdk141.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27016.1 +VisualStudioVersion = 15.0.27018.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" EndProject @@ -41,6 +41,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Client141", "Rele EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest141", "Release\samples\BingRequest\BingRequest141\BingRequest141.vcxproj", "{2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprest141.android", "Release\src\build\vs141.android\cpprest141.android.vcxproj", "{AFB49019-965B-4C10-BAFF-C86C16D58010}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 @@ -51,6 +53,8 @@ Global Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 + Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 + Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -214,6 +218,16 @@ Global {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.Build.0 = Release|x64 {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.ActiveCfg = Release|Win32 {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.Build.0 = Release|Win32 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.ActiveCfg = Debug|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.Build.0 = Debug|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x64.ActiveCfg = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.ActiveCfg = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.Build.0 = Debug|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.ActiveCfg = Release|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.Build.0 = Release|ARM + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x64.ActiveCfg = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.ActiveCfg = Release|x86 + {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -236,6 +250,7 @@ Global {84350CD1-D406-4A4F-9571-261CA46D77C5} = {EF775754-D70A-4611-A00C-F49F224FD236} {830B6E2F-9224-41D1-B9C7-A51FC78B00C7} = {EF775754-D70A-4611-A00C-F49F224FD236} {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} = {EF775754-D70A-4611-A00C-F49F224FD236} + {AFB49019-965B-4C10-BAFF-C86C16D58010} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5782CB9E-B335-4D07-A195-717BF4093536} From d310b6d860703fca18aa1843b0f44086cd2456b9 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 20 Oct 2017 19:49:42 -0700 Subject: [PATCH 311/609] Update iOS configure script --- Build_iOS/configure.sh | 53 ++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/Build_iOS/configure.sh b/Build_iOS/configure.sh index 8c9c9eafd7..8b0599512c 100755 --- a/Build_iOS/configure.sh +++ b/Build_iOS/configure.sh @@ -1,28 +1,41 @@ #!/bin/bash set -e -git clone https://gist.github.com/c629ae4c7168216a9856.git boostoniphone -pushd boostoniphone -git apply ../fix_boost_version.patch -./boost.sh -popd -mv boostoniphone/ios/framework/boost.framework . +if [ ! -e boost.framework ] + then + git clone -n https://github.com/faithfracture/Apple-Boost-BuildScript Apple-Boost-BuildScript + pushd Apple-Boost-BuildScript + git checkout 86f7570fceaef00846cc75f59c61474758fc65cb + BOOST_LIBS="thread chrono filesystem regex system random" ./boost.sh + popd + mv Apple-Boost-BuildScript/build/boost/1.63.0/ios/framework/boost.framework . + mv boost.framework/Versions/A/Headers boost.headers + mkdir -p boost.framework/Versions/A/Headers + mv boost.headers boost.framework/Versions/A/Headers/boost +fi -git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git -pushd OpenSSL-for-iPhone -./build-libssl.sh -popd -mkdir -p openssl/lib -cp -r OpenSSL-for-iPhone/bin/iPhoneOS8.2-armv7.sdk/include openssl -cp OpenSSL-for-iPhone/include/LICENSE openssl -lipo -create -output openssl/lib/libssl.a OpenSSL-for-iPhone/bin/iPhone*/lib/libssl.a -lipo -create -output openssl/lib/libcrypto.a OpenSSL-for-iPhone/bin/iPhone*/lib/libcrypto.a +if [ ! -e openssl/lib/libcrypto.a ] + then + git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git + pushd OpenSSL-for-iPhone + ./build-libssl.sh + popd + mkdir -p openssl/lib + cp -r OpenSSL-for-iPhone/bin/iPhoneOS9.2-armv7.sdk/include openssl + cp OpenSSL-for-iPhone/include/LICENSE openssl + lipo -create -output openssl/lib/libssl.a OpenSSL-for-iPhone/bin/iPhone*/lib/libssl.a + lipo -create -output openssl/lib/libcrypto.a OpenSSL-for-iPhone/bin/iPhone*/lib/libcrypto.a +fi -git clone https://github.com/cristeab/ios-cmake.git -pushd ios-cmake -git apply ../fix_ios_cmake_compiler.patch -popd -mkdir build.ios +if [ ! -e ios-cmake/toolchain/iOS.cmake ] + then + git clone https://github.com/cristeab/ios-cmake.git + pushd ios-cmake + git apply ../fix_ios_cmake_compiler.patch + popd +fi + +mkdir -p build.ios pushd build.ios cmake .. -DCMAKE_BUILD_TYPE=Release make From 4375362370309a587f4c39b1fdc8fe2fefe3443a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 21 Oct 2017 00:50:08 -0700 Subject: [PATCH 312/609] Update readme to include new CMake find_package() scripts --- README.md | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b0e0d051e9..ae75be9704 100644 --- a/README.md +++ b/README.md @@ -29,26 +29,10 @@ To use from CMake: cmake_minimum_required(VERSION 3.7) project(main) -find_path(CPPREST_INCLUDE cpprest/http_client.h) -find_library(CPPREST_LIB NAMES cpprest_2_9d cpprest_2_9 cpprestd cpprest) -find_package(Boost REQUIRED COMPONENTS random system thread filesystem chrono atomic date_time regex) -find_package(OpenSSL 1.0.0 REQUIRED) +find_package(cpprestsdk REQUIRED) add_executable(main main.cpp) -target_include_directories(main ${CPPREST_INCLUDE}) -target_link_libraries(main - ${CPPREST_LIB} - Boost::boost - Boost::random - Boost::system - Boost::thread - Boost::filesystem - Boost::chrono - Boost::atomic - Boost::date_time - Boost::regex - OpenSSL::SSL -) +target_link_libraries(main PRIVATE cpprestsdk::cpprest) ``` ## What's in the SDK: From 71332b5e18acf6e403da09137f6e8948cb802687 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 21 Oct 2017 00:53:54 -0700 Subject: [PATCH 313/609] Add changelog for v2.10.0 --- changelog.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 changelog.md diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000000..c3db452003 --- /dev/null +++ b/changelog.md @@ -0,0 +1,52 @@ +cpprestsdk (2.10.0) +---------------------- +* Removed VS2013 MSBuild files. Use CMake with the "Visual Studio 12 2013" generator. +* Added VS2017 MSBuild files for convenience. It is highly recommended to use vcpkg or CMake instead to build the product library. +* Added UWP versions of the Windows Store samples for VS2017. +* Updated minimum required cmake version to 3.0. +* Added CMake config-file support to installation. This should be consumed by doing: +```cmake +find_package(cpprestsdk REQUIRED) +target_link_libraries(my_executable PRIVATE cpprestsdk::cpprest) +``` +* Fixed several race conditions and memory leaks in the ASIO `http_client`. +* Fixed process termination bug around certain exceptional cases in all `http_client`s. +* Improved handling of `/Zcwchar_t-` on MSVC. That doesn't make it a good idea. +* Fixed use-after-free in the Windows Desktop `http_client` exposed by VS2017. +* Totally overhaul the CMake buildsystem for much better support of Windows and more shared code between platforms. +* PR#550 adds all remaining official HTTP status codes to `http::status_codes`. +* PR#563 wraps SSL errors on Windows Desktop in `http_exception`s, with more readable descriptions. +* PR#562 and PR#307 fixes building with LibreSSL. +* PR#551 adds convenience wrappers `json::value::has_T_field(T)` for inspecting object values. +* PR#549 fixes a race condition in the ASIO client during header parsing. +* PR#495 fixes a memory leak during proxy autodetection on Windows Desktop. +* PR#496 and PR#500 expand proxy autodetection to also consider Internet Explorer settings on Windows Desktop. +* PR#498 fixes error when handling responses of type NoContent, NotModified, or from 100 to 199. +* PR#398 enables specifying the User Agent used in OAuth2 requests. +* PR#494 improves the BingRequest sample's handling of proxies. +* PR#516 enables certificate revocation checks on Windows Desktop. +* PR#502 improves compatibility with glibc 2.26. +* PR#507 adds `http_request::get_remote_address()` to expose the client's IP address for `http_listener`. +* PR#521 enables use of empty passwords on Windows in `web::credentials`. +* PR#526 and PR#285 improve compatibility with openssl 1.1.0. +* PR#527 fixes a bug in the ASIO `http_client` where the proxy is passed the same credentials as the target host. +* PR#504 makes `uri_builder::to_string()` and `uri_builder::to_uri()` `const`. +* PR#446 adds handling for the host wildchar `+` to the ASIO `http_listener`. +* PR#465 improves compatibility with clang on Linux. +* PR#454 improves compatibility with icc 17.0. +* PR#487 fixes static library builds of `test_runner` on non-Windows platforms. +* PR#415 handles malformed URL requests to the ASIO `http_listener` instead of crashing. +* PR#393 fixes a race condition in the websocketpp `websocket_client`. +* PR#259 fixes several races in the ASIO `http_listener` which result in memory leaks or use after free of the connection objects. +* PR#376 adds `http_client_config::set_nativesessionhandle_options()` which enables customization of the session handle on Windows Desktop. +* PR#365 updates our convenience OpenSSL build scripts for Android to use openssl 1.0.2k. +* PR#336 makes the ASIO `http_client` more consistent with the Windows clients by not appending the port when it is default. This improves compatibility with AWS S3. +* PR#251 dramatically improves UTF8/16 conversions from 6s per 1MB to 3s per 1GB (2000x improvement). +* PR#246 enables TLS 1.1 and 1.2 on Windows 7 and Windows 8. +* PR#308 enables limited IPv6 support to `http_client` and `http_server`, depending on the underlying platform. +* PR#309 fixes a bug in base64 encoding that previously read beyond the input array, causing segfaults/AVs. +* PR#233 adds compression support (deflate and gzip) for Windows Desktop and ASIO `http_client`s based on Zlib. +* PR#218 fixes a memory leak in the UWP `http_client` when processing headers. +* PR#260 fixes inappropriate handling of certain connections errors in the ASIO `http_listener`. + +-- cpprestsdk team SAT, 21 Oct 2017 00:52:00 -0800 From 28919d0e127fc8d5cf57fae2db5d1b92b4eab381 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 21 Oct 2017 01:41:28 -0700 Subject: [PATCH 314/609] Fix issue CMake building for UWP --- Release/CMakeLists.txt | 9 +++++++-- Release/src/CMakeLists.txt | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index a06623bf20..bc1d612ec9 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -69,7 +69,7 @@ elseif(UNIX AND NOT APPLE) # Note: also android set(CPPREST_HTTP_CLIENT_IMPL asio CACHE STRING "Internal use.") set(CPPREST_HTTP_LISTENER_IMPL asio CACHE STRING "Internal use.") elseif(WINDOWS_PHONE OR WINDOWS_STORE) - set(CPPREST_PPLX_IMPL win CACHE STRING "Internal use.") + set(CPPREST_PPLX_IMPL winrt CACHE STRING "Internal use.") set(CPPREST_WEBSOCKETS_IMPL winrt CACHE STRING "Internal use.") set(CPPREST_FILEIO_IMPL winrt CACHE STRING "Internal use.") set(CPPREST_HTTP_CLIENT_IMPL winrt CACHE STRING "Internal use.") @@ -115,7 +115,12 @@ elseif(ANDROID) ) elseif(UNIX) # This includes OSX elseif(WIN32) - add_definitions(-DUNICODE -D_UNICODE -D_WIN32_WINNT=0x0600 -DWIN32 -D_SCL_SECURE_NO_WARNINGS) + add_definitions(-DUNICODE -D_UNICODE -DWIN32 -D_SCL_SECURE_NO_WARNINGS) + if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + add_definitions(-D_WIN32_WINNT=0x0A00) + else() + add_definitions(-D_WIN32_WINNT=0x0600) + endif() if(NOT BUILD_SHARED_LIBS) # This causes cmake to not link the test libraries separately, but instead hold onto their object files. diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 1c460684ab..070ab41c01 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -80,6 +80,11 @@ elseif(CPPREST_PPLX_IMPL STREQUAL "winpplx") pplx/threadpool.cpp pplx/pplxwin.cpp ) +elseif(CPPREST_PPLX_IMPL STREQUAL "winrt") + list(APPEND SOURCES + pplx/pplxwin.cpp + ) + list(FILTER HEADERS_PPLX EXCLUDE REGEX "threadpool\\.h") endif() # Http client component @@ -186,6 +191,7 @@ if(CPPREST_PPLX_IMPL STREQUAL "apple") target_link_libraries(cpprest PRIVATE ${COREFOUNDATION} ${SECURITY}) elseif(CPPREST_PPLX_IMPL STREQUAL "linux") elseif(CPPREST_PPLX_IMPL STREQUAL "win") +elseif(CPPREST_PPLX_IMPL STREQUAL "winrt") elseif(CPPREST_PPLX_IMPL STREQUAL "winpplx") target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_PPLX=1) else() From 5a87137fa62d8358222bb81b5eb49ec1c9b4eda7 Mon Sep 17 00:00:00 2001 From: Adam Duskett Date: Mon, 23 Oct 2017 09:06:12 -0400 Subject: [PATCH 315/609] fix compiling with non-glib Linux c libraries This commit fixes building against uclibc and musl c libraries. - musl requires sys/time.h - musl and uclibc don't define __GLIBC__, and don't include xlocal.h. Instead of adding more define checks, have cmake check for the header and set the define "HAVE_XLOCALE_H", then check for that instead. --- Release/CMakeLists.txt | 2 ++ Release/include/cpprest/asyncrt_utils.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index bc1d612ec9..b6ce47d2e2 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -42,6 +42,7 @@ include(cmake/cpprest_find_boost.cmake) include(cmake/cpprest_find_zlib.cmake) include(cmake/cpprest_find_openssl.cmake) include(cmake/cpprest_find_websocketpp.cmake) +include(CheckIncludeFiles) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) @@ -56,6 +57,7 @@ if(CPPREST_EXCLUDE_WEBSOCKETS) set(CPPREST_WEBSOCKETS_IMPL none CACHE STRING "Internal use.") endif() +CHECK_INCLUDE_FILES(xlocale.h HAVE_XLOCALE_H) if(APPLE) # Note: also iOS set(CPPREST_PPLX_IMPL apple CACHE STRING "Internal use.") set(CPPREST_WEBSOCKETS_IMPL wspp CACHE STRING "Internal use.") diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index fac70a91a9..064d00f9c2 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -19,17 +19,17 @@ #include #include #include - #include "pplx/pplxtasks.h" #include "cpprest/details/basic_types.h" #if !defined(_WIN32) || (_MSC_VER >= 1700) +#include #include #endif #ifndef _WIN32 #include -#if !defined(ANDROID) && !defined(__ANDROID__) && !defined(__GLIBC__) // CodePlex 269 +#if !defined(ANDROID) && !defined(__ANDROID__) && defined(HAVE_XLOCALE_H) // CodePlex 269 /* Systems using glibc: xlocale.h has been removed from glibc 2.26 The above include of locale.h is sufficient Further details: https://sourceware.org/git/?p=glibc.git;a=commit;h=f0be25b6336db7492e47d2e8e72eb8af53b5506d */ From c0e31f075d300014c826c63bdfaed491a43944af Mon Sep 17 00:00:00 2001 From: deeringc Date: Tue, 24 Oct 2017 10:38:14 +0100 Subject: [PATCH 316/609] Add type checks to oauth2 parsing code --- Release/src/http/oauth/oauth2.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Release/src/http/oauth/oauth2.cpp b/Release/src/http/oauth/oauth2.cpp index 09a453835c..e133a65202 100644 --- a/Release/src/http/oauth/oauth2.cpp +++ b/Release/src/http/oauth/oauth2.cpp @@ -149,7 +149,7 @@ oauth2_token oauth2_config::_parse_token_from_json(const json::value& token_json { oauth2_token result; - if (token_json.has_field(oauth2_strings::access_token)) + if (token_json.has_string_field(oauth2_strings::access_token)) { result.set_access_token(token_json.at(oauth2_strings::access_token).as_string()); } @@ -158,7 +158,7 @@ oauth2_token oauth2_config::_parse_token_from_json(const json::value& token_json throw oauth2_exception(U("response json contains no 'access_token': ") + token_json.serialize()); } - if (token_json.has_field(oauth2_strings::token_type)) + if (token_json.has_string_field(oauth2_strings::token_type)) { result.set_token_type(token_json.at(oauth2_strings::token_type).as_string()); } @@ -174,7 +174,7 @@ oauth2_token oauth2_config::_parse_token_from_json(const json::value& token_json throw oauth2_exception(U("only 'token_type=bearer' access tokens are currently supported: ") + token_json.serialize()); } - if (token_json.has_field(oauth2_strings::refresh_token)) + if (token_json.has_string_field(oauth2_strings::refresh_token)) { result.set_refresh_token(token_json.at(oauth2_strings::refresh_token).as_string()); } @@ -205,7 +205,7 @@ oauth2_token oauth2_config::_parse_token_from_json(const json::value& token_json result.set_expires_in(oauth2_token::undefined_expiration); } - if (token_json.has_field(oauth2_strings::scope)) + if (token_json.has_string_field(oauth2_strings::scope)) { // The authorization server may return different scope from the one requested. // This however doesn't necessarily mean the token authorization scope is different. From a7e49f51866b3c743024ec919977356b06eb9bdd Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 31 Oct 2017 05:22:51 -0700 Subject: [PATCH 317/609] Apply fixes from #568 to VS2017 projects. --- .../BingRequest141/BingRequest141.vcxproj | 4 +++- .../BlackJack_Client141.vcxproj | 4 +++- .../BlackJack_Server141.vcxproj | 4 +++- .../BlackJack_UIClient141.vcxproj | 12 +++++++++--- .../CasaLens/CasaLens141/CasaLens141.vcxproj | 4 +++- .../FacebookDemo/FacebookDemo141.vcxproj | 8 ++++---- .../samples/OAuth2Live/OAuth2Live141.vcxproj | 8 ++++---- .../Oauth1Client141/Oauth1Client141.vcxproj | 4 +++- .../Oauth2Client141/Oauth2Client141.vcxproj | 3 ++- .../SearchFile141/SearchFile141.vcxproj | 3 ++- .../WindowsLiveAuth/WindowsLiveAuth141.vcxproj | 2 +- Release/src/android/asm/page.h | 5 +++++ .../vs141.android/cpprest141.android.vcxproj | 18 ++++++++++-------- .../src/build/vs141.uwp/cpprest141.uwp.vcxproj | 6 +++--- Release/src/build/vs141/cpprest141.vcxproj | 9 ++++++++- 15 files changed, 63 insertions(+), 31 deletions(-) create mode 100644 Release/src/android/asm/page.h diff --git a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj index 04ca9dee54..b5af27cbca 100644 --- a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj +++ b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj @@ -1,4 +1,4 @@ - + @@ -26,6 +26,7 @@ SAK Win32Proj $(VCTargetsPath12) + 10.0.16299.0 @@ -123,6 +124,7 @@ + {1014c621-bc2d-4813-b8c1-6d83ad6f9249} diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj index f06fd04ff8..8770125299 100644 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj +++ b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj @@ -1,4 +1,4 @@ - + @@ -27,6 +27,7 @@ SAK SAK $(VCTargetsPath12) + 10.0.16299.0 @@ -141,6 +142,7 @@ + {1014c621-bc2d-4813-b8c1-6d83ad6f9249} diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj index 928d64e91c..ff8468da47 100644 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj +++ b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj @@ -1,4 +1,4 @@ - + @@ -27,6 +27,7 @@ SAK $(VCTargetsPath12) SAK + 10.0.16299.0 @@ -147,6 +148,7 @@ + {1014c621-bc2d-4813-b8c1-6d83ad6f9249} diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj index 2479ddea21..9fd3069aa1 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj +++ b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj @@ -38,8 +38,8 @@ SAK Windows Store 10.0 - 10.0.10240.0 - 10.0.10240.0 + 10.0.16299.0 + 10.0.16299.0 @@ -107,6 +107,12 @@ WIN32;%(PreprocessorDefinitions) $(CasablancaIncludeDir);%(AdditionalIncludeDirectories) 4100;4267;4450;4453;4702;%(DisableSpecificWarnings) + /Zm150 %(AdditionalOptions) + /Zm150 %(AdditionalOptions) + /Zm150 %(AdditionalOptions) + /Zm150 %(AdditionalOptions) + /Zm150 %(AdditionalOptions) + /Zm150 %(AdditionalOptions) @@ -173,7 +179,7 @@ - {198ED804-2655-4D92-8104-C220E3EA9452} + {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} diff --git a/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj b/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj index bc93468518..e43ab1b904 100644 --- a/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj +++ b/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj @@ -1,4 +1,4 @@ - + @@ -26,6 +26,7 @@ SAK Win32Proj $(VCTargetsPath12) + 10.0.16299.0 @@ -140,6 +141,7 @@ + {1014c621-bc2d-4813-b8c1-6d83ad6f9249} diff --git a/Release/samples/FacebookDemo/FacebookDemo141.vcxproj b/Release/samples/FacebookDemo/FacebookDemo141.vcxproj index af5715d233..fb8baf2f63 100644 --- a/Release/samples/FacebookDemo/FacebookDemo141.vcxproj +++ b/Release/samples/FacebookDemo/FacebookDemo141.vcxproj @@ -1,4 +1,4 @@ - + @@ -33,8 +33,8 @@ 14.0 true Windows Store - 10.0.10240.0 - 10.0.10240.0 + 10.0.16299.0 + 10.0.16299.0 10.0 @@ -175,7 +175,7 @@ - {198ed804-2655-4d92-8104-c220e3ea9452} + {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} diff --git a/Release/samples/OAuth2Live/OAuth2Live141.vcxproj b/Release/samples/OAuth2Live/OAuth2Live141.vcxproj index 4607d183a0..07d4d46897 100644 --- a/Release/samples/OAuth2Live/OAuth2Live141.vcxproj +++ b/Release/samples/OAuth2Live/OAuth2Live141.vcxproj @@ -1,4 +1,4 @@ - + @@ -33,8 +33,8 @@ 14.0 true Windows Store - 10.0.10240.0 - 10.0.10240.0 + 10.0.16299.0 + 10.0.16299.0 10.0 @@ -181,7 +181,7 @@ - {198ed804-2655-4d92-8104-c220e3ea9452} + {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} diff --git a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj index 9dff0e2207..6ff9eeb18a 100644 --- a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj +++ b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj @@ -1,4 +1,4 @@ - + @@ -35,6 +35,7 @@ SAK SAK $(VCTargetsPath12) + 10.0.16299.0 @@ -198,6 +199,7 @@ + {1014c621-bc2d-4813-b8c1-6d83ad6f9249} diff --git a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj index a0d3d0fdeb..1ff3cc807d 100644 --- a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj +++ b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj @@ -1,4 +1,4 @@ - + @@ -35,6 +35,7 @@ SAK SAK $(VCTargetsPath12) + 10.0.16299.0 diff --git a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj index 7fa2bd5235..4c1d729dcd 100644 --- a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj +++ b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj @@ -1,4 +1,4 @@ - + @@ -26,6 +26,7 @@ SAK Win32Proj $(VCTargetsPath12) + 10.0.16299.0 diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj b/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj index 3983220d9e..7fec114667 100644 --- a/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj +++ b/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj @@ -182,7 +182,7 @@ - {198ed804-2655-4d92-8104-c220e3ea9452} + {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} diff --git a/Release/src/android/asm/page.h b/Release/src/android/asm/page.h new file mode 100644 index 0000000000..bd2f6e60c5 --- /dev/null +++ b/Release/src/android/asm/page.h @@ -0,0 +1,5 @@ +#pragma once + +// This file is to fix a break introduced by Android 5 in Boost 1.55. + +// As noted in http://code.google.com/p/android/issues/detail?id=39983, asm/page.h was removed. diff --git a/Release/src/build/vs141.android/cpprest141.android.vcxproj b/Release/src/build/vs141.android/cpprest141.android.vcxproj index e70534ecfc..99a265fa01 100644 --- a/Release/src/build/vs141.android/cpprest141.android.vcxproj +++ b/Release/src/build/vs141.android/cpprest141.android.vcxproj @@ -1,5 +1,5 @@ - - + + @@ -26,8 +26,9 @@ {AFB49019-965B-4C10-BAFF-C86C16D58010} Android Android - 2.0 + 3.0 cpprest141.android + 15.0 @@ -36,6 +37,7 @@ true Clang_3_8 gnustl_static + android-24 StaticLibrary @@ -68,7 +70,7 @@ EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) Enabled c++11 true @@ -79,7 +81,7 @@ EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) c++11 Enabled true @@ -90,7 +92,7 @@ EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) c++11 Enabled true @@ -101,7 +103,7 @@ EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) + $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) c++11 Enabled true @@ -135,4 +137,4 @@ - + \ No newline at end of file diff --git a/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj b/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj index 874315ee1f..f0ee5aae9d 100644 --- a/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj +++ b/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj @@ -1,4 +1,4 @@ - + @@ -34,8 +34,8 @@ 14.0 true Windows Store - 10.0.10240.0 - 10.0.10240.0 + 10.0.16299.0 + 10.0.16299.0 10.0 cpprest141.uwp v141 diff --git a/Release/src/build/vs141/cpprest141.vcxproj b/Release/src/build/vs141/cpprest141.vcxproj index 323553b4cc..794a5155ba 100644 --- a/Release/src/build/vs141/cpprest141.vcxproj +++ b/Release/src/build/vs141/cpprest141.vcxproj @@ -1,4 +1,4 @@ - + @@ -13,6 +13,13 @@ false false cpprest141 + 10.0.16299.0 + + + true + true + true + true From 8bd803235f5efa6bcbce480c000f562568f37368 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Fri, 3 Nov 2017 12:05:35 +0000 Subject: [PATCH 318/609] Resolve gcc "warning: comparison between signed and unsigned integer expressions [-Wsign-compare]" --- Release/include/cpprest/filestream.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/filestream.h b/Release/include/cpprest/filestream.h index 2e60732b05..b8b982556a 100644 --- a/Release/include/cpprest/filestream.h +++ b/Release/include/cpprest/filestream.h @@ -360,7 +360,7 @@ namespace details { size_t written = _putn_fsb(m_info, callback, ptr, count, sizeof(_CharType)); - if ( written != 0 && written != -1 ) + if ( written != 0 && written != size_t(-1) ) { delete callback; written = written/sizeof(_CharType); @@ -572,7 +572,7 @@ namespace details { size_t read = _getn_fsb(m_info, callback, ptr, count, sizeof(_CharType)); - if ( read != 0 && read != -1) + if ( read != 0 && read != size_t(-1) ) { delete callback; pplx::extensibility::scoped_recursive_lock_t lck(m_info->m_lock); From 8ccd130ed2b5447db23157632044f7dbd5e680f5 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 5 Nov 2017 00:45:00 -0700 Subject: [PATCH 319/609] Refactor CMake for better UWP support --- Release/CMakeLists.txt | 13 +- Release/cmake/cpprest_find_boost.cmake | 4 +- Release/src/CMakeLists.txt | 282 ++++++++---------- .../tests/common/TestRunner/CMakeLists.txt | 5 +- .../common/TestRunner/test_module_loader.cpp | 147 +++++---- .../common/TestRunner/test_module_loader.h | 49 +-- .../tests/common/TestRunner/test_runner.cpp | 20 +- .../UnitTestpp/src/TestReporterStdout.cpp | 9 +- .../functional/http/client/CMakeLists.txt | 16 +- .../functional/http/listener/CMakeLists.txt | 13 +- .../functional/http/utilities/CMakeLists.txt | 17 +- Release/tests/functional/json/CMakeLists.txt | 8 +- .../tests/functional/streams/CMakeLists.txt | 16 +- .../functional/streams/stdstream_tests.cpp | 4 +- Release/tests/functional/uri/CMakeLists.txt | 2 +- Release/tests/functional/utils/CMakeLists.txt | 6 +- .../functional/websockets/CMakeLists.txt | 25 +- .../websockets/client/CMakeLists.txt | 15 - 18 files changed, 288 insertions(+), 363 deletions(-) delete mode 100644 Release/tests/functional/websockets/client/CMakeLists.txt diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index bc1d612ec9..218adcbb34 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -125,11 +125,9 @@ elseif(WIN32) if(NOT BUILD_SHARED_LIBS) # This causes cmake to not link the test libraries separately, but instead hold onto their object files. set(TEST_LIBRARY_TARGET_TYPE OBJECT) - set(Casablanca_DEFINITIONS -D_NO_ASYNCRTIMP -D_NO_PPLXIMP CACHE INTERNAL "Definitions for consume casablanca library") - else() - set(Casablanca_DEFINITIONS "" CACHE INTERNAL "Definitions for consume casablanca library") endif() - add_definitions(${Casablanca_DEFINITIONS} -D_WINSOCK_DEPRECATED_NO_WARNINGS) + + add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS) else() message(FATAL_ERROR "-- Unsupported Build Platform.") endif() @@ -198,16 +196,15 @@ function(add_casablanca_test NAME SOURCES_VAR) add_library(${NAME} ${TEST_LIBRARY_TARGET_TYPE} ${${SOURCES_VAR}}) message("-- Added test library ${NAME}") if(TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") - foreach(_dep httptest_utilities common_utilities unittestpp cpprest) + foreach(_dep cpprest common_utilities unittestpp) target_include_directories(${NAME} PRIVATE $) target_compile_definitions(${NAME} PRIVATE $) endforeach() else() - target_link_libraries(${NAME} - httptest_utilities + target_link_libraries(${NAME} PRIVATE + cpprest common_utilities unittestpp - cpprest ${ANDROID_STL_FLAGS} ) if (BUILD_SHARED_LIBS) diff --git a/Release/cmake/cpprest_find_boost.cmake b/Release/cmake/cpprest_find_boost.cmake index 69b07964c5..298b080aae 100644 --- a/Release/cmake/cpprest_find_boost.cmake +++ b/Release/cmake/cpprest_find_boost.cmake @@ -35,9 +35,9 @@ function(cpprest_find_boost) if(_prev STREQUAL "optimized") list(APPEND _libs "$<$>:${_lib}>") elseif(_prev STREQUAL "debug") - list(APPEND _libs "$<$:${_lib}>") + list(APPEND _libs "$<$:${_lib}>") else() - list(APPEND _libs "${_lib}") + list(APPEND _libs "${_lib}") endif() endif() set(_prev "${_lib}") diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 070ab41c01..e01e075707 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -1,5 +1,9 @@ cmake_policy(SET CMP0022 NEW) +set(CPPREST_VERSION_MAJOR 2) +set(CPPREST_VERSION_MINOR 10) +set(CPPREST_VERSION_REVISION 0) + file(GLOB HEADERS_CPPREST "../include/cpprest/*.h" "../include/cpprest/*.hpp" "../include/cpprest/*.dat") file(GLOB HEADERS_PPLX "../include/pplx/*.h" "../include/pplx/*.hpp") file(GLOB HEADERS_DETAILS "../include/cpprest/details/*.h" "../include/cpprest/details/*.hpp" "../include/cpprest/details/*.dat" "../include/pplx/*.hpp" "../include/pplx/*.dat") @@ -7,6 +11,7 @@ source_group("Header Files\\cpprest" FILES ${HEADERS_CPPREST}) source_group("Header Files\\pplx" FILES ${HEADERS_PPLX}) source_group("Header Files\\cpprest\\details" FILES ${HEADERS_DETAILS}) +list(FILTER HEADERS_PPLX EXCLUDE REGEX "threadpool\\.h") set(SOURCES ${HEADERS_CPPREST} ${HEADERS_PPLX} @@ -37,97 +42,7 @@ set(SOURCES utilities/web_utilities.cpp ) -## Sub-component sources -# Websockets component -if(CPPREST_WEBSOCKETS_IMPL STREQUAL "none") -elseif(CPPREST_WEBSOCKETS_IMPL STREQUAL "winrt") - list(APPEND SOURCES - websockets/client/ws_msg.cpp - websockets/client/ws_client.cpp - websockets/client/ws_client_winrt.cpp - websockets/client/ws_client_impl.h - ) -elseif(CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") - list(APPEND SOURCES - websockets/client/ws_msg.cpp - websockets/client/ws_client.cpp - websockets/client/ws_client_wspp.cpp - websockets/client/ws_client_impl.h - ) -endif() - -# Compression component -# No sources to add - -# PPLX component -if(CPPREST_PPLX_IMPL STREQUAL "apple") - list(APPEND SOURCES - pplx/threadpool.cpp - pplx/pplxapple.cpp - ) -elseif(CPPREST_PPLX_IMPL STREQUAL "linux") - list(APPEND SOURCES - pplx/threadpool.cpp - pplx/pplxlinux.cpp - ) -elseif(CPPREST_PPLX_IMPL STREQUAL "win") - list(APPEND SOURCES - pplx/threadpool.cpp - pplx/pplxwin.cpp - ) -elseif(CPPREST_PPLX_IMPL STREQUAL "winpplx") - list(APPEND SOURCES - pplx/threadpool.cpp - pplx/pplxwin.cpp - ) -elseif(CPPREST_PPLX_IMPL STREQUAL "winrt") - list(APPEND SOURCES - pplx/pplxwin.cpp - ) - list(FILTER HEADERS_PPLX EXCLUDE REGEX "threadpool\\.h") -endif() - -# Http client component -if(CPPREST_HTTP_CLIENT_IMPL STREQUAL "asio") - list(APPEND SOURCES http/client/http_client_asio.cpp) -elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttp") - list(APPEND SOURCES http/client/http_client_winhttp.cpp) -elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winrt") - list(APPEND SOURCES http/client/http_client_winrt.cpp) -endif() - -# fileio streams component -if(CPPREST_FILEIO_IMPL STREQUAL "win32") - list(APPEND SOURCES streams/fileio_win32.cpp) -elseif(CPPREST_FILEIO_IMPL STREQUAL "winrt") - list(APPEND SOURCES streams/fileio_winrt.cpp) -elseif(CPPREST_FILEIO_IMPL STREQUAL "posix") - list(APPEND SOURCES streams/fileio_posix.cpp) -endif() - -# http listener component -if(CPPREST_HTTP_LISTENER_IMPL STREQUAL "asio") - list(APPEND SOURCES http/listener/http_server_asio.cpp) -elseif(CPPREST_HTTP_LISTENER_IMPL STREQUAL "httpsys") - list(APPEND SOURCES - http/listener/http_server_httpsys.cpp - http/listener/http_server_httpsys.h) -endif() - -if(MSVC) - set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - - if (NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio .*") - set_property(SOURCE pch/stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${SOURCES} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - add_library(cpprest ${SOURCES} pch/stdafx.cpp) - target_compile_options(cpprest PRIVATE /Yustdafx.h /Zm200) -else() - add_library(cpprest ${SOURCES}) -endif() - +add_library(cpprest ${SOURCES}) target_include_directories(cpprest PUBLIC $ $ @@ -135,128 +50,170 @@ target_include_directories(cpprest pch ) -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") - if(WERROR) - target_compile_options(cpprest PRIVATE -Werror) - endif() - target_compile_options(cpprest PRIVATE -pedantic) -elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - if(WERROR) - target_compile_options(cpprest PRIVATE /WX) - endif() -endif() - -if (BUILD_SHARED_LIBS AND WIN32) - target_compile_definitions(cpprest PRIVATE -D_ASYNCRT_EXPORT -D_PPLX_EXPORT -D_USRDLL) -endif() - -target_compile_options(cpprest PRIVATE ${WARNINGS}) - -set(CPPREST_USES_BOOST OFF) -set(CPPREST_USES_OPENSSL OFF) -set(CPPREST_USES_ZLIB OFF) -set(CPPREST_USES_WEBSOCKETPP OFF) - -if (WIN32 AND NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) - target_link_libraries(cpprest PRIVATE - bcrypt.lib - crypt32.lib - ) -endif() - +## Sub-components # Websockets component if(CPPREST_WEBSOCKETS_IMPL STREQUAL "none") target_compile_definitions(cpprest PUBLIC -DCPPREST_EXCLUDE_WEBSOCKETS=1) elseif(CPPREST_WEBSOCKETS_IMPL STREQUAL "winrt") + target_sources(cpprest PRIVATE + websockets/client/ws_msg.cpp + websockets/client/ws_client.cpp + websockets/client/ws_client_impl.h + websockets/client/ws_client_winrt.cpp + ) elseif(CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") - set(CPPREST_USES_WEBSOCKETPP ON) - set(CPPREST_USES_BOOST ON) - set(CPPREST_USES_OPENSSL ON) - set(CPPREST_USES_ZLIB ON) + target_sources(cpprest PRIVATE + websockets/client/ws_msg.cpp + websockets/client/ws_client.cpp + websockets/client/ws_client_impl.h + websockets/client/ws_client_wspp.cpp + ) + cpprest_find_websocketpp() + target_link_libraries(cpprest PRIVATE cpprestsdk_websocketpp_internal) else() message(FATAL_ERROR "Invalid implementation") endif() # Compression component if(CPPREST_EXCLUDE_COMPRESSION) - target_compile_definitions(cpprest PUBLIC -DCPPREST_EXCLUDE_COMPRESSION=1) + target_compile_definitions(cpprest PRIVATE -DCPPREST_EXCLUDE_COMPRESSION=1) else() - set(CPPREST_USES_ZLIB ON) + cpprest_find_zlib() + target_link_libraries(cpprest PRIVATE cpprestsdk_zlib_internal) endif() # PPLX component if(CPPREST_PPLX_IMPL STREQUAL "apple") find_library(COREFOUNDATION CoreFoundation "/") find_library(SECURITY Security "/") - target_link_libraries(cpprest PRIVATE ${COREFOUNDATION} ${SECURITY}) + target_link_libraries(cpprest PUBLIC ${COREFOUNDATION} ${SECURITY}) + target_sources(cpprest PRIVATE pplx/pplxapple.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) + if(CPPREST_INSTALL_HEADERS) + install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) + endif() elseif(CPPREST_PPLX_IMPL STREQUAL "linux") + target_sources(cpprest PRIVATE pplx/pplxlinux.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) + if(CPPREST_INSTALL_HEADERS) + install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) + endif() elseif(CPPREST_PPLX_IMPL STREQUAL "win") -elseif(CPPREST_PPLX_IMPL STREQUAL "winrt") + target_sources(cpprest PRIVATE pplx/pplxwin.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) + if(CPPREST_INSTALL_HEADERS) + install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) + endif() elseif(CPPREST_PPLX_IMPL STREQUAL "winpplx") target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_PPLX=1) + target_sources(cpprest PRIVATE pplx/pplxwin.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) + if(CPPREST_INSTALL_HEADERS) + install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) + endif() +elseif(CPPREST_PPLX_IMPL STREQUAL "winrt") + target_sources(cpprest PRIVATE pplx/pplxwin.cpp) else() message(FATAL_ERROR "Invalid implementation") endif() # Http client component if(CPPREST_HTTP_CLIENT_IMPL STREQUAL "asio") - set(CPPREST_USES_BOOST ON) - set(CPPREST_USES_OPENSSL ON) + cpprest_find_boost() + cpprest_find_openssl() target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_HTTP_CLIENT_ASIO) + target_sources(cpprest PRIVATE http/client/http_client_asio.cpp) + target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal) elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttp") target_link_libraries(cpprest PRIVATE httpapi.lib Winhttp.lib ) + target_sources(cpprest PRIVATE http/client/http_client_winhttp.cpp) elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winrt") + target_sources(cpprest PRIVATE http/client/http_client_winrt.cpp) else() message(FATAL_ERROR "Invalid implementation") endif() # fileio streams component if(CPPREST_FILEIO_IMPL STREQUAL "win32") + target_sources(cpprest PRIVATE streams/fileio_win32.cpp) elseif(CPPREST_FILEIO_IMPL STREQUAL "winrt") + target_sources(cpprest PRIVATE streams/fileio_winrt.cpp) elseif(CPPREST_FILEIO_IMPL STREQUAL "posix") + target_sources(cpprest PRIVATE streams/fileio_posix.cpp) else() message(FATAL_ERROR "Invalid implementation") endif() # http listener component if(CPPREST_HTTP_LISTENER_IMPL STREQUAL "asio") - set(CPPREST_USES_BOOST ON) - set(CPPREST_USES_OPENSSL ON) + cpprest_find_boost() + cpprest_find_openssl() target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_HTTP_LISTENER_ASIO) + target_sources(cpprest PRIVATE http/listener/http_server_asio.cpp) + target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal) elseif(CPPREST_HTTP_LISTENER_IMPL STREQUAL "httpsys") + target_sources(cpprest PRIVATE + http/listener/http_server_httpsys.cpp + http/listener/http_server_httpsys.h + ) elseif(CPPREST_HTTP_LISTENER_IMPL STREQUAL "none") else() message(FATAL_ERROR "Invalid implementation") endif() -# Add any libraries that were used. -if(CPPREST_USES_WEBSOCKETPP) - cpprest_find_websocketpp() - target_link_libraries(cpprest PRIVATE cpprestsdk_websocketpp_internal) -endif() -if(CPPREST_USES_BOOST) - cpprest_find_boost() - target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal) -endif() -if(CPPREST_USES_OPENSSL) - cpprest_find_openssl() - target_link_libraries(cpprest PUBLIC cpprestsdk_openssl_internal) +if(MSVC) + get_target_property(_srcs cpprest SOURCES) + + set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + list(FILTER _srcs EXCLUDE REGEX "pch/stdafx\\.cpp$") + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE pch/stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + target_sources(cpprest PRIVATE pch/stdafx.cpp) + target_compile_options(cpprest PRIVATE /Yustdafx.h /Zm200) endif() -if(CPPREST_USES_ZLIB) - cpprest_find_zlib() - target_link_libraries(cpprest PRIVATE cpprestsdk_zlib_internal) + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") + if(WERROR) + target_compile_options(cpprest PRIVATE -Werror) + endif() + target_compile_options(cpprest PRIVATE -pedantic ${WARNINGS}) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + if(WERROR) + target_compile_options(cpprest PRIVATE /WX ${WARNINGS}) + endif() +else() + message(FATAL_ERROR "Unknown compiler") endif() -if(ANDROID) + +if(WIN32) + if (BUILD_SHARED_LIBS) + target_compile_definitions(cpprest PRIVATE -D_ASYNCRT_EXPORT -D_PPLX_EXPORT -D_USRDLL) + else() + target_compile_definitions(cpprest INTERFACE -D_NO_ASYNCRTIMP -D_NO_PPLXIMP) + endif() +elseif(ANDROID) target_link_libraries(cpprest PRIVATE ${ANDROID_STL_FLAGS}) endif() -# Portions specific to cpprest binary versioning. -set (CPPREST_VERSION_MAJOR 2) -set (CPPREST_VERSION_MINOR 10) -set (CPPREST_VERSION_REVISION 0) +if (WIN32 AND NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) + target_link_libraries(cpprest PRIVATE + bcrypt.lib + crypt32.lib + ) +elseif(WINDOWS_STORE) + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + target_compile_definitions(cpprest PRIVATE -DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP) + get_target_property(LINK_FLAGS cpprest LINK_FLAGS) + if(NOT LINK_FLAGS) + set(LINK_FLAGS "") + endif() + set(LINK_FLAGS "${LINK_FLAGS} /APPCONTAINER") + set_target_properties(cpprest PROPERTIES LINK_FLAGS "${LINK_FLAGS}") + endif() +endif() if(WIN32) set_target_properties(cpprest PROPERTIES @@ -269,16 +226,29 @@ else() SOVERSION ${CPPREST_VERSION_MAJOR}.${CPPREST_VERSION_MINOR}) endif() +if(CPPREST_INSTALL_HEADERS) + install(FILES ${HEADERS_CPPREST} DESTINATION include/cpprest) + install(FILES ${HEADERS_PPLX} DESTINATION include/pplx) + install(FILES ${HEADERS_DETAILS} DESTINATION include/cpprest/details) +endif() + if(CPPREST_INSTALL) + set(CPPREST_USES_BOOST OFF) + set(CPPREST_USES_ZLIB OFF) + set(CPPREST_USES_OPENSSL OFF) + set(CPPREST_TARGETS cpprest) if(TARGET cpprestsdk_boost_internal) list(APPEND CPPREST_TARGETS cpprestsdk_boost_internal) + set(CPPREST_USES_BOOST ON) endif() if(TARGET cpprestsdk_zlib_internal) list(APPEND CPPREST_TARGETS cpprestsdk_zlib_internal) + set(CPPREST_USES_ZLIB ON) endif() if(TARGET cpprestsdk_openssl_internal) list(APPEND CPPREST_TARGETS cpprestsdk_openssl_internal) + set(CPPREST_USES_OPENSSL ON) endif() if(TARGET cpprestsdk_websocketpp_internal) list(APPEND CPPREST_TARGETS cpprestsdk_websocketpp_internal) @@ -291,12 +261,6 @@ if(CPPREST_INSTALL) ARCHIVE DESTINATION lib ) - if(CPPREST_INSTALL_HEADERS) - install(FILES ${HEADERS_CPPREST} DESTINATION include/cpprest) - install(FILES ${HEADERS_PPLX} DESTINATION include/pplx) - install(FILES ${HEADERS_DETAILS} DESTINATION include/cpprest/details) - endif() - configure_file(../cmake/cpprestsdk-config.in.cmake "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config.cmake" @ONLY) install( @@ -309,4 +273,4 @@ if(CPPREST_INSTALL) NAMESPACE cpprestsdk:: DESTINATION ${CPPREST_EXPORT_DIR} ) -endif() \ No newline at end of file +endif() diff --git a/Release/tests/common/TestRunner/CMakeLists.txt b/Release/tests/common/TestRunner/CMakeLists.txt index ec74598dee..59b720d24c 100644 --- a/Release/tests/common/TestRunner/CMakeLists.txt +++ b/Release/tests/common/TestRunner/CMakeLists.txt @@ -9,7 +9,7 @@ endif() add_executable(test_runner test_runner.cpp test_module_loader.cpp) target_link_libraries(test_runner PRIVATE unittestpp ${CMAKE_DL_LIBS}) -if(BUILD_SHARED_LIBS) +if(BUILD_SHARED_LIBS AND NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") elseif(APPLE) target_link_libraries(test_runner PRIVATE -Wl,-force_load httpclient_test @@ -51,6 +51,9 @@ else() httptest_utilities cpprest ) + if(TARGET websockettest_utilities) + target_link_libraries(test_runner PRIVATE websockettest_utilities) + endif() if(CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") cpprest_find_websocketpp() target_link_libraries(test_runner PRIVATE cpprestsdk_websocketpp_internal) diff --git a/Release/tests/common/TestRunner/test_module_loader.cpp b/Release/tests/common/TestRunner/test_module_loader.cpp index 6f4d9f79e7..65968e7a0d 100644 --- a/Release/tests/common/TestRunner/test_module_loader.cpp +++ b/Release/tests/common/TestRunner/test_module_loader.cpp @@ -6,72 +6,24 @@ */ #ifdef WIN32 #include +#else +#include "dlfcn.h" +#include #endif #include "test_module_loader.h" #include -#ifdef WIN32 - -// Windows module -class windows_module : public test_module +class test_module { public: - windows_module(const std::string &dllName) : test_module(dllName), m_hModule(nullptr) {} + test_module(const std::string& dllName) : m_dllName(dllName), m_handle(nullptr) {} GetTestsFunc get_test_list() { - return (GetTestsFunc)GetProcAddress(m_hModule, "GetTestList"); - } - -protected: - - virtual unsigned long load_impl() - { - // Make sure ends in .dll - if(*(m_dllName.end() - 1) != 'l' - || *(m_dllName.end() - 2) != 'l' - || *(m_dllName.end() - 3) != 'd' - || *(m_dllName.end() - 4) != '.') - { - return (unsigned long)-1; - } - m_hModule = LoadLibraryA(m_dllName.c_str()); - if(m_hModule == nullptr) - { - return GetLastError(); - } - return 0; - } - - virtual unsigned long unload_impl() - { - if(!FreeLibrary(m_hModule)) - { - return GetLastError(); - } - return 0; - } - - HMODULE m_hModule; - -private: - windows_module(const windows_module &); - windows_module & operator=(const windows_module &); - -}; - +#if defined(_WIN32) + return (GetTestsFunc)GetProcAddress(m_handle, "GetTestList"); #else -#include "dlfcn.h" -#include - -class linux_module : public test_module -{ -public: - linux_module(const std::string &soName) : test_module(soName), m_handle(nullptr) {} - - GetTestsFunc get_test_list() - { auto ptr = dlsym(m_handle, "GetTestList"); if (ptr == nullptr) { @@ -81,44 +33,87 @@ class linux_module : public test_module #endif std::endl; } - return (GetTestsFunc)ptr; + return (GetTestsFunc)ptr; +#endif } -protected: - - virtual unsigned long load_impl() + unsigned long load() { + if (m_handle == nullptr) + { +#if defined(_WIN32) + // Make sure ends in .dll + if (*(m_dllName.end() - 1) != 'l' + || *(m_dllName.end() - 2) != 'l' + || *(m_dllName.end() - 3) != 'd' + || *(m_dllName.end() - 4) != '.') + { + return (unsigned long)-1; + } + m_handle = LoadLibraryA(m_dllName.c_str()); + if (m_handle == nullptr) + { + return GetLastError(); + } + return 0; +#else #ifdef __APPLE__ - auto exe_directory = getcwd(nullptr, 0); - auto path = std::string(exe_directory) + "/" + m_dllName; - free(exe_directory); + auto exe_directory = getcwd(nullptr, 0); + auto path = std::string(exe_directory) + "/" + m_dllName; + free(exe_directory); #else - auto path = boost::filesystem::initial_path().string() + "/" + m_dllName; + auto path = boost::filesystem::initial_path().string() + "/" + m_dllName; #endif - m_handle = dlopen(path.c_str(), RTLD_LAZY|RTLD_GLOBAL); - if (m_handle == nullptr) - { - std::cerr << std::string(dlerror()) << std::endl; - return -1; + m_handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL); + if (m_handle == nullptr) + { + std::cerr << std::string(dlerror()) << std::endl; + return -1; + } + return 0; +#endif } return 0; } - virtual unsigned long unload_impl() + unsigned long unload() { - if (dlclose(m_handle) != 0) + if (m_handle != nullptr) { - std::cerr << std::string(dlerror()) << std::endl; - return -1; +#if defined(_WIN32) + if (!FreeLibrary(m_handle)) + { + return GetLastError(); + } + m_handle = nullptr; + return 0; +#else + if (dlclose(m_handle) != 0) + { + std::cerr << std::string(dlerror()) << std::endl; + return -1; + } + m_handle = nullptr; + return 0; +#endif } return 0; } +private: + const std::string m_dllName; + +#if defined(_WIN32) + HMODULE m_handle; +#else void* m_handle; -}; #endif + test_module(const test_module &) = delete; + test_module & operator=(const test_module &) = delete; +}; + test_module_loader::test_module_loader() { } @@ -141,11 +136,7 @@ unsigned long test_module_loader::load(const std::string &dllName) } test_module *pModule; -#ifdef WIN32 - pModule = new windows_module(dllName); -#else - pModule = new linux_module(dllName); -#endif + pModule = new test_module(dllName); // Load dll. const unsigned long error_code = pModule->load(); diff --git a/Release/tests/common/TestRunner/test_module_loader.h b/Release/tests/common/TestRunner/test_module_loader.h index cd2389f829..01d90ba4c7 100644 --- a/Release/tests/common/TestRunner/test_module_loader.h +++ b/Release/tests/common/TestRunner/test_module_loader.h @@ -15,51 +15,7 @@ typedef UnitTest::TestList & (__cdecl *GetTestsFunc)(); // Interface to implement on each platform to be be able to load/unload and call global functions. -class test_module -{ -public: - test_module(const std::string &dllName) : m_dllName(dllName), m_loaded(false) {} - virtual ~test_module() {} - - unsigned long load() - { - if(!m_loaded) - { - m_loaded = true; - unsigned long error_code = load_impl(); - if(error_code != 0) - { - m_loaded = false; - } - return error_code; - } - return 0; - } - - virtual GetTestsFunc get_test_list() = 0; - - unsigned long unload() - { - if(m_loaded) - { - m_loaded = false; - return unload_impl(); - } - return 0; - } - -protected: - - virtual unsigned long load_impl() = 0; - virtual unsigned long unload_impl() = 0; - - bool m_loaded; - const std::string m_dllName; - -private: - test_module(const test_module &); - test_module & operator=(const test_module &); -}; +class test_module; // Handles organizing all test binaries and using the correct module loader. class test_module_loader @@ -75,6 +31,9 @@ class test_module_loader UnitTest::TestList& get_test_list(const std::string &dllName); private: + test_module_loader(const test_module_loader &) = delete; + test_module_loader & operator=(const test_module_loader &) = delete; + std::map m_modules; }; diff --git a/Release/tests/common/TestRunner/test_runner.cpp b/Release/tests/common/TestRunner/test_runner.cpp index 263eb82c91..bb5160d4d9 100644 --- a/Release/tests/common/TestRunner/test_runner.cpp +++ b/Release/tests/common/TestRunner/test_runner.cpp @@ -336,7 +336,8 @@ static void handle_list_option(bool listProperties, const UnitTest::TestList &te static void ChangeConsoleTextColorToRed() { -#ifdef _WIN32 +#if defined(__cplusplus_winrt) +#elif defined(_WIN32) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0004 | 0x0008); #else std::cout << "\033[1;31m"; @@ -345,7 +346,8 @@ static void ChangeConsoleTextColorToRed() static void ChangeConsoleTextColorToGreen() { -#ifdef _WIN32 +#if defined(__cplusplus_winrt) +#elif defined(_WIN32) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0002 | 0x0008); #else std::cout << "\033[1;32m"; @@ -354,7 +356,8 @@ static void ChangeConsoleTextColorToGreen() static void ChangeConsoleTextColorToGrey() { -#ifdef _WIN32 +#if defined(__cplusplus_winrt) +#elif defined(_WIN32) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); #else std::cout << "\033[0m"; @@ -494,9 +497,15 @@ void run_all_tests(UnitTest::TestRunner& testRunner, testlist_t& testlists) } } +#if defined(__cplusplus_winrt) +#include "ROApi.h" +#endif + int main(int argc, char* argv[]) { -#ifdef _WIN32 +#if defined(__cplusplus_winrt) + Windows::Foundation::Initialize(RO_INIT_MULTITHREADED); +#elif defined(_WIN32) // Add standard error as output as well. _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW | _CRTDBG_MODE_DEBUG); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); @@ -623,7 +632,8 @@ int main(int argc, char* argv[]) << "Took " << elapsedTime << "ms" << std::endl; } -#ifdef _WIN32 +#if defined(__cplusplus_winrt) +#elif defined(_WIN32) if(hComBase != nullptr) { typedef void (WINAPI *RoUnInit)(); diff --git a/Release/tests/common/UnitTestpp/src/TestReporterStdout.cpp b/Release/tests/common/UnitTestpp/src/TestReporterStdout.cpp index ee0b154224..a6e9b25b08 100644 --- a/Release/tests/common/UnitTestpp/src/TestReporterStdout.cpp +++ b/Release/tests/common/UnitTestpp/src/TestReporterStdout.cpp @@ -68,7 +68,8 @@ static void PrintfWrapper(const char* format, ...) static void ChangeConsoleTextColorToRed() { -#ifdef _WIN32 +#if defined(__cplusplus_winrt) +#elif defined(_WIN32) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0004 | 0x0008); #else std::cout << "\033[1;31m"; @@ -77,7 +78,8 @@ static void ChangeConsoleTextColorToRed() static void ChangeConsoleTextColorToGreen() { -#ifdef _WIN32 +#if defined(__cplusplus_winrt) +#elif defined(_WIN32) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 0x0002 | 0x0008); #else std::cout << "\033[1;32m"; @@ -86,7 +88,8 @@ static void ChangeConsoleTextColorToGreen() static void ChangeConsoleTextColorToGrey() { -#ifdef _WIN32 +#if defined(__cplusplus_winrt) +#elif defined(_WIN32) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); #else std::cout << "\033[0m"; diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 93bc5475bb..60804e1742 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -1,9 +1,3 @@ -include_directories( - ../utilities/include - ../utilities/testlistener/include - ${Casablanca_INCLUDE_DIRS} -) - set(SOURCES authentication_tests.cpp building_request_tests.cpp @@ -30,8 +24,14 @@ set(SOURCES stdafx.cpp ) +add_casablanca_test(httpclient_test SOURCES) +if(TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") + target_include_directories(httpclient_test PRIVATE ../utilities/include) +else() + target_link_libraries(httpclient_test PRIVATE httptest_utilities) +endif() + if(NOT WIN32) cpprest_find_boost() - link_libraries(cpprestsdk_boost_internal) + target_link_libraries(httpclient_test PRIVATE cpprestsdk_boost_internal) endif() -add_casablanca_test(httpclient_test SOURCES) diff --git a/Release/tests/functional/http/listener/CMakeLists.txt b/Release/tests/functional/http/listener/CMakeLists.txt index 270b89de25..33be6fb354 100644 --- a/Release/tests/functional/http/listener/CMakeLists.txt +++ b/Release/tests/functional/http/listener/CMakeLists.txt @@ -1,6 +1,4 @@ -if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) - include_directories (../utilities/include) - +if(NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) set (SOURCES building_response_tests.cpp connections_and_errors.cpp @@ -17,6 +15,11 @@ if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) to_string_tests.cpp stdafx.cpp ) - + add_casablanca_test(httplistener_test SOURCES) -endif () \ No newline at end of file + if(TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") + target_include_directories(httplistener_test PRIVATE ../utilities/include) + else() + target_link_libraries(httplistener_test PRIVATE httptest_utilities) + endif() +endif() diff --git a/Release/tests/functional/http/utilities/CMakeLists.txt b/Release/tests/functional/http/utilities/CMakeLists.txt index e93e2c4e91..3edf3296e5 100644 --- a/Release/tests/functional/http/utilities/CMakeLists.txt +++ b/Release/tests/functional/http/utilities/CMakeLists.txt @@ -1,9 +1,3 @@ -include_directories(include) - -if(WIN32) - add_definitions(-DHTTPTESTUTILITY_EXPORTS) -endif() - set(SOURCES http_asserts.cpp test_http_client.cpp @@ -12,8 +6,15 @@ set(SOURCES ) add_library(httptest_utilities ${SOURCES}) -target_link_libraries(httptest_utilities +if(WIN32) + target_compile_definitions(httptest_utilities PRIVATE -DHTTPTESTUTILITY_EXPORTS) +endif() +target_include_directories(httptest_utilities PUBLIC include) +target_link_libraries(httptest_utilities PUBLIC + cpprest unittestpp common_utilities - cpprest ) +if(WINDOWS_STORE) + target_compile_options(httptest_utilities PRIVATE /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP) +endif() diff --git a/Release/tests/functional/json/CMakeLists.txt b/Release/tests/functional/json/CMakeLists.txt index 2972052f01..379a6bd4bf 100644 --- a/Release/tests/functional/json/CMakeLists.txt +++ b/Release/tests/functional/json/CMakeLists.txt @@ -1,4 +1,4 @@ -set (SOURCES +set(SOURCES construction_tests.cpp negative_parsing_tests.cpp parsing_tests.cpp @@ -7,12 +7,12 @@ set (SOURCES json_numbers_tests.cpp stdafx.cpp ) -if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) +if(NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) list(APPEND SOURCES fuzz_tests.cpp) endif() +add_casablanca_test(json_test SOURCES) if(UNIX AND NOT APPLE) cpprest_find_boost() - link_libraries(cpprestsdk_boost_internal) + target_link_libraries(json_test PRIVATE cpprestsdk_boost_internal) endif() -add_casablanca_test(json_test SOURCES) diff --git a/Release/tests/functional/streams/CMakeLists.txt b/Release/tests/functional/streams/CMakeLists.txt index 14cb97f2ce..af45beffca 100644 --- a/Release/tests/functional/streams/CMakeLists.txt +++ b/Release/tests/functional/streams/CMakeLists.txt @@ -6,17 +6,17 @@ set(SOURCES stdstream_tests.cpp stdafx.cpp ) -if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) +if(WINDOWS_STORE OR WINDOWS_PHONE) + list(APPEND SOURCES winrt_interop_tests.cpp) +else() list(APPEND SOURCES fuzz_tests.cpp) - if (WIN32) + if(WIN32) list(APPEND SOURCES CppSparseFile.cpp) - endif () -else () - list(APPEND SOURCES winrt_interop_tests.cpp) -endif () + endif() +endif() +add_casablanca_test(streams_test SOURCES) if(NOT WIN32 OR CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") cpprest_find_boost() - link_libraries(cpprestsdk_boost_internal) + target_link_libraries(streams_test PRIVATE cpprestsdk_boost_internal) endif() -add_casablanca_test(streams_test SOURCES) diff --git a/Release/tests/functional/streams/stdstream_tests.cpp b/Release/tests/functional/streams/stdstream_tests.cpp index bd24c2bbe7..a8fde13499 100644 --- a/Release/tests/functional/streams/stdstream_tests.cpp +++ b/Release/tests/functional/streams/stdstream_tests.cpp @@ -14,7 +14,7 @@ #include "cpprest/filestream.h" #include "cpprest/producerconsumerstream.h" -#if !defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS) +#if (!defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS)) && !defined(__cplusplus_winrt) #include #endif @@ -777,7 +777,7 @@ TEST(sync_on_async_close_with_exception) } } -#if !defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS) +#if (!defined(_WIN32) || !defined(CPPREST_EXCLUDE_WEBSOCKETS)) && !defined(__cplusplus_winrt) TEST(ostream_full_throw_exception) { char tgt_buffer[5]; diff --git a/Release/tests/functional/uri/CMakeLists.txt b/Release/tests/functional/uri/CMakeLists.txt index 19c2052817..f869e24d18 100644 --- a/Release/tests/functional/uri/CMakeLists.txt +++ b/Release/tests/functional/uri/CMakeLists.txt @@ -11,4 +11,4 @@ set(SOURCES stdafx.cpp ) -add_casablanca_test(${LIB}uri_test SOURCES) +add_casablanca_test(uri_test SOURCES) diff --git a/Release/tests/functional/utils/CMakeLists.txt b/Release/tests/functional/utils/CMakeLists.txt index 5c6577b24e..ff175283f8 100644 --- a/Release/tests/functional/utils/CMakeLists.txt +++ b/Release/tests/functional/utils/CMakeLists.txt @@ -8,8 +8,8 @@ set(SOURCES stdafx.cpp ) -add_casablanca_test(${LIB}utils_test SOURCES) +add_casablanca_test(utils_test SOURCES) if(CMAKE_COMPILER_IS_GNUCXX) - target_compile_options(${LIB}utils_test PRIVATE "-Wno-deprecated-declarations") -endif() \ No newline at end of file + target_compile_options(utils_test PRIVATE "-Wno-deprecated-declarations") +endif() diff --git a/Release/tests/functional/websockets/CMakeLists.txt b/Release/tests/functional/websockets/CMakeLists.txt index b232922576..889a4e0484 100644 --- a/Release/tests/functional/websockets/CMakeLists.txt +++ b/Release/tests/functional/websockets/CMakeLists.txt @@ -1,10 +1,5 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) - - set(SOURCES - utilities/test_websocket_server.cpp - ) - - add_library(websockettest_utilities ${SOURCES}) + add_library(websockettest_utilities utilities/test_websocket_server.cpp) target_include_directories(websockettest_utilities PUBLIC utilities) target_compile_definitions(websockettest_utilities PRIVATE -DWEBSOCKETTESTUTILITY_EXPORTS) if(NOT WIN32) @@ -15,11 +10,25 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) cpprest_find_websocketpp() target_link_libraries(websockettest_utilities PRIVATE - unittestpp cpprest + unittestpp common_utilities cpprestsdk_websocketpp_internal ) - add_subdirectory(client) + # websocketsclient_test + set(SOURCES + client/authentication_tests.cpp + client/client_construction.cpp + client/close_tests.cpp + client/error_tests.cpp + client/receive_msg_tests.cpp + client/send_msg_tests.cpp + client/stdafx.cpp + ) + + add_casablanca_test(websocketsclient_test SOURCES) + if(NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") + target_link_libraries(websocketsclient_test PRIVATE websockettest_utilities) + endif() endif() diff --git a/Release/tests/functional/websockets/client/CMakeLists.txt b/Release/tests/functional/websockets/client/CMakeLists.txt deleted file mode 100644 index bda6b6e6a8..0000000000 --- a/Release/tests/functional/websockets/client/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -if (NOT CPPREST_EXCLUDE_WEBSOCKETS) - set(SOURCES - authentication_tests.cpp - client_construction.cpp - close_tests.cpp - error_tests.cpp - receive_msg_tests.cpp - send_msg_tests.cpp - stdafx.cpp - ) - - # This works around "OBJECT" tests - link_libraries(websockettest_utilities) - add_casablanca_test(websocketclient_test SOURCES) -endif() \ No newline at end of file From b0634729ae3ece059f5d727e6176f9bf8b9a0e77 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 5 Nov 2017 00:47:17 -0700 Subject: [PATCH 320/609] Refactor out uri_parser, moving it into the underlying uri implementation --- Release/include/cpprest/asyncrt_utils.h | 14 +- Release/include/cpprest/base_uri.h | 115 +--- Release/include/cpprest/details/uri_parser.h | 201 ------- Release/include/cpprest/uri_builder.h | 52 +- Release/src/CMakeLists.txt | 2 +- Release/src/build/common.vcxitems | 188 +++--- Release/src/build/common.vcxitems.filters | 464 +++++++-------- Release/src/pch/stdafx.h | 1 - Release/src/uri/uri.cpp | 534 ++++++++++++++++-- Release/src/uri/uri_builder.cpp | 30 +- Release/src/uri/uri_parser.cpp | 352 ------------ .../tests/functional/uri/encoding_tests.cpp | 8 +- 12 files changed, 888 insertions(+), 1073 deletions(-) delete mode 100644 Release/include/cpprest/details/uri_parser.h delete mode 100644 Release/src/uri/uri_parser.cpp diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index fac70a91a9..85d94438fc 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -269,6 +269,16 @@ namespace conversions return val; } + template + utf8string print_utf8string(const Source& val) + { + return conversions::to_utf8string(print_string(val)); + } + inline const utf8string& print_utf8string(const utf8string& val) + { + return val; + } + template Target scan_string(const utility::string_t &str) { @@ -407,9 +417,9 @@ class windows_category_impl : public std::error_category public: virtual const char *name() const CPPREST_NOEXCEPT { return "windows"; } - _ASYNCRTIMP virtual std::string message(int errorCode) const CPPREST_NOEXCEPT; + virtual std::string message(int errorCode) const CPPREST_NOEXCEPT; - _ASYNCRTIMP virtual std::error_condition default_error_condition(int errorCode) const CPPREST_NOEXCEPT; + virtual std::error_condition default_error_condition(int errorCode) const CPPREST_NOEXCEPT; }; /// diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index a8b0f54ff4..1d2874a41b 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -27,58 +27,13 @@ namespace web { { struct uri_components { - uri_components() : m_path(_XPLATSTR("/")), m_port(-1) - {} - - uri_components(const uri_components &other) : - m_scheme(other.m_scheme), - m_host(other.m_host), - m_user_info(other.m_user_info), - m_path(other.m_path), - m_query(other.m_query), - m_fragment(other.m_fragment), - m_port(other.m_port) - {} - - uri_components & operator=(const uri_components &other) - { - if (this != &other) - { - m_scheme = other.m_scheme; - m_host = other.m_host; - m_user_info = other.m_user_info; - m_path = other.m_path; - m_query = other.m_query; - m_fragment = other.m_fragment; - m_port = other.m_port; - } - return *this; - } - - uri_components(uri_components &&other) CPPREST_NOEXCEPT : - m_scheme(std::move(other.m_scheme)), - m_host(std::move(other.m_host)), - m_user_info(std::move(other.m_user_info)), - m_path(std::move(other.m_path)), - m_query(std::move(other.m_query)), - m_fragment(std::move(other.m_fragment)), - m_port(other.m_port) - {} - - uri_components & operator=(uri_components &&other) CPPREST_NOEXCEPT - { - if (this != &other) - { - m_scheme = std::move(other.m_scheme); - m_host = std::move(other.m_host); - m_user_info = std::move(other.m_user_info); - m_path = std::move(other.m_path); - m_query = std::move(other.m_query); - m_fragment = std::move(other.m_fragment); - m_port = other.m_port; - } - return *this; - } + uri_components() : m_path(_XPLATSTR("/")), m_port(-1) {} + + uri_components(const uri_components &other) = default; + uri_components & operator=(const uri_components &other) = default; + + uri_components(uri_components &&other) = default; + uri_components & operator=(uri_components &&other) = default; _ASYNCRTIMP utility::string_t join(); @@ -174,9 +129,8 @@ namespace web { /// Encodes a string by converting all characters except for RFC 3986 unreserved characters to their /// hexadecimal representation. /// - /// The UTF-8 string data. /// The encoded string. - _ASYNCRTIMP static utility::string_t __cdecl encode_data_string(const utility::string_t &utf8data); + _ASYNCRTIMP static utility::string_t __cdecl encode_data_string(const utility::string_t &data); /// /// Decodes an encoded string. @@ -202,6 +156,9 @@ namespace web { /// /// Validates a string as a URI. /// + /// + /// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query'). + /// /// The URI string to be validated. /// true if the given string represents a valid URI, false otherwise. _ASYNCRTIMP static bool __cdecl validate(const utility::string_t &uri_string); @@ -209,13 +166,7 @@ namespace web { /// /// Creates an empty uri /// - uri() { m_uri = _XPLATSTR("/");}; - - /// - /// Creates a URI from the given URI components. - /// - /// A URI components object to create the URI instance. - _ASYNCRTIMP uri(const details::uri_components &components); + uri() : m_uri(_XPLATSTR("/")) {} /// /// Creates a URI from the given encoded string. This will throw an exception if the string @@ -234,44 +185,22 @@ namespace web { /// /// Copy constructor. /// - uri(const uri &other) : - m_uri(other.m_uri), - m_components(other.m_components) - {} + uri(const uri &other) = default; /// /// Copy assignment operator. /// - uri & operator=(const uri &other) - { - if (this != &other) - { - m_uri = other.m_uri; - m_components = other.m_components; - } - return *this; - } + uri & operator=(const uri &other) = default; /// /// Move constructor. /// - uri(uri &&other) CPPREST_NOEXCEPT : - m_uri(std::move(other.m_uri)), - m_components(std::move(other.m_components)) - {} + uri(uri &&other) = default; /// /// Move assignment operator /// - uri & operator=(uri &&other) CPPREST_NOEXCEPT - { - if (this != &other) - { - m_uri = std::move(other.m_uri); - m_components = std::move(other.m_components); - } - return *this; - } + uri & operator=(uri &&other) = default; /// /// Get the scheme component of the URI as an encoded string. @@ -372,7 +301,7 @@ namespace web { return !(is_empty() || is_host_loopback() || is_host_wildcard()); } - // + /// /// A default port is one where the port is unspecified, and will be determined by the operating system. /// The choice of default port may be dictated by the scheme (http -> 80) or not. /// @@ -434,8 +363,14 @@ namespace web { private: friend class uri_builder; - // Encodes all characters not in given set determined by given function. - _ASYNCRTIMP static utility::string_t __cdecl encode_impl(const utility::string_t &raw, const std::function& should_encode); + /// + /// Creates a URI from the given URI components. + /// + /// A URI components object to create the URI instance. + _ASYNCRTIMP uri(const details::uri_components &components); + + // Used by uri_builder + static utility::string_t __cdecl encode_query_impl(const utf8string& raw); utility::string_t m_uri; details::uri_components m_components; diff --git a/Release/include/cpprest/details/uri_parser.h b/Release/include/cpprest/details/uri_parser.h deleted file mode 100644 index e1b43db85c..0000000000 --- a/Release/include/cpprest/details/uri_parser.h +++ /dev/null @@ -1,201 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* URI parsing implementation -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#pragma once - -#include - -namespace web { namespace details -{ - namespace uri_parser - { - - /// - /// Parses the uri, attempting to determine its validity. - /// - /// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query') - /// - bool validate(const utility::string_t &encoded_string); - - /// - /// Parses the uri, setting each provided string to the value of that component. Components - /// that are not part of the provided text are set to the empty string. Component strings - /// DO NOT contain their beginning or ending delimiters. - /// - /// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query') - /// - bool parse(const utility::string_t &encoded_string, uri_components &components); - - /// - /// Unreserved characters are those that are allowed in a URI but do not have a reserved purpose. They include: - /// - A-Z - /// - a-z - /// - 0-9 - /// - '-' (hyphen) - /// - '.' (period) - /// - '_' (underscore) - /// - '~' (tilde) - /// - inline bool is_unreserved(int c) - { - return ::utility::details::is_alnum((char)c) || c == '-' || c == '.' || c == '_' || c == '~'; - } - - /// - /// General delimiters serve as the delimiters between different uri components. - /// General delimiters include: - /// - All of these :/?#[]@ - /// - inline bool is_gen_delim(int c) - { - return c == ':' || c == '/' || c == '?' || c == '#' || c == '[' || c == ']' || c == '@'; - } - - /// - /// Subdelimiters are those characters that may have a defined meaning within component - /// of a uri for a particular scheme. They do not serve as delimiters in any case between - /// uri segments. sub_delimiters include: - /// - All of these !$&'()*+,;= - /// - inline bool is_sub_delim(int c) - { - switch (c) - { - case '!': - case '$': - case '&': - case '\'': - case '(': - case ')': - case '*': - case '+': - case ',': - case ';': - case '=': - return true; - default: - return false; - } - } - - /// - /// Reserved characters includes the general delimiters and sub delimiters. Some characters - /// are neither reserved nor unreserved, and must be percent-encoded. - /// - inline bool is_reserved(int c) - { - return is_gen_delim(c) || is_sub_delim(c); - } - - /// - /// Legal characters in the scheme portion include: - /// - Any alphanumeric character - /// - '+' (plus) - /// - '-' (hyphen) - /// - '.' (period) - /// - /// Note that the scheme must BEGIN with an alpha character. - /// - inline bool is_scheme_character(int c) - { - return ::utility::details::is_alnum((char)c) || c == '+' || c == '-' || c == '.'; - } - - /// - /// Legal characters in the user information portion include: - /// - Any unreserved character - /// - The percent character ('%'), and thus any percent-endcoded octet - /// - The sub-delimiters - /// - ':' (colon) - /// - inline bool is_user_info_character(int c) - { - return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':'; - } - - /// - /// Legal characters in the host portion include: - /// - Any unreserved character - /// - The percent character ('%'), and thus any percent-endcoded octet - /// - The sub-delimiters - /// - ':' (colon) - /// - '[' (open bracket) - /// - ']' (close bracket) - /// - inline bool is_host_character(int c) - { - return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':' || c == '[' || c == ']'; - } - - /// - /// Legal characters in the authority portion include: - /// - Any unreserved character - /// - The percent character ('%'), and thus any percent-endcoded octet - /// - The sub-delimiters - /// - ':' (colon) - /// - IPv6 requires '[]' allowed for it to be valid URI and passed to underlying platform for IPv6 support - /// - inline bool is_authority_character(int c) - { - return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == '@' || c == ':' || c == '[' || c == ']'; - } - - /// - /// Legal characters in the path portion include: - /// - Any unreserved character - /// - The percent character ('%'), and thus any percent-endcoded octet - /// - The sub-delimiters - /// - ':' (colon) - /// - '@' (ampersand) - /// - inline bool is_path_character(int c) - { - return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == '/' || c == ':' || c == '@'; - } - - /// - /// Legal characters in the query portion include: - /// - Any path character - /// - '?' (question mark) - /// - inline bool is_query_character(int c) - { - return is_path_character(c) || c == '?'; - } - - /// - /// Legal characters in the fragment portion include: - /// - Any path character - /// - '?' (question mark) - /// - inline bool is_fragment_character(int c) - { - // this is intentional, they have the same set of legal characters - return is_query_character(c); - } - - /// - /// Parses the uri, setting the given pointers to locations inside the given buffer. - /// 'encoded' is expected to point to an encoded zero-terminated string containing a uri - /// - bool inner_parse( - const utility::char_t *encoded, - const utility::char_t **scheme_begin, const utility::char_t **scheme_end, - const utility::char_t **uinfo_begin, const utility::char_t **uinfo_end, - const utility::char_t **host_begin, const utility::char_t **host_end, - _Out_ int *port, - const utility::char_t **path_begin, const utility::char_t **path_end, - const utility::char_t **query_begin, const utility::char_t **query_end, - const utility::char_t **fragment_begin, const utility::char_t **fragment_end); - } -}} diff --git a/Release/include/cpprest/uri_builder.h b/Release/include/cpprest/uri_builder.h index 4827534249..6e03e5e2c0 100644 --- a/Release/include/cpprest/uri_builder.h +++ b/Release/include/cpprest/uri_builder.h @@ -18,7 +18,6 @@ #include #include "cpprest/base_uri.h" -#include "cpprest/details/uri_parser.h" namespace web { @@ -32,7 +31,7 @@ namespace web /// /// Creates a builder with an initially empty URI. /// - uri_builder() {} + uri_builder() = default; /// /// Creates a builder with a existing URI object. @@ -134,18 +133,7 @@ namespace web /// Port as a string. /// A reference to this uri_builder to support chaining. /// When string can't be converted to an integer the port is left unchanged. - uri_builder & set_port(const utility::string_t &port) - { - utility::istringstream_t portStream(port); - int port_tmp; - portStream >> port_tmp; - if(portStream.fail() || portStream.bad()) - { - throw std::invalid_argument("invalid port argument, must be non empty string containing integer value"); - } - m_uri.m_port = port_tmp; - return *this; - } + _ASYNCRTIMP uri_builder & set_port(const utility::string_t &port); /// /// Set the path component of the URI. @@ -225,36 +213,11 @@ namespace web template uri_builder &append_query(const utility::string_t &name, const T &value, bool do_encoding = true) { - auto encodedName = name; - auto encodedValue = utility::conversions::details::print_string(value); - if (do_encoding) - { - auto encodingCheck = [](int ch) - { - switch (ch) - { - // Encode '&', ';', and '=' since they are used - // as delimiters in query component. - case '&': - case ';': - case '=': - case '%': - case '+': - return true; - default: - return !::web::details::uri_parser::is_query_character(ch); - } - }; - encodedName = uri::encode_impl(encodedName, encodingCheck); - encodedValue = uri::encode_impl(encodedValue, encodingCheck); - } - - auto encodedQuery = encodedName; - encodedQuery.append(_XPLATSTR("=")); - encodedQuery.append(encodedValue); - // The query key value pair was already encoded by us or the user separately. - return append_query(encodedQuery, false); + append_query_encode_impl(name, utility::conversions::details::print_utf8string(value)); + else + append_query_no_encode_impl(name, utility::conversions::details::print_string(value)); + return *this; } /// @@ -276,6 +239,9 @@ namespace web _ASYNCRTIMP bool is_valid(); private: + _ASYNCRTIMP void append_query_encode_impl(const utility::string_t &name, const utf8string &value); + _ASYNCRTIMP void append_query_no_encode_impl(const utility::string_t &name, const utility::string_t &value); + details::uri_components m_uri; }; } // namespace web diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index e01e075707..cfe3dbe760 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -12,6 +12,7 @@ source_group("Header Files\\pplx" FILES ${HEADERS_PPLX}) source_group("Header Files\\cpprest\\details" FILES ${HEADERS_DETAILS}) list(FILTER HEADERS_PPLX EXCLUDE REGEX "threadpool\\.h") + set(SOURCES ${HEADERS_CPPREST} ${HEADERS_PPLX} @@ -36,7 +37,6 @@ set(SOURCES pplx/pplx.cpp uri/uri.cpp uri/uri_builder.cpp - uri/uri_parser.cpp utilities/asyncrt_utils.cpp utilities/base64.cpp utilities/web_utilities.cpp diff --git a/Release/src/build/common.vcxitems b/Release/src/build/common.vcxitems index 8e9142fa9a..4abeacb737 100644 --- a/Release/src/build/common.vcxitems +++ b/Release/src/build/common.vcxitems @@ -1,95 +1,95 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 248F659F-DAC5-46E8-AC09-60EC9FC95053 - true - b19fa703-0bf0-4e1f-8927-b0eaeb6aa823 - {594dcb5f-07e3-4084-a2ce-268611fa629f} - common - common - - - - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - - - - - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + 248F659F-DAC5-46E8-AC09-60EC9FC95053 + true + b19fa703-0bf0-4e1f-8927-b0eaeb6aa823 + {594dcb5f-07e3-4084-a2ce-268611fa629f} + common + common + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Release/src/build/common.vcxitems.filters b/Release/src/build/common.vcxitems.filters index 437868082e..8839f755df 100644 --- a/Release/src/build/common.vcxitems.filters +++ b/Release/src/build/common.vcxitems.filters @@ -1,233 +1,233 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {3bdf9ddb-6199-4b83-84cd-e8617e78294e} - - - {42f86193-fcdc-443d-8ede-8fd31abe6643} - - - {ed89d519-15d6-47d9-90cb-e6c25bcaa323} - - - {e5ecd256-178a-403a-9249-5d15463ad051} - - - {d32b3879-7333-4ab4-8ef2-dd72aed7b5dc} - - - {1c12997c-5bf5-4b60-853e-a5f9c8303760} - - - {97da7aee-41c8-4948-bb0e-c31cec1bfb16} - - - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\pch - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest - - - Header Files\cpprest\details - - - Header Files\private - - - Header Files\private - - - Header Files\private - - - Header Files\private - - - - - Header Files\cpprest\details - - + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + {3bdf9ddb-6199-4b83-84cd-e8617e78294e} + + + {42f86193-fcdc-443d-8ede-8fd31abe6643} + + + {ed89d519-15d6-47d9-90cb-e6c25bcaa323} + + + {e5ecd256-178a-403a-9249-5d15463ad051} + + + {d32b3879-7333-4ab4-8ef2-dd72aed7b5dc} + + + {1c12997c-5bf5-4b60-853e-a5f9c8303760} + + + {97da7aee-41c8-4948-bb0e-c31cec1bfb16} + + + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\pch + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\pplx + + + Header Files\cpprest\details + + + Header Files\cpprest\details + + + Header Files\cpprest + + + Header Files\cpprest\details + + + Header Files\private + + + Header Files\private + + + Header Files\private + + + Header Files\private + + + + + Header Files\cpprest\details + + \ No newline at end of file diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index 05a004dec4..6f61163dfe 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -111,7 +111,6 @@ // uri #include "cpprest/base_uri.h" -#include "cpprest/details/uri_parser.h" // utilities #include "cpprest/asyncrt_utils.h" diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index 3157b96a6d..f257787e94 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -17,6 +17,436 @@ using namespace utility::conversions; namespace web { namespace details { +namespace +{ + /// + /// Unreserved characters are those that are allowed in a URI but do not have a reserved purpose. They include: + /// - A-Z + /// - a-z + /// - 0-9 + /// - '-' (hyphen) + /// - '.' (period) + /// - '_' (underscore) + /// - '~' (tilde) + /// + inline bool is_unreserved(int c) + { + return ::utility::details::is_alnum((char)c) || c == '-' || c == '.' || c == '_' || c == '~'; + } + + /// + /// General delimiters serve as the delimiters between different uri components. + /// General delimiters include: + /// - All of these :/?#[]@ + /// + inline bool is_gen_delim(int c) + { + return c == ':' || c == '/' || c == '?' || c == '#' || c == '[' || c == ']' || c == '@'; + } + + /// + /// Subdelimiters are those characters that may have a defined meaning within component + /// of a uri for a particular scheme. They do not serve as delimiters in any case between + /// uri segments. sub_delimiters include: + /// - All of these !$&'()*+,;= + /// + inline bool is_sub_delim(int c) + { + switch (c) + { + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case '=': + return true; + default: + return false; + } + } + + /// + /// Reserved characters includes the general delimiters and sub delimiters. Some characters + /// are neither reserved nor unreserved, and must be percent-encoded. + /// + inline bool is_reserved(int c) + { + return is_gen_delim(c) || is_sub_delim(c); + } + + /// + /// Legal characters in the scheme portion include: + /// - Any alphanumeric character + /// - '+' (plus) + /// - '-' (hyphen) + /// - '.' (period) + /// + /// Note that the scheme must BEGIN with an alpha character. + /// + inline bool is_scheme_character(int c) + { + return ::utility::details::is_alnum((char)c) || c == '+' || c == '-' || c == '.'; + } + + /// + /// Legal characters in the user information portion include: + /// - Any unreserved character + /// - The percent character ('%'), and thus any percent-endcoded octet + /// - The sub-delimiters + /// - ':' (colon) + /// + inline bool is_user_info_character(int c) + { + return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':'; + } + + /// + /// Legal characters in the host portion include: + /// - Any unreserved character + /// - The percent character ('%'), and thus any percent-endcoded octet + /// - The sub-delimiters + /// - ':' (colon) + /// - '[' (open bracket) + /// - ']' (close bracket) + /// + inline bool is_host_character(int c) + { + return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':' || c == '[' || c == ']'; + } + + /// + /// Legal characters in the authority portion include: + /// - Any unreserved character + /// - The percent character ('%'), and thus any percent-endcoded octet + /// - The sub-delimiters + /// - ':' (colon) + /// - IPv6 requires '[]' allowed for it to be valid URI and passed to underlying platform for IPv6 support + /// + inline bool is_authority_character(int c) + { + return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == '@' || c == ':' || c == '[' || c == ']'; + } + + /// + /// Legal characters in the path portion include: + /// - Any unreserved character + /// - The percent character ('%'), and thus any percent-endcoded octet + /// - The sub-delimiters + /// - ':' (colon) + /// - '@' (ampersand) + /// + inline bool is_path_character(int c) + { + return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == '/' || c == ':' || c == '@'; + } + + /// + /// Legal characters in the query portion include: + /// - Any path character + /// - '?' (question mark) + /// + inline bool is_query_character(int c) + { + return is_path_character(c) || c == '?'; + } + + /// + /// Legal characters in the fragment portion include: + /// - Any path character + /// - '?' (question mark) + /// + inline bool is_fragment_character(int c) + { + // this is intentional, they have the same set of legal characters + return is_query_character(c); + } + + struct inner_parse_out + { + const utility::char_t *scheme_begin = nullptr; + const utility::char_t *scheme_end = nullptr; + const utility::char_t *uinfo_begin = nullptr; + const utility::char_t *uinfo_end = nullptr; + const utility::char_t *host_begin = nullptr; + const utility::char_t *host_end = nullptr; + int port = 0; + const utility::char_t *path_begin = nullptr; + const utility::char_t *path_end = nullptr; + const utility::char_t *query_begin = nullptr; + const utility::char_t *query_end = nullptr; + const utility::char_t *fragment_begin = nullptr; + const utility::char_t *fragment_end = nullptr; + + /// + /// Parses the uri, setting the given pointers to locations inside the given buffer. + /// 'encoded' is expected to point to an encoded zero-terminated string containing a uri + /// + bool parse_from(const utility::char_t *encoded) + { + const utility::char_t *p = encoded; + + // IMPORTANT -- A uri may either be an absolute uri, or an relative-reference + // Absolute: 'http://host.com' + // Relative-Reference: '//:host.com', '/path1/path2?query', './path1:path2' + // A Relative-Reference can be disambiguated by parsing for a ':' before the first slash + + bool is_relative_reference = true; + const utility::char_t *p2 = p; + for (; *p2 != _XPLATSTR('/') && *p2 != _XPLATSTR('\0'); p2++) + { + if (*p2 == _XPLATSTR(':')) + { + // found a colon, the first portion is a scheme + is_relative_reference = false; + break; + } + } + + if (!is_relative_reference) + { + // the first character of a scheme must be a letter + if (!isalpha(*p)) + { + return false; + } + + // start parsing the scheme, it's always delimited by a colon (must be present) + scheme_begin = p++; + for (; *p != ':'; p++) + { + if (!is_scheme_character(*p)) + { + return false; + } + } + scheme_end = p; + + // skip over the colon + p++; + } + + // if we see two slashes next, then we're going to parse the authority portion + // later on we'll break up the authority into the port and host + const utility::char_t *authority_begin = nullptr; + const utility::char_t *authority_end = nullptr; + if (*p == _XPLATSTR('/') && p[1] == _XPLATSTR('/')) + { + // skip over the slashes + p += 2; + authority_begin = p; + + // the authority is delimited by a slash (resource), question-mark (query) or octothorpe (fragment) + // or by EOS. The authority could be empty ('file:///C:\file_name.txt') + for (; *p != _XPLATSTR('/') && *p != _XPLATSTR('?') && *p != _XPLATSTR('#') && *p != _XPLATSTR('\0'); p++) + { + // We're NOT currently supporting IPvFuture or username/password in authority + // IPv6 as the host (i.e. http://[:::::::]) is allowed as valid URI and passed to subsystem for support. + if (!is_authority_character(*p)) + { + return false; + } + } + authority_end = p; + + // now lets see if we have a port specified -- by working back from the end + if (authority_begin != authority_end) + { + // the port is made up of all digits + const utility::char_t *port_begin = authority_end - 1; + for (; isdigit(*port_begin) && port_begin != authority_begin; port_begin--) + { + } + + if (*port_begin == _XPLATSTR(':')) + { + // has a port + host_begin = authority_begin; + host_end = port_begin; + + //skip the colon + port_begin++; + + port = utility::conversions::details::scan_string(utility::string_t(port_begin, authority_end)); + } + else + { + // no port + host_begin = authority_begin; + host_end = authority_end; + } + + // look for a user_info component + const utility::char_t *u_end = host_begin; + for (; is_user_info_character(*u_end) && u_end != host_end; u_end++) + { + } + + if (*u_end == _XPLATSTR('@')) + { + host_begin = u_end + 1; + uinfo_begin = authority_begin; + uinfo_end = u_end; + } + } + } + + // if we see a path character or a slash, then the + // if we see a slash, or any other legal path character, parse the path next + if (*p == _XPLATSTR('/') || is_path_character(*p)) + { + path_begin = p; + + // the path is delimited by a question-mark (query) or octothorpe (fragment) or by EOS + for (; *p != _XPLATSTR('?') && *p != _XPLATSTR('#') && *p != _XPLATSTR('\0'); p++) + { + if (!is_path_character(*p)) + { + return false; + } + } + path_end = p; + } + + // if we see a ?, then the query is next + if (*p == _XPLATSTR('?')) + { + // skip over the question mark + p++; + query_begin = p; + + // the query is delimited by a '#' (fragment) or EOS + for (; *p != _XPLATSTR('#') && *p != _XPLATSTR('\0'); p++) + { + if (!is_query_character(*p)) + { + return false; + } + } + query_end = p; + } + + // if we see a #, then the fragment is next + if (*p == _XPLATSTR('#')) + { + // skip over the hash mark + p++; + fragment_begin = p; + + // the fragment is delimited by EOS + for (; *p != _XPLATSTR('\0'); p++) + { + if (!is_fragment_character(*p)) + { + return false; + } + } + fragment_end = p; + } + + return true; + } + + void write_to(uri_components& components) + { + if (scheme_begin) + { + components.m_scheme.assign(scheme_begin, scheme_end); + + // convert scheme to lowercase + std::transform(components.m_scheme.begin(), components.m_scheme.end(), components.m_scheme.begin(), [](utility::char_t c) { + return (utility::char_t)tolower(c); + }); + } + else + { + components.m_scheme.clear(); + } + + if (uinfo_begin) + { + components.m_user_info.assign(uinfo_begin, uinfo_end); + } + + if (host_begin) + { + components.m_host.assign(host_begin, host_end); + + // convert host to lowercase + std::transform(components.m_host.begin(), components.m_host.end(), components.m_host.begin(), [](utility::char_t c) { + return (utility::char_t)tolower(c); + }); + } + else + { + components.m_host.clear(); + } + + components.m_port = port; + + if (path_begin) + { + components.m_path.assign(path_begin, path_end); + } + else + { + // default path to begin with a slash for easy comparison + components.m_path = _XPLATSTR("/"); + } + + if (query_begin) + { + components.m_query.assign(query_begin, query_end); + } + else + { + components.m_query.clear(); + } + + if (fragment_begin) + { + components.m_fragment.assign(fragment_begin, fragment_end); + } + else + { + components.m_fragment.clear(); + } + } + }; + + // Encodes all characters not in given set determined by given function. + template + utility::string_t encode_impl(const utf8string &raw, F should_encode) + { + const utility::char_t * const hex = _XPLATSTR("0123456789ABCDEF"); + utility::string_t encoded; + for (auto iter = raw.begin(); iter != raw.end(); ++iter) + { + // for utf8 encoded string, char ASCII can be greater than 127. + int ch = static_cast(*iter); + // ch should be same under both utf8 and utf16. + if (should_encode(ch)) + { + encoded.push_back(_XPLATSTR('%')); + encoded.push_back(hex[(ch >> 4) & 0xF]); + encoded.push_back(hex[ch & 0xF]); + } + else + { + // ASCII don't need to be encoded, which should be same on both utf8 and utf16. + encoded.push_back((utility::char_t)ch); + } + } + return encoded; + } + +} + utility::string_t uri_components::join() { // canonicalize components first @@ -90,114 +520,109 @@ utility::string_t uri_components::join() } } -using namespace details; - uri::uri(const details::uri_components &components) : m_components(components) { m_uri = m_components.join(); - if (!details::uri_parser::validate(m_uri)) + + if (!uri::validate(m_uri.c_str())) { throw uri_exception("provided uri is invalid: " + utility::conversions::to_utf8string(m_uri)); } } -uri::uri(const utility::string_t &uri_string) -{ - if (!details::uri_parser::parse(uri_string, m_components)) - { - throw uri_exception("provided uri is invalid: " + utility::conversions::to_utf8string(uri_string)); - } - m_uri = m_components.join(); -} +uri::uri(const utility::string_t &uri_string) : uri(uri_string.c_str()) {} -uri::uri(const utility::char_t *uri_string): m_uri(uri_string) +uri::uri(const utility::char_t *uri_string) { - if (!details::uri_parser::parse(uri_string, m_components)) + details::inner_parse_out out; + + if (!out.parse_from(uri_string)) { throw uri_exception("provided uri is invalid: " + utility::conversions::to_utf8string(uri_string)); } + + out.write_to(m_components); m_uri = m_components.join(); } -utility::string_t uri::encode_impl(const utility::string_t &raw, const std::function& should_encode) +utility::string_t uri::encode_query_impl(const utf8string & raw) { - const utility::char_t * const hex = _XPLATSTR("0123456789ABCDEF"); - utility::string_t encoded; - std::string utf8raw = to_utf8string(raw); - for (auto iter = utf8raw.begin(); iter != utf8raw.end(); ++iter) - { - // for utf8 encoded string, char ASCII can be greater than 127. - int ch = static_cast(*iter); - // ch should be same under both utf8 and utf16. - if(should_encode(ch)) - { - encoded.push_back(_XPLATSTR('%')); - encoded.push_back(hex[(ch >> 4) & 0xF]); - encoded.push_back(hex[ch & 0xF]); - } - else + return details::encode_impl(raw, [](int ch) -> bool + { + switch (ch) { - // ASCII don't need to be encoded, which should be same on both utf8 and utf16. - encoded.push_back((utility::char_t)ch); + // Encode '&', ';', and '=' since they are used + // as delimiters in query component. + case '&': + case ';': + case '=': + case '%': + case '+': + return true; + default: + return !details::is_query_character(ch); } - } - return encoded; + }); } /// /// Encodes a string by converting all characters except for RFC 3986 unreserved characters to their /// hexadecimal representation. /// -utility::string_t uri::encode_data_string(const utility::string_t &raw) +utility::string_t uri::encode_data_string(const utility::string_t &data) { - return uri::encode_impl(raw, [](int ch) -> bool + auto&& raw = utility::conversions::to_utf8string(data); + + return details::encode_impl(raw, [](int ch) -> bool { - return !uri_parser::is_unreserved(ch); + return !details::is_unreserved(ch); }); } utility::string_t uri::encode_uri(const utility::string_t &raw, uri::components::component component) { + auto&& raw_utf8 = utility::conversions::to_utf8string(raw); + // Note: we also encode the '+' character because some non-standard implementations // encode the space character as a '+' instead of %20. To better interoperate we encode // '+' to avoid any confusion and be mistaken as a space. switch(component) { case components::user_info: - return uri::encode_impl(raw, [](int ch) -> bool + return details::encode_impl(raw_utf8, [](int ch) -> bool { - return !uri_parser::is_user_info_character(ch) + return !details::is_user_info_character(ch) || ch == '%' || ch == '+'; }); case components::host: - return uri::encode_impl(raw, [](int ch) -> bool + return details::encode_impl(raw_utf8, [](int ch) -> bool { // No encoding of ASCII characters in host name (RFC 3986 3.2.2) return ch > 127; }); case components::path: - return uri::encode_impl(raw, [](int ch) -> bool + return details::encode_impl(raw_utf8, [](int ch) -> bool { - return !uri_parser::is_path_character(ch) + return !details::is_path_character(ch) || ch == '%' || ch == '+'; }); case components::query: - return uri::encode_impl(raw, [](int ch) -> bool + return details::encode_impl(raw_utf8, [](int ch) -> bool { - return !uri_parser::is_query_character(ch) + return !details::is_query_character(ch) || ch == '%' || ch == '+'; }); case components::fragment: - return uri::encode_impl(raw, [](int ch) -> bool + return details::encode_impl(raw_utf8, [](int ch) -> bool { - return !uri_parser::is_fragment_character(ch) + return !details::is_fragment_character(ch) || ch == '%' || ch == '+'; }); case components::full_uri: default: - return uri::encode_impl(raw, [](int ch) -> bool + return details::encode_impl(raw_utf8, [](int ch) -> bool { - return !uri_parser::is_unreserved(ch) && !uri_parser::is_reserved(ch); + return !details::is_unreserved(ch) && !details::is_reserved(ch); }); }; } @@ -230,7 +655,7 @@ static int hex_char_digit_to_decimal_char(int hex) utility::string_t uri::decode(const utility::string_t &encoded) { - std::string utf8raw; + utf8string raw; for(auto iter = encoded.begin(); iter != encoded.end(); ++iter) { if(*iter == _XPLATSTR('%')) @@ -246,15 +671,19 @@ utility::string_t uri::decode(const utility::string_t &encoded) } decimal_value += hex_char_digit_to_decimal_char(static_cast(*iter)); - utf8raw.push_back(static_cast(decimal_value)); + raw.push_back(static_cast(decimal_value)); + } + else if (*iter > CHAR_MAX || *iter < 0) + { + throw uri_exception("Invalid encoded URI string, must be entirely ascii"); } else { // encoded string has to be ASCII. - utf8raw.push_back(reinterpret_cast(*iter)); + raw.push_back(static_cast(*iter)); } } - return to_string_t(utf8raw); + return to_string_t(raw); } std::vector uri::split_path(const utility::string_t &path) @@ -315,7 +744,8 @@ std::map uri::split_query(const utility::s bool uri::validate(const utility::string_t &uri_string) { - return uri_parser::validate(uri_string); + details::inner_parse_out out; + return out.parse_from(uri_string.c_str()); } uri uri::authority() const diff --git a/Release/src/uri/uri_builder.cpp b/Release/src/uri/uri_builder.cpp index b7d08b6380..02dd024b9b 100644 --- a/Release/src/uri/uri_builder.cpp +++ b/Release/src/uri/uri_builder.cpp @@ -83,6 +83,20 @@ uri_builder &uri_builder::append_query(const utility::string_t &query, bool is_e return *this; } +uri_builder &uri_builder::set_port(const utility::string_t &port) +{ + utility::istringstream_t portStream(port); + portStream.imbue(std::locale::classic()); + int port_tmp; + portStream >> port_tmp; + if (portStream.fail() || portStream.bad()) + { + throw std::invalid_argument("invalid port argument, must be non empty string containing integer value"); + } + m_uri.m_port = port_tmp; + return *this; +} + uri_builder &uri_builder::append(const http::uri &relative_uri) { append_path(relative_uri.path()); @@ -106,5 +120,19 @@ bool uri_builder::is_valid() return uri::validate(m_uri.join()); } -} // namespace web +void uri_builder::append_query_encode_impl(const utility::string_t & name, const utf8string & value) +{ + utility::string_t encodedQuery = uri::encode_query_impl(utility::conversions::to_utf8string(name)); + encodedQuery.append(_XPLATSTR("=")); + encodedQuery.append(uri::encode_query_impl(value)); + + // The query key value pair was already encoded by us or the user separately. + append_query(encodedQuery, false); +} +void uri_builder::append_query_no_encode_impl(const utility::string_t & name, const utility::string_t & value) +{ + append_query(name + _XPLATSTR("=") + value, false); +} + +} // namespace web diff --git a/Release/src/uri/uri_parser.cpp b/Release/src/uri/uri_parser.cpp deleted file mode 100644 index 2778ae64a2..0000000000 --- a/Release/src/uri/uri_parser.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* URI parsing implementation -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ -#include "stdafx.h" -#include - -namespace web { namespace details { namespace uri_parser -{ - -bool validate(const utility::string_t &encoded_string) -{ - const utility::char_t *scheme_begin = nullptr; - const utility::char_t *scheme_end = nullptr; - const utility::char_t *uinfo_begin = nullptr; - const utility::char_t *uinfo_end = nullptr; - const utility::char_t *host_begin = nullptr; - const utility::char_t *host_end = nullptr; - int port_ptr = 0; - const utility::char_t *path_begin = nullptr; - const utility::char_t *path_end = nullptr; - const utility::char_t *query_begin = nullptr; - const utility::char_t *query_end = nullptr; - const utility::char_t *fragment_begin = nullptr; - const utility::char_t *fragment_end = nullptr; - - // perform a parse, but don't copy out the data - return inner_parse( - encoded_string.c_str(), - &scheme_begin, - &scheme_end, - &uinfo_begin, - &uinfo_end, - &host_begin, - &host_end, - &port_ptr, - &path_begin, - &path_end, - &query_begin, - &query_end, - &fragment_begin, - &fragment_end); -} - -bool parse(const utility::string_t &encoded_string, uri_components &components) -{ - const utility::char_t *scheme_begin = nullptr; - const utility::char_t *scheme_end = nullptr; - const utility::char_t *host_begin = nullptr; - const utility::char_t *host_end = nullptr; - const utility::char_t *uinfo_begin = nullptr; - const utility::char_t *uinfo_end = nullptr; - int port_ptr = 0; - const utility::char_t *path_begin = nullptr; - const utility::char_t *path_end = nullptr; - const utility::char_t *query_begin = nullptr; - const utility::char_t *query_end = nullptr; - const utility::char_t *fragment_begin = nullptr; - const utility::char_t *fragment_end = nullptr; - - if (inner_parse( - encoded_string.c_str(), - &scheme_begin, - &scheme_end, - &uinfo_begin, - &uinfo_end, - &host_begin, - &host_end, - &port_ptr, - &path_begin, - &path_end, - &query_begin, - &query_end, - &fragment_begin, - &fragment_end)) - { - if (scheme_begin) - { - components.m_scheme.assign(scheme_begin, scheme_end); - - // convert scheme to lowercase - std::transform(components.m_scheme.begin(), components.m_scheme.end(), components.m_scheme.begin(), [](utility::char_t c) { - return (utility::char_t)tolower(c); - }); - } - else - { - components.m_scheme.clear(); - } - - if (uinfo_begin) - { - components.m_user_info.assign(uinfo_begin, uinfo_end); - } - - if (host_begin) - { - components.m_host.assign(host_begin, host_end); - - // convert host to lowercase - std::transform(components.m_host.begin(), components.m_host.end(), components.m_host.begin(), [](utility::char_t c) { - return (utility::char_t)tolower(c); - }); - } - else - { - components.m_host.clear(); - } - - if (port_ptr) - { - components.m_port = port_ptr; - } - else - { - components.m_port = 0; - } - - if (path_begin) - { - components.m_path.assign(path_begin, path_end); - } - else - { - // default path to begin with a slash for easy comparison - components.m_path = _XPLATSTR("/"); - } - - if (query_begin) - { - components.m_query.assign(query_begin, query_end); - } - else - { - components.m_query.clear(); - } - - if (fragment_begin) - { - components.m_fragment.assign(fragment_begin, fragment_end); - } - else - { - components.m_fragment.clear(); - } - - return true; - } - else - { - return false; - } -} - -bool inner_parse( - const utility::char_t *encoded, - const utility::char_t **scheme_begin, const utility::char_t **scheme_end, - const utility::char_t **uinfo_begin, const utility::char_t **uinfo_end, - const utility::char_t **host_begin, const utility::char_t **host_end, - _Out_ int *port, - const utility::char_t **path_begin, const utility::char_t **path_end, - const utility::char_t **query_begin, const utility::char_t **query_end, - const utility::char_t **fragment_begin, const utility::char_t **fragment_end) -{ - *scheme_begin = nullptr; - *scheme_end = nullptr; - *uinfo_begin = nullptr; - *uinfo_end = nullptr; - *host_begin = nullptr; - *host_end = nullptr; - *port = 0; - *path_begin = nullptr; - *path_end = nullptr; - *query_begin = nullptr; - *query_end = nullptr; - *fragment_begin = nullptr; - *fragment_end = nullptr; - - const utility::char_t *p = encoded; - - // IMPORTANT -- A uri may either be an absolute uri, or an relative-reference - // Absolute: 'http://host.com' - // Relative-Reference: '//:host.com', '/path1/path2?query', './path1:path2' - // A Relative-Reference can be disambiguated by parsing for a ':' before the first slash - - bool is_relative_reference = true; - const utility::char_t *p2 = p; - for (;*p2 != _XPLATSTR('/') && *p2 != _XPLATSTR('\0'); p2++) - { - if (*p2 == _XPLATSTR(':')) - { - // found a colon, the first portion is a scheme - is_relative_reference = false; - break; - } - } - - if (!is_relative_reference) - { - // the first character of a scheme must be a letter - if (!isalpha(*p)) - { - return false; - } - - // start parsing the scheme, it's always delimited by a colon (must be present) - *scheme_begin = p++; - for (;*p != ':'; p++) - { - if (!is_scheme_character(*p)) - { - return false; - } - } - *scheme_end = p; - - // skip over the colon - p++; - } - - // if we see two slashes next, then we're going to parse the authority portion - // later on we'll break up the authority into the port and host - const utility::char_t *authority_begin = nullptr; - const utility::char_t *authority_end = nullptr; - if (*p == _XPLATSTR('/') && p[1] == _XPLATSTR('/')) - { - // skip over the slashes - p += 2; - authority_begin = p; - - // the authority is delimited by a slash (resource), question-mark (query) or octothorpe (fragment) - // or by EOS. The authority could be empty ('file:///C:\file_name.txt') - for (;*p != _XPLATSTR('/') && *p != _XPLATSTR('?') && *p != _XPLATSTR('#') && *p != _XPLATSTR('\0'); p++) - { - // We're NOT currently supporting IPvFuture or username/password in authority - // IPv6 as the host (i.e. http://[:::::::]) is allowed as valid URI and passed to subsystem for support. - if (!is_authority_character(*p)) - { - return false; - } - } - authority_end = p; - - // now lets see if we have a port specified -- by working back from the end - if (authority_begin != authority_end) - { - // the port is made up of all digits - const utility::char_t *port_begin = authority_end - 1; - for (;isdigit(*port_begin) && port_begin != authority_begin; port_begin--) - { } - - if (*port_begin == _XPLATSTR(':')) - { - // has a port - *host_begin = authority_begin; - *host_end = port_begin; - - //skip the colon - port_begin++; - - *port = utility::conversions::details::scan_string(utility::string_t(port_begin, authority_end)); - } - else - { - // no port - *host_begin = authority_begin; - *host_end = authority_end; - } - - // look for a user_info component - const utility::char_t *u_end = *host_begin; - for (;is_user_info_character(*u_end) && u_end != *host_end; u_end++) - { } - - if (*u_end == _XPLATSTR('@')) - { - *host_begin = u_end+1; - *uinfo_begin = authority_begin; - *uinfo_end = u_end; - } - else - { - uinfo_end = uinfo_begin = nullptr; - } - } - } - - // if we see a path character or a slash, then the - // if we see a slash, or any other legal path character, parse the path next - if (*p == _XPLATSTR('/') || is_path_character(*p)) - { - *path_begin = p; - - // the path is delimited by a question-mark (query) or octothorpe (fragment) or by EOS - for (;*p != _XPLATSTR('?') && *p != _XPLATSTR('#') && *p != _XPLATSTR('\0'); p++) - { - if (!is_path_character(*p)) - { - return false; - } - } - *path_end = p; - } - - // if we see a ?, then the query is next - if (*p == _XPLATSTR('?')) - { - // skip over the question mark - p++; - *query_begin = p; - - // the query is delimited by a '#' (fragment) or EOS - for (;*p != _XPLATSTR('#') && *p != _XPLATSTR('\0'); p++) - { - if (!is_query_character(*p)) - { - return false; - } - } - *query_end = p; - } - - // if we see a #, then the fragment is next - if (*p == _XPLATSTR('#')) - { - // skip over the hash mark - p++; - *fragment_begin = p; - - // the fragment is delimited by EOS - for (;*p != _XPLATSTR('\0'); p++) - { - if (!is_fragment_character(*p)) - { - return false; - } - } - *fragment_end = p; - } - - return true; -} - -}}} diff --git a/Release/tests/functional/uri/encoding_tests.cpp b/Release/tests/functional/uri/encoding_tests.cpp index e24cc73462..3daff234f8 100644 --- a/Release/tests/functional/uri/encoding_tests.cpp +++ b/Release/tests/functional/uri/encoding_tests.cpp @@ -33,11 +33,11 @@ TEST(encode_string) TEST(decode_string) { - utility::string_t result = uri::encode_uri(L"first%second\u4e2d\u56fd"); - VERIFY_ARE_EQUAL(L"first%second\u4e2d\u56fd", uri::decode(result)); + utility::string_t result = uri::decode(U("first%25second%E4%B8%AD%E5%9B%BD")); + VERIFY_ARE_EQUAL(L"first%second\u4e2d\u56fd", result); - result = uri::encode_uri(U("first%second")); - VERIFY_ARE_EQUAL(U("first%second"), uri::decode(result)); + result = uri::decode(U("first%25second")); + VERIFY_ARE_EQUAL(U("first%second"), result); } #pragma warning (pop) #endif From a24b81a58bd34e3881fa0a1a37cd366c67b84d9a Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sun, 5 Nov 2017 01:23:52 -0700 Subject: [PATCH 321/609] Fixup static Win32 builds --- Release/src/CMakeLists.txt | 2 +- Release/tests/functional/streams/CMakeLists.txt | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index cfe3dbe760..be53a53305 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -192,7 +192,7 @@ if(WIN32) if (BUILD_SHARED_LIBS) target_compile_definitions(cpprest PRIVATE -D_ASYNCRT_EXPORT -D_PPLX_EXPORT -D_USRDLL) else() - target_compile_definitions(cpprest INTERFACE -D_NO_ASYNCRTIMP -D_NO_PPLXIMP) + target_compile_definitions(cpprest PUBLIC -D_NO_ASYNCRTIMP -D_NO_PPLXIMP) endif() elseif(ANDROID) target_link_libraries(cpprest PRIVATE ${ANDROID_STL_FLAGS}) diff --git a/Release/tests/functional/streams/CMakeLists.txt b/Release/tests/functional/streams/CMakeLists.txt index af45beffca..4b11173b18 100644 --- a/Release/tests/functional/streams/CMakeLists.txt +++ b/Release/tests/functional/streams/CMakeLists.txt @@ -18,5 +18,9 @@ endif() add_casablanca_test(streams_test SOURCES) if(NOT WIN32 OR CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") cpprest_find_boost() - target_link_libraries(streams_test PRIVATE cpprestsdk_boost_internal) + if(NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") + target_link_libraries(streams_test PRIVATE cpprestsdk_boost_internal) + else() + target_include_directories(streams_test PRIVATE $) + endif() endif() From 9bea093a39b797a204e598189f9fae6f165550fb Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Thu, 9 Nov 2017 09:27:50 +0000 Subject: [PATCH 322/609] Patch to get e.g. "cpprest140d_2_10.dll" as described in Microsoft/cpprestsdk#577 --- Release/src/CMakeLists.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index be53a53305..927e98be0f 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -216,8 +216,18 @@ elseif(WINDOWS_STORE) endif() if(WIN32) - set_target_properties(cpprest PROPERTIES - OUTPUT_NAME "cpprest_${CPPREST_VERSION_MAJOR}_${CPPREST_VERSION_MINOR}") + string(SUBSTRING ${CMAKE_VS_PLATFORM_TOOLSET} 1 -1 TOOLSET) + set(CPPREST_VERSION_POSTFIX "_${CPPREST_VERSION_MAJOR}_${CPPREST_VERSION_MINOR}") + foreach(CFG ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER ${CFG} CFG) + get_target_property(CFG_POSTFIX cpprest ${CFG}_POSTFIX) + if (NOT CFG_POSTFIX) + # forget "NOTFOUND" + set(CFG_POSTFIX) + endif() + set_target_properties(cpprest PROPERTIES + ${CFG}_POSTFIX "${TOOLSET}${CFG_POSTFIX}${CPPREST_VERSION_POSTFIX}") + endforeach() elseif(ANDROID) # Do not use SOVERSION on android. It is completely unsupported (and causes problems). # Perhaps revisit in the future? (NDK r9d, 8/7/14) From 88fd367c8ab38bff2e86ed29550e9dec4b364480 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 9 Nov 2017 12:15:54 -0800 Subject: [PATCH 323/609] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ae75be9704..79277b4a10 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,6 @@ target_link_libraries(main PRIVATE cpprestsdk::cpprest) * PPL Tasks - A powerful model for composing asynchronous operations based on C++ 11 features * Platforms - Windows desktop, Windows Store, Windows Phone, Ubuntu, OS X, iOS, and Android * Support for Visual Studio 2012, 2013, and 2015 with debugger visualizers -* NuGet package with binaries for Windows and Android platforms ## Contribute Back! From 1a7237d9064ee95a7ce1b83885f0abde46565635 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 9 Nov 2017 12:17:00 -0800 Subject: [PATCH 324/609] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 79277b4a10..89bd7e1ad3 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,8 @@ target_link_libraries(main PRIVATE cpprestsdk::cpprest) * Features - HTTP client/server, JSON, URI, asynchronous streams, WebSockets client, oAuth * PPL Tasks - A powerful model for composing asynchronous operations based on C++ 11 features -* Platforms - Windows desktop, Windows Store, Windows Phone, Ubuntu, OS X, iOS, and Android -* Support for Visual Studio 2012, 2013, and 2015 with debugger visualizers +* Platforms - Windows desktop, Windows Store (UWP), Linux, OS X, Unix, iOS, and Android +* Support for Visual Studio 2015 and 2017 with debugger visualizers ## Contribute Back! From 8120975601997f469d5da6fce3814027c7f6f096 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 13 Nov 2017 23:43:41 -0800 Subject: [PATCH 325/609] Remove use of CMake 3.6 feature: list(FILTER). Fixes #603. --- Release/src/CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index be53a53305..b862e44117 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -11,7 +11,8 @@ source_group("Header Files\\cpprest" FILES ${HEADERS_CPPREST}) source_group("Header Files\\pplx" FILES ${HEADERS_PPLX}) source_group("Header Files\\cpprest\\details" FILES ${HEADERS_DETAILS}) -list(FILTER HEADERS_PPLX EXCLUDE REGEX "threadpool\\.h") +file(GLOB HEADER_PPLX_THREADPOOL "../include/pplx/threadpool.h") +list(REMOVE_ITEM HEADERS_PPLX ${HEADER_PPLX_THREADPOOL}) set(SOURCES ${HEADERS_CPPREST} @@ -163,14 +164,12 @@ endif() if(MSVC) get_target_property(_srcs cpprest SOURCES) - set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - list(FILTER _srcs EXCLUDE REGEX "pch/stdafx\\.cpp$") - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") set_property(SOURCE pch/stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") endif() + set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") target_sources(cpprest PRIVATE pch/stdafx.cpp) target_compile_options(cpprest PRIVATE /Yustdafx.h /Zm200) endif() From fc1f692dbeb639c5eff8f31292dc5825f26c787c Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 14 Nov 2017 02:10:39 -0800 Subject: [PATCH 326/609] Remove use of find_dependency(Boost) since it causes problems with CMake versions before 3.9 --- Release/cmake/cpprestsdk-config.in.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/cmake/cpprestsdk-config.in.cmake b/Release/cmake/cpprestsdk-config.in.cmake index 39f636c77d..522f8f7db1 100644 --- a/Release/cmake/cpprestsdk-config.in.cmake +++ b/Release/cmake/cpprestsdk-config.in.cmake @@ -7,11 +7,11 @@ if(@CPPREST_USES_OPENSSL@) find_dependency(OpenSSL) endif() -if(@CPPREST_USES_BOOST@) +if(@CPPREST_USES_BOOST@ AND OFF) if(UNIX) find_dependency(Boost COMPONENTS random system thread filesystem chrono atomic date_time regex) else() find_dependency(Boost COMPONENTS system date_time regex) endif() endif() -include("${CMAKE_CURRENT_LIST_DIR}/cpprestsdk-targets.cmake") \ No newline at end of file +include("${CMAKE_CURRENT_LIST_DIR}/cpprestsdk-targets.cmake") From c42a369d179db28baeca76e9037435adb40b6801 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Tue, 21 Nov 2017 10:33:42 +0000 Subject: [PATCH 327/609] GCC 4.7 in experimental C++11 mode tokenises '<::' at the beginning of a template argument list or *_cast conversion incorrectly as the digraph '<:' (meaning '[') followed by a single ':'; the former can be resolved by -fpermissive, the latter isn't --- Release/CMakeLists.txt | 3 +++ Release/tests/functional/json/parsing_tests.cpp | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 218adcbb34..4f02df386f 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -163,6 +163,9 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") + endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") message("-- Setting msvc options") diff --git a/Release/tests/functional/json/parsing_tests.cpp b/Release/tests/functional/json/parsing_tests.cpp index 2d4925d87a..c1cc7a8305 100644 --- a/Release/tests/functional/json/parsing_tests.cpp +++ b/Release/tests/functional/json/parsing_tests.cpp @@ -223,7 +223,7 @@ TEST(escaping_control_characters) for (int i : chars) { - ::utility::stringstream_t ss; + utility::stringstream_t ss; ss << U("\"\\u") << std::uppercase << std::setfill(U('0')) << std::setw(4) << std::hex << i << U("\""); const auto &str = ss.str(); auto expectedStr = str; @@ -257,8 +257,8 @@ TEST(escaping_control_characters) } // Try constructing a json string value directly. - ::utility::string_t schar; - schar.push_back(static_cast<::utility::string_t::value_type>(i)); + utility::string_t schar; + schar.push_back(static_cast(i)); const auto &sv = json::value::string(schar); VERIFY_ARE_EQUAL(expectedStr, sv.serialize()); From a282292b043e9eca64270b2e50c1071bcc83d2e3 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Tue, 21 Nov 2017 10:39:16 +0000 Subject: [PATCH 328/609] Workaround for libstdc++ issue with GCC 4.7 (ultimately fixed in GCC 4.9) that means std::this_thread::yield() and std::this_thread::sleep_for() are only conditionally provided; see https://stackoverflow.com/a/12961816 --- Release/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 4f02df386f..86a1a8475e 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -164,7 +164,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -D_GLIBCXX_USE_SCHED_YIELD -D_GLIBCXX_USE_NANOSLEEP") endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") From 7ee017664c8a8280ae7e835aa0ded9c47e858e19 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Tue, 21 Nov 2017 10:41:12 +0000 Subject: [PATCH 329/609] At GCC 4.7, libstdc++ std::map didn't provide emplace(); using insert() is insignificant here --- Release/tests/common/TestRunner/test_runner.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/common/TestRunner/test_runner.cpp b/Release/tests/common/TestRunner/test_runner.cpp index bb5160d4d9..7ec573dbbd 100644 --- a/Release/tests/common/TestRunner/test_runner.cpp +++ b/Release/tests/common/TestRunner/test_runner.cpp @@ -409,7 +409,7 @@ testlist_t load_all_tests(test_module_loader& module_loader) testlist_t testlists; // Retrieve the static tests and clear for dll loading. - testlists.emplace("", UnitTest::GetTestList()); + testlists.insert({ "", UnitTest::GetTestList() }); UnitTest::GetTestList().Clear(); // Cycle through all the test binaries and load them @@ -445,7 +445,7 @@ testlist_t load_all_tests(test_module_loader& module_loader) std::cout << "Loaded " << binary << "..." << std::endl; // Store the loaded binary into the test list map - testlists.emplace(binary, UnitTest::GetTestList()); + testlists.insert({ binary, UnitTest::GetTestList() }); UnitTest::GetTestList().Clear(); } } From 43a6f73cfe44b1954f5e5052e06ca96dba9f1707 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Tue, 21 Nov 2017 10:45:51 +0000 Subject: [PATCH 330/609] At GCC 4.7, C++11 rules for noexcept specification of implicit destructors (and default specification on explicit destructors without exception specifications) aren't perfectly implemented --- Release/src/websockets/client/ws_client_wspp.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index e9e7658b18..dd1f809f6d 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -127,7 +127,7 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: #endif {} - ~wspp_callback_client() + ~wspp_callback_client() CPPREST_NOEXCEPT { _ASSERTE(m_state < DESTROYED); std::unique_lock lock(m_wspp_client_lock); @@ -730,6 +730,7 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: }; struct websocketpp_client : websocketpp_client_base { + ~websocketpp_client() CPPREST_NOEXCEPT {} websocketpp::client & non_tls_client() override { return m_client; @@ -739,6 +740,7 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: }; struct websocketpp_tls_client : websocketpp_client_base { + ~websocketpp_tls_client() CPPREST_NOEXCEPT {} websocketpp::client & tls_client() override { return m_client; From 5244af7ccf165709ec26c558dfcdb2531e0415cd Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Tue, 21 Nov 2017 12:42:42 +0000 Subject: [PATCH 331/609] =?UTF-8?q?At=20GCC=204.7,=20there=20are=20several?= =?UTF-8?q?=20bugs=20that=20cause=20"error:=20=E2=80=98this=E2=80=99=20was?= =?UTF-8?q?=20not=20captured=20for=20this=20lambda=20function"=20to=20be?= =?UTF-8?q?=20reported=20incorrectly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Release/src/http/client/http_client_asio.cpp | 28 +++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 19e09b2427..dc0e5daad3 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -44,6 +44,16 @@ #include #include +#if !defined(__GNUC__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS +#else +// GCC Bug 56222 - Pointer to member in lambda should not require this to be captured +// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56222 +// GCC Bug 51494 - Legal program rejection - capturing "this" when using static method inside lambda +// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494 +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS , this +#endif + using boost::asio::ip::tcp; #ifdef __ANDROID__ @@ -620,7 +630,7 @@ class asio_context : public request_context, public std::enable_shared_from_this proxy_host = utility::conversions::to_utf8string(proxy_uri.host()); } - auto start_http_request_flow = [proxy_type, proxy_host, proxy_port](std::shared_ptr ctx) + auto start_http_request_flow = [proxy_type, proxy_host, proxy_port AND_CAPTURE_MEMBER_FUNCTION_POINTERS](std::shared_ptr ctx) { if (ctx->m_request._cancellation_token().is_canceled()) { @@ -1010,7 +1020,7 @@ class asio_context : public request_context, public std::enable_shared_from_this auto readbuf = _get_readbuffer(); uint8_t *buf = boost::asio::buffer_cast(m_body_buf.prepare(chunkSize + http::details::chunked_encoding::additional_encoding_space)); const auto this_request = shared_from_this(); - readbuf.getn(buf + http::details::chunked_encoding::data_offset, chunkSize).then([this_request, buf, chunkSize](pplx::task op) + readbuf.getn(buf + http::details::chunked_encoding::data_offset, chunkSize).then([this_request, buf, chunkSize AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { size_t readSize = 0; try @@ -1067,7 +1077,7 @@ class asio_context : public request_context, public std::enable_shared_from_this const auto this_request = shared_from_this(); const auto readSize = static_cast(std::min(static_cast(m_http_client->client_config().chunksize()), m_content_length - m_uploaded)); auto readbuf = _get_readbuffer(); - readbuf.getn(boost::asio::buffer_cast(m_body_buf.prepare(readSize)), readSize).then([this_request](pplx::task op) + readbuf.getn(boost::asio::buffer_cast(m_body_buf.prepare(readSize)), readSize).then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { try { @@ -1370,7 +1380,7 @@ class asio_context : public request_context, public std::enable_shared_from_this auto shared_decompressed = std::make_shared(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) - .then([this_request, to_read, shared_decompressed](pplx::task op) + .then([this_request, to_read, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { try { @@ -1388,7 +1398,7 @@ class asio_context : public request_context, public std::enable_shared_from_this } else { - writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read).then([this_request, to_read](pplx::task op) + writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read).then([this_request, to_read AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { try { @@ -1485,7 +1495,7 @@ class asio_context : public request_context, public std::enable_shared_from_this auto shared_decompressed = std::make_shared(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) - .then([this_request, read_size, shared_decompressed](pplx::task op) + .then([this_request, read_size, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { size_t writtenSize = 0; try @@ -1507,7 +1517,7 @@ class asio_context : public request_context, public std::enable_shared_from_this else { writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), read_size) - .then([this_request](pplx::task op) + .then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { size_t writtenSize = 0; try @@ -1558,7 +1568,7 @@ class asio_context : public request_context, public std::enable_shared_from_this m_timer.expires_from_now(m_duration); auto ctx = m_ctx; - m_timer.async_wait([ctx](const boost::system::error_code& ec) + m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) { handle_timeout(ec, ctx); }); @@ -1573,7 +1583,7 @@ class asio_context : public request_context, public std::enable_shared_from_this // The existing handler was canceled so schedule a new one. assert(m_state == started); auto ctx = m_ctx; - m_timer.async_wait([ctx](const boost::system::error_code& ec) + m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) { handle_timeout(ec, ctx); }); From ca81f1f80e84777efe74c83777bfdd365f6597df Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 21 Nov 2017 20:19:26 -0800 Subject: [PATCH 332/609] Complete removal of uri_parser --- Release/src/build/common.vcxitems | 2 -- Release/src/build/common.vcxitems.filters | 6 ------ 2 files changed, 8 deletions(-) diff --git a/Release/src/build/common.vcxitems b/Release/src/build/common.vcxitems index 4abeacb737..520e0dbac3 100644 --- a/Release/src/build/common.vcxitems +++ b/Release/src/build/common.vcxitems @@ -34,7 +34,6 @@ - @@ -58,7 +57,6 @@ - diff --git a/Release/src/build/common.vcxitems.filters b/Release/src/build/common.vcxitems.filters index 8839f755df..5445979e22 100644 --- a/Release/src/build/common.vcxitems.filters +++ b/Release/src/build/common.vcxitems.filters @@ -52,9 +52,6 @@ Source Files - - Source Files - Source Files @@ -173,9 +170,6 @@ Header Files\cpprest\details - - Header Files\cpprest\details - Header Files\cpprest\details From fe308d9fe3b4928ccd293b527fa4f097c09a1a72 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 21 Nov 2017 20:54:40 -0800 Subject: [PATCH 333/609] Fix for #595 --- Release/src/uri/uri.cpp | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index f257787e94..4c06e52e2b 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -106,20 +106,6 @@ namespace return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':'; } - /// - /// Legal characters in the host portion include: - /// - Any unreserved character - /// - The percent character ('%'), and thus any percent-endcoded octet - /// - The sub-delimiters - /// - ':' (colon) - /// - '[' (open bracket) - /// - ']' (close bracket) - /// - inline bool is_host_character(int c) - { - return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':' || c == '[' || c == ']'; - } - /// /// Legal characters in the authority portion include: /// - Any unreserved character @@ -653,19 +639,20 @@ static int hex_char_digit_to_decimal_char(int hex) return decimal; } -utility::string_t uri::decode(const utility::string_t &encoded) +template +static std::string decode_template(const String& encoded) { - utf8string raw; - for(auto iter = encoded.begin(); iter != encoded.end(); ++iter) + std::string raw; + for (auto iter = encoded.begin(); iter != encoded.end(); ++iter) { - if(*iter == _XPLATSTR('%')) + if (*iter == '%') { - if(++iter == encoded.end()) + if (++iter == encoded.end()) { throw uri_exception("Invalid URI string, two hexadecimal digits must follow '%'"); } int decimal_value = hex_char_digit_to_decimal_char(static_cast(*iter)) << 4; - if(++iter == encoded.end()) + if (++iter == encoded.end()) { throw uri_exception("Invalid URI string, two hexadecimal digits must follow '%'"); } @@ -673,7 +660,7 @@ utility::string_t uri::decode(const utility::string_t &encoded) raw.push_back(static_cast(decimal_value)); } - else if (*iter > CHAR_MAX || *iter < 0) + else if (*iter > 127 || *iter < 0) { throw uri_exception("Invalid encoded URI string, must be entirely ascii"); } @@ -683,7 +670,12 @@ utility::string_t uri::decode(const utility::string_t &encoded) raw.push_back(static_cast(*iter)); } } - return to_string_t(raw); + return raw; +} + +utility::string_t uri::decode(const utility::string_t &encoded) +{ + return to_string_t(decode_template(encoded)); } std::vector uri::split_path(const utility::string_t &path) From 307c447367377d9b13752d32118f6778833d7978 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 21 Nov 2017 21:13:41 -0800 Subject: [PATCH 334/609] Fix outside_tests:ignore_server_cert_invalid --- Release/tests/functional/http/client/outside_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 56825fa00d..4c16fb4db6 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -198,7 +198,7 @@ TEST(ignore_server_cert_invalid, http_client_config config; config.set_validate_certificates(false); config.set_timeout(std::chrono::seconds(1)); - http_client client(U("https://www.pcwebshop.co.uk/"), config); + http_client client(U("https://expired.badssl.com/"), config); auto request = client.request(methods::GET).get(); VERIFY_ARE_EQUAL(status_codes::OK, request.status_code()); From d0ce63e06422bd5eaa85cffb3aa39629c67ce4d9 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Thu, 23 Nov 2017 17:03:51 +0000 Subject: [PATCH 335/609] VS2013 incorrectly reports "warning C4573: the usage of 'symbol' requires the compiler to capture 'this' but the current default capture mode does not allow it"; the issue and workaround is the same as for GCC 4.7 in commit:5244af7c. --- Release/src/http/client/http_client_asio.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index dc0e5daad3..36e3b10362 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -44,7 +44,9 @@ #include #include -#if !defined(__GNUC__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +#if defined(__GNUC__) + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) #define AND_CAPTURE_MEMBER_FUNCTION_POINTERS #else // GCC Bug 56222 - Pointer to member in lambda should not require this to be captured @@ -54,6 +56,21 @@ #define AND_CAPTURE_MEMBER_FUNCTION_POINTERS , this #endif +#elif defined(_MSC_VER) + +#if _MSC_VER >= 1900 +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS +#else +// This bug also afflicts VS2013 which incorrectly reports "warning C4573: the usage of 'symbol' requires the compiler to capture 'this' but the current default capture mode does not allow it" +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS , this +#endif + +#else + +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS + +#endif + using boost::asio::ip::tcp; #ifdef __ANDROID__ From b226326a1df1e0404686cd59e9b8546cf54382cc Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Thu, 23 Nov 2017 17:12:55 +0000 Subject: [PATCH 336/609] Define http_listener if CPPREST_FORCE_HTTP_LISTENER_ASIO is defined --- Release/include/cpprest/http_listener.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/http_listener.h b/Release/include/cpprest/http_listener.h index 3c154e49a6..88faa97da1 100644 --- a/Release/include/cpprest/http_listener.h +++ b/Release/include/cpprest/http_listener.h @@ -21,7 +21,7 @@ #include #endif -#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) +#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) namespace web { From 823f3b737127bf23bb97fd42ab3aad3ec7cc994f Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Fri, 24 Nov 2017 17:45:16 +0000 Subject: [PATCH 337/609] Define http_listener_impl and http_server_api if CPPREST_FORCE_HTTP_LISTENER_ASIO is defined --- Release/src/http/listener/http_listener.cpp | 2 +- Release/src/http/listener/http_server_api.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/src/http/listener/http_listener.cpp b/Release/src/http/listener/http_listener.cpp index 704e17c475..baa204b56d 100644 --- a/Release/src/http/listener/http_listener.cpp +++ b/Release/src/http/listener/http_listener.cpp @@ -13,7 +13,7 @@ #include "stdafx.h" -#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) +#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) using namespace web::http::experimental; diff --git a/Release/src/http/listener/http_server_api.cpp b/Release/src/http/listener/http_server_api.cpp index b72d6cf8ef..9a8289b7fa 100644 --- a/Release/src/http/listener/http_server_api.cpp +++ b/Release/src/http/listener/http_server_api.cpp @@ -11,7 +11,7 @@ #include "stdafx.h" -#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) +#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) #include "http_server_impl.h" using namespace web; From ff50bb0305ba6495ffc1d4170f4c2eec88404700 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Fri, 24 Nov 2017 17:41:57 +0000 Subject: [PATCH 338/609] Suppress two instances of "warning C4503: 'identifier' : decorated name length exceeded, name was truncated" generated too late for disable to be effective inside push/pop --- .../functional/websockets/utilities/test_websocket_server.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp index 108b0455cc..b4cfd806c4 100644 --- a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp +++ b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp @@ -18,8 +18,9 @@ #include "test_websocket_server.h" #ifdef _WIN32 +#pragma warning(disable : 4503) // generated too late for disable to be effective inside push/pop #pragma warning( push ) -#pragma warning(disable : 4100 4127 4996 4512 4701 4267 4067 4503 4005) +#pragma warning(disable : 4100 4127 4996 4512 4701 4267 4067 4005) #define _WEBSOCKETPP_CPP11_STL_ #define _WEBSOCKETPP_CONSTEXPR_TOKEN_ #if _MSC_VER < 1900 From c2f2388479779f64f34652871fbdf93fa4b0b58b Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Fri, 24 Nov 2017 17:50:29 +0000 Subject: [PATCH 339/609] Enable test create_https_listener_get on Windows if CPPREST_FORCE_HTTP_LISTENER_ASIO is defined --- .../functional/http/listener/listener_construction_tests.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Release/tests/functional/http/listener/listener_construction_tests.cpp b/Release/tests/functional/http/listener/listener_construction_tests.cpp index 1637160bc0..1bf31ffa88 100644 --- a/Release/tests/functional/http/listener/listener_construction_tests.cpp +++ b/Release/tests/functional/http/listener/listener_construction_tests.cpp @@ -430,7 +430,7 @@ TEST_FIXTURE(uri_address, listener_config_creation) } } -#if !defined(_WIN32) && !defined(__cplusplus_winrt) +#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) TEST_FIXTURE(uri_address, create_https_listener_get, "Ignore", "github 209") { @@ -545,7 +545,6 @@ XzJTD4slrGSJrcpLt/g/Jqqdjg== for (auto&& h : all_headers) { - std::cout << "HEADER - " << h.first << ": " << h.second << std::endl; VERIFY_IS_TRUE(request.headers().has(h.first)); VERIFY_ARE_EQUAL(h.second, request.headers().find(h.first)->second); } From 0f658589ad8a39152dc15c03eda06bbc878343d9 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Fri, 24 Nov 2017 17:57:39 +0000 Subject: [PATCH 340/609] VS2013 incorrectly reports "warning C4573: the usage of 'symbol' requires the compiler to capture 'this' but the current default capture mode does not allow it"; the issue and workaround is the same as for GCC 4.7 in commit:5244af7c. (cherry picked from commit d0ce63e06422bd5eaa85cffb3aa39629c67ce4d9) --- Release/src/http/client/http_client_asio.cpp | 45 ++++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 19e09b2427..36e3b10362 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -44,6 +44,33 @@ #include #include +#if defined(__GNUC__) + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS +#else +// GCC Bug 56222 - Pointer to member in lambda should not require this to be captured +// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56222 +// GCC Bug 51494 - Legal program rejection - capturing "this" when using static method inside lambda +// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494 +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS , this +#endif + +#elif defined(_MSC_VER) + +#if _MSC_VER >= 1900 +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS +#else +// This bug also afflicts VS2013 which incorrectly reports "warning C4573: the usage of 'symbol' requires the compiler to capture 'this' but the current default capture mode does not allow it" +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS , this +#endif + +#else + +#define AND_CAPTURE_MEMBER_FUNCTION_POINTERS + +#endif + using boost::asio::ip::tcp; #ifdef __ANDROID__ @@ -620,7 +647,7 @@ class asio_context : public request_context, public std::enable_shared_from_this proxy_host = utility::conversions::to_utf8string(proxy_uri.host()); } - auto start_http_request_flow = [proxy_type, proxy_host, proxy_port](std::shared_ptr ctx) + auto start_http_request_flow = [proxy_type, proxy_host, proxy_port AND_CAPTURE_MEMBER_FUNCTION_POINTERS](std::shared_ptr ctx) { if (ctx->m_request._cancellation_token().is_canceled()) { @@ -1010,7 +1037,7 @@ class asio_context : public request_context, public std::enable_shared_from_this auto readbuf = _get_readbuffer(); uint8_t *buf = boost::asio::buffer_cast(m_body_buf.prepare(chunkSize + http::details::chunked_encoding::additional_encoding_space)); const auto this_request = shared_from_this(); - readbuf.getn(buf + http::details::chunked_encoding::data_offset, chunkSize).then([this_request, buf, chunkSize](pplx::task op) + readbuf.getn(buf + http::details::chunked_encoding::data_offset, chunkSize).then([this_request, buf, chunkSize AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { size_t readSize = 0; try @@ -1067,7 +1094,7 @@ class asio_context : public request_context, public std::enable_shared_from_this const auto this_request = shared_from_this(); const auto readSize = static_cast(std::min(static_cast(m_http_client->client_config().chunksize()), m_content_length - m_uploaded)); auto readbuf = _get_readbuffer(); - readbuf.getn(boost::asio::buffer_cast(m_body_buf.prepare(readSize)), readSize).then([this_request](pplx::task op) + readbuf.getn(boost::asio::buffer_cast(m_body_buf.prepare(readSize)), readSize).then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { try { @@ -1370,7 +1397,7 @@ class asio_context : public request_context, public std::enable_shared_from_this auto shared_decompressed = std::make_shared(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) - .then([this_request, to_read, shared_decompressed](pplx::task op) + .then([this_request, to_read, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { try { @@ -1388,7 +1415,7 @@ class asio_context : public request_context, public std::enable_shared_from_this } else { - writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read).then([this_request, to_read](pplx::task op) + writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read).then([this_request, to_read AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { try { @@ -1485,7 +1512,7 @@ class asio_context : public request_context, public std::enable_shared_from_this auto shared_decompressed = std::make_shared(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) - .then([this_request, read_size, shared_decompressed](pplx::task op) + .then([this_request, read_size, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { size_t writtenSize = 0; try @@ -1507,7 +1534,7 @@ class asio_context : public request_context, public std::enable_shared_from_this else { writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), read_size) - .then([this_request](pplx::task op) + .then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { size_t writtenSize = 0; try @@ -1558,7 +1585,7 @@ class asio_context : public request_context, public std::enable_shared_from_this m_timer.expires_from_now(m_duration); auto ctx = m_ctx; - m_timer.async_wait([ctx](const boost::system::error_code& ec) + m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) { handle_timeout(ec, ctx); }); @@ -1573,7 +1600,7 @@ class asio_context : public request_context, public std::enable_shared_from_this // The existing handler was canceled so schedule a new one. assert(m_state == started); auto ctx = m_ctx; - m_timer.async_wait([ctx](const boost::system::error_code& ec) + m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) { handle_timeout(ec, ctx); }); From 38bf3f3ae53956a33860c67ea217d4a3c9b5a7e1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 29 Nov 2017 12:05:09 -0800 Subject: [PATCH 341/609] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 89bd7e1ad3..f084f87e9f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,13 @@ The C++ REST SDK is a Microsoft project for cloud-based client-server communicat ## Getting Started +[![Vcpkg package](https://repology.org/badge/version-for-repo/vcpkg/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk) +[![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk) +[![Ubuntu 18.04 package](https://repology.org/badge/version-for-repo/ubuntu_18_04/casablanca.svg)](https://repology.org/metapackage/casablanca) +[![Fedora Rawhide package](https://repology.org/badge/version-for-repo/fedora_rawhide/cpprest.svg)](https://repology.org/metapackage/cpprest) +[![openSUSE Tumbleweed package](https://repology.org/badge/version-for-repo/opensuse_tumbleweed/cpprest.svg)](https://repology.org/metapackage/cpprest) +[![Debian Testing package](https://repology.org/badge/version-for-repo/debian_testing/casablanca.svg)](https://repology.org/metapackage/casablanca) + With [vcpkg](https://github.com/Microsoft/vcpkg) on Windows ``` PS> vcpkg install cpprestsdk cpprestsdk:x64-windows From ece8108832a6ae6f6b64105c44f59c7fbb90bfd6 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 30 Nov 2017 15:27:46 -0800 Subject: [PATCH 342/609] Prevent automatic instantiation of Concurrency::Details::_do_while() --- Release/include/cpprest/astreambuf.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Release/include/cpprest/astreambuf.h b/Release/include/cpprest/astreambuf.h index cca1abc9cb..c0463835b2 100644 --- a/Release/include/cpprest/astreambuf.h +++ b/Release/include/cpprest/astreambuf.h @@ -26,13 +26,13 @@ namespace Concurrency { namespace details { - template - pplx::task _do_while(std::function(void)> func) + template + pplx::task _do_while(F func) { - pplx::task first = func(); - return first.then([=](bool guard) -> pplx::task { + pplx::task first = func(); + return first.then([=](bool guard) -> pplx::task { if (guard) - return Concurrency::details::_do_while(func); + return Concurrency::details::_do_while(func); else return first; }); @@ -1200,3 +1200,4 @@ namespace streams }; }} + From 91a666b9e76e51b227e44e9db6c371a19f7d2fcb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 1 Dec 2017 13:59:23 -0800 Subject: [PATCH 343/609] Update badges --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f084f87e9f..4669fd8871 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ The C++ REST SDK is a Microsoft project for cloud-based client-server communicat ## Getting Started -[![Vcpkg package](https://repology.org/badge/version-for-repo/vcpkg/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk) -[![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk) -[![Ubuntu 18.04 package](https://repology.org/badge/version-for-repo/ubuntu_18_04/casablanca.svg)](https://repology.org/metapackage/casablanca) -[![Fedora Rawhide package](https://repology.org/badge/version-for-repo/fedora_rawhide/cpprest.svg)](https://repology.org/metapackage/cpprest) -[![openSUSE Tumbleweed package](https://repology.org/badge/version-for-repo/opensuse_tumbleweed/cpprest.svg)](https://repology.org/metapackage/cpprest) -[![Debian Testing package](https://repology.org/badge/version-for-repo/debian_testing/casablanca.svg)](https://repology.org/metapackage/casablanca) +[![Vcpkg package](https://repology.org/badge/version-for-repo/vcpkg/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
+[![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
+[![Ubuntu 18.04 package](https://repology.org/badge/version-for-repo/ubuntu_18_04/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
+[![Fedora Rawhide package](https://repology.org/badge/version-for-repo/fedora_rawhide/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
+[![openSUSE Tumbleweed package](https://repology.org/badge/version-for-repo/opensuse_tumbleweed/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
+[![Debian Testing package](https://repology.org/badge/version-for-repo/debian_testing/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
With [vcpkg](https://github.com/Microsoft/vcpkg) on Windows ``` From 09d5984e022d36295e1afa276d6923b1d579f67e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 2 Dec 2017 15:50:36 -0800 Subject: [PATCH 344/609] Improve MSVC compiler throughput by avoiding unneeded instantiations --- Release/include/cpprest/astreambuf.h | 1 + Release/include/pplx/pplxtasks.h | 72 ++++++++-------------------- 2 files changed, 20 insertions(+), 53 deletions(-) diff --git a/Release/include/cpprest/astreambuf.h b/Release/include/cpprest/astreambuf.h index c0463835b2..642f0738dd 100644 --- a/Release/include/cpprest/astreambuf.h +++ b/Release/include/cpprest/astreambuf.h @@ -1200,4 +1200,5 @@ namespace streams }; }} + diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index c3f9552e35..212c6ba4cc 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -60,6 +60,7 @@ void cpprest_init(JavaVM*); #include #if defined(_MSC_VER) +#include #if defined(__cplusplus_winrt) #include #include @@ -6698,7 +6699,7 @@ auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions /// /**/ template -task> operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) +auto operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) { task<_ReturnType> _PTasks[2] = {_Lhs, _Rhs}; return when_all(_PTasks, _PTasks+2); @@ -6730,7 +6731,7 @@ task> operator&&(const task<_ReturnType> & _Lhs, const /// /**/ template -task> operator&&(const task> & _Lhs, const task<_ReturnType> & _Rhs) +auto operator&&(const task> & _Lhs, const task<_ReturnType> & _Rhs) { return details::_WhenAllVectorAndValue(_Lhs, _Rhs, true); } @@ -6761,7 +6762,7 @@ task> operator&&(const task> & /// /**/ template -task> operator&&(const task<_ReturnType> & _Lhs, const task> & _Rhs) +auto operator&&(const task<_ReturnType> & _Lhs, const task> & _Rhs) { return details::_WhenAllVectorAndValue(_Rhs, _Lhs, false); } @@ -6792,43 +6793,12 @@ task> operator&&(const task<_ReturnType> & _Lhs, const /// /**/ template -task> operator&&(const task> & _Lhs, const task> & _Rhs) +auto operator&&(const task> & _Lhs, const task> & _Rhs) { task> _PTasks[2] = {_Lhs, _Rhs}; return when_all(_PTasks, _PTasks+2); } -/// -/// Creates a task that will complete succesfully when both of the tasks supplied as arguments complete successfully. -/// -/// -/// The type of the returned task. -/// -/// -/// The first task to combine into the resulting task. -/// -/// -/// The second task to combine into the resulting task. -/// -/// -/// A task that completes successfully when both of the input tasks have completed successfully. If the input tasks are of type T, -/// the output of this function will be a task<std::vector<T>>. If the input tasks are of type void the output -/// task will also be a task<void>. -/// To allow for a construct of the sort taskA && taskB && taskC, which are combined in pairs, the && operator -/// produces a task<std::vector<T>> if either one or both of the tasks are of type task<std::vector<T>>. -/// -/// -/// If one of the tasks is canceled or throws an exception, the returned task will complete early, in the canceled state, and the exception, -/// if one is encoutered, will be thrown if you call get() or wait() on that task. -/// -/// -/**/ -inline task operator&&(const task & _Lhs, const task & _Rhs) -{ - task _PTasks[2] = {_Lhs, _Rhs}; - return when_all(_PTasks, _PTasks+2); -} - namespace details { // Helper struct for when_any operators to know when tasks have completed @@ -7114,7 +7084,7 @@ auto when_any(_Iterator _Begin, _Iterator _End, cancellation_token _Cancellation /// /**/ template -task<_ReturnType> operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) +auto operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) { auto _PParam = new details::_RunAnyParam>(); @@ -7175,7 +7145,7 @@ task<_ReturnType> operator||(const task<_ReturnType> & _Lhs, const task<_ReturnT /// /**/ template -task> operator||(const task> & _Lhs, const task<_ReturnType> & _Rhs) +auto operator||(const task> & _Lhs, const task<_ReturnType> & _Rhs) { auto _PParam = new details::_RunAnyParam, details::_CancellationTokenState *>>(); @@ -7249,7 +7219,7 @@ task> operator||(const task> & /// /**/ template -task> operator||(const task<_ReturnType> & _Lhs, const task> & _Rhs) +auto operator||(const task<_ReturnType> & _Lhs, const task> & _Rhs) { return _Rhs || _Lhs; } @@ -7280,14 +7250,17 @@ task> operator||(const task<_ReturnType> & _Lhs, const /// /// /**/ -inline task operator||(const task & _Lhs, const task & _Rhs) +template, typename _Pair = std::pair> +_Ty operator||(const task & _Lhs_arg, const task & _Rhs_arg) { - auto _PParam = new details::_RunAnyParam>(); + const _Ty& _Lhs = _Lhs_arg; + const _Ty& _Rhs = _Rhs_arg; + auto _PParam = new details::_RunAnyParam<_Pair>(); task> _Any_task_completed(_PParam->_M_Completed, _PParam->_M_cancellationSource.get_token()); // Chain the return continuation task here to ensure it will get inline execution when _M_Completed.set is called, // So that _PParam can be used before it getting deleted. - auto _ReturnTask = _Any_task_completed._Then([=](std::pair _Ret) { + auto _ReturnTask = _Any_task_completed._Then([=](_Pair _Ret) { _ASSERTE(_Ret.second); details::_JoinAllTokens_Add(_PParam->_M_cancellationSource, _Ret.second); }, nullptr); @@ -7298,7 +7271,7 @@ inline task operator||(const task & _Lhs, const task & _Rhs) } _PParam->_M_numTasks = 2; - auto _Continuation = [_PParam](task _ResultTask) mutable { + auto _Continuation = [_PParam](_Ty _ResultTask) mutable { // Dev10 compiler needs this. auto _PParam1 = _PParam; auto _Func = [&_ResultTask, _PParam1]() { @@ -7321,18 +7294,10 @@ task<_Ty> task_from_result(_Ty _Param, const task_options& _TaskOptions = task_o return create_task(_Tce, _TaskOptions); } -// Work around VS 2010 compiler bug -#if _MSC_VER == 1600 -inline task task_from_result(bool _Param) -{ - task_completion_event _Tce; - _Tce.set(_Param); - return create_task(_Tce, task_options()); -} -#endif -inline task task_from_result(const task_options& _TaskOptions = task_options()) +template +inline task<_Ty> task_from_result(const task_options& _TaskOptions = task_options()) { - task_completion_event _Tce; + task_completion_event<_Ty> _Tce; _Tce.set(); return create_task(_Tce, _TaskOptions); } @@ -7367,3 +7332,4 @@ namespace concurrency = Concurrency; #endif #endif // _PPLXTASKS_H + From b855c0abc7586103bef33e4e533a9f1ce8c7c3d4 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Tue, 5 Dec 2017 12:01:29 +0000 Subject: [PATCH 345/609] Add http_listener configuration for the backlog, the maximum length of the queue of pending connections on the port. --- Release/include/cpprest/http_listener.h | 26 +++++++++++++++++++ .../src/http/listener/http_server_asio.cpp | 11 +++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/http_listener.h b/Release/include/cpprest/http_listener.h index 3c154e49a6..d51e6e512f 100644 --- a/Release/include/cpprest/http_listener.h +++ b/Release/include/cpprest/http_listener.h @@ -46,6 +46,7 @@ class http_listener_config ///
http_listener_config() : m_timeout(utility::seconds(120)) + , m_backlog(0) {} ///
@@ -54,6 +55,7 @@ class http_listener_config /// http_listener_config to copy. http_listener_config(const http_listener_config &other) : m_timeout(other.m_timeout) + , m_backlog(other.m_backlog) #if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) , m_ssl_context_callback(other.m_ssl_context_callback) #endif @@ -65,6 +67,7 @@ class http_listener_config /// http_listener_config to move from. http_listener_config(http_listener_config &&other) : m_timeout(std::move(other.m_timeout)) + , m_backlog(std::move(other.m_backlog)) #if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) , m_ssl_context_callback(std::move(other.m_ssl_context_callback)) #endif @@ -79,6 +82,7 @@ class http_listener_config if(this != &rhs) { m_timeout = rhs.m_timeout; + m_backlog = rhs.m_backlog; #if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) m_ssl_context_callback = rhs.m_ssl_context_callback; #endif @@ -95,6 +99,7 @@ class http_listener_config if(this != &rhs) { m_timeout = std::move(rhs.m_timeout); + m_backlog = std::move(rhs.m_backlog); #if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) m_ssl_context_callback = std::move(rhs.m_ssl_context_callback); #endif @@ -120,6 +125,26 @@ class http_listener_config m_timeout = std::move(timeout); } + /// + /// Get the listen backlog + /// + /// The maximum length of the queue of pending connections, or zero for the implementation default. + /// The implementation may not honour this value. + int backlog() const + { + return m_backlog; + } + + /// + /// Set the listen backlog + /// + /// The maximum length of the queue of pending connections, or zero for the implementation default. + /// The implementation may not honour this value. + void set_backlog(int backlog) + { + m_backlog = backlog; + } + #if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) /// /// Get the callback of ssl context @@ -143,6 +168,7 @@ class http_listener_config private: utility::seconds m_timeout; + int m_backlog; #if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) std::function m_ssl_context_callback; #endif diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 99351c13a0..7fe2a76938 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -122,6 +122,7 @@ namespace class hostport_listener { private: + int m_backlog; std::unique_ptr m_acceptor; std::map m_listeners; pplx::extensibility::reader_writer_lock_t m_listeners_lock; @@ -140,7 +141,8 @@ namespace public: hostport_listener(http_linux_server* server, const std::string& hostport, bool is_https, const http_listener_config& config) - : m_acceptor() + : m_backlog(config.backlog()) + , m_acceptor() , m_listeners() , m_listeners_lock() , m_connections_lock() @@ -482,8 +484,11 @@ void hostport_listener::start() tcp::endpoint endpoint = *resolver.resolve(query); - m_acceptor.reset(new tcp::acceptor(service, endpoint)); - m_acceptor->set_option(tcp::acceptor::reuse_address(true)); + m_acceptor.reset(new tcp::acceptor(service)); + m_acceptor->open(endpoint.protocol()); + m_acceptor->set_option(socket_base::reuse_address(true)); + m_acceptor->bind(endpoint); + m_acceptor->listen(0 != m_backlog ? m_backlog : socket_base::max_connections); auto socket = new ip::tcp::socket(service); m_acceptor->async_accept(*socket, [this, socket](const boost::system::error_code& ec) From 23f1c7c49896b7543af6a12924215a3ca3227ee9 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 5 Dec 2017 15:41:36 -0800 Subject: [PATCH 346/609] Fix identation (should be spaces) --- Release/include/cpprest/streams.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 823466aa3b..1aaf95ed9e 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -883,11 +883,11 @@ namespace Concurrency { namespace streams if (ch == concurrency::streams::char_traits::eof()) return pplx::task_from_result(false); if (ch == '\n') { - return buffer.bumpc().then([]( + return buffer.bumpc().then([]( #ifndef _WIN32 // Required by GCC - typename + typename #endif - concurrency::streams::char_traits::int_type) { return false; }); + concurrency::streams::char_traits::int_type) { return false; }); } return pplx::task_from_result(false); }; From 05e474a2d8f041f56691a4e9f7f79bd0f110809c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 5 Dec 2017 15:43:17 -0800 Subject: [PATCH 347/609] Typename required by MSVC now too --- Release/include/cpprest/streams.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 1aaf95ed9e..c928bfd50d 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -884,10 +884,7 @@ namespace Concurrency { namespace streams if (ch == '\n') { return buffer.bumpc().then([]( -#ifndef _WIN32 // Required by GCC - typename -#endif - concurrency::streams::char_traits::int_type) { return false; }); + typename concurrency::streams::char_traits::int_type) { return false; }); } return pplx::task_from_result(false); }; @@ -896,10 +893,7 @@ namespace Concurrency { namespace streams { while ( buffer.in_avail() > 0 ) { -#ifndef _WIN32 // Required by GCC, because concurrency::streams::char_traits is a dependent scope - typename -#endif - concurrency::streams::char_traits::int_type ch; + typename concurrency::streams::char_traits::int_type ch; if (_locals->saw_CR) { From 7946980b9a6aab6962c85cfa9da515d5e0524d5c Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 5 Dec 2017 16:47:34 -0800 Subject: [PATCH 348/609] Remove :: from ::utility (workaround two-phase msvc bug) --- Release/include/cpprest/http_client.h | 2 +- Release/include/cpprest/http_msg.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 80c48265a1..a936a23ede 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -603,7 +603,7 @@ class http_client const method &mtd, const utf16string &path_query_fragment, const utf16string &body_data, - const utf16string &content_type = ::utility::conversions::to_utf16string("text/plain"), + const utf16string &content_type = utility::conversions::to_utf16string("text/plain"), const pplx::cancellation_token &token = pplx::cancellation_token::none()) { http_request msg(mtd); diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 8ca25edc69..083e75713e 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -568,7 +568,7 @@ class http_response /// /// This will overwrite any previously set body data and "Content-Type" header. /// - void set_body(const utf16string &body_text, utf16string content_type = ::utility::conversions::to_utf16string("text/plain")) + void set_body(const utf16string &body_text, utf16string content_type = utility::conversions::to_utf16string("text/plain")) { if (content_type.find(::utility::conversions::to_utf16string("charset=")) != content_type.npos) { @@ -978,7 +978,7 @@ class http_request /// /// This will overwrite any previously set body data and "Content-Type" header. /// - void set_body(const utf16string &body_text, utf16string content_type = ::utility::conversions::to_utf16string("text/plain")) + void set_body(const utf16string &body_text, utf16string content_type = utility::conversions::to_utf16string("text/plain")) { if(content_type.find(::utility::conversions::to_utf16string("charset=")) != content_type.npos) { @@ -1207,7 +1207,7 @@ class http_request // Callers of this function do NOT need to block waiting for the response to be /// sent to before the body data is destroyed or goes out of scope. /// - pplx::task reply(http::status_code status, const utf16string &body_data, const utf16string &content_type = ::utility::conversions::to_utf16string("text/plain")) const + pplx::task reply(http::status_code status, const utf16string &body_data, const utf16string &content_type = utility::conversions::to_utf16string("text/plain")) const { http_response response(status); response.set_body(body_data, content_type); From 19b67d592bad60a44ed8a20ba7505fb6f468b566 Mon Sep 17 00:00:00 2001 From: Alexander Karatarakis Date: Tue, 5 Dec 2017 17:22:44 -0800 Subject: [PATCH 349/609] Fix /Zc:strictStrings issues raised by /permissive- --- Release/src/http/client/x509_cert_utilities.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/src/http/client/x509_cert_utilities.cpp b/Release/src/http/client/x509_cert_utilities.cpp index 48c50e07df..1d4e7137e7 100644 --- a/Release/src/http/client/x509_cert_utilities.cpp +++ b/Release/src/http/client/x509_cert_utilities.cpp @@ -431,11 +431,11 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std params.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; LPSTR usages [] = { - szOID_PKIX_KP_SERVER_AUTH, + (LPSTR)szOID_PKIX_KP_SERVER_AUTH, // For older servers and to match IE. - szOID_SERVER_GATED_CRYPTO, - szOID_SGC_NETSCAPE + (LPSTR)szOID_SERVER_GATED_CRYPTO, + (LPSTR)szOID_SGC_NETSCAPE }; params.RequestedUsage.Usage.cUsageIdentifier = std::extent::value; params.RequestedUsage.Usage.rgpszUsageIdentifier = usages; From e56e3d79d8323196292695d728c13216c050c74c Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 5 Dec 2017 18:19:41 -0800 Subject: [PATCH 350/609] Revert regression in c++11 support. Fixes #621. --- Release/include/pplx/pplxtasks.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index 212c6ba4cc..998ecba29d 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -6699,7 +6699,7 @@ auto when_all(_Iterator _Begin, _Iterator _End, const task_options& _TaskOptions /// /**/ template -auto operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) +auto operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) -> decltype(when_all(&_Lhs, &_Lhs)) { task<_ReturnType> _PTasks[2] = {_Lhs, _Rhs}; return when_all(_PTasks, _PTasks+2); @@ -6731,7 +6731,7 @@ auto operator&&(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) /// /**/ template -auto operator&&(const task> & _Lhs, const task<_ReturnType> & _Rhs) +auto operator&&(const task> & _Lhs, const task<_ReturnType> & _Rhs) -> decltype(details::_WhenAllVectorAndValue(_Lhs, _Rhs, true)) { return details::_WhenAllVectorAndValue(_Lhs, _Rhs, true); } @@ -6762,7 +6762,7 @@ auto operator&&(const task> & _Lhs, const task<_ReturnT /// /**/ template -auto operator&&(const task<_ReturnType> & _Lhs, const task> & _Rhs) +auto operator&&(const task<_ReturnType> & _Lhs, const task> & _Rhs) -> decltype(details::_WhenAllVectorAndValue(_Rhs, _Lhs, false)) { return details::_WhenAllVectorAndValue(_Rhs, _Lhs, false); } @@ -6793,7 +6793,7 @@ auto operator&&(const task<_ReturnType> & _Lhs, const task /**/ template -auto operator&&(const task> & _Lhs, const task> & _Rhs) +auto operator&&(const task> & _Lhs, const task> & _Rhs) -> decltype(when_all(&_Lhs, &_Lhs)) { task> _PTasks[2] = {_Lhs, _Rhs}; return when_all(_PTasks, _PTasks+2); @@ -7084,7 +7084,7 @@ auto when_any(_Iterator _Begin, _Iterator _End, cancellation_token _Cancellation /// /**/ template -auto operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) +task<_ReturnType> operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) { auto _PParam = new details::_RunAnyParam>(); @@ -7145,7 +7145,7 @@ auto operator||(const task<_ReturnType> & _Lhs, const task<_ReturnType> & _Rhs) /// /**/ template -auto operator||(const task> & _Lhs, const task<_ReturnType> & _Rhs) +task> operator||(const task> & _Lhs, const task<_ReturnType> & _Rhs) { auto _PParam = new details::_RunAnyParam, details::_CancellationTokenState *>>(); @@ -7219,7 +7219,7 @@ auto operator||(const task> & _Lhs, const task<_ReturnT /// /**/ template -auto operator||(const task<_ReturnType> & _Lhs, const task> & _Rhs) +auto operator||(const task<_ReturnType> & _Lhs, const task> & _Rhs) -> decltype(_Rhs || _Lhs) { return _Rhs || _Lhs; } From 242da36338b73198e892a439550d41db4233990f Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 5 Dec 2017 18:20:08 -0800 Subject: [PATCH 351/609] Remove excessive specialization of type_parser to improve compiler throughput. --- Release/include/cpprest/streams.h | 51 +++---------------------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index c928bfd50d..7e240c0c94 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -1711,55 +1711,11 @@ class type_parser : public _type_parser_base }; #ifdef _WIN32 -template<> -class type_parser> : public _type_parser_base +template +class type_parser>> : public _type_parser_base { public: - static pplx::task parse(streams::streambuf buffer) - { - return _parse_input,std::basic_string>(buffer, _accept_char, _extract_result); - } - -private: - static bool _accept_char(const std::shared_ptr> &state, int_type ch) - { - if ( ch == concurrency::streams::char_traits::eof() || isspace(ch)) return false; - state->push_back(char(ch)); - return true; - } - static pplx::task> _extract_result(std::shared_ptr> state) - { - return pplx::task_from_result(utility::conversions::utf8_to_utf16(*state)); - } -}; - -template<> -class type_parser> : public _type_parser_base -{ -public: - static pplx::task parse(streams::streambuf buffer) - { - return _parse_input,std::basic_string>(buffer, _accept_char, _extract_result); - } - -private: - static bool _accept_char(const std::shared_ptr> &state, int_type ch) - { - if ( ch == concurrency::streams::char_traits::eof() || isspace(ch)) return false; - state->push_back(char(ch)); - return true; - } - static pplx::task> _extract_result(std::shared_ptr> state) - { - return pplx::task_from_result(utility::conversions::utf8_to_utf16(*state)); - } -}; - -template<> -class type_parser> : public _type_parser_base -{ -public: - static pplx::task parse(streams::streambuf buffer) + static pplx::task parse(streams::streambuf buffer) { return _parse_input,std::basic_string>(buffer, _accept_char, _extract_result); } @@ -1781,3 +1737,4 @@ class type_parser> : public _type_parse }} #endif + From c258a4ac4d62f7550f51800588ca89699e9ffc84 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 14 Dec 2017 18:38:39 -0800 Subject: [PATCH 352/609] Remove NOMINMAX definition to better catch Windows.h issues in the future. --- Release/include/pplx/pplxtasks.h | 1 + .../src/http/client/http_client_winhttp.cpp | 4 ++++ Release/src/http/common/http_msg.cpp | 4 ++++ .../src/http/listener/http_server_httpsys.cpp | 5 ++++- Release/src/json/json.cpp | 4 ++++ Release/src/pch/stdafx.h | 20 ++++--------------- .../src/websockets/client/ws_client_wspp.cpp | 5 +++++ .../tests/common/utilities/os_utilities.cpp | 2 +- 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index 998ecba29d..e784306d40 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -7332,4 +7332,5 @@ namespace concurrency = Concurrency; #endif #endif // _PPLXTASKS_H + diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 60a4d060d5..07f5fdb3b9 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -21,6 +21,9 @@ #include #endif +#undef min +#undef max + namespace web { namespace http @@ -1527,3 +1530,4 @@ std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage( } }}}} + diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 6a857d7531..363d49c158 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -13,6 +13,9 @@ #include "stdafx.h" #include "../common/internal_http_helpers.h" +#undef min +#undef max + using namespace web; using namespace utility; using namespace concurrency; @@ -1043,3 +1046,4 @@ details::_http_request::_http_request(std::unique_ptr make_http_httpsys_server() }}}} -#endif \ No newline at end of file +#endif diff --git a/Release/src/json/json.cpp b/Release/src/json/json.cpp index e5a6089aea..04ddbe0fe4 100644 --- a/Release/src/json/json.cpp +++ b/Release/src/json/json.cpp @@ -13,6 +13,9 @@ #include "stdafx.h" +#undef min +#undef max + using namespace web; bool json::details::g_keep_json_object_unsorted = false; @@ -516,3 +519,4 @@ const web::json::details::json_error_category_impl& web::json::details::json_err #endif return instance; } + diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index 6f61163dfe..1532db2f54 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -19,9 +19,6 @@ #pragma clang diagnostic ignored "-Winfinite-recursion" #endif -#include "cpprest/details/cpprest_compat.h" -#include "cpprest/details/basic_types.h" - #ifdef _WIN32 #ifdef CPPREST_TARGET_XP #include @@ -37,12 +34,7 @@ #include #endif -#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#define NOMINMAX -#endif - #include #include @@ -96,6 +88,9 @@ #include #include +#include "cpprest/details/cpprest_compat.h" +#include "cpprest/details/basic_types.h" + #include "pplx/pplxtasks.h" #include "cpprest/version.h" @@ -140,13 +135,6 @@ #endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA #endif -#if defined(max) -#error: max macro defined -- make sure to #define NOMINMAX before including windows.h -#endif -#if defined(min) -#error: min macro defined -- make sure to #define NOMINMAX before including windows.h -#endif - #if defined(__clang__) #pragma clang diagnostic pop -#endif +#endif diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index e9e7658b18..78c443a27a 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -20,6 +20,10 @@ #include "ws_client_impl.h" +// These must be undef'ed before including websocketpp because it is not Windows.h safe. +#undef min +#undef max + // Force websocketpp to use C++ std::error_code instead of Boost. #define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_ #if defined(_MSC_VER) @@ -792,3 +796,4 @@ websocket_callback_client::websocket_callback_client(websocket_client_config con }}} #endif + diff --git a/Release/tests/common/utilities/os_utilities.cpp b/Release/tests/common/utilities/os_utilities.cpp index 1172b732bb..639460078e 100644 --- a/Release/tests/common/utilities/os_utilities.cpp +++ b/Release/tests/common/utilities/os_utilities.cpp @@ -15,7 +15,6 @@ #ifdef WIN32 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX #include #else #include @@ -55,3 +54,4 @@ long os_utilities::interlocked_exchange(volatile long *target, long value) } }}} + From bd4afa3b18bf5fddbe9fe2b88b527137655f6cfc Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 14 Dec 2017 18:48:07 -0800 Subject: [PATCH 353/609] Fix warnings on GCC7. --- Release/samples/Oauth1Client/Oauth1Client.cpp | 5 +++-- Release/samples/Oauth2Client/Oauth2Client.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Release/samples/Oauth1Client/Oauth1Client.cpp b/Release/samples/Oauth1Client/Oauth1Client.cpp index 065f0a1516..d360d37d54 100644 --- a/Release/samples/Oauth1Client/Oauth1Client.cpp +++ b/Release/samples/Oauth1Client/Oauth1Client.cpp @@ -64,11 +64,11 @@ static void open_browser(utility::string_t auth_uri) #elif defined(__APPLE__) // NOTE: OS X only. string_t browser_cmd(U("open \"") + auth_uri + U("\"")); - system(browser_cmd.c_str()); + (void)system(browser_cmd.c_str()); #else // NOTE: Linux/X11 only. string_t browser_cmd(U("xdg-open \"") + auth_uri + U("\"")); - system(browser_cmd.c_str()); + (void)system(browser_cmd.c_str()); #endif } @@ -301,3 +301,4 @@ int main(int argc, char *argv[]) ucout << "Done." << std::endl; return 0; } + diff --git a/Release/samples/Oauth2Client/Oauth2Client.cpp b/Release/samples/Oauth2Client/Oauth2Client.cpp index 3b988f00b3..59a963eaff 100644 --- a/Release/samples/Oauth2Client/Oauth2Client.cpp +++ b/Release/samples/Oauth2Client/Oauth2Client.cpp @@ -67,11 +67,11 @@ static void open_browser(utility::string_t auth_uri) #elif defined(__APPLE__) // NOTE: OS X only. string_t browser_cmd(U("open \"") + auth_uri + U("\"")); - system(browser_cmd.c_str()); + (void)system(browser_cmd.c_str()); #else // NOTE: Linux/X11 only. string_t browser_cmd(U("xdg-open \"") + auth_uri + U("\"")); - system(browser_cmd.c_str()); + (void)system(browser_cmd.c_str()); #endif } @@ -321,3 +321,4 @@ int main(int argc, char *argv[]) ucout << "Done." << std::endl; return 0; } + From e8dda215426172cd348e4d6d455141f40768bf47 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 14 Dec 2017 18:57:43 -0800 Subject: [PATCH 354/609] Push version number to 2.10.1 --- Build/version.props | 2 +- Release/include/cpprest/version.h | 3 ++- Release/src/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Build/version.props b/Build/version.props index 13b7b76e69..cbf33ac51b 100644 --- a/Build/version.props +++ b/Build/version.props @@ -4,7 +4,7 @@ cpprest 2 10 - 0 + 1 $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index c91a3db40a..2324dddddb 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -3,8 +3,9 @@ * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * */ -#define CPPREST_VERSION_REVISION 0 +#define CPPREST_VERSION_REVISION 1 #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) + diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index b862e44117..3f8a0f8d88 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_policy(SET CMP0022 NEW) set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 0) +set(CPPREST_VERSION_REVISION 1) file(GLOB HEADERS_CPPREST "../include/cpprest/*.h" "../include/cpprest/*.hpp" "../include/cpprest/*.dat") file(GLOB HEADERS_PPLX "../include/pplx/*.h" "../include/pplx/*.hpp") From c7444407f66c47739af107bba63aafe133d1e945 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Fri, 15 Dec 2017 11:14:35 +0000 Subject: [PATCH 355/609] Default the debug postfix for library filenames to "d" on Windows (it may still be overridden to the empty string) --- Release/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 218adcbb34..2b0e8d5f7b 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -32,6 +32,10 @@ else() set(BUILD_SAMPLES ON CACHE BOOL "Build sample applications.") endif() +if(WIN32) + set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Default filename postfix for libraries under configuration DEBUG") +endif() + if(ANDROID) set(Boost_USE_STATIC_LIBS ON CACHE BOOL "Link against boost statically.") else() From 3e8dcf5b574fa7f23920de3166e03fee5bf5aae1 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 19 Dec 2017 04:14:17 -0800 Subject: [PATCH 356/609] Fix UWP issues with min/max macros. --- Release/include/cpprest/streams.h | 1 + Release/src/http/client/http_client_winrt.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 7e240c0c94..60d5504e78 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -1714,6 +1714,7 @@ class type_parser : public _type_parser_base template class type_parser>> : public _type_parser_base { + typedef typename concurrency::streams::streambuf::int_type int_type; public: static pplx::task parse(streams::streambuf buffer) { diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 697f48a337..4ada65a75b 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -28,6 +28,9 @@ using namespace std; using namespace Platform; using namespace Microsoft::WRL; +#undef min +#undef max + namespace web { namespace http From 81d67e44e36f3e8aa05a19db3c0847c97d945836 Mon Sep 17 00:00:00 2001 From: garethsb-sony Date: Wed, 20 Dec 2017 10:24:55 +0000 Subject: [PATCH 357/609] Handle std::range_error (from count_utf16_to_utf8) like web::uri_exception --- Release/src/http/listener/http_server_asio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 99351c13a0..fcc531ecfe 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -637,7 +637,7 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys { m_request.set_request_uri(utility::conversions::to_string_t(http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1))); } - catch(const web::uri_exception &e) + catch (const std::exception& e) // may be std::range_error indicating invalid Unicode, or web::uri_exception { m_request.reply(status_codes::BadRequest, e.what()); m_close = true; @@ -913,7 +913,7 @@ will_deref_and_erase_t asio_server_connection::dispatch_request_to_listener() { pListener = m_p_parent->find_listener(m_request.relative_uri()); } - catch (const web::uri_exception&) + catch (const std::exception&) // may be web::uri_exception, or std::range_error indicating invalid Unicode { m_request.reply(status_codes::BadRequest); (will_erase_from_parent_t)do_response(); From 7105325b30aa8405ab6ee061e8677fde79aa9435 Mon Sep 17 00:00:00 2001 From: Jonathan Gawrych Date: Thu, 21 Dec 2017 18:49:25 -0800 Subject: [PATCH 358/609] Fix string use after destruct introduced in merge commit b7fa0b1 --- Release/src/http/client/http_client_winhttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 07f5fdb3b9..66ca12ddd1 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -412,6 +412,7 @@ class winhttp_client : public _http_client_communicator DWORD access_type; LPCWSTR proxy_name; LPCWSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS; + utility::string_t proxy_str; http::uri uri; const auto& config = client_config(); @@ -485,7 +486,6 @@ class winhttp_client : public _http_client_communicator } else { - utility::string_t proxy_str; if (uri.port() > 0) { utility::ostringstream_t ss; From 6b2e0480018530b616f61d5cdc786c92ba148bb7 Mon Sep 17 00:00:00 2001 From: John Hruby Date: Tue, 26 Dec 2017 16:52:13 +0100 Subject: [PATCH 359/609] fixed strand --- .../libs/websocketpp/websocketpp/transport/asio/connection.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/libs/websocketpp/websocketpp/transport/asio/connection.hpp b/Release/libs/websocketpp/websocketpp/transport/asio/connection.hpp index 0be40f6b45..395632c3f3 100644 --- a/Release/libs/websocketpp/websocketpp/transport/asio/connection.hpp +++ b/Release/libs/websocketpp/websocketpp/transport/asio/connection.hpp @@ -422,7 +422,7 @@ class connection : public config::socket_type::socket_con_type { m_io_service = io_service; if (config::enable_multithreading) { - m_strand = lib::make_shared( + m_strand = lib::make_shared( lib::ref(*io_service)); m_async_read_handler = m_strand->wrap(lib::bind( From 31ec7923b1eaf06567cea3bb7760f78ce44c447e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 3 Jan 2018 14:09:21 -0800 Subject: [PATCH 360/609] Extract the abi tag to make it more platform independent. --- Release/CMakeLists.txt | 20 ++++++++++++++++++-- Release/src/CMakeLists.txt | 17 +---------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 2b0e8d5f7b..416d5c1496 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -4,11 +4,15 @@ if(POLICY CMP0042) cmake_policy(SET CMP0042 NEW) # use MACOSX_RPATH endif() if(UNIX) - project(cpprest C CXX) + project(cpprestsdk C CXX) else() - project(cpprest CXX) + project(cpprestsdk CXX) endif() +set(CPPREST_VERSION_MAJOR 2) +set(CPPREST_VERSION_MINOR 10) +set(CPPREST_VERSION_REVISION 1) + enable_testing() set(WERROR ON CACHE BOOL "Treat Warnings as Errors.") @@ -34,6 +38,18 @@ endif() if(WIN32) set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Default filename postfix for libraries under configuration DEBUG") +else() + set(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Default filename postfix for libraries under configuration DEBUG") +endif() + +if(WIN32) + set(TOOLSET) + if(CMAKE_VS_PLATFORM_TOOLSET) + string(REGEX REPLACE "^v" "" TOOLSET "${CMAKE_VS_PLATFORM_TOOLSET}") + endif() + set(CPPREST_ABI_TAG "${TOOLSET}_${CPPREST_VERSION_MAJOR}_${CPPREST_VERSION_MINOR}" CACHE STRING "Postfix tag for the cpprest abi") +else() + set(CPPREST_ABI_TAG "" CACHE STRING "Postfix tag for the cpprest abi") endif() if(ANDROID) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 26dcc32ba3..a37a8cff9d 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -1,9 +1,5 @@ cmake_policy(SET CMP0022 NEW) -set(CPPREST_VERSION_MAJOR 2) -set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 1) - file(GLOB HEADERS_CPPREST "../include/cpprest/*.h" "../include/cpprest/*.hpp" "../include/cpprest/*.dat") file(GLOB HEADERS_PPLX "../include/pplx/*.h" "../include/pplx/*.hpp") file(GLOB HEADERS_DETAILS "../include/cpprest/details/*.h" "../include/cpprest/details/*.hpp" "../include/cpprest/details/*.dat" "../include/pplx/*.hpp" "../include/pplx/*.dat") @@ -214,19 +210,8 @@ elseif(WINDOWS_STORE) endif() endif() +set_target_properties(cpprest PROPERTIES OUTPUT_NAME "cpprest${CPPREST_ABI_TAG}") if(WIN32) - string(SUBSTRING ${CMAKE_VS_PLATFORM_TOOLSET} 1 -1 TOOLSET) - set(CPPREST_VERSION_POSTFIX "_${CPPREST_VERSION_MAJOR}_${CPPREST_VERSION_MINOR}") - foreach(CFG ${CMAKE_CONFIGURATION_TYPES}) - string(TOUPPER ${CFG} CFG) - get_target_property(CFG_POSTFIX cpprest ${CFG}_POSTFIX) - if (NOT CFG_POSTFIX) - # forget "NOTFOUND" - set(CFG_POSTFIX) - endif() - set_target_properties(cpprest PROPERTIES - ${CFG}_POSTFIX "${TOOLSET}${CFG_POSTFIX}${CPPREST_VERSION_POSTFIX}") - endforeach() elseif(ANDROID) # Do not use SOVERSION on android. It is completely unsupported (and causes problems). # Perhaps revisit in the future? (NDK r9d, 8/7/14) From 17a198081379384ed9373828f905592ce9c4bdf3 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 3 Jan 2018 14:09:36 -0800 Subject: [PATCH 361/609] Fix warning due to boost 1.66 --- Release/include/pplx/threadpool.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index c67db358a0..db1e97c870 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -67,9 +67,10 @@ class threadpool boost::asio::io_service& service() { return m_service; } protected: - threadpool(size_t num_threads) : m_service(num_threads) {} + threadpool(size_t num_threads) : m_service(static_cast(num_threads)) {} boost::asio::io_service m_service; }; } + From 3f04578f98d1356dc6898a2d55fa8bed3d485a48 Mon Sep 17 00:00:00 2001 From: dimarusyy Date: Thu, 4 Jan 2018 11:18:16 +0200 Subject: [PATCH 362/609] #643 : ssl proxy port is hard coded to 443 - use base URI port in "CONNECT" request to proxy server --- Release/src/http/client/http_client_asio.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 19e09b2427..e726760f2d 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -450,12 +450,13 @@ class asio_context : public request_context, public std::enable_shared_from_this const auto &base_uri = m_context->m_http_client->base_uri(); const auto &host = utility::conversions::to_utf8string(base_uri.host()); + const auto &port = base_uri.port(); std::ostream request_stream(&m_request); request_stream.imbue(std::locale::classic()); - request_stream << "CONNECT " << host << ":" << 443 << " HTTP/1.1" << CRLF; - request_stream << "Host: " << host << ":" << 443 << CRLF; + request_stream << "CONNECT " << host << ":" << ((port != 0) ? port : 443) << " HTTP/1.1" << CRLF; + request_stream << "Host: " << host << ":" << ((port != 0) ? port : 443) << CRLF; request_stream << "Proxy-Connection: Keep-Alive" << CRLF; if(m_context->m_http_client->client_config().proxy().credentials().is_set()) From 88fa4d27ec3fb1239a85114e8254ce3664b45fc8 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 9 Jan 2018 02:39:06 -0800 Subject: [PATCH 363/609] Fix Windows build regression (do not include sys/time.h) --- Release/include/cpprest/asyncrt_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 064d00f9c2..ad49baa5c3 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -23,11 +23,11 @@ #include "cpprest/details/basic_types.h" #if !defined(_WIN32) || (_MSC_VER >= 1700) -#include #include #endif #ifndef _WIN32 +#include #include #if !defined(ANDROID) && !defined(__ANDROID__) && defined(HAVE_XLOCALE_H) // CodePlex 269 /* Systems using glibc: xlocale.h has been removed from glibc 2.26 From b8d1c063ae4f366a3725d20e97ff1d6f2e488467 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 9 Jan 2018 02:52:18 -0800 Subject: [PATCH 364/609] Fix build regression on Windows (CHECK_INCLUDE_FILES requires C language support) --- Release/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 6d18afae1b..9b90129eaf 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -77,7 +77,10 @@ if(CPPREST_EXCLUDE_WEBSOCKETS) set(CPPREST_WEBSOCKETS_IMPL none CACHE STRING "Internal use.") endif() -CHECK_INCLUDE_FILES(xlocale.h HAVE_XLOCALE_H) +if(NOT WIN32) + CHECK_INCLUDE_FILES(xlocale.h HAVE_XLOCALE_H) +endif() + if(APPLE) # Note: also iOS set(CPPREST_PPLX_IMPL apple CACHE STRING "Internal use.") set(CPPREST_WEBSOCKETS_IMPL wspp CACHE STRING "Internal use.") From 391540826cf4e81c0138d58af102f8dc1e1f2dcf Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 24 Jan 2018 08:29:09 -0800 Subject: [PATCH 365/609] Disable "disable_sni" test due to lack of robust test servers. The current test can be run and does pass, but relies on a timeout. --- .../functional/websockets/client/authentication_tests.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/websockets/client/authentication_tests.cpp b/Release/tests/functional/websockets/client/authentication_tests.cpp index 5db5207697..00a498cb67 100644 --- a/Release/tests/functional/websockets/client/authentication_tests.cpp +++ b/Release/tests/functional/websockets/client/authentication_tests.cpp @@ -162,15 +162,18 @@ TEST(sni_with_older_server_test) } // WinRT doesn't expose option for disabling. -TEST(disable_sni) +// No stable server is available to reliably test this. +// The configuration below relies on a timeout in the success case. +TEST(disable_sni, "Ignore", "Manual") { websocket_client_config config; + config.set_server_name("expired.badssl.com"); config.disable_sni(); websocket_client client(config); try { - client.connect(U("wss://swordsoftruth.com")).wait(); + client.connect(U("wss://badssl.com")).wait(); // Should never be reached. VERIFY_IS_TRUE(false); @@ -239,3 +242,4 @@ TEST(cert_expired) }}}} #endif + From eba38b867dcf6749d9612f21c6b7cf1ef9d1625f Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Wed, 24 Jan 2018 16:31:59 +0000 Subject: [PATCH 366/609] Making crossplat::threadpool::shared_instance() safe to use in cpprest DLL (#611) * When the C++ REST SDK is built as a DLL on Windows, and unloaded before the process exits, the crossplat::threadpool::shared_instance() is destroyed at DLL_PROCESS_DETACH, at which stage joining threads causes deadlock. Use the workaround provided by asio to terminate the threads in this case. * Take 2. We can't just use TerminateThread indiscriminately because the thread may be holding e.g. the heap lock, so we need to ensure the thread is in a known state. Rather than reinvent the wheel, use asio's own thread class which already provides the necessary mechanism. * Export the shared instance to allow cross-platform implementation of functionality (e.g. complete_after) that needs access to the io_service when using the asio-based default scheduler * Use improved shutdown logic even when building as static lib, because users could include it in a DLL. --- Release/include/pplx/threadpool.h | 2 +- Release/src/pplx/threadpool.cpp | 65 ++++++++++++++++--------------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index db1e97c870..919eb75552 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -52,7 +52,7 @@ using java_local_ref = std::unique_ptr::type, ja class threadpool { public: - static threadpool& shared_instance(); + _ASYNCRTIMP static threadpool& shared_instance(); _ASYNCRTIMP static std::unique_ptr __cdecl construct(size_t num_threads); virtual ~threadpool() = default; diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index 8d3eadadc6..d2dc6161a2 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -9,16 +9,7 @@ #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) || !defined(_WIN32) #include "pplx/threadpool.h" -#if !defined(_WIN32) -#define CPPREST_PTHREADS -#endif - -#if defined(CPPREST_PTHREADS) -#include -#else -#include -#endif - +#include #include #if defined(__ANDROID__) @@ -44,27 +35,14 @@ struct threadpool_impl final : crossplat::threadpool m_service.stop(); for (auto iter = m_threads.begin(); iter != m_threads.end(); ++iter) { -#if defined(CPPREST_PTHREADS) - pthread_t t = *iter; - void* res; - pthread_join(t, &res); -#else - iter->join(); -#endif + (*iter)->join(); } } private: void add_thread() { -#ifdef CPPREST_PTHREADS - pthread_t t; - auto result = pthread_create(&t, nullptr, &thread_start, this); - if (result == 0) - m_threads.push_back(t); -#else - m_threads.push_back(std::thread(&thread_start, this)); -#endif + m_threads.push_back(std::unique_ptr(new boost::asio::detail::thread([&]{ thread_start(this); }))); } #if defined(__ANDROID__) @@ -89,11 +67,7 @@ struct threadpool_impl final : crossplat::threadpool return arg; } -#if defined(CPPREST_PTHREADS) - std::vector m_threads; -#else - std::vector m_threads; -#endif + std::vector> m_threads; boost::asio::io_service::work m_work; }; } @@ -133,6 +107,35 @@ threadpool& threadpool::shared_instance() return s_shared; } +#elif defined(_WIN32) + +// if linked into a DLL, the threadpool shared instance will be destroyed at DLL_PROCESS_DETACH, +// at which stage joining threads causes deadlock, hence this dance +threadpool& threadpool::shared_instance() +{ + static bool terminate_threads = false; + static struct restore_terminate_threads + { + ~restore_terminate_threads() + { + boost::asio::detail::thread::set_terminate_threads(terminate_threads); + } + } destroyed_after; + + static threadpool_impl s_shared(40); + + static struct enforce_terminate_threads + { + ~enforce_terminate_threads() + { + terminate_threads = boost::asio::detail::thread::terminate_threads(); + boost::asio::detail::thread::set_terminate_threads(true); + } + } destroyed_before; + + return s_shared; +} + #else // initialize the static shared threadpool @@ -156,4 +159,4 @@ std::unique_ptr crossplat::threadpool::construct(size_t n { return std::unique_ptr(new threadpool_impl(num_threads)); } -#endif \ No newline at end of file +#endif From 859292a8f70c2e4ae91c585a3d448ab345b0f989 Mon Sep 17 00:00:00 2001 From: Mathy Vanvoorden Date: Wed, 24 Jan 2018 20:15:38 +0100 Subject: [PATCH 367/609] Make it possible to set the user agent for websockets (#606) * Make it possible to set the user agent for websockets * Use headers() to communicate the user agent for websockets. * Fix set_user_agent on Linux; use to_string_t. --- Release/include/cpprest/ws_client.h | 6 ++++++ Release/src/websockets/client/ws_client_wspp.cpp | 10 +++++++++- Release/src/websockets/client/ws_msg.cpp | 6 ++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Release/include/cpprest/ws_client.h b/Release/include/cpprest/ws_client.h index 9c9e5d818d..9a324cde51 100644 --- a/Release/include/cpprest/ws_client.h +++ b/Release/include/cpprest/ws_client.h @@ -150,6 +150,12 @@ class websocket_client_config return m_sni_hostname; } + /// + /// Sets the User Agent to be used for the connection + /// + /// The User Agent to use, as a string. + _ASYNCRTIMP void set_user_agent(const utf8string &user_agent); + /// /// Gets the headers of the HTTP request message used in the WebSocket protocol handshake. /// diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 5074ebb062..8f2658a8f5 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -316,6 +316,15 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: shutdown_wspp_impl(con_hdl, false); }); + // Set User Agent specified by the user. This needs to happen before any connection is created + const auto& headers = m_config.headers(); + + auto user_agent_it = headers.find(web::http::header_names::user_agent); + if (user_agent_it != headers.end()) + { + client.set_user_agent(utility::conversions::to_utf8string(user_agent_it->second)); + } + // Get the connection handle to save for later, have to create temporary // because type erasure occurs with connection_hdl. websocketpp::lib::error_code ec; @@ -327,7 +336,6 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: } // Add any request headers specified by the user. - const auto & headers = m_config.headers(); for (const auto & header : headers) { if (!utility::details::str_icmp(header.first, g_subProtocolHeader)) diff --git a/Release/src/websockets/client/ws_msg.cpp b/Release/src/websockets/client/ws_msg.cpp index 10bce338e6..1d24409c67 100644 --- a/Release/src/websockets/client/ws_msg.cpp +++ b/Release/src/websockets/client/ws_msg.cpp @@ -28,6 +28,12 @@ namespace client { static ::utility::string_t g_subProtocolHeader = _XPLATSTR("Sec-WebSocket-Protocol"); + +void websocket_client_config::set_user_agent(const utf8string &user_agent) +{ + headers().add(web::http::header_names::user_agent, utility::conversions::to_string_t(user_agent)); +} + void websocket_client_config::add_subprotocol(const ::utility::string_t &name) { m_headers.add(g_subProtocolHeader, name); From fec80b0fdc59226cbb00dedffbb54b624bab3383 Mon Sep 17 00:00:00 2001 From: juntek Date: Wed, 24 Jan 2018 20:30:21 +0100 Subject: [PATCH 368/609] fixes #628 (#629) From 7db35851c16ecbe79a42f4ea4647cef647b7bf2c Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 24 Jan 2018 11:35:53 -0800 Subject: [PATCH 369/609] Fix min/max issues on Windows. --- Release/src/http/client/http_client_asio.cpp | 3 +++ Release/src/http/listener/http_server_asio.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 1e41ebe8f0..4ba3e0851b 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -15,6 +15,9 @@ #include "stdafx.h" +#undef min +#undef max + #include "cpprest/asyncrt_utils.h" #include "../common/internal_http_helpers.h" diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index c1d9791726..3fadebb03b 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -13,6 +13,10 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */ #include "stdafx.h" + +#undef min +#undef max + #include #include #include From 639726178046803d7193785b2eb2e75137df40f3 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Wed, 24 Jan 2018 22:53:59 +0000 Subject: [PATCH 370/609] Add support for retrieving HTTP version of a request in HTTP listener (#565) * Grab HTTP protocol version from the underlying request message and expose in http_request * Use error_code overload to resolve https://github.com/Microsoft/cpprestsdk/issues/545 * Rename get_http_version and get_remote_address without 'get_' prefix for consistency with rest of class public interface * Add test case for http_version * Fix GCC "error: changes meaning of 'http_version'..." that should have been in commit:1ba5ebfd * Use struct for http_version instead of pair. * Restore get_remote_address to avoid breaking source compat --- Release/include/cpprest/http_msg.h | 43 +++++++++++++++++++ Release/src/http/common/http_msg.cpp | 10 ++++- .../src/http/listener/http_server_asio.cpp | 22 +++++++++- .../src/http/listener/http_server_httpsys.cpp | 2 + .../http/listener/request_handler_tests.cpp | 35 ++++++++++++++- 5 files changed, 107 insertions(+), 5 deletions(-) diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 083e75713e..6b49bc4960 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -43,6 +43,34 @@ namespace client class http_client; } +/// +/// Represents the HTTP protocol version of a message, as {major, minor}. +/// +struct http_version +{ + uint8_t major; + uint8_t minor; + + inline bool operator==(const http_version& other) const { return major == other.major && minor == other.minor; } + inline bool operator<(const http_version& other) const { return major < other.major || (major == other.major && minor < other.minor); } + + inline bool operator!=(const http_version& other) const { return !(*this == other); } + inline bool operator>=(const http_version& other) const { return !(*this < other); } + inline bool operator>(const http_version& other) const { return !(*this < other || *this == other); } + inline bool operator<=(const http_version& other) const { return *this < other || *this == other; } +}; + +/// +/// Predefined HTTP protocol versions. +/// +class http_versions +{ +public: + _ASYNCRTIMP static const http_version HTTP_0_9; + _ASYNCRTIMP static const http_version HTTP_1_0; + _ASYNCRTIMP static const http_version HTTP_1_1; +}; + /// /// Predefined method strings for the standard HTTP methods mentioned in the /// HTTP 1.1 specification. @@ -715,6 +743,8 @@ class _http_request final : public http::details::http_msg_base, public std::ena _ASYNCRTIMP void set_request_uri(const uri&); + http::http_version http_version() const { return m_http_version; } + const utility::string_t& remote_address() const { return m_remote_address; } const pplx::cancellation_token &cancellation_token() const { return m_cancellationToken; } @@ -757,6 +787,8 @@ class _http_request final : public http::details::http_msg_base, public std::ena void _set_base_uri(const http::uri &base_uri) { m_base_uri = base_uri; } + void _set_http_version(const http::http_version &http_version) { m_http_version = http_version; } + void _set_remote_address(const utility::string_t &remote_address) { m_remote_address = remote_address; } private: @@ -783,6 +815,8 @@ class _http_request final : public http::details::http_msg_base, public std::ena pplx::task_completion_event m_response; + http::http_version m_http_version; + utility::string_t m_remote_address; }; @@ -875,10 +909,19 @@ class http_request /// const http_headers &headers() const { return _m_impl->headers(); } + /// + /// Returns the HTTP protocol version of this request message. + /// + /// The HTTP protocol version. + http::http_version http_version() const { return _m_impl->http_version(); } + /// /// Returns a string representation of the remote IP address. /// /// The remote IP address. + const utility::string_t& remote_address() const { return _m_impl->remote_address(); } + + CASABLANCA_DEPRECATED("Use `remote_address()` instead.") const utility::string_t& get_remote_address() const { return _m_impl->remote_address(); } /// diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 363d49c158..5e6eb73386 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -998,7 +998,8 @@ details::_http_request::_http_request(http::method mtd) : m_method(std::move(mtd)), m_initiated_response(0), m_server_context(), - m_cancellationToken(pplx::cancellation_token::none()) + m_cancellationToken(pplx::cancellation_token::none()), + m_http_version(http::http_version{0, 0}) { if(m_method.empty()) { @@ -1009,10 +1010,15 @@ details::_http_request::_http_request(http::method mtd) details::_http_request::_http_request(std::unique_ptr server_context) : m_initiated_response(0), m_server_context(std::move(server_context)), - m_cancellationToken(pplx::cancellation_token::none()) + m_cancellationToken(pplx::cancellation_token::none()), + m_http_version(http::http_version{0, 0}) { } +const http_version http_versions::HTTP_0_9 = { 0, 9 }; +const http_version http_versions::HTTP_1_0 = { 1, 0 }; +const http_version http_versions::HTTP_1_1 = { 1, 1 }; + #define _METHODS #define DAT(a,b) const method methods::a = b; #include "cpprest/details/http_constants.dat" diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 3fadebb03b..1a28a3ce6d 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -657,14 +657,32 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys // Get the version std::string http_version = http_path_and_version.substr(http_path_and_version.size() - VersionPortionSize + 1, VersionPortionSize - 2); + + auto m_request_impl = m_request._get_impl().get(); + web::http::http_version parsed_version = { 0, 0 }; + if (boost::starts_with(http_version, "HTTP/")) + { + std::istringstream version{ http_version.substr(5) }; + version >> parsed_version.major; + char dot; version >> dot; + version >> parsed_version.minor; + + m_request_impl->_set_http_version(parsed_version); + } + // if HTTP version is 1.0 then disable pipelining - if (http_version == "HTTP/1.0") + if (parsed_version == web::http::http_versions::HTTP_1_0) { m_close = true; } // Get the remote IP address - m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t(m_socket->remote_endpoint().address().to_string())); + boost::system::error_code socket_ec; + auto endpoint = m_socket->remote_endpoint(socket_ec); + if (!socket_ec) + { + m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t(endpoint.address().to_string())); + } return handle_headers(); } diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 9a0e257ef7..7d3cea203c 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -560,6 +560,8 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD m_msg.set_method(parse_request_method(m_request)); parse_http_headers(m_request->Headers, m_msg.headers()); + m_msg._get_impl()->_set_http_version({ (uint8_t)m_request->Version.MajorVersion, (uint8_t)m_request->Version.MinorVersion }); + // Retrieve the remote IP address std::vector remoteAddressBuffer(50); diff --git a/Release/tests/functional/http/listener/request_handler_tests.cpp b/Release/tests/functional/http/listener/request_handler_tests.cpp index 33f7d0ea85..3a1e135b13 100644 --- a/Release/tests/functional/http/listener/request_handler_tests.cpp +++ b/Release/tests/functional/http/listener/request_handler_tests.cpp @@ -448,6 +448,39 @@ TEST_FIXTURE(uri_address, test_leaks) listener.close().wait(); } +TEST_FIXTURE(uri_address, http_version) +{ + http_listener listener(U("http://localhost:45678/path1")); + listener.open().wait(); + + test_http_client::scoped_client client(U("http://localhost:45678")); + test_http_client * p_client = client.client(); + + volatile unsigned long requestCount = 0; + + listener.support(methods::GET, [&requestCount](http_request request) + { + const auto& httpVersion = request.http_version(); + + // All clients currently use HTTP/1.1 + VERIFY_IS_TRUE(httpVersion == http_versions::HTTP_1_1); + + os_utilities::interlocked_increment(&requestCount); + request.reply(status_codes::NoContent); + }); + + // Send a request to the listener + VERIFY_ARE_EQUAL(0, p_client->request(methods::GET, U("/path1"))); + + p_client->next_response().then([](test_response *p_response) + { + http_asserts::assert_test_response_equals(p_response, status_codes::NoContent); + }).wait(); + + VERIFY_IS_TRUE(requestCount >= 1); + listener.close().wait(); +} + TEST_FIXTURE(uri_address, remote_address) { http_listener listener(U("http://localhost:45678/path1")); @@ -460,7 +493,7 @@ TEST_FIXTURE(uri_address, remote_address) listener.support(methods::GET, [&requestCount](http_request request) { - const string_t& remoteAddr = request.get_remote_address(); + const string_t& remoteAddr = request.remote_address(); const string_t& localhost4 = string_t(U("127.0.0.1")); const string_t& localhost6 = string_t(U("::1")); From a159e4e7b5eb640a0a09eca8decff32827cb40be Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Thu, 25 Jan 2018 21:18:25 +0000 Subject: [PATCH 371/609] Fix VS2013 compilation errors (#678) * Revert explicitly defaulted move constructors and assignment operators (part of commit b0634729ae3ece059f5d727e6176f9bf8b9a0e77) to restore compatibility with VS2013 (fix #674) * Simplify and make consistent use of member typedefs in basic_istream and the type_parser hierarchy, which also fixes #675 * Restore EOL: Unix (seems to have been EOL: Mixed at commit 3e8dcf5b574fa7f23920de3166e03fee5bf5aae1) * Add comments explicitly indicating suboptimal code for VS2013 compat --- Release/include/cpprest/base_uri.h | 45 ++++++++++- Release/include/cpprest/streams.h | 123 ++++++++++++++++++----------- 2 files changed, 117 insertions(+), 51 deletions(-) diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index 1d2874a41b..b5fc8fcfd0 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -32,8 +32,32 @@ namespace web { uri_components(const uri_components &other) = default; uri_components & operator=(const uri_components &other) = default; - uri_components(uri_components &&other) = default; - uri_components & operator=(uri_components &&other) = default; + // This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped. + uri_components(uri_components &&other) CPPREST_NOEXCEPT : + m_scheme(std::move(other.m_scheme)), + m_host(std::move(other.m_host)), + m_user_info(std::move(other.m_user_info)), + m_path(std::move(other.m_path)), + m_query(std::move(other.m_query)), + m_fragment(std::move(other.m_fragment)), + m_port(other.m_port) + {} + + // This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped. + uri_components & operator=(uri_components &&other) CPPREST_NOEXCEPT + { + if (this != &other) + { + m_scheme = std::move(other.m_scheme); + m_host = std::move(other.m_host); + m_user_info = std::move(other.m_user_info); + m_path = std::move(other.m_path); + m_query = std::move(other.m_query); + m_fragment = std::move(other.m_fragment); + m_port = other.m_port; + } + return *this; + } _ASYNCRTIMP utility::string_t join(); @@ -195,12 +219,25 @@ namespace web { /// /// Move constructor. /// - uri(uri &&other) = default; + // This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped. + uri(uri &&other) CPPREST_NOEXCEPT : + m_uri(std::move(other.m_uri)), + m_components(std::move(other.m_components)) + {} /// /// Move assignment operator /// - uri & operator=(uri &&other) = default; + // This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped. + uri & operator=(uri &&other) CPPREST_NOEXCEPT + { + if (this != &other) + { + m_uri = std::move(other.m_uri); + m_components = std::move(other.m_components); + } + return *this; + } /// /// Get the scheme component of the URI as an encoded string. diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 60d5504e78..0903713497 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -24,7 +24,7 @@ namespace Concurrency { namespace streams template class basic_istream; namespace details { - template + template class basic_ostream_helper { public: @@ -95,8 +95,7 @@ namespace Concurrency { namespace streams class basic_ostream { public: - - typedef Concurrency::streams::char_traits traits; + typedef char_traits traits; typedef typename traits::int_type int_type; typedef typename traits::pos_type pos_type; typedef typename traits::off_type off_type; @@ -480,7 +479,8 @@ namespace Concurrency { namespace streams class _type_parser_base { public: - typedef typename ::concurrency::streams::char_traits::int_type int_type; + typedef char_traits traits; + typedef typename traits::int_type int_type; _type_parser_base() { } @@ -560,7 +560,7 @@ namespace Concurrency { namespace streams public: typedef char_traits traits; - typedef typename char_traits::int_type int_type; + typedef typename traits::int_type int_type; typedef typename traits::pos_type pos_type; typedef typename traits::off_type off_type; @@ -769,7 +769,7 @@ namespace Concurrency { namespace streams // Capture 'buffer' rather than 'helper' here due to VC++ 2010 limitations. auto buffer = helper()->m_buffer; - int_type req_async = ::concurrency::streams::char_traits::requires_async(); + int_type req_async = traits::requires_async(); std::shared_ptr<_read_helper> _locals = std::make_shared<_read_helper>(); @@ -785,7 +785,7 @@ namespace Concurrency { namespace streams auto update = [=](int_type ch) mutable { - if (ch == ::concurrency::streams::char_traits::eof()) return false; + if (ch == traits::eof()) return false; if (ch == delim) return false; _locals->outbuf[_locals->write_pos] = static_cast(ch); @@ -841,7 +841,7 @@ namespace Concurrency { namespace streams // Capture 'buffer' rather than 'helper' here due to VC++ 2010 limitations. concurrency::streams::streambuf buffer = helper()->m_buffer; - typename concurrency::streams::char_traits::int_type req_async = concurrency::streams::char_traits::requires_async(); + int_type req_async = traits::requires_async(); std::shared_ptr<_read_helper> _locals = std::make_shared<_read_helper>(); @@ -855,9 +855,9 @@ namespace Concurrency { namespace streams }); }; - auto update = [=](typename concurrency::streams::char_traits::int_type ch) mutable + auto update = [=](int_type ch) mutable { - if (ch == concurrency::streams::char_traits::eof()) return false; + if (ch == traits::eof()) return false; if (ch == '\n') return false; if (ch == '\r') { @@ -878,13 +878,12 @@ namespace Concurrency { namespace streams return true; }; - auto update_after_cr = [=] (typename concurrency::streams::char_traits::int_type ch) mutable -> pplx::task + auto update_after_cr = [=] (int_type ch) mutable -> pplx::task { - if (ch == concurrency::streams::char_traits::eof()) return pplx::task_from_result(false); + if (ch == traits::eof()) return pplx::task_from_result(false); if (ch == '\n') { - return buffer.bumpc().then([]( - typename concurrency::streams::char_traits::int_type) { return false; }); + return buffer.bumpc().then([](int_type) { return false; }); } return pplx::task_from_result(false); }; @@ -893,7 +892,7 @@ namespace Concurrency { namespace streams { while ( buffer.in_avail() > 0 ) { - typename concurrency::streams::char_traits::int_type ch; + int_type ch; if (_locals->saw_CR) { @@ -1123,9 +1122,9 @@ namespace Concurrency { namespace streams typedef basic_istream wistream; template -pplx::task concurrency::streams::_type_parser_base::_skip_whitespace(streams::streambuf buffer) +pplx::task _type_parser_base::_skip_whitespace(streams::streambuf buffer) { - int_type req_async = concurrency::streams::char_traits::requires_async(); + int_type req_async = traits::requires_async(); auto update = [=] (int_type ch) mutable { @@ -1168,7 +1167,7 @@ pplx::task concurrency::streams::_type_parser_base::_skip_whites template template -pplx::task concurrency::streams::_type_parser_base::_parse_input( +pplx::task _type_parser_base::_parse_input( concurrency::streams::streambuf buffer, AcceptFunctor accept_character, ExtractFunctor extract) @@ -1178,7 +1177,7 @@ pplx::task concurrency::streams::_type_parser_base::_parse auto update = [=] (pplx::task op) -> pplx::task { int_type ch = op.get(); - if (ch == concurrency::streams::char_traits::eof()) return pplx::task_from_result(false); + if (ch == traits::eof()) return pplx::task_from_result(false); bool accptd = accept_character(state, ch); if (!accptd) return pplx::task_from_result(false); @@ -1225,17 +1224,20 @@ pplx::task concurrency::streams::_type_parser_base::_parse template class type_parser> : public _type_parser_base { - typedef typename _type_parser_base::int_type int_type; + typedef _type_parser_base base; public: + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return concurrency::streams::_type_parser_base::template _parse_input, std::string>(buffer, _accept_char, _extract_result); + return base::template _parse_input, std::string>(buffer, _accept_char, _extract_result); } private: static bool _accept_char(std::shared_ptr> state, int_type ch) { - if ( ch == concurrency::streams::char_traits::eof() || isspace(ch)) return false; + if ( ch == traits::eof() || isspace(ch)) return false; state->push_back(CharType(ch)); return true; } @@ -1248,11 +1250,14 @@ class type_parser> : public _type_parser_ba template class type_parser : public _type_parser_base { + typedef _type_parser_base base; public: - typedef typename _type_parser_base::int_type int_type; + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::template _parse_input<_int64_state, int64_t>(buffer, _accept_char, _extract_result); + return base::template _parse_input<_int64_state, int64_t>(buffer, _accept_char, _extract_result); } private: struct _int64_state @@ -1266,7 +1271,7 @@ class type_parser : public _type_parser_base static bool _accept_char(std::shared_ptr<_int64_state> state, int_type ch) { - if ( ch == concurrency::streams::char_traits::eof()) return false; + if ( ch == traits::eof()) return false; if ( state->minus == 0 ) { // OK to find a sign. @@ -1487,11 +1492,14 @@ static pplx::task _extract_result(std::shared_ptr<_double_state class type_parser : public _type_parser_base { + typedef _type_parser_base base; public: - typedef typename _type_parser_base::int_type int_type; + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::template _parse_input<_double_state, double>(buffer, _accept_char, _extract_result); + return base::template _parse_input<_double_state, double>(buffer, _accept_char, _extract_result); } protected: }; @@ -1499,11 +1507,14 @@ class type_parser : public _type_parser_base template class type_parser : public _type_parser_base { + typedef _type_parser_base base; public: - typedef typename _type_parser_base::int_type int_type; + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::template _parse_input<_double_state, float>(buffer, _accept_char, _extract_result); + return base::template _parse_input<_double_state, float>(buffer, _accept_char, _extract_result); } protected: }; @@ -1512,11 +1523,14 @@ class type_parser : public _type_parser_base template class type_parser : public _type_parser_base { + typedef _type_parser_base base; public: - typedef typename _type_parser_base::int_type int_type; + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::template _parse_input<_uint64_state,uint64_t>(buffer, _accept_char, _extract_result); + return base::template _parse_input<_uint64_state,uint64_t>(buffer, _accept_char, _extract_result); } private: @@ -1552,11 +1566,14 @@ class type_parser : public _type_parser_base template class type_parser : public _type_parser_base { + typedef _type_parser_base base; public: - typedef typename _type_parser_base::int_type int_type; + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::template _parse_input<_bool_state,bool>(buffer, _accept_char, _extract_result); + return base::template _parse_input<_bool_state,bool>(buffer, _accept_char, _extract_result); } private: struct _bool_state @@ -1626,11 +1643,14 @@ class type_parser : public _type_parser_base template class type_parser : public _type_parser_base { - typedef typename concurrency::streams::streambuf::int_type int_type; + typedef _type_parser_base base; public: + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::_skip_whitespace(buffer).then( + return base::_skip_whitespace(buffer).then( [=](pplx::task op) -> pplx::task { op.wait(); @@ -1642,10 +1662,10 @@ class type_parser : public _type_parser_base { concurrency::streams::streambuf buf = buffer; return buf.bumpc().then( - [=](pplx::task::int_type> op) -> signed char + [=](pplx::task op) -> signed char { int_type val = op.get(); - if (val == concurrency::streams::char_traits::eof()) + if (val == traits::eof()) throw std::runtime_error("reached end-of-stream while constructing a value"); return static_cast(val); }); @@ -1655,11 +1675,14 @@ class type_parser : public _type_parser_base template class type_parser : public _type_parser_base { - typedef typename concurrency::streams::streambuf::int_type int_type; + typedef _type_parser_base base; public: + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::_skip_whitespace(buffer).then( + return base::_skip_whitespace(buffer).then( [=](pplx::task op) -> pplx::task { op.wait(); @@ -1671,10 +1694,10 @@ class type_parser : public _type_parser_base { concurrency::streams::streambuf buf = buffer; return buf.bumpc().then( - [=](pplx::task::int_type> op) -> unsigned char + [=](pplx::task op) -> unsigned char { int_type val = op.get(); - if (val == concurrency::streams::char_traits::eof()) + if (val == traits::eof()) throw std::runtime_error("reached end-of-stream while constructing a value"); return static_cast(val); }); @@ -1684,11 +1707,14 @@ class type_parser : public _type_parser_base template class type_parser : public _type_parser_base { - typedef typename concurrency::streams::streambuf::int_type int_type; + typedef _type_parser_base base; public: + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { - return _type_parser_base::_skip_whitespace(buffer).then( + return base::_skip_whitespace(buffer).then( [=](pplx::task op) -> pplx::task { op.wait(); @@ -1700,10 +1726,10 @@ class type_parser : public _type_parser_base { concurrency::streams::streambuf buf = buffer; return buf.bumpc().then( - [=](pplx::task::int_type> op) -> char + [=](pplx::task op) -> char { int_type val = op.get(); - if (val == concurrency::streams::char_traits::eof()) + if (val == traits::eof()) throw std::runtime_error("reached end-of-stream while constructing a value"); return char(val); }); @@ -1714,8 +1740,11 @@ class type_parser : public _type_parser_base template class type_parser>> : public _type_parser_base { - typedef typename concurrency::streams::streambuf::int_type int_type; + typedef _type_parser_base base; public: + typedef typename base::traits traits; + typedef typename base::int_type int_type; + static pplx::task parse(streams::streambuf buffer) { return _parse_input,std::basic_string>(buffer, _accept_char, _extract_result); @@ -1738,4 +1767,4 @@ class type_parser Date: Fri, 26 Jan 2018 18:14:50 +0000 Subject: [PATCH 372/609] Fix a regression in parsing an HTTP-Version string (#677) * Fix a regression in parsing an HTTP-Version string, pulling the parsing code out into http_version::from_string; add extra unit tests * Restore EOL: Unix * Remove dependency on locale from http_version member functions. Prefer UTF-8. --- Release/include/cpprest/http_msg.h | 11 +++++++ Release/src/http/common/http_msg.cpp | 31 ++++++++++++++++++- .../src/http/listener/http_server_asio.cpp | 12 ++----- .../http/listener/request_handler_tests.cpp | 23 ++++++++++++++ 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 6b49bc4960..00f58e1350 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -58,6 +58,17 @@ struct http_version inline bool operator>=(const http_version& other) const { return !(*this < other); } inline bool operator>(const http_version& other) const { return !(*this < other || *this == other); } inline bool operator<=(const http_version& other) const { return *this < other || *this == other; } + + /// + /// Creates http_version from an HTTP-Version string, "HTTP" "/" 1*DIGIT "." 1*DIGIT. + /// + /// Returns a http_version of {0, 0} if not successful. + static _ASYNCRTIMP http_version __cdecl from_string(const utility::string_t& http_version_string); + + /// + /// Returns the string representation of the http_version. + /// + _ASYNCRTIMP std::string to_utf8string() const; }; /// diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 5e6eb73386..459aff5609 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -254,6 +254,35 @@ void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers } +http_version __cdecl http_version::from_string(const utility::string_t& http_version_string) +{ + utility::istringstream_t str(http_version_string); + str.imbue(std::locale::classic()); + + utility::string_t http; std::getline(str, http, _XPLATSTR('/')); + unsigned int major = 0; str >> major; + utility::char_t dot = _XPLATSTR('\0'); str >> dot; + unsigned int minor = 0; str >> minor; + + // check no failure, fully consumed, and correct fixed text + if (!str.fail() && str.eof() && _XPLATSTR("HTTP") == http && _XPLATSTR('.') == dot) + { + return{ (uint8_t)major, (uint8_t)minor }; + } + return{ 0, 0 }; +} + +std::string http_version::to_utf8string() const +{ + std::string ret; + ret.reserve(8); + ret.append("HTTP/"); + ret.append(std::to_string(static_cast(major))); + ret.append("."); + ret.append(std::to_string(static_cast(minor))); + return ret; +} + static const utility::char_t * stream_was_set_explicitly = _XPLATSTR("A stream was set on the message and extraction is not possible"); static const utility::char_t * unsupported_charset = _XPLATSTR("Charset must be iso-8859-1, utf-8, utf-16, utf-16le, or utf-16be to be extracted."); @@ -1052,4 +1081,4 @@ const http_version http_versions::HTTP_1_1 = { 1, 1 }; #undef DAT #endif }} // namespace web::http - + diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 1a28a3ce6d..e7f9232816 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -659,16 +659,8 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys std::string http_version = http_path_and_version.substr(http_path_and_version.size() - VersionPortionSize + 1, VersionPortionSize - 2); auto m_request_impl = m_request._get_impl().get(); - web::http::http_version parsed_version = { 0, 0 }; - if (boost::starts_with(http_version, "HTTP/")) - { - std::istringstream version{ http_version.substr(5) }; - version >> parsed_version.major; - char dot; version >> dot; - version >> parsed_version.minor; - - m_request_impl->_set_http_version(parsed_version); - } + web::http::http_version parsed_version = web::http::http_version::from_string(utility::conversions::to_string_t(http_version)); + m_request_impl->_set_http_version(parsed_version); // if HTTP version is 1.0 then disable pipelining if (parsed_version == web::http::http_versions::HTTP_1_0) diff --git a/Release/tests/functional/http/listener/request_handler_tests.cpp b/Release/tests/functional/http/listener/request_handler_tests.cpp index 3a1e135b13..269a0e23b0 100644 --- a/Release/tests/functional/http/listener/request_handler_tests.cpp +++ b/Release/tests/functional/http/listener/request_handler_tests.cpp @@ -450,6 +450,29 @@ TEST_FIXTURE(uri_address, test_leaks) TEST_FIXTURE(uri_address, http_version) { + // formatting should succeed + VERIFY_IS_TRUE("HTTP/0.9" == http_versions::HTTP_0_9.to_utf8string()); + VERIFY_IS_TRUE("HTTP/1.0" == http_versions::HTTP_1_0.to_utf8string()); + VERIFY_IS_TRUE("HTTP/1.1" == http_versions::HTTP_1_1.to_utf8string()); + VERIFY_IS_TRUE("HTTP/12.3" == (http_version{ 12, 3 }).to_utf8string()); + // parsing should succeed + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/0.9")) == http_versions::HTTP_0_9); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/1.0")) == http_versions::HTTP_1_0); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/1.1")) == http_versions::HTTP_1_1); + VERIFY_IS_TRUE((http_version::from_string(U("HTTP/12.3")) == http_version{ 12, 3 })); + // parsing should fail + http_version unknown = { 0, 0 }; + VERIFY_IS_TRUE(http_version::from_string(U("http/12.3")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/12.3foo")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/12.")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/12")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/.3")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP/")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("HTTP")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("foo")) == unknown); + VERIFY_IS_TRUE(http_version::from_string(U("")) == unknown); + http_listener listener(U("http://localhost:45678/path1")); listener.open().wait(); From 1e4717e5aefb080bfc3edd3b9d6ca6e2546c0111 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 26 Jan 2018 11:52:35 -0800 Subject: [PATCH 373/609] Convert http_versions::from_string to use UTF-8 --- Release/include/cpprest/http_msg.h | 2 +- Release/src/http/common/http_msg.cpp | 10 +++---- .../http/listener/request_handler_tests.cpp | 28 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 00f58e1350..b85e98ff42 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -63,7 +63,7 @@ struct http_version /// Creates http_version from an HTTP-Version string, "HTTP" "/" 1*DIGIT "." 1*DIGIT. /// /// Returns a http_version of {0, 0} if not successful. - static _ASYNCRTIMP http_version __cdecl from_string(const utility::string_t& http_version_string); + static _ASYNCRTIMP http_version __cdecl from_string(const std::string& http_version_string); /// /// Returns the string representation of the http_version. diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 459aff5609..ad2c70e9d7 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -254,18 +254,18 @@ void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers } -http_version __cdecl http_version::from_string(const utility::string_t& http_version_string) +http_version __cdecl http_version::from_string(const std::string& http_version_string) { - utility::istringstream_t str(http_version_string); + std::stringstream str(http_version_string); str.imbue(std::locale::classic()); - utility::string_t http; std::getline(str, http, _XPLATSTR('/')); + std::string http; std::getline(str, http, '/'); unsigned int major = 0; str >> major; - utility::char_t dot = _XPLATSTR('\0'); str >> dot; + char dot = '\0'; str >> dot; unsigned int minor = 0; str >> minor; // check no failure, fully consumed, and correct fixed text - if (!str.fail() && str.eof() && _XPLATSTR("HTTP") == http && _XPLATSTR('.') == dot) + if (!str.fail() && str.eof() && "HTTP" == http && '.' == dot) { return{ (uint8_t)major, (uint8_t)minor }; } diff --git a/Release/tests/functional/http/listener/request_handler_tests.cpp b/Release/tests/functional/http/listener/request_handler_tests.cpp index 269a0e23b0..74137193ae 100644 --- a/Release/tests/functional/http/listener/request_handler_tests.cpp +++ b/Release/tests/functional/http/listener/request_handler_tests.cpp @@ -456,22 +456,22 @@ TEST_FIXTURE(uri_address, http_version) VERIFY_IS_TRUE("HTTP/1.1" == http_versions::HTTP_1_1.to_utf8string()); VERIFY_IS_TRUE("HTTP/12.3" == (http_version{ 12, 3 }).to_utf8string()); // parsing should succeed - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/0.9")) == http_versions::HTTP_0_9); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/1.0")) == http_versions::HTTP_1_0); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/1.1")) == http_versions::HTTP_1_1); - VERIFY_IS_TRUE((http_version::from_string(U("HTTP/12.3")) == http_version{ 12, 3 })); + VERIFY_IS_TRUE(http_version::from_string("HTTP/0.9") == http_versions::HTTP_0_9); + VERIFY_IS_TRUE(http_version::from_string("HTTP/1.0") == http_versions::HTTP_1_0); + VERIFY_IS_TRUE(http_version::from_string("HTTP/1.1") == http_versions::HTTP_1_1); + VERIFY_IS_TRUE((http_version::from_string("HTTP/12.3") == http_version{ 12, 3 })); // parsing should fail http_version unknown = { 0, 0 }; - VERIFY_IS_TRUE(http_version::from_string(U("http/12.3")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/12.3foo")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/12.")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/12")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/.3")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP/")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("HTTP")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("foo")) == unknown); - VERIFY_IS_TRUE(http_version::from_string(U("")) == unknown); + VERIFY_IS_TRUE(http_version::from_string("http/12.3") == unknown); + VERIFY_IS_TRUE(http_version::from_string("HTTP/12.3foo") == unknown); + VERIFY_IS_TRUE(http_version::from_string("HTTP/12.") == unknown); + VERIFY_IS_TRUE(http_version::from_string("HTTP/12") == unknown); + VERIFY_IS_TRUE(http_version::from_string("HTTP/.3") == unknown); + VERIFY_IS_TRUE(http_version::from_string("HTTP/") == unknown); + VERIFY_IS_TRUE(http_version::from_string("HTTP") == unknown); + VERIFY_IS_TRUE(http_version::from_string("HTTP") == unknown); + VERIFY_IS_TRUE(http_version::from_string("foo") == unknown); + VERIFY_IS_TRUE(http_version::from_string("") == unknown); http_listener listener(U("http://localhost:45678/path1")); listener.open().wait(); From fea848e2a77563cf2a6f28f8eab396fd6e787fbf Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 6 Feb 2018 15:23:26 -0800 Subject: [PATCH 374/609] Push version number to 2.10.2 --- Build/version.props | 2 +- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Build/version.props b/Build/version.props index cbf33ac51b..81b45b0316 100644 --- a/Build/version.props +++ b/Build/version.props @@ -4,7 +4,7 @@ cpprest 2 10 - 1 + 2 $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index ff775ed43e..3e0871c99c 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 1) +set(CPPREST_VERSION_REVISION 2) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index 2324dddddb..f3d9602e67 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -3,9 +3,9 @@ * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * */ -#define CPPREST_VERSION_REVISION 1 +#define CPPREST_VERSION_REVISION 2 #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) - + From f3ec72364703eab8ec8dfae41d50cb63c700933b Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Wed, 7 Feb 2018 18:22:41 +0000 Subject: [PATCH 375/609] Don't use the ``U()`` preprocessor macro in public headers (#693) * Don't use the ``U()`` preprocessor macro in public headers, in order to work when ``_TURN_OFF_PLATFORM_STRING`` is defined. * Add the explanation of the 'U' macro (and the use of '_TURN_OFF_PLATFORM_STRING') taken from the FAQ, close to its definition. --- Release/include/cpprest/details/basic_types.h | 3 +++ Release/include/cpprest/details/http_helpers.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/details/basic_types.h b/Release/include/cpprest/details/basic_types.h index 36aad71b98..eadba01684 100644 --- a/Release/include/cpprest/details/basic_types.h +++ b/Release/include/cpprest/details/basic_types.h @@ -80,6 +80,9 @@ typedef std::stringstream stringstream_t; #endif // endif _UTF16_STRINGS #ifndef _TURN_OFF_PLATFORM_STRING +// The 'U' macro can be used to create a string or character literal of the platform type, i.e. utility::char_t. +// If you are using a library causing conflicts with 'U' macro, it can be turned off by defining the macro +// '_TURN_OFF_PLATFORM_STRING' before including the C++ REST SDK header files, and e.g. use '_XPLATSTR' instead. #define U(x) _XPLATSTR(x) #endif // !_TURN_OFF_PLATFORM_STRING diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 05db40243a..2d2c1b6091 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -58,11 +58,11 @@ namespace details static compression_algorithm to_compression_algorithm(const utility::string_t& alg) { - if (U("gzip") == alg) + if (_XPLATSTR("gzip") == alg) { return compression_algorithm::gzip; } - else if (U("deflate") == alg) + else if (_XPLATSTR("deflate") == alg) { return compression_algorithm::deflate; } From 4cc30c7b631d426ebeb3f2d9bee94a3c3a20681f Mon Sep 17 00:00:00 2001 From: Marcin Buchwald Date: Fri, 16 Feb 2018 23:37:33 +0100 Subject: [PATCH 376/609] No need for ostringstream here (#700) --- Release/samples/BlackJack/BlackJack_Server/Dealer.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp b/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp index b03cab9e26..7cb81d5bc2 100644 --- a/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp +++ b/Release/samples/BlackJack/BlackJack_Server/Dealer.cpp @@ -47,12 +47,9 @@ BlackJackDealer::BlackJackDealer(utility::string_t url) : m_listener(url) m_listener.support(methods::PUT, std::bind(&BlackJackDealer::handle_put, this, std::placeholders::_1)); m_listener.support(methods::POST, std::bind(&BlackJackDealer::handle_post, this, std::placeholders::_1)); m_listener.support(methods::DEL, std::bind(&BlackJackDealer::handle_delete, this, std::placeholders::_1)); - - utility::ostringstream_t nextIdString; - nextIdString << nextId; std::shared_ptr tbl = std::make_shared(nextId, 8, 6); - s_tables[nextIdString.str()] = tbl; + s_tables[conversions::to_string_t(std::to_string(nextId))] = tbl; nextId += 1; } From b024470efc6b12f0bba82d825cc487c980beac13 Mon Sep 17 00:00:00 2001 From: Jan Nils Ferner Date: Thu, 22 Feb 2018 12:21:56 +0100 Subject: [PATCH 377/609] Fix XML in comment (#705) --- Release/include/cpprest/json.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index f4987f5c21..07c5450243 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -266,7 +266,7 @@ namespace json /// /// This overload has O(n) performance because it tries to determine if /// specified string has characters that should be properly escaped in JSON. - /// + /// static _ASYNCRTIMP value __cdecl string(utility::string_t value); /// From e0d42b5d4278aac0b4d89f2bb5177b7bdaccba70 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Fri, 27 Apr 2018 11:42:43 +0100 Subject: [PATCH 378/609] Fix compilation failure with ``CPPREST_FORCE_PPLX=1`` (resolves #734) (#746) * Make sure internal _do_while is in the same namespace as other pplx tasks implementation details (resolves #734) * Reformat astreambuf.h line endings --- Release/include/cpprest/astreambuf.h | 14 +++++++++++--- Release/include/cpprest/streams.h | 10 +++++----- Release/tests/functional/streams/istream_tests.cpp | 2 +- .../tests/functional/streams/memstream_tests.cpp | 14 +++++++------- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Release/include/cpprest/astreambuf.h b/Release/include/cpprest/astreambuf.h index 642f0738dd..baff9a934d 100644 --- a/Release/include/cpprest/astreambuf.h +++ b/Release/include/cpprest/astreambuf.h @@ -22,7 +22,11 @@ #include "cpprest/details/basic_types.h" #include "cpprest/asyncrt_utils.h" -namespace Concurrency +#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX +namespace Concurrency // since namespace pplx = Concurrency +#else +namespace pplx +#endif { namespace details { @@ -32,12 +36,16 @@ namespace Concurrency pplx::task first = func(); return first.then([=](bool guard) -> pplx::task { if (guard) - return Concurrency::details::_do_while(func); + return pplx::details::_do_while(func); else return first; }); } } +} + +namespace Concurrency +{ /// Library for asynchronous streams. namespace streams @@ -1201,4 +1209,4 @@ namespace streams }} - + diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 0903713497..75deb8fc59 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -801,7 +801,7 @@ namespace Concurrency { namespace streams return true; }; - auto loop = Concurrency::details::_do_while([=]() mutable -> pplx::task + auto loop = pplx::details::_do_while([=]() mutable -> pplx::task { while (buffer.in_avail() > 0) { @@ -888,7 +888,7 @@ namespace Concurrency { namespace streams return pplx::task_from_result(false); }; - auto loop = Concurrency::details::_do_while([=]() mutable -> pplx::task + auto loop = pplx::details::_do_while([=]() mutable -> pplx::task { while ( buffer.in_avail() > 0 ) { @@ -968,7 +968,7 @@ namespace Concurrency { namespace streams }); }; - auto loop = Concurrency::details::_do_while(copy_to_target); + auto loop = pplx::details::_do_while(copy_to_target); return loop.then([=](bool) mutable -> size_t { @@ -1142,7 +1142,7 @@ pplx::task _type_parser_base::_skip_whitespace(streams::streambu return false; }; - auto loop = Concurrency::details::_do_while([=]() mutable -> pplx::task + auto loop = pplx::details::_do_while([=]() mutable -> pplx::task { while (buffer.in_avail() > 0) { @@ -1217,7 +1217,7 @@ pplx::task _type_parser_base::_parse_input( return _skip_whitespace(buffer).then([=](pplx::task op) -> pplx::task { op.wait(); - return Concurrency::details::_do_while(peek_char).then(finish); + return pplx::details::_do_while(peek_char).then(finish); }); } diff --git a/Release/tests/functional/streams/istream_tests.cpp b/Release/tests/functional/streams/istream_tests.cpp index 63995fc8c3..db12390c57 100644 --- a/Release/tests/functional/streams/istream_tests.cpp +++ b/Release/tests/functional/streams/istream_tests.cpp @@ -714,7 +714,7 @@ TEST(fstream_read_to_end_3) else return pplx::task_from_result(false); }; - Concurrency::details::_do_while([=]()-> pplx::task { + pplx::details::_do_while([=]()-> pplx::task { return stream.read().then(lambda1); }).wait(); diff --git a/Release/tests/functional/streams/memstream_tests.cpp b/Release/tests/functional/streams/memstream_tests.cpp index 1e20facf3e..5395cf2cf7 100644 --- a/Release/tests/functional/streams/memstream_tests.cpp +++ b/Release/tests/functional/streams/memstream_tests.cpp @@ -48,7 +48,7 @@ void streambuf_putc(StreamBufferType& wbuf) size_t count = 10; auto seg2 = [&count](typename StreamBufferType::int_type ) { return (--count > 0); }; auto seg1 = [&s,&wbuf, seg2]() { return wbuf.putc(s[0]).then(seg2); }; - Concurrency::details::_do_while(seg1).wait(); + pplx::details::_do_while(seg1).wait(); VERIFY_ARE_EQUAL(s.size() + 10, wbuf.in_avail()); @@ -83,7 +83,7 @@ void streambuf_putc(concurrency::streams::rawptr_buffer& wbuf) size_t count = 10; auto seg2 = [&count](typename StreamBufferType::int_type ) { return (--count > 0); }; auto seg1 = [&s,&wbuf, seg2]() { return wbuf.putc(s[0]).then(seg2); }; - Concurrency::details::_do_while(seg1).wait(); + pplx::details::_do_while(seg1).wait(); VERIFY_ARE_EQUAL(s.size() + 10, wbuf.block().size()); @@ -119,7 +119,7 @@ void streambuf_putc(concurrency::streams::container_buffer& wbuf size_t count = 10; auto seg2 = [&count](typename StreamBufferType::int_type ) { return (--count > 0); }; auto seg1 = [&s,&wbuf, seg2]() { return wbuf.putc(s[0]).then(seg2); }; - Concurrency::details::_do_while(seg1).wait(); + pplx::details::_do_while(seg1).wait(); VERIFY_ARE_EQUAL(s.size() + 10, wbuf.collection().size()); @@ -150,7 +150,7 @@ void streambuf_putn(StreamBufferType& wbuf) int count = 10; auto seg2 = [&count](size_t ) { return (--count > 0); }; auto seg1 = [&s,&wbuf, seg2]() { return wbuf.putn_nocopy(s.data(), s.size()).then(seg2); }; - Concurrency::details::_do_while(seg1).wait(); + pplx::details::_do_while(seg1).wait(); VERIFY_ARE_EQUAL(s.size() * 12, wbuf.in_avail()); wbuf.close().get(); @@ -180,7 +180,7 @@ void streambuf_putn(concurrency::streams::rawptr_buffer& wbuf) int count = 10; auto seg2 = [&count](size_t ) { return (--count > 0); }; auto seg1 = [&s,&wbuf, seg2]() { return wbuf.putn_nocopy(s.data(), s.size()).then(seg2); }; - Concurrency::details::_do_while(seg1).wait(); + pplx::details::_do_while(seg1).wait(); wbuf.close().get(); VERIFY_IS_FALSE(wbuf.can_write()); @@ -209,7 +209,7 @@ void streambuf_putn(concurrency::streams::container_buffer& wbuf int count = 10; auto seg2 = [&count](size_t ) { return (--count > 0); }; auto seg1 = [&s,&wbuf, seg2]() { return wbuf.putn_nocopy(s.data(), s.size()).then(seg2); }; - Concurrency::details::_do_while(seg1).wait(); + pplx::details::_do_while(seg1).wait(); wbuf.close().get(); VERIFY_IS_FALSE(wbuf.can_write()); @@ -1935,7 +1935,7 @@ void IStreamTest11() auto seg2 = [&ch](int val) { return (val != -1) && (++ch <= 'z'); }; auto seg1 = [=,&ch,&rbuf]() { return rbuf.putc(ch).then(seg2); }; - Concurrency::details::_do_while(seg1).wait(); + pplx::details::_do_while(seg1).wait(); VERIFY_ARE_EQUAL(26u, rbuf.in_avail()); From 3439ea40412542ed3034670022db714f37abe9ae Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Fri, 27 Apr 2018 16:52:39 +0100 Subject: [PATCH 379/609] Fix to work with commit 1e4717e5aefb080bfc3edd3b9d6ca6e2546c0111 (#681) --- Release/src/http/listener/http_server_asio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index e7f9232816..78193fa3e2 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -659,7 +659,7 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys std::string http_version = http_path_and_version.substr(http_path_and_version.size() - VersionPortionSize + 1, VersionPortionSize - 2); auto m_request_impl = m_request._get_impl().get(); - web::http::http_version parsed_version = web::http::http_version::from_string(utility::conversions::to_string_t(http_version)); + web::http::http_version parsed_version = web::http::http_version::from_string(http_version); m_request_impl->_set_http_version(parsed_version); // if HTTP version is 1.0 then disable pipelining From 175d0ac77c11be53f3e66f85b5791e3a4d793500 Mon Sep 17 00:00:00 2001 From: VZ Date: Sun, 6 May 2018 01:52:15 +0200 Subject: [PATCH 380/609] Require at least CMake 3.1 due to use of target_sources (#752) target_sources() is only available since this version and this avoids CMake Error at src/CMakeLists.txt:92 (target_sources): Unknown CMake command "target_sources". when using CMake 3.0, for example. Closes #633. --- Release/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 3e0871c99c..5362d1cd9e 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -1,5 +1,5 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0) -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.1) if(POLICY CMP0042) cmake_policy(SET CMP0042 NEW) # use MACOSX_RPATH endif() From 68b0ddf52cf1d8364b64900e8cf1a0629f5d3bef Mon Sep 17 00:00:00 2001 From: Thomas Barnekov <37448419+tbarnekov@users.noreply.github.com> Date: Fri, 18 May 2018 04:53:21 +0200 Subject: [PATCH 381/609] Fixed issue with Automatic Proxy detection when using WPAD on Windows 8.1 or higher (#722) --- .../src/http/client/http_client_winhttp.cpp | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 1d17db5899..2417859956 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -431,37 +431,40 @@ class winhttp_client : public _http_client_communicator #ifndef CPPREST_TARGET_XP if (IsWindows8Point1OrGreater()) { + // Windows 8.1 and newer supports automatic proxy discovery and auto-fallback to IE proxy settings access_type = WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY; } - - // However, if it is not configured... - proxy_info proxyDefault; - if(!WinHttpGetDefaultProxyConfiguration(&proxyDefault) || - proxyDefault.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY) + else { - // ... then try to fall back on the default WinINET proxy, as - // recommended for the desktop applications (if we're not - // running under a user account, the function below will just - // fail, so there is no real need to check for this explicitly) - if(WinHttpGetIEProxyConfigForCurrentUser(&proxyIE)) + // However, if it is not configured... + proxy_info proxyDefault; + if (!WinHttpGetDefaultProxyConfiguration(&proxyDefault) || + proxyDefault.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY) { - if(proxyIE.fAutoDetect) - { - m_proxy_auto_config = true; - } - else if(proxyIE.lpszAutoConfigUrl) + // ... then try to fall back on the default WinINET proxy, as + // recommended for the desktop applications (if we're not + // running under a user account, the function below will just + // fail, so there is no real need to check for this explicitly) + if (WinHttpGetIEProxyConfigForCurrentUser(&proxyIE)) { - m_proxy_auto_config = true; - m_proxy_auto_config_url = proxyIE.lpszAutoConfigUrl; - } - else if(proxyIE.lpszProxy) - { - access_type = WINHTTP_ACCESS_TYPE_NAMED_PROXY; - proxy_name = proxyIE.lpszProxy; - - if(proxyIE.lpszProxyBypass) + if (proxyIE.fAutoDetect) { - proxy_bypass = proxyIE.lpszProxyBypass; + m_proxy_auto_config = true; + } + else if (proxyIE.lpszAutoConfigUrl) + { + m_proxy_auto_config = true; + m_proxy_auto_config_url = proxyIE.lpszAutoConfigUrl; + } + else if (proxyIE.lpszProxy) + { + access_type = WINHTTP_ACCESS_TYPE_NAMED_PROXY; + proxy_name = proxyIE.lpszProxy; + + if (proxyIE.lpszProxyBypass) + { + proxy_bypass = proxyIE.lpszProxyBypass; + } } } } @@ -1122,10 +1125,10 @@ class winhttp_client : public _http_client_communicator try { web::uri current_uri(get_request_url(hRequestHandle)); - is_redirect = p_request_context->m_request.absolute_uri().to_string() != current_uri.to_string(); + is_redirect = p_request_context->m_request.absolute_uri().to_string() != current_uri.to_string(); } catch (const std::exception&) {} - + // If we have been redirected, then WinHttp needs the proxy credentials again to make the next request leg (which may be on a different server) if (is_redirect || !p_request_context->m_proxy_authentication_tried) { From 81442344caac03d307131069876c02018b5d34e8 Mon Sep 17 00:00:00 2001 From: Robert Andrzejuk Date: Tue, 17 Jul 2018 22:33:38 +0200 Subject: [PATCH 382/609] Fix for compilation with MSVC permissive- (#809) Related Visual Studio issue: https://developercommunity.visualstudio.com/content/problem/238445/template-class-cant-access-protected-member-when-c.html Problem is with code compiling with /permissive-, so the template functions are affected by this issue. --- Release/include/cpprest/streams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 75deb8fc59..5a46c7f077 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -1747,7 +1747,7 @@ class type_parser parse(streams::streambuf buffer) { - return _parse_input,std::basic_string>(buffer, _accept_char, _extract_result); + return base::_parse_input,std::basic_string>(buffer, _accept_char, _extract_result); } private: From 3839196d551abc79191be81e86bcfaa31dba80eb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Tue, 17 Jul 2018 13:34:38 -0700 Subject: [PATCH 383/609] Fix test issues under /permissive- --- Release/include/cpprest/streams.h | 3 ++- Release/tests/functional/websockets/CMakeLists.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 5a46c7f077..cb7cd4d0ea 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -577,7 +577,8 @@ namespace Concurrency { namespace streams /// The data type of the basic element of the stream. /// /// A stream buffer. - basic_istream(streams::streambuf buffer) : m_helper(std::make_shared>(buffer)) + template + basic_istream(streams::streambuf buffer) : m_helper(std::make_shared>(std::move(buffer))) { _verify_and_throw(details::_in_streambuf_msg); } diff --git a/Release/tests/functional/websockets/CMakeLists.txt b/Release/tests/functional/websockets/CMakeLists.txt index 889a4e0484..c8efb77ca1 100644 --- a/Release/tests/functional/websockets/CMakeLists.txt +++ b/Release/tests/functional/websockets/CMakeLists.txt @@ -31,4 +31,5 @@ if (NOT CPPREST_EXCLUDE_WEBSOCKETS) if(NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") target_link_libraries(websocketsclient_test PRIVATE websockettest_utilities) endif() + target_include_directories(websocketsclient_test PRIVATE utilities) endif() From 1d8be69c58e474e891084c15a35ad6c153649834 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 20 Jul 2018 16:09:48 -0700 Subject: [PATCH 384/609] Add root CMakeLists.txt --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..c66d502345 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.0) +project(cpprestsdk-root NONE) + +add_subdirectory(Release) From 48189bd460e08919befffe18cb239ecd8e5ad228 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 11 Jul 2018 03:27:33 -0700 Subject: [PATCH 385/609] Do not fail on unrecognized content encoding (such as chunked) when compression is enabled. --- .../include/cpprest/details/http_helpers.h | 2 + Release/src/http/client/http_client.cpp | 38 ++++++++++ Release/src/http/client/http_client_asio.cpp | 26 ++----- Release/src/http/client/http_client_impl.h | 9 +++ .../src/http/client/http_client_winhttp.cpp | 37 +++------- .../http/client/request_helper_tests.cpp | 72 +++++++++++++++++++ 6 files changed, 138 insertions(+), 46 deletions(-) diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 2d2c1b6091..596ac9efaa 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -70,6 +70,8 @@ namespace details return compression_algorithm::invalid; } + static utility::string_t known_algorithms() { return _XPLATSTR("deflate, gzip"); } + _ASYNCRTIMP static bool __cdecl is_supported(); _ASYNCRTIMP stream_decompressor(compression_algorithm alg); diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 164bec3f48..fdaca8f151 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -96,6 +96,44 @@ void request_context::report_exception(std::exception_ptr exceptionPtr) finish(); } +bool request_context::handle_content_encoding_compression() +{ + if (web::http::details::compression::stream_decompressor::is_supported() && m_http_client->client_config().request_compressed_response()) + { + // If the response body is compressed we will read the encoding header and create a decompressor object which will later decompress the body + auto&& headers = m_response.headers(); + auto it_ce = headers.find(web::http::header_names::content_encoding); + if (it_ce != headers.end()) + { + auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(it_ce->second); + + if (alg != web::http::details::compression::compression_algorithm::invalid) + { + m_decompressor = std::make_unique(alg); + } + else + { + report_exception( + http_exception("Unsupported compression algorithm in the Content-Encoding header: " + + utility::conversions::to_utf8string(it_ce->second))); + return false; + } + } + } + return true; +} + +void request_context::add_accept_encoding_header(utility::string_t& headers) const +{ + // Add the header needed to request a compressed response if supported on this platform and it has been specified in the config + if (web::http::details::compression::stream_decompressor::is_supported() && m_http_client->client_config().request_compressed_response()) + { + headers.append(U("Accept-Encoding: ")); + headers.append(web::http::details::compression::stream_decompressor::known_algorithms()); + headers.append(U("\r\n")); + } +} + concurrency::streams::streambuf request_context::_get_readbuffer() { auto instream = m_request.body(); diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 4ba3e0851b..600bf26605 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -718,11 +718,7 @@ class asio_context : public request_context, public std::enable_shared_from_this extra_headers.append(ctx->generate_basic_auth_header()); } - // Add the header needed to request a compressed response if supported on this platform and it has been specified in the config - if (web::http::details::compression::stream_decompressor::is_supported() && ctx->m_http_client->client_config().request_compressed_response()) - { - extra_headers.append("Accept-Encoding: deflate, gzip\r\n"); - } + ctx->add_accept_encoding_header(extra_headers); // Check user specified transfer-encoding. std::string transferencoding; @@ -1240,26 +1236,18 @@ class asio_context : public request_context, public std::enable_shared_from_this m_response.headers().add(utility::conversions::to_string_t(std::move(name)), utility::conversions::to_string_t(std::move(value))); } } - complete_headers(); m_content_length = std::numeric_limits::max(); // Without Content-Length header, size should be same as TCP stream - set it size_t max. m_response.headers().match(header_names::content_length, m_content_length); - utility::string_t content_encoding; - if(web::http::details::compression::stream_decompressor::is_supported() && m_response.headers().match(header_names::content_encoding, content_encoding)) + if (!this->handle_content_encoding_compression()) { - auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(content_encoding); - - if (alg != web::http::details::compression::compression_algorithm::invalid) - { - m_decompressor = utility::details::make_unique(alg); - } - else - { - report_exception(std::runtime_error("Unsupported compression algorithm in the Content Encoding header: " + utility::conversions::to_utf8string(content_encoding))); - } + // false indicates report_exception was called + return; } + complete_headers(); + // Check for HEAD requests and status codes which cannot contain a // message body in HTTP/1.1 (see 3.3.3/1 of the RFC 7230). // @@ -1661,8 +1649,6 @@ class asio_context : public request_context, public std::enable_shared_from_this boost::asio::streambuf m_body_buf; std::shared_ptr m_connection; - std::unique_ptr m_decompressor; - #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) bool m_openssl_failed; #endif diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h index b292323ee0..4e47687aa4 100644 --- a/Release/src/http/client/http_client_impl.h +++ b/Release/src/http/client/http_client_impl.h @@ -70,6 +70,13 @@ class request_context report_exception(std::make_exception_ptr(e)); } + /// Set m_decompressor based on the response headers, or call report_exception + /// false on failure + bool handle_content_encoding_compression(); + + /// Append an Accept-Encoding header if requested by the http_client settings + void add_accept_encoding_header(utility::string_t& headers) const; + concurrency::streams::streambuf _get_writebuffer(); // Reference to the http_client implementation. @@ -88,6 +95,8 @@ class request_context // Registration for cancellation notification if enabled. pplx::cancellation_token_registration m_cancellationRegistration; + std::unique_ptr m_decompressor; + protected: request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request); diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 2417859956..8f9b2b3146 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -245,7 +245,6 @@ class winhttp_request_context : public request_context // This self reference will keep us alive until finish() is called. std::shared_ptr m_self_reference; memory_holder m_body_data; - std::unique_ptr decompressor; virtual void cleanup() { @@ -733,15 +732,13 @@ class winhttp_client : public _http_client_communicator } } - if(web::http::details::compression::stream_decompressor::is_supported() && client_config().request_compressed_response()) - { - msg.headers().add(web::http::header_names::accept_encoding, U("deflate, gzip")); - } + utility::string_t flattened_headers = web::http::details::flatten_http_headers(msg.headers()); + + winhttp_context->add_accept_encoding_header(flattened_headers); // Add headers. - if(!msg.headers().empty()) + if(!flattened_headers.empty()) { - const utility::string_t flattened_headers = web::http::details::flatten_http_headers(msg.headers()); if(!WinHttpAddRequestHeaders( winhttp_context->m_request_handle, flattened_headers.c_str(), @@ -1371,22 +1368,10 @@ class winhttp_client : public _http_client_communicator } } - // If the response body is compressed we will read the encoding header and create a decompressor object which will later decompress the body - utility::string_t encoding; - if (web::http::details::compression::stream_decompressor::is_supported() && response.headers().match(web::http::header_names::content_encoding, encoding)) + if (!p_request_context->handle_content_encoding_compression()) { - auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(encoding); - - if (alg != web::http::details::compression::compression_algorithm::invalid) - { - p_request_context->decompressor = std::make_unique(alg); - } - else - { - utility::string_t error = U("Unsupported compression algorithm in the Content Encoding header: "); - error += encoding; - p_request_context->report_exception(http_exception(error)); - } + // false indicates report_exception was called + return; } // Signal that the headers are available. @@ -1417,7 +1402,7 @@ class winhttp_client : public _http_client_communicator if(num_bytes > 0) { - if (p_request_context->decompressor) + if (p_request_context->m_decompressor) { // Decompression is too slow to reliably do on this callback. Therefore we need to store it now in order to decompress it at a later stage in the flow. // However, we want to eventually use the writebuf to store the decompressed body. Therefore we'll store the compressed body as an internal allocation in the request_context @@ -1486,11 +1471,11 @@ class winhttp_client : public _http_client_communicator auto writebuf = p_request_context->_get_writebuffer(); // If we have compressed data it is stored in the local allocation of the p_request_context. We will store the decompressed buffer in the external allocation of the p_request_context. - if (p_request_context->decompressor) + if (p_request_context->m_decompressor) { - web::http::details::compression::data_buffer decompressed = p_request_context->decompressor->decompress(p_request_context->m_body_data.get(), bytesRead); + web::http::details::compression::data_buffer decompressed = p_request_context->m_decompressor->decompress(p_request_context->m_body_data.get(), bytesRead); - if (p_request_context->decompressor->has_error()) + if (p_request_context->m_decompressor->has_error()) { p_request_context->report_exception(std::runtime_error("Failed to decompress the response body")); return; diff --git a/Release/tests/functional/http/client/request_helper_tests.cpp b/Release/tests/functional/http/client/request_helper_tests.cpp index cf7147ecb3..624dff19e2 100644 --- a/Release/tests/functional/http/client/request_helper_tests.cpp +++ b/Release/tests/functional/http/client/request_helper_tests.cpp @@ -30,6 +30,78 @@ namespace tests { namespace functional { namespace http { namespace client { SUITE(request_helper_tests) { +TEST_FIXTURE(uri_address, do_not_fail_on_content_encoding_when_not_requested) +{ + test_http_server::scoped_server scoped(m_uri); + auto& server = *scoped.server(); + http_client client(m_uri); + + server.next_request().then([](test_request *p_request) { + p_request->reply(200, U("OK"), { {header_names::content_encoding, U("chunked")} }); + }); + + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::OK); +} + +TEST_FIXTURE(uri_address, fail_on_content_encoding_if_unsupported) +{ + if (web::http::details::compression::stream_compressor::is_supported()) + { + test_http_server::scoped_server scoped(m_uri); + auto& server = *scoped.server(); + http_client_config config; + config.set_request_compressed_response(true); + http_client client(m_uri, config); + + server.next_request().then([](test_request *p_request) { + p_request->reply(200, U("OK"), { {header_names::content_encoding, U("unsupported-algorithm")} }); + }); + + VERIFY_THROWS(client.request(methods::GET).get(), web::http::http_exception); + } +} + +TEST_FIXTURE(uri_address, send_accept_encoding) +{ + if (web::http::details::compression::stream_compressor::is_supported()) + { + test_http_server::scoped_server scoped(m_uri); + auto& server = *scoped.server(); + http_client_config config; + config.set_request_compressed_response(true); + http_client client(m_uri, config); + + std::atomic found_accept_encoding = false; + + server.next_request().then([&found_accept_encoding](test_request *p_request) { + found_accept_encoding = p_request->m_headers.find(header_names::accept_encoding) != p_request->m_headers.end(); + p_request->reply(200, U("OK")); + }); + + client.request(methods::GET).get(); + + VERIFY_IS_TRUE(found_accept_encoding); + } +} + +TEST_FIXTURE(uri_address, do_not_send_accept_encoding) +{ + test_http_server::scoped_server scoped(m_uri); + auto& server = *scoped.server(); + http_client client(m_uri); + + std::atomic found_accept_encoding = true; + + server.next_request().then([&found_accept_encoding](test_request *p_request) { + found_accept_encoding = p_request->m_headers.find(header_names::accept_encoding) != p_request->m_headers.end(); + p_request->reply(200, U("OK")); + }); + + client.request(methods::GET).get(); + + VERIFY_IS_FALSE(found_accept_encoding); +} + TEST_FIXTURE(uri_address, compress_and_decompress) { if (web::http::details::compression::stream_compressor::is_supported()) From aa4065bd24aff94d790b31c4e11115359d8666bf Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 1 Aug 2018 02:01:01 -0700 Subject: [PATCH 386/609] Delete open() from _http_client_communicator (#819) * Delete open() from _http_client_communicator and move its functionality into WinHTTP, as that is the only backend using that thing. * Some CR comments from Robert. --- Release/src/http/client/http_client.cpp | 67 +++++-------------- Release/src/http/client/http_client_asio.cpp | 2 - Release/src/http/client/http_client_impl.h | 15 ++--- .../src/http/client/http_client_winhttp.cpp | 31 ++++++++- Release/src/http/client/http_client_winrt.cpp | 6 -- 5 files changed, 50 insertions(+), 71 deletions(-) diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index fdaca8f151..1e4e5036c2 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -167,7 +167,7 @@ request_context::request_context(const std::shared_ptr<_http_client_communicator responseImpl->_prepare_to_receive_data(); } -void _http_client_communicator::open_and_send_request_async(const std::shared_ptr &request) +void _http_client_communicator::async_send_request_impl(const std::shared_ptr &request) { auto self = std::static_pointer_cast<_http_client_communicator>(this->shared_from_this()); // Schedule a task to start sending. @@ -175,7 +175,7 @@ void _http_client_communicator::open_and_send_request_async(const std::shared_pt { try { - self->open_and_send_request(request); + self->send_request(request); } catch (...) { @@ -188,20 +188,21 @@ void _http_client_communicator::async_send_request(const std::shared_ptr &request) -{ - // First see if client needs to be opened. - unsigned long error = 0; - - if (!m_opened) - { - pplx::extensibility::scoped_critical_section_t l(m_open_lock); - - // Check again with the lock held - if (!m_opened) - { - error = open(); - - if (error == 0) - { - m_opened = true; - } - } - } - - if (error != 0) - { - // Failed to open - request->report_error(error, _XPLATSTR("Open failed")); - - // DO NOT TOUCH the this pointer after completing the request - // This object could be freed along with the request as it could - // be the last reference to this object - return; - } - - send_request(request); -} - inline void request_context::finish() { // If cancellation is enabled and registration was performed, unregister. @@ -437,4 +404,4 @@ pplx::task http_client::request(http_request request, const pplx: } -}}} \ No newline at end of file +}}} diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 600bf26605..f9b9ac1f73 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -400,8 +400,6 @@ class asio_client final : public _http_client_communicator void send_request(const std::shared_ptr &request_ctx) override; - unsigned long open() override { return 0; } - void release_connection(std::shared_ptr& conn) { m_pool->release(conn); diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h index 4e47687aa4..e4508ebcf1 100644 --- a/Release/src/http/client/http_client_impl.h +++ b/Release/src/http/client/http_client_impl.h @@ -126,30 +126,23 @@ class _http_client_communicator : public http_pipeline_stage protected: _http_client_communicator(http::uri&& address, http_client_config&& client_config); - // Method to open client. - virtual unsigned long open() = 0; - // HTTP client implementations must implement send_request. virtual void send_request(_In_ const std::shared_ptr &request) = 0; // URI to connect to. const http::uri m_uri; + pplx::extensibility::critical_section_t m_client_lock; private: http_client_config m_client_config; - std::atomic m_opened; - - pplx::extensibility::critical_section_t m_open_lock; - // Wraps opening the client around sending a request. - void open_and_send_request_async(const std::shared_ptr &request); - void open_and_send_request(const std::shared_ptr &request); + void async_send_request_impl(const std::shared_ptr &request); // Queue used to guarantee ordering of requests, when applicable. std::queue> m_requests_queue; - int m_scheduled; + bool m_outstanding; }; /// @@ -157,4 +150,4 @@ class _http_client_communicator : public http_pipeline_stage /// std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config); -}}}} \ No newline at end of file +}}}} diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 8f9b2b3146..c81dd6b317 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -14,6 +14,8 @@ ****/ #include "stdafx.h" +#include + #include "cpprest/http_headers.h" #include "http_client_impl.h" @@ -350,6 +352,7 @@ class winhttp_client : public _http_client_communicator winhttp_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) , m_secure(m_uri.scheme() == _XPLATSTR("https")) + , m_opened(false) , m_hSession(nullptr) , m_hConnection(nullptr) { } @@ -402,8 +405,19 @@ class winhttp_client : public _http_client_communicator } // Open session and connection with the server. - virtual unsigned long open() override + unsigned long open() { + if (m_opened) + { + return 0; + } + + pplx::extensibility::scoped_critical_section_t l(m_client_lock); + if (m_opened) + { + return 0; + } + // This object have lifetime greater than proxy_name and proxy_bypass // which may point to its elements. ie_proxy_config proxyIE; @@ -574,12 +588,24 @@ class winhttp_client : public _http_client_communicator return report_failure(_XPLATSTR("Error opening connection")); } + m_opened = true; return S_OK; } // Start sending request. void send_request(_In_ const std::shared_ptr &request) { + // First see if we need to be opened. + unsigned long error = open(); + if (error != 0) + { + // DO NOT TOUCH the this pointer after completing the request + // This object could be freed along with the request as it could + // be the last reference to this object + request->report_error(error, _XPLATSTR("Open failed")); + return; + } + http_request &msg = request->m_request; std::shared_ptr winhttp_context = std::static_pointer_cast(request); std::weak_ptr weak_winhttp_context = winhttp_context; @@ -1531,6 +1557,8 @@ class winhttp_client : public _http_client_communicator } } + std::atomic m_opened; + // WinHTTP session and connection HINTERNET m_hSession; HINTERNET m_hConnection; @@ -1549,4 +1577,3 @@ std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage( } }}}} - diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 4ada65a75b..e8ee50a018 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -378,12 +378,6 @@ class winrt_client : public _http_client_communicator protected: - // Method to open client. - unsigned long open() - { - return 0; - } - // Start sending request. void send_request(_In_ const std::shared_ptr &request) { From ef7e37e289c16dc82988d3675c9b40e4590cf1bc Mon Sep 17 00:00:00 2001 From: Gianfranco Costamagna Date: Wed, 1 Aug 2018 11:04:41 +0200 Subject: [PATCH 387/609] Fix boost1.63 build failure Fixes: #813 (#815) --- .../websocketpp/websocketpp/transport/asio/security/tls.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp b/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp index 8932655803..74e4234766 100644 --- a/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp +++ b/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp @@ -312,7 +312,7 @@ class connection : public lib::enable_shared_from_this { return make_error_code(transport::error::tls_short_read); #else if (ERR_GET_REASON(ec.value()) == boost::asio::ssl::error::stream_truncated) { - return make_error_code(boost::asio::ssl::error::stream_truncated); + return make_error_code(static_cast(boost::asio::ssl::error::stream_truncated)); #endif } else { // We know it is a TLS related error, but otherwise don't know From fac1470f8ac757ff57c41b5b7ba75cf7027adcd2 Mon Sep 17 00:00:00 2001 From: Andreas Stieger Date: Wed, 1 Aug 2018 11:08:42 +0200 Subject: [PATCH 388/609] Fix gcc8 error/warning -Werror=format-truncation= (#787) utilities::datetime::to_string(): datetime_str and buf were oversized for fitting into output without possible trunctation --- Release/src/utilities/asyncrt_utils.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 0e62bdeea4..be38907c6e 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -691,12 +691,13 @@ utility::string_t datetime::to_string(date_format format) const { // Append fractional second, which is a 7-digit value with no trailing zeros // This way, '1200' becomes '00012' - char buf[9] = { 0 }; + const int max_frac_length = 8; + char buf[max_frac_length+1] = { 0 }; snprintf(buf, sizeof(buf), ".%07ld", (long int)frac_sec); // trim trailing zeros - for (int i = 7; buf[i] == '0'; i--) buf[i] = '\0'; + for (int i = max_frac_length-1; buf[i] == '0'; i--) buf[i] = '\0'; // format the datetime into a separate buffer - char datetime_str[max_dt_length+1] = {0}; + char datetime_str[max_dt_length-max_frac_length-1+1] = {0}; strftime(datetime_str, sizeof(datetime_str), "%Y-%m-%dT%H:%M:%S", &datetime); // now print this buffer into the output buffer snprintf(output, sizeof(output), "%s%sZ", datetime_str, buf); From 48ae6d2fa09bc3f1c41e07638ead68c73a28595a Mon Sep 17 00:00:00 2001 From: Alex Moriarty Date: Wed, 1 Aug 2018 02:09:03 -0700 Subject: [PATCH 389/609] [gcc-8][clang++-6] disable more -Werror warnings (#779) gcc-8: -Wno-format-truncation clang-6: -Wdelete-non-virtual-dtor clang-6: -Wunused-lambda-capture removed duplicated: -Wno-reorder This fixes #778 --- Release/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 5362d1cd9e..aea81d7c0d 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -166,12 +166,12 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR IOS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith") elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") set(WARNINGS -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls) - set(LINUX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs) + set(LINUX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-unused-local-typedefs -Wno-delete-non-virtual-dtor -Wno-unused-lambda-capture) set(WARNINGS ${WARNINGS} ${LINUX_SUPPRESSIONS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") else() set(WARNINGS -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls) - set(OSX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs) + set(OSX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-unused-local-typedefs -Wno-delete-non-virtual-dtor -Wno-unused-lambda-capture) set(WARNINGS ${WARNINGS} ${OSX_SUPPRESSIONS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") @@ -184,7 +184,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR IOS) elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") message("-- Setting gcc options") - set(WARNINGS -Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code) + set(WARNINGS -Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code -Wno-format-truncation) set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") From 08de668deb39ec868c92687cedf40e4f110b3ec8 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 1 Aug 2018 03:24:39 -0700 Subject: [PATCH 390/609] Fix some issues with gcc-5 --- Release/src/http/client/http_client.cpp | 2 +- Release/tests/functional/http/client/request_helper_tests.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 1e4e5036c2..62701737cc 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -109,7 +109,7 @@ bool request_context::handle_content_encoding_compression() if (alg != web::http::details::compression::compression_algorithm::invalid) { - m_decompressor = std::make_unique(alg); + m_decompressor = utility::details::make_unique(alg); } else { diff --git a/Release/tests/functional/http/client/request_helper_tests.cpp b/Release/tests/functional/http/client/request_helper_tests.cpp index 624dff19e2..32a49490ef 100644 --- a/Release/tests/functional/http/client/request_helper_tests.cpp +++ b/Release/tests/functional/http/client/request_helper_tests.cpp @@ -71,7 +71,7 @@ TEST_FIXTURE(uri_address, send_accept_encoding) config.set_request_compressed_response(true); http_client client(m_uri, config); - std::atomic found_accept_encoding = false; + std::atomic found_accept_encoding(false); server.next_request().then([&found_accept_encoding](test_request *p_request) { found_accept_encoding = p_request->m_headers.find(header_names::accept_encoding) != p_request->m_headers.end(); @@ -90,7 +90,7 @@ TEST_FIXTURE(uri_address, do_not_send_accept_encoding) auto& server = *scoped.server(); http_client client(m_uri); - std::atomic found_accept_encoding = true; + std::atomic found_accept_encoding(true); server.next_request().then([&found_accept_encoding](test_request *p_request) { found_accept_encoding = p_request->m_headers.find(header_names::accept_encoding) != p_request->m_headers.end(); From 651bba7d2e99b083641eb9f57f3c9d9c6650284e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 1 Aug 2018 03:25:05 -0700 Subject: [PATCH 391/609] Remove empty objects when using CMake on Windows --- Release/src/CMakeLists.txt | 21 ++++++++++++--------- Release/src/pplx/pplx.cpp | 2 +- Release/src/pplx/pplxwin.cpp | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index a37a8cff9d..86a2f45b3e 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -18,7 +18,6 @@ set(SOURCES http/client/http_client.cpp http/client/http_client_msg.cpp http/client/http_client_impl.h - http/client/x509_cert_utilities.cpp http/common/internal_http_helpers.h http/common/http_helpers.cpp http/common/http_msg.cpp @@ -31,7 +30,6 @@ set(SOURCES json/json.cpp json/json_parsing.cpp json/json_serialization.cpp - pplx/pplx.cpp uri/uri.cpp uri/uri_builder.cpp utilities/asyncrt_utils.cpp @@ -84,23 +82,25 @@ if(CPPREST_PPLX_IMPL STREQUAL "apple") find_library(COREFOUNDATION CoreFoundation "/") find_library(SECURITY Security "/") target_link_libraries(cpprest PUBLIC ${COREFOUNDATION} ${SECURITY}) - target_sources(cpprest PRIVATE pplx/pplxapple.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) + target_sources(cpprest PRIVATE pplx/pplxapple.cpp pplx/pplx.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) if(CPPREST_INSTALL_HEADERS) install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) endif() elseif(CPPREST_PPLX_IMPL STREQUAL "linux") - target_sources(cpprest PRIVATE pplx/pplxlinux.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) + target_sources(cpprest PRIVATE pplx/pplxlinux.cpp pplx/pplx.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) if(CPPREST_INSTALL_HEADERS) install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) endif() elseif(CPPREST_PPLX_IMPL STREQUAL "win") - target_sources(cpprest PRIVATE pplx/pplxwin.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) - if(CPPREST_INSTALL_HEADERS) - install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) + if(CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") + target_sources(cpprest PRIVATE pplx/threadpool.cpp ../include/pplx/threadpool.h) + if(CPPREST_INSTALL_HEADERS) + install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) + endif() endif() elseif(CPPREST_PPLX_IMPL STREQUAL "winpplx") target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_PPLX=1) - target_sources(cpprest PRIVATE pplx/pplxwin.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) + target_sources(cpprest PRIVATE pplx/pplxwin.cpp pplx/pplx.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) if(CPPREST_INSTALL_HEADERS) install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) endif() @@ -115,7 +115,7 @@ if(CPPREST_HTTP_CLIENT_IMPL STREQUAL "asio") cpprest_find_boost() cpprest_find_openssl() target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_HTTP_CLIENT_ASIO) - target_sources(cpprest PRIVATE http/client/http_client_asio.cpp) + target_sources(cpprest PRIVATE http/client/http_client_asio.cpp http/client/x509_cert_utilities.cpp) target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal) elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttp") target_link_libraries(cpprest PRIVATE @@ -123,6 +123,9 @@ elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttp") Winhttp.lib ) target_sources(cpprest PRIVATE http/client/http_client_winhttp.cpp) + if(CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") + target_sources(cpprest PRIVATE http/client/x509_cert_utilities.cpp) + endif() elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winrt") target_sources(cpprest PRIVATE http/client/http_client_winrt.cpp) else() diff --git a/Release/src/pplx/pplx.cpp b/Release/src/pplx/pplx.cpp index 40c76fc3b6..99d00e9ea5 100644 --- a/Release/src/pplx/pplx.cpp +++ b/Release/src/pplx/pplx.cpp @@ -13,7 +13,7 @@ #include "stdafx.h" -#if !defined(_WIN32) || _MSC_VER < 1800 || CPPREST_FORCE_PPLX +#if !defined(_WIN32) || CPPREST_FORCE_PPLX #include "pplx/pplx.h" diff --git a/Release/src/pplx/pplxwin.cpp b/Release/src/pplx/pplxwin.cpp index d586e7d69c..e511c0ad5d 100644 --- a/Release/src/pplx/pplxwin.cpp +++ b/Release/src/pplx/pplxwin.cpp @@ -13,7 +13,7 @@ #include "stdafx.h" -#if !defined(_WIN32) || _MSC_VER < 1800 || CPPREST_FORCE_PPLX +#if !defined(_WIN32) || CPPREST_FORCE_PPLX #include "pplx/pplxwin.h" From 3d5cb468b3d474b1cd2443b778f8419932583474 Mon Sep 17 00:00:00 2001 From: Zeke Snider Date: Fri, 2 Feb 2018 16:50:39 -0800 Subject: [PATCH 392/609] Don't enable certificate revocation check if client config has validate certificates set to false --- Release/src/http/client/http_client_winhttp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index c81dd6b317..737c430b71 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -667,7 +667,7 @@ class winhttp_client : public _http_client_communicator } // Enable the certificate revocation check - if (m_secure) + if (m_secure && client_config().validate_certificates()) { DWORD dwEnableSSLRevocOpt = WINHTTP_ENABLE_SSL_REVOCATION; if (!WinHttpSetOption(winhttp_context->m_request_handle, WINHTTP_OPTION_ENABLE_FEATURE, &dwEnableSSLRevocOpt, sizeof(dwEnableSSLRevocOpt))) From 074590c8fc53b262b3c4e15f61c4559c43254595 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 1 Aug 2018 14:00:35 -0700 Subject: [PATCH 393/609] Add tests for set_validate_certificates(false). --- .../functional/http/client/outside_tests.cpp | 92 +++++++++++++++---- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 4c16fb4db6..00404a290f 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -75,7 +75,7 @@ TEST_FIXTURE(uri_address, outside_wikipedia_compressed_http_response) auto s = response.extract_utf8string().get(); VERIFY_IS_FALSE(s.empty()); - + utility::string_t encoding; VERIFY_IS_TRUE(response.headers().match(web::http::header_names::content_encoding, encoding)); @@ -93,14 +93,14 @@ TEST_FIXTURE(uri_address, outside_google_dot_com) VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); } } - + TEST_FIXTURE(uri_address, multiple_https_requests) { handle_timeout([&] { // Use code.google.com instead of www.google.com, which redirects http_client client(U("https://code.google.com")); - + http_response response; for(int i = 0; i < 5; ++i) { @@ -155,38 +155,90 @@ TEST_FIXTURE(uri_address, no_transfer_encoding_content_length) // https://www.ssllabs.com/ssltest/ // http://www.internetsociety.org/deploy360/resources/dane-test-sites/ // https://onlinessl.netlock.hu/# -TEST(server_selfsigned_cert) +static void test_failed_ssl_cert(const uri& base_uri) { - handle_timeout([] + handle_timeout([&base_uri] { - http_client client(U("https://self-signed.badssl.com/")); + http_client client(base_uri); auto requestTask = client.request(methods::GET); VERIFY_THROWS(requestTask.get(), http_exception); }); } -TEST(server_hostname_mismatch) +#if !defined(__cplusplus_winrt) +static void test_ignored_ssl_cert(const uri& base_uri) { - handle_timeout([] + handle_timeout([&base_uri] { - http_client client(U("https://wrong.host.badssl.com/")); - auto requestTask = client.request(methods::GET); - VERIFY_THROWS(requestTask.get(), http_exception); + http_client_config config; + config.set_validate_certificates(false); + http_client client(base_uri, config); + auto request = client.request(methods::GET).get(); + VERIFY_ARE_EQUAL(status_codes::OK, request.status_code()); }); } +#endif // !defined(__cplusplus_winrt) + +TEST(server_selfsigned_cert) +{ + test_failed_ssl_cert(U("https://self-signed.badssl.com/")); +} + +#if !defined(__cplusplus_winrt) +TEST(server_selfsigned_cert_ignored) +{ + test_ignored_ssl_cert(U("https://self-signed.badssl.com/")); +} +#endif // !defined(__cplusplus_winrt) + +TEST(server_hostname_mismatch) +{ + test_failed_ssl_cert(U("https://wrong.host.badssl.com/")); +} + +#if !defined(__cplusplus_winrt) +TEST(server_hostname_mismatch_ignored) +{ + test_ignored_ssl_cert(U("https://wrong.host.badssl.com/")); +} +#endif // !defined(__cplusplus_winrt) TEST(server_cert_expired) { - handle_timeout([] - { - http_client_config config; - config.set_timeout(std::chrono::seconds(1)); - http_client client(U("https://expired.badssl.com/"), config); - auto requestTask = client.request(methods::GET); - VERIFY_THROWS(requestTask.get(), http_exception); - }); + test_failed_ssl_cert(U("https://expired.badssl.com/")); +} + +#if !defined(__cplusplus_winrt) +TEST(server_cert_expired_ignored) +{ + test_ignored_ssl_cert(U("https://expired.badssl.com/")); +} +#endif // !defined(__cplusplus_winrt) + +TEST(server_cert_revoked) +{ + test_failed_ssl_cert(U("https://revoked.badssl.com/")); +} + +#if !defined(__cplusplus_winrt) +TEST(server_cert_revoked_ignored) +{ + test_ignored_ssl_cert(U("https://revoked.badssl.com/")); +} +#endif // !defined(__cplusplus_winrt) + +TEST(server_cert_untrusted) +{ + test_failed_ssl_cert(U("https://untrusted-root.badssl.com/")); } +#if !defined(__cplusplus_winrt) +TEST(server_cert_untrusted_ignored) +{ + test_ignored_ssl_cert(U("https://untrusted-root.badssl.com/")); +} +#endif // !defined(__cplusplus_winrt) + #if !defined(__cplusplus_winrt) TEST(ignore_server_cert_invalid, "Ignore:Android", "229", @@ -204,7 +256,7 @@ TEST(ignore_server_cert_invalid, VERIFY_ARE_EQUAL(status_codes::OK, request.status_code()); }); } -#endif +#endif // !defined(__cplusplus_winrt) TEST_FIXTURE(uri_address, outside_ssl_json) { From ee2cde689a41f55657ae405f515cc0f5b6062da3 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 1 Aug 2018 14:05:34 -0700 Subject: [PATCH 394/609] Unbreak ASIO build on Windows. (#821) --- Release/src/http/client/http_client.cpp | 8 +- Release/src/http/client/http_client_asio.cpp | 84 +++++++++---------- Release/src/http/client/http_client_impl.h | 2 +- .../src/http/client/http_client_winhttp.cpp | 3 +- 4 files changed, 50 insertions(+), 47 deletions(-) diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 62701737cc..2963fae3c2 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -123,15 +123,19 @@ bool request_context::handle_content_encoding_compression() return true; } -void request_context::add_accept_encoding_header(utility::string_t& headers) const +utility::string_t request_context::get_accept_encoding_header() const { + utility::string_t headers; // Add the header needed to request a compressed response if supported on this platform and it has been specified in the config - if (web::http::details::compression::stream_decompressor::is_supported() && m_http_client->client_config().request_compressed_response()) + if (web::http::details::compression::stream_decompressor::is_supported() + && m_http_client->client_config().request_compressed_response()) { headers.append(U("Accept-Encoding: ")); headers.append(web::http::details::compression::stream_decompressor::known_algorithms()); headers.append(U("\r\n")); } + + return headers; } concurrency::streams::streambuf request_context::_get_readbuffer() diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index f9b9ac1f73..3a79963a0c 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -460,14 +460,14 @@ class asio_context : public request_context, public std::enable_shared_from_this ctx->m_timer.set_ctx(std::weak_ptr(ctx)); return ctx; } - + class ssl_proxy_tunnel : public std::enable_shared_from_this { public: ssl_proxy_tunnel(std::shared_ptr context, std::function)> ssl_tunnel_established) : m_ssl_tunnel_established(ssl_tunnel_established), m_context(context) {} - + void start_proxy_connect() { auto proxy = m_context->m_http_client->client_config().proxy(); @@ -502,7 +502,7 @@ class asio_context : public request_context, public std::enable_shared_from_this client->m_resolver.async_resolve(query, boost::bind(&ssl_proxy_tunnel::handle_resolve, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } - private: + private: void handle_resolve(const boost::system::error_code& ec, tcp::resolver::iterator endpoints) { if (ec) @@ -553,7 +553,7 @@ class asio_context : public request_context, public std::enable_shared_from_this m_context->report_error("Failed to send connect request to proxy.", err, httpclient_errorcode_context::writebody); } } - + void handle_status_line(const boost::system::error_code& ec) { if (!ec) @@ -565,13 +565,13 @@ class asio_context : public request_context, public std::enable_shared_from_this response_stream >> http_version; status_code status_code; response_stream >> status_code; - + if (!response_stream || http_version.substr(0, 5) != "HTTP/") { m_context->report_error("Invalid HTTP status line during proxy connection", ec, httpclient_errorcode_context::readheader); return; } - + if (status_code != 200) { m_context->report_error("Expected a 200 response from proxy, received: " + to_string(status_code), ec, httpclient_errorcode_context::readheader); @@ -593,14 +593,14 @@ class asio_context : public request_context, public std::enable_shared_from_this // Failed to write to socket because connection was already closed while it was in the pool. // close() here ensures socket is closed in a robust way and prevents the connection from being put to the pool again. m_context->m_connection->close(); - + // Create a new context and copy the request object, completion event and // cancellation registration to maintain the old state. // This also obtains a new connection from pool. auto new_ctx = m_context->create_request_context(m_context->m_http_client, m_context->m_request); new_ctx->m_request_completion = m_context->m_request_completion; new_ctx->m_cancellationRegistration = m_context->m_cancellationRegistration; - + auto client = std::static_pointer_cast(m_context->m_http_client); // Resend the request using the new context. client->send_request(new_ctx); @@ -611,15 +611,15 @@ class asio_context : public request_context, public std::enable_shared_from_this } } } - + std::function)> m_ssl_tunnel_established; std::shared_ptr m_context; - + boost::asio::streambuf m_request; boost::asio::streambuf m_response; }; - - + + enum class http_proxy_type { none, @@ -634,11 +634,11 @@ class asio_context : public request_context, public std::enable_shared_from_this request_context::report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user."); return; } - + http_proxy_type proxy_type = http_proxy_type::none; std::string proxy_host; int proxy_port = -1; - + // There is no support for auto-detection of proxies on non-windows platforms, it must be specified explicitly from the client code. if (m_http_client->client_config().proxy().is_specified()) { @@ -648,7 +648,7 @@ class asio_context : public request_context, public std::enable_shared_from_this proxy_port = proxy_uri.port() == -1 ? 8080 : proxy_uri.port(); proxy_host = utility::conversions::to_utf8string(proxy_uri.host()); } - + auto start_http_request_flow = [proxy_type, proxy_host, proxy_port AND_CAPTURE_MEMBER_FUNCTION_POINTERS](std::shared_ptr ctx) { if (ctx->m_request._cancellation_token().is_canceled()) @@ -656,20 +656,20 @@ class asio_context : public request_context, public std::enable_shared_from_this ctx->request_context::report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user."); return; } - + const auto &base_uri = ctx->m_http_client->base_uri(); const auto full_uri = uri_builder(base_uri).append(ctx->m_request.relative_uri()).to_uri(); - + // For a normal http proxy, we need to specify the full request uri, otherwise just specify the resource auto encoded_resource = proxy_type == http_proxy_type::http ? full_uri.to_string() : full_uri.resource().to_string(); - + if (encoded_resource.empty()) { encoded_resource = U("/"); } - + const auto &method = ctx->m_request.method(); - + // stop injection of headers via method // resource should be ok, since it's been encoded // and host won't resolve @@ -678,20 +678,20 @@ class asio_context : public request_context, public std::enable_shared_from_this ctx->report_exception(http_exception("The method string is invalid.")); return; } - + std::ostream request_stream(&ctx->m_body_buf); request_stream.imbue(std::locale::classic()); const auto &host = utility::conversions::to_utf8string(base_uri.host()); - + request_stream << utility::conversions::to_utf8string(method) << " " << utility::conversions::to_utf8string(encoded_resource) << " " << "HTTP/1.1" << CRLF; - + int port = base_uri.port(); - + if (base_uri.is_port_default()) { port = (ctx->m_connection->is_ssl() ? 443 : 80); } - + // Add the Host header if user has not specified it explicitly if (!ctx->m_request.headers().has(header_names::host)) { @@ -701,10 +701,10 @@ class asio_context : public request_context, public std::enable_shared_from_this } request_stream << CRLF; } - + // Extra request headers are constructed here. std::string extra_headers; - + // Add header for basic proxy authentication if (proxy_type == http_proxy_type::http && ctx->m_http_client->client_config().proxy().credentials().is_set()) { @@ -716,7 +716,7 @@ class asio_context : public request_context, public std::enable_shared_from_this extra_headers.append(ctx->generate_basic_auth_header()); } - ctx->add_accept_encoding_header(extra_headers); + extra_headers += utility::conversions::to_utf8string(ctx->get_accept_encoding_header()); // Check user specified transfer-encoding. std::string transferencoding; @@ -740,25 +740,25 @@ class asio_context : public request_context, public std::enable_shared_from_this extra_headers.append("Content-Length: 0\r\n"); } } - + if (proxy_type == http_proxy_type::http) { extra_headers.append( "Cache-Control: no-store, no-cache\r\n" "Pragma: no-cache\r\n"); } - + request_stream << utility::conversions::to_utf8string(::web::http::details::flatten_http_headers(ctx->m_request.headers())); request_stream << extra_headers; // Enforce HTTP connection keep alive (even for the old HTTP/1.0 protocol). request_stream << "Connection: Keep-Alive" << CRLF << CRLF; - + // Start connection timeout timer. if (!ctx->m_timer.has_started()) { ctx->m_timer.start(); } - + if (ctx->m_connection->is_reused() || proxy_type == http_proxy_type::ssl_tunnel) { // If socket is a reused connection or we're connected via an ssl-tunneling proxy, try to write the request directly. In both cases we have already established a tcp connection. @@ -768,16 +768,16 @@ class asio_context : public request_context, public std::enable_shared_from_this { // If the connection is new (unresolved and unconnected socket), then start async // call to resolve first, leading eventually to request write. - + // For normal http proxies, we want to connect directly to the proxy server. It will relay our request. auto tcp_host = proxy_type == http_proxy_type::http ? proxy_host : host; auto tcp_port = proxy_type == http_proxy_type::http ? proxy_port : port; - + tcp::resolver::query query(tcp_host, to_string(tcp_port)); auto client = std::static_pointer_cast(ctx->m_http_client); client->m_resolver.async_resolve(query, boost::bind(&asio_context::handle_resolve, ctx, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } - + // Register for notification on cancellation to abort this request. if (ctx->m_request._cancellation_token() != pplx::cancellation_token::none()) { @@ -794,7 +794,7 @@ class asio_context : public request_context, public std::enable_shared_from_this }); } }; - + if (proxy_type == http_proxy_type::ssl_tunnel) { // The ssl_tunnel_proxy keeps the context alive and then calls back once the ssl tunnel is established via 'start_http_request_flow' @@ -1073,7 +1073,7 @@ class asio_context : public request_context, public std::enable_shared_from_this // Reuse error handling. return handle_write_body(ec); } - + m_timer.reset(); const auto &progress = m_request._get_impl()->_progress_handler(); if (progress) @@ -1154,7 +1154,7 @@ class asio_context : public request_context, public std::enable_shared_from_this response_stream >> http_version; status_code status_code; response_stream >> status_code; - + std::string status_message; std::getline(response_stream, status_message); @@ -1418,7 +1418,7 @@ class asio_context : public request_context, public std::enable_shared_from_this } this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf this_request->m_connection->async_read_until(this_request->m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); - }); + }); } } } @@ -1471,7 +1471,7 @@ class asio_context : public request_context, public std::enable_shared_from_this if(m_decompressor) { auto decompressed = m_decompressor->decompress(boost::asio::buffer_cast(m_body_buf.data()), read_size); - + if (m_decompressor->has_error()) { this_request->report_exception(std::runtime_error("Failed to decompress the response body")); @@ -1646,7 +1646,7 @@ class asio_context : public request_context, public std::enable_shared_from_this timeout_timer m_timer; boost::asio::streambuf m_body_buf; std::shared_ptr m_connection; - + #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) bool m_openssl_failed; #endif @@ -1668,7 +1668,7 @@ void asio_client::send_request(const std::shared_ptr &request_c { client_config().invoke_nativehandle_options(ctx->m_connection->m_ssl_stream.get()); } - else + else { client_config().invoke_nativehandle_options(&(ctx->m_connection->m_socket)); } diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h index e4508ebcf1..7b6c974a0d 100644 --- a/Release/src/http/client/http_client_impl.h +++ b/Release/src/http/client/http_client_impl.h @@ -75,7 +75,7 @@ class request_context bool handle_content_encoding_compression(); /// Append an Accept-Encoding header if requested by the http_client settings - void add_accept_encoding_header(utility::string_t& headers) const; + utility::string_t get_accept_encoding_header() const; concurrency::streams::streambuf _get_writebuffer(); diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index c81dd6b317..f92f252bd9 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -759,8 +759,7 @@ class winhttp_client : public _http_client_communicator } utility::string_t flattened_headers = web::http::details::flatten_http_headers(msg.headers()); - - winhttp_context->add_accept_encoding_header(flattened_headers); + flattened_headers += winhttp_context->get_accept_encoding_header(); // Add headers. if(!flattened_headers.empty()) From c55ada9659c140104e3366e67024a39f4376ce7b Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 1 Aug 2018 16:39:58 -0700 Subject: [PATCH 395/609] Add branchless is_alnum borrowed from MSVC++'s std::regex' _Is_word; should be about 5x faster. (#823) The _Is_word change resulted in the following results in microbenchmarks; the previous is_alnum looks like branching_ranges. .\word_character_test.exe 08/01/18 16:33:03 Running .\word_character_test.exe Run on (12 X 2904 MHz CPU s) CPU Caches: L1 Data 32K (x6) L1 Instruction 32K (x6) L2 Unified 262K (x6) L3 Unified 12582K (x1) -------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------- strchr_search 19426572900 ns 19421875000 ns 1 branching_ranges 7582129000 ns 7578125000 ns 1 branching_search 6592977800 ns 6593750000 ns 1 table_index 1091321300 ns 1078125000 ns 1 --- Release/include/cpprest/asyncrt_utils.h | 43 ++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 68aa738be0..6abcc9fc34 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "pplx/pplxtasks.h" #include "cpprest/details/basic_types.h" @@ -356,11 +357,45 @@ namespace details /// Our own implementation of alpha numeric instead of std::isalnum to avoid /// taking global lock for performance reasons. /// - inline bool __cdecl is_alnum(char ch) + inline bool __cdecl is_alnum(const unsigned char uch) noexcept + { // test if uch is an alnum character + // special casing char to avoid branches + static constexpr bool is_alnum_table[UCHAR_MAX + 1] = + { + /* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */ + /* 0X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 1X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 2X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0-9 */ + /* 4X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A-Z */ + /* 5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + /* 6X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a-z */ + /* 7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 + /* non-ASCII values initialized to 0 */ + }; + return (is_alnum_table[uch]); + } + + /// + /// Our own implementation of alpha numeric instead of std::isalnum to avoid + /// taking global lock for performance reasons. + /// + inline bool __cdecl is_alnum(const char ch) noexcept + { + return (is_alnum(static_cast(ch))); + } + + /// + /// Our own implementation of alpha numeric instead of std::isalnum to avoid + /// taking global lock for performance reasons. + /// + template + inline bool __cdecl is_alnum(Elem ch) noexcept { - return (ch >= '0' && ch <= '9') - || (ch >= 'A' && ch <= 'Z') - || (ch >= 'a' && ch <= 'z'); + // assumes 'x' == L'x' for the ASCII range + typedef typename std::make_unsigned::type UElem; + const auto uch = static_cast(ch); + return (uch <= static_cast('z') && is_alnum(static_cast(uch))); } /// From a6b41536e0cbb28a3ce57e2cd53f983e3312c3e0 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 1 Aug 2018 17:14:08 -0700 Subject: [PATCH 396/609] Unify handling of tolower operations to avoid locale sensitivity. (#822) --- Release/include/cpprest/asyncrt_utils.h | 83 ++++++++--------- Release/include/cpprest/http_headers.h | 40 ++++----- .../BlackJack_Client/BlackJackClient.cpp | 38 ++++---- Release/src/http/common/http_msg.cpp | 73 ++++++++------- Release/src/http/oauth/oauth2.cpp | 6 +- Release/src/uri/uri.cpp | 21 +---- Release/src/utilities/asyncrt_utils.cpp | 89 ++++++++++++++++++- .../src/websockets/client/ws_client_winrt.cpp | 6 +- .../src/websockets/client/ws_client_wspp.cpp | 3 +- 9 files changed, 210 insertions(+), 149 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 6abcc9fc34..b5e61c9d14 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -29,7 +29,6 @@ #ifndef _WIN32 #include -#include #if !defined(ANDROID) && !defined(__ANDROID__) && defined(HAVE_XLOCALE_H) // CodePlex 269 /* Systems using glibc: xlocale.h has been removed from glibc 2.26 The above include of locale.h is sufficient @@ -428,19 +427,48 @@ namespace details } /// - /// Cross platform utility function for performing case insensitive string comparision. + /// Cross platform utility function for performing case insensitive string equality comparision. /// /// First string to compare. /// Second strong to compare. /// true if the strings are equivalent, false otherwise - inline bool str_icmp(const utility::string_t &left, const utility::string_t &right) - { -#ifdef _WIN32 - return _wcsicmp(left.c_str(), right.c_str()) == 0; -#else - return boost::iequals(left, right); -#endif - } + _ASYNCRTIMP bool __cdecl str_iequal(const std::string &left, const std::string &right) CPPREST_NOEXCEPT; + + /// + /// Cross platform utility function for performing case insensitive string equality comparision. + /// + /// First string to compare. + /// Second strong to compare. + /// true if the strings are equivalent, false otherwise + _ASYNCRTIMP bool __cdecl str_iequal(const std::wstring &left, const std::wstring &right) CPPREST_NOEXCEPT; + + /// + /// Cross platform utility function for performing case insensitive string less-than comparision. + /// + /// First string to compare. + /// Second strong to compare. + /// true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise, false. + _ASYNCRTIMP bool __cdecl str_iless(const std::string &left, const std::string &right) CPPREST_NOEXCEPT; + + /// + /// Cross platform utility function for performing case insensitive string less-than comparision. + /// + /// First string to compare. + /// Second strong to compare. + /// true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise, false. + _ASYNCRTIMP bool __cdecl str_iless(const std::wstring &left, const std::wstring &right) CPPREST_NOEXCEPT; + + /// + /// Convert a string to lowercase in place. + /// + /// The string to convert to lowercase. + _ASYNCRTIMP void __cdecl inplace_tolower(std::string &target) CPPREST_NOEXCEPT; + + /// + /// Convert a string to lowercase in place. + /// + /// The string to convert to lowercase. + _ASYNCRTIMP void __cdecl inplace_tolower(std::wstring &target) CPPREST_NOEXCEPT; #ifdef _WIN32 @@ -642,41 +670,6 @@ class datetime interval_type m_interval; }; -#ifndef _WIN32 - -// temporary workaround for the fact that -// utf16char is not fully supported in GCC -class cmp -{ -public: - - static int icmp(std::string left, std::string right) - { - size_t i; - for (i = 0; i < left.size(); ++i) - { - if (i == right.size()) return 1; - - auto l = cmp::tolower(left[i]); - auto r = cmp::tolower(right[i]); - if (l > r) return 1; - if (l < r) return -1; - } - if (i < right.size()) return -1; - return 0; - } - -private: - static char tolower(char c) - { - if (c >= 'A' && c <= 'Z') - return static_cast(c - 'A' + 'a'); - return c; - } -}; - -#endif - inline int operator- (datetime t1, datetime t2) { auto diff = (t1.m_interval - t2.m_interval); diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 2458872410..f5bee96535 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -68,30 +68,30 @@ class http_headers { bool operator()(const utility::string_t &str1, const utility::string_t &str2) const { -#ifdef _WIN32 - return _wcsicmp(str1.c_str(), str2.c_str()) < 0; -#else - return utility::cmp::icmp(str1, str2) < 0; -#endif + return utility::details::str_iless(str1, str2); } }; +private: + typedef std::map inner_container; +public: + /// /// STL-style typedefs /// - typedef std::map::key_type key_type; - typedef std::map::key_compare key_compare; - typedef std::map::allocator_type allocator_type; - typedef std::map::size_type size_type; - typedef std::map::difference_type difference_type; - typedef std::map::pointer pointer; - typedef std::map::const_pointer const_pointer; - typedef std::map::reference reference; - typedef std::map::const_reference const_reference; - typedef std::map::iterator iterator; - typedef std::map::const_iterator const_iterator; - typedef std::map::reverse_iterator reverse_iterator; - typedef std::map::const_reverse_iterator const_reverse_iterator; + typedef typename inner_container::key_type key_type; + typedef typename inner_container::key_compare key_compare; + typedef typename inner_container::allocator_type allocator_type; + typedef typename inner_container::size_type size_type; + typedef typename inner_container::difference_type difference_type; + typedef typename inner_container::pointer pointer; + typedef typename inner_container::const_pointer const_pointer; + typedef typename inner_container::reference reference; + typedef typename inner_container::const_reference const_reference; + typedef typename inner_container::iterator iterator; + typedef typename inner_container::const_iterator const_iterator; + typedef typename inner_container::reverse_iterator reverse_iterator; + typedef typename inner_container::const_reverse_iterator const_reverse_iterator; /// /// Constructs an empty set of HTTP headers. @@ -318,7 +318,7 @@ class http_headers } // Headers are stored in a map with case insensitive key. - std::map m_headers; + inner_container m_headers; }; -}} \ No newline at end of file +}} diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp index 0e84d14d69..1ca303fbdc 100644 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp +++ b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp @@ -13,17 +13,12 @@ #include #include #include +#include #include #include "../BlackJack_Server/messagetypes.h" -#ifdef _WIN32 -# define iequals(x, y) (_stricmp((x), (y))==0) -#else -# define iequals(x, y) boost::iequals((x), (y)) -#endif - using namespace std; -using namespace web; +using namespace web; using namespace utility; using namespace http; using namespace http::client; @@ -134,7 +129,7 @@ void PrintTable(const http_response &response, bool &refresh) } } -// +// // Entry point for the blackjack client. // Arguments: BlackJack_Client.exe // If port is not specified, client will assume that the server is listening on port 34568 @@ -179,7 +174,11 @@ int main(int argc, char *argv[]) ucout << "Enter method:"; cin >> method; - if ( iequals(method.c_str(), "quit") ) + const auto methodFirst = &method[0]; + const auto methodLast = methodFirst + method.size(); + std::use_facet>(std::locale::classic()).tolower(methodFirst, methodLast); + + if (method == "quit") { if ( !userName.empty() && !table.empty() ) { @@ -190,12 +189,12 @@ int main(int argc, char *argv[]) break; } - if ( iequals(method.c_str(), "name") ) + if (method == "name") { ucout << "Enter user name:"; ucin >> userName; } - else if ( iequals(method.c_str(), "join") ) + else if (method == "join") { ucout << "Enter table name:"; ucin >> table; @@ -206,16 +205,16 @@ int main(int argc, char *argv[]) buf << table << U("?name=") << userName; CheckResponse("blackjack/dealer", bjDealer.request(methods::POST, buf.str()).get(), was_refresh); } - else if ( iequals(method.c_str(), "hit") - || iequals(method.c_str(), "stay") - || iequals(method.c_str(), "double") ) + else if (method == "hit" + || method == "stay" + || method == "double") { utility::ostringstream_t buf; buf << table << U("?request=") << utility::conversions::to_string_t(method) << U("&name=") << userName; PrintTable(CheckResponse("blackjack/dealer", bjDealer.request(methods::PUT, buf.str()).get()), was_refresh); } - else if ( iequals(method.c_str(), "bet") - || iequals(method.c_str(), "insure") ) + else if (method == "bet" + ||method == "insure") { utility::string_t bet; ucout << "Enter bet:"; @@ -227,11 +226,11 @@ int main(int argc, char *argv[]) buf << table << U("?request=") << utility::conversions::to_string_t(method) << U("&name=") << userName << U("&amount=") << bet; PrintTable(CheckResponse("blackjack/dealer", bjDealer.request(methods::PUT, buf.str()).get()), was_refresh); } - else if ( iequals(method.c_str(), "newtbl") ) + else if (method == "newtbl") { CheckResponse("blackjack/dealer", bjDealer.request(methods::POST).get(), was_refresh); } - else if ( iequals(method.c_str(), "leave") ) + else if (method == "leave") { ucout << "Enter table:"; ucin >> table; @@ -242,7 +241,7 @@ int main(int argc, char *argv[]) buf << table << U("?name=") << userName; CheckResponse("blackjack/dealer", bjDealer.request(methods::DEL, buf.str()).get(), was_refresh); } - else if ( iequals(method.c_str(), "list") ) + else if (method == "list") { was_refresh = false; http_response response = CheckResponse("blackjack/dealer", bjDealer.request(methods::GET).get()); @@ -268,4 +267,3 @@ int main(int argc, char *argv[]) return 0; } - diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index ad2c70e9d7..ece2d08c1e 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -422,7 +422,7 @@ static bool is_content_type_one_of(const utility::string_t *first, const utility { while (first != last) { - if (utility::details::str_icmp(*first, value)) + if (utility::details::str_iequal(*first, value)) { return true; } @@ -460,7 +460,7 @@ static bool is_content_type_textual(const utility::string_t &content_type) }; #endif - if (content_type.size() >= 4 && utility::details::str_icmp(content_type.substr(0, 4), _XPLATSTR("text"))) + if (content_type.size() >= 4 && utility::details::str_iequal(content_type.substr(0, 4), _XPLATSTR("text"))) { return true; } @@ -554,7 +554,7 @@ static void parse_content_type_and_charset(const utility::string_t &content_type // Split and make sure 'charset' utility::string_t charset_key = possible_charset.substr(0, equals_index); trim_whitespace(charset_key); - if (!utility::details::str_icmp(charset_key, _XPLATSTR("charset"))) + if (!utility::details::str_iequal(charset_key, _XPLATSTR("charset"))) { charset = get_default_charset(content); return; @@ -609,9 +609,9 @@ utf8string details::http_msg_base::extract_utf8string(bool ignore_content_type) auto buf_r = instream().streambuf(); // Perform the correct character set conversion if one is necessary. - if (utility::details::str_icmp(charset, charset_types::utf8) - || utility::details::str_icmp(charset, charset_types::usascii) - || utility::details::str_icmp(charset, charset_types::ascii)) + if (utility::details::str_iequal(charset, charset_types::utf8) + || utility::details::str_iequal(charset, charset_types::usascii) + || utility::details::str_iequal(charset, charset_types::ascii)) { std::string body; body.resize((std::string::size_type)buf_r.in_avail()); @@ -620,7 +620,7 @@ utf8string details::http_msg_base::extract_utf8string(bool ignore_content_type) } // Latin1 - else if (utility::details::str_icmp(charset, charset_types::latin1)) + else if (utility::details::str_iequal(charset, charset_types::latin1)) { std::string body; body.resize((std::string::size_type)buf_r.in_avail()); @@ -629,7 +629,7 @@ utf8string details::http_msg_base::extract_utf8string(bool ignore_content_type) } // utf-16 - else if (utility::details::str_icmp(charset, charset_types::utf16)) + else if (utility::details::str_iequal(charset, charset_types::utf16)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -638,7 +638,7 @@ utf8string details::http_msg_base::extract_utf8string(bool ignore_content_type) } // utf-16le - else if (utility::details::str_icmp(charset, charset_types::utf16le)) + else if (utility::details::str_iequal(charset, charset_types::utf16le)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -647,7 +647,7 @@ utf8string details::http_msg_base::extract_utf8string(bool ignore_content_type) } // utf-16be - else if (utility::details::str_icmp(charset, charset_types::utf16be)) + else if (utility::details::str_iequal(charset, charset_types::utf16be)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -671,7 +671,7 @@ utf16string details::http_msg_base::extract_utf16string(bool ignore_content_type auto buf_r = instream().streambuf(); // Perform the correct character set conversion if one is necessary. - if (utility::details::str_icmp(charset, charset_types::utf16le)) + if (utility::details::str_iequal(charset, charset_types::utf16le)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -680,9 +680,9 @@ utf16string details::http_msg_base::extract_utf16string(bool ignore_content_type } // utf-8, ascii - else if (utility::details::str_icmp(charset, charset_types::utf8) - || utility::details::str_icmp(charset, charset_types::usascii) - || utility::details::str_icmp(charset, charset_types::ascii)) + else if (utility::details::str_iequal(charset, charset_types::utf8) + || utility::details::str_iequal(charset, charset_types::usascii) + || utility::details::str_iequal(charset, charset_types::ascii)) { std::string body; body.resize((std::string::size_type)buf_r.in_avail()); @@ -691,7 +691,7 @@ utf16string details::http_msg_base::extract_utf16string(bool ignore_content_type } // Latin1 - else if (utility::details::str_icmp(charset, charset_types::latin1)) + else if (utility::details::str_iequal(charset, charset_types::latin1)) { std::string body; body.resize((std::string::size_type)buf_r.in_avail()); @@ -700,7 +700,7 @@ utf16string details::http_msg_base::extract_utf16string(bool ignore_content_type } // utf-16 - else if (utility::details::str_icmp(charset, charset_types::utf16)) + else if (utility::details::str_iequal(charset, charset_types::utf16)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -709,7 +709,7 @@ utf16string details::http_msg_base::extract_utf16string(bool ignore_content_type } // utf-16be - else if (utility::details::str_icmp(charset, charset_types::utf16be)) + else if (utility::details::str_iequal(charset, charset_types::utf16be)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -733,8 +733,8 @@ utility::string_t details::http_msg_base::extract_string(bool ignore_content_typ auto buf_r = instream().streambuf(); // Perform the correct character set conversion if one is necessary. - if (utility::details::str_icmp(charset, charset_types::usascii) - || utility::details::str_icmp(charset, charset_types::ascii)) + if (utility::details::str_iequal(charset, charset_types::usascii) + || utility::details::str_iequal(charset, charset_types::ascii)) { std::string body; body.resize((std::string::size_type)buf_r.in_avail()); @@ -743,7 +743,7 @@ utility::string_t details::http_msg_base::extract_string(bool ignore_content_typ } // Latin1 - if(utility::details::str_icmp(charset, charset_types::latin1)) + if(utility::details::str_iequal(charset, charset_types::latin1)) { std::string body; body.resize((std::string::size_type)buf_r.in_avail()); @@ -753,7 +753,7 @@ utility::string_t details::http_msg_base::extract_string(bool ignore_content_typ } // utf-8. - else if(utility::details::str_icmp(charset, charset_types::utf8)) + else if(utility::details::str_iequal(charset, charset_types::utf8)) { std::string body; body.resize((std::string::size_type)buf_r.in_avail()); @@ -762,7 +762,7 @@ utility::string_t details::http_msg_base::extract_string(bool ignore_content_typ } // utf-16. - else if(utility::details::str_icmp(charset, charset_types::utf16)) + else if(utility::details::str_iequal(charset, charset_types::utf16)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -771,7 +771,7 @@ utility::string_t details::http_msg_base::extract_string(bool ignore_content_typ } // utf-16le - else if(utility::details::str_icmp(charset, charset_types::utf16le)) + else if(utility::details::str_iequal(charset, charset_types::utf16le)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -780,7 +780,7 @@ utility::string_t details::http_msg_base::extract_string(bool ignore_content_typ } // utf-16be - else if(utility::details::str_icmp(charset, charset_types::utf16be)) + else if(utility::details::str_iequal(charset, charset_types::utf16be)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -804,7 +804,7 @@ json::value details::http_msg_base::_extract_json(bool ignore_content_type) auto buf_r = instream().streambuf(); // Latin1 - if(utility::details::str_icmp(charset, charset_types::latin1)) + if(utility::details::str_iequal(charset, charset_types::latin1)) { std::string body; body.resize(buf_r.in_avail()); @@ -814,9 +814,9 @@ json::value details::http_msg_base::_extract_json(bool ignore_content_type) } // utf-8, usascii and ascii - else if(utility::details::str_icmp(charset, charset_types::utf8) - || utility::details::str_icmp(charset, charset_types::usascii) - || utility::details::str_icmp(charset, charset_types::ascii)) + else if(utility::details::str_iequal(charset, charset_types::utf8) + || utility::details::str_iequal(charset, charset_types::usascii) + || utility::details::str_iequal(charset, charset_types::ascii)) { std::string body; body.resize(buf_r.in_avail()); @@ -825,7 +825,7 @@ json::value details::http_msg_base::_extract_json(bool ignore_content_type) } // utf-16. - else if(utility::details::str_icmp(charset, charset_types::utf16)) + else if(utility::details::str_iequal(charset, charset_types::utf16)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -834,7 +834,7 @@ json::value details::http_msg_base::_extract_json(bool ignore_content_type) } // utf-16le - else if(utility::details::str_icmp(charset, charset_types::utf16le)) + else if(utility::details::str_iequal(charset, charset_types::utf16le)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -843,7 +843,7 @@ json::value details::http_msg_base::_extract_json(bool ignore_content_type) } // utf-16be - else if(utility::details::str_icmp(charset, charset_types::utf16be)) + else if(utility::details::str_iequal(charset, charset_types::utf16be)) { utf16string body; body.resize(buf_r.in_avail() / sizeof(utf16string::value_type)); @@ -898,7 +898,7 @@ static utility::string_t convert_body_to_string_t(const utility::string_t &conte } // Latin1 - if(utility::details::str_icmp(charset, charset_types::latin1)) + if(utility::details::str_iequal(charset, charset_types::latin1)) { std::string body; body.resize(streambuf.in_avail()); @@ -907,7 +907,7 @@ static utility::string_t convert_body_to_string_t(const utility::string_t &conte } // utf-8. - else if(utility::details::str_icmp(charset, charset_types::utf8)) + else if(utility::details::str_iequal(charset, charset_types::utf8)) { std::string body; body.resize(streambuf.in_avail()); @@ -916,7 +916,7 @@ static utility::string_t convert_body_to_string_t(const utility::string_t &conte } // utf-16. - else if(utility::details::str_icmp(charset, charset_types::utf16)) + else if(utility::details::str_iequal(charset, charset_types::utf16)) { utf16string body; body.resize(streambuf.in_avail() / sizeof(utf16string::value_type)); @@ -925,7 +925,7 @@ static utility::string_t convert_body_to_string_t(const utility::string_t &conte } // utf-16le - else if(utility::details::str_icmp(charset, charset_types::utf16le)) + else if(utility::details::str_iequal(charset, charset_types::utf16le)) { utf16string body; body.resize(streambuf.in_avail() / sizeof(utf16string::value_type)); @@ -934,7 +934,7 @@ static utility::string_t convert_body_to_string_t(const utility::string_t &conte } // utf-16be - else if(utility::details::str_icmp(charset, charset_types::utf16be)) + else if(utility::details::str_iequal(charset, charset_types::utf16be)) { utf16string body; body.resize(streambuf.in_avail() / sizeof(utf16string::value_type)); @@ -1081,4 +1081,3 @@ const http_version http_versions::HTTP_1_1 = { 1, 1 }; #undef DAT #endif }} // namespace web::http - diff --git a/Release/src/http/oauth/oauth2.cpp b/Release/src/http/oauth/oauth2.cpp index e133a65202..247241933f 100644 --- a/Release/src/http/oauth/oauth2.cpp +++ b/Release/src/http/oauth/oauth2.cpp @@ -101,7 +101,7 @@ pplx::task oauth2_config::_request_token(uri_builder& request_body_ub) http_request request; request.set_method(methods::POST); request.set_request_uri(utility::string_t()); - + if(!user_agent().empty()) { request.headers().add(web::http::header_names::user_agent, user_agent()); @@ -169,7 +169,7 @@ oauth2_token oauth2_config::_parse_token_from_json(const json::value& token_json // As workaround we act as if 'token_type=bearer' was received. result.set_token_type(oauth2_strings::bearer); } - if (!utility::details::str_icmp(result.token_type(), oauth2_strings::bearer)) + if (!utility::details::str_iequal(result.token_type(), oauth2_strings::bearer)) { throw oauth2_exception(U("only 'token_type=bearer' access tokens are currently supported: ") + token_json.serialize()); } @@ -189,7 +189,7 @@ oauth2_token oauth2_config::_parse_token_from_json(const json::value& token_json if (json_expires_in_val.is_number()) result.set_expires_in(json_expires_in_val.as_number().to_int64()); - else + else { // Handle the case of a number as a JSON "string". // Using streams because std::stoll isn't avaliable on Android. diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index 4c06e52e2b..737ed12e1b 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -343,11 +343,7 @@ namespace if (scheme_begin) { components.m_scheme.assign(scheme_begin, scheme_end); - - // convert scheme to lowercase - std::transform(components.m_scheme.begin(), components.m_scheme.end(), components.m_scheme.begin(), [](utility::char_t c) { - return (utility::char_t)tolower(c); - }); + utility::details::inplace_tolower(components.m_scheme); } else { @@ -362,11 +358,7 @@ namespace if (host_begin) { components.m_host.assign(host_begin, host_end); - - // convert host to lowercase - std::transform(components.m_host.begin(), components.m_host.end(), components.m_host.begin(), [](utility::char_t c) { - return (utility::char_t)tolower(c); - }); + utility::details::inplace_tolower(components.m_host); } else { @@ -438,14 +430,9 @@ utility::string_t uri_components::join() // canonicalize components first // convert scheme to lowercase - std::transform(m_scheme.begin(), m_scheme.end(), m_scheme.begin(), [](utility::char_t c) { - return (utility::char_t)tolower(c); - }); - + utility::details::inplace_tolower(m_scheme); // convert host to lowercase - std::transform(m_host.begin(), m_host.end(), m_host.begin(), [](utility::char_t c) { - return (utility::char_t)tolower(c); - }); + utility::details::inplace_tolower(m_host); // canonicalize the path to have a leading slash if it's a full uri if (!m_host.empty() && m_path.empty()) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index be38907c6e..893de3729b 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -12,6 +12,9 @@ ****/ #include "stdafx.h" +#include +#include +#include #ifndef _WIN32 #if defined(__clang__) @@ -29,12 +32,94 @@ using namespace web; using namespace utility; using namespace utility::conversions; +namespace +{ + struct to_lower_ch_impl + { + char operator()(char c) const CPPREST_NOEXCEPT + { + if (c >= 'A' && c <= 'Z') + return static_cast(c - 'A' + 'a'); + return c; + } + + wchar_t operator()(wchar_t c) const CPPREST_NOEXCEPT + { + if (c >= L'A' && c <= L'Z') + return static_cast(c - L'A' + L'a'); + return c; + } + }; + + constexpr to_lower_ch_impl to_lower_ch; + + struct eq_lower_ch_impl + { + template + inline CharT operator()(const CharT left, const CharT right) const CPPREST_NOEXCEPT + { + return to_lower_ch(left) == to_lower_ch(right); + } + }; + + constexpr eq_lower_ch_impl eq_lower_ch; + + struct lt_lower_ch_impl + { + template + inline CharT operator()(const CharT left, const CharT right) const CPPREST_NOEXCEPT + { + return to_lower_ch(left) < to_lower_ch(right); + } + }; + + constexpr lt_lower_ch_impl lt_lower_ch; +} + namespace utility { namespace details { +_ASYNCRTIMP bool __cdecl str_iequal(const std::string &left, const std::string &right) CPPREST_NOEXCEPT +{ + return left.size() == right.size() + && std::equal(left.cbegin(), left.cend(), right.cbegin(), eq_lower_ch); +} + +_ASYNCRTIMP bool __cdecl str_iequal(const std::wstring &left, const std::wstring &right) CPPREST_NOEXCEPT +{ + return left.size() == right.size() + && std::equal(left.cbegin(), left.cend(), right.cbegin(), eq_lower_ch); +} + +_ASYNCRTIMP bool __cdecl str_iless(const std::string &left, const std::string &right) CPPREST_NOEXCEPT +{ + return std::lexicographical_compare(left.cbegin(), left.cend(), right.cbegin(), right.cend(), lt_lower_ch); +} + +_ASYNCRTIMP bool __cdecl str_iless(const std::wstring &left, const std::wstring &right) CPPREST_NOEXCEPT +{ + return std::lexicographical_compare(left.cbegin(), left.cend(), right.cbegin(), right.cend(), lt_lower_ch); +} + +_ASYNCRTIMP void __cdecl inplace_tolower(std::string &target) CPPREST_NOEXCEPT +{ + for (auto& ch : target) + { + ch = to_lower_ch(ch); + } +} + +_ASYNCRTIMP void __cdecl inplace_tolower(std::wstring &target) CPPREST_NOEXCEPT +{ + for (auto& ch : target) + { + ch = to_lower_ch(ch); + } +} + #if !defined(ANDROID) && !defined(__ANDROID__) std::once_flag g_c_localeFlag; std::unique_ptr g_c_locale(nullptr, [](scoped_c_thread_locale::xplat_locale *){}); @@ -205,7 +290,7 @@ std::error_condition windows_category_impl::default_error_condition(int errorCod // First see if the STL implementation can handle the mapping for common cases. const std::error_condition errCondition = std::system_category().default_error_condition(errorCode); const std::string errConditionMsg = errCondition.message(); - if(_stricmp(errConditionMsg.c_str(), "unknown error") != 0) + if(!utility::details::str_iequal(errConditionMsg, "unknown error")) { return errCondition; } @@ -346,7 +431,7 @@ utf16string __cdecl conversions::utf8_to_utf16(const std::string &s) utf16string dest(count_utf8_to_utf16(s), L'\0'); utf16string::value_type* const destData = &dest[0]; size_t destIndex = 0; - + for (size_t index = 0; index < srcSize; ++index) { std::string::value_type src = srcData[index]; diff --git a/Release/src/websockets/client/ws_client_winrt.cpp b/Release/src/websockets/client/ws_client_winrt.cpp index c7197947df..38b4f7989d 100644 --- a/Release/src/websockets/client/ws_client_winrt.cpp +++ b/Release/src/websockets/client/ws_client_winrt.cpp @@ -86,7 +86,7 @@ class winrt_callback_client : public websocket_client_callback_impl, public std: { // Unfortunately the MessageWebSocket API throws a COMException if you try to set the // 'Sec-WebSocket-Protocol' header here. It requires you to go through their API instead. - if (!utility::details::str_icmp(header.first, protocolHeader)) + if (!utility::details::str_iequal(header.first, protocolHeader)) { m_msg_websocket->SetRequestHeader(Platform::StringReference(header.first.c_str()), Platform::StringReference(header.second.c_str())); } @@ -171,7 +171,7 @@ class winrt_callback_client : public websocket_client_callback_impl, public std: std::weak_ptr thisWeakPtr = shared_from_this(); return pplx::create_task(m_msg_websocket->ConnectAsync(uri)).then([thisWeakPtr](pplx::task result) -> pplx::task { - // result.get() should happen before anything else, to make sure there is no unobserved exception + // result.get() should happen before anything else, to make sure there is no unobserved exception // in the task chain. try { @@ -421,7 +421,7 @@ class winrt_callback_client : public websocket_client_callback_impl, public std: // External callback for handling received and close event std::function m_external_message_handler; std::function m_external_close_handler; - + // Queue to track pending sends outgoing_msg_queue m_out_queue; }; diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 8f2658a8f5..66b85744f4 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -338,7 +338,7 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: // Add any request headers specified by the user. for (const auto & header : headers) { - if (!utility::details::str_icmp(header.first, g_subProtocolHeader)) + if (!utility::details::str_iequal(header.first, g_subProtocolHeader)) { con->append_header(utility::conversions::to_utf8string(header.first), utility::conversions::to_utf8string(header.second)); } @@ -806,4 +806,3 @@ websocket_callback_client::websocket_callback_client(websocket_client_config con }}} #endif - From 6b1e9d47702814c129255b0e91e19dafb651801e Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 1 Aug 2018 11:25:17 -0700 Subject: [PATCH 397/609] Push version to 2.10.3 --- Build/version.props | 2 +- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Build/version.props b/Build/version.props index 81b45b0316..983ce9e3c5 100644 --- a/Build/version.props +++ b/Build/version.props @@ -4,7 +4,7 @@ cpprest 2 10 - 2 + 3 $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index aea81d7c0d..5a60107b75 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 2) +set(CPPREST_VERSION_REVISION 3) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index f3d9602e67..a4cf42cb5b 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,7 +5,7 @@ */ #define CPPREST_VERSION_REVISION 2 #define CPPREST_VERSION_MINOR 10 -#define CPPREST_VERSION_MAJOR 2 +#define CPPREST_VERSION_MAJOR 3 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) From e388a2e523f4d0b6aee2bb923637d82d8b969556 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Thu, 2 Aug 2018 15:40:30 -0700 Subject: [PATCH 398/609] Update changelog --- changelog.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/changelog.md b/changelog.md index c3db452003..047ca874f3 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,12 @@ +cpprestsdk (2.10.3) +---------------------- +* Added a root `CMakeLists.txt` to improve support for VS2017 Open Folder. +* PR#809 improves support for `/permissive-` in MSVC +* Issue#804 fixed a regression due to compression support; we no longer fail on unknown Content-Encoding headers if we did not set Accepts-Encoding +* PR#813 fixes build failure with boost 1.63 +* PR#779 PR#787 suppress and fix some warnings with new versions of gcc and clang +-- cpprestsdk team THU, 2 Aug 2018 15:52:00 -0800 + cpprestsdk (2.10.0) ---------------------- * Removed VS2013 MSBuild files. Use CMake with the "Visual Studio 12 2013" generator. From 8edc9a474c6a77bc5ba9984f3704ac56861b6c08 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Thu, 2 Aug 2018 19:35:36 -0700 Subject: [PATCH 399/609] Deduplicate some code in HTTP headers. (#825) --- Release/include/cpprest/http_headers.h | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index f5bee96535..2bc1975acd 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -145,13 +145,15 @@ class http_headers template void add(const key_type& name, const _t1& value) { - if (has(name)) + auto printedValue = utility::conversions::details::print_string(value); + auto& mapVal = m_headers[name]; + if (mapVal.empty()) { - m_headers[name].append(_XPLATSTR(", ")).append(utility::conversions::details::print_string(value)); + mapVal = std::move(printedValue); } else { - m_headers[name] = utility::conversions::details::print_string(value); + mapVal.append(_XPLATSTR(", ")).append(std::move(printedValue)); } } @@ -212,20 +214,12 @@ class http_headers bool match(const key_type &name, _t1 &value) const { auto iter = m_headers.find(name); - if (iter != m_headers.end()) - { - // Check to see if doesn't have a value. - if(iter->second.empty()) - { - bind_impl(iter->second, value); - return true; - } - return bind_impl(iter->second, value); - } - else + if (iter == m_headers.end()) { return false; } + + return bind_impl(iter->second, value) || iter->second.empty(); } /// @@ -311,6 +305,7 @@ class http_headers ref = utility::conversions::to_utf16string(text); return true; } + bool bind_impl(const key_type &text, std::string &ref) const { ref = utility::conversions::to_utf8string(text); From c214c811b9666f71be791a713f967c974ba886bf Mon Sep 17 00:00:00 2001 From: mobileben Date: Thu, 2 Aug 2018 19:46:23 -0700 Subject: [PATCH 400/609] =?UTF-8?q?#436=20Building=20iOS=20doesn=E2=80=99t?= =?UTF-8?q?=20seem=20to=20work=20(#776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This moves iOS.cmake into the file so there is on need to add it. Also allows for boost to be static libs versus framework --- Build_iOS/CMakeLists.txt | 6 +- Build_iOS/fix_ios_cmake_compiler.patch | 18 -- Build_iOS/iOS.cmake | 225 +++++++++++++++++++ Release/CMakeLists.txt | 2 +- Release/cmake/cpprest_find_boost.cmake | 17 +- Release/src/http/client/http_client_asio.cpp | 2 +- 6 files changed, 244 insertions(+), 26 deletions(-) delete mode 100644 Build_iOS/fix_ios_cmake_compiler.patch create mode 100644 Build_iOS/iOS.cmake diff --git a/Build_iOS/CMakeLists.txt b/Build_iOS/CMakeLists.txt index 16782b7d83..1c1ea90152 100644 --- a/Build_iOS/CMakeLists.txt +++ b/Build_iOS/CMakeLists.txt @@ -3,7 +3,11 @@ cmake_minimum_required(VERSION 2.6) enable_testing() -set(TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ios-cmake/toolchain/iOS.cmake") +if (CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET) + set (ENV{CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET} ${CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET}) +endif() + +set(TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/iOS.cmake") set(SIM_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/build.i386" CACHE INTERNAL "") set(SIM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Release" CACHE INTERNAL "") diff --git a/Build_iOS/fix_ios_cmake_compiler.patch b/Build_iOS/fix_ios_cmake_compiler.patch deleted file mode 100644 index 85eeec18c4..0000000000 --- a/Build_iOS/fix_ios_cmake_compiler.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/toolchain/iOS.cmake b/toolchain/iOS.cmake -index 195e3fc..567a8d3 100644 ---- a/toolchain/iOS.cmake -+++ b/toolchain/iOS.cmake -@@ -45,10 +45,10 @@ if (CMAKE_UNAME) - string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") - endif (CMAKE_UNAME) - --# Force the compilers to gcc for iOS -+# Force the compilers to clang for iOS - include (CMakeForceCompiler) --CMAKE_FORCE_C_COMPILER (/usr/bin/gcc Apple) --CMAKE_FORCE_CXX_COMPILER (/usr/bin/g++ Apple) -+CMAKE_FORCE_C_COMPILER (/usr/bin/clang Apple) -+CMAKE_FORCE_CXX_COMPILER (/usr/bin/clang++ Apple) - set(CMAKE_AR ar CACHE FILEPATH "" FORCE) - - # Skip the platform compiler checks for cross compiling diff --git a/Build_iOS/iOS.cmake b/Build_iOS/iOS.cmake new file mode 100644 index 0000000000..7001592b30 --- /dev/null +++ b/Build_iOS/iOS.cmake @@ -0,0 +1,225 @@ +# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake +# files which are included with CMake 2.8.4 +# It has been altered for iOS development + +# Options: +# +# IOS_PLATFORM = OS (default) or SIMULATOR or SIMULATOR64 +# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders +# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch. +# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch. +# +# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder +# By default this location is automatcially chosen based on the IOS_PLATFORM value above. +# If set manually, it will override the default location and force the user of a particular Developer Platform +# +# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder +# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value. +# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path. +# If set manually, this will force the use of a specific SDK version + +# Macros: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE) +# A convenience macro for setting xcode specific properties on targets +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1") +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the iOS environment. +# Thanks to the android-cmake project for providing the command + +# Standard settings +set (CMAKE_SYSTEM_NAME Darwin) +set (CMAKE_SYSTEM_VERSION 1) +set (UNIX True) +set (APPLE True) +set (IOS True) + +# Required as of cmake 2.8.10 +set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE) + +# Allow external setting of CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET. This is clumsy +# but it provides flexibility of not having to hardcode the deployment version in the file or have +# numerous copies of the file +if ($ENV{CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET $ENV{CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET}) +endif ($ENV{CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET}) + +# Determine the cmake host system version so we know where to find the iOS SDKs +find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin) +if (CMAKE_UNAME) + exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) + string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") +endif (CMAKE_UNAME) + +# Use clang. Use xcrun to determine the location +EXEC_PROGRAM(xcrun ARGS -find clang OUTPUT_VARIABLE APPLE_CLANG) +EXEC_PROGRAM(xcrun ARGS -find clang++ OUTPUT_VARIABLE APPLE_CLANGPP) +set (CMAKE_C_COMPILER ${APPLE_CLANG}) +set (CMAKE_CXX_COMPILER ${APPLE_CLANGPP}) + +set (CMAKE_AR ar CACHE FILEPATH "" FORCE) + +set (CMAKE_THREAD_LIBS_INIT "-lpthread") +set (CMAKE_HAVE_THREADS_LIBRARY 1) +set (CMAKE_USE_WIN32_THREADS_INIT 0) +set (CMAKE_USE_PTHREADS_INIT 1) + +# Skip the platform compiler checks for cross compiling +set (CMAKE_CXX_COMPILER_WORKS TRUE) +set (CMAKE_C_COMPILER_WORKS TRUE) + +# All iOS/Darwin specific settings - some may be redundant +set (CMAKE_SHARED_LIBRARY_PREFIX "lib") +set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set (CMAKE_SHARED_MODULE_PREFIX "lib") +set (CMAKE_SHARED_MODULE_SUFFIX ".so") +set (CMAKE_MODULE_EXISTS 1) +set (CMAKE_DL_LIBS "") + +set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +# Hidden visibilty is required for cxx on iOS +set (CMAKE_C_FLAGS_INIT "") +set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden") + +set (CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "" CACHE STRING "Force unset of CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN" FORCE) + +set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") +set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") + +set (CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names") +set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names") +set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a") +set (CMAKE_MACOSX_BUNDLE ON) +set (CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED OFF) + + +# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree +# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache +# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun) +# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex +if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool) +endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + +# Setup iOS platform unless specified manually with IOS_PLATFORM +if (NOT DEFINED IOS_PLATFORM) + set (IOS_PLATFORM "OS") +endif (NOT DEFINED IOS_PLATFORM) +set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") + +# Setup building for arm64 or not +if (NOT DEFINED BUILD_ARM64) + set (BUILD_ARM64 true) +endif (NOT DEFINED BUILD_ARM64) +set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not") + +# Check the platform selection and setup for developer root +if (${IOS_PLATFORM} STREQUAL "OS") + set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + + # This causes the installers to properly locate the output libraries + set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +else (${IOS_PLATFORM} STREQUAL "OS") + message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR") +endif (${IOS_PLATFORM} STREQUAL "OS") + +# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT +# Note Xcode 4.3 changed the installation location, choose the most recent one available +exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR) +set (XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) + if (EXISTS ${XCODE_POST_43_ROOT}) + set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT}) + elseif(EXISTS ${XCODE_PRE_43_ROOT}) + set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT}) + endif (EXISTS ${XCODE_POST_43_ROOT}) +endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) +set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform") + +# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT +if (NOT DEFINED CMAKE_IOS_SDK_ROOT) + file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*") + if (_CMAKE_IOS_SDKS) + list (SORT _CMAKE_IOS_SDKS) + list (REVERSE _CMAKE_IOS_SDKS) + list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT) + else (_CMAKE_IOS_SDKS) + message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.") + endif (_CMAKE_IOS_SDKS) + message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}") +endif (NOT DEFINED CMAKE_IOS_SDK_ROOT) +set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK") + +# Set the sysroot default to the most recent SDK +set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") + +# set the architecture for iOS +if (${IOS_PLATFORM} STREQUAL "OS") + set (IOS_ARCH armv7 armv7s arm64) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") + set (IOS_ARCH i386) +elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR64") + set (IOS_ARCH x86_64) +endif (${IOS_PLATFORM} STREQUAL "OS") + +set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS") + +# Set the find root to the iOS developer roots and to user defined paths +set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root") + +# default to searching for frameworks first +set (CMAKE_FIND_FRAMEWORK FIRST) + +# set up the default search directories for frameworks +set (CMAKE_SYSTEM_FRAMEWORK_PATH + ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks + ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks + ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks +) + +# only search the iOS sdks, not the remainder of the host filesystem +set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + + +# This little macro lets you set any XCode specific property +macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) + set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) +endmacro (set_xcode_property) + + +# This macro lets you find executable programs on the host system +macro (find_host_package) + set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set (IOS FALSE) + + find_package(${ARGN}) + + set (IOS TRUE) + set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) + set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endmacro (find_host_package) + diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 5a60107b75..1c6f88f286 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -115,7 +115,7 @@ set(ANDROID_STL_FLAGS) # Platform (not compiler) specific settings if(IOS) # The cxx_flags must be reset here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag. - set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden") + set(CMAKE_CXX_FLAGS "-fvisibility=hidden") elseif(ANDROID) if(ARM) set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/thumb/libgnustl_static.a") diff --git a/Release/cmake/cpprest_find_boost.cmake b/Release/cmake/cpprest_find_boost.cmake index 298b080aae..67f5dad9b8 100644 --- a/Release/cmake/cpprest_find_boost.cmake +++ b/Release/cmake/cpprest_find_boost.cmake @@ -4,9 +4,15 @@ function(cpprest_find_boost) endif() if(IOS) - set(IOS_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../Build_iOS") - set(Boost_LIBRARIES "${IOS_SOURCE_DIR}/boost.framework/boost" CACHE INTERNAL "") - set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers" CACHE INTERNAL "") + if (EXISTS "${PROJECT_SOURCE_DIR}/../Build_iOS/boost") + set(IOS_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../Build_iOS") + set(Boost_LIBRARIES "${IOS_SOURCE_DIR}/boost/lib" CACHE INTERNAL "") + set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost/include" CACHE INTERNAL "") + else() + set(IOS_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../Build_iOS") + set(Boost_LIBRARIES "${IOS_SOURCE_DIR}/boost.framework/boost" CACHE INTERNAL "") + set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers" CACHE INTERNAL "") + endif() elseif(ANDROID) set(Boost_COMPILER "-clang") if(ARM) @@ -42,8 +48,9 @@ function(cpprest_find_boost) endif() set(_prev "${_lib}") endforeach() - target_link_libraries(cpprestsdk_boost_internal INTERFACE "$") - + if (NOT IOS OR NOT EXISTS "${PROJECT_SOURCE_DIR}/../Build_iOS/boost") + target_link_libraries(cpprestsdk_boost_internal INTERFACE "$") + endif() else() if(ANDROID) target_link_libraries(cpprestsdk_boost_internal INTERFACE diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 3a79963a0c..df25c32aaa 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -47,7 +47,7 @@ #include #include -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__clang__) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) #define AND_CAPTURE_MEMBER_FUNCTION_POINTERS From c8c92277dbc3639dba479d823b4719b28e404e90 Mon Sep 17 00:00:00 2001 From: "sridhar madhugiri (msft)" Date: Thu, 2 Aug 2018 22:24:23 -0700 Subject: [PATCH 401/609] Improve error handling in on_accept (#750) * Improve error handling in on_accept * Move lock to the top of the function * Lock shared data at the right locations. * [http_listener] improve refcount and lifetime management by using RAII. --- .../src/http/listener/http_server_asio.cpp | 98 ++++++++++++++----- 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 78193fa3e2..bef47126dc 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -200,7 +200,7 @@ namespace } private: - void on_accept(boost::asio::ip::tcp::socket* socket, const boost::system::error_code& ec); + void on_accept(std::unique_ptr socket, const boost::system::error_code& ec); }; @@ -333,7 +333,6 @@ class asio_server_connection std::unique_ptr m_ssl_context; std::unique_ptr m_ssl_stream; -public: asio_server_connection(std::unique_ptr socket, http_linux_server* server, hostport_listener* parent) : m_socket(std::move(socket)) , m_request_buf() @@ -341,12 +340,34 @@ class asio_server_connection , m_p_server(server) , m_p_parent(parent) , m_close(false) + , m_chunked(false) , m_refs(1) { } - will_deref_and_erase_t start(bool is_https, const std::function& ssl_context_callback) + struct Dereferencer + { + void operator()(asio_server_connection* conn) const { conn->deref(); } + }; + +public: + using refcount_ptr = std::unique_ptr; + + static refcount_ptr create(std::unique_ptr socket, http_linux_server* server, hostport_listener* parent) + { + return refcount_ptr(new asio_server_connection(std::move(socket), server, parent)); + } + + refcount_ptr get_reference() { + ++m_refs; + return refcount_ptr(this); + } + + will_erase_from_parent_t start_connection(bool is_https, const std::function& ssl_context_callback) + { + auto unique_reference = this->get_reference(); + if (is_https) { m_ssl_context = make_unique(boost::asio::ssl::context::sslv23); @@ -360,11 +381,14 @@ class asio_server_connection { (will_deref_and_erase_t)this->start_request_response(); }); - return will_deref_and_erase_t{}; + unique_reference.release(); + return will_erase_from_parent_t{}; } else { - return start_request_response(); + (will_deref_and_erase_t)start_request_response(); + unique_reference.release(); + return will_erase_from_parent_t{}; } } @@ -385,7 +409,7 @@ class asio_server_connection will_deref_and_erase_t dispatch_request_to_listener(); will_erase_from_parent_t do_response() { - ++m_refs; + auto unique_reference = this->get_reference(); m_request.get_response().then([=](pplx::task r_task) { http_response response; @@ -406,11 +430,12 @@ class asio_server_connection (will_deref_and_erase_t)this->async_write(&asio_server_connection::handle_headers_written, response); }); }); + unique_reference.release(); return will_erase_from_parent_t{}; } will_erase_from_parent_t do_bad_response() { - ++m_refs; + auto unique_reference = this->get_reference(); m_request.get_response().then([=](pplx::task r_task) { http_response response; @@ -428,6 +453,7 @@ class asio_server_connection (will_deref_and_erase_t)async_write(&asio_server_connection::handle_headers_written, response); }); + unique_reference.release(); return will_erase_from_parent_t{}; } @@ -495,10 +521,13 @@ void hostport_listener::start() m_acceptor->listen(0 != m_backlog ? m_backlog : socket_base::max_connections); auto socket = new ip::tcp::socket(service); + std::unique_ptr usocket(socket); m_acceptor->async_accept(*socket, [this, socket](const boost::system::error_code& ec) { - this->on_accept(socket, ec); + std::unique_ptr usocket(socket); + this->on_accept(std::move(usocket), ec); }); + usocket.release(); } void asio_server_connection::close() @@ -538,30 +567,53 @@ will_deref_and_erase_t asio_server_connection::start_request_response() return will_deref_and_erase_t{}; } -void hostport_listener::on_accept(ip::tcp::socket* socket, const boost::system::error_code& ec) +void hostport_listener::on_accept(std::unique_ptr socket, const boost::system::error_code& ec) { - std::unique_ptr usocket(std::move(socket)); + // Listener closed + if (ec == boost::asio::error::operation_aborted) + { + return; + } + + std::lock_guard lock(m_connections_lock); + // Handle successful accept if (!ec) { - auto conn = new asio_server_connection(std::move(usocket), m_p_server, this); + auto conn = asio_server_connection::create(std::move(socket), m_p_server, this); - std::lock_guard lock(m_connections_lock); - m_connections.insert(conn); - conn->start(m_is_https, m_ssl_context_callback); - if (m_connections.size() == 1) - m_all_connections_complete.reset(); + m_connections.insert(conn.get()); + try + { + (will_erase_from_parent_t)conn->start_connection(m_is_https, m_ssl_context_callback); + // at this point an asynchronous task has been launched which will call + // m_connections.erase(conn.get()) eventually - if (m_acceptor) + // the following cannot throw + if (m_connections.size() == 1) + m_all_connections_complete.reset(); + } + catch (boost::system::system_error&) { - // spin off another async accept - auto newSocket = new ip::tcp::socket(crossplat::threadpool::shared_instance().service()); - m_acceptor->async_accept(*newSocket, [this, newSocket](const boost::system::error_code& ec) - { - this->on_accept(newSocket, ec); - }); + // boost ssl apis throw boost::system::system_error. + // Exception indicates something went wrong setting ssl context. + // Drop connection and continue handling other connections. + m_connections.erase(conn.get()); } } + + if (m_acceptor) + { + // spin off another async accept + auto newSocket = new ip::tcp::socket(crossplat::threadpool::shared_instance().service()); + std::unique_ptr usocket(newSocket); + m_acceptor->async_accept(*newSocket, [this, newSocket](const boost::system::error_code& ec) + { + std::unique_ptr usocket(newSocket); + this->on_accept(std::move(usocket), ec); + }); + usocket.release(); + } } will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::system::error_code& ec) From 5021303f339f10c946022401d46d5abdc7c8cb48 Mon Sep 17 00:00:00 2001 From: VZ Date: Fri, 3 Aug 2018 08:18:05 +0200 Subject: [PATCH 402/609] Fix handling of timed out connections kept alive in connection pool under Unix (#762) * Add asio_connection::was_closed_by_server() to reduce duplication Reduce code duplication between ssl_proxy_tunnel::handle_status_line() and the method with the same name in asio_context itself by moving the common handling of connections closed by server into a new function. No real changes, this is a pure refactoring. * Fix checking for server-side closure of HTTPS connections When an SSL connection times out due to being closed by server, a different error code is returned, so we need to check for it too in was_closed_by_server(). Without this, losing connection was not detected at all when using HTTPS, resulting in "Failed to read HTTP status line" errors whenever the same http_client was reused after more than the server keep alive timeout of inactivity. See #592. * Fix bug with using re-opened connections with ASIO Creating a new request when the existing connection being used was closed by the server didn't work correctly because the associated input stream was already exhausted, as its contents had been already "sent" to the server using the now discarded connection, so starting a new request using the same body stream never worked. Fix this by explicitly rewinding the stream to the beginning before using it again. Note that even with this fix using a custom body stream which is not positioned at the beginning initially (or which doesn't support rewinding) still wouldn't work, but at least it fixes the most common use case. See #592. * Reduce duplicate code between ssl_proxy and asio_context in handle_read_status_line. Avoid increasing public surface with rewind function. --- Release/src/http/client/http_client_asio.cpp | 126 +++++++++++-------- 1 file changed, 74 insertions(+), 52 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index df25c32aaa..3bf1fcba23 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -28,6 +28,7 @@ #endif #include #include +#include #include #include #include @@ -170,6 +171,45 @@ class asio_connection bool keep_alive() const { return m_keep_alive; } bool is_ssl() const { return m_ssl_stream ? true : false; } + // Check if the error code indicates that the connection was closed by the + // server: this is used to detect if a connection in the pool was closed during + // its period of inactivity and we should reopen it. + bool was_reused_and_closed_by_server(const boost::system::error_code& ec) const + { + if (!is_reused()) + { + // Don't bother reopening the connection if it's a new one: in this + // case, even if the connection was really lost, it's still a real + // error and we shouldn't try to reopen it. + return false; + } + + // These errors tell if connection was closed. + if ((boost::asio::error::eof == ec) + || (boost::asio::error::connection_reset == ec) + || (boost::asio::error::connection_aborted == ec)) + { + return true; + } + + if (is_ssl()) + { + // For SSL connections, we can also get a different error due to + // incorrect secure connection shutdown if it was closed by the + // server due to inactivity. Unfortunately, the exact error we get + // in this case depends on the Boost.Asio version used. +#if BOOST_ASIO_VERSION >= 101008 + if (boost::asio::ssl::error::stream_truncated == ec) + return true; +#else // Asio < 1.10.8 didn't have ssl::error::stream_truncated + if (boost::system::error_code(ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), boost::asio::error::get_ssl_category()) == ec) + return true; +#endif + } + + return false; + } + template void async_connect(const Iterator &begin, const Handler &handler) { @@ -578,37 +618,13 @@ class asio_context : public request_context, public std::enable_shared_from_this return; } - m_context->m_connection->upgrade_to_ssl(m_context->m_http_client->client_config().get_ssl_context_callback()); + m_context->upgrade_to_ssl(); m_ssl_tunnel_established(m_context); } else { - // These errors tell if connection was closed. - const bool socket_was_closed((boost::asio::error::eof == ec) - || (boost::asio::error::connection_reset == ec) - || (boost::asio::error::connection_aborted == ec)); - if (socket_was_closed && m_context->m_connection->is_reused()) - { - // Failed to write to socket because connection was already closed while it was in the pool. - // close() here ensures socket is closed in a robust way and prevents the connection from being put to the pool again. - m_context->m_connection->close(); - - // Create a new context and copy the request object, completion event and - // cancellation registration to maintain the old state. - // This also obtains a new connection from pool. - auto new_ctx = m_context->create_request_context(m_context->m_http_client, m_context->m_request); - new_ctx->m_request_completion = m_context->m_request_completion; - new_ctx->m_cancellationRegistration = m_context->m_cancellationRegistration; - - auto client = std::static_pointer_cast(m_context->m_http_client); - // Resend the request using the new context. - client->send_request(new_ctx); - } - else - { - m_context->report_error("Failed to read HTTP status line from proxy", ec, httpclient_errorcode_context::readheader); - } + m_context->handle_failed_read_status_line(ec, "Failed to read HTTP status line from proxy"); } } @@ -619,7 +635,6 @@ class asio_context : public request_context, public std::enable_shared_from_this boost::asio::streambuf m_response; }; - enum class http_proxy_type { none, @@ -821,6 +836,11 @@ class asio_context : public request_context, public std::enable_shared_from_this } private: + void upgrade_to_ssl() + { + m_connection->upgrade_to_ssl(m_http_client->client_config().get_ssl_context_callback()); + } + std::string generate_basic_auth_header() { std::string header; @@ -1173,31 +1193,33 @@ class asio_context : public request_context, public std::enable_shared_from_this } else { - // These errors tell if connection was closed. - const bool socket_was_closed((boost::asio::error::eof == ec) - || (boost::asio::error::connection_reset == ec) - || (boost::asio::error::connection_aborted == ec)); - if (socket_was_closed && m_connection->is_reused()) - { - // Failed to write to socket because connection was already closed while it was in the pool. - // close() here ensures socket is closed in a robust way and prevents the connection from being put to the pool again. - m_connection->close(); - - // Create a new context and copy the request object, completion event and - // cancellation registration to maintain the old state. - // This also obtains a new connection from pool. - auto new_ctx = create_request_context(m_http_client, m_request); - new_ctx->m_request_completion = m_request_completion; - new_ctx->m_cancellationRegistration = m_cancellationRegistration; - - auto client = std::static_pointer_cast(m_http_client); - // Resend the request using the new context. - client->send_request(new_ctx); - } - else - { - report_error("Failed to read HTTP status line", ec, httpclient_errorcode_context::readheader); - } + handle_failed_read_status_line(ec, "Failed to read HTTP status line"); + } + } + + void handle_failed_read_status_line(const boost::system::error_code& ec, const char* generic_error_message) + { + if (m_connection->was_reused_and_closed_by_server(ec)) + { + // Failed to write to socket because connection was already closed while it was in the pool. + // close() here ensures socket is closed in a robust way and prevents the connection from being put to the pool again. + m_connection->close(); + + // Create a new context and copy the request object, completion event and + // cancellation registration to maintain the old state. + // This also obtains a new connection from pool. + auto new_ctx = create_request_context(m_http_client, m_request); + new_ctx->m_request._get_impl()->instream().seek(0); + new_ctx->m_request_completion = m_request_completion; + new_ctx->m_cancellationRegistration = m_cancellationRegistration; + + auto client = std::static_pointer_cast(m_http_client); + // Resend the request using the new context. + client->send_request(new_ctx); + } + else + { + report_error(generic_error_message, ec, httpclient_errorcode_context::readheader); } } From ecabd2b0e0140b2c85cbaa376713f625be99f922 Mon Sep 17 00:00:00 2001 From: Gianfranco Costamagna Date: Fri, 3 Aug 2018 08:39:05 +0200 Subject: [PATCH 403/609] Update CMakeLists.txt to install the cmake bindings in the right location (#737) * Update CMakeLists.txt to install the cmake bindings in the right location /usr/lib/cpprestsdk is not the correct FHS standard cmake location. It should be placed in /usr/lib//cmake/cpprestsdk instead. Same goes for libraries, support multiarch location if we use UNIX * Revert changes to CPPREST_EXPORT_DIR. Use GNUInstallDirs on all platforms. --- Release/CMakeLists.txt | 1 + Release/src/CMakeLists.txt | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 1c6f88f286..a79a4ffbbc 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -63,6 +63,7 @@ include(cmake/cpprest_find_zlib.cmake) include(cmake/cpprest_find_openssl.cmake) include(cmake/cpprest_find_websocketpp.cmake) include(CheckIncludeFiles) +include(GNUInstallDirs) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 86a2f45b3e..a34605bda2 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -253,9 +253,9 @@ if(CPPREST_INSTALL) install( TARGETS ${CPPREST_TARGETS} EXPORT cpprestsdk-targets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) configure_file(../cmake/cpprestsdk-config.in.cmake "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config.cmake" @ONLY) From 14adc2e631fdf476969f2bdcb415d895400e7af1 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Thu, 2 Aug 2018 23:45:08 -0700 Subject: [PATCH 404/609] Various micro perf fixes and cleanup found while implementing CN overrides so far (#818) * Microperf: Use lock_guard instead of unique_lock. * Bill hates lock_guard more. * Ref them connections. * Demacroize. * Commonize port and merge some CRLFs into adjacent string literals. * Add missing template keyword. * Avoid stringstream in constructing the proxy_str. * Remove unused forward declarations of some HTTP things. * Use NOMINMAX instead of undef min and max everywhere. * Bunch of inheritance hygiene. * What do you mean you want examples to compile? * More CR comments from Robert. * Add static. * Use existing to_string_t. --- Release/include/cpprest/asyncrt_utils.h | 8 +-- .../include/cpprest/details/web_utilities.h | 11 ---- Release/include/cpprest/streams.h | 2 +- Release/src/http/client/http_client_asio.cpp | 50 +++++++++---------- .../src/http/client/http_client_winhttp.cpp | 23 +++------ Release/src/http/client/http_client_winrt.cpp | 15 +++--- Release/src/http/common/http_msg.cpp | 3 -- .../src/http/listener/http_server_asio.cpp | 7 +-- .../src/http/listener/http_server_httpsys.cpp | 15 +++--- Release/src/json/json.cpp | 4 -- Release/src/pch/stdafx.h | 3 +- .../src/websockets/client/ws_client_wspp.cpp | 15 +++--- 12 files changed, 60 insertions(+), 96 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index b5e61c9d14..3fbebd7d95 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -228,7 +228,7 @@ namespace conversions #if defined(__ANDROID__) template - inline std::string to_string(const T& t) + inline std::string to_string(const T t) { std::ostringstream os; os.imbue(std::locale::classic()); @@ -238,16 +238,16 @@ namespace conversions #endif template - inline utility::string_t to_string_t(T&& t) + inline utility::string_t to_string_t(const T t) { #ifdef _UTF16_STRINGS using std::to_wstring; - return to_wstring(std::forward(t)); + return to_wstring(t); #else #if !defined(__ANDROID__) using std::to_string; #endif - return to_string(std::forward(t)); + return to_string(t); #endif } diff --git a/Release/include/cpprest/details/web_utilities.h b/Release/include/cpprest/details/web_utilities.h index ba6416546e..f99a8aa933 100644 --- a/Release/include/cpprest/details/web_utilities.h +++ b/Release/include/cpprest/details/web_utilities.h @@ -14,17 +14,6 @@ namespace web { - -namespace http { namespace client { namespace details { -class winhttp_client; -class winrt_client; -class asio_context; -}}} -namespace websockets { namespace client { namespace details { -class winrt_callback_client; -class wspp_callback_client; -}}} - namespace details { diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index cb7cd4d0ea..d2923d3774 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -1748,7 +1748,7 @@ class type_parser parse(streams::streambuf buffer) { - return base::_parse_input,std::basic_string>(buffer, _accept_char, _extract_result); + return base::template _parse_input,std::basic_string>(buffer, _accept_char, _extract_result); } private: diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 3bf1fcba23..67d56c1e8f 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -15,9 +15,6 @@ #include "stdafx.h" -#undef min -#undef max - #include "cpprest/asyncrt_utils.h" #include "../common/internal_http_helpers.h" @@ -83,7 +80,7 @@ using utility::conversions::details::to_string; using std::to_string; #endif -#define CRLF std::string("\r\n") +static const std::string CRLF("\r\n"); namespace web { namespace http { @@ -213,14 +210,15 @@ class asio_connection template void async_connect(const Iterator &begin, const Handler &handler) { - std::unique_lock lock(m_socket_lock); - if (!m_closed) - m_socket.async_connect(begin, handler); - else { - lock.unlock(); - handler(boost::asio::error::operation_aborted); - } + std::lock_guard lock(m_socket_lock); + if (!m_closed) { + m_socket.async_connect(begin, handler); + return; + } + } // unlock + + handler(boost::asio::error::operation_aborted); } template @@ -339,7 +337,7 @@ class asio_connection /// } /// /// -class asio_connection_pool : public std::enable_shared_from_this +class asio_connection_pool final : public std::enable_shared_from_this { public: asio_connection_pool() : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) @@ -396,24 +394,25 @@ class asio_connection_pool : public std::enable_shared_from_this lock(self.m_lock); if (self.m_prev_epoch == self.m_epoch) { - self.m_connections.clear(); + connections.clear(); self.is_timer_running = false; return; } else { auto prev_epoch = self.m_prev_epoch; - auto erase_end = std::find_if(self.m_connections.begin(), self.m_connections.end(), + auto erase_end = std::find_if(connections.begin(), connections.end(), [prev_epoch](std::pair>& p) { return p.first > prev_epoch; }); - self.m_connections.erase(self.m_connections.begin(), erase_end); + connections.erase(connections.begin(), erase_end); start_epoch_interval(pool); } }); @@ -438,7 +437,7 @@ class asio_client final : public _http_client_communicator , m_start_with_ssl(base_uri().scheme() == U("https") && !this->client_config().proxy().is_specified()) {} - void send_request(const std::shared_ptr &request_ctx) override; + virtual void send_request(const std::shared_ptr &request_ctx) override; void release_connection(std::shared_ptr& conn) { @@ -468,7 +467,7 @@ class asio_client final : public _http_client_communicator const bool m_start_with_ssl; }; -class asio_context : public request_context, public std::enable_shared_from_this +class asio_context final : public request_context, public std::enable_shared_from_this { friend class asio_client; public: @@ -501,7 +500,7 @@ class asio_context : public request_context, public std::enable_shared_from_this return ctx; } - class ssl_proxy_tunnel : public std::enable_shared_from_this + class ssl_proxy_tunnel final : public std::enable_shared_from_this { public: ssl_proxy_tunnel(std::shared_ptr context, std::function)> ssl_tunnel_established) @@ -518,14 +517,15 @@ class asio_context : public request_context, public std::enable_shared_from_this const auto &base_uri = m_context->m_http_client->base_uri(); const auto &host = utility::conversions::to_utf8string(base_uri.host()); - const auto &port = base_uri.port(); + const int portRaw = base_uri.port(); + const int port = (portRaw != 0) ? portRaw : 443; std::ostream request_stream(&m_request); request_stream.imbue(std::locale::classic()); - request_stream << "CONNECT " << host << ":" << ((port != 0) ? port : 443) << " HTTP/1.1" << CRLF; - request_stream << "Host: " << host << ":" << ((port != 0) ? port : 443) << CRLF; - request_stream << "Proxy-Connection: Keep-Alive" << CRLF; + request_stream << "CONNECT " << host << ":" << port << " HTTP/1.1\r\n"; + request_stream << "Host: " << host << ":" << port << CRLF; + request_stream << "Proxy-Connection: Keep-Alive\r\n"; if(m_context->m_http_client->client_config().proxy().credentials().is_set()) { @@ -698,7 +698,7 @@ class asio_context : public request_context, public std::enable_shared_from_this request_stream.imbue(std::locale::classic()); const auto &host = utility::conversions::to_utf8string(base_uri.host()); - request_stream << utility::conversions::to_utf8string(method) << " " << utility::conversions::to_utf8string(encoded_resource) << " " << "HTTP/1.1" << CRLF; + request_stream << utility::conversions::to_utf8string(method) << " " << utility::conversions::to_utf8string(encoded_resource) << " " << "HTTP/1.1\r\n"; int port = base_uri.port(); @@ -766,7 +766,7 @@ class asio_context : public request_context, public std::enable_shared_from_this request_stream << utility::conversions::to_utf8string(::web::http::details::flatten_http_headers(ctx->m_request.headers())); request_stream << extra_headers; // Enforce HTTP connection keep alive (even for the old HTTP/1.0 protocol). - request_stream << "Connection: Keep-Alive" << CRLF << CRLF; + request_stream << "Connection: Keep-Alive\r\n\r\n"; // Start connection timeout timer. if (!ctx->m_timer.has_started()) @@ -1345,7 +1345,7 @@ class asio_context : public request_context, public std::enable_shared_from_this } else { - async_read_until_buffersize(octets + CRLF.size(), // + 2 for crlf + async_read_until_buffersize(octets + CRLF.size(), boost::bind(&asio_context::handle_chunk, shared_from_this(), boost::asio::placeholders::error, octets)); } } diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index f6d343c2b2..ce037a4954 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -23,9 +23,6 @@ #include #endif -#undef min -#undef max - namespace web { namespace http @@ -185,7 +182,7 @@ enum msg_body_type }; // Additional information necessary to track a WinHTTP request. -class winhttp_request_context : public request_context +class winhttp_request_context final : public request_context { public: @@ -248,7 +245,7 @@ class winhttp_request_context : public request_context std::shared_ptr m_self_reference; memory_holder m_body_data; - virtual void cleanup() + void cleanup() { if(m_request_handle != nullptr) { @@ -260,7 +257,7 @@ class winhttp_request_context : public request_context protected: - virtual void finish() + virtual void finish() override { request_context::finish(); assert(m_self_reference != nullptr); @@ -346,7 +343,7 @@ struct ie_proxy_config : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG }; // WinHTTP client. -class winhttp_client : public _http_client_communicator +class winhttp_client final : public _http_client_communicator { public: winhttp_client(http::uri address, http_client_config client_config) @@ -502,17 +499,13 @@ class winhttp_client : public _http_client_communicator } else { + proxy_str = uri.host(); if (uri.port() > 0) { - utility::ostringstream_t ss; - ss.imbue(std::locale::classic()); - ss << uri.host() << _XPLATSTR(":") << uri.port(); - proxy_str = ss.str(); - } - else - { - proxy_str = uri.host(); + proxy_str.push_back(_XPLATSTR(':')); + proxy_str.append(::utility::conversions::details::to_string_t(uri.port())); } + proxy_name = proxy_str.c_str(); } } diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index e8ee50a018..5a0697b489 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -28,9 +28,6 @@ using namespace std; using namespace Platform; using namespace Microsoft::WRL; -#undef min -#undef max - namespace web { namespace http @@ -41,7 +38,7 @@ namespace details { // Additional information necessary to track a WinRT request. -class winrt_request_context : public request_context +class winrt_request_context final : public request_context { public: @@ -63,7 +60,7 @@ class winrt_request_context : public request_context }; // Implementation of IXMLHTTPRequest2Callback. -class HttpRequestCallback : +class HttpRequestCallback final : public RuntimeClass, IXMLHTTPRequest2Callback, FtmBase> { public: @@ -190,7 +187,7 @@ class HttpRequestCallback : /// read and write operations. The I/O will be done off the UI thread, so there is no risk /// of causing the UI to become unresponsive. /// -class IRequestStream +class IRequestStream final : public Microsoft::WRL::RuntimeClass, ISequentialStream> { public: @@ -279,7 +276,7 @@ class IRequestStream /// read and write operations. The I/O will be done off the UI thread, so there is no risk /// of causing the UI to become unresponsive. /// -class IResponseStream +class IResponseStream final : public Microsoft::WRL::RuntimeClass, ISequentialStream> { public: @@ -353,7 +350,7 @@ class IResponseStream }; // WinRT client. -class winrt_client : public _http_client_communicator +class winrt_client final : public _http_client_communicator { public: winrt_client(http::uri&& address, http_client_config&& client_config) @@ -379,7 +376,7 @@ class winrt_client : public _http_client_communicator protected: // Start sending request. - void send_request(_In_ const std::shared_ptr &request) + virtual void send_request(_In_ const std::shared_ptr &request) override { http_request &msg = request->m_request; auto winrt_context = std::static_pointer_cast(request); diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index ece2d08c1e..8f218cb913 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -13,9 +13,6 @@ #include "stdafx.h" #include "../common/internal_http_helpers.h" -#undef min -#undef max - using namespace web; using namespace utility; using namespace concurrency; diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index bef47126dc..13b813b858 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -14,9 +14,6 @@ */ #include "stdafx.h" -#undef min -#undef max - #include #include #include @@ -1085,7 +1082,7 @@ will_deref_and_erase_t asio_server_connection::cancel_sending_response_with_erro { auto * context = static_cast(response._get_server_context()); context->m_response_completed.set_exception(eptr); - + // always terminate the connection since error happens return finish_request_response(); } @@ -1096,7 +1093,7 @@ will_deref_and_erase_t asio_server_connection::handle_write_chunked_response(con { return handle_response_written(response, ec); } - + auto readbuf = response._get_impl()->instream().streambuf(); if (readbuf.is_eof()) { diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 7d3cea203c..8da74d0083 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -22,9 +22,6 @@ #include "http_server_httpsys.h" #include "http_server_impl.h" -#undef min -#undef max - using namespace web; using namespace utility; using namespace concurrency; @@ -482,7 +479,7 @@ windows_request_context::~windows_request_context() // Bug is that task_completion_event accesses internal state after setting. // Workaround is to use a lock incurring additional synchronization, if can acquire // the lock then setting of the event has completed. - std::unique_lock lock(m_responseCompletedLock); + std::lock_guard lock(m_responseCompletedLock); // Add a task-based continuation so no exceptions thrown from the task go 'unobserved'. pplx::create_task(m_response_completed).then([](pplx::task t) @@ -759,7 +756,7 @@ void windows_request_context::init_response_callbacks(ShouldWaitForBody shouldWa catch (...) { // Should never get here, if we do there's a chance that a circular reference will cause leaks, - // or worse, undefined behaviour as we don't know who owns 'this' anymore + // or worse, undefined behaviour as we don't know who owns 'this' anymore _ASSERTE(false); m_response = http::http_response(status_codes::InternalError); } @@ -899,7 +896,7 @@ void windows_request_context::transmit_body() if ( !m_sending_in_chunks && !m_transfer_encoding ) { // We are done sending data. - std::unique_lock lock(m_responseCompletedLock); + std::lock_guard lock(m_responseCompletedLock); m_response_completed.set(); return; } @@ -1024,7 +1021,7 @@ void windows_request_context::send_response_body_io_completion(DWORD error_code, /// void windows_request_context::cancel_request_io_completion(DWORD, DWORD) { - std::unique_lock lock(m_responseCompletedLock); + std::lock_guard lock(m_responseCompletedLock); m_response_completed.set_exception(m_except_ptr); } @@ -1047,7 +1044,7 @@ void windows_request_context::cancel_request(std::exception_ptr except_ptr) if(error_code != NO_ERROR && error_code != ERROR_IO_PENDING) { CancelThreadpoolIo(pServer->m_threadpool_io); - std::unique_lock lock(m_responseCompletedLock); + std::lock_guard lock(m_responseCompletedLock); m_response_completed.set_exception(except_ptr); } } @@ -1059,4 +1056,4 @@ std::unique_ptr make_http_httpsys_server() }}}} -#endif +#endif diff --git a/Release/src/json/json.cpp b/Release/src/json/json.cpp index 04ddbe0fe4..e5a6089aea 100644 --- a/Release/src/json/json.cpp +++ b/Release/src/json/json.cpp @@ -13,9 +13,6 @@ #include "stdafx.h" -#undef min -#undef max - using namespace web; bool json::details::g_keep_json_object_unsorted = false; @@ -519,4 +516,3 @@ const web::json::details::json_error_category_impl& web::json::details::json_err #endif return instance; } - diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index 1532db2f54..93ad966509 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -20,6 +20,7 @@ #endif #ifdef _WIN32 +#define NOMINMAX #ifdef CPPREST_TARGET_XP #include #ifndef _WIN32_WINNT @@ -137,4 +138,4 @@ #if defined(__clang__) #pragma clang diagnostic pop -#endif +#endif diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 66b85744f4..c670dd0a61 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -20,10 +20,6 @@ #include "ws_client_impl.h" -// These must be undef'ed before including websocketpp because it is not Windows.h safe. -#undef min -#undef max - // Force websocketpp to use C++ std::error_code instead of Boost. #define _WEBSOCKETPP_CPP11_SYSTEM_ERROR_ #if defined(_MSC_VER) @@ -134,22 +130,23 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: ~wspp_callback_client() CPPREST_NOEXCEPT { _ASSERTE(m_state < DESTROYED); - std::unique_lock lock(m_wspp_client_lock); + State localState; + { + std::lock_guard lock(m_wspp_client_lock); + localState = m_state; + } // Unlock the mutex so connect/close can use it. // Now, what states could we be in? - switch (m_state) { + switch (localState) { case DESTROYED: // This should be impossible std::abort(); case CREATED: - lock.unlock(); break; case CLOSED: case CONNECTING: case CONNECTED: case CLOSING: - // Unlock the mutex so connect/close can use it. - lock.unlock(); try { // This will do nothing in the already-connected case From ae50037e020b0a4e4c41009c356994a18e5c0581 Mon Sep 17 00:00:00 2001 From: Adam Duskett Date: Fri, 3 Aug 2018 02:46:05 -0400 Subject: [PATCH 405/609] fix template whitespace syntax (#715) Some files don't have a space inbetween the '<' and '::' charachters, which will cause build failures on older toolchains. Adding a space inbetween these two characters fixes the issue. See http://autobuild.buildroot.net/results/797a9b5fdf6ab0f16f2249324b48292dfab61d9f/build-end.log for more information. --- Release/include/cpprest/details/web_utilities.h | 2 +- Release/include/cpprest/http_client.h | 2 +- Release/include/cpprest/json.h | 2 +- Release/include/cpprest/ws_client.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Release/include/cpprest/details/web_utilities.h b/Release/include/cpprest/details/web_utilities.h index f99a8aa933..c32a58e5e3 100644 --- a/Release/include/cpprest/details/web_utilities.h +++ b/Release/include/cpprest/details/web_utilities.h @@ -22,7 +22,7 @@ class zero_memory_deleter public: _ASYNCRTIMP void operator()(::utility::string_t *data) const; }; -typedef std::unique_ptr<::utility::string_t, zero_memory_deleter> plaintext_string; +typedef std::unique_ptr< ::utility::string_t, zero_memory_deleter> plaintext_string; #if defined(_WIN32) && !defined(CPPREST_TARGET_XP) #if defined(__cplusplus_winrt) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index a936a23ede..f5ad8fac70 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -757,7 +757,7 @@ class http_client private: - std::shared_ptr<::web::http::client::http_pipeline> m_pipeline; + std::shared_ptr< ::web::http::client::http_pipeline> m_pipeline; }; namespace details { diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 07c5450243..dfdeead4f3 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -301,7 +301,7 @@ namespace json /// Field names associated with JSON values /// Whether to preserve the original order of the fields /// A non-empty JSON object value - static _ASYNCRTIMP json::value __cdecl object(std::vector> fields, bool keep_order = false); + static _ASYNCRTIMP json::value __cdecl object(std::vector> fields, bool keep_order = false); /// /// Creates an empty JSON array diff --git a/Release/include/cpprest/ws_client.h b/Release/include/cpprest/ws_client.h index 9a324cde51..98f933e149 100644 --- a/Release/include/cpprest/ws_client.h +++ b/Release/include/cpprest/ws_client.h @@ -184,7 +184,7 @@ class websocket_client_config /// Vector of all the subprotocols /// If you want all the subprotocols in a comma separated string /// they can be directly looked up in the headers using 'Sec-WebSocket-Protocol'. - _ASYNCRTIMP std::vector<::utility::string_t> subprotocols() const; + _ASYNCRTIMP std::vector< ::utility::string_t> subprotocols() const; /// /// Gets the server certificate validation property. From bcafee3799344572fa06d08687e02319256b80aa Mon Sep 17 00:00:00 2001 From: Wu Yongwei Date: Fri, 3 Aug 2018 14:57:51 +0800 Subject: [PATCH 406/609] Fix a build problem on Clang. (#732) AND_CAPTURE_MEMBER_FUNCTION_POINTERS workaround had a check for GCC, but did not exclude Clang. Clang has a fake GCC version of 4.2, thus caused problems. From 77e184ac7dee11c7ffbfc9b8b36125b4535aeb11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Meusel?= Date: Sat, 4 Aug 2018 01:14:11 +0200 Subject: [PATCH 407/609] set the default open() O_CREAT file permissions to 666 (#736) --- Release/src/streams/fileio_posix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/streams/fileio_posix.cpp b/Release/src/streams/fileio_posix.cpp index 88056e8c38..ce166957ce 100644 --- a/Release/src/streams/fileio_posix.cpp +++ b/Release/src/streams/fileio_posix.cpp @@ -160,7 +160,7 @@ bool _open_fsb_str(_filestream_callback *callback, const char *filename, std::io cmode |= O_CREAT; } - int f = open(name.c_str(), cmode, 0600); + int f = open(name.c_str(), cmode, 0666); _finish_create(f, callback, mode, prot); }); From 8111f2f3128ce5aefad17e80c74a8c39f6d006a9 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 1 Aug 2018 13:11:32 -0700 Subject: [PATCH 408/609] Factor shared threadpool setup/teardown behavior out of platform dependent policies. --- Release/src/pplx/threadpool.cpp | 130 ++++++++++++++++---------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index d2dc6161a2..f96c2c5109 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -10,7 +10,9 @@ #include "pplx/threadpool.h" #include +#include #include +#include #if defined(__ANDROID__) #include @@ -19,6 +21,32 @@ namespace { +#if defined(__ANDROID__) +// This pointer will be 0-initialized by default (at load time). +std::atomic JVM; + +JNIEnv* get_jvm_env() +{ + abort_if_no_jvm(); + JNIEnv* env = nullptr; + auto result = JVM.load()->AttachCurrentThread(&env, nullptr); + if (result != JNI_OK) + { + throw std::runtime_error("Could not attach to JVM"); + } + + return env; +} + +static void abort_if_no_jvm() +{ + if (JVM == nullptr) + { + __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s", "The CppREST SDK must be initialized before first use on android: https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); + std::abort(); + } +} +#endif // __ANDROID__ struct threadpool_impl final : crossplat::threadpool { @@ -39,6 +67,11 @@ struct threadpool_impl final : crossplat::threadpool } } + threadpool_impl& get_shared() + { + return *this; + } + private: void add_thread() { @@ -50,7 +83,7 @@ struct threadpool_impl final : crossplat::threadpool { crossplat::JVM.load()->DetachCurrentThread(); } -#endif +#endif // __ANDROID__ static void* thread_start(void *arg) CPPREST_NOEXCEPT { @@ -58,95 +91,62 @@ struct threadpool_impl final : crossplat::threadpool // Calling get_jvm_env() here forces the thread to be attached. crossplat::get_jvm_env(); pthread_cleanup_push(detach_from_java, nullptr); -#endif +#endif // __ANDROID__ threadpool_impl* _this = reinterpret_cast(arg); _this->m_service.run(); #if defined(__ANDROID__) pthread_cleanup_pop(true); -#endif +#endif // __ANDROID__ return arg; } std::vector> m_threads; boost::asio::io_service::work m_work; }; -} -namespace crossplat +#if defined(_WIN32) +struct shared_threadpool { -#if defined(__ANDROID__) -// This pointer will be 0-initialized by default (at load time). -std::atomic JVM; + typename std::aligned_union<0, threadpool_impl>::type shared_storage; -static void abort_if_no_jvm() -{ - if (JVM == nullptr) + threadpool_impl& get_shared() { - __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s", "The CppREST SDK must be initialized before first use on android: https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); - std::abort(); + return reinterpret_cast(shared_storage); } -} -JNIEnv* get_jvm_env() -{ - abort_if_no_jvm(); - JNIEnv* env = nullptr; - auto result = JVM.load()->AttachCurrentThread(&env, nullptr); - if (result != JNI_OK) + shared_threadpool(size_t n) { - throw std::runtime_error("Could not attach to JVM"); + ::new (static_cast(&get_shared())) threadpool_impl(n); } - - return env; -} - -threadpool& threadpool::shared_instance() -{ - abort_if_no_jvm(); - static threadpool_impl s_shared(40); - return s_shared; -} - -#elif defined(_WIN32) - -// if linked into a DLL, the threadpool shared instance will be destroyed at DLL_PROCESS_DETACH, -// at which stage joining threads causes deadlock, hence this dance -threadpool& threadpool::shared_instance() -{ - static bool terminate_threads = false; - static struct restore_terminate_threads + ~shared_threadpool() { - ~restore_terminate_threads() - { - boost::asio::detail::thread::set_terminate_threads(terminate_threads); - } - } destroyed_after; - - static threadpool_impl s_shared(40); + // if linked into a DLL, the threadpool shared instance will be + // destroyed at DLL_PROCESS_DETACH, at which stage joining threads + // causes deadlock, hence this dance + bool terminate_threads = boost::asio::detail::thread::terminate_threads(); + boost::asio::detail::thread::set_terminate_threads(true); + get_shared().~threadpool_impl(); + boost::asio::detail::thread::set_terminate_threads(terminate_threads); + } +}; - static struct enforce_terminate_threads - { - ~enforce_terminate_threads() - { - terminate_threads = boost::asio::detail::thread::terminate_threads(); - boost::asio::detail::thread::set_terminate_threads(true); - } - } destroyed_before; +typedef shared_threadpool platform_shared_threadpool; +#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv // +typedef threadpool_impl platform_shared_threadpool; +#endif - return s_shared; } -#else - -// initialize the static shared threadpool +namespace crossplat +{ threadpool& threadpool::shared_instance() { - static threadpool_impl s_shared(40); - return s_shared; +#if defined(__ANDROID__) + abort_if_no_jvm(); +#endif // __ANDROID__ + static platform_shared_threadpool s_shared_impl(40); + return s_shared_impl.get_shared(); } - -#endif - } #if defined(__ANDROID__) @@ -159,4 +159,4 @@ std::unique_ptr crossplat::threadpool::construct(size_t n { return std::unique_ptr(new threadpool_impl(num_threads)); } -#endif +#endif // !defined(CPPREST_EXCLUDE_WEBSOCKETS) || !defined(_WIN32) From 4c6abf33b5dc33c05a93dfb949e5a10ad5903253 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 1 Aug 2018 13:39:25 -0700 Subject: [PATCH 409/609] Add initialize_with_threads feature to control thread count. --- Release/include/pplx/threadpool.h | 12 ++++++++- Release/src/pplx/threadpool.cpp | 41 +++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/Release/include/pplx/threadpool.h b/Release/include/pplx/threadpool.h index 919eb75552..dfa3344db8 100644 --- a/Release/include/pplx/threadpool.h +++ b/Release/include/pplx/threadpool.h @@ -57,6 +57,17 @@ class threadpool virtual ~threadpool() = default; + /// + /// Initializes the cpprestsdk threadpool with a custom number of threads + /// + /// + /// This function allows an application (in their main function) to initialize the cpprestsdk + /// threadpool with a custom threadcount. Libraries should avoid calling this function to avoid + /// a diamond problem with multiple consumers attempting to customize the pool. + /// + /// Thrown if the threadpool has already been initialized + static void initialize_with_threads(size_t num_threads); + template CASABLANCA_DEPRECATED("Use `.service().post(task)` directly.") void schedule(T task) @@ -73,4 +84,3 @@ class threadpool }; } - diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index f96c2c5109..0e92411375 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -42,7 +42,9 @@ static void abort_if_no_jvm() { if (JVM == nullptr) { - __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s", "The CppREST SDK must be initialized before first use on android: https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); + __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s", + "The CppREST SDK must be initialized before first use on android: " + "https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); std::abort(); } } @@ -75,7 +77,8 @@ struct threadpool_impl final : crossplat::threadpool private: void add_thread() { - m_threads.push_back(std::unique_ptr(new boost::asio::detail::thread([&]{ thread_start(this); }))); + m_threads.push_back(std::unique_ptr( + new boost::asio::detail::thread([&]{ thread_start(this); }))); } #if defined(__ANDROID__) @@ -135,17 +138,41 @@ typedef shared_threadpool platform_shared_threadpool; typedef threadpool_impl platform_shared_threadpool; #endif +std::pair initialize_shared_threadpool(size_t num_threads) +{ + static std::once_flag of; + static typename std::aligned_union<0, platform_shared_threadpool>::type storage; + +#if defined(__ANDROID__) + abort_if_no_jvm(); +#endif // __ANDROID__ + platform_shared_threadpool* const ptr = + &reinterpret_cast(storage); + bool initialized_this_time = false; + std::call_once(of, [num_threads, ptr, &initialized_this_time] { + ::new (ptr) platform_shared_threadpool(num_threads); + initialized_this_time = true; + }); + + return {initialized_this_time, ptr}; +} } namespace crossplat { threadpool& threadpool::shared_instance() { -#if defined(__ANDROID__) - abort_if_no_jvm(); -#endif // __ANDROID__ - static platform_shared_threadpool s_shared_impl(40); - return s_shared_impl.get_shared(); + return initialize_shared_threadpool(40).second->get_shared(); +} + + +void threadpool::initialize_with_threads(size_t num_threads) +{ + const auto result = initialize_shared_threadpool(num_threads); + if (!result.first) + { + throw std::runtime_error("the cpprestsdk threadpool has already been initialized"); + } } } From ed2b047229229e501bd019cc6021e4f1011c3516 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 1 Aug 2018 15:02:32 -0700 Subject: [PATCH 410/609] Use double checked locking instead of call_once on Android due to paranoia. --- Release/src/pplx/threadpool.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index 0e92411375..9bfeb398ba 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -140,19 +140,38 @@ typedef threadpool_impl platform_shared_threadpool; std::pair initialize_shared_threadpool(size_t num_threads) { - static std::once_flag of; static typename std::aligned_union<0, platform_shared_threadpool>::type storage; - -#if defined(__ANDROID__) - abort_if_no_jvm(); -#endif // __ANDROID__ platform_shared_threadpool* const ptr = &reinterpret_cast(storage); bool initialized_this_time = false; +#if defined(__ANDROID__) + // mutex based implementation due to paranoia about (lack of) call_once support on Android + // remove this if/when call_once is supported + static std::mutex mtx; + static std::atomic initialized; + abort_if_no_jvm(); + if (!initialized.load()) + { + std::lock_guard guard(mtx); + if (!initialized.load()) + { + ::new (static_cast(ptr)) platform_shared_threadpool(num_threads); + initialized.store(true); + initialized_this_time = true; + } + } // also unlock + +#else // ^^^ __ANDROID__ ^^^ // vvv !__ANDROID___ vvv // + static std::once_flag of; + +// #if defined(__ANDROID__) // if call_once can be used for android +// abort_if_no_jvm(); +// #endif // __ANDROID__ std::call_once(of, [num_threads, ptr, &initialized_this_time] { - ::new (ptr) platform_shared_threadpool(num_threads); + ::new (static_cast(ptr)) platform_shared_threadpool(num_threads); initialized_this_time = true; }); +#endif // __ANDROID__ return {initialized_this_time, ptr}; } From 633322537e1057e311984932642513c25499ace6 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Mon, 6 Aug 2018 06:17:23 -0700 Subject: [PATCH 411/609] Workaround Apple clang bugs in constexpr evaluation. (#829) --- Release/src/utilities/asyncrt_utils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 893de3729b..72f12ccf10 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -51,7 +51,7 @@ namespace } }; - constexpr to_lower_ch_impl to_lower_ch; + constexpr to_lower_ch_impl to_lower_ch{}; struct eq_lower_ch_impl { @@ -62,7 +62,7 @@ namespace } }; - constexpr eq_lower_ch_impl eq_lower_ch; + constexpr eq_lower_ch_impl eq_lower_ch{}; struct lt_lower_ch_impl { @@ -73,7 +73,7 @@ namespace } }; - constexpr lt_lower_ch_impl lt_lower_ch; + constexpr lt_lower_ch_impl lt_lower_ch{}; } namespace utility From d92e0fe3e83819486009ca7b2eb3ce4dc7411d29 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 9 Aug 2018 13:51:16 -0700 Subject: [PATCH 412/609] Add .clang-format file from vcpkg to cpprestsdk. --- .clang-format | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..4700062c73 --- /dev/null +++ b/.clang-format @@ -0,0 +1,32 @@ +--- +BasedOnStyle: WebKit +Language: Cpp +Standard: Cpp11 + +UseTab: Never +IndentWidth: 4 +ColumnLimit: 120 +PointerAlignment: Left + +BreakBeforeBraces: Allman + +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakTemplateDeclarations: true +AlignAfterOpenBracket: true +AlignOperands: true +AlignTrailingComments: true +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: None +BreakConstructorInitializersBeforeComma: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true +Cpp11BracedListStyle: true +IndentCaseLabels: true +KeepEmptyLinesAtTheStartOfBlocks: false +NamespaceIndentation: All +PenaltyReturnTypeOnItsOwnLine: 1000 +SpaceAfterTemplateKeyword: false \ No newline at end of file From 7d843a896f8c8eb03db08f53471628aa3bd5c37f Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 9 Aug 2018 13:53:52 -0700 Subject: [PATCH 413/609] Set namespace indentation to none. --- .clang-format | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.clang-format b/.clang-format index 4700062c73..5ef3ed9647 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,3 @@ ---- BasedOnStyle: WebKit Language: Cpp Standard: Cpp11 @@ -27,6 +26,6 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true Cpp11BracedListStyle: true IndentCaseLabels: true KeepEmptyLinesAtTheStartOfBlocks: false -NamespaceIndentation: All +NamespaceIndentation: None PenaltyReturnTypeOnItsOwnLine: 1000 -SpaceAfterTemplateKeyword: false \ No newline at end of file +SpaceAfterTemplateKeyword: false From fcbbfa2b1205d13ca4ce57c5a6b14ffc132dbe17 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Thu, 9 Aug 2018 13:54:23 -0700 Subject: [PATCH 414/609] Apply clang-format to the asio implementation. --- Release/src/http/client/http_client_asio.cpp | 746 ++++++++++-------- .../src/http/client/x509_cert_utilities.cpp | 316 ++++---- 2 files changed, 560 insertions(+), 502 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 67d56c1e8f..ec41762b3f 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1,33 +1,33 @@ /*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* HTTP Library: Client-side APIs. -* -* This file contains a cross platform implementation based on Boost.ASIO. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * HTTP Library: Client-side APIs. + * + * This file contains a cross platform implementation based on Boost.ASIO. + * + * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ #include "stdafx.h" -#include "cpprest/asyncrt_utils.h" #include "../common/internal_http_helpers.h" +#include "cpprest/asyncrt_utils.h" #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-local-typedef" #pragma clang diagnostic ignored "-Winfinite-recursion" #endif +#include #include #include #include #include -#include #include #if defined(__clang__) #pragma clang diagnostic pop @@ -37,13 +37,13 @@ #error "Cpp rest SDK requires c++11 smart pointer support from boost" #endif -#include "pplx/threadpool.h" -#include "http_client_impl.h" #include "cpprest/base_uri.h" -#include "cpprest/details/x509_cert_utilities.h" #include "cpprest/details/http_helpers.h" -#include +#include "cpprest/details/x509_cert_utilities.h" +#include "http_client_impl.h" +#include "pplx/threadpool.h" #include +#include #if defined(__GNUC__) && !defined(__clang__) @@ -62,7 +62,8 @@ #if _MSC_VER >= 1900 #define AND_CAPTURE_MEMBER_FUNCTION_POINTERS #else -// This bug also afflicts VS2013 which incorrectly reports "warning C4573: the usage of 'symbol' requires the compiler to capture 'this' but the current default capture mode does not allow it" +// This bug also afflicts VS2013 which incorrectly reports "warning C4573: the usage of 'symbol' requires the compiler +// to capture 'this' but the current default capture mode does not allow it" #define AND_CAPTURE_MEMBER_FUNCTION_POINTERS , this #endif @@ -82,13 +83,14 @@ using std::to_string; static const std::string CRLF("\r\n"); -namespace web { namespace http +namespace web +{ +namespace http { namespace client { namespace details { - enum class httpclient_errorcode_context { none = 0, @@ -114,19 +116,15 @@ class asio_connection_pool; class asio_connection { friend class asio_client; + public: asio_connection(boost::asio::io_service& io_service) - : m_socket(io_service), - m_is_reused(false), - m_keep_alive(true), - m_closed(false) - {} - - ~asio_connection() + : m_socket(io_service), m_is_reused(false), m_keep_alive(true), m_closed(false) { - close(); } + ~asio_connection() { close(); } + // This simply instantiates the internal state to support ssl. It does not perform the handshake. void upgrade_to_ssl(const std::function& ssl_context_callback) { @@ -139,7 +137,8 @@ class asio_connection { ssl_context_callback(ssl_context); } - m_ssl_stream = utility::details::make_unique>(m_socket, ssl_context); + m_ssl_stream = utility::details::make_unique>( + m_socket, ssl_context); } void close() @@ -182,9 +181,8 @@ class asio_connection } // These errors tell if connection was closed. - if ((boost::asio::error::eof == ec) - || (boost::asio::error::connection_reset == ec) - || (boost::asio::error::connection_aborted == ec)) + if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec) || + (boost::asio::error::connection_aborted == ec)) { return true; } @@ -196,10 +194,10 @@ class asio_connection // server due to inactivity. Unfortunately, the exact error we get // in this case depends on the Boost.Asio version used. #if BOOST_ASIO_VERSION >= 101008 - if (boost::asio::ssl::error::stream_truncated == ec) - return true; + if (boost::asio::ssl::error::stream_truncated == ec) return true; #else // Asio < 1.10.8 didn't have ssl::error::stream_truncated - if (boost::system::error_code(ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), boost::asio::error::get_ssl_category()) == ec) + if (boost::system::error_code(ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), + boost::asio::error::get_ssl_category()) == ec) return true; #endif } @@ -207,26 +205,27 @@ class asio_connection return false; } - template - void async_connect(const Iterator &begin, const Handler &handler) + template + void async_connect(const Iterator& begin, const Handler& handler) { { std::lock_guard lock(m_socket_lock); - if (!m_closed) { + if (!m_closed) + { m_socket.async_connect(begin, handler); return; } - } // unlock + } // unlock handler(boost::asio::error::operation_aborted); } - template + template void async_handshake(boost::asio::ssl::stream_base::handshake_type type, - const http_client_config &config, + const http_client_config& config, const std::string& host_name, - const HandshakeHandler &handshake_handler, - const CertificateHandler &cert_handler) + const HandshakeHandler& handshake_handler, + const CertificateHandler& cert_handler) { std::lock_guard lock(m_socket_lock); assert(is_ssl()); @@ -245,14 +244,14 @@ class asio_connection // Check to set host name for Server Name Indication (SNI) if (config.is_tlsext_sni_enabled()) { - SSL_set_tlsext_host_name(m_ssl_stream->native_handle(), const_cast(host_name.data())); + SSL_set_tlsext_host_name(m_ssl_stream->native_handle(), const_cast(host_name.data())); } m_ssl_stream->async_handshake(type, handshake_handler); } - template - void async_write(ConstBufferSequence &buffer, const Handler &writeHandler) + template + void async_write(ConstBufferSequence& buffer, const Handler& writeHandler) { std::lock_guard lock(m_socket_lock); if (m_ssl_stream) @@ -265,8 +264,8 @@ class asio_connection } } - template - void async_read(MutableBufferSequence &buffer, const CompletionCondition &condition, const Handler &readHandler) + template + void async_read(MutableBufferSequence& buffer, const CompletionCondition& condition, const Handler& readHandler) { std::lock_guard lock(m_socket_lock); if (m_ssl_stream) @@ -279,8 +278,8 @@ class asio_connection } } - template - void async_read_until(boost::asio::streambuf &buffer, const std::string &delim, const Handler &readHandler) + template + void async_read_until(boost::asio::streambuf& buffer, const std::string& delim, const Handler& readHandler) { std::lock_guard lock(m_socket_lock); if (m_ssl_stream) @@ -293,10 +292,7 @@ class asio_connection } } - void start_reuse() - { - m_is_reused = true; - } + void start_reuse() { m_is_reused = true; } private: // Guards concurrent access to socket/ssl::stream. This is necessary @@ -304,7 +300,7 @@ class asio_connection // as normal message processing. std::mutex m_socket_lock; tcp::socket m_socket; - std::unique_ptr > m_ssl_stream; + std::unique_ptr> m_ssl_stream; bool m_is_reused; bool m_keep_alive; @@ -340,15 +336,13 @@ class asio_connection class asio_connection_pool final : public std::enable_shared_from_this { public: - asio_connection_pool() : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) - {} + asio_connection_pool() : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) {} std::shared_ptr acquire() { std::lock_guard lock(m_lock); - if (m_connections.empty()) - return nullptr; + if (m_connections.empty()) return nullptr; auto conn = std::move(m_connections.back().second); m_connections.pop_back(); @@ -360,8 +354,7 @@ class asio_connection_pool final : public std::enable_shared_from_thiscancel(); - if (!connection->keep_alive()) - return; + if (!connection->keep_alive()) return; std::lock_guard lock(m_lock); if (!is_timer_running) @@ -385,14 +378,11 @@ class asio_connection_pool final : public std::enable_shared_from_thism_pool_epoch_timer.expires_from_now(boost::posix_time::seconds(30)); - pool->m_pool_epoch_timer.async_wait([weak_pool](const boost::system::error_code& ec) - { - if (ec) - return; + pool->m_pool_epoch_timer.async_wait([weak_pool](const boost::system::error_code& ec) { + if (ec) return; auto pool = weak_pool.lock(); - if (!pool) - return; + if (!pool) return; auto& self = *pool; auto& connections = self.m_connections; @@ -406,11 +396,11 @@ class asio_connection_pool final : public std::enable_shared_from_this>& p) - { - return p.first > prev_epoch; - }); + auto erase_end = std::find_if(connections.begin(), + connections.end(), + [prev_epoch](std::pair>& p) { + return p.first > prev_epoch; + }); connections.erase(connections.begin(), erase_end); start_epoch_interval(pool); @@ -435,14 +425,12 @@ class asio_client final : public _http_client_communicator , m_resolver(crossplat::threadpool::shared_instance().service()) , m_pool(std::make_shared()) , m_start_with_ssl(base_uri().scheme() == U("https") && !this->client_config().proxy().is_specified()) - {} - - virtual void send_request(const std::shared_ptr &request_ctx) override; - - void release_connection(std::shared_ptr& conn) { - m_pool->release(conn); } + + virtual void send_request(const std::shared_ptr& request_ctx) override; + + void release_connection(std::shared_ptr& conn) { m_pool->release(conn); } std::shared_ptr obtain_connection() { std::shared_ptr conn = m_pool->acquire(); @@ -451,8 +439,7 @@ class asio_client final : public _http_client_communicator { // Pool was empty. Create a new connection conn = std::make_shared(crossplat::threadpool::shared_instance().service()); - if (m_start_with_ssl) - conn->upgrade_to_ssl(this->client_config().get_ssl_context_callback()); + if (m_start_with_ssl) conn->upgrade_to_ssl(this->client_config().get_ssl_context_callback()); } return conn; @@ -462,6 +449,7 @@ class asio_client final : public _http_client_communicator public: tcp::resolver m_resolver; + private: const std::shared_ptr m_pool; const bool m_start_with_ssl; @@ -470,19 +458,21 @@ class asio_client final : public _http_client_communicator class asio_context final : public request_context, public std::enable_shared_from_this { friend class asio_client; + public: - asio_context(const std::shared_ptr<_http_client_communicator> &client, - http_request &request, - const std::shared_ptr &connection) - : request_context(client, request) - , m_content_length(0) - , m_needChunked(false) - , m_timer(client->client_config().timeout()) - , m_connection(connection) + asio_context(const std::shared_ptr<_http_client_communicator>& client, + http_request& request, + const std::shared_ptr& connection) + : request_context(client, request) + , m_content_length(0) + , m_needChunked(false) + , m_timer(client->client_config().timeout()) + , m_connection(connection) #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) - , m_openssl_failed(false) + , m_openssl_failed(false) #endif - {} + { + } virtual ~asio_context() { @@ -491,7 +481,8 @@ class asio_context final : public request_context, public std::enable_shared_fro std::static_pointer_cast(m_http_client)->release_connection(m_connection); } - static std::shared_ptr create_request_context(std::shared_ptr<_http_client_communicator> &client, http_request &request) + static std::shared_ptr create_request_context(std::shared_ptr<_http_client_communicator>& client, + http_request& request) { auto client_cast(std::static_pointer_cast(client)); auto connection(client_cast->obtain_connection()); @@ -503,9 +494,11 @@ class asio_context final : public request_context, public std::enable_shared_fro class ssl_proxy_tunnel final : public std::enable_shared_from_this { public: - ssl_proxy_tunnel(std::shared_ptr context, std::function)> ssl_tunnel_established) + ssl_proxy_tunnel(std::shared_ptr context, + std::function)> ssl_tunnel_established) : m_ssl_tunnel_established(ssl_tunnel_established), m_context(context) - {} + { + } void start_proxy_connect() { @@ -515,8 +508,8 @@ class asio_context final : public request_context, public std::enable_shared_fro utility::string_t proxy_host = proxy_uri.host(); int proxy_port = proxy_uri.port() == -1 ? 8080 : proxy_uri.port(); - const auto &base_uri = m_context->m_http_client->base_uri(); - const auto &host = utility::conversions::to_utf8string(base_uri.host()); + const auto& base_uri = m_context->m_http_client->base_uri(); + const auto& host = utility::conversions::to_utf8string(base_uri.host()); const int portRaw = base_uri.port(); const int port = (portRaw != 0) ? portRaw : 443; @@ -527,7 +520,7 @@ class asio_context final : public request_context, public std::enable_shared_fro request_stream << "Host: " << host << ":" << port << CRLF; request_stream << "Proxy-Connection: Keep-Alive\r\n"; - if(m_context->m_http_client->client_config().proxy().credentials().is_set()) + if (m_context->m_http_client->client_config().proxy().credentials().is_set()) { request_stream << m_context->generate_basic_proxy_auth_header() << CRLF; } @@ -539,7 +532,11 @@ class asio_context final : public request_context, public std::enable_shared_fro tcp::resolver::query query(utility::conversions::to_utf8string(proxy_host), to_string(proxy_port)); auto client = std::static_pointer_cast(m_context->m_http_client); - client->m_resolver.async_resolve(query, boost::bind(&ssl_proxy_tunnel::handle_resolve, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::iterator)); + client->m_resolver.async_resolve(query, + boost::bind(&ssl_proxy_tunnel::handle_resolve, + shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::iterator)); } private: @@ -553,7 +550,11 @@ class asio_context final : public request_context, public std::enable_shared_fro { m_context->m_timer.reset(); auto endpoint = *endpoints; - m_context->m_connection->async_connect(endpoint, boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); + m_context->m_connection->async_connect(endpoint, + boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, + shared_from_this(), + boost::asio::placeholders::error, + ++endpoints)); } } @@ -562,11 +563,15 @@ class asio_context final : public request_context, public std::enable_shared_fro if (!ec) { m_context->m_timer.reset(); - m_context->m_connection->async_write(m_request, boost::bind(&ssl_proxy_tunnel::handle_write_request, shared_from_this(), boost::asio::placeholders::error)); + m_context->m_connection->async_write(m_request, + boost::bind(&ssl_proxy_tunnel::handle_write_request, + shared_from_this(), + boost::asio::placeholders::error)); } else if (endpoints == tcp::resolver::iterator()) { - m_context->report_error("Failed to connect to any resolved proxy endpoint", ec, httpclient_errorcode_context::connect); + m_context->report_error( + "Failed to connect to any resolved proxy endpoint", ec, httpclient_errorcode_context::connect); } else { @@ -576,9 +581,12 @@ class asio_context final : public request_context, public std::enable_shared_fro m_context->m_connection = client->obtain_connection(); auto endpoint = *endpoints; - m_context->m_connection->async_connect(endpoint, boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); + m_context->m_connection->async_connect(endpoint, + boost::bind(&ssl_proxy_tunnel::handle_tcp_connect, + shared_from_this(), + boost::asio::placeholders::error, + ++endpoints)); } - } void handle_write_request(const boost::system::error_code& err) @@ -586,11 +594,16 @@ class asio_context final : public request_context, public std::enable_shared_fro if (!err) { m_context->m_timer.reset(); - m_context->m_connection->async_read_until(m_response, CRLF + CRLF, boost::bind(&ssl_proxy_tunnel::handle_status_line, shared_from_this(), boost::asio::placeholders::error)); + m_context->m_connection->async_read_until(m_response, + CRLF + CRLF, + boost::bind(&ssl_proxy_tunnel::handle_status_line, + shared_from_this(), + boost::asio::placeholders::error)); } else { - m_context->report_error("Failed to send connect request to proxy.", err, httpclient_errorcode_context::writebody); + m_context->report_error( + "Failed to send connect request to proxy.", err, httpclient_errorcode_context::writebody); } } @@ -608,13 +621,17 @@ class asio_context final : public request_context, public std::enable_shared_fro if (!response_stream || http_version.substr(0, 5) != "HTTP/") { - m_context->report_error("Invalid HTTP status line during proxy connection", ec, httpclient_errorcode_context::readheader); + m_context->report_error("Invalid HTTP status line during proxy connection", + ec, + httpclient_errorcode_context::readheader); return; } if (status_code != 200) { - m_context->report_error("Expected a 200 response from proxy, received: " + to_string(status_code), ec, httpclient_errorcode_context::readheader); + m_context->report_error("Expected a 200 response from proxy, received: " + to_string(status_code), + ec, + httpclient_errorcode_context::readheader); return; } @@ -646,7 +663,8 @@ class asio_context final : public request_context, public std::enable_shared_fro { if (m_request._cancellation_token().is_canceled()) { - request_context::report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user."); + request_context::report_error(make_error_code(std::errc::operation_canceled).value(), + "Request canceled by user."); return; } @@ -654,36 +672,40 @@ class asio_context final : public request_context, public std::enable_shared_fro std::string proxy_host; int proxy_port = -1; - // There is no support for auto-detection of proxies on non-windows platforms, it must be specified explicitly from the client code. + // There is no support for auto-detection of proxies on non-windows platforms, it must be specified explicitly + // from the client code. if (m_http_client->client_config().proxy().is_specified()) { - proxy_type = m_http_client->base_uri().scheme() == U("https") ? http_proxy_type::ssl_tunnel : http_proxy_type::http; + proxy_type = + m_http_client->base_uri().scheme() == U("https") ? http_proxy_type::ssl_tunnel : http_proxy_type::http; auto proxy = m_http_client->client_config().proxy(); auto proxy_uri = proxy.address(); proxy_port = proxy_uri.port() == -1 ? 8080 : proxy_uri.port(); proxy_host = utility::conversions::to_utf8string(proxy_uri.host()); } - auto start_http_request_flow = [proxy_type, proxy_host, proxy_port AND_CAPTURE_MEMBER_FUNCTION_POINTERS](std::shared_ptr ctx) - { + auto start_http_request_flow = [proxy_type, proxy_host, proxy_port AND_CAPTURE_MEMBER_FUNCTION_POINTERS]( + std::shared_ptr ctx) { if (ctx->m_request._cancellation_token().is_canceled()) { - ctx->request_context::report_error(make_error_code(std::errc::operation_canceled).value(), "Request canceled by user."); + ctx->request_context::report_error(make_error_code(std::errc::operation_canceled).value(), + "Request canceled by user."); return; } - const auto &base_uri = ctx->m_http_client->base_uri(); + const auto& base_uri = ctx->m_http_client->base_uri(); const auto full_uri = uri_builder(base_uri).append(ctx->m_request.relative_uri()).to_uri(); // For a normal http proxy, we need to specify the full request uri, otherwise just specify the resource - auto encoded_resource = proxy_type == http_proxy_type::http ? full_uri.to_string() : full_uri.resource().to_string(); + auto encoded_resource = + proxy_type == http_proxy_type::http ? full_uri.to_string() : full_uri.resource().to_string(); if (encoded_resource.empty()) { encoded_resource = U("/"); } - const auto &method = ctx->m_request.method(); + const auto& method = ctx->m_request.method(); // stop injection of headers via method // resource should be ok, since it's been encoded @@ -696,9 +718,11 @@ class asio_context final : public request_context, public std::enable_shared_fro std::ostream request_stream(&ctx->m_body_buf); request_stream.imbue(std::locale::classic()); - const auto &host = utility::conversions::to_utf8string(base_uri.host()); + const auto& host = utility::conversions::to_utf8string(base_uri.host()); - request_stream << utility::conversions::to_utf8string(method) << " " << utility::conversions::to_utf8string(encoded_resource) << " " << "HTTP/1.1\r\n"; + request_stream << utility::conversions::to_utf8string(method) << " " + << utility::conversions::to_utf8string(encoded_resource) << " " + << "HTTP/1.1\r\n"; int port = base_uri.port(); @@ -711,7 +735,8 @@ class asio_context final : public request_context, public std::enable_shared_fro if (!ctx->m_request.headers().has(header_names::host)) { request_stream << "Host: " << host; - if (!base_uri.is_port_default()) { + if (!base_uri.is_port_default()) + { request_stream << ":" << port; } request_stream << CRLF; @@ -721,7 +746,8 @@ class asio_context final : public request_context, public std::enable_shared_fro std::string extra_headers; // Add header for basic proxy authentication - if (proxy_type == http_proxy_type::http && ctx->m_http_client->client_config().proxy().credentials().is_set()) + if (proxy_type == http_proxy_type::http && + ctx->m_http_client->client_config().proxy().credentials().is_set()) { extra_headers.append(ctx->generate_basic_proxy_auth_header()); } @@ -735,7 +761,8 @@ class asio_context final : public request_context, public std::enable_shared_fro // Check user specified transfer-encoding. std::string transferencoding; - if (ctx->m_request.headers().match(header_names::transfer_encoding, transferencoding) && transferencoding == "chunked") + if (ctx->m_request.headers().match(header_names::transfer_encoding, transferencoding) && + transferencoding == "chunked") { ctx->m_needChunked = true; } @@ -758,12 +785,12 @@ class asio_context final : public request_context, public std::enable_shared_fro if (proxy_type == http_proxy_type::http) { - extra_headers.append( - "Cache-Control: no-store, no-cache\r\n" - "Pragma: no-cache\r\n"); + extra_headers.append("Cache-Control: no-store, no-cache\r\n" + "Pragma: no-cache\r\n"); } - request_stream << utility::conversions::to_utf8string(::web::http::details::flatten_http_headers(ctx->m_request.headers())); + request_stream << utility::conversions::to_utf8string( + ::web::http::details::flatten_http_headers(ctx->m_request.headers())); request_stream << extra_headers; // Enforce HTTP connection keep alive (even for the old HTTP/1.0 protocol). request_stream << "Connection: Keep-Alive\r\n\r\n"; @@ -776,7 +803,8 @@ class asio_context final : public request_context, public std::enable_shared_fro if (ctx->m_connection->is_reused() || proxy_type == http_proxy_type::ssl_tunnel) { - // If socket is a reused connection or we're connected via an ssl-tunneling proxy, try to write the request directly. In both cases we have already established a tcp connection. + // If socket is a reused connection or we're connected via an ssl-tunneling proxy, try to write the + // request directly. In both cases we have already established a tcp connection. ctx->write_request(); } else @@ -790,17 +818,20 @@ class asio_context final : public request_context, public std::enable_shared_fro tcp::resolver::query query(tcp_host, to_string(tcp_port)); auto client = std::static_pointer_cast(ctx->m_http_client); - client->m_resolver.async_resolve(query, boost::bind(&asio_context::handle_resolve, ctx, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); + client->m_resolver.async_resolve(query, + boost::bind(&asio_context::handle_resolve, + ctx, + boost::asio::placeholders::error, + boost::asio::placeholders::iterator)); } - // Register for notification on cancellation to abort this request. + // Register for notification on cancellation to abort this request. if (ctx->m_request._cancellation_token() != pplx::cancellation_token::none()) { // weak_ptr prevents lambda from taking shared ownership of the context. // Otherwise context replacement in the handle_status_line() would leak the objects. std::weak_ptr ctx_weak(ctx); - ctx->m_cancellationRegistration = ctx->m_request._cancellation_token().register_callback([ctx_weak]() - { + ctx->m_cancellationRegistration = ctx->m_request._cancellation_token().register_callback([ctx_weak]() { if (auto ctx_lock = ctx_weak.lock()) { // Shut down transmissions, close the socket and prevent connection from being pooled. @@ -812,8 +843,10 @@ class asio_context final : public request_context, public std::enable_shared_fro if (proxy_type == http_proxy_type::ssl_tunnel) { - // The ssl_tunnel_proxy keeps the context alive and then calls back once the ssl tunnel is established via 'start_http_request_flow' - std::shared_ptr ssl_tunnel = std::make_shared(shared_from_this(), start_http_request_flow); + // The ssl_tunnel_proxy keeps the context alive and then calls back once the ssl tunnel is established via + // 'start_http_request_flow' + std::shared_ptr ssl_tunnel = + std::make_shared(shared_from_this(), start_http_request_flow); ssl_tunnel->start_proxy_connect(); } else @@ -823,7 +856,7 @@ class asio_context final : public request_context, public std::enable_shared_fro } template - void report_exception(const _ExceptionType &e) + void report_exception(const _ExceptionType& e) { report_exception(std::make_exception_ptr(e)); } @@ -836,10 +869,7 @@ class asio_context final : public request_context, public std::enable_shared_fro } private: - void upgrade_to_ssl() - { - m_connection->upgrade_to_ssl(m_http_client->client_config().get_ssl_context_callback()); - } + void upgrade_to_ssl() { m_connection->upgrade_to_ssl(m_http_client->client_config().get_ssl_context_callback()); } std::string generate_basic_auth_header() { @@ -859,7 +889,9 @@ class asio_context final : public request_context, public std::enable_shared_fro return header; } - void report_error(const std::string &message, const boost::system::error_code &ec, httpclient_errorcode_context context = httpclient_errorcode_context::none) + void report_error(const std::string& message, + const boost::system::error_code& ec, + httpclient_errorcode_context context = httpclient_errorcode_context::none) { // By default, errorcodeValue don't need to converted long errorcodeValue = ec.value(); @@ -887,13 +919,13 @@ class asio_context final : public request_context, public std::enable_shared_fro } break; case httpclient_errorcode_context::readheader: - if (ec.default_error_condition().value() == boost::system::errc::no_such_file_or_directory) // bug in boost error_code mapping + if (ec.default_error_condition().value() == + boost::system::errc::no_such_file_or_directory) // bug in boost error_code mapping { errorcodeValue = make_error_code(std::errc::connection_aborted).value(); } break; - default: - break; + default: break; } } request_context::report_error(errorcodeValue, message); @@ -906,7 +938,8 @@ class asio_context final : public request_context, public std::enable_shared_fro { write_request(); } - else if (ec.value() == boost::system::errc::operation_canceled || ec.value() == boost::asio::error::operation_aborted) + else if (ec.value() == boost::system::errc::operation_canceled || + ec.value() == boost::asio::error::operation_aborted) { request_context::report_error(ec.value(), "Request canceled by user."); } @@ -921,7 +954,10 @@ class asio_context final : public request_context, public std::enable_shared_fro m_connection = client->obtain_connection(); auto endpoint = *endpoints; - m_connection->async_connect(endpoint, boost::bind(&asio_context::handle_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); + m_connection->async_connect( + endpoint, + boost::bind( + &asio_context::handle_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); } } @@ -935,7 +971,10 @@ class asio_context final : public request_context, public std::enable_shared_fro { m_timer.reset(); auto endpoint = *endpoints; - m_connection->async_connect(endpoint, boost::bind(&asio_context::handle_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); + m_connection->async_connect( + endpoint, + boost::bind( + &asio_context::handle_connect, shared_from_this(), boost::asio::placeholders::error, ++endpoints)); } } @@ -945,26 +984,28 @@ class asio_context final : public request_context, public std::enable_shared_fro if (m_connection->is_ssl() && !m_connection->is_reused()) { const auto weakCtx = std::weak_ptr(shared_from_this()); - m_connection->async_handshake(boost::asio::ssl::stream_base::client, - m_http_client->client_config(), - utility::conversions::to_utf8string(m_http_client->base_uri().host()), - boost::bind(&asio_context::handle_handshake, shared_from_this(), boost::asio::placeholders::error), - - // Use a weak_ptr since the verify_callback is stored until the connection is destroyed. - // This avoids creating a circular reference since we pool connection objects. - [weakCtx](bool preverified, boost::asio::ssl::verify_context &verify_context) - { - auto this_request = weakCtx.lock(); - if(this_request) - { - return this_request->handle_cert_verification(preverified, verify_context); - } - return false; - }); + m_connection->async_handshake( + boost::asio::ssl::stream_base::client, + m_http_client->client_config(), + utility::conversions::to_utf8string(m_http_client->base_uri().host()), + boost::bind(&asio_context::handle_handshake, shared_from_this(), boost::asio::placeholders::error), + + // Use a weak_ptr since the verify_callback is stored until the connection is destroyed. + // This avoids creating a circular reference since we pool connection objects. + [weakCtx](bool preverified, boost::asio::ssl::verify_context& verify_context) { + auto this_request = weakCtx.lock(); + if (this_request) + { + return this_request->handle_cert_verification(preverified, verify_context); + } + return false; + }); } else { - m_connection->async_write(m_body_buf, boost::bind(&asio_context::handle_write_headers, shared_from_this(), boost::asio::placeholders::error)); + m_connection->async_write( + m_body_buf, + boost::bind(&asio_context::handle_write_headers, shared_from_this(), boost::asio::placeholders::error)); } } @@ -972,7 +1013,9 @@ class asio_context final : public request_context, public std::enable_shared_fro { if (!ec) { - m_connection->async_write(m_body_buf, boost::bind(&asio_context::handle_write_headers, shared_from_this(), boost::asio::placeholders::error)); + m_connection->async_write( + m_body_buf, + boost::bind(&asio_context::handle_write_headers, shared_from_this(), boost::asio::placeholders::error)); } else { @@ -980,7 +1023,7 @@ class asio_context final : public request_context, public std::enable_shared_fro } } - bool handle_cert_verification(bool preverified, boost::asio::ssl::verify_context &verifyCtx) + bool handle_cert_verification(bool preverified, boost::asio::ssl::verify_context& verifyCtx) { // OpenSSL calls the verification callback once per certificate in the chain, // starting with the root CA certificate. The 'leaf', non-Certificate Authority (CA) @@ -988,17 +1031,17 @@ class asio_context final : public request_context, public std::enable_shared_fro // certificate chain, the rest are optional intermediate certificates, followed // finally by the root CA self signed certificate. - const auto &host = utility::conversions::to_utf8string(m_http_client->base_uri().host()); + const auto& host = utility::conversions::to_utf8string(m_http_client->base_uri().host()); #if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) // On OS X, iOS, and Android, OpenSSL doesn't have access to where the OS // stores keychains. If OpenSSL fails we will doing verification at the // end using the whole certificate chain so wait until the 'leaf' cert. // For now return true so OpenSSL continues down the certificate chain. - if(!preverified) + if (!preverified) { m_openssl_failed = true; } - if(m_openssl_failed) + if (m_openssl_failed) { return verify_cert_chain_platform_specific(verifyCtx, host); } @@ -1010,7 +1053,7 @@ class asio_context final : public request_context, public std::enable_shared_fro void handle_write_headers(const boost::system::error_code& ec) { - if(ec) + if (ec) { report_error("Failed to write request headers", ec, httpclient_errorcode_context::writeheader); } @@ -1027,7 +1070,6 @@ class asio_context final : public request_context, public std::enable_shared_fro } } - void handle_write_chunked_body(const boost::system::error_code& ec) { if (ec) @@ -1037,53 +1079,58 @@ class asio_context final : public request_context, public std::enable_shared_fro } m_timer.reset(); - const auto &progress = m_request._get_impl()->_progress_handler(); + const auto& progress = m_request._get_impl()->_progress_handler(); if (progress) { try { (*progress)(message_direction::upload, m_uploaded); } - catch(...) + catch (...) { report_exception(std::current_exception()); return; } } - const auto & chunkSize = m_http_client->client_config().chunksize(); + const auto& chunkSize = m_http_client->client_config().chunksize(); auto readbuf = _get_readbuffer(); - uint8_t *buf = boost::asio::buffer_cast(m_body_buf.prepare(chunkSize + http::details::chunked_encoding::additional_encoding_space)); + uint8_t* buf = boost::asio::buffer_cast( + m_body_buf.prepare(chunkSize + http::details::chunked_encoding::additional_encoding_space)); const auto this_request = shared_from_this(); - readbuf.getn(buf + http::details::chunked_encoding::data_offset, chunkSize).then([this_request, buf, chunkSize AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) - { - size_t readSize = 0; - try - { - readSize = op.get(); - } - catch (...) - { - this_request->report_exception(std::current_exception()); - return; - } + readbuf.getn(buf + http::details::chunked_encoding::data_offset, chunkSize) + .then([this_request, buf, chunkSize AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { + size_t readSize = 0; + try + { + readSize = op.get(); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } - const size_t offset = http::details::chunked_encoding::add_chunked_delimiters(buf, chunkSize + http::details::chunked_encoding::additional_encoding_space, readSize); - this_request->m_body_buf.commit(readSize + http::details::chunked_encoding::additional_encoding_space); - this_request->m_body_buf.consume(offset); - this_request->m_uploaded += static_cast(readSize); + const size_t offset = http::details::chunked_encoding::add_chunked_delimiters( + buf, chunkSize + http::details::chunked_encoding::additional_encoding_space, readSize); + this_request->m_body_buf.commit(readSize + http::details::chunked_encoding::additional_encoding_space); + this_request->m_body_buf.consume(offset); + this_request->m_uploaded += static_cast(readSize); - if (readSize != 0) - { - this_request->m_connection->async_write(this_request->m_body_buf, - boost::bind(&asio_context::handle_write_chunked_body, this_request, boost::asio::placeholders::error)); - } - else - { - this_request->m_connection->async_write(this_request->m_body_buf, - boost::bind(&asio_context::handle_write_body, this_request, boost::asio::placeholders::error)); - } - }); + if (readSize != 0) + { + this_request->m_connection->async_write(this_request->m_body_buf, + boost::bind(&asio_context::handle_write_chunked_body, + this_request, + boost::asio::placeholders::error)); + } + else + { + this_request->m_connection->async_write( + this_request->m_body_buf, + boost::bind(&asio_context::handle_write_body, this_request, boost::asio::placeholders::error)); + } + }); } void handle_write_large_body(const boost::system::error_code& ec) @@ -1095,14 +1142,14 @@ class asio_context final : public request_context, public std::enable_shared_fro } m_timer.reset(); - const auto &progress = m_request._get_impl()->_progress_handler(); + const auto& progress = m_request._get_impl()->_progress_handler(); if (progress) { try { (*progress)(message_direction::upload, m_uploaded); } - catch(...) + catch (...) { report_exception(std::current_exception()); return; @@ -1110,28 +1157,33 @@ class asio_context final : public request_context, public std::enable_shared_fro } const auto this_request = shared_from_this(); - const auto readSize = static_cast(std::min(static_cast(m_http_client->client_config().chunksize()), m_content_length - m_uploaded)); + const auto readSize = static_cast( + std::min(static_cast(m_http_client->client_config().chunksize()), m_content_length - m_uploaded)); auto readbuf = _get_readbuffer(); - readbuf.getn(boost::asio::buffer_cast(m_body_buf.prepare(readSize)), readSize).then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) - { - try - { - const auto actualReadSize = op.get(); - if(actualReadSize == 0) + readbuf.getn(boost::asio::buffer_cast(m_body_buf.prepare(readSize)), readSize) + .then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { + try + { + const auto actualReadSize = op.get(); + if (actualReadSize == 0) + { + this_request->report_exception(http_exception( + "Unexpected end of request body stream encountered before Content-Length satisfied.")); + return; + } + this_request->m_uploaded += static_cast(actualReadSize); + this_request->m_body_buf.commit(actualReadSize); + this_request->m_connection->async_write(this_request->m_body_buf, + boost::bind(&asio_context::handle_write_large_body, + this_request, + boost::asio::placeholders::error)); + } + catch (...) { - this_request->report_exception(http_exception("Unexpected end of request body stream encountered before Content-Length satisfied.")); + this_request->report_exception(std::current_exception()); return; } - this_request->m_uploaded += static_cast(actualReadSize); - this_request->m_body_buf.commit(actualReadSize); - this_request->m_connection->async_write(this_request->m_body_buf, boost::bind(&asio_context::handle_write_large_body, this_request, boost::asio::placeholders::error)); - } - catch (...) - { - this_request->report_exception(std::current_exception()); - return; - } - }); + }); } void handle_write_body(const boost::system::error_code& ec) @@ -1139,14 +1191,14 @@ class asio_context final : public request_context, public std::enable_shared_fro if (!ec) { m_timer.reset(); - const auto &progress = m_request._get_impl()->_progress_handler(); + const auto& progress = m_request._get_impl()->_progress_handler(); if (progress) { try { (*progress)(message_direction::upload, m_uploaded); } - catch(...) + catch (...) { report_exception(std::current_exception()); return; @@ -1154,7 +1206,10 @@ class asio_context final : public request_context, public std::enable_shared_fro } // Read until the end of entire headers - m_connection->async_read_until(m_body_buf, CRLF + CRLF, boost::bind(&asio_context::handle_status_line, shared_from_this(), boost::asio::placeholders::error)); + m_connection->async_read_until( + m_body_buf, + CRLF + CRLF, + boost::bind(&asio_context::handle_status_line, shared_from_this(), boost::asio::placeholders::error)); } else { @@ -1202,7 +1257,8 @@ class asio_context final : public request_context, public std::enable_shared_fro if (m_connection->was_reused_and_closed_by_server(ec)) { // Failed to write to socket because connection was already closed while it was in the pool. - // close() here ensures socket is closed in a robust way and prevents the connection from being put to the pool again. + // close() here ensures socket is closed in a robust way and prevents the connection from being put to the + // pool again. m_connection->close(); // Create a new context and copy the request object, completion event and @@ -1253,11 +1309,13 @@ class asio_context final : public request_context, public std::enable_shared_fro m_connection->set_keep_alive(!boost::iequals(value, U("close"))); } - m_response.headers().add(utility::conversions::to_string_t(std::move(name)), utility::conversions::to_string_t(std::move(value))); + m_response.headers().add(utility::conversions::to_string_t(std::move(name)), + utility::conversions::to_string_t(std::move(value))); } } - m_content_length = std::numeric_limits::max(); // Without Content-Length header, size should be same as TCP stream - set it size_t max. + m_content_length = std::numeric_limits::max(); // Without Content-Length header, size should be same as + // TCP stream - set it size_t max. m_response.headers().match(header_names::content_length, m_content_length); if (!this->handle_content_encoding_compression()) @@ -1274,21 +1332,18 @@ class asio_context final : public request_context, public std::enable_shared_fro // note: need to check for 'chunked' here as well, azure storage sends both // transfer-encoding:chunked and content-length:0 (although HTTP says not to) const auto status = m_response.status_code(); - if (m_request.method() == U("HEAD") - || (status >= 100 && status < 200) - || status == status_codes::NoContent - || status == status_codes::NotModified - || (!needChunked && m_content_length == 0)) + if (m_request.method() == U("HEAD") || (status >= 100 && status < 200) || status == status_codes::NoContent || + status == status_codes::NotModified || (!needChunked && m_content_length == 0)) { // we can stop early - no body - const auto &progress = m_request._get_impl()->_progress_handler(); + const auto& progress = m_request._get_impl()->_progress_handler(); if (progress) { try { (*progress)(message_direction::download, 0); } - catch(...) + catch (...) { report_exception(std::current_exception()); return; @@ -1301,18 +1356,25 @@ class asio_context final : public request_context, public std::enable_shared_fro { if (!needChunked) { - async_read_until_buffersize(static_cast(std::min(m_content_length, static_cast(m_http_client->client_config().chunksize()))), - boost::bind(&asio_context::handle_read_content, shared_from_this(), boost::asio::placeholders::error)); + async_read_until_buffersize( + static_cast( + std::min(m_content_length, static_cast(m_http_client->client_config().chunksize()))), + boost::bind( + &asio_context::handle_read_content, shared_from_this(), boost::asio::placeholders::error)); } else { - m_connection->async_read_until(m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, shared_from_this(), boost::asio::placeholders::error)); + m_connection->async_read_until(m_body_buf, + CRLF, + boost::bind(&asio_context::handle_chunk_header, + shared_from_this(), + boost::asio::placeholders::error)); } } } - template - void async_read_until_buffersize(size_t size, const ReadHandler &handler) + template + void async_read_until_buffersize(size_t size, const ReadHandler& handler) { size_t size_to_read = 0; if (m_body_buf.size() < size) @@ -1341,12 +1403,16 @@ class asio_context final : public request_context, public std::enable_shared_fro if (octetLine.fail()) { - report_error("Invalid chunked response header", boost::system::error_code(), httpclient_errorcode_context::readbody); + report_error("Invalid chunked response header", + boost::system::error_code(), + httpclient_errorcode_context::readbody); } else { - async_read_until_buffersize(octets + CRLF.size(), - boost::bind(&asio_context::handle_chunk, shared_from_this(), boost::asio::placeholders::error, octets)); + async_read_until_buffersize( + octets + CRLF.size(), + boost::bind( + &asio_context::handle_chunk, shared_from_this(), boost::asio::placeholders::error, octets)); } } else @@ -1362,7 +1428,7 @@ class asio_context final : public request_context, public std::enable_shared_fro m_timer.reset(); m_downloaded += static_cast(to_read); - const auto &progress = m_request._get_impl()->_progress_handler(); + const auto& progress = m_request._get_impl()->_progress_handler(); if (progress) { try @@ -1385,9 +1451,10 @@ class asio_context final : public request_context, public std::enable_shared_fro { auto writeBuffer = _get_writebuffer(); const auto this_request = shared_from_this(); - if(m_decompressor) + if (m_decompressor) { - auto decompressed = m_decompressor->decompress(boost::asio::buffer_cast(m_body_buf.data()), to_read); + auto decompressed = m_decompressor->decompress( + boost::asio::buffer_cast(m_body_buf.data()), to_read); if (m_decompressor->has_error()) { @@ -1395,11 +1462,16 @@ class asio_context final : public request_context, public std::enable_shared_fro return; } - // It is valid for the decompressor to sometimes return an empty output for a given chunk, the data will be flushed when the next chunk is received + // It is valid for the decompressor to sometimes return an empty output for a given chunk, the data + // will be flushed when the next chunk is received if (decompressed.empty()) { m_body_buf.consume(to_read + CRLF.size()); // consume crlf - m_connection->async_read_until(m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); + m_connection->async_read_until(m_body_buf, + CRLF, + boost::bind(&asio_context::handle_chunk_header, + this_request, + boost::asio::placeholders::error)); } else { @@ -1409,38 +1481,47 @@ class asio_context final : public request_context, public std::enable_shared_fro auto shared_decompressed = std::make_shared(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) - .then([this_request, to_read, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) - { + .then([this_request, to_read, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS]( + pplx::task op) { + try + { + op.get(); + this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf + this_request->m_connection->async_read_until( + this_request->m_body_buf, + CRLF, + boost::bind(&asio_context::handle_chunk_header, + this_request, + boost::asio::placeholders::error)); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } + }); + } + } + else + { + writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read) + .then([this_request, to_read AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { try { - op.get(); - this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf - this_request->m_connection->async_read_until(this_request->m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); + op.wait(); } catch (...) { this_request->report_exception(std::current_exception()); return; } + this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf + this_request->m_connection->async_read_until(this_request->m_body_buf, + CRLF, + boost::bind(&asio_context::handle_chunk_header, + this_request, + boost::asio::placeholders::error)); }); - } - } - else - { - writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), to_read).then([this_request, to_read AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) - { - try - { - op.wait(); - } - catch (...) - { - this_request->report_exception(std::current_exception()); - return; - } - this_request->m_body_buf.consume(to_read + CRLF.size()); // consume crlf - this_request->m_connection->async_read_until(this_request->m_body_buf, CRLF, boost::bind(&asio_context::handle_chunk_header, this_request, boost::asio::placeholders::error)); - }); } } } @@ -1454,7 +1535,6 @@ class asio_context final : public request_context, public std::enable_shared_fro { auto writeBuffer = _get_writebuffer(); - if (ec) { if (ec == boost::asio::error::eof && m_content_length == std::numeric_limits::max()) @@ -1469,7 +1549,7 @@ class asio_context final : public request_context, public std::enable_shared_fro } m_timer.reset(); - const auto &progress = m_request._get_impl()->_progress_handler(); + const auto& progress = m_request._get_impl()->_progress_handler(); if (progress) { try @@ -1488,11 +1568,13 @@ class asio_context final : public request_context, public std::enable_shared_fro // more data need to be read const auto this_request = shared_from_this(); - auto read_size = static_cast(std::min(static_cast(m_body_buf.size()), m_content_length - m_downloaded)); + auto read_size = static_cast( + std::min(static_cast(m_body_buf.size()), m_content_length - m_downloaded)); - if(m_decompressor) + if (m_decompressor) { - auto decompressed = m_decompressor->decompress(boost::asio::buffer_cast(m_body_buf.data()), read_size); + auto decompressed = + m_decompressor->decompress(boost::asio::buffer_cast(m_body_buf.data()), read_size); if (m_decompressor->has_error()) { @@ -1500,15 +1582,20 @@ class asio_context final : public request_context, public std::enable_shared_fro return; } - // It is valid for the decompressor to sometimes return an empty output for a given chunk, the data will be flushed when the next chunk is received + // It is valid for the decompressor to sometimes return an empty output for a given chunk, the data will + // be flushed when the next chunk is received if (decompressed.empty()) { try { this_request->m_downloaded += static_cast(read_size); - this_request->async_read_until_buffersize(static_cast(std::min(static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), - boost::bind(&asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); + this_request->async_read_until_buffersize( + static_cast(std::min( + static_cast(this_request->m_http_client->client_config().chunksize()), + this_request->m_content_length - this_request->m_downloaded)), + boost::bind( + &asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); } catch (...) { @@ -1524,16 +1611,47 @@ class asio_context final : public request_context, public std::enable_shared_fro auto shared_decompressed = std::make_shared(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) - .then([this_request, read_size, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) - { + .then([this_request, read_size, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS]( + pplx::task op) { + size_t writtenSize = 0; + try + { + writtenSize = op.get(); + this_request->m_downloaded += static_cast(read_size); + this_request->m_body_buf.consume(writtenSize); + this_request->async_read_until_buffersize( + static_cast(std::min( + static_cast(this_request->m_http_client->client_config().chunksize()), + this_request->m_content_length - this_request->m_downloaded)), + boost::bind(&asio_context::handle_read_content, + this_request, + boost::asio::placeholders::error)); + } + catch (...) + { + this_request->report_exception(std::current_exception()); + return; + } + }); + } + } + else + { + writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), read_size) + .then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { size_t writtenSize = 0; try { writtenSize = op.get(); - this_request->m_downloaded += static_cast(read_size); + this_request->m_downloaded += static_cast(writtenSize); this_request->m_body_buf.consume(writtenSize); - this_request->async_read_until_buffersize(static_cast(std::min(static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), - boost::bind(&asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); + this_request->async_read_until_buffersize( + static_cast(std::min( + static_cast(this_request->m_http_client->client_config().chunksize()), + this_request->m_content_length - this_request->m_downloaded)), + boost::bind(&asio_context::handle_read_content, + this_request, + boost::asio::placeholders::error)); } catch (...) { @@ -1541,28 +1659,6 @@ class asio_context final : public request_context, public std::enable_shared_fro return; } }); - } - } - else - { - writeBuffer.putn_nocopy(boost::asio::buffer_cast(m_body_buf.data()), read_size) - .then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) - { - size_t writtenSize = 0; - try - { - writtenSize = op.get(); - this_request->m_downloaded += static_cast(writtenSize); - this_request->m_body_buf.consume(writtenSize); - this_request->async_read_until_buffersize(static_cast(std::min(static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), - boost::bind(&asio_context::handle_read_content, this_request, boost::asio::placeholders::error)); - } - catch (...) - { - this_request->report_exception(std::current_exception()); - return; - } - }); } } else @@ -1577,18 +1673,13 @@ class asio_context final : public request_context, public std::enable_shared_fro class timeout_timer { public: - - timeout_timer(const std::chrono::microseconds& timeout) : - m_duration(timeout.count()), - m_state(created), - m_timer(crossplat::threadpool::shared_instance().service()) - {} - - void set_ctx(const std::weak_ptr &ctx) + timeout_timer(const std::chrono::microseconds& timeout) + : m_duration(timeout.count()), m_state(created), m_timer(crossplat::threadpool::shared_instance().service()) { - m_ctx = ctx; } + void set_ctx(const std::weak_ptr& ctx) { m_ctx = ctx; } + void start() { assert(m_state == created); @@ -1597,23 +1688,21 @@ class asio_context final : public request_context, public std::enable_shared_fro m_timer.expires_from_now(m_duration); auto ctx = m_ctx; - m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) - { - handle_timeout(ec, ctx); - }); + m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) { + handle_timeout(ec, ctx); + }); } void reset() { assert(m_state == started || m_state == timedout); assert(!m_ctx.expired()); - if(m_timer.expires_from_now(m_duration) > 0) + if (m_timer.expires_from_now(m_duration) > 0) { // The existing handler was canceled so schedule a new one. assert(m_state == started); auto ctx = m_ctx; - m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) - { + m_timer.async_wait([ctx AND_CAPTURE_MEMBER_FUNCTION_POINTERS](const boost::system::error_code& ec) { handle_timeout(ec, ctx); }); } @@ -1629,10 +1718,9 @@ class asio_context final : public request_context, public std::enable_shared_fro m_timer.cancel(); } - static void handle_timeout(const boost::system::error_code& ec, - const std::weak_ptr &ctx) + static void handle_timeout(const boost::system::error_code& ec, const std::weak_ptr& ctx) { - if(!ec) + if (!ec) { auto shared_ctx = ctx.lock(); if (shared_ctx) @@ -1674,13 +1762,13 @@ class asio_context final : public request_context, public std::enable_shared_fro #endif }; - -std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config) +std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, + http_client_config&& client_config) { return std::make_shared(std::move(base_uri), std::move(client_config)); } -void asio_client::send_request(const std::shared_ptr &request_ctx) +void asio_client::send_request(const std::shared_ptr& request_ctx) { auto ctx = std::static_pointer_cast(request_ctx); @@ -1717,5 +1805,7 @@ pplx::task asio_client::propagate(http_request request) return result_task; } - -}}}} // namespaces +} +} +} +} // namespaces diff --git a/Release/src/http/client/x509_cert_utilities.cpp b/Release/src/http/client/x509_cert_utilities.cpp index 1d4e7137e7..baf1ae8488 100644 --- a/Release/src/http/client/x509_cert_utilities.cpp +++ b/Release/src/http/client/x509_cert_utilities.cpp @@ -1,26 +1,27 @@ /*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* Contains utility functions for helping to verify server certificates in OS X/iOS. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * Contains utility functions for helping to verify server certificates in OS X/iOS. + * + * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ #include "stdafx.h" -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) +#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || \ + (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) #include "cpprest/details/x509_cert_utilities.h" #include #if defined(ANDROID) || defined(__ANDROID__) -#include #include "pplx/threadpool.h" +#include #endif #if defined(__APPLE__) @@ -36,20 +37,26 @@ #include #endif -namespace web { namespace http { namespace client { namespace details { - -static bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName); +namespace web +{ +namespace http +{ +namespace client +{ +namespace details +{ +static bool verify_X509_cert_chain(const std::vector& certChain, const std::string& hostName); -bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verifyCtx, const std::string &hostName) +bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context& verifyCtx, const std::string& hostName) { - X509_STORE_CTX *storeContext = verifyCtx.native_handle(); + X509_STORE_CTX* storeContext = verifyCtx.native_handle(); int currentDepth = X509_STORE_CTX_get_error_depth(storeContext); if (currentDepth != 0) { return true; } - STACK_OF(X509) *certStack = X509_STORE_CTX_get_chain(storeContext); + STACK_OF(X509)* certStack = X509_STORE_CTX_get_chain(storeContext); const int numCerts = sk_X509_num(certStack); if (numCerts < 0) { @@ -60,7 +67,7 @@ bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verif certChain.reserve(numCerts); for (int i = 0; i < numCerts; ++i) { - X509 *cert = sk_X509_value(certStack, i); + X509* cert = sk_X509_value(certStack, i); // Encode into DER format into raw memory. int len = i2d_X509(cert, nullptr); @@ -71,7 +78,7 @@ bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verif std::string certData; certData.resize(len); - unsigned char * buffer = reinterpret_cast(&certData[0]); + unsigned char* buffer = reinterpret_cast(&certData[0]); len = i2d_X509(cert, &buffer); if (len < 0) { @@ -102,9 +109,9 @@ using namespace crossplat; /// occurred when calling a JNI function. /// /// true if JNI call failed, false otherwise. -static bool jni_failed(JNIEnv *env) +static bool jni_failed(JNIEnv* env) { - if(env->ExceptionOccurred()) + if (env->ExceptionOccurred()) { // Clear exception otherwise no other JNI functions can be called. // In the future if we improve error reporting the exception message @@ -114,28 +121,31 @@ static bool jni_failed(JNIEnv *env) } return false; } -template -static bool jni_failed(JNIEnv *env, const java_local_ref &result) +template +static bool jni_failed(JNIEnv* env, const java_local_ref& result) { - if(jni_failed(env) || !result) + if (jni_failed(env) || !result) { return true; } return false; } -static bool jni_failed(JNIEnv *env, const jmethodID &result) +static bool jni_failed(JNIEnv* env, const jmethodID& result) { - if(jni_failed(env) || result == nullptr) + if (jni_failed(env) || result == nullptr) { return true; } return false; } -#define CHECK_JREF(env, obj) if(jni_failed(env, obj)) return false; -#define CHECK_JMID(env, mid) if(jni_failed(env, mid)) return false; -#define CHECK_JNI(env) if(jni_failed(env)) return false; - -bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName) +#define CHECK_JREF(env, obj) \ + if (jni_failed(env, obj)) return false; +#define CHECK_JMID(env, mid) \ + if (jni_failed(env, mid)) return false; +#define CHECK_JNI(env) \ + if (jni_failed(env)) return false; + +bool verify_X509_cert_chain(const std::vector& certChain, const std::string& hostName) { JNIEnv* env = get_jvm_env(); @@ -148,24 +158,19 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std // ByteArrayInputStream java_local_ref byteArrayInputStreamClass(env->FindClass("java/io/ByteArrayInputStream")); CHECK_JREF(env, byteArrayInputStreamClass); - jmethodID byteArrayInputStreamConstructorMethod = env->GetMethodID( - byteArrayInputStreamClass.get(), - "", - "([B)V"); + jmethodID byteArrayInputStreamConstructorMethod = + env->GetMethodID(byteArrayInputStreamClass.get(), "", "([B)V"); CHECK_JMID(env, byteArrayInputStreamConstructorMethod); // CertificateFactory java_local_ref certificateFactoryClass(env->FindClass("java/security/cert/CertificateFactory")); CHECK_JREF(env, certificateFactoryClass); jmethodID certificateFactoryGetInstanceMethod = env->GetStaticMethodID( - certificateFactoryClass.get(), - "getInstance", - "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); + certificateFactoryClass.get(), "getInstance", "(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); CHECK_JMID(env, certificateFactoryGetInstanceMethod); - jmethodID generateCertificateMethod = env->GetMethodID( - certificateFactoryClass.get(), - "generateCertificate", - "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); + jmethodID generateCertificateMethod = env->GetMethodID(certificateFactoryClass.get(), + "generateCertificate", + "(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); CHECK_JMID(env, generateCertificateMethod); // X509Certificate @@ -176,48 +181,40 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std java_local_ref trustManagerFactoryClass(env->FindClass("javax/net/ssl/TrustManagerFactory")); CHECK_JREF(env, trustManagerFactoryClass); jmethodID trustManagerFactoryGetInstanceMethod = env->GetStaticMethodID( - trustManagerFactoryClass.get(), - "getInstance", - "(Ljava/lang/String;)Ljavax/net/ssl/TrustManagerFactory;"); + trustManagerFactoryClass.get(), "getInstance", "(Ljava/lang/String;)Ljavax/net/ssl/TrustManagerFactory;"); CHECK_JMID(env, trustManagerFactoryGetInstanceMethod); - jmethodID trustManagerFactoryInitMethod = env->GetMethodID( - trustManagerFactoryClass.get(), - "init", - "(Ljava/security/KeyStore;)V"); + jmethodID trustManagerFactoryInitMethod = + env->GetMethodID(trustManagerFactoryClass.get(), "init", "(Ljava/security/KeyStore;)V"); CHECK_JMID(env, trustManagerFactoryInitMethod); - jmethodID trustManagerFactoryGetTrustManagersMethod = env->GetMethodID( - trustManagerFactoryClass.get(), - "getTrustManagers", - "()[Ljavax/net/ssl/TrustManager;"); + jmethodID trustManagerFactoryGetTrustManagersMethod = + env->GetMethodID(trustManagerFactoryClass.get(), "getTrustManagers", "()[Ljavax/net/ssl/TrustManager;"); CHECK_JMID(env, trustManagerFactoryGetTrustManagersMethod); // X509TrustManager java_local_ref X509TrustManagerClass(env->FindClass("javax/net/ssl/X509TrustManager")); CHECK_JREF(env, X509TrustManagerClass); - jmethodID X509TrustManagerCheckServerTrustedMethod = env->GetMethodID( - X509TrustManagerClass.get(), - "checkServerTrusted", - "([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V"); + jmethodID X509TrustManagerCheckServerTrustedMethod = + env->GetMethodID(X509TrustManagerClass.get(), + "checkServerTrusted", + "([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V"); CHECK_JMID(env, X509TrustManagerCheckServerTrustedMethod); // StrictHostnameVerifier - java_local_ref strictHostnameVerifierClass(env->FindClass("org/apache/http/conn/ssl/StrictHostnameVerifier")); + java_local_ref strictHostnameVerifierClass( + env->FindClass("org/apache/http/conn/ssl/StrictHostnameVerifier")); CHECK_JREF(env, strictHostnameVerifierClass); - jmethodID strictHostnameVerifierConstructorMethod = env->GetMethodID(strictHostnameVerifierClass.get(), "", "()V"); + jmethodID strictHostnameVerifierConstructorMethod = + env->GetMethodID(strictHostnameVerifierClass.get(), "", "()V"); CHECK_JMID(env, strictHostnameVerifierConstructorMethod); jmethodID strictHostnameVerifierVerifyMethod = env->GetMethodID( - strictHostnameVerifierClass.get(), - "verify", - "(Ljava/lang/String;Ljava/security/cert/X509Certificate;)V"); + strictHostnameVerifierClass.get(), "verify", "(Ljava/lang/String;Ljava/security/cert/X509Certificate;)V"); CHECK_JMID(env, strictHostnameVerifierVerifyMethod); // Create CertificateFactory java_local_ref XDot509String(env->NewStringUTF("X.509")); CHECK_JREF(env, XDot509String); java_local_ref certificateFactory(env->CallStaticObjectMethod( - certificateFactoryClass.get(), - certificateFactoryGetInstanceMethod, - XDot509String.get())); + certificateFactoryClass.get(), certificateFactoryGetInstanceMethod, XDot509String.get())); CHECK_JREF(env, certificateFactory); // Create Java array to store all the certs in. @@ -229,22 +226,18 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std // 2. Create Certificate using CertificateFactory.generateCertificate // 3. Add Certificate to array int i = 0; - for(const auto &certData : certChain) + for (const auto& certData : certChain) { java_local_ref byteArray(env->NewByteArray(certData.size())); CHECK_JREF(env, byteArray); - env->SetByteArrayRegion(byteArray.get(), 0, certData.size(), reinterpret_cast(certData.c_str())); + env->SetByteArrayRegion(byteArray.get(), 0, certData.size(), reinterpret_cast(certData.c_str())); CHECK_JNI(env); - java_local_ref byteArrayInputStream(env->NewObject( - byteArrayInputStreamClass.get(), - byteArrayInputStreamConstructorMethod, - byteArray.get())); + java_local_ref byteArrayInputStream( + env->NewObject(byteArrayInputStreamClass.get(), byteArrayInputStreamConstructorMethod, byteArray.get())); CHECK_JREF(env, byteArrayInputStream); - java_local_ref cert(env->CallObjectMethod( - certificateFactory.get(), - generateCertificateMethod, - byteArrayInputStream.get())); + java_local_ref cert( + env->CallObjectMethod(certificateFactory.get(), generateCertificateMethod, byteArrayInputStream.get())); CHECK_JREF(env, cert); env->SetObjectArrayElement(certsArray.get(), i, cert.get()); @@ -256,9 +249,7 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std java_local_ref X509String(env->NewStringUTF("X509")); CHECK_JREF(env, X509String); java_local_ref trustFactoryManager(env->CallStaticObjectMethod( - trustManagerFactoryClass.get(), - trustManagerFactoryGetInstanceMethod, - X509String.get())); + trustManagerFactoryClass.get(), trustManagerFactoryGetInstanceMethod, X509String.get())); CHECK_JREF(env, trustFactoryManager); env->CallVoidMethod(trustFactoryManager.get(), trustManagerFactoryInitMethod, nullptr); CHECK_JNI(env); @@ -274,25 +265,18 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std java_local_ref RSAString(env->NewStringUTF("RSA")); CHECK_JREF(env, RSAString); env->CallVoidMethod( - trustManager.get(), - X509TrustManagerCheckServerTrustedMethod, - certsArray.get(), - RSAString.get()); + trustManager.get(), X509TrustManagerCheckServerTrustedMethod, certsArray.get(), RSAString.get()); CHECK_JNI(env); // Verify hostname on certificate according to RFC 2818. - java_local_ref hostnameVerifier(env->NewObject( - strictHostnameVerifierClass.get(), strictHostnameVerifierConstructorMethod)); + java_local_ref hostnameVerifier( + env->NewObject(strictHostnameVerifierClass.get(), strictHostnameVerifierConstructorMethod)); CHECK_JREF(env, hostnameVerifier); java_local_ref hostNameString(env->NewStringUTF(hostName.c_str())); CHECK_JREF(env, hostNameString); java_local_ref cert(env->GetObjectArrayElement(certsArray.get(), 0)); CHECK_JREF(env, cert); - env->CallVoidMethod( - hostnameVerifier.get(), - strictHostnameVerifierVerifyMethod, - hostNameString.get(), - cert.get()); + env->CallVoidMethod(hostnameVerifier.get(), strictHostnameVerifierVerifyMethod, hostNameString.get(), cert.get()); CHECK_JNI(env); return true; @@ -300,64 +284,65 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std #endif #if defined(__APPLE__) -namespace { - // Simple RAII pattern wrapper to perform CFRelease on objects. - template - class cf_ref +namespace +{ +// Simple RAII pattern wrapper to perform CFRelease on objects. +template +class cf_ref +{ +public: + cf_ref(T v) : value(v) { - public: - cf_ref(T v) : value(v) - { - static_assert(sizeof(cf_ref) == sizeof(T), "Code assumes just a wrapper, see usage in CFArrayCreate below."); - } - cf_ref() : value(nullptr) {} - cf_ref(cf_ref &&other) : value(other.value) { other.value = nullptr; } + static_assert(sizeof(cf_ref) == sizeof(T), "Code assumes just a wrapper, see usage in CFArrayCreate below."); + } + cf_ref() : value(nullptr) {} + cf_ref(cf_ref&& other) : value(other.value) { other.value = nullptr; } - ~cf_ref() + ~cf_ref() + { + if (value != nullptr) { - if(value != nullptr) - { - CFRelease(value); - } + CFRelease(value); } + } - T & get() - { - return value; - } - private: - cf_ref(const cf_ref &); - cf_ref & operator=(const cf_ref &); - T value; - }; + T& get() { return value; } + +private: + cf_ref(const cf_ref&); + cf_ref& operator=(const cf_ref&); + T value; +}; } -bool verify_X509_cert_chain(const std::vector &certChain, const std::string &hostName) +bool verify_X509_cert_chain(const std::vector& certChain, const std::string& hostName) { // Build up CFArrayRef with all the certificates. // All this code is basically just to get into the correct structures for the Apple APIs. // Copies are avoided whenever possible. std::vector> certs; - for(const auto & certBuf : certChain) + for (const auto& certBuf : certChain) { - cf_ref certDataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, - reinterpret_cast(certBuf.c_str()), - certBuf.size(), - kCFAllocatorNull); - if(certDataRef.get() == nullptr) + cf_ref certDataRef = + CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + reinterpret_cast(certBuf.c_str()), + certBuf.size(), + kCFAllocatorNull); + if (certDataRef.get() == nullptr) { return false; } cf_ref certObj = SecCertificateCreateWithData(nullptr, certDataRef.get()); - if(certObj.get() == nullptr) + if (certObj.get() == nullptr) { return false; } certs.push_back(std::move(certObj)); } - cf_ref certsArray = CFArrayCreate(kCFAllocatorDefault, const_cast(reinterpret_cast(&certs[0])), certs.size(), nullptr); - if(certsArray.get() == nullptr) + cf_ref certsArray = CFArrayCreate( + kCFAllocatorDefault, const_cast(reinterpret_cast(&certs[0])), certs.size(), nullptr); + if (certsArray.get() == nullptr) { return false; } @@ -365,23 +350,21 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std // Create trust management object with certificates and SSL policy. // Note: SecTrustCreateWithCertificates expects the certificate to be // verified is the first element. - cf_ref cfHostName = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, - hostName.c_str(), - kCFStringEncodingASCII, - kCFAllocatorNull); - if(cfHostName.get() == nullptr) + cf_ref cfHostName = CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, hostName.c_str(), kCFStringEncodingASCII, kCFAllocatorNull); + if (cfHostName.get() == nullptr) { return false; } cf_ref policy = SecPolicyCreateSSL(true /* client side */, cfHostName.get()); cf_ref trust; OSStatus status = SecTrustCreateWithCertificates(certsArray.get(), policy.get(), &trust.get()); - if(status == noErr) + if (status == noErr) { // Perform actual certificate verification. SecTrustResultType trustResult; status = SecTrustEvaluate(trust.get(), &trustResult); - if(status == noErr && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) + if (status == noErr && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed)) { return true; } @@ -392,33 +375,27 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std #endif #if defined(_WIN32) -namespace { - // Helper RAII unique_ptrs to free Windows structures. - struct cert_free_certificate_context - { - void operator()(const CERT_CONTEXT *ctx) const - { - CertFreeCertificateContext(ctx); - } - }; - typedef std::unique_ptr cert_context; - struct cert_free_certificate_chain - { - void operator()(const CERT_CHAIN_CONTEXT *chain) const - { - CertFreeCertificateChain(chain); - } - }; - typedef std::unique_ptr chain_context; +namespace +{ +// Helper RAII unique_ptrs to free Windows structures. +struct cert_free_certificate_context +{ + void operator()(const CERT_CONTEXT* ctx) const { CertFreeCertificateContext(ctx); } +}; +typedef std::unique_ptr cert_context; +struct cert_free_certificate_chain +{ + void operator()(const CERT_CHAIN_CONTEXT* chain) const { CertFreeCertificateChain(chain); } +}; +typedef std::unique_ptr chain_context; } -bool verify_X509_cert_chain(const std::vector &certChain, const std::string &) +bool verify_X509_cert_chain(const std::vector& certChain, const std::string&) { // Create certificate context from server certificate. - cert_context cert(CertCreateCertificateContext( - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - reinterpret_cast(certChain[0].c_str()), - static_cast(certChain[0].size()))); + cert_context cert(CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + reinterpret_cast(certChain[0].c_str()), + static_cast(certChain[0].size()))); if (cert == nullptr) { return false; @@ -429,27 +406,17 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std ZeroMemory(¶ms, sizeof(params)); params.cbSize = sizeof(CERT_CHAIN_PARA); params.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; - LPSTR usages [] = - { - (LPSTR)szOID_PKIX_KP_SERVER_AUTH, + LPSTR usages[] = {(LPSTR)szOID_PKIX_KP_SERVER_AUTH, - // For older servers and to match IE. - (LPSTR)szOID_SERVER_GATED_CRYPTO, - (LPSTR)szOID_SGC_NETSCAPE - }; + // For older servers and to match IE. + (LPSTR)szOID_SERVER_GATED_CRYPTO, + (LPSTR)szOID_SGC_NETSCAPE}; params.RequestedUsage.Usage.cUsageIdentifier = std::extent::value; params.RequestedUsage.Usage.rgpszUsageIdentifier = usages; PCCERT_CHAIN_CONTEXT chainContext; chain_context chain; if (!CertGetCertificateChain( - nullptr, - cert.get(), - nullptr, - nullptr, - ¶ms, - CERT_CHAIN_REVOCATION_CHECK_CHAIN, - nullptr, - &chainContext)) + nullptr, cert.get(), nullptr, nullptr, ¶ms, CERT_CHAIN_REVOCATION_CHECK_CHAIN, nullptr, &chainContext)) { return false; } @@ -464,8 +431,9 @@ bool verify_X509_cert_chain(const std::vector &certChain, const std return true; } #endif - - -}}}} +} +} +} +} #endif From f884d916ee196324711ac26f06e43aa52af83585 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Thu, 9 Aug 2018 17:11:23 -0700 Subject: [PATCH 415/609] Attempt to repair VS2013 builds. (#833) --- Release/include/cpprest/asyncrt_utils.h | 6 +++--- Release/include/cpprest/http_headers.h | 26 ++++++++++++------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 3fbebd7d95..5978a2b051 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -356,7 +356,7 @@ namespace details /// Our own implementation of alpha numeric instead of std::isalnum to avoid /// taking global lock for performance reasons. /// - inline bool __cdecl is_alnum(const unsigned char uch) noexcept + inline bool __cdecl is_alnum(const unsigned char uch) CPPREST_NOEXCEPT { // test if uch is an alnum character // special casing char to avoid branches static constexpr bool is_alnum_table[UCHAR_MAX + 1] = @@ -379,7 +379,7 @@ namespace details /// Our own implementation of alpha numeric instead of std::isalnum to avoid /// taking global lock for performance reasons. /// - inline bool __cdecl is_alnum(const char ch) noexcept + inline bool __cdecl is_alnum(const char ch) CPPREST_NOEXCEPT { return (is_alnum(static_cast(ch))); } @@ -389,7 +389,7 @@ namespace details /// taking global lock for performance reasons. /// template - inline bool __cdecl is_alnum(Elem ch) noexcept + inline bool __cdecl is_alnum(Elem ch) CPPREST_NOEXCEPT { // assumes 'x' == L'x' for the ASCII range typedef typename std::make_unsigned::type UElem; diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 2bc1975acd..c2e35f6079 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -79,19 +79,19 @@ class http_headers /// /// STL-style typedefs /// - typedef typename inner_container::key_type key_type; - typedef typename inner_container::key_compare key_compare; - typedef typename inner_container::allocator_type allocator_type; - typedef typename inner_container::size_type size_type; - typedef typename inner_container::difference_type difference_type; - typedef typename inner_container::pointer pointer; - typedef typename inner_container::const_pointer const_pointer; - typedef typename inner_container::reference reference; - typedef typename inner_container::const_reference const_reference; - typedef typename inner_container::iterator iterator; - typedef typename inner_container::const_iterator const_iterator; - typedef typename inner_container::reverse_iterator reverse_iterator; - typedef typename inner_container::const_reverse_iterator const_reverse_iterator; + typedef inner_container::key_type key_type; + typedef inner_container::key_compare key_compare; + typedef inner_container::allocator_type allocator_type; + typedef inner_container::size_type size_type; + typedef inner_container::difference_type difference_type; + typedef inner_container::pointer pointer; + typedef inner_container::const_pointer const_pointer; + typedef inner_container::reference reference; + typedef inner_container::const_reference const_reference; + typedef inner_container::iterator iterator; + typedef inner_container::const_iterator const_iterator; + typedef inner_container::reverse_iterator reverse_iterator; + typedef inner_container::const_reverse_iterator const_reverse_iterator; /// /// Constructs an empty set of HTTP headers. From 6f65e878b3936143dd27679bfa17406799d9e294 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Thu, 9 Aug 2018 20:50:09 -0700 Subject: [PATCH 416/609] Implement host override of CN checking in the WinHTTP backend (#824) * Implement CN overrides via the Host: header in the WinHTTP backend. * Repair lack of fallback CN verification on Windows. * Set security settings even for non-HTTPS URIs in WinHTTP, in case we get upgraded to SSL/TLS later. * Add test to make sure this doesn't explode. * Repair CPPREST_EXCLUDE_WEBSOCKETS support. * Move x509_cert_utilities.h out of public headers. --- Release/src/http/client/http_client_asio.cpp | 16 +- .../src/http/client/http_client_winhttp.cpp | 291 ++++++++++++++---- .../src/http/client/x509_cert_utilities.cpp | 97 +++--- .../http/common}/x509_cert_utilities.h | 51 ++- .../src/websockets/client/ws_client_wspp.cpp | 18 +- .../functional/http/client/outside_tests.cpp | 33 +- 6 files changed, 374 insertions(+), 132 deletions(-) rename Release/{include/cpprest/details => src/http/common}/x509_cert_utilities.h (51%) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index ec41762b3f..d3002dfc09 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -39,7 +39,7 @@ #include "cpprest/base_uri.h" #include "cpprest/details/http_helpers.h" -#include "cpprest/details/x509_cert_utilities.h" +#include "../common/x509_cert_utilities.h" #include "http_client_impl.h" #include "pplx/threadpool.h" #include @@ -468,7 +468,7 @@ class asio_context final : public request_context, public std::enable_shared_fro , m_needChunked(false) , m_timer(client->client_config().timeout()) , m_connection(connection) -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE , m_openssl_failed(false) #endif { @@ -1032,11 +1032,11 @@ class asio_context final : public request_context, public std::enable_shared_fro // finally by the root CA self signed certificate. const auto& host = utility::conversions::to_utf8string(m_http_client->base_uri().host()); -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) - // On OS X, iOS, and Android, OpenSSL doesn't have access to where the OS - // stores keychains. If OpenSSL fails we will doing verification at the - // end using the whole certificate chain so wait until the 'leaf' cert. - // For now return true so OpenSSL continues down the certificate chain. +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE + // Attempt to use platform certificate validation when it is available: + // If OpenSSL fails we will doing verification at the end using the whole certificate chain, + // so wait until the 'leaf' cert. For now return true so OpenSSL continues down the certificate + // chain. if (!preverified) { m_openssl_failed = true; @@ -1757,7 +1757,7 @@ class asio_context final : public request_context, public std::enable_shared_fro boost::asio::streambuf m_body_buf; std::shared_ptr m_connection; -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE bool m_openssl_failed; #endif }; diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index ce037a4954..83a60d6ce5 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -15,14 +15,55 @@ #include "stdafx.h" #include +#include #include "cpprest/http_headers.h" +#include "../common/x509_cert_utilities.h" #include "http_client_impl.h" #ifndef CPPREST_TARGET_XP #include #endif +namespace +{ +struct security_failure_message +{ + std::uint32_t flag; + const char * text; +}; + +constexpr security_failure_message g_security_failure_messages[] = { + { WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED, + "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED failed to check revocation status."}, + { WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT, + "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT SSL certificate is invalid."}, + { WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED, + "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED SSL certificate was revoked."}, + { WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA, + "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA SSL invalid CA."}, + { WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID, + "WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID SSL common name does not match."}, + { WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID, + "WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID SLL certificate is expired."}, + { WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR, + "WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR internal error."}, +}; + +std::string generate_security_failure_message(std::uint32_t flags) +{ + std::string result("SSL Error:"); + for (const auto& message : g_security_failure_messages) { + if (flags & message.flag) { + result.push_back(' '); + result.append(message.text); + } + } + + return result; +} + +} // unnamed namespace namespace web { namespace http @@ -255,6 +296,124 @@ class winhttp_request_context final : public request_context } } + void install_custom_cn_check(const utility::string_t& customHost) + { + m_customCnCheck = customHost; + utility::details::inplace_tolower(m_customCnCheck); + } + + void on_send_request_validate_cn() + { + if (m_customCnCheck.empty()) + { + // no custom validation selected; either we've delegated that to winhttp or + // certificate checking is completely disabled + return; + } + + winhttp_cert_context certContext; + DWORD bufferSize = sizeof(certContext.raw); + if (!WinHttpQueryOption( + m_request_handle, + WINHTTP_OPTION_SERVER_CERT_CONTEXT, + &certContext.raw, + &bufferSize)) + { + auto errorCode = GetLastError(); + if (errorCode == HRESULT_CODE(WININET_E_INCORRECT_HANDLE_STATE)) + { + // typically happens when given a custom host with an initially HTTP connection + return; + } + + report_error(errorCode, build_error_msg(errorCode, + "WinHttpQueryOption WINHTTP_OPTION_SERVER_CERT_CONTEXT")); + cleanup(); + return; + } + + const auto encodedFirst = certContext.raw->pbCertEncoded; + const auto encodedLast = encodedFirst + certContext.raw->cbCertEncoded; + if (certContext.raw->cbCertEncoded == m_cachedEncodedCert.size() + && std::equal(encodedFirst, encodedLast, m_cachedEncodedCert.begin())) + { + // already validated OK + return; + } + + char oidPkixKpServerAuth[] = szOID_PKIX_KP_SERVER_AUTH; + char oidServerGatedCrypto[] = szOID_SERVER_GATED_CRYPTO; + char oidSgcNetscape[] = szOID_SGC_NETSCAPE; + char *chainUses[] = { + oidPkixKpServerAuth, + oidServerGatedCrypto, + oidSgcNetscape, + }; + + winhttp_cert_chain_context chainContext; + CERT_CHAIN_PARA chainPara = {sizeof(chainPara)}; + chainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; + chainPara.RequestedUsage.Usage.cUsageIdentifier = + sizeof(chainUses) / sizeof(char *); + chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = chainUses; + + // note that the following chain only checks the end certificate; we + // assume WinHTTP already validated everything but the common name. + if (!CertGetCertificateChain( + NULL, + certContext.raw, + nullptr, + certContext.raw->hCertStore, + &chainPara, + CERT_CHAIN_CACHE_END_CERT, + NULL, + &chainContext.raw)) + { + auto errorCode = GetLastError(); + report_error(errorCode, build_error_msg(errorCode, + "CertGetCertificateChain")); + cleanup(); + return; + } + + HTTPSPolicyCallbackData policyData = { + {sizeof(policyData)}, + AUTHTYPE_SERVER, + // we assume WinHTTP already checked these: + 0x00000080 /* SECURITY_FLAG_IGNORE_REVOCATION */ + | 0x00000100 /* SECURITY_FLAG_IGNORE_UNKNOWN_CA */ + | 0x00000200 /* SECURITY_FLAG_IGNORE_WRONG_USAGE */ + | 0x00002000 /* SECURITY_FLAG_IGNORE_CERT_DATE_INVALID */, + &m_customCnCheck[0], + }; + CERT_CHAIN_POLICY_PARA policyPara = {sizeof(policyPara)}; + policyPara.pvExtraPolicyPara = &policyData; + + CERT_CHAIN_POLICY_STATUS policyStatus = {sizeof(policyStatus)}; + if (!CertVerifyCertificateChainPolicy( + CERT_CHAIN_POLICY_SSL, + chainContext.raw, + &policyPara, + &policyStatus)) + { + auto errorCode = GetLastError(); + report_error(errorCode, build_error_msg(errorCode, + "CertVerifyCertificateChainPolicy")); + cleanup(); + return; + } + + if (policyStatus.dwError) + { + report_error(policyStatus.dwError, + build_error_msg(policyStatus.dwError, "Incorrect common name")); + cleanup(); + return; + } + + m_cachedEncodedCert.assign(encodedFirst, encodedLast); + } + protected: virtual void finish() override @@ -267,6 +426,9 @@ class winhttp_request_context final : public request_context private: + utility::string_t m_customCnCheck; + std::vector m_cachedEncodedCert; + // Can only create on the heap using factory function. winhttp_request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request) : request_context(client, request), @@ -393,14 +555,6 @@ class winhttp_client final : public _http_client_communicator protected: - unsigned long report_failure(const utility::string_t& errorMessage) - { - // Should we log? - CASABLANCA_UNREFERENCED_PARAMETER(errorMessage); - - return GetLastError(); - } - // Open session and connection with the server. unsigned long open() { @@ -519,7 +673,7 @@ class winhttp_client final : public _http_client_communicator WINHTTP_FLAG_ASYNC); if(!m_hSession) { - return report_failure(_XPLATSTR("Error opening session")); + return GetLastError(); } // Set timeouts. @@ -531,7 +685,7 @@ class winhttp_client final : public _http_client_communicator milliseconds, milliseconds)) { - return report_failure(_XPLATSTR("Error setting timeouts")); + return GetLastError(); } if(config.guarantee_order()) @@ -540,7 +694,7 @@ class winhttp_client final : public _http_client_communicator DWORD maxConnections = 1; if(!WinHttpSetOption(m_hSession, WINHTTP_OPTION_MAX_CONNS_PER_SERVER, &maxConnections, sizeof(maxConnections))) { - return report_failure(_XPLATSTR("Error setting options")); + return GetLastError(); } } @@ -552,7 +706,7 @@ class winhttp_client final : public _http_client_communicator win32_result = ::WinHttpSetOption(m_hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols)); if(FALSE == win32_result) { - return report_failure(_XPLATSTR("Error setting session options")); + return GetLastError(); } #endif @@ -562,10 +716,13 @@ class winhttp_client final : public _http_client_communicator if(WINHTTP_INVALID_STATUS_CALLBACK == WinHttpSetStatusCallback( m_hSession, &winhttp_client::completion_callback, - WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS | WINHTTP_CALLBACK_FLAG_HANDLES | WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, + WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS + | WINHTTP_CALLBACK_FLAG_HANDLES + | WINHTTP_CALLBACK_FLAG_SECURE_FAILURE + | WINHTTP_CALLBACK_FLAG_SEND_REQUEST, 0)) { - return report_failure(_XPLATSTR("Error registering callback")); + return GetLastError(); } // Open connection. @@ -578,7 +735,7 @@ class winhttp_client final : public _http_client_communicator if(m_hConnection == nullptr) { - return report_failure(_XPLATSTR("Error opening connection")); + return GetLastError(); } m_opened = true; @@ -600,6 +757,7 @@ class winhttp_client final : public _http_client_communicator } http_request &msg = request->m_request; + http_headers &headers = msg.headers(); std::shared_ptr winhttp_context = std::static_pointer_cast(request); std::weak_ptr weak_winhttp_context = winhttp_context; @@ -659,18 +817,6 @@ class winhttp_client final : public _http_client_communicator return; } - // Enable the certificate revocation check - if (m_secure && client_config().validate_certificates()) - { - DWORD dwEnableSSLRevocOpt = WINHTTP_ENABLE_SSL_REVOCATION; - if (!WinHttpSetOption(winhttp_context->m_request_handle, WINHTTP_OPTION_ENABLE_FEATURE, &dwEnableSSLRevocOpt, sizeof(dwEnableSSLRevocOpt))) - { - auto errorCode = GetLastError(); - request->report_error(errorCode, build_error_msg(errorCode, "Error enabling SSL revocation check")); - return; - } - } - if(proxy_info_required) { auto result = WinHttpSetOption( @@ -707,24 +853,49 @@ class winhttp_client final : public _http_client_communicator } // Check to turn off server certificate verification. - if(!client_config().validate_certificates()) + DWORD ignoredCertificateValidationSteps = 0; + if (client_config().validate_certificates()) + { + // if we are validating certificates, also turn on revocation checking + DWORD dwEnableSSLRevocOpt = WINHTTP_ENABLE_SSL_REVOCATION; + if (!WinHttpSetOption(winhttp_context->m_request_handle, WINHTTP_OPTION_ENABLE_FEATURE, + &dwEnableSSLRevocOpt, sizeof(dwEnableSSLRevocOpt))) + { + auto errorCode = GetLastError(); + request->report_error(errorCode, build_error_msg(errorCode, "Error enabling SSL revocation check")); + return; + } + + // check if the user has overridden the desired Common Name with the host header + const auto hostHeader = headers.find(_XPLATSTR("Host")); + if (hostHeader != headers.end()) + { + const auto& requestHost = hostHeader->second; + if (!utility::details::str_iequal(requestHost, m_uri.host())) + { + winhttp_context->install_custom_cn_check(requestHost); + ignoredCertificateValidationSteps = SECURITY_FLAG_IGNORE_CERT_CN_INVALID; + } + } + } + else { - DWORD data = SECURITY_FLAG_IGNORE_UNKNOWN_CA + ignoredCertificateValidationSteps = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; + } - auto result = WinHttpSetOption( + if(ignoredCertificateValidationSteps + && !WinHttpSetOption( winhttp_context->m_request_handle, WINHTTP_OPTION_SECURITY_FLAGS, - &data, - sizeof(data)); - if(!result) - { - auto errorCode = GetLastError(); - request->report_error(errorCode, build_error_msg(errorCode, "Setting ignore server certificate verification")); - return; - } + &ignoredCertificateValidationSteps, + sizeof(ignoredCertificateValidationSteps))) + { + auto errorCode = GetLastError(); + request->report_error(errorCode, build_error_msg(errorCode, "Setting ignore server certificate verification")); + return; } const size_t content_length = msg._get_impl()->_get_content_length(); @@ -751,7 +922,7 @@ class winhttp_client final : public _http_client_communicator } } - utility::string_t flattened_headers = web::http::details::flatten_http_headers(msg.headers()); + utility::string_t flattened_headers = web::http::details::flatten_http_headers(headers); flattened_headers += winhttp_context->get_accept_encoding_header(); // Add headers. @@ -1218,7 +1389,9 @@ class winhttp_client final : public _http_client_communicator std::weak_ptr* p_weak_request_context = reinterpret_cast *>(context); if (p_weak_request_context == nullptr) + { return; + } if (statusCode == WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING) { @@ -1230,8 +1403,10 @@ class winhttp_client final : public _http_client_communicator auto p_request_context = p_weak_request_context->lock(); if (!p_request_context) + { // The request context was already released, probably due to cancellation return; + } switch (statusCode) { @@ -1254,7 +1429,7 @@ class winhttp_client final : public _http_client_communicator } p_request_context->report_error(errorCode, build_error_msg(error_result)); - break; + return; } case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE : { @@ -1288,25 +1463,15 @@ class winhttp_client final : public _http_client_communicator p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReceiveResponse")); } } - break; + return; } + case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST: + p_request_context->on_send_request_validate_cn(); + return; case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: - { - auto *flagsPtr = reinterpret_cast(statusInfo); - auto flags = *flagsPtr; - - std::string err = "SSL error: "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED failed to check revocation status. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT) err += "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT SSL certificate is invalid. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED SSL certificate was revoked. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) err += "WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA SSL invalid CA. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID SSL common name does not match. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID) err += "WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID SLL certificate is expired. "; - if (flags & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR) err += "WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR internal error. "; - - p_request_context->report_exception(web::http::http_exception(std::move(err))); - break; - } + p_request_context->report_exception(web::http::http_exception( + generate_security_failure_message(*reinterpret_cast(statusInfo)))); + return; case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE : { DWORD bytesWritten = *((DWORD *)statusInfo); @@ -1347,7 +1512,7 @@ class winhttp_client final : public _http_client_communicator p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpReceiveResponse")); } } - break; + return; } case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE : { @@ -1411,7 +1576,7 @@ class winhttp_client final : public _http_client_communicator // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 read_next_response_chunk(p_request_context.get(), 0, true); - break; + return; } case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE : { @@ -1459,7 +1624,7 @@ class winhttp_client final : public _http_client_communicator p_request_context->complete_request(p_request_context->m_downloaded); } - break; + return; } case WINHTTP_CALLBACK_STATUS_READ_COMPLETE : { @@ -1483,7 +1648,7 @@ class winhttp_client final : public _http_client_communicator if (bytesRead == 0) { p_request_context->complete_request(p_request_context->m_downloaded); - break; + return; } auto writebuf = p_request_context->_get_writebuffer(); @@ -1544,9 +1709,9 @@ class winhttp_client final : public _http_client_communicator read_next_response_chunk(p_request_context.get(), bytesRead); }); } - break; + return; } - } + } } std::atomic m_opened; diff --git a/Release/src/http/client/x509_cert_utilities.cpp b/Release/src/http/client/x509_cert_utilities.cpp index baf1ae8488..0a7a762d50 100644 --- a/Release/src/http/client/x509_cert_utilities.cpp +++ b/Release/src/http/client/x509_cert_utilities.cpp @@ -12,11 +12,11 @@ ****/ #include "stdafx.h" +#include "../common/x509_cert_utilities.h" -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || \ - (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE -#include "cpprest/details/x509_cert_utilities.h" +#include #include #if defined(ANDROID) || defined(__ANDROID__) @@ -32,11 +32,6 @@ #include #endif -#if defined(_WIN32) -#include -#include -#endif - namespace web { namespace http @@ -375,55 +370,67 @@ bool verify_X509_cert_chain(const std::vector& certChain, const std #endif #if defined(_WIN32) -namespace -{ -// Helper RAII unique_ptrs to free Windows structures. -struct cert_free_certificate_context -{ - void operator()(const CERT_CONTEXT* ctx) const { CertFreeCertificateContext(ctx); } -}; -typedef std::unique_ptr cert_context; -struct cert_free_certificate_chain -{ - void operator()(const CERT_CHAIN_CONTEXT* chain) const { CertFreeCertificateChain(chain); } -}; -typedef std::unique_ptr chain_context; -} - -bool verify_X509_cert_chain(const std::vector& certChain, const std::string&) +bool verify_X509_cert_chain(const std::vector& certChain, const std::string& hostname) { // Create certificate context from server certificate. - cert_context cert(CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - reinterpret_cast(certChain[0].c_str()), - static_cast(certChain[0].size()))); - if (cert == nullptr) + winhttp_cert_context cert; + cert.raw = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + reinterpret_cast(certChain[0].c_str()), + static_cast(certChain[0].size())); + if (cert.raw == nullptr) { return false; } // Let the OS build a certificate chain from the server certificate. - CERT_CHAIN_PARA params; - ZeroMemory(¶ms, sizeof(params)); - params.cbSize = sizeof(CERT_CHAIN_PARA); - params.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; - LPSTR usages[] = {(LPSTR)szOID_PKIX_KP_SERVER_AUTH, - - // For older servers and to match IE. - (LPSTR)szOID_SERVER_GATED_CRYPTO, - (LPSTR)szOID_SGC_NETSCAPE}; - params.RequestedUsage.Usage.cUsageIdentifier = std::extent::value; - params.RequestedUsage.Usage.rgpszUsageIdentifier = usages; - PCCERT_CHAIN_CONTEXT chainContext; - chain_context chain; - if (!CertGetCertificateChain( - nullptr, cert.get(), nullptr, nullptr, ¶ms, CERT_CHAIN_REVOCATION_CHECK_CHAIN, nullptr, &chainContext)) + char oidPkixKpServerAuth[] = szOID_PKIX_KP_SERVER_AUTH; + char oidServerGatedCrypto[] = szOID_SERVER_GATED_CRYPTO; + char oidSgcNetscape[] = szOID_SGC_NETSCAPE; + char* chainUses[] = { + oidPkixKpServerAuth, + oidServerGatedCrypto, + oidSgcNetscape, + }; + CERT_CHAIN_PARA chainPara = {sizeof(chainPara)}; + chainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; + chainPara.RequestedUsage.Usage.cUsageIdentifier = sizeof(chainUses) / sizeof(char*); + chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = chainUses; + + winhttp_cert_chain_context chainContext; + if (!CertGetCertificateChain(nullptr, + cert.raw, + nullptr, + cert.raw->hCertStore, + &chainPara, + CERT_CHAIN_REVOCATION_CHECK_CHAIN, + nullptr, + &chainContext.raw)) { return false; } - chain.reset(chainContext); // Check to see if the certificate chain is actually trusted. - if (chain->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) + if (chainContext.raw->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) + { + return false; + } + + auto u16HostName = utility::conversions::to_utf16string(hostname); + HTTPSPolicyCallbackData policyData = { + {sizeof(policyData)}, + AUTHTYPE_SERVER, + 0, + &u16HostName[0], + }; + CERT_CHAIN_POLICY_PARA policyPara = {sizeof(policyPara)}; + policyPara.pvExtraPolicyPara = &policyData; + CERT_CHAIN_POLICY_STATUS policyStatus = {sizeof(policyStatus)}; + if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, chainContext.raw, &policyPara, &policyStatus)) + { + return false; + } + + if (policyStatus.dwError) { return false; } diff --git a/Release/include/cpprest/details/x509_cert_utilities.h b/Release/src/http/common/x509_cert_utilities.h similarity index 51% rename from Release/include/cpprest/details/x509_cert_utilities.h rename to Release/src/http/common/x509_cert_utilities.h index cc40d9ccfb..e19af0498a 100644 --- a/Release/include/cpprest/details/x509_cert_utilities.h +++ b/Release/src/http/common/x509_cert_utilities.h @@ -13,9 +13,52 @@ #pragma once -#include +#if defined(_WIN32) +#include + +namespace web { namespace http { namespace client { namespace details { + +struct winhttp_cert_context +{ + PCCERT_CONTEXT raw; + winhttp_cert_context() noexcept : raw(nullptr) {} + winhttp_cert_context(const winhttp_cert_context&) = delete; + winhttp_cert_context& operator=(const winhttp_cert_context&) = delete; + ~winhttp_cert_context() + { + // https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-certfreecertificatecontext + // "The function always returns nonzero." + if (raw) + { + (void)CertFreeCertificateContext(raw); + } + } +}; + +struct winhttp_cert_chain_context +{ + PCCERT_CHAIN_CONTEXT raw; + winhttp_cert_chain_context() noexcept : raw(nullptr) {} + winhttp_cert_chain_context(const winhttp_cert_chain_context&) = delete; + winhttp_cert_chain_context& operator=(const winhttp_cert_chain_context&) = delete; + ~winhttp_cert_chain_context() + { + if (raw) + { + CertFreeCertificateChain(raw); + } + } +}; -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) +}}}} // namespaces +#endif // _WIN32 + +#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) + #define CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE +#endif + +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE +#include #if defined(_MSC_VER) #pragma warning(push) @@ -37,7 +80,7 @@ namespace web { namespace http { namespace client { namespace details { /// /// Using platform specific APIs verifies server certificate. -/// Currently implemented to work on iOS, Android, and OS X. +/// Currently implemented to work on Windows, iOS, Android, and OS X. /// /// Boost.ASIO context to get certificate chain from. /// Host name from the URI. @@ -46,4 +89,4 @@ bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verif }}}} -#endif \ No newline at end of file +#endif // CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index c670dd0a61..39b7121d57 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -15,7 +15,7 @@ #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) -#include "cpprest/details/x509_cert_utilities.h" +#include "../../http/common/x509_cert_utilities.h" #include "pplx/threadpool.h" #include "ws_client_impl.h" @@ -122,7 +122,7 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: wspp_callback_client(websocket_client_config config) : websocket_client_callback_impl(std::move(config)), m_state(CREATED) -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || defined(_WIN32) +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE , m_openssl_failed(false) #endif {} @@ -188,16 +188,16 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: sslContext->set_verify_mode(boost::asio::ssl::context::verify_none); } -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || defined(_WIN32) +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE m_openssl_failed = false; #endif sslContext->set_verify_callback([this](bool preverified, boost::asio::ssl::verify_context &verifyCtx) { -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || defined(_WIN32) - // On OS X, iOS, and Android, OpenSSL doesn't have access to where the OS - // stores keychains. If OpenSSL fails we will doing verification at the - // end using the whole certificate chain so wait until the 'leaf' cert. - // For now return true so OpenSSL continues down the certificate chain. +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE + // Attempt to use platform certificate validation when it is available: + // If OpenSSL fails we will doing verification at the end using the whole certificate chain, + // so wait until the 'leaf' cert. For now return true so OpenSSL continues down the certificate + // chain. if(!preverified) { m_openssl_failed = true; @@ -778,7 +778,7 @@ class wspp_callback_client : public websocket_client_callback_impl, public std:: // Used to track if any of the OpenSSL server certificate verifications // failed. This can safely be tracked at the client level since connections // only happen once for each client. -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || defined(_WIN32) +#ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE bool m_openssl_failed; #endif diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 00404a290f..f6ea1396cf 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -173,8 +173,8 @@ static void test_ignored_ssl_cert(const uri& base_uri) http_client_config config; config.set_validate_certificates(false); http_client client(base_uri, config); - auto request = client.request(methods::GET).get(); - VERIFY_ARE_EQUAL(status_codes::OK, request.status_code()); + auto response = client.request(methods::GET).get(); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); }); } #endif // !defined(__cplusplus_winrt) @@ -197,10 +197,34 @@ TEST(server_hostname_mismatch) } #if !defined(__cplusplus_winrt) +TEST(server_hostname_host_override, + "Ignore:Android", "229", + "Ignore:Apple", "229", + "Ignore:Linux", "229") +{ + handle_timeout([] + { + http_client client(U("https://wrong.host.badssl.com/")); + http_request req(methods::GET); + req.headers().add(U("Host"), U("badssl.com")); + auto response = client.request(req).get(); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); + }); +} + TEST(server_hostname_mismatch_ignored) { test_ignored_ssl_cert(U("https://wrong.host.badssl.com/")); } + +TEST(server_hostname_host_override_after_upgrade) +{ + http_client client(U("http://198.35.26.96/")); + http_request req(methods::GET); + req.headers().add(U("Host"), U("en.wikipedia.org")); + auto response = client.request(req).get(); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); +} #endif // !defined(__cplusplus_winrt) TEST(server_cert_expired) @@ -215,7 +239,10 @@ TEST(server_cert_expired_ignored) } #endif // !defined(__cplusplus_winrt) -TEST(server_cert_revoked) +TEST(server_cert_revoked, + "Ignore:Android", "229", + "Ignore:Apple", "229", + "Ignore:Linux", "229") { test_failed_ssl_cert(U("https://revoked.badssl.com/")); } From b569ec3983b32b662b39a01afac3e0ea1fd3186d Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Sat, 11 Aug 2018 22:36:23 -0700 Subject: [PATCH 417/609] Avoid saying constexpr for VS2013. (#834) --- Release/include/cpprest/asyncrt_utils.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 5978a2b051..b4b6c591f4 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -359,7 +359,13 @@ namespace details inline bool __cdecl is_alnum(const unsigned char uch) CPPREST_NOEXCEPT { // test if uch is an alnum character // special casing char to avoid branches - static constexpr bool is_alnum_table[UCHAR_MAX + 1] = + static + #if !defined(_MSC_VER) || _MSC_VER >= 1900 + constexpr + #else + const + #endif + bool is_alnum_table[UCHAR_MAX + 1] = { /* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */ /* 0X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, From 4e19c0cfb439febf6b3ee20efc857313ca2ba7f7 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 15 Aug 2018 12:22:20 -0700 Subject: [PATCH 418/609] Implement host override of CN checking in the ASIO backend (#832) * Implement host override of CN checking in the ASIO backend Add new function calc_cn_host which applies our host header override policy. Add the CN hostname used to asio_connection. Change the protocol such that the SSL upgrade request needs to come with the target hostname to use. Replace std::deque in connection pooling with a version that has constant amortized time per insertion. (std::deque is only constant amortized time for insertions in terms of element operations, not overall). Factor out the replacement policy from the overall pool machinery. Change release() to take shared_ptr&& to make sure the caller has let go. Enable verify_cert_chain_platform_specific on Windows; otherwise OpenSSL says that the root CAs are untrusted and all SSL tests fail on Windows. This accidentially repairs these test cases on Windows: **** outside_tests:outside_wikipedia_compressed_http_response FAILED **** **** outside_tests:multiple_https_requests FAILED **** **** outside_tests:outside_ssl_json FAILED **** * Add missing std::move. * Use hot connections instead of cold connections in connection pool. * Put timer start code back. * Reset the shared_ptr when it is being dropped. * Fix end comment broken by merge hell. --- Release/src/http/client/http_client_asio.cpp | 255 ++++++++++++------ Release/src/http/common/x509_cert_utilities.h | 62 +++-- .../functional/http/client/outside_tests.cpp | 10 +- 3 files changed, 221 insertions(+), 106 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index d3002dfc09..e3ea15c9ff 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -81,7 +81,35 @@ using utility::conversions::details::to_string; using std::to_string; #endif -static const std::string CRLF("\r\n"); +namespace +{ +const std::string CRLF("\r\n"); + +std::string calc_cn_host(const bool secure, + const web::http::uri& baseUri, + const web::http::http_headers& requestHeaders) +{ + std::string result; + if (secure) + { + const utility::string_t* encResult; + const auto hostHeader = requestHeaders.find(_XPLATSTR("Host")); + if (hostHeader == requestHeaders.end()) + { + encResult = &baseUri.host(); + } + else + { + encResult = &hostHeader->second; + } + + result = utility::conversions::to_utf8string(*encResult); + utility::details::inplace_tolower(result); + } + + return result; +} +} // namespace namespace web { @@ -119,14 +147,21 @@ class asio_connection public: asio_connection(boost::asio::io_service& io_service) - : m_socket(io_service), m_is_reused(false), m_keep_alive(true), m_closed(false) + : m_socket_lock() + , m_socket(io_service) + , m_ssl_stream() + , m_cn_hostname() + , m_is_reused(false) + , m_keep_alive(true) + , m_closed(false) { } ~asio_connection() { close(); } // This simply instantiates the internal state to support ssl. It does not perform the handshake. - void upgrade_to_ssl(const std::function& ssl_context_callback) + void upgrade_to_ssl(std::string&& cn_hostname, + const std::function& ssl_context_callback) { std::lock_guard lock(m_socket_lock); assert(!is_ssl()); @@ -139,6 +174,7 @@ class asio_connection } m_ssl_stream = utility::details::make_unique>( m_socket, ssl_context); + m_cn_hostname = std::move(cn_hostname); } void close() @@ -166,6 +202,7 @@ class asio_connection void set_keep_alive(bool keep_alive) { m_keep_alive = keep_alive; } bool keep_alive() const { return m_keep_alive; } bool is_ssl() const { return m_ssl_stream ? true : false; } + const std::string& cn_hostname() const { return m_cn_hostname; } // Check if the error code indicates that the connection was closed by the // server: this is used to detect if a connection in the pool was closed during @@ -223,7 +260,6 @@ class asio_connection template void async_handshake(boost::asio::ssl::stream_base::handshake_type type, const http_client_config& config, - const std::string& host_name, const HandshakeHandler& handshake_handler, const CertificateHandler& cert_handler) { @@ -244,7 +280,7 @@ class asio_connection // Check to set host name for Server Name Indication (SNI) if (config.is_tlsext_sni_enabled()) { - SSL_set_tlsext_host_name(m_ssl_stream->native_handle(), const_cast(host_name.data())); + SSL_set_tlsext_host_name(m_ssl_stream->native_handle(), &m_cn_hostname[0]); } m_ssl_stream->async_handshake(type, handshake_handler); @@ -301,22 +337,60 @@ class asio_connection std::mutex m_socket_lock; tcp::socket m_socket; std::unique_ptr> m_ssl_stream; + std::string m_cn_hostname; bool m_is_reused; bool m_keep_alive; bool m_closed; }; +class connection_pool_stack +{ +public: + // attempts to acquire a connection from the deque; returns nullptr if no connection is + // available + std::shared_ptr try_acquire() CPPREST_NOEXCEPT + { + const size_t oldConnectionsSize = m_connections.size(); + if (m_highWater > oldConnectionsSize) + { + m_highWater = oldConnectionsSize; + } + + if (oldConnectionsSize == 0) + { + return nullptr; + } + + auto result = std::move(m_connections.back()); + m_connections.pop_back(); + return result; + } + + // releases `released` back to the connection pool + void release(std::shared_ptr&& released) + { + m_connections.push_back(std::move(released)); + } + + bool free_stale_connections() CPPREST_NOEXCEPT + { + m_connections.erase(m_connections.begin(), m_connections.begin() + m_highWater); + const size_t connectionsSize = m_connections.size(); + m_highWater = connectionsSize; + return (connectionsSize != 0); + } + +private: + size_t m_highWater = 0; + std::vector> m_connections; +}; + /// Implements a connection pool with adaptive connection removal /// -/// The timeout mechanism is based on the `uint64_t m_epoch` member. Every 30 seconds, -/// the lambda in `start_epoch_interval` fires, triggering the cleanup of any -/// connections that have resided in the pool since the last cleanup phase's epoch. -/// -/// This works because the `m_connections` member functions is used in LIFO order. -/// LIFO usage guarantees that the elements remain sorted based on epoch number, -/// since the highest epoch is always removed and on insertion the next monotonically -/// increasing epoch is used. +/// Every 30 seconds, the lambda in `start_epoch_interval` fires, triggering the +/// cleanup of any connections that have resided in the pool since the last +/// cleanup phase. /// /// During the cleanup phase, connections are removed starting with the oldest. This /// ensures that if a high intensity workload is followed by a low intensity workload, @@ -327,93 +401,107 @@ class asio_connection /// /// while(1) /// { -/// auto conn = pool.acquire(); +/// auto conn = pool.try_acquire(); /// if (!conn) conn = new_conn(); -/// pool.release(conn); +/// pool.release(std::move(conn)); /// } /// /// class asio_connection_pool final : public std::enable_shared_from_this { public: - asio_connection_pool() : m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) {} + asio_connection_pool() + : m_lock() + , m_connections() + , m_is_timer_running(false) + , m_pool_epoch_timer(crossplat::threadpool::shared_instance().service()) + { + } - std::shared_ptr acquire() + asio_connection_pool(const asio_connection_pool&) = delete; + asio_connection_pool& operator=(const asio_connection_pool&) = delete; + + std::shared_ptr try_acquire(const std::string& cn_hostname) { std::lock_guard lock(m_lock); + if (m_connections.empty()) + { + return nullptr; + } - if (m_connections.empty()) return nullptr; + auto conn = m_connections[cn_hostname].try_acquire(); + if (conn) + { + conn->start_reuse(); + } - auto conn = std::move(m_connections.back().second); - m_connections.pop_back(); - conn->start_reuse(); return conn; } - void release(const std::shared_ptr& connection) + void release(std::shared_ptr&& connection) { connection->cancel(); - - if (!connection->keep_alive()) return; + if (!connection->keep_alive()) + { + connection.reset(); + return; + } std::lock_guard lock(m_lock); - if (!is_timer_running) + if (!m_is_timer_running) { start_epoch_interval(shared_from_this()); - is_timer_running = true; + m_is_timer_running = true; } - m_epoch++; - m_connections.emplace_back(m_epoch, std::move(connection)); + m_connections[connection->cn_hostname()].release(std::move(connection)); } private: // Note: must be called under m_lock static void start_epoch_interval(const std::shared_ptr& pool) { - _ASSERTE(pool.get() != nullptr); - auto& self = *pool; std::weak_ptr weak_pool = pool; - self.m_prev_epoch = self.m_epoch; - pool->m_pool_epoch_timer.expires_from_now(boost::posix_time::seconds(30)); - pool->m_pool_epoch_timer.async_wait([weak_pool](const boost::system::error_code& ec) { - if (ec) return; + self.m_pool_epoch_timer.expires_from_now(boost::posix_time::seconds(30)); + self.m_pool_epoch_timer.async_wait([weak_pool](const boost::system::error_code& ec) { + if (ec) + { + return; + } auto pool = weak_pool.lock(); - if (!pool) return; - auto& self = *pool; - auto& connections = self.m_connections; + if (!pool) + { + return; + } + auto& self = *pool; std::lock_guard lock(self.m_lock); - if (self.m_prev_epoch == self.m_epoch) + bool restartTimer = false; + for (auto& entry : self.m_connections) { - connections.clear(); - self.is_timer_running = false; - return; + if (entry.second.free_stale_connections()) + { + restartTimer = true; + } } - else + + if (restartTimer) { - auto prev_epoch = self.m_prev_epoch; - auto erase_end = std::find_if(connections.begin(), - connections.end(), - [prev_epoch](std::pair>& p) { - return p.first > prev_epoch; - }); - - connections.erase(connections.begin(), erase_end); start_epoch_interval(pool); } + else + { + self.m_is_timer_running = false; + } }); } std::mutex m_lock; - std::deque>> m_connections; - - uint64_t m_epoch = 0; - uint64_t m_prev_epoch = 0; - bool is_timer_running = false; + std::map m_connections; + bool m_is_timer_running; boost::asio::deadline_timer m_pool_epoch_timer; }; @@ -430,16 +518,20 @@ class asio_client final : public _http_client_communicator virtual void send_request(const std::shared_ptr& request_ctx) override; - void release_connection(std::shared_ptr& conn) { m_pool->release(conn); } - std::shared_ptr obtain_connection() - { - std::shared_ptr conn = m_pool->acquire(); + void release_connection(std::shared_ptr&& conn) { m_pool->release(std::move(conn)); } + std::shared_ptr obtain_connection(const http_request& req) + { + std::string cn_host = calc_cn_host(m_start_with_ssl, base_uri(), req.headers()); + std::shared_ptr conn = m_pool->try_acquire(cn_host); if (conn == nullptr) { // Pool was empty. Create a new connection conn = std::make_shared(crossplat::threadpool::shared_instance().service()); - if (m_start_with_ssl) conn->upgrade_to_ssl(this->client_config().get_ssl_context_callback()); + if (m_start_with_ssl) + { + conn->upgrade_to_ssl(std::move(cn_host), this->client_config().get_ssl_context_callback()); + } } return conn; @@ -447,7 +539,8 @@ class asio_client final : public _http_client_communicator virtual pplx::task propagate(http_request request) override; -public: + bool start_with_ssl() const CPPREST_NOEXCEPT { return m_start_with_ssl; } + tcp::resolver m_resolver; private: @@ -470,7 +563,7 @@ class asio_context final : public request_context, public std::enable_shared_fro , m_connection(connection) #ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE , m_openssl_failed(false) -#endif +#endif // CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE { } @@ -478,14 +571,14 @@ class asio_context final : public request_context, public std::enable_shared_fro { m_timer.stop(); // Release connection back to the pool. If connection was not closed, it will be put to the pool for reuse. - std::static_pointer_cast(m_http_client)->release_connection(m_connection); + std::static_pointer_cast(m_http_client)->release_connection(std::move(m_connection)); } static std::shared_ptr create_request_context(std::shared_ptr<_http_client_communicator>& client, http_request& request) { auto client_cast(std::static_pointer_cast(client)); - auto connection(client_cast->obtain_connection()); + auto connection(client_cast->obtain_connection(request)); auto ctx = std::make_shared(client, request, connection); ctx->m_timer.set_ctx(std::weak_ptr(ctx)); return ctx; @@ -578,7 +671,7 @@ class asio_context final : public request_context, public std::enable_shared_fro m_context->m_timer.reset(); //// Replace the connection. This causes old connection object to go out of scope. auto client = std::static_pointer_cast(m_context->m_http_client); - m_context->m_connection = client->obtain_connection(); + m_context->m_connection = client->obtain_connection(m_context->m_request); auto endpoint = *endpoints; m_context->m_connection->async_connect(endpoint, @@ -869,7 +962,12 @@ class asio_context final : public request_context, public std::enable_shared_fro } private: - void upgrade_to_ssl() { m_connection->upgrade_to_ssl(m_http_client->client_config().get_ssl_context_callback()); } + void upgrade_to_ssl() + { + auto& client = static_cast(*m_http_client); + m_connection->upgrade_to_ssl(calc_cn_host(client.start_with_ssl(), client.base_uri(), m_request.headers()), + client.client_config().get_ssl_context_callback()); + } std::string generate_basic_auth_header() { @@ -951,7 +1049,7 @@ class asio_context final : public request_context, public std::enable_shared_fro { // Replace the connection. This causes old connection object to go out of scope. auto client = std::static_pointer_cast(m_http_client); - m_connection = client->obtain_connection(); + m_connection = client->obtain_connection(m_request); auto endpoint = *endpoints; m_connection->async_connect( @@ -987,11 +1085,11 @@ class asio_context final : public request_context, public std::enable_shared_fro m_connection->async_handshake( boost::asio::ssl::stream_base::client, m_http_client->client_config(), - utility::conversions::to_utf8string(m_http_client->base_uri().host()), boost::bind(&asio_context::handle_handshake, shared_from_this(), boost::asio::placeholders::error), - // Use a weak_ptr since the verify_callback is stored until the connection is destroyed. - // This avoids creating a circular reference since we pool connection objects. + // Use a weak_ptr since the verify_callback is stored until the connection is + // destroyed. This avoids creating a circular reference since we pool connection + // objects. [weakCtx](bool preverified, boost::asio::ssl::verify_context& verify_context) { auto this_request = weakCtx.lock(); if (this_request) @@ -1031,23 +1129,22 @@ class asio_context final : public request_context, public std::enable_shared_fro // certificate chain, the rest are optional intermediate certificates, followed // finally by the root CA self signed certificate. - const auto& host = utility::conversions::to_utf8string(m_http_client->base_uri().host()); #ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE - // Attempt to use platform certificate validation when it is available: - // If OpenSSL fails we will doing verification at the end using the whole certificate chain, - // so wait until the 'leaf' cert. For now return true so OpenSSL continues down the certificate - // chain. + // If OpenSSL fails we will doing verification at the end using the whole certificate + // chain so wait until the 'leaf' cert. For now return true so OpenSSL continues down + // the certificate chain. if (!preverified) { m_openssl_failed = true; } + if (m_openssl_failed) { - return verify_cert_chain_platform_specific(verifyCtx, host); + return verify_cert_chain_platform_specific(verifyCtx, m_connection->cn_hostname()); } -#endif +#endif // CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE - boost::asio::ssl::rfc2818_verification rfc2818(host); + boost::asio::ssl::rfc2818_verification rfc2818(m_connection->cn_hostname()); return rfc2818(preverified, verifyCtx); } @@ -1759,7 +1856,7 @@ class asio_context final : public request_context, public std::enable_shared_fro #ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE bool m_openssl_failed; -#endif +#endif // CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE }; std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, diff --git a/Release/src/http/common/x509_cert_utilities.h b/Release/src/http/common/x509_cert_utilities.h index e19af0498a..581a5189c4 100644 --- a/Release/src/http/common/x509_cert_utilities.h +++ b/Release/src/http/common/x509_cert_utilities.h @@ -1,23 +1,29 @@ /*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* Contains utility functions for helping to verify server certificates in OS X/iOS and Android. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * Contains utility functions for helping to verify server certificates in OS X/iOS and Android. + * + * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ #pragma once #if defined(_WIN32) #include -namespace web { namespace http { namespace client { namespace details { - +namespace web +{ +namespace http +{ +namespace client +{ +namespace details +{ struct winhttp_cert_context { PCCERT_CONTEXT raw; @@ -49,12 +55,16 @@ struct winhttp_cert_chain_context } } }; - -}}}} // namespaces +} +} +} +} // namespaces #endif // _WIN32 -#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) - #define CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE +#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || \ + (defined(_WIN32) && defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)) || \ + (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS)) +#define CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE #endif #ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE @@ -76,8 +86,14 @@ struct winhttp_cert_chain_context #pragma warning(pop) #endif -namespace web { namespace http { namespace client { namespace details { - +namespace web +{ +namespace http +{ +namespace client +{ +namespace details +{ /// /// Using platform specific APIs verifies server certificate. /// Currently implemented to work on Windows, iOS, Android, and OS X. @@ -85,8 +101,10 @@ namespace web { namespace http { namespace client { namespace details { /// Boost.ASIO context to get certificate chain from. /// Host name from the URI. /// True if verification passed and server can be trusted, false otherwise. -bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verifyCtx, const std::string &hostName); - -}}}} +bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context& verifyCtx, const std::string& hostName); +} +} +} +} #endif // CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index f6ea1396cf..7c0438d48c 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -197,10 +197,7 @@ TEST(server_hostname_mismatch) } #if !defined(__cplusplus_winrt) -TEST(server_hostname_host_override, - "Ignore:Android", "229", - "Ignore:Apple", "229", - "Ignore:Linux", "229") +TEST(server_hostname_host_override) { handle_timeout([] { @@ -223,7 +220,10 @@ TEST(server_hostname_host_override_after_upgrade) http_request req(methods::GET); req.headers().add(U("Host"), U("en.wikipedia.org")); auto response = client.request(req).get(); - VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); + // WinHTTP will transparently follow the HTTP 301 upgrade request redirect, + // ASIO does not and will return the 301 directly. + const auto statusCode = response.status_code(); + CHECK(statusCode == status_codes::OK || statusCode == status_codes::MovedPermanently); } #endif // !defined(__cplusplus_winrt) From 29e23c253b63bd753923c3822fc9051a67399fc3 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 15 Aug 2018 12:40:46 -0700 Subject: [PATCH 419/609] Mint version 2.10.4 --- Build/version.props | 2 +- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- changelog.md | 12 ++++++++++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Build/version.props b/Build/version.props index 983ce9e3c5..8f840c5f3d 100644 --- a/Build/version.props +++ b/Build/version.props @@ -4,7 +4,7 @@ cpprest 2 10 - 3 + 4 $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index a79a4ffbbc..c93d3cc498 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 3) +set(CPPREST_VERSION_REVISION 4) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index a4cf42cb5b..3167e148b0 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,7 +5,7 @@ */ #define CPPREST_VERSION_REVISION 2 #define CPPREST_VERSION_MINOR 10 -#define CPPREST_VERSION_MAJOR 3 +#define CPPREST_VERSION_MAJOR 4 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index 047ca874f3..b37c24792e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,15 @@ +cpprestsdk (2.10.4) +---------------------- +* Added a `.clang-format` to enable consistent formatting. +* Added support for `Host:` headers changing the checked CNAME field for SSL certificates in WinHTTP and Asio. +* PR#736 passes 0666 to open() for creating files to better match the default behavior for other http clients (wget, etc). +* PR#732 fixes a build issue with clang +* PR#737 taught our cmake to respect the GNUInstallDirs variables +* PR#762 improved handling of dead connections in the connection pool on Asio. +* PR#750 improved error handling in the accept() call in `http_listener` +* PR#776 improved the iOS buildsystem +-- cpprestsdk team WED, 15 Aug 2018 12:35:00 -0800 + cpprestsdk (2.10.3) ---------------------- * Added a root `CMakeLists.txt` to improve support for VS2017 Open Folder. From 25d6b26f7038eeec3b51e2e0a70960a8e34fcd68 Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Fri, 17 Aug 2018 09:48:34 -0700 Subject: [PATCH 420/609] Fix incorrect version.h. Fixes #942 --- Release/include/cpprest/version.h | 4 ++-- changelog.md | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index 3167e148b0..df0f99cf45 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -3,9 +3,9 @@ * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * */ -#define CPPREST_VERSION_REVISION 2 +#define CPPREST_VERSION_REVISION 5 #define CPPREST_VERSION_MINOR 10 -#define CPPREST_VERSION_MAJOR 4 +#define CPPREST_VERSION_MAJOR 2 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index b37c24792e..569401e517 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +cpprestsdk (2.10.5) +---------------------- +* Issue#842 Fix incorrect `cpprest/version.h` +-- cpprestsdk team FRI, 17 Aug 2018 09:47:00 -0800 + cpprestsdk (2.10.4) ---------------------- * Added a `.clang-format` to enable consistent formatting. From f9f518e4ad84577eb684ad8235181e4495299af4 Mon Sep 17 00:00:00 2001 From: Gianfranco Costamagna Date: Mon, 20 Aug 2018 19:27:01 +0200 Subject: [PATCH 421/609] Fix another clang build failure (Fixes: #747) (#844) * Fix another clang build failure (Fixes: #747) ===> Building for cpprestsdk-2.9.1_5 [1/161] /usr/local/libexec/ccache/c++ -Dcpprest_EXPORTS -Iinclude -isystem /usr/local/include -isystem libs/websocketpp -Isrc/../include -Isrc/pch -O2 -pipe -fstack-protector -fno-strict-aliasing -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration -std=c++11 -fno-strict-aliasing -O2 -pipe -fstack-protector -fno-strict-aliasing -fPIC -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs -Werror -pedantic -MD -MT src/CMakeFiles/cpprest.dir/pplx/pplx.cpp.o -MF src/CMakeFiles/cpprest.dir/pplx/pplx.cpp.o.d -o src/CMakeFiles/cpprest.dir/pplx/pplx.cpp.o -c src/pplx/pplx.cpp FAILED: src/CMakeFiles/cpprest.dir/pplx/pplx.cpp.o /usr/local/libexec/ccache/c++ -Dcpprest_EXPORTS -Iinclude -isystem /usr/local/include -isystem libs/websocketpp -Isrc/../include -Isrc/pch -O2 -pipe -fstack-protector -fno-strict-aliasing -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration -std=c++11 -fno-strict-aliasing -O2 -pipe -fstack-protector -fno-strict-aliasing -fPIC -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs -Werror -pedantic -MD -MT src/CMakeFiles/cpprest.dir/pplx/pplx.cpp.o -MF src/CMakeFiles/cpprest.dir/pplx/pplx.cpp.o.d -o src/CMakeFiles/cpprest.dir/pplx/pplx.cpp.o -c src/pplx/pplx.cpp In file included from src/pplx/pplx.cpp:14: In file included from src/pch/stdafx.h:23: In file included from include/cpprest/details/basic_types.h:16: In file included from /usr/include/c++/v1/string:477: In file included from /usr/include/c++/v1/string_view:176: In file included from /usr/include/c++/v1/__string:56: In file included from /usr/include/c++/v1/algorithm:643: /usr/include/c++/v1/memory:3656:5: error: destructor called on non-final 'pplx::details::linux_scheduler' that has virtual functions but non-virtual destructor [-Werror,-Wdelete-non-virtual-dtor] __data_.second().~_Tp(); ^ /usr/include/c++/v1/memory:3612:5: note: in instantiation of member function 'std::__1::__shared_ptr_emplace >::__on_zero_shared' requested here __shared_ptr_emplace(_Alloc __a) ^ /usr/include/c++/v1/memory:4277:26: note: in instantiation of member function 'std::__1::__shared_ptr_emplace >::__shared_ptr_emplace' requested here ::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...); ^ /usr/include/c++/v1/memory:4656:29: note: in instantiation of function template specialization 'std::__1::shared_ptr::make_shared<>' requested here return shared_ptr<_Tp>::make_shared(_VSTD::forward<_Args>(__args)...); ^ src/pplx/pplx.cpp:94:40: note: in instantiation of function template specialization 'std::__1::make_shared' requested here m_scheduler = std::make_shared< ::pplx::default_scheduler_t>(); ^ /usr/include/c++/v1/memory:3656:23: note: qualify call to silence this warning __data_.second().~_Tp(); ^ 1 error generated. * Fix apple build, by defining apple_scheduler there. --- Release/include/pplx/pplxlinux.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Release/include/pplx/pplxlinux.h b/Release/include/pplx/pplxlinux.h index 6aa1ba352e..78b6e1801a 100644 --- a/Release/include/pplx/pplxlinux.h +++ b/Release/include/pplx/pplxlinux.h @@ -240,6 +240,11 @@ namespace platform { public: _PPLXIMP virtual void schedule( TaskProc_t proc, _In_ void* param); +#if defined(__APPLE__) + virtual ~apple_scheduler() {} +#else + virtual ~linux_scheduler() {} +#endif }; } // namespace details From 66e50f02dde92f802bbd3a8d79c6352954665b9b Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Mon, 20 Aug 2018 16:52:11 -0700 Subject: [PATCH 422/609] Fix compiler errors and mint v2.10.6 --- Build/version.props | 2 +- Release/CMakeLists.txt | 2 +- Release/include/cpprest/asyncrt_utils.h | 8 +------- Release/include/cpprest/details/cpprest_compat.h | 3 +++ Release/include/cpprest/version.h | 2 +- Release/src/http/client/http_client_winhttp.cpp | 2 +- Release/src/http/common/x509_cert_utilities.h | 4 ++-- Release/src/utilities/asyncrt_utils.cpp | 8 ++++---- changelog.md | 5 +++++ 9 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Build/version.props b/Build/version.props index 8f840c5f3d..2b67f6647e 100644 --- a/Build/version.props +++ b/Build/version.props @@ -4,7 +4,7 @@ cpprest 2 10 - 4 + 6 $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index c93d3cc498..3b99b85309 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 4) +set(CPPREST_VERSION_REVISION 6) enable_testing() diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index b4b6c591f4..21c92de294 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -359,13 +359,7 @@ namespace details inline bool __cdecl is_alnum(const unsigned char uch) CPPREST_NOEXCEPT { // test if uch is an alnum character // special casing char to avoid branches - static - #if !defined(_MSC_VER) || _MSC_VER >= 1900 - constexpr - #else - const - #endif - bool is_alnum_table[UCHAR_MAX + 1] = + static CPPREST_CONSTEXPR bool is_alnum_table[UCHAR_MAX + 1] = { /* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */ /* 0X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/Release/include/cpprest/details/cpprest_compat.h b/Release/include/cpprest/details/cpprest_compat.h index 7b4f3c1842..1c48552eff 100644 --- a/Release/include/cpprest/details/cpprest_compat.h +++ b/Release/include/cpprest/details/cpprest_compat.h @@ -18,8 +18,10 @@ #if _MSC_VER >= 1900 #define CPPREST_NOEXCEPT noexcept +#define CPPREST_CONSTEXPR constexpr #else #define CPPREST_NOEXCEPT +#define CPPREST_CONSTEXPR const #endif #define CASABLANCA_UNREFERENCED_PARAMETER(x) (x) @@ -36,6 +38,7 @@ #define __assume(x) do { if (!(x)) __builtin_unreachable(); } while (false) #define CASABLANCA_UNREFERENCED_PARAMETER(x) (void)x #define CPPREST_NOEXCEPT noexcept +#define CPPREST_CONSTEXPR constexpr #include #define _ASSERTE(x) assert(x) diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index df0f99cf45..cb47ab9d05 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -3,7 +3,7 @@ * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. * */ -#define CPPREST_VERSION_REVISION 5 +#define CPPREST_VERSION_REVISION 6 #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 83a60d6ce5..a1f69ab215 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -33,7 +33,7 @@ struct security_failure_message const char * text; }; -constexpr security_failure_message g_security_failure_messages[] = { +CPPREST_CONSTEXPR security_failure_message g_security_failure_messages[] = { { WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED, "WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED failed to check revocation status."}, { WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT, diff --git a/Release/src/http/common/x509_cert_utilities.h b/Release/src/http/common/x509_cert_utilities.h index 581a5189c4..9884b05993 100644 --- a/Release/src/http/common/x509_cert_utilities.h +++ b/Release/src/http/common/x509_cert_utilities.h @@ -27,7 +27,7 @@ namespace details struct winhttp_cert_context { PCCERT_CONTEXT raw; - winhttp_cert_context() noexcept : raw(nullptr) {} + winhttp_cert_context() CPPREST_NOEXCEPT : raw(nullptr) {} winhttp_cert_context(const winhttp_cert_context&) = delete; winhttp_cert_context& operator=(const winhttp_cert_context&) = delete; ~winhttp_cert_context() @@ -44,7 +44,7 @@ struct winhttp_cert_context struct winhttp_cert_chain_context { PCCERT_CHAIN_CONTEXT raw; - winhttp_cert_chain_context() noexcept : raw(nullptr) {} + winhttp_cert_chain_context() CPPREST_NOEXCEPT : raw(nullptr) {} winhttp_cert_chain_context(const winhttp_cert_chain_context&) = delete; winhttp_cert_chain_context& operator=(const winhttp_cert_chain_context&) = delete; ~winhttp_cert_chain_context() diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 72f12ccf10..3faffd1e40 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -51,7 +51,7 @@ namespace } }; - constexpr to_lower_ch_impl to_lower_ch{}; + CPPREST_CONSTEXPR to_lower_ch_impl to_lower_ch{}; struct eq_lower_ch_impl { @@ -62,7 +62,7 @@ namespace } }; - constexpr eq_lower_ch_impl eq_lower_ch{}; + CPPREST_CONSTEXPR eq_lower_ch_impl eq_lower_ch{}; struct lt_lower_ch_impl { @@ -73,8 +73,8 @@ namespace } }; - constexpr lt_lower_ch_impl lt_lower_ch{}; -} + CPPREST_CONSTEXPR lt_lower_ch_impl lt_lower_ch{}; + } namespace utility { diff --git a/changelog.md b/changelog.md index 569401e517..dd190b70a9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +cpprestsdk (2.10.6) +---------------------- +* PR#844 Fix clang build error +-- cpprestsdk team MON, 30 Aug 2018 16:51:00 -0800 + cpprestsdk (2.10.5) ---------------------- * Issue#842 Fix incorrect `cpprest/version.h` From cdc2948614df5e034f8b0f2e64e52c140404f670 Mon Sep 17 00:00:00 2001 From: Ernie Pistor Date: Wed, 12 Sep 2018 10:50:15 -0400 Subject: [PATCH 423/609] Add Transfer-Encoding compression/decompression support and extensible compress/decompress API --- Release/CMakeLists.txt | 2 + Release/cmake/cpprest_find_brotli.cmake | 10 + Release/cmake/cpprestsdk-config.in.cmake | 4 + Release/include/cpprest/asyncrt_utils.h | 2 +- .../include/cpprest/details/http_helpers.h | 66 - Release/include/cpprest/http_client.h | 12 +- Release/include/cpprest/http_compression.h | 329 ++++ Release/include/cpprest/http_msg.h | 156 ++ Release/src/CMakeLists.txt | 12 + Release/src/http/client/http_client.cpp | 65 +- Release/src/http/client/http_client_asio.cpp | 76 +- Release/src/http/client/http_client_impl.h | 6 +- .../src/http/client/http_client_winhttp.cpp | 813 +++++++++- Release/src/http/common/http_compression.cpp | 1110 +++++++++++++ Release/src/http/common/http_helpers.cpp | 325 ---- Release/src/http/common/http_msg.cpp | 80 +- .../src/http/listener/http_server_httpsys.cpp | 298 +++- .../src/http/listener/http_server_httpsys.h | 7 + .../functional/http/client/CMakeLists.txt | 1 + .../http/client/compression_tests.cpp | 1401 +++++++++++++++++ .../functional/http/client/outside_tests.cpp | 2 +- .../http/client/request_helper_tests.cpp | 62 +- .../http/utilities/include/test_http_server.h | 56 +- .../http/utilities/test_http_server.cpp | 4 +- 24 files changed, 4286 insertions(+), 613 deletions(-) create mode 100644 Release/cmake/cpprest_find_brotli.cmake create mode 100644 Release/include/cpprest/http_compression.h create mode 100644 Release/src/http/common/http_compression.cpp create mode 100644 Release/tests/functional/http/client/compression_tests.cpp diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 3b99b85309..18ece49310 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -18,6 +18,7 @@ enable_testing() set(WERROR ON CACHE BOOL "Treat Warnings as Errors.") set(CPPREST_EXCLUDE_WEBSOCKETS OFF CACHE BOOL "Exclude websockets functionality.") set(CPPREST_EXCLUDE_COMPRESSION OFF CACHE BOOL "Exclude compression functionality.") +set(CPPREST_EXCLUDE_BROTLI ON CACHE BOOL "Exclude Brotli compression functionality.") set(CPPREST_EXPORT_DIR lib/cpprestsdk CACHE STRING "Directory to install CMake config files.") set(CPPREST_INSTALL_HEADERS ON CACHE BOOL "Install header files.") set(CPPREST_INSTALL ON CACHE BOOL "Add install commands.") @@ -62,6 +63,7 @@ include(cmake/cpprest_find_boost.cmake) include(cmake/cpprest_find_zlib.cmake) include(cmake/cpprest_find_openssl.cmake) include(cmake/cpprest_find_websocketpp.cmake) +include(cmake/cpprest_find_brotli.cmake) include(CheckIncludeFiles) include(GNUInstallDirs) diff --git a/Release/cmake/cpprest_find_brotli.cmake b/Release/cmake/cpprest_find_brotli.cmake new file mode 100644 index 0000000000..7366100939 --- /dev/null +++ b/Release/cmake/cpprest_find_brotli.cmake @@ -0,0 +1,10 @@ +function(cpprest_find_brotli) + if(TARGET cpprestsdk_brotli_internal) + return() + endif() + + find_package(UNOFFICIAL-BROTLI REQUIRED) + + add_library(cpprestsdk_brotli_internal INTERFACE) + target_link_libraries(cpprestsdk_brotli_internal INTERFACE unofficial::brotli::brotlienc unofficial::brotli::brotlidec unofficial::brotli::brotlicommon) +endfunction() diff --git a/Release/cmake/cpprestsdk-config.in.cmake b/Release/cmake/cpprestsdk-config.in.cmake index 522f8f7db1..a00caa2f95 100644 --- a/Release/cmake/cpprestsdk-config.in.cmake +++ b/Release/cmake/cpprestsdk-config.in.cmake @@ -3,6 +3,10 @@ if(@CPPREST_USES_ZLIB@) find_dependency(ZLIB) endif() +if(@CPPREST_USES_BROTLI@) + find_dependency(UNOFFICIAL-BROTLI) +endif() + if(@CPPREST_USES_OPENSSL@) find_dependency(OpenSSL) endif() diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 21c92de294..2739a13e35 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -503,7 +503,7 @@ _ASYNCRTIMP const std::error_category & __cdecl linux_category(); /// /// Gets the one global instance of the current platform's error category. -/// +/// _ASYNCRTIMP const std::error_category & __cdecl platform_category(); /// diff --git a/Release/include/cpprest/details/http_helpers.h b/Release/include/cpprest/details/http_helpers.h index 596ac9efaa..ad01e2eb67 100644 --- a/Release/include/cpprest/details/http_helpers.h +++ b/Release/include/cpprest/details/http_helpers.h @@ -41,70 +41,4 @@ namespace details _ASYNCRTIMP size_t __cdecl add_chunked_delimiters(_Out_writes_(buffer_size) uint8_t *data, _In_ size_t buffer_size, size_t bytes_read); } - namespace compression - { - enum class compression_algorithm : int - { - deflate = 15, - gzip = 31, - invalid = 9999 - }; - - using data_buffer = std::vector; - - class stream_decompressor - { - public: - - static compression_algorithm to_compression_algorithm(const utility::string_t& alg) - { - if (_XPLATSTR("gzip") == alg) - { - return compression_algorithm::gzip; - } - else if (_XPLATSTR("deflate") == alg) - { - return compression_algorithm::deflate; - } - - return compression_algorithm::invalid; - } - - static utility::string_t known_algorithms() { return _XPLATSTR("deflate, gzip"); } - - _ASYNCRTIMP static bool __cdecl is_supported(); - - _ASYNCRTIMP stream_decompressor(compression_algorithm alg); - - _ASYNCRTIMP data_buffer decompress(const data_buffer& input); - - _ASYNCRTIMP data_buffer decompress(const uint8_t* input, size_t input_size); - - _ASYNCRTIMP bool has_error() const; - - private: - class stream_decompressor_impl; - std::shared_ptr m_pimpl; - }; - - class stream_compressor - { - public: - - _ASYNCRTIMP static bool __cdecl is_supported(); - - _ASYNCRTIMP stream_compressor(compression_algorithm alg); - - _ASYNCRTIMP data_buffer compress(const data_buffer& input, bool finish); - - _ASYNCRTIMP data_buffer compress(const uint8_t* input, size_t input_size, bool finish); - - _ASYNCRTIMP bool has_error() const; - - private: - class stream_compressor_impl; - std::shared_ptr m_pimpl; - }; - - } }}} diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index f5ad8fac70..9ccd19e61f 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -247,20 +247,22 @@ class http_client_config } /// - /// Checks if requesting a compressed response is turned on, the default is off. + /// Checks if requesting a compressed response using Content-Encoding is turned on, the default is off. /// - /// True if compressed response is enabled, false otherwise + /// True if a content-encoded compressed response is allowed, false otherwise bool request_compressed_response() const { return m_request_compressed; } /// - /// Request that the server responds with a compressed body. - /// If true, in cases where the server does not support compression, this will have no effect. + /// Request that the server respond with a compressed body using Content-Encoding; to use Transfer-Encoding, do not + /// set this, and specify a vector of pointers + /// to the set_decompress_factories method of the object for the request. + /// If true and the server does not support compression, this will have no effect. /// The response body is internally decompressed before the consumer receives the data. /// - /// True to turn on response body compression, false otherwise. + /// True to turn on content-encoded response body compression, false otherwise. /// Please note there is a performance cost due to copying the request data. Currently only supported on Windows and OSX. void set_request_compressed_response(bool request_compressed) { diff --git a/Release/include/cpprest/http_compression.h b/Release/include/cpprest/http_compression.h new file mode 100644 index 0000000000..87b1d5dda8 --- /dev/null +++ b/Release/include/cpprest/http_compression.h @@ -0,0 +1,329 @@ +/*** + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * HTTP Library: Compression and decompression interfaces + * + * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ +#pragma once + +namespace web +{ +namespace http +{ +namespace compression +{ +/// +/// Hint as to whether a compress or decompress call is meant to be the last for a particular HTTP request or reply +/// +enum operation_hint +{ + is_last, // Used for the expected last compress() call, or for an expected single decompress() call + has_more // Used when further compress() calls will be made, or when multiple decompress() calls may be required +}; + +/// +/// Result structure for asynchronous compression and decompression operations +/// +struct operation_result +{ + size_t input_bytes_processed; // From the input buffer + size_t output_bytes_produced; // To the output buffer + bool done; // For compress, set when 'last' is true and there was enough space to complete compression; + // for decompress, set if the end of the decompression stream has been reached +}; + +/// +/// Compression interface for use with HTTP requests +/// +class compress_provider +{ +public: + virtual const utility::string_t& algorithm() const = 0; + virtual size_t compress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + operation_hint hint, + size_t& input_bytes_processed, + bool* done = nullptr) = 0; + virtual pplx::task compress( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0; + virtual void reset() = 0; + virtual ~compress_provider() = default; +}; + +/// +/// Decompression interface for use with HTTP requests +/// +class decompress_provider +{ +public: + virtual const utility::string_t& algorithm() const = 0; + virtual size_t decompress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + operation_hint hint, + size_t& input_bytes_processed, + bool* done = nullptr) = 0; + virtual pplx::task decompress( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0; + virtual void reset() = 0; + virtual ~decompress_provider() = default; +}; + +/// +/// Factory interface for compressors for use with received HTTP requests +/// +class compress_factory +{ +public: + virtual const utility::string_t& algorithm() const = 0; + virtual std::unique_ptr make_compressor() const = 0; + virtual ~compress_factory() = default; +}; + +/// +/// Factory interface for decompressors for use with HTTP requests +/// +class decompress_factory +{ +public: + virtual const utility::string_t& algorithm() const = 0; + virtual const uint16_t weight() const = 0; + virtual std::unique_ptr make_decompressor() const = 0; + virtual ~decompress_factory() = default; +}; + +/// +/// Built-in compression support +/// +namespace builtin +{ +/// +/// Test whether cpprestsdk was built with built-in compression support +/// True if cpprestsdk was built with built-in compression support, and false if not. +/// +_ASYNCRTIMP bool supported(); + +/// +// String constants for each built-in compression algorithm, for convenient use with the factory functions +/// +class algorithm +{ +public: + _ASYNCRTIMP static const utility::string_t GZIP; + _ASYNCRTIMP static const utility::string_t DEFLATE; + _ASYNCRTIMP static const utility::string_t BROTLI; + + /// + /// Test whether cpprestsdk was built with built-in compression support and + /// the supplied string matches a supported built-in algorithm + /// The name of the algorithm to test for built-in support. + /// True if cpprestsdk was built with built-in compression support and + /// the supplied string matches a supported built-in algorithm, and false if not. + /// + _ASYNCRTIMP static bool supported(const utility::string_t& algorithm); + +private: + algorithm() {} +}; + +/// +/// Factory function to instantiate a built-in compression provider with default parameters by compression algorithm +/// name. +/// +/// The name of the algorithm for which to instantiate a provider. +/// +/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists. +/// +_ASYNCRTIMP std::unique_ptr make_compressor(const utility::string_t& algorithm); + +/// +/// Factory function to instantiate a built-in decompression provider with default parameters by compression algorithm +/// name. +/// +/// The name of the algorithm for which to instantiate a provider. +/// +/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists. +/// +_ASYNCRTIMP std::unique_ptr make_decompressor(const utility::string_t& algorithm); + +/// +/// Factory function to obtain a pointer to a built-in compression provider factory by compression algorithm name. +/// +/// The name of the algorithm for which to find a factory. +/// +/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists. +/// +_ASYNCRTIMP std::shared_ptr get_compress_factory(const utility::string_t& algorithm); + +/// +/// Factory function to obtain a pointer to a built-in decompression provider factory by compression algorithm name. +/// +/// The name of the algorithm for which to find a factory. +/// +/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists. +/// +_ASYNCRTIMP std::shared_ptr get_decompress_factory(const utility::string_t& algorithm); + +/// +// Factory function to instantiate a built-in gzip compression provider with caller-selected parameters. +/// +/// +/// A caller-owned pointer to a gzip compression provider, or to nullptr if the library was built without built-in +/// compression support. +/// +_ASYNCRTIMP std::unique_ptr make_gzip_compressor(int compressionLevel, + int method, + int strategy, + int memLevel); + +/// +// Factory function to instantiate a built-in deflate compression provider with caller-selected parameters. +/// +/// +/// A caller-owned pointer to a deflate compression provider, or to nullptr if the library was built without built-in +/// compression support.. +/// +_ASYNCRTIMP std::unique_ptr make_deflate_compressor(int compressionLevel, + int method, + int strategy, + int memLevel); + +/// +// Factory function to instantiate a built-in Brotli compression provider with caller-selected parameters. +/// +/// +/// A caller-owned pointer to a Brotli compression provider, or to nullptr if the library was built without built-in +/// compression support. +/// +_ASYNCRTIMP std::unique_ptr make_brotli_compressor(uint32_t window, uint32_t quality, uint32_t mode); +} // namespace builtin + +/// +/// Factory function to instantiate a compression provider factory by compression algorithm name. +/// +/// The name of the algorithm supported by the factory. Must match that returned by the +/// web::http::compression::compress_provider type instantiated by the factory's make_compressor function. +/// The supplied string is copied, and thus need not remain valid once the call returns. +/// A factory function to be used to instantiate a compressor matching the factory's +/// reported algorithm. +/// +/// A pointer to a generic provider factory implementation configured with the supplied parameters. +/// +/// +/// This method may be used to conveniently instantiate a factory object for a caller-selected compress_provider. +/// That provider may be of the caller's own design, or it may be one of the built-in types. As such, this method may +/// be helpful when a caller wishes to build vectors containing a mix of custom and built-in providers. +/// +_ASYNCRTIMP std::shared_ptr make_compress_factory( + const utility::string_t& algorithm, std::function()> make_compressor); + +/// +/// Factory function to instantiate a decompression provider factory by compression algorithm name. +/// +/// The name of the algorithm supported by the factory. Must match that returned by the +/// web::http::compression::decompress_provider type instantiated by the factory's make_decompressor function. +/// The supplied string is copied, and thus need not remain valid once the call returns. +/// A numeric weight for the compression algorithm, times 1000, for use as a "quality value" when +/// requesting that the server send a compressed response. Valid values are between 0 and 1000, inclusive, where higher +/// values indicate more preferred algorithms, and 0 indicates that the algorithm is not allowed; values greater than +/// 1000 are treated as 1000. +/// A factory function to be used to instantiate a decompressor matching the factory's +/// reported algorithm. +/// +/// A pointer to a generic provider factory implementation configured with the supplied parameters. +/// +/// +/// This method may be used to conveniently instantiate a factory object for a caller-selected +/// decompress_provider. That provider may be of the caller's own design, or it may be one of the built-in +/// types. As such, this method may be helpful when a caller wishes to change the weights of built-in provider types, +/// to use custom providers without explicitly implementing a decompress_factory, or to build vectors containing +/// a mix of custom and built-in providers. +/// +_ASYNCRTIMP std::shared_ptr make_decompress_factory( + const utility::string_t& algorithm, + uint16_t weight, + std::function()> make_decompressor); + +namespace details +{ +namespace builtin +{ +// Internal-only helper function +const std::vector> get_decompress_factories(); +} // namespace builtin + +/// +/// Header type enum for use with compressor and decompressor header parsing and building functions +/// +enum header_types +{ + transfer_encoding, + content_encoding, + te, + accept_encoding +}; + +/// +/// Factory function to instantiate an appropriate compression provider, if any. +/// +/// A TE or Accept-Encoding header to interpret. +/// Specifies the type of header whose contents are in the encoding parameter; valid values are +/// header_type::te and header_type::accept_encoding. +/// A compressor object of the caller's preferred (possibly custom) type, which is used if +/// possible. +/// A collection of factory objects for use in construction of an appropriate compressor, if +/// any. If empty or not supplied, the set of supported built-in compressors is used. +/// +/// A pointer to a compressor object that is acceptable per the supplied header, or to nullptr if no matching +/// algorithm is found. +/// +_ASYNCRTIMP std::unique_ptr get_compressor_from_header( + const utility::string_t& encoding, + header_types type, + const std::vector>& factories = std::vector>()); + +/// +/// Factory function to instantiate an appropriate decompression provider, if any. +/// +/// A Transfer-Encoding or Content-Encoding header to interpret. +/// Specifies the type of header whose contents are in the encoding parameter; valid values are +/// header_type::transfer_encoding and header_type::content_encoding. +/// A collection of factory objects for use in construction of an appropriate decompressor, +/// if any. If empty or not supplied, the set of supported built-in compressors is used. +/// +/// A pointer to a decompressor object that is acceptable per the supplied header, or to nullptr if no matching +/// algorithm is found. +/// +_ASYNCRTIMP std::unique_ptr get_decompressor_from_header( + const utility::string_t& encoding, + header_types type, + const std::vector>& factories = + std::vector>()); + +/// +/// Helper function to compose a TE or Accept-Encoding header with supported, and possibly ranked, compression +/// algorithms. +/// +/// Specifies the type of header to be built; valid values are header_type::te and +/// header_type::accept_encoding. +/// A collection of factory objects for use in header construction. If empty or not +/// supplied, the set of supported built-in compressors is used. +/// +/// A well-formed header, without the header name, specifying the acceptable ranked compression types. +/// +_ASYNCRTIMP utility::string_t build_supported_header(header_types type, + const std::vector>& factories = + std::vector>()); +} // namespace details +} // namespace compression +} // namespace http +} // namespace web diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index b85e98ff42..85840b6836 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -26,6 +26,7 @@ #include "cpprest/asyncrt_utils.h" #include "cpprest/streams.h" #include "cpprest/containerstream.h" +#include "cpprest/http_compression.h" namespace web { @@ -338,6 +339,38 @@ class http_msg_base /// const concurrency::streams::ostream & outstream() const { return m_outStream; } + /// + /// Sets the compressor for the message body + /// + void set_compressor(std::unique_ptr compressor) + { + m_compressor = std::move(compressor); + } + + /// + /// Gets the compressor for the message body, if any + /// + std::unique_ptr &compressor() + { + return m_compressor; + } + + /// + /// Sets the collection of factory classes for decompressors for use with the message body + /// + void set_decompress_factories(const std::vector> &factories) + { + m_decompressors = factories; + } + + /// + /// Gets the collection of factory classes for decompressors to be used to decompress the message body, if any + /// + const std::vector> &decompress_factories() + { + return m_decompressors; + } + const pplx::task_completion_event & _get_data_available() const { return m_data_available; } /// @@ -345,6 +378,20 @@ class http_msg_base /// _ASYNCRTIMP void _prepare_to_receive_data(); + + /// + /// Determine the remaining input stream length + /// + /// + /// size_t::max if the stream's remaining length cannot be determined + /// length if the stream's remaining length (which may be 0) can be determined + /// + /// + /// This routine should only be called after a msg (request/response) has been + /// completely constructed. + /// + _ASYNCRTIMP size_t _get_stream_length(); + /// /// Determine the content length /// @@ -359,8 +406,27 @@ class http_msg_base /// _ASYNCRTIMP size_t _get_content_length(); + /// + /// Determine the content length, and, if necessary, manage compression in the Transfer-Encoding header + /// + /// + /// size_t::max if there is content with unknown length (transfer_encoding:chunked) + /// 0 if there is no content + /// length if there is content with known length + /// + /// + /// This routine is like _get_content_length, except that it adds a compression algorithm to + /// the Trasfer-Length header if compression is configured. It throws if a Transfer-Encoding + /// header exists and does not match the one it generated. + /// + _ASYNCRTIMP size_t _get_content_length_and_set_compression(); + protected: + std::unique_ptr m_compressor; + std::unique_ptr m_decompressor; + std::vector> m_decompressors; + /// /// Stream to read the message body. /// By default this is an invalid stream. The user could set the instream on @@ -386,6 +452,8 @@ class http_msg_base /// The TCE is used to signal the availability of the message body. pplx::task_completion_event m_data_available; + + size_t _get_content_length(bool honor_compression); }; /// @@ -1149,6 +1217,94 @@ class http_request return _m_impl->set_response_stream(stream); } + /// + /// Sets a compressor that will be used to compress the body of the HTTP message as it is sent. + /// + /// A pointer to an instantiated compressor of the desired type. + /// + /// This cannot be used in conjunction with any other means of compression. The Transfer-Encoding + /// header will be managed internally, and must not be set by the client. + /// + void set_compressor(std::unique_ptr compressor) + { + return _m_impl->set_compressor(std::move(compressor)); + } + + /// + /// Sets a compressor that will be used to compress the body of the HTTP message as it is sent. + /// + /// The built-in compression algorithm to use. + /// + /// True if a built-in compressor was instantiated, otherwise false. + /// + /// + /// This cannot be used in conjunction with any other means of compression. The Transfer-Encoding + /// header will be managed internally, and must not be set by the client. + /// + bool set_compressor(utility::string_t algorithm) + { + _m_impl->set_compressor(http::compression::builtin::make_compressor(algorithm)); + return (bool)_m_impl->compressor(); + } + + /// + /// Gets the compressor to be used to compress the message body, if any. + /// + /// + /// The compressor itself. + /// + std::unique_ptr &compressor() + { + return _m_impl->compressor(); + } + + /// + /// Sets the default collection of built-in factory classes for decompressors that may be used to + /// decompress the body of the HTTP message as it is received, effectively enabling decompression. + /// + /// The collection of factory classes for allowable decompressors. The + /// supplied vector itself need not remain valid after the call returns. + /// + /// This default collection is implied if request_compressed_response() is set in the associated + /// client::http_client_config and neither overload of this method has been called. + /// + /// This cannot be used in conjunction with any external means of decompression. The TE and Accept-Encoding + /// headers must not be set by the client, as they will be managed internally as appropriate. + /// + _ASYNCRTIMP void set_decompress_factories(); + + /// + /// Sets a collection of factory classes for decompressors that may be used to decompress the + /// body of the HTTP message as it is received, effectively enabling decompression. + /// + /// + /// If set, this collection takes the place of the built-in compression providers. It may contain + /// custom factory classes and/or factory classes for built-in providers, and may be used to adjust + /// the weights of the built-in providers, which default to 500 (i.e. "q=0.500"). + /// + /// This cannot be used in conjunction with any external means of decompression. The TE and Accept-Encoding + /// headers must not be set by the client, as they will be managed internally as appropriate. + /// + void set_decompress_factories(const std::vector> &factories) + { + return _m_impl->set_decompress_factories(factories); + } + + /// + /// Gets the collection of factory classes for decompressors to be used to decompress the message body, if any. + /// + /// + /// The collection of factory classes itself. + /// + /// + /// This cannot be used in conjunction with any other means of decompression. The TE + /// header must not be set by the client, as it will be managed internally. + /// + const std::vector> &decompress_factories() const + { + return _m_impl->decompress_factories(); + } + /// /// Defines a callback function that will be invoked for every chunk of data uploaded or downloaded /// as part of the request. diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index a34605bda2..a748698a45 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES http/common/internal_http_helpers.h http/common/http_helpers.cpp http/common/http_msg.cpp + http/common/http_compression.cpp http/listener/http_listener.cpp http/listener/http_listener_msg.cpp http/listener/http_server_api.cpp @@ -75,6 +76,12 @@ if(CPPREST_EXCLUDE_COMPRESSION) else() cpprest_find_zlib() target_link_libraries(cpprest PRIVATE cpprestsdk_zlib_internal) + if(CPPREST_EXCLUDE_BROTLI) + target_compile_definitions(cpprest PRIVATE -DCPPREST_EXCLUDE_BROTLI=1) + else() + cpprest_find_brotli() + target_link_libraries(cpprest PRIVATE cpprestsdk_brotli_internal) + endif() endif() # PPLX component @@ -232,6 +239,7 @@ endif() if(CPPREST_INSTALL) set(CPPREST_USES_BOOST OFF) set(CPPREST_USES_ZLIB OFF) + set(CPPREST_USES_BROTLI OFF) set(CPPREST_USES_OPENSSL OFF) set(CPPREST_TARGETS cpprest) @@ -243,6 +251,10 @@ if(CPPREST_INSTALL) list(APPEND CPPREST_TARGETS cpprestsdk_zlib_internal) set(CPPREST_USES_ZLIB ON) endif() + if(TARGET cpprestsdk_brotli_internal) + list(APPEND CPPREST_TARGETS cpprestsdk_brotli_internal) + set(CPPREST_USES_BROTLI ON) + endif() if(TARGET cpprestsdk_openssl_internal) list(APPEND CPPREST_TARGETS cpprestsdk_openssl_internal) set(CPPREST_USES_OPENSSL ON) diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 2963fae3c2..89eaa4941a 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -96,42 +96,57 @@ void request_context::report_exception(std::exception_ptr exceptionPtr) finish(); } -bool request_context::handle_content_encoding_compression() +bool request_context::handle_compression() { - if (web::http::details::compression::stream_decompressor::is_supported() && m_http_client->client_config().request_compressed_response()) + // If the response body is compressed we will read the encoding header and create a decompressor object which will later decompress the body + try { - // If the response body is compressed we will read the encoding header and create a decompressor object which will later decompress the body - auto&& headers = m_response.headers(); - auto it_ce = headers.find(web::http::header_names::content_encoding); - if (it_ce != headers.end()) + utility::string_t encoding; + http_headers &headers = m_response.headers(); + + // Note that some headers, for example "Transfer-Encoding: chunked", may legitimately not produce a decompressor + if (m_http_client->client_config().request_compressed_response() && headers.match(web::http::header_names::content_encoding, encoding)) + { + // Note that, while Transfer-Encoding (chunked only) is valid with Content-Encoding, + // we don't need to look for it here because winhttp de-chunks for us in that case + m_decompressor = compression::details::get_decompressor_from_header(encoding, compression::details::header_types::content_encoding, m_request.decompress_factories()); + } + else if (!m_request.decompress_factories().empty() && headers.match(web::http::header_names::transfer_encoding, encoding)) { - auto alg = web::http::details::compression::stream_decompressor::to_compression_algorithm(it_ce->second); - - if (alg != web::http::details::compression::compression_algorithm::invalid) - { - m_decompressor = utility::details::make_unique(alg); - } - else - { - report_exception( - http_exception("Unsupported compression algorithm in the Content-Encoding header: " - + utility::conversions::to_utf8string(it_ce->second))); - return false; - } + m_decompressor = compression::details::get_decompressor_from_header(encoding, compression::details::header_types::transfer_encoding, m_request.decompress_factories()); } } + catch (...) + { + report_exception(std::current_exception()); + return false; + } + return true; } -utility::string_t request_context::get_accept_encoding_header() const +utility::string_t request_context::get_compression_header() const { utility::string_t headers; - // Add the header needed to request a compressed response if supported on this platform and it has been specified in the config - if (web::http::details::compression::stream_decompressor::is_supported() - && m_http_client->client_config().request_compressed_response()) + + // Add the correct header needed to request a compressed response if supported + // on this platform and it has been specified in the config and/or request + if (m_http_client->client_config().request_compressed_response()) + { + if (!m_request.decompress_factories().empty() || web::http::compression::builtin::supported()) + { + // Accept-Encoding -- request Content-Encoding from the server + headers.append(header_names::accept_encoding + U(": ")); + headers.append(compression::details::build_supported_header(compression::details::header_types::accept_encoding, m_request.decompress_factories())); + headers.append(U("\r\n")); + } + } + else if (!m_request.decompress_factories().empty()) { - headers.append(U("Accept-Encoding: ")); - headers.append(web::http::details::compression::stream_decompressor::known_algorithms()); + // TE -- request Transfer-Encoding from the server + headers.append(header_names::connection + U(": TE\r\n") + // Required by Section 4.3 of RFC-7230 + header_names::te + U(": ")); + headers.append(compression::details::build_supported_header(compression::details::header_types::te, m_request.decompress_factories())); headers.append(U("\r\n")); } diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index e3ea15c9ff..893d36d74d 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -850,12 +850,12 @@ class asio_context final : public request_context, public std::enable_shared_fro extra_headers.append(ctx->generate_basic_auth_header()); } - extra_headers += utility::conversions::to_utf8string(ctx->get_accept_encoding_header()); + extra_headers += utility::conversions::to_utf8string(ctx->get_compression_header()); // Check user specified transfer-encoding. std::string transferencoding; if (ctx->m_request.headers().match(header_names::transfer_encoding, transferencoding) && - transferencoding == "chunked") + boost::icontains(transferencoding, U("chunked"))) { ctx->m_needChunked = true; } @@ -1394,7 +1394,7 @@ class asio_context final : public request_context, public std::enable_shared_fro if (boost::iequals(name, header_names::transfer_encoding)) { - needChunked = boost::iequals(value, U("chunked")); + needChunked = boost::icontains(value, U("chunked")); } if (boost::iequals(name, header_names::connection)) @@ -1415,7 +1415,7 @@ class asio_context final : public request_context, public std::enable_shared_fro // TCP stream - set it size_t max. m_response.headers().match(header_names::content_length, m_content_length); - if (!this->handle_content_encoding_compression()) + if (!this->handle_compression()) { // false indicates report_exception was called return; @@ -1518,6 +1518,52 @@ class asio_context final : public request_context, public std::enable_shared_fro } } + bool decompress(const uint8_t* input, size_t input_size, std::vector& output) + { + size_t processed; + size_t got; + size_t inbytes; + size_t outbytes; + bool done; + + // Need to guard against attempting to decompress when we're already finished or encountered an error! + if (input == nullptr || input_size == 0) + { + return false; + } + + inbytes = 0; + outbytes = 0; + done = false; + try + { + output.resize(input_size * 3); + do + { + if (inbytes) + { + output.resize(output.size() + (input_size > 1024 ? input_size : 1024)); + } + got = m_decompressor->decompress(input + inbytes, + input_size - inbytes, + output.data() + outbytes, + output.size() - outbytes, + web::http::compression::operation_hint::has_more, + processed, + &done); + inbytes += processed; + outbytes += got; + } while (got && !done); + output.resize(outbytes); + } + catch (...) + { + return false; + } + + return true; + } + void handle_chunk(const boost::system::error_code& ec, int to_read) { if (!ec) @@ -1550,10 +1596,11 @@ class asio_context final : public request_context, public std::enable_shared_fro const auto this_request = shared_from_this(); if (m_decompressor) { - auto decompressed = m_decompressor->decompress( - boost::asio::buffer_cast(m_body_buf.data()), to_read); + std::vector decompressed; - if (m_decompressor->has_error()) + bool boo = + decompress(boost::asio::buffer_cast(m_body_buf.data()), to_read, decompressed); + if (!boo) { report_exception(std::runtime_error("Failed to decompress the response body")); return; @@ -1574,8 +1621,7 @@ class asio_context final : public request_context, public std::enable_shared_fro { // Move the decompressed buffer into a shared_ptr to keep it alive until putn_nocopy completes. // When VS 2013 support is dropped, this should be changed to a unique_ptr plus a move capture. - using web::http::details::compression::data_buffer; - auto shared_decompressed = std::make_shared(std::move(decompressed)); + auto shared_decompressed = std::make_shared>(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) .then([this_request, to_read, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS]( @@ -1670,10 +1716,11 @@ class asio_context final : public request_context, public std::enable_shared_fro if (m_decompressor) { - auto decompressed = - m_decompressor->decompress(boost::asio::buffer_cast(m_body_buf.data()), read_size); + std::vector decompressed; - if (m_decompressor->has_error()) + bool boo = + decompress(boost::asio::buffer_cast(m_body_buf.data()), read_size, decompressed); + if (!boo) { this_request->report_exception(std::runtime_error("Failed to decompress the response body")); return; @@ -1704,8 +1751,7 @@ class asio_context final : public request_context, public std::enable_shared_fro { // Move the decompressed buffer into a shared_ptr to keep it alive until putn_nocopy completes. // When VS 2013 support is dropped, this should be changed to a unique_ptr plus a move capture. - using web::http::details::compression::data_buffer; - auto shared_decompressed = std::make_shared(std::move(decompressed)); + auto shared_decompressed = std::make_shared>(std::move(decompressed)); writeBuffer.putn_nocopy(shared_decompressed->data(), shared_decompressed->size()) .then([this_request, read_size, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS]( @@ -1715,7 +1761,7 @@ class asio_context final : public request_context, public std::enable_shared_fro { writtenSize = op.get(); this_request->m_downloaded += static_cast(read_size); - this_request->m_body_buf.consume(writtenSize); + this_request->m_body_buf.consume(read_size); this_request->async_read_until_buffersize( static_cast(std::min( static_cast(this_request->m_http_client->client_config().chunksize()), diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h index 7b6c974a0d..067233ab63 100644 --- a/Release/src/http/client/http_client_impl.h +++ b/Release/src/http/client/http_client_impl.h @@ -72,10 +72,10 @@ class request_context /// Set m_decompressor based on the response headers, or call report_exception /// false on failure - bool handle_content_encoding_compression(); + bool handle_compression(); /// Append an Accept-Encoding header if requested by the http_client settings - utility::string_t get_accept_encoding_header() const; + utility::string_t get_compression_header() const; concurrency::streams::streambuf _get_writebuffer(); @@ -95,7 +95,7 @@ class request_context // Registration for cancellation notification if enabled. pplx::cancellation_token_registration m_cancellationRegistration; - std::unique_ptr m_decompressor; + std::unique_ptr m_decompressor; protected: diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index a1f69ab215..d60f7ef1f5 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -182,9 +182,10 @@ class memory_holder { uint8_t* m_externalData; std::vector m_internalData; + size_t m_length; public: - memory_holder() : m_externalData(nullptr) + memory_holder() : m_externalData(nullptr), m_length(0) { } @@ -197,10 +198,11 @@ class memory_holder m_externalData = nullptr; } - inline void reassign_to(_In_opt_ uint8_t *block) + inline void reassign_to(_In_opt_ uint8_t *block, size_t length) { assert(block != nullptr); m_externalData = block; + m_length = length; } inline bool is_internally_allocated() const @@ -212,6 +214,11 @@ class memory_holder { return is_internally_allocated() ? &m_internalData[0] : m_externalData ; } + + inline size_t length() const + { + return is_internally_allocated() ? m_internalData.size() : m_length; + } }; // Possible ways a message body can be sent/received. @@ -245,7 +252,7 @@ class winhttp_request_context final : public request_context if (block == nullptr) m_body_data.allocate_space(length); else - m_body_data.reassign_to(block); + m_body_data.reassign_to(block, length); } void allocate_reply_space(_In_opt_ uint8_t *block, size_t length) @@ -253,7 +260,7 @@ class winhttp_request_context final : public request_context if (block == nullptr) m_body_data.allocate_space(length); else - m_body_data.reassign_to(block); + m_body_data.reassign_to(block, length); } bool is_externally_allocated() const @@ -286,8 +293,224 @@ class winhttp_request_context final : public request_context std::shared_ptr m_self_reference; memory_holder m_body_data; + // Compress/decompress-related processing state lives here + class compression_state + { + public: + compression_state() + : m_acquired(nullptr), m_bytes_read(0), m_bytes_processed(0), m_needs_flush(false), m_started(false), m_done(false), m_chunked(false) + { + } + + // Minimal state for on-the-fly decoding of "chunked" encoded data + class _chunk_helper + { + public: + _chunk_helper() + : m_bytes_remaining(0), m_chunk_size(true), m_chunk_delim(false), m_expect_linefeed(false), m_ignore(false), m_trailer(false) + { + } + + // Returns true if the end of chunked data has been reached, specifically whether the 0-length + // chunk and its trailing delimiter has been processed. Otherwise, offset and length bound the + // portion of buffer that represents a contiguous (and possibly partial) chunk of consumable + // data; offset+length is the total number of bytes processed from the buffer on this pass. + bool process_buffer(uint8_t *buffer, size_t buffer_size, size_t &offset, size_t &length) + { + bool done = false; + size_t n = 0; + size_t l = 0; + + while (n < buffer_size) + { + if (m_ignore) + { + if (m_expect_linefeed) + { + _ASSERTE(m_chunk_delim && m_trailer); + if (buffer[n] != '\n') + { + // The data stream does not conform to "chunked" encoding + throw http_exception(status_codes::BadRequest, "Transfer-Encoding malformed trailer"); + } + + // Look for further trailer fields or the end of the stream + m_expect_linefeed = false; + m_trailer = false; + } + else if (buffer[n] == '\r') + { + if (!m_trailer) + { + // We're at the end of the data we need to ignore + _ASSERTE(m_chunk_size || m_chunk_delim); + m_ignore = false; + m_chunk_delim = false; // this is only set if we're at the end of the message + } // else we're at the end of a trailer field + m_expect_linefeed = true; + } + else if (m_chunk_delim) + { + // We're processing (and ignoring) a trailer field + m_trailer = true; + } + } + else if (m_expect_linefeed) + { + // We've already seen a carriage return; confirm the linefeed + if (buffer[n] != '\n') + { + // The data stream does not conform to "chunked" encoding + throw http_exception(status_codes::BadRequest, "Transfer-Encoding malformed delimiter"); + } + if (m_chunk_size) + { + if (!m_bytes_remaining) + { + // We're processing the terminating "empty" chunk; there's + // no data, we just need to confirm the final chunk delimiter, + // possibly ignoring a trailer part along the way + m_ignore = true; + m_chunk_delim = true; + } // else we move on to the chunk data itself + m_chunk_size = false; + } + else + { + // Now we move on to the next chunk size + _ASSERTE(!m_bytes_remaining); + if (m_chunk_delim) + { + // We expect a chunk size next + m_chunk_size = true; + } + else + { + // We just processed the end-of-input delimiter + done = true; + } + m_chunk_delim = false; + } + m_expect_linefeed = false; + } + else if (m_chunk_delim) + { + // We're processing a post-chunk delimiter + if (buffer[n] != '\r') + { + // The data stream does not conform to "chunked" encoding + throw http_exception(status_codes::BadRequest, "Transfer-Encoding malformed chunk delimiter"); + } + + // We found the carriage return; look for the linefeed + m_expect_linefeed = true; + } + else if (m_chunk_size) + { + // We're processing an ASCII hexadecimal chunk size + if (buffer[n] >= 'a' && buffer[n] <= 'f') + { + m_bytes_remaining *= 16; + m_bytes_remaining += 10 + buffer[n] - 'a'; + } + else if (buffer[n] >= 'A' && buffer[n] <= 'F') + { + m_bytes_remaining *= 16; + m_bytes_remaining += 10 + buffer[n] - 'A'; + } + else if (buffer[n] >= '0' && buffer[n] <= '9') + { + m_bytes_remaining *= 16; + m_bytes_remaining += buffer[n] - '0'; + } + else if (buffer[n] == '\r') + { + // We've reached the end of the size, and there's no chunk extention + m_expect_linefeed = true; + } + else if (buffer[n] == ';') + { + // We've reached the end of the size, and there's a chunk extention; + // we don't support extensions, so we ignore them per RFC + m_ignore = true; + } + else + { + // The data stream does not conform to "chunked" encoding + throw http_exception(status_codes::BadRequest, "Transfer-Encoding malformed chunk size or extension"); + } + } + else + { + if (m_bytes_remaining) + { + // We're at the offset of a chunk of consumable data; let the caller process it + l = std::min(m_bytes_remaining, buffer_size-n); + m_bytes_remaining -= l; + if (!m_bytes_remaining) + { + // We're moving on to the post-chunk delimiter + m_chunk_delim = true; + } + } + else + { + // We've previously processed the terminating empty chunk and its + // trailing delimiter; skip the entire buffer, and inform the caller + n = buffer_size; + done = true; + } + + // Let the caller process the result + break; + } + + // Move on to the next byte + n++; + } + + offset = n; + length = l; + return buffer_size ? done : (!m_bytes_remaining && !m_chunk_size && !m_chunk_delim); + } + + private: + size_t m_bytes_remaining; // the number of bytes remaining in the chunk we're currently processing + bool m_chunk_size; // if true, we're processing a chunk size or its trailing delimiter + bool m_chunk_delim; // if true, we're processing a delimiter between a chunk and the next chunk's size + bool m_expect_linefeed; // if true, we're processing a delimiter, and we've already seen its carriage return + bool m_ignore; // if true, we're processing a chunk extension or trailer, which we don't support + bool m_trailer; // if true, we're processing (and ignoring) a trailer field; m_ignore is also true + }; + + std::vector m_buffer; // we read data from the stream into this before compressing + uint8_t *m_acquired; // we use this in place of m_buffer if the stream has directly-accessible data available + size_t m_bytes_read; // we most recently read this many bytes, which may be less than m_buffer.size() + size_t m_bytes_processed; // we've compressed this many bytes of m_bytes_read so far + bool m_needs_flush; // we've read and compressed all bytes, but the compressor still has compressed bytes to give us + bool m_started; // we've sent at least some number of bytes to m_decompressor + bool m_done; // we've read, compressed, and consumed all bytes + bool m_chunked; // if true, we need to decode and decompress a transfer-encoded message + size_t m_chunk_bytes; // un-decompressed bytes remaining in the most-recently-obtained data from m_chunk + std::unique_ptr<_chunk_helper> m_chunk; + } m_compression_state; + void cleanup() { + if (m_compression_state.m_acquired != nullptr) + { + // We may still hold a piece of the buffer if we encountered an exception; release it here + if (m_decompressor) + { + _get_writebuffer().commit(0); + } + else + { + _get_readbuffer().release(m_compression_state.m_acquired, m_compression_state.m_bytes_processed); + } + m_compression_state.m_acquired = nullptr; + } + if(m_request_handle != nullptr) { auto tmp_handle = m_request_handle; @@ -898,7 +1121,16 @@ class winhttp_client final : public _http_client_communicator return; } - const size_t content_length = msg._get_impl()->_get_content_length(); + size_t content_length; + try + { + content_length = msg._get_impl()->_get_content_length_and_set_compression(); + } + catch (...) + { + request->report_exception(std::current_exception()); + return; + } if (content_length > 0) { if ( msg.method() == http::methods::GET || msg.method() == http::methods::HEAD ) @@ -910,9 +1142,11 @@ class winhttp_client final : public _http_client_communicator // There is a request body that needs to be transferred. if (content_length == std::numeric_limits::max()) { - // The content length is unknown and the application set a stream. This is an - // indication that we will use transfer encoding chunked. + // The content length is not set and the application set a stream. This is an + // indication that we will use transfer encoding chunked. We still want to + // know that stream's effective length if possible for memory efficiency. winhttp_context->m_bodyType = transfer_encoding_chunked; + winhttp_context->m_remaining_to_write = msg._get_impl()->_get_stream_length(); } else { @@ -923,7 +1157,11 @@ class winhttp_client final : public _http_client_communicator } utility::string_t flattened_headers = web::http::details::flatten_http_headers(headers); - flattened_headers += winhttp_context->get_accept_encoding_header(); + if (winhttp_context->m_request.method() == http::methods::GET) + { + // Prepare to request a compressed response from the server if necessary. + flattened_headers += winhttp_context->get_compression_header(); + } // Add headers. if(!flattened_headers.empty()) @@ -1062,19 +1300,36 @@ class winhttp_client final : public _http_client_communicator else { // If bytes read is less than the chunk size this request is done. + // Is it really, though? The WinHttpReadData docs suggest that less can be returned regardless... const size_t chunkSize = pContext->m_http_client->client_config().chunksize(); - if (bytesRead < chunkSize && !firstRead) + std::unique_ptr &decompressor = pContext->m_decompressor; + if (!decompressor && bytesRead < chunkSize && !firstRead) { pContext->complete_request(pContext->m_downloaded); } else { - auto writebuf = pContext->_get_writebuffer(); - pContext->allocate_reply_space(writebuf.alloc(chunkSize), chunkSize); + uint8_t *buffer; + + if (!decompressor) + { + auto writebuf = pContext->_get_writebuffer(); + pContext->allocate_reply_space(writebuf.alloc(chunkSize), chunkSize); + buffer = pContext->m_body_data.get(); + } + else + { + // m_buffer holds the compressed data; we'll decompress into the caller's buffer later + if (pContext->m_compression_state.m_buffer.capacity() < chunkSize) + { + pContext->m_compression_state.m_buffer.reserve(chunkSize); + } + buffer = pContext->m_compression_state.m_buffer.data(); + } if (!WinHttpReadData( pContext->m_request_handle, - pContext->m_body_data.get(), + buffer, static_cast(chunkSize), nullptr)) { @@ -1087,11 +1342,38 @@ class winhttp_client final : public _http_client_communicator static void _transfer_encoding_chunked_write_data(_In_ winhttp_request_context * p_request_context) { - const size_t chunk_size = p_request_context->m_http_client->client_config().chunksize(); + size_t chunk_size; + std::unique_ptr &compressor = p_request_context->m_request.compressor(); - p_request_context->allocate_request_space(nullptr, chunk_size+http::details::chunked_encoding::additional_encoding_space); + // Set the chunk size up front; we need it before the lambda functions come into scope + if (compressor) + { + // We could allocate less than a chunk for the compressed data here, though that + // would result in more trips through this path for not-so-compressible data... + if (p_request_context->m_body_data.length() > http::details::chunked_encoding::additional_encoding_space) + { + // If we've previously allocated space for the compressed data, don't reduce it + chunk_size = p_request_context->m_body_data.length() - http::details::chunked_encoding::additional_encoding_space; + } + else if (p_request_context->m_remaining_to_write != std::numeric_limits::max()) + { + // Choose a semi-intelligent size based on how much total data is left to compress + chunk_size = std::min((size_t)p_request_context->m_remaining_to_write+128, p_request_context->m_http_client->client_config().chunksize()); + } + else + { + // Just base our allocation on the chunk size, since we don't have any other data available + chunk_size = p_request_context->m_http_client->client_config().chunksize(); + } + } + else + { + // We're not compressing; use the smaller of the remaining data (if known) and the configured (or default) chunk size + chunk_size = std::min((size_t)p_request_context->m_remaining_to_write, p_request_context->m_http_client->client_config().chunksize()); + } + p_request_context->allocate_request_space(nullptr, chunk_size + http::details::chunked_encoding::additional_encoding_space); - auto after_read = [p_request_context, chunk_size](pplx::task op) + auto after_read = [p_request_context, chunk_size, &compressor](pplx::task op) { size_t bytes_read; try @@ -1102,7 +1384,10 @@ class winhttp_client final : public _http_client_communicator { // We have raw memory here writing to a memory stream so it is safe to wait // since it will always be non-blocking. - p_request_context->m_readBufferCopy->putn_nocopy(&p_request_context->m_body_data.get()[http::details::chunked_encoding::data_offset], bytes_read).wait(); + if (!compressor) + { + p_request_context->m_readBufferCopy->putn_nocopy(&p_request_context->m_body_data.get()[http::details::chunked_encoding::data_offset], bytes_read).wait(); + } } } catch (...) @@ -1115,7 +1400,21 @@ class winhttp_client final : public _http_client_communicator size_t offset = http::details::chunked_encoding::add_chunked_delimiters(p_request_context->m_body_data.get(), chunk_size + http::details::chunked_encoding::additional_encoding_space, bytes_read); + if (!compressor && p_request_context->m_remaining_to_write != std::numeric_limits::max()) + { + if (bytes_read == 0 && p_request_context->m_remaining_to_write) + { + // The stream ended earlier than we detected it should + http_exception ex(U("Unexpected end of request body stream encountered before expected length met.")); + p_request_context->report_exception(ex); + return; + } + p_request_context->m_remaining_to_write -= bytes_read; + } + // Stop writing chunks if we reached the end of the stream. + // Note that we could detect end-of-stream based on !m_remaining_to_write, and insert + // the last (0) chunk if we have enough extra space... though we currently don't. if (bytes_read == 0) { p_request_context->m_bodyType = no_body; @@ -1140,7 +1439,171 @@ class winhttp_client final : public _http_client_communicator } }; - p_request_context->_get_readbuffer().getn(&p_request_context->m_body_data.get()[http::details::chunked_encoding::data_offset], chunk_size).then(after_read); + if (compressor) + { + auto do_compress = [p_request_context, chunk_size, &compressor](pplx::task op) -> pplx::task + { + size_t bytes_read; + + try + { + bytes_read = op.get(); + } + catch (...) + { + return pplx::task_from_exception(std::current_exception()); + } + _ASSERTE(bytes_read >= 0); + + uint8_t *buffer = p_request_context->m_compression_state.m_acquired; + if (buffer == nullptr) + { + buffer = p_request_context->m_compression_state.m_buffer.data(); + } + + web::http::compression::operation_hint hint = web::http::compression::operation_hint::has_more; + + if (bytes_read) + { + // An actual read always resets compression state for the next chunk + _ASSERTE(p_request_context->m_compression_state.m_bytes_processed == p_request_context->m_compression_state.m_bytes_read); + _ASSERTE(!p_request_context->m_compression_state.m_needs_flush); + p_request_context->m_compression_state.m_bytes_read = bytes_read; + p_request_context->m_compression_state.m_bytes_processed = 0; + if (p_request_context->m_readBufferCopy) + { + // If we've been asked to keep a copy of the raw data for restarts, do so here, pre-compression + p_request_context->m_readBufferCopy->putn_nocopy(buffer, bytes_read).wait(); + } + if (p_request_context->m_remaining_to_write == bytes_read) + { + // We've read to the end of the stream; finalize here if possible. We'll + // decrement the remaining count as we actually process the read buffer. + hint = web::http::compression::operation_hint::is_last; + } + } + else if (p_request_context->m_compression_state.m_needs_flush) + { + // All input has been consumed, but we still need to collect additional compressed output; + // this is done (in theory it can be multiple times) as a finalizing operation + hint = web::http::compression::operation_hint::is_last; + } + else if (p_request_context->m_compression_state.m_bytes_processed == p_request_context->m_compression_state.m_bytes_read) + { + if (p_request_context->m_remaining_to_write && p_request_context->m_remaining_to_write != std::numeric_limits::max()) + { + // The stream ended earlier than we detected it should + return pplx::task_from_exception(http_exception(U("Unexpected end of request body stream encountered before expected length met."))); + } + + // We think we're done; inform the compression library so it can finalize and/or give us any pending compressed bytes. + // Note that we may end up here multiple times if m_needs_flush is set, until all compressed bytes are drained. + hint = web::http::compression::operation_hint::is_last; + } + // else we're still compressing bytes from the previous read + + _ASSERTE(p_request_context->m_compression_state.m_bytes_processed <= p_request_context->m_compression_state.m_bytes_read); + + uint8_t *in = buffer + p_request_context->m_compression_state.m_bytes_processed; + size_t inbytes = p_request_context->m_compression_state.m_bytes_read - p_request_context->m_compression_state.m_bytes_processed; + return compressor->compress(in, inbytes, &p_request_context->m_body_data.get()[http::details::chunked_encoding::data_offset], chunk_size, hint) + .then([p_request_context, bytes_read, hint, chunk_size](pplx::task op) -> pplx::task + { + http::compression::operation_result r; + + try + { + r = op.get(); + } + catch (...) + { + return pplx::task_from_exception(std::current_exception()); + } + + if (hint == web::http::compression::operation_hint::is_last) + { + // We're done reading all chunks, but the compressor may still have compressed bytes to drain from previous reads + _ASSERTE(r.done || r.output_bytes_produced == chunk_size); + p_request_context->m_compression_state.m_needs_flush = !r.done; + p_request_context->m_compression_state.m_done = r.done; + } + + // Update the number of bytes compressed in this read chunk; if it's been fully compressed, + // we'll reset m_bytes_processed and m_bytes_read after reading the next chunk + p_request_context->m_compression_state.m_bytes_processed += r.input_bytes_processed; + _ASSERTE(p_request_context->m_compression_state.m_bytes_processed <= p_request_context->m_compression_state.m_bytes_read); + if (p_request_context->m_remaining_to_write != std::numeric_limits::max()) + { + _ASSERTE(p_request_context->m_remaining_to_write >= r.input_bytes_processed); + p_request_context->m_remaining_to_write -= r.input_bytes_processed; + } + + if (p_request_context->m_compression_state.m_acquired != nullptr && p_request_context->m_compression_state.m_bytes_processed == p_request_context->m_compression_state.m_bytes_read) + { + // Release the acquired buffer back to the streambuf at the earliest possible point + p_request_context->_get_readbuffer().release(p_request_context->m_compression_state.m_acquired, p_request_context->m_compression_state.m_bytes_processed); + p_request_context->m_compression_state.m_acquired = nullptr; + } + + return pplx::task_from_result(r.output_bytes_produced); + }); + }; + + if (p_request_context->m_compression_state.m_bytes_processed < p_request_context->m_compression_state.m_bytes_read || p_request_context->m_compression_state.m_needs_flush) + { + // We're still working on data from a previous read; continue compression without reading new data + do_compress(pplx::task_from_result(0)).then(after_read); + } + else if (p_request_context->m_compression_state.m_done) + { + // We just need to send the last (zero-length) chunk; there's no sense in going through the compression path + after_read(pplx::task_from_result(0)); + } + else + { + size_t length; + + // We need to read from the input stream, then compress before sending + if (p_request_context->_get_readbuffer().acquire(p_request_context->m_compression_state.m_acquired, length)) + { + if (length == 0) + { + if (p_request_context->_get_readbuffer().exception()) + { + p_request_context->report_exception(p_request_context->_get_readbuffer().exception()); + return; + } + else if (p_request_context->m_remaining_to_write && p_request_context->m_remaining_to_write != std::numeric_limits::max()) + { + // Unexpected end-of-stream. + p_request_context->report_error(GetLastError(), _XPLATSTR("Outgoing HTTP body stream ended early.")); + return; + } + } + else if (length > p_request_context->m_remaining_to_write) + { + // The stream grew, but we won't + length = p_request_context->m_remaining_to_write; + } + + do_compress(pplx::task_from_result(length)).then(after_read); + } + else + { + length = std::min((size_t)p_request_context->m_remaining_to_write, p_request_context->m_http_client->client_config().chunksize()); + if (p_request_context->m_compression_state.m_buffer.capacity() < length) + { + p_request_context->m_compression_state.m_buffer.reserve(length); + } + p_request_context->_get_readbuffer().getn(p_request_context->m_compression_state.m_buffer.data(), length).then(do_compress).then(after_read); + } + } + } + else + { + // We're not compressing; just read and chunk + p_request_context->_get_readbuffer().getn(&p_request_context->m_body_data.get()[http::details::chunked_encoding::data_offset], chunk_size).then(after_read); + } } static void _multiple_segment_write_data(_In_ winhttp_request_context * p_request_context) @@ -1272,7 +1735,21 @@ class winhttp_client final : public _http_client_communicator { return false; } + + // We successfully seeked back; now reset the compression state, if any, to match + if (p_request_context->m_request.compressor()) + { + try + { + p_request_context->m_request.compressor()->reset(); + } + catch (...) + { + return false; + } + } } + p_request_context->m_compression_state = winhttp_request_context::compression_state(); // If we got ERROR_WINHTTP_RESEND_REQUEST, the response header is not available, // we cannot call WinHttpQueryAuthSchemes and WinHttpSetCredentials. @@ -1346,7 +1823,16 @@ class winhttp_client final : public _http_client_communicator } // Reset the request body type since it might have already started sending. - const size_t content_length = request._get_impl()->_get_content_length(); + size_t content_length; + try + { + content_length = request._get_impl()->_get_content_length_and_set_compression(); + } + catch (...) + { + return false; + } + if (content_length > 0) { // There is a request body that needs to be transferred. @@ -1355,6 +1841,7 @@ class winhttp_client final : public _http_client_communicator // The content length is unknown and the application set a stream. This is an // indication that we will need to chunk the data. p_request_context->m_bodyType = transfer_encoding_chunked; + p_request_context->m_remaining_to_write = request._get_impl()->_get_stream_length(); } else { @@ -1551,11 +2038,17 @@ class winhttp_client final : public _http_client_communicator } } - if (!p_request_context->handle_content_encoding_compression()) + // Check whether the request is compressed, and if so, whether we're handling it. + if (!p_request_context->handle_compression()) { // false indicates report_exception was called return; } + if (p_request_context->m_decompressor && !p_request_context->m_http_client->client_config().request_compressed_response()) + { + p_request_context->m_compression_state.m_chunk = std::make_unique(); + p_request_context->m_compression_state.m_chunked = true; + } // Signal that the headers are available. p_request_context->complete_headers(); @@ -1582,25 +2075,30 @@ class winhttp_client final : public _http_client_communicator { // Status information contains pointer to DWORD containing number of bytes available. const DWORD num_bytes = *(PDWORD)statusInfo; + uint8_t *buffer; - if(num_bytes > 0) + if (num_bytes > 0) { if (p_request_context->m_decompressor) { - // Decompression is too slow to reliably do on this callback. Therefore we need to store it now in order to decompress it at a later stage in the flow. - // However, we want to eventually use the writebuf to store the decompressed body. Therefore we'll store the compressed body as an internal allocation in the request_context - p_request_context->allocate_reply_space(nullptr, num_bytes); + // Allocate space for the compressed data; we'll decompress it into the caller stream once it's been filled in + if (p_request_context->m_compression_state.m_buffer.capacity() < num_bytes) + { + p_request_context->m_compression_state.m_buffer.reserve(num_bytes); + } + buffer = p_request_context->m_compression_state.m_buffer.data(); } else { auto writebuf = p_request_context->_get_writebuffer(); p_request_context->allocate_reply_space(writebuf.alloc(num_bytes), num_bytes); + buffer = p_request_context->m_body_data.get(); } - // Read in body all at once. + // Read in available body data all at once. if(!WinHttpReadData( hRequestHandle, - p_request_context->m_body_data.get(), + buffer, num_bytes, nullptr)) { @@ -1610,6 +2108,21 @@ class winhttp_client final : public _http_client_communicator } else { + if (p_request_context->m_decompressor) + { + if (p_request_context->m_compression_state.m_chunked) + { + // We haven't seen the 0-length chunk and/or trailing delimiter that indicate the end of chunked input + p_request_context->report_exception(http_exception("Chunked response stream ended unexpectedly")); + return; + } + if (p_request_context->m_compression_state.m_started && !p_request_context->m_compression_state.m_done) + { + p_request_context->report_exception(http_exception("Received incomplete compressed stream")); + return; + } + } + // No more data available, complete the request. auto progress = p_request_context->m_request._get_impl()->_progress_handler(); if (progress) @@ -1647,68 +2160,240 @@ class winhttp_client final : public _http_client_communicator // If no bytes have been read, then this is the end of the response. if (bytesRead == 0) { + if (p_request_context->m_decompressor) + { + if (p_request_context->m_compression_state.m_chunked) + { + // We haven't seen the 0-length chunk and/or trailing delimiter that indicate the end of chunked input + p_request_context->report_exception(http_exception("Chunked response stream ended unexpectedly")); + return; + } + if (p_request_context->m_compression_state.m_started && !p_request_context->m_compression_state.m_done) + { + p_request_context->report_exception(http_exception("Received incomplete compressed stream")); + return; + } + } p_request_context->complete_request(p_request_context->m_downloaded); return; } auto writebuf = p_request_context->_get_writebuffer(); - // If we have compressed data it is stored in the local allocation of the p_request_context. We will store the decompressed buffer in the external allocation of the p_request_context. if (p_request_context->m_decompressor) { - web::http::details::compression::data_buffer decompressed = p_request_context->m_decompressor->decompress(p_request_context->m_body_data.get(), bytesRead); - - if (p_request_context->m_decompressor->has_error()) - { - p_request_context->report_exception(std::runtime_error("Failed to decompress the response body")); - return; - } + size_t chunk_size = std::max((size_t)bytesRead, p_request_context->m_http_client->client_config().chunksize()); + p_request_context->m_compression_state.m_bytes_read = static_cast(bytesRead); + p_request_context->m_compression_state.m_chunk_bytes = 0; - // We've decompressed this chunk of the body, need to now store it in the writebuffer. - auto decompressed_size = decompressed.size(); + // Note, some servers seem to send a first chunk of body data that decompresses to nothing, but + // initializes the decompression state; this produces no decompressed output. Subsequent chunks + // will then begin emitting decompressed body data. - if (decompressed_size > 0) + // Oddly enough, WinHttp doesn't de-chunk for us if "chunked" isn't the only + // encoding, so we need to do so on the fly as we process the received data + auto process_buffer = [chunk_size](winhttp_request_context *c, size_t bytes_produced, bool outer) -> bool { - auto p = writebuf.alloc(decompressed_size); - p_request_context->allocate_reply_space(p, decompressed_size); - std::memcpy(p_request_context->m_body_data.get(), &decompressed[0], decompressed_size); - } - // Note, some servers seem to send a first chunk of body data that decompresses to nothing but initializes the zlib decryption state. This produces no decompressed output. - // Subsequent chunks will then begin emmiting decompressed body data. + if (!c->m_compression_state.m_chunk_bytes) + { + if (c->m_compression_state.m_chunked) + { + size_t offset; + bool done; + + // Process the next portion of this piece of the transfer-encoded message + done = c->m_compression_state.m_chunk->process_buffer(c->m_compression_state.m_buffer.data()+c->m_compression_state.m_bytes_processed, c->m_compression_state.m_bytes_read-c->m_compression_state.m_bytes_processed, offset, c->m_compression_state.m_chunk_bytes); + + // Skip chunk-related metadata; it isn't relevant to decompression + _ASSERTE(c->m_compression_state.m_bytes_processed+offset <= c->m_compression_state.m_bytes_read); + c->m_compression_state.m_bytes_processed += offset; + + if (!c->m_compression_state.m_chunk_bytes) + { + if (done) + { + // We've processed/validated all bytes in this transfer-encoded message. + // Note that we currently ignore "extra" trailing bytes, i.e. c->m_compression_state.m_bytes_processed < c->m_compression_state.m_bytes_read + if (c->m_compression_state.m_done) + { + c->complete_request(c->m_downloaded); + return false; + } + else if (!outer && bytes_produced != chunk_size) + { + throw http_exception("Transfer ended before decompression completed"); + } + } + else if (!outer && bytes_produced != chunk_size) + { + // There should be more data to receive; look for it + c->m_compression_state.m_bytes_processed = 0; + read_next_response_chunk(c, static_cast(c->m_compression_state.m_bytes_read)); + return false; + } + } + } + else + { + _ASSERTE(!c->m_compression_state.m_bytes_processed || c->m_compression_state.m_bytes_processed == c->m_compression_state.m_bytes_read); + if (c->m_compression_state.m_done) + { + // Decompression is done; complete the request + c->complete_request(c->m_downloaded); + return false; + } + else if (c->m_compression_state.m_bytes_processed != c->m_compression_state.m_bytes_read) + { + // We still have more data to process in the current buffer + c->m_compression_state.m_chunk_bytes = c->m_compression_state.m_bytes_read - c->m_compression_state.m_bytes_processed; + } + else if (!outer && bytes_produced != chunk_size) + { + // There should be more data to receive; look for it + c->m_compression_state.m_bytes_processed = 0; + read_next_response_chunk(c, static_cast(c->m_compression_state.m_bytes_read)); + return false; + } + // Otherwise, we've processed all bytes in the input buffer, but there's a good chance that + // there are still decompressed bytes to emit; we'll do so before reading the next chunk + } + } - bytesRead = static_cast(decompressed_size); - } + // We're still processing the current message chunk + return true; + }; - // If the data was allocated directly from the buffer then commit, otherwise we still - // need to write to the response stream buffer. - if (p_request_context->is_externally_allocated()) - { - writebuf.commit(bytesRead); - read_next_response_chunk(p_request_context.get(), bytesRead); - } - else - { - writebuf.putn_nocopy(p_request_context->m_body_data.get(), bytesRead).then( - [hRequestHandle, p_request_context, bytesRead] (pplx::task op) + Concurrency::details::_do_while([p_request_context, chunk_size, process_buffer]() -> pplx::task { - size_t written = 0; - try { written = op.get(); } + uint8_t *buffer; + + try + { + if (!process_buffer(p_request_context.get(), 0, true)) + { + // The chunked request has been completely processed (or contains no data in the first place) + return pplx::task_from_result(false); + } + } catch (...) { - p_request_context->report_exception(std::current_exception()); - return; + // The outer do-while requires an explicit task return to activate the then() clause + return pplx::task_from_exception(std::current_exception()); } - // If we couldn't write everything, it's time to exit. - if (written != bytesRead) + // If it's possible to know how much post-compression data we're expecting (for instance if we can discern how + // much total data the ostream can support, we could allocate (or at least attempt to acquire) based on that + p_request_context->m_compression_state.m_acquired = p_request_context->_get_writebuffer().alloc(chunk_size); + if (p_request_context->m_compression_state.m_acquired) { - p_request_context->report_exception(std::runtime_error("response stream unexpectedly failed to write the requested number of bytes")); - return; + buffer = p_request_context->m_compression_state.m_acquired; + } + else + { + // The streambuf couldn't accommodate our request; we'll use m_body_data's + // internal vector as temporary storage, then putn() to the caller's stream + p_request_context->allocate_reply_space(nullptr, chunk_size); + buffer = p_request_context->m_body_data.get(); } - read_next_response_chunk(p_request_context.get(), bytesRead); + uint8_t *in = p_request_context->m_compression_state.m_buffer.data() + p_request_context->m_compression_state.m_bytes_processed; + size_t inbytes = p_request_context->m_compression_state.m_chunk_bytes; + if (inbytes) + { + p_request_context->m_compression_state.m_started = true; + } + return p_request_context->m_decompressor->decompress(in, inbytes, buffer, chunk_size, web::http::compression::operation_hint::has_more).then( + [p_request_context, buffer, chunk_size, process_buffer] (pplx::task op) + { + auto r = op.get(); + auto keep_going = [&r, process_buffer](winhttp_request_context *c) -> pplx::task + { + _ASSERTE(r.input_bytes_processed <= c->m_compression_state.m_chunk_bytes); + c->m_compression_state.m_chunk_bytes -= r.input_bytes_processed; + c->m_compression_state.m_bytes_processed += r.input_bytes_processed; + c->m_compression_state.m_done = r.done; + + try + { + // See if we still have more work to do for this section and/or for the response in general + return pplx::task_from_result(process_buffer(c, r.output_bytes_produced, false)); + } + catch (...) + { + return pplx::task_from_exception(std::current_exception()); + } + }; + + _ASSERTE(p_request_context->m_compression_state.m_bytes_processed+r.input_bytes_processed <= p_request_context->m_compression_state.m_bytes_read); + + if (p_request_context->m_compression_state.m_acquired != nullptr) + { + // We decompressed directly into the output stream + p_request_context->m_compression_state.m_acquired = nullptr; + p_request_context->_get_writebuffer().commit(r.output_bytes_produced); + return keep_going(p_request_context.get()); + } + + // We decompressed into our own buffer; let the stream copy the data + return p_request_context->_get_writebuffer().putn_nocopy(buffer, r.output_bytes_produced).then([p_request_context, r, keep_going](pplx::task op) { + if (op.get() != r.output_bytes_produced) + { + return pplx::task_from_exception(std::runtime_error("Response stream unexpectedly failed to write the requested number of bytes")); + } + return keep_going(p_request_context.get()); + }); + }); + }).then([p_request_context](pplx::task op) + { + try + { + bool ignored = op.get(); + } + catch (...) + { + // We're only here to pick up any exception that may have been thrown, and to clean up if needed + if (p_request_context->m_compression_state.m_acquired) + { + p_request_context->_get_writebuffer().commit(0); + p_request_context->m_compression_state.m_acquired = nullptr; + } + p_request_context->report_exception(std::current_exception()); + } }); } + else + { + // If the data was allocated directly from the buffer then commit, otherwise we still + // need to write to the response stream buffer. + if (p_request_context->is_externally_allocated()) + { + writebuf.commit(bytesRead); + read_next_response_chunk(p_request_context.get(), bytesRead); + } + else + { + writebuf.putn_nocopy(p_request_context->m_body_data.get(), bytesRead).then( + [hRequestHandle, p_request_context, bytesRead] (pplx::task op) + { + size_t written = 0; + try { written = op.get(); } + catch (...) + { + p_request_context->report_exception(std::current_exception()); + return; + } + + // If we couldn't write everything, it's time to exit. + if (written != bytesRead) + { + p_request_context->report_exception(std::runtime_error("response stream unexpectedly failed to write the requested number of bytes")); + return; + } + + read_next_response_chunk(p_request_context.get(), bytesRead); + }); + } + } return; } } diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp new file mode 100644 index 0000000000..89840b8867 --- /dev/null +++ b/Release/src/http/common/http_compression.cpp @@ -0,0 +1,1110 @@ +/*** + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * HTTP Library: Compression and decompression interfaces + * + * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ + +#include "stdafx.h" + +// CPPREST_EXCLUDE_COMPRESSION is set if we're on a platform that supports compression but we want to explicitly disable +// it. CPPREST_EXCLUDE_BROTLI is set if we want to explicitly disable Brotli compression support. +// CPPREST_EXCLUDE_WEBSOCKETS is a flag that now essentially means "no external dependencies". TODO: Rename + +#if __APPLE__ +#include "TargetConditionals.h" +#if defined(TARGET_OS_MAC) +#if !defined(CPPREST_EXCLUDE_COMPRESSION) +#define CPPREST_HTTP_COMPRESSION +#endif // !defined(CPPREST_EXCLUDE_COMPRESSION) +#endif // defined(TARGET_OS_MAC) +#elif defined(_WIN32) && (!defined(WINAPI_FAMILY) || WINAPI_PARTITION_DESKTOP) +#if !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) +#define CPPREST_HTTP_COMPRESSION +#endif // !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) +#endif + +#if defined(CPPREST_HTTP_COMPRESSION) +#include +#if !defined(CPPREST_EXCLUDE_BROTLI) +#define CPPREST_BROTLI_COMPRESSION +#endif // CPPREST_EXCLUDE_BROTLI +#if defined(CPPREST_BROTLI_COMPRESSION) +#include +#include +#endif // CPPREST_BROTLI_COMPRESSION +#endif + +namespace web +{ +namespace http +{ +namespace compression +{ +namespace builtin +{ +#if defined(CPPREST_HTTP_COMPRESSION) +// A shared base class for the gzip and deflate compressors +class zlib_compressor_base : public compress_provider +{ +public: + zlib_compressor_base(int windowBits, + int compressionLevel = Z_DEFAULT_COMPRESSION, + int method = Z_DEFLATED, + int strategy = Z_DEFAULT_STRATEGY, + int memLevel = MAX_MEM_LEVEL) + : m_algorithm(windowBits >= 16 ? algorithm::GZIP : algorithm::DEFLATE) + { + m_state = deflateInit2(&m_stream, compressionLevel, method, windowBits, memLevel, strategy); + } + + const utility::string_t& algorithm() const { return m_algorithm; } + + size_t compress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + operation_hint hint, + size_t& input_bytes_processed, + bool* done) + { + if (m_state == Z_STREAM_END || (hint != operation_hint::is_last && !input_size)) + { + input_bytes_processed = 0; + if (done) + { + *done = (m_state == Z_STREAM_END); + } + return 0; + } + + if (m_state != Z_OK && m_state != Z_BUF_ERROR && m_state != Z_STREAM_ERROR) + { + std::stringstream ss; + ss << "Prior unrecoverable compression stream error " << m_state; + throw std::runtime_error(std::move(ss.str())); + } + + m_stream.next_in = const_cast(input); + m_stream.avail_in = static_cast(input_size); + m_stream.next_out = const_cast(output); + m_stream.avail_out = static_cast(output_size); + + m_state = deflate(&m_stream, (hint == operation_hint::is_last) ? Z_FINISH : Z_PARTIAL_FLUSH); + if (m_state != Z_OK && m_state != Z_STREAM_ERROR && + !(hint == operation_hint::is_last && (m_state == Z_STREAM_END || m_state == Z_BUF_ERROR))) + { + std::stringstream ss; + ss << "Unrecoverable compression stream error " << m_state; + throw std::runtime_error(std::move(ss.str())); + } + + input_bytes_processed = input_size - m_stream.avail_in; + if (done) + { + *done = (m_state == Z_STREAM_END); + } + return output_size - m_stream.avail_out; + } + + pplx::task compress( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) + { + operation_result r; + + try + { + r.output_bytes_produced = + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + } + catch (...) + { + pplx::task_completion_event ev; + ev.set_exception(std::current_exception()); + return pplx::create_task(ev); + } + + return pplx::task_from_result(r); + } + + void reset() + { + m_state = deflateReset(&m_stream); + if (m_state != Z_OK) + { + std::stringstream ss; + ss << "Failed to reset zlib compressor " << m_state; + throw std::runtime_error(std::move(ss.str())); + } + } + + ~zlib_compressor_base() { (void)deflateEnd(&m_stream); } + +private: + int m_state{Z_BUF_ERROR}; + z_stream m_stream{0}; + const utility::string_t& m_algorithm; +}; + +// A shared base class for the gzip and deflate decompressors +class zlib_decompressor_base : public decompress_provider +{ +public: + zlib_decompressor_base(int windowBits) : m_algorithm(windowBits >= 16 ? algorithm::GZIP : algorithm::DEFLATE) + { + m_state = inflateInit2(&m_stream, windowBits); + } + + const utility::string_t& algorithm() const { return m_algorithm; } + + size_t decompress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + operation_hint hint, + size_t& input_bytes_processed, + bool* done) + { + if (m_state == Z_STREAM_END || !input_size) + { + input_bytes_processed = 0; + if (done) + { + *done = (m_state == Z_STREAM_END); + } + return 0; + } + + if (m_state != Z_OK && m_state != Z_BUF_ERROR && m_state != Z_STREAM_ERROR) + { + std::stringstream ss; + ss << "Prior unrecoverable decompression stream error " << m_state; + throw std::runtime_error(std::move(ss.str())); + } + + m_stream.next_in = const_cast(input); + m_stream.avail_in = static_cast(input_size); + m_stream.next_out = const_cast(output); + m_stream.avail_out = static_cast(output_size); + + m_state = inflate(&m_stream, (hint == operation_hint::is_last) ? Z_FINISH : Z_PARTIAL_FLUSH); + if (m_state != Z_OK && m_state != Z_STREAM_ERROR && m_state != Z_STREAM_END && m_state != Z_BUF_ERROR) + { + // Z_BUF_ERROR is a success code for Z_FINISH, and the caller can continue as if operation_hint::is_last was + // not given + std::stringstream ss; + ss << "Unrecoverable decompression stream error " << m_state; + throw std::runtime_error(std::move(ss.str())); + } + + input_bytes_processed = input_size - m_stream.avail_in; + if (done) + { + *done = (m_state == Z_STREAM_END); + } + return output_size - m_stream.avail_out; + } + + pplx::task decompress( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) + { + operation_result r; + + try + { + r.output_bytes_produced = + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + } + catch (...) + { + pplx::task_completion_event ev; + ev.set_exception(std::current_exception()); + return pplx::create_task(ev); + } + + return pplx::task_from_result(r); + } + + void reset() + { + m_state = inflateReset(&m_stream); + if (m_state != Z_OK) + { + std::stringstream ss; + ss << "Failed to reset zlib decompressor " << m_state; + throw std::runtime_error(std::move(ss.str())); + } + } + + ~zlib_decompressor_base() { (void)inflateEnd(&m_stream); } + +private: + int m_state{Z_BUF_ERROR}; + z_stream m_stream{0}; + const utility::string_t& m_algorithm; +}; + +class gzip_compressor : public zlib_compressor_base +{ +public: + gzip_compressor() : zlib_compressor_base(31) // 15 is MAX_WBITS in zconf.h; add 16 for gzip + { + } + + gzip_compressor(int compressionLevel, int method, int strategy, int memLevel) + : zlib_compressor_base(31, compressionLevel, method, strategy, memLevel) + { + } +}; + +class gzip_decompressor : public zlib_decompressor_base +{ +public: + gzip_decompressor::gzip_decompressor() : zlib_decompressor_base(16) // gzip auto-detect + { + } +}; + +class deflate_compressor : public zlib_compressor_base +{ +public: + deflate_compressor() : zlib_compressor_base(15) // 15 is MAX_WBITS in zconf.h + { + } + + deflate_compressor(int compressionLevel, int method, int strategy, int memLevel) + : zlib_compressor_base(15, compressionLevel, method, strategy, memLevel) + { + } +}; + +class deflate_decompressor : public zlib_decompressor_base +{ +public: + deflate_decompressor() : zlib_decompressor_base(0) // deflate auto-detect + { + } +}; + +#if defined(CPPREST_BROTLI_COMPRESSION) +class brotli_compressor : public compress_provider +{ +public: + brotli_compressor(uint32_t window = BROTLI_DEFAULT_WINDOW, + uint32_t quality = BROTLI_DEFAULT_QUALITY, + uint32_t mode = BROTLI_DEFAULT_MODE) + : m_window(window), m_quality(quality), m_mode(mode) + { + (void)reset(); + } + + const utility::string_t& algorithm() const { return algorithm::BROTLI; } + + size_t compress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + operation_hint hint, + size_t& input_bytes_processed, + bool* done) + { + if (m_done || (hint != operation_hint::is_last && !input_size)) + { + input_bytes_processed = 0; + if (done) + { + *done = m_done; + } + return 0; + } + + if (m_state != BROTLI_TRUE) + { + throw std::runtime_error("Prior unrecoverable compression stream error"); + } + + const uint8_t* next_in = input; + size_t avail_in; + uint8_t* next_out = output; + size_t avail_out = output_size; + size_t total_out; + + if (BrotliEncoderHasMoreOutput(m_stream) == BROTLI_TRUE) + { + avail_in = 0; + do + { + m_state = BrotliEncoderCompressStream(m_stream, + (hint == operation_hint::is_last) ? BROTLI_OPERATION_FINISH + : BROTLI_OPERATION_FLUSH, + &avail_in, + &next_in, + &avail_out, + &next_out, + &total_out); + } while (m_state == BROTLI_TRUE && avail_out && BrotliEncoderHasMoreOutput(m_stream) == BROTLI_TRUE); + } + + if (m_state == BROTLI_TRUE && avail_out) + { + avail_in = input_size; + do + { + m_state = BrotliEncoderCompressStream(m_stream, + (hint == operation_hint::is_last) ? BROTLI_OPERATION_FINISH + : BROTLI_OPERATION_FLUSH, + &avail_in, + &next_in, + &avail_out, + &next_out, + &total_out); + } while (m_state == BROTLI_TRUE && avail_out && BrotliEncoderHasMoreOutput(m_stream) == BROTLI_TRUE); + } + + if (m_state != BROTLI_TRUE) + { + throw std::runtime_error("Unrecoverable compression stream error"); + } + + if (hint == operation_hint::is_last) + { + m_done = (BrotliEncoderIsFinished(m_stream) == BROTLI_TRUE); + } + + input_bytes_processed = input_size - avail_in; + if (done) + { + *done = m_done; + } + return output_size - avail_out; + } + + pplx::task compress( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) + { + operation_result r; + + try + { + r.output_bytes_produced = + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + } + catch (...) + { + pplx::task_completion_event ev; + ev.set_exception(std::current_exception()); + return pplx::create_task(ev); + } + + return pplx::task_from_result(r); + } + + void reset() + { + if (m_stream) + { + BrotliEncoderDestroyInstance(m_stream); + } + + m_stream = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr); + m_state = m_stream ? BROTLI_TRUE : BROTLI_FALSE; + + if (m_state == BROTLI_TRUE && m_window != BROTLI_DEFAULT_WINDOW) + { + m_state = BrotliEncoderSetParameter(m_stream, BROTLI_PARAM_LGWIN, m_window); + } + if (m_state == BROTLI_TRUE && m_quality != BROTLI_DEFAULT_QUALITY) + { + m_state = BrotliEncoderSetParameter(m_stream, BROTLI_PARAM_QUALITY, m_quality); + } + if (m_state == BROTLI_TRUE && m_mode != BROTLI_DEFAULT_MODE) + { + m_state = BrotliEncoderSetParameter(m_stream, BROTLI_PARAM_MODE, m_window); + } + + if (m_state != BROTLI_TRUE) + { + throw std::runtime_error("Failed to reset Brotli compressor"); + } + } + + ~brotli_compressor() + { + if (m_stream) + { + BrotliEncoderDestroyInstance(m_stream); + } + } + +private: + BROTLI_BOOL m_state{BROTLI_FALSE}; + BrotliEncoderState* m_stream{nullptr}; + bool m_done{false}; + uint32_t m_window; + uint32_t m_quality; + uint32_t m_mode; +}; + +class brotli_decompressor : public decompress_provider +{ +public: + brotli_decompressor() + { + try + { + reset(); + } + catch (...) + { + } + } + + const utility::string_t& algorithm() const { return algorithm::BROTLI; } + + size_t decompress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + operation_hint hint, + size_t& input_bytes_processed, + bool* done) + { + if (m_state == BROTLI_DECODER_RESULT_SUCCESS /* || !input_size*/) + { + input_bytes_processed = 0; + if (done) + { + *done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); + } + return 0; + } + + if (m_state == BROTLI_DECODER_RESULT_ERROR) + { + throw std::runtime_error("Prior unrecoverable decompression stream error"); + } + + const uint8_t* next_in = input; + size_t avail_in = input_size; + uint8_t* next_out = output; + size_t avail_out = output_size; + size_t total_out; + + // N.B. we ignore 'hint' here. We could instead call BrotliDecoderDecompress() if it's set, but we'd either + // have to first allocate a guaranteed-large-enough buffer and then copy out of it, or we'd have to call + // reset() if it failed due to insufficient output buffer space (and we'd need to use + // BrotliDecoderGetErrorCode() to tell if that's why it failed) + m_state = BrotliDecoderDecompressStream(m_stream, &avail_in, &next_in, &avail_out, &next_out, &total_out); + if (m_state == BROTLI_DECODER_RESULT_ERROR) + { + throw std::runtime_error("Unrecoverable decompression stream error"); + } + + input_bytes_processed = input_size - avail_in; + if (done) + { + *done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); + } + return output_size - avail_out; + } + + pplx::task decompress( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) + { + operation_result r; + + try + { + r.output_bytes_produced = + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + } + catch (...) + { + pplx::task_completion_event ev; + ev.set_exception(std::current_exception()); + return pplx::create_task(ev); + } + + return pplx::task_from_result(r); + } + + void reset() + { + if (m_stream) + { + BrotliDecoderDestroyInstance(m_stream); + } + + m_stream = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr); + m_state = m_stream ? BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT : BROTLI_DECODER_RESULT_ERROR; + + if (m_state != BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) + { + throw std::runtime_error("Failed to reset Brotli decompressor"); + } + } + + ~brotli_decompressor() + { + if (m_stream) + { + BrotliDecoderDestroyInstance(m_stream); + } + } + +private: + BrotliDecoderResult m_state{BROTLI_DECODER_RESULT_ERROR}; + BrotliDecoderState* m_stream{nullptr}; +}; +#endif // CPPREST_BROTLI_COMPRESSION +#endif // CPPREST_HTTP_COMPRESSION + +const utility::string_t algorithm::GZIP = _XPLATSTR("gzip"); +const utility::string_t algorithm::DEFLATE = _XPLATSTR("deflate"); +const utility::string_t algorithm::BROTLI = _XPLATSTR("br"); + +// Generic internal implementation of the compress_factory API +class generic_compress_factory : public compress_factory +{ +public: + generic_compress_factory(const utility::string_t& algorithm, + std::function()> make_compressor) + : _algorithm(algorithm), _make_compressor(make_compressor) + { + } + + const utility::string_t& algorithm() const { return _algorithm; } + + std::unique_ptr make_compressor() const { return _make_compressor(); } + +private: + const utility::string_t _algorithm; + std::function()> _make_compressor; +}; + +// Generic internal implementation of the decompress_factory API +class generic_decompress_factory : public decompress_factory +{ +public: + generic_decompress_factory(const utility::string_t& algorithm, + uint16_t weight, + std::function()> make_decompressor) + : _algorithm(algorithm), _weight(weight), _make_decompressor(make_decompressor) + { + } + + const utility::string_t& algorithm() const { return _algorithm; } + + const uint16_t weight() const { return _weight; } + + std::unique_ptr make_decompressor() const { return _make_decompressor(); } + +private: + const utility::string_t _algorithm; + uint16_t _weight; + std::function()> _make_decompressor; +}; + +// "Private" algorithm-to-factory tables for namespace static helpers +static const std::vector> g_compress_factories +#if defined(CPPREST_HTTP_COMPRESSION) + = {std::make_shared( + algorithm::GZIP, []() -> std::unique_ptr { return std::make_unique(); }), + std::make_shared( + algorithm::DEFLATE, + []() -> std::unique_ptr { return std::make_unique(); }), +#if defined(CPPREST_BROTLI_COMPRESSION) + std::make_shared( + algorithm::BROTLI, + []() -> std::unique_ptr { return std::make_unique(); }) +#endif // CPPREST_BROTLI_COMPRESSION +}; +#else // CPPREST_HTTP_COMPRESSION + ; +#endif // CPPREST_HTTP_COMPRESSION + +static const std::vector> g_decompress_factories +#if defined(CPPREST_HTTP_COMPRESSION) + = {std::make_shared( + algorithm::GZIP, + 500, + []() -> std::unique_ptr { return std::make_unique(); }), + std::make_shared( + algorithm::DEFLATE, + 500, + []() -> std::unique_ptr { return std::make_unique(); }), +#if defined(CPPREST_BROTLI_COMPRESSION) + std::make_shared( + algorithm::BROTLI, + 500, + []() -> std::unique_ptr { return std::make_unique(); }) +#endif // CPPREST_BROTLI_COMPRESSION +}; +#else // CPPREST_HTTP_COMPRESSION + ; +#endif // CPPREST_HTTP_COMPRESSION + +bool supported() { return !g_compress_factories.empty(); } + +bool algorithm::supported(const utility::string_t& algorithm) +{ + auto size = g_compress_factories.size(); + + for (int i = 0; i < size; i++) + { + if (utility::details::str_iequal(algorithm, g_compress_factories[i]->algorithm())) + { + return true; + } + } + + return false; +} + +static std::unique_ptr _make_compressor( + const std::vector>& factories, const utility::string_t& algorithm) +{ + auto size = factories.size(); + + for (int i = 0; i < size; i++) + { + auto factory = factories[i].get(); + if (factory && utility::details::str_iequal(algorithm, factory->algorithm())) + { + return factory->make_compressor(); + } + } + + return std::unique_ptr(); +} + +std::unique_ptr make_compressor(const utility::string_t& algorithm) +{ + return _make_compressor(g_compress_factories, algorithm); +} + +static std::unique_ptr _make_decompressor( + const std::vector>& factories, const utility::string_t& algorithm) +{ + auto size = factories.size(); + + for (int i = 0; i < size; i++) + { + auto factory = factories[i].get(); + if (factory && utility::details::str_iequal(algorithm, factory->algorithm())) + { + return factory->make_decompressor(); + } + } + + return std::unique_ptr(); +} + +std::unique_ptr make_decompressor(const utility::string_t& algorithm) +{ + return _make_decompressor(g_decompress_factories, algorithm); +} + +std::shared_ptr get_compress_factory(const utility::string_t& algorithm) +{ + auto size = g_compress_factories.size(); + + for (int i = 0; i < size; i++) + { + if (utility::details::str_iequal(algorithm, g_compress_factories[i]->algorithm())) + { + return g_compress_factories[i]; + } + } + + return std::shared_ptr(); +} + +std::shared_ptr get_decompress_factory(const utility::string_t& algorithm) +{ + auto size = g_decompress_factories.size(); + + for (int i = 0; i < size; i++) + { + if (utility::details::str_iequal(algorithm, g_decompress_factories[i]->algorithm())) + { + return g_decompress_factories[i]; + } + } + + return std::shared_ptr(); +} + +std::unique_ptr make_gzip_compressor(int compressionLevel, int method, int strategy, int memLevel) +{ +#if defined(CPPREST_HTTP_COMPRESSION) + return std::move(std::make_unique(compressionLevel, method, strategy, memLevel)); +#else // CPPREST_HTTP_COMPRESSION + return std::unique_ptr(); +#endif // CPPREST_HTTP_COMPRESSION +} + +std::unique_ptr make_deflate_compressor(int compressionLevel, int method, int strategy, int memLevel) +{ +#if defined(CPPREST_HTTP_COMPRESSION) + return std::move(std::make_unique(compressionLevel, method, strategy, memLevel)); +#else // CPPREST_HTTP_COMPRESSION + return std::unique_ptr(); +#endif // CPPREST_HTTP_COMPRESSION +} + +std::unique_ptr make_brotli_compressor(uint32_t window, uint32_t quality, uint32_t mode) +{ +#if defined(CPPREST_HTTP_COMPRESSION) && defined(CPPREST_BROTLI_COMPRESSION) + return std::move(std::make_unique(window, quality, mode)); +#else // CPPREST_BROTLI_COMPRESSION + return std::unique_ptr(); +#endif // CPPREST_BROTLI_COMPRESSION +} +} // namespace builtin + +std::shared_ptr make_compress_factory( + const utility::string_t& algorithm, std::function()> make_compressor) +{ + return std::make_shared(algorithm, make_compressor); +} + +std::shared_ptr make_decompress_factory( + const utility::string_t& algorithm, + uint16_t weight, + std::function()> make_decompressor) +{ + return std::make_shared(algorithm, weight, make_decompressor); +} + +namespace details +{ +namespace builtin +{ +const std::vector> get_decompress_factories() +{ + return web::http::compression::builtin::g_decompress_factories; +} +} // namespace builtin + +static bool is_http_whitespace(utility::char_t ch) { return ch == _XPLATSTR(" ")[0] || ch == _XPLATSTR("\t")[0]; } + +static void remove_surrounding_http_whitespace(const utility::string_t& encoding, size_t& start, size_t& length) +{ + while (length > 0 && is_http_whitespace(encoding.at(start))) + { + start++; + length--; + } + while (length > 0 && is_http_whitespace(encoding.at(start + length - 1))) + { + length--; + } +} + +std::unique_ptr get_compressor_from_header( + const utility::string_t& encoding, + header_types type, + const std::vector>& factories) +{ + const std::vector>& f = + factories.empty() ? web::http::compression::builtin::g_compress_factories : factories; + std::unique_ptr compressor; + struct _tuple + { + size_t start; + size_t length; + size_t rank; + } t; + std::vector<_tuple> tokens; + size_t highest; + size_t mark; + size_t end; + size_t n; + bool first; + + _ASSERTE(type == header_types::te || type == header_types::accept_encoding); + + // See https://tools.ietf.org/html/rfc7230#section-4.3 (TE) and + // https://tools.ietf.org/html/rfc7231#section-5.3.4 (Accept-Encoding) for details + + n = 0; + highest = 0; + first = true; + while (n != utility::string_t::npos) + { + // Tokenize by commas first + mark = encoding.find(_XPLATSTR(","), n); + t.start = n; + t.rank = static_cast(-1); + if (mark == utility::string_t::npos) + { + t.length = encoding.size() - n; + n = utility::string_t::npos; + } + else + { + t.length = mark - n; + n = mark + 1; + } + + // Then remove leading and trailing whitespace + remove_surrounding_http_whitespace(encoding, t.start, t.length); + + // Next split at the semicolon, if any, and deal with rank and additional whitespace + mark = encoding.find(_XPLATSTR(";")[0], t.start); + if (mark < t.start + t.length) + { + end = t.start + t.length - 1; + t.length = mark - t.start; + while (t.length > 0 && is_http_whitespace(encoding.at(t.start + t.length - 1))) + { + // Skip trailing whitespace in encoding type + t.length--; + } + if (mark < end) + { + // Check for an optional ranking, max. length "q=0.999" + mark = encoding.find(_XPLATSTR("q="), mark + 1); + if (mark != utility::string_t::npos && mark + 1 < end && end - mark <= 6) + { + // Determine ranking; leading whitespace has been implicitly skipped by find(). + // The ranking always starts with '1' or '0' per standard, and has at most 3 decimal places + mark += 1; + t.rank = 1000 * (encoding.at(mark + 1) - _XPLATSTR("0")[0]); + if (mark + 2 < end && encoding.at(mark + 2) == _XPLATSTR(".")[0]) + { + // This is a real number rank; convert decimal part to hundreds and apply it + size_t factor = 100; + mark += 2; + for (size_t i = mark + 1; i <= end; i++) + { + t.rank += (encoding.at(i) - _XPLATSTR("0")[0]) * factor; + factor /= 10; + } + } + if (t.rank > 1000) + { + throw http_exception(status_codes::BadRequest, "Invalid q-value in header"); + } + } + } + } + + if (!t.length) + { + if (!first || n != utility::string_t::npos) + { + // An entirely empty header is OK per RFC, but an extraneous comma is not + throw http_exception(status_codes::BadRequest, "Empty field in header"); + } + return std::unique_ptr(); + } + + if (!compressor) + { + if (t.rank == static_cast(1000) || t.rank == static_cast(-1)) + { + // Immediately try to instantiate a compressor for any unranked or top-ranked algorithm + compressor = web::http::compression::builtin::_make_compressor(f, encoding.substr(t.start, t.length)); + } + else if (t.rank) + { + // Store off remaining ranked algorithms, sorting as we go + if (t.rank >= highest) + { + tokens.emplace_back(t); + highest = t.rank; + } + else + { + for (auto x = tokens.begin(); x != tokens.end(); x++) + { + if (t.rank <= x->rank) + { + tokens.emplace(x, t); + break; + } + } + } + } + // else a rank of 0 means "not permitted" + } + // else we've chosen a compressor; we're just validating the rest of the header + + first = false; + } + // Note: for Accept-Encoding, we don't currently explicitly handle "identity;q=0" and "*;q=0" + + if (compressor) + { + return std::move(compressor); + } + + // If we're here, we didn't match the caller's compressor above; + // try any that we saved off in order of highest to lowest rank + for (auto t = tokens.rbegin(); t != tokens.rend(); t++) + { + auto coding = encoding.substr(t->start, t->length); + + // N.B for TE, "trailers" will simply fail to instantiate a + // compressor; ditto for "*" and "identity" for Accept-Encoding + auto compressor = web::http::compression::builtin::_make_compressor(f, coding); + if (compressor) + { + return std::move(compressor); + } + if (type == header_types::accept_encoding && utility::details::str_iequal(coding, _XPLATSTR("identity"))) + { + // The client specified a preference for "no encoding" vs. anything else we might still have + return std::unique_ptr(); + } + } + + return std::unique_ptr(); +} + +std::unique_ptr get_decompressor_from_header( + const utility::string_t& encoding, + header_types type, + const std::vector>& factories) +{ + const std::vector>& f = + factories.empty() ? web::http::compression::builtin::g_decompress_factories : factories; + std::unique_ptr decompressor; + utility::string_t token; + size_t start; + size_t length; + size_t comma; + size_t n; + + _ASSERTE(type == header_types::transfer_encoding || type == header_types::content_encoding); + + n = 0; + while (n != utility::string_t::npos) + { + // Tokenize by commas first + comma = encoding.find(_XPLATSTR(","), n); + start = n; + if (comma == utility::string_t::npos) + { + length = encoding.size() - n; + n = utility::string_t::npos; + } + else + { + length = comma - n; + n = comma + 1; + } + + // Then remove leading and trailing whitespace + remove_surrounding_http_whitespace(encoding, start, length); + + if (!length) + { + throw http_exception(status_codes::BadRequest, "Empty field in header"); + } + + // Immediately try to instantiate a decompressor + token = encoding.substr(start, length); + auto d = web::http::compression::builtin::_make_decompressor(f, token); + if (d) + { + if (decompressor) + { + status_code code = status_codes::NotImplemented; + if (type == header_types::content_encoding) + { + code = status_codes::UnsupportedMediaType; + } + throw http_exception(code, "Multiple compression algorithms not supported for a single request"); + } + + // We found our decompressor; store it off while we process the rest of the header + decompressor = std::move(d); + } + else + { + if (n != utility::string_t::npos) + { + if (type == header_types::transfer_encoding && + utility::details::str_iequal(_XPLATSTR("chunked"), token)) + { + throw http_exception(status_codes::BadRequest, + "Chunked must come last in the Transfer-Encoding header"); + } + } + if (!decompressor && !f.empty() && (n != utility::string_t::npos || type == header_types::content_encoding)) + { + // The first encoding type did not match; throw an informative + // exception with an encoding-type-appropriate HTTP error code + status_code code = status_codes::NotImplemented; + if (type == header_types::content_encoding) + { + code = status_codes::UnsupportedMediaType; + } + throw http_exception(code, "Unsupported encoding type"); + } + } + } + + if (type == header_types::transfer_encoding && !utility::details::str_iequal(_XPLATSTR("chunked"), token)) + { + throw http_exception(status_codes::BadRequest, "Transfer-Encoding header missing chunked"); + } + + // Either the response is compressed and we have a decompressor that can handle it, or + // built-in compression is not enabled and we don't have an alternate set of decompressors + return std::move(decompressor); +} + +utility::string_t build_supported_header(header_types type, + const std::vector>& factories) +{ + const std::vector>& f = + factories.empty() ? web::http::compression::builtin::g_decompress_factories : factories; + utility::ostringstream_t os; + bool start; + + _ASSERTE(type == header_types::te || type == header_types::accept_encoding); + + // Add all specified algorithms and their weights to the header + start = true; + for (int i = 0; i < f.size(); i++) + { + auto factory = f[i].get(); + if (factory) + { + auto weight = factory->weight(); + + if (!start) + { + os << _XPLATSTR(", "); + } + os << factory->algorithm(); + if (weight <= 1000) + { + os << _XPLATSTR(";q=") << weight / 1000 << _XPLATSTR(".") << weight % 1000; + } + start = false; + } + } + + if (start && type == header_types::accept_encoding) + { + // Request that no encoding be applied + os << _XPLATSTR("identity;q=1, *;q=0"); + } + + return std::move(os.str()); +} +} // namespace details +} // namespace compression +} // namespace http +} // namespace web diff --git a/Release/src/http/common/http_helpers.cpp b/Release/src/http/common/http_helpers.cpp index 2c45e5961d..0d17c569eb 100644 --- a/Release/src/http/common/http_helpers.cpp +++ b/Release/src/http/common/http_helpers.cpp @@ -12,27 +12,6 @@ ****/ #include "stdafx.h" - -// CPPREST_EXCLUDE_COMPRESSION is set if we're on a platform that supports compression but we want to explicitly disable it. -// CPPREST_EXCLUDE_WEBSOCKETS is a flag that now essentially means "no external dependencies". TODO: Rename - -#if __APPLE__ -#include "TargetConditionals.h" -#if defined(TARGET_OS_MAC) -#if !defined(CPPREST_EXCLUDE_COMPRESSION) -#define CPPREST_HTTP_COMPRESSION -#endif // !defined(CPPREST_EXCLUDE_COMPRESSION) -#endif // defined(TARGET_OS_MAC) -#elif defined(_WIN32) && (!defined(WINAPI_FAMILY) || WINAPI_PARTITION_DESKTOP) -#if !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) -#define CPPREST_HTTP_COMPRESSION -#endif // !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) -#endif - -#if defined(CPPREST_HTTP_COMPRESSION) -#include -#endif - #include "internal_http_helpers.h" using namespace web; @@ -142,309 +121,5 @@ bool validate_method(const utility::string_t& method) return true; } -namespace compression -{ -#if defined(CPPREST_HTTP_COMPRESSION) - - class compression_base_impl - { - public: - compression_base_impl(compression_algorithm alg) : m_alg(alg), m_zLibState(Z_OK) - { - memset(&m_zLibStream, 0, sizeof(m_zLibStream)); - } - - size_t read_output(size_t input_offset, size_t available_input, size_t total_out_before, uint8_t* temp_buffer, data_buffer& output) - { - input_offset += (available_input - stream().avail_in); - auto out_length = stream().total_out - total_out_before; - output.insert(output.end(), temp_buffer, temp_buffer + out_length); - - return input_offset; - } - - bool is_complete() const - { - return state() == Z_STREAM_END; - } - - bool has_error() const - { - return !is_complete() && state() != Z_OK; - } - - int state() const - { - return m_zLibState; - } - - void set_state(int state) - { - m_zLibState = state; - } - - compression_algorithm algorithm() const - { - return m_alg; - } - - z_stream& stream() - { - return m_zLibStream; - } - - int to_zlib_alg(compression_algorithm alg) - { - return static_cast(alg); - } - - private: - const compression_algorithm m_alg; - - std::atomic m_zLibState{ Z_OK }; - z_stream m_zLibStream; - }; - - class stream_decompressor::stream_decompressor_impl : public compression_base_impl - { - public: - stream_decompressor_impl(compression_algorithm alg) : compression_base_impl(alg) - { - set_state(inflateInit2(&stream(), to_zlib_alg(alg))); - } - - ~stream_decompressor_impl() - { - inflateEnd(&stream()); - } - - data_buffer decompress(const uint8_t* input, size_t input_size) - { - if (input == nullptr || input_size == 0) - { - set_state(Z_BUF_ERROR); - return data_buffer(); - } - - // Need to guard against attempting to decompress when we're already finished or encountered an error! - if (is_complete() || has_error()) - { - set_state(Z_STREAM_ERROR); - return data_buffer(); - } - - const size_t BUFFER_SIZE = 1024; - unsigned char temp_buffer[BUFFER_SIZE]; - - data_buffer output; - output.reserve(input_size * 3); - - size_t input_offset{ 0 }; - - while (state() == Z_OK && input_offset < input_size) - { - auto total_out_before = stream().total_out; - - auto available_input = input_size - input_offset; - stream().next_in = const_cast(&input[input_offset]); - stream().avail_in = static_cast(available_input); - stream().next_out = temp_buffer; - stream().avail_out = BUFFER_SIZE; - - set_state(inflate(&stream(), Z_PARTIAL_FLUSH)); - - if (has_error()) - { - return data_buffer(); - } - - input_offset = read_output(input_offset, available_input, total_out_before, temp_buffer, output); - } - - return output; - } - }; - - class stream_compressor::stream_compressor_impl : public compression_base_impl - { - public: - stream_compressor_impl(compression_algorithm alg) : compression_base_impl(alg) - { - const int level = Z_DEFAULT_COMPRESSION; - if (alg == compression_algorithm::gzip) - { - set_state(deflateInit2(&stream(), level, Z_DEFLATED, to_zlib_alg(alg), MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY)); - } - else if (alg == compression_algorithm::deflate) - { - set_state(deflateInit(&stream(), level)); - } - } - - web::http::details::compression::data_buffer compress(const uint8_t* input, size_t input_size, bool finish) - { - if (input == nullptr || input_size == 0) - { - set_state(Z_BUF_ERROR); - return data_buffer(); - } - - if (state() != Z_OK) - { - set_state(Z_STREAM_ERROR); - return data_buffer(); - } - - data_buffer output; - output.reserve(input_size); - - const size_t BUFFER_SIZE = 1024; - uint8_t temp_buffer[BUFFER_SIZE]; - - size_t input_offset{ 0 }; - auto flush = Z_NO_FLUSH; - - while (flush == Z_NO_FLUSH) - { - auto total_out_before = stream().total_out; - auto available_input = input_size - input_offset; - - if (available_input == 0) - { - flush = finish ? Z_FINISH : Z_PARTIAL_FLUSH; - } - else - { - stream().avail_in = static_cast(available_input); - stream().next_in = const_cast(&input[input_offset]); - } - - do - { - stream().next_out = temp_buffer; - stream().avail_out = BUFFER_SIZE; - - set_state(deflate(&stream(), flush)); - - if (has_error()) - { - return data_buffer(); - } - - input_offset = read_output(input_offset, available_input, total_out_before, temp_buffer, output); - - } while (stream().avail_out == 0); - } - - return output; - } - - ~stream_compressor_impl() - { - deflateEnd(&stream()); - } - }; -#else // Stub impl for when compression is not supported - - class compression_base_impl - { - public: - bool has_error() const - { - return true; - } - }; - - class stream_compressor::stream_compressor_impl : public compression_base_impl - { - public: - stream_compressor_impl(compression_algorithm) {} - compression::data_buffer compress(const uint8_t* data, size_t size, bool) - { - return data_buffer(data, data + size); - } - }; - - class stream_decompressor::stream_decompressor_impl : public compression_base_impl - { - public: - stream_decompressor_impl(compression_algorithm) {} - compression::data_buffer decompress(const uint8_t* data, size_t size) - { - return data_buffer(data, data + size); - } - }; -#endif - - bool __cdecl stream_decompressor::is_supported() - { -#if !defined(CPPREST_HTTP_COMPRESSION) - return false; -#else - return true; -#endif - } - - stream_decompressor::stream_decompressor(compression_algorithm alg) - : m_pimpl(std::make_shared(alg)) - { - } - - compression::data_buffer stream_decompressor::decompress(const data_buffer& input) - { - if (input.empty()) - { - return data_buffer(); - } - - return m_pimpl->decompress(&input[0], input.size()); - } - - web::http::details::compression::data_buffer stream_decompressor::decompress(const uint8_t* input, size_t input_size) - { - return m_pimpl->decompress(input, input_size); - } - - bool stream_decompressor::has_error() const - { - return m_pimpl->has_error(); - } - - bool __cdecl stream_compressor::is_supported() - { -#if !defined(CPPREST_HTTP_COMPRESSION) - return false; -#else - return true; -#endif - } - - stream_compressor::stream_compressor(compression_algorithm alg) - : m_pimpl(std::make_shared(alg)) - { - - } - - compression::data_buffer stream_compressor::compress(const data_buffer& input, bool finish) - { - if (input.empty()) - { - return compression::data_buffer(); - } - - return m_pimpl->compress(&input[0], input.size(), finish); - } - - web::http::details::compression::data_buffer stream_compressor::compress(const uint8_t* input, size_t input_size, bool finish) - { - return m_pimpl->compress(input, input_size, finish); - } - - bool stream_compressor::has_error() const - { - return m_pimpl->has_error(); - } - -} // namespace compression } // namespace details }} // namespace web::http diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 8f218cb913..d17d09dcef 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -310,36 +310,95 @@ void http_msg_base::_prepare_to_receive_data() // or media (like file) that the user can read from... } -size_t http_msg_base::_get_content_length() +size_t http_msg_base::_get_stream_length() +{ + auto &stream = instream(); + + if (stream.can_seek()) + { + auto offset = stream.tell(); + auto end = stream.seek(0, std::ios_base::end); + stream.seek(offset); + return static_cast(end - offset); + } + + return std::numeric_limits::max(); +} + +size_t http_msg_base::_get_content_length(bool honor_compression) { // An invalid response_stream indicates that there is no body if ((bool)instream()) { - size_t content_length = 0; + size_t content_length; utility::string_t transfer_encoding; - bool has_cnt_length = headers().match(header_names::content_length, content_length); - bool has_xfr_encode = headers().match(header_names::transfer_encoding, transfer_encoding); + if (headers().match(header_names::transfer_encoding, transfer_encoding)) + { + // Transfer encoding is set; it trumps any content length that may or may not be present + if (honor_compression && m_compressor) + { + http::http_headers tmp; + + // Build a header for comparison with the existing one + tmp.add(header_names::transfer_encoding, m_compressor->algorithm()); + tmp.add(header_names::transfer_encoding, _XPLATSTR("chunked")); + + if (!utility::details::str_iequal(transfer_encoding, tmp[header_names::transfer_encoding])) + { + // Some external entity added this header, and it doesn't match our + // expectations; bail out, since the caller's intentions are not clear + throw http_exception("Transfer-Encoding header is internally managed when compressing"); + } + } - if (has_xfr_encode) + return std::numeric_limits::max(); + } + + if (honor_compression && m_compressor) { + // A compressor is set; this implies transfer encoding, since we don't know the compressed length + // up front for content encoding. We return the uncompressed length if we can figure it out. + headers().add(header_names::transfer_encoding, m_compressor->algorithm()); + headers().add(header_names::transfer_encoding, _XPLATSTR("chunked")); return std::numeric_limits::max(); } - if (has_cnt_length) + if (headers().match(header_names::content_length, content_length)) + { + // An explicit content length is set; trust it, since we + // may not be required to send the stream's entire contents + return content_length; + } + + content_length = _get_stream_length(); + if (content_length != std::numeric_limits::max()) { + // The content length wasn't explcitly set, but we figured it out; + // use it, since sending this way is more efficient than chunking + headers().add(header_names::content_length, content_length); return content_length; } - // Neither is set. Assume transfer-encoding for now (until we have the ability to determine - // the length of the stream). + // We don't know the content length; we'll chunk the stream headers().add(header_names::transfer_encoding, _XPLATSTR("chunked")); return std::numeric_limits::max(); } + // There is no content return 0; } +size_t http_msg_base::_get_content_length_and_set_compression() +{ + return _get_content_length(true); +} + +size_t http_msg_base::_get_content_length() +{ + return _get_content_length(false); +} + // Helper function to inline continuation if possible. struct inline_continuation { @@ -1041,6 +1100,11 @@ details::_http_request::_http_request(std::unique_ptrset_decompress_factories(compression::details::builtin::get_decompress_factories()); +} + const http_version http_versions::HTTP_0_9 = { 0, 9 }; const http_version http_versions::HTTP_1_0 = { 1, 0 }; const http_version http_versions::HTTP_1_1 = { 1, 1 }; diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 8da74d0083..3adb4fb882 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -85,7 +85,7 @@ static utility::string_t HttpServerAPIKnownHeaders[] = U("Proxy-Authorization"), U("Referer"), U("Range"), - U("Te"), + U("TE"), U("Translate"), U("User-Agent"), U("Request-Maximum"), @@ -539,6 +539,7 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD } else { + utility::string_t header; std::string badRequestMsg; try { @@ -557,6 +558,66 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD m_msg.set_method(parse_request_method(m_request)); parse_http_headers(m_request->Headers, m_msg.headers()); + // See if we need to compress or decompress the incoming request body, and if so, prepare for it + try + { + if (m_msg.headers().match(header_names::transfer_encoding, header)) + { + try + { + m_decompressor = http::compression::details::get_decompressor_from_header(header, http::compression::details::header_types::transfer_encoding); + } + catch (http_exception &e) + { + if (e.error_code().value() != status_codes::NotImplemented) + { + // Something is wrong with the header; we'll fail here + throw; + } + // We could not find a decompressor; we'll see if the user's handler adds one later + m_decompress_header_type = http::compression::details::header_types::transfer_encoding; + m_decompress_header = std::move(header); + } + } + else if (m_msg.headers().match(header_names::content_encoding, header)) + { + try + { + m_decompressor = http::compression::details::get_decompressor_from_header(header, http::compression::details::header_types::content_encoding); + } + catch (http_exception &e) + { + if (e.error_code().value() != status_codes::UnsupportedMediaType) + { + // Something is wrong with the header; we'll fail here + throw; + } + // We could not find a decompressor; we'll see if the user's handler adds one later + m_decompress_header_type = http::compression::details::header_types::content_encoding; + m_decompress_header = std::move(header); + } + } + else if (m_msg.headers().match(header_names::te, header)) + { + // Note that init_response_headers throws away m_msg, so we need to set our compressor here. If + // the header contains all unsupported algorithms, it's not an error -- we just won't compress + m_compressor = http::compression::details::get_compressor_from_header(header, http::compression::details::header_types::te); + } + else if (m_msg.headers().match(header_names::accept_encoding, header)) + { + // This would require pre-compression of the input stream, since we MUST send Content-Length, so we'll (legally) ignore it + //m_compressor = http::compression::details::get_compressor_from_header(header, http::compression::details::header_types:accept_encoding); + } + } + catch (http_exception &e) + { + if (badRequestMsg.empty()) + { + // Respond with a reasonable message + badRequestMsg = e.what(); + } + } + m_msg._get_impl()->_set_http_version({ (uint8_t)m_request->Version.MajorVersion, (uint8_t)m_request->Version.MinorVersion }); // Retrieve the remote IP address @@ -601,12 +662,24 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD void windows_request_context::read_request_body_chunk() { auto *pServer = static_cast(http_server_api::server_api()); + PVOID body; // The read_body_io_completion callback function m_overlapped.set_http_io_completion([this](DWORD error, DWORD nBytes){ read_body_io_completion(error, nBytes);}); auto request_body_buf = m_msg._get_impl()->outstream().streambuf(); - auto body = request_body_buf.alloc(CHUNK_SIZE); + if (!m_decompressor) + { + body = request_body_buf.alloc(CHUNK_SIZE); + } + else + { + if (m_compress_buffer.size() < CHUNK_SIZE) + { + m_compress_buffer.resize(CHUNK_SIZE); + } + body = m_compress_buffer.data(); + } // Once we allow users to set the output stream the following assert could fail. // At that time we would need compensation code that would allocate a buffer from the heap instead. @@ -626,7 +699,10 @@ void windows_request_context::read_request_body_chunk() { // There was no more data to read. CancelThreadpoolIo(pServer->m_threadpool_io); - request_body_buf.commit(0); + if (!m_decompressor) + { + request_body_buf.commit(0); + } if(error_code == ERROR_HANDLE_EOF) { m_msg._get_impl()->_complete(request_body_buf.in_avail()); @@ -647,17 +723,49 @@ void windows_request_context::read_body_io_completion(DWORD error_code, DWORD by if (error_code == NO_ERROR) { - request_body_buf.commit(bytes_read); + if (!m_decompressor) + { + request_body_buf.commit(bytes_read); + } + else + { + size_t got; + size_t used; + size_t total_used = 0; + + do + { + auto body = request_body_buf.alloc(CHUNK_SIZE); + try + { + got = m_decompressor->decompress(m_compress_buffer.data()+total_used, bytes_read-total_used, body, CHUNK_SIZE, http::compression::operation_hint::has_more, used, NULL); + } + catch (...) + { + request_body_buf.commit(0); + m_msg._get_impl()->_complete(0, std::current_exception()); + return; + } + request_body_buf.commit(got); + total_used += used; + } while (total_used != bytes_read); + } read_request_body_chunk(); } else if (error_code == ERROR_HANDLE_EOF) { - request_body_buf.commit(0); + if (!m_decompressor) + { + request_body_buf.commit(0); + } m_msg._get_impl()->_complete(request_body_buf.in_avail()); } else { - request_body_buf.commit(0); + if (!m_decompressor) + { + request_body_buf.commit(0); + } m_msg._get_impl()->_complete(0, std::make_exception_ptr(http_exception(error_code))); } } @@ -800,8 +908,53 @@ void windows_request_context::async_process_response() const std::string reason = utf16_to_utf8(m_response.reason_phrase()); win_api_response.pReason = reason.c_str(); win_api_response.ReasonLength = (USHORT)reason.size(); + size_t content_length; - size_t content_length = m_response._get_impl()->_get_content_length(); + if (m_compressor || m_response._get_impl()->compressor()) + { + if (m_response.headers().has(header_names::content_length)) + { + // Content-Length should not be sent with Transfer-Encoding + m_response.headers().remove(header_names::content_length); + } + if (!m_response._get_impl()->compressor()) + { + // Temporarily move the compressor to the reponse, so _get_content_length() will honor it + m_response._get_impl()->set_compressor(std::move(m_compressor)); + } // else one was already set from a callback, and we'll (blindly) use it + content_length = m_response._get_impl()->_get_content_length_and_set_compression(); + m_compressor = std::move(m_response._get_impl()->compressor()); + m_response._get_impl()->set_compressor(nullptr); + } + else + { + if (!m_decompress_header.empty()) + { + auto factories = m_response._get_impl()->decompress_factories(); + try + { + m_decompressor = http::compression::details::get_decompressor_from_header(m_decompress_header, m_decompress_header_type, factories); + m_decompress_header.clear(); + if (!m_decompressor) + { + http::status_code code = http::status_codes::NotImplemented; + if (m_decompress_header_type == http::compression::details::header_types::content_encoding) + { + code = status_codes::UnsupportedMediaType; + } + throw http_exception(code); + } + } + catch (http_exception &e) + { + // No matching decompressor was supplied via callback + CancelThreadpoolIo(pServer->m_threadpool_io); + cancel_request(std::make_exception_ptr(e)); + return; + } + } + content_length = m_response._get_impl()->_get_content_length(); + } m_headers = std::unique_ptr(new HTTP_UNKNOWN_HEADER[msl::safeint3::SafeInt(m_response.headers().size())]); m_headers_buffer.resize(msl::safeint3::SafeInt(m_response.headers().size()) * 2); @@ -822,8 +975,6 @@ void windows_request_context::async_process_response() // Send response callback function m_overlapped.set_http_io_completion([this](DWORD error, DWORD nBytes){ send_response_io_completion(error, nBytes);}); - m_remaining_to_write = content_length; - // Figure out how to send the entity body of the message. if (content_length == 0) { @@ -854,6 +1005,12 @@ void windows_request_context::async_process_response() _ASSERTE(content_length > 0); m_sending_in_chunks = (content_length != std::numeric_limits::max()); m_transfer_encoding = (content_length == std::numeric_limits::max()); + m_remaining_to_write = content_length; + if (content_length == std::numeric_limits::max()) + { + // Attempt to figure out the remaining length of the input stream + m_remaining_to_write = m_response._get_impl()->_get_stream_length(); + } StartThreadpoolIo(pServer->m_threadpool_io); const unsigned long error_code = HttpSendHttpResponse( @@ -901,11 +1058,12 @@ void windows_request_context::transmit_body() return; } + msl::safeint3::SafeInt safeCount = m_remaining_to_write; + size_t next_chunk_size = safeCount.Min(CHUNK_SIZE); + // In both cases here we could perform optimizations to try and use acquire on the streams to avoid an extra copy. if ( m_sending_in_chunks ) { - msl::safeint3::SafeInt safeCount = m_remaining_to_write; - size_t next_chunk_size = safeCount.Min(CHUNK_SIZE); m_body_data.resize(CHUNK_SIZE); streams::rawptr_buffer buf(&m_body_data[0], next_chunk_size); @@ -937,33 +1095,109 @@ void windows_request_context::transmit_body() else { // We're transfer-encoding... - const size_t body_data_length = CHUNK_SIZE+http::details::chunked_encoding::additional_encoding_space; - m_body_data.resize(body_data_length); - - streams::rawptr_buffer buf(&m_body_data[http::details::chunked_encoding::data_offset], body_data_length); - - m_response.body().read(buf, CHUNK_SIZE).then([this, body_data_length](pplx::task op) + if (m_compressor) { - size_t bytes_read = 0; + // ...and compressing. For simplicity, we allocate a buffer that's "too large to fail" while compressing. + const size_t body_data_length = 2*CHUNK_SIZE + http::details::chunked_encoding::additional_encoding_space; + m_body_data.resize(body_data_length); - // If an exception occurs surface the error to user on the server side - // and cancel the request so the client sees the error. - try - { - bytes_read = op.get(); - } catch (...) + // We'll read into a temporary buffer before compressing + if (m_compress_buffer.capacity() < next_chunk_size) { - cancel_request(std::current_exception()); - return; + m_compress_buffer.reserve(next_chunk_size); } - // Check whether this is the last one to send... - m_transfer_encoding = (bytes_read > 0); - size_t offset = http::details::chunked_encoding::add_chunked_delimiters(&m_body_data[0], body_data_length, bytes_read); + streams::rawptr_buffer buf(m_compress_buffer.data(), next_chunk_size); - auto data_length = bytes_read + (http::details::chunked_encoding::additional_encoding_space-offset); - send_entity_body(&m_body_data[offset], data_length); - }); + m_response.body().read(buf, next_chunk_size).then([this, body_data_length](pplx::task op) + { + size_t bytes_read = 0; + + // If an exception occurs surface the error to user on the server side + // and cancel the request so the client sees the error. + try + { + bytes_read = op.get(); + } + catch (...) + { + cancel_request(std::current_exception()); + return; + } + _ASSERTE(bytes_read >= 0); + + // Compress this chunk; if we read no data, allow the compressor to finalize its stream + http::compression::operation_hint hint = http::compression::operation_hint::has_more; + if (!bytes_read) + { + hint = http::compression::operation_hint::is_last; + } + m_compressor->compress(m_compress_buffer.data(), bytes_read, &m_body_data[http::details::chunked_encoding::data_offset], body_data_length, hint) + .then([this, bytes_read, body_data_length](pplx::task op) + { + http::compression::operation_result r; + + try + { + r = op.get(); + } + catch (...) + { + cancel_request(std::current_exception()); + return; + } + + if (r.input_bytes_processed != bytes_read || + r.output_bytes_produced == body_data_length - http::details::chunked_encoding::additional_encoding_space || + r.done != !bytes_read) + { + // We chose our parameters so that compression should + // never overflow body_data_length; fail if it does + cancel_request(std::make_exception_ptr(std::exception("Compressed data exceeds internal buffer size."))); + return; + } + + // Check whether this is the last one to send; note that this is a + // few lines of near-duplicate code with the non-compression path + _ASSERTE(bytes_read <= m_remaining_to_write); + m_remaining_to_write -= bytes_read; + m_transfer_encoding = (r.output_bytes_produced > 0); + size_t offset = http::details::chunked_encoding::add_chunked_delimiters(&m_body_data[0], body_data_length, r.output_bytes_produced); + send_entity_body(&m_body_data[offset], r.output_bytes_produced + http::details::chunked_encoding::additional_encoding_space - offset); + }); + }); + } + else + { + const size_t body_data_length = CHUNK_SIZE + http::details::chunked_encoding::additional_encoding_space; + m_body_data.resize(body_data_length); + + streams::rawptr_buffer buf(&m_body_data[http::details::chunked_encoding::data_offset], body_data_length); + + m_response.body().read(buf, next_chunk_size).then([this, body_data_length](pplx::task op) + { + size_t bytes_read = 0; + + // If an exception occurs surface the error to user on the server side + // and cancel the request so the client sees the error. + try + { + bytes_read = op.get(); + } + catch (...) + { + cancel_request(std::current_exception()); + return; + } + + // Check whether this is the last one to send... + m_transfer_encoding = (bytes_read > 0); + size_t offset = http::details::chunked_encoding::add_chunked_delimiters(&m_body_data[0], body_data_length, bytes_read); + + auto data_length = bytes_read + (http::details::chunked_encoding::additional_encoding_space - offset); + send_entity_body(&m_body_data[offset], data_length); + }); + } } } diff --git a/Release/src/http/listener/http_server_httpsys.h b/Release/src/http/listener/http_server_httpsys.h index 2523d62e4e..5a8cbd137b 100644 --- a/Release/src/http/listener/http_server_httpsys.h +++ b/Release/src/http/listener/http_server_httpsys.h @@ -143,6 +143,13 @@ struct windows_request_context : http::details::_http_server_context http_response m_response; std::exception_ptr m_except_ptr; + + std::vector m_compress_buffer; + std::unique_ptr m_compressor; + std::unique_ptr m_decompressor; + utility::string_t m_decompress_header; + http::compression::details::header_types m_decompress_header_type; + private: windows_request_context(const windows_request_context &); windows_request_context& operator=(const windows_request_context &); diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 60804e1742..17cf4eff81 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCES status_code_reason_phrase_tests.cpp to_string_tests.cpp http_client_fuzz_tests.cpp + compression_tests.cpp stdafx.cpp ) diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp new file mode 100644 index 0000000000..2a49f2263f --- /dev/null +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -0,0 +1,1401 @@ +/*** + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * compression_tests.cpp + * + * Tests cases, including client/server, for the web::http::compression namespace. + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ + +#include "cpprest/details/http_helpers.h" +#include "cpprest/version.h" +#include "stdafx.h" +#include + +#ifndef __cplusplus_winrt +#include "cpprest/http_listener.h" +#endif + +using namespace web; +using namespace utility; +using namespace web::http; +using namespace web::http::client; + +using namespace tests::functional::http::utilities; + +namespace tests +{ +namespace functional +{ +namespace http +{ +namespace client +{ +SUITE(compression_tests) +{ + // A fake "pass-through" compressor/decompressor for testing + class fake_provider : public web::http::compression::compress_provider, + public web::http::compression::decompress_provider + { + public: + static const utility::string_t FAKE; + + fake_provider(size_t size = static_cast(-1)) : _size(size), _so_far(0), _done(false) {} + + virtual const utility::string_t& algorithm() const { return FAKE; } + + virtual size_t decompress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + web::http::compression::operation_hint hint, + size_t& input_bytes_processed, + bool* done) + { + size_t bytes; + + if (_done) + { + input_bytes_processed = 0; + if (*done) + { + *done = true; + } + return 0; + } + if (_size == static_cast(-1) || input_size > _size - _so_far) + { + std::stringstream ss; + ss << "Fake decompress - invalid data " << input_size << ", " << output_size << " with " << _so_far + << " / " << _size; + throw std::runtime_error(std::move(ss.str())); + } + bytes = std::min(input_size, output_size); + if (bytes) + { + memcpy(output, input, bytes); + } + _so_far += bytes; + _done = (_so_far == _size); + if (done) + { + *done = _done; + } + input_bytes_processed = bytes; + return input_bytes_processed; + } + + virtual pplx::task decompress( + const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + web::http::compression::operation_hint hint) + { + web::http::compression::operation_result r; + + try + { + r.output_bytes_produced = + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + } + catch (...) + { + pplx::task_completion_event ev; + ev.set_exception(std::current_exception()); + return pplx::create_task(ev); + } + + return pplx::task_from_result(r); + } + + virtual size_t compress(const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + web::http::compression::operation_hint hint, + size_t& input_bytes_processed, + bool* done) + { + size_t bytes; + + if (_done) + { + input_bytes_processed = 0; + if (*done) + { + *done = true; + } + return 0; + } + if (_size == static_cast(-1) || input_size > _size - _so_far) + { + std::stringstream ss; + ss << "Fake compress - invalid data " << input_size << ", " << output_size << " with " << _so_far + << " / " << _size; + throw std::runtime_error(std::move(ss.str())); + } + bytes = std::min(input_size, output_size); + if (bytes) + { + memcpy(output, input, bytes); + } + _so_far += bytes; + _done = (hint == web::http::compression::operation_hint::is_last && _so_far == _size); + if (done) + { + *done = _done; + } + input_bytes_processed = bytes; + return input_bytes_processed; + } + + virtual pplx::task compress( + const uint8_t* input, + size_t input_size, + uint8_t* output, + size_t output_size, + web::http::compression::operation_hint hint) + { + web::http::compression::operation_result r; + + try + { + r.output_bytes_produced = + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + } + catch (...) + { + pplx::task_completion_event ev; + ev.set_exception(std::current_exception()); + return pplx::create_task(ev); + } + + return pplx::task_from_result(r); + } + + virtual void reset() + { + _done = false; + _so_far = 0; + } + + private: + size_t _size; + size_t _so_far; + bool _done; + }; + + const utility::string_t fake_provider::FAKE = _XPLATSTR("fake"); + + void compress_and_decompress( + const utility::string_t& algorithm, const size_t buffer_size, const size_t chunk_size, bool compressible) + { + std::unique_ptr compressor; + std::unique_ptr decompressor; + std::vector input_buffer; + std::vector cmp_buffer; + std::vector dcmp_buffer; + web::http::compression::operation_result r; + std::vector chunk_sizes; + Concurrency::task_group_status result; + size_t csize; + size_t dsize; + size_t i; + size_t nn; + + if (algorithm == fake_provider::FAKE) + { + compressor = std::make_unique(buffer_size); + decompressor = std::make_unique(buffer_size); + } + else + { + compressor = web::http::compression::builtin::make_compressor(algorithm); + decompressor = web::http::compression::builtin::make_decompressor(algorithm); + } + VERIFY_IS_TRUE((bool)compressor); + VERIFY_IS_TRUE((bool)decompressor); + + input_buffer.reserve(buffer_size); + for (size_t i = 0; i < buffer_size; ++i) + { + if (compressible) + { + input_buffer.push_back(static_cast('a' + i % 26)); + } + else + { + input_buffer.push_back(static_cast(std::rand())); + } + } + + // compress in chunks + csize = 0; + cmp_buffer.resize(buffer_size); // pessimistic (or not, for non-compressible data) + for (i = 0; i < buffer_size; i += chunk_size) + { + result = compressor + ->compress(input_buffer.data() + i, + std::min(chunk_size, buffer_size - i), + cmp_buffer.data() + csize, + std::min(chunk_size, buffer_size - csize), + web::http::compression::operation_hint::has_more) + .then([&r](web::http::compression::operation_result x) { r = x; }) + .wait(); + VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(r.input_bytes_processed, std::min(chunk_size, buffer_size - i)); + VERIFY_ARE_EQUAL(r.done, false); + chunk_sizes.push_back(r.output_bytes_produced); + csize += r.output_bytes_produced; + } + if (i >= buffer_size) + { + size_t cmpsize = buffer_size; + do + { + if (csize == cmpsize) + { + // extend the output buffer if there may be more compressed bytes to retrieve + cmpsize += std::min(chunk_size, (size_t)200); + cmp_buffer.resize(cmpsize); + } + result = compressor + ->compress(NULL, + 0, + cmp_buffer.data() + csize, + std::min(chunk_size, cmpsize - csize), + web::http::compression::operation_hint::is_last) + .then([&r](web::http::compression::operation_result x) { r = x; }) + .wait(); + VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); + chunk_sizes.push_back(r.output_bytes_produced); + csize += r.output_bytes_produced; + } while (csize == cmpsize); + VERIFY_ARE_EQUAL(r.done, true); + + // once more with no input, to assure no error and done + result = compressor->compress(NULL, 0, NULL, 0, web::http::compression::operation_hint::is_last) + .then([&r](web::http::compression::operation_result x) { r = x; }) + .wait(); + VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); + VERIFY_ARE_EQUAL(r.output_bytes_produced, 0); + VERIFY_ARE_EQUAL(r.done, true); + } + cmp_buffer.resize(csize); // actual + + // decompress in as-compressed chunks + nn = 0; + dsize = 0; + dcmp_buffer.resize(buffer_size); + for (std::vector::iterator it = chunk_sizes.begin(); it != chunk_sizes.end(); ++it) + { + if (*it) + { + auto hint = web::http::compression::operation_hint::has_more; + if (it == chunk_sizes.begin()) + { + hint = web::http::compression::operation_hint::is_last; + } + result = decompressor + ->decompress(cmp_buffer.data() + nn, + *it, + dcmp_buffer.data() + dsize, + std::min(chunk_size, buffer_size - dsize), + hint) + .then([&r](web::http::compression::operation_result x) { r = x; }) + .wait(); + VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + nn += *it; + dsize += r.output_bytes_produced; + } + } + VERIFY_ARE_EQUAL(csize, nn); + VERIFY_ARE_EQUAL(dsize, buffer_size); + VERIFY_ARE_EQUAL(input_buffer, dcmp_buffer); + VERIFY_IS_TRUE(r.done); + + // decompress again in fixed-size chunks + nn = 0; + dsize = 0; + decompressor->reset(); + memset(dcmp_buffer.data(), 0, dcmp_buffer.size()); + do + { + size_t n = std::min(chunk_size, csize - nn); + do + { + result = decompressor + ->decompress(cmp_buffer.data() + nn, + n, + dcmp_buffer.data() + dsize, + std::min(chunk_size, buffer_size - dsize), + web::http::compression::operation_hint::has_more) + .then([&r](web::http::compression::operation_result x) { r = x; }) + .wait(); + VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + dsize += r.output_bytes_produced; + nn += r.input_bytes_processed; + n -= r.input_bytes_processed; + } while (n); + } while (nn < csize || !r.done); + VERIFY_ARE_EQUAL(csize, nn); + VERIFY_ARE_EQUAL(dsize, buffer_size); + VERIFY_ARE_EQUAL(input_buffer, dcmp_buffer); + VERIFY_IS_TRUE(r.done); + + // once more with no input, to assure no error and done + result = decompressor->decompress(NULL, 0, NULL, 0, web::http::compression::operation_hint::has_more) + .then([&r](web::http::compression::operation_result x) { r = x; }) + .wait(); + VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); + VERIFY_ARE_EQUAL(r.output_bytes_produced, 0); + VERIFY_IS_TRUE(r.done); + + // decompress all at once + decompressor->reset(); + memset(dcmp_buffer.data(), 0, dcmp_buffer.size()); + result = decompressor + ->decompress(cmp_buffer.data(), + csize, + dcmp_buffer.data(), + dcmp_buffer.size(), + web::http::compression::operation_hint::is_last) + .then([&r](web::http::compression::operation_result x) { r = x; }) + .wait(); + VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(r.output_bytes_produced, buffer_size); + VERIFY_ARE_EQUAL(input_buffer, dcmp_buffer); + + if (algorithm != fake_provider::FAKE) + { + // invalid decompress buffer, first and subsequent tries + cmp_buffer[0] = ~cmp_buffer[1]; + decompressor->reset(); + for (i = 0; i < 2; i++) + { + nn = 0; + try + { + result = decompressor + ->decompress(cmp_buffer.data(), + csize, + dcmp_buffer.data(), + dcmp_buffer.size(), + web::http::compression::operation_hint::is_last) + .then([&nn](web::http::compression::operation_result x) { nn++; }) + .wait(); + nn++; + } + catch (std::runtime_error) + { + } + VERIFY_ARE_EQUAL(nn, 0); + } + } + } + + void compress_test(const utility::string_t& algorithm) + { + size_t tuples[][2] = {{7999, 8192}, + {8192, 8192}, + {16001, 8192}, + {16384, 8192}, + {140000, 65536}, + {256 * 1024, 65536}, + {256 * 1024, 256 * 1024}, + {263456, 256 * 1024}}; + + for (int i = 0; i < sizeof(tuples) / sizeof(tuples[0]); i++) + { + for (int j = 0; j < 2; j++) + { + compress_and_decompress(algorithm, tuples[i][0], tuples[i][1], !!j); + } + } + } + + TEST_FIXTURE(uri_address, compress_and_decompress) + { + compress_test(fake_provider::FAKE); + if (web::http::compression::builtin::algorithm::supported(web::http::compression::builtin::algorithm::GZIP)) + { + compress_test(web::http::compression::builtin::algorithm::GZIP); + } + if (web::http::compression::builtin::algorithm::supported(web::http::compression::builtin::algorithm::DEFLATE)) + { + compress_test(web::http::compression::builtin::algorithm::DEFLATE); + } + if (web::http::compression::builtin::algorithm::supported(web::http::compression::builtin::algorithm::BROTLI)) + { + compress_test(web::http::compression::builtin::algorithm::BROTLI); + } + } + + TEST_FIXTURE(uri_address, compress_headers) + { + const utility::string_t _NONE = _XPLATSTR("none"); + + std::unique_ptr c; + std::unique_ptr d; + + std::shared_ptr fcf = web::http::compression::make_compress_factory( + fake_provider::FAKE, []() -> std::unique_ptr { + return std::make_unique(); + }); + std::vector> fcv; + fcv.push_back(fcf); + std::shared_ptr fdf = + web::http::compression::make_decompress_factory( + fake_provider::FAKE, 800, []() -> std::unique_ptr { + return std::make_unique(); + }); + std::vector> fdv; + fdv.push_back(fdf); + + std::shared_ptr ncf = web::http::compression::make_compress_factory( + _NONE, []() -> std::unique_ptr { + return std::make_unique(); + }); + std::vector> ncv; + ncv.push_back(ncf); + std::shared_ptr ndf = + web::http::compression::make_decompress_factory( + _NONE, 800, []() -> std::unique_ptr { + return std::make_unique(); + }); + std::vector> ndv; + ndv.push_back(ndf); + + // Supported algorithms + VERIFY_ARE_EQUAL( + web::http::compression::builtin::supported(), + web::http::compression::builtin::algorithm::supported(web::http::compression::builtin::algorithm::GZIP)); + VERIFY_ARE_EQUAL( + web::http::compression::builtin::supported(), + web::http::compression::builtin::algorithm::supported(web::http::compression::builtin::algorithm::DEFLATE)); + if (web::http::compression::builtin::algorithm::supported(web::http::compression::builtin::algorithm::BROTLI)) + { + VERIFY_IS_TRUE(web::http::compression::builtin::supported()); + } + VERIFY_IS_FALSE(web::http::compression::builtin::algorithm::supported(_XPLATSTR(""))); + VERIFY_IS_FALSE(web::http::compression::builtin::algorithm::supported(_XPLATSTR("foo"))); + + // Strings that double as both Transfer-Encoding and TE + std::vector encodings = {_XPLATSTR("gzip"), + _XPLATSTR("gZip "), + _XPLATSTR(" GZIP"), + _XPLATSTR(" gzip "), + _XPLATSTR(" gzip , chunked "), + _XPLATSTR(" gZip , chunked "), + _XPLATSTR("GZIP,chunked")}; + + // Similar, but geared to match a non-built-in algorithm + std::vector fake = {_XPLATSTR("fake"), + _XPLATSTR("faKe "), + _XPLATSTR(" FAKE"), + _XPLATSTR(" fake "), + _XPLATSTR(" fake , chunked "), + _XPLATSTR(" faKe , chunked "), + _XPLATSTR("FAKE,chunked")}; + + std::vector invalid = {_XPLATSTR(","), + _XPLATSTR(",gzip"), + _XPLATSTR("gzip,"), + _XPLATSTR(",gzip, chunked"), + _XPLATSTR(" ,gzip, chunked"), + _XPLATSTR("gzip, chunked,"), + _XPLATSTR("gzip, chunked, "), + _XPLATSTR("gzip,, chunked"), + _XPLATSTR("gzip , , chunked"), + _XPLATSTR("foo")}; + + std::vector invalid_tes = { + _XPLATSTR("deflate;q=0.5, gzip;q=2"), + _XPLATSTR("deflate;q=1.5, gzip;q=1"), + }; + + std::vector empty = {_XPLATSTR(""), _XPLATSTR(" ")}; + + // Repeat for Transfer-Encoding (which also covers part of TE) and Content-Encoding (which also covers all of + // Accept-Encoding) + for (int transfer = 0; transfer < 2; transfer++) + { + web::http::compression::details::header_types ctype = + transfer ? web::http::compression::details::header_types::te + : web::http::compression::details::header_types::accept_encoding; + web::http::compression::details::header_types dtype = + transfer ? web::http::compression::details::header_types::transfer_encoding + : web::http::compression::details::header_types::content_encoding; + + // No compression - Transfer-Encoding + d = web::http::compression::details::get_decompressor_from_header( + _XPLATSTR(" chunked "), web::http::compression::details::header_types::transfer_encoding); + VERIFY_IS_FALSE((bool)d); + + for (auto encoding = encodings.begin(); encoding != encodings.end(); encoding++) + { + bool has_comma = false; + + has_comma = encoding->find(_XPLATSTR(",")) != utility::string_t::npos; + + // Built-in only + c = web::http::compression::details::get_compressor_from_header(*encoding, ctype); + VERIFY_ARE_EQUAL((bool)c, web::http::compression::builtin::supported()); + if (c) + { + VERIFY_ARE_EQUAL(c->algorithm(), web::http::compression::builtin::algorithm::GZIP); + } + + try + { + d = web::http::compression::details::get_decompressor_from_header(*encoding, dtype); + VERIFY_ARE_EQUAL((bool)d, web::http::compression::builtin::supported()); + if (d) + { + VERIFY_ARE_EQUAL(d->algorithm(), web::http::compression::builtin::algorithm::GZIP); + } + } + catch (http_exception) + { + VERIFY_IS_TRUE(transfer == !has_comma); + } + } + + for (auto encoding = fake.begin(); encoding != fake.end(); encoding++) + { + bool has_comma = false; + + has_comma = encoding->find(_XPLATSTR(",")) != utility::string_t::npos; + + // Supplied compressor/decompressor + c = web::http::compression::details::get_compressor_from_header(*encoding, ctype, fcv); + VERIFY_IS_TRUE((bool)c); + VERIFY_IS_TRUE(c->algorithm() == fcf->algorithm()); + + try + { + d = web::http::compression::details::get_decompressor_from_header(*encoding, dtype, fdv); + VERIFY_IS_TRUE((bool)d); + VERIFY_IS_TRUE(d->algorithm() == fdf->algorithm()); + } + catch (http_exception) + { + VERIFY_IS_TRUE(transfer == !has_comma); + } + + // No matching compressor + c = web::http::compression::details::get_compressor_from_header(*encoding, ctype, ncv); + VERIFY_IS_FALSE((bool)c); + + try + { + d = web::http::compression::details::get_decompressor_from_header(*encoding, dtype, ndv); + VERIFY_IS_FALSE(true); + } + catch (http_exception) + { + } + } + + // Negative tests - invalid headers, no matching algorithm, etc. + for (auto encoding = invalid.begin(); encoding != invalid.end(); encoding++) + { + try + { + c = web::http::compression::details::get_compressor_from_header(*encoding, ctype); + VERIFY_IS_TRUE(encoding->find(_XPLATSTR(",")) == utility::string_t::npos); + VERIFY_IS_FALSE((bool)c); + } + catch (http_exception) + { + } + + try + { + d = web::http::compression::details::get_decompressor_from_header(*encoding, dtype); + VERIFY_IS_TRUE(!web::http::compression::builtin::supported() && + encoding->find(_XPLATSTR(",")) == utility::string_t::npos); + VERIFY_IS_FALSE((bool)d); + } + catch (http_exception) + { + } + } + + // Negative tests - empty headers + for (auto encoding = empty.begin(); encoding != empty.end(); encoding++) + { + c = web::http::compression::details::get_compressor_from_header(*encoding, ctype); + VERIFY_IS_FALSE((bool)c); + + try + { + d = web::http::compression::details::get_decompressor_from_header(*encoding, dtype); + VERIFY_IS_FALSE(true); + } + catch (http_exception) + { + } + } + + // Negative tests - invalid rankings + for (auto te = invalid_tes.begin(); te != invalid_tes.end(); te++) + { + try + { + c = web::http::compression::details::get_compressor_from_header(*te, ctype); + VERIFY_IS_FALSE(true); + } + catch (http_exception) + { + } + } + + utility::string_t builtin; + std::vector> dv; + + // Builtins + builtin = web::http::compression::details::build_supported_header(ctype); + if (transfer) + { + VERIFY_ARE_EQUAL(!builtin.empty(), web::http::compression::builtin::supported()); + } + else + { + VERIFY_IS_FALSE(builtin.empty()); + } + + // Null decompressor - effectively forces no compression algorithms + dv.push_back(std::shared_ptr()); + builtin = web::http::compression::details::build_supported_header(ctype, dv); + VERIFY_ARE_EQUAL((bool)transfer, builtin.empty()); + dv.pop_back(); + + if (web::http::compression::builtin::supported()) + { + dv.push_back(web::http::compression::builtin::get_decompress_factory( + web::http::compression::builtin::algorithm::GZIP)); + builtin = web::http::compression::details::build_supported_header(ctype, dv); // --> "gzip;q=1.0" + VERIFY_IS_FALSE(builtin.empty()); + } + else + { + builtin = _XPLATSTR("gzip;q=1.0"); + } + + // TE- and/or Accept-Encoding-specific test cases, regenerated for each pass + std::vector tes = { + builtin, + _XPLATSTR(" deflate;q=0.777 ,foo;q=0,gzip;q=0.9, bar;q=1.0, xxx;q=1 "), + _XPLATSTR("gzip ; q=1, deflate;q=0.5"), + _XPLATSTR("gzip;q=1.0, deflate;q=0.5"), + _XPLATSTR("deflate;q=0.5, gzip;q=1"), + _XPLATSTR("gzip,deflate;q=0.7"), + _XPLATSTR("trailers,gzip,deflate;q=0.7")}; + + for (int fake = 0; fake < 2; fake++) + { + if (fake) + { + // Switch built-in vs. supplied results the second time around + for (int i = 0; i < tes.size(); i++) + { + tes[i].replace(tes[i].find(web::http::compression::builtin::algorithm::GZIP), + web::http::compression::builtin::algorithm::GZIP.size(), + fake_provider::FAKE); + if (tes[i].find(web::http::compression::builtin::algorithm::DEFLATE) != utility::string_t::npos) + { + tes[i].replace(tes[i].find(web::http::compression::builtin::algorithm::DEFLATE), + web::http::compression::builtin::algorithm::DEFLATE.size(), + _NONE); + } + } + } + + for (auto te = tes.begin(); te != tes.end(); te++) + { + // Built-in only + c = web::http::compression::details::get_compressor_from_header(*te, ctype); + if (c) + { + VERIFY_IS_TRUE(web::http::compression::builtin::supported()); + VERIFY_IS_FALSE((bool)fake); + VERIFY_ARE_EQUAL(c->algorithm(), web::http::compression::builtin::algorithm::GZIP); + } + else + { + VERIFY_IS_TRUE((bool)fake || !web::http::compression::builtin::supported()); + } + + // Supplied compressor - both matching and non-matching + c = web::http::compression::details::get_compressor_from_header(*te, ctype, fcv); + VERIFY_ARE_EQUAL((bool)c, (bool)fake); + if (c) + { + VERIFY_ARE_EQUAL(c->algorithm(), fake_provider::FAKE); + } + } + } + } + } + + template + class my_rawptr_buffer : public concurrency::streams::rawptr_buffer<_CharType> + { + public: + my_rawptr_buffer(const _CharType* data, size_t size) + : concurrency::streams::rawptr_buffer<_CharType>(data, size) + { + } + + // No acquire(), to force non-acquire compression client codepaths + virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count) + { + ptr; + count; + return false; + } + + virtual void release(_Out_writes_(count) _CharType* ptr, _In_ size_t count) + { + ptr; + count; + } + + static concurrency::streams::basic_istream<_CharType> open_istream(const _CharType* data, size_t size) + { + return concurrency::streams::basic_istream<_CharType>( + concurrency::streams::streambuf<_CharType>(std::make_shared>(data, size))); + } + }; + + TEST_FIXTURE(uri_address, compress_client_server) + { + bool processed; + bool skip_transfer_put = false; + int transfer; + + size_t buffer_sizes[] = {0, 1, 3, 4, 4096, 65536, 100000, 157890}; + + std::vector> dfactories; + std::vector> cfactories; + +#if defined(_WIN32) && !defined(CPPREST_FORCE_HTTP_CLIENT_ASIO) + // Run a quick test to see if we're dealing with older/broken winhttp for compressed transfer encoding + { + test_http_server* p_server = nullptr; + std::unique_ptr scoped = + std::move(std::make_unique(m_uri)); + scoped->server()->next_request().then([&skip_transfer_put](pplx::task op) { + try + { + op.get()->reply(static_cast(status_codes::OK)); + } + catch (std::runtime_error) + { + // The test server throws if it's destructed with outstanding tasks, + // which will happen if winhttp responds 501 without informing us + VERIFY_IS_TRUE(skip_transfer_put); + } + }); + + http_client client(m_uri); + http_request msg(methods::PUT); + msg.set_compressor(std::make_unique(0)); + msg.set_body(concurrency::streams::rawptr_stream::open_istream((const uint8_t*)nullptr, 0)); + http_response rsp = client.request(msg).get(); + rsp.content_ready().wait(); + if (rsp.status_code() == status_codes::NotImplemented) + { + skip_transfer_put = true; + } + else + { + VERIFY_IS_TRUE(rsp.status_code() == status_codes::OK); + } + } +#endif // _WIN32 + + // Test decompression both explicitly through the test server and implicitly through the listener; + // this is the top-level loop in order to avoid thrashing the listeners more than necessary + for (int real = 0; real < 2; real++) + { + web::http::experimental::listener::http_listener listener; + std::unique_ptr scoped; + test_http_server* p_server = nullptr; + std::vector v; + size_t buffer_size; + + // Start the listener, and configure callbacks if necessary + if (real) + { + listener = std::move(web::http::experimental::listener::http_listener(m_uri)); + listener.open().wait(); + listener.support(methods::PUT, [&v, &dfactories, &processed](http_request request) { + utility::string_t encoding; + http_response rsp; + + if (request.headers().match(web::http::header_names::transfer_encoding, encoding) || + request.headers().match(web::http::header_names::content_encoding, encoding)) + { + if (encoding.find(fake_provider::FAKE) != utility::string_t::npos) + { + // This one won't be found by the server in the default set... + rsp._get_impl()->set_decompress_factories(dfactories); + } + } + processed = true; + rsp.set_status_code(status_codes::OK); + request.reply(rsp); + }); + listener.support( + methods::GET, [&v, &buffer_size, &cfactories, &processed, &transfer](http_request request) { + utility::string_t encoding; + http_response rsp; + bool done; + + if (transfer) + { +#if defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(CPPREST_FORCE_HTTP_CLIENT_ASIO) + // Compression happens in the listener itself + done = request.headers().match(web::http::header_names::te, encoding); + VERIFY_IS_TRUE(done); + if (encoding.find(fake_provider::FAKE) != utility::string_t::npos) + { + // This one won't be found in the server's default set... + rsp._get_impl()->set_compressor(std::make_unique(buffer_size)); + } +#endif // _WIN32 + rsp.set_body( + concurrency::streams::rawptr_stream::open_istream(v.data(), v.size())); + } + else + { + std::unique_ptr c; + std::vector pre; + size_t used; + + done = request.headers().match(web::http::header_names::accept_encoding, encoding); + VERIFY_IS_TRUE(done); + pre.resize(v.size() + 128); + c = web::http::compression::details::get_compressor_from_header( + encoding, web::http::compression::details::header_types::accept_encoding, cfactories); + VERIFY_IS_TRUE((bool)c); + auto got = c->compress(v.data(), + v.size(), + pre.data(), + pre.size(), + web::http::compression::operation_hint::is_last, + used, + &done); + VERIFY_IS_TRUE(used == v.size()); + VERIFY_IS_TRUE(done); + + // Add a single pre-compressed stream, since Content-Encoding requires Content-Length + pre.resize(got); + rsp.headers().add(header_names::content_encoding, c->algorithm()); + rsp.set_body( + concurrency::streams::container_stream>::open_istream(pre)); + } + processed = true; + rsp.set_status_code(status_codes::OK); + request.reply(rsp); + }); + } + else + { + scoped = std::move(std::make_unique(m_uri)); + p_server = scoped->server(); + } + + // Test various buffer sizes + for (int sz = 0; sz < sizeof(buffer_sizes) / sizeof(buffer_sizes[0]); sz++) + { + std::vector algs; + std::map> dmap; + + buffer_size = buffer_sizes[sz]; + + dfactories.clear(); + cfactories.clear(); + + // Re-build the sets of compress and decompress factories, to account for the buffer size in our "fake" + // ones + if (web::http::compression::builtin::algorithm::supported( + web::http::compression::builtin::algorithm::GZIP)) + { + algs.push_back(web::http::compression::builtin::algorithm::GZIP); + dmap[web::http::compression::builtin::algorithm::GZIP] = + web::http::compression::builtin::get_decompress_factory( + web::http::compression::builtin::algorithm::GZIP); + dfactories.push_back(dmap[web::http::compression::builtin::algorithm::GZIP]); + cfactories.push_back(web::http::compression::builtin::get_compress_factory( + web::http::compression::builtin::algorithm::GZIP)); + } + if (web::http::compression::builtin::algorithm::supported( + web::http::compression::builtin::algorithm::DEFLATE)) + { + algs.push_back(web::http::compression::builtin::algorithm::DEFLATE); + dmap[web::http::compression::builtin::algorithm::DEFLATE] = + web::http::compression::builtin::get_decompress_factory( + web::http::compression::builtin::algorithm::DEFLATE); + dfactories.push_back(dmap[web::http::compression::builtin::algorithm::DEFLATE]); + cfactories.push_back(web::http::compression::builtin::get_compress_factory( + web::http::compression::builtin::algorithm::DEFLATE)); + } + if (web::http::compression::builtin::algorithm::supported( + web::http::compression::builtin::algorithm::BROTLI)) + { + algs.push_back(web::http::compression::builtin::algorithm::BROTLI); + dmap[web::http::compression::builtin::algorithm::BROTLI] = + web::http::compression::builtin::get_decompress_factory( + web::http::compression::builtin::algorithm::BROTLI); + dfactories.push_back(dmap[web::http::compression::builtin::algorithm::BROTLI]); + cfactories.push_back(web::http::compression::builtin::get_compress_factory( + web::http::compression::builtin::algorithm::BROTLI)); + } + algs.push_back(fake_provider::FAKE); + dmap[fake_provider::FAKE] = web::http::compression::make_decompress_factory( + fake_provider::FAKE, + 1000, + [buffer_size]() -> std::unique_ptr { + return std::make_unique(buffer_size); + }); + dfactories.push_back(dmap[fake_provider::FAKE]); + cfactories.push_back(web::http::compression::make_compress_factory( + fake_provider::FAKE, [buffer_size]() -> std::unique_ptr { + return std::make_unique(buffer_size); + })); + + v.resize(buffer_size); + + // Test compressible (net shrinking) and non-compressible (net growing) buffers + for (int compressible = 0; compressible < 2; compressible++) + { + for (size_t x = 0; x < buffer_size; x++) + { + if (compressible) + { + v[x] = static_cast('a' + x % 26); + } + else + { + v[x] = static_cast(std::rand()); + } + } + + // Test both Transfer-Encoding and Content-Encoding + for (transfer = 0; transfer < 2; transfer++) + { + web::http::client::http_client_config config; + config.set_request_compressed_response(!transfer); + http_client client(m_uri, config); + + // Test supported compression algorithms + for (int alg = 0; alg < algs.size(); alg++) + { + // Test both GET and PUT + for (int put = 0; put < 2; put++) + { + if (transfer && put && skip_transfer_put) + { + continue; + } + + processed = false; + + if (put) + { + std::vector streams; + std::vector pre; + + if (transfer) + { + // Add a pair of non-compressed streams for Transfer-Encoding, one with and one + // without acquire/release support + streams.emplace_back(concurrency::streams::rawptr_stream::open_istream( + (const uint8_t*)v.data(), v.size())); + streams.emplace_back( + my_rawptr_buffer::open_istream(v.data(), v.size())); + } + else + { + bool done; + size_t used; + pre.resize(v.size() + 128); + + auto c = web::http::compression::builtin::make_compressor(algs[alg]); + if (algs[alg] == fake_provider::FAKE) + { + VERIFY_IS_FALSE((bool)c); + c = std::make_unique(buffer_size); + } + VERIFY_IS_TRUE((bool)c); + auto got = c->compress(v.data(), + v.size(), + pre.data(), + pre.size(), + web::http::compression::operation_hint::is_last, + used, + &done); + VERIFY_ARE_EQUAL(used, v.size()); + VERIFY_IS_TRUE(done); + + // Add a single pre-compressed stream, since Content-Encoding requires + // Content-Length + streams.emplace_back(concurrency::streams::rawptr_stream::open_istream( + pre.data(), got)); + } + + for (int str = 0; str < streams.size(); str++) + { + concurrency::streams::istream& stream = streams[str]; + http_request msg(methods::PUT); + + processed = false; + + msg.set_body(stream); + if (transfer) + { + bool boo = msg.set_compressor(algs[alg]); + VERIFY_ARE_EQUAL(boo, algs[alg] != fake_provider::FAKE); + if (algs[alg] == fake_provider::FAKE) + { + msg.set_compressor(std::make_unique(buffer_size)); + } + } + else + { + msg.headers().add(header_names::content_encoding, algs[alg]); + } + + if (!real) + { + // We implement the decompression path in the server, to prove that valid, + // compressed data is sent + p_server->next_request().then([&](test_request* p_request) { + std::unique_ptr d; + std::vector vv; + utility::string_t header; + size_t used; + size_t got; + bool done; + + http_asserts::assert_test_request_equals( + p_request, methods::PUT, U("/")); + + if (transfer) + { + VERIFY_IS_FALSE(p_request->match_header( + header_names::content_encoding, header)); + done = p_request->match_header(header_names::transfer_encoding, + header); + VERIFY_IS_TRUE(done); + d = web::http::compression::details::get_decompressor_from_header( + header, + web::http::compression::details::header_types:: + transfer_encoding, + dfactories); + } + else + { + done = p_request->match_header(header_names::transfer_encoding, + header); + if (done) + { + VERIFY_IS_TRUE( + utility::details::str_iequal(_XPLATSTR("chunked"), header)); + } + done = + p_request->match_header(header_names::content_encoding, header); + VERIFY_IS_TRUE(done); + d = web::http::compression::details::get_decompressor_from_header( + header, + web::http::compression::details::header_types::content_encoding, + dfactories); + } +#if defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(CPPREST_FORCE_HTTP_CLIENT_ASIO) + VERIFY_IS_TRUE((bool)d); +#else // _WIN32 + VERIFY_ARE_NOT_EQUAL((bool)d, !!transfer); +#endif // _WIN32 + + vv.resize(buffer_size + 128); + if (d) + { + got = d->decompress(p_request->m_body.data(), + p_request->m_body.size(), + vv.data(), + vv.size(), + web::http::compression::operation_hint::is_last, + used, + &done); + VERIFY_ARE_EQUAL(used, p_request->m_body.size()); + VERIFY_IS_TRUE(done); + } + else + { + memcpy(vv.data(), v.data(), v.size()); + got = v.size(); + } + VERIFY_ARE_EQUAL(buffer_size, got); + vv.resize(buffer_size); + VERIFY_ARE_EQUAL(v, vv); + processed = true; + + p_request->reply(static_cast(status_codes::OK)); + }); + } + + // Send the request + http_response rsp = client.request(msg).get(); + VERIFY_ARE_EQUAL(rsp.status_code(), status_codes::OK); + rsp.content_ready().wait(); + stream.close().wait(); + VERIFY_IS_TRUE(processed); + } + } + else + { + std::vector vv; + concurrency::streams::ostream stream = + concurrency::streams::rawptr_stream::open_ostream(vv.data(), + buffer_size); + http_request msg(methods::GET); + + std::vector> df = { + dmap[algs[alg]]}; + msg.set_decompress_factories(df); + + vv.resize(buffer_size + 128); // extra to ensure no overflow + + concurrency::streams::rawptr_buffer buf( + vv.data(), vv.size(), std::ios::out); + + if (!real) + { + p_server->next_request().then([&](test_request* p_request) { + std::map headers; + std::unique_ptr c; + utility::string_t header; + std::vector cmp; + size_t used; + size_t extra = 0; + size_t skip = 0; + size_t got; + bool done; + + std::string ext = ";x=y"; + std::string trailer = "a=b\r\nx=y\r\n"; + + http_asserts::assert_test_request_equals(p_request, methods::GET, U("/")); + + if (transfer) + { + // On Windows, someone along the way adds "Accept-Encoding: peerdist", + // so we can't unconditionally assert that Accept-Encoding is not + // present + done = p_request->match_header(header_names::accept_encoding, header); + VERIFY_IS_TRUE(!done || + header.find(algs[alg]) == utility::string_t::npos); + done = p_request->match_header(header_names::te, header); + if (done) + { + c = web::http::compression::details::get_compressor_from_header( + header, + web::http::compression::details::header_types::te, + cfactories); + } + + // Account for space for the chunk header and delimiters, plus a chunk + // extension and a chunked trailer part + extra = 2 * web::http::details::chunked_encoding:: + additional_encoding_space + + ext.size() + trailer.size(); + skip = web::http::details::chunked_encoding::data_offset + ext.size(); + } + else + { + VERIFY_IS_FALSE(p_request->match_header(header_names::te, header)); + done = p_request->match_header(header_names::accept_encoding, header); + VERIFY_IS_TRUE(done); + c = web::http::compression::details::get_compressor_from_header( + header, + web::http::compression::details::header_types::accept_encoding, + cfactories); + } +#if !defined __cplusplus_winrt + VERIFY_IS_TRUE((bool)c); +#else // __cplusplus_winrt + VERIFY_ARE_NOT_EQUAL((bool)c, !!transfer); +#endif // __cplusplus_winrt + cmp.resize(extra + buffer_size + 128); + if (c) + { + got = c->compress(v.data(), + v.size(), + cmp.data() + skip, + cmp.size() - extra, + web::http::compression::operation_hint::is_last, + used, + &done); + VERIFY_ARE_EQUAL(used, v.size()); + VERIFY_IS_TRUE(done); + } + else + { + memcpy(cmp.data() + skip, v.data(), v.size()); + got = v.size(); + } + if (transfer) + { + // Add delimiters for the first (and only) data chunk, plus the final + // 0-length chunk, and hack in a dummy chunk extension and a dummy + // trailer part. Note that we put *two* "0\r\n" in here in the 0-length + // case... and none of the parsers complain. + size_t total = + got + + web::http::details::chunked_encoding::additional_encoding_space + + ext.size(); + _ASSERTE(ext.size() >= 2); + if (got > ext.size() - 1) + { + cmp[total - 2] = + cmp[got + web::http::details::chunked_encoding::data_offset]; + } + if (got > ext.size() - 2) + { + cmp[total - 1] = + cmp[got + web::http::details::chunked_encoding::data_offset + + 1]; + } + size_t offset = + web::http::details::chunked_encoding::add_chunked_delimiters( + cmp.data(), total, got); + size_t offset2 = + web::http::details::chunked_encoding::add_chunked_delimiters( + cmp.data() + total - 7, + web::http::details::chunked_encoding::additional_encoding_space, + 0); + _ASSERTE( + offset2 == 7 && + web::http::details::chunked_encoding::additional_encoding_space - + 7 == + 5); + memcpy(cmp.data() + web::http::details::chunked_encoding::data_offset - + 2, + ext.data(), + ext.size()); + cmp[web::http::details::chunked_encoding::data_offset + ext.size() - + 2] = '\r'; + cmp[web::http::details::chunked_encoding::data_offset + ext.size() - + 1] = '\n'; + if (got > ext.size() - 1) + { + cmp[got + web::http::details::chunked_encoding::data_offset] = + cmp[total - 2]; + } + if (got > ext.size() - 2) + { + cmp[got + web::http::details::chunked_encoding::data_offset + 1] = + cmp[total - 1]; + } + cmp[total - 2] = '\r'; + cmp[total - 1] = '\n'; + memcpy(cmp.data() + total + 3, trailer.data(), trailer.size()); + cmp[total + trailer.size() + 3] = '\r'; + cmp[total + trailer.size() + 4] = '\n'; + cmp.erase(cmp.begin(), cmp.begin() + offset); + cmp.resize( + ext.size() + got + trailer.size() + + web::http::details::chunked_encoding::additional_encoding_space - + offset + 5); + if (c) + { + headers[header_names::transfer_encoding] = + c->algorithm() + _XPLATSTR(", chunked"); + } + else + { + headers[header_names::transfer_encoding] = _XPLATSTR("chunked"); + } + } + else + { + cmp.resize(got); + headers[header_names::content_encoding] = c->algorithm(); + } + processed = true; + + if (cmp.size()) + { + p_request->reply(static_cast(status_codes::OK), + utility::string_t(), + headers, + cmp); + } + else + { + p_request->reply(static_cast(status_codes::OK), + utility::string_t(), + headers); + } + }); + } + + // Common send and response processing code + http_response rsp = client.request(msg).get(); + VERIFY_ARE_EQUAL(rsp.status_code(), status_codes::OK); + VERIFY_NO_THROWS(rsp.content_ready().wait()); + + if (transfer) + { + VERIFY_IS_TRUE(rsp.headers().has(header_names::transfer_encoding)); + VERIFY_IS_FALSE(rsp.headers().has(header_names::content_encoding)); + } + else + { + utility::string_t header; + + VERIFY_IS_TRUE(rsp.headers().has(header_names::content_encoding)); + bool boo = rsp.headers().match(header_names::transfer_encoding, header); + if (boo) + { + VERIFY_IS_TRUE(utility::details::str_iequal(_XPLATSTR("chunked"), header)); + } + } + + size_t offset; + VERIFY_NO_THROWS(offset = rsp.body().read_to_end(buf).get()); + VERIFY_ARE_EQUAL(offset, buffer_size); + VERIFY_ARE_EQUAL(offset, static_cast(buf.getpos(std::ios::out))); + vv.resize(buffer_size); + VERIFY_ARE_EQUAL(v, vv); + buf.close(std::ios_base::out).wait(); + stream.close().wait(); + } + VERIFY_IS_TRUE(processed); + } + } + } + } + } + if (real) + { + listener.close().wait(); + } + } + } +} // SUITE(request_helper_tests) +} +} +} +} diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 7c0438d48c..bec9b0c458 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -58,7 +58,7 @@ TEST_FIXTURE(uri_address, outside_cnn_dot_com) TEST_FIXTURE(uri_address, outside_wikipedia_compressed_http_response) { - if (web::http::details::compression::stream_decompressor::is_supported() == false) + if (web::http::compression::builtin::supported() == false) { // On platforms which do not support compressed http, nothing to check. return; diff --git a/Release/tests/functional/http/client/request_helper_tests.cpp b/Release/tests/functional/http/client/request_helper_tests.cpp index 32a49490ef..fa3360756b 100644 --- a/Release/tests/functional/http/client/request_helper_tests.cpp +++ b/Release/tests/functional/http/client/request_helper_tests.cpp @@ -45,7 +45,7 @@ TEST_FIXTURE(uri_address, do_not_fail_on_content_encoding_when_not_requested) TEST_FIXTURE(uri_address, fail_on_content_encoding_if_unsupported) { - if (web::http::details::compression::stream_compressor::is_supported()) + if (web::http::compression::builtin::supported()) { test_http_server::scoped_server scoped(m_uri); auto& server = *scoped.server(); @@ -63,7 +63,7 @@ TEST_FIXTURE(uri_address, fail_on_content_encoding_if_unsupported) TEST_FIXTURE(uri_address, send_accept_encoding) { - if (web::http::details::compression::stream_compressor::is_supported()) + if (web::http::compression::builtin::supported()) { test_http_server::scoped_server scoped(m_uri); auto& server = *scoped.server(); @@ -93,7 +93,14 @@ TEST_FIXTURE(uri_address, do_not_send_accept_encoding) std::atomic found_accept_encoding(true); server.next_request().then([&found_accept_encoding](test_request *p_request) { - found_accept_encoding = p_request->m_headers.find(header_names::accept_encoding) != p_request->m_headers.end(); + utility::string_t header; + + found_accept_encoding = p_request->match_header(header_names::accept_encoding, header); + if (found_accept_encoding) + { + // On Windows, someone along the way (not us!) adds "Accept-Encoding: peerdist" + found_accept_encoding = header != _XPLATSTR("peerdist"); + } p_request->reply(200, U("OK")); }); @@ -102,55 +109,6 @@ TEST_FIXTURE(uri_address, do_not_send_accept_encoding) VERIFY_IS_FALSE(found_accept_encoding); } -TEST_FIXTURE(uri_address, compress_and_decompress) -{ - if (web::http::details::compression::stream_compressor::is_supported()) - { - auto compress_and_decompress = [](web::http::details::compression::compression_algorithm alg) - { - auto compressor = std::make_shared(alg); - auto decompressor = std::make_shared(alg); - - const size_t buffer_size = 100; - const size_t split_pos = buffer_size / 2; - - web::http::details::compression::data_buffer input_buffer; - input_buffer.reserve(buffer_size); - - for (size_t i = 0; i < buffer_size; ++i) - { - input_buffer.push_back(static_cast(i)); - } - - web::http::details::compression::data_buffer buffer1(input_buffer.begin(), input_buffer.begin() + split_pos); - web::http::details::compression::data_buffer buffer2(input_buffer.begin() + split_pos, input_buffer.end()); - - auto compressed_data1 = compressor->compress(buffer1, false); - VERIFY_IS_FALSE(compressed_data1.empty()); - VERIFY_IS_FALSE(compressor->has_error()); - - auto compressed_data2 = compressor->compress(buffer2, true); - VERIFY_IS_FALSE(compressed_data2.empty()); - VERIFY_IS_FALSE(compressor->has_error()); - - auto decompressed_data1 = decompressor->decompress(compressed_data1); - VERIFY_IS_FALSE(decompressed_data1.empty()); - VERIFY_IS_FALSE(decompressor->has_error()); - - auto decompressed_data2 = decompressor->decompress(compressed_data2); - VERIFY_IS_FALSE(decompressed_data2.empty()); - VERIFY_IS_FALSE(decompressor->has_error()); - - decompressed_data1.insert(decompressed_data1.end(), decompressed_data2.begin(), decompressed_data2.end()); - - VERIFY_ARE_EQUAL(input_buffer, decompressed_data1); - }; - - compress_and_decompress(web::http::details::compression::compression_algorithm::gzip); - compress_and_decompress(web::http::details::compression::compression_algorithm::deflate); - } -} - TEST_FIXTURE(uri_address, non_rvalue_bodies) { test_http_server::scoped_server scoped(m_uri); diff --git a/Release/tests/functional/http/utilities/include/test_http_server.h b/Release/tests/functional/http/utilities/include/test_http_server.h index 84eb27d4ab..4b2ededbd5 100644 --- a/Release/tests/functional/http/utilities/include/test_http_server.h +++ b/Release/tests/functional/http/utilities/include/test_http_server.h @@ -46,6 +46,15 @@ class test_request return reply_impl(status_code, reason_phrase, headers, (void *)&data[0], data.size() * sizeof(utf8char)); } + unsigned long reply( + const unsigned short status_code, + const utility::string_t &reason_phrase, + const std::map &headers, + const std::vector &data) + { + return reply_impl(status_code, reason_phrase, headers, (void *)&data[0], data.size()); + } + unsigned long reply( const unsigned short status_code, const utility::string_t &reason_phrase, @@ -60,20 +69,12 @@ class test_request bool match_header(const utility::string_t & header_name, T & header_value) { auto iter = m_headers.find(header_name); - if (iter != m_headers.end()) - { - utility::istringstream_t iss(iter->second); - iss >> header_value; - if (iss.fail() || !iss.eof()) - { - return false; - } - return true; - } - else - { - return false; - } + if (iter == m_headers.end()) + { + return false; + } + + return bind_impl(iter->second, header_value) || iter->second.empty(); } // Request data. @@ -93,6 +94,33 @@ class test_request const std::map &headers, void * data, size_t data_length); + +private: + + template + bool bind_impl(const utility::string_t &text, T &ref) const + { + utility::istringstream_t iss(text); + iss.imbue(std::locale::classic()); + iss >> ref; + if (iss.fail() || !iss.eof()) + { + return false; + } + + return true; + } + + bool bind_impl(const utility::string_t &text, utf16string &ref) const + { + ref = utility::conversions::to_utf16string(text); + return true; + } + bool bind_impl(const utility::string_t &text, std::string &ref) const + { + ref = utility::conversions::to_utf8string(text); + return true; + } }; /// diff --git a/Release/tests/functional/http/utilities/test_http_server.cpp b/Release/tests/functional/http/utilities/test_http_server.cpp index cd359b1592..c4f848c009 100644 --- a/Release/tests/functional/http/utilities/test_http_server.cpp +++ b/Release/tests/functional/http/utilities/test_http_server.cpp @@ -160,7 +160,7 @@ static utility::string_t HttpServerAPIKnownHeaders[] = U("Proxy-Authorization"), U("Referer"), U("Range"), - U("Te"), + U("TE"), U("Translate"), U("User-Agent"), U("Request-Maximum"), @@ -345,7 +345,7 @@ class _test_http_server utility::string_t transfer_encoding; const bool has_transfer_encoding = p_test_request->match_header(U("Transfer-Encoding"), transfer_encoding); - if (has_transfer_encoding && transfer_encoding == U("chunked")) + if (has_transfer_encoding && transfer_encoding.find(U("chunked")) != std::string::npos) { content_length = 0; char buf[4096]; From 645637b9847438dcdf94c152f98f6659c163f777 Mon Sep 17 00:00:00 2001 From: Rishabh Anand Date: Tue, 2 Oct 2018 03:05:47 +0530 Subject: [PATCH 424/609] Linkify Visual Studio reference in README.md (#882) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4669fd8871..d6b0934320 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ target_link_libraries(main PRIVATE cpprestsdk::cpprest) * Features - HTTP client/server, JSON, URI, asynchronous streams, WebSockets client, oAuth * PPL Tasks - A powerful model for composing asynchronous operations based on C++ 11 features * Platforms - Windows desktop, Windows Store (UWP), Linux, OS X, Unix, iOS, and Android -* Support for Visual Studio 2015 and 2017 with debugger visualizers +* Support for [Visual Studio 2015 and 2017](https://visualstudio.microsoft.com/) with debugger visualizers ## Contribute Back! From b14f9ff6c48a30da8c57d1982d2e87b3c885dc59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20St=C3=B6ggl?= Date: Tue, 2 Oct 2018 00:13:21 +0200 Subject: [PATCH 425/609] Use the same cmake_minimum_required version 3.1 (#847) as in Release/CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c66d502345..594e6be65e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.1) project(cpprestsdk-root NONE) add_subdirectory(Release) From f897582260f2942284f9213ab9027486bde21b73 Mon Sep 17 00:00:00 2001 From: Gianfranco Costamagna Date: Tue, 2 Oct 2018 01:17:19 +0200 Subject: [PATCH 426/609] Fix install (#879) * Fix default installation path * Fixup previous commit. This makes the install location not correct for Debian and similar linux distro, but upstream don't plan to change "lib/cpprestsdk" location, so at least we can override the location with -DCPPREST_EXPORT_DIR=cmake and keep the CMAKE_INSTALL_LIBDIR multiarch location --- Release/CMakeLists.txt | 2 +- Release/src/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 3b99b85309..563b13d0dc 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -18,7 +18,7 @@ enable_testing() set(WERROR ON CACHE BOOL "Treat Warnings as Errors.") set(CPPREST_EXCLUDE_WEBSOCKETS OFF CACHE BOOL "Exclude websockets functionality.") set(CPPREST_EXCLUDE_COMPRESSION OFF CACHE BOOL "Exclude compression functionality.") -set(CPPREST_EXPORT_DIR lib/cpprestsdk CACHE STRING "Directory to install CMake config files.") +set(CPPREST_EXPORT_DIR cpprestsdk CACHE STRING "Directory to install CMake config files.") set(CPPREST_INSTALL_HEADERS ON CACHE BOOL "Install header files.") set(CPPREST_INSTALL ON CACHE BOOL "Add install commands.") diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index a34605bda2..050ff71fc2 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -262,12 +262,12 @@ if(CPPREST_INSTALL) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config.cmake" - DESTINATION ${CPPREST_EXPORT_DIR} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CPPREST_EXPORT_DIR} ) install( EXPORT cpprestsdk-targets FILE cpprestsdk-targets.cmake NAMESPACE cpprestsdk:: - DESTINATION ${CPPREST_EXPORT_DIR} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CPPREST_EXPORT_DIR} ) endif() From 982793de5ff79fb2035172511792b61e385697b0 Mon Sep 17 00:00:00 2001 From: Ernie Pistor Date: Thu, 4 Oct 2018 02:10:52 -0400 Subject: [PATCH 427/609] address review comments --- Release/cmake/cpprest_find_brotli.cmake | 2 +- Release/cmake/cpprestsdk-config.in.cmake | 2 +- Release/include/cpprest/http_compression.h | 34 ++---- Release/include/cpprest/http_headers.h | 23 ++-- Release/include/cpprest/http_msg.h | 16 +-- Release/src/CMakeLists.txt | 3 + Release/src/http/client/http_client_asio.cpp | 17 ++- .../src/http/client/http_client_winhttp.cpp | 36 +++--- Release/src/http/common/http_compression.cpp | 105 ++++++++++-------- .../src/http/common/internal_http_helpers.h | 16 +++ .../http/client/compression_tests.cpp | 50 ++++----- .../http/client/request_helper_tests.cpp | 9 +- .../http/utilities/include/test_http_server.h | 29 +---- 13 files changed, 164 insertions(+), 178 deletions(-) diff --git a/Release/cmake/cpprest_find_brotli.cmake b/Release/cmake/cpprest_find_brotli.cmake index 7366100939..2ec59a9ad9 100644 --- a/Release/cmake/cpprest_find_brotli.cmake +++ b/Release/cmake/cpprest_find_brotli.cmake @@ -3,7 +3,7 @@ function(cpprest_find_brotli) return() endif() - find_package(UNOFFICIAL-BROTLI REQUIRED) + find_package(unofficial-brotli REQUIRED) add_library(cpprestsdk_brotli_internal INTERFACE) target_link_libraries(cpprestsdk_brotli_internal INTERFACE unofficial::brotli::brotlienc unofficial::brotli::brotlidec unofficial::brotli::brotlicommon) diff --git a/Release/cmake/cpprestsdk-config.in.cmake b/Release/cmake/cpprestsdk-config.in.cmake index a00caa2f95..8b5e8a6ff3 100644 --- a/Release/cmake/cpprestsdk-config.in.cmake +++ b/Release/cmake/cpprestsdk-config.in.cmake @@ -4,7 +4,7 @@ if(@CPPREST_USES_ZLIB@) endif() if(@CPPREST_USES_BROTLI@) - find_dependency(UNOFFICIAL-BROTLI) + find_dependency(unofficial-brotli) endif() if(@CPPREST_USES_OPENSSL@) diff --git a/Release/include/cpprest/http_compression.h b/Release/include/cpprest/http_compression.h index 87b1d5dda8..13b183af00 100644 --- a/Release/include/cpprest/http_compression.h +++ b/Release/include/cpprest/http_compression.h @@ -115,24 +115,20 @@ _ASYNCRTIMP bool supported(); /// // String constants for each built-in compression algorithm, for convenient use with the factory functions /// -class algorithm +namespace algorithm { -public: - _ASYNCRTIMP static const utility::string_t GZIP; - _ASYNCRTIMP static const utility::string_t DEFLATE; - _ASYNCRTIMP static const utility::string_t BROTLI; - - /// - /// Test whether cpprestsdk was built with built-in compression support and - /// the supplied string matches a supported built-in algorithm - /// The name of the algorithm to test for built-in support. - /// True if cpprestsdk was built with built-in compression support and - /// the supplied string matches a supported built-in algorithm, and false if not. - /// - _ASYNCRTIMP static bool supported(const utility::string_t& algorithm); +constexpr utility::char_t *GZIP = _XPLATSTR("gzip"); +constexpr utility::char_t *DEFLATE = _XPLATSTR("deflate"); +constexpr utility::char_t *BROTLI = _XPLATSTR("br"); -private: - algorithm() {} +/// +/// Test whether cpprestsdk was built with built-in compression support and +/// the supplied string matches a supported built-in algorithm +/// The name of the algorithm to test for built-in support. +/// True if cpprestsdk was built with built-in compression support and +/// the supplied string matches a supported built-in algorithm, and false if not. +/// +_ASYNCRTIMP bool supported(const utility::string_t& algorithm); }; /// @@ -255,12 +251,6 @@ _ASYNCRTIMP std::shared_ptr make_decompress_factory( namespace details { -namespace builtin -{ -// Internal-only helper function -const std::vector> get_decompress_factories(); -} // namespace builtin - /// /// Header type enum for use with compressor and decompressor header parsing and building functions /// diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index c2e35f6079..077266a7d5 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -219,7 +219,7 @@ class http_headers return false; } - return bind_impl(iter->second, value) || iter->second.empty(); + return details::bind_impl(iter->second, value) || iter->second.empty(); } /// @@ -285,9 +285,14 @@ class http_headers _ASYNCRTIMP void set_date(const utility::datetime& date); private: + // Headers are stored in a map with case insensitive key. + inner_container m_headers; +}; - template - bool bind_impl(const key_type &text, _t &ref) const +namespace details +{ + template + bool bind_impl(const key_type &text, _t &ref) { utility::istringstream_t iss(text); iss.imbue(std::locale::classic()); @@ -300,20 +305,18 @@ class http_headers return true; } - bool bind_impl(const key_type &text, utf16string &ref) const + template + bool bind_impl(const key_type &text, utf16string &ref) { ref = utility::conversions::to_utf16string(text); return true; } - bool bind_impl(const key_type &text, std::string &ref) const + template + bool bind_impl(const key_type &text, std::string &ref) { ref = utility::conversions::to_utf8string(text); return true; } - - // Headers are stored in a map with case insensitive key. - inner_container m_headers; -}; - +} }} diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 85840b6836..39649ef833 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -383,7 +383,7 @@ class http_msg_base /// Determine the remaining input stream length /// /// - /// size_t::max if the stream's remaining length cannot be determined + /// std::numeric_limits::max() if the stream's remaining length cannot be determined /// length if the stream's remaining length (which may be 0) can be determined /// /// @@ -396,7 +396,7 @@ class http_msg_base /// Determine the content length /// /// - /// size_t::max if there is content with unknown length (transfer_encoding:chunked) + /// std::numeric_limits::max() if there is content with unknown length (transfer_encoding:chunked) /// 0 if there is no content /// length if there is content with known length /// @@ -410,7 +410,7 @@ class http_msg_base /// Determine the content length, and, if necessary, manage compression in the Transfer-Encoding header /// /// - /// size_t::max if there is content with unknown length (transfer_encoding:chunked) + /// std::numeric_limits::max() if there is content with unknown length (transfer_encoding:chunked) /// 0 if there is no content /// length if there is content with known length /// @@ -739,7 +739,7 @@ class http_response /// A readable, open asynchronous stream. /// A string holding the MIME type of the message body. /// - /// This cannot be used in conjunction with any other means of setting the body of the request. + /// This cannot be used in conjunction with any external means of setting the body of the request. /// The stream will not be read until the message is sent. /// void set_body(const concurrency::streams::istream &stream, const utility::string_t &content_type = _XPLATSTR("application/octet-stream")) @@ -755,7 +755,7 @@ class http_response /// The size of the data to be sent in the body. /// A string holding the MIME type of the message body. /// - /// This cannot be used in conjunction with any other means of setting the body of the request. + /// This cannot be used in conjunction with any external means of setting the body of the request. /// The stream will not be read until the message is sent. /// void set_body(const concurrency::streams::istream &stream, utility::size64_t content_length, const utility::string_t &content_type = _XPLATSTR("application/octet-stream")) @@ -1222,7 +1222,7 @@ class http_request /// /// A pointer to an instantiated compressor of the desired type. /// - /// This cannot be used in conjunction with any other means of compression. The Transfer-Encoding + /// This cannot be used in conjunction with any external means of compression. The Transfer-Encoding /// header will be managed internally, and must not be set by the client. /// void set_compressor(std::unique_ptr compressor) @@ -1238,7 +1238,7 @@ class http_request /// True if a built-in compressor was instantiated, otherwise false. /// /// - /// This cannot be used in conjunction with any other means of compression. The Transfer-Encoding + /// This cannot be used in conjunction with any external means of compression. The Transfer-Encoding /// header will be managed internally, and must not be set by the client. /// bool set_compressor(utility::string_t algorithm) @@ -1297,7 +1297,7 @@ class http_request /// The collection of factory classes itself. /// /// - /// This cannot be used in conjunction with any other means of decompression. The TE + /// This cannot be used in conjunction with any external means of decompression. The TE /// header must not be set by the client, as it will be managed internally. /// const std::vector> &decompress_factories() const diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index a748698a45..ff0ebfc451 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -72,6 +72,9 @@ endif() # Compression component if(CPPREST_EXCLUDE_COMPRESSION) + if(NOT CPPREST_EXCLUDE_BROTLI) + message(FATAL_ERROR "Use of Brotli requires compression to be enabled") + endif() target_compile_definitions(cpprest PRIVATE -DCPPREST_EXCLUDE_COMPRESSION=1) else() cpprest_find_zlib() diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 893d36d74d..7590497420 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1520,21 +1520,18 @@ class asio_context final : public request_context, public std::enable_shared_fro bool decompress(const uint8_t* input, size_t input_size, std::vector& output) { - size_t processed; - size_t got; - size_t inbytes; - size_t outbytes; - bool done; - // Need to guard against attempting to decompress when we're already finished or encountered an error! if (input == nullptr || input_size == 0) { return false; } - inbytes = 0; - outbytes = 0; - done = false; + size_t processed; + size_t got; + size_t inbytes = 0; + size_t outbytes = 0; + bool done = false; + try { output.resize(input_size * 3); @@ -1542,7 +1539,7 @@ class asio_context final : public request_context, public std::enable_shared_fro { if (inbytes) { - output.resize(output.size() + (input_size > 1024 ? input_size : 1024)); + output.resize(output.size() + std::max(input_size, static_cast(1024))); } got = m_decompressor->decompress(input + inbytes, input_size - inbytes, diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index d60f7ef1f5..0a135d039e 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -182,10 +182,10 @@ class memory_holder { uint8_t* m_externalData; std::vector m_internalData; - size_t m_length; + size_t m_size; public: - memory_holder() : m_externalData(nullptr), m_length(0) + memory_holder() : m_externalData(nullptr), m_size(0) { } @@ -202,7 +202,7 @@ class memory_holder { assert(block != nullptr); m_externalData = block; - m_length = length; + m_size = length; } inline bool is_internally_allocated() const @@ -215,9 +215,9 @@ class memory_holder return is_internally_allocated() ? &m_internalData[0] : m_externalData ; } - inline size_t length() const + inline size_t size() const { - return is_internally_allocated() ? m_internalData.size() : m_length; + return is_internally_allocated() ? m_internalData.size() : m_size; } }; @@ -1311,13 +1311,7 @@ class winhttp_client final : public _http_client_communicator { uint8_t *buffer; - if (!decompressor) - { - auto writebuf = pContext->_get_writebuffer(); - pContext->allocate_reply_space(writebuf.alloc(chunkSize), chunkSize); - buffer = pContext->m_body_data.get(); - } - else + if (decompressor) { // m_buffer holds the compressed data; we'll decompress into the caller's buffer later if (pContext->m_compression_state.m_buffer.capacity() < chunkSize) @@ -1326,6 +1320,12 @@ class winhttp_client final : public _http_client_communicator } buffer = pContext->m_compression_state.m_buffer.data(); } + else + { + auto writebuf = pContext->_get_writebuffer(); + pContext->allocate_reply_space(writebuf.alloc(chunkSize), chunkSize); + buffer = pContext->m_body_data.get(); + } if (!WinHttpReadData( pContext->m_request_handle, @@ -1350,15 +1350,15 @@ class winhttp_client final : public _http_client_communicator { // We could allocate less than a chunk for the compressed data here, though that // would result in more trips through this path for not-so-compressible data... - if (p_request_context->m_body_data.length() > http::details::chunked_encoding::additional_encoding_space) + if (p_request_context->m_body_data.size() > http::details::chunked_encoding::additional_encoding_space) { // If we've previously allocated space for the compressed data, don't reduce it - chunk_size = p_request_context->m_body_data.length() - http::details::chunked_encoding::additional_encoding_space; + chunk_size = p_request_context->m_body_data.size() - http::details::chunked_encoding::additional_encoding_space; } else if (p_request_context->m_remaining_to_write != std::numeric_limits::max()) { // Choose a semi-intelligent size based on how much total data is left to compress - chunk_size = std::min((size_t)p_request_context->m_remaining_to_write+128, p_request_context->m_http_client->client_config().chunksize()); + chunk_size = std::min(static_cast(p_request_context->m_remaining_to_write)+128, p_request_context->m_http_client->client_config().chunksize()); } else { @@ -1369,7 +1369,7 @@ class winhttp_client final : public _http_client_communicator else { // We're not compressing; use the smaller of the remaining data (if known) and the configured (or default) chunk size - chunk_size = std::min((size_t)p_request_context->m_remaining_to_write, p_request_context->m_http_client->client_config().chunksize()); + chunk_size = std::min(static_cast(p_request_context->m_remaining_to_write), p_request_context->m_http_client->client_config().chunksize()); } p_request_context->allocate_request_space(nullptr, chunk_size + http::details::chunked_encoding::additional_encoding_space); @@ -1590,7 +1590,7 @@ class winhttp_client final : public _http_client_communicator } else { - length = std::min((size_t)p_request_context->m_remaining_to_write, p_request_context->m_http_client->client_config().chunksize()); + length = std::min(static_cast(p_request_context->m_remaining_to_write), p_request_context->m_http_client->client_config().chunksize()); if (p_request_context->m_compression_state.m_buffer.capacity() < length) { p_request_context->m_compression_state.m_buffer.reserve(length); @@ -2182,7 +2182,7 @@ class winhttp_client final : public _http_client_communicator if (p_request_context->m_decompressor) { - size_t chunk_size = std::max((size_t)bytesRead, p_request_context->m_http_client->client_config().chunksize()); + size_t chunk_size = std::max(static_cast(bytesRead), p_request_context->m_http_client->client_config().chunksize()); p_request_context->m_compression_state.m_bytes_read = static_cast(bytesRead); p_request_context->m_compression_state.m_chunk_bytes = 0; diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index 89840b8867..e7e7f9a927 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -54,12 +54,15 @@ namespace builtin class zlib_compressor_base : public compress_provider { public: + static const utility::string_t GZIP; + static const utility::string_t DEFLATE; + zlib_compressor_base(int windowBits, int compressionLevel = Z_DEFAULT_COMPRESSION, int method = Z_DEFLATED, int strategy = Z_DEFAULT_STRATEGY, int memLevel = MAX_MEM_LEVEL) - : m_algorithm(windowBits >= 16 ? algorithm::GZIP : algorithm::DEFLATE) + : m_algorithm(windowBits >= 16 ? GZIP : DEFLATE) { m_state = deflateInit2(&m_stream, compressionLevel, method, windowBits, memLevel, strategy); } @@ -91,6 +94,11 @@ class zlib_compressor_base : public compress_provider throw std::runtime_error(std::move(ss.str())); } + if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) + { + throw std::runtime_error("Compression input or output size out of range"); + } + m_stream.next_in = const_cast(input); m_stream.avail_in = static_cast(input_size); m_stream.next_out = const_cast(output); @@ -152,11 +160,15 @@ class zlib_compressor_base : public compress_provider const utility::string_t& m_algorithm; }; +const utility::string_t zlib_compressor_base::GZIP(algorithm::GZIP); +const utility::string_t zlib_compressor_base::DEFLATE(algorithm::DEFLATE); + // A shared base class for the gzip and deflate decompressors class zlib_decompressor_base : public decompress_provider { public: - zlib_decompressor_base(int windowBits) : m_algorithm(windowBits >= 16 ? algorithm::GZIP : algorithm::DEFLATE) + zlib_decompressor_base(int windowBits) + : m_algorithm(windowBits >= 16 ? zlib_compressor_base::GZIP : zlib_compressor_base::DEFLATE) { m_state = inflateInit2(&m_stream, windowBits); } @@ -188,6 +200,11 @@ class zlib_decompressor_base : public decompress_provider throw std::runtime_error(std::move(ss.str())); } + if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) + { + throw std::runtime_error("Compression input or output size out of range"); + } + m_stream.next_in = const_cast(input); m_stream.avail_in = static_cast(input_size); m_stream.next_out = const_cast(output); @@ -296,15 +313,17 @@ class deflate_decompressor : public zlib_decompressor_base class brotli_compressor : public compress_provider { public: + static const utility::string_t BROTLI; + brotli_compressor(uint32_t window = BROTLI_DEFAULT_WINDOW, uint32_t quality = BROTLI_DEFAULT_QUALITY, uint32_t mode = BROTLI_DEFAULT_MODE) - : m_window(window), m_quality(quality), m_mode(mode) + : m_algorithm(BROTLI), m_window(window), m_quality(quality), m_mode(mode) { (void)reset(); } - const utility::string_t& algorithm() const { return algorithm::BROTLI; } + const utility::string_t& algorithm() const { return m_algorithm; } size_t compress(const uint8_t* input, size_t input_size, @@ -449,12 +468,15 @@ class brotli_compressor : public compress_provider uint32_t m_window; uint32_t m_quality; uint32_t m_mode; + const utility::string_t& m_algorithm; }; +const utility::string_t brotli_compressor::BROTLI(algorithm::BROTLI); + class brotli_decompressor : public decompress_provider { public: - brotli_decompressor() + brotli_decompressor() : m_algorithm(brotli_compressor::BROTLI) { try { @@ -465,7 +487,7 @@ class brotli_decompressor : public decompress_provider } } - const utility::string_t& algorithm() const { return algorithm::BROTLI; } + const utility::string_t& algorithm() const { return m_algorithm; } size_t decompress(const uint8_t* input, size_t input_size, @@ -561,30 +583,27 @@ class brotli_decompressor : public decompress_provider private: BrotliDecoderResult m_state{BROTLI_DECODER_RESULT_ERROR}; BrotliDecoderState* m_stream{nullptr}; + const utility::string_t& m_algorithm; }; #endif // CPPREST_BROTLI_COMPRESSION #endif // CPPREST_HTTP_COMPRESSION -const utility::string_t algorithm::GZIP = _XPLATSTR("gzip"); -const utility::string_t algorithm::DEFLATE = _XPLATSTR("deflate"); -const utility::string_t algorithm::BROTLI = _XPLATSTR("br"); - // Generic internal implementation of the compress_factory API class generic_compress_factory : public compress_factory { public: generic_compress_factory(const utility::string_t& algorithm, std::function()> make_compressor) - : _algorithm(algorithm), _make_compressor(make_compressor) + : m_algorithm(algorithm), _make_compressor(make_compressor) { } - const utility::string_t& algorithm() const { return _algorithm; } + const utility::string_t& algorithm() const { return m_algorithm; } std::unique_ptr make_compressor() const { return _make_compressor(); } private: - const utility::string_t _algorithm; + const utility::string_t m_algorithm; std::function()> _make_compressor; }; @@ -595,19 +614,19 @@ class generic_decompress_factory : public decompress_factory generic_decompress_factory(const utility::string_t& algorithm, uint16_t weight, std::function()> make_decompressor) - : _algorithm(algorithm), _weight(weight), _make_decompressor(make_decompressor) + : m_algorithm(algorithm), m_weight(weight), _make_decompressor(make_decompressor) { } - const utility::string_t& algorithm() const { return _algorithm; } + const utility::string_t& algorithm() const { return m_algorithm; } - const uint16_t weight() const { return _weight; } + const uint16_t weight() const { return m_weight; } std::unique_ptr make_decompressor() const { return _make_decompressor(); } private: - const utility::string_t _algorithm; - uint16_t _weight; + const utility::string_t m_algorithm; + uint16_t m_weight; std::function()> _make_decompressor; }; @@ -654,11 +673,9 @@ bool supported() { return !g_compress_factories.empty(); } bool algorithm::supported(const utility::string_t& algorithm) { - auto size = g_compress_factories.size(); - - for (int i = 0; i < size; i++) + for (auto& factory : g_compress_factories) { - if (utility::details::str_iequal(algorithm, g_compress_factories[i]->algorithm())) + if (utility::details::str_iequal(algorithm, factory->algorithm())) { return true; } @@ -670,11 +687,8 @@ bool algorithm::supported(const utility::string_t& algorithm) static std::unique_ptr _make_compressor( const std::vector>& factories, const utility::string_t& algorithm) { - auto size = factories.size(); - - for (int i = 0; i < size; i++) + for (auto& factory : factories) { - auto factory = factories[i].get(); if (factory && utility::details::str_iequal(algorithm, factory->algorithm())) { return factory->make_compressor(); @@ -692,11 +706,8 @@ std::unique_ptr make_compressor(const utility::string_t& algo static std::unique_ptr _make_decompressor( const std::vector>& factories, const utility::string_t& algorithm) { - auto size = factories.size(); - - for (int i = 0; i < size; i++) + for (auto& factory : factories) { - auto factory = factories[i].get(); if (factory && utility::details::str_iequal(algorithm, factory->algorithm())) { return factory->make_decompressor(); @@ -713,13 +724,11 @@ std::unique_ptr make_decompressor(const utility::string_t& std::shared_ptr get_compress_factory(const utility::string_t& algorithm) { - auto size = g_compress_factories.size(); - - for (int i = 0; i < size; i++) + for (auto& factory : g_compress_factories) { - if (utility::details::str_iequal(algorithm, g_compress_factories[i]->algorithm())) + if (utility::details::str_iequal(algorithm, factory->algorithm())) { - return g_compress_factories[i]; + return factory; } } @@ -728,13 +737,11 @@ std::shared_ptr get_compress_factory(const utility::string_t& std::shared_ptr get_decompress_factory(const utility::string_t& algorithm) { - auto size = g_decompress_factories.size(); - - for (int i = 0; i < size; i++) + for (auto& factory : g_decompress_factories) { - if (utility::details::str_iequal(algorithm, g_decompress_factories[i]->algorithm())) + if (utility::details::str_iequal(algorithm, factory->algorithm())) { - return g_decompress_factories[i]; + return factory; } } @@ -793,7 +800,7 @@ const std::vector> get_decompress_factories( } } // namespace builtin -static bool is_http_whitespace(utility::char_t ch) { return ch == _XPLATSTR(" ")[0] || ch == _XPLATSTR("\t")[0]; } +static bool is_http_whitespace(utility::char_t ch) { return ch == _XPLATSTR(' ') || ch == _XPLATSTR('\t'); } static void remove_surrounding_http_whitespace(const utility::string_t& encoding, size_t& start, size_t& length) { @@ -840,7 +847,7 @@ std::unique_ptr get_compressor_from_header( while (n != utility::string_t::npos) { // Tokenize by commas first - mark = encoding.find(_XPLATSTR(","), n); + mark = encoding.find(_XPLATSTR(','), n); t.start = n; t.rank = static_cast(-1); if (mark == utility::string_t::npos) @@ -858,7 +865,7 @@ std::unique_ptr get_compressor_from_header( remove_surrounding_http_whitespace(encoding, t.start, t.length); // Next split at the semicolon, if any, and deal with rank and additional whitespace - mark = encoding.find(_XPLATSTR(";")[0], t.start); + mark = encoding.find(_XPLATSTR(';'), t.start); if (mark < t.start + t.length) { end = t.start + t.length - 1; @@ -877,15 +884,15 @@ std::unique_ptr get_compressor_from_header( // Determine ranking; leading whitespace has been implicitly skipped by find(). // The ranking always starts with '1' or '0' per standard, and has at most 3 decimal places mark += 1; - t.rank = 1000 * (encoding.at(mark + 1) - _XPLATSTR("0")[0]); - if (mark + 2 < end && encoding.at(mark + 2) == _XPLATSTR(".")[0]) + t.rank = 1000 * (encoding.at(mark + 1) - _XPLATSTR('0')); + if (mark + 2 < end && encoding.at(mark + 2) == _XPLATSTR('.')) { // This is a real number rank; convert decimal part to hundreds and apply it size_t factor = 100; mark += 2; for (size_t i = mark + 1; i <= end; i++) { - t.rank += (encoding.at(i) - _XPLATSTR("0")[0]) * factor; + t.rank += (encoding.at(i) - _XPLATSTR('0')) * factor; factor /= 10; } } @@ -990,7 +997,7 @@ std::unique_ptr get_decompressor_from_header( while (n != utility::string_t::npos) { // Tokenize by commas first - comma = encoding.find(_XPLATSTR(","), n); + comma = encoding.find(_XPLATSTR(','), n); start = n; if (comma == utility::string_t::npos) { @@ -1076,9 +1083,9 @@ utility::string_t build_supported_header(header_types type, // Add all specified algorithms and their weights to the header start = true; - for (int i = 0; i < f.size(); i++) + os.imbue(std::locale::classic()); + for each (auto& factory in f) { - auto factory = f[i].get(); if (factory) { auto weight = factory->weight(); diff --git a/Release/src/http/common/internal_http_helpers.h b/Release/src/http/common/internal_http_helpers.h index 024ac84ac4..ef19612270 100644 --- a/Release/src/http/common/internal_http_helpers.h +++ b/Release/src/http/common/internal_http_helpers.h @@ -31,3 +31,19 @@ void trim_whitespace(std::basic_string &str) bool validate_method(const utility::string_t& method); }}} + +namespace web { namespace http { namespace compression { + +class compression::decompress_factory; + +namespace details { namespace builtin { + +/// +/// Helper function to get the set of built-in decompress factories +/// + +const std::vector> get_decompress_factories(); + +}} + +}}} diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index 2a49f2263f..e9cc9ef661 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -540,6 +540,7 @@ SUITE(compression_tests) _XPLATSTR(" chunked "), web::http::compression::details::header_types::transfer_encoding); VERIFY_IS_FALSE((bool)d); + utility::string_t gzip(web::http::compression::builtin::algorithm::GZIP); for (auto encoding = encodings.begin(); encoding != encodings.end(); encoding++) { bool has_comma = false; @@ -551,7 +552,7 @@ SUITE(compression_tests) VERIFY_ARE_EQUAL((bool)c, web::http::compression::builtin::supported()); if (c) { - VERIFY_ARE_EQUAL(c->algorithm(), web::http::compression::builtin::algorithm::GZIP); + VERIFY_ARE_EQUAL(c->algorithm(), gzip); } try @@ -560,7 +561,7 @@ SUITE(compression_tests) VERIFY_ARE_EQUAL((bool)d, web::http::compression::builtin::supported()); if (d) { - VERIFY_ARE_EQUAL(d->algorithm(), web::http::compression::builtin::algorithm::GZIP); + VERIFY_ARE_EQUAL(d->algorithm(), gzip); } } catch (http_exception) @@ -706,15 +707,15 @@ SUITE(compression_tests) if (fake) { // Switch built-in vs. supplied results the second time around - for (int i = 0; i < tes.size(); i++) + for (auto &te : tes) { - tes[i].replace(tes[i].find(web::http::compression::builtin::algorithm::GZIP), - web::http::compression::builtin::algorithm::GZIP.size(), + te.replace(te.find(web::http::compression::builtin::algorithm::GZIP), + gzip.size(), fake_provider::FAKE); - if (tes[i].find(web::http::compression::builtin::algorithm::DEFLATE) != utility::string_t::npos) + if (te.find(web::http::compression::builtin::algorithm::DEFLATE) != utility::string_t::npos) { - tes[i].replace(tes[i].find(web::http::compression::builtin::algorithm::DEFLATE), - web::http::compression::builtin::algorithm::DEFLATE.size(), + te.replace(te.find(web::http::compression::builtin::algorithm::DEFLATE), + utility::string_t(web::http::compression::builtin::algorithm::DEFLATE).size(), _NONE); } } @@ -728,7 +729,7 @@ SUITE(compression_tests) { VERIFY_IS_TRUE(web::http::compression::builtin::supported()); VERIFY_IS_FALSE((bool)fake); - VERIFY_ARE_EQUAL(c->algorithm(), web::http::compression::builtin::algorithm::GZIP); + VERIFY_ARE_EQUAL(c->algorithm(), gzip); } else { @@ -919,7 +920,7 @@ SUITE(compression_tests) // Test various buffer sizes for (int sz = 0; sz < sizeof(buffer_sizes) / sizeof(buffer_sizes[0]); sz++) { - std::vector algs; + std::vector algorithms; std::map> dmap; buffer_size = buffer_sizes[sz]; @@ -932,7 +933,7 @@ SUITE(compression_tests) if (web::http::compression::builtin::algorithm::supported( web::http::compression::builtin::algorithm::GZIP)) { - algs.push_back(web::http::compression::builtin::algorithm::GZIP); + algorithms.push_back(web::http::compression::builtin::algorithm::GZIP); dmap[web::http::compression::builtin::algorithm::GZIP] = web::http::compression::builtin::get_decompress_factory( web::http::compression::builtin::algorithm::GZIP); @@ -943,7 +944,7 @@ SUITE(compression_tests) if (web::http::compression::builtin::algorithm::supported( web::http::compression::builtin::algorithm::DEFLATE)) { - algs.push_back(web::http::compression::builtin::algorithm::DEFLATE); + algorithms.push_back(web::http::compression::builtin::algorithm::DEFLATE); dmap[web::http::compression::builtin::algorithm::DEFLATE] = web::http::compression::builtin::get_decompress_factory( web::http::compression::builtin::algorithm::DEFLATE); @@ -954,7 +955,7 @@ SUITE(compression_tests) if (web::http::compression::builtin::algorithm::supported( web::http::compression::builtin::algorithm::BROTLI)) { - algs.push_back(web::http::compression::builtin::algorithm::BROTLI); + algorithms.push_back(web::http::compression::builtin::algorithm::BROTLI); dmap[web::http::compression::builtin::algorithm::BROTLI] = web::http::compression::builtin::get_decompress_factory( web::http::compression::builtin::algorithm::BROTLI); @@ -962,7 +963,7 @@ SUITE(compression_tests) cfactories.push_back(web::http::compression::builtin::get_compress_factory( web::http::compression::builtin::algorithm::BROTLI)); } - algs.push_back(fake_provider::FAKE); + algorithms.push_back(fake_provider::FAKE); dmap[fake_provider::FAKE] = web::http::compression::make_decompress_factory( fake_provider::FAKE, 1000, @@ -1000,7 +1001,7 @@ SUITE(compression_tests) http_client client(m_uri, config); // Test supported compression algorithms - for (int alg = 0; alg < algs.size(); alg++) + for (auto& algorithm : algorithms) { // Test both GET and PUT for (int put = 0; put < 2; put++) @@ -1032,8 +1033,8 @@ SUITE(compression_tests) size_t used; pre.resize(v.size() + 128); - auto c = web::http::compression::builtin::make_compressor(algs[alg]); - if (algs[alg] == fake_provider::FAKE) + auto c = web::http::compression::builtin::make_compressor(algorithm); + if (algorithm == fake_provider::FAKE) { VERIFY_IS_FALSE((bool)c); c = std::make_unique(buffer_size); @@ -1055,9 +1056,8 @@ SUITE(compression_tests) pre.data(), got)); } - for (int str = 0; str < streams.size(); str++) + for (auto &stream : streams) { - concurrency::streams::istream& stream = streams[str]; http_request msg(methods::PUT); processed = false; @@ -1065,16 +1065,16 @@ SUITE(compression_tests) msg.set_body(stream); if (transfer) { - bool boo = msg.set_compressor(algs[alg]); - VERIFY_ARE_EQUAL(boo, algs[alg] != fake_provider::FAKE); - if (algs[alg] == fake_provider::FAKE) + bool boo = msg.set_compressor(algorithm); + VERIFY_ARE_EQUAL(boo, algorithm != fake_provider::FAKE); + if (algorithm == fake_provider::FAKE) { msg.set_compressor(std::make_unique(buffer_size)); } } else { - msg.headers().add(header_names::content_encoding, algs[alg]); + msg.headers().add(header_names::content_encoding, algorithm); } if (!real) @@ -1172,7 +1172,7 @@ SUITE(compression_tests) http_request msg(methods::GET); std::vector> df = { - dmap[algs[alg]]}; + dmap[algorithm]}; msg.set_decompress_factories(df); vv.resize(buffer_size + 128); // extra to ensure no overflow @@ -1205,7 +1205,7 @@ SUITE(compression_tests) // present done = p_request->match_header(header_names::accept_encoding, header); VERIFY_IS_TRUE(!done || - header.find(algs[alg]) == utility::string_t::npos); + header.find(algorithm) == utility::string_t::npos); done = p_request->match_header(header_names::te, header); if (done) { diff --git a/Release/tests/functional/http/client/request_helper_tests.cpp b/Release/tests/functional/http/client/request_helper_tests.cpp index fa3360756b..ee4ff762b6 100644 --- a/Release/tests/functional/http/client/request_helper_tests.cpp +++ b/Release/tests/functional/http/client/request_helper_tests.cpp @@ -95,12 +95,9 @@ TEST_FIXTURE(uri_address, do_not_send_accept_encoding) server.next_request().then([&found_accept_encoding](test_request *p_request) { utility::string_t header; - found_accept_encoding = p_request->match_header(header_names::accept_encoding, header); - if (found_accept_encoding) - { - // On Windows, someone along the way (not us!) adds "Accept-Encoding: peerdist" - found_accept_encoding = header != _XPLATSTR("peerdist"); - } + // On Windows, someone along the way (not us!) adds "Accept-Encoding: peerdist" + found_accept_encoding = + p_request->match_header(header_names::accept_encoding, header) && header != _XPLATSTR("peerdist"); p_request->reply(200, U("OK")); }); diff --git a/Release/tests/functional/http/utilities/include/test_http_server.h b/Release/tests/functional/http/utilities/include/test_http_server.h index 4b2ededbd5..8220f0b331 100644 --- a/Release/tests/functional/http/utilities/include/test_http_server.h +++ b/Release/tests/functional/http/utilities/include/test_http_server.h @@ -74,7 +74,7 @@ class test_request return false; } - return bind_impl(iter->second, header_value) || iter->second.empty(); + return web::http::details::bind_impl(iter->second, header_value) || iter->second.empty(); } // Request data. @@ -94,33 +94,6 @@ class test_request const std::map &headers, void * data, size_t data_length); - -private: - - template - bool bind_impl(const utility::string_t &text, T &ref) const - { - utility::istringstream_t iss(text); - iss.imbue(std::locale::classic()); - iss >> ref; - if (iss.fail() || !iss.eof()) - { - return false; - } - - return true; - } - - bool bind_impl(const utility::string_t &text, utf16string &ref) const - { - ref = utility::conversions::to_utf16string(text); - return true; - } - bool bind_impl(const utility::string_t &text, std::string &ref) const - { - ref = utility::conversions::to_utf8string(text); - return true; - } }; /// From ed94a6cddb46f2e216997b85bc6c1f04ffb510c6 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Mon, 8 Oct 2018 19:25:17 -0700 Subject: [PATCH 428/609] Fix build breaks on GCC 5.4, iOS, and OSX (#894) * Move up bind_impl so that it can be found by non-MSVC. * Avoid useless qualification making GCC unhappy. * Make GZIP/DEFLATE/BROTLI constant chars. * Remove unneeded ; * Remove broken qualification attempting to forward declare web::http::compression::decompress_factory. * Don't use nonstandard for each. * Remove another unnecessary const. * Mark unused parameters with (void). * Guard -Wno-format-truncation from GCC 5.4. * Fix bogus writtenSize warning from GCC 5.4. * Attempt to avoid std::make_unique in compression tests. * Avoid Concurrency::task_group_status because gcc 5.4 hates it for some reason. --- Release/CMakeLists.txt | 6 +- Release/include/cpprest/http_compression.h | 10 +-- Release/include/cpprest/http_headers.h | 62 +++++++++---------- Release/src/http/client/http_client_asio.cpp | 1 + Release/src/http/common/http_compression.cpp | 17 ++++- .../src/http/common/internal_http_helpers.h | 2 +- .../http/client/compression_tests.cpp | 45 +++++++------- 7 files changed, 80 insertions(+), 63 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 4a5bdef421..00fa7a7d11 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -187,7 +187,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR IOS) elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") message("-- Setting gcc options") - set(WARNINGS -Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code -Wno-format-truncation) + set(WARNINGS -Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code) + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6.0") + set(WARNINGS ${WARNINGS} -Wno-format-truncation) + endif() + set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") diff --git a/Release/include/cpprest/http_compression.h b/Release/include/cpprest/http_compression.h index 13b183af00..1993e6244c 100644 --- a/Release/include/cpprest/http_compression.h +++ b/Release/include/cpprest/http_compression.h @@ -96,7 +96,7 @@ class decompress_factory { public: virtual const utility::string_t& algorithm() const = 0; - virtual const uint16_t weight() const = 0; + virtual uint16_t weight() const = 0; virtual std::unique_ptr make_decompressor() const = 0; virtual ~decompress_factory() = default; }; @@ -117,9 +117,9 @@ _ASYNCRTIMP bool supported(); /// namespace algorithm { -constexpr utility::char_t *GZIP = _XPLATSTR("gzip"); -constexpr utility::char_t *DEFLATE = _XPLATSTR("deflate"); -constexpr utility::char_t *BROTLI = _XPLATSTR("br"); +constexpr const utility::char_t *GZIP = _XPLATSTR("gzip"); +constexpr const utility::char_t *DEFLATE = _XPLATSTR("deflate"); +constexpr const utility::char_t *BROTLI = _XPLATSTR("br"); /// /// Test whether cpprestsdk was built with built-in compression support and @@ -129,7 +129,7 @@ constexpr utility::char_t *BROTLI = _XPLATSTR("br"); /// the supplied string matches a supported built-in algorithm, and false if not. /// _ASYNCRTIMP bool supported(const utility::string_t& algorithm); -}; +} /// /// Factory function to instantiate a built-in compression provider with default parameters by compression algorithm diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 077266a7d5..3761940c8b 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -57,6 +57,37 @@ bool bind(const key_type &text, utility::string_t &ref) //const return true; } +namespace details +{ + template + bool bind_impl(const key_type &text, _t &ref) + { + utility::istringstream_t iss(text); + iss.imbue(std::locale::classic()); + iss >> ref; + if (iss.fail() || !iss.eof()) + { + return false; + } + + return true; + } + + template + bool bind_impl(const key_type &text, utf16string &ref) + { + ref = utility::conversions::to_utf16string(text); + return true; + } + + template + bool bind_impl(const key_type &text, std::string &ref) + { + ref = utility::conversions::to_utf8string(text); + return true; + } +} + /// /// Represents HTTP headers, acts like a map. /// @@ -288,35 +319,4 @@ class http_headers // Headers are stored in a map with case insensitive key. inner_container m_headers; }; - -namespace details -{ - template - bool bind_impl(const key_type &text, _t &ref) - { - utility::istringstream_t iss(text); - iss.imbue(std::locale::classic()); - iss >> ref; - if (iss.fail() || !iss.eof()) - { - return false; - } - - return true; - } - - template - bool bind_impl(const key_type &text, utf16string &ref) - { - ref = utility::conversions::to_utf16string(text); - return true; - } - - template - bool bind_impl(const key_type &text, std::string &ref) - { - ref = utility::conversions::to_utf8string(text); - return true; - } -} }} diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 7590497420..72e13f046c 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1754,6 +1754,7 @@ class asio_context final : public request_context, public std::enable_shared_fro .then([this_request, read_size, shared_decompressed AND_CAPTURE_MEMBER_FUNCTION_POINTERS]( pplx::task op) { size_t writtenSize = 0; + (void)writtenSize; try { writtenSize = op.get(); diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index e7e7f9a927..7fc229642d 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -620,7 +620,7 @@ class generic_decompress_factory : public decompress_factory const utility::string_t& algorithm() const { return m_algorithm; } - const uint16_t weight() const { return m_weight; } + uint16_t weight() const { return m_weight; } std::unique_ptr make_decompressor() const { return _make_decompressor(); } @@ -753,6 +753,10 @@ std::unique_ptr make_gzip_compressor(int compressionLevel, in #if defined(CPPREST_HTTP_COMPRESSION) return std::move(std::make_unique(compressionLevel, method, strategy, memLevel)); #else // CPPREST_HTTP_COMPRESSION + (void)compressionLevel; + (void)method; + (void)strategy; + (void)memLevel; return std::unique_ptr(); #endif // CPPREST_HTTP_COMPRESSION } @@ -762,6 +766,10 @@ std::unique_ptr make_deflate_compressor(int compressionLevel, #if defined(CPPREST_HTTP_COMPRESSION) return std::move(std::make_unique(compressionLevel, method, strategy, memLevel)); #else // CPPREST_HTTP_COMPRESSION + (void)compressionLevel; + (void)method; + (void)strategy; + (void)memLevel; return std::unique_ptr(); #endif // CPPREST_HTTP_COMPRESSION } @@ -771,6 +779,9 @@ std::unique_ptr make_brotli_compressor(uint32_t window, uint3 #if defined(CPPREST_HTTP_COMPRESSION) && defined(CPPREST_BROTLI_COMPRESSION) return std::move(std::make_unique(window, quality, mode)); #else // CPPREST_BROTLI_COMPRESSION + (void)window; + (void)quality; + (void)mode; return std::unique_ptr(); #endif // CPPREST_BROTLI_COMPRESSION } @@ -800,7 +811,7 @@ const std::vector> get_decompress_factories( } } // namespace builtin -static bool is_http_whitespace(utility::char_t ch) { return ch == _XPLATSTR(' ') || ch == _XPLATSTR('\t'); } +static bool is_http_whitespace(const utility::char_t ch) { return ch == _XPLATSTR(' ') || ch == _XPLATSTR('\t'); } static void remove_surrounding_http_whitespace(const utility::string_t& encoding, size_t& start, size_t& length) { @@ -1084,7 +1095,7 @@ utility::string_t build_supported_header(header_types type, // Add all specified algorithms and their weights to the header start = true; os.imbue(std::locale::classic()); - for each (auto& factory in f) + for (auto& factory : f) { if (factory) { diff --git a/Release/src/http/common/internal_http_helpers.h b/Release/src/http/common/internal_http_helpers.h index ef19612270..76b4f4f4da 100644 --- a/Release/src/http/common/internal_http_helpers.h +++ b/Release/src/http/common/internal_http_helpers.h @@ -34,7 +34,7 @@ bool validate_method(const utility::string_t& method); namespace web { namespace http { namespace compression { -class compression::decompress_factory; +class decompress_factory; namespace details { namespace builtin { diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index e9cc9ef661..ca2215afd9 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -13,6 +13,7 @@ #include "cpprest/details/http_helpers.h" #include "cpprest/version.h" +#include "cpprest/asyncrt_utils.h" #include "stdafx.h" #include @@ -202,7 +203,7 @@ SUITE(compression_tests) std::vector dcmp_buffer; web::http::compression::operation_result r; std::vector chunk_sizes; - Concurrency::task_group_status result; + pplx::task_status result; size_t csize; size_t dsize; size_t i; @@ -210,8 +211,8 @@ SUITE(compression_tests) if (algorithm == fake_provider::FAKE) { - compressor = std::make_unique(buffer_size); - decompressor = std::make_unique(buffer_size); + compressor = utility::details::make_unique(buffer_size); + decompressor = utility::details::make_unique(buffer_size); } else { @@ -247,7 +248,7 @@ SUITE(compression_tests) web::http::compression::operation_hint::has_more) .then([&r](web::http::compression::operation_result x) { r = x; }) .wait(); - VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(result, pplx::task_status::completed); VERIFY_ARE_EQUAL(r.input_bytes_processed, std::min(chunk_size, buffer_size - i)); VERIFY_ARE_EQUAL(r.done, false); chunk_sizes.push_back(r.output_bytes_produced); @@ -272,7 +273,7 @@ SUITE(compression_tests) web::http::compression::operation_hint::is_last) .then([&r](web::http::compression::operation_result x) { r = x; }) .wait(); - VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(result, pplx::task_status::completed); VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); chunk_sizes.push_back(r.output_bytes_produced); csize += r.output_bytes_produced; @@ -283,7 +284,7 @@ SUITE(compression_tests) result = compressor->compress(NULL, 0, NULL, 0, web::http::compression::operation_hint::is_last) .then([&r](web::http::compression::operation_result x) { r = x; }) .wait(); - VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(result, pplx::task_status::completed); VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); VERIFY_ARE_EQUAL(r.output_bytes_produced, 0); VERIFY_ARE_EQUAL(r.done, true); @@ -311,7 +312,7 @@ SUITE(compression_tests) hint) .then([&r](web::http::compression::operation_result x) { r = x; }) .wait(); - VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(result, pplx::task_status::completed); nn += *it; dsize += r.output_bytes_produced; } @@ -339,7 +340,7 @@ SUITE(compression_tests) web::http::compression::operation_hint::has_more) .then([&r](web::http::compression::operation_result x) { r = x; }) .wait(); - VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(result, pplx::task_status::completed); dsize += r.output_bytes_produced; nn += r.input_bytes_processed; n -= r.input_bytes_processed; @@ -354,7 +355,7 @@ SUITE(compression_tests) result = decompressor->decompress(NULL, 0, NULL, 0, web::http::compression::operation_hint::has_more) .then([&r](web::http::compression::operation_result x) { r = x; }) .wait(); - VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(result, pplx::task_status::completed); VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); VERIFY_ARE_EQUAL(r.output_bytes_produced, 0); VERIFY_IS_TRUE(r.done); @@ -370,7 +371,7 @@ SUITE(compression_tests) web::http::compression::operation_hint::is_last) .then([&r](web::http::compression::operation_result x) { r = x; }) .wait(); - VERIFY_ARE_EQUAL(result, Concurrency::task_group_status::completed); + VERIFY_ARE_EQUAL(result, pplx::task_status::completed); VERIFY_ARE_EQUAL(r.output_bytes_produced, buffer_size); VERIFY_ARE_EQUAL(input_buffer, dcmp_buffer); @@ -448,28 +449,28 @@ SUITE(compression_tests) std::shared_ptr fcf = web::http::compression::make_compress_factory( fake_provider::FAKE, []() -> std::unique_ptr { - return std::make_unique(); + return utility::details::make_unique(); }); std::vector> fcv; fcv.push_back(fcf); std::shared_ptr fdf = web::http::compression::make_decompress_factory( fake_provider::FAKE, 800, []() -> std::unique_ptr { - return std::make_unique(); + return utility::details::make_unique(); }); std::vector> fdv; fdv.push_back(fdf); std::shared_ptr ncf = web::http::compression::make_compress_factory( _NONE, []() -> std::unique_ptr { - return std::make_unique(); + return utility::details::make_unique(); }); std::vector> ncv; ncv.push_back(ncf); std::shared_ptr ndf = web::http::compression::make_decompress_factory( _NONE, 800, []() -> std::unique_ptr { - return std::make_unique(); + return utility::details::make_unique(); }); std::vector> ndv; ndv.push_back(ndf); @@ -794,7 +795,7 @@ SUITE(compression_tests) { test_http_server* p_server = nullptr; std::unique_ptr scoped = - std::move(std::make_unique(m_uri)); + std::move(utility::details::make_unique(m_uri)); scoped->server()->next_request().then([&skip_transfer_put](pplx::task op) { try { @@ -810,7 +811,7 @@ SUITE(compression_tests) http_client client(m_uri); http_request msg(methods::PUT); - msg.set_compressor(std::make_unique(0)); + msg.set_compressor(utility::details::make_unique(0)); msg.set_body(concurrency::streams::rawptr_stream::open_istream((const uint8_t*)nullptr, 0)); http_response rsp = client.request(msg).get(); rsp.content_ready().wait(); @@ -872,7 +873,7 @@ SUITE(compression_tests) if (encoding.find(fake_provider::FAKE) != utility::string_t::npos) { // This one won't be found in the server's default set... - rsp._get_impl()->set_compressor(std::make_unique(buffer_size)); + rsp._get_impl()->set_compressor(utility::details::make_unique(buffer_size)); } #endif // _WIN32 rsp.set_body( @@ -913,7 +914,7 @@ SUITE(compression_tests) } else { - scoped = std::move(std::make_unique(m_uri)); + scoped = std::move(utility::details::make_unique(m_uri)); p_server = scoped->server(); } @@ -968,12 +969,12 @@ SUITE(compression_tests) fake_provider::FAKE, 1000, [buffer_size]() -> std::unique_ptr { - return std::make_unique(buffer_size); + return utility::details::make_unique(buffer_size); }); dfactories.push_back(dmap[fake_provider::FAKE]); cfactories.push_back(web::http::compression::make_compress_factory( fake_provider::FAKE, [buffer_size]() -> std::unique_ptr { - return std::make_unique(buffer_size); + return utility::details::make_unique(buffer_size); })); v.resize(buffer_size); @@ -1037,7 +1038,7 @@ SUITE(compression_tests) if (algorithm == fake_provider::FAKE) { VERIFY_IS_FALSE((bool)c); - c = std::make_unique(buffer_size); + c = utility::details::make_unique(buffer_size); } VERIFY_IS_TRUE((bool)c); auto got = c->compress(v.data(), @@ -1069,7 +1070,7 @@ SUITE(compression_tests) VERIFY_ARE_EQUAL(boo, algorithm != fake_provider::FAKE); if (algorithm == fake_provider::FAKE) { - msg.set_compressor(std::make_unique(buffer_size)); + msg.set_compressor(utility::details::make_unique(buffer_size)); } } else From fba9a5945a166d695c854454d85f3f47a69f9d9e Mon Sep 17 00:00:00 2001 From: copterquad <43890166+copterquad@users.noreply.github.com> Date: Tue, 9 Oct 2018 07:56:45 +0530 Subject: [PATCH 429/609] typo a an -> an (#886) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6b0934320..32374d716a 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Big or small we'd like to take your [contributions](https://github.com/Microsoft ## Having Trouble? -We'd love to get your review score, whether good or bad, but even more than that, we want to fix your problem. If you submit your issue as a Review, we won't be able to respond to your problem and ask any follow-up questions that may be necessary. The most efficient way to do that is to open a an issue in our [issue tracker](https://github.com/Microsoft/cpprestsdk/issues). +We'd love to get your review score, whether good or bad, but even more than that, we want to fix your problem. If you submit your issue as a Review, we won't be able to respond to your problem and ask any follow-up questions that may be necessary. The most efficient way to do that is to open an issue in our [issue tracker](https://github.com/Microsoft/cpprestsdk/issues). ### Quick Links From 98550a4e5db3379db76f1948d5c7c19c2367e3f4 Mon Sep 17 00:00:00 2001 From: Christian <43907599+chris0x44@users.noreply.github.com> Date: Tue, 9 Oct 2018 04:28:31 +0200 Subject: [PATCH 430/609] Correct exception messages and comments in asyncrt_utils (#889) --- Release/src/utilities/asyncrt_utils.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 3faffd1e40..e971c3c544 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -374,7 +374,7 @@ inline size_t count_utf8_to_utf16(const std::string& s) const char c2{ sData[index++] }; if ((c2 & 0xC0) != BIT8) { - throw std::range_error("UTF-8 continuation byte is missing leading byte"); + throw std::range_error("UTF-8 continuation byte is missing leading bit mask"); } // can't require surrogates for 7FF @@ -391,7 +391,7 @@ inline size_t count_utf8_to_utf16(const std::string& s) const char c3{ sData[index++] }; if (((c2 | c3) & 0xC0) != BIT8) { - throw std::range_error("UTF-8 continuation byte is missing leading byte"); + throw std::range_error("UTF-8 continuation byte is missing leading bit mask"); } result -= 2; @@ -408,7 +408,7 @@ inline size_t count_utf8_to_utf16(const std::string& s) const char c4{ sData[index++] }; if (((c2 | c3 | c4) & 0xC0) != BIT8) { - throw std::range_error("UTF-8 continuation byte is missing leading byte"); + throw std::range_error("UTF-8 continuation byte is missing leading bit mask"); } const uint32_t codePoint = ((c & LOW_3BITS) << 18) | ((c2 & LOW_6BITS) << 12) | ((c3 & LOW_6BITS) << 6) | (c4 & LOW_6BITS); @@ -500,7 +500,7 @@ inline size_t count_utf16_to_utf8(const utf16string &w) } } // Check for high surrogate. - else if (ch >= H_SURROGATE_START && ch <= H_SURROGATE_END) // 4 bytes need using 21 bits + else if (ch >= H_SURROGATE_START && ch <= H_SURROGATE_END) // 4 bytes needed (21 bits used) { ++index; if (index == srcSize) @@ -555,8 +555,8 @@ std::string __cdecl conversions::utf16_to_utf8(const utf16string &w) const auto lowSurrogate = srcData[++index]; // To get from surrogate pair to Unicode code point: - // - subract 0xD800 from high surrogate, this forms top ten bits - // - subract 0xDC00 from low surrogate, this forms low ten bits + // - subtract 0xD800 from high surrogate, this forms top ten bits + // - subtract 0xDC00 from low surrogate, this forms low ten bits // - add 0x10000 // Leaves a code point in U+10000 to U+10FFFF range. uint32_t codePoint = highSurrogate - H_SURROGATE_START; @@ -564,7 +564,7 @@ std::string __cdecl conversions::utf16_to_utf8(const utf16string &w) codePoint |= lowSurrogate - L_SURROGATE_START; codePoint += SURROGATE_PAIR_START; - // 4 bytes need using 21 bits + // 4 bytes needed (21 bits used) destData[destIndex++] = static_cast((codePoint >> 18) | 0xF0); // leading 3 bits destData[destIndex++] = static_cast(((codePoint >> 12) & LOW_6BITS) | BIT8); // next 6 bits destData[destIndex++] = static_cast(((codePoint >> 6) & LOW_6BITS) | BIT8); // next 6 bits @@ -592,6 +592,8 @@ utf16string __cdecl conversions::latin1_to_utf16(const std::string &s) // Latin1 is the first 256 code points in Unicode. // In UTF-16 encoding each of these is represented as exactly the numeric code point. utf16string dest; + // Prefer resize combined with for-loop over constructor dest(s.begin(), s.end()) + // for faster assignment. dest.resize(s.size()); for (size_t i = 0; i < s.size(); ++i) { From 948b70b5b56c5501786e47f5aa95f235f9af4be2 Mon Sep 17 00:00:00 2001 From: mobileben Date: Mon, 8 Oct 2018 19:41:23 -0700 Subject: [PATCH 431/609] Various fixes on #866 which broke building for iOS and Mac (#888) * Various fixes on #866 which broke building for iOS and Mac * Remove trailing semicolon from namespace since flags error when building on Ubuntu * Ubuntu builds needs to factor in unused arguments/variables * Remove trailing spaces from empty lines * Remove duplicate bind_impls. * Fix some merge fallout with master. --- Release/include/cpprest/http_headers.h | 3 +- Release/src/http/common/http_compression.cpp | 35 ++++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Release/include/cpprest/http_headers.h b/Release/include/cpprest/http_headers.h index 3761940c8b..34f0122b3f 100644 --- a/Release/include/cpprest/http_headers.h +++ b/Release/include/cpprest/http_headers.h @@ -18,7 +18,6 @@ #include "cpprest/asyncrt_utils.h" namespace web { namespace http { - /// /// Binds an individual reference to a string value. /// @@ -250,7 +249,7 @@ class http_headers return false; } - return details::bind_impl(iter->second, value) || iter->second.empty(); + return web::http::details::bind_impl(iter->second, value) || iter->second.empty(); } /// diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index 7fc229642d..194f1efc97 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -156,7 +156,7 @@ class zlib_compressor_base : public compress_provider private: int m_state{Z_BUF_ERROR}; - z_stream m_stream{0}; + z_stream m_stream{}; const utility::string_t& m_algorithm; }; @@ -263,7 +263,7 @@ class zlib_decompressor_base : public decompress_provider private: int m_state{Z_BUF_ERROR}; - z_stream m_stream{0}; + z_stream m_stream{}; const utility::string_t& m_algorithm; }; @@ -283,7 +283,7 @@ class gzip_compressor : public zlib_compressor_base class gzip_decompressor : public zlib_decompressor_base { public: - gzip_decompressor::gzip_decompressor() : zlib_decompressor_base(16) // gzip auto-detect + gzip_decompressor() : zlib_decompressor_base(16) // gzip auto-detect { } }; @@ -634,14 +634,14 @@ class generic_decompress_factory : public decompress_factory static const std::vector> g_compress_factories #if defined(CPPREST_HTTP_COMPRESSION) = {std::make_shared( - algorithm::GZIP, []() -> std::unique_ptr { return std::make_unique(); }), + algorithm::GZIP, []() -> std::unique_ptr { return utility::details::make_unique(); }), std::make_shared( algorithm::DEFLATE, - []() -> std::unique_ptr { return std::make_unique(); }), + []() -> std::unique_ptr { return utility::details::make_unique(); }), #if defined(CPPREST_BROTLI_COMPRESSION) std::make_shared( algorithm::BROTLI, - []() -> std::unique_ptr { return std::make_unique(); }) + []() -> std::unique_ptr { return utility::details::make_unique(); }) #endif // CPPREST_BROTLI_COMPRESSION }; #else // CPPREST_HTTP_COMPRESSION @@ -653,16 +653,16 @@ static const std::vector> g_decompress_facto = {std::make_shared( algorithm::GZIP, 500, - []() -> std::unique_ptr { return std::make_unique(); }), + []() -> std::unique_ptr { return utility::details::make_unique(); }), std::make_shared( algorithm::DEFLATE, 500, - []() -> std::unique_ptr { return std::make_unique(); }), + []() -> std::unique_ptr { return utility::details::make_unique(); }), #if defined(CPPREST_BROTLI_COMPRESSION) std::make_shared( algorithm::BROTLI, 500, - []() -> std::unique_ptr { return std::make_unique(); }) + []() -> std::unique_ptr { return utility::details::make_unique(); }) #endif // CPPREST_BROTLI_COMPRESSION }; #else // CPPREST_HTTP_COMPRESSION @@ -748,10 +748,11 @@ std::shared_ptr get_decompress_factory(const utility::string return std::shared_ptr(); } + std::unique_ptr make_gzip_compressor(int compressionLevel, int method, int strategy, int memLevel) { #if defined(CPPREST_HTTP_COMPRESSION) - return std::move(std::make_unique(compressionLevel, method, strategy, memLevel)); + return utility::details::make_unique(compressionLevel, method, strategy, memLevel); #else // CPPREST_HTTP_COMPRESSION (void)compressionLevel; (void)method; @@ -760,11 +761,11 @@ std::unique_ptr make_gzip_compressor(int compressionLevel, in return std::unique_ptr(); #endif // CPPREST_HTTP_COMPRESSION } - + std::unique_ptr make_deflate_compressor(int compressionLevel, int method, int strategy, int memLevel) { #if defined(CPPREST_HTTP_COMPRESSION) - return std::move(std::make_unique(compressionLevel, method, strategy, memLevel)); + return utility::details::make_unique(compressionLevel, method, strategy, memLevel); #else // CPPREST_HTTP_COMPRESSION (void)compressionLevel; (void)method; @@ -777,7 +778,7 @@ std::unique_ptr make_deflate_compressor(int compressionLevel, std::unique_ptr make_brotli_compressor(uint32_t window, uint32_t quality, uint32_t mode) { #if defined(CPPREST_HTTP_COMPRESSION) && defined(CPPREST_BROTLI_COMPRESSION) - return std::move(std::make_unique(window, quality, mode)); + return utility::details::make_unique(window, quality, mode); #else // CPPREST_BROTLI_COMPRESSION (void)window; (void)quality; @@ -962,7 +963,7 @@ std::unique_ptr get_compressor_from_header( if (compressor) { - return std::move(compressor); + return compressor; } // If we're here, we didn't match the caller's compressor above; @@ -976,7 +977,7 @@ std::unique_ptr get_compressor_from_header( auto compressor = web::http::compression::builtin::_make_compressor(f, coding); if (compressor) { - return std::move(compressor); + return compressor; } if (type == header_types::accept_encoding && utility::details::str_iequal(coding, _XPLATSTR("identity"))) { @@ -1079,7 +1080,7 @@ std::unique_ptr get_decompressor_from_header( // Either the response is compressed and we have a decompressor that can handle it, or // built-in compression is not enabled and we don't have an alternate set of decompressors - return std::move(decompressor); + return decompressor; } utility::string_t build_supported_header(header_types type, @@ -1120,7 +1121,7 @@ utility::string_t build_supported_header(header_types type, os << _XPLATSTR("identity;q=1, *;q=0"); } - return std::move(os.str()); + return os.str(); } } // namespace details } // namespace compression From b211145688802492e4783478e51758156cfc2f59 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Mon, 8 Oct 2018 19:44:59 -0700 Subject: [PATCH 432/609] Fix narrowing conversion warnings on Windows. (#895) --- Release/src/http/client/http_client_winhttp.cpp | 2 +- Release/src/http/common/http_msg.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 0a135d039e..ab415bb8b4 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -1583,7 +1583,7 @@ class winhttp_client final : public _http_client_communicator else if (length > p_request_context->m_remaining_to_write) { // The stream grew, but we won't - length = p_request_context->m_remaining_to_write; + length = static_cast(p_request_context->m_remaining_to_write); } do_compress(pplx::task_from_result(length)).then(after_read); diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index d17d09dcef..7a80017828 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -319,7 +319,7 @@ size_t http_msg_base::_get_stream_length() auto offset = stream.tell(); auto end = stream.seek(0, std::ios_base::end); stream.seek(offset); - return static_cast(end - offset); + return static_cast(end - offset); } return std::numeric_limits::max(); From eadff24ec83e2a3449deabb424ae2104b8fedb31 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 9 Oct 2018 12:12:53 -0700 Subject: [PATCH 433/609] Harden winrt_encryption slightly and avoid a potential reallocation. (#896) --- Release/src/json/json_parsing.cpp | 2 +- Release/src/utilities/web_utilities.cpp | 61 ++++++++++++++----------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index 13ecb5437c..295bd6e16a 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -1026,7 +1026,7 @@ std::unique_ptr JSON_Parser::_ParseObject( ::std::sort(elems.begin(), elems.end(), json::object::compare_pairs); } - return std::move(obj); + return obj; error: if (!tkn.m_error) diff --git a/Release/src/utilities/web_utilities.cpp b/Release/src/utilities/web_utilities.cpp index f17b5ab099..7ac9d306a2 100644 --- a/Release/src/utilities/web_utilities.cpp +++ b/Release/src/utilities/web_utilities.cpp @@ -12,6 +12,7 @@ ****/ #include "stdafx.h" +#include #if defined(_WIN32) && !defined(__cplusplus_winrt) #include @@ -92,23 +93,28 @@ plaintext_string winrt_encryption::decrypt() const win32_encryption::win32_encryption(const std::wstring &data) : m_numCharacters(data.size()) { - // Early return because CryptProtectMemory crashs with empty string + // Early return because CryptProtectMemory crashes with empty string if (m_numCharacters == 0) { return; } - const auto dataNumBytes = data.size() * sizeof(std::wstring::value_type); - m_buffer.resize(dataNumBytes); - memcpy_s(m_buffer.data(), m_buffer.size(), data.c_str(), dataNumBytes); - - // Buffer must be a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE - const auto mod = m_buffer.size() % CRYPTPROTECTMEMORY_BLOCK_SIZE; - if (mod != 0) + if (data.size() > (std::numeric_limits::max)() / sizeof(wchar_t)) { - m_buffer.resize(m_buffer.size() + CRYPTPROTECTMEMORY_BLOCK_SIZE - mod); + throw std::length_error("Encryption string too long"); } - if (!CryptProtectMemory(m_buffer.data(), static_cast(m_buffer.size()), CRYPTPROTECTMEMORY_SAME_PROCESS)) + + const auto dataSizeDword = static_cast(data.size() * sizeof(wchar_t)); + + // Round up dataSizeDword to be a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE + static_assert(CRYPTPROTECTMEMORY_BLOCK_SIZE == 16, "Power of 2 assumptions in this bit masking violated"); + const auto mask = static_cast(CRYPTPROTECTMEMORY_BLOCK_SIZE - 1u); + const auto dataNumBytes = (dataSizeDword & ~mask) + ((dataSizeDword & mask) != 0) * CRYPTPROTECTMEMORY_BLOCK_SIZE; + assert((dataNumBytes % CRYPTPROTECTMEMORY_BLOCK_SIZE) == 0); + assert(dataNumBytes >= dataSizeDword); + m_buffer.resize(dataNumBytes); + memcpy_s(m_buffer.data(), m_buffer.size(), data.c_str(), dataNumBytes); + if (!CryptProtectMemory(m_buffer.data(), dataNumBytes, CRYPTPROTECTMEMORY_SAME_PROCESS)) { throw ::utility::details::create_system_error(GetLastError()); } @@ -121,20 +127,25 @@ win32_encryption::~win32_encryption() plaintext_string win32_encryption::decrypt() const { - if (m_buffer.empty()) - return plaintext_string(new std::wstring()); - // Copy the buffer and decrypt to avoid having to re-encrypt. - auto data = plaintext_string(new std::wstring(reinterpret_cast(m_buffer.data()), m_buffer.size() / 2)); - if (!CryptUnprotectMemory( - const_cast(data->c_str()), - static_cast(m_buffer.size()), - CRYPTPROTECTMEMORY_SAME_PROCESS)) - { - throw ::utility::details::create_system_error(GetLastError()); + auto result = plaintext_string(new std::wstring( + reinterpret_cast(m_buffer.data()), m_buffer.size() / sizeof(wchar_t))); + auto& data = *result; + if (!m_buffer.empty()) { + if (!CryptUnprotectMemory( + &data[0], + static_cast(m_buffer.size()), + CRYPTPROTECTMEMORY_SAME_PROCESS)) + { + throw ::utility::details::create_system_error(GetLastError()); + } + + assert(m_numCharacters <= m_buffer.size()); + SecureZeroMemory(&data[m_numCharacters], data.size() - m_numCharacters); + data.erase(m_numCharacters); } - data->resize(m_numCharacters); - return std::move(data); + + return result; } #endif #endif @@ -143,12 +154,10 @@ void zero_memory_deleter::operator()(::utility::string_t *data) const { CASABLANCA_UNREFERENCED_PARAMETER(data); #if defined(_WIN32) - SecureZeroMemory( - const_cast<::utility::string_t::value_type *>(data->data()), - data->size() * sizeof(::utility::string_t::value_type)); + SecureZeroMemory(&(*data)[0], data->size() * sizeof(::utility::string_t::value_type)); delete data; #endif } } -} \ No newline at end of file +} From 40eb6d22d06fc7efa545c30f4a9473aab8cc0d6e Mon Sep 17 00:00:00 2001 From: Juan Eugenio Abadie Date: Tue, 9 Oct 2018 16:25:45 -0300 Subject: [PATCH 434/609] Remove unused variables to avoid warnings in some compilers (#855) --- Release/include/cpprest/base_uri.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index b5fc8fcfd0..687844dbb4 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -29,8 +29,8 @@ namespace web { { uri_components() : m_path(_XPLATSTR("/")), m_port(-1) {} - uri_components(const uri_components &other) = default; - uri_components & operator=(const uri_components &other) = default; + uri_components(const uri_components &) = default; + uri_components & operator=(const uri_components &) = default; // This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped. uri_components(uri_components &&other) CPPREST_NOEXCEPT : @@ -209,12 +209,12 @@ namespace web { /// /// Copy constructor. /// - uri(const uri &other) = default; + uri(const uri &) = default; /// /// Copy assignment operator. /// - uri & operator=(const uri &other) = default; + uri & operator=(const uri &) = default; /// /// Move constructor. From 81eb4cfc5c3645c10d025507ba22677cf4037abc Mon Sep 17 00:00:00 2001 From: Christian <43907599+chris0x44@users.noreply.github.com> Date: Tue, 9 Oct 2018 21:36:41 +0200 Subject: [PATCH 435/609] Enable multi-processor compilation (#890) --- Release/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 00fa7a7d11..4bf08ef820 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -204,6 +204,11 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(WARNINGS) set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4264") add_compile_options(/bigobj) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MP") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MP") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MP") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MP") + if (WINDOWS_STORE OR WINDOWS_PHONE) add_compile_options(/ZW) endif() From 2aa4a641b61c6d9d805c7a85b649671d4b55cd27 Mon Sep 17 00:00:00 2001 From: Christian <43907599+chris0x44@users.noreply.github.com> Date: Tue, 9 Oct 2018 23:20:23 +0200 Subject: [PATCH 436/609] Enable precompiled headers for test/functional (#891) --- Release/tests/functional/http/client/CMakeLists.txt | 13 +++++++++++++ Release/tests/functional/json/CMakeLists.txt | 13 +++++++++++++ .../tests/functional/pplx/pplx_test/CMakeLists.txt | 13 +++++++++++++ Release/tests/functional/streams/CMakeLists.txt | 13 +++++++++++++ Release/tests/functional/uri/CMakeLists.txt | 13 +++++++++++++ Release/tests/functional/utils/CMakeLists.txt | 13 +++++++++++++ 6 files changed, 78 insertions(+) diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 17cf4eff81..1cf9b6e6f5 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -32,6 +32,19 @@ else() target_link_libraries(httpclient_test PRIVATE httptest_utilities) endif() +if(MSVC) + get_target_property(_srcs httpclient_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + target_sources(httpclient_test PRIVATE stdafx.cpp) + target_compile_options(httpclient_test PRIVATE /Yustdafx.h /Zm200) +endif() + if(NOT WIN32) cpprest_find_boost() target_link_libraries(httpclient_test PRIVATE cpprestsdk_boost_internal) diff --git a/Release/tests/functional/json/CMakeLists.txt b/Release/tests/functional/json/CMakeLists.txt index 379a6bd4bf..c9dccfcfeb 100644 --- a/Release/tests/functional/json/CMakeLists.txt +++ b/Release/tests/functional/json/CMakeLists.txt @@ -16,3 +16,16 @@ if(UNIX AND NOT APPLE) cpprest_find_boost() target_link_libraries(json_test PRIVATE cpprestsdk_boost_internal) endif() + +if(MSVC) + get_target_property(_srcs json_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + target_sources(json_test PRIVATE stdafx.cpp) + target_compile_options(json_test PRIVATE /Yustdafx.h /Zm200) +endif() diff --git a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt index 01c56f7522..a51776989b 100644 --- a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt +++ b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt @@ -6,3 +6,16 @@ set(SOURCES ) add_casablanca_test(pplx_test SOURCES) + +if(MSVC) + get_target_property(_srcs pplx_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + target_sources(pplx_test PRIVATE stdafx.cpp) + target_compile_options(pplx_test PRIVATE /Yustdafx.h /Zm200) +endif() diff --git a/Release/tests/functional/streams/CMakeLists.txt b/Release/tests/functional/streams/CMakeLists.txt index 4b11173b18..d2b6858f15 100644 --- a/Release/tests/functional/streams/CMakeLists.txt +++ b/Release/tests/functional/streams/CMakeLists.txt @@ -24,3 +24,16 @@ if(NOT WIN32 OR CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") target_include_directories(streams_test PRIVATE $) endif() endif() + +if(MSVC) + get_target_property(_srcs streams_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + target_sources(streams_test PRIVATE stdafx.cpp) + target_compile_options(streams_test PRIVATE /Yustdafx.h /Zm200) +endif() diff --git a/Release/tests/functional/uri/CMakeLists.txt b/Release/tests/functional/uri/CMakeLists.txt index f869e24d18..86cd0e867a 100644 --- a/Release/tests/functional/uri/CMakeLists.txt +++ b/Release/tests/functional/uri/CMakeLists.txt @@ -12,3 +12,16 @@ set(SOURCES ) add_casablanca_test(uri_test SOURCES) + +if(MSVC) + get_target_property(_srcs uri_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + target_sources(uri_test PRIVATE stdafx.cpp) + target_compile_options(uri_test PRIVATE /Yustdafx.h /Zm200) +endif() diff --git a/Release/tests/functional/utils/CMakeLists.txt b/Release/tests/functional/utils/CMakeLists.txt index ff175283f8..ff5d4cb49c 100644 --- a/Release/tests/functional/utils/CMakeLists.txt +++ b/Release/tests/functional/utils/CMakeLists.txt @@ -13,3 +13,16 @@ add_casablanca_test(utils_test SOURCES) if(CMAKE_COMPILER_IS_GNUCXX) target_compile_options(utils_test PRIVATE "-Wno-deprecated-declarations") endif() + +if(MSVC) + get_target_property(_srcs utils_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") + target_sources(utils_test PRIVATE stdafx.cpp) + target_compile_options(utils_test PRIVATE /Yustdafx.h /Zm200) +endif() From 19c9f1c602efbc754d11890ba8e86afc2a8ba138 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 9 Oct 2018 16:51:40 -0700 Subject: [PATCH 437/609] Add Ubuntu 16.04 Azure Pipelines Validation (#898) --- azure-pipelines.yml | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000..dab028e6fa --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,41 @@ +# CppRestSdk Azure Pipelines Configuration + +jobs: + - job: Ubuntu_1604_Apt_Debug + pool: + vmImage: 'Ubuntu 16.04' + steps: + - script: | + sudo apt-get install -y ppa-purge + sudo ppa-purge -y ppa:ondrej/php + sudo apt-get install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev brotli openssl libssl-dev ninja-build + displayName: Apt install dependencies + - script: mkdir build.debug + displayName: Make build.debug + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' + - script: | + cd build.debug + ninja -j 2 + displayName: 'Run ninja' + - job: Ubuntu_1604_Apt_Release + pool: + vmImage: 'Ubuntu 16.04' + steps: + - script: | + sudo apt-get install -y ppa-purge + sudo ppa-purge -y ppa:ondrej/php + sudo apt-get install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev brotli openssl libssl-dev ninja-build + displayName: Apt install dependencies + - script: mkdir build.release + displayName: Make build.release + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' + - script: | + cd build.release + ninja -j 2 + displayName: 'Run ninja' From 625c666eb6b6002793dd77e3f70eda10c83d5f8e Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 9 Oct 2018 16:58:10 -0700 Subject: [PATCH 438/609] Add Azure Pipelines badge. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 32374d716a..6739483ebf 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ The C++ REST SDK is a Microsoft project for cloud-based client-server communicat [![openSUSE Tumbleweed package](https://repology.org/badge/version-for-repo/opensuse_tumbleweed/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
[![Debian Testing package](https://repology.org/badge/version-for-repo/debian_testing/cpprestsdk.svg)](https://repology.org/metapackage/cpprestsdk)
+[![Build Status](https://dev.azure.com/vclibs/cpprestsdk/_apis/build/status/Microsoft.cpprestsdk.Ubuntu)](https://dev.azure.com/vclibs/cpprestsdk/_build/latest?definitionId=1) + With [vcpkg](https://github.com/Microsoft/vcpkg) on Windows ``` PS> vcpkg install cpprestsdk cpprestsdk:x64-windows From b0ebae3591c7e407feeb289202340d1842c87c8a Mon Sep 17 00:00:00 2001 From: paul Date: Thu, 11 Oct 2018 01:05:37 +0300 Subject: [PATCH 439/609] Added URI resolution according to RFC3986 (#897) Added URI resolution according to RFC3986, Section 5 (https://tools.ietf.org/html/rfc3986#section-5) --- Release/include/cpprest/base_uri.h | 12 +- Release/src/uri/uri.cpp | 123 +++++++++++++++++- Release/tests/functional/uri/CMakeLists.txt | 1 + .../functional/uri/resolve_uri_tests.cpp | 68 ++++++++++ 4 files changed, 195 insertions(+), 9 deletions(-) create mode 100644 Release/tests/functional/uri/resolve_uri_tests.cpp diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index 687844dbb4..9448bb5d35 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -379,12 +379,20 @@ namespace web { /// /// Returns the full (encoded) URI as a string. /// - /// The full encoded URI string. + /// The full encoded URI string. utility::string_t to_string() const { return m_uri; } + /// + /// Returns an URI resolved against this as the base URI + /// according to RFC3986, Section 5 (https://tools.ietf.org/html/rfc3986#section-5). + /// + /// The relative URI to be resolved against this as base. + /// The new resolved URI string. + _ASYNCRTIMP utility::string_t resolve_uri(const utility::string_t &relativeUri) const; + _ASYNCRTIMP bool operator == (const uri &other) const; bool operator < (const uri &other) const @@ -413,4 +421,4 @@ namespace web { details::uri_components m_components; }; -} // namespace web +} // namespace web diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index 737ed12e1b..1953564a9f 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -19,6 +19,9 @@ namespace web { namespace details { namespace { + const ::utility::string_t dotSegment = _XPLATSTR("."); + const ::utility::string_t dotDotSegment = _XPLATSTR(".."); + /// /// Unreserved characters are those that are allowed in a URI but do not have a reserved purpose. They include: /// - A-Z @@ -423,7 +426,60 @@ namespace return encoded; } -} + // 5.2.3. Merge Paths https://tools.ietf.org/html/rfc3986#section-5.2.3 + utility::string_t mergePaths(const utility::string_t &base, const utility::string_t &relative) + { + const auto lastSlash = base.rfind(_XPLATSTR('/')); + if (lastSlash == utility::string_t::npos) + { + return base + _XPLATSTR('/') + relative; + } + else if (lastSlash == base.size() - 1) + { + return base + relative; + } + // path contains and does not end with '/', we remove segment after last '/' + return base.substr(0, lastSlash + 1) + relative; + } + + // 5.2.4. Remove Dot Segments https://tools.ietf.org/html/rfc3986#section-5.2.4 + void removeDotSegments(uri_builder &builder) + { + if (builder.path().find(_XPLATSTR('.')) == utility::string_t::npos) + return; + + const auto segments = uri::split_path(builder.path()); + std::vector> result; + for (auto& segment : segments) + { + if (segment == dotSegment) + continue; + else if (segment != dotDotSegment) + result.push_back(segment); + else if (!result.empty()) + result.pop_back(); + } + if (result.empty()) + { + builder.set_path(utility::string_t()); + return; + } + utility::string_t path = result.front().get(); + for (size_t i = 1; i != result.size(); ++i) + { + path += _XPLATSTR('/'); + path += result[i].get(); + } + if (segments.back() == dotDotSegment + || segments.back() == dotSegment + || builder.path().back() == _XPLATSTR('/')) + { + path += _XPLATSTR('/'); + } + + builder.set_path(std::move(path)); + } +} // namespace utility::string_t uri_components::join() { @@ -448,7 +504,8 @@ utility::string_t uri_components::join() if (!m_scheme.empty()) { - ret.append(m_scheme).append({ _XPLATSTR(':') }); + ret.append(m_scheme); + ret.push_back(_XPLATSTR(':')); } if (!m_host.empty()) @@ -473,7 +530,7 @@ utility::string_t uri_components::join() // only add the leading slash when the host is present if (!m_host.empty() && m_path.front() != _XPLATSTR('/')) { - ret.append({ _XPLATSTR('/') }); + ret.push_back(_XPLATSTR('/')); } ret.append(m_path); @@ -481,17 +538,19 @@ utility::string_t uri_components::join() if (!m_query.empty()) { - ret.append({ _XPLATSTR('?') }).append(m_query); + ret.push_back(_XPLATSTR('?')); + ret.append(m_query); } if (!m_fragment.empty()) { - ret.append({ _XPLATSTR('#') }).append(m_fragment); + ret.push_back(_XPLATSTR('#')); + ret.append(m_fragment); } return ret; } -} +} // namespace details uri::uri(const details::uri_components &components) : m_components(components) { @@ -715,7 +774,7 @@ std::map uri::split_query(const utility::s utility::string_t key(key_value_pair.begin(), key_value_pair.begin() + equals_index); utility::string_t value(key_value_pair.begin() + equals_index + 1, key_value_pair.end()); results[key] = value; - } + } } return results; @@ -784,4 +843,54 @@ bool uri::operator == (const uri &other) const return true; } +//resolving URI according to RFC3986, Section 5 https://tools.ietf.org/html/rfc3986#section-5 +utility::string_t uri::resolve_uri(const utility::string_t &relativeUri) const +{ + if (relativeUri.empty()) + { + return to_string(); + } + + if (relativeUri[0] == _XPLATSTR('/')) // starts with '/' + { + if (relativeUri.size() >= 2 && relativeUri[1] == _XPLATSTR('/')) // starts with '//' + { + return this->scheme() + _XPLATSTR(':') + relativeUri; + } + + // otherwise relative to root + auto builder = uri_builder(this->authority()); + builder.append(relativeUri); + details::removeDotSegments(builder); + return builder.to_string(); + } + + const auto url = uri(relativeUri); + if (!url.scheme().empty()) + return relativeUri; + + if (!url.authority().is_empty()) + { + return uri_builder(url).set_scheme(this->scheme()).to_string(); + } + + // relative url + auto builder = uri_builder(*this); + if (url.path() == _XPLATSTR("/") || url.path().empty()) // web::uri considers empty path as '/' + { + if (!url.query().empty()) + { + builder.set_query(url.query()); + } + } + else if (!this->path().empty()) + { + builder.set_path(details::mergePaths(this->path(), url.path())); + details::removeDotSegments(builder); + builder.set_query(url.query()); + } + + return builder.set_fragment(url.fragment()).to_string(); } + +} // namespace web diff --git a/Release/tests/functional/uri/CMakeLists.txt b/Release/tests/functional/uri/CMakeLists.txt index 86cd0e867a..1a4aaee947 100644 --- a/Release/tests/functional/uri/CMakeLists.txt +++ b/Release/tests/functional/uri/CMakeLists.txt @@ -8,6 +8,7 @@ set(SOURCES operator_tests.cpp splitting_tests.cpp uri_builder_tests.cpp + resolve_uri_tests.cpp stdafx.cpp ) diff --git a/Release/tests/functional/uri/resolve_uri_tests.cpp b/Release/tests/functional/uri/resolve_uri_tests.cpp new file mode 100644 index 0000000000..963be8656f --- /dev/null +++ b/Release/tests/functional/uri/resolve_uri_tests.cpp @@ -0,0 +1,68 @@ +#include "stdafx.h" + +using namespace web; +using namespace utility; + +namespace tests { namespace functional { namespace uri_tests { + +//testing resolution against examples from Section 5.4 https://tools.ietf.org/html/rfc3986#section-5.4 +SUITE(resolve_uri_tests) +{ +//5.4.1. Normal Examples https://tools.ietf.org/html/rfc3986#section-5.4.1 +TEST(resolve_uri_normal) +{ + const uri baseUri = U("http://a/b/c/d;p?q"); + + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g:h")), U("g:h")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g")), U("http://a/b/c/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("./g")), U("http://a/b/c/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g/")), U("http://a/b/c/g/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("/g")), U("http://a/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("//g")), U("http://g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("?y")), U("http://a/b/c/d;p?y")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g?y")), U("http://a/b/c/g?y")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("#s")), U("http://a/b/c/d;p?q#s")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g#s")), U("http://a/b/c/g#s")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g?y#s")), U("http://a/b/c/g?y#s")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U(";x")), U("http://a/b/c/;x")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g;x")), U("http://a/b/c/g;x")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g;x?y#s")), U("http://a/b/c/g;x?y#s")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("")), U("http://a/b/c/d;p?q")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U(".")), U("http://a/b/c/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("./")), U("http://a/b/c/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("..")), U("http://a/b/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("../")), U("http://a/b/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("../g")), U("http://a/b/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("../..")), U("http://a/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("../../")), U("http://a/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("../../g")), U("http://a/g")); +} +//5.4.2. Abnormal Examples https://tools.ietf.org/html/rfc3986#section-5.4.2 +TEST(resolve_uri_abnormal) +{ + const uri baseUri = U("http://a/b/c/d;p?q"); + + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("../../../g")), U("http://a/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("../../../../g")), U("http://a/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("/./g")), U("http://a/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("/../g")), U("http://a/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g.")), U("http://a/b/c/g.")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U(".g")), U("http://a/b/c/.g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g..")), U("http://a/b/c/g..")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("..g")), U("http://a/b/c/..g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("./../g")), U("http://a/b/g")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("./g/.")), U("http://a/b/c/g/")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g/./h")), U("http://a/b/c/g/h")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g/../h")), U("http://a/b/c/h")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g;x=1/./y")), U("http://a/b/c/g;x=1/y")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g;x=1/../y")), U("http://a/b/c/y")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g?y/./x")), U("http://a/b/c/g?y/./x")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g?y/../x")), U("http://a/b/c/g?y/../x")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g#s/./x")), U("http://a/b/c/g#s/./x")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("g#s/../x")), U("http://a/b/c/g#s/../x")); + VERIFY_ARE_EQUAL(baseUri.resolve_uri(U("http:g")), U("http:g")); +} + +} // SUITE(resolve_uri_tests) + +}}} From c6377e933e2d3a73de5b467ad292b4b7e3d8ec0a Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 10 Oct 2018 15:40:26 -0700 Subject: [PATCH 440/609] Add MacOS pipelines build support. (#902) * Attempt to add MacOS pipelines support; increase parallelism to 4. * Fix "expression unused" warnings on MacOS. --- .../http/client/compression_tests.cpp | 8 ++--- azure-pipelines.yml | 36 +++++++++++++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index ca2215afd9..256c174c69 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -761,15 +761,15 @@ SUITE(compression_tests) // No acquire(), to force non-acquire compression client codepaths virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count) { - ptr; - count; + (void)ptr; + (void)count; return false; } virtual void release(_Out_writes_(count) _CharType* ptr, _In_ size_t count) { - ptr; - count; + (void)ptr; + (void)count; } static concurrency::streams::basic_istream<_CharType> open_istream(const _CharType* data, size_t size) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index dab028e6fa..f49e5ecdbc 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,7 +18,7 @@ jobs: cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' - script: | cd build.debug - ninja -j 2 + ninja -j 4 displayName: 'Run ninja' - job: Ubuntu_1604_Apt_Release pool: @@ -37,5 +37,37 @@ jobs: cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' - script: | cd build.release - ninja -j 2 + ninja -j 4 + displayName: 'Run ninja' + - job: MacOS_Debug + pool: + vmImage: 'macOS-10.13' + steps: + - script: brew install boost openssl ninja + displayName: Berw install dependencies + - script: mkdir build.debug + displayName: Make build.debug + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' + - script: | + cd build.debug + ninja -j 4 + displayName: 'Run ninja' + - job: MacOS_Release + pool: + vmImage: 'macOS-10.13' + steps: + - script: brew install boost openssl ninja + displayName: Berw install dependencies + - script: mkdir build.release + displayName: Make build.release + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' + - script: | + cd build.release + ninja -j 4 displayName: 'Run ninja' From 10494918aabd47b0d16181a6717f582e3ce65a67 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 10 Oct 2018 17:00:20 -0700 Subject: [PATCH 441/609] Adding test runs to Azure Pipelines. (#899) * Adding test runs to Pipelines. * Use get instead of then/wait in compression tests. * Fix typo to not write to *done. * Use dylib on MacOS. --- .../http/client/compression_tests.cpp | 88 +++++++------------ azure-pipelines.yml | 16 ++++ 2 files changed, 46 insertions(+), 58 deletions(-) diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index 256c174c69..10e37186fa 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -62,7 +62,7 @@ SUITE(compression_tests) if (_done) { input_bytes_processed = 0; - if (*done) + if (done) { *done = true; } @@ -127,7 +127,7 @@ SUITE(compression_tests) if (_done) { input_bytes_processed = 0; - if (*done) + if (done) { *done = true; } @@ -203,7 +203,6 @@ SUITE(compression_tests) std::vector dcmp_buffer; web::http::compression::operation_result r; std::vector chunk_sizes; - pplx::task_status result; size_t csize; size_t dsize; size_t i; @@ -240,15 +239,11 @@ SUITE(compression_tests) cmp_buffer.resize(buffer_size); // pessimistic (or not, for non-compressible data) for (i = 0; i < buffer_size; i += chunk_size) { - result = compressor - ->compress(input_buffer.data() + i, - std::min(chunk_size, buffer_size - i), - cmp_buffer.data() + csize, - std::min(chunk_size, buffer_size - csize), - web::http::compression::operation_hint::has_more) - .then([&r](web::http::compression::operation_result x) { r = x; }) - .wait(); - VERIFY_ARE_EQUAL(result, pplx::task_status::completed); + r = compressor->compress(input_buffer.data() + i, + std::min(chunk_size, buffer_size - i), + cmp_buffer.data() + csize, + std::min(chunk_size, buffer_size - csize), + web::http::compression::operation_hint::has_more).get(); VERIFY_ARE_EQUAL(r.input_bytes_processed, std::min(chunk_size, buffer_size - i)); VERIFY_ARE_EQUAL(r.done, false); chunk_sizes.push_back(r.output_bytes_produced); @@ -265,15 +260,11 @@ SUITE(compression_tests) cmpsize += std::min(chunk_size, (size_t)200); cmp_buffer.resize(cmpsize); } - result = compressor - ->compress(NULL, + r = compressor->compress(NULL, 0, cmp_buffer.data() + csize, std::min(chunk_size, cmpsize - csize), - web::http::compression::operation_hint::is_last) - .then([&r](web::http::compression::operation_result x) { r = x; }) - .wait(); - VERIFY_ARE_EQUAL(result, pplx::task_status::completed); + web::http::compression::operation_hint::is_last).get(); VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); chunk_sizes.push_back(r.output_bytes_produced); csize += r.output_bytes_produced; @@ -281,14 +272,12 @@ SUITE(compression_tests) VERIFY_ARE_EQUAL(r.done, true); // once more with no input, to assure no error and done - result = compressor->compress(NULL, 0, NULL, 0, web::http::compression::operation_hint::is_last) - .then([&r](web::http::compression::operation_result x) { r = x; }) - .wait(); - VERIFY_ARE_EQUAL(result, pplx::task_status::completed); + r = compressor->compress(NULL, 0, NULL, 0, web::http::compression::operation_hint::is_last).get(); VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); VERIFY_ARE_EQUAL(r.output_bytes_produced, 0); VERIFY_ARE_EQUAL(r.done, true); } + cmp_buffer.resize(csize); // actual // decompress in as-compressed chunks @@ -304,15 +293,12 @@ SUITE(compression_tests) { hint = web::http::compression::operation_hint::is_last; } - result = decompressor - ->decompress(cmp_buffer.data() + nn, - *it, - dcmp_buffer.data() + dsize, - std::min(chunk_size, buffer_size - dsize), - hint) - .then([&r](web::http::compression::operation_result x) { r = x; }) - .wait(); - VERIFY_ARE_EQUAL(result, pplx::task_status::completed); + + r = decompressor->decompress(cmp_buffer.data() + nn, + *it, + dcmp_buffer.data() + dsize, + std::min(chunk_size, buffer_size - dsize), + hint).get(); nn += *it; dsize += r.output_bytes_produced; } @@ -332,15 +318,11 @@ SUITE(compression_tests) size_t n = std::min(chunk_size, csize - nn); do { - result = decompressor - ->decompress(cmp_buffer.data() + nn, - n, - dcmp_buffer.data() + dsize, - std::min(chunk_size, buffer_size - dsize), - web::http::compression::operation_hint::has_more) - .then([&r](web::http::compression::operation_result x) { r = x; }) - .wait(); - VERIFY_ARE_EQUAL(result, pplx::task_status::completed); + r = decompressor->decompress(cmp_buffer.data() + nn, + n, + dcmp_buffer.data() + dsize, + std::min(chunk_size, buffer_size - dsize), + web::http::compression::operation_hint::has_more).get(); dsize += r.output_bytes_produced; nn += r.input_bytes_processed; n -= r.input_bytes_processed; @@ -352,10 +334,7 @@ SUITE(compression_tests) VERIFY_IS_TRUE(r.done); // once more with no input, to assure no error and done - result = decompressor->decompress(NULL, 0, NULL, 0, web::http::compression::operation_hint::has_more) - .then([&r](web::http::compression::operation_result x) { r = x; }) - .wait(); - VERIFY_ARE_EQUAL(result, pplx::task_status::completed); + r = decompressor->decompress(NULL, 0, NULL, 0, web::http::compression::operation_hint::has_more).get(); VERIFY_ARE_EQUAL(r.input_bytes_processed, 0); VERIFY_ARE_EQUAL(r.output_bytes_produced, 0); VERIFY_IS_TRUE(r.done); @@ -363,15 +342,11 @@ SUITE(compression_tests) // decompress all at once decompressor->reset(); memset(dcmp_buffer.data(), 0, dcmp_buffer.size()); - result = decompressor - ->decompress(cmp_buffer.data(), - csize, - dcmp_buffer.data(), - dcmp_buffer.size(), - web::http::compression::operation_hint::is_last) - .then([&r](web::http::compression::operation_result x) { r = x; }) - .wait(); - VERIFY_ARE_EQUAL(result, pplx::task_status::completed); + r = decompressor->decompress(cmp_buffer.data(), + csize, + dcmp_buffer.data(), + dcmp_buffer.size(), + web::http::compression::operation_hint::is_last).get(); VERIFY_ARE_EQUAL(r.output_bytes_produced, buffer_size); VERIFY_ARE_EQUAL(input_buffer, dcmp_buffer); @@ -385,14 +360,11 @@ SUITE(compression_tests) nn = 0; try { - result = decompressor - ->decompress(cmp_buffer.data(), + r = decompressor->decompress(cmp_buffer.data(), csize, dcmp_buffer.data(), dcmp_buffer.size(), - web::http::compression::operation_hint::is_last) - .then([&nn](web::http::compression::operation_result x) { nn++; }) - .wait(); + web::http::compression::operation_hint::is_last).get(); nn++; } catch (std::runtime_error) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f49e5ecdbc..d984c4094e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -20,6 +20,10 @@ jobs: cd build.debug ninja -j 4 displayName: 'Run ninja' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.so + displayName: 'Run Tests' - job: Ubuntu_1604_Apt_Release pool: vmImage: 'Ubuntu 16.04' @@ -39,6 +43,10 @@ jobs: cd build.release ninja -j 4 displayName: 'Run ninja' + - script: | + cd build.release/Release/Binaries + ./test_runner *test.so + displayName: 'Run Tests' - job: MacOS_Debug pool: vmImage: 'macOS-10.13' @@ -55,6 +63,10 @@ jobs: cd build.debug ninja -j 4 displayName: 'Run ninja' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run Tests' - job: MacOS_Release pool: vmImage: 'macOS-10.13' @@ -71,3 +83,7 @@ jobs: cd build.release ninja -j 4 displayName: 'Run ninja' + - script: | + cd build.release/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run Tests' From 5a9f3bc25714dfbfea7fd006085a1f18ee6acde2 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 10 Oct 2018 17:27:48 -0700 Subject: [PATCH 442/609] Move dotSegment and dotDotSegment back into local variables, as suggested by @toughengineer --- Release/src/uri/uri.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index 1953564a9f..fac048c9da 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -19,9 +19,6 @@ namespace web { namespace details { namespace { - const ::utility::string_t dotSegment = _XPLATSTR("."); - const ::utility::string_t dotDotSegment = _XPLATSTR(".."); - /// /// Unreserved characters are those that are allowed in a URI but do not have a reserved purpose. They include: /// - A-Z @@ -445,6 +442,9 @@ namespace // 5.2.4. Remove Dot Segments https://tools.ietf.org/html/rfc3986#section-5.2.4 void removeDotSegments(uri_builder &builder) { + const ::utility::string_t dotSegment = _XPLATSTR("."); + const ::utility::string_t dotDotSegment = _XPLATSTR(".."); + if (builder.path().find(_XPLATSTR('.')) == utility::string_t::npos) return; From 8484f5d97af41a9b0980eed2bd5d736f4c355f1c Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 10 Oct 2018 18:12:37 -0700 Subject: [PATCH 443/609] Revert "Enable precompiled headers for test/functional (#891)" (#904) This reverts commit 2aa4a641b61c6d9d805c7a85b649671d4b55cd27 because it fails to compile: D:\cpprestsdk\build.debug>ninja ninja: error: dependency cycle: Release/tests/functional/http/client/stdafx.pch -> Release/tests/functional/http/client/CMakeFiles/httpclient_test.dir/stdafx.cpp.obj -> Release/tests/functional/http/client/stdafx.pch --- Release/tests/functional/http/client/CMakeLists.txt | 13 ------------- Release/tests/functional/json/CMakeLists.txt | 13 ------------- .../tests/functional/pplx/pplx_test/CMakeLists.txt | 13 ------------- Release/tests/functional/streams/CMakeLists.txt | 13 ------------- Release/tests/functional/uri/CMakeLists.txt | 13 ------------- Release/tests/functional/utils/CMakeLists.txt | 13 ------------- 6 files changed, 78 deletions(-) diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 1cf9b6e6f5..17cf4eff81 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -32,19 +32,6 @@ else() target_link_libraries(httpclient_test PRIVATE httptest_utilities) endif() -if(MSVC) - get_target_property(_srcs httpclient_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - target_sources(httpclient_test PRIVATE stdafx.cpp) - target_compile_options(httpclient_test PRIVATE /Yustdafx.h /Zm200) -endif() - if(NOT WIN32) cpprest_find_boost() target_link_libraries(httpclient_test PRIVATE cpprestsdk_boost_internal) diff --git a/Release/tests/functional/json/CMakeLists.txt b/Release/tests/functional/json/CMakeLists.txt index c9dccfcfeb..379a6bd4bf 100644 --- a/Release/tests/functional/json/CMakeLists.txt +++ b/Release/tests/functional/json/CMakeLists.txt @@ -16,16 +16,3 @@ if(UNIX AND NOT APPLE) cpprest_find_boost() target_link_libraries(json_test PRIVATE cpprestsdk_boost_internal) endif() - -if(MSVC) - get_target_property(_srcs json_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - target_sources(json_test PRIVATE stdafx.cpp) - target_compile_options(json_test PRIVATE /Yustdafx.h /Zm200) -endif() diff --git a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt index a51776989b..01c56f7522 100644 --- a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt +++ b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt @@ -6,16 +6,3 @@ set(SOURCES ) add_casablanca_test(pplx_test SOURCES) - -if(MSVC) - get_target_property(_srcs pplx_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - target_sources(pplx_test PRIVATE stdafx.cpp) - target_compile_options(pplx_test PRIVATE /Yustdafx.h /Zm200) -endif() diff --git a/Release/tests/functional/streams/CMakeLists.txt b/Release/tests/functional/streams/CMakeLists.txt index d2b6858f15..4b11173b18 100644 --- a/Release/tests/functional/streams/CMakeLists.txt +++ b/Release/tests/functional/streams/CMakeLists.txt @@ -24,16 +24,3 @@ if(NOT WIN32 OR CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") target_include_directories(streams_test PRIVATE $) endif() endif() - -if(MSVC) - get_target_property(_srcs streams_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - target_sources(streams_test PRIVATE stdafx.cpp) - target_compile_options(streams_test PRIVATE /Yustdafx.h /Zm200) -endif() diff --git a/Release/tests/functional/uri/CMakeLists.txt b/Release/tests/functional/uri/CMakeLists.txt index 1a4aaee947..54d80ac254 100644 --- a/Release/tests/functional/uri/CMakeLists.txt +++ b/Release/tests/functional/uri/CMakeLists.txt @@ -13,16 +13,3 @@ set(SOURCES ) add_casablanca_test(uri_test SOURCES) - -if(MSVC) - get_target_property(_srcs uri_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - target_sources(uri_test PRIVATE stdafx.cpp) - target_compile_options(uri_test PRIVATE /Yustdafx.h /Zm200) -endif() diff --git a/Release/tests/functional/utils/CMakeLists.txt b/Release/tests/functional/utils/CMakeLists.txt index ff5d4cb49c..ff175283f8 100644 --- a/Release/tests/functional/utils/CMakeLists.txt +++ b/Release/tests/functional/utils/CMakeLists.txt @@ -13,16 +13,3 @@ add_casablanca_test(utils_test SOURCES) if(CMAKE_COMPILER_IS_GNUCXX) target_compile_options(utils_test PRIVATE "-Wno-deprecated-declarations") endif() - -if(MSVC) - get_target_property(_srcs utils_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") - target_sources(utils_test PRIVATE stdafx.cpp) - target_compile_options(utils_test PRIVATE /Yustdafx.h /Zm200) -endif() From acd96cfba2e12989bc69a152b8a320ac5ea50ee2 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 10 Oct 2018 20:11:20 -0700 Subject: [PATCH 444/609] Burninate internal use of ostringstream, and done a ref (#905) * Burninate internal use of ostringstream, and make compressors' done parameter required. * Remove errant ::details. * Remove even more errant ::details. --- Release/include/cpprest/http_compression.h | 4 +- Release/include/cpprest/json.h | 54 ++++---- Release/src/http/client/http_client_asio.cpp | 4 +- Release/src/http/client/http_client_msg.cpp | 41 ++++-- Release/src/http/client/http_client_winrt.cpp | 3 +- Release/src/http/common/http_compression.cpp | 95 +++++-------- Release/src/http/common/http_msg.cpp | 18 +-- .../src/http/listener/http_server_asio.cpp | 9 +- .../src/http/listener/http_server_httpsys.cpp | 18 ++- Release/src/http/oauth/oauth1.cpp | 123 ++++++++++------- Release/src/http/oauth/oauth2.cpp | 11 +- Release/src/json/json_parsing.cpp | 11 +- Release/src/utilities/asyncrt_utils.cpp | 128 ++++++++++-------- .../src/websockets/client/ws_client_wspp.cpp | 12 +- Release/src/websockets/client/ws_msg.cpp | 2 +- .../http/client/compression_tests.cpp | 43 +++--- 16 files changed, 305 insertions(+), 271 deletions(-) diff --git a/Release/include/cpprest/http_compression.h b/Release/include/cpprest/http_compression.h index 1993e6244c..b6df43e026 100644 --- a/Release/include/cpprest/http_compression.h +++ b/Release/include/cpprest/http_compression.h @@ -51,7 +51,7 @@ class compress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done = nullptr) = 0; + bool& done) = 0; virtual pplx::task compress( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0; virtual void reset() = 0; @@ -71,7 +71,7 @@ class decompress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done = nullptr) = 0; + bool& done) = 0; virtual pplx::task decompress( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0; virtual void reset() = 0; diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index dfdeead4f3..1e88ddd2f0 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -714,7 +714,11 @@ namespace json private: std::string _message; public: - json_exception(const utility::char_t * const &message) : _message(utility::conversions::to_utf8string(message)) { } + json_exception(const char * const message) : _message(message) { } +#ifdef _UTF16_STRINGS + json_exception(const wchar_t * const message) : _message(utility::conversions::utf16_to_utf8(message)) { } +#endif // _UTF16_STRINGS + json_exception(std::string&& message) : _message(std::move(message)) { } // Must be narrow string because it derives from std::exception const char* what() const CPPREST_NOEXCEPT @@ -930,7 +934,7 @@ namespace json { if (index >= m_elements.size()) { - throw json_exception(_XPLATSTR("index out of bounds")); + throw json_exception("index out of bounds"); } m_elements.erase(m_elements.begin() + index); } @@ -943,7 +947,7 @@ namespace json json::value& at(size_type index) { if (index >= m_elements.size()) - throw json_exception(_XPLATSTR("index out of bounds")); + throw json_exception("index out of bounds"); return m_elements[index]; } @@ -956,7 +960,7 @@ namespace json const json::value& at(size_type index) const { if (index >= m_elements.size()) - throw json_exception(_XPLATSTR("index out of bounds")); + throw json_exception("index out of bounds"); return m_elements[index]; } @@ -1145,7 +1149,7 @@ namespace json auto iter = find_by_key(key); if (iter == m_elements.end()) { - throw web::json::json_exception(_XPLATSTR("Key not found")); + throw web::json::json_exception("Key not found"); } m_elements.erase(iter); @@ -1161,7 +1165,7 @@ namespace json auto iter = find_by_key(key); if (iter == m_elements.end()) { - throw web::json::json_exception(_XPLATSTR("Key not found")); + throw web::json::json_exception("Key not found"); } return iter->second; @@ -1177,7 +1181,7 @@ namespace json auto iter = find_by_key(key); if (iter == m_elements.end()) { - throw web::json::json_exception(_XPLATSTR("Key not found")); + throw web::json::json_exception("Key not found"); } return iter->second; @@ -1464,14 +1468,14 @@ namespace json virtual std::unique_ptr<_Value> _copy_value() = 0; virtual bool has_field(const utility::string_t &) const { return false; } - virtual value get_field(const utility::string_t &) const { throw json_exception(_XPLATSTR("not an object")); } - virtual value get_element(array::size_type) const { throw json_exception(_XPLATSTR("not an array")); } + virtual value get_field(const utility::string_t &) const { throw json_exception("not an object"); } + virtual value get_element(array::size_type) const { throw json_exception("not an array"); } - virtual value &index(const utility::string_t &) { throw json_exception(_XPLATSTR("not an object")); } - virtual value &index(array::size_type) { throw json_exception(_XPLATSTR("not an array")); } + virtual value &index(const utility::string_t &) { throw json_exception("not an object"); } + virtual value &index(array::size_type) { throw json_exception("not an array"); } - virtual const value &cnst_index(const utility::string_t &) const { throw json_exception(_XPLATSTR("not an object")); } - virtual const value &cnst_index(array::size_type) const { throw json_exception(_XPLATSTR("not an array")); } + virtual const value &cnst_index(const utility::string_t &) const { throw json_exception("not an object"); } + virtual const value &cnst_index(array::size_type) const { throw json_exception("not an array"); } // Common function used for serialization to strings and streams. virtual void serialize_impl(std::string& str) const @@ -1494,18 +1498,18 @@ namespace json virtual json::value::value_type type() const { return json::value::Null; } - virtual bool is_integer() const { throw json_exception(_XPLATSTR("not a number")); } - virtual bool is_double() const { throw json_exception(_XPLATSTR("not a number")); } - - virtual const json::number& as_number() { throw json_exception(_XPLATSTR("not a number")); } - virtual double as_double() const { throw json_exception(_XPLATSTR("not a number")); } - virtual int as_integer() const { throw json_exception(_XPLATSTR("not a number")); } - virtual bool as_bool() const { throw json_exception(_XPLATSTR("not a boolean")); } - virtual json::array& as_array() { throw json_exception(_XPLATSTR("not an array")); } - virtual const json::array& as_array() const { throw json_exception(_XPLATSTR("not an array")); } - virtual json::object& as_object() { throw json_exception(_XPLATSTR("not an object")); } - virtual const json::object& as_object() const { throw json_exception(_XPLATSTR("not an object")); } - virtual const utility::string_t& as_string() const { throw json_exception(_XPLATSTR("not a string")); } + virtual bool is_integer() const { throw json_exception("not a number"); } + virtual bool is_double() const { throw json_exception("not a number"); } + + virtual const json::number& as_number() { throw json_exception("not a number"); } + virtual double as_double() const { throw json_exception("not a number"); } + virtual int as_integer() const { throw json_exception("not a number"); } + virtual bool as_bool() const { throw json_exception("not a boolean"); } + virtual json::array& as_array() { throw json_exception("not an array"); } + virtual const json::array& as_array() const { throw json_exception("not an array"); } + virtual json::object& as_object() { throw json_exception("not an object"); } + virtual const json::object& as_object() const { throw json_exception("not an object"); } + virtual const utility::string_t& as_string() const { throw json_exception("not a string"); } virtual size_t size() const { return 0; } diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 72e13f046c..7ee22133fe 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1530,7 +1530,7 @@ class asio_context final : public request_context, public std::enable_shared_fro size_t got; size_t inbytes = 0; size_t outbytes = 0; - bool done = false; + bool done; try { @@ -1547,7 +1547,7 @@ class asio_context final : public request_context, public std::enable_shared_fro output.size() - outbytes, web::http::compression::operation_hint::has_more, processed, - &done); + done); inbytes += processed; outbytes += got; } while (got && !done); diff --git a/Release/src/http/client/http_client_msg.cpp b/Release/src/http/client/http_client_msg.cpp index 9cab7c8da9..dd7f3dc5c5 100644 --- a/Release/src/http/client/http_client_msg.cpp +++ b/Release/src/http/client/http_client_msg.cpp @@ -12,6 +12,7 @@ ****/ #include "stdafx.h" #include "../common/internal_http_helpers.h" +#include "cpprest/asyncrt_utils.h" namespace web { namespace http { @@ -61,29 +62,41 @@ void details::_http_request::set_request_uri(const uri& relative) utility::string_t details::_http_request::to_string() const { - utility::ostringstream_t buffer; - buffer.imbue(std::locale::classic()); - buffer << m_method << _XPLATSTR(" ") << (this->m_uri.is_empty() ? _XPLATSTR("/") : this->m_uri.to_string()) << _XPLATSTR(" HTTP/1.1\r\n"); - buffer << http_msg_base::to_string(); - return buffer.str(); + utility::string_t result(m_method); + result += _XPLATSTR(' '); + if (this->m_uri.is_empty()) + { + result += _XPLATSTR('/'); + } + else + { + result += this->m_uri.to_string(); + } + + result += _XPLATSTR(" HTTP/1.1\r\n"); + result += http_msg_base::to_string(); + return result; } utility::string_t details::_http_response::to_string() const { + utility::string_t result(_XPLATSTR("HTTP/1.1 ")); + result += utility::conversions::details::to_string_t(m_status_code); + result += ' '; // If the user didn't explicitly set a reason phrase then we should have it default // if they used one of the standard known status codes. - auto reason_phrase = m_reason_phrase; - if(reason_phrase.empty()) + if (m_reason_phrase.empty()) { - reason_phrase = get_default_reason_phrase(status_code()); + result += get_default_reason_phrase(status_code()); + } + else + { + result += m_reason_phrase; } - utility::ostringstream_t buffer; - buffer.imbue(std::locale::classic()); - buffer << _XPLATSTR("HTTP/1.1 ") << m_status_code << _XPLATSTR(" ") << reason_phrase << _XPLATSTR("\r\n"); - - buffer << http_msg_base::to_string(); - return buffer.str(); + result += _XPLATSTR("\r\n"); + result += http_msg_base::to_string(); + return result; } }} // namespace web::http diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 5a0697b489..79f682ec50 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -160,7 +160,8 @@ class HttpRequestCallback final : std::wstring msg(L"IXMLHttpRequest2Callback::OnError: "); msg.append(std::to_wstring(hrError)); msg.append(L": "); - msg.append(utility::conversions::to_string_t(utility::details::windows_category().message(hrError))); + msg.append(utility::conversions::to_string_t( + utility::details::windows_category().message(hrError))); m_request->report_error(hrError, msg); } else diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index 194f1efc97..9d409906c5 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -75,23 +75,19 @@ class zlib_compressor_base : public compress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_state == Z_STREAM_END || (hint != operation_hint::is_last && !input_size)) { input_bytes_processed = 0; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return 0; } if (m_state != Z_OK && m_state != Z_BUF_ERROR && m_state != Z_STREAM_ERROR) { - std::stringstream ss; - ss << "Prior unrecoverable compression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Prior unrecoverable compression stream error " + + std::to_string(m_state)); } if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) @@ -108,16 +104,11 @@ class zlib_compressor_base : public compress_provider if (m_state != Z_OK && m_state != Z_STREAM_ERROR && !(hint == operation_hint::is_last && (m_state == Z_STREAM_END || m_state == Z_BUF_ERROR))) { - std::stringstream ss; - ss << "Unrecoverable compression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Unrecoverable compression stream error " + std::to_string(m_state)); } input_bytes_processed = input_size - m_stream.avail_in; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return output_size - m_stream.avail_out; } @@ -129,7 +120,7 @@ class zlib_compressor_base : public compress_provider try { r.output_bytes_produced = - compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -146,9 +137,7 @@ class zlib_compressor_base : public compress_provider m_state = deflateReset(&m_stream); if (m_state != Z_OK) { - std::stringstream ss; - ss << "Failed to reset zlib compressor " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Failed to reset zlib compressor " + std::to_string(m_state)); } } @@ -181,23 +170,18 @@ class zlib_decompressor_base : public decompress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_state == Z_STREAM_END || !input_size) { input_bytes_processed = 0; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return 0; } if (m_state != Z_OK && m_state != Z_BUF_ERROR && m_state != Z_STREAM_ERROR) { - std::stringstream ss; - ss << "Prior unrecoverable decompression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Prior unrecoverable decompression stream error " + std::to_string(m_state)); } if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) @@ -215,16 +199,11 @@ class zlib_decompressor_base : public decompress_provider { // Z_BUF_ERROR is a success code for Z_FINISH, and the caller can continue as if operation_hint::is_last was // not given - std::stringstream ss; - ss << "Unrecoverable decompression stream error " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Unrecoverable decompression stream error " + std::to_string(m_state)); } input_bytes_processed = input_size - m_stream.avail_in; - if (done) - { - *done = (m_state == Z_STREAM_END); - } + done = (m_state == Z_STREAM_END); return output_size - m_stream.avail_out; } @@ -236,7 +215,7 @@ class zlib_decompressor_base : public decompress_provider try { r.output_bytes_produced = - decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -253,9 +232,7 @@ class zlib_decompressor_base : public decompress_provider m_state = inflateReset(&m_stream); if (m_state != Z_OK) { - std::stringstream ss; - ss << "Failed to reset zlib decompressor " << m_state; - throw std::runtime_error(std::move(ss.str())); + throw std::runtime_error("Failed to reset zlib decompressor " + std::to_string(m_state)); } } @@ -331,15 +308,12 @@ class brotli_compressor : public compress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_done || (hint != operation_hint::is_last && !input_size)) { input_bytes_processed = 0; - if (done) - { - *done = m_done; - } + done = m_done; return 0; } @@ -397,10 +371,7 @@ class brotli_compressor : public compress_provider } input_bytes_processed = input_size - avail_in; - if (done) - { - *done = m_done; - } + done = m_done; return output_size - avail_out; } @@ -495,15 +466,12 @@ class brotli_decompressor : public decompress_provider size_t output_size, operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { if (m_state == BROTLI_DECODER_RESULT_SUCCESS /* || !input_size*/) { input_bytes_processed = 0; - if (done) - { - *done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); - } + done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); return 0; } @@ -529,10 +497,7 @@ class brotli_decompressor : public decompress_provider } input_bytes_processed = input_size - avail_in; - if (done) - { - *done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); - } + done = (m_state == BROTLI_DECODER_RESULT_SUCCESS); return output_size - avail_out; } @@ -761,7 +726,7 @@ std::unique_ptr make_gzip_compressor(int compressionLevel, in return std::unique_ptr(); #endif // CPPREST_HTTP_COMPRESSION } - + std::unique_ptr make_deflate_compressor(int compressionLevel, int method, int strategy, int memLevel) { #if defined(CPPREST_HTTP_COMPRESSION) @@ -1088,14 +1053,13 @@ utility::string_t build_supported_header(header_types type, { const std::vector>& f = factories.empty() ? web::http::compression::builtin::g_decompress_factories : factories; - utility::ostringstream_t os; + utility::string_t result; bool start; _ASSERTE(type == header_types::te || type == header_types::accept_encoding); // Add all specified algorithms and their weights to the header start = true; - os.imbue(std::locale::classic()); for (auto& factory : f) { if (factory) @@ -1104,12 +1068,15 @@ utility::string_t build_supported_header(header_types type, if (!start) { - os << _XPLATSTR(", "); + result += _XPLATSTR(", "); } - os << factory->algorithm(); + result += factory->algorithm(); if (weight <= 1000) { - os << _XPLATSTR(";q=") << weight / 1000 << _XPLATSTR(".") << weight % 1000; + result += _XPLATSTR(";q="); + result += utility::conversions::details::to_string_t(weight / 1000); + result += _XPLATSTR('.'); + result += utility::conversions::details::to_string_t(weight % 1000); } start = false; } @@ -1118,10 +1085,10 @@ utility::string_t build_supported_header(header_types type, if (start && type == header_types::accept_encoding) { // Request that no encoding be applied - os << _XPLATSTR("identity;q=1, *;q=0"); + result += _XPLATSTR("identity;q=1, *;q=0"); } - return os.str(); + return result; } } // namespace details } // namespace compression diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 7a80017828..44870f5420 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -253,7 +253,7 @@ void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers http_version __cdecl http_version::from_string(const std::string& http_version_string) { - std::stringstream str(http_version_string); + std::istringstream str(http_version_string); str.imbue(std::locale::classic()); std::string http; std::getline(str, http, '/'); @@ -1009,22 +1009,24 @@ static utility::string_t convert_body_to_string_t(const utility::string_t &conte // static utility::string_t http_headers_body_to_string(const http_headers &headers, concurrency::streams::istream instream) { - utility::ostringstream_t buffer; - buffer.imbue(std::locale::classic()); - + utility::string_t result; for (const auto &header : headers) { - buffer << header.first << _XPLATSTR(": ") << header.second << CRLF; + result += header.first; + result += _XPLATSTR(": "); + result += header.second; + result += CRLF; } - buffer << CRLF; + + result += CRLF; utility::string_t content_type; if(headers.match(http::header_names::content_type, content_type)) { - buffer << convert_body_to_string_t(content_type, instream); + result += convert_body_to_string_t(content_type, instream); } - return buffer.str(); + return result; } utility::string_t details::http_msg_base::to_string() const diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 13b813b858..5ab3086954 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -693,7 +693,8 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys // Get the path - remove the version portion and prefix space try { - m_request.set_request_uri(utility::conversions::to_string_t(http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1))); + m_request.set_request_uri(utility::conversions::to_string_t( + http_path_and_version.substr(1, http_path_and_version.size() - VersionPortionSize - 1))); } catch (const std::exception& e) // may be std::range_error indicating invalid Unicode, or web::uri_exception { @@ -722,7 +723,8 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys auto endpoint = m_socket->remote_endpoint(socket_ec); if (!socket_ec) { - m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t(endpoint.address().to_string())); + m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t( + endpoint.address().to_string())); } return handle_headers(); @@ -743,7 +745,8 @@ will_deref_and_erase_t asio_server_connection::handle_headers() if (colon != std::string::npos && colon != 0) { auto name = utility::conversions::to_string_t(header.substr(0, colon)); - auto value = utility::conversions::to_string_t(header.substr(colon + 1, header.length() - (colon + 1))); // also exclude '\r' + auto value = utility::conversions::to_string_t( + header.substr(colon + 1, header.length() - (colon + 1))); // also exclude '\r' web::http::details::trim_whitespace(name); web::http::details::trim_whitespace(value); diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 3adb4fb882..242dae4800 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -243,7 +243,7 @@ pplx::task http_windows_server::register_listener(_In_ web::http::experime utility::string_t host_uri = http::uri::decode(u.to_string()); if(host_uri.back() != U('/') && u.query().empty() && u.fragment().empty()) { - host_uri.append(U("/")); + host_uri.push_back(U('/')); } // inside here we check for a few specific error types that know about @@ -252,19 +252,16 @@ pplx::task http_windows_server::register_listener(_In_ web::http::experime if(errorCode) { HttpCloseUrlGroup(urlGroupId); - utility::stringstream_t os; - os.imbue(std::locale::classic()); - if(errorCode == ERROR_ALREADY_EXISTS || errorCode == ERROR_SHARING_VIOLATION) { - os << _XPLATSTR("Address '") << pListener->uri().to_string() << _XPLATSTR("' is already in use"); - return pplx::task_from_exception(http_exception(errorCode, os.str())); + return pplx::task_from_exception(http_exception(errorCode, + _XPLATSTR("Address '") + pListener->uri().to_string() + _XPLATSTR("' is already in use"))); } else if (errorCode == ERROR_ACCESS_DENIED) { - os << _XPLATSTR("Access denied: attempting to add Address '") << pListener->uri().to_string() << _XPLATSTR("'. "); - os << _XPLATSTR("Run as administrator to listen on an hostname other than localhost, or to listen on port 80."); - return pplx::task_from_exception(http_exception(errorCode, os.str())); + return pplx::task_from_exception(http_exception(errorCode, + _XPLATSTR("Access denied: attempting to add Address '") + pListener->uri().to_string() + _XPLATSTR("'. ") + _XPLATSTR("Run as administrator to listen on an hostname other than localhost, or to listen on port 80."))); } else { @@ -738,7 +735,8 @@ void windows_request_context::read_body_io_completion(DWORD error_code, DWORD by auto body = request_body_buf.alloc(CHUNK_SIZE); try { - got = m_decompressor->decompress(m_compress_buffer.data()+total_used, bytes_read-total_used, body, CHUNK_SIZE, http::compression::operation_hint::has_more, used, NULL); + bool done_unused; + got = m_decompressor->decompress(m_compress_buffer.data()+total_used, bytes_read-total_used, body, CHUNK_SIZE, http::compression::operation_hint::has_more, used, done_unused); } catch (...) { diff --git a/Release/src/http/oauth/oauth1.cpp b/Release/src/http/oauth/oauth1.cpp index 37c71deb22..22029593b8 100644 --- a/Release/src/http/oauth/oauth1.cpp +++ b/Release/src/http/oauth/oauth1.cpp @@ -12,6 +12,7 @@ ****/ #include "stdafx.h" +#include "cpprest/asyncrt_utils.h" #if !defined(CPPREST_TARGET_XP) @@ -153,15 +154,17 @@ std::vector oauth1_config::_hmac_sha1(const utility::string_t& ke // - If URI port is unspecified. utility::string_t oauth1_config::_build_base_string_uri(const uri& u) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << u.scheme() << "://" << u.host(); + utility::string_t result(u.scheme()); + result += _XPLATSTR("://"); + result += u.host(); if (!u.is_port_default() && u.port() != 80 && u.port() != 443) { - os << ":" << u.port(); + result += _XPLATSTR(':'); + result += utility::conversions::details::to_string_t(u.port()); } - os << u.path(); - return uri::encode_data_string(os.str()); + + result += u.path(); + return uri::encode_data_string(std::move(result)); } utility::string_t oauth1_config::_build_normalized_parameters(web::http::uri u, const oauth1_state& state) const @@ -172,18 +175,12 @@ utility::string_t oauth1_config::_build_normalized_parameters(web::http::uri u, std::vector queries; for (const auto& query : queries_map) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << query.first << "=" << query.second; - queries.push_back(os.str()); + queries.push_back(query.first + _XPLATSTR('=') + query.second); } for (const auto& query : parameters()) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << query.first << "=" << query.second; - queries.push_back(os.str()); + queries.push_back(query.first + _XPLATSTR('=') + query.second); } // Push oauth1 parameters. @@ -202,15 +199,21 @@ utility::string_t oauth1_config::_build_normalized_parameters(web::http::uri u, } // Sort parameters and build the string. - sort(queries.begin(), queries.end()); - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - for (auto i = queries.begin(); i != queries.end() - 1; ++i) + utility::string_t result; + if (!queries.empty()) { - os << *i << U("&"); + auto i = queries.begin(); + auto e = queries.end(); + sort(i, e); + result = *i; + while (++i != e) + { + result += _XPLATSTR('&'); + result += *i; + } } - os << queries.back(); - return uri::encode_data_string(os.str()); + + return uri::encode_data_string(result); } static bool is_application_x_www_form_urlencoded (http_request &request) @@ -222,10 +225,9 @@ static bool is_application_x_www_form_urlencoded (http_request &request) utility::string_t oauth1_config::_build_signature_base_string(http_request request, oauth1_state state) const { uri u(request.absolute_uri()); - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << request.method(); - os << "&" << _build_base_string_uri(u); + utility::string_t result(request.method()); + result += _XPLATSTR('&'); + result += _build_base_string_uri(u); // http://oauth.net/core/1.0a/#signing_process // 9.1.1. Normalize Request Parameters @@ -233,19 +235,21 @@ utility::string_t oauth1_config::_build_signature_base_string(http_request reque // - Parameters in the OAuth HTTP Authorization header excluding the realm parameter. // - Parameters in the HTTP POST request body (with a content-type of application/x-www-form-urlencoded). // - HTTP GET parameters added to the URLs in the query part (as defined by [RFC3986] section 3). + result += _XPLATSTR('&'); if (is_application_x_www_form_urlencoded(request)) { // Note: this should be improved to not block and handle any potential exceptions. utility::string_t str = request.extract_string(true).get(); request.set_body(str, web::http::details::mime_types::application_x_www_form_urlencoded); uri v = http::uri_builder(request.absolute_uri()).append_query(std::move(str), false).to_uri(); - os << "&" << _build_normalized_parameters(std::move(v), std::move(state)); + result += _build_normalized_parameters(std::move(v), std::move(state)); } else { - os << "&" << _build_normalized_parameters(std::move(u), std::move(state)); + result += _build_normalized_parameters(std::move(u), std::move(state)); } - return os.str(); + + return result; } utility::string_t oauth1_config::_build_signature(http_request request, oauth1_state state) const @@ -323,31 +327,57 @@ pplx::task oauth1_config::_request_token(oauth1_state state, bool is_temp_ void oauth1_config::_authenticate_request(http_request &request, oauth1_state state) { - utility::ostringstream_t os; - os.imbue(std::locale::classic()); - os << "OAuth "; + utility::string_t authHeader(_XPLATSTR("OAuth ")); if (!realm().empty()) { - os << oauth1_strings::realm << "=\"" << web::uri::encode_data_string (realm()) << "\", "; + authHeader += oauth1_strings::realm; + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string(realm()); + authHeader += _XPLATSTR("\", "); } - os << oauth1_strings::version << "=\"1.0"; - os << "\", " << oauth1_strings::consumer_key << "=\"" << web::uri::encode_data_string (consumer_key()); + + authHeader += oauth1_strings::version; + authHeader += _XPLATSTR("=\"1.0\", "); + authHeader += oauth1_strings::consumer_key; + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string (consumer_key()); + if (!m_token.access_token().empty()) { - os << "\", " << oauth1_strings::token << "=\"" << web::uri::encode_data_string(m_token.access_token()); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::token; + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string(m_token.access_token()); } - os << "\", " << oauth1_strings::signature_method << "=\"" << method(); - os << "\", " << oauth1_strings::timestamp << "=\"" << state.timestamp(); - os << "\", " << oauth1_strings::nonce << "=\"" << state.nonce(); - os << "\", " << oauth1_strings::signature << "=\"" << uri::encode_data_string(_build_signature(request, state)); - os << "\""; + + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::signature_method; + authHeader += _XPLATSTR("=\""); + authHeader += method(); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::timestamp; + authHeader += _XPLATSTR("=\""); + authHeader += state.timestamp(); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::nonce; + authHeader += _XPLATSTR("=\""); + authHeader += state.nonce(); + authHeader += _XPLATSTR("\", "); + authHeader += oauth1_strings::signature; + authHeader += _XPLATSTR("=\""); + authHeader += uri::encode_data_string(_build_signature(request, state)); + authHeader += _XPLATSTR("\""); if (!state.extra_key().empty()) { - os << ", " << state.extra_key() << "=\"" << web::uri::encode_data_string(state.extra_value()) << "\""; + authHeader += _XPLATSTR(", "); + authHeader += state.extra_key(); + authHeader += _XPLATSTR("=\""); + authHeader += web::uri::encode_data_string(state.extra_value()); + authHeader += _XPLATSTR("\""); } - request.headers().add(header_names::authorization, os.str()); + request.headers().add(header_names::authorization, std::move(authHeader)); } pplx::task oauth1_config::build_authorization_uri() @@ -373,11 +403,10 @@ pplx::task oauth1_config::token_from_redirected_uri(const web::http::uri& } if (m_token.access_token() != token_param->second) { - utility::ostringstream_t err; - err.imbue(std::locale::classic()); - err << U("redirected URI parameter 'oauth_token'='") << token_param->second - << U("' does not match temporary token='") << m_token.access_token() << U("'."); - return pplx::task_from_exception(oauth1_exception(err.str().c_str())); + return pplx::task_from_exception(oauth1_exception( + _XPLATSTR("redirected URI parameter 'oauth_token'='") + token_param->second + + _XPLATSTR("' does not match temporary token='") + m_token.access_token() + _XPLATSTR("'.") + )); } auto verifier_param = query.find(oauth1_strings::verifier); diff --git a/Release/src/http/oauth/oauth2.cpp b/Release/src/http/oauth/oauth2.cpp index 247241933f..c85cf44c2f 100644 --- a/Release/src/http/oauth/oauth2.cpp +++ b/Release/src/http/oauth/oauth2.cpp @@ -71,11 +71,12 @@ pplx::task oauth2_config::token_from_redirected_uri(const web::http::uri& } if (state() != state_param->second) { - utility::ostringstream_t err; - err.imbue(std::locale::classic()); - err << U("redirected URI parameter 'state'='") << state_param->second - << U("' does not match state='") << state() << U("'."); - return pplx::task_from_exception(oauth2_exception(err.str())); + utility::string_t err(_XPLATSTR("redirected URI parameter 'state'='")); + err += state_param->second; + err += _XPLATSTR("' does not match state='"); + err += state(); + err += _XPLATSTR("'."); + return pplx::task_from_exception(oauth2_exception(std::move(err))); } auto code_param = query.find(oauth2_strings::code); diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index 295bd6e16a..a73a84b3ad 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -49,10 +49,13 @@ template #endif void CreateException(const Token &tk, const utility::string_t &message) { - utility::ostringstream_t os; - os << _XPLATSTR("* Line ") << tk.start.m_line << _XPLATSTR(", Column ") << tk.start.m_column << _XPLATSTR(" Syntax error: ") << message; - utility::string_t osStr = os.str(); - throw web::json::json_exception(osStr.c_str()); + std::string str("* Line "); + str += std::to_string(tk.start.m_line); + str += ", Column "; + str += std::to_string(tk.start.m_column); + str += " Syntax error: "; + str += utility::conversions::to_utf8string(message); + throw web::json::json_exception(std::move(str)); } template diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index e971c3c544..3903ce9ca7 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -275,11 +275,10 @@ std::string windows_category_impl::message(int errorCode) const CPPREST_NOEXCEPT &buffer[0], buffer_size, NULL); + if (result == 0) { - std::ostringstream os; - os << "Unable to get an error message for error code: " << errorCode << "."; - return os.str(); + return "Unable to get an error message for error code: " + std::to_string(errorCode) + "."; } return utility::conversions::to_utf8string(buffer); @@ -688,80 +687,92 @@ utility::string_t datetime::to_string(date_format format) const throw utility::details::create_system_error(GetLastError()); } - std::wostringstream outStream; - outStream.imbue(std::locale::classic()); - + std::wstring result; if (format == RFC_1123) { + { + wchar_t dateStr[18] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR dateStr[18] = {0}; - status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, __TEXT("ddd',' dd MMM yyyy"), dateStr, sizeof(dateStr) / sizeof(TCHAR)); + status = GetDateFormatW(LOCALE_INVARIANT, 0, &systemTime, L"ddd',' dd MMM yyyy", dateStr, sizeof(dateStr) / sizeof(wchar_t)); #else - wchar_t dateStr[18] = {0}; - status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"ddd',' dd MMM yyyy", dateStr, sizeof(dateStr) / sizeof(wchar_t), NULL); + status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"ddd',' dd MMM yyyy", dateStr, sizeof(dateStr) / sizeof(wchar_t), NULL); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += dateStr; + result += L' '; } + { + wchar_t timeStr[10] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR timeStr[10] = {0}; - status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, __TEXT("HH':'mm':'ss"), timeStr, sizeof(timeStr) / sizeof(TCHAR)); + status = GetTimeFormatW(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t)); #else - wchar_t timeStr[10] = {0}; - status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t)); + status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, sizeof(timeStr) / sizeof(wchar_t)); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += timeStr; + result += L" GMT"; } - outStream << dateStr << " " << timeStr << " " << "GMT"; } else if (format == ISO_8601) { const size_t buffSize = 64; + { + wchar_t dateStr[buffSize] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR dateStr[buffSize] = {0}; - status = GetDateFormat(LOCALE_INVARIANT, 0, &systemTime, __TEXT("yyyy-MM-dd"), dateStr, buffSize); + status = GetDateFormatW(LOCALE_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize); #else - wchar_t dateStr[buffSize] = {0}; - status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize, NULL); + status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize, NULL); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += dateStr; + result += L'T'; } + { + wchar_t timeStr[buffSize] = {0}; #if _WIN32_WINNT < _WIN32_WINNT_VISTA - TCHAR timeStr[buffSize] = {0}; - status = GetTimeFormat(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, __TEXT("HH':'mm':'ss"), timeStr, buffSize); + status = GetTimeFormatW(LOCALE_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize); #else - wchar_t timeStr[buffSize] = {0}; - status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize); + status = GetTimeFormatEx(LOCALE_NAME_INVARIANT, TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, &systemTime, L"HH':'mm':'ss", timeStr, buffSize); #endif // _WIN32_WINNT < _WIN32_WINNT_VISTA - if (status == 0) - { - throw utility::details::create_system_error(GetLastError()); + if (status == 0) + { + throw utility::details::create_system_error(GetLastError()); + } + + result += timeStr; } - outStream << dateStr << "T" << timeStr; + uint64_t frac_sec = largeInt.QuadPart % _secondTicks; if (frac_sec > 0) { // Append fractional second, which is a 7-digit value with no trailing zeros // This way, '1200' becomes '00012' - char buf[9] = { 0 }; - sprintf_s(buf, sizeof(buf), ".%07ld", (long int)frac_sec); - // trim trailing zeros - for (int i = 7; buf[i] == '0'; i--) buf[i] = '\0'; - outStream << buf; + wchar_t buf[9] = { 0 }; + size_t appended = swprintf_s(buf, 9, L".%07ld", static_cast(frac_sec)); + while (buf[appended - 1] == L'0') --appended; // trim trailing zeros + result.append(buf, appended); } - outStream << "Z"; + + result += L'Z'; } - return outStream.str(); + return result; #else //LINUX uint64_t input = m_interval; uint64_t frac_sec = input % _secondTicks; @@ -1103,33 +1114,44 @@ utility::string_t __cdecl timespan::seconds_to_xml_duration(utility::seconds dur // The format is: // PdaysDThoursHminutesMsecondsS - utility::ostringstream_t oss; - oss.imbue(std::locale::classic()); - - oss << _XPLATSTR("P"); + utility::string_t result; + // (approximate mins/hours/secs as 2 digits each + 1 prefix character) + 1 for P prefix + 1 for T + size_t baseReserveSize = ((numHours > 0) + (numMins > 0) + (numSecs > 0)) * 3 + 1; if (numDays > 0) { - oss << numDays << _XPLATSTR("D"); + utility::string_t daysStr = utility::conversions::details::to_string_t(numDays); + result.reserve(baseReserveSize + daysStr.size() + 1); + result += _XPLATSTR('P'); + result += daysStr; + result += _XPLATSTR('D'); + } + else + { + result.reserve(baseReserveSize); + result += _XPLATSTR('P'); } - oss << _XPLATSTR("T"); + result += _XPLATSTR('T'); if (numHours > 0) { - oss << numHours << _XPLATSTR("H"); + result += utility::conversions::details::to_string_t(numHours); + result += _XPLATSTR('H'); } if (numMins > 0) { - oss << numMins << _XPLATSTR("M"); + result += utility::conversions::details::to_string_t(numMins); + result += _XPLATSTR('M'); } if (numSecs > 0) { - oss << numSecs << _XPLATSTR("S"); + result += utility::conversions::details::to_string_t(numSecs); + result += _XPLATSTR('S'); } - return oss.str(); + return result; } utility::seconds __cdecl timespan::xml_duration_to_seconds(const utility::string_t ×panString) diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 39b7121d57..c4c46941ba 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -97,12 +97,12 @@ namespace details // Utility function to build up error string based on error code and location. static std::string build_error_msg(const std::error_code &ec, const std::string &location) { - std::stringstream ss; - ss.imbue(std::locale::classic()); - ss << location - << ": " << ec.value() - << ": " << ec.message(); - return ss.str(); + std::string result = location; + result += ": "; + result += std::to_string(ec.value()); + result += ": "; + result += ec.message(); + return result; } static utility::string_t g_subProtocolHeader(_XPLATSTR("Sec-WebSocket-Protocol")); diff --git a/Release/src/websockets/client/ws_msg.cpp b/Release/src/websockets/client/ws_msg.cpp index 1d24409c67..ee27cde01f 100644 --- a/Release/src/websockets/client/ws_msg.cpp +++ b/Release/src/websockets/client/ws_msg.cpp @@ -45,7 +45,7 @@ std::vector<::utility::string_t> websocket_client_config::subprotocols() const auto subprotocolHeader = m_headers.find(g_subProtocolHeader); if (subprotocolHeader != m_headers.end()) { - utility::stringstream_t header(subprotocolHeader->second); + utility::istringstream_t header(subprotocolHeader->second); utility::string_t token; while (std::getline(header, token, U(','))) { diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index 10e37186fa..fd9142931a 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -55,17 +55,14 @@ SUITE(compression_tests) size_t output_size, web::http::compression::operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { size_t bytes; if (_done) { input_bytes_processed = 0; - if (done) - { - *done = true; - } + done = true; return 0; } if (_size == static_cast(-1) || input_size > _size - _so_far) @@ -82,10 +79,7 @@ SUITE(compression_tests) } _so_far += bytes; _done = (_so_far == _size); - if (done) - { - *done = _done; - } + done = _done; input_bytes_processed = bytes; return input_bytes_processed; } @@ -102,7 +96,7 @@ SUITE(compression_tests) try { r.output_bytes_produced = - decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -120,17 +114,14 @@ SUITE(compression_tests) size_t output_size, web::http::compression::operation_hint hint, size_t& input_bytes_processed, - bool* done) + bool& done) { size_t bytes; if (_done) { input_bytes_processed = 0; - if (done) - { - *done = true; - } + done = true; return 0; } if (_size == static_cast(-1) || input_size > _size - _so_far) @@ -147,10 +138,7 @@ SUITE(compression_tests) } _so_far += bytes; _done = (hint == web::http::compression::operation_hint::is_last && _so_far == _size); - if (done) - { - *done = _done; - } + done = _done; input_bytes_processed = bytes; return input_bytes_processed; } @@ -167,7 +155,7 @@ SUITE(compression_tests) try { r.output_bytes_produced = - compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -224,14 +212,17 @@ SUITE(compression_tests) input_buffer.reserve(buffer_size); for (size_t i = 0; i < buffer_size; ++i) { + uint8_t element; if (compressible) { - input_buffer.push_back(static_cast('a' + i % 26)); + element = static_cast('a' + i % 26); } else { - input_buffer.push_back(static_cast(std::rand())); + element = static_cast(std::rand()); } + + input_buffer.push_back(element); } // compress in chunks @@ -869,7 +860,7 @@ SUITE(compression_tests) pre.size(), web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_IS_TRUE(used == v.size()); VERIFY_IS_TRUE(done); @@ -1019,7 +1010,7 @@ SUITE(compression_tests) pre.size(), web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_ARE_EQUAL(used, v.size()); VERIFY_IS_TRUE(done); @@ -1110,7 +1101,7 @@ SUITE(compression_tests) vv.size(), web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_ARE_EQUAL(used, p_request->m_body.size()); VERIFY_IS_TRUE(done); } @@ -1219,7 +1210,7 @@ SUITE(compression_tests) cmp.size() - extra, web::http::compression::operation_hint::is_last, used, - &done); + done); VERIFY_ARE_EQUAL(used, v.size()); VERIFY_IS_TRUE(done); } From b9dd8eab814892f110853be1098df1b3f77b2ff0 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 10 Oct 2018 20:28:41 -0700 Subject: [PATCH 445/609] Reduce stdafx.h header inclusion to avoid running out of memory on *nix boxes in Pipelines (#906) * Pare down stdafx.h to avoid running out of memory on the Linux builders with ninja. * Remove ninja -j. --- Release/include/cpprest/asyncrt_utils.h | 11 ++++------- Release/src/http/client/http_client_asio.cpp | 1 + Release/src/http/common/http_msg.cpp | 2 ++ Release/src/http/listener/http_server_asio.cpp | 2 ++ .../src/http/listener/http_server_httpsys.cpp | 1 + Release/src/http/oauth/oauth2.cpp | 2 ++ Release/src/pch/stdafx.h | 18 ------------------ Release/src/pplx/pplxlinux.cpp | 1 + Release/src/uri/uri.cpp | 2 ++ Release/src/uri/uri_builder.cpp | 10 ++++++---- Release/src/utilities/asyncrt_utils.cpp | 1 + Release/src/websockets/client/ws_client.cpp | 3 ++- .../src/websockets/client/ws_client_wspp.cpp | 1 + Release/src/websockets/client/ws_msg.cpp | 3 +++ azure-pipelines.yml | 8 ++++---- 15 files changed, 32 insertions(+), 34 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 2739a13e35..03bd6fbf90 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -13,20 +13,17 @@ #pragma once -#include -#include +#include #include -#include #include +#include +#include +#include #include #include #include "pplx/pplxtasks.h" #include "cpprest/details/basic_types.h" -#if !defined(_WIN32) || (_MSC_VER >= 1700) -#include -#endif - #ifndef _WIN32 #include #if !defined(ANDROID) && !defined(__ANDROID__) && defined(HAVE_XLOCALE_H) // CodePlex 269 diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 7ee22133fe..645b45466c 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -14,6 +14,7 @@ ****/ #include "stdafx.h" +#include #include "../common/internal_http_helpers.h" #include "cpprest/asyncrt_utils.h" diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 44870f5420..91da2c2c3e 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -11,7 +11,9 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ #include "stdafx.h" +#include #include "../common/internal_http_helpers.h" +#include "cpprest/producerconsumerstream.h" using namespace web; using namespace utility; diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 5ab3086954..591e623d82 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -14,6 +14,8 @@ */ #include "stdafx.h" +#include +#include #include #include #include diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 242dae4800..9cde3f522e 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -14,6 +14,7 @@ ****/ #include "stdafx.h" +#include "cpprest/rawptrstream.h" #if _WIN32_WINNT >= _WIN32_WINNT_VISTA diff --git a/Release/src/http/oauth/oauth2.cpp b/Release/src/http/oauth/oauth2.cpp index c85cf44c2f..f37f876dbc 100644 --- a/Release/src/http/oauth/oauth2.cpp +++ b/Release/src/http/oauth/oauth2.cpp @@ -13,6 +13,8 @@ #include "stdafx.h" +#include + using web::http::client::http_client; using web::http::client::http_client_config; using web::http::oauth2::details::oauth2_strings; diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index 93ad966509..dc909d5afd 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -49,8 +49,6 @@ #include #include #include -#include -#include #include #include #include "pthread.h" @@ -75,19 +73,14 @@ // This is to help track how many developers are directly building from source themselves. #define _CASA_BUILD_FROM_SRC -#include -#include #include #include #include -#include #include #include #include #include #include -#include -#include #include "cpprest/details/cpprest_compat.h" #include "cpprest/details/basic_types.h" @@ -95,13 +88,6 @@ #include "pplx/pplxtasks.h" #include "cpprest/version.h" -// streams -#include "cpprest/streams.h" -#include "cpprest/astreambuf.h" -#include "cpprest/rawptrstream.h" -#include "cpprest/interopstream.h" -#include "cpprest/producerconsumerstream.h" - // json #include "cpprest/json.h" @@ -124,10 +110,6 @@ #endif #include "cpprest/oauth2.h" -// websockets -#include "cpprest/ws_client.h" -#include "cpprest/ws_msg.h" - #if !defined(__cplusplus_winrt) #if _WIN32_WINNT >= _WIN32_WINNT_VISTA #include "cpprest/details/http_server.h" diff --git a/Release/src/pplx/pplxlinux.cpp b/Release/src/pplx/pplxlinux.cpp index b2dc524c86..50365794a3 100644 --- a/Release/src/pplx/pplxlinux.cpp +++ b/Release/src/pplx/pplxlinux.cpp @@ -15,6 +15,7 @@ #include "pplx/pplx.h" #include "pplx/threadpool.h" #include "sys/syscall.h" +#include #ifdef _WIN32 #error "ERROR: This file should only be included in non-windows Build" diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index fac048c9da..eaacb5ccfd 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -13,6 +13,8 @@ #include "stdafx.h" +#include + using namespace utility::conversions; namespace web { namespace details diff --git a/Release/src/uri/uri_builder.cpp b/Release/src/uri/uri_builder.cpp index 02dd024b9b..f99923c487 100644 --- a/Release/src/uri/uri_builder.cpp +++ b/Release/src/uri/uri_builder.cpp @@ -13,6 +13,8 @@ #include "stdafx.h" +#include + namespace web { @@ -120,8 +122,8 @@ bool uri_builder::is_valid() return uri::validate(m_uri.join()); } -void uri_builder::append_query_encode_impl(const utility::string_t & name, const utf8string & value) -{ +void uri_builder::append_query_encode_impl(const utility::string_t & name, const utf8string & value) +{ utility::string_t encodedQuery = uri::encode_query_impl(utility::conversions::to_utf8string(name)); encodedQuery.append(_XPLATSTR("=")); encodedQuery.append(uri::encode_query_impl(value)); @@ -130,8 +132,8 @@ void uri_builder::append_query_encode_impl(const utility::string_t & name, const append_query(encodedQuery, false); } -void uri_builder::append_query_no_encode_impl(const utility::string_t & name, const utility::string_t & value) -{ +void uri_builder::append_query_no_encode_impl(const utility::string_t & name, const utility::string_t & value) +{ append_query(name + _XPLATSTR("=") + value, false); } diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 3903ce9ca7..eb20f91f0e 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #ifndef _WIN32 #if defined(__clang__) diff --git a/Release/src/websockets/client/ws_client.cpp b/Release/src/websockets/client/ws_client.cpp index 4caceb3b2e..1d829eb746 100644 --- a/Release/src/websockets/client/ws_client.cpp +++ b/Release/src/websockets/client/ws_client.cpp @@ -9,6 +9,7 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ #include "stdafx.h" +#include "cpprest/ws_client.h" #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) @@ -91,4 +92,4 @@ pplx::task websocket_client_task_impl::receive() }}}} -#endif \ No newline at end of file +#endif diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index c4c46941ba..5ba93d25eb 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -12,6 +12,7 @@ ****/ #include "stdafx.h" +#include #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) diff --git a/Release/src/websockets/client/ws_msg.cpp b/Release/src/websockets/client/ws_msg.cpp index ee27cde01f..c9a5bea8ae 100644 --- a/Release/src/websockets/client/ws_msg.cpp +++ b/Release/src/websockets/client/ws_msg.cpp @@ -13,6 +13,9 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ #include "stdafx.h" +#include +#include "cpprest/ws_client.h" +#include "cpprest/ws_msg.h" #include "../../http/common/internal_http_helpers.h" #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d984c4094e..f40964713a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,7 +18,7 @@ jobs: cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' - script: | cd build.debug - ninja -j 4 + ninja displayName: 'Run ninja' - script: | cd build.debug/Release/Binaries @@ -41,7 +41,7 @@ jobs: cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' - script: | cd build.release - ninja -j 4 + ninja displayName: 'Run ninja' - script: | cd build.release/Release/Binaries @@ -61,7 +61,7 @@ jobs: cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' - script: | cd build.debug - ninja -j 4 + ninja displayName: 'Run ninja' - script: | cd build.debug/Release/Binaries @@ -81,7 +81,7 @@ jobs: cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' - script: | cd build.release - ninja -j 4 + ninja displayName: 'Run ninja' - script: | cd build.release/Release/Binaries From a072579126e3dfb750f489785b85f5752239f53e Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Fri, 12 Oct 2018 13:26:32 -0700 Subject: [PATCH 446/609] Add Windows CI to Pipelines using vcpkg for dependencies; merge debug and release for other platforms. (#911) --- .gitmodules | 3 + azure-pipelines.yml | 219 +++++++++++++++++++++++++++++++++++--------- vcpkg | 1 + 3 files changed, 182 insertions(+), 41 deletions(-) create mode 100644 .gitmodules create mode 160000 vcpkg diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..3c19d8d07f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/Microsoft/vcpkg diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f40964713a..bb52036b90 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,30 +1,135 @@ # CppRestSdk Azure Pipelines Configuration jobs: - - job: Ubuntu_1604_Apt_Debug + - job: Windows_VS2017_x86 pool: - vmImage: 'Ubuntu 16.04' + vmImage: 'vs2017-win2016' steps: + - script: .\vcpkg\bootstrap-vcpkg.bat + displayName: Bootstrap vcpkg + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp + displayName: vcpkg install dependencies + - script: mkdir build.common + displayName: Make Build Directory + - task: CMake@1 + inputs: + workingDirectory: 'build.common' + cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true - script: | - sudo apt-get install -y ppa-purge - sudo ppa-purge -y ppa:ondrej/php - sudo apt-get install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev brotli openssl libssl-dev ninja-build - displayName: Apt install dependencies - - script: mkdir build.debug - displayName: Make build.debug + cd build.common\Release\Binaries\Debug + .\test_runner.exe *testd.dll + displayName: 'Run tests, debug' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true + configuration: 'Release' + - script: | + cd build.common\Release\Binaries\Release + .\test_runner.exe *test.dll + displayName: 'Run tests, release' + - job: Windows_VS2017_x64 + pool: + vmImage: 'vs2017-win2016' + steps: + - script: .\vcpkg\bootstrap-vcpkg.bat + displayName: Bootstrap vcpkg + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp --triplet x64-windows + displayName: vcpkg install dependencies + - script: mkdir build.common + displayName: Make Build Directory - task: CMake@1 inputs: - workingDirectory: 'build.debug' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' + workingDirectory: 'build.common' + cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true + platform: 'x64' - script: | - cd build.debug - ninja - displayName: 'Run ninja' + cd build.common\Release\Binaries\Debug + .\test_runner.exe *testd.dll + displayName: 'Run tests, debug' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true + platform: 'x64' + configuration: 'Release' - script: | - cd build.debug/Release/Binaries - ./test_runner *test.so - displayName: 'Run Tests' - - job: Ubuntu_1604_Apt_Release + cd build.common\Release\Binaries\Release + .\test_runner.exe *test.dll + displayName: 'Run tests, release' + - job: Windows_VS2015_x86 + pool: + vmImage: 'vs2015-win2012r2' + steps: + - script: .\vcpkg\bootstrap-vcpkg.bat + displayName: Bootstrap vcpkg + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp + displayName: vcpkg install dependencies + - script: mkdir build.common + displayName: Make Build Directory + - task: CMake@1 + inputs: + workingDirectory: 'build.common' + cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true + - script: | + cd build.common\Release\Binaries\Debug + .\test_runner.exe *testd.dll + displayName: 'Run tests, debug' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true + configuration: 'Release' + - script: | + cd build.common\Release\Binaries\Release + .\test_runner.exe *test.dll + displayName: 'Run tests, release' + - job: Windows_VS2015_x64 + pool: + vmImage: 'vs2015-win2012r2' + steps: + - script: .\vcpkg\bootstrap-vcpkg.bat + displayName: Bootstrap vcpkg + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp --triplet x64-windows + displayName: vcpkg install dependencies + - script: mkdir build.common + displayName: Make Build Directory + - task: CMake@1 + inputs: + workingDirectory: 'build.common' + cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true + platform: 'x64' + - script: | + cd build.common\Release\Binaries\Debug + .\test_runner.exe *testd.dll + displayName: 'Run tests, debug' + - task: MSBuild@1 + inputs: + solution: 'build.common/ALL_BUILD.vcxproj' + maximumCpuCount: true + platform: 'x64' + configuration: 'Release' + - script: | + cd build.common\Release\Binaries\Release + .\test_runner.exe *test.dll + displayName: 'Run tests, release' + - job: Ubuntu_1604_Apt pool: vmImage: 'Ubuntu 16.04' steps: @@ -33,57 +138,89 @@ jobs: sudo ppa-purge -y ppa:ondrej/php sudo apt-get install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev brotli openssl libssl-dev ninja-build displayName: Apt install dependencies - - script: mkdir build.release - displayName: Make build.release + - script: | + mkdir build.debug + mkdir build.release + displayName: Make Build Directories + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' - task: CMake@1 inputs: workingDirectory: 'build.release' cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' + - script: | + cd build.debug + ninja + displayName: 'Run ninja, debug' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.so + displayName: 'Run tests, debug' - script: | cd build.release ninja - displayName: 'Run ninja' + displayName: 'Run ninja, release' - script: | cd build.release/Release/Binaries ./test_runner *test.so - displayName: 'Run Tests' - - job: MacOS_Debug + displayName: 'Run tests, release' + + # vcpkg on Linux missing for now due to OpenSSL root certificates + # - job: Ubuntu_1604_Vcpkg_Debug + # pool: + # vmImage: 'Ubuntu 16.04' + # steps: + # - script: | + # ./vcpkg/bootstrap-vcpkg.sh + # ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono + # displayName: Apt install dependencies + # - script: mkdir build.debug + # displayName: Make build.debug + # - task: CMake@1 + # inputs: + # workingDirectory: 'build.debug' + # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + # - script: | + # cd build.debug + # ninja + # displayName: 'Run ninja' + # - script: | + # cd build.debug/Release/Binaries + # ./test_runner *test.so + # displayName: 'Run Tests' + - job: MacOS pool: vmImage: 'macOS-10.13' steps: - script: brew install boost openssl ninja - displayName: Berw install dependencies - - script: mkdir build.debug - displayName: Make build.debug + displayName: Brew install dependencies + - script: | + mkdir build.debug + mkdir build.release + displayName: Make Build Directories - task: CMake@1 inputs: workingDirectory: 'build.debug' cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' - script: | cd build.debug ninja - displayName: 'Run ninja' + displayName: 'Run ninja, debug' - script: | cd build.debug/Release/Binaries ./test_runner *test.dylib - displayName: 'Run Tests' - - job: MacOS_Release - pool: - vmImage: 'macOS-10.13' - steps: - - script: brew install boost openssl ninja - displayName: Berw install dependencies - - script: mkdir build.release - displayName: Make build.release - - task: CMake@1 - inputs: - workingDirectory: 'build.release' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' + displayName: 'Run tests, debug' - script: | cd build.release ninja - displayName: 'Run ninja' + displayName: 'Run ninja, release' - script: | cd build.release/Release/Binaries ./test_runner *test.dylib - displayName: 'Run Tests' + displayName: 'Run tests, release' diff --git a/vcpkg b/vcpkg new file mode 160000 index 0000000000..29858b3cb2 --- /dev/null +++ b/vcpkg @@ -0,0 +1 @@ +Subproject commit 29858b3cb2c8a0ec2c85b1b14d6d0a0d1dfe309e From 61b1699af21740a2fb5bc8f4d2b81494a4b220e8 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Fri, 12 Oct 2018 16:58:01 -0700 Subject: [PATCH 447/609] Enable Brotli in CI. (#912) * Enable Brotli in CI. --- Release/src/http/common/http_compression.cpp | 4 +-- azure-pipelines.yml | 27 +++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index 9d409906c5..d73167239b 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -383,7 +383,7 @@ class brotli_compressor : public compress_provider try { r.output_bytes_produced = - compress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + compress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { @@ -509,7 +509,7 @@ class brotli_decompressor : public decompress_provider try { r.output_bytes_produced = - decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, &r.done); + decompress(input, input_size, output, output_size, hint, r.input_bytes_processed, r.done); } catch (...) { diff --git a/azure-pipelines.yml b/azure-pipelines.yml index bb52036b90..76766a59b4 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -7,14 +7,14 @@ jobs: steps: - script: .\vcpkg\bootstrap-vcpkg.bat displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli displayName: vcpkg install dependencies - script: mkdir build.common displayName: Make Build Directory - task: CMake@1 inputs: workingDirectory: 'build.common' - cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - task: MSBuild@1 inputs: solution: 'build.common/ALL_BUILD.vcxproj' @@ -38,14 +38,14 @@ jobs: steps: - script: .\vcpkg\bootstrap-vcpkg.bat displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp --triplet x64-windows + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli --triplet x64-windows displayName: vcpkg install dependencies - script: mkdir build.common displayName: Make Build Directory - task: CMake@1 inputs: workingDirectory: 'build.common' - cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - task: MSBuild@1 inputs: solution: 'build.common/ALL_BUILD.vcxproj' @@ -71,14 +71,14 @@ jobs: steps: - script: .\vcpkg\bootstrap-vcpkg.bat displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli displayName: vcpkg install dependencies - script: mkdir build.common displayName: Make Build Directory - task: CMake@1 inputs: workingDirectory: 'build.common' - cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - task: MSBuild@1 inputs: solution: 'build.common/ALL_BUILD.vcxproj' @@ -102,14 +102,14 @@ jobs: steps: - script: .\vcpkg\bootstrap-vcpkg.bat displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp --triplet x64-windows + - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli --triplet x64-windows displayName: vcpkg install dependencies - script: mkdir build.common displayName: Make Build Directory - task: CMake@1 inputs: workingDirectory: 'build.common' - cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - task: MSBuild@1 inputs: solution: 'build.common/ALL_BUILD.vcxproj' @@ -136,7 +136,7 @@ jobs: - script: | sudo apt-get install -y ppa-purge sudo ppa-purge -y ppa:ondrej/php - sudo apt-get install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev brotli openssl libssl-dev ninja-build + sudo apt-get install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev openssl libssl-dev ninja-build displayName: Apt install dependencies - script: | mkdir build.debug @@ -199,6 +199,7 @@ jobs: - script: | mkdir build.debug mkdir build.release + mkdir build.release.static displayName: Make Build Directories - task: CMake@1 inputs: @@ -208,6 +209,10 @@ jobs: inputs: workingDirectory: 'build.release' cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release.static' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF ..' - script: | cd build.debug ninja @@ -224,3 +229,7 @@ jobs: cd build.release/Release/Binaries ./test_runner *test.dylib displayName: 'Run tests, release' + - script: | + cd build.release.static + ninja + displayName: 'Run ninja, release static' From 8a1eec818a86ee9372ca89f976ffa982d4591a9f Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Sun, 14 Oct 2018 15:02:28 -0700 Subject: [PATCH 448/609] Restore PCHes and delete unmaintained / broken legacy project files. (#914) --- Build/Common.Build.Traversal.targets | 28 -- Build/Common.Build.settings | 242 ---------- Build/Config.Definitions.props | 29 -- Build/Release.Product.settings | 64 --- Build/Release.Tests.settings | 27 -- Build/version.props | 11 - NuGet.Config | 6 - .../BingRequest140.xp.vcxproj | 133 ------ .../BingRequest140.xp.vcxproj.filters | 13 - .../BingRequest140/BingRequest140.vcxproj | 141 ------ .../BingRequest140.vcxproj.filters | 13 - .../BingRequest141/BingRequest141.vcxproj | 134 ------ .../BingRequest141.vcxproj.filters | 12 - .../BlackJack_Client/BlackJackClient.cpp | 31 +- .../BlackJack_Client140.vcxproj | 148 ------ .../BlackJack_Client140.vcxproj.filters | 33 -- .../BlackJack_Client141.vcxproj | 149 ------ .../BlackJack_Client141.vcxproj.filters | 30 -- .../BlackJack/BlackJack_Client/CMakeLists.txt | 1 - .../BlackJack/BlackJack_Client/stdafx.cpp | 15 - .../BlackJack/BlackJack_Client/stdafx.h | 44 -- .../BlackJack/BlackJack_Client/targetver.h | 18 - .../BlackJack_Server140.vcxproj | 154 ------ .../BlackJack_Server140.vcxproj.filters | 45 -- .../BlackJack_Server141.vcxproj | 155 ------- .../BlackJack_Server141.vcxproj.filters | 42 -- .../BlackJack/BlackJack_Server/CMakeLists.txt | 12 +- Release/samples/Oauth1Client/CMakeLists.txt | 5 +- Release/samples/Oauth1Client/Oauth1Client.cpp | 4 +- .../Oauth1Client140/Oauth1Client140.vcxproj | 205 -------- .../Oauth1Client140.vcxproj.filters | 33 -- .../Oauth1Client141/Oauth1Client141.vcxproj | 206 --------- .../Oauth1Client141.vcxproj.filters | 33 -- Release/samples/Oauth1Client/stdafx.cpp | 15 - Release/samples/Oauth1Client/stdafx.h | 17 - Release/samples/Oauth2Client/CMakeLists.txt | 3 +- Release/samples/Oauth2Client/Oauth2Client.cpp | 4 +- .../Oauth2Client140/Oauth2Client140.vcxproj | 205 -------- .../Oauth2Client140.vcxproj.filters | 33 -- .../Oauth2Client141/Oauth2Client141.vcxproj | 206 --------- .../Oauth2Client141.vcxproj.filters | 33 -- Release/samples/Oauth2Client/stdafx.cpp | 15 - Release/samples/Oauth2Client/stdafx.h | 17 - .../SearchFile140/SearchFile140.vcxproj | 146 ------ .../SearchFile140.vcxproj.filters | 13 - .../SearchFile141/SearchFile141.vcxproj | 147 ------ .../SearchFile141.vcxproj.filters | 13 - Release/src/CMakeLists.txt | 2 +- Release/src/build/android.vcxitems | 31 -- Release/src/build/android.vcxitems.filters | 39 -- Release/src/build/common.vcxitems | 93 ---- Release/src/build/common.vcxitems.filters | 227 --------- Release/src/build/cpprest.natvis | 207 --------- Release/src/build/init.ps1 | 23 - Release/src/build/other.vcxitems | 22 - Release/src/build/other.vcxitems.filters | 16 - .../casablanca140.android.vcxproj | 138 ------ .../src/build/vs14.android/packages.config | 11 - .../vs14.static/casablanca140.static.vcxproj | 84 ---- Release/src/build/vs14.static/packages.config | 11 - .../cpprestsdk140.uwp.staticlib.vcxproj | 110 ----- .../build/vs14.uwp/cpprestsdk140.uwp.vcxproj | 99 ---- .../build/vs14.xp/casablanca140.xp.vcxproj | 86 ---- Release/src/build/vs14.xp/packages.config | 11 - Release/src/build/vs14/casablanca140.vcxproj | 78 ---- Release/src/build/vs14/packages.config | 11 - .../vs141.android/cpprest141.android.vcxproj | 140 ------ .../src/build/vs141.android/packages.config | 11 - .../build/vs141.uwp/cpprest141.uwp.vcxproj | 91 ---- Release/src/build/vs141/cpprest141.vcxproj | 85 ---- Release/src/build/vs141/packages.config | 11 - Release/src/build/win32.vcxitems | 33 -- Release/src/build/win32.vcxitems.filters | 39 -- Release/src/build/winrt.vcxitems | 31 -- Release/src/build/winrt.vcxitems.filters | 33 -- .../ios/ios_runner.xcodeproj/project.pbxproj | 368 --------------- .../contents.xcworkspacedata | 7 - .../xcschemes/ios_runner.xcscheme | 110 ----- .../TestRunner/ios/ios_runnerTests/Info.plist | 24 - .../ios/ios_runnerTests/ios_runnerTests.mm | 67 --- .../TestRunner.android.NativeActivity.vcxproj | 284 ------------ ...ner.android.NativeActivity.vcxproj.filters | 14 - .../android_native_app_glue.c | 426 ----------------- .../android_native_app_glue.h | 344 -------------- .../main.cpp | 437 ------------------ .../packages.config | 12 - .../TestRunner.android.NativeActivity/pch.h | 23 - .../AndroidManifest.xml | 30 -- .../TestRunner.android.Packaging.androidproj | 84 ---- .../TestRunner.android.Packaging/build.xml | 82 ---- .../project.properties | 2 - .../res/values/strings.xml | 4 - .../vs14.uwp/TestRunner140.uwp.vcxproj | 118 ----- .../TestRunner140.uwp.vcxproj.filters | 24 - .../TestRunner/vs14/TestRunner140.vcxproj | 248 ---------- .../vs14/TestRunner140.vcxproj.filters | 24 - .../UnitTestpp140.android.vcxproj | 199 -------- .../UnitTestpp140.android.vcxproj.filters | 168 ------- .../vs14.uwp/UnitTestpp140.uwp.vcxproj | 208 --------- .../UnitTestpp140.uwp.vcxproj.filters | 159 ------- .../UnitTestpp/vs14/TestUnitTestpp140.vcxproj | 202 -------- .../vs14/TestUnitTestpp140.vcxproj.filters | 72 --- .../UnitTestpp/vs14/UnitTestpp140.vcxproj | 228 --------- .../vs14/UnitTestpp140.vcxproj.filters | 159 ------- Release/tests/common/utilities/CMakeLists.txt | 1 - .../tests/common/utilities/os_utilities.cpp | 7 +- Release/tests/common/utilities/stdafx.cpp | 18 - Release/tests/common/utilities/stdafx.h | 24 - Release/tests/common/utilities/targetver.h | 20 - .../CommonUtilities140.android.vcxproj | 148 ------ ...CommonUtilities140.android.vcxproj.filters | 36 -- .../vs14.uwp/CommonUtilities140.uwp.vcxproj | 167 ------- .../CommonUtilities140.uwp.vcxproj.filters | 33 -- .../vs14.xp/CommonUtilities140.xp.vcxproj | 150 ------ .../utilities/vs14/CommonUtilities140.vcxproj | 200 -------- .../vs14/CommonUtilities140.vcxproj.filters | 33 -- .../functional/http/client/CMakeLists.txt | 14 +- .../http/client/compression_tests.cpp | 3 +- .../HttpClient140_test.android.vcxproj | 168 ------- ...HttpClient140_test.android.vcxproj.filters | 90 ---- .../http/client/vs14.android/packages.config | 5 - .../vs14.uwp/HttpClient140_test.uwp.vcxproj | 153 ------ .../HttpClient140_test.uwp.vcxproj.filters | 87 ---- .../client/vs14/HttpClient140_test.vcxproj | 240 ---------- .../vs14/HttpClient140_test.vcxproj.filters | 88 ---- .../functional/http/listener/CMakeLists.txt | 12 +- .../HttpListener140_test.android.vcxproj | 160 ------- ...tpListener140_test.android.vcxproj.filters | 66 --- .../vs14/HttpListener140_test.vcxproj | 242 ---------- .../vs14/HttpListener140_test.vcxproj.filters | 63 --- .../HttpTestUtilities140.android.vcxproj | 156 ------- ...tpTestUtilities140.android.vcxproj.filters | 54 --- .../vs14.uwp/HttpTestUtilities140.uwp.vcxproj | 183 -------- .../HttpTestUtilities140.uwp.vcxproj.filters | 51 -- .../vs14/HttpTestUtilities140.vcxproj | 218 --------- .../vs14/HttpTestUtilities140.vcxproj.filters | 51 -- Release/tests/functional/json/CMakeLists.txt | 14 +- .../vs14.android/JSON140_test.android.vcxproj | 154 ------ .../JSON140_test.android.vcxproj.filters | 48 -- .../json/vs14.uwp/JSON140_test.uwp.vcxproj | 128 ----- .../vs14.uwp/JSON140_test.uwp.vcxproj.filters | 42 -- .../json/vs14.xp/JSON140_test.xp.vcxproj | 151 ------ .../functional/json/vs14/JSON140_test.vcxproj | 211 --------- .../json/vs14/JSON140_test.vcxproj.filters | 47 -- .../misc/version/vs14/version140_test.vcxproj | 100 ---- .../functional/pplx/pplx_test/CMakeLists.txt | 14 +- .../vs14.android/pplx140_test.android.vcxproj | 149 ------ .../vs14.uwp/pplx140_test.uwp.vcxproj | 130 ------ .../pplx_test/vs14.xp/pplx140_test.xp.vcxproj | 158 ------- .../pplx/pplx_test/vs14/pplx140_test.vcxproj | 212 --------- .../tests/functional/streams/CMakeLists.txt | 14 +- .../streams140_test.android.vcxproj | 153 ------ .../streams140_test.android.vcxproj.filters | 43 -- .../vs14.uwp/streams140_test.uwp.vcxproj | 137 ------ .../streams140_test.uwp.vcxproj.filters | 45 -- .../vs14.xp/streams140_test.xp.vcxproj | 163 ------- .../streams/vs14/streams140_test.vcxproj | 219 --------- .../vs14/streams140_test.vcxproj.filters | 43 -- Release/tests/functional/uri/CMakeLists.txt | 14 +- .../vs14.android/Uri140_test.android.vcxproj | 156 ------- .../Uri140_test.android.vcxproj.filters | 54 --- .../vs14.uwp/URI140_test.uwp.vcxproj.filters | 57 --- .../uri/vs14.uwp/Uri140_test.uwp.vcxproj | 136 ------ .../uri/vs14.xp/Uri140_test.xp.vcxproj | 155 ------- .../functional/uri/vs14/Uri140_test.vcxproj | 212 --------- .../uri/vs14/Uri140_test.vcxproj.filters | 53 --- Release/tests/functional/utils/CMakeLists.txt | 14 +- .../Utils140_test.android.vcxproj | 152 ------ .../Utils140_test.android.vcxproj.filters | 42 -- .../utils/vs14.uwp/Utils140_test.uwp.vcxproj | 131 ------ .../Utils140_test.uwp.vcxproj.filters | 36 -- .../utils/vs14.xp/Utils140_test.xp.vcxproj | 151 ------ .../utils/vs14/Utils140_test.vcxproj | 208 --------- .../utils/vs14/Utils140_test.vcxproj.filters | 38 -- .../websocketsclient140_test.android.vcxproj | 154 ------ .../websocketsclient140_test.uwp.vcxproj | 127 ----- .../websocketsclient140_test.xp.vcxproj | 123 ----- .../vs14/websocketsclient140_test.vcxproj | 125 ----- .../utilities/vs14.android/packages.config | 5 - ...bsockets_test_utilities140.android.vcxproj | 148 ------ .../utilities/vs14.uwp/packages.config | 7 - .../websockets_test_utilities140.uwp.vcxproj | 147 ------ .../websockets_test_utilities140.xp.vcxproj | 132 ------ .../websockets/utilities/vs14/packages.config | 7 - .../vs14/websockets_test_utilities140.vcxproj | 151 ------ build.root | 1 - cpprestsdk140.sln | 292 ------------ cpprestsdk141.sln | 258 ----------- 188 files changed, 143 insertions(+), 17442 deletions(-) delete mode 100644 Build/Common.Build.Traversal.targets delete mode 100644 Build/Common.Build.settings delete mode 100644 Build/Config.Definitions.props delete mode 100644 Build/Release.Product.settings delete mode 100644 Build/Release.Tests.settings delete mode 100644 Build/version.props delete mode 100644 NuGet.Config delete mode 100644 Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj delete mode 100644 Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters delete mode 100644 Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj delete mode 100644 Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj.filters delete mode 100644 Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj delete mode 100644 Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj.filters delete mode 100644 Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj.filters delete mode 100644 Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj.filters delete mode 100644 Release/samples/BlackJack/BlackJack_Client/stdafx.cpp delete mode 100644 Release/samples/BlackJack/BlackJack_Client/stdafx.h delete mode 100644 Release/samples/BlackJack/BlackJack_Client/targetver.h delete mode 100644 Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj.filters delete mode 100644 Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj.filters delete mode 100644 Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj delete mode 100644 Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj.filters delete mode 100644 Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj delete mode 100644 Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj.filters delete mode 100644 Release/samples/Oauth1Client/stdafx.cpp delete mode 100644 Release/samples/Oauth1Client/stdafx.h delete mode 100644 Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj delete mode 100644 Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj.filters delete mode 100644 Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj delete mode 100644 Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj.filters delete mode 100644 Release/samples/Oauth2Client/stdafx.cpp delete mode 100644 Release/samples/Oauth2Client/stdafx.h delete mode 100644 Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj delete mode 100644 Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj.filters delete mode 100644 Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj delete mode 100644 Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj.filters delete mode 100644 Release/src/build/android.vcxitems delete mode 100644 Release/src/build/android.vcxitems.filters delete mode 100644 Release/src/build/common.vcxitems delete mode 100644 Release/src/build/common.vcxitems.filters delete mode 100644 Release/src/build/cpprest.natvis delete mode 100644 Release/src/build/init.ps1 delete mode 100644 Release/src/build/other.vcxitems delete mode 100644 Release/src/build/other.vcxitems.filters delete mode 100644 Release/src/build/vs14.android/casablanca140.android.vcxproj delete mode 100644 Release/src/build/vs14.android/packages.config delete mode 100644 Release/src/build/vs14.static/casablanca140.static.vcxproj delete mode 100644 Release/src/build/vs14.static/packages.config delete mode 100644 Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj delete mode 100644 Release/src/build/vs14.uwp/cpprestsdk140.uwp.vcxproj delete mode 100644 Release/src/build/vs14.xp/casablanca140.xp.vcxproj delete mode 100644 Release/src/build/vs14.xp/packages.config delete mode 100644 Release/src/build/vs14/casablanca140.vcxproj delete mode 100644 Release/src/build/vs14/packages.config delete mode 100644 Release/src/build/vs141.android/cpprest141.android.vcxproj delete mode 100644 Release/src/build/vs141.android/packages.config delete mode 100644 Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj delete mode 100644 Release/src/build/vs141/cpprest141.vcxproj delete mode 100644 Release/src/build/vs141/packages.config delete mode 100644 Release/src/build/win32.vcxitems delete mode 100644 Release/src/build/win32.vcxitems.filters delete mode 100644 Release/src/build/winrt.vcxitems delete mode 100644 Release/src/build/winrt.vcxitems.filters delete mode 100644 Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.pbxproj delete mode 100644 Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/xcshareddata/xcschemes/ios_runner.xcscheme delete mode 100644 Release/tests/common/TestRunner/ios/ios_runnerTests/Info.plist delete mode 100644 Release/tests/common/TestRunner/ios/ios_runnerTests/ios_runnerTests.mm delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj.filters delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.c delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.h delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/main.cpp delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/pch.h delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/TestRunner.android.Packaging.androidproj delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/build.xml delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/project.properties delete mode 100644 Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/res/values/strings.xml delete mode 100644 Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj delete mode 100644 Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj.filters delete mode 100644 Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj delete mode 100644 Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj.filters delete mode 100644 Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj delete mode 100644 Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj.filters delete mode 100644 Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj delete mode 100644 Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj.filters delete mode 100644 Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj delete mode 100644 Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj.filters delete mode 100644 Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj delete mode 100644 Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj.filters delete mode 100644 Release/tests/common/utilities/stdafx.cpp delete mode 100644 Release/tests/common/utilities/stdafx.h delete mode 100644 Release/tests/common/utilities/targetver.h delete mode 100644 Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj delete mode 100644 Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj.filters delete mode 100644 Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj delete mode 100644 Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj.filters delete mode 100644 Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj delete mode 100644 Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj delete mode 100644 Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj.filters delete mode 100644 Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj delete mode 100644 Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj.filters delete mode 100644 Release/tests/functional/http/client/vs14.android/packages.config delete mode 100644 Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj delete mode 100644 Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj.filters delete mode 100644 Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj delete mode 100644 Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj.filters delete mode 100644 Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj delete mode 100644 Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj.filters delete mode 100644 Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj delete mode 100644 Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj.filters delete mode 100644 Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj delete mode 100644 Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj.filters delete mode 100644 Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj delete mode 100644 Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj.filters delete mode 100644 Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj delete mode 100644 Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj.filters delete mode 100644 Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj delete mode 100644 Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj.filters delete mode 100644 Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj delete mode 100644 Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj.filters delete mode 100644 Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj delete mode 100644 Release/tests/functional/json/vs14/JSON140_test.vcxproj delete mode 100644 Release/tests/functional/json/vs14/JSON140_test.vcxproj.filters delete mode 100644 Release/tests/functional/misc/version/vs14/version140_test.vcxproj delete mode 100644 Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj delete mode 100644 Release/tests/functional/pplx/pplx_test/vs14.uwp/pplx140_test.uwp.vcxproj delete mode 100644 Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj delete mode 100644 Release/tests/functional/pplx/pplx_test/vs14/pplx140_test.vcxproj delete mode 100644 Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj delete mode 100644 Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj.filters delete mode 100644 Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj delete mode 100644 Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj.filters delete mode 100644 Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj delete mode 100644 Release/tests/functional/streams/vs14/streams140_test.vcxproj delete mode 100644 Release/tests/functional/streams/vs14/streams140_test.vcxproj.filters delete mode 100644 Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj delete mode 100644 Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj.filters delete mode 100644 Release/tests/functional/uri/vs14.uwp/URI140_test.uwp.vcxproj.filters delete mode 100644 Release/tests/functional/uri/vs14.uwp/Uri140_test.uwp.vcxproj delete mode 100644 Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj delete mode 100644 Release/tests/functional/uri/vs14/Uri140_test.vcxproj delete mode 100644 Release/tests/functional/uri/vs14/Uri140_test.vcxproj.filters delete mode 100644 Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj delete mode 100644 Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj.filters delete mode 100644 Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj delete mode 100644 Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj.filters delete mode 100644 Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj delete mode 100644 Release/tests/functional/utils/vs14/Utils140_test.vcxproj delete mode 100644 Release/tests/functional/utils/vs14/Utils140_test.vcxproj.filters delete mode 100644 Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj delete mode 100644 Release/tests/functional/websockets/client/vs14.uwp/websocketsclient140_test.uwp.vcxproj delete mode 100644 Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj delete mode 100644 Release/tests/functional/websockets/client/vs14/websocketsclient140_test.vcxproj delete mode 100644 Release/tests/functional/websockets/utilities/vs14.android/packages.config delete mode 100644 Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj delete mode 100644 Release/tests/functional/websockets/utilities/vs14.uwp/packages.config delete mode 100644 Release/tests/functional/websockets/utilities/vs14.uwp/websockets_test_utilities140.uwp.vcxproj delete mode 100644 Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj delete mode 100644 Release/tests/functional/websockets/utilities/vs14/packages.config delete mode 100644 Release/tests/functional/websockets/utilities/vs14/websockets_test_utilities140.vcxproj delete mode 100644 build.root delete mode 100644 cpprestsdk140.sln delete mode 100644 cpprestsdk141.sln diff --git a/Build/Common.Build.Traversal.targets b/Build/Common.Build.Traversal.targets deleted file mode 100644 index db26ed7ada..0000000000 --- a/Build/Common.Build.Traversal.targets +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - true - - - - - - - - - - - - - - - - diff --git a/Build/Common.Build.settings b/Build/Common.Build.settings deleted file mode 100644 index 16ba09aa54..0000000000 --- a/Build/Common.Build.settings +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - - Debug - Win32 - - - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root)) - $(BuildRoot)\Build - $(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion@CurrentVersion) - - 140 - 120 - 110 - - $(WindowsSdkDir) - true - true - false - - - - - - $(BuildRoot)\Binaries\$(Platform)\$(Configuration)\ - $(OutputPath) - $(BuildRoot)\Intermediate\$(MSBuildProjectName)\$(Platform)\$(Configuration)\ - $(BuildRoot)\Release\Tests - $(BuildRoot)\Release\src - $(BuildRoot)\Release\Resource - $(BuildRoot)\Release\include - $(BuildRoot)\Release\libs\websocketpp - $(BuildRoot)\packages - $(BuildRoot)\..\Tools\packages - - - - - $(OutDir)\ - - - - $(VS110COMNTOOLS)..\IDE - - - - $(VS120COMNTOOLS)..\IDE - - - - $(TargetsPath)\BinaryDependencies - prompt - 4 - - - false - - - false - $(RunCodeAnalysis) - true - - true - - - true - false - false - true - - - - - Level4 - Use - true - $(EnableCPPAnalysis) - true - /d2notypeopt %(AdditionalOptions) - - - /DTARGET_NAME="$(TARGETNAME)" %(AdditionalOptions) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - true - - - - - - _WIN64;_DEBUG;%(PreprocessorDefinitions) - - - true - - - - - - _DEBUG;%(PreprocessorDefinitions) - - - true - - - - - - _WIN64;NDEBUG;%(PreprocessorDefinitions) - - - true - - - - - - NDEBUG;%(PreprocessorDefinitions) - - - true - - - - - - NDEBUG;%(PreprocessorDefinitions) - - - true - - - - - true - full - false - DEBUG;TRACE - x86 - - - - true - full - false - DEBUG;TRACE;X64 - - - - pdbonly - true - TRACE - x86 - - - - pdbonly - true - TRACE;X64 - - - - true - full - false - DEBUG;TRACE;ARM - - - - pdbonly - true - TRACE;ARM - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ResolvedProjectReferencePaths> - Undefined - - - - - - - - <_ResolvedProjectReferencePaths Condition="'%(CopyToOutputDirectory)' != 'Undefined'" - Remove="@(_ResolvedProjectReferencePaths)" /> - - - - - - - diff --git a/Build/Config.Definitions.props b/Build/Config.Definitions.props deleted file mode 100644 index 9eaabbb298..0000000000 --- a/Build/Config.Definitions.props +++ /dev/null @@ -1,29 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - \ No newline at end of file diff --git a/Build/Release.Product.settings b/Build/Release.Product.settings deleted file mode 100644 index 30d0bc9a4f..0000000000 --- a/Build/Release.Product.settings +++ /dev/null @@ -1,64 +0,0 @@ - - - - - true - false - - - - false - true - - - - Unicode - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - - false - - $(RunCodeAnalysis) - - - - - - $(CasablancaIncludeDir) - - - - - false - - - Windows - false - true - /SAFESEH%(AdditionalOptions) - - - - - - Disabled - - - - - - NDEBUG;%(PreprocessorDefinitions) - MaxSpeed - true - true - - - - diff --git a/Build/Release.Tests.settings b/Build/Release.Tests.settings deleted file mode 100644 index 2bbff91192..0000000000 --- a/Build/Release.Tests.settings +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - - false - - - - - - - $(TestRoot)\Common\utilities\include;$(TestRoot)\Common\UnitTestpp - $(BinariesDirectory)\inc;$(CasablancaIncludeDir) - - - - - - - - diff --git a/Build/version.props b/Build/version.props deleted file mode 100644 index 2b67f6647e..0000000000 --- a/Build/version.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - cpprest - 2 - 10 - 6 - $(CppRestSDKVersionMajor)_$(CppRestSDKVersionMinor) - $(CppRestSDKVersionMajor).$(CppRestSDKVersionMinor) - - diff --git a/NuGet.Config b/NuGet.Config deleted file mode 100644 index abc5b1378c..0000000000 --- a/NuGet.Config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj deleted file mode 100644 index 56afcd81b3..0000000000 --- a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath14) - - - - Application - true - NotSet - v140_xp - - - Application - true - NotSet - v140_xp - - - Application - false - true - NotSet - v140_xp - - - Application - false - true - NotSet - v140_xp - - - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - CPPREST_TARGET_XP;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - - - - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9} - - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters b/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters deleted file mode 100644 index cee450afc2..0000000000 --- a/Release/samples/BingRequest/BingRequest140.xp/BingRequest140.xp.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {786631e0-badc-4b3f-bd98-9b13e6a8e5f8} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj b/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj deleted file mode 100644 index bf9a63acc9..0000000000 --- a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj +++ /dev/null @@ -1,141 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - - - $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root)) - $(BuildRoot)\Binaries\$(Platform)\$(Configuration)\ - $(OutputPath) - $(BuildRoot)\Release\src - $(BuildRoot)\Release\include - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj.filters b/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj.filters deleted file mode 100644 index b78f1994bb..0000000000 --- a/Release/samples/BingRequest/BingRequest140/BingRequest140.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {bc214923-f806-44a3-abd4-08a1aa1a9b3b} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj deleted file mode 100644 index b5af27cbca..0000000000 --- a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - 10.0.16299.0 - - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - \ No newline at end of file diff --git a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj.filters b/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj.filters deleted file mode 100644 index bb6411f159..0000000000 --- a/Release/samples/BingRequest/BingRequest141/BingRequest141.vcxproj.filters +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp index 1ca303fbdc..9a17d8983d 100644 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp +++ b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp @@ -9,7 +9,36 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" +#ifdef _WIN32 +#include + +#include +#include + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#define NOMINMAX +#include +#include +#include + +// ws2tcpip.h - isn't warning clean. +#pragma warning(push) +#pragma warning(disable : 6386) +#include +#pragma warning(pop) + +#include +#endif + +#include +#include +#include +#include + +#include "cpprest/http_client.h" + #include #include #include diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj deleted file mode 100644 index 6a247f1616..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {830b6e2f-9224-41d1-b9c7-a51fc78b00c7} - Win32Proj - BlackJack_Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj.filters deleted file mode 100644 index 127018be70..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client140/BlackJack_Client140.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj deleted file mode 100644 index 8770125299..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj +++ /dev/null @@ -1,149 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {830b6e2f-9224-41d1-b9c7-a51fc78b00c7} - Win32Proj - BlackJack_Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - 10.0.16299.0 - - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);..\..\BlackJack_Server;$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj.filters deleted file mode 100644 index d19e3a56d0..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJack_Client141/BlackJack_Client141.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - h;hpp;hxx;hm;inl;inc;xsd - - - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Client/CMakeLists.txt b/Release/samples/BlackJack/BlackJack_Client/CMakeLists.txt index f884ca8f8d..e5845aa827 100644 --- a/Release/samples/BlackJack/BlackJack_Client/CMakeLists.txt +++ b/Release/samples/BlackJack/BlackJack_Client/CMakeLists.txt @@ -4,7 +4,6 @@ endif() add_executable(blackjackclient BlackJackClient.cpp - stdafx.cpp ) target_link_libraries(blackjackclient cpprest) diff --git a/Release/samples/BlackJack/BlackJack_Client/stdafx.cpp b/Release/samples/BlackJack/BlackJack_Client/stdafx.cpp deleted file mode 100644 index cd389fa0d6..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/stdafx.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.cpp : source file that includes just the standard includes -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#include "stdafx.h" - -// reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/Release/samples/BlackJack/BlackJack_Client/stdafx.h b/Release/samples/BlackJack/BlackJack_Client/stdafx.h deleted file mode 100644 index 82b776702a..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/stdafx.h +++ /dev/null @@ -1,44 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.h : include file for standard system include files, -* or project specific include files that are used frequently, but -* are changed infrequently -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#pragma once - -#ifdef _WIN32 -#include "targetver.h" - -#include -#include - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#define NOMINMAX -#include -#include -#include - -// ws2tcpip.h - isn't warning clean. -#pragma warning(push) -#pragma warning(disable : 6386) -#include -#pragma warning(pop) - -#include -#endif - -#include -#include -#include -#include - -#include "cpprest/http_client.h" diff --git a/Release/samples/BlackJack/BlackJack_Client/targetver.h b/Release/samples/BlackJack/BlackJack_Client/targetver.h deleted file mode 100644 index 951583c45d..0000000000 --- a/Release/samples/BlackJack/BlackJack_Client/targetver.h +++ /dev/null @@ -1,18 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* targetver.h -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj deleted file mode 100644 index de642bde3c..0000000000 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj +++ /dev/null @@ -1,154 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {84350cd1-d406-4a4f-9571-261ca46d77c5} - Win32Proj - BlackJack_Server - SAK - SAK - SAK - $(VCTargetsPath12) - SAK - - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj.filters deleted file mode 100644 index 2de41685ef..0000000000 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server140/BlackJack_Server140.vcxproj.filters +++ /dev/null @@ -1,45 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj deleted file mode 100644 index ff8468da47..0000000000 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj +++ /dev/null @@ -1,155 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {84350cd1-d406-4a4f-9571-261ca46d77c5} - Win32Proj - BlackJack_Server - SAK - SAK - SAK - $(VCTargetsPath12) - SAK - 10.0.16299.0 - - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj.filters b/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj.filters deleted file mode 100644 index a13f88916c..0000000000 --- a/Release/samples/BlackJack/BlackJack_Server/BlackJack_Server141/BlackJack_Server141.vcxproj.filters +++ /dev/null @@ -1,42 +0,0 @@ - - - - - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - h;hpp;hxx;hm;inl;inc;xsd - - - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt b/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt index c5b2fec0af..8073412fc1 100644 --- a/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt +++ b/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt @@ -5,8 +5,18 @@ endif() add_executable(blackjackserver BlackJack_Server.cpp Dealer.cpp - stdafx.cpp Table.cpp ) target_link_libraries(blackjackserver cpprest) + +if(MSVC) + get_target_property(_srcs blackjackserver SOURCES) + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/blackjack-server-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/blackjack-server-stdafx.pch") + endif() + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpblackjack-server-stdafx.pch") + target_sources(blackjackserver PRIVATE stdafx.cpp) + target_compile_options(blackjackserver PRIVATE /Yustdafx.h /Fpblackjack-server-stdafx.pch) +endif() diff --git a/Release/samples/Oauth1Client/CMakeLists.txt b/Release/samples/Oauth1Client/CMakeLists.txt index 4630cba8fe..e77d3fdeaa 100644 --- a/Release/samples/Oauth1Client/CMakeLists.txt +++ b/Release/samples/Oauth1Client/CMakeLists.txt @@ -1,8 +1,7 @@ if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) add_executable(oauth1client Oauth1Client.cpp - stdafx.cpp ) - + target_link_libraries(oauth1client cpprest) -endif() \ No newline at end of file +endif() diff --git a/Release/samples/Oauth1Client/Oauth1Client.cpp b/Release/samples/Oauth1Client/Oauth1Client.cpp index d360d37d54..8c27ef2f4e 100644 --- a/Release/samples/Oauth1Client/Oauth1Client.cpp +++ b/Release/samples/Oauth1Client/Oauth1Client.cpp @@ -26,7 +26,8 @@ Set following entry in the hosts file: 127.0.0.1 testhost.local */ -#include "stdafx.h" +#include +#include "cpprest/http_client.h" #if defined(_WIN32) && !defined(__cplusplus_winrt) // Extra includes for Windows desktop. @@ -301,4 +302,3 @@ int main(int argc, char *argv[]) ucout << "Done." << std::endl; return 0; } - diff --git a/Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj b/Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj deleted file mode 100644 index 2d9d51c16d..0000000000 --- a/Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj +++ /dev/null @@ -1,205 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {850CCB95-CFA8-4E41-9D1D-387C0C186740} - Win32Proj - Oauth1Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj.filters b/Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj.filters deleted file mode 100644 index 48d2ebae5f..0000000000 --- a/Release/samples/Oauth1Client/Oauth1Client140/Oauth1Client140.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj deleted file mode 100644 index 6ff9eeb18a..0000000000 --- a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj +++ /dev/null @@ -1,206 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {850CCB95-CFA8-4E41-9D1D-387C0C186740} - Win32Proj - Oauth1Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - 10.0.16299.0 - - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj.filters b/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj.filters deleted file mode 100644 index 48d2ebae5f..0000000000 --- a/Release/samples/Oauth1Client/Oauth1Client141/Oauth1Client141.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/Oauth1Client/stdafx.cpp b/Release/samples/Oauth1Client/stdafx.cpp deleted file mode 100644 index cd389fa0d6..0000000000 --- a/Release/samples/Oauth1Client/stdafx.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.cpp : source file that includes just the standard includes -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#include "stdafx.h" - -// reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/Release/samples/Oauth1Client/stdafx.h b/Release/samples/Oauth1Client/stdafx.h deleted file mode 100644 index 88797e88c3..0000000000 --- a/Release/samples/Oauth1Client/stdafx.h +++ /dev/null @@ -1,17 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.h : include file for standard system include files, -* or project specific include files that are used frequently, but -* are changed infrequently -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#pragma once - -#include -#include "cpprest/http_client.h" diff --git a/Release/samples/Oauth2Client/CMakeLists.txt b/Release/samples/Oauth2Client/CMakeLists.txt index 8c3bdbc118..4da12bb474 100644 --- a/Release/samples/Oauth2Client/CMakeLists.txt +++ b/Release/samples/Oauth2Client/CMakeLists.txt @@ -1,8 +1,7 @@ if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) add_executable(oauth2client Oauth2Client.cpp - stdafx.cpp ) target_link_libraries(oauth2client cpprest) -endif() \ No newline at end of file +endif() diff --git a/Release/samples/Oauth2Client/Oauth2Client.cpp b/Release/samples/Oauth2Client/Oauth2Client.cpp index 59a963eaff..8d62b89cda 100644 --- a/Release/samples/Oauth2Client/Oauth2Client.cpp +++ b/Release/samples/Oauth2Client/Oauth2Client.cpp @@ -26,7 +26,8 @@ Set following entry in the hosts file: 127.0.0.1 testhost.local */ -#include "stdafx.h" +#include +#include "cpprest/http_client.h" #if defined(_WIN32) && !defined(__cplusplus_winrt) // Extra includes for Windows desktop. @@ -321,4 +322,3 @@ int main(int argc, char *argv[]) ucout << "Done." << std::endl; return 0; } - diff --git a/Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj b/Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj deleted file mode 100644 index 5b69ac56a5..0000000000 --- a/Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj +++ /dev/null @@ -1,205 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654} - Win32Proj - Oauth2Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj.filters b/Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj.filters deleted file mode 100644 index d11e5aec8b..0000000000 --- a/Release/samples/Oauth2Client/Oauth2Client140/Oauth2Client140.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj deleted file mode 100644 index 1ff3cc807d..0000000000 --- a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj +++ /dev/null @@ -1,206 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654} - Win32Proj - Oauth2Client - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - 10.0.16299.0 - - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - -Zm140 %(AdditionalOptions) - - - Console - true - true - true - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - \ No newline at end of file diff --git a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj.filters b/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj.filters deleted file mode 100644 index d11e5aec8b..0000000000 --- a/Release/samples/Oauth2Client/Oauth2Client141/Oauth2Client141.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/Oauth2Client/stdafx.cpp b/Release/samples/Oauth2Client/stdafx.cpp deleted file mode 100644 index cd389fa0d6..0000000000 --- a/Release/samples/Oauth2Client/stdafx.cpp +++ /dev/null @@ -1,15 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.cpp : source file that includes just the standard includes -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#include "stdafx.h" - -// reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/Release/samples/Oauth2Client/stdafx.h b/Release/samples/Oauth2Client/stdafx.h deleted file mode 100644 index 88797e88c3..0000000000 --- a/Release/samples/Oauth2Client/stdafx.h +++ /dev/null @@ -1,17 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.h : include file for standard system include files, -* or project specific include files that are used frequently, but -* are changed infrequently -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#pragma once - -#include -#include "cpprest/http_client.h" diff --git a/Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj b/Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj deleted file mode 100644 index c749d29e9c..0000000000 --- a/Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj +++ /dev/null @@ -1,146 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {F03BEE03-BEFB-4B17-A774-D9C8246530D4} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - \ No newline at end of file diff --git a/Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj.filters b/Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj.filters deleted file mode 100644 index 2794140178..0000000000 --- a/Release/samples/SearchFile/SearchFile140/SearchFile140.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {bc214923-f806-44a3-abd4-08a1aa1a9b3b} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj deleted file mode 100644 index 4c1d729dcd..0000000000 --- a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj +++ /dev/null @@ -1,147 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {F03BEE03-BEFB-4B17-A774-D9C8246530D4} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - 10.0.16299.0 - - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj %(AdditionalOptions) - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - \ No newline at end of file diff --git a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj.filters b/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj.filters deleted file mode 100644 index 2794140178..0000000000 --- a/Release/samples/SearchFile/SearchFile141/SearchFile141.vcxproj.filters +++ /dev/null @@ -1,13 +0,0 @@ - - - - - {bc214923-f806-44a3-abd4-08a1aa1a9b3b} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index bb3065e607..eceaad7437 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -180,7 +180,7 @@ if(MSVC) set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h") target_sources(cpprest PRIVATE pch/stdafx.cpp) - target_compile_options(cpprest PRIVATE /Yustdafx.h /Zm200) + target_compile_options(cpprest PRIVATE /Yustdafx.h) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") diff --git a/Release/src/build/android.vcxitems b/Release/src/build/android.vcxitems deleted file mode 100644 index eaf19e2057..0000000000 --- a/Release/src/build/android.vcxitems +++ /dev/null @@ -1,31 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 248F659F-DAC5-46E8-AC09-60EC9FC95053 - true - 6a3ec03a-67b9-4430-9eb3-a56acc7d127e - {65951c40-a332-4b54-89c2-7cdaf30d5f66} - android - - - - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/android.vcxitems.filters b/Release/src/build/android.vcxitems.filters deleted file mode 100644 index 819746782d..0000000000 --- a/Release/src/build/android.vcxitems.filters +++ /dev/null @@ -1,39 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {8660c551-ea8d-4dda-86b8-4a74cfa9a271} - - - {5489914b-c16a-429b-b787-2d4621924a1c} - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/src/build/common.vcxitems b/Release/src/build/common.vcxitems deleted file mode 100644 index 520e0dbac3..0000000000 --- a/Release/src/build/common.vcxitems +++ /dev/null @@ -1,93 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 248F659F-DAC5-46E8-AC09-60EC9FC95053 - true - b19fa703-0bf0-4e1f-8927-b0eaeb6aa823 - {594dcb5f-07e3-4084-a2ce-268611fa629f} - common - common - - - - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - - - - - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/common.vcxitems.filters b/Release/src/build/common.vcxitems.filters deleted file mode 100644 index 5445979e22..0000000000 --- a/Release/src/build/common.vcxitems.filters +++ /dev/null @@ -1,227 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {3bdf9ddb-6199-4b83-84cd-e8617e78294e} - - - {42f86193-fcdc-443d-8ede-8fd31abe6643} - - - {ed89d519-15d6-47d9-90cb-e6c25bcaa323} - - - {e5ecd256-178a-403a-9249-5d15463ad051} - - - {d32b3879-7333-4ab4-8ef2-dd72aed7b5dc} - - - {1c12997c-5bf5-4b60-853e-a5f9c8303760} - - - {97da7aee-41c8-4948-bb0e-c31cec1bfb16} - - - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\pch - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\pplx - - - Header Files\cpprest\details - - - Header Files\cpprest\details - - - Header Files\cpprest - - - Header Files\cpprest\details - - - Header Files\private - - - Header Files\private - - - Header Files\private - - - Header Files\private - - - - - Header Files\cpprest\details - - - \ No newline at end of file diff --git a/Release/src/build/cpprest.natvis b/Release/src/build/cpprest.natvis deleted file mode 100644 index 621c147881..0000000000 --- a/Release/src/build/cpprest.natvis +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - m_scheme - m_host - m_port - m_user_info - m_path - m_query - m_fragment - - - - - {m_uri} - - m_components - - - - - - m_uri - - - - - {m_username} - - m_username - - - - - {"default"} - {"disabled"} - {"auto discovery"} - {m_address} - - "default" - "disabled" - "auto discovery" - m_address - m_credentials - - - - - - m_proxy - m_credentials - m_timeout._MyRep - m_guarantee_order - m_chunksize - - - - - {_base_uri} - - - - {m_uri} - - - - [{_m_impl._Ptr->m_method}] - - _m_impl._Ptr->m_method - _m_impl._Ptr->m_uri - ((*((web::http::details::http_msg_base*)(&(*((web::http::details::_http_request*)((_m_impl)._Ptr)))))).m_headers).m_headers - - - - - [{_m_impl._Ptr->m_status_code}, {_m_impl._Ptr->m_reason_phrase}] - - _m_impl._Ptr->m_status_code - _m_impl._Ptr->m_reason_phrase - ((*((web::http::details::http_msg_base*)(&(*((web::http::details::_http_request*)((_m_impl)._Ptr)))))).m_headers).m_headers - - - - - - m_proxy - m_credentials - m_headers - - - - - {m_client._Ptr->m_callback_client._Ptr->m_uri} - - m_client._Ptr->m_callback_client._Ptr->m_uri - m_client._Ptr->m_callback_client._Ptr->m_config - - - - - {m_client._Ptr->m_uri} - - m_client._Ptr->m_uri - m_client._Ptr->m_config - - - - - - text" - "binary" - "close" - "ping" - "pong" - m_length - m_body - - - - - - "text" - "binary" - "close" - "ping" - "pong" - m_body - - - - - - {m_intval} - - - - {m_uintval} - - - - {m_value} - - - - - {{size = {m_elements._Mylast - m_elements._Myfirst}}} - - - m_elements._Mylast - m_elements._Myfirst - m_elements._Myfirst - - - - - - {{size = {m_elements._Mylast - m_elements._Myfirst}}} - - - m_elements._Mylast - m_elements._Myfirst - m_elements._Myfirst - - - - - - - {(*((web::json::details::_Number*)((m_value)._Myptr))).m_number} - - - - {(*((web::json::details::_Boolean*)(m_value._Myptr))).m_value} - - - - {((((&((*((web::json::details::_String*)(m_value._Myptr))).m_string)))))} - - - null - - not initialized - not initialized - - - object {(*((web::json::details::_Object*)(m_value._Myptr))).m_object} - - - - array {(*((web::json::details::_Array*)(m_value._Myptr))).m_array} - - - - - (*((web::json::details::_Object*)(m_value._Myptr))).m_object.m_elements._Mylast - (*((web::json::details::_Object*)(m_value._Myptr))).m_object.m_elements._Myfirst - (*((web::json::details::_Object*)(m_value._Myptr))).m_object.m_elements._Myfirst - - - - (*((web::json::details::_Array*)(m_value._Myptr))).m_array.m_elements._Mylast - (*((web::json::details::_Array*)(m_value._Myptr))).m_array.m_elements._Myfirst - (*((web::json::details::_Array*)(m_value._Myptr))).m_array.m_elements._Myfirst - - - - - - \ No newline at end of file diff --git a/Release/src/build/init.ps1 b/Release/src/build/init.ps1 deleted file mode 100644 index 595baeaaa9..0000000000 --- a/Release/src/build/init.ps1 +++ /dev/null @@ -1,23 +0,0 @@ -param($installPath, $toolsPath, $package) - -function Copy-Natvis($DestFolder) -{ - if ((Test-Path $DestFolder) -eq $True) - { - # Update casablanca version for each release here. - $DestFile = Join-Path -path $DestFolder -childpath "cpprest2_10.natvis"; - - # Check to see if cpp rest natvis file for this version already exists - # if not, then copy into user profile for Visual Studio to pick up - if ((Test-Path $DestFile) -eq $False) - { - $SrcFile = Join-Path -path $toolsPath -childpath "cpprest.natvis"; - Copy-Item $SrcFile $DestFile; - } - } -} - -$VS2013Folder = Join-Path -path $env:userprofile -childpath "Documents\Visual Studio 2013\Visualizers"; -$VS2015Folder = Join-Path -path $env:userprofile -childpath "Documents\Visual Studio 2015\Visualizers"; -Copy-Natvis $VS2013Folder; -Copy-Natvis $VS2015Folder; \ No newline at end of file diff --git a/Release/src/build/other.vcxitems b/Release/src/build/other.vcxitems deleted file mode 100644 index 2199600b11..0000000000 --- a/Release/src/build/other.vcxitems +++ /dev/null @@ -1,22 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 248F659F-DAC5-46E8-AC09-60EC9FC95053 - true - 388fd5af-5c41-4452-97f0-2841cee780b6 - {3d5908f7-7673-4229-bc46-2007a7af9cae} - other - - - - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/other.vcxitems.filters b/Release/src/build/other.vcxitems.filters deleted file mode 100644 index caa96f0b2a..0000000000 --- a/Release/src/build/other.vcxitems.filters +++ /dev/null @@ -1,16 +0,0 @@ - - - - - {627bd7c9-4277-424f-b76c-849f88aa536a} - - - {efbed7e8-e66d-48e1-97f5-d687726e1748} - - - - - Source Files - - - \ No newline at end of file diff --git a/Release/src/build/vs14.android/casablanca140.android.vcxproj b/Release/src/build/vs14.android/casablanca140.android.vcxproj deleted file mode 100644 index 038f56b125..0000000000 --- a/Release/src/build/vs14.android/casablanca140.android.vcxproj +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - {AFB49019-965B-4C10-BAFF-C86C16D58010} - Android - Android - 2.0 - cpprestsdk140.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - - true - - - true - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - $(CppRestBaseFileName)140$(DebugFileSuffix)_android_$(CppRestSDKVersionFileSuffix) - - - true - - - true - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/src/build/vs14.android/packages.config b/Release/src/build/vs14.android/packages.config deleted file mode 100644 index 746b7f61a2..0000000000 --- a/Release/src/build/vs14.android/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14.static/casablanca140.static.vcxproj b/Release/src/build/vs14.static/casablanca140.static.vcxproj deleted file mode 100644 index cda12db6a7..0000000000 --- a/Release/src/build/vs14.static/casablanca140.static.vcxproj +++ /dev/null @@ -1,84 +0,0 @@ - - - - - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A} - Win32Proj - SAK - SAK - SAK - SAK - StaticLibrary - v140 - false - false - cpprestsdk140.static - 8.1 - - - - - - - - - - - - - - - - - - - d - - - lib$(CppRestBaseFileName)140$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) - - - - Designer - - - - - _NO_ASYNCRTIMP;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm300 /bigobj %(AdditionalOptions) - MultiThreadedDebugDLL - MultiThreadedDLL - true - - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - false - false - false - false - false - false - - - Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14.static/packages.config b/Release/src/build/vs14.static/packages.config deleted file mode 100644 index 21a51fdf83..0000000000 --- a/Release/src/build/vs14.static/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj b/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj deleted file mode 100644 index 2918824b65..0000000000 --- a/Release/src/build/vs14.uwp/cpprestsdk140.uwp.staticlib.vcxproj +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {47A5CFDC-C244-45A6-9830-38CB303CB495} - StaticLibrary - en-US - 14.0 - true - Windows Store - 8.2 - cpprestsdk140.uwp.staticlib - v140 - StaticLibrary - $(OutDir)\$(MsBuildProjectName) - 10.0.10240.0 - 10.0.10240.0 - - - - - - - - - - - - - - - - d - - - lib$(CppRestBaseFileName)140$(DebugFileSuffix)_uwp_$(CppRestSDKVersionFileSuffix) - - - - - false - false - - - - _NO_ASYNCRTIMP;_NO_PPLXIMP;_USRDLL;%(PreprocessorDefinitions); - Use - true - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm250 /bigobj %(AdditionalOptions) - true - - - Console - false - UseLinkTimeCodeGeneration - false - - - - - - copy /Y $(OutDir)\* $(OutDir)..\ - exit 0 - Copying $(TargetName).winrt binaries to OutDir and removing appcontainer flag - - - MachineX86 - - - MachineX86 - - - MachineX64 - - - MachineX64 - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14.uwp/cpprestsdk140.uwp.vcxproj b/Release/src/build/vs14.uwp/cpprestsdk140.uwp.vcxproj deleted file mode 100644 index 88a336088c..0000000000 --- a/Release/src/build/vs14.uwp/cpprestsdk140.uwp.vcxproj +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - DynamicLibrary - en-US - 14.0 - true - Windows Store - 10.0.10240.0 - 10.0.10240.0 - 10.0 - cpprestsdk140.uwp - v140 - DynamicLibrary - $(OutDir)\$(MsBuildProjectName) - - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)140$(DebugFileSuffix)_uwp_$(CppRestSDKVersionFileSuffix) - - - - - false - false - - - - _ASYNCRT_EXPORT;_PPLX_EXPORT;_USRDLL;%(PreprocessorDefinitions); - Use - true - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm250 /bigobj %(AdditionalOptions) - true - - - Console - false - UseLinkTimeCodeGeneration - false - - - - - - copy /Y "$(OutDir)\*" "$(OutDir)..\" - link /edit /appcontainer:no "$(OutDir)..\$(TargetName).dll" - exit 0 - Copying $(TargetName).winrt binaries to OutDir and removing appcontainer flag - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14.xp/casablanca140.xp.vcxproj b/Release/src/build/vs14.xp/casablanca140.xp.vcxproj deleted file mode 100644 index 7f3e81937a..0000000000 --- a/Release/src/build/vs14.xp/casablanca140.xp.vcxproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9} - Win32Proj - SAK - SAK - SAK - SAK - DynamicLibrary - v140_xp - false - true - cpprestsdk140.xp - 8.1 - - - - - - - - true - true - true - true - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)140$(DebugFileSuffix)_xp_$(CppRestSDKVersionFileSuffix) - - - - Designer - - - - - CPPREST_TARGET_XP;_ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm300 /bigobj %(AdditionalOptions) - MultiThreadedDebugDLL - MultiThreadedDLL - true - - - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - - - Winhttp.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14.xp/packages.config b/Release/src/build/vs14.xp/packages.config deleted file mode 100644 index 21a51fdf83..0000000000 --- a/Release/src/build/vs14.xp/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14/casablanca140.vcxproj b/Release/src/build/vs14/casablanca140.vcxproj deleted file mode 100644 index cca6328ef9..0000000000 --- a/Release/src/build/vs14/casablanca140.vcxproj +++ /dev/null @@ -1,78 +0,0 @@ - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - Win32Proj - SAK - SAK - SAK - SAK - DynamicLibrary - v140 - false - false - cpprestsdk140 - - - - - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)140$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) - - - - Designer - - - - - _ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm300 /bigobj %(AdditionalOptions) - MultiThreadedDebugDLL - MultiThreadedDLL - true - - - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - - - Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs14/packages.config b/Release/src/build/vs14/packages.config deleted file mode 100644 index 21a51fdf83..0000000000 --- a/Release/src/build/vs14/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs141.android/cpprest141.android.vcxproj b/Release/src/build/vs141.android/cpprest141.android.vcxproj deleted file mode 100644 index 99a265fa01..0000000000 --- a/Release/src/build/vs141.android/cpprest141.android.vcxproj +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - {AFB49019-965B-4C10-BAFF-C86C16D58010} - Android - Android - 3.0 - cpprest141.android - 15.0 - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - android-24 - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - - true - - - true - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(CasablancaSrcDir)\android;$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - $(CppRestBaseFileName)141$(DebugFileSuffix)_android_$(CppRestSDKVersionFileSuffix) - - - true - - - true - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs141.android/packages.config b/Release/src/build/vs141.android/packages.config deleted file mode 100644 index 746b7f61a2..0000000000 --- a/Release/src/build/vs141.android/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj b/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj deleted file mode 100644 index f0ee5aae9d..0000000000 --- a/Release/src/build/vs141.uwp/cpprest141.uwp.vcxproj +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - DynamicLibrary - en-US - 14.0 - true - Windows Store - 10.0.16299.0 - 10.0.16299.0 - 10.0 - cpprest141.uwp - v141 - DynamicLibrary - $(OutDir)\$(MsBuildProjectName) - - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)141$(DebugFileSuffix)_uwp_$(CppRestSDKVersionFileSuffix) - - - - - false - false - - - - _ASYNCRT_EXPORT;_PPLX_EXPORT;_USRDLL;%(PreprocessorDefinitions); - Use - true - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm250 /bigobj %(AdditionalOptions) - true - - - Console - false - UseLinkTimeCodeGeneration - false - - - - - - \ No newline at end of file diff --git a/Release/src/build/vs141/cpprest141.vcxproj b/Release/src/build/vs141/cpprest141.vcxproj deleted file mode 100644 index 794a5155ba..0000000000 --- a/Release/src/build/vs141/cpprest141.vcxproj +++ /dev/null @@ -1,85 +0,0 @@ - - - - - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} - Win32Proj - SAK - SAK - SAK - SAK - DynamicLibrary - v141 - false - false - cpprest141 - 10.0.16299.0 - - - true - true - true - true - - - - - - - - - - - - - - - - - - - d - - - $(CppRestBaseFileName)141$(DebugFileSuffix)_$(CppRestSDKVersionFileSuffix) - - - - Designer - - - - - _ASYNCRT_EXPORT;_PPLX_EXPORT;WIN32;_MBCS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Use - stdafx.h - -Zm300 /bigobj %(AdditionalOptions) - MultiThreadedDebugDLL - MultiThreadedDLL - true - - - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - 4503;4592;%(DisableSpecificWarnings) - - - Winhttp.lib;httpapi.lib;bcrypt.lib;crypt32.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/Release/src/build/vs141/packages.config b/Release/src/build/vs141/packages.config deleted file mode 100644 index 21a51fdf83..0000000000 --- a/Release/src/build/vs141/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/win32.vcxitems b/Release/src/build/win32.vcxitems deleted file mode 100644 index 216b00fca5..0000000000 --- a/Release/src/build/win32.vcxitems +++ /dev/null @@ -1,33 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 248F659F-DAC5-46E8-AC09-60EC9FC95053 - true - c9564eb9-0f37-49cc-a2d6-b1a42b8bfb10 - {f40f4804-50f9-4257-8d74-b9cbb19ac4c3} - win32 - - - - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/win32.vcxitems.filters b/Release/src/build/win32.vcxitems.filters deleted file mode 100644 index 0a8e8e865a..0000000000 --- a/Release/src/build/win32.vcxitems.filters +++ /dev/null @@ -1,39 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {48e3e0ed-8995-4e0b-b58c-a9c38bac54de} - - - {95470a15-70ac-4e0f-ae3b-e5721e93400c} - - - - - Header Files - - - Header Files - - - - - - \ No newline at end of file diff --git a/Release/src/build/winrt.vcxitems b/Release/src/build/winrt.vcxitems deleted file mode 100644 index c07ce03c97..0000000000 --- a/Release/src/build/winrt.vcxitems +++ /dev/null @@ -1,31 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 248F659F-DAC5-46E8-AC09-60EC9FC95053 - true - 6b93d548-6644-4909-8c97-3e19aac98514 - {0a9ba181-7876-4b3d-a5e0-ee673fa51c05} - winrt - - - - %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/src/build/winrt.vcxitems.filters b/Release/src/build/winrt.vcxitems.filters deleted file mode 100644 index 746985781b..0000000000 --- a/Release/src/build/winrt.vcxitems.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - {1a4ff9ed-f148-42a8-8119-185e2c58800e} - - - {5e8ffeb7-9f5b-45ae-baa1-45d4634d7dc4} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - - - - \ No newline at end of file diff --git a/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.pbxproj b/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.pbxproj deleted file mode 100644 index 4fa4952084..0000000000 --- a/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,368 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - D5E513901A1BEA1D0060F252 /* ios_runnerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D5E5138F1A1BEA1D0060F252 /* ios_runnerTests.mm */; }; - D5E5139A1A1BFDD80060F252 /* libunittestpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513991A1BFDD80060F252 /* libunittestpp.a */; }; - D5E5139C1A1BFECD0060F252 /* libcpprest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E5139B1A1BFECD0060F252 /* libcpprest.a */; }; - D5E513A61A1BFEE20060F252 /* libcommon_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E5139D1A1BFEE20060F252 /* libcommon_utilities.a */; }; - D5E513A71A1BFEE20060F252 /* libhttpclient_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E5139E1A1BFEE20060F252 /* libhttpclient_test.a */; }; - D5E513A81A1BFEE20060F252 /* libhttplistener_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E5139F1A1BFEE20060F252 /* libhttplistener_test.a */; }; - D5E513A91A1BFEE20060F252 /* libhttptest_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513A01A1BFEE20060F252 /* libhttptest_utilities.a */; }; - D5E513AA1A1BFEE20060F252 /* libjson_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513A11A1BFEE20060F252 /* libjson_test.a */; }; - D5E513AB1A1BFEE20060F252 /* libpplx_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513A21A1BFEE20060F252 /* libpplx_test.a */; }; - D5E513AC1A1BFEE20060F252 /* libstreams_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513A31A1BFEE20060F252 /* libstreams_test.a */; }; - D5E513AD1A1BFEE20060F252 /* liburi_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513A41A1BFEE20060F252 /* liburi_test.a */; }; - D5E513AE1A1BFEE20060F252 /* libutils_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513A51A1BFEE20060F252 /* libutils_test.a */; }; - D5E513B01A1C01820060F252 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513AF1A1C01820060F252 /* libiconv.dylib */; }; - D5E513B41A1C02210060F252 /* libcrypto.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513B21A1C02200060F252 /* libcrypto.a */; }; - D5E513B51A1C02210060F252 /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513B31A1C02210060F252 /* libssl.a */; }; - D5E513B71A1C02570060F252 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513B61A1C02570060F252 /* Security.framework */; }; - D5E513B81A1C02CF0060F252 /* boost.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5E513B11A1C01D30060F252 /* boost.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - D52BABA91A1C064100FAE04C /* libwebsocketclient_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libwebsocketclient_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libwebsocketclient_test.a; sourceTree = ""; }; - D52BABAA1A1C064100FAE04C /* libwebsockettest_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libwebsockettest_utilities.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libwebsockettest_utilities.a; sourceTree = ""; }; - D5E513891A1BEA1D0060F252 /* ios_runnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ios_runnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - D5E5138E1A1BEA1D0060F252 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D5E5138F1A1BEA1D0060F252 /* ios_runnerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ios_runnerTests.mm; sourceTree = ""; }; - D5E513991A1BFDD80060F252 /* libunittestpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libunittestpp.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libunittestpp.a; sourceTree = ""; }; - D5E5139B1A1BFECD0060F252 /* libcpprest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcpprest.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libcpprest.a; sourceTree = ""; }; - D5E5139D1A1BFEE20060F252 /* libcommon_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcommon_utilities.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libcommon_utilities.a; sourceTree = ""; }; - D5E5139E1A1BFEE20060F252 /* libhttpclient_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhttpclient_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libhttpclient_test.a; sourceTree = ""; }; - D5E5139F1A1BFEE20060F252 /* libhttplistener_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhttplistener_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libhttplistener_test.a; sourceTree = ""; }; - D5E513A01A1BFEE20060F252 /* libhttptest_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhttptest_utilities.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libhttptest_utilities.a; sourceTree = ""; }; - D5E513A11A1BFEE20060F252 /* libjson_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjson_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libjson_test.a; sourceTree = ""; }; - D5E513A21A1BFEE20060F252 /* libpplx_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpplx_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libpplx_test.a; sourceTree = ""; }; - D5E513A31A1BFEE20060F252 /* libstreams_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libstreams_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libstreams_test.a; sourceTree = ""; }; - D5E513A41A1BFEE20060F252 /* liburi_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liburi_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/liburi_test.a; sourceTree = ""; }; - D5E513A51A1BFEE20060F252 /* libutils_test.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libutils_test.a; path = ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug/libutils_test.a; sourceTree = ""; }; - D5E513AF1A1C01820060F252 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; }; - D5E513B11A1C01D30060F252 /* boost.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = boost.framework; path = ../../../../../Build_iOS/boost.framework; sourceTree = ""; }; - D5E513B21A1C02200060F252 /* libcrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcrypto.a; path = ../../../../../Build_iOS/openssl/lib/libcrypto.a; sourceTree = ""; }; - D5E513B31A1C02210060F252 /* libssl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libssl.a; path = ../../../../../Build_iOS/openssl/lib/libssl.a; sourceTree = ""; }; - D5E513B61A1C02570060F252 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - D5E513861A1BEA1D0060F252 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D5E513B81A1C02CF0060F252 /* boost.framework in Frameworks */, - D5E513B71A1C02570060F252 /* Security.framework in Frameworks */, - D5E513B41A1C02210060F252 /* libcrypto.a in Frameworks */, - D5E513B51A1C02210060F252 /* libssl.a in Frameworks */, - D5E513B01A1C01820060F252 /* libiconv.dylib in Frameworks */, - D5E513A61A1BFEE20060F252 /* libcommon_utilities.a in Frameworks */, - D5E513A71A1BFEE20060F252 /* libhttpclient_test.a in Frameworks */, - D5E513A81A1BFEE20060F252 /* libhttplistener_test.a in Frameworks */, - D5E513A91A1BFEE20060F252 /* libhttptest_utilities.a in Frameworks */, - D5E513AA1A1BFEE20060F252 /* libjson_test.a in Frameworks */, - D5E513AB1A1BFEE20060F252 /* libpplx_test.a in Frameworks */, - D5E513AC1A1BFEE20060F252 /* libstreams_test.a in Frameworks */, - D5E513AD1A1BFEE20060F252 /* liburi_test.a in Frameworks */, - D5E513AE1A1BFEE20060F252 /* libutils_test.a in Frameworks */, - D5E5139C1A1BFECD0060F252 /* libcpprest.a in Frameworks */, - D5E5139A1A1BFDD80060F252 /* libunittestpp.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - D5E513671A1BEA1D0060F252 = { - isa = PBXGroup; - children = ( - D52BABA91A1C064100FAE04C /* libwebsocketclient_test.a */, - D52BABAA1A1C064100FAE04C /* libwebsockettest_utilities.a */, - D5E513B61A1C02570060F252 /* Security.framework */, - D5E513B21A1C02200060F252 /* libcrypto.a */, - D5E513B31A1C02210060F252 /* libssl.a */, - D5E513B11A1C01D30060F252 /* boost.framework */, - D5E513AF1A1C01820060F252 /* libiconv.dylib */, - D5E5139D1A1BFEE20060F252 /* libcommon_utilities.a */, - D5E5139E1A1BFEE20060F252 /* libhttpclient_test.a */, - D5E5139F1A1BFEE20060F252 /* libhttplistener_test.a */, - D5E513A01A1BFEE20060F252 /* libhttptest_utilities.a */, - D5E513A11A1BFEE20060F252 /* libjson_test.a */, - D5E513A21A1BFEE20060F252 /* libpplx_test.a */, - D5E513A31A1BFEE20060F252 /* libstreams_test.a */, - D5E513A41A1BFEE20060F252 /* liburi_test.a */, - D5E513A51A1BFEE20060F252 /* libutils_test.a */, - D5E5139B1A1BFECD0060F252 /* libcpprest.a */, - D5E513991A1BFDD80060F252 /* libunittestpp.a */, - D5E5138C1A1BEA1D0060F252 /* ios_runnerTests */, - D5E513711A1BEA1D0060F252 /* Products */, - ); - sourceTree = ""; - }; - D5E513711A1BEA1D0060F252 /* Products */ = { - isa = PBXGroup; - children = ( - D5E513891A1BEA1D0060F252 /* ios_runnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - D5E5138C1A1BEA1D0060F252 /* ios_runnerTests */ = { - isa = PBXGroup; - children = ( - D5E5138F1A1BEA1D0060F252 /* ios_runnerTests.mm */, - D5E5138D1A1BEA1D0060F252 /* Supporting Files */, - ); - path = ios_runnerTests; - sourceTree = ""; - }; - D5E5138D1A1BEA1D0060F252 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - D5E5138E1A1BEA1D0060F252 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - D5E513881A1BEA1D0060F252 /* ios_runnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = D5E513961A1BEA1D0060F252 /* Build configuration list for PBXNativeTarget "ios_runnerTests" */; - buildPhases = ( - D5E513851A1BEA1D0060F252 /* Sources */, - D5E513861A1BEA1D0060F252 /* Frameworks */, - D5E513871A1BEA1D0060F252 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = ios_runnerTests; - productName = ios_runnerTests; - productReference = D5E513891A1BEA1D0060F252 /* ios_runnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D5E513681A1BEA1D0060F252 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = "Steve Gates"; - TargetAttributes = { - D5E513881A1BEA1D0060F252 = { - CreatedOnToolsVersion = 6.1; - }; - }; - }; - buildConfigurationList = D5E5136B1A1BEA1D0060F252 /* Build configuration list for PBXProject "ios_runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = D5E513671A1BEA1D0060F252; - productRefGroup = D5E513711A1BEA1D0060F252 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D5E513881A1BEA1D0060F252 /* ios_runnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - D5E513871A1BEA1D0060F252 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - D5E513851A1BEA1D0060F252 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D5E513901A1BEA1D0060F252 /* ios_runnerTests.mm in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - D5E513911A1BEA1D0060F252 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - USER_HEADER_SEARCH_PATHS = ../../unittestpp/; - VALID_ARCHS = i386; - }; - name = Debug; - }; - D5E513921A1BEA1D0060F252 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - MTL_ENABLE_DEBUG_INFO = NO; - ONLY_ACTIVE_ARCH = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - USER_HEADER_SEARCH_PATHS = ../../unittestpp/; - VALIDATE_PRODUCT = YES; - VALID_ARCHS = i386; - }; - name = Release; - }; - D5E513971A1BEA1D0060F252 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ../../../../../Build_iOS, - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = ios_runnerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - ../../../../../Build_iOS/build.debug/build.i386/Binaries/Debug, - ../../../../../Build_iOS/openssl/lib, - ); - OTHER_LDFLAGS = ( - "$(inherited)", - "-all_load", - "-framework", - XCTest, - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "../../unittestpp/ ../../../../include ../../../../../Build_iOS/boost.framework/Headers"; - }; - name = Debug; - }; - D5E513981A1BEA1D0060F252 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ../../../../../Build_iOS, - ); - INFOPLIST_FILE = ios_runnerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - ../../../../../Build_iOS/build.release/build.i386/Binaries/Release, - ../../../../../Build_iOS/openssl/lib, - ); - OTHER_LDFLAGS = ( - "$(inherited)", - "-all_load", - "-framework", - XCTest, - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - USER_HEADER_SEARCH_PATHS = "../../unittestpp/ ../../../../include ../../../../../Build_iOS/boost.framework/Headers"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - D5E5136B1A1BEA1D0060F252 /* Build configuration list for PBXProject "ios_runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D5E513911A1BEA1D0060F252 /* Debug */, - D5E513921A1BEA1D0060F252 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D5E513961A1BEA1D0060F252 /* Build configuration list for PBXNativeTarget "ios_runnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D5E513971A1BEA1D0060F252 /* Debug */, - D5E513981A1BEA1D0060F252 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D5E513681A1BEA1D0060F252 /* Project object */; -} diff --git a/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index f7799a8bc6..0000000000 --- a/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/xcshareddata/xcschemes/ios_runner.xcscheme b/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/xcshareddata/xcschemes/ios_runner.xcscheme deleted file mode 100644 index bef34bb582..0000000000 --- a/Release/tests/common/TestRunner/ios/ios_runner.xcodeproj/xcshareddata/xcschemes/ios_runner.xcscheme +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/TestRunner/ios/ios_runnerTests/Info.plist b/Release/tests/common/TestRunner/ios/ios_runnerTests/Info.plist deleted file mode 100644 index 04f6d96780..0000000000 --- a/Release/tests/common/TestRunner/ios/ios_runnerTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - blah.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/Release/tests/common/TestRunner/ios/ios_runnerTests/ios_runnerTests.mm b/Release/tests/common/TestRunner/ios/ios_runnerTests/ios_runnerTests.mm deleted file mode 100644 index b0f578a59f..0000000000 --- a/Release/tests/common/TestRunner/ios/ios_runnerTests/ios_runnerTests.mm +++ /dev/null @@ -1,67 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* ==--== -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* Creates an Xcode test to bride with our UnitTestpp tests. Can be used to run -* iOS tests in the simulator or a connected physically device. -* -* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ -#import -#import - -#include "unittestpp.h" -#include "src/TestReporterStdout.h" - -@interface ios_runnerTests : XCTestCase - -@end - -@implementation ios_runnerTests - -- (void)setUp { - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testCppRestSdk { - UnitTest::TestReporterStdout testReporter; - UnitTest::TestRunner testRunner(testReporter); - - UnitTest::TestList& tests = UnitTest::GetTestList(); - testRunner.RunTestsIf(tests, - [&](UnitTest::Test *pTest) - { - if (pTest->m_properties.Has("Ignore")) return false; - if (pTest->m_properties.Has("Ignore:Apple")) return false; - if (pTest->m_properties.Has("Ignore:IOS")) return false; - if (pTest->m_properties.Has("Requires")) return false; - return true; - }, - 60000 * 3); - - int totalTestCount = testRunner.GetTestResults()->GetTotalTestCount(); - int failedTestCount = testRunner.GetTestResults()->GetFailedTestCount(); - if(failedTestCount > 0) - { - printf("%i tests FAILED\n", failedTestCount); - XCTAssert(false); - } - else - { - printf("All %i tests PASSED\n", totalTestCount); - XCTAssert(YES, @"Pass"); - } -} - -@end diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj deleted file mode 100644 index d798ca823d..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj +++ /dev/null @@ -1,284 +0,0 @@ - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - {d1060d0a-a10e-444d-9f6b-9676ea453f9a} - Android - TestRunner.android.NativeActivity - TestRunner_android - en-US - 14.0 - Android - 2.0 - - - - DynamicLibrary - true - gnustl_static - Clang_3_8 - - - DynamicLibrary - true - gnustl_static - Clang_3_8 - - - DynamicLibrary - false - gnustl_static - Clang_3_8 - - - DynamicLibrary - false - gnustl_static - Clang_3_8 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Use - pch.h - CompileAsCpp - Enabled - true - c++11 - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - %(LibraryDependencies);GLESv1_CM;EGL;m - - - - - Use - pch.h - CompileAsCpp - Enabled - true - c++11 - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - %(LibraryDependencies);GLESv1_CM;EGL;m - - - - - Use - pch.h - CompileAsCpp - Enabled - true - c++11 - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - %(LibraryDependencies);GLESv1_CM;EGL;m - - - - - Use - pch.h - CompileAsCpp - Enabled - true - c++11 - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - %(LibraryDependencies);GLESv1_CM;EGL;m - - - - - - - - - - - - - {afb49019-965b-4c10-baff-c86c16d58010} - true - false - false - true - true - - - {0ee481da-a97f-4831-9119-c65eb2d7b4da} - true - false - false - true - true - - - {2b00d1c0-1a93-4a32-8932-c3cc43acff45} - true - false - false - true - true - - - {b444ee47-1340-4a74-820d-cdd55f9f22f7} - true - false - false - true - true - - - {169555ef-8a80-405e-a815-cfe70028ca45} - true - false - false - true - true - - - {df670b4e-692c-424e-bcfd-f63d34fe5cd3} - true - false - false - true - true - - - {b9da540f-95f7-485e-adf4-c94a17bfa1eb} - true - false - false - true - true - - - {63569c1a-a168-442a-b160-76d0256803af} - true - false - false - true - true - - - {423fce6d-7400-4c09-9038-4438fbb089d4} - true - false - false - true - true - - - {3e8466b1-7cbc-489d-8e6b-5e45bab4d627} - true - false - false - true - true - - - {0149e1c2-fbf3-48b6-9996-d6753f689dfb} - true - false - false - true - true - - - {3efd8540-a54d-4900-887e-f856162535a0} - true - false - false - true - true - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - true - false - false - true - true - - - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj.filters b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj.filters deleted file mode 100644 index 52b354d8e3..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/TestRunner.android.NativeActivity.vcxproj.filters +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.c b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.c deleted file mode 100644 index 6de5362a00..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__)) - -/* For debug builds, always enable the debug traces in this library */ -#ifndef NDEBUG -# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__)) -#else -# define LOGV(...) ((void)0) -#endif - -static void free_saved_state(struct android_app* android_app) { - pthread_mutex_lock(&android_app->mutex); - if (android_app->savedState != NULL) { - free(android_app->savedState); - android_app->savedState = NULL; - android_app->savedStateSize = 0; - } - pthread_mutex_unlock(&android_app->mutex); -} - -int8_t android_app_read_cmd(struct android_app* android_app) { - int8_t cmd; - if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { - switch (cmd) { - case APP_CMD_SAVE_STATE: - free_saved_state(android_app); - break; - } - return cmd; - } else { - LOGE("No data on command pipe!"); - } - return -1; -} - -static void print_cur_config(struct android_app* android_app) { - char lang[2], country[2]; - AConfiguration_getLanguage(android_app->config, lang); - AConfiguration_getCountry(android_app->config, country); - - LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " - "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " - "modetype=%d modenight=%d", - AConfiguration_getMcc(android_app->config), - AConfiguration_getMnc(android_app->config), - lang[0], lang[1], country[0], country[1], - AConfiguration_getOrientation(android_app->config), - AConfiguration_getTouchscreen(android_app->config), - AConfiguration_getDensity(android_app->config), - AConfiguration_getKeyboard(android_app->config), - AConfiguration_getNavigation(android_app->config), - AConfiguration_getKeysHidden(android_app->config), - AConfiguration_getNavHidden(android_app->config), - AConfiguration_getSdkVersion(android_app->config), - AConfiguration_getScreenSize(android_app->config), - AConfiguration_getScreenLong(android_app->config), - AConfiguration_getUiModeType(android_app->config), - AConfiguration_getUiModeNight(android_app->config)); -} - -void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { - switch (cmd) { - case APP_CMD_INPUT_CHANGED: - LOGV("APP_CMD_INPUT_CHANGED\n"); - pthread_mutex_lock(&android_app->mutex); - if (android_app->inputQueue != NULL) { - AInputQueue_detachLooper(android_app->inputQueue); - } - android_app->inputQueue = android_app->pendingInputQueue; - if (android_app->inputQueue != NULL) { - LOGV("Attaching input queue to looper"); - AInputQueue_attachLooper(android_app->inputQueue, - android_app->looper, LOOPER_ID_INPUT, NULL, - &android_app->inputPollSource); - } - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_INIT_WINDOW: - LOGV("APP_CMD_INIT_WINDOW\n"); - pthread_mutex_lock(&android_app->mutex); - android_app->window = android_app->pendingWindow; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_TERM_WINDOW: - LOGV("APP_CMD_TERM_WINDOW\n"); - pthread_cond_broadcast(&android_app->cond); - break; - - case APP_CMD_RESUME: - case APP_CMD_START: - case APP_CMD_PAUSE: - case APP_CMD_STOP: - LOGV("activityState=%d\n", cmd); - pthread_mutex_lock(&android_app->mutex); - android_app->activityState = cmd; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_CONFIG_CHANGED: - LOGV("APP_CMD_CONFIG_CHANGED\n"); - AConfiguration_fromAssetManager(android_app->config, - android_app->activity->assetManager); - print_cur_config(android_app); - break; - - case APP_CMD_DESTROY: - LOGV("APP_CMD_DESTROY\n"); - android_app->destroyRequested = 1; - break; - } -} - -void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { - switch (cmd) { - case APP_CMD_TERM_WINDOW: - LOGV("APP_CMD_TERM_WINDOW\n"); - pthread_mutex_lock(&android_app->mutex); - android_app->window = NULL; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_SAVE_STATE: - LOGV("APP_CMD_SAVE_STATE\n"); - pthread_mutex_lock(&android_app->mutex); - android_app->stateSaved = 1; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_RESUME: - free_saved_state(android_app); - break; - } -} - -static void android_app_destroy(struct android_app* android_app) { - LOGV("android_app_destroy!"); - free_saved_state(android_app); - pthread_mutex_lock(&android_app->mutex); - if (android_app->inputQueue != NULL) { - AInputQueue_detachLooper(android_app->inputQueue); - } - AConfiguration_delete(android_app->config); - android_app->destroyed = 1; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - // Can't touch android_app object after this. -} - -static void process_input(struct android_app* app, struct android_poll_source* source) { - AInputEvent* event = NULL; - while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { - LOGV("New input event: type=%d\n", AInputEvent_getType(event)); - if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { - continue; - } - int32_t handled = 0; - if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); - AInputQueue_finishEvent(app->inputQueue, event, handled); - } -} - -static void process_cmd(struct android_app* app, struct android_poll_source* source) { - int8_t cmd = android_app_read_cmd(app); - android_app_pre_exec_cmd(app, cmd); - if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); - android_app_post_exec_cmd(app, cmd); -} - -static void* android_app_entry(void* param) { - struct android_app* android_app = (struct android_app*)param; - - android_app->config = AConfiguration_new(); - AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); - - print_cur_config(android_app); - - android_app->cmdPollSource.id = LOOPER_ID_MAIN; - android_app->cmdPollSource.app = android_app; - android_app->cmdPollSource.process = process_cmd; - android_app->inputPollSource.id = LOOPER_ID_INPUT; - android_app->inputPollSource.app = android_app; - android_app->inputPollSource.process = process_input; - - ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); - ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, - &android_app->cmdPollSource); - android_app->looper = looper; - - pthread_mutex_lock(&android_app->mutex); - android_app->running = 1; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - - android_main(android_app); - - android_app_destroy(android_app); - return NULL; -} - -// -------------------------------------------------------------------- -// Native activity interaction (called from main thread) -// -------------------------------------------------------------------- - -static struct android_app* android_app_create(ANativeActivity* activity, - void* savedState, size_t savedStateSize) { - struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); - memset(android_app, 0, sizeof(struct android_app)); - android_app->activity = activity; - - pthread_mutex_init(&android_app->mutex, NULL); - pthread_cond_init(&android_app->cond, NULL); - - if (savedState != NULL) { - android_app->savedState = malloc(savedStateSize); - android_app->savedStateSize = savedStateSize; - memcpy(android_app->savedState, savedState, savedStateSize); - } - - int msgpipe[2]; - if (pipe(msgpipe)) { - LOGE("could not create pipe: %s", strerror(errno)); - return NULL; - } - android_app->msgread = msgpipe[0]; - android_app->msgwrite = msgpipe[1]; - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&android_app->thread, &attr, android_app_entry, android_app); - - // Wait for thread to start. - pthread_mutex_lock(&android_app->mutex); - while (!android_app->running) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); - - return android_app; -} - -static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { - if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { - LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); - } -} - -static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { - pthread_mutex_lock(&android_app->mutex); - android_app->pendingInputQueue = inputQueue; - android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); - while (android_app->inputQueue != android_app->pendingInputQueue) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); -} - -static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { - pthread_mutex_lock(&android_app->mutex); - if (android_app->pendingWindow != NULL) { - android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); - } - android_app->pendingWindow = window; - if (window != NULL) { - android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); - } - while (android_app->window != android_app->pendingWindow) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); -} - -static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { - pthread_mutex_lock(&android_app->mutex); - android_app_write_cmd(android_app, cmd); - while (android_app->activityState != cmd) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); -} - -static void android_app_free(struct android_app* android_app) { - pthread_mutex_lock(&android_app->mutex); - android_app_write_cmd(android_app, APP_CMD_DESTROY); - while (!android_app->destroyed) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); - - close(android_app->msgread); - close(android_app->msgwrite); - pthread_cond_destroy(&android_app->cond); - pthread_mutex_destroy(&android_app->mutex); - free(android_app); -} - -static void onDestroy(ANativeActivity* activity) { - LOGV("Destroy: %p\n", activity); - android_app_free((struct android_app*)activity->instance); -} - -static void onStart(ANativeActivity* activity) { - LOGV("Start: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); -} - -static void onResume(ANativeActivity* activity) { - LOGV("Resume: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); -} - -static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { - struct android_app* android_app = (struct android_app*)activity->instance; - void* savedState = NULL; - - LOGV("SaveInstanceState: %p\n", activity); - pthread_mutex_lock(&android_app->mutex); - android_app->stateSaved = 0; - android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); - while (!android_app->stateSaved) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - - if (android_app->savedState != NULL) { - savedState = android_app->savedState; - *outLen = android_app->savedStateSize; - android_app->savedState = NULL; - android_app->savedStateSize = 0; - } - - pthread_mutex_unlock(&android_app->mutex); - - return savedState; -} - -static void onPause(ANativeActivity* activity) { - LOGV("Pause: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); -} - -static void onStop(ANativeActivity* activity) { - LOGV("Stop: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); -} - -static void onConfigurationChanged(ANativeActivity* activity) { - struct android_app* android_app = (struct android_app*)activity->instance; - LOGV("ConfigurationChanged: %p\n", activity); - android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); -} - -static void onLowMemory(ANativeActivity* activity) { - struct android_app* android_app = (struct android_app*)activity->instance; - LOGV("LowMemory: %p\n", activity); - android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); -} - -static void onWindowFocusChanged(ANativeActivity* activity, int focused) { - LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); - android_app_write_cmd((struct android_app*)activity->instance, - focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); -} - -static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { - LOGV("NativeWindowCreated: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, window); -} - -static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { - LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, NULL); -} - -static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { - LOGV("InputQueueCreated: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, queue); -} - -static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { - LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, NULL); -} - -void ANativeActivity_onCreate(ANativeActivity* activity, - void* savedState, size_t savedStateSize) { - LOGV("Creating: %p\n", activity); - activity->callbacks->onDestroy = onDestroy; - activity->callbacks->onStart = onStart; - activity->callbacks->onResume = onResume; - activity->callbacks->onSaveInstanceState = onSaveInstanceState; - activity->callbacks->onPause = onPause; - activity->callbacks->onStop = onStop; - activity->callbacks->onConfigurationChanged = onConfigurationChanged; - activity->callbacks->onLowMemory = onLowMemory; - activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; - activity->callbacks->onInputQueueCreated = onInputQueueCreated; - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; - - activity->instance = android_app_create(activity, savedState, savedStateSize); -} diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.h b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.h deleted file mode 100644 index 1b390c2d46..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/android_native_app_glue.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef _ANDROID_NATIVE_APP_GLUE_H -#define _ANDROID_NATIVE_APP_GLUE_H - -#include -#include -#include - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The native activity interface provided by - * is based on a set of application-provided callbacks that will be called - * by the Activity's main thread when certain events occur. - * - * This means that each one of this callbacks _should_ _not_ block, or they - * risk having the system force-close the application. This programming - * model is direct, lightweight, but constraining. - * - * The 'threaded_native_app' static library is used to provide a different - * execution model where the application can implement its own main event - * loop in a different thread instead. Here's how it works: - * - * 1/ The application must provide a function named "android_main()" that - * will be called when the activity is created, in a new thread that is - * distinct from the activity's main thread. - * - * 2/ android_main() receives a pointer to a valid "android_app" structure - * that contains references to other important objects, e.g. the - * ANativeActivity obejct instance the application is running in. - * - * 3/ the "android_app" object holds an ALooper instance that already - * listens to two important things: - * - * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX - * declarations below. - * - * - input events coming from the AInputQueue attached to the activity. - * - * Each of these correspond to an ALooper identifier returned by - * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT, - * respectively. - * - * Your application can use the same ALooper to listen to additional - * file-descriptors. They can either be callback based, or with return - * identifiers starting with LOOPER_ID_USER. - * - * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event, - * the returned data will point to an android_poll_source structure. You - * can call the process() function on it, and fill in android_app->onAppCmd - * and android_app->onInputEvent to be called for your own processing - * of the event. - * - * Alternatively, you can call the low-level functions to read and process - * the data directly... look at the process_cmd() and process_input() - * implementations in the glue to see how to do this. - * - * See the sample named "native-activity" that comes with the NDK with a - * full usage example. Also look at the JavaDoc of NativeActivity. - */ - -struct android_app; - -/** - * Data associated with an ALooper fd that will be returned as the "outData" - * when that source has data ready. - */ -struct android_poll_source { - // The identifier of this source. May be LOOPER_ID_MAIN or - // LOOPER_ID_INPUT. - int32_t id; - - // The android_app this ident is associated with. - struct android_app* app; - - // Function to call to perform the standard processing of data from - // this source. - void (*process)(struct android_app* app, struct android_poll_source* source); -}; - -/** - * This is the interface for the standard glue code of a threaded - * application. In this model, the application's code is running - * in its own thread separate from the main thread of the process. - * It is not required that this thread be associated with the Java - * VM, although it will need to be in order to make JNI calls any - * Java objects. - */ -struct android_app { - // The application can place a pointer to its own state object - // here if it likes. - void* userData; - - // Fill this in with the function to process main app commands (APP_CMD_*) - void (*onAppCmd)(struct android_app* app, int32_t cmd); - - // Fill this in with the function to process input events. At this point - // the event has already been pre-dispatched, and it will be finished upon - // return. Return 1 if you have handled the event, 0 for any default - // dispatching. - int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); - - // The ANativeActivity object instance that this app is running in. - ANativeActivity* activity; - - // The current configuration the app is running in. - AConfiguration* config; - - // This is the last instance's saved state, as provided at creation time. - // It is NULL if there was no state. You can use this as you need; the - // memory will remain around until you call android_app_exec_cmd() for - // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL. - // These variables should only be changed when processing a APP_CMD_SAVE_STATE, - // at which point they will be initialized to NULL and you can malloc your - // state and place the information here. In that case the memory will be - // freed for you later. - void* savedState; - size_t savedStateSize; - - // The ALooper associated with the app's thread. - ALooper* looper; - - // When non-NULL, this is the input queue from which the app will - // receive user input events. - AInputQueue* inputQueue; - - // When non-NULL, this is the window surface that the app can draw in. - ANativeWindow* window; - - // Current content rectangle of the window; this is the area where the - // window's content should be placed to be seen by the user. - ARect contentRect; - - // Current state of the app's activity. May be either APP_CMD_START, - // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below. - int activityState; - - // This is non-zero when the application's NativeActivity is being - // destroyed and waiting for the app thread to complete. - int destroyRequested; - - // ------------------------------------------------- - // Below are "private" implementation of the glue code. - - pthread_mutex_t mutex; - pthread_cond_t cond; - - int msgread; - int msgwrite; - - pthread_t thread; - - struct android_poll_source cmdPollSource; - struct android_poll_source inputPollSource; - - int running; - int stateSaved; - int destroyed; - int redrawNeeded; - AInputQueue* pendingInputQueue; - ANativeWindow* pendingWindow; - ARect pendingContentRect; -}; - -enum { - /** - * Looper data ID of commands coming from the app's main thread, which - * is returned as an identifier from ALooper_pollOnce(). The data for this - * identifier is a pointer to an android_poll_source structure. - * These can be retrieved and processed with android_app_read_cmd() - * and android_app_exec_cmd(). - */ - LOOPER_ID_MAIN = 1, - - /** - * Looper data ID of events coming from the AInputQueue of the - * application's window, which is returned as an identifier from - * ALooper_pollOnce(). The data for this identifier is a pointer to an - * android_poll_source structure. These can be read via the inputQueue - * object of android_app. - */ - LOOPER_ID_INPUT = 2, - - /** - * Start of user-defined ALooper identifiers. - */ - LOOPER_ID_USER = 3, -}; - -enum { - /** - * Command from main thread: the AInputQueue has changed. Upon processing - * this command, android_app->inputQueue will be updated to the new queue - * (or NULL). - */ - APP_CMD_INPUT_CHANGED, - - /** - * Command from main thread: a new ANativeWindow is ready for use. Upon - * receiving this command, android_app->window will contain the new window - * surface. - */ - APP_CMD_INIT_WINDOW, - - /** - * Command from main thread: the existing ANativeWindow needs to be - * terminated. Upon receiving this command, android_app->window still - * contains the existing window; after calling android_app_exec_cmd - * it will be set to NULL. - */ - APP_CMD_TERM_WINDOW, - - /** - * Command from main thread: the current ANativeWindow has been resized. - * Please redraw with its new size. - */ - APP_CMD_WINDOW_RESIZED, - - /** - * Command from main thread: the system needs that the current ANativeWindow - * be redrawn. You should redraw the window before handing this to - * android_app_exec_cmd() in order to avoid transient drawing glitches. - */ - APP_CMD_WINDOW_REDRAW_NEEDED, - - /** - * Command from main thread: the content area of the window has changed, - * such as from the soft input window being shown or hidden. You can - * find the new content rect in android_app::contentRect. - */ - APP_CMD_CONTENT_RECT_CHANGED, - - /** - * Command from main thread: the app's activity window has gained - * input focus. - */ - APP_CMD_GAINED_FOCUS, - - /** - * Command from main thread: the app's activity window has lost - * input focus. - */ - APP_CMD_LOST_FOCUS, - - /** - * Command from main thread: the current device configuration has changed. - */ - APP_CMD_CONFIG_CHANGED, - - /** - * Command from main thread: the system is running low on memory. - * Try to reduce your memory use. - */ - APP_CMD_LOW_MEMORY, - - /** - * Command from main thread: the app's activity has been started. - */ - APP_CMD_START, - - /** - * Command from main thread: the app's activity has been resumed. - */ - APP_CMD_RESUME, - - /** - * Command from main thread: the app should generate a new saved state - * for itself, to restore from later if needed. If you have saved state, - * allocate it with malloc and place it in android_app.savedState with - * the size in android_app.savedStateSize. The will be freed for you - * later. - */ - APP_CMD_SAVE_STATE, - - /** - * Command from main thread: the app's activity has been paused. - */ - APP_CMD_PAUSE, - - /** - * Command from main thread: the app's activity has been stopped. - */ - APP_CMD_STOP, - - /** - * Command from main thread: the app's activity is being destroyed, - * and waiting for the app thread to clean up and exit before proceeding. - */ - APP_CMD_DESTROY, -}; - -/** - * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next - * app command message. - */ -int8_t android_app_read_cmd(struct android_app* android_app); - -/** - * Call with the command returned by android_app_read_cmd() to do the - * initial pre-processing of the given command. You can perform your own - * actions for the command after calling this function. - */ -void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); - -/** - * Call with the command returned by android_app_read_cmd() to do the - * final post-processing of the given command. You must have done your own - * actions for the command before calling this function. - */ -void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); - -/** - * This is the function that application code must implement, representing - * the main entry to the app. - */ -extern void android_main(struct android_app* app); - -#ifdef __cplusplus -} -#endif - -#endif /* _ANDROID_NATIVE_APP_GLUE_H */ diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/main.cpp b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/main.cpp deleted file mode 100644 index d6333e1fd5..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/main.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/* -* Copyright (C) 2010 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -*/ - -#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "AndroidProject1.NativeActivity", __VA_ARGS__)) -#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "AndroidProject1.NativeActivity", __VA_ARGS__)) - -/** -* Our saved state data. -*/ -struct saved_state { - float angle; - int32_t x; - int32_t y; -}; - -/** -* Shared state for our app. -*/ -struct engine { - struct android_app* app; - - ASensorManager* sensorManager; - const ASensor* accelerometerSensor; - ASensorEventQueue* sensorEventQueue; - - int animating; - EGLDisplay display; - EGLSurface surface; - EGLContext context; - int32_t width; - int32_t height; - struct saved_state state; -}; - -/** -* Initialize an EGL context for the current display. -*/ -static int engine_init_display(struct engine* engine) { - // initialize OpenGL ES and EGL - - /* - * Here specify the attributes of the desired configuration. - * Below, we select an EGLConfig with at least 8 bits per color - * component compatible with on-screen windows - */ - const EGLint attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_NONE - }; - EGLint w, h, format; - EGLint numConfigs; - EGLConfig config; - EGLSurface surface; - EGLContext context; - - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - eglInitialize(display, 0, 0); - - /* Here, the application chooses the configuration it desires. In this - * sample, we have a very simplified selection process, where we pick - * the first EGLConfig that matches our criteria */ - eglChooseConfig(display, attribs, &config, 1, &numConfigs); - - /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is - * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). - * As soon as we picked a EGLConfig, we can safely reconfigure the - * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ - eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); - - ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); - - surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); - context = eglCreateContext(display, config, NULL, NULL); - - if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { - LOGW("Unable to eglMakeCurrent"); - return -1; - } - - eglQuerySurface(display, surface, EGL_WIDTH, &w); - eglQuerySurface(display, surface, EGL_HEIGHT, &h); - - engine->display = display; - engine->context = context; - engine->surface = surface; - engine->width = w; - engine->height = h; - engine->state.angle = 0; - - // Initialize GL state. - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glEnable(GL_CULL_FACE); - glShadeModel(GL_SMOOTH); - glDisable(GL_DEPTH_TEST); - - return 0; -} - -/** -* Just the current frame in the display. -*/ -static void engine_draw_frame(struct engine* engine) { - if (engine->display == NULL) { - // No display. - return; - } - - // Just fill the screen with a color. - glClearColor(((float)engine->state.x) / engine->width, engine->state.angle, - ((float)engine->state.y) / engine->height, 1); - glClear(GL_COLOR_BUFFER_BIT); - - eglSwapBuffers(engine->display, engine->surface); -} - -/** -* Tear down the EGL context currently associated with the display. -*/ -static void engine_term_display(struct engine* engine) { - if (engine->display != EGL_NO_DISPLAY) { - eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (engine->context != EGL_NO_CONTEXT) { - eglDestroyContext(engine->display, engine->context); - } - if (engine->surface != EGL_NO_SURFACE) { - eglDestroySurface(engine->display, engine->surface); - } - eglTerminate(engine->display); - } - engine->animating = 0; - engine->display = EGL_NO_DISPLAY; - engine->context = EGL_NO_CONTEXT; - engine->surface = EGL_NO_SURFACE; -} - -/** -* Process the next input event. -*/ -static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) { - struct engine* engine = (struct engine*)app->userData; - if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { - engine->state.x = AMotionEvent_getX(event, 0); - engine->state.y = AMotionEvent_getY(event, 0); - return 1; - } - return 0; -} - -/** -* Process the next main command. -*/ -static void engine_handle_cmd(struct android_app* app, int32_t cmd) { - struct engine* engine = (struct engine*)app->userData; - switch (cmd) { - case APP_CMD_SAVE_STATE: - // The system has asked us to save our current state. Do so. - engine->app->savedState = malloc(sizeof(struct saved_state)); - *((struct saved_state*)engine->app->savedState) = engine->state; - engine->app->savedStateSize = sizeof(struct saved_state); - break; - case APP_CMD_INIT_WINDOW: - // The window is being shown, get it ready. - if (engine->app->window != NULL) { - engine_init_display(engine); - engine_draw_frame(engine); - } - break; - case APP_CMD_TERM_WINDOW: - // The window is being hidden or closed, clean it up. - engine_term_display(engine); - break; - case APP_CMD_GAINED_FOCUS: - // When our app gains focus, we start monitoring the accelerometer. - if (engine->accelerometerSensor != NULL) { - ASensorEventQueue_enableSensor(engine->sensorEventQueue, - engine->accelerometerSensor); - // We'd like to get 60 events per second (in us). - ASensorEventQueue_setEventRate(engine->sensorEventQueue, - engine->accelerometerSensor, (1000L / 60) * 1000); - } - break; - case APP_CMD_LOST_FOCUS: - // When our app loses focus, we stop monitoring the accelerometer. - // This is to avoid consuming battery while not being used. - if (engine->accelerometerSensor != NULL) { - ASensorEventQueue_disableSensor(engine->sensorEventQueue, - engine->accelerometerSensor); - } - // Also stop animating. - engine->animating = 0; - engine_draw_frame(engine); - break; - } -} - -#include -#include -#include -#include -#include -#include -#include "unittestpp.h" -#include "src/TestReporter.h" -#include "src/TestDetails.h" -#include -#include -#include - -void printLn(const std::string& s) { - __android_log_print(ANDROID_LOG_WARN, "UnitTestpp", "%s", s.c_str()); -} - -struct MyTestReporter : UnitTest::TestReporter { - UNITTEST_LINKAGE virtual void ReportTestStart(UnitTest::TestDetails const& test) { - std::stringstream ss; - ss << test.suiteName << ":" << test.testName << ": Start."; - printLn(ss.str()); - } - UNITTEST_LINKAGE virtual void ReportFailure(UnitTest::TestDetails const& test, char const* failure) { - std::stringstream ss; - ss << test.suiteName << ":" << test.testName << ": " << failure; - printLn(ss.str()); - } - UNITTEST_LINKAGE virtual void ReportTestFinish(UnitTest::TestDetails const& test, bool passed, float secondsElapsed) { - if (!passed) { - std::stringstream ss; - ss << test.suiteName << ":" << test.testName << ": Failed. Seconds: " << secondsElapsed; - printLn(ss.str()); - } - } - UNITTEST_LINKAGE virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) { - std::stringstream ss; - ss << "Tests complete. Total: " << totalTestCount << ", Failed: " << failedTestCount << ", Time: " << secondsElapsed; - printLn(ss.str()); - // Print a bunch of messages to defeat any batching that may be applied by adb or logcat - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - printLn("--- Flush buffer ---"); - } - UNITTEST_LINKAGE virtual void print(const std::string& s) { - printLn(s); - } -}; - -static std::string to_lower(const std::string &str) -{ - std::string lower; - for (auto iter = str.begin(); iter != str.end(); ++iter) - { - lower.push_back((char)tolower(*iter)); - } - return lower; -} - -bool matched_properties(UnitTest::TestProperties const& test_props) { - if (test_props.Has("Requires")) { - std::string const requires = test_props.Get("Requires"); - std::vector requirements; - - // Can be multiple requirements, a semi colon seperated list - std::string::size_type pos = requires.find_first_of(';'); - std::string::size_type last_pos = 0; - while (pos != std::string::npos) - { - requirements.push_back(requires.substr(last_pos, pos - last_pos)); - last_pos = pos + 1; - pos = requires.find_first_of(';', last_pos); - } - requirements.push_back(requires.substr(last_pos)); - for (auto iter = requirements.begin(); iter != requirements.end(); ++iter) - { - if (!UnitTest::GlobalSettings::Has(to_lower(*iter))) - { - return false; - } - } - } - return true; -} - -bool should_run_test(UnitTest::Test *pTest) -{ - if (pTest->m_properties.Has("Ignore")) return false; - if (pTest->m_properties.Has("Ignore:Linux")) return false; - if (pTest->m_properties.Has("Ignore:Android")) return false; - if (matched_properties(pTest->m_properties)) { - return true; - } - return false; -} - -void* RunTests() { - UnitTest::TestList& tests = UnitTest::GetTestList(); - - MyTestReporter mtr; - - // Do work - UnitTest::TestRunner testrunner(mtr, false); - testrunner.RunTestsIf(tests, - [](UnitTest::Test *pTest) -> bool - { - if (should_run_test(pTest)) - return true; - auto& test = pTest->m_details; - std::stringstream ss; - ss << test.suiteName << ":" << test.testName << ": Skipped."; - printLn(ss.str()); - return false; - }, 0); - - return nullptr; -} - -/** -* This is the main entry point of a native application that is using -* android_native_app_glue. It runs in its own thread, with its own -* event loop for receiving input events and doing other things. -*/ -void android_main(struct android_app* state) { - struct engine engine; - - cpprest_init(state->activity->vm); - - // Begin change path to temp dir - jobject nAct = state->activity->clazz; - auto env = crossplat::get_jvm_env(); - - auto contextClass = env->FindClass("android/content/Context"); - auto getCacheDir = env->GetMethodID(contextClass, "getCacheDir", "()Ljava/io/File;"); - - auto fileClass = env->FindClass("java/io/File"); - auto getPath = env->GetMethodID(fileClass, "getPath", "()Ljava/lang/String;"); - - auto cacheDir = env->CallObjectMethod(nAct, getCacheDir); - jstring cacheDirPath = (jstring)env->CallObjectMethod(cacheDir, getPath); - auto st = env->GetStringUTFChars(cacheDirPath, nullptr); - chdir(st); - env->ReleaseStringUTFChars(cacheDirPath, st); - // End change path to temp dir - - RunTests(); - - memset(&engine, 0, sizeof(engine)); - state->userData = &engine; - state->onAppCmd = engine_handle_cmd; - state->onInputEvent = engine_handle_input; - engine.app = state; - - // Prepare to monitor accelerometer - engine.sensorManager = ASensorManager_getInstance(); - engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, - ASENSOR_TYPE_ACCELEROMETER); - engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager, - state->looper, LOOPER_ID_USER, NULL, NULL); - - if (state->savedState != NULL) { - // We are starting with a previous saved state; restore from it. - engine.state = *(struct saved_state*)state->savedState; - } - - engine.animating = 1; - - // loop waiting for stuff to do. - - while (1) { - // Read all pending events. - int ident; - int events; - struct android_poll_source* source; - - // If not animating, we will block forever waiting for events. - // If animating, we loop until all events are read, then continue - // to draw the next frame of animation. - while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, - (void**)&source)) >= 0) { - - // Process this event. - if (source != NULL) { - source->process(state, source); - } - - // Check if we are exiting. - if (state->destroyRequested != 0) { - engine_term_display(&engine); - return; - } - } - - if (engine.animating) { - // Done with events; draw next animation frame. - engine.state.angle += .01f; - if (engine.state.angle > 1) { - engine.state.angle = 0; - } - - // Drawing is throttled to the screen update rate, so there - // is no need to do timing here. - engine_draw_frame(&engine); - } - } -} diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config deleted file mode 100644 index c99b35a84e..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/packages.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/pch.h b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/pch.h deleted file mode 100644 index 5bf4b11366..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.NativeActivity/pch.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// pch.h -// Header for standard system include files. -// -// Used by the build system to generate the precompiled header. Note that no -// pch.cpp is needed and the pch.h is automatically included in all cpp files -// that are part of the project -// - -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include -#include "android_native_app_glue.h" diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml deleted file mode 100644 index 711b77cda6..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/TestRunner.android.Packaging.androidproj b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/TestRunner.android.Packaging.androidproj deleted file mode 100644 index d4e2b5fcc6..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/TestRunner.android.Packaging.androidproj +++ /dev/null @@ -1,84 +0,0 @@ - - - - - Debug - ARM - - - Release - ARM - - - Debug - x86 - - - Release - x86 - - - - TestRunner_android - 14.0 - 1.0 - {7cf3c460-3486-4106-80cd-eb802dfef373} - - - - true - - - false - - - true - - - false - - - - - - - - TestRunner_android - - - - - TestRunner_android - - - - - TestRunner_android - - - - - TestRunner_android - - - - - - - - - - - - {d1060d0a-a10e-444d-9f6b-9676ea453f9a} - - - - - - - - - - - diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/build.xml b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/build.xml deleted file mode 100644 index 3b9c329d4a..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/build.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/project.properties b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/project.properties deleted file mode 100644 index e613b43798..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/project.properties +++ /dev/null @@ -1,2 +0,0 @@ -# Project target -target=$(androidapilevel) diff --git a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/res/values/strings.xml b/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/res/values/strings.xml deleted file mode 100644 index 31108df64d..0000000000 --- a/Release/tests/common/TestRunner/vs14.android/TestRunner.android.Packaging/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - TestRunner.android.Packaging - diff --git a/Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj b/Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj deleted file mode 100644 index 231344b499..0000000000 --- a/Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj +++ /dev/null @@ -1,118 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {5E421824-72D7-4482-A161-8D7D02308E52} - Win32Proj - SAK - SAK - SAK - SAK - 14.0 - v140 - Unicode - Application - - - - true - - - false - true - - - false - true - - - false - true - - - - - - - - - - - TestRunner.winrt - - - - - NotUsing - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - WINRT_TEST_RUNNER;WIN32;_CONSOLE;%(PreprocessorDefinitions) - false - - - Console - $(OutDir);%(AdditionalLibraryDirectories) - true - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - - - - diff --git a/Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj.filters b/Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj.filters deleted file mode 100644 index f9fa6c25ca..0000000000 --- a/Release/tests/common/TestRunner/vs14.uwp/TestRunner140.uwp.vcxproj.filters +++ /dev/null @@ -1,24 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - {5e4d32c8-a472-4388-b880-920a7a546fa3} - - - {f05a925c-282c-4424-ae9a-10fe7f88fe47} - - - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj b/Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj deleted file mode 100644 index e14b9ab7e0..0000000000 --- a/Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj +++ /dev/null @@ -1,248 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {6490C580-DD4A-4F2D-A345-732C5148349F} - Win32Proj - TestRunner - $(VCTargetsPath12) - SAK - SAK - SAK - SAK - - - - Application - true - Unicode - v140 - - - Application - true - Unicode - v140 - - - Application - true - Unicode - v140 - - - Application - false - true - Unicode - v140 - - - Application - false - true - Unicode - v140 - - - Application - false - true - Unicode - v140 - - - - - - - - - - - - - - - - - - - - - - - TestRunner - - - TestRunner - - - TestRunner - - - false - TestRunner - - - false - TestRunner - - - false - TestRunner - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - NotUsing - Disabled - DESKTOP_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - Disabled - DESKTOP_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - Disabled - DESKTOP_TEST_RUNNER;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - DESKTOP_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - DESKTOP_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - NotUsing - MaxSpeed - true - true - DESKTOP_TEST_RUNNER;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - $(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - false - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - - - - \ No newline at end of file diff --git a/Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj.filters b/Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj.filters deleted file mode 100644 index f9fa6c25ca..0000000000 --- a/Release/tests/common/TestRunner/vs14/TestRunner140.vcxproj.filters +++ /dev/null @@ -1,24 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - {5e4d32c8-a472-4388-b880-920a7a546fa3} - - - {f05a925c-282c-4424-ae9a-10fe7f88fe47} - - - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj deleted file mode 100644 index c7b52f072b..0000000000 --- a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - {afb49019-965b-4c10-baff-c86c16d58010} - false - false - false - false - false - - - - {3EFD8540-A54D-4900-887E-F856162535A0} - Android - Android - 2.0 - UnitTestpp140.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - UnitTestpp140.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj.filters b/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj.filters deleted file mode 100644 index eccc1b629f..0000000000 --- a/Release/tests/common/UnitTestpp/vs14.android/UnitTestpp140.android.vcxproj.filters +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - {99f8e13d-e0d8-4917-83d5-6658b4a57e8e} - - - {40c405e2-9304-484c-b23b-441e611abff6} - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj b/Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj deleted file mode 100644 index 01a4ef1b5d..0000000000 --- a/Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj +++ /dev/null @@ -1,208 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - Win32Proj - UnitTest - SAK - SAK - SAK - SAK - 14.0 - Windows Store - 10.0.10240.0 - 10.0.10240.0 - 10.0 - - - - DynamicLibrary - Unicode - v140 - - - true - - - false - true - - - - - - $(CasablancaIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories); - NotUsing - UNITTEST_DLL_EXPORT;WIN32;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - $(WindowsSdkDir)\UnionMetadata;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - true - false - stdafx.h - - - Windows - true - true - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store;%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;msvcrtd.lib;msvcprtd.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store\arm;%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;uuid.lib;ole32.lib;msvcrtd.lib;msvcprtd.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store\amd64;%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;msvcrtd.lib;msvcprtd.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store;%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;msvcrt.lib;msvcprt.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store\arm;%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;uuid.lib;ole32.lib;msvcrt.lib;msvcprt.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store\amd64;%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;msvcrt.lib;msvcprt.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj.filters b/Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj.filters deleted file mode 100644 index 6fd73f9e3b..0000000000 --- a/Release/tests/common/UnitTestpp/vs14.uwp/UnitTestpp140.uwp.vcxproj.filters +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {640fb93d-0deb-4bc4-a035-5d44d5c2af4b} - - - {b883825b-c6c4-4545-806e-dfe105753ac8} - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj b/Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj deleted file mode 100644 index b1ccc17621..0000000000 --- a/Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj +++ /dev/null @@ -1,202 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {E715BBE6-743D-47C2-8F43-92AA18F6ED19} - Win32Proj - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - TestUnitTestpp140 - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);%(AdditionalIncludeDirectories); - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - MaxSpeed - NotUsing - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj.filters b/Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj.filters deleted file mode 100644 index 44e0743ad6..0000000000 --- a/Release/tests/common/UnitTestpp/vs14/TestUnitTestpp140.vcxproj.filters +++ /dev/null @@ -1,72 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - - - {420b7d9f-7900-40f3-8aa7-3c800278bc98} - - - {7ddca59d-156c-46f2-af93-4a03f915bbcb} - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj b/Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj deleted file mode 100644 index 3bd4978222..0000000000 --- a/Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj +++ /dev/null @@ -1,228 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - Win32Proj - UnitTest - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - UnitTestpp140 - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories); - Use - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - NotUsing - Disabled - UNITTEST_DLL_EXPORT;WIN32;_DEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - MaxSpeed - NotUsing - true - true - UNITTEST_DLL_EXPORT;WIN32;NDEBUG;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj.filters b/Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj.filters deleted file mode 100644 index 6fd73f9e3b..0000000000 --- a/Release/tests/common/UnitTestpp/vs14/UnitTestpp140.vcxproj.filters +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {640fb93d-0deb-4bc4-a035-5d44d5c2af4b} - - - {b883825b-c6c4-4545-806e-dfe105753ac8} - - - \ No newline at end of file diff --git a/Release/tests/common/utilities/CMakeLists.txt b/Release/tests/common/utilities/CMakeLists.txt index dfe4852da6..a2d2306577 100644 --- a/Release/tests/common/utilities/CMakeLists.txt +++ b/Release/tests/common/utilities/CMakeLists.txt @@ -6,7 +6,6 @@ endif() add_library(common_utilities os_utilities.cpp - stdafx.cpp ) if(NOT BUILD_SHARED_LIBS) diff --git a/Release/tests/common/utilities/os_utilities.cpp b/Release/tests/common/utilities/os_utilities.cpp index 639460078e..0e318e8069 100644 --- a/Release/tests/common/utilities/os_utilities.cpp +++ b/Release/tests/common/utilities/os_utilities.cpp @@ -4,17 +4,17 @@ * * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * -* os_utilities.cpp - defines an abstraction for common OS functions like Sleep, hiding the underlying platform. +* os_utilities.cpp - defines an abstraction for common OS functions like Sleep, hiding the underlying platform. * * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" - #include "os_utilities.h" #ifdef WIN32 +#define NOMINMAX #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include #include #else #include @@ -54,4 +54,3 @@ long os_utilities::interlocked_exchange(volatile long *target, long value) } }}} - diff --git a/Release/tests/common/utilities/stdafx.cpp b/Release/tests/common/utilities/stdafx.cpp deleted file mode 100644 index b5b248455b..0000000000 --- a/Release/tests/common/utilities/stdafx.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.cpp -* -* Pre-compiled headers -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -// stdafx.cpp : source file that includes just the standard includes -// Server.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/Release/tests/common/utilities/stdafx.h b/Release/tests/common/utilities/stdafx.h deleted file mode 100644 index db5203bed7..0000000000 --- a/Release/tests/common/utilities/stdafx.h +++ /dev/null @@ -1,24 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* stdafx.h -* -* Pre-compiled headers -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ - -#pragma once - -#ifdef WIN32 - -#include "targetver.h" - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#include - -#endif diff --git a/Release/tests/common/utilities/targetver.h b/Release/tests/common/utilities/targetver.h deleted file mode 100644 index 95417e6073..0000000000 --- a/Release/tests/common/utilities/targetver.h +++ /dev/null @@ -1,20 +0,0 @@ -/*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -* -* targetver.h -* -* Standard VS-generated header file. -* -* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -****/ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include diff --git a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj deleted file mode 100644 index 53592625d0..0000000000 --- a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - {3efd8540-a54d-4900-887e-f856162535a0} - - - - {7C4E6E33-42E2-4472-9319-DDE7564F3DAE} - Android - Android - 2.0 - CommonUtilities140.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - - - - d - - - CommonUtilities140.android - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj.filters b/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj.filters deleted file mode 100644 index 65f1bbe659..0000000000 --- a/Release/tests/common/utilities/vs14.android/CommonUtilities140.android.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - {31a9e4f4-e463-4a16-afeb-4e08578514f0} - - - {0354a1e4-1028-4f71-ae58-465027fa590d} - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj b/Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj deleted file mode 100644 index 10b6ac1e01..0000000000 --- a/Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - Win32Proj - CommonUtilities140 - SAK - SAK - SAK - SAK - en-US - 14.0 - 10.0.10240.0 - 10.0.10240.0 - Unicode - v140 - DynamicLibrary - true - - - - true - - - false - true - - - - - - - Use - WIN32;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - true - false - stdafx.h - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories); - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {5E421824-72D7-4482-A161-8D7D02308E52} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj.filters b/Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj.filters deleted file mode 100644 index 1325242b47..0000000000 --- a/Release/tests/common/utilities/vs14.uwp/CommonUtilities140.uwp.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {24e13f0e-e0f6-4fe0-922a-5cf7cbe823f4} - - - {ef18a939-f1a3-4e9e-b93a-05826fbae7f6} - - - \ No newline at end of file diff --git a/Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj b/Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj deleted file mode 100644 index 202e5daf98..0000000000 --- a/Release/tests/common/utilities/vs14.xp/CommonUtilities140.xp.vcxproj +++ /dev/null @@ -1,150 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - Win32Proj - CommonUtilities140 - SAK - SAK - SAK - SAK - $(VCTargetsPath14) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Create - Create - Create - Create - - - - - - - - - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {6490c580-dd4a-4f2d-a345-732c5148349f} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - - - - \ No newline at end of file diff --git a/Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj b/Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj deleted file mode 100644 index c5a179f24c..0000000000 --- a/Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj +++ /dev/null @@ -1,200 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - Win32Proj - CommonUtilities120 - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Advapi32.lib;kernel32.lib;user32.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Advapi32.lib;kernel32.lib;user32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONUTILITIES_EXPORTS;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - - - - \ No newline at end of file diff --git a/Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj.filters b/Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj.filters deleted file mode 100644 index 1325242b47..0000000000 --- a/Release/tests/common/utilities/vs14/CommonUtilities140.vcxproj.filters +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {24e13f0e-e0f6-4fe0-922a-5cf7cbe823f4} - - - {ef18a939-f1a3-4e9e-b93a-05826fbae7f6} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 17cf4eff81..d92b477481 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -22,7 +22,6 @@ set(SOURCES to_string_tests.cpp http_client_fuzz_tests.cpp compression_tests.cpp - stdafx.cpp ) add_casablanca_test(httpclient_test SOURCES) @@ -32,6 +31,19 @@ else() target_link_libraries(httpclient_test PRIVATE httptest_utilities) endif() +if(MSVC) + get_target_property(_srcs httpclient_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/client-tests-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/client-tests-stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpclient-tests-stdafx.pch") + target_sources(httpclient_test PRIVATE stdafx.cpp) + target_compile_options(httpclient_test PRIVATE /Yustdafx.h /Fpclient-tests-stdafx.pch) +endif() + if(NOT WIN32) cpprest_find_boost() target_link_libraries(httpclient_test PRIVATE cpprestsdk_boost_internal) diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index fd9142931a..889ab71797 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -11,10 +11,11 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ +#include "stdafx.h" + #include "cpprest/details/http_helpers.h" #include "cpprest/version.h" #include "cpprest/asyncrt_utils.h" -#include "stdafx.h" #include #ifndef __cplusplus_winrt diff --git a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj deleted file mode 100644 index 9d4978a9af..0000000000 --- a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - {b444ee47-1340-4a74-820d-cdd55f9f22f7} - - - - {0EE481DA-A97F-4831-9119-C65EB2D7B4DA} - Android - Android - 2.0 - HttpClient140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - HttpClient140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj.filters b/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj.filters deleted file mode 100644 index 832cc001c1..0000000000 --- a/Release/tests/functional/http/client/vs14.android/HttpClient140_test.android.vcxproj.filters +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - {2102c5c5-ec68-4b17-a463-475af72c31aa} - - - {2e4123cf-9aa6-4269-93d6-4a24f7eb2af0} - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/vs14.android/packages.config b/Release/tests/functional/http/client/vs14.android/packages.config deleted file mode 100644 index 4bd0fd80ad..0000000000 --- a/Release/tests/functional/http/client/vs14.android/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj b/Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj deleted file mode 100644 index 704e677f5a..0000000000 --- a/Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj +++ /dev/null @@ -1,153 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {E1E5C85C-9C98-49FC-A645-C1368E981940} - HttpTests - SAK - SAK - SAK - SAK - en-US - Windows Store - 14.0 - true - Unicode - v140 - DynamicLibrary - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities\include;%(AdditionalIncludeDirectories) - WIN32;_USRDLL;%(PreprocessorDefinitions) - true - false - stdafx.h - -Zm350 /bigobj%(AdditionalOptions) - - - Windows - true - CommonUtilities140.uwp.lib;%(AdditionalDependencies) - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - {039BA657-296A-4E11-8E37-948A5919F0B8} - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - diff --git a/Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj.filters b/Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj.filters deleted file mode 100644 index a8536ce996..0000000000 --- a/Release/tests/functional/http/client/vs14.uwp/HttpClient140_test.uwp.vcxproj.filters +++ /dev/null @@ -1,87 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - - - {fadb7f38-3d0c-4a31-af39-6364be0d9793} - - - {ee68ca67-bbcf-4196-89c7-fbf59083ac16} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj b/Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj deleted file mode 100644 index 691f035901..0000000000 --- a/Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj +++ /dev/null @@ -1,240 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {dc215f97-c43c-47f5-9784-711908a24ae3} - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities\include;%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj %(AdditionalOptions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - -Zm350 /bigobj%(AdditionalOptions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;httpapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {6837625b-c0db-4fd0-aee2-19699031b76e} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj.filters b/Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj.filters deleted file mode 100644 index 6a577a5662..0000000000 --- a/Release/tests/functional/http/client/vs14/HttpClient140_test.vcxproj.filters +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - Source Files - - - - - Header Files - - - Header Files - - - - - {fadb7f38-3d0c-4a31-af39-6364be0d9793} - - - {ee68ca67-bbcf-4196-89c7-fbf59083ac16} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/listener/CMakeLists.txt b/Release/tests/functional/http/listener/CMakeLists.txt index 33be6fb354..aa4245fed8 100644 --- a/Release/tests/functional/http/listener/CMakeLists.txt +++ b/Release/tests/functional/http/listener/CMakeLists.txt @@ -13,7 +13,6 @@ if(NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) response_stream_tests.cpp status_code_reason_phrase_tests.cpp to_string_tests.cpp - stdafx.cpp ) add_casablanca_test(httplistener_test SOURCES) @@ -22,4 +21,15 @@ if(NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) else() target_link_libraries(httplistener_test PRIVATE httptest_utilities) endif() + + if(MSVC) + get_target_property(_srcs httplistener_test SOURCES) + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/listener-tests-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/listener-tests-stdafx.pch") + endif() + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fplistener-tests-stdafx.pch") + target_sources(httplistener_test PRIVATE stdafx.cpp) + target_compile_options(httplistener_test PRIVATE /Yustdafx.h /Fplistener-tests-stdafx.pch) + endif() endif() diff --git a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj deleted file mode 100644 index 2bb8421046..0000000000 --- a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - {b444ee47-1340-4a74-820d-cdd55f9f22f7} - - - - {2B00D1C0-1A93-4A32-8932-C3CC43ACFF45} - Android - Android - 2.0 - HttpListener140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - HttpListener140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj.filters b/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj.filters deleted file mode 100644 index 48553613bc..0000000000 --- a/Release/tests/functional/http/listener/vs14.android/HttpListener140_test.android.vcxproj.filters +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - {fa079c21-f36e-4713-a05c-fced62c90650} - - - {c62749db-a977-4b3f-abe9-839f3f8a21b4} - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj b/Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj deleted file mode 100644 index 23a5617b20..0000000000 --- a/Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj +++ /dev/null @@ -1,242 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {2853ec0b-1b8e-4d9d-8436-4ef6dded5378} - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - - - - - - - - - - - - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - FastCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - FastCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - FastCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - FastCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - FastCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(TestRoot)\functional\http\utilities\include;%(AdditionalIncludeDirectories) - -Zm140 /bigobj%(AdditionalOptions) - FastCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {6837625b-c0db-4fd0-aee2-19699031b76e} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj.filters b/Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj.filters deleted file mode 100644 index 6041b38df7..0000000000 --- a/Release/tests/functional/http/listener/vs14/HttpListener140_test.vcxproj.filters +++ /dev/null @@ -1,63 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - - - {3de7d3df-7d70-4ea1-a460-bc378ed266c2} - - - {4ac74123-f940-4347-9a8e-d9e35ba7c7ac} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj deleted file mode 100644 index 62a0cf8a5a..0000000000 --- a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - - - - {B444EE47-1340-4A74-820D-CDD55F9F22F7} - Android - Android - 2.0 - HttpTestUtilities140.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - HttpTestUtilities140.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj.filters b/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj.filters deleted file mode 100644 index cd9c4f61a3..0000000000 --- a/Release/tests/functional/http/utilities/vs14.android/HttpTestUtilities140.android.vcxproj.filters +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - {0bfc92ca-392b-4e84-86de-9f87dea20ad1} - - - {6fdd8038-3b97-4ab2-8b8d-0e15fc4dbfdc} - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj b/Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj deleted file mode 100644 index c5282c8210..0000000000 --- a/Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj +++ /dev/null @@ -1,183 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {039BA657-296A-4E11-8E37-948A5919F0B8} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 14.0 - Unicode - v140 - DynamicLibrary - Windows Store - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - Use - WIN32;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include - $(WindowsSdkDir)\UnionMetadata;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - stdafx.h - - - Windows - true - true - CommonUtilities140.uwp.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;msvcrtd.lib;msvcprtd.lib;concrtd.lib;Winhttp.lib;Httpapi.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;msvcrtd.lib;msvcprtd.lib;concrtd.lib;Winhttp.lib;Httpapi.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store\arm;$(OutDir);%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;msvcrtd.lib;msvcprtd.lib;concrtd.lib;Winhttp.lib;Httpapi.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store\arm;$(OutDir);%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;msvcrt.lib;msvcprt.lib;concrt.lib;Winhttp.lib;Httpapi.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;msvcrt.lib;msvcprt.lib;concrt.lib;Winhttp.lib;Httpapi.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;msvcrt.lib;msvcprt.lib;concrt.lib;Winhttp.lib;Httpapi.lib;RuntimeObject.lib;%(AdditionalDependencies) - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj.filters b/Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj.filters deleted file mode 100644 index c965e9cb22..0000000000 --- a/Release/tests/functional/http/utilities/vs14.uwp/HttpTestUtilities140.uwp.vcxproj.filters +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {96f6b99e-76ae-4ace-801c-39bb8d308125} - - - {d4ba757b-dfdc-4d61-a9bd-19e957c5a09c} - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj b/Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj deleted file mode 100644 index d06012ad6d..0000000000 --- a/Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj +++ /dev/null @@ -1,218 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {6837625b-c0db-4fd0-aee2-19699031b76e} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\include;%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm140 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm140 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - Winhttp.lib;Httpapi.lib;%(AdditionalDependencies) - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj.filters b/Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj.filters deleted file mode 100644 index 1e583ce8ed..0000000000 --- a/Release/tests/functional/http/utilities/vs14/HttpTestUtilities140.vcxproj.filters +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - {d0052d1d-10e0-42da-9df6-72be473a8ebe} - - - {a4317631-da2e-4508-982f-e689f8d4a039} - - - \ No newline at end of file diff --git a/Release/tests/functional/json/CMakeLists.txt b/Release/tests/functional/json/CMakeLists.txt index 379a6bd4bf..1d44a99ce6 100644 --- a/Release/tests/functional/json/CMakeLists.txt +++ b/Release/tests/functional/json/CMakeLists.txt @@ -5,7 +5,6 @@ set(SOURCES to_as_and_operators_tests.cpp iterator_tests.cpp json_numbers_tests.cpp - stdafx.cpp ) if(NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) list(APPEND SOURCES fuzz_tests.cpp) @@ -16,3 +15,16 @@ if(UNIX AND NOT APPLE) cpprest_find_boost() target_link_libraries(json_test PRIVATE cpprestsdk_boost_internal) endif() + +if(MSVC) + get_target_property(_srcs json_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/json-tests-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/json-tests-stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpjson-tests-stdafx.pch") + target_sources(json_test PRIVATE stdafx.cpp) + target_compile_options(json_test PRIVATE /Yustdafx.h /Fpjson-tests-stdafx.pch) +endif() diff --git a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj deleted file mode 100644 index 16dd72d5bc..0000000000 --- a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - - - - {169555EF-8A80-405E-A815-CFE70028CA45} - Android - Android - 2.0 - JSON140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - JSON140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj.filters b/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj.filters deleted file mode 100644 index 9d4e307758..0000000000 --- a/Release/tests/functional/json/vs14.android/JSON140_test.android.vcxproj.filters +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - {ea88708b-1006-422c-b275-3f1394e595c8} - - - {9142d997-6ead-4b83-a03f-9e03e4da038d} - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj b/Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj deleted file mode 100644 index b2b05a4d50..0000000000 --- a/Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj +++ /dev/null @@ -1,128 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {D398DF71-8642-4BC4-940F-9AE2B0AE1CE4} - Windows Store - en-US - 14.0 - true - Unicode - v140 - DynamicLibrary - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - - Use - WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - false - false - stdafx.h - -Zm250 %(AdditionalOptions) - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj.filters b/Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj.filters deleted file mode 100644 index ae62883eba..0000000000 --- a/Release/tests/functional/json/vs14.uwp/JSON140_test.uwp.vcxproj.filters +++ /dev/null @@ -1,42 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {db714d7a-c017-4d4f-99ab-f1f195ba360c} - - - {3ea4dfd5-d8b3-4370-adda-ea04dcaf401b} - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj b/Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj deleted file mode 100644 index 6b4e8ee881..0000000000 --- a/Release/tests/functional/json/vs14.xp/JSON140_test.xp.vcxproj +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {ABA69F91-45D4-41D8-991A-10A6319E42C3} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath14) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - $(OutDir)%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs14/JSON140_test.vcxproj b/Release/tests/functional/json/vs14/JSON140_test.vcxproj deleted file mode 100644 index 58928de7d0..0000000000 --- a/Release/tests/functional/json/vs14/JSON140_test.vcxproj +++ /dev/null @@ -1,211 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {6f026328-4d10-4ef1-bd6c-8fd3cbe0f530} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - FastCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - FastCall - - - Console - true - $(OutDir)%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - FastCall - - - Console - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - FastCall - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - FastCall - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;COMMONTESTS_EXPORTS;%(PreprocessorDefinitions) - FastCall - - - Console - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/json/vs14/JSON140_test.vcxproj.filters b/Release/tests/functional/json/vs14/JSON140_test.vcxproj.filters deleted file mode 100644 index 9908627f9a..0000000000 --- a/Release/tests/functional/json/vs14/JSON140_test.vcxproj.filters +++ /dev/null @@ -1,47 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/misc/version/vs14/version140_test.vcxproj b/Release/tests/functional/misc/version/vs14/version140_test.vcxproj deleted file mode 100644 index f62231600c..0000000000 --- a/Release/tests/functional/misc/version/vs14/version140_test.vcxproj +++ /dev/null @@ -1,100 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {1263db26-9035-43c4-adab-a2c71ae92cce} - Win32Proj - version - SAK - SAK - SAK - SAK - version - - - - DynamicLibrary - Unicode - v140 - - - - - - - - - - - - - - NotUsing - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;HEADER_TEST_EXPORTS;%(PreprocessorDefinitions);_AFXDLL - $(CommonTestIncludeDir);$(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - MultiThreadedDebugDLL - - - Windows - true - - - - - - NotUsing - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HEADER_TEST_EXPORTS;%(PreprocessorDefinitions);_AFXDLL - $(CommonTestIncludeDir);$(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - MultiThreadedDLL - - - Windows - true - true - true - - - - - - _VER_MAJOR=$(CppRestSDKVersionMajor);_VER_MINOR=$(CppRestSDKVersionMinor);_VER_REVISION=$(CppRestSDKVersionRevision);%(PreprocessorDefinitions) - - - - - - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt index 01c56f7522..0e2672b73e 100644 --- a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt +++ b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt @@ -2,7 +2,19 @@ set(SOURCES pplx_op_test.cpp pplx_task_options.cpp pplxtask_tests.cpp - stdafx.cpp ) add_casablanca_test(pplx_test SOURCES) + +if(MSVC) + get_target_property(_srcs pplx_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/pplx-tests-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pplx-tests-stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fppplx-tests-stdafx.pch") + target_sources(pplx_test PRIVATE stdafx.cpp) + target_compile_options(pplx_test PRIVATE /Yustdafx.h /Fppplx-tests-stdafx.pch) +endif() diff --git a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj deleted file mode 100644 index 7fd3c7b631..0000000000 --- a/Release/tests/functional/pplx/pplx_test/vs14.android/pplx140_test.android.vcxproj +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - - - - {DF670B4E-692C-424E-BCFD-F63D34FE5CD3} - Android - Android - 2.0 - pplx140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - pplx140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/pplx/pplx_test/vs14.uwp/pplx140_test.uwp.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14.uwp/pplx140_test.uwp.vcxproj deleted file mode 100644 index b42ef70c16..0000000000 --- a/Release/tests/functional/pplx/pplx_test/vs14.uwp/pplx140_test.uwp.vcxproj +++ /dev/null @@ -1,130 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {23A43AC2-1E04-4589-B0A9-0295962755DC} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - en-US - 14.0 - true - DynamicLibrary - v140 - 10.0.10240.0 - 10.0.10240.0 - Unicode - - - - true - - - false - true - - - - - - - Use - WIN32;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - /bigobj %(AdditionalOptions) - true - false - stdafx.h - - - Windows - true - CommonUtilities140.uwp.lib;%(AdditionalDependencies) - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj deleted file mode 100644 index bedd4efee8..0000000000 --- a/Release/tests/functional/pplx/pplx_test/vs14.xp/pplx140_test.xp.vcxproj +++ /dev/null @@ -1,158 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {EB4A3750-CA93-4968-89D7-3ED467DB2C59} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath14) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Level4 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level4 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level4 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level4 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - {75885703-7F3D-4086-8E60-C60B9B126F7E} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/pplx/pplx_test/vs14/pplx140_test.vcxproj b/Release/tests/functional/pplx/pplx_test/vs14/pplx140_test.vcxproj deleted file mode 100644 index 95c586743b..0000000000 --- a/Release/tests/functional/pplx/pplx_test/vs14/pplx140_test.vcxproj +++ /dev/null @@ -1,212 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {06F8344D-4EBA-4B9F-A209-5FCEFA9D62EB} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Level3 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/CMakeLists.txt b/Release/tests/functional/streams/CMakeLists.txt index 4b11173b18..29d09bbac8 100644 --- a/Release/tests/functional/streams/CMakeLists.txt +++ b/Release/tests/functional/streams/CMakeLists.txt @@ -4,7 +4,6 @@ set(SOURCES memstream_tests.cpp ostream_tests.cpp stdstream_tests.cpp - stdafx.cpp ) if(WINDOWS_STORE OR WINDOWS_PHONE) list(APPEND SOURCES winrt_interop_tests.cpp) @@ -24,3 +23,16 @@ if(NOT WIN32 OR CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") target_include_directories(streams_test PRIVATE $) endif() endif() + +if(MSVC) + get_target_property(_srcs streams_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/streams-tests-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/streams-tests-stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpstreams-tests-stdafx.pch") + target_sources(streams_test PRIVATE stdafx.cpp) + target_compile_options(streams_test PRIVATE /Yustdafx.h /Fpstreams-tests-stdafx.pch) +endif() diff --git a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj deleted file mode 100644 index 81ff3ad878..0000000000 --- a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - - - - {B9DA540F-95F7-485E-ADF4-C94A17BFA1EB} - Android - Android - 2.0 - streams140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - streams140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj.filters b/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj.filters deleted file mode 100644 index 2288fd4da5..0000000000 --- a/Release/tests/functional/streams/vs14.android/streams140_test.android.vcxproj.filters +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - {086f8ce7-3abe-46b1-a418-069737cb878b} - - - {5a4e8b16-a7c4-439b-afb3-c4a50dbfb681} - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj b/Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj deleted file mode 100644 index 11b8c9404d..0000000000 --- a/Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj +++ /dev/null @@ -1,137 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {B4C6E439-20F9-406C-9586-792FB5B073C2} - Win32Proj - SAK - SAK - SAK - SAK - en-US - 14.0 - true - v140 - DynamicLibrary - e13f21ed - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - - Use - WIN32;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - /bigobj %(AdditionalOptions) - true - false - stdafx.h - -Zm160 %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj.filters b/Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj.filters deleted file mode 100644 index 86b36e3575..0000000000 --- a/Release/tests/functional/streams/vs14.uwp/streams140_test.uwp.vcxproj.filters +++ /dev/null @@ -1,45 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {274676f3-573c-4a10-adbb-0421159c8a2a} - - - {dd303bf1-0c87-4079-a035-c16d23cf129d} - - - - - Header Files - - - Header Files - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj b/Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj deleted file mode 100644 index cdd4ff6820..0000000000 --- a/Release/tests/functional/streams/vs14.xp/streams140_test.xp.vcxproj +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {F279F1ED-8AFF-478D-9A20-DDCAD8CBA336} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath14) - 2276c549 - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs14/streams140_test.vcxproj b/Release/tests/functional/streams/vs14/streams140_test.vcxproj deleted file mode 100644 index 07520fe5ac..0000000000 --- a/Release/tests/functional/streams/vs14/streams140_test.vcxproj +++ /dev/null @@ -1,219 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {181ccb80-9ae8-4ed7-8b7d-4c0cbc80eedd} - Win32Proj - HttpTests - SAK - SAK - SAK - SAK - $(VCTargetsPath12) - 84fd5b75 - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - ARM;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - ARM;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTPTESTS_EXPORTS;%(PreprocessorDefinitions) - /bigobj %(AdditionalOptions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/streams/vs14/streams140_test.vcxproj.filters b/Release/tests/functional/streams/vs14/streams140_test.vcxproj.filters deleted file mode 100644 index fec2efca0f..0000000000 --- a/Release/tests/functional/streams/vs14/streams140_test.vcxproj.filters +++ /dev/null @@ -1,43 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - - {1de3a9ce-57af-48bd-8125-3af4f406be26} - - - {3c2936bc-8d1e-4a33-96c9-5cfb3d83b30d} - - - - - Header Files - - - Header Files - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/CMakeLists.txt b/Release/tests/functional/uri/CMakeLists.txt index 54d80ac254..e3f7de1da2 100644 --- a/Release/tests/functional/uri/CMakeLists.txt +++ b/Release/tests/functional/uri/CMakeLists.txt @@ -9,7 +9,19 @@ set(SOURCES splitting_tests.cpp uri_builder_tests.cpp resolve_uri_tests.cpp - stdafx.cpp ) add_casablanca_test(uri_test SOURCES) + +if(MSVC) + get_target_property(_srcs uri_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/uri-tests-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/uri-tests-stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpuri-tests-stdafx.pch") + target_sources(uri_test PRIVATE stdafx.cpp) + target_compile_options(uri_test PRIVATE /Yustdafx.h /Fpuri-tests-stdafx.pch) +endif() diff --git a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj deleted file mode 100644 index bf66be6210..0000000000 --- a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - - - - {63569C1A-A168-442A-B160-76D0256803AF} - Android - Android - 2.0 - Uri140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - Uri140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj.filters b/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj.filters deleted file mode 100644 index ca869127a3..0000000000 --- a/Release/tests/functional/uri/vs14.android/Uri140_test.android.vcxproj.filters +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - {2a91a18a-e13e-4f80-8066-55d069396647} - - - {9ee2024f-1bd0-452f-bdf2-14f9dd9998d1} - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/vs14.uwp/URI140_test.uwp.vcxproj.filters b/Release/tests/functional/uri/vs14.uwp/URI140_test.uwp.vcxproj.filters deleted file mode 100644 index fd4f136ea8..0000000000 --- a/Release/tests/functional/uri/vs14.uwp/URI140_test.uwp.vcxproj.filters +++ /dev/null @@ -1,57 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {e30fa8ae-3cb4-4a63-870b-a7e85088a9ad} - - - {e7f8af98-2e23-4c57-93e1-2936a3f0ac84} - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/vs14.uwp/Uri140_test.uwp.vcxproj b/Release/tests/functional/uri/vs14.uwp/Uri140_test.uwp.vcxproj deleted file mode 100644 index 3225698298..0000000000 --- a/Release/tests/functional/uri/vs14.uwp/Uri140_test.uwp.vcxproj +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {9169C20C-B98A-46C6-A138-A107C458E8DD} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 14.0 - true - DynamicLibrary - Unicode - v140 - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - - Use - WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - true - false - stdafx.h - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - - - - diff --git a/Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj b/Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj deleted file mode 100644 index 988d387b15..0000000000 --- a/Release/tests/functional/uri/vs14.xp/Uri140_test.xp.vcxproj +++ /dev/null @@ -1,155 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {66B6D1E2-A91C-4DA3-8568-B7457FA7ED6D} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath14) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/vs14/Uri140_test.vcxproj b/Release/tests/functional/uri/vs14/Uri140_test.vcxproj deleted file mode 100644 index c7758a2a41..0000000000 --- a/Release/tests/functional/uri/vs14/Uri140_test.vcxproj +++ /dev/null @@ -1,212 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {3d9c3f25-1736-4d39-a31f-6b2de34e20cf} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/uri/vs14/Uri140_test.vcxproj.filters b/Release/tests/functional/uri/vs14/Uri140_test.vcxproj.filters deleted file mode 100644 index a05e44e9f0..0000000000 --- a/Release/tests/functional/uri/vs14/Uri140_test.vcxproj.filters +++ /dev/null @@ -1,53 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/CMakeLists.txt b/Release/tests/functional/utils/CMakeLists.txt index ff175283f8..201af77039 100644 --- a/Release/tests/functional/utils/CMakeLists.txt +++ b/Release/tests/functional/utils/CMakeLists.txt @@ -5,7 +5,6 @@ set(SOURCES macro_test.cpp nonce_generator_tests.cpp win32_encryption_tests.cpp - stdafx.cpp ) add_casablanca_test(utils_test SOURCES) @@ -13,3 +12,16 @@ add_casablanca_test(utils_test SOURCES) if(CMAKE_COMPILER_IS_GNUCXX) target_compile_options(utils_test PRIVATE "-Wno-deprecated-declarations") endif() + +if(MSVC) + get_target_property(_srcs utils_test SOURCES) + + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/utils-tests-stdafx.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/utils-tests-stdafx.pch") + endif() + + set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fputils-tests-stdafx.pch") + target_sources(utils_test PRIVATE stdafx.cpp) + target_compile_options(utils_test PRIVATE /Yustdafx.h /Fputils-tests-stdafx.pch) +endif() diff --git a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj deleted file mode 100644 index 3bffb9f385..0000000000 --- a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - - - - {423FCE6D-7400-4C09-9038-4438FBB089D4} - Android - Android - 2.0 - Utils140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - Utils140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj.filters b/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj.filters deleted file mode 100644 index 72c7afdac7..0000000000 --- a/Release/tests/functional/utils/vs14.android/Utils140_test.android.vcxproj.filters +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - {22ca4c16-d08f-4f8d-9a72-1177da20c0e9} - - - {c59c025e-d09f-4eff-8553-3ec14490cdc0} - - - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj b/Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj deleted file mode 100644 index e02821bda3..0000000000 --- a/Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj +++ /dev/null @@ -1,131 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {4fddc511-5cfd-48a0-b373-43b13a43fb45} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 14.0 - true - Unicode - v140 - DynamicLibrary - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - - Use - WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir) - true - false - stdafx.h - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - - - - - - - - diff --git a/Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj.filters b/Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj.filters deleted file mode 100644 index a2199f62fb..0000000000 --- a/Release/tests/functional/utils/vs14.uwp/Utils140_test.uwp.vcxproj.filters +++ /dev/null @@ -1,36 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - {e30fa8ae-3cb4-4a63-870b-a7e85088a9ad} - - - {e7f8af98-2e23-4c57-93e1-2936a3f0ac84} - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj b/Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj deleted file mode 100644 index 45ee435b2b..0000000000 --- a/Release/tests/functional/utils/vs14.xp/Utils140_test.xp.vcxproj +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {E9E26CDB-4CE3-4B0E-AAF8-D32F57E48856} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath14) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5ad81270-b089-4e1b-8741-6486f39de273} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/vs14/Utils140_test.vcxproj b/Release/tests/functional/utils/vs14/Utils140_test.vcxproj deleted file mode 100644 index 37cd0326f0..0000000000 --- a/Release/tests/functional/utils/vs14/Utils140_test.vcxproj +++ /dev/null @@ -1,208 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {50386698-0180-4ebc-8827-f2c36561f6b4} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - $(CasablancaIncludeDir);$(CommonTestIncludeDir);%(AdditionalIncludeDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - StdCall - - - Windows - true - true - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3EB86C0D-432C-4FFC-BAD4-8DF4EFC7D0FF} - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/utils/vs14/Utils140_test.vcxproj.filters b/Release/tests/functional/utils/vs14/Utils140_test.vcxproj.filters deleted file mode 100644 index dfa7b86991..0000000000 --- a/Release/tests/functional/utils/vs14/Utils140_test.vcxproj.filters +++ /dev/null @@ -1,38 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj b/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj deleted file mode 100644 index 230810860b..0000000000 --- a/Release/tests/functional/websockets/client/vs14.android/websocketsclient140_test.android.vcxproj +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - {0149e1c2-fbf3-48b6-9996-d6753f689dfb} - - - - {3E8466B1-7CBC-489D-8E6B-5E45BAB4D627} - Android - Android - 2.0 - websocketsclient140_test.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(TestRoot)\functional\websockets\utilities;%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);$(TestRoot)\functional\websockets\utilities;%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(TestRoot)\functional\websockets\utilities;%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(TestRoot)\functional\websockets\utilities;%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - websocketsclient140_test.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/websockets/client/vs14.uwp/websocketsclient140_test.uwp.vcxproj b/Release/tests/functional/websockets/client/vs14.uwp/websocketsclient140_test.uwp.vcxproj deleted file mode 100644 index 17ba6a3ffb..0000000000 --- a/Release/tests/functional/websockets/client/vs14.uwp/websocketsclient140_test.uwp.vcxproj +++ /dev/null @@ -1,127 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {CE900295-F777-446C-8954-894891F0A9D4} - SAK - SAK - SAK - SAK - en-US - 14.0 - true - DynamicLibrary - Unicode - v140 - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - - Use - WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities; - true - false - stdafx.h - - - Windows - true - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - -Zm200 %(AdditionalOptions) - - - true - true - - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - {D452C5CF-681B-4B64-B3A9-A916E842988F} - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj b/Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj deleted file mode 100644 index 9791f3d90c..0000000000 --- a/Release/tests/functional/websockets/client/vs14.xp/websocketsclient140_test.xp.vcxproj +++ /dev/null @@ -1,123 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - WebsocketTests - SAK - SAK - SAK - SAK - websocketsclient140_test.xp - {BBE711C0-568C-48E5-A9EB-2F3741D0687B} - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities;%(AdditionalIncludeDirectories) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Disabled - CPPREST_TARGET_XP;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - - - MaxSpeed - true - true - CPPREST_TARGET_XP;WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - true - true - - - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - - - {3803246A-F31E-44EC-BCA9-87DF68C5EB8D} - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - diff --git a/Release/tests/functional/websockets/client/vs14/websocketsclient140_test.vcxproj b/Release/tests/functional/websockets/client/vs14/websocketsclient140_test.vcxproj deleted file mode 100644 index 9d23e7da8a..0000000000 --- a/Release/tests/functional/websockets/client/vs14/websocketsclient140_test.vcxproj +++ /dev/null @@ -1,125 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {9A23F9D2-4876-423B-9393-A604764601B0} - WebsocketTests - SAK - SAK - SAK - SAK - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);..\..\utilities;%(AdditionalIncludeDirectories) - -Zm200 %(AdditionalOptions) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - - - true - true - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {14f7b7a0-a057-4e15-8ec4-12baf00b0f64} - - - - - - - - - - - - - - - - Create - Create - Create - Create - Create - Create - - - - - - diff --git a/Release/tests/functional/websockets/utilities/vs14.android/packages.config b/Release/tests/functional/websockets/utilities/vs14.android/packages.config deleted file mode 100644 index 4bd0fd80ad..0000000000 --- a/Release/tests/functional/websockets/utilities/vs14.android/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj b/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj deleted file mode 100644 index 3962040a52..0000000000 --- a/Release/tests/functional/websockets/utilities/vs14.android/websockets_test_utilities140.android.vcxproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - Debug - ARM - - - Debug - x86 - - - Release - ARM - - - Release - x86 - - - - - Create - Create - Create - Create - - - - - - - - - - - - - {7c4e6e33-42e2-4472-9319-dde7564f3dae} - - - - {0149E1C2-FBF3-48B6-9996-D6753F689DFB} - Android - Android - 2.0 - websockets_test_utilities140.android - - - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - true - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - StaticLibrary - false - Clang_3_8 - gnustl_static - - - - - - 378b82c3 - - - - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - Enabled - c++11 - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);$(StlIncludeDirectories);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-arm\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - - EnableAllWarnings - $(NDKRoot)\platforms\$(AndroidAPILevel)\arch-x86\usr\include;$(StlIncludeDirectories);$(CasablancaIncludeDir);$(TestRoot)\functional\http\utilities\include;$(CommonTestIncludeDir);$(CasablancaSrcDir)\pch;$(WebsocketppIncludeDir);%(AdditionalIncludeDirectories) - c++11 - Enabled - true - true - -funwind-tables -Wno-unused-local-typedef %(AdditionalOptions) - - - - d - - - websockets_test_utilities140.android - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - diff --git a/Release/tests/functional/websockets/utilities/vs14.uwp/packages.config b/Release/tests/functional/websockets/utilities/vs14.uwp/packages.config deleted file mode 100644 index 7438d474dd..0000000000 --- a/Release/tests/functional/websockets/utilities/vs14.uwp/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs14.uwp/websockets_test_utilities140.uwp.vcxproj b/Release/tests/functional/websockets/utilities/vs14.uwp/websockets_test_utilities140.uwp.vcxproj deleted file mode 100644 index 71c92e1697..0000000000 --- a/Release/tests/functional/websockets/utilities/vs14.uwp/websockets_test_utilities140.uwp.vcxproj +++ /dev/null @@ -1,147 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {D452C5CF-681B-4B64-B3A9-A916E842988F} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 14.0 - Unicode - v140 - DynamicLibrary - Windows Store - 10.0.10240.0 - 10.0.10240.0 - - - - true - - - false - true - - - - - - Use - WIN32;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);..\include - $(WindowsSdkDir)\UnionMetadata;$(VSInstallDir)\vc\vcpackages;$(AdditionalUsingDirectories) - -Zm200 %(AdditionalOptions) - true - false - stdafx.h - - - Windows - true - true - CommonUtilities140.uwp.lib;Ws2_32.lib;Mswsock.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;msvcrtd.lib;msvcprtd.lib;concrtd.lib;RuntimeObject.lib;libboost_system-vc140-mt-gd-1_58.lib;%(AdditionalDependencies) - - - - - Disabled - _DEBUG;%(PreprocessorDefinitions) - - - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - ucrtd.lib;vcruntimed.lib;vccorlibd.lib;msvcrtd.lib;msvcprtd.lib;concrtd.lib;RuntimeObject.lib;libboost_system-vc140-mt-gd-1_58.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store;$(OutDir);%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;msvcrt.lib;msvcprt.lib;concrt.lib;RuntimeObject.lib;libboost_system-vc140-mt-1_58.lib;%(AdditionalDependencies) - - - - - MaxSpeed - true - true - NDEBUG;%(PreprocessorDefinitions) - - - true - true - $(VCINSTALLDIR)\lib\store\amd64;$(OutDir);%(AdditionalLibraryDirectories); - ucrt.lib;vcruntime.lib;vccorlib.lib;msvcrt.lib;msvcprt.lib;concrt.lib;RuntimeObject.lib;libboost_system-vc140-mt-1_58.lib;%(AdditionalDependencies) - - - - - {DA089EAD-00A2-43CF-9954-DF01E8ED5E94} - - - {04214181-57D7-45F5-8499-1A5530CE6CBF} - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj b/Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj deleted file mode 100644 index c1410e701a..0000000000 --- a/Release/tests/functional/websockets/utilities/vs14.xp/websockets_test_utilities140.xp.vcxproj +++ /dev/null @@ -1,132 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - SAK - SAK - SAK - SAK - Win32Proj - en-US - 11.0 - tests::common::websockets_test_utilities - websockets_test_utilities140.xp - {3803246A-F31E-44EC-BCA9-87DF68C5EB8D} - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories) - - - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - 4503;%(DisableSpecificWarnings) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - true - true - - - - - - Create - Create - Create - Create - - - - - - - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {75885703-7f3d-4086-8e60-c60b9b126f7e} - - - {5AD81270-B089-4E1B-8741-6486F39DE273} - - - - - - - - - - - - - diff --git a/Release/tests/functional/websockets/utilities/vs14/packages.config b/Release/tests/functional/websockets/utilities/vs14/packages.config deleted file mode 100644 index 7438d474dd..0000000000 --- a/Release/tests/functional/websockets/utilities/vs14/packages.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Release/tests/functional/websockets/utilities/vs14/websockets_test_utilities140.vcxproj b/Release/tests/functional/websockets/utilities/vs14/websockets_test_utilities140.vcxproj deleted file mode 100644 index 23eb5b26c3..0000000000 --- a/Release/tests/functional/websockets/utilities/vs14/websockets_test_utilities140.vcxproj +++ /dev/null @@ -1,151 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {14F7B7A0-A057-4E15-8EC4-12BAF00B0F64} - SAK - SAK - SAK - SAK - Win32Proj - en-US - 11.0 - tests::common::websockets_test_utilities - websockets_test_utilities140 - - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - DynamicLibrary - false - true - Unicode - v140 - - - - - - - Use - $(CasablancaIncludeDir);$(CommonTestIncludeDir);$(WebsocketppIncludeDir);$(TestRoot)\Common\UnitTestpp\src\;%(AdditionalIncludeDirectories) - 4503;%(DisableSpecificWarnings) - -Zm200 /bigobj %(AdditionalOptions) - - - Windows - $(OutDir);%(AdditionalLibraryDirectories) - - - - - - Disabled - _DEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - - - MaxSpeed - true - true - NDEBUG;_WINDOWS;_USRDLL;WEBSOCKETTESTUTILITY_EXPORTS;%(PreprocessorDefinitions) - - - true - true - - - - - - Create - Create - Create - Create - Create - Create - - - - - - - - - {0c9d50d9-94fb-4732-a4ad-58e068315bb2} - - - {3eb86c0d-432c-4ffc-bad4-8df4efc7d0ff} - - - {90D85FF4-F0AE-4816-923F-0EF2758F30AB} - - - - - - - - - - - - - diff --git a/build.root b/build.root deleted file mode 100644 index d423a1a70c..0000000000 --- a/build.root +++ /dev/null @@ -1 +0,0 @@ -Marker file indicating root of build system. diff --git a/cpprestsdk140.sln b/cpprestsdk140.sln deleted file mode 100644 index 4a9087e936..0000000000 --- a/cpprestsdk140.sln +++ /dev/null @@ -1,292 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140", "Release\src\build\vs14\casablanca140.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "Release\src\build\common.vcxitems", "{594DCB5F-07E3-4084-A2CE-268611FA629F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "other", "Release\src\build\other.vcxitems", "{3D5908F7-7673-4229-BC46-2007A7AF9CAE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32", "Release\src\build\win32.vcxitems", "{F40F4804-50F9-4257-8D74-B9CBB19AC4C3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrt", "Release\src\build\winrt.vcxitems", "{0A9BA181-7876-4B3D-A5E0-EE673FA51C05}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{64F2F240-04BE-43B2-97BE-DA47FDFE8393}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B572F8D5-9728-409C-AB5E-063C7D3CA781}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BingRequest", "BingRequest", "{00EF03C1-74A9-4832-B26B-E6478C2A96AC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BlackJack", "BlackJack", "{B6F7411C-FE75-4CD2-A384-083A526FE6DF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CasaLens", "CasaLens", "{76FA5645-FF99-44C0-87DB-B96AFAC2F800}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SearchFile", "SearchFile", "{22309B46-EE6F-45D0-A993-2F45D98DEF22}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest140", "Release\samples\BingRequest\BingRequest140\BingRequest140.vcxproj", "{2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Client", "Client", "{8E54A174-9108-45BF-8080-92A916C43A54}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{DADA0A65-A970-4114-8F9C-EA3327F90712}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Client140", "Release\samples\BlackJack\BlackJack_Client\BlackJack_Client140\BlackJack_Client140.vcxproj", "{830B6E2F-9224-41D1-B9C7-A51FC78B00C7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Server140", "Release\samples\BlackJack\BlackJack_Server\BlackJack_Server140\BlackJack_Server140.vcxproj", "{84350CD1-D406-4A4F-9571-261CA46D77C5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CasaLens140", "Release\samples\CasaLens\CasaLens140\CasaLens140.vcxproj", "{FFBFD6C1-B525-4D35-AB64-A2FE9460B147}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile140", "Release\samples\SearchFile\SearchFile140\SearchFile140.vcxproj", "{F03BEE03-BEFB-4B17-A774-D9C8246530D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.android", "Release\src\build\vs14.android\casablanca140.android.vcxproj", "{AFB49019-965B-4C10-BAFF-C86C16D58010}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.vcxproj", "{36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.uwp.staticlib", "Release\src\build\vs14.uwp\cpprestsdk140.uwp.staticlib.vcxproj", "{47A5CFDC-C244-45A6-9830-38CB303CB495}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.static", "Release\src\build\vs14.static\casablanca140.static.vcxproj", "{79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprestsdk140.xp", "Release\src\build\vs14.xp\casablanca140.xp.vcxproj", "{39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest140.xp", "Release\samples\BingRequest\BingRequest140.xp\BingRequest140.xp.vcxproj", "{7009BCBE-D67C-4B54-BEFC-A44E62656CF1}" -EndProject -Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 - Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\winrt.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{47a5cfdc-c244-45a6-9830-38cb303cb495}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 - Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{79c9bbec-d7c9-4ba3-b2b3-5c3a14a9f24a}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{39f7e851-7ef8-4dfb-9907-b480cb8d2ac9}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 - Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|ARM.ActiveCfg = Debug|ARM - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|Win32.ActiveCfg = Debug|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|Win32.Build.0 = Debug|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.ActiveCfg = Debug|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.Build.0 = Debug|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.ActiveCfg = Debug|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.Build.0 = Debug|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|ARM.ActiveCfg = Release|ARM - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|Win32.ActiveCfg = Release|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|Win32.Build.0 = Release|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.ActiveCfg = Release|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.Build.0 = Release|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.ActiveCfg = Release|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.Build.0 = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|ARM.ActiveCfg = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.ActiveCfg = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|Win32.Build.0 = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.ActiveCfg = Debug|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.Build.0 = Debug|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.ActiveCfg = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.Build.0 = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|ARM.ActiveCfg = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.ActiveCfg = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|Win32.Build.0 = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.ActiveCfg = Release|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.Build.0 = Release|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.ActiveCfg = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.Build.0 = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|ARM.ActiveCfg = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.ActiveCfg = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|Win32.Build.0 = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.ActiveCfg = Debug|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.Build.0 = Debug|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.ActiveCfg = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.Build.0 = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|ARM.ActiveCfg = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.ActiveCfg = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|Win32.Build.0 = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.ActiveCfg = Release|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.Build.0 = Release|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.ActiveCfg = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.Build.0 = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|ARM.ActiveCfg = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.ActiveCfg = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|Win32.Build.0 = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.ActiveCfg = Debug|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.Build.0 = Debug|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.ActiveCfg = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.Build.0 = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|ARM.ActiveCfg = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.ActiveCfg = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|Win32.Build.0 = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.ActiveCfg = Release|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.Build.0 = Release|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.ActiveCfg = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.Build.0 = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|ARM.ActiveCfg = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.ActiveCfg = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|Win32.Build.0 = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.ActiveCfg = Debug|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.Build.0 = Debug|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.ActiveCfg = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.Build.0 = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|ARM.ActiveCfg = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.ActiveCfg = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|Win32.Build.0 = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.ActiveCfg = Release|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.Build.0 = Release|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.ActiveCfg = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.Build.0 = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|ARM.ActiveCfg = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.ActiveCfg = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|Win32.Build.0 = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.ActiveCfg = Debug|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.Build.0 = Debug|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.ActiveCfg = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.Build.0 = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|ARM.ActiveCfg = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.ActiveCfg = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|Win32.Build.0 = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.ActiveCfg = Release|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.Build.0 = Release|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.ActiveCfg = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.Build.0 = Release|Win32 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.ActiveCfg = Debug|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.Build.0 = Debug|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|Win32.ActiveCfg = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|Win32.Build.0 = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x64.ActiveCfg = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.ActiveCfg = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.Build.0 = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.ActiveCfg = Release|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.Build.0 = Release|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|Win32.ActiveCfg = Release|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|Win32.Build.0 = Release|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x64.ActiveCfg = Release|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.ActiveCfg = Release|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.Build.0 = Release|x86 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.ActiveCfg = Debug|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.Build.0 = Debug|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|Win32.ActiveCfg = Debug|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|Win32.Build.0 = Debug|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.ActiveCfg = Debug|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.Build.0 = Debug|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.ActiveCfg = Debug|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.Build.0 = Debug|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.ActiveCfg = Release|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.Build.0 = Release|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|Win32.ActiveCfg = Release|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|Win32.Build.0 = Release|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.ActiveCfg = Release|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.Build.0 = Release|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.ActiveCfg = Release|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.Build.0 = Release|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|ARM.ActiveCfg = Debug|ARM - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|ARM.Build.0 = Debug|ARM - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|Win32.ActiveCfg = Debug|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|Win32.Build.0 = Debug|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x64.ActiveCfg = Debug|x64 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x64.Build.0 = Debug|x64 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x86.ActiveCfg = Debug|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Debug|x86.Build.0 = Debug|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|ARM.ActiveCfg = Release|ARM - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|ARM.Build.0 = Release|ARM - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|Win32.ActiveCfg = Release|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|Win32.Build.0 = Release|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x64.ActiveCfg = Release|x64 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x64.Build.0 = Release|x64 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.ActiveCfg = Release|Win32 - {47A5CFDC-C244-45A6-9830-38CB303CB495}.Release|x86.Build.0 = Release|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.ActiveCfg = Debug|ARM - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|ARM.Build.0 = Debug|ARM - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|Win32.ActiveCfg = Debug|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|Win32.Build.0 = Debug|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x64.ActiveCfg = Debug|x64 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x64.Build.0 = Debug|x64 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x86.ActiveCfg = Debug|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Debug|x86.Build.0 = Debug|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|ARM.ActiveCfg = Release|ARM - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|ARM.Build.0 = Release|ARM - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|Win32.ActiveCfg = Release|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|Win32.Build.0 = Release|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x64.ActiveCfg = Release|x64 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x64.Build.0 = Release|x64 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x86.ActiveCfg = Release|Win32 - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A}.Release|x86.Build.0 = Release|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|ARM.ActiveCfg = Debug|ARM - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|ARM.Build.0 = Debug|ARM - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|Win32.ActiveCfg = Debug|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|Win32.Build.0 = Debug|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x64.ActiveCfg = Debug|x64 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x64.Build.0 = Debug|x64 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x86.ActiveCfg = Debug|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Debug|x86.Build.0 = Debug|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|ARM.ActiveCfg = Release|ARM - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|ARM.Build.0 = Release|ARM - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|Win32.ActiveCfg = Release|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|Win32.Build.0 = Release|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x64.ActiveCfg = Release|x64 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x64.Build.0 = Release|x64 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x86.ActiveCfg = Release|Win32 - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9}.Release|x86.Build.0 = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|ARM.ActiveCfg = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.ActiveCfg = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|Win32.Build.0 = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.ActiveCfg = Debug|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x64.Build.0 = Debug|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x86.ActiveCfg = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Debug|x86.Build.0 = Debug|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|ARM.ActiveCfg = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.ActiveCfg = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|Win32.Build.0 = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.ActiveCfg = Release|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x64.Build.0 = Release|x64 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.ActiveCfg = Release|Win32 - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {65951C40-A332-4B54-89C2-7CDAF30D5F66} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {594DCB5F-07E3-4084-A2CE-268611FA629F} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {3D5908F7-7673-4229-BC46-2007A7AF9CAE} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {F40F4804-50F9-4257-8D74-B9CBB19AC4C3} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {0A9BA181-7876-4B3D-A5E0-EE673FA51C05} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {00EF03C1-74A9-4832-B26B-E6478C2A96AC} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} - {B6F7411C-FE75-4CD2-A384-083A526FE6DF} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} - {76FA5645-FF99-44C0-87DB-B96AFAC2F800} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} - {22309B46-EE6F-45D0-A993-2F45D98DEF22} = {B572F8D5-9728-409C-AB5E-063C7D3CA781} - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} = {00EF03C1-74A9-4832-B26B-E6478C2A96AC} - {8E54A174-9108-45BF-8080-92A916C43A54} = {B6F7411C-FE75-4CD2-A384-083A526FE6DF} - {DADA0A65-A970-4114-8F9C-EA3327F90712} = {B6F7411C-FE75-4CD2-A384-083A526FE6DF} - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7} = {8E54A174-9108-45BF-8080-92A916C43A54} - {84350CD1-D406-4A4F-9571-261CA46D77C5} = {DADA0A65-A970-4114-8F9C-EA3327F90712} - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} = {76FA5645-FF99-44C0-87DB-B96AFAC2F800} - {F03BEE03-BEFB-4B17-A774-D9C8246530D4} = {22309B46-EE6F-45D0-A993-2F45D98DEF22} - {AFB49019-965B-4C10-BAFF-C86C16D58010} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {47A5CFDC-C244-45A6-9830-38CB303CB495} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {79C9BBEC-D7C9-4BA3-B2B3-5C3A14A9F24A} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {39F7E851-7EF8-4DFB-9907-B480CB8D2AC9} = {64F2F240-04BE-43B2-97BE-DA47FDFE8393} - {7009BCBE-D67C-4B54-BEFC-A44E62656CF1} = {00EF03C1-74A9-4832-B26B-E6478C2A96AC} - EndGlobalSection -EndGlobal diff --git a/cpprestsdk141.sln b/cpprestsdk141.sln deleted file mode 100644 index f4ed2d2d51..0000000000 --- a/cpprestsdk141.sln +++ /dev/null @@ -1,258 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27018.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android", "Release\src\build\android.vcxitems", "{65951C40-A332-4B54-89C2-7CDAF30D5F66}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "Release\src\build\common.vcxitems", "{594DCB5F-07E3-4084-A2CE-268611FA629F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "other", "Release\src\build\other.vcxitems", "{3D5908F7-7673-4229-BC46-2007A7AF9CAE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32", "Release\src\build\win32.vcxitems", "{F40F4804-50F9-4257-8D74-B9CBB19AC4C3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winrt", "Release\src\build\winrt.vcxitems", "{0A9BA181-7876-4B3D-A5E0-EE673FA51C05}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{92944FCF-7E50-41FD-8A99-DD6869F9AEA5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprest141", "Release\src\build\vs141\cpprest141.vcxproj", "{1014C621-BC2D-4813-B8C1-6D83AD6F9249}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprest141.uwp", "Release\src\build\vs141.uwp\cpprest141.uwp.vcxproj", "{36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{EF775754-D70A-4611-A00C-F49F224FD236}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SearchFile141", "Release\samples\SearchFile\SearchFile141\SearchFile141.vcxproj", "{F03BEE03-BEFB-4B17-A774-D9C8246530D4}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OAuth2Live141", "Release\samples\OAuth2Live\OAuth2Live141.vcxproj", "{2887A786-B818-4B3D-94EF-21EFD6AFDC22}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Oauth2Client141", "Release\samples\Oauth2Client\Oauth2Client141\Oauth2Client141.vcxproj", "{35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Oauth1Client141", "Release\samples\Oauth1Client\Oauth1Client141\Oauth1Client141.vcxproj", "{850CCB95-CFA8-4E41-9D1D-387C0C186740}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FacebookDemo141", "Release\samples\FacebookDemo\FacebookDemo141.vcxproj", "{43DE4DF3-ACAA-429E-B260-CC6D4FE82658}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CasaLens141", "Release\samples\CasaLens\CasaLens141\CasaLens141.vcxproj", "{FFBFD6C1-B525-4D35-AB64-A2FE9460B147}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_UIClient141", "Release\samples\BlackJack\BlackJack_UIClient\BlackJack_UIClient141.vcxproj", "{B8D3F85B-DA71-4ACA-87BA-10FED681DC79}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Server141", "Release\samples\BlackJack\BlackJack_Server\BlackJack_Server141\BlackJack_Server141.vcxproj", "{84350CD1-D406-4A4F-9571-261CA46D77C5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlackJack_Client141", "Release\samples\BlackJack\BlackJack_Client\BlackJack_Client141\BlackJack_Client141.vcxproj", "{830B6E2F-9224-41D1-B9C7-A51FC78B00C7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BingRequest141", "Release\samples\BingRequest\BingRequest141\BingRequest141.vcxproj", "{2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpprest141.android", "Release\src\build\vs141.android\cpprest141.android.vcxproj", "{AFB49019-965B-4C10-BAFF-C86C16D58010}" -EndProject -Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - Release\src\build\winrt.vcxitems*{0a9ba181-7876-4b3d-a5e0-ee673fa51c05}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{1014c621-bc2d-4813-b8c1-6d83ad6f9249}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 - Release\src\build\winrt.vcxitems*{36d79e79-7e9e-4b3a-88a3-9f9b295c80b9}*SharedItemsImports = 4 - Release\src\build\other.vcxitems*{3d5908f7-7673-4229-bc46-2007a7af9cae}*SharedItemsImports = 9 - Release\src\build\common.vcxitems*{594dcb5f-07e3-4084-a2ce-268611fa629f}*SharedItemsImports = 9 - Release\src\build\android.vcxitems*{65951c40-a332-4b54-89c2-7cdaf30d5f66}*SharedItemsImports = 9 - Release\src\build\android.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 - Release\src\build\common.vcxitems*{afb49019-965b-4c10-baff-c86c16d58010}*SharedItemsImports = 4 - Release\src\build\win32.vcxitems*{f40f4804-50f9-4257-8d74-b9cbb19ac4c3}*SharedItemsImports = 9 - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|ARM.ActiveCfg = Debug|ARM - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|ARM.Build.0 = Debug|ARM - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.ActiveCfg = Debug|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x64.Build.0 = Debug|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.ActiveCfg = Debug|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Debug|x86.Build.0 = Debug|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|ARM.ActiveCfg = Release|ARM - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|ARM.Build.0 = Release|ARM - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.ActiveCfg = Release|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x64.Build.0 = Release|x64 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.ActiveCfg = Release|Win32 - {1014C621-BC2D-4813-B8C1-6D83AD6F9249}.Release|x86.Build.0 = Release|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.ActiveCfg = Debug|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|ARM.Build.0 = Debug|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.ActiveCfg = Debug|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x64.Build.0 = Debug|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.ActiveCfg = Debug|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Debug|x86.Build.0 = Debug|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.ActiveCfg = Release|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|ARM.Build.0 = Release|ARM - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.ActiveCfg = Release|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x64.Build.0 = Release|x64 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.ActiveCfg = Release|Win32 - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9}.Release|x86.Build.0 = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|ARM.ActiveCfg = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.ActiveCfg = Debug|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x64.Build.0 = Debug|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.ActiveCfg = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Debug|x86.Build.0 = Debug|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|ARM.ActiveCfg = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.ActiveCfg = Release|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x64.Build.0 = Release|x64 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.ActiveCfg = Release|Win32 - {F03BEE03-BEFB-4B17-A774-D9C8246530D4}.Release|x86.Build.0 = Release|Win32 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|ARM.ActiveCfg = Debug|ARM - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|ARM.Build.0 = Debug|ARM - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|ARM.Deploy.0 = Debug|ARM - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x64.ActiveCfg = Debug|x64 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x64.Build.0 = Debug|x64 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x64.Deploy.0 = Debug|x64 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x86.ActiveCfg = Debug|Win32 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x86.Build.0 = Debug|Win32 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Debug|x86.Deploy.0 = Debug|Win32 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|ARM.ActiveCfg = Release|ARM - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|ARM.Build.0 = Release|ARM - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|ARM.Deploy.0 = Release|ARM - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x64.ActiveCfg = Release|x64 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x64.Build.0 = Release|x64 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x64.Deploy.0 = Release|x64 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x86.ActiveCfg = Release|Win32 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x86.Build.0 = Release|Win32 - {2887A786-B818-4B3D-94EF-21EFD6AFDC22}.Release|x86.Deploy.0 = Release|Win32 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|ARM.ActiveCfg = Debug|ARM - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|ARM.Build.0 = Debug|ARM - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x64.ActiveCfg = Debug|x64 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x64.Build.0 = Debug|x64 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x86.ActiveCfg = Debug|Win32 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Debug|x86.Build.0 = Debug|Win32 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|ARM.ActiveCfg = Release|ARM - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|ARM.Build.0 = Release|ARM - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x64.ActiveCfg = Release|x64 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x64.Build.0 = Release|x64 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x86.ActiveCfg = Release|Win32 - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654}.Release|x86.Build.0 = Release|Win32 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|ARM.ActiveCfg = Debug|ARM - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|ARM.Build.0 = Debug|ARM - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x64.ActiveCfg = Debug|x64 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x64.Build.0 = Debug|x64 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x86.ActiveCfg = Debug|Win32 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Debug|x86.Build.0 = Debug|Win32 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|ARM.ActiveCfg = Release|ARM - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|ARM.Build.0 = Release|ARM - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x64.ActiveCfg = Release|x64 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x64.Build.0 = Release|x64 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x86.ActiveCfg = Release|Win32 - {850CCB95-CFA8-4E41-9D1D-387C0C186740}.Release|x86.Build.0 = Release|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.ActiveCfg = Debug|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Build.0 = Debug|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|ARM.Deploy.0 = Debug|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.ActiveCfg = Debug|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Build.0 = Debug|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x64.Deploy.0 = Debug|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x86.ActiveCfg = Debug|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x86.Build.0 = Debug|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Debug|x86.Deploy.0 = Debug|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.ActiveCfg = Release|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Build.0 = Release|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|ARM.Deploy.0 = Release|ARM - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.ActiveCfg = Release|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Build.0 = Release|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x64.Deploy.0 = Release|x64 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x86.ActiveCfg = Release|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x86.Build.0 = Release|Win32 - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658}.Release|x86.Deploy.0 = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|ARM.ActiveCfg = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.ActiveCfg = Debug|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x64.Build.0 = Debug|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.ActiveCfg = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Debug|x86.Build.0 = Debug|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|ARM.ActiveCfg = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.ActiveCfg = Release|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x64.Build.0 = Release|x64 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.ActiveCfg = Release|Win32 - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147}.Release|x86.Build.0 = Release|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.ActiveCfg = Debug|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Build.0 = Debug|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|ARM.Deploy.0 = Debug|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.ActiveCfg = Debug|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Build.0 = Debug|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x64.Deploy.0 = Debug|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x86.ActiveCfg = Debug|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x86.Build.0 = Debug|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Debug|x86.Deploy.0 = Debug|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.ActiveCfg = Release|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Build.0 = Release|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|ARM.Deploy.0 = Release|ARM - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.ActiveCfg = Release|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Build.0 = Release|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x64.Deploy.0 = Release|x64 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x86.ActiveCfg = Release|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x86.Build.0 = Release|Win32 - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79}.Release|x86.Deploy.0 = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|ARM.ActiveCfg = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.ActiveCfg = Debug|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x64.Build.0 = Debug|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.ActiveCfg = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Debug|x86.Build.0 = Debug|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|ARM.ActiveCfg = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.ActiveCfg = Release|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x64.Build.0 = Release|x64 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.ActiveCfg = Release|Win32 - {84350CD1-D406-4A4F-9571-261CA46D77C5}.Release|x86.Build.0 = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|ARM.ActiveCfg = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.ActiveCfg = Debug|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x64.Build.0 = Debug|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.ActiveCfg = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Debug|x86.Build.0 = Debug|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|ARM.ActiveCfg = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.ActiveCfg = Release|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x64.Build.0 = Release|x64 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.ActiveCfg = Release|Win32 - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7}.Release|x86.Build.0 = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|ARM.ActiveCfg = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.ActiveCfg = Debug|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x64.Build.0 = Debug|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.ActiveCfg = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Debug|x86.Build.0 = Debug|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|ARM.ActiveCfg = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.ActiveCfg = Release|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x64.Build.0 = Release|x64 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.ActiveCfg = Release|Win32 - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D}.Release|x86.Build.0 = Release|Win32 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.ActiveCfg = Debug|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|ARM.Build.0 = Debug|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x64.ActiveCfg = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.ActiveCfg = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Debug|x86.Build.0 = Debug|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.ActiveCfg = Release|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|ARM.Build.0 = Release|ARM - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x64.ActiveCfg = Release|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.ActiveCfg = Release|x86 - {AFB49019-965B-4C10-BAFF-C86C16D58010}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {65951C40-A332-4B54-89C2-7CDAF30D5F66} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - {594DCB5F-07E3-4084-A2CE-268611FA629F} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - {3D5908F7-7673-4229-BC46-2007A7AF9CAE} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - {F40F4804-50F9-4257-8D74-B9CBB19AC4C3} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - {0A9BA181-7876-4B3D-A5E0-EE673FA51C05} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - {1014C621-BC2D-4813-B8C1-6D83AD6F9249} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - {36D79E79-7E9E-4B3A-88A3-9F9B295C80B9} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - {F03BEE03-BEFB-4B17-A774-D9C8246530D4} = {EF775754-D70A-4611-A00C-F49F224FD236} - {2887A786-B818-4B3D-94EF-21EFD6AFDC22} = {EF775754-D70A-4611-A00C-F49F224FD236} - {35DFAAD1-4B25-4ED9-BB18-84F0EFCE1654} = {EF775754-D70A-4611-A00C-F49F224FD236} - {850CCB95-CFA8-4E41-9D1D-387C0C186740} = {EF775754-D70A-4611-A00C-F49F224FD236} - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} = {EF775754-D70A-4611-A00C-F49F224FD236} - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} = {EF775754-D70A-4611-A00C-F49F224FD236} - {B8D3F85B-DA71-4ACA-87BA-10FED681DC79} = {EF775754-D70A-4611-A00C-F49F224FD236} - {84350CD1-D406-4A4F-9571-261CA46D77C5} = {EF775754-D70A-4611-A00C-F49F224FD236} - {830B6E2F-9224-41D1-B9C7-A51FC78B00C7} = {EF775754-D70A-4611-A00C-F49F224FD236} - {2EB9CCAA-541D-4DC1-BE2C-B1AE9712194D} = {EF775754-D70A-4611-A00C-F49F224FD236} - {AFB49019-965B-4C10-BAFF-C86C16D58010} = {92944FCF-7E50-41FD-8A99-DD6869F9AEA5} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {5782CB9E-B335-4D07-A195-717BF4093536} - EndGlobalSection -EndGlobal From b209ac17d994fa082d182b05b35a2e9fb7c0d801 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Mon, 15 Oct 2018 13:48:26 -0700 Subject: [PATCH 449/609] Add vcpkg based dependency resolution for *nix platforms. (#913) --- .gitmodules | 2 +- azure-pipelines.yml | 102 +++++++++++++++++++++++++++++++++----------- vcpkg | 2 +- 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/.gitmodules b/.gitmodules index 3c19d8d07f..326611e519 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "vcpkg"] path = vcpkg - url = https://github.com/Microsoft/vcpkg + url = https://github.com/BillyONeal/vcpkg diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 76766a59b4..a5d63c55df 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -166,31 +166,46 @@ jobs: cd build.release/Release/Binaries ./test_runner *test.so displayName: 'Run tests, release' - - # vcpkg on Linux missing for now due to OpenSSL root certificates - # - job: Ubuntu_1604_Vcpkg_Debug - # pool: - # vmImage: 'Ubuntu 16.04' - # steps: - # - script: | - # ./vcpkg/bootstrap-vcpkg.sh - # ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono - # displayName: Apt install dependencies - # - script: mkdir build.debug - # displayName: Make build.debug - # - task: CMake@1 - # inputs: - # workingDirectory: 'build.debug' - # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - # - script: | - # cd build.debug - # ninja - # displayName: 'Run ninja' - # - script: | - # cd build.debug/Release/Binaries - # ./test_runner *test.so - # displayName: 'Run Tests' - - job: MacOS + - job: Ubuntu_1604_Vcpkg + pool: + vmImage: 'Ubuntu 16.04' + steps: + - script: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + sudo apt-get -y update + sudo apt-get install g++-7 ninja-build -y + ./vcpkg/bootstrap-vcpkg.sh + ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli + displayName: Vcpkg install dependencies + - script: | + mkdir build.debug + mkdir build.release + displayName: Make Build Directories + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - script: | + cd build.debug + ninja + displayName: 'Run ninja debug' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.so + displayName: 'Run Tests debug' + - script: | + cd build.release + ninja + displayName: 'Run ninja, release' + - script: | + cd build.release/Release/Binaries + ./test_runner *test.so + displayName: 'Run tests, release' + - job: MacOS_Homebrew pool: vmImage: 'macOS-10.13' steps: @@ -233,3 +248,40 @@ jobs: cd build.release.static ninja displayName: 'Run ninja, release static' + - job: MacOS_Vcpkg + pool: + vmImage: 'macOS-10.13' + steps: + - script: | + brew install gcc ninja + ./vcpkg/bootstrap-vcpkg.sh + ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli + displayName: Vcpkg install dependencies + - script: | + mkdir build.debug + mkdir build.release + displayName: Make Build Directories + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - script: | + cd build.debug + ninja + displayName: 'Run ninja debug' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run Tests debug' + - script: | + cd build.release + ninja + displayName: 'Run ninja, release' + - script: | + cd build.release/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run tests, release' diff --git a/vcpkg b/vcpkg index 29858b3cb2..76ea5e321c 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 29858b3cb2c8a0ec2c85b1b14d6d0a0d1dfe309e +Subproject commit 76ea5e321cf88cf1c99a7bd0fcebae7c8f990ee0 From ada8e57059e47727ebed8098a60fa9cbfe556cdb Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 15 Oct 2018 14:15:32 -0700 Subject: [PATCH 450/609] Correct .gitmodules to point to upstream vcpkg. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 326611e519..3c19d8d07f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "vcpkg"] path = vcpkg - url = https://github.com/BillyONeal/vcpkg + url = https://github.com/Microsoft/vcpkg From 943c6f8370dda65c092fe0217b2358944044a6fd Mon Sep 17 00:00:00 2001 From: Randy Ramos Date: Tue, 16 Oct 2018 03:38:44 -0400 Subject: [PATCH 451/609] Add install instructions for Fedora (#919) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6739483ebf..391027675b 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ With [apt-get](https://launchpad.net/ubuntu/+source/casablanca/2.8.0-2build2) on ``` $ sudo apt-get install libcpprest-dev ``` +With [dnf](https://apps.fedoraproject.org/packages/cpprest) on Fedora +``` +$ sudo dnf install cpprest-devel +``` With [brew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/cpprestsdk.rb) on OSX ``` $ brew install cpprestsdk From 9c8e0d41fb6e27acb2ae0edbd08022b392c2a33c Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 16 Oct 2018 14:31:43 -0700 Subject: [PATCH 452/609] Fix off-by-one error in connection pooling introduced with asio certificate changes in 2.10.4 (#920) * Fix off-by-one error introduced in connection pool stack. This got introduced when the connection pool queue was changed into a stack to reuse hot connections. * Make connection_pool_stack testable and add tests. --- Release/src/CMakeLists.txt | 7 +- Release/src/http/client/http_client_asio.cpp | 45 +------------ .../src/http/common/connection_pool_helpers.h | 66 +++++++++++++++++++ .../functional/http/client/CMakeLists.txt | 5 +- .../http/client/connection_pool_tests.cpp | 45 +++++++++++++ 5 files changed, 120 insertions(+), 48 deletions(-) create mode 100644 Release/src/http/common/connection_pool_helpers.h create mode 100644 Release/tests/functional/http/client/connection_pool_tests.cpp diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index eceaad7437..cea7048c7d 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -16,12 +16,13 @@ set(SOURCES ${HEADERS_DETAILS} pch/stdafx.h http/client/http_client.cpp - http/client/http_client_msg.cpp http/client/http_client_impl.h - http/common/internal_http_helpers.h + http/client/http_client_msg.cpp + http/common/connection_pool_helpers.h + http/common/http_compression.cpp http/common/http_helpers.cpp http/common/http_msg.cpp - http/common/http_compression.cpp + http/common/internal_http_helpers.h http/listener/http_listener.cpp http/listener/http_listener_msg.cpp http/listener/http_server_api.cpp diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 645b45466c..ada8e9494d 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -17,6 +17,7 @@ #include #include "../common/internal_http_helpers.h" +#include "../common/connection_pool_helpers.h" #include "cpprest/asyncrt_utils.h" #if defined(__clang__) @@ -345,48 +346,6 @@ class asio_connection bool m_closed; }; -class connection_pool_stack -{ -public: - // attempts to acquire a connection from the deque; returns nullptr if no connection is - // available - std::shared_ptr try_acquire() CPPREST_NOEXCEPT - { - const size_t oldConnectionsSize = m_connections.size(); - if (m_highWater > oldConnectionsSize) - { - m_highWater = oldConnectionsSize; - } - - if (oldConnectionsSize == 0) - { - return nullptr; - } - - auto result = std::move(m_connections.back()); - m_connections.pop_back(); - return result; - } - - // releases `released` back to the connection pool - void release(std::shared_ptr&& released) - { - m_connections.push_back(std::move(released)); - } - - bool free_stale_connections() CPPREST_NOEXCEPT - { - m_connections.erase(m_connections.begin(), m_connections.begin() + m_highWater); - const size_t connectionsSize = m_connections.size(); - m_highWater = connectionsSize; - return (connectionsSize != 0); - } - -private: - size_t m_highWater = 0; - std::vector> m_connections; -}; - /// Implements a connection pool with adaptive connection removal /// /// Every 30 seconds, the lambda in `start_epoch_interval` fires, triggering the @@ -501,7 +460,7 @@ class asio_connection_pool final : public std::enable_shared_from_this m_connections; + std::map> m_connections; bool m_is_timer_running; boost::asio::deadline_timer m_pool_epoch_timer; }; diff --git a/Release/src/http/common/connection_pool_helpers.h b/Release/src/http/common/connection_pool_helpers.h new file mode 100644 index 0000000000..580b82af23 --- /dev/null +++ b/Release/src/http/common/connection_pool_helpers.h @@ -0,0 +1,66 @@ +#pragma once + +#include "cpprest/details/cpprest_compat.h" +#include +#include +#include + +namespace web +{ +namespace http +{ +namespace client +{ +namespace details +{ + +template +class connection_pool_stack +{ +public: + // attempts to acquire a connection from the deque; returns nullptr if no connection is + // available + std::shared_ptr try_acquire() CPPREST_NOEXCEPT + { + const size_t oldConnectionsSize = m_connections.size(); + if (oldConnectionsSize == 0) + { + m_staleBefore = 0; + return nullptr; + } + + auto result = std::move(m_connections.back()); + m_connections.pop_back(); + const size_t newConnectionsSize = m_connections.size(); + if (m_staleBefore > newConnectionsSize) + { + m_staleBefore = newConnectionsSize; + } + + return result; + } + + // releases `released` back to the connection pool + void release(std::shared_ptr&& released) + { + m_connections.push_back(std::move(released)); + } + + bool free_stale_connections() CPPREST_NOEXCEPT + { + assert(m_staleBefore <= m_connections.size()); + m_connections.erase(m_connections.begin(), m_connections.begin() + m_staleBefore); + const size_t connectionsSize = m_connections.size(); + m_staleBefore = connectionsSize; + return (connectionsSize != 0); + } + +private: + std::vector> m_connections; + size_t m_staleBefore = 0; +}; + +} // details +} // client +} // http +} // web diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index d92b477481..45f0d9af02 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -2,8 +2,11 @@ set(SOURCES authentication_tests.cpp building_request_tests.cpp client_construction.cpp + compression_tests.cpp + connection_pool_tests.cpp connections_and_errors.cpp header_tests.cpp + http_client_fuzz_tests.cpp http_client_tests.cpp http_methods_tests.cpp multiple_requests.cpp @@ -20,8 +23,6 @@ set(SOURCES response_stream_tests.cpp status_code_reason_phrase_tests.cpp to_string_tests.cpp - http_client_fuzz_tests.cpp - compression_tests.cpp ) add_casablanca_test(httpclient_test SOURCES) diff --git a/Release/tests/functional/http/client/connection_pool_tests.cpp b/Release/tests/functional/http/client/connection_pool_tests.cpp new file mode 100644 index 0000000000..037ed69d88 --- /dev/null +++ b/Release/tests/functional/http/client/connection_pool_tests.cpp @@ -0,0 +1,45 @@ +#include "stdafx.h" +#include +#include "../../../src/http/common/connection_pool_helpers.h" + +using namespace web::http::client::details; + +SUITE(connection_pooling) { + TEST(empty_returns_nullptr) { + connection_pool_stack connectionStack; + VERIFY_ARE_EQUAL(connectionStack.try_acquire(), std::shared_ptr{}); + } + + static int noisyCount = 0; + struct noisy { + noisy() = delete; + noisy(int) { ++noisyCount; } + noisy(const noisy&) = delete; + noisy(noisy&&) { ++noisyCount; } + noisy& operator=(const noisy&) = delete; + noisy& operator=(noisy&&) = delete; + ~noisy() { --noisyCount; } + }; + + TEST(cycled_connections_survive) { + connection_pool_stack connectionStack; + VERIFY_ARE_EQUAL(0, noisyCount); + connectionStack.release(std::make_shared(42)); + connectionStack.release(std::make_shared(42)); + connectionStack.release(std::make_shared(42)); + VERIFY_ARE_EQUAL(3, noisyCount); + VERIFY_IS_TRUE(connectionStack.free_stale_connections()); + auto tmp = connectionStack.try_acquire(); + VERIFY_ARE_NOT_EQUAL(tmp, std::shared_ptr{}); + connectionStack.release(std::move(tmp)); + VERIFY_ARE_EQUAL(tmp, std::shared_ptr{}); + tmp = connectionStack.try_acquire(); + VERIFY_ARE_NOT_EQUAL(tmp, std::shared_ptr{}); + connectionStack.release(std::move(tmp)); + VERIFY_IS_TRUE(connectionStack.free_stale_connections()); + VERIFY_ARE_EQUAL(1, noisyCount); + VERIFY_IS_FALSE(connectionStack.free_stale_connections()); + VERIFY_ARE_EQUAL(0, noisyCount); + VERIFY_IS_FALSE(connectionStack.free_stale_connections()); + } +}; From 06619a7c4561d81190971e4431cd96924afc377d Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 16 Oct 2018 15:26:21 -0700 Subject: [PATCH 453/609] Update embedded websockets to 0.8.1 and use submodule instead of checkin (#921) * Delete checked in websocketpp. * Add submodule reference to websocketpp 0.8.1. --- .gitmodules | 3 + Release/libs/websocketpp | 1 + Release/libs/websocketpp/.gitattributes | 18 - Release/libs/websocketpp/.gitignore | 90 - Release/libs/websocketpp/.travis.yml | 23 - Release/libs/websocketpp/CMakeLists.txt | 247 -- Release/libs/websocketpp/COPYING | 145 -- Release/libs/websocketpp/Doxyfile | 1874 -------------- Release/libs/websocketpp/SConstruct | 266 -- Release/libs/websocketpp/changelog.md | 234 -- .../docs/simple_broadcast_server.cpp | 52 - .../docs/simple_count_server_thread.cpp | 65 - .../libs/websocketpp/examples/CMakeLists.txt | 6 - .../associative_storage.cpp | 88 - .../examples/broadcast_server/SConscript | 23 - .../broadcast_server/broadcast_server.cpp | 156 -- .../examples/debug_client/SConscript | 24 - .../examples/debug_client/debug_client.cpp | 166 -- .../examples/debug_server/CMakeLists.txt | 10 - .../examples/debug_server/SConscript | 23 - .../examples/debug_server/debug_server.cpp | 174 -- .../libs/websocketpp/examples/dev/SConscript | 18 - .../libs/websocketpp/examples/dev/main.cpp | 200 -- .../examples/echo_server/CMakeLists.txt | 10 - .../examples/echo_server/SConscript | 23 - .../examples/echo_server/echo_handler.hpp | 37 - .../examples/echo_server/echo_server.cpp | 58 - .../examples/echo_server_both/CMakeLists.txt | 15 - .../examples/echo_server_both/SConscript | 24 - .../echo_server_both/echo_server_both.cpp | 87 - .../examples/echo_server_both/server.pem | 58 - .../examples/echo_server_tls/CMakeLists.txt | 15 - .../examples/echo_server_tls/SConscript | 24 - .../echo_server_tls/echo_server_tls.cpp | 73 - .../examples/echo_server_tls/server.pem | 58 - .../enriched_storage/enriched_storage.cpp | 87 - .../handler_switch/handler_switch.cpp | 42 - .../examples/iostream_server/SConscript | 23 - .../iostream_server/iostream_server.cpp | 89 - .../examples/print_server/CMakeLists.txt | 10 - .../examples/print_server/SConscript | 23 - .../examples/print_server/print_server.cpp | 22 - .../simple_broadcast_server.cpp | 51 - .../examples/sip_client/CMakeLists.txt | 11 - .../examples/sip_client/README.txt | 22 - .../examples/sip_client/SConscript | 23 - .../examples/sip_client/sip_client.cpp | 84 - .../examples/subprotocol_server/SConscript | 23 - .../subprotocol_server/subprotocol_server.cpp | 48 - .../examples/telemetry_client/CMakeLists.txt | 10 - .../examples/telemetry_client/SConscript | 23 - .../telemetry_client/telemetry_client.cpp | 156 -- .../examples/telemetry_server/CMakeLists.txt | 10 - .../examples/telemetry_server/SConscript | 23 - .../examples/telemetry_server/index.html | 85 - .../telemetry_server/telemetry_server.cpp | 204 -- .../examples/testee_client/CMakeLists.txt | 11 - .../examples/testee_client/SConscript | 23 - .../examples/testee_client/testee_client.cpp | 80 - .../examples/testee_server/SConscript | 23 - .../examples/testee_server/testee_server.cpp | 138 - .../examples/utility_client/CMakeLists.txt | 11 - .../examples/utility_client/SConscript | 23 - .../utility_client/utility_client.cpp | 325 --- Release/libs/websocketpp/readme.md | 45 - Release/libs/websocketpp/roadmap.md | 43 - .../websocketpp/test/connection/SConscript | 25 - .../test/connection/connection.cpp | 478 ---- .../test/connection/connection_tu2.cpp | 62 - .../test/connection/connection_tu2.hpp | 51 - .../libs/websocketpp/test/endpoint/SConscript | 24 - .../websocketpp/test/endpoint/endpoint.cpp | 126 - .../websocketpp/test/extension/SConscript | 27 - .../websocketpp/test/extension/extension.cpp | 37 - .../test/extension/permessage_deflate.cpp | 543 ---- Release/libs/websocketpp/test/http/SConscript | 23 - Release/libs/websocketpp/test/http/parser.cpp | 1127 -------- .../websocketpp/test/http/parser_perf.cpp | 141 - .../libs/websocketpp/test/logger/SConscript | 23 - .../libs/websocketpp/test/logger/basic.cpp | 81 - .../test/message_buffer/SConscript | 27 - .../websocketpp/test/message_buffer/alloc.cpp | 96 - .../test/message_buffer/message.cpp | 72 - .../websocketpp/test/message_buffer/pool.cpp | 156 -- .../websocketpp/test/processors/SConscript | 47 - .../extension_permessage_compress.cpp | 198 -- .../websocketpp/test/processors/hybi00.cpp | 274 -- .../websocketpp/test/processors/hybi07.cpp | 193 -- .../websocketpp/test/processors/hybi08.cpp | 197 -- .../websocketpp/test/processors/hybi13.cpp | 693 ----- .../websocketpp/test/processors/processor.cpp | 135 - .../libs/websocketpp/test/random/SConscript | 27 - Release/libs/websocketpp/test/random/none.cpp | 40 - .../websocketpp/test/random/random_device.cpp | 50 - .../libs/websocketpp/test/roles/SConscript | 27 - .../libs/websocketpp/test/roles/client.cpp | 194 -- .../libs/websocketpp/test/roles/server.cpp | 247 -- .../websocketpp/test/transport/SConscript | 24 - .../test/transport/asio/SConscript | 28 - .../websocketpp/test/transport/asio/base.cpp | 49 - .../test/transport/asio/timers.cpp | 187 -- .../websocketpp/test/transport/hybi_util.cpp | 98 - .../test/transport/integration.cpp | 609 ----- .../test/transport/iostream/SConscript | 31 - .../test/transport/iostream/base.cpp | 33 - .../test/transport/iostream/connection.cpp | 575 ----- .../test/transport/iostream/endpoint.cpp | 41 - .../libs/websocketpp/test/utility/SConscript | 40 - .../libs/websocketpp/test/utility/close.cpp | 125 - .../libs/websocketpp/test/utility/error.cpp | 54 - .../libs/websocketpp/test/utility/frame.cpp | 538 ---- .../libs/websocketpp/test/utility/sha1.cpp | 81 - Release/libs/websocketpp/test/utility/uri.cpp | 246 -- .../websocketpp/test/utility/utilities.cpp | 73 - .../broadcast_tutorial/broadcast_tutorial.md | 17 - .../tutorials/chat_tutorial/chat_tutorial.md | 13 - .../tutorials/utility_client/step1.cpp | 56 - .../tutorials/utility_client/step2.cpp | 61 - .../tutorials/utility_client/step3.cpp | 81 - .../tutorials/utility_client/step4.cpp | 202 -- .../tutorials/utility_client/step5.cpp | 280 -- .../tutorials/utility_client/step6.cpp | 335 --- .../utility_client/utility_client.md | 856 ------- .../websocketpp/websocketpp-config.cmake.in | 7 - .../websocketpp-configVersion.cmake.in | 11 - .../websocketpp/websocketpp/CMakeLists.txt | 2 - .../websocketpp/websocketpp/base64/base64.hpp | 178 -- .../libs/websocketpp/websocketpp/client.hpp | 33 - .../libs/websocketpp/websocketpp/close.hpp | 342 --- .../websocketpp/websocketpp/common/chrono.hpp | 55 - .../websocketpp/common/connection_hdl.hpp | 52 - .../websocketpp/websocketpp/common/cpp11.hpp | 150 -- .../websocketpp/common/functional.hpp | 105 - .../websocketpp/websocketpp/common/md5.hpp | 448 ---- .../websocketpp/websocketpp/common/memory.hpp | 86 - .../websocketpp/common/network.hpp | 104 - .../websocketpp/common/platforms.hpp | 46 - .../websocketpp/websocketpp/common/random.hpp | 82 - .../websocketpp/websocketpp/common/regex.hpp | 59 - .../websocketpp/websocketpp/common/stdint.hpp | 73 - .../websocketpp/common/system_error.hpp | 82 - .../websocketpp/websocketpp/common/thread.hpp | 76 - .../websocketpp/websocketpp/common/time.hpp | 56 - .../websocketpp/concurrency/basic.hpp | 46 - .../websocketpp/concurrency/none.hpp | 80 - .../websocketpp/websocketpp/config/asio.hpp | 77 - .../websocketpp/config/asio_client.hpp | 77 - .../websocketpp/config/asio_no_tls.hpp | 73 - .../websocketpp/config/asio_no_tls_client.hpp | 73 - .../websocketpp/config/boost_config.hpp | 72 - .../websocketpp/websocketpp/config/core.hpp | 285 --- .../websocketpp/config/core_client.hpp | 294 --- .../websocketpp/websocketpp/config/debug.hpp | 286 --- .../websocketpp/config/debug_asio.hpp | 77 - .../websocketpp/config/debug_asio_no_tls.hpp | 73 - .../websocketpp/config/minimal_client.hpp | 72 - .../websocketpp/config/minimal_server.hpp | 312 --- .../websocketpp/websocketpp/connection.hpp | 1537 ----------- .../websocketpp/connection_base.hpp | 38 - .../libs/websocketpp/websocketpp/endpoint.hpp | 619 ----- .../websocketpp/websocketpp/endpoint_base.hpp | 38 - .../libs/websocketpp/websocketpp/error.hpp | 272 -- .../websocketpp/error_container.hpp | 71 - .../websocketpp/extensions/extension.hpp | 102 - .../permessage_deflate/disabled.hpp | 106 - .../extensions/permessage_deflate/enabled.hpp | 725 ------ .../libs/websocketpp/websocketpp/frame.hpp | 863 ------- .../websocketpp/http/constants.hpp | 308 --- .../websocketpp/http/impl/parser.hpp | 196 -- .../websocketpp/http/impl/request.hpp | 191 -- .../websocketpp/http/impl/response.hpp | 266 -- .../websocketpp/websocketpp/http/parser.hpp | 615 ----- .../websocketpp/websocketpp/http/request.hpp | 124 - .../websocketpp/websocketpp/http/response.hpp | 188 -- .../websocketpp/impl/connection_impl.hpp | 2267 ----------------- .../websocketpp/impl/endpoint_impl.hpp | 255 -- .../websocketpp/impl/utilities_impl.hpp | 87 - .../websocketpp/websocketpp/logger/basic.hpp | 169 -- .../websocketpp/websocketpp/logger/levels.hpp | 203 -- .../websocketpp/websocketpp/logger/stub.hpp | 119 - .../websocketpp/websocketpp/logger/syslog.hpp | 146 -- .../websocketpp/message_buffer/alloc.hpp | 105 - .../websocketpp/message_buffer/message.hpp | 340 --- .../websocketpp/message_buffer/pool.hpp | 229 -- .../websocketpp/processors/base.hpp | 299 --- .../websocketpp/processors/hybi00.hpp | 448 ---- .../websocketpp/processors/hybi07.hpp | 78 - .../websocketpp/processors/hybi08.hpp | 83 - .../websocketpp/processors/hybi13.hpp | 1005 -------- .../websocketpp/processors/processor.hpp | 392 --- .../websocketpp/websocketpp/random/none.hpp | 60 - .../websocketpp/random/random_device.hpp | 80 - .../websocketpp/roles/client_endpoint.hpp | 170 -- .../websocketpp/roles/server_endpoint.hpp | 166 -- .../libs/websocketpp/websocketpp/server.hpp | 33 - .../websocketpp/websocketpp/sha1/sha1.hpp | 189 -- .../websocketpp/transport/asio/base.hpp | 251 -- .../websocketpp/transport/asio/connection.hpp | 1162 --------- .../websocketpp/transport/asio/endpoint.hpp | 1094 -------- .../transport/asio/security/base.hpp | 152 -- .../transport/asio/security/none.hpp | 329 --- .../transport/asio/security/tls.hpp | 426 ---- .../websocketpp/transport/base/connection.hpp | 238 -- .../websocketpp/transport/base/endpoint.hpp | 77 - .../websocketpp/transport/debug/base.hpp | 104 - .../transport/debug/connection.hpp | 397 --- .../websocketpp/transport/debug/endpoint.hpp | 140 - .../websocketpp/transport/iostream/base.hpp | 121 - .../transport/iostream/connection.hpp | 661 ----- .../transport/iostream/endpoint.hpp | 222 -- .../websocketpp/transport/stub/base.hpp | 95 - .../websocketpp/transport/stub/connection.hpp | 272 -- .../websocketpp/transport/stub/endpoint.hpp | 140 - Release/libs/websocketpp/websocketpp/uri.hpp | 354 --- .../websocketpp/utf8_validator.hpp | 154 -- .../websocketpp/websocketpp/utilities.hpp | 182 -- .../libs/websocketpp/websocketpp/version.hpp | 60 - 217 files changed, 4 insertions(+), 40106 deletions(-) create mode 160000 Release/libs/websocketpp delete mode 100644 Release/libs/websocketpp/.gitattributes delete mode 100644 Release/libs/websocketpp/.gitignore delete mode 100644 Release/libs/websocketpp/.travis.yml delete mode 100644 Release/libs/websocketpp/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/COPYING delete mode 100644 Release/libs/websocketpp/Doxyfile delete mode 100644 Release/libs/websocketpp/SConstruct delete mode 100644 Release/libs/websocketpp/changelog.md delete mode 100644 Release/libs/websocketpp/docs/simple_broadcast_server.cpp delete mode 100644 Release/libs/websocketpp/docs/simple_count_server_thread.cpp delete mode 100644 Release/libs/websocketpp/examples/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/associative_storage/associative_storage.cpp delete mode 100644 Release/libs/websocketpp/examples/broadcast_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/broadcast_server/broadcast_server.cpp delete mode 100644 Release/libs/websocketpp/examples/debug_client/SConscript delete mode 100644 Release/libs/websocketpp/examples/debug_client/debug_client.cpp delete mode 100644 Release/libs/websocketpp/examples/debug_server/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/debug_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/debug_server/debug_server.cpp delete mode 100644 Release/libs/websocketpp/examples/dev/SConscript delete mode 100644 Release/libs/websocketpp/examples/dev/main.cpp delete mode 100644 Release/libs/websocketpp/examples/echo_server/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/echo_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/echo_server/echo_handler.hpp delete mode 100644 Release/libs/websocketpp/examples/echo_server/echo_server.cpp delete mode 100644 Release/libs/websocketpp/examples/echo_server_both/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/echo_server_both/SConscript delete mode 100644 Release/libs/websocketpp/examples/echo_server_both/echo_server_both.cpp delete mode 100644 Release/libs/websocketpp/examples/echo_server_both/server.pem delete mode 100644 Release/libs/websocketpp/examples/echo_server_tls/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/echo_server_tls/SConscript delete mode 100644 Release/libs/websocketpp/examples/echo_server_tls/echo_server_tls.cpp delete mode 100644 Release/libs/websocketpp/examples/echo_server_tls/server.pem delete mode 100644 Release/libs/websocketpp/examples/enriched_storage/enriched_storage.cpp delete mode 100644 Release/libs/websocketpp/examples/handler_switch/handler_switch.cpp delete mode 100644 Release/libs/websocketpp/examples/iostream_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/iostream_server/iostream_server.cpp delete mode 100644 Release/libs/websocketpp/examples/print_server/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/print_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/print_server/print_server.cpp delete mode 100644 Release/libs/websocketpp/examples/simple_broadcast_server/simple_broadcast_server.cpp delete mode 100644 Release/libs/websocketpp/examples/sip_client/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/sip_client/README.txt delete mode 100644 Release/libs/websocketpp/examples/sip_client/SConscript delete mode 100644 Release/libs/websocketpp/examples/sip_client/sip_client.cpp delete mode 100644 Release/libs/websocketpp/examples/subprotocol_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/subprotocol_server/subprotocol_server.cpp delete mode 100644 Release/libs/websocketpp/examples/telemetry_client/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/telemetry_client/SConscript delete mode 100644 Release/libs/websocketpp/examples/telemetry_client/telemetry_client.cpp delete mode 100644 Release/libs/websocketpp/examples/telemetry_server/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/telemetry_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/telemetry_server/index.html delete mode 100644 Release/libs/websocketpp/examples/telemetry_server/telemetry_server.cpp delete mode 100644 Release/libs/websocketpp/examples/testee_client/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/testee_client/SConscript delete mode 100644 Release/libs/websocketpp/examples/testee_client/testee_client.cpp delete mode 100644 Release/libs/websocketpp/examples/testee_server/SConscript delete mode 100644 Release/libs/websocketpp/examples/testee_server/testee_server.cpp delete mode 100644 Release/libs/websocketpp/examples/utility_client/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/examples/utility_client/SConscript delete mode 100644 Release/libs/websocketpp/examples/utility_client/utility_client.cpp delete mode 100644 Release/libs/websocketpp/readme.md delete mode 100644 Release/libs/websocketpp/roadmap.md delete mode 100644 Release/libs/websocketpp/test/connection/SConscript delete mode 100644 Release/libs/websocketpp/test/connection/connection.cpp delete mode 100644 Release/libs/websocketpp/test/connection/connection_tu2.cpp delete mode 100644 Release/libs/websocketpp/test/connection/connection_tu2.hpp delete mode 100644 Release/libs/websocketpp/test/endpoint/SConscript delete mode 100644 Release/libs/websocketpp/test/endpoint/endpoint.cpp delete mode 100644 Release/libs/websocketpp/test/extension/SConscript delete mode 100644 Release/libs/websocketpp/test/extension/extension.cpp delete mode 100644 Release/libs/websocketpp/test/extension/permessage_deflate.cpp delete mode 100644 Release/libs/websocketpp/test/http/SConscript delete mode 100644 Release/libs/websocketpp/test/http/parser.cpp delete mode 100644 Release/libs/websocketpp/test/http/parser_perf.cpp delete mode 100644 Release/libs/websocketpp/test/logger/SConscript delete mode 100644 Release/libs/websocketpp/test/logger/basic.cpp delete mode 100644 Release/libs/websocketpp/test/message_buffer/SConscript delete mode 100644 Release/libs/websocketpp/test/message_buffer/alloc.cpp delete mode 100644 Release/libs/websocketpp/test/message_buffer/message.cpp delete mode 100644 Release/libs/websocketpp/test/message_buffer/pool.cpp delete mode 100644 Release/libs/websocketpp/test/processors/SConscript delete mode 100644 Release/libs/websocketpp/test/processors/extension_permessage_compress.cpp delete mode 100644 Release/libs/websocketpp/test/processors/hybi00.cpp delete mode 100644 Release/libs/websocketpp/test/processors/hybi07.cpp delete mode 100644 Release/libs/websocketpp/test/processors/hybi08.cpp delete mode 100644 Release/libs/websocketpp/test/processors/hybi13.cpp delete mode 100644 Release/libs/websocketpp/test/processors/processor.cpp delete mode 100644 Release/libs/websocketpp/test/random/SConscript delete mode 100644 Release/libs/websocketpp/test/random/none.cpp delete mode 100644 Release/libs/websocketpp/test/random/random_device.cpp delete mode 100644 Release/libs/websocketpp/test/roles/SConscript delete mode 100644 Release/libs/websocketpp/test/roles/client.cpp delete mode 100644 Release/libs/websocketpp/test/roles/server.cpp delete mode 100644 Release/libs/websocketpp/test/transport/SConscript delete mode 100644 Release/libs/websocketpp/test/transport/asio/SConscript delete mode 100644 Release/libs/websocketpp/test/transport/asio/base.cpp delete mode 100644 Release/libs/websocketpp/test/transport/asio/timers.cpp delete mode 100644 Release/libs/websocketpp/test/transport/hybi_util.cpp delete mode 100644 Release/libs/websocketpp/test/transport/integration.cpp delete mode 100644 Release/libs/websocketpp/test/transport/iostream/SConscript delete mode 100644 Release/libs/websocketpp/test/transport/iostream/base.cpp delete mode 100644 Release/libs/websocketpp/test/transport/iostream/connection.cpp delete mode 100644 Release/libs/websocketpp/test/transport/iostream/endpoint.cpp delete mode 100644 Release/libs/websocketpp/test/utility/SConscript delete mode 100644 Release/libs/websocketpp/test/utility/close.cpp delete mode 100644 Release/libs/websocketpp/test/utility/error.cpp delete mode 100644 Release/libs/websocketpp/test/utility/frame.cpp delete mode 100644 Release/libs/websocketpp/test/utility/sha1.cpp delete mode 100644 Release/libs/websocketpp/test/utility/uri.cpp delete mode 100644 Release/libs/websocketpp/test/utility/utilities.cpp delete mode 100644 Release/libs/websocketpp/tutorials/broadcast_tutorial/broadcast_tutorial.md delete mode 100644 Release/libs/websocketpp/tutorials/chat_tutorial/chat_tutorial.md delete mode 100644 Release/libs/websocketpp/tutorials/utility_client/step1.cpp delete mode 100644 Release/libs/websocketpp/tutorials/utility_client/step2.cpp delete mode 100644 Release/libs/websocketpp/tutorials/utility_client/step3.cpp delete mode 100644 Release/libs/websocketpp/tutorials/utility_client/step4.cpp delete mode 100644 Release/libs/websocketpp/tutorials/utility_client/step5.cpp delete mode 100644 Release/libs/websocketpp/tutorials/utility_client/step6.cpp delete mode 100644 Release/libs/websocketpp/tutorials/utility_client/utility_client.md delete mode 100644 Release/libs/websocketpp/websocketpp-config.cmake.in delete mode 100644 Release/libs/websocketpp/websocketpp-configVersion.cmake.in delete mode 100644 Release/libs/websocketpp/websocketpp/CMakeLists.txt delete mode 100644 Release/libs/websocketpp/websocketpp/base64/base64.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/client.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/close.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/chrono.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/connection_hdl.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/cpp11.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/functional.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/md5.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/memory.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/network.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/platforms.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/random.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/regex.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/stdint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/system_error.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/thread.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/common/time.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/concurrency/basic.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/concurrency/none.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/asio.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/asio_client.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/asio_no_tls.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/asio_no_tls_client.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/boost_config.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/core.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/core_client.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/debug.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/debug_asio.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/debug_asio_no_tls.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/minimal_client.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/config/minimal_server.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/connection.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/connection_base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/endpoint_base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/error.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/error_container.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/extensions/extension.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/extensions/permessage_deflate/disabled.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/extensions/permessage_deflate/enabled.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/frame.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/http/constants.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/http/impl/parser.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/http/impl/request.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/http/impl/response.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/http/parser.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/http/request.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/http/response.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/impl/connection_impl.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/impl/endpoint_impl.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/impl/utilities_impl.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/logger/basic.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/logger/levels.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/logger/stub.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/logger/syslog.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/message_buffer/alloc.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/message_buffer/message.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/message_buffer/pool.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/processors/base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/processors/hybi00.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/processors/hybi07.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/processors/hybi08.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/processors/hybi13.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/processors/processor.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/random/none.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/random/random_device.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/roles/client_endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/roles/server_endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/server.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/sha1/sha1.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/asio/base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/asio/connection.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/asio/endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/asio/security/base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/asio/security/none.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/base/connection.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/base/endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/debug/base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/debug/connection.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/debug/endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/iostream/base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/iostream/connection.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/iostream/endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/stub/base.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/stub/connection.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/transport/stub/endpoint.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/uri.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/utf8_validator.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/utilities.hpp delete mode 100644 Release/libs/websocketpp/websocketpp/version.hpp diff --git a/.gitmodules b/.gitmodules index 3c19d8d07f..5a33829602 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "vcpkg"] path = vcpkg url = https://github.com/Microsoft/vcpkg +[submodule "websocketspp"] + path = Release/libs/websocketpp + url = https://github.com/zaphoyd/websocketpp/ diff --git a/Release/libs/websocketpp b/Release/libs/websocketpp new file mode 160000 index 0000000000..c6d7e295bf --- /dev/null +++ b/Release/libs/websocketpp @@ -0,0 +1 @@ +Subproject commit c6d7e295bf5a0ab9b5f896720cc1a0e0fdc397a7 diff --git a/Release/libs/websocketpp/.gitattributes b/Release/libs/websocketpp/.gitattributes deleted file mode 100644 index a9e4fc784b..0000000000 --- a/Release/libs/websocketpp/.gitattributes +++ /dev/null @@ -1,18 +0,0 @@ -# Lineendings -*.sln eol=crlf -*.vcproj eol=crlf -*.vcxproj* eol=crlf - -# Whitespace rules -# strict (no trailing, no tabs) -*.cpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol -*.hpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol -*.c whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol -*.h whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol - -# normal (no trailing) -*.sql whitespace=trailing-space,space-before-tab,cr-at-eol -*.txt whitespace=trailing-space,space-before-tab,cr-at-eol - -# special files which must ignore whitespace -*.patch whitespace=-trailing-space diff --git a/Release/libs/websocketpp/.gitignore b/Release/libs/websocketpp/.gitignore deleted file mode 100644 index 558a1b3d7f..0000000000 --- a/Release/libs/websocketpp/.gitignore +++ /dev/null @@ -1,90 +0,0 @@ -# make .git* files visible to git -!.gitignore -!.gitattributes - -.DS_Store - -#vim stuff -*~ -*.swp - -*.o -*.so -*.so.? -*.so.?.?.? -*.a -*.dylib -lib/* - -# CMake -*.cmake -*.dir -CMakeFiles -INSTALL.* -ZERO_CHECK.* -CMakeCache.txt -install_manifest.txt - -# Windows/Visual Studio -*.vcproj* -*.sln -*.suo -*.ncb -*/Debug/* -*/*/Debug/* -bin/Debug -*/Release/* -*/*/Release/* -*/RelWithDebInfo/* -*/*/RelWithDebInfo/* - -# explicitly allow this path with /debug/ in it -!websocketpp/transport/debug/* - -objs_shared/ -objs_static/ - -examples/chat_server/chat_server -examples/echo_server/echo_server -examples/chat_client/chat_client -examples/echo_client/echo_client -test/basic/tests -libwebsocketpp.dylib.0.1.0 - -websocketpp.xcodeproj/xcuserdata/* -websocketpp.xcodeproj/project.xcworkspace/xcuserdata/* -policy_based_notes.hpp - -examples/echo_server_tls/echo_server_tls - -examples/fuzzing_client/fuzzing_client - -examples/stress_client/stress_client - -examples/broadcast_server_tls/broadcast_server - -test/basic/perf - -examples/echo_server_tls/echo_server_tls - -examples/concurrent_server/concurrent_server - -examples/fuzzing_server_tls/fuzzing_server - -examples/wsperf/wsperf - -.sconsign.dblite - -build/ -doxygen/ -examples/wsperf/wsperf_client - -*.out - -*.log -*.opensdf -*.sdf -*.vcxproj -*.vcxproj.filters -*.user -install diff --git a/Release/libs/websocketpp/.travis.yml b/Release/libs/websocketpp/.travis.yml deleted file mode 100644 index 027ac560ed..0000000000 --- a/Release/libs/websocketpp/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: cpp -compiler: - - gcc -before_install: - - sudo apt-get install libboost-regex1.48-dev libboost-system1.48-dev libboost-thread1.48-dev libboost-test1.48-dev libboost-random1.48-dev -y -env: - global: - - BOOST_INCLUDES=/usr/include - - BOOST_LIBS=/usr/lib -script: scons -j 2 && scons test -branches: - only: - - master - - permessage-deflate - - experimental - - 0.3.x-cmake - - develop -notifications: - recipients: - - travis@zaphoyd.com - email: - on_success: change - on_failure: always diff --git a/Release/libs/websocketpp/CMakeLists.txt b/Release/libs/websocketpp/CMakeLists.txt deleted file mode 100644 index f8df9de08a..0000000000 --- a/Release/libs/websocketpp/CMakeLists.txt +++ /dev/null @@ -1,247 +0,0 @@ - -############ Setup project and cmake - -# Project name -project (websocketpp) - -# Minimum cmake requirement. We should require a quite recent -# cmake for the dependency find macros etc. to be up to date. -cmake_minimum_required (VERSION 2.6) - -set (WEBSOCKETPP_MAJOR_VERSION 0) -set (WEBSOCKETPP_MINOR_VERSION 5) -set (WEBSOCKETPP_PATCH_VERSION 1) -set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION}) - -set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") -if (WIN32 AND NOT CYGWIN) - set (DEF_INSTALL_CMAKE_DIR cmake) -else () - set (DEF_INSTALL_CMAKE_DIR lib/cmake/websocketpp) -endif () -set (INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") - -# Make relative paths absolute (needed later on) -foreach (p INCLUDE CMAKE) - set (var INSTALL_${p}_DIR) - if (NOT IS_ABSOLUTE "${${var}}") - set (${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") - endif () -endforeach () - -# Set CMake library search policy -if (COMMAND cmake_policy) - cmake_policy (SET CMP0003 NEW) - cmake_policy (SET CMP0005 NEW) -endif () - -# Disable unnecessary build types -set (CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug" CACHE STRING "Configurations" FORCE) - -# Include our cmake macros -set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) -include (CMakeHelpers) - -############ Paths - -set (WEBSOCKETPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) -set (WEBSOCKETPP_INCLUDE ${WEBSOCKETPP_ROOT}/websocketpp) -set (WEBSOCKETPP_BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR}) -set (WEBSOCKETPP_BIN ${WEBSOCKETPP_BUILD_ROOT}/bin) -set (WEBSOCKETPP_LIB ${WEBSOCKETPP_BUILD_ROOT}/lib) - -# CMake install step prefix. I assume linux users want the prefix to -# be the default /usr or /usr/local so this is only adjusted on Windows. -# - Windows: Build the INSTALL project in your solution file. -# - Linux/OSX: make install. -if (MSVC) - set (CMAKE_INSTALL_PREFIX "${WEBSOCKETPP_ROOT}/install") -endif () - -############ Build customization - -# Override from command line "CMake -D