Merged upstream and resolved confilicts

This commit is contained in:
Sven Almgren
2012-03-14 13:15:01 +01:00
34 changed files with 153 additions and 5249 deletions

View File

@@ -71,8 +71,12 @@ else:
env['BOOST_LIBS']]
platform_libs = []
tls_libs = []
if env['PLATFORM'] == 'posix':
platform_libs = ['pthread', 'rt']
tls_libs = ['ssl', 'crypto']
elif env['PLATFORM'] == 'darwin':
tls_libs = ['ssl', 'crypto']
elif env['PLATFORM'].startswith('win'):
# Win/VC++ supports autolinking. nothing to do.
pass
@@ -85,6 +89,7 @@ builddir = releasedir
Export('env')
Export('platform_libs')
Export('boostlibs')
Export('tls_libs')
## END OF CONFIG !!
@@ -104,3 +109,25 @@ wsperf = SConscript('#/examples/wsperf/SConscript',
echo_server = SConscript('#/examples/echo_server/SConscript',
variant_dir = builddir + 'echo_server',
duplicate = 0)
echo_server_tls = SConscript('#/examples/echo_server_tls/SConscript',
variant_dir = builddir + 'echo_server_tls',
duplicate = 0)
echo_client = SConscript('#/examples/echo_client/SConscript',
variant_dir = builddir + 'echo_client',
duplicate = 0)
chat_client = SConscript('#/examples/chat_client/SConscript',
variant_dir = builddir + 'chat_client',
duplicate = 0)
chat_server = SConscript('#/examples/chat_server/SConscript',
variant_dir = builddir + 'chat_server',
duplicate = 0)
concurrent_server = SConscript('#/examples/concurrent_server/SConscript',
variant_dir = builddir + 'concurrent_server',
duplicate = 0)

View File

@@ -1,5 +1,4 @@
DIRS=broadcast_server_tls chat_client chat_server echo_client echo_server echo_server_tls fuzzing_client fuzzing_server_tls stress_client wsperf
# Broken: concurrent_server
DIRS=broadcast_server_tls chat_client chat_server concurrent_server echo_client echo_server echo_server_tls fuzzing_client fuzzing_server_tls stress_client wsperf
.PHONY:
all: build

View File

@@ -0,0 +1,21 @@
## chat_client
##
Import('env')
Import('boostlibs')
Import('wslib')
Import('platform_libs')
localenv = env.Clone ()
sources = ["chat_client","chat_client_handler.cpp"]
LIBS = [wslib, platform_libs] + boostlibs(['system',
'date_time',
'regex',
'thread',
'random'])
prg = localenv.Program('chat_client', sources, LIBS = LIBS)
Return('prg')

View File

@@ -0,0 +1,20 @@
## chat_server
##
Import('env')
Import('boostlibs')
Import('wslib')
Import('platform_libs')
localenv = env.Clone ()
sources = ["chat_server.cpp","chat.cpp"]
LIBS = [wslib, platform_libs] + boostlibs(['system',
'date_time',
'regex',
'thread'])
prg = localenv.Program('chat_server', sources, LIBS = LIBS)
Return('prg')

View File

@@ -40,7 +40,7 @@ int main(int argc, char* argv[]) {
if (argc == 2) {
// TODO: input validation?
port = atoi(argv[2]);
port = atoi(argv[1]);
}
try {
@@ -50,9 +50,11 @@ int main(int argc, char* argv[]) {
// create a server that listens on port `port` and uses our handler
server endpoint(handler);
endpoint.elog().set_levels(websocketpp::log::elevel::DEVEL,websocketpp::log::elevel::FATAL);
endpoint.alog().set_level(websocketpp::log::alevel::CONNECT);
endpoint.alog().set_level(websocketpp::log::alevel::DISCONNECT);
endpoint.alog().set_level(websocketpp::log::alevel::ALL);
endpoint.elog().set_level(websocketpp::log::elevel::RERROR);
endpoint.elog().set_level(websocketpp::log::elevel::FATAL);
// setup server settings
// Chat server should only be receiving small text messages, reduce max

View File

@@ -1,4 +1,4 @@
BOOST_LIBS=boost_system boost_date_time boost_program_options boost_thread
BOOST_LIBS=boost_system boost_date_time boost_program_options boost_thread boost_regex
include ../common.mk

View File

@@ -0,0 +1,20 @@
## concurrent_server.cpp
##
Import('env')
Import('boostlibs')
Import('wslib')
Import('platform_libs')
localenv = env.Clone ()
sources = ["concurrent_server.cpp"]
LIBS = [wslib, platform_libs] + boostlibs(['system',
'date_time',
'regex',
'thread'])
prg = localenv.Program('concurrent_server', sources, LIBS = LIBS)
Return('prg')

View File

@@ -183,7 +183,7 @@ int main(int argc, char* argv[]) {
echo_endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
echo_endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
echo_endpoint.elog().set_level(websocketpp::log::elevel::ERROR);
echo_endpoint.elog().set_level(websocketpp::log::elevel::RERROR);
echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);
std::list<boost::shared_ptr<boost::thread> > threads;

View File

@@ -0,0 +1,21 @@
## echo_client
##
Import('env')
Import('boostlibs')
Import('wslib')
Import('platform_libs')
localenv = env.Clone ()
sources = ["echo_client.cpp"]
LIBS = [wslib, platform_libs] + boostlibs(['system',
'date_time',
'regex',
'thread',
'random'])
prg = localenv.Program('echo_client', sources, LIBS = LIBS)
Return('prg')

View File

@@ -1,56 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "echo_client_handler.hpp"
#include <boost/algorithm/string/replace.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using websocketecho::echo_client_handler;
using websocketpp::client_session_ptr;
void echo_client_handler::on_open(session_ptr s) {
std::cout << " Successfully connected (handshake complete): " << s->get_resource() << std::endl;
}
void echo_client_handler::on_close(session_ptr s) {
std::cout << " client was disconnected (WS state is now CLOSED)" << std::endl;
}
void echo_client_handler::on_message(session_ptr s,const std::string &msg) {
if (s->get_resource() == "/getCaseCount") {
std::cout << "Detected " << msg << " test cases." << std::endl;
m_case_count = atoi(msg.c_str());
} else {
s->send(msg);
}
}
void echo_client_handler::on_message(session_ptr s,
const std::vector<unsigned char> &data) {
s->send(data);
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef ECHO_CLIENT_HANDLER_HPP
#define ECHO_CLIENT_HANDLER_HPP
// com.zaphoyd.websocketpp.chat protocol
//
// client messages:
// alias [UTF8 text, 16 characters max]
// msg [UTF8 text]
//
// server messages:
// {"type":"msg","sender":"<sender>","value":"<msg>" }
// {"type":"participants","value":[<participant>,...]}
#include <boost/shared_ptr.hpp>
#include "../../src/websocketpp.hpp"
#include "../../src/websocket_connection_handler.hpp"
#include <map>
#include <string>
#include <queue>
namespace websocketecho {
class echo_client_handler : public websocketpp::connection_handler {
public:
echo_client_handler() : m_case_count(0) {}
virtual ~echo_client_handler() {}
// connection to chat room complete
void on_open(session_ptr s);
// connection to chat room closed
void on_close(session_ptr sn);
// got a new message from server
void on_message(session_ptr s,const std::string &msg);
// ignore messages
void on_message(session_ptr s,const std::vector<unsigned char> &data);
int m_case_count;
};
typedef boost::shared_ptr<echo_client_handler> echo_client_handler_ptr;
}
#endif // ECHO_CLIENT_HANDLER_HPP

View File

@@ -1,27 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

View File

@@ -1,32 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef ECHO_SERVER_HANDLER_HPP
#define ECHO_SERVER_HANDLER_HPP
#endif // ECHO_SERVER_HANDLER_HPP

View File

@@ -58,6 +58,7 @@ int main(int argc, char* argv[]) {
echo_endpoint.elog().unset_level(websocketpp::log::elevel::ALL);
echo_endpoint.alog().set_level(websocketpp::log::alevel::CONNECT);
echo_endpoint.alog().set_level(websocketpp::log::alevel::DISCONNECT);
echo_endpoint.elog().set_level(websocketpp::log::elevel::RERROR);
echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);

View File

@@ -0,0 +1,21 @@
## echo_server_tls
##
Import('env')
Import('boostlibs')
Import('wslib')
Import('platform_libs')
Import('tls_libs')
localenv = env.Clone ()
sources = ["echo_server_tls.cpp"]
LIBS = [wslib, platform_libs, tls_libs] + boostlibs(['system',
'date_time',
'regex',
'thread'])
prg = localenv.Program('echo_server_tls', sources, LIBS = LIBS)
Return('prg')

View File

@@ -1,104 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_INTERFACE_CONNECTION_HANDLER_HPP
#define WEBSOCKET_INTERFACE_CONNECTION_HANDLER_HPP
#include <boost/shared_ptr.hpp>
#include <string>
#include <map>
namespace websocketpp {
class connection_handler {
public:
// 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
// negotiate subprotocols). To reject the connection throw a handshake_error
//
// Validate is never called for client sessions. To refuse a client session
// (ex: if you do not like the set of extensions/subprotocols the server
// chose) you can close the connection immediately in the on_open method.
//
// handshake_error parameters:
// log_message - error message to send to server log
// http_error_code - numeric HTTP error code to return to the client
// http_error_msg - (optional) string HTTP error code to return to the
// client (useful for returning non-standard error codes)
virtual void validate(session_ptr session) {};
// on_open is called after the websocket session has been successfully
// established and is in the OPEN state. The session is now avaliable to
// send messages and will begin reading frames and calling the on_message/
// on_close/on_error callbacks. A client may reject the connection by
// closing the session at this point.
virtual void on_open(session_ptr session) = 0;
// on_close is called whenever an open session is closed for any reason.
// This can be due to either endpoint requesting a connection close or an
// error occuring. Information about why the session was closed can be
// extracted from the session itself.
//
// on_close will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_close(session_ptr session) = 0;
// on_message (binary version) will be called when a binary message is
// recieved. Message data is passed as a vector of bytes (unsigned char).
// data will not be avaliable after this callback ends so the handler must
// either completely process the message or copy it somewhere else for
// processing later.
virtual void on_message(session_ptr session,
const std::vector<unsigned char> &data) = 0;
// on_message (text version). Identical to on_message except the data
// parameter is a string interpreted as UTF-8. WebSocket++ guarantees that
// this string is valid UTF-8.
virtual void on_message(session_ptr session,const std::string &msg) = 0;
// #### optional error cases ####
// on_fail is called whenever a session is terminated or failed before it
// was successfully established. This happens if there is an error during
// the handshake process or if the server refused the connection.
//
// on_fail will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_fail(session_ptr session) {};
// experimental
virtual void on_ping_timeout(session_ptr session) {}
};
}
#endif // WEBSOCKET_INTERFACE_CONNECTION_HANDLER_HPP

View File

@@ -1,135 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_INTERFACE_FRAME_PARSER_HPP
#define WEBSOCKET_INTERFACE_FRAME_PARSER_HPP
#include <istream>
#include <stdint.h>
#include <exception>
namespace websocketpp {
namespace frame {
namespace error {
enum value {
FATAL_SESSION_ERROR = 0, // force session end
SOFT_SESSION_ERROR = 1, // should log and ignore
PROTOCOL_VIOLATION = 2, // must end session
PAYLOAD_VIOLATION = 3, // should end session
INTERNAL_SERVER_ERROR = 4, // cleanly end session
MESSAGE_TOO_BIG = 5 // ???
};
}
// Opcodes are 4 bits
// See spec section 5.2
namespace opcode {
enum value {
CONTINUATION = 0x0,
TEXT = 0x1,
BINARY = 0x2,
RSV3 = 0x3,
RSV4 = 0x4,
RSV5 = 0x5,
RSV6 = 0x6,
RSV7 = 0x7,
CLOSE = 0x8,
PING = 0x9,
PONG = 0xA,
CONTROL_RSVB = 0xB,
CONTROL_RSVC = 0xC,
CONTROL_RSVD = 0xD,
CONTROL_RSVE = 0xE,
CONTROL_RSVF = 0xF,
};
inline bool reserved(value v) {
return (v >= RSV3 && v <= RSV7) ||
(v >= CONTROL_RSVB && v <= CONTROL_RSVF);
}
inline bool invalid(value v) {
return (v > 0xF || v < 0);
}
inline bool is_control(value v) {
return v >= 0x8;
}
}
namespace limits {
static const uint8_t PAYLOAD_SIZE_BASIC = 125;
static const uint16_t PAYLOAD_SIZE_EXTENDED = 0xFFFF; // 2^16, 65535
static const uint64_t PAYLOAD_SIZE_JUMBO = 0x7FFFFFFFFFFFFFFF;//2^63
// hardcoded limit
static const uint64_t INTERNAL_MAX_PAYLOAD_SIZE = 100000000; // 100MB
}
class exception : public std::exception {
public:
exception(const std::string& msg,
frame::error::value code = frame::error::FATAL_SESSION_ERROR)
: m_msg(msg),m_code(code) {}
~exception() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
frame::error::value code() const throw() {
return m_code;
}
std::string m_msg;
frame::error::value m_code;
};
class interface {
public:
// consume
virtual bool ready() const = 0;
virtual bool uint64_t get_bytes_needed() const = 0;
virtual void reset() = 0;
virtual void consume(std::istream& s) = 0;
// retrieve buffers
// read frame options
// Is the last fragment in a message sequence?
virtual bool get_fin() const = 0;
virtual opcode::value() const = 0;
};
}
}
#endif // WEBSOCKET_INTERFACE_FRAME_PARSER_HPP

View File

@@ -1,325 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_INTERFACE_SESSION_HPP
#define WEBSOCKET_INTERFACE_SESSION_HPP
#include <boost/shared_ptr.hpp>
#include <string>
#include <vector>
#include "../websocket_constants.hpp"
#include "../network_utilities.hpp"
namespace websocketpp {
namespace session {
namespace state {
enum value {
CONNECTING = 0,
OPEN = 1,
CLOSING = 2,
CLOSED = 3
};
}
namespace error {
enum value {
FATAL_ERROR = 0, // force session end
SOFT_ERROR = 1, // should log and ignore
PROTOCOL_VIOLATION = 2, // must end session
PAYLOAD_VIOLATION = 3, // should end session
INTERNAL_SERVER_ERROR = 4, // cleanly end session
MESSAGE_TOO_BIG = 5 // ???
};
}
class exception : public std::exception {
public:
exception(const std::string& msg,
error::value code = error::FATAL_ERROR)
: m_msg(msg),m_code(code) {}
~exception() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
error::value code() const throw() {
return m_code;
}
std::string m_msg;
error::value m_code;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Server API *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
server(uint16_t port, server_handler_ptr handler)
void run();
*/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Server Session API *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class server {
public:
// Valid always
virtual session::state::value get_state() const = 0;
virtual unsigned int get_version() const = 0;
virtual std::string get_request_header(const std::string& key) const = 0;
virtual std::string get_origin() const = 0;
// Information about the requested URI
virtual bool get_secure() const = 0;
virtual std::string get_host() const = 0;
virtual std::string get_resource() const = 0;
virtual uint16_t get_port() const = 0;
// Information about the connected endpoint
/* Tentative API member function */ virtual boost::asio::ip::tcp::endpoint get_endpoint() const = 0;
// Valid for CONNECTING state
virtual void add_response_header(const std::string& key, const std::string& value) = 0;
virtual void replace_response_header(const std::string& key, const std::string& value) = 0;
virtual const std::vector<std::string>& get_subprotocols() const = 0;
virtual const std::vector<std::string>& get_extensions() const = 0;
virtual void select_subprotocol(const std::string& value) = 0;
virtual void select_extension(const std::string& value) = 0;
// Valid for OPEN state
virtual void send(const utf8_string& payload) = 0;
virtual void send(const binary_string& data) = 0;
virtual void close(close::status::value code, const utf8_string& reason) = 0;
virtual void ping(const binary_string& payload) = 0;
virtual void pong(const binary_string& payload) = 0;
virtual uint64_t buffered_amount() const = 0;
// Valid for CLOSED state
virtual close::status::value get_local_close_code() const = 0;
virtual utf8_string get_local_close_reason() const = 0;
virtual close::status::value get_remote_close_code() const = 0;
virtual utf8_string get_remote_close_reason() const = 0;
virtual bool get_failed_by_me() const = 0;
virtual bool get_dropped_by_me() const = 0;
virtual bool get_closed_by_me() const = 0;
};
typedef boost::shared_ptr<server> server_ptr;
typedef server_ptr server_session_ptr;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Server Handler API *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class server_handler {
public:
virtual ~server_handler() {}
// 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
// negotiate subprotocols). To reject the connection throw a handshake_error
//
// handshake_error parameters:
// log_message - error message to send to server log
// http_error_code - numeric HTTP error code to return to the client
// http_error_msg - (optional) string HTTP error code to return to the
// client (useful for returning non-standard error codes)
virtual void validate(server_ptr session) = 0;
// on_open is called after the websocket session has been successfully
// established and is in the OPEN state. The session is now avaliable to
// send messages and will begin reading frames and calling the on_message/
// on_close/on_error callbacks. A client may reject the connection by
// closing the session at this point.
virtual void on_open(server_ptr session) = 0;
// on_close is called whenever an open session is closed for any reason.
// This can be due to either endpoint requesting a connection close or an
// error occuring. Information about why the session was closed can be
// extracted from the session itself.
//
// on_close will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_close(server_ptr session) = 0;
// on_message (binary version) will be called when a binary message is
// recieved. Message data is passed as a vector of bytes (unsigned char).
// data will not be avaliable after this callback ends so the handler must
// either completely process the message or copy it somewhere else for
// processing later.
virtual void on_message(server_ptr session, binary_string_ptr data) = 0;
// on_message (text version). Identical to on_message except the data
// parameter is a string interpreted as UTF-8. WebSocket++ guarantees that
// this string is valid UTF-8.
virtual void on_message(server_ptr session, utf8_string_ptr msg) = 0;
// on_fail is called whenever a session is terminated or failed before it
// was successfully established. This happens if there is an error during
// the handshake process or if the server refused the connection.
//
// on_fail will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_fail(server_ptr session) {};
// on_ping is called whenever a ping is recieved with the binary
// application data from the ping. If on_ping returns true the
// implimentation will send a response pong.
virtual bool on_ping(server_ptr session, binary_string_ptr data) {
return true;
}
// on_pong is called whenever a pong is recieved with the binary
// application data from the pong.
virtual void on_pong(server_ptr session, binary_string_ptr data) {}
// TODO: on_ping_timeout
};
typedef boost::shared_ptr<server_handler> server_handler_ptr;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Client Session API *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class client {
public:
client(const std::string& uri) {};
// Valid always
virtual session::state::value get_state() const = 0;
virtual int get_version() const = 0;
virtual std::string get_origin() const = 0;
virtual bool get_secure() const = 0;
virtual std::string get_host() const = 0;
virtual std::string get_resource() const = 0;
virtual uint16_t get_port() const = 0;
// Valid for CONNECTING state
virtual void set_origin(const std::string& origin) = 0;
virtual void add_request_header(const std::string& key, const std::string& value) = 0;
virtual void replace_request_header(const std::string& key, const std::string& value) = 0;
virtual void request_subprotocol(const std::string& value) = 0;
virtual void request_extension(const std::string& value) = 0;
// Valid for OPEN state
virtual std::string get_response_header(const std::string& key) const = 0;
virtual std::string get_subprotocol() const;
virtual const std::vector<std::string>& get_extensions() const = 0;
virtual void send(const utf8_string& msg) = 0;
virtual void send(const binary_string& data) = 0;
virtual void close(close::status::value code, const binary_string& reason) = 0;
virtual void ping(const binary_string& payload) = 0;
virtual void pong(const binary_string& payload) = 0;
// Valid for CLOSED state
virtual close::status::value get_local_close_code() const = 0;
virtual utf8_string get_local_close_reason() const = 0;
virtual close::status::value get_remote_close_code() const = 0;
virtual utf8_string get_remote_close_reason() const = 0;
virtual bool failed_by_me() const = 0;
virtual bool dropped_by_me() const = 0;
virtual bool closed_by_me() const = 0;
};
typedef boost::shared_ptr<client> client_ptr;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Client Handler API *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
class client_handler {
public:
// on_open is called after the websocket session has been successfully
// established and is in the OPEN state. The session is now avaliable to
// send messages and will begin reading frames and calling the on_message/
// on_close/on_error callbacks. A client may reject the connection by
// closing the session at this point.
virtual void on_open(client_ptr session) = 0;
// on_close is called whenever an open session is closed for any reason.
// This can be due to either endpoint requesting a connection close or an
// error occuring. Information about why the session was closed can be
// extracted from the session itself.
//
// on_close will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_close(client_ptr session) = 0;
// on_message (binary version) will be called when a binary message is
// recieved. Message data is passed as a vector of bytes (unsigned char).
// data will not be avaliable after this callback ends so the handler must
// either completely process the message or copy it somewhere else for
// processing later.
virtual void on_message(client_ptr session, binary_string_ptr data) = 0;
// on_message (text version). Identical to on_message except the data
// parameter is a string interpreted as UTF-8. WebSocket++ guarantees that
// this string is valid UTF-8.
virtual void on_message(client_ptr session, utf8_string_ptr msg) = 0;
// on_fail is called whenever a session is terminated or failed before it
// was successfully established. This happens if there is an error during
// the handshake process or if the server refused the connection.
//
// on_fail will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_fail(client_ptr session) {};
// on_ping is called whenever a ping is recieved with the binary
// application data from the ping. If on_ping returns true the
// implimentation will send a response pong.
virtual bool on_ping(server_ptr session, binary_string_ptr data) {
return true;
}
// on_pong is called whenever a pong is recieved with the binary
// application data from the pong.
virtual void on_pong(server_ptr session, binary_string_ptr data) {}
// TODO: on_ping_timeout
};
typedef boost::shared_ptr<client_handler> client_handler_ptr;
}
}
#endif // WEBSOCKET_INTERFACE_SESSION_HPP

View File

@@ -1,103 +0,0 @@
/*
build situation
endpoint.hpp
- libboost_system
- libboost_date_time (if you use the default logger)
sockets/ssl.hpp
- libcrypto
- libssl
*/
// Application start
#include "endpoint.hpp"
#include "roles/server.hpp"
#include "sockets/ssl.hpp"
typedef websocketpp::endpoint<websocketpp::role::server,websocketpp::socket::plain> endpoint_type;
//typedef websocketpp::endpoint<websocketpp::role::server> endpoint_type;
typedef websocketpp::role::server<endpoint_type>::handler handler_type;
typedef websocketpp::role::server<endpoint_type>::handler_ptr handler_ptr;
// application headers
class application_server_handler : public handler_type {
public:
void validate(handler_type::connection_ptr connection) {
//std::cout << "state: " << connection->get_state() << std::endl;
}
void on_open(handler_type::connection_ptr connection) {
//std::cout << "connection opened" << std::endl;
}
void on_close(handler_type::connection_ptr connection) {
//std::cout << "connection closed" << std::endl;
}
void on_message(connection_ptr connection,websocketpp::utf8_string_ptr msg) {
//std::cout << "got message: " << *msg << std::endl;
connection->send(*msg);
}
void on_message(connection_ptr connection,websocketpp::binary_string_ptr data) {
//std::cout << "got binary message of length: " << data->size() << std::endl;
connection->send(*data);
}
void http(handler_type::connection_ptr connection) {
connection->set_body("HTTP Response!!");
}
void on_fail(handler_type::connection_ptr connection) {
std::cout << "connection failed" << std::endl;
}
};
typedef websocketpp::endpoint<websocketpp::role::client,websocketpp::socket::plain> basic_client;
typedef websocketpp::role::client<basic_client>::handler client_handler_type;
typedef websocketpp::role::client<basic_client>::handler_ptr client_handler_ptr;
class application_client_handler : public client_handler_type {
void validate(handler_type::connection_ptr connection) {
std::cout << "state: " << connection->get_state() << std::endl;
}
void on_open(handler_type::connection_ptr connection) {
std::cout << "connection opened" << std::endl;
}
void on_close(handler_type::connection_ptr connection) {
std::cout << "connection closed" << std::endl;
}
void on_message(connection_ptr connection,websocketpp::utf8_string_ptr msg) {
std::cout << "got message: " << *msg << std::endl;
connection->send(*msg);
}
void on_message(connection_ptr connection,websocketpp::binary_string_ptr data) {
std::cout << "got binary message of length: " << data->size() << std::endl;
connection->send(*data);
}
void http(handler_type::connection_ptr connection) {
connection->set_body("HTTP Response!!");
}
void on_fail(handler_type::connection_ptr connection) {
std::cout << "connection failed" << std::endl;
}
};
int main () {
handler_ptr h(new application_client_handler());
endpoint_type e(h);
e.alog().set_level(websocketpp::log::alevel::ALL);
e.elog().set_level(websocketpp::log::elevel::ALL);
e.connect("ws://localhost:9002");
return 0;
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKETPP_SESSION_HANDLER_INTERFACE_HPP
#define WEBSOCKETPP_SESSION_HANDLER_INTERFACE_HPP
#include <boost/shared_ptr.hpp>
#include <string>
#include <map>
namespace websocketpp {
namespace session {
class session_handler_interface {
public:
};
}
}
#endif // WEBSOCKETPP_SESSION_HANDLER_INTERFACE_HPP

View File

@@ -1,200 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "websocket_client.hpp"
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
using websocketpp::client;
using boost::asio::ip::tcp;
client::client(boost::asio::io_service& io_service,
websocketpp::connection_handler_ptr defc)
: m_elog_level(LOG_OFF),
m_alog_level(ALOG_OFF),
m_state(CLIENT_STATE_NULL),
m_max_message_size(DEFAULT_MAX_MESSAGE_SIZE),
m_io_service(io_service),
m_resolver(io_service),
m_def_con_handler(defc) {}
void client::init() {
// TODO: sanity check whether the session buffer size bound could be reduced
m_client_session = client_session_ptr(
new client_session(
shared_from_this(),
m_io_service,
m_def_con_handler,
m_max_message_size*2
)
);
m_state = CLIENT_STATE_INITIALIZED;
}
void client::connect(const std::string& uri) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("connect can only be called after init and before a connection has been established");
}
m_client_session->set_uri(uri);
std::stringstream port;
port << m_client_session->get_port();
tcp::resolver::query query(m_client_session->get_host(),
port.str());
tcp::resolver::iterator iterator = m_resolver.resolve(query);
boost::asio::async_connect(m_client_session->socket(),
iterator,boost::bind(&client::handle_connect,
this,
boost::asio::placeholders::error));
m_state = CLIENT_STATE_CONNECTING;
}
void client::add_subprotocol(const std::string& p) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("add_protocol can only be called after init and before connect");
}
m_client_session->add_subprotocol(p);
}
void client::set_header(const std::string& key,const std::string& val) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("set_header can only be called after init and before connect");
}
m_client_session->set_header(key,val);
}
void client::set_origin(const std::string& val) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("set_origin can only be called after init and before connect");
}
m_client_session->set_origin(val);
}
void client::set_max_message_size(uint64_t val) {
if (val > frame::PAYLOAD_64BIT_LIMIT) {
std::stringstream err;
err << "Invalid maximum message size: " << val;
// TODO: Figure out what the ideal error behavior for this method.
// Options:
// Throw exception
// Log error and set value to maximum allowed
// Log error and leave value at whatever it was before
log(err.str(),LOG_WARN);
//throw client_error(err.str());
}
m_max_message_size = val;
}
bool client::test_elog_level(uint16_t level) {
return (level >= m_elog_level);
}
void client::set_elog_level(uint16_t level) {
std::stringstream msg;
msg << "Error logging level changing from "
<< m_elog_level << " to " << level;
log(msg.str(),LOG_INFO);
m_elog_level = level;
}
bool client::test_alog_level(uint16_t level) {
return ((level & m_alog_level) != 0);
}
void client::set_alog_level(uint16_t level) {
if (test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being set";
access_log(msg.str(),ALOG_INFO);
m_alog_level |= level;
}
void client::unset_alog_level(uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being unset";
access_log(msg.str(),ALOG_INFO);
m_alog_level &= ~level;
}
bool client::validate_message_size(uint64_t val) {
if (val > m_max_message_size) {
return false;
}
return true;
}
void client::log(std::string msg,uint16_t level) {
if (!test_elog_level(level)) {
return;
}
std::cerr << "[Error Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
void client::access_log(std::string msg,uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::cout << "[Access Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
void client::handle_connect(const boost::system::error_code& error) {
if (!error) {
std::stringstream err;
err << "Successful Connection ";
log(err.str(),LOG_ERROR);
std::cout << boost::posix_time::to_iso_extended_string(boost::posix_time::microsec_clock::local_time()) << " TCP established" << std::endl;
m_state = CLIENT_STATE_CONNECTED;
m_client_session->on_connect();
} else {
std::stringstream err;
err << "An error occurred while establishing a connection: " << error;
log(err.str(),LOG_ERROR);
throw client_error(err.str());
}
}

View File

@@ -1,295 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_CLIENT_HPP
#define WEBSOCKET_CLIENT_HPP
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
#include <set>
#include "websocketpp.hpp"
#include "websocket_session.hpp"
#include "websocket_connection_handler.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
#include "rng/boost_rng.hpp"
#include "http/parser.hpp"
using boost::asio::ip::tcp;
namespace websocketpp {
class client_error : public std::exception {
public:
client_error(const std::string& msg)
: m_msg(msg) {}
~client_error() throw() {}
virtual const char* what() const throw() {
return m_msg.c_str();
}
private:
std::string m_msg;
};
template <typename rng_policy = boost_rng>
class client : public boost::enable_shared_from_this<client<rng_policy> > {
public:
typedef rng_policy rng_t;
typedef client<rng_policy> endpoint_type;
typedef session<endpoint_type> session_type;
typedef connection_handler<session_type> connection_handler_type;
typedef boost::shared_ptr<endpoint_type> ptr;
typedef boost::shared_ptr<session_type> session_ptr;
typedef boost::shared_ptr<connection_handler_type> connection_handler_ptr;
static const uint16_t CLIENT_STATE_NULL = 0;
static const uint16_t CLIENT_STATE_INITIALIZED = 1;
static const uint16_t CLIENT_STATE_CONNECTING = 2;
static const uint16_t CLIENT_STATE_CONNECTED = 3;
client<rng_policy>(boost::asio::io_service& io_service,
connection_handler_ptr defc)
: m_elog_level(LOG_OFF),
m_alog_level(ALOG_OFF),
m_state(CLIENT_STATE_NULL),
m_max_message_size(DEFAULT_MAX_MESSAGE_SIZE),
m_io_service(io_service),
m_resolver(io_service),
m_def_con_handler(defc) {}
// INTERFACE FOR LOCAL APPLICATIONS
// initializes the session. Methods that affect the opening handshake
// such as add_protocol and set_header must be called after init and
// before connect.
void init() {
// TODO: sanity check whether the session buffer size bound could be reduced
m_client_session = session_ptr(
new session_type(
endpoint_type::shared_from_this(),
m_io_service,
m_def_con_handler,
m_max_message_size*2
)
);
m_state = CLIENT_STATE_INITIALIZED;
}
// starts the connection process. Should be called before
// io_service.run(), connection process will not start until run() has
// been called.
void connect(const std::string& u) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("connect can only be called after init and before a connection has been established");
}
ws_uri uri;
if (!uri.parse(u)) {
throw client_error("Invalid WebSocket URI");
}
if (uri.secure) {
throw client_error("wss / secure connections are not supported at this time");
}
m_client_session->set_uri(uri);
std::stringstream port;
port << uri.port;
tcp::resolver::query query(uri.host,port.str());
tcp::resolver::iterator iterator = m_resolver.resolve(query);
boost::asio::async_connect(
m_client_session->socket(),
iterator,
boost::bind(
&endpoint_type::handle_connect,
endpoint_type::shared_from_this(),
boost::asio::placeholders::error
)
);
m_state = CLIENT_STATE_CONNECTING;
}
// Adds a protocol to the opening handshake.
// Must be called before connect
void add_subprotocol(const std::string& p) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("add_protocol can only be called after init and before connect");
}
m_client_session->add_subprotocol(p);
}
// Sets the value of the given HTTP header to be sent during the
// opening handshake. Must be called before connect
void set_header(const std::string& key,const std::string& val) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("set_header can only be called after init and before connect");
}
m_client_session->set_request_header(key,val);
}
void set_origin(const std::string& val) {
if (m_state != CLIENT_STATE_INITIALIZED) {
throw client_error("set_origin can only be called after init and before connect");
}
m_client_session->set_origin(val);
}
void set_max_message_size(uint64_t val) {
if (val > frame::limits::PAYLOAD_SIZE_JUMBO) {
std::stringstream err;
err << "Invalid maximum message size: " << val;
// TODO: Figure out what the ideal error behavior for this method.
// Options:
// Throw exception
// Log error and set value to maximum allowed
// Log error and leave value at whatever it was before
log(err.str(),LOG_WARN);
//throw client_error(err.str());
}
m_max_message_size = val;
}
// Test methods determine if a message of the given level should be
// written. elog shows all values above the level set. alog shows only
// the values explicitly set.
bool test_elog_level(uint16_t level) {
return (level >= m_elog_level);
}
void set_elog_level(uint16_t level) {
std::stringstream msg;
msg << "Error logging level changing from "
<< m_elog_level << " to " << level;
log(msg.str(),LOG_INFO);
m_elog_level = level;
}
bool test_alog_level(uint16_t level) {
return ((level & m_alog_level) != 0);
}
void set_alog_level(uint16_t level) {
if (test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being set";
access_log(msg.str(),ALOG_INFO);
m_alog_level |= level;
}
void unset_alog_level(uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::stringstream msg;
msg << "Access logging level " << level << " being unset";
access_log(msg.str(),ALOG_INFO);
m_alog_level &= ~level;
}
// INTERFACE FOR SESSIONS
// Check if message size is within server's acceptable parameters
bool validate_message_size(uint64_t val) {
if (val > m_max_message_size) {
return false;
}
return true;
}
// write to the server's logs
void log(std::string msg,uint16_t level = LOG_ERROR) {
if (!test_elog_level(level)) {
return;
}
std::cerr << "[Error Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
void access_log(std::string msg,uint16_t level) {
if (!test_alog_level(level)) {
return;
}
std::cout << "[Access Log] "
<< boost::posix_time::to_iso_extended_string(
boost::posix_time::second_clock::local_time())
<< " " << msg << std::endl;
}
private:
// if no errors starts the session's read loop and returns to the
// start_accept phase.
void handle_connect(const boost::system::error_code& error) {
if (!error) {
std::stringstream err;
err << "Successful Connection ";
log(err.str(),LOG_ERROR);
m_state = CLIENT_STATE_CONNECTED;
m_client_session->on_connect();
} else {
std::stringstream err;
err << "An error occurred while establishing a connection: " << error;
log(err.str(),LOG_ERROR);
throw client_error(err.str());
}
}
private:
uint16_t m_elog_level;
uint16_t m_alog_level;
uint16_t m_state;
std::set<std::string> m_hosts;
uint64_t m_max_message_size;
boost::asio::io_service& m_io_service;
tcp::resolver m_resolver;
session_ptr m_client_session;
connection_handler_ptr m_def_con_handler;
};
}
#endif // WEBSOCKET_CLIENT_HPP

