C++ Rest SDK
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.
http_server_asio.h
1 /*
2 * Copyright (c) Microsoft Corporation. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14 
15 #pragma once
16 
17 #if defined(__clang__)
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 #endif
21 #include <boost/asio.hpp>
22 #include <boost/asio/ssl.hpp>
23 #if defined(__clang__)
24 #pragma clang diagnostic pop
25 #endif
26 #include <boost/bind.hpp>
27 #include <set>
28 #include "pplx/threadpool.h"
29 #include "cpprest/details/http_server.h"
30 
31 namespace web
32 {
33 namespace http
34 {
35 namespace experimental
36 {
37 namespace listener
38 {
39 
40 class http_linux_server;
41 
42 namespace details
43 {
44 
46 {
48 
49  pplx::task_completion_event<void> m_response_completed;
50 
51 private:
54 };
55 
56 class hostport_listener;
57 
59 {
60 private:
61  typedef void (connection::*ResponseFuncPtr) (const http_response &response, const boost::system::error_code& ec);
62 
63  std::unique_ptr<boost::asio::ip::tcp::socket> m_socket;
64  boost::asio::streambuf m_request_buf;
65  boost::asio::streambuf m_response_buf;
66  http_linux_server* m_p_server;
67  hostport_listener* m_p_parent;
68  http_request m_request;
69  size_t m_read, m_write;
70  size_t m_read_size, m_write_size;
71  bool m_close;
72  bool m_chunked;
73  std::atomic<int> m_refs; // track how many threads are still referring to this
74 
75  std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>> m_ssl_stream;
76 
77 public:
78  connection(std::unique_ptr<boost::asio::ip::tcp::socket> socket, http_linux_server* server, hostport_listener* parent, bool is_https, const std::function<void(boost::asio::ssl::context&)>& ssl_context_callback)
79  : m_socket(std::move(socket))
80  , m_request_buf()
81  , m_response_buf()
82  , m_p_server(server)
83  , m_p_parent(parent)
84  , m_refs(1)
85  {
86  if (is_https)
87  {
88  boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23);
89  ssl_context_callback(ssl_context);
90  m_ssl_stream = utility::details::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>(*m_socket, ssl_context);
91  m_ssl_stream->async_handshake(boost::asio::ssl::stream_base::server, [this](const boost::system::error_code&) { this->start_request_response(); });
92  }
93  else
94  {
95  start_request_response();
96  }
97  }
98 
99  connection(const connection&) = delete;
100  connection& operator=(const connection&) = delete;
101 
102  void close();
103 
104 private:
105  void start_request_response();
106  void handle_http_line(const boost::system::error_code& ec);
107  void handle_headers();
108  void handle_body(const boost::system::error_code& ec);
109  void handle_chunked_header(const boost::system::error_code& ec);
110  void handle_chunked_body(const boost::system::error_code& ec, int toWrite);
111  void dispatch_request_to_listener();
112  void do_response(bool bad_request);
113  void async_write(ResponseFuncPtr response_func_ptr, const http_response &response);
114  template <typename CompletionCondition, typename Handler>
115  void async_read(CompletionCondition &&condition, Handler &&read_handler);
116  void async_read_until();
117  template <typename ReadHandler>
118  void async_read_until_buffersize(size_t size, const ReadHandler &handler);
119  void async_process_response(http_response response);
120  void cancel_sending_response_with_error(const http_response &response, const std::exception_ptr &);
121  void handle_headers_written(const http_response &response, const boost::system::error_code& ec);
122  void handle_write_large_response(const http_response &response, const boost::system::error_code& ec);
123  void handle_write_chunked_response(const http_response &response, const boost::system::error_code& ec);
124  void handle_response_written(const http_response &response, const boost::system::error_code& ec);
125  void finish_request_response();
126 };
127 
129 {
130 private:
131  friend class connection;
132 
133  std::unique_ptr<boost::asio::ip::tcp::acceptor> m_acceptor;
134  std::map<std::string, web::http::experimental::listener::details::http_listener_impl* > m_listeners;
136 
137  pplx::extensibility::recursive_lock_t m_connections_lock;
138  pplx::extensibility::event_t m_all_connections_complete;
139  std::set<connection*> m_connections;
140 
141  http_linux_server* m_p_server;
142 
143  std::string m_host;
144  std::string m_port;
145 
146  bool m_is_https;
147  const std::function<void(boost::asio::ssl::context&)>& m_ssl_context_callback;
148 
149 public:
150  hostport_listener(http_linux_server* server, const std::string& hostport, bool is_https, const http_listener_config& config)
151  : m_acceptor()
152  , m_listeners()
153  , m_listeners_lock()
154  , m_connections_lock()
155  , m_connections()
156  , m_p_server(server)
157  , m_is_https(is_https)
158  , m_ssl_context_callback(config.get_ssl_context_callback())
159  {
160  m_all_connections_complete.set();
161 
162  std::istringstream hostport_in(hostport);
163  hostport_in.imbue(std::locale::classic());
164 
165  std::getline(hostport_in, m_host, ':');
166  std::getline(hostport_in, m_port);
167  }
168 
170  {
171  stop();
172  }
173 
174  void start();
175  void stop();
176 
177  void add_listener(const std::string& path, web::http::experimental::listener::details::http_listener_impl* listener);
178  void remove_listener(const std::string& path, web::http::experimental::listener::details::http_listener_impl* listener);
179 
180 private:
181  void on_accept(boost::asio::ip::tcp::socket* socket, const boost::system::error_code& ec);
182 
183 };
184 
185 }
186 
187 struct iequal_to
188 {
189  bool operator()(const std::string& left, const std::string& right) const
190  {
191  return boost::ilexicographical_compare(left, right);
192  }
193 };
194 
196 {
197 private:
199 
201  std::map<std::string, std::unique_ptr<details::hostport_listener>, iequal_to> m_listeners;
202  std::unordered_map<details::http_listener_impl *, std::unique_ptr<pplx::extensibility::reader_writer_lock_t>> m_registered_listeners;
203  bool m_started;
204 
205 public:
207  : m_listeners_lock()
208  , m_listeners()
209  , m_started(false)
210  {}
211 
213  {
214  stop();
215  }
216 
217  virtual pplx::task<void> start();
218  virtual pplx::task<void> stop();
219 
222 
224 };
225 
226 }}}}
Configuration class used to set various options when constructing and http_listener instance...
Definition: http_listener.h:54
The task_completion_event class allows you to delay the execution of a task until a condition is sati...
Definition: pplxtasks.h:2934
Represents an HTTP response.
Definition: http_msg.h:383
The web namespace contains functionality common to multiple protocols like HTTP and WebSockets...
Definition: base_uri.h:37
virtual pplx::task< void > stop()
Stop processing and listening for incoming requests.
Definition: http_server_asio.h:187
Recursive mutex
Definition: pplxlinux.h:196
The Parallel Patterns Library (PPL) task class. A task object represents work that can be executed as...
Definition: pplxtasks.h:4173
const std::function< void(boost::asio::ssl::context &)> & get_ssl_context_callback() const
Get the callback of ssl context
Definition: http_listener.h:142
Manual reset event
Definition: pplxlinux.h:84
Represents an HTTP request.
Definition: http_msg.h:771
Reader writer lock
Definition: pplxlinux.h:140
Internal class for pointer to implementation design pattern.
Definition: http_listener.h:171
Base structure for associating internal server information with an HTTP request/response.
Definition: http_msg.h:338
Interface http listeners interact with for receiving and responding to http requests.
Definition: http_server.h:42
virtual pplx::task< void > start()
Start listening for incoming requests.
pplx::task< void > respond(http::http_response response)
Asynchronously sends the specified http response.