adds connection client methods for adding subprotocols to the handshake request

This commit is contained in:
Peter Thorson
2013-04-07 12:18:03 -05:00
parent a9b30b6b07
commit 1e97e3dcf5
5 changed files with 145 additions and 7 deletions

View File

@@ -36,7 +36,7 @@ Implimented, needs more testing
- exception/error handling
- Logging
- Client role
- Server subprotocol negotiation
- Subprotocol negotiation
Implimented, API not finalized
- open_handler
@@ -46,7 +46,6 @@ Implimented, API not finalized
Needs work:
- PowerPC support
- Client subprotocol negotiation
- Extension support
- permessage_compress extension
- Visual Studio / Windows support

View File

@@ -133,7 +133,63 @@ BOOST_AUTO_TEST_CASE( connect_con ) {
channel2 >> *con;
}
BOOST_AUTO_TEST_CASE( select_subprotocol ) {
client c;
websocketpp::lib::error_code ec;
using websocketpp::error::make_error_code;
connection_ptr con = c.get_connection("ws://localhost/", ec);
BOOST_CHECK( con );
con->select_subprotocol("foo",ec);
BOOST_CHECK_EQUAL( ec , make_error_code(websocketpp::error::server_only) );
BOOST_CHECK_THROW( con->select_subprotocol("foo") , websocketpp::lib::error_code );
}
BOOST_AUTO_TEST_CASE( add_subprotocols_invalid ) {
client c;
websocketpp::lib::error_code ec;
using websocketpp::error::make_error_code;
connection_ptr con = c.get_connection("ws://localhost/", ec);
BOOST_CHECK( con );
con->add_subprotocol("",ec);
BOOST_CHECK_EQUAL( ec , make_error_code(websocketpp::error::invalid_subprotocol) );
BOOST_CHECK_THROW( con->add_subprotocol("") , websocketpp::lib::error_code );
con->add_subprotocol("foo,bar",ec);
BOOST_CHECK_EQUAL( ec , make_error_code(websocketpp::error::invalid_subprotocol) );
BOOST_CHECK_THROW( con->add_subprotocol("foo,bar") , websocketpp::lib::error_code );
}
BOOST_AUTO_TEST_CASE( add_subprotocols ) {
client c;
websocketpp::lib::error_code ec;
std::stringstream out;
std::string o;
c.register_ostream(&out);
connection_ptr con = c.get_connection("ws://localhost/", ec);
BOOST_CHECK( con );
con->add_subprotocol("foo",ec);
BOOST_CHECK( !ec );
BOOST_CHECK_NO_THROW( con->add_subprotocol("bar") );
c.connect(con);
o = out.str();
websocketpp::http::parser::request r;
r.consume(o.data(),o.size());
std::cout << o << std::endl;
BOOST_CHECK( r.ready() );
BOOST_CHECK_EQUAL( r.get_header("Sec-WebSocket-Protocol"), "foo, bar");
}

View File

@@ -39,11 +39,11 @@
#include <websocketpp/processors/processor.hpp>
#include <websocketpp/transport/base/connection.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <vector>
namespace websocketpp {
@@ -542,6 +542,35 @@ public:
*/
const std::vector<std::string> & get_requested_subprotocols() const;
/// Adds the given subprotocol string to the request list (exception free)
/**
* Adds a subprotocol to the list to send with the opening handshake. This
* may be called multiple times to request more than one. If the server
* supports one of these, it may choose one. If so, it will return it
* in it's handshake reponse and the value will be available via
* get_subprotocol(). Subprotocol requests should be added in order of
* preference.
*
* @param request The subprotocol to request
*
* @param ec A reference to an error code that will be filled in the case of
* errors
*/
void add_subprotocol(const std::string &request, lib::error_code & ec);
/// Adds the given subprotocol string to the request list
/**
* Adds a subprotocol to the list to send with the opening handshake. This
* may be called multiple times to request more than one. If the server
* supports one of these, it may choose one. If so, it will return it
* in it's handshake reponse and the value will be available via
* get_subprotocol(). Subprotocol requests should be added in order of
* preference.
*
* @param request The subprotocol to request
*/
void add_subprotocol(const std::string &request);
/// Select a subprotocol to use (exception free)
/**
* Indicates which subprotocol should be used for this connection. Valid
@@ -549,6 +578,8 @@ public:
* been requested by the client. Consult get_requested_subprotocols() for a
* list of valid subprotocols.
*
* This member function is valid on server endpoints/connections only
*
* @param value The subprotocol to select
*
* @param ec A reference to an error code that will be filled in the case of
@@ -563,6 +594,8 @@ public:
* been requested by the client. Consult get_requested_subprotocols() for a
* list of valid subprotocols.
*
* This member function is valid on server endpoints/connections only
*
* @param value The subprotocol to select
*/
void select_subprotocol(const std::string & value);

View File

@@ -77,6 +77,9 @@ enum value {
/// Invalid UTF-8
invalid_utf8,
/// Invalid subprotocol
invalid_subprotocol,
/// Bad or unknown connection
bad_connection,
@@ -87,7 +90,13 @@ enum value {
con_creation_failed,
/// Selected subprotocol was not requested by the client
unrequested_subprotocol
unrequested_subprotocol,
/// Attempted to use a client specific feature on a server endpoint
client_only,
/// Attempted to use a server specific feature on a client endpoint
server_only,
}; // enum value
@@ -125,6 +134,8 @@ public:
return "Extracted close code is in a reserved range";
case error::invalid_utf8:
return "Invalid UTF-8";
case error::invalid_subprotocol:
return "Invalid subprotocol";
case error::bad_connection:
return "Bad Connection";
case error::test:
@@ -133,6 +144,10 @@ public:
return "Connection creation attempt failed";
case error::unrequested_subprotocol:
return "Selected subprotocol was not requested by the client";
case error::client_only:
return "Feature not available on server endpoints";
case error::server_only:
return "Feature not available on client endpoints";
default:
return "Unknown";
}

View File

@@ -327,10 +327,45 @@ connection<config>::get_requested_subprotocols() const {
return m_requested_subprotocols;
}
template <typename config>
void connection<config>::add_subprotocol(const std::string & value,
lib::error_code & ec)
{
if (m_is_server) {
ec = error::make_error_code(error::client_only);
return;
}
// If the value is empty or has a non-RFC2616 token character it is invalid.
if (value.empty() || std::find_if(value.begin(),value.end(),
http::is_not_token_char) != value.end())
{
ec = error::make_error_code(error::invalid_subprotocol);
return;
}
m_requested_subprotocols.push_back(value);
}
template <typename config>
void connection<config>::add_subprotocol(const std::string & value) {
lib::error_code ec;
this->add_subprotocol(value,ec);
if (ec) {
throw ec;
}
}
template <typename config>
void connection<config>::select_subprotocol(const std::string & value,
lib::error_code & ec)
{
if (!m_is_server) {
ec = error::make_error_code(error::server_only);
return;
}
if (value.empty()) {
ec = lib::error_code();
return;