View File

@@ -1,350 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "websocketpp.hpp"
#include "websocket_client_session.hpp"
#include "websocket_frame.hpp"
#include "utf8_validator/utf8_validator.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
using websocketpp::client_session;
client_session::client_session (websocketpp::client_ptr c,
boost::asio::io_service& io_service,
websocketpp::connection_handler_ptr defc,
uint64_t buf_size)
: session(io_service,defc,buf_size),m_client(c) {}
void client_session::on_connect() {
// TODO: section 4.1: Figure out if we have another connection to this
// host/port pending.
write_handshake();
}
void client_session::set_uri(const std::string& uri) {
if (!m_uri.parse(uri)) {
throw client_error("Invalid WebSocket URI");
}
if (m_uri.secure) {
throw client_error("wss / secure connections are not supported at this time");
}
m_resource = m_uri.resource;
std::stringstream l;
l << "parsed websocket url: secure: " << m_uri.secure << " host: " << m_uri.host
<< " port (final): " << m_uri.port << " resource " << m_uri.resource;
log(l.str(),LOG_DEBUG);
}
bool client_session::get_secure() const {
return m_uri.secure;
}
std::string client_session::get_host() const{
return m_uri.host;
}
uint16_t client_session::get_port() const {
return m_uri.port;
}
void client_session::set_header(const std::string &key,const std::string &val) {
// TODO: prevent use of reserved headers
m_client_headers[key] = val;
}
void client_session::set_origin(const std::string& val) {
// TODO: input validation
m_client_origin = val;
}
void client_session::add_subprotocol(const std::string &val) {
// TODO: input validation
m_client_subprotocols.push_back(val);
}
void client_session::add_extension(const std::string& val) {
// TODO: input validation
m_client_extensions.push_back(val);
}
void client_session::read_handshake() {
boost::asio::async_read_until(
m_socket,
m_buf,
"\r\n\r\n",
boost::bind(
&session::handle_read_handshake,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void client_session::handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred) {
if (e) {
log_error("Error reading server handshake",e);
drop_tcp();
return;
}
// parse server handshake
std::istream response_stream(&m_buf);
std::string header;
std::string::size_type end;
// get status line
std::getline(response_stream, header);
if (header[header.size()-1] == '\r') {
header.erase(header.end()-1);
m_server_http_request = header;
m_raw_server_handshake += header+"\n";
}
// get headers
while (std::getline(response_stream, header) && header != "\r") {
if (header[header.size()-1] != '\r') {
continue; // ignore malformed header lines?
} else {
header.erase(header.end()-1);
}
end = header.find(": ",0);
if (end != std::string::npos) {
std::string h = header.substr(0,end);
if (get_server_header(h) == "") {
m_server_headers[h] = header.substr(end+2);
} else {
m_server_headers[h] += ", " + header.substr(end+2);
}
}
m_raw_server_handshake += header+"\n";
}
// temporary debugging
if (m_buf.size() > 0) {
std::stringstream foo;
foo << "bytes left over: " << m_buf.size();
access_log(foo.str(), ALOG_HANDSHAKE);
}
m_client->access_log(m_raw_server_handshake,ALOG_HANDSHAKE);
// handshake error checking
try {
std::stringstream err;
std::string h;
// TODO: allow versions greater than 1.1
if (m_server_http_request.substr(0,9) != "HTTP/1.1 ") {
err << "Websocket handshake has invalid HTTP version: "
<< m_server_http_request.substr(0,9);
throw(handshake_error(err.str(),400));
}
// check the HTTP version
if (m_server_http_request.substr(9,3) != "101") {
err << "Websocket handshake ended with status "
<< m_server_http_request.substr(9);
// TODO: check version header for other supported versions.
throw(handshake_error(err.str(),400));
}
// verify the presence of required headers
h = get_server_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_server_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_server_header("Sec-WebSocket-Accept") == "") {
throw(handshake_error("Required Sec-WebSocket-Key header is missing",400));
} else {
// TODO: make a helper function for this.
std::string server_key = m_client_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)) {
m_client->log("Error computing handshake sha1 hash.",LOG_ERROR);
// TODO: close behavior
return;
}
// 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);
if (server_key != get_server_header("Sec-WebSocket-Accept")) {
m_client->log("Server key does not match",LOG_ERROR);
// TODO: close behavior
return;
}
}
} catch (const handshake_error& e) {
std::stringstream err;
err << "Caught handshake exception: " << e.what();
m_client->access_log(e.what(),ALOG_HANDSHAKE);
m_client->log(err.str(),LOG_ERROR);
// TODO: close behavior
return;
}
log_open_result();
m_state = STATE_OPEN;
if (m_local_interface) {
m_local_interface->on_open(shared_from_this());
}
reset_message();
read_frame();
}
void client_session::write_handshake() {
// generate client handshake.
std::string client_handshake;
client_handshake += "GET "+m_resource+" HTTP/1.1\r\n";
set_header("Upgrade","websocket");
set_header("Connection","Upgrade");
set_header("Sec-WebSocket-Version","13");
set_header("Host",m_uri.host);
if (m_client_origin != "") {
set_header("Origin",m_client_origin);
}
// TODO: generate proper key
m_client_key = "XO4pxrIMLnK1CEVQP9untQ==";
int32_t raw_key[4];
boost::random::random_device rng;
boost::random::variate_generator<boost::random::random_device&, boost::random::uniform_int_distribution<> > gen(rng, boost::random::uniform_int_distribution<>(INT32_MIN,INT32_MAX));
for (int i = 0; i < 4; i++) {
raw_key[i] = gen();
}
m_client_key = base64_encode(reinterpret_cast<unsigned char const*>(raw_key), 16);
m_client->access_log("Client key chosen: "+m_client_key, ALOG_HANDSHAKE);
set_header("Sec-WebSocket-Key",m_client_key);
set_header("User Agent","WebSocket++/2011-09-25");
header_list::iterator it;
for (it = m_client_headers.begin(); it != m_client_headers.end(); it++) {
client_handshake += it->first + ": " + it->second + "\r\n";
}
client_handshake += "\r\n";
m_raw_client_handshake = client_handshake;
// start async write to handle_write_handshake
boost::asio::async_write(
m_socket,
boost::asio::buffer(m_raw_client_handshake),
boost::bind(
&session::handle_write_handshake,
shared_from_this(),
boost::asio::placeholders::error
)
);
}
void client_session::handle_write_handshake(const boost::system::error_code& error) {
if (error) {
log_error("Error writing handshake",error);
drop_tcp();
return;
}
read_handshake();
}
void client_session::log(const std::string& msg, uint16_t level) const {
m_client->log(msg,level);
}
void client_session::access_log(const std::string& msg, uint16_t level) const {
m_client->access_log(msg,level);
}

