1 /* 2 * Copyright (c) 2014, Peter Thorson. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * * Neither the name of the WebSocket++ Project nor the 12 * names of its contributors may be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 #ifndef WEBSOCKETPP_CLIENT_ENDPOINT_HPP 29 #define WEBSOCKETPP_CLIENT_ENDPOINT_HPP 30 31 #include <websocketpp/endpoint.hpp> 32 #include <websocketpp/uri.hpp> 33 34 #include <websocketpp/logger/levels.hpp> 35 36 #include <websocketpp/common/system_error.hpp> 37 38 #include <string> 39 40 namespace websocketpp { 41 42 /// Client endpoint role based on the given config 43 /** 44 * 45 */ 46 template <typename config> 47 class client : public endpoint<connection<config>,config> { 48 public: 49 /// Type of this endpoint 50 typedef client<config> type; 51 52 /// Type of the endpoint concurrency component 53 typedef typename config::concurrency_type concurrency_type; 54 /// Type of the endpoint transport component 55 typedef typename config::transport_type transport_type; 56 57 /// Type of the connections this server will create 58 typedef connection<config> connection_type; 59 /// Type of a shared pointer to the connections this server will create 60 typedef typename connection_type::ptr connection_ptr; 61 62 /// Type of the connection transport component 63 typedef typename transport_type::transport_con_type transport_con_type; 64 /// Type of a shared pointer to the connection transport component 65 typedef typename transport_con_type::ptr transport_con_ptr; 66 67 /// Type of the endpoint component of this server 68 typedef endpoint<connection_type,config> endpoint_type; 69 70 friend class connection<config>; 71 client()72 explicit client() : endpoint_type(false) 73 { 74 endpoint_type::m_alog.write(log::alevel::devel, "client constructor"); 75 } 76 77 /// Get a new connection 78 /** 79 * Creates and returns a pointer to a new connection to the given URI 80 * suitable for passing to connect(connection_ptr). This method allows 81 * applying connection specific settings before performing the opening 82 * handshake. 83 * 84 * @param [in] location URI to open the connection to as a uri_ptr 85 * @param [out] ec An status code indicating failure reasons, if any 86 * 87 * @return A connection_ptr to the new connection 88 */ get_connection(uri_ptr location,lib::error_code & ec)89 connection_ptr get_connection(uri_ptr location, lib::error_code & ec) { 90 if (location->get_secure() && !transport_type::is_secure()) { 91 ec = error::make_error_code(error::endpoint_not_secure); 92 return connection_ptr(); 93 } 94 95 connection_ptr con = endpoint_type::create_connection(); 96 97 if (!con) { 98 ec = error::make_error_code(error::con_creation_failed); 99 return con; 100 } 101 102 con->set_uri(location); 103 104 ec = lib::error_code(); 105 return con; 106 } 107 108 /// Get a new connection (string version) 109 /** 110 * Creates and returns a pointer to a new connection to the given URI 111 * suitable for passing to connect(connection_ptr). This overload allows 112 * default construction of the uri_ptr from a standard string. 113 * 114 * @param [in] u URI to open the connection to as a string 115 * @param [out] ec An status code indicating failure reasons, if any 116 * 117 * @return A connection_ptr to the new connection 118 */ get_connection(std::string const & u,lib::error_code & ec)119 connection_ptr get_connection(std::string const & u, lib::error_code & ec) { 120 uri_ptr location = lib::make_shared<uri>(u); 121 122 if (!location->get_valid()) { 123 ec = error::make_error_code(error::invalid_uri); 124 return connection_ptr(); 125 } 126 127 return get_connection(location, ec); 128 } 129 130 /// Begin the connection process for the given connection 131 /** 132 * Initiates the opening connection handshake for connection con. Exact 133 * behavior depends on the underlying transport policy. 134 * 135 * @param con The connection to connect 136 * 137 * @return The pointer to the connection originally passed in. 138 */ connect(connection_ptr con)139 connection_ptr connect(connection_ptr con) { 140 // Ask transport to perform a connection 141 transport_type::async_connect( 142 lib::static_pointer_cast<transport_con_type>(con), 143 con->get_uri(), 144 lib::bind( 145 &type::handle_connect, 146 this, 147 con, 148 lib::placeholders::_1 149 ) 150 ); 151 152 return con; 153 } 154 private: 155 // handle_connect handle_connect(connection_ptr con,lib::error_code const & ec)156 void handle_connect(connection_ptr con, lib::error_code const & ec) { 157 if (ec) { 158 con->terminate(ec); 159 160 endpoint_type::m_elog.write(log::elevel::rerror, 161 "handle_connect error: "+ec.message()); 162 } else { 163 endpoint_type::m_alog.write(log::alevel::connect, 164 "Successful connection"); 165 166 con->start(); 167 } 168 } 169 }; 170 171 } // namespace websocketpp 172 173 #endif //WEBSOCKETPP_CLIENT_ENDPOINT_HPP 174