1 // This may look like C code, but it's really -*- C++ -*- 2 /* 3 * Copyright (C) 2008 Emweb bv, Herent, Belgium. 4 * 5 * All rights reserved. 6 */ 7 // 8 // connection.hpp 9 // ~~~~~~~~~~~~~~ 10 // 11 // Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com) 12 // 13 // Distributed under the Boost Software License, Version 1.0. (See accompanying 14 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 15 // 16 17 #ifndef HTTP_CONNECTION_HPP 18 #define HTTP_CONNECTION_HPP 19 20 #include <Wt/AsioWrapper/asio.hpp> 21 #include <Wt/AsioWrapper/strand.hpp> 22 #include <Wt/AsioWrapper/steady_timer.hpp> 23 24 #include "Buffer.h" 25 #include "Reply.h" 26 #include "Request.h" 27 #include "RequestHandler.h" 28 #include "RequestParser.h" 29 30 #include "Wt/WFlags.h" 31 32 namespace http { 33 namespace server { 34 35 namespace asio = Wt::AsioWrapper::asio; 36 37 class ConnectionManager; 38 class Server; 39 40 /// Represents a single connection from a client. 41 class Connection : public std::enable_shared_from_this<Connection> 42 { 43 public: 44 /// Construct a connection with the given io_service. 45 Connection(asio::io_service& io_service, Server *server, 46 ConnectionManager& manager, RequestHandler& handler); 47 48 Connection(const Connection& other) = delete; 49 50 /// Get the socket associated with the connection. 51 virtual asio::ip::tcp::socket& socket() = 0; 52 53 /// Start the first asynchronous operation for the connection. 54 virtual void start(); 55 56 void close(); 57 bool closed() const; 58 59 /// Like CGI's Url scheme: http or https 60 virtual const char *urlScheme() = 0; 61 62 virtual ~Connection(); 63 server()64 Server *server() const { return server_; } strand()65 Wt::AsioWrapper::strand& strand() { return strand_; } 66 67 /// Stop all asynchronous operations associated with the connection. 68 void scheduleStop(); 69 70 #ifdef HTTP_WITH_SSL registerSslHandle(SSL * ssl)71 void registerSslHandle(SSL *ssl) { request_.ssl = ssl; } 72 #endif 73 waitingResponse()74 bool waitingResponse() const { return waitingResponse_; } setHaveResponse()75 void setHaveResponse() { haveResponse_ = true; } 76 void startWriteResponse(ReplyPtr reply); 77 78 void handleReadBody(ReplyPtr reply); 79 void readMore(ReplyPtr reply, int timeout); 80 bool readAvailable(); 81 82 // NOTE: detectDisconnect will only register one callback at a time, 83 // further calls to detectDisconnect are ignored 84 void detectDisconnect(ReplyPtr reply, 85 const std::function<void()>& callback); 86 void asyncDetectDisconnect(ReplyPtr reply, 87 const std::function<void()>& callback); 88 89 protected: 90 /// Get the native handle of the socket 91 #if (defined(WT_ASIO_IS_BOOST_ASIO) && BOOST_VERSION >= 106600) || (defined(WT_ASIO_IS_STANDALONE_ASIO) && ASIO_VERSION >= 101100) 92 asio::ip::tcp::socket::native_handle_type native(); 93 #else 94 asio::ip::tcp::socket::native_type native(); 95 #endif 96 97 void handleWriteResponse0(ReplyPtr reply, 98 const Wt::AsioWrapper::error_code& e, 99 std::size_t bytes_transferred); 100 void handleWriteResponse(ReplyPtr reply); 101 void handleReadRequest(const Wt::AsioWrapper::error_code& e, 102 std::size_t bytes_transferred); 103 /// Process read buffer, reading request. 104 void handleReadRequest0(); 105 void handleReadBody0(ReplyPtr reply, 106 const Wt::AsioWrapper::error_code& e, 107 std::size_t bytes_transferred); 108 109 void setReadTimeout(int seconds); 110 void setWriteTimeout(int seconds); 111 112 /// The manager for this connection. 113 ConnectionManager& ConnectionManager_; 114 115 Wt::AsioWrapper::strand strand_; 116 117 void finishReply(); 118 119 enum State { 120 Idle = 0x0, 121 Reading = 0x1, 122 Writing = 0x2 123 }; 124 125 Wt::WFlags<State> state_; 126 127 virtual void stop(); 128 129 private: 130 /* 131 * Asynchronoulsy reading a request 132 */ 133 virtual void startAsyncReadRequest(Buffer& buffer, int timeout) = 0; 134 135 /* 136 * Asynchronoulsy reading a request body 137 */ 138 virtual void startAsyncReadBody(ReplyPtr reply, Buffer& buffer, 139 int timeout) = 0; 140 141 /* 142 * Asynchronoulsy writing a response 143 */ 144 virtual void startAsyncWriteResponse(ReplyPtr reply, 145 const std::vector<asio::const_buffer>& buffers, 146 int timeout) = 0; 147 148 /// Generic I/O error handling: closes the connection and cancels timers 149 void handleError(const Wt::AsioWrapper::error_code& e); 150 151 void sendStockReply(Reply::status_type code); 152 153 /// The handler used to process the incoming request. 154 RequestHandler& request_handler_; 155 156 void cancelReadTimer(); 157 void cancelWriteTimer(); 158 159 void timeout(const Wt::AsioWrapper::error_code& e); 160 void doTimeout(); 161 162 /// Timer for reading data. 163 asio::steady_timer readTimer_, writeTimer_; 164 165 /// Current request buffer data 166 std::list<Buffer> rcv_buffers_; 167 168 /// Size of last buffer and iterator for next request in last buffer 169 std::size_t rcv_buffer_size_; 170 char *rcv_remaining_; 171 bool rcv_body_buffer_; 172 173 /// The incoming request. 174 Request request_; 175 176 /// The parser for the incoming request. 177 RequestParser request_parser_; 178 179 /// Recycled reply pointers 180 ReplyPtr lastWtReply_, lastProxyReply_, lastStaticReply_; 181 182 /// The server that owns this connection 183 Server *server_; 184 185 /// Indicates that we're waiting for a response while invoking a 186 /// Reply function and thus that Reply function should not start a 187 /// write response but simply indicate haveResponse_ 188 bool waitingResponse_; 189 190 /// Indicates that we can send a response 191 bool haveResponse_; 192 193 /// Indicates that the current response is finished (after the 194 /// current write operation) 195 bool responseDone_; 196 197 std::function<void()> disconnectCallback_; 198 }; 199 200 typedef std::shared_ptr<Connection> ConnectionPtr; 201 202 } // namespace server 203 } // namespace http 204 205 #endif // HTTP_CONNECTION_HPP 206