View File

@@ -1,135 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_CLIENT_SESSION_HPP
#define WEBSOCKET_CLIENT_SESSION_HPP
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#if defined(WIN32)
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <algorithm>
#include <exception>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace websocketpp {
class client_session;
typedef boost::shared_ptr<client_session> client_session_ptr;
}
#include "websocket_session.hpp"
#include "websocket_client.hpp"
using boost::asio::ip::tcp;
namespace websocketpp {
class client_session : public session {
public:
client_session (client_ptr c,
boost::asio::io_service& io_service,
connection_handler_ptr defc,
uint64_t buf_size);
/*** CLIENT INTERFACE ***/
// This function is called when a tcp connection has been established and
// the connection is ready to start the opening handshake.
void on_connect();
/*** HANDSHAKE INTERFACE ***/
void set_uri(const std::string& url);
bool get_secure() const;
std::string get_host() const;
uint16_t get_port() const;
// Set an HTTP header for the outgoing client handshake.
void set_header(const std::string& key,const std::string& val);
// adds a subprotocol. This will result in the appropriate
// Sec-WebSocket-Protocol header being sent with the opening connection.
// Values will be sent in the order they were added. Servers interpret this
// order as the preferred order.
void add_subprotocol(const std::string &val);
// Sets the origin value that will be sent to the server
void set_origin(const std::string &val);
// Adds an extension to the extension list. Extensions are sent in the
// order added
void add_extension(const std::string& val);
/*** SESSION INTERFACE ***/
// see session
bool is_server() const {return false;}
void log(const std::string& msg, uint16_t level) const;
void access_log(const std::string& msg, uint16_t level) const;
protected:
// Opening handshake processors and callbacks.
virtual void write_handshake();
virtual void handle_write_handshake(const boost::system::error_code& e);
virtual void read_handshake();
virtual void handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred);
private:
protected:
ws_uri m_uri;
// url parts
bool m_secure;
std::string m_host;
uint16_t m_port;
// handshake stuff
std::string m_client_key;
// connection resources
client_ptr m_client;
private:
};
}
#endif // WEBSOCKET_CLIENT_SESSION_HPP

