mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Merged upstream and resolved confilicts
This commit is contained in:
27
SConstruct
27
SConstruct
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
21
examples/chat_client/SConscript
Normal file
21
examples/chat_client/SConscript
Normal 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')
|
||||
20
examples/chat_server/SConscript
Normal file
20
examples/chat_server/SConscript
Normal 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')
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
20
examples/concurrent_server/SConscript
Normal file
20
examples/concurrent_server/SConscript
Normal 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')
|
||||
@@ -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;
|
||||
|
||||
21
examples/echo_client/SConscript
Normal file
21
examples/echo_client/SConscript
Normal 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')
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
21
examples/echo_server_tls/SConscript
Normal file
21
examples/echo_server_tls/SConscript
Normal 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')
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user