more work, compiles and passes tests now

This commit is contained in:
Peter Thorson
2011-10-30 07:43:59 -05:00
parent 95fe9d8966
commit d806bea762
14 changed files with 485 additions and 152 deletions

View File

@@ -28,10 +28,9 @@
# It's authors were Jonathan Wallace and Bernhard Fluehmann.
objects = websocket_server_session.o websocket_client_session.o websocket_session.o websocket_server.o websocket_client.o websocket_frame.o \
network_utilities.o sha1.o base64.o
objects = network_utilities.o sha1.o base64.o
libs = -lboost_system -lboost_date_time -lboost_regex -lboost_random
libs = -lboost_system -lboost_date_time -lboost_regex -lboost_random -lboost_program_options
OS=$(shell uname)

View File

@@ -5,7 +5,7 @@ CXX ?= c++
SHARED ?= "1"
ifeq ($(SHARED), 1)
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lwebsocketpp
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_program_options -lwebsocketpp
else
LDFLAGS := $(LDFLAGS) -lboost_system -lboost_date_time -lboost_regex -lboost_random -lboost_program_options ../../libwebsocketpp.a
endif

View File

@@ -25,17 +25,3 @@
*
*/
#include "echo.hpp"
using websocketecho::echo_server_handler;
void echo_server_handler::validate(websocketpp::session_ptr client) {}
void echo_server_handler::on_message(websocketpp::session_ptr client, const std::string &msg) {
client->send(msg);
}
void echo_server_handler::on_message(websocketpp::session_ptr client,
const std::vector<unsigned char> &data) {
client->send(data);
}

View File

@@ -34,17 +34,20 @@
#include <string>
#include <vector>
using websocketpp::session_ptr;
namespace websocketecho {
class echo_server_handler : public websocketpp::connection_handler {
template <typename session_type>
class echo_server_handler : public websocketpp::connection_handler<session_type> {
public:
//typedef boost::shared_ptr<echo_server_handler<session_type> >
//typedef typename websocketpp::connection_handler<session_type>::ptr session_ptr;
typedef typename websocketpp::connection_handler<session_type>::session_ptr session_ptr;
echo_server_handler() {}
virtual ~echo_server_handler() {}
// The echo server allows all domains is protocol free.
void validate(session_ptr client);
void validate(session_ptr client) {}
// an echo server is stateless.
// The handler has no need to keep track of connected clients.
@@ -53,13 +56,15 @@ public:
void on_close(session_ptr client) {}
// both text and binary messages are echoed back to the sending client.
void on_message(session_ptr client,const std::string &msg);
void on_message(session_ptr client,const std::string &msg) {
client->send(msg);
}
void on_message(session_ptr client,
const std::vector<unsigned char> &data);
const std::vector<unsigned char> &data) {
client->send(data);
}
};
typedef boost::shared_ptr<echo_server_handler> echo_server_handler_ptr;
}
#endif // ECHO_SERVER_HANDLER_HPP

View File