View File

@@ -1,112 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_CONNECTION_HANDLER_HPP
#define WEBSOCKET_CONNECTION_HANDLER_HPP
#include <boost/shared_ptr.hpp>
#include <string>
#include <map>
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
// negotiate subprotocols). To reject the connection throw a handshake_error
//
// Validate is never called for client sessions. To refuse a client session
// (ex: if you do not like the set of extensions/subprotocols the server
// chose) you can close the connection immediately in the on_open method.
//
// handshake_error parameters:
// log_message - error message to send to server log
// http_error_code - numeric HTTP error code to return to the client
// http_error_msg - (optional) string HTTP error code to return to the
// client (useful for returning non-standard error codes)
virtual void validate(session_ptr session) {};
// on_open is called after the websocket session has been successfully
// established and is in the OPEN state. The session is now avaliable to
// send messages and will begin reading frames and calling the on_message/
// on_close/on_error callbacks. A client may reject the connection by
// closing the session at this point.
virtual void on_open(session_ptr session) = 0;
// on_close is called whenever an open session is closed for any reason.
// This can be due to either endpoint requesting a connection close or an
// error occuring. Information about why the session was closed can be
// extracted from the session itself.
//
// on_close will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_close(session_ptr session) = 0;
// on_message (binary version) will be called when a binary message is
// recieved. Message data is passed as a vector of bytes (unsigned char).
// data will not be avaliable after this callback ends so the handler must
// either completely process the message or copy it somewhere else for
// processing later.
virtual void on_message(session_ptr session,
const std::vector<unsigned char> &data) = 0;
// on_message (text version). Identical to on_message except the data
// parameter is a string interpreted as UTF-8. WebSocket++ guarantees that
// this string is valid UTF-8.
virtual void on_message(session_ptr session,const std::string &msg) = 0;
// #### optional error cases ####
// on_fail is called whenever a session is terminated or failed before it
// was successfully established. This happens if there is an error during
// the handshake process or if the server refused the connection.
//
// on_fail will be the last time a session calls its handler. If your
// application will need information from `session` after this function you
// should either save the session_ptr somewhere or copy the data out.
virtual void on_fail(session_ptr session) {};
// experimental
virtual void on_ping_timeout(session_ptr session) {}
};
}
#endif // WEBSOCKET_CONNECTION_HANDLER_HPP

View File

@@ -1,55 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_ENDPOINT_HPP
#define WEBSOCKET_ENDPOINT_HPP
#include <boost/shared_ptr.hpp>
#include <string>
#include <map>
namespace websocketpp {
class endpoint;
typedef boost::shared_ptr<endpoint> endpoint_ptr;
}
#include "websocket_session.hpp"
namespace websocketpp {
class endpoint : public boost::enable_shared_from_this<endpoint> {
public:
virtual bool is_server() = 0;
// log
// access_log
};
}
#endif // WEBSOCKET_ENDPOINT_HPP

View File

@@ -1,27 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

View File

@@ -1,27 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,362 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "websocketpp.hpp"
#include "websocket_server_session.hpp"
#include "websocket_frame.hpp"
#include "utf8_validator/utf8_validator.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
using websocketpp::server_session;
server_session::server_session(websocketpp::server_ptr s,
boost::asio::io_service& io_service,
websocketpp::connection_handler_ptr defc,
uint64_t buf_size)
: session(io_service,defc,buf_size),m_server(s) {}
void server_session::on_connect() {
read_handshake();
}
void server_session::set_header(const std::string &key,const std::string &val) {
// TODO: prevent use of reserved headers;
m_server_headers[key] = val;
}
void server_session::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 server_session::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);
}
void server_session::read_handshake() {
m_timer.expires_from_now(boost::posix_time::seconds(5));
m_timer.async_wait(
boost::bind(
&session::handle_handshake_expired,
shared_from_this(),
boost::asio::placeholders::error
)
);
boost::asio::async_read_until(
m_socket,
m_buf,
"\r\n\r\n",
boost::bind(
&session::handle_read_handshake,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void server_session::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_server->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(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();
}
void server_session::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::handle_write_handshake,
shared_from_this(),
boost::asio::placeholders::error
)
);
}
void server_session::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(shared_from_this());
}
reset_message();
this->read_frame();
}
void server_session::log(const std::string& msg, uint16_t level) const {
m_server->log(msg,level);
}
void server_session::access_log(const std::string& msg, uint16_t level) const {
m_server->access_log(msg,level);
}