@@ -50,15 +50,22 @@ int main(int argc, char* argv[]) {
temp << host << ":" << port;
full_host = temp.str();
websocketecho::echo_server_handler_ptr echo_handler(new websocketecho::echo_server_handler());
try {
boost::asio::io_service io_service;
tcp::endpoint endpoint(tcp::v6(), port);
websocketpp::server_ptr server(
new websocketpp::server<>(io_service,endpoint,echo_handler)
);
using websocketpp::server;
typedef boost::shared_ptr< server<> > server_ptr;
//typedef server<>::ptr server_ptr;
server_ptr s(new server<>(io_service,endpoint));
server<>::connection_handler_ptr handler = s->make_handler<websocketecho::echo_server_handler>();
s->set_default_connection_handler(handler);
//server->parse_command_line(argc, argv);
@@ -68,10 +75,10 @@ int main(int argc, char* argv[]) {
// bump up max message size to maximum since we may be using the echo
// server to test performance and protocol extremes.
server->set_max_message_size(websocketpp::frame::PAYLOAD_64BIT_LIMIT);
s->set_max_message_size(websocketpp::frame::limits::PAYLOAD_SIZE_JUMBO);
// start the server
server->start_accept();
s->start_accept();
std::cout << "Starting echo server on " << full_host << std::endl;

View File

@@ -26,13 +26,3 @@
* This Makefile was derived from a similar one included in the libjson project
* It's authors were Jonathan Wallace and Bernhard Fluehmann.
*/
#include "blank_rng.hpp"
using websocketpp::blank_rng;
blank_rng::blank_rng() {}
int32_t blank_rng::gen() {
throw "Random Number generation not supported";
}

View File

@@ -36,8 +36,9 @@ namespace websocketpp {
class blank_rng {
public:
blank_rng();
int32_t gen();
int32_t gen() {
throw "Random Number generation not supported";
}
};
}

View File

@@ -33,17 +33,16 @@
#include <string>
#include <map>
namespace websocketpp {
class connection_handler;
typedef boost::shared_ptr<connection_handler> connection_handler_ptr;
}
#include "websocket_session.hpp"
namespace websocketpp {
template <typename session_type>
class connection_handler {
public:
typedef connection_handler<session_type> connection_handler_type;
typedef boost::shared_ptr<connection_handler_type> ptr;
typedef boost::shared_ptr<session_type> session_ptr;
// validate will be called after a websocket handshake has been received and
// before it is accepted. It provides a handler the ability to refuse a
// connection based on application specific logic (ex: restrict domains or

View File

@@ -32,6 +32,10 @@
#include <stdint.h>
// for exceptions that should be somewhere else
#include <string>
#include <exception>
// Defaults
namespace websocketpp {
const uint64_t DEFAULT_MAX_MESSAGE_SIZE = 0xFFFFFF; // ~16MB
@@ -151,6 +155,20 @@ namespace websocketpp {
static const uint64_t PAYLOAD_SIZE_JUMBO = 0x7FFFFFFFFFFFFFFF;//2^63
}
}
// TODO: these classes need a better place to live
class server_error : public std::exception {
public:
server_error(const std::string& msg)
: m_msg(msg) {}
~server_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
private:
std::string m_msg;
};
}
#endif // WEBSOCKET_CONSTANTS_HPP

View File

@@ -534,7 +534,10 @@ public:
if (payload_size > max_payload_size) {
// TODO: frame/message size limits
throw websocketpp::server_error("got frame with payload greater than maximum frame buffer size.");
// TODO: find a way to throw a server error without coupling frame
// with server
// throw websocketpp::server_error("got frame with payload greater than maximum frame buffer size.");
throw "Got frame with payload greater than maximum frame buffer size.";
}
m_payload.resize(payload_size);
m_bytes_needed = payload_size;

View File

@@ -36,11 +36,6 @@ namespace po = boost::program_options;
#include <set>
namespace websocketpp {
//class server;
//typedef boost::shared_ptr<server> server_ptr;
}
#include "websocketpp.hpp"
#include "websocket_session.hpp"
#include "websocket_connection_handler.hpp"
@@ -53,34 +48,28 @@ using boost::asio::ip::tcp;
namespace websocketpp {
class server_error : public std::exception {
public:
server_error(const std::string& msg)
: m_msg(msg) {}
~server_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
private:
std::string m_msg;
};
template <class rng_policy = blank_rng>
template <typename rng_policy = blank_rng>
class server : public boost::enable_shared_from_this< server<rng_policy> > {
public:
typedef boost::shared_ptr< server<rng_policy> > ptr;
typedef rng_policy rng_t;
typedef server<rng_policy> server_type;
typedef session<server_type> session_type;
typedef connection_handler<session_type> connection_handler_type;
typedef boost::shared_ptr<server_type> ptr;
typedef boost::shared_ptr<session_type> session_ptr;
typedef boost::shared_ptr<connection_handler_type> connection_handler_ptr;
server<rng_policy>(boost::asio::io_service& io_service,
const tcp::endpoint& endpoint,
connection_handler_ptr defc)
const tcp::endpoint& endpoint)
: m_elog_level(LOG_ALL),
m_alog_level(ALOG_ALL),
m_max_message_size(DEFAULT_MAX_MESSAGE_SIZE),
m_io_service(io_service),
m_acceptor(io_service, endpoint),
m_def_con_handler(defc),
m_desc("websocketpp::server")
{
m_desc.add_options()
@@ -90,13 +79,21 @@ public:
;
}
void set_default_connection_handler(connection_handler_ptr c) {
m_def_con_handler = c;
}
// creates a new session object and connects the next websocket
// connection to it.
void start_accept() {
if (m_def_con_handler == connection_handler_ptr()) {
throw server_error("start_accept called before a connection handler was set");
}
// TODO: sanity check whether the session buffer size bound could be reduced
session<server<rng_policy> >::ptr new_session(
new session<server<rng_policy> >(
shared_from_this(),
session_ptr new_session(
new session_type(
server_type::shared_from_this(),
m_io_service,
m_def_con_handler,
m_max_message_size*2
@@ -106,26 +103,20 @@ public:
m_acceptor.async_accept(
new_session->socket(),
boost::bind(
&server::handle_accept,
shared_from_this(),
&server_type::handle_accept,
server_type::shared_from_this(),
new_session,
boost::asio::placeholders::error
)
);
}
// INTERFACE FOR LOCAL APPLICATIONS
// Add or remove a host string (host:port) to the list of acceptable
// hosts to accept websocket connections from. Additions/deletions here
// only affect new connections.
void add_host(std::string host) {
m_hosts.insert(host);
}
void remove_host(std::string host) {
m_hosts.erase(host);
template <template <class> class T>
connection_handler_ptr make_handler() {
return boost::shared_ptr< T<session_type> >(new T<session_type>());
}
// INTERFACE FOR LOCAL APPLICATIONS
void set_max_message_size(uint64_t val) {
if (val > frame::limits::PAYLOAD_SIZE_JUMBO) {
std::stringstream err;
@@ -205,15 +196,25 @@ public:
// INTERFACE FOR SESSIONS
static const bool is_server = true;
rng_policy& get_rng() {
return &m_rng;
return m_rng;
}
// Check if this server will respond to this host.
// Confirms that the port in the host string matches the port we are listening
// on. End user application is responsible for checking the /host/ part.
bool validate_host(std::string host) {
if (m_hosts.find(host) == m_hosts.end()) {
return false;
}
// find colon.
// if no colon assume default port
// if port == port
// return true
// else
// return false
// TODO: just check the port. Otherwise user is responsible for checking this
return true;
}
@@ -247,8 +248,7 @@ public:
private:
// if no errors starts the session's read loop and returns to the
// start_accept phase.
void handle_accept(server_session_ptr session,
const boost::system::error_code& error)
void handle_accept(session_ptr session,const boost::system::error_code& error)
{
if (!error) {
session->on_connect();
@@ -266,8 +266,9 @@ private:
private:
uint16_t m_elog_level;
uint16_t m_alog_level;
std::set<std::string> m_hosts;
std::vector<session_ptr> m_sessions;
uint64_t m_max_message_size;
boost::asio::io_service& m_io_service;
tcp::acceptor m_acceptor;

View File

@@ -104,6 +104,7 @@ namespace websocketpp {
#include "websocketpp.hpp"
#include "websocket_frame.hpp"
#include "websocket_server.hpp" // for server error?
#include "websocket_connection_handler.hpp"
#include "base64/base64.h"
@@ -122,19 +123,42 @@ namespace state {
CLOSED = 3
};
}
// Exception classes
class handshake_error : public std::exception {
public:
handshake_error(const std::string& msg,
int http_error,
const std::string& http_msg = "")
: m_msg(msg),m_http_error_code(http_error),m_http_error_msg(http_msg) {}
~handshake_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
std::string m_msg;
int m_http_error_code;
std::string m_http_error_msg;
};
typedef std::map<std::string,std::string> header_list;
template <typename endpoint_policy>
class session : public boost::enable_shared_from_this<session<endpoint_policy> > {
class session : public boost::enable_shared_from_this< session<endpoint_policy> > {
public:
typedef endpoint_policy endpoint_t;
typedef boost::shared_ptr<session<endpoint_policy> > ptr;
typedef endpoint_policy endpoint_type;
typedef session<endpoint_policy> session_type;
typedef connection_handler<session_type> connection_handler_type;
typedef boost::shared_ptr<endpoint_type> endpoint_ptr;
typedef boost::shared_ptr<session_type> ptr;
typedef boost::shared_ptr<connection_handler_type> connection_handler_ptr;
friend class handshake_error;
session (typename endpoint_policy::ptr e,
session (endpoint_ptr e,
boost::asio::io_service& io_service,
connection_handler_ptr defc,
uint64_t buf_size)
@@ -147,6 +171,7 @@ public:
m_dropped_by_me(false),
m_socket(io_service),
m_io_service(io_service),
m_endpoint(e),
m_local_interface(defc),
m_timer(io_service,boost::posix_time::seconds(0)),
m_buf(buf_size), // maximum buffered (unconsumed) bytes from network
@@ -171,7 +196,10 @@ public:
// that come after it are called as a result of an async event completing.
// if any method in this chain returns before adding a new async event the
// session will end.
virtual void on_connect() = 0;
// TODO: this needs to be a template specialization or member of the endpoint
void on_connect() {
read_handshake();
}
// sets the internal connection handler of this connection to new_con.
// This is useful if you want to switch handler objects during a connection
@@ -184,7 +212,7 @@ public:
//m_local_interface->disconnect(shared_from_this(),4000,"Setting new connection handler");
}
m_local_interface = new_con;
m_local_interface->on_open(shared_from_this());
m_local_interface->on_open(session_type::shared_from_this());
}
@@ -199,7 +227,9 @@ public:
const std::string& get_subprotocol() const {
if (m_state == state::CONNECTING) {
log("Subprotocol is not avaliable before the handshake has completed.",LOG_WARN);
throw server_error("Subprotocol is not avaliable before the handshake has completed.");
// TODO: fix server_error
//throw server_error("Subprotocol is not avaliable before the handshake has completed.");
throw "Subprotocol is not avaliable before the handshake has completed";
}
return m_server_subprotocol;
}
@@ -223,6 +253,48 @@ public:
return m_version;
}
/**** TODO: SERVER SPECIFIC ****/
void set_header(const std::string &key,const std::string &val) {
// TODO: prevent use of reserved headers;
m_server_headers[key] = val;
}
void select_subprotocol(const std::string& val) {
std::vector<std::string>::iterator it;
it = std::find(m_client_subprotocols.begin(),
m_client_subprotocols.end(),
val);
if (val != "" && it == m_client_subprotocols.end()) {
throw server_error("Attempted to choose a subprotocol not proposed by the client");
}
m_server_subprotocol = val;
}
void select_extension(const std::string& val) {
if (val == "") {
return;
}
std::vector<std::string>::iterator it;
it = std::find(m_client_extensions.begin(),
m_client_extensions.end(),
val);
if (it == m_client_extensions.end()) {
throw server_error("Attempted to choose an extension not proposed by the client");
}
m_server_extensions.push_back(val);
}
/********/
/*** SESSION INTERFACE ***/
// send basic frame types
@@ -278,16 +350,279 @@ public:
send_close(status,reason);
}
virtual bool is_server() const = 0;
bool is_server() const {
return endpoint_type::is_server;
}
// Opening handshake processors and callbacks. These need to be defined in
// derived classes.
virtual void handle_write_handshake(const boost::system::error_code& e) = 0;
virtual void handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred) = 0;
// TODO: endpoint specific
//virtual void handle_write_handshake(const boost::system::error_code& e) = 0;
void handle_write_handshake(const boost::system::error_code& error) {
if (error) {
log_error("Error writing handshake response",error);
drop_tcp();
return;
}
log_open_result();
if (m_server_http_code != 101) {
std::stringstream err;
err << "Handshake ended with HTTP error: " << m_server_http_code << " "
<< (m_server_http_string != "" ? m_server_http_string : lookup_http_error_string(m_server_http_code));
log(err.str(),LOG_ERROR);
drop_tcp();
// TODO: tell client that connection failed.
return;
}
m_state = state::OPEN;
// stop the handshake timer
m_timer.cancel();
if (m_local_interface) {
m_local_interface->on_open(session_type::shared_from_this());
}
reset_message();
this->read_frame();
}
// TODO: endpoint specific
//virtual void handle_read_handshake(const boost::system::error_code& e,std::size_t bytes_transferred) = 0;
void handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred) {
std::ostringstream line;
line << &m_buf;
m_raw_client_handshake += line.str();
access_log(m_raw_client_handshake,ALOG_HANDSHAKE);
std::vector<std::string> tokens;
std::string::size_type start = 0;
std::string::size_type end;
// Get request and parse headers
end = m_raw_client_handshake.find("\r\n",start);
while(end != std::string::npos) {
tokens.push_back(m_raw_client_handshake.substr(start, end - start));
start = end + 2;
end = m_raw_client_handshake.find("\r\n",start);
}
for (size_t i = 0; i < tokens.size(); i++) {
if (i == 0) {
m_client_http_request = tokens[i];
}
end = tokens[i].find(": ",0);
if (end != std::string::npos) {
std::string h = tokens[i].substr(0,end);
if (get_client_header(h) == "") {
m_client_headers[h] = tokens[i].substr(end+2);
} else {
m_client_headers[h] += ", " + tokens[i].substr(end+2);
}
}
}
// handshake error checking
try {
std::stringstream err;
std::string h;
// check the method
if (m_client_http_request.substr(0,4) != "GET ") {
err << "Websocket handshake has invalid method: "
<< m_client_http_request.substr(0,4);
throw(handshake_error(err.str(),400));
}
// check the HTTP version
// TODO: allow versions greater than 1.1
end = m_client_http_request.find(" HTTP/1.1",4);
if (end == std::string::npos) {
err << "Websocket handshake has invalid HTTP version";
throw(handshake_error(err.str(),400));
}
m_resource = m_client_http_request.substr(4,end-4);
// verify the presence of required headers
h = get_client_header("Host");
if (h == "") {
throw(handshake_error("Required Host header is missing",400));
} else if (!m_endpoint->validate_host(h)) {
err << "Host " << h << " is not one of this server's names.";
throw(handshake_error(err.str(),400));
}
h = get_client_header("Upgrade");
if (h == "") {
throw(handshake_error("Required Upgrade header is missing",400));
} else if (!boost::iequals(h,"websocket")) {
err << "Upgrade header was " << h << " instead of \"websocket\"";
throw(handshake_error(err.str(),400));
}
h = get_client_header("Connection");
if (h == "") {
throw(handshake_error("Required Connection header is missing",400));
} else if (!boost::ifind_first(h,"upgrade")) {
err << "Connection header, \"" << h
<< "\", does not contain required token \"upgrade\"";
throw(handshake_error(err.str(),400));
}
if (get_client_header("Sec-WebSocket-Key") == "") {
throw(handshake_error("Required Sec-WebSocket-Key header is missing",400));
}
h = get_client_header("Sec-WebSocket-Version");
if (h == "") {
throw(handshake_error("Required Sec-WebSocket-Version header is missing",400));
} else {
m_version = atoi(h.c_str());
if (m_version != 7 && m_version != 8 && m_version != 13) {
err << "This server doesn't support WebSocket protocol version "
<< m_version;
throw(handshake_error(err.str(),400));
}
}
if (m_version < 13) {
h = get_client_header("Sec-WebSocket-Origin");
} else {
h = get_client_header("Origin");
}
if (h != "") {
m_client_origin = h;
}
// TODO: extract subprotocols
// TODO: extract extensions
// optional headers (delegated to the local interface)
if (m_local_interface) {
m_local_interface->validate(session_type::shared_from_this());
}
m_server_http_code = 101;
m_server_http_string = "Switching Protocols";
} catch (const handshake_error& e) {
std::stringstream err;
err << "Caught handshake exception: " << e.what();
access_log(e.what(),ALOG_HANDSHAKE);
log(err.str(),LOG_ERROR);
m_server_http_code = e.m_http_error_code;
m_server_http_string = e.m_http_error_msg;
}
write_handshake();
}
public: //protected:
virtual void write_handshake() = 0;
virtual void read_handshake() = 0;
// TODO: endpoint specific
void write_handshake() {
std::stringstream h;
if (m_server_http_code == 101) {
std::string server_key = get_client_header("Sec-WebSocket-Key");
server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
SHA1 sha;
uint32_t message_digest[5];
sha.Reset();
sha << server_key.c_str();
if (sha.Result(message_digest)){
// convert sha1 hash bytes to network byte order because this sha1
// library works on ints rather than bytes
for (int i = 0; i < 5; i++) {
message_digest[i] = htonl(message_digest[i]);
}
server_key = base64_encode(
reinterpret_cast<const unsigned char*>(message_digest),20);
// set handshake accept headers
set_header("Sec-WebSocket-Accept",server_key);
set_header("Upgrade","websocket");
set_header("Connection","Upgrade");
} else {
log("Error computing handshake sha1 hash.",LOG_ERROR);
m_server_http_code = 500;
m_server_http_string = "";
}
}
// hardcoded server headers
set_header("Server","WebSocket++/2011-09-25");
h << "HTTP/1.1 " << m_server_http_code << " "
<< (m_server_http_string != "" ? m_server_http_string :
lookup_http_error_string(m_server_http_code))
<< "\r\n";
header_list::iterator it;
for (it = m_server_headers.begin(); it != m_server_headers.end(); it++) {
h << it->first << ": " << it->second << "\r\n";
}
h << "\r\n";
m_raw_server_handshake = h.str();
// start async write to handle_write_handshake
boost::asio::async_write(
m_socket,
boost::asio::buffer(m_raw_server_handshake),
boost::bind(
&session_type::handle_write_handshake,
session_type::shared_from_this(),
boost::asio::placeholders::error
)
);
}
// TODO: endpoint specific
//virtual void read_handshake() = 0;
void read_handshake() {
m_timer.expires_from_now(boost::posix_time::seconds(5));
m_timer.async_wait(
boost::bind(
&session_type::handle_handshake_expired,
session_type::shared_from_this(),
boost::asio::placeholders::error
)
);
boost::asio::async_read_until(
m_socket,
m_buf,
"\r\n\r\n",
boost::bind(
&session_type::handle_read_handshake,
session_type::shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void read_frame() {
// the initial read in the handshake may have read in the first frame.
@@ -335,13 +670,13 @@ public: //protected:
std::stringstream err;
err << "consuming. have: " << m_buf.size() << " bytes. Need: " << m_read_frame.get_bytes_needed() << " state: " << (int)m_read_frame.get_state();
log(err.str(),LOG_DEBUG);
//err << "consuming. have: " << m_buf.size() << " bytes. Need: " << m_read_frame.get_bytes_needed() << " state: " << (int)m_read_frame.get_state();
//log(err.str(),LOG_DEBUG);
m_read_frame.consume(s);
err.str("");
err << "consume complete, " << m_buf.size() << " bytes left, " << m_read_frame.get_bytes_needed() << " still needed, state: " << (int)m_read_frame.get_state();
log(err.str(),LOG_DEBUG);
//err.str("");
//err << "consume complete, " << m_buf.size() << " bytes left, " << m_read_frame.get_bytes_needed() << " still needed, state: " << (int)m_read_frame.get_state();
//log(err.str(),LOG_DEBUG);
if (m_read_frame.ready()) {
// process frame and reset frame state for the next frame.
@@ -408,8 +743,8 @@ public: //protected:
m_buf,
boost::asio::transfer_at_least(m_read_frame.get_bytes_needed()),
boost::bind(
&session::handle_read_frame,
shared_from_this(),
&session<endpoint_policy>::handle_read_frame,
session<endpoint_policy>::shared_from_this(),
boost::asio::placeholders::error
)
);
@@ -418,7 +753,7 @@ public: //protected:
if (m_local_interface) {
// TODO: make sure close code/msg are properly set.
m_local_interface->on_close(shared_from_this());
m_local_interface->on_close(session_type::shared_from_this());
}
m_timer.cancel();
@@ -455,8 +790,8 @@ public: //protected:
m_socket,
data,
boost::bind(
&session::handle_write_frame,
shared_from_this(),
&session<endpoint_policy>::handle_write_frame,
session<endpoint_policy>::shared_from_this(),
boost::asio::placeholders::error
)
);
@@ -671,9 +1006,9 @@ public: //protected:
if (m_current_opcode == frame::opcode::BINARY) {
//log("Dispatching Binary Message",LOG_DEBUG);
if (m_fragmented) {
m_local_interface->on_message(shared_from_this(),m_current_message);
m_local_interface->on_message(session_type::shared_from_this(),m_current_message);
} else {
m_local_interface->on_message(shared_from_this(),
m_local_interface->on_message(session_type::shared_from_this(),
m_read_frame.get_payload());
}
} else if (m_current_opcode == frame::opcode::TEXT) {
@@ -698,7 +1033,7 @@ public: //protected:
}
//log("Dispatching Text Message",LOG_DEBUG);
m_local_interface->on_message(shared_from_this(),msg);
m_local_interface->on_message(session_type::shared_from_this(),msg);
} else {
// Not sure if this should be a fatal error or not
std::stringstream err;
@@ -727,8 +1062,13 @@ public: //protected:
}
// logging
virtual void log(const std::string& msg, uint16_t level) const = 0;
virtual void access_log(const std::string& msg, uint16_t level) const = 0;
// TODO: endpoint specific
void log(const std::string& msg, uint16_t level) const {
m_endpoint->log(msg,level);
}
void access_log(const std::string& msg, uint16_t level) const {
m_endpoint->access_log(msg,level);
}
void log_close_result() {
std::stringstream msg;
@@ -788,8 +1128,8 @@ public: //protected:
m_timer.async_wait(
boost::bind(
&session::handle_close_expired,
shared_from_this(),
&session<endpoint_policy>::handle_close_expired,
session<endpoint_policy>::shared_from_this(),
boost::asio::placeholders::error
)
);
@@ -884,6 +1224,7 @@ protected:
// Connection Resources
tcp::socket m_socket;
boost::asio::io_service& m_io_service;
endpoint_ptr m_endpoint;
connection_handler_ptr m_local_interface;
boost::asio::deadline_timer m_timer;
@@ -905,24 +1246,7 @@ protected:
bool m_error;
};
// Exception classes
class handshake_error : public std::exception {
public:
handshake_error(const std::string& msg,
int http_error,
const std::string& http_msg = "")
: m_msg(msg),m_http_error_code(http_error),m_http_error_msg(http_msg) {}
~handshake_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
std::string m_msg;
int m_http_error_code;
std::string m_http_error_msg;
};
}

View File

@@ -34,7 +34,7 @@
#include "websocket_constants.hpp"
#include "websocket_session.hpp"
//#include "websocket_session.hpp"
//#include "websocket_server_session.hpp"
//#include "websocket_client_session.hpp"
#include "websocket_server.hpp"

View File

@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
B613878F145CA61300ED9B19 /* libboost_date_time.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1CBE1434AF6A0029A1B1 /* libboost_date_time.dylib */; };
B6138790145CA61C00ED9B19 /* libboost_program_options.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6FE8CEB145A0F1900B32547 /* libboost_program_options.dylib */; };
B68288871437460E002BA48B /* chat_client_handler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6828875143745DA002BA48B /* chat_client_handler.cpp */; };
B68288881437460E002BA48B /* chat_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6828877143745DA002BA48B /* chat_client.cpp */; };
B682888914374617002BA48B /* libwebsocketpp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B6DF1C721434A8280029A1B1 /* libwebsocketpp.dylib */; };
@@ -33,11 +35,9 @@
B6DF1C901434AC3E0029A1B1 /* utf8_validator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C8F1434AC3E0029A1B1 /* utf8_validator.hpp */; };
B6DF1C911434AC3E0029A1B1 /* utf8_validator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C8F1434AC3E0029A1B1 /* utf8_validator.hpp */; };
B6DF1CA01434AC470029A1B1 /* websocket_client_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DF1C921434AC470029A1B1 /* websocket_client_session.cpp */; };
B6DF1CA11434AC470029A1B1 /* websocket_client_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DF1C921434AC470029A1B1 /* websocket_client_session.cpp */; };
B6DF1CA21434AC470029A1B1 /* websocket_client_session.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C931434AC470029A1B1 /* websocket_client_session.hpp */; };
B6DF1CA31434AC470029A1B1 /* websocket_client_session.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C931434AC470029A1B1 /* websocket_client_session.hpp */; };
B6DF1CA41434AC470029A1B1 /* websocket_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DF1C941434AC470029A1B1 /* websocket_client.cpp */; };
B6DF1CA51434AC470029A1B1 /* websocket_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DF1C941434AC470029A1B1 /* websocket_client.cpp */; };
B6DF1CA61434AC470029A1B1 /* websocket_client.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C951434AC470029A1B1 /* websocket_client.hpp */; };
B6DF1CA71434AC470029A1B1 /* websocket_client.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C951434AC470029A1B1 /* websocket_client.hpp */; };
B6DF1CA81434AC470029A1B1 /* websocket_connection_handler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C961434AC470029A1B1 /* websocket_connection_handler.hpp */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -47,7 +47,6 @@
B6DF1CAC1434AC470029A1B1 /* websocket_frame.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C981434AC470029A1B1 /* websocket_frame.hpp */; };
B6DF1CAD1434AC470029A1B1 /* websocket_frame.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C981434AC470029A1B1 /* websocket_frame.hpp */; };
B6DF1CAE1434AC470029A1B1 /* websocket_server_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DF1C991434AC470029A1B1 /* websocket_server_session.cpp */; };
B6DF1CAF1434AC470029A1B1 /* websocket_server_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DF1C991434AC470029A1B1 /* websocket_server_session.cpp */; };
B6DF1CB01434AC470029A1B1 /* websocket_server_session.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C9A1434AC470029A1B1 /* websocket_server_session.hpp */; };
B6DF1CB11434AC470029A1B1 /* websocket_server_session.hpp in Headers */ = {isa = PBXBuildFile; fileRef = B6DF1C9A1434AC470029A1B1 /* websocket_server_session.hpp */; };
B6DF1CB21434AC470029A1B1 /* websocket_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B6DF1C9B1434AC470029A1B1 /* websocket_server.cpp */; };
@@ -129,6 +128,7 @@
B6138765145AD1F700ED9B19 /* chat.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = chat.cpp; path = examples/chat_server/chat.cpp; sourceTree = "<group>"; };
B6138766145AD1F700ED9B19 /* chat.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = chat.hpp; path = examples/chat_server/chat.hpp; sourceTree = "<group>"; };
B6138767145AD1F700ED9B19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; name = Makefile; path = examples/chat_server/Makefile; sourceTree = "<group>"; };
B6138791145CA6F700ED9B19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
B6828875143745DA002BA48B /* chat_client_handler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = chat_client_handler.cpp; path = examples/chat_client/chat_client_handler.cpp; sourceTree = "<group>"; };
B6828876143745DA002BA48B /* chat_client_handler.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = chat_client_handler.hpp; path = examples/chat_client/chat_client_handler.hpp; sourceTree = "<group>"; };
B6828877143745DA002BA48B /* chat_client.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = chat_client.cpp; path = examples/chat_client/chat_client.cpp; sourceTree = "<group>"; };
@@ -228,6 +228,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B6138790145CA61C00ED9B19 /* libboost_program_options.dylib in Frameworks */,
B613878F145CA61300ED9B19 /* libboost_date_time.dylib in Frameworks */,
B6DF1CE41435F8250029A1B1 /* Foundation.framework in Frameworks */,
B6DF1CE21435F1860029A1B1 /* libboost_system.dylib in Frameworks */,
B6DF1CDE1435EDF00029A1B1 /* libwebsocketpp.dylib in Frameworks */,
@@ -261,6 +263,7 @@
B6FE8CE4144DE18900B32547 /* documentation */,
B6DF1CC61435ED380029A1B1 /* examples */,
B6DF1CC51435ECE40029A1B1 /* libraries */,
B6138791145CA6F700ED9B19 /* Makefile */,
B6DF1C7F1434ABB70029A1B1 /* src */,
B6DF1C6A1434A7A30029A1B1 /* Products */,
);
@@ -625,10 +628,7 @@
B6DF1CC41434AF9E0029A1B1 /* network_utilities.cpp in Sources */,
B6DF1C841434ABE20029A1B1 /* base64.cpp in Sources */,
B6DF1C8B1434AC330029A1B1 /* sha1.cpp in Sources */,
B6DF1CA11434AC470029A1B1 /* websocket_client_session.cpp in Sources */,
B6DF1CA51434AC470029A1B1 /* websocket_client.cpp in Sources */,
B6DF1CAB1434AC470029A1B1 /* websocket_frame.cpp in Sources */,
B6DF1CAF1434AC470029A1B1 /* websocket_server_session.cpp in Sources */,
B6DF1CB31434AC470029A1B1 /* websocket_server.cpp in Sources */,
B6DF1CB71434AC470029A1B1 /* websocket_session.cpp in Sources */,
);