View File

@@ -1,118 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_SERVER_SESSION_HPP
#define WEBSOCKET_SERVER_SESSION_HPP
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#if defined(WIN32)
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <algorithm>
#include <exception>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
namespace websocketpp {
class server_session;
typedef boost::shared_ptr<server_session> server_session_ptr;
}
#include "websocket_session.hpp"
#include "websocket_server.hpp"
using boost::asio::ip::tcp;
namespace websocketpp {
class server_session : public session {
public:
server_session (server_ptr s,
boost::asio::io_service& io_service,
connection_handler_ptr defc,
uint64_t buf_size);
/*** SERVER INTERFACE ***/
// This function is called when a connection to a new client has been
// established and the server is ready to read the client handshake.
void on_connect();
/*** HANDSHAKE INTERFACE ***/
// Set an HTTP header for the outgoing server handshake response.
void set_header(const std::string& key, const std::string& val);
// Selects a subprotocol for the connection to use. val must be a value
// present in the client's opening handshake or the empty string for null.
void select_subprotocol(const std::string& val);
// Selects an extension from the list offered by the client. Each extension
// selected must have been offered by the client. Extensions will be used
// in the order that they were selected here.
void select_extension(const std::string& val);
/*** SESSION INTERFACE ***/
// see session
virtual bool is_server() const { return true;}
void log(const std::string& msg, uint16_t level) const;
void access_log(const std::string& msg, uint16_t level) const;
protected:
// Opening handshake processors and callbacks. These need to be defined in
virtual void write_handshake();
virtual void handle_write_handshake(const boost::system::error_code& e);
virtual void read_handshake();
virtual void handle_read_handshake(const boost::system::error_code& e,
std::size_t bytes_transferred);
private:
protected:
// connection resources
server_ptr m_server;
private:
};
}
#endif // WEBSOCKET_SERVER_SESSION_HPP

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 2011, Peter Thorson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the WebSocket++ Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

File diff suppressed because it is too large Load Diff

View File

@@ -244,7 +244,6 @@
/* Begin PBXFileReference section */
B6138760145AD09700ED9B19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; name = Makefile; path = examples/echo_server/Makefile; sourceTree = "<group>"; };
B6138762145AD0A500ED9B19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; name = Makefile; path = examples/echo_client/Makefile; sourceTree = "<group>"; };
B6138763145AD1F700ED9B19 /* chat_client.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = chat_client.html; path = examples/chat_server/chat_client.html; sourceTree = "<group>"; };
B6138764145AD1F700ED9B19 /* chat_server.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = chat_server.cpp; path = examples/chat_server/chat_server.cpp; sourceTree = "<group>"; };
B6138765145AD1F700ED9B19 /* chat.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = chat.cpp; path = examples/chat_server/chat.cpp; sourceTree = "<group>"; };
@@ -276,6 +275,13 @@
B62A5A71147759EA005F9EB0 /* common.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = common.hpp; path = src/common.hpp; sourceTree = "<group>"; };
B63E51A814C9A5790006BF9A /* shared_const_buffer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = shared_const_buffer.hpp; path = src/shared_const_buffer.hpp; sourceTree = "<group>"; };
B649759D150BA96100BE17D1 /* wscmd.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = wscmd.cpp; path = examples/wsperf/wscmd.cpp; sourceTree = "<group>"; };
B64975A01510B3FD00BE17D1 /* SConscript */ = {isa = PBXFileReference; lastKnownFileType = text; name = SConscript; path = examples/echo_server/SConscript; sourceTree = "<group>"; };
B64975A11510B41400BE17D1 /* SConscript */ = {isa = PBXFileReference; lastKnownFileType = text; path = SConscript; sourceTree = "<group>"; };
B64975A21510B54900BE17D1 /* SConscript */ = {isa = PBXFileReference; lastKnownFileType = text; name = SConscript; path = examples/chat_server/SConscript; sourceTree = "<group>"; };
B64975A31510B55600BE17D1 /* SConscript */ = {isa = PBXFileReference; lastKnownFileType = text; name = SConscript; path = examples/chat_client/SConscript; sourceTree = "<group>"; };
B64975A41510B62700BE17D1 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; name = Makefile; path = examples/chat_client/Makefile; sourceTree = "<group>"; };
B64975A51510B86B00BE17D1 /* SConscript */ = {isa = PBXFileReference; lastKnownFileType = text; path = SConscript; sourceTree = "<group>"; };
B64975A61510B8D900BE17D1 /* SConscript */ = {isa = PBXFileReference; lastKnownFileType = text; name = SConscript; path = examples/echo_server_tls/SConscript; sourceTree = "<group>"; };
B64E12D214BDE132006F20F0 /* logging.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = logging.cpp; sourceTree = "<group>"; };
B64E12D314BDE132006F20F0 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
B64E12D414BDE132006F20F0 /* parsing.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = parsing.cpp; sourceTree = "<group>"; };
@@ -568,6 +574,7 @@
B61A51B714DC207600456432 /* concurrent_client.html */,
B61A51B814DC207600456432 /* concurrent_server.cpp */,
B61A51B914DC207600456432 /* Makefile */,
B64975A51510B86B00BE17D1 /* SConscript */,
);
name = concurrent_server;
path = examples/concurrent_server;
@@ -629,6 +636,7 @@
children = (
B66388451487D71800DDAE13 /* echo_server_tls.cpp */,
B66388461487D71800DDAE13 /* Makefile */,
B64975A61510B8D900BE17D1 /* SConscript */,
);
name = echo_server_tls;
sourceTree = "<group>";
@@ -727,6 +735,7 @@
B6CF18121437C370009295BE /* echo_client */ = {
isa = PBXGroup;
children = (
B64975A11510B41400BE17D1 /* SConscript */,
B6CF18131437C370009295BE /* echo_client.cpp */,
B6CF18141437C370009295BE /* echo_client_handler.cpp */,
B6CF18151437C370009295BE /* echo_client_handler.hpp */,
@@ -870,6 +879,7 @@
B6DF1CC71435ED420029A1B1 /* echo_server */ = {
isa = PBXGroup;
children = (
B64975A01510B3FD00BE17D1 /* SConscript */,
B6DF1CCA1435ED760029A1B1 /* echo_server.cpp */,
B6DF1CCB1435ED760029A1B1 /* echo.cpp */,
B6DF1CCC1435ED760029A1B1 /* echo.hpp */,
@@ -884,7 +894,8 @@
B6828875143745DA002BA48B /* chat_client_handler.cpp */,
B6828876143745DA002BA48B /* chat_client_handler.hpp */,
B6828877143745DA002BA48B /* chat_client.cpp */,
B6138762145AD0A500ED9B19 /* Makefile */,
B64975A31510B55600BE17D1 /* SConscript */,
B64975A41510B62700BE17D1 /* Makefile */,
);
name = chat_client;
sourceTree = "<group>";
@@ -896,6 +907,7 @@
B6138764145AD1F700ED9B19 /* chat_server.cpp */,
B6138765145AD1F700ED9B19 /* chat.cpp */,
B6138766145AD1F700ED9B19 /* chat.hpp */,
B64975A21510B54900BE17D1 /* SConscript */,
B6138767145AD1F700ED9B19 /* Makefile */,
);
name = chat